Subversion Repositories wimsdev

Compare Revisions

No changes between revisions

Ignore whitespace Rev 3652 → Rev 3653

/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/build.xml
0,0 → 1,101
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for MathView.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="MathView" default="jar" basedir=".">
 
<description>MathView build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create MathView jar">
<exec executable="/bin/sh">
<arg line="-c 'mkdir -p ${build}/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'mkdir -p ${build}/fr/ove/openmath/jome/ctrlview/bidim/images/relation'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'mkdir -p ${build}/fr/ove/openmath/jome/ctrlview/bidim/images/rsets'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'mkdir -p ${build}/fr/ove/openmath/jome/ctrlview/bidim/images/symbols'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'cp -rv ${source-dir}/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/*.gif ${build}/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'cp -rv ${source-dir}/fr/ove/openmath/jome/ctrlview/bidim/images/relation/*.gif ${build}/fr/ove/openmath/jome/ctrlview/bidim/images/relation/'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'cp -rv ${source-dir}/fr/ove/openmath/jome/ctrlview/bidim/images/sets/*.gif ${build}/fr/ove/openmath/jome/ctrlview/bidim/images/rsets/'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'cp -rv ${source-dir}/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/*.gif ${build}/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'cp -rv ${source-dir}/fr/ove/openmath/jome/model/*.properties ${build}/fr/ove/openmath/jome/model'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'cp -rv ${source-dir}/fr/ove/openmath/jome/ctrlview/bidim/*.properties ${build}/fr/ove/openmath/jome/ctrlview/bidim'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'cp -rv ${source-dir}/fr/ove/openmath/jome/ctrl/linear/*.properties ${build}/fr/ove/openmath/jome/ctrl/linear'"/>
</exec>
<exec executable="/bin/sh">
<arg line="-c 'cp -rv ${source-dir}/fr/ove/openmath/jome/ctrlview/bidim/images/*.properties ${build}/fr/ove/openmath/jome/ctrlview/bidim/images'"/>
</exec>
<mkdir dir="${dist}"/>
<jar destfile="${dist}/MathView.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="MathView"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="MathView"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="MathView">
<attribute name="Specification-Title" value="MathView"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="MathView"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/test.html
0,0 → 1,35
<html>
<body>
<script language="javascript" type="text/javascript">
function lees(){
var input=document.applets[0].getLinear();
alert("we send to WIMS :\n "+input);
}
</script>
<applet id="MathView" code="MathView.class" codebase="dist" archive="MathView.jar" width="640" height="480">
<param name="bgcolor" value="0xffff96">
<param name="bgcolor" value="#ffffff">
<param name="largefont" value="26">
<param name="smallfont" value="14">
<param name="oldreply" value="">
<param name="wimsvars" value="x">
<param name="special_fraction" value="0">
<param name="my_panel" value="module_title:->:sqrt[3]():sqrt[4]():sqrt[5]():sqrt[6]()">
<param name="helptext" value="234/32=">
</applet>
<p>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:lees();">
</body>
</html>
 
<!-- <param name=bgcolor value="0xffff50">
<param name="bgcolor" value="0xffff96">
<param name="bgcolor" value="#ffffff">
<param name="largefont" value="26">
<param name="smallfont" value="14">
<param name="oldreply" value="x_1 = -(sqrt(61)+1)/(6) and x_2 = sqrt[12345](1/(4x))">
<param name="wimsvars" value="x">
<param name="special_fraction" value="yes">
<param name="my_panel" value="module_title:->:sqrt[3]():sqrt[4]():sqrt[5]():sqrt[6]()">
<param name="helptext" value="{vlist(f(x)=4*x^2-6*x,.,g(x)=x^2-7*x+5)}->">
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/MathView.java
0,0 → 1,891
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
 
/*
* This is a slight modification of a JomeInput.java program
* The applet now accepts a few "parms" like:
*
* <param name="bgcolor" value="0xffff96">
* <param name="largefont" value="24">
* <param name="smallfont" value="16">
* <param name="wimsvars" value="x,y,z,n,d">
* <param name="oldreply" value="$wims_reply">
* <param name="my_panel" value="module_title:log[3]():sqrt[5]():and:or:isin:notin:R:Z:N:Q">
* <param name="helptext" value="f(x)=sin(3x)/cos(x^2)->f'(x)=">
*
* --> my_panel: a custom button panel ,tunable for the exercise at hand.
* --> wimsvars: a rudimentary form of "rawmath"...
* --> helptext: the exercise description ,some text may be allowed ?
*
*
* version 0.1
* 5/2007
* first rudimentary adaption for wims usage: filtering with javascript
*
* version 0.2
* 11/2007
* --> Introduction of log[g](a) and sqrt[g](a)
* --> Filtering now in poorly written java :)
* --> There still are some unresolved issues with "spaces" being turned into "+" signs by the included jome-code of applet.
* This is due to the fact that the applet -the way I use it- is not suitable for multiple-answers.(single line)
* --> The function "filter(String s1 , int k)" will change the "helptext" appletparam from ascii-math into "unicode" and reverse.
* Handling most common cases of false "+" signs.
* --> More reserved keywords can be included, if needed. [added div,times,notin,isin...etc etc]
* --> The helptext now gets stripped away in this applet, when the function getLinear() is called by javascript.
* (and will thus not be send as part of the answer)
*
*
* version 0.3
* 1/2008
* --> Deleted all useless references to MathML,OML...reducing size > 50% !
* --> Introduced <param name="oldreply" value="$wim_reply"> echoing the wims-rejected answer in the textareafield
* --> All (?) flaws of the applet are -hopefully- corrected...it should now be a one-line matheditor.
* In "Multi-aswers" statements/parts can be "glued" with arrows,and,or
* --> Domainsyntax allowed: [0:+inf> --> javascript --> lbracket 0 : +inf rangle
* --> Input sqrt[6](123) is also allowed...for "compatibility" with JS checkfiles
* --> Input log[8](123) is also allowed...for "compatibility" with JS checkfiles
* --> added reserved word array(1,2) used for a twoline "statement"
* --> multilines: array(first line , array(line two,line three)) etc etc
* --> restored the "," as special symbol -> n-th root : root(p,n) == sqrt[n](p)
* --> both n-th root syntaxes are read by javascript as: sqrt[n](p) --> send to wims as p^(1/n)
*
* version 0.4
* 3/2008
* --> compatible with java 1.4 ??? new replace function .... String.replace(String1,String2)
* --> vlist(line1,line2,line3....)
*/
 
import fr.ove.openmath.jome.Jome;
import java.applet.Applet;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.PrintStream;
 
public class MathView extends Applet
implements ActionListener, ItemListener, TextListener, WindowListener
{
// function that implements a java 1.5 style: String0.replace(String1,String2) --> replace(String0,String1,String2)
// thanks to Bernadette Perrin and her java 1.4 ;)
public static String replace(String source, String pattern, String replace)
{
if (source!=null)
{
final int len = pattern.length();
StringBuffer sb = new StringBuffer();
int found = -1;
int start = 0;
while( (found = source.indexOf(pattern, start) ) != -1) {
sb.append(source.substring(start, found));
sb.append(replace);
start = found + len;
}
sb.append(source.substring(start));
return sb.toString();
}
else return "";
}
 
public void setWindow(JFrame frame)
{
standaloneWindow = frame;
inAnApplet = false;
}
 
public void toggleFont()
{
Jome jome = j;
if(jome.getFont() == bigFont)
{
jome.setFont(defaultFont);
linearInput.setFont(defaultFont);
} else
{
jome.setFont(bigFont);
linearInput.setFont(bigFont);
}
invalidate();
jome.invalidate();
linearInput.invalidate();
linearInput.requestFocus();
repaint();
jome.repaint();
linearInput.repaint();
}
 
public static void main(String args[])
{
MathView mathview = new MathView();
JFrame frame = new JFrame();
mathview.setWindow(frame);
frame.add(mathview);
frame.setTitle("WIMS JAVA INPUT");
frame.addWindowListener(mathview);
mathview.init();
frame.pack();
frame.setSize(640,480);
frame.setVisible(true);
frame.validate();
mathview.start();
mathview.repaint();
 
 
}
 
private String removespecial(String t){
/// vlist(1,2,3,4) and restanswer -> 1 and 2 and 3 and 4 and restanswer
int begin=t.indexOf("vlist(");
if(begin==-1){return t;}
String org=t;
int t1;int t2;int tot;int Got;int Wait;int End;char chr;int s;
String value;String exp;String val;String L;String R;int cnt=0;
while (begin >= 0){
cnt++;if(cnt>1000){return org+" vlist(a,b) syntax error" ;}
tot=t.length();Wait=0;Got=0;End=0;
for(s=begin+5;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='('){Wait=Wait+1;}
if(chr==')'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
value=t.substring(begin+6,End);
t1=value.indexOf(",");if(t1<0){return org+" syntax error: comma missing\nvlist(a,b,c,d)";}
t2=value.length();
val=value.substring(0,t2);
if(val.indexOf("vlist(")!=-1){return org + "error :vlist within vlist";}
L="vlist("+val+")";R=val;
t=replace(t,L,R);
//System.out.println("val= " + val +" L= "+L);
begin=t.indexOf("vlist(");
}
t=replace(t,","," and ");
return t;
}
private String root2sqrtn(String t){
int begin=t.indexOf("root(");
if(begin==-1){return t;}
String org=t;
int t1;int t2;int tot;int Got;int Wait;int End;char chr;int s;
String value;String exp;String val;String L;String R;int cnt=0;
while (begin >= 0){
cnt++;if(cnt>1000){return org+" root(a,b) syntax error" ;}
tot=t.length();Wait=0;Got=0;End=0;
for(s=begin+4;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='('){Wait=Wait+1;}
if(chr==')'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
value=t.substring(begin+5,End);
t1=value.indexOf(",");if(t1<0){return org+" syntax error: comma missing\nroot(a,b)";}
t2=value.length();
val=value.substring(0,t1);exp=value.substring(t1+1,t2);
if(val.indexOf("root(")!=-1){return org + "error : absurd root-syntax";}
if(exp.indexOf("root(")!=-1){return org + "error : absurd root-syntax";}
L="root("+val+","+exp+")";R="sqrt["+exp+"]#"+val+"@";
t=replace(t,L,R);
//System.out.println("val= " + val + " exp= "+ exp+ " L= "+L+" R= "+R);
begin=t.indexOf("root(");
}
t=t.replace('#','(');
t=t.replace('@',')');
return t;
}
 
private String sqrtn2root(String t){
int begin=t.indexOf("sqrt[");
if(begin==-1){return t;}
String org=t;
int tot;int Got;int Wait;int End;char chr;int s;int restart;
String value;String exp;String val;String L;String R;int cnt=0;
while (begin >= 0){
cnt++;if(cnt>1000){return org+"sqrt[]() syntax error" ;}
tot=t.length();Wait=0;Got=0;End=0;
for(s=begin+4;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='['){Wait=Wait+1;}
if(chr==']'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
restart=End;
exp=t.substring(begin+5,End);
Wait=0;Got=0;End=0;
for(s=restart;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='('){Wait=Wait+1;}
if(chr==')'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
val=t.substring(restart+2,End);
R="root#"+val+","+exp+"@";L="sqrt["+exp+"]("+val+")";
t=replace(t,L,R);
//System.out.println("val= " + val + " exp= "+ exp+ " L= "+L+" R= "+R);
begin=t.indexOf("sqrt[");
}
t=t.replace('#','(');
t=t.replace('@',')');
return t;
}
 
private String filter1(String s1 , int k ){
int p;String r1;String r2;
String d1[] = new String[]{"of","et","en","*","cdot","times","div","N","Z","Q","R","\\",
"f^-1(x)","isin","and","or","notin","-->","=>","inf","->",
"log[2]","log[3]","log[4]","log[5]","log[6]","log[7]","log[8]","log[9]"};
String d2[] = new String[]{"\u22C1","\u22C0","\u22C0","\u2027","\u2027","X","\u00F7","\u2115","\u2124","\u211A","\u211D","\u2216",
"f\u00AF\u00B9(x)","\u2208","\u22C0","\u22C1","\u2209","rightarrow","\u21D4","\u221E","\u2192",
"\u00B2log","\u00B3log","\u2074log","\u2075log","\u2076log","\u2077log","\u2078log","\u2079log"};
String d3[] = new String[]{" or "," and "," and ","*","*","*","/","N","Z","Q","R","\\",
"f^-1(x)"," isin "," and "," or "," notin "," -> "," -> "," inf "," -> ",
"log[2]","log[3]","log[4]","log[5]","log[6]","log[7]","log[8]","log[9]"};
int d=d1.length;
//int e=d1.length;int f=d1.length;if( d!=e || d!=f){System.out.println("ERROR array lengte verschil d= " + d +"\n e= "+ e +"\n f =" +f) ;}
// d1=applettext from wims
// d2=unchangable text in math-area from applet
// d3=the syntax we want to read by javascript: basically spaces/words for readablitity
if(k==1){
// from ascii applettext-param to unicode applet and visa versa
for ( p=0;p<d;p++){
r1=d1[p];
r2=d2[p];
s1=replace(s1,r1,r2);
}
s1=sqrtn2root(s1);
}
else
{
for ( p=0;p<d;p++){
r1=d3[p];
r2=d2[p];
s1=replace(s1,r2,r1);
}
}
return s1;
}
private String filter2(String s){
if(Special_Fraction){s=replace(s," ","+");}// param "special_fraction" inserts a "+" sign -> 1 1/2 == 1+1/2
String vars=readParams("wimsvars");
if(vars.length()==0){vars="x";}
vars=vars.toString();vars=replace(vars,",","");
StringBuffer S=new StringBuffer(s);int p;int r;char x;char getal;char P1;char P2;char P3;String P4="";
String nummers="0123456789"+vars;nummers=nummers.toString();int t=vars.length();
int q=nummers.length();int m;int max=S.length();
String[] mathopts={"sq","si","co","ta","ab","lo","ln"};int opts=7;String mop="";int a;
int current = linearInput.getCaretPosition();
if(max>1){
for(r=0;r<t;r++){
x=vars.charAt(r);
for(p=0;p<q;p++){
getal=nummers.charAt(p);
for(m=0;m<max-1;m++){
P1=S.charAt(m);P2=S.charAt(m+1);
if(P1==getal && P2==x){
S=S.insert(m+1,"*");max++;linearInput.setText(S.toString());
current++;
}
}
max=S.length();
if(max>3){
for(m=0;m<max-2;m++){
P1=S.charAt(m);P2=S.charAt(m+1);P3=S.charAt(m+2);
if( (P1==' ' && P2==' ' && P3==' ') || (P1==' ' && P2=='e' && P3=='n') || (P1=='e' && P2=='n' && P3==' ') || (P1=='e' && P2=='n' && P3==x) ){
S=S.delete(m,m+3);S=S.append(" and ");m=m+3;linearInput.setText(S.toString());
}
else
{
if( (P1==' ' && P2=='o' && P3=='f') || (P1=='o' && P2=='f' && P3==' ') || (P1=='o' && P2=='f' && P3==x) ){
S=S.delete(m,m+3);S=S.append(" or ");m=m+2;current++;linearInput.setText(S.toString());
}
else
{
// poormans rawmath for "common function"
if(P1==getal || P1==x ){
P4="" + P2 + P3;
for(a=0;a<opts;a++){
mop=mathopts[a];if(P4.equals(mop)){S=S.insert(m+1,"*");a=opts;m=m+4;current++;linearInput.setText(S.toString());}
}
}
}
}
max=S.length();
}
}
}
}
}
linearInput.setCaretPosition(current);
linearInput.requestFocus();
s=S.toString();
s=sqrtn2root(s);
return s;
}
private String readParams(String s){
String c=getParameter(s);
return c;
}
 
private void reportError(String s)
{
if(!inAnApplet)
System.err.println(s);
}
 
private void addPaletteCard(Choice choice, Container container, String s, Container container1)
{
choice.add(s);
container.add(container1, s);
}
 
private JButton addButton(Container container, String s, String s1)
{
JButton button = new JButton(s);
button.setActionCommand(s1);
button.addActionListener(this);
container.add(button);
return button;
}
 
private JButton addButton(Container container, String s, String s1, String s2)
{
JButton button = new JButton(s);
button.setActionCommand(s1);
button.addActionListener(this);
container.add(button, s2);
return button;
}
 
public void start()
{
linearInput.setFont(defaultFont);
linearInput.invalidate();
j.invalidate();
repaint();
linearInput.requestFocus();
String oldreply=readParams("oldreply");
if(oldreply.length()!=0){
oldreply=replace(oldreply," ","");
oldreply=filter1(oldreply,1);
linearInput.setText(oldreply.toString());
}
}
public void init(){
try{String helen = readParams("special_fraction");
if(helen.equalsIgnoreCase("yes") || helen.equals("1")){Special_Fraction = true;}
}catch(Exception e){}
String special=readParams("my_panel");
String smallfont=readParams("smallfont");
String largefont=readParams("largefont");
int font1;int font2;
/* check op getallen */
if(smallfont==null){font1=16;}else{font1 = Integer.parseInt(smallfont);}
if(largefont==null){font2=24;}else{font2 = Integer.parseInt(largefont);}
bigFont = new Font("Helvetica", 0, font2);defaultFont = new Font("Helvetica", 0, font1);
 
String kleur=readParams("bgcolor");
Color bgcolor = new Color(0xffffff);// default white
if(kleur!=null){
try{ bgcolor=Color.decode(kleur);}catch(Exception e){System.out.println("do\'t know color "+kleur);}
}
setBackground(bgcolor);
j = new Jome();
j.setFont(defaultFont);
j.setDrawBounds(true);
//j.setBackground(new Color(0xffffdd));
j.setBackground(bgcolor);
BorderLayout borderlayout = new BorderLayout();
setLayout(new BorderLayout());
 
controlPane = new JPanel();
controlPane.setFont(defaultFont);
controlPane.setLayout(new BorderLayout());
palette = new JPanel();
palette.setLayout(new BorderLayout());
palette.setFont(defaultFont);
paletteCards = new JPanel();
paletteCardsLayout = new CardLayout(5, 4);
paletteCards.setLayout(paletteCardsLayout);
paletteChoice = new Choice();
paletteChoice.addItemListener(this);
 
// param name="my_panel" value="title : function1 : function1 : function1 : function1 "
if(special!=null){
int maxfun=7;
String[] results = special.split(":");
JPanel panel01 = new JPanel();
panel01.setLayout(new GridLayout());
int p;
int pos=results.length;
String P;
String PP="";
String titel=results[0];
for (p=1;p<pos;p++){
P=results[p];
// converting wims-module syntax to panel buttons
if(P.equals("sqrt()")){PP="\u221A";}
else
if(P.equals("sqrt[2]()")){P="sqrt()";PP="<html><sup>2</sup>\u221A</html>";}
else
if(P.equals("sqrt[3]()")){PP="<html><sup>3</sup>\u221A</font></html>";}
else
if(P.equals("sqrt[4]()")){PP="<html><sup>4</sup>\u221A</html>";}
else
if(P.equals("sqrt[5]()")){PP="<html><sup>5</sup>\u221A</html>";}
else
if(P.equals("sqrt[6]()")){PP="<html><sup>6</sup>\u221A</html>";}
else
if(P.equals("sqrt[7]()")){PP="<html><sup>7</sup>\u221A</html>";}
else
if(P.equals("sqrt[8]()")){PP="<html><sup>8</sup>\u221A</html>";}
else
if(P.equals("sqrt[9]()")){PP="<html><sup>9</sup>\u221A</html>";}
else
if(P.equals("sqrt[n]()")){PP="<html><sup>n</sup>\u221A</html>";}
else
if(P.equals("log[2]()")){P="\u00B2log()";PP="<html><sup>2</sup>log</html>";}
else
if(P.equals("log[3]()")){P="\u00B3log()";PP="<html><sup>3</sup>log</html>";}
else
if(P.equals("log[4]()")){P="\u2074log()";PP="<html><sup>4</sup>log</html>";}
else
if(P.equals("log[5]()")){P="\u2075log()";PP="<html><sup>5</sup>log</html>";}
else
if(P.equals("log[6]()")){P="\u2076log()";PP="<html><sup>6</sup>log</html>";}
else
if(P.equals("log[7]()")){P="\u2077log()";PP="<html><sup>7</sup>log</html>";}
else
if(P.equals("log[8]()")){P="\u2078log()";PP="<html><sup>8</sup>log</html>";}
else
if(P.equals("log[9]()")){P="\u2079log()";PP="<html><sup>9</sup>log</html>";}
else
if(P.equals("isin")){P="\u0020in\u0020" ;PP="\u2208 [isin]";}
else
if(P.equals("and")){P="\u0020and\u0020";PP="\u22C0 [and]";}
else
if(P.equals("or")){P="\u0020or\u0020";PP="\u22C1 [or]";}
else
if(P.equals("pi")){P="\u0020pi\u0020";PP="\u03C0";}
else
if(P.equals("notin")){P="\u0020notin\u0020";PP="\u2209 [notin]";}
else
if(P.equals("->")){P="\u2192";PP="\u2192";}
else
if(P.equals("=>")){P="\u2192";PP=P;}
else
if(P.equals("<=>")){P="\u21E4";PP=P;}
else
if(P.equals("<->")){P="\u21D4";PP=P;}
else
if(P.equals("<->")){P="\u21D4";PP=P;}
else
if(P.equals("langle")){P="\u0020langle\u0020";PP="<";}
else
if(P.equals("rangle")){P="\u0020rangle\u0020";PP=">";}
else
if(P.equals("lbracket")){P="\u0020lbracket\u0020";PP="[";}
else
if(P.equals("rbracket")){P="\u0020rbracket\u0020";PP="]";}
else
if(P.equals("inf")){P="infty";PP="\u221E";}
else{PP=P;}
addButton(panel01,PP,"insert "+P);
}
addPaletteCard(paletteChoice, paletteCards , titel , panel01);
palette.add(paletteChoice, "North");
palette.add(paletteCards, "Center");
controlPane.add(palette, "Center");
j.setVisible(true);
add(j, "Center");
}
 
JPanel panel04 = new JPanel();
panel04.setLayout(new GridLayout());
addButton(panel04, "\u22C0 [and]", "insert \u0020and ");
addButton(panel04, "\u22C1 [or]", "insert \u0020or ");
addButton(panel04, "\u2208 [in]", "insert \u0020in");
addButton(panel04, "\u2209 [notin]", "insert \u0020notin");
addButton(panel04, "\u2192", "insert \u0020\u2192\u0020");
addButton(panel04, "\u21D4", "insert \u21D4");
addButton(panel04, "\u221E [inf]", "insert \u221E");
addPaletteCard(paletteChoice, paletteCards, "Misc. Symbols", panel04);
palette.add(paletteChoice, "North");
palette.add(paletteCards, "Center");
controlPane.add(palette, "Center");
j.setVisible(true);
add(j, "Center");
 
JPanel panel05 = new JPanel();
panel05.setLayout(new GridLayout());
addButton(panel05, "multiple answers", "insert vlist(answer1,answer2,answer3,answer4)");
addButton(panel05, "ln", "append ln()");
addButton(panel05, "|x|", "append |x|");
addButton(panel05, "f \u00AF\u00B9(x)= [inverse]", "append f\u00AF\u00B9(x)=");
addPaletteCard(paletteChoice, paletteCards, "Misc.", panel05);
palette.add(paletteChoice, "North");
palette.add(paletteCards, "Center");
controlPane.add(palette, "Center");
j.setVisible(true);
add(j, "Center");
 
JPanel panel07 = new JPanel();
panel07.setLayout(new GridLayout());
addButton(panel07, "log", "append log()");
addButton(panel07, "<html><sup>2</sup>log</html>", "append \u00B2log()");
addButton(panel07, "<html><sup>3</sup>log</html>", "append \u00B3log()");
addButton(panel07, "<html><sup>4</sup>log</html>", "append \u2074log()");
addButton(panel07, "<html><sup>5</sup>log</html>", "append \u2075log()");
addButton(panel07, "<html><sup>6</sup>log</html>", "append \u2076log()");
addButton(panel07, "<html><sup>7</sup>log</html>", "append \u2077log()");
addButton(panel07, "<html><sup>8</sup>log</html>", "append \u2078log()");
addButton(panel07, "<html><sup>9</sup>log</html>", "append \u2079log()");
addPaletteCard(paletteChoice, paletteCards, "Log", panel07);
palette.add(paletteChoice, "North");
palette.add(paletteCards, "Center");
controlPane.add(palette, "Center");
j.setVisible(true);
add(j, "Center");
 
JPanel panel08 = new JPanel();
panel08.setLayout(new GridLayout());
addButton(panel08, "\u221A", "append sqrt()");
addButton(panel08, "<html><sup>3</sup>\u221A</html>", "append sqrt[3]()");
addButton(panel08, "<html><sup>4</sup>\u221A</html>", "append sqrt[4]()");
addButton(panel08, "<html><sup>5</sup>\u221A</html>", "append sqrt[5]()");
addButton(panel08, "<html><sup>6</sup>\u221A</html>", "append sqrt[6]()");
addButton(panel08, "<html><sup>7</sup>\u221A</html>", "append sqrt[7]()");
addButton(panel08, "<html><sup>8</sup>\u221A</html>", "append sqrt[8]()");
addButton(panel08, "<html><sup>n</sup>\u221A</html>", "append sqrt[n](p)");
addPaletteCard(paletteChoice, paletteCards, "\u221A", panel08);
palette.add(paletteChoice, "North");
palette.add(paletteCards, "Center");
controlPane.add(palette, "Center");
j.setVisible(true);
add(j, "Center");
 
JPanel panel09 = new JPanel();
panel09.setLayout(new GridLayout());
addButton(panel09, "\u03C0 [pi]", "insert \u0020pi ");
addButton(panel09, "sin()", "append sin()");
addButton(panel09, "sin\u00B2()", "append sin()^2");
addButton(panel09, "cos()", "append cos()");
addButton(panel09, "cos\u00B2()", "append cos()^2");
addButton(panel09, "tan()", "append tan()");
addButton(panel09, "tan\u00B2()", "append tan()^2");
addPaletteCard(paletteChoice, paletteCards, "Trigonometry", panel09);
palette.add(paletteChoice, "North");
palette.add(paletteCards, "Center");
controlPane.add(palette, "Center");
j.setVisible(true);
add(j, "Center");
 
JPanel panel10 = new JPanel();
panel10.setLayout(new GridLayout());
addButton(panel10, " < : > ", "append \u0020langle\u0020:\u0020rangle");
addButton(panel10, " [ : > ", "append \u0020lbracket\u0020:\u0020rangle");
addButton(panel10, " < : ] ", "append \u0020langle\u0020:\u0020rbracket");
addButton(panel10, " [ : ] ", "append \u0020lbracket\u0020:\u0020rbracket");
addButton(panel10, "-\u221E [-inf]", "insert -\u221E");
addButton(panel10, "+\u221E [+inf]", "insert +\u221E");
addPaletteCard(paletteChoice, paletteCards, "Domains I", panel10);
palette.add(paletteChoice, "North");
palette.add(paletteCards, "Center");
controlPane.add(palette, "Center");
j.setVisible(true);
add(j, "Center");
 
JPanel panel11 = new JPanel();
panel11.setLayout(new GridLayout());
addButton(panel11, "x \u2208 \u2115 \u2216 \u007B a \u003B b \u007D", "insert x\u2208\u2115\u0020\u2216\u0020\u007Ba:b:c\u007D");
addButton(panel11, "x \u2208 \u2124 \u2216 \u007B a \u003B b \u007D", "insert x\u2208\u2124\u0020\u2216\u0020\u007Ba:b:c\u007D");
addButton(panel11, "x \u2208 \u211A \u2216 \u007B a \u003B b \u007D", "insert x\u2208\u211A\u0020\u2216\u0020\u007Ba:b:c\u007D");
addButton(panel11, "x \u2208 \u211D \u2216 \u007B a \u003B b \u007D", "insert x\u2208\u211D\u0020\u2216\u0020\u007Ba:b:c\u007D");
addPaletteCard(paletteChoice, paletteCards, "Domains II", panel11);
palette.add(paletteChoice, "North");
palette.add(paletteCards, "Center");
controlPane.add(palette, "Center");
j.setVisible(true);
add(j, "Center");
JPanel panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
 
JPanel panel4 = new JPanel();
panel2.add(panel4, "South");
reportError("OK");
JPanel panel3 = new JPanel();
panel2.add(panel3, "West");
undoButton = addButton(panel3, "\u21A9", "undo");
redoButton = null;
addButton(panel3, "\261", "toggle_font", "Center");
controlPane.add(panel2, "South");
linearInput = new TextArea("",1,1,TextArea.SCROLLBARS_NONE);
linearInput.addTextListener(this);
linearInput.setFont(bigFont);
linearInput.setBackground(Color.white);
controlPane.add(linearInput, "North");
add(controlPane, "South");
setVisible(true);
setLinear("");
linearInput.requestFocus();
}
 
private void setLinear(String s){
markUndo();
linearInput.setText(s);
updateJomeView();
}
 
private void markUndo()
{
if(redoButton != null)
{
undoBuffer[undoBufferCursor] = linearInput.getText();
undoBufferCursor++;
if(undoBufferCursor >= undoBuffer.length)
undoBufferCursor = 0;
if(undoBufferValidSize < undoBuffer.length)
{
undoBufferValidSize++;
undoBufferValidSizeMax = undoBufferValidSize;
}
updateUndoRedoButtons();
} else
{
previousLinear = linearInput.getText();
}
}
 
private void redo()
{
if(undoBufferValidSize < undoBufferValidSizeMax)
{
undoBufferCursor++;
undoBufferValidSize++;
if(undoBufferCursor >= undoBuffer.length)
undoBufferCursor = 0;
linearInput.setText(undoBuffer[undoBufferCursor]);
}
updateUndoRedoButtons();
updateJomeView();
}
private void undo()
{
if(redoButton != null)
{
if(undoBufferValidSize > 0)
{
undoBufferValidSize--;
undoBufferCursor--;
if(undoBufferCursor < 0)
undoBufferCursor = undoBuffer.length - 1;
if(undoBuffer[undoBufferCursor] != null)
linearInput.setText(undoBuffer[undoBufferCursor]);
}
updateUndoRedoButtons();
} else
if(previousLinear != null)
{
String s = linearInput.getText();
linearInput.setText(previousLinear);
previousLinear = s;
}
updateJomeView();
}
 
private void updateUndoRedoButtons()
{
undoButton.setEnabled(undoBufferValidSize > 0);
redoButton.setEnabled(undoBufferValidSize < undoBufferValidSizeMax);
}
 
private void updateJomeView()
{
String s=linearInput.getText().toString();
s=filter2(s);
String applettext=readParams("helptext");
if(applettext!=null || applettext.length()>1){
applettext=filter1(applettext,1);
s=applettext+s;
s=s.toString();
}
j.setLinear(s);
}
public MathView()
{
standaloneWindow = null;
inAnApplet = true;
previousLinear = null;
undoBuffer = new String[50];
undoBufferCursor = 0;
undoBufferValidSize = 0;
undoBufferValidSizeMax = 0;
bigFont = new Font("Helvetica", 0, 32);
defaultFont = new Font("Helvetica", 0, 18);
}
 
public void actionPerformed(ActionEvent actionevent)
{
String s = actionevent.getActionCommand();
if(s.startsWith("append "))
{
markUndo();
linearInput.setText(linearInput.getText() + s.substring("append ".length()));
} else
 
if(s.startsWith("insert "))
{
markUndo();
String s1 = linearInput.getText();
int i = linearInput.getCaretPosition();
linearInput.setText(s1.substring(0, i) + s.substring("insert ".length()) + s1.substring(i));
} else
if(s.startsWith("enclose "))
{
markUndo();
String s2 = linearInput.getText();
String s3 = s.substring("append ".length(), s.length() - 1);
String s4 = s.substring(s.length() - 1);
int k = linearInput.getSelectionStart();
int l = linearInput.getSelectionEnd();
linearInput.setText(s2.substring(0, k) + s3 + linearInput.getSelectedText() + s4 + s2.substring(l));
} else
if(s.equals("undo"))
undo();
else
if(s.equals("redo"))
redo();
else
if(s.equals("toggle_font"))
{
toggleFont();
} else
{
updateJomeView();
}
}
 
public void itemStateChanged(ItemEvent itemevent)
{
 
paletteCardsLayout.show(paletteCards, (String)itemevent.getItem());
linearInput.requestFocus();
}
 
public void textValueChanged(TextEvent textevent)
{
updateJomeView();
}
 
public void windowOpened(WindowEvent windowevent)
{
}
 
public void windowIconified(WindowEvent windowevent)
{
}
 
public void windowDeiconified(WindowEvent windowevent)
{
}
 
public void windowActivated(WindowEvent windowevent)
{
}
 
public void windowDeactivated(WindowEvent windowevent)
{
}
 
public void windowResized(WindowEvent windowevent)
{
}
 
public void windowClosing(WindowEvent windowevent)
{
stop();
destroy();
if(!inAnApplet)
{
standaloneWindow.setVisible(false);
standaloneWindow.dispose();
}
}
 
 
public void windowClosed(WindowEvent windowevent)
{
System.exit(0);
}
 
public String getLinear(){
String S=j.getLinear(); int lu;
String applettext=readParams("helptext");
if(applettext!=null){
applettext=filter1(applettext , 1);
// cut helptext/applettext from the reply string
int li=applettext.length();
if(li > 0){
lu=S.length();
S=S.substring(li,lu);
}
}
// back to ascii wims/javascript processable syntax
S=filter1(S, 0);
S=root2sqrtn(S);
S=removespecial(S);
return S;
}
Jome j;
JFrame standaloneWindow;
JPanel controlPane;
JPanel palette;
JPanel paletteCards;
CardLayout paletteCardsLayout;
Choice paletteChoice;
TextArea linearInput;
JButton undoButton;
JButton redoButton;
boolean inAnApplet;
String previousLinear;
String undoBuffer[];
int undoBufferCursor;
int undoBufferValidSize;
int undoBufferValidSizeMax;
Font bigFont;
Font defaultFont;
boolean Special_Fraction=false; // param Special_Fraction inserts a "+" sign -> 1 1/2 == 1+1/2
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/ObjectsRepository.java
0,0 → 1,64
/*
$Id: ObjectsRepository.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import java.util.*;
 
/**
* A repository of the main objects used by the programm.
* <P>
* It is used as a repository of the different objects created that are
* supposed to be used (listener registering, ...) by other objects.
* Provide a convenient way to give the reference of objects to an another one.
* Rather than explicitly pass the reference to objects needed, pass the
* instance. The needed references are then obtains via a name that identifies
* the different objects.
*/
public class ObjectsRepository {
/**
* The repository
*/
private Hashtable repository;
/**
* The Constructor.
*/
public ObjectsRepository() {
repository = new Hashtable();
}
/**
* Puts an object with the specified name idenfier in the repository.
* @param object the object to add.
* @param name the name that identifies the object.
*/
public Object putObject(Object object, String name) {
return repository.put(name, object);
}
/**
* Gets the object with the specified name indentifier in the repository.
* @param name the name that identifies the object.
*/
public Object getObject(String name) {
return repository.get(name);
}
/**
* Remove the object with the specified name identifier from the repository.
* @param name the name that identifies the object.
*/
public Object removeObject(String name) {
return repository.remove(name);
}
/**
* Gets the repository.
*/
public Hashtable getRepository() {
return repository;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/ConnectionHandler.java
0,0 → 1,19
/*
$Id: ConnectionHandler.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import fr.ove.utils.Connection;
 
/**
* A connection handler.<BR>
*/
public interface ConnectionHandler {
/**
* Handles the specified connection.
* @param connection the connection to handle.
*/
public void handleConnection(Connection connection);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/Connection.java
0,0 → 1,140
/*
$Id: Connection.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import java.io.*;
import java.net.*;
 
/**
* A connection object.
* Opens a socket to the specified host on the specified port number.
*/
public class Connection implements ConnectionConfigurable {
/**
* The socket of the connection
*/
private Socket socket;
 
/**
* The input stream to read from the socket.
*/
private InputStream inputStream = null;
 
/**
* The output stream to write into the socket.
*/
private OutputStream outputStream = null;
 
/**
* The host name to connect.
*/
private String hostName;
 
/**
* The port number.
*/
private int portNumber;
 
/**
* The default constructor.
* The default host name is "localhost" and the default port number is 6666.
*/
public Connection() {
this("localhost", 6666);
}
 
/**
* The Constructor.
* @param hostName the host name.
* @param portNumber the port number.
*/
public Connection(String hostName, int portNumber) {
this.hostName = hostName;
this.portNumber = portNumber;
}
 
/**
* Sets the host name for the connection to create.
* @param name the host name.
*/
public void setHostName(String name) {
hostName = name;
}
 
/**
* Returns the host name for the connection to create.
*/
public String getHostName() {
return hostName;
}
 
/**
* Sets the port number for the connexion to create.
* @param number the port number.
*/
public void setPortNumber(int number) {
portNumber = number;
}
 
/**
* Returns the port number for the connexion to create.
*/
public int getPortNumber() {
return portNumber;
}
 
/**
* Opens the connection.
*/
public void open() throws IOException {
socket = new Socket(InetAddress.getByName(hostName), portNumber);
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
}
 
/**
* Opens the connection through the specified socket.
* @param socket the specified socket.
*/
public void open(Socket socket) throws IOException {
this.socket = socket;
hostName = socket.getInetAddress().getHostName();
portNumber = socket.getPort();
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
}
 
/**
* Checks wether the connection is opened.
*/
public boolean isOpened() {
return ((outputStream != null) && (inputStream != null));
}
 
/**
* Closes the connection.
*/
public void close() throws IOException {
outputStream.close();
inputStream.close();
outputStream = null;
inputStream = null;
}
 
/**
* Gets the input stream to read from the socket.
*/
public InputStream getInputStream() {
return inputStream;
}
 
/**
* Gets the output stream to write into the socket.
*/
public OutputStream getOutputStream() {
return outputStream;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/FileChooser.java
0,0 → 1,63
/*
$Id: FileChooser.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import javax.swing.JFileChooser;
import java.awt.Component;
import java.io.File;
 
/**
* A file chooser.
*/
public class FileChooser extends JFileChooser {
/**
*
*/
private Component compReference = null;
/**
* The Constructor.
*/
public FileChooser() {
this(null);
}
/**
* The Constructor.
*/
public FileChooser(Component compReference) {
super();
this.compReference = compReference;
}
/**
* Pops the instance for opening a file.
*/
public int showOpen() {
return showOpenDialog(compReference);
}
/**
* Pops the instance for saving a file.
*/
public int showSave() {
return showSaveDialog(compReference);
}
/**
*
*/
public void setCompReference(Component compReference) {
this.compReference = compReference;
}
/**
*
*/
public Component getCompReference() {
return compReference;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/ResourcesManager.java
0,0 → 1,86
/*
$Id: ResourcesManager.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import java.net.*;
import java.util.*;
 
/**
* A resources manager.<BR>
* All the resources are specified in a properties file, each property defined in a key = val1:val2:....:valn.<BR>
* The key represents the name of the property. The different vali the parameters identifying the property.<BR>
* Each parameter is separated by the ':' character.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 17/12/1999
*/
public class ResourcesManager implements java.io.Serializable {
private ResourceBundle resources;
/**
* Constructor
* @param resourcesName the name of the resources file. <BR> he name is specified without the ".properties"
* extension. If the property file is located in a package, the fully qualified name (e.g. my.package.filename)
* must be used.
*/
public ResourcesManager(String resourcesName) {
try {
//resources = ResourceBundle.getBundle(resourcesName, Locale.getDefault());
resources = ResourceBundle.getBundle(resourcesName);
}
catch (MissingResourceException mre) {
System.err.println(resourcesName+".properties not found");
System.exit(1);
}
}
 
/**
* Get the raw string for the given property
*/
public String getResourceString(String prop) {
String str;
try {
str = resources.getString(prop);
}
catch (MissingResourceException mre) {
str = null;
}
 
return str;
}
 
/**
* Get the resource strings for the given property
*/
public String [] getResourceStrings(String prop) {
return tokenize(getResourceString (prop));
}
 
/**
* Take the given string and chop it up into a series
* of strings on whitespace boundries. This is useful
* for trying to get an array of strings out of the
* resource file.
*/
private String[] tokenize(String input) {
if (input != null) {
Vector v = new Vector();
StringTokenizer t = new StringTokenizer (input, ":");
String cmd[];
 
while (t.hasMoreTokens())
v.addElement(t.nextToken());
cmd = new String[v.size()];
for (int i = 0; i < cmd.length; i++)
cmd[i] = (String) v.elementAt(i);
 
return cmd;
}
else
return new String [0];
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/Comparable.java
0,0 → 1,67
/*
$Id: Comparable.java,v 1.3 2003/02/18 11:48:48 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.utils;
 
/**
* The interface to implements to allow comparison abilities.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 02/07/1999
*/
public interface Comparable {
/**
* Tests if the instance is equal to the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isEqual(Comparable toCompare);
/**
* Tests if the instance is greater than the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isGreater(Comparable toCompare);
/**
* Tests if the instance is greater or equal than the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isGreaterOrEqual(Comparable toCompare);
/**
* Tests if the instance is lesser than the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isLesser(Comparable toCompare);
/**
* Tests if the instance is lesser or equal than the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isLesserOrEqual(Comparable toCompare);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/Factory.java
0,0 → 1,48
/*
$Id: Factory.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
/**
* A little factory to dynamically instanciate classes.
*
* @author © 1999 DIRAT Laurent
* @version 1.0 29/10/1999
*/
public class Factory implements java.io.Serializable {
/**
* Returns an instance of the class with the specified name.
* @param className the name of the class we want an instance.
*/
public static Object getClassInstance(String className) {
Object newClass = null;
try {
Class c = Class.forName(className);
try {
newClass = c.newInstance();
}
catch (InstantiationException e ) {
System.out.println(className + " cannot be instantiated");
return null;
}
catch (IllegalAccessException e ) {
System.out.println(className + " impossible to access default constructor");
return null;
}
catch (NoClassDefFoundError e ) {
System.out.println("No definition of " + className + " can be found");
}
 
}
catch (ClassNotFoundException e) {
System.out.println("Class " + className + " not found");
return null;
}
 
return newClass;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/Queueable.java
0,0 → 1,50
/*
$Id: Queueable.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import java.util.*;
 
/**
* Interface to respect to have a queue behaviour
*
* @author © 2000 DIRAT Laurent
* @version 1.0 28/06/2000
*/
 
public interface Queueable {
/**
* Adds the specified element to the queue
*/
public void enqueue(Object element);
 
/**
* Removes the first element added into the queue.
* Returns the element removed. <CODE>null</CODE> if the queue is empty
*/
public Object dequeue();
 
/**
* Returns the first element added into the queue.
* <CODE>null</CODE> if the queue is empty
*/
public Object peek();
 
/**
* Checks if the queue is empty.
* Returns <CODE>true</CODE> if the queue is empty. <CODE>false</CODE> otherwise.
*/
public boolean isEmpty();
/**
* Clears the queue
*/
public void clear();
/**
* Returns an @see Enumeration of the elements in the queue.
*/
public Enumeration elements();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/NumberUtils.java
0,0 → 1,69
/*
$Id: NumberUtils.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import java.text.NumberFormat;
 
/**
*
* @author © 1999 DIRAT Laurent
* @version 2.0 28/06/1999
*/
public class NumberUtils {
/**
* Analyzes a token and determines whether it is a number (integer or float) or
* not.<BR>
* If not, considers this token as a variable.
*
* @param token the token to anlazye.
* @return <CODE>true</CODE> if the token is a number. <CODE>false</CODE> otherwise.
*/
public static boolean isNumber(String token) {
char oneChar;
for (int i = 0; i < token.length(); i++) {
oneChar = token.charAt(i);
if (!Character.isDigit(oneChar) && (oneChar != '.'))
return false;
}
return true;
}
/**
* Analyzes the token and determines wheter it is an integer or a float. We assume that
* the specified token is already a number.
* @param token the token to analyze.
* @return <CODE>true</CODE> if the token is a float. <CODE>false</CODE>
* if the token is an integer.
*/
public static boolean isFloat(String token) {
for (int i = 0; i < token.length(); i++)
if (token.charAt(i) == '.')
return true;
return false;
}
/**
* Formats the specified double value with two digits after decimal place
* @param dValue the value to format.
*/
public static String formatDouble(String dValue) {
NumberFormat form;
form = NumberFormat.getInstance();//get local number format instance
form.setMaximumFractionDigits(2);//set for 2 digits only after decimal place
form.setMinimumFractionDigits(1);//set for 2 digits after decimal place
form.setGroupingUsed(false);//no comma for thousands
form.setMinimumIntegerDigits(1);//leading 0 if < 1
 
try {
return form.format((Double.valueOf(dValue)).doubleValue());
} catch (Exception execp) {
return dValue;
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/FormaterRepository.java
0,0 → 1,57
/*
$Id: FormaterRepository.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import fr.ove.utils.Formater;
 
/**
* A formater repository.<BR>
* The aim of this class is to format, as a string, an object by the means of @see Formater the instance manages.<BR>
* To each objet (or part of object) corresponds a @see Formater.
* <P>
* The different subclasses have to implement the @see format method in the @see Formater interface the instance
* pretends to implement.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 07/01/2000
*/
public abstract class FormaterRepository implements Formater {
private String indent = " ";
/**
* Returns the current indentation
*/
public String getIndent() {
return indent;
}
/**
* Increments the indentation.
*/
public void incIndent() {
indent += " ";
}
/**
* Decrements the indentation.
*/
public void decIndent() {
indent = indent.substring(0, indent.length() - 2);
}
/**
* Init indentation
*/
public void initIndent() {
indent = " ";
}
/**
* Returns the formater with the specified identifier.
* @param objectId the object (to format) identifier.
*/
public abstract Formater getFormater(String objectId);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/Formater.java
0,0 → 1,24
/*
$Id: Formater.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import fr.ove.utils.FormaterRepository;
 
/**
* The interface to implement to format an object as a string.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 07/01/2000
*/
public interface Formater {
/**
* Returns the specified object formatted as a string.
* @param formatedObject the formatted object (for structured object, could represents the beginning).
* @param formaterRepository where the different other formaters are.
* @param obj the object to format.
*/
public String format(String formatedObject, FormaterRepository formaterRepository, Object obj);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/LinkedElement.java
0,0 → 1,113
/*
$Id: LinkedElement.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import java.io.Serializable;
 
/**
* A element of linked structure (queue, lists, etc..
* <P>
* Contains the element added in the structure and the reference to the previous
* and the next element in the structure.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 28/06/2000
*/
public class LinkedElement implements Serializable {
/**
* The element in the structure.
*/
private Object element;
/**
* The previous element in the structure.
*/
private LinkedElement previous;
/**
* The next element in the structure.
*/
private LinkedElement next;
/**
* The default contstructor
*/
public LinkedElement() {
this(null);
}
/**
* The contstructor
* @param element the element in the structure
*/
public LinkedElement(Object element) {
this.element = element;
previous = null;
next = null;
}
/**
* Sets the element
*/
public void setElement(Object element) {
this.element = element;
}
/**
* Returns the element
*/
public Object getElement() {
return element;
}
/**
* Sets the previous element of the instance
*/
public void setPrevious(LinkedElement previous) {
this.previous = previous;
}
/**
* Returns the previous element of the instance
*/
public LinkedElement getPrevious() {
return previous;
}
/**
* Sets the next element of the instance
*/
public void setNext(LinkedElement next) {
this.next = next;
}
/**
* Returns the next element of the instance
*/
public LinkedElement getNext() {
return next;
}
/**
* Removes the instance from the structure
*/
public void remove() {
element = null;
if (previous != null)
previous.next = next;
if (next != null)
next.previous = previous;
}
/**
* Returns a string representation of the element
*/
public String toString() {
return element.toString();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/ConnectionConfigurable.java
0,0 → 1,34
/*
$Id: ConnectionConfigurable.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
/**
* The interface to implement for all objects that are intended to configure
* a connection.
*/
public interface ConnectionConfigurable {
/**
* Sets the host name for the connection to configure.
* @param name the host name.
*/
public void setHostName(String name);
/**
* Returns the host name for the connection to configure.
*/
public String getHostName();
/**
* Sets the port number for the connexion to configure.
* @param number the port number.
*/
public void setPortNumber(int number);
/**
* Returns the port number for the connexion to configure.
*/
public int getPortNumber() ;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/CachingResourcesManager.java
0,0 → 1,57
/*
$Id: CachingResourcesManager.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import fr.ove.utils.ResourcesManager;
 
/**
* The resources manager caching the last resource required.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 17/12/1999
*/
public class CachingResourcesManager extends ResourcesManager {
/**
* The last resource name accessed by the instance.
*/
private String cachedResource = "";
/**
* The list of properties associated to the last resource accessed by the instance.
*/
private String[] cachedProperties = null;
/**
* The Constructor.
* @param resourcesName the name of the resources file.
*/
public CachingResourcesManager(String resourcesName) {
super(resourcesName);
}
/**
* Returns the index-th resource of the specified property.
* @param propertyName the name of the property
* @param index the index of the resource
*/
public String accessResource(String resource, int index) {
String property = null;
if (!cachedResource.equals(resource)) {
String[] properties = getResourceStrings(resource);
if ((index >= 0) && (index < properties.length)) {
property = properties[index];
cachedResource = resource;
cachedProperties = properties;
}
}
else if ((index >= 0) && (index < cachedProperties.length))
property = cachedProperties[index];
return property;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/FontInfo.java
0,0 → 1,232
/*
$Id: FontInfo.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import java.awt.*;
import java.io.Serializable;
import java.awt.image.*;
 
/**
* A class that gives information about the font used.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 01/09/1999
*/
public class FontInfo implements Serializable {
/**
* Returns the thickness of the line elements of the characters in the specified font.<BR>
* Typically this corresponds to the width of the character '|'.
* @param component
* @param font the specified font
*/
public static int getLineThickness(Component component, Font font) {
// On créé une petite image contenant le caractère '-'.
// Le fond de cette image est blanc, tandis que le charactère est écrit en noir.
// Une fois l'image générée, on va en créer un tableau d'entier, que l'on va parcourir jusqu'à
// trouver un entier dont la valeur est différente de la valeur du blanc. (cela correspond à tomber
// sur le début du '-', l'image étant parcourrue de haut en bas). Tant que l'on trouve cette valeur,
// on est sur le '-'. Dès que l'on retombe sur la valeur du blanc, c'est qu'on est sorti du '-'.
// On a récupéré l'épaisseur du charactère.
// L'alignement sur le '-' correspond à la distance du haut de l'image sur le début du '-' plus la moitié
// de sa taille.
 
Graphics g = component.getGraphics();
// On récupère les caractéristiques de la police utilisée
FontMetrics fontMetrics = g.getFontMetrics(font);
int height = fontMetrics.getHeight();
int width = fontMetrics.stringWidth("-");
// On créé l'image où l'on va écrire les '|'
Image image = component.createImage(1, height);
g = image.getGraphics();
// Le fond est blanc et...
g.setColor(Color.white);
g.fillRect(0, 0, 1, height);
// ...on écrit en noir
g.setColor(Color.black);
g.setFont(font);
g.drawString("-", -width/2, fontMetrics.getAscent());
 
// On récupère un tableau d'entier de l'image
int img[] = new int[height];
PixelGrabber grabber = new PixelGrabber(image, 0, 0, 1, height, img, 0, 1);
try {
grabber.grabPixels();
}
catch (InterruptedException e) {
System.err.println("interrupted waiting for pixels!");
return -1;
}
 
if ((grabber.getStatus() & ImageObserver.ABORT) != 0) {
System.err.println("image fetch aborted or errored");
return -1;
}
 
int blanc = img[0];
int thickness = 0;
for (int i = 0; i < height; i++) {
if (img[i] == blanc) {
if (thickness == 0)
continue; // depuis le début on est sur du blanc, on continue le parcours de l'image
else
break; // on a trouvé du noir, et on retrouve du blanc, on a l'épaisseur, on arrête.
}
 
thickness++;
}
 
return (thickness > 0) ? thickness : 1;
}
/**
* Returns the width of the specified string, with the specified font.
* @param component
* @param font the specified font
* @param str the specified string.
*/
public static int getStringWidth(Component component, Font font, String str) {
Graphics g = component.getGraphics();
FontMetrics fontMetrics = g.getFontMetrics(font);
return fontMetrics.stringWidth(str);
}
/**
* Returns the ascent corresponding to the middle of the width of the minus character
* @param component
* @param font the specified font
*/
public static int getMinusAlignment(Component component, Font font) {
// On créé une petite image contenant le caractère '-'.
// Le fond de cette image est blanc, tandis que le charactère est écrit en noir.
// Une fois l'image générée, on va en créer un tableau d'entier, que l'on va parcourir jusqu'à
// trouver un entier dont la valeur est différente de la valeur du blanc. (cela correspond à tomber
// sur le début du '-', l'image étant parcourrue de haut en bas). Tant que l'on trouve cette valeur,
// on est sur le '-'. Dès que l'on retombe sur la valeur du blanc, c'est qu'on est sorti du '-'.
// On a récupéré l'épaisseur du charactère.
// L'alignement sur le '-' correspond à la distance du haut de l'image sur le début du '-' plus la moitié
// de sa taille.
 
Graphics g = component.getGraphics();
// On récupère les caractéristiques de la police utilisée
FontMetrics fontMetrics = g.getFontMetrics(font);
int height = fontMetrics.getHeight();
int width = fontMetrics.stringWidth("-");
// On créé l'image où l'on va écrire les '|'
Image image = component.createImage(1, height);
g = image.getGraphics();
// Le fond est blanc et...
g.setColor(Color.white);
g.fillRect(0, 0, 1, height);
// ...on écrit en noir
g.setColor(Color.black);
g.setFont(font);
g.drawString("-", -width/2, fontMetrics.getAscent());
 
// On récupère un tableau d'entier de l'image
int img[] = new int[height];
PixelGrabber grabber = new PixelGrabber(image, 0, 0, 1, height, img, 0, 1);
try {
grabber.grabPixels();
}
catch (InterruptedException e) {
System.err.println("interrupted waiting for pixels!");
return -1;
}
 
if ((grabber.getStatus() & ImageObserver.ABORT) != 0) {
System.err.println("image fetch aborted or errored");
return -1;
}
 
int blanc = img[0];
int thickness = 0;
int startMinus = 0;
for (int i = 0; i < height; i++) {
if (img[i] == blanc) {
if (thickness == 0) {
startMinus++;
continue; // depuis le début on est sur du blanc, on continue le parcours de l'image
}
else
break; // on a trouvé du noir, et on retrouve du blanc, on a l'épaisseur, on arrête.
}
 
thickness++;
}
thickness /= 2;
thickness = (thickness > 0) ? thickness : 1;
return startMinus + thickness;
}
public static int getPlusAlignment(Component component, Font font) {
// On créé une petite image contenant le caractère '-'.
// Le fond de cette image est blanc, tandis que le charactère est écrit en noir.
// Une fois l'image générée, on va en créer un tableau d'entier, que l'on va parcourir jusqu'à
// trouver un entier dont la valeur est différente de la valeur du blanc. (cela correspond à tomber
// sur le début du '-', l'image étant parcourrue de haut en bas). Tant que l'on trouve cette valeur,
// on est sur le '-'. Dès que l'on retombe sur la valeur du blanc, c'est qu'on est sorti du '-'.
// On a récupéré l'épaisseur du charactère.
// L'alignement sur le '-' correspond à la distance du haut de l'image sur le début du '-' plus la moitié
// de sa taille.
 
Graphics g = component.getGraphics();
// On récupère les caractéristiques de la police utilisée
FontMetrics fontMetrics = g.getFontMetrics(font);
int height = fontMetrics.getHeight();
int width = fontMetrics.stringWidth("+");
// On créé l'image où l'on va écrire les '|'
Image image = component.createImage(1, height);
g = image.getGraphics();
// Le fond est blanc et...
g.setColor(Color.white);
g.fillRect(0, 0, 1, height);
// ...on écrit en noir
g.setColor(Color.black);
g.setFont(font);
g.drawString("+", -width/2, fontMetrics.getAscent());
 
// On récupère un tableau d'entier de l'image
int img[] = new int[height];
PixelGrabber grabber = new PixelGrabber(image, 0, 0, 1, height, img, 0, 1);
try {
grabber.grabPixels();
}
catch (InterruptedException e) {
System.err.println("interrupted waiting for pixels!");
return -1;
}
 
if ((grabber.getStatus() & ImageObserver.ABORT) != 0) {
System.err.println("image fetch aborted or errored");
return -1;
}
 
int blanc = img[0];
int thickness = 0;
int startMinus = 0;
for (int i = 0; i < height; i++) {
if (img[i] == blanc) {
if (thickness == 0) {
startMinus++;
continue; // depuis le début on est sur du blanc, on continue le parcours de l'image
}
else
break; // on a trouvé du noir, et on retrouve du blanc, on a l'épaisseur, on arrête.
}
 
thickness++;
}
thickness /= 2;
thickness = (thickness > 0) ? thickness : 1;
return startMinus + thickness;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/GenericFileFilter.java
0,0 → 1,108
/*
$Id: GenericFileFilter.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import javax.swing.filechooser.FileFilter;
import java.io.File;
 
/**
* A file filter for the specified extension.
*/
public class GenericFileFilter extends FileFilter {
/**
* The type of files to filter.
*/
private String type;
/**
* The extension of files to filter.
*/
private String extension;
/**
* The default constructor. Builds a text files (with a txt extension) filter.
*/
public GenericFileFilter() {
this("Text", "txt");
}
/**
* The constructor.
* @param type the file type (e.g. Text, JPEG, etc).
* @param extension the file extension (e.g. txt, jpeg, etc).
*/
public GenericFileFilter(String type, String extension) {
this.type = type;
this.extension = extension;
}
/**
* Sets the file type.
* @param type the file type (e.g. Text, JPEG, etc).
*/
public void setType(String type) {
this.type = type;
}
/**
* Gets the file type.
*/
public String getType() {
return type;
}
/**
* Sets the file extension.
* @param extension the file extension (e.g. txt, jpeg, etc);
*/
public void setExtension(String extension) {
this.extension = extension;
}
/**
* Gets the file extension.
*/
public String getExtension() {
return extension;
}
/**
* Whether the given file is accepted by this filter.
* @param file the given file.
*/
public boolean accept(File file) {
boolean accept = file.isDirectory();
if (!accept) {
String suffix = getSuffix(file);
if (suffix != null)
accept = suffix.equals(extension);
}
return accept;
}
/**
* The description of this filter.
*/
public String getDescription() {
return type + " Files (*." + extension + ")";
}
/**
* Gets the suffix of the specified file.
* @param file the file.
*/
private String getSuffix(File file) {
String path = file.getPath();
String suffix = null;
int index = path.lastIndexOf('.');
if ((index > 0) && (index < (path.length() - 1)))
suffix = path.substring(index + 1).toLowerCase();
return suffix;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/Queue.java
0,0 → 1,208
/*
$Id: Queue.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import java.io.Serializable;
import java.util.*;
import fr.ove.utils.Queueable;
import fr.ove.utils.LinkedElement;
 
/**
* A queue.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 28/06/2000
*/
public class Queue implements Queueable, Serializable {
/**
* The head of the queue.
*/
private LinkedElement head;
/**
* The tail of the queue.
*/
private LinkedElement tail;
/**
* The number of elements.
*/
private int nbElements;
/**
* The Constructor
*/
public Queue() {
head = tail = null;
nbElements = 0;
}
/**
* Adds the specified element to the queue
*/
public void enqueue(Object element) {
LinkedElement newElement = new LinkedElement(element);
if (nbElements == 0)
head = tail = newElement;
else {
newElement.setNext(tail);
tail.setPrevious(newElement);
tail = newElement;
}
nbElements++;
}
 
/**
* Removes the first element added into the queue.
* Returns the element removed. <CODE>null</CODE> if the queue is empty.
*/
public Object dequeue() {
Object element = null;
if (nbElements != 0) {
LinkedElement dequeued = head;
element = dequeued.getElement();
head = dequeued.getPrevious();
dequeued.remove();
if (nbElements == 1)
head = tail = null;
nbElements--;
}
return element;
}
 
/**
* Returns the first element added into the queue.
* <CODE>null</CODE> if the queue is empty
*/
public Object peek() {
if (nbElements != 0)
return head.getElement();
else
return null;
}
 
/**
* Checks if the queue is empty.
* Returns <CODE>true</CODE> if the queue is empty. <CODE>false</CODE> otherwise.
*/
public boolean isEmpty() {
return (nbElements == 0);
}
/**
* Clears the queue
*/
public void clear() {
head = tail = null;
nbElements = 0;
}
/**
* Returns an @see Enumeration of the elements in the queue.
*/
public Enumeration elements() {
synchronized (this) {
return (Enumeration) new QueueEnumerator(this);
}
}
/**
* Returns an array of the elements contained in the queue.<BR>
* If the queue is empty, returns <CODE>null</CODE>.
*/
public Object[] getElements() {
Object elements[] = null;
if (nbElements != 0) {
elements = new Object[nbElements];
LinkedElement ptr = tail;
int index = 0;
while (ptr != null) {
elements[index++] = ptr.getElement();
ptr = ptr.getNext();
}
}
return elements;
}
/**
* Returns a string representation of the queue
*/
public String toString() {
String string = "";
LinkedElement ptr = tail;
while (ptr != null) {
string += " " + ptr.toString();
ptr = ptr.getNext();
}
return string + " ";
}
 
 
 
/*
* An Enumeration representation of a queue.
*/
private class QueueEnumerator implements Enumeration, Serializable {
/**
* The queue to enumerate
*/
Queue queue;
/**
* The next element in the queue;
*/
LinkedElement next;
/**
* The constructor
* @param queue the queue to enumerate
*/
public QueueEnumerator(Queue queue) {
this.queue = queue;
next = queue.head;
}
/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if this enumeration contains more elements;
* <code>false</code> otherwise.
*/
public boolean hasMoreElements() {
return (next != null);
}
 
/**
* Returns the next element of this enumeration.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
public Object nextElement() {
synchronized (queue) {
if (next != null) {
Object element = next.getElement();
next = next.getPrevious();
return element;
}
}
throw new NoSuchElementException("QueueEnumerator");
}
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/ByteVector.java
0,0 → 1,152
/*
$Id: ByteVector.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
public class ByteVector implements java.io.Serializable {
protected byte elementData[];
protected int elementCount;
protected int capacityIncrement;
 
public ByteVector(int initialCapacity, int capacityIncrement) {
super();
this.elementData = new byte[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
 
public ByteVector(int initialCapacity) {
this(initialCapacity, 5);
}
 
public ByteVector() {
this(10);
}
 
public final synchronized void trimToSize() {
int oldCapacity = elementData.length;
if (elementCount < oldCapacity) {
byte oldData[] = elementData;
elementData = new byte[elementCount];
System.arraycopy(oldData, 0, elementData, 0, elementCount);
}
}
 
public final int size() {
return elementCount;
}
 
public final boolean isEmpty() {
return elementCount == 0;
}
 
public final boolean contains(byte elem) {
return indexOf(elem, 0) >= 0;
}
 
public final int indexOf(byte elem) {
return indexOf(elem, 0);
}
 
public final synchronized int indexOf(byte elem, int index) {
for (int i = index; i < elementCount; i++) {
if (elem == elementData[i])
return i;
}
return -1;
}
 
public final synchronized byte elementAt(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
 
try {
return elementData[index];
} catch (ArrayIndexOutOfBoundsException e) {
throw new ArrayIndexOutOfBoundsException(index + " < 0");
}
}
 
public final synchronized void addElement(byte b) {
ensureCapacity(elementCount + 1);
elementData[elementCount++] = b;
}
 
public final synchronized void addElements(byte[] b) {
if (b != null) {
ensureCapacity(elementCount + b.length);
System.arraycopy(b, 0, elementData, elementCount, b.length);
elementCount += b.length;
}
else
throw new NullPointerException("Try to add null elements");
}
 
public final synchronized void addElements(byte[] b, int length) {
if (b != null) {
if ((length > 0) && (length <= b.length)) {
ensureCapacity(elementCount + b.length);
System.arraycopy(b, 0, elementData, elementCount, length);
elementCount += length;
}
else
throw new IllegalArgumentException("Invalid length argument : " + length);
}
else
throw new NullPointerException("Try to add null elements");
}
 
public final synchronized boolean removeElement(byte b) {
int i = indexOf(b);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
 
public final synchronized void removeElementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
}
 
public final synchronized void removeAllElements() {
elementCount = 0;
elementData = new byte[capacityIncrement];
}
 
public final synchronized byte[] getBytes() {
trimToSize();
return elementData;
}
 
public final synchronized void ensureCapacity(int minCapacity) {
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
byte oldData[] = elementData;
int newCapacity = (capacityIncrement > 0) ? (oldCapacity + capacityIncrement) : (oldCapacity * 2);
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = new byte[newCapacity];
System.arraycopy(oldData, 0, elementData, 0, elementCount);
}
}
 
public final synchronized String toString() {
String s = " [ ";
for (int i = 0 ; i <elementCount ; i++)
s += elementData[i] + " ";
s += "]";
return s;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/utils/ConnectionFactory.java
0,0 → 1,71
/*
$Id: ConnectionFactory.java,v 1.2 2003/02/18 11:48:48 sander Exp $
*/
 
 
package fr.ove.utils;
 
import fr.ove.utils.Connection;
 
/**
* A connection factory.
*/
public class ConnectionFactory implements ConnectionConfigurable {
/**
* The host name for the connection to create.
* The default host is localhost.
*/
private String hostName = "localhost";
/**
* The port number for the connection to create.
* The default port number is 6666;
*/
private int portNumber = 6666;
/**
* Sets the host name for the connection to create.
* @param name the host name.
*/
public void setHostName(String name) {
hostName = name;
}
/**
* Returns the host name for the connection to create.
*/
public String getHostName() {
return hostName;
}
/**
* Sets the port number for the connexion to create.
* @param number the port number.
*/
public void setPortNumber(int number) {
portNumber = number;
}
/**
* Returns the port number for the connexion to create.
*/
public int getPortNumber() {
return portNumber;
}
/**
* Returns a connection with the set parameters.
*/
public Connection createConnection() {
return new Connection(hostName, portNumber);
}
/**
* Returns a connection with the specified parameters.
* @param hostName the host name.
* @param portNumber the port number.
*/
public static Connection createConnection(String hostName, int portNumber) {
return new Connection(hostName, portNumber);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/errordialog/MainPanelError.java
0,0 → 1,227
/*
$Id: MainPanelError.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.errordialog;
 
import java.awt.*;
import java.awt.event.*;
import fr.ove.errordialog.*;
//import fr.ove.utils.PanelImage;
 
/**
* A panel to insert in the <CODE>fr.ove.errordialog.ErrorDialod</CODE> dialog
* box to display an error.
* The instance can display specific error message and give more details about
* the error.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 13/04/99
*/
public class MainPanelError extends Panel {
Panel panelError;
Panel panelErrorName;
PanelImage smileyL, smileyR;
Label labelErrorName;
Panel panelErrorMesgs;
Label labelMesg1;
Label labelMesg2;
Label labelMesg3;
Panel panelButton;
Button buttonCloseWindow;
Button buttonDetails;
TextArea details;
Window window;
/**
* The constructor
*/
public MainPanelError (Window theWindow, String errorMessage) {
window = theWindow;
Font commonFont = new Font("Dialog", Font.PLAIN, 14);
// Le panel qui contient tout ce qui est information de l'erreur (le nom, les messages, ...)
setLayout(new BorderLayout(0,0));
panelError = new Panel();
panelError.setLayout(new BorderLayout(0,0));
add("North", panelError);
// Le panel qui contient le nom de l'erreur (avec le smiley)
panelErrorName = new Panel();
panelErrorName.setLayout(new BorderLayout(0,0));
panelErrorName.setBackground(Color.white);
panelError.add("North", panelErrorName);
try {
// Comme PanelImage est dans un autre package que le courant il faut que l'on donne
// le chemin de l'image à charger relativement au package de PanelImage.
// Donc :
// PanelImage est dans le package fr.ove.utils
// L'instance dans le package fr.ove.errordialog, répertoire ou se trouve smiley.gif
// D'où le chemin ../errordialog/smiley.gif
//smileyL = new PanelImage("../errordialog/smiley.gif");
// Bon on verra cette histoire si on refait passer PanelImage dans fr.ove.utils et l'image
// ailleurs
smileyL = new PanelImage("smiley.gif");
panelErrorName.add("West", smileyL);
}
catch(Exception e) {
e.printStackTrace();
}
labelErrorName = new Label(errorMessage, Label.CENTER);
labelErrorName.setFont(new Font("Dialog", Font.PLAIN, 20));
panelErrorName.add("Center", labelErrorName);
try {
//smileyR = new PanelImage("../errordialog/smiley.gif");
smileyR = new PanelImage("smiley.gif");
panelErrorName.add("East", smileyR);
}
catch(Exception e) {
e.printStackTrace();
}
 
// Le panel qui contient tous les messages et boutons de commande
panelErrorMesgs = new Panel();
panelErrorMesgs.setLayout(new GridLayout(4,1,0,0));
panelError.add("Center", panelErrorMesgs);
// Un message d'erreur
labelMesg1 = new Label("",Label.CENTER);
labelMesg1.setFont(commonFont);
panelErrorMesgs.add(labelMesg1);
// Un autre message d'erreur
labelMesg2 = new Label("",Label.CENTER);
labelMesg2.setFont(commonFont);
panelErrorMesgs.add(labelMesg2);
// Et le dernier
labelMesg3 = new Label("",Label.CENTER);
labelMesg3.setFont(commonFont);
panelErrorMesgs.add(labelMesg3);
// Le panel qui contient les boutons de commande
panelButton = new Panel();
panelButton.setLayout(new FlowLayout(FlowLayout.CENTER,80,5));
panelErrorMesgs.add(panelButton);
 
// On ferme la la fenêtre qui contient notre instance
buttonCloseWindow = new Button();
buttonCloseWindow.setLabel("Close Window");
buttonCloseWindow.setFont(commonFont);
panelButton.add(buttonCloseWindow);
// On montre ou cache les détails
buttonDetails = new Button();
buttonDetails.setLabel("Show Details >>");
buttonDetails.setFont(commonFont);
panelButton.add(buttonDetails);
// Les éventuels détails de l'erreur
details = new TextArea();
//add("Center", details);
// La gestion des actions
// On affiche ou on cache les détails de l'erreur
buttonDetails.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
Button button = (Button) event.getSource();
String label = button.getLabel();
Dimension size = window.getSize();
if (label.equals("Show Details >>")) {
button.setLabel("Hide Details <<");
MainPanelError.this.add("Center", details);
size.height += 250;
}
else {
button.setLabel("Show Details >>");
MainPanelError.this.remove(details);
size.height -= 250;
}
window.setSize(size);
window.validate();
}
}
);
// On ferme le fenêtre d'erreur
buttonCloseWindow.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
window.setVisible(false);
}
}
);
}
/**
* Sets the first of the three messages that can be displayed
* @param mesg the error message
*/
public void setMesg1(String mesg) {
labelMesg1.setText(mesg);
}
/**
* Sets the second of the three messages that can be displayed
* @param mesg the error message
*/
public void setMesg2(String mesg) {
labelMesg2.setText(mesg);
}
/**
* Sets the third of the three messages that can be displayed
* @param mesg the error message
*/
public void setMesg3(String mesg) {
labelMesg3.setText(mesg);
}
/**
* Sets the details of the error
* @param theDetails the details of the error
*/
public void setDetails(String theDetails) {
details.setText(theDetails);
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/errordialog/PanelImage.java
0,0 → 1,124
/*
$Id: PanelImage.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.errordialog;
 
import java.awt.*;
import java.io.*;
import fr.ove.utils.ByteVector;
 
/**
* A simple panel that contains an image to display.<BR>
* The image to display must be in the same package of the instance.
* (possibly the subpackages with the correct path specified in the
* constructo)
*
* @author © 1998 DIRAT Laurent
* @version 1.0 13/04/99
*/
 
/* The image is loaded fom the package of the instance fr.ove.utils.<BR>
* So when we create a new instance, the path of the image to load must
* must be relatif to fr.ove.utils.
* For example, in the package fr.ove.errordialog we create a PanelImage with
* the smiley.gif image (in the same directory/package), so the instanciation
* must be new <CODE>PanelImage("../errordialog/smiley.gif");</CODE> to respect
* the requirements aforementioned.
*/
public class PanelImage extends Panel {
private Image image;
/**
* The constructor.
* @param imageName the name of the image the instance displays.
*/
public PanelImage(String imageName) throws Exception {
java.io.InputStream iStream = getClass().getResourceAsStream(imageName);
try {
/*
int avaliable = iStream.available();
byte imageBytes[] = new byte[avaliable];
int bytesRead = iStream.read(imageBytes);
bytesRead = iStream.read(imageBytes);
image = (Toolkit.getDefaultToolkit()).createImage(imageBytes);
iStream.close();
*/
int read;
ByteVector byteImage = new ByteVector();
while ((read = iStream.read()) != -1) {
byteImage.addElement((byte) read);
if (iStream.available() == 0)
break;
}
image = (Toolkit.getDefaultToolkit()).createImage(byteImage.getBytes());
iStream.close();
}
catch (IOException e){
System.out.println("Impossible to read image : IO problems");
e.printStackTrace();
}
catch (Exception e){
System.out.println("Impossible to create image");
e.printStackTrace();
}
if (image != null) {
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(image, 0);
// On attend que toutes les images soient chargées.
try {
tracker.waitForAll();
}
catch (InterruptedException e) {
System.out.print(e.toString());
}
if (tracker.isErrorAny())
throw new Exception("Impossible to load image");
}
}
/**
* Returns the preferred size of the instance.
*/
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(this), image.getHeight(this));
}
/**
* Paints the instance.
* @param g the graphics where to paint.
*/
public void paint(Graphics g) {
g.drawImage(image, 0, 0, this);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/errordialog/ErrorDialog.java
0,0 → 1,63
/*
$Id: ErrorDialog.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.errordialog;
 
import java.awt.*;
import java.awt.event.*;
 
/**
* A dialog box for error messages.<BR>
* The error messages must take the form of a <CODE>java.awt.Component</CODE>
* (and subclasses), that way sophisticated managment errors can be achieved.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 13/04/99
*/
public class ErrorDialog extends Dialog {
public ErrorDialog(Frame parent, boolean modal) {
super(parent, modal);
setLayout(new BorderLayout(0, 0));
setTitle("Oups, we've got a problem...");
addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent event) {
dispose();
}
}
);
}
public void addMesg(Component mesg) {
add("Center", mesg);
validate();
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/behaviour/Modifiable.java
0,0 → 1,48
/*
$Id: Modifiable.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.behaviour;
 
/**
* The interface to implement if we want to modifiable.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/07/1999
*/
public interface Modifiable {
/**
* Sets a value to the instance.<BR>
* @param value the value to set.
*/
public void setValue(String value);
/**
* Returns the current value of the instance.
*/
public String getValue();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/behaviour/Maskable.java
0,0 → 1,49
/*
$Id: Maskable.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.behaviour;
 
/**
* Interface that must implement all objects that want to be visible or not.<BR>
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public interface Maskable {
/**
* Sets the instance as vissible or not.
* @param isVisible <CODE>true</CODE> if the instance is visible. <CODE>false</CODE> otherwise.
*/
public void setIsVisble(boolean isVisible);
 
/**
* Checks if the instance is visible.
* @returns <CODE>true</CODE> if the instance is visible. <CODE>false</CODE> otherwise.
*/
public boolean isVisible();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/behaviour/Selectable.java
0,0 → 1,76
/*
$Id: Selectable.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.behaviour;
 
/**
* The interface to implement if we want selection abilities.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/06/1999
*/
public interface Selectable {
/**
* Selects the instance.<BR>
* In the case of an instance composed by different elements (for example trees), this
* method is recursive, and then selects the different elements.
*/
public void select();
/**
* Marks the instance as selected.
*/
public void setSelected();
/**
* Deselects the instance.<BR>
* In the case of an instance composed by different elements (for example trees), this
* method is recursive, and then deselects the different elements.
*/
public void deselect();
/**
* Marks the instance as not selected.
*/
public void setNotSelected();
/**
* Checks if the instance is selected.
* @returns <CODE>true</CODE> if the instance is selected. <CODE>false</CODE>
* otherwise.
*/
public boolean isSelected();
/**
* In the case of an instance composed by different elements (for example trees), this
* method checks if there are some selected elements.
* @returns <CODE>true</CODE> if the instance has selected elements. <CODE>false</CODE>
* otherwise.
*/
public boolean gotSelectedElements();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/behaviour/Iconifiable.java
0,0 → 1,91
/*
$Id: Iconifiable.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.behaviour;
 
/**
* Interface that must implement all objects that want to be iconified and then uniconified.<BR>
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/06/1999
*/
public interface Iconifiable {
/**
* Associates an icon name to the instance.
*
* @param iconName the name of the icon
*/
public void setIconName(String iconName);
 
/**
* Returns the name of the icon associated to the instance.
*
* @returns The name of the icon, or <CODE>null</CODE> if there is no name
* associated.
*/
public String getIconName();
/**
* @return <CODE>true</CODE> if the instance is an icon. <CODE>false</CODE> otherwise.
*/
public boolean isIcon();
/**
* Iconifies the selection of the instance.<BR>
* An icon, can't be inconified. But, we can inconify icons _plus_
* non-icon parts. The process works as russian dolls.
*/
public void iconify();
/**
* Uniconifies all the selected icons.<BR>
* If the icons contains other icons, these are _not_ uniconified. There is no
* recursion process.
*/
public void uniconify();
/**
* Uniconifies all the selected icons.<BR>
* If the icons contains other icons, these are uniconified. There is a
* recursion process.
*/
public void uniconifyAll();
/**
* Sets the istance as iconifiable.
* @param isIconifiable <CODE>true</CODE> if the instance is iconifiable.
* <CODE>false</CODE> otherwise.
*/
public void setIsIconifiable(boolean isIconifiable);
/**
* Returns <CODE>true</CODE> if the instance is iconifiable.
* <CODE>false</CODE> otherwise.
*/
public boolean isIconifiable();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/LinearParserBeanInfo.java
0,0 → 1,92
/*
$Id: LinearParserBeanInfo.java,v 1.4 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrl.linear;
 
import java.beans.*;
import java.beans.SimpleBeanInfo;
//import symantec.itools.beans.*;
 
public class LinearParserBeanInfo extends java.beans.SimpleBeanInfo
{
public LinearParserBeanInfo()
{
}
 
/**
* Gets a BeanInfo for the superclass of this bean.
* @return BeanInfo[] containing this bean's superclass BeanInfo
*/
public BeanInfo[] getAdditionalBeanInfo()
{
try
{
BeanInfo[] bi = new BeanInfo[1];
bi[0] = Introspector.getBeanInfo(beanClass.getSuperclass());
return bi;
}
catch (IntrospectionException e)
{
throw new Error(e.toString());
}
}
 
/**
* Gets the SymantecBeanDescriptor for this bean.
* @return an object of type SymantecBeanDescriptor
* @see symantec.itools.beans.SymantecBeanDescriptor
*/
public BeanDescriptor getBeanDescriptor()
{
BeanDescriptor bd = new BeanDescriptor(beanClass);
return bd;
}
 
/**
* Gets an image that may be used to visually represent this bean
* (in the toolbar, on a form, etc).
* @param iconKind the type of icon desired, one of: BeanInfo.ICON_MONO_16x16,
* BeanInfo.ICON_COLOR_16x16, BeanInfo.ICON_MONO_32x32, or BeanInfo.ICON_COLOR_32x32.
* @return an image for this bean
* @see BeanInfo#ICON_MONO_16x16
* @see BeanInfo#ICON_COLOR_16x16
* @see BeanInfo#ICON_MONO_32x32
* @see BeanInfo#ICON_COLOR_32x32
*/
public java.awt.Image getIcon(int nIconKind)
{
java.awt.Image img = null;
if (nIconKind == BeanInfo.ICON_COLOR_16x16)
img = loadImage("LinearParser_16.gif");
if (nIconKind == BeanInfo.ICON_COLOR_32x32)
img = loadImage("LinearParser_32.gif");
return img;
}
 
private final static Class beanClass = LinearParser.class;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/LinearParserResources.properties
0,0 → 1,104
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
# The resources file for the linear parser.
# This file serves as a definition file for all the words the parser
# should consider as specific keywords.
# By default, when an identificator during the parsing is found, if it is not immediately
# followed by a "(" which means we have a function name, the identificator is considered as
# a variable. To consider this identificator as it should be, it is defined in this file.
#
# The format of this file is a succesion of line such as : key = value.
# "key" represents the word we want it to be treated as a specific keyword
# "value" can only have 2 values : RESERVED or SPECIALIZED.
# These specific value are constant defined in the LinearParserEvent class.
# The one currently used is RESERVED which, as its name should say, it a reserved word
# SPECIALIZED was defined in order to specialise some operators to give them extra definition.
# but it is not used for the moment (will it be...)
 
# Defined sets
C = RESERVED
N = RESERVED
Q = RESERVED
R = RESERVED
Z = RESERVED
 
# Sets operators
in = RESERVED
notin = RESERVED
 
# Special symbols
pi = RESERVED
 
langle = RESERVED
rangle = RESERVED
lbracket = RESERVED
rbracket = RESERVED
cup = RESERVED
mapsto = RESERVED
and = RESERVED
or = RESERVED
rightarrow = RESERVED
\u2192 = RESERVED
\u21D4 = RESERVED
\u211E = RESERVED
 
# exp(1)
E = RESERVED
 
# I \I^2 = -1
I = RESERVED
o = RESERVED
 
# Infinity symbol
infty = RESERVED
 
# Logic values
true = RESERVED
false = RESERVED
 
 
# Greek letters
delta = RESERVED
gamma = RESERVED
alpha = RESERVED
alfa = RESERVED
beta = RESERVED
chi = RESERVED
epsilon = RESERVED
eta = RESERVED
iota = RESERVED
kappa = RESERVED
mu = RESERVED
nabla = RESERVED
nu = RESERVED
omega = RESERVED
phi = RESERVED
psi = RESERVED
rho = RESERVED
tau = RESERVED
theta = RESERVED
upsilon = RESERVED
zeta = RESERVED
xi = RESERVED
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/LinearParserResources_en.properties
0,0 → 1,104
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
# The resources file for the linear parser.
# This file serves as a definition file for all the words the parser
# should consider as specific keywords.
# By default, when an identificator during the parsing is found, if it is not immediately
# followed by a "(" which means we have a function name, the identificator is considered as
# a variable. To consider this identificator as it should be, it is defined in this file.
#
# The format of this file is a succesion of line such as : key = value.
# "key" represents the word we want it to be treated as a specific keyword
# "value" can only have 2 values : RESERVED or SPECIALIZED.
# These specific value are constant defined in the LinearParserEvent class.
# The one currently used is RESERVED which, as its name should say, it a reserved word
# SPECIALIZED was defined in order to specialise some operators to give them extra definition.
# but it is not used for the moment (will it be...)
 
# Defined sets
C = RESERVED
N = RESERVED
Q = RESERVED
R = RESERVED
Z = RESERVED
 
# Sets operators
in = RESERVED
notin = RESERVED
 
# Special symbols
pi = RESERVED
 
langle = RESERVED
rangle = RESERVED
lbracket = RESERVED
rbracket = RESERVED
cup = RESERVED
mapsto = RESERVED
and = RESERVED
or = RESERVED
rightarrow = RESERVED
\u2192 = RESERVED
\u21D4 = RESERVED
\u211E = RESERVED
 
# exp(1)
E = RESERVED
 
# I \I^2 = -1
I = RESERVED
o = RESERVED
 
# Infinity symbol
infty = RESERVED
 
# Logic values
true = RESERVED
false = RESERVED
 
 
# Greek letters
delta = RESERVED
gamma = RESERVED
alpha = RESERVED
alfa = RESERVED
beta = RESERVED
chi = RESERVED
epsilon = RESERVED
eta = RESERVED
iota = RESERVED
kappa = RESERVED
mu = RESERVED
nabla = RESERVED
nu = RESERVED
omega = RESERVED
phi = RESERVED
psi = RESERVED
rho = RESERVED
tau = RESERVED
theta = RESERVED
upsilon = RESERVED
zeta = RESERVED
xi = RESERVED
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/LinearParserResources.java
0,0 → 1,3
package fr.ove.openmath.jome.ctrl.linear;
public class LinearParserResources{
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/LinearParserResources_en.java
0,0 → 1,3
package fr.ove.openmath.jome.ctrl.linear;
public class LinearParserResources_en{
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/events/LinearParserEventSource.java
0,0 → 1,55
/*
$Id: LinearParserEventSource.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrl.linear.events;
 
/**
* the interface to implement to become a LinearParserEvent event source.
*
* @author © 1999 DIRAT Laurent
* @version 1.0 06/10/1999
*/
public interface LinearParserEventSource {
/**
* Registers another listener of the instance.
* @param linearParserListener the listener to add.
*/
public void addLinearParserListener(LinearParserListener linearParserListener);
 
/**
* Removes a listener.
* @param linearParserListener the listener to remove.
*/
public void removeLinearParserListener(LinearParserListener linearParserListener);
 
/**
* Fires a LinearParserEvent event to registered listeners.
* @param linearParserEvent event encapsulating relevant information.
*/
public void fireLinearParserEvent(LinearParserEvent linearParserEvent);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/events/LinearParserListener.java
0,0 → 1,46
/*
$Id: LinearParserListener.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrl.linear.events;
 
import java.util.EventListener;
import fr.ove.openmath.jome.ctrl.linear.events.LinearParserEvent;
 
/**
* The interface to implement in order to receive @see LinearParserEvent.
*
* @author © 1999 DIRAT Laurent
* @version 1.0 27/09/1999
*/
public interface LinearParserListener extends EventListener {
/**
* Treats the event received.
* @param linearParserEvent the event received.
*/
public void consumeLinearParserEvent(LinearParserEvent linearParserEvent);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/events/LinearParserEvent.java
0,0 → 1,284
/*
$Id: LinearParserEvent.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrl.linear.events;
 
import java.util.EventObject;
 
/**
* The event sent during the parsing of a linear form of an expression.<BR>
* Each event sent corresponds to token in the expression parsed. The tokens are the following :
* <UL>
* <LI> VARIABLE when a variable is encountered in the expression </LI>
* <LI> INTEGER when an integer is encountered in the expression </LI>
* <LI> FLOAT when a real number is encountered in the expression </LI>
* <LI> ADDITION when the + operator is encountered in the expression </LI>
* <LI> SUBSTRACTION when the - operator is encountered in the expression </LI>
* <LI> MULTIPLICATION when the * operator is encountered in the expression </LI>
* <LI> DIVISION when the / operator is encountered in the expression </LI>
* <LI> POWER when the ^ operator is encountered in the expression </LI>
* <LI> EQUAL when the = operator is encountered in the expression </LI>
* <LI> UNEQUAL when the <> operator is encountered in the expression </LI>
* <LI> LESS when the < operator is encountered in the expression </LI>
* <LI> LESSEQUAL when the <= operator is encountered in the expression </LI>
* <LI> GREATER when the > operator is encountered in the expression </LI>
* <LI> GREATEREQUAL when the >= operator is encountered in the expression </LI>
* <LI> FUNCTION when a name of a function (an function is expected to be an identificator immediately followed
* by an opening parenthesis) is encountered in the expression </LI>
* <LI> SEPARATOR when a separator (, or ;) is encountered in the expression </LI>
* <LI> OPEN_PAREN when an opening paranthesis is encountered in the expression </LI>
* <LI> CLOSE_PAREN when a closing paranthesis is encountered in the expression </LI>
* <LI> OPEN_BRACKET when an opening bracket is encountered in the expression </LI>
* <LI> CLOSE_BRACKET when a closing bracket is encountered in the expression </LI>
* <LI> OPEN_CURLY when an opening curly brace is encountered in the expression </LI>
* <LI> CLOSE_CURLY when a closing curly brace is encountered in the expression </LI>
* <LI> UNDERSCRIPT when the underscript (_) operator is encountered in the expression </LI>
* </UL>
*
* There exists other token identifiers :
* <UL>
* <LI> RESERVED when a specific keyword (define in the property file of the parser) is encountered
* in the expression </LI>
* <LI> SPECIALIZED when a specialized operator is encountered in the expression.<BR>
* (not really clearly defined :o( )</LI>
* </UL>
*
* Finally, 2 other token identifiers dealing with the parsing itself.
* <UL>
* <LI> START_EXPRESSION when the parsing of the expression starts </LI>
* <LI> END_EXPRESSION when the parsing of the expression ends </LI>
* </UL>
*
* @author © 1999 DIRAT Laurent
* @version 1.0 27/09/1999
*/
public class LinearParserEvent extends EventObject {
/**
* The token identifier.
*/
private int identifier;
 
/**
* The token value.
*/
private String value;
 
/**
* The constructor.
* @param src the object which produces this event.
*/
public LinearParserEvent(Object src) {
super(src);
}
 
/**
* Sets the identifier of the token and its value, if needed.
* @param identifier the token identifier.
* @param value the token value.
*/
public void setToken(int identifier, String value) {
this.identifier = identifier;
this.value = value;
}
 
/**
* Returns the identifier of the token wrapped into the event.
*/
public int getIdentifier() {
return identifier;
}
 
/**
* Returns the identifier of the token wrapped into the event, as a string
*/
public String getIdentifierAsString() {
String str = "";
 
switch (identifier) {
case SPACE : str += "SPACE"; break;
case VARIABLE : str += "VARIABLE"; break;
case INTEGER : str += "INTEGER"; break;
case FLOAT : str += "FLOAT"; break;
case ADDITION : str += "ADDITION"; break;
case SUBSTRACTION : str += "SUBSTRACTION"; break;
case MULTIPLICATION: str += "MULTIPLICATION"; break;
case DIVISION : str += "DIVISION"; break;
case POWER : str += "POWER"; break;
case EQUAL : str += "EQUAL"; break;
case UNEQUAL : str += "UNEQUAL"; break;
case LESS : str += "LESS"; break;
case LESSEQUAL : str += "LESSEQUAL"; break;
case GREATER : str += "GREATER"; break;
case GREATEREQUAL : str += "GREATEREQUAL"; break;
case FUNCTION : str += "FUNCTION"; break;
case SEPARATOR : str += "SEPARATOR"; break;
case OPEN_PAREN : str += "OPEN_PAREN"; break;
case CLOSE_PAREN : str += "CLOSE_PAREN"; break;
case OPEN_BRACKET : str += "OPEN_BRACKET"; break;
case CLOSE_BRACKET : str += "CLOSE_BRACKET"; break;
case OPEN_CURLY : str += "OPEN_CURLY"; break;
case CLOSE_CURLY : str += "CLOSE_CURLY"; break;
case UNDERSCRIPT : str += "UNDERSCRIPT"; break;
case RESERVED : str += "RESERVED"; break;
case SPECIALIZED : str += "SPECIALIZED"; break;
case START_EXPRESSION : str += "START_EXPRESSION"; break;
case END_EXPRESSION : str += "END_EXPRESSION"; break;
}
 
return str;
}
/**
* Returns the int value of the specified identifier string representation .
*/
public static int getStringIdentifierAsInt(String identifier) {
int value = 0;
 
if (identifier.equals("SPACE"))
value = 0;
if (identifier.equals("VARIABLE"))
value = 1;
else if (identifier.equals("INTEGER"))
value = 2;
else if (identifier.equals("FLOAT"))
value = 3;
else if (identifier.equals("ADDITION"))
value = 4;
else if (identifier.equals("SUBSTRACTION"))
value = 5;
else if (identifier.equals("MULTIPLICATION"))
value = 6;
else if (identifier.equals("DIVISION"))
value = 7;
else if (identifier.equals("POWER"))
value = 8;
else if (identifier.equals("EQUAL"))
value = 9;
else if (identifier.equals("UNEQUAL"))
value = 10;
else if (identifier.equals("LESS"))
value = 11;
else if (identifier.equals("LESSEQUAL"))
value = 12;
else if (identifier.equals("GREATER"))
value = 13;
else if (identifier.equals("GREATEREQUAL"))
value = 14;
else if (identifier.equals("FUNCTION"))
value = 15;
else if (identifier.equals("SEPARATOR"))
value = 16;
else if (identifier.equals("OPEN_PAREN"))
value = 17;
else if (identifier.equals("CLOSE_PAREN"))
value = 18;
else if (identifier.equals("OPEN_BRACKET"))
value = 19;
else if (identifier.equals("CLOSE_BRACKET"))
value = 20;
else if (identifier.equals("OPEN_CURLY"))
value = 21;
else if (identifier.equals("CLOSE_CURLY"))
value = 22;
else if (identifier.equals("RESERVED"))
value = 23;
else if (identifier.equals("UNDERSCRIPT"))
value = 24;
else if (identifier.equals("SPECIALIZED"))
value = 25;
else if (identifier.equals("START_EXPRESSION"))
value = 26;
else if (identifier.equals("END_EXPRESSION"))
value = 27;
 
return value;
}
/**
* Returns the value of the identifier.
*/
public String getValue() {
return value;
}
/**
* Returns a @see String representation of the instance.<BR>
* Mainly for debugg.
*/
public String toString() {
return getIdentifierAsString() + "\t" + value;
}
 
/**
* The different command tokens.
*/
 
// The basic elements of a formula
public static final int SPACE = 0;
public static final int VARIABLE = 1;
public static final int INTEGER = 2;
public static final int FLOAT = 3;
 
// The basic operators
public static final int ADDITION = 4;
public static final int SUBSTRACTION = 5;
public static final int MULTIPLICATION = 6;
public static final int DIVISION = 7;
public static final int POWER = 8;
 
// The relational operators
public static final int EQUAL = 9;
public static final int UNEQUAL = 10;
public static final int LESS = 11;
public static final int LESSEQUAL = 12;
public static final int GREATER = 13;
public static final int GREATEREQUAL = 14;
 
// Special operators
public static final int FUNCTION = 15;
public static final int SEPARATOR = 16;
 
// The different kinds of bracket
public static final int OPEN_PAREN = 17;
public static final int CLOSE_PAREN = 18;
public static final int OPEN_BRACKET = 19;
public static final int CLOSE_BRACKET = 20;
public static final int OPEN_CURLY = 21;
public static final int CLOSE_CURLY = 22;
 
// Special terminals
public static final int RESERVED = 23;
 
// Special operators
public static final int UNDERSCRIPT = 24;
public static final int SPECIALIZED = 25;
 
// Parsing event
public static final int START_EXPRESSION = 26;
public static final int END_EXPRESSION = 27;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrl/linear/LinearParser.java
0,0 → 1,299
/*
$Id: LinearParser.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrl.linear;
 
import java.util.*;
import fr.ove.openmath.jome.ctrl.linear.events.*;
import fr.ove.utils.*;
 
/**
* A bean which parses, more precisely tokenizes, what we can call the linear form of an expression.<BR>
* For each specific token encountered, an event (@see LinearParserEvent) is fired to all the listeners
* (@see LinearParserListener) of the instance.<BR>
* The event fired is made of 2 parts :
* <UL>
* <LI> the token identifier (for example, for + (addition) the associated identifier is
* <CODE>LinearParserEvent.ADDITION</CODE>)</LI>
* <LI> the value of the token, if needed. (for example, when the digit 2 is encountered, the identifier
* has the <CODE>LinearParserEvent.INTEGER</CODE> value, and the token value is represented by the @see String "2")</LI>
* </UL>
* When the parsing starts, an event whith the identifier set to <CODE>LinearParserEvent.START_EXPRESSION</CODE> is
* fired.
* Similarly, when the parsing ends (the end of the linear form has been reached), an event whith the identifier
* set to <CODE>LinearParserEvent.END_EXPRESSION</CODE> is fired.<BR>
* In order to make distinctions between what should be variables and special keywords, a resources file
* (LinearParserResources.properties) is attached to the parser. This file contains the user defined keywords.<BR>
* To add your own keywords, edit this properties file with respect to the used format (see this file for further
* details).
*
* @author © 1999 DIRAT Laurent
* @version 1.0 27/09/1999
*/
public class LinearParser implements java.io.Serializable {
/**
* The parser resources manager.<BR>
* Reads into the properties file (LinearParserResources.properties) to get the user defined specific
* keywords.
*/
private ResourcesManager resourcesManager;
/**
* The list of listeners of the instance
*/
private Vector listeners = new Vector();
 
/**
* The event sent to all the listeners of the instance during the parsing.
*/
private LinearParserEvent linearParserEvent = new LinearParserEvent(this);
/**
* The constructor.
*/
public LinearParser() {
resourcesManager = new ResourcesManager("fr.ove.openmath.jome.ctrl.linear.LinearParserResources");
}
/**
* Registers another listener of the instance.
* @param linearParserListener the listener to add.
*/
public synchronized void addLinearParserListener(LinearParserListener linearParserListener) {
listeners.addElement(linearParserListener);
}
 
/**
* Removes a listener.
* @param linearParserListener the listener to remove.
*/
public synchronized void removeLinearParserListener(LinearParserListener linearParserListener) {
listeners.removeElement(linearParserListener);
}
 
/**
* Fires a LinearParserEvent event to registered listeners.
* @param linearParserEvent event encapsulating relevant information.
*/
public void fireLinearParserEvent(LinearParserEvent linearParserEvent) {
for (int i = 0; i < listeners.size(); i++)
((LinearParserListener) listeners.elementAt(i)).consumeLinearParserEvent(linearParserEvent);
}
 
/**
* Parses the specified linear form of the formula.
* @param expression the linear form of the formula.
*/
public void parse(String expression) {
// Le nombre de tokens utilisés .
int nbTokenUsed = 0;
// On spécifie ici quels sont les tokens qui vont permettre de découper
// l'expression passée en argument.
StringTokenizer theTokens = new StringTokenizer(expression, "+-/*^_()=<>;, {}\\?!\u2192\u21D4\u211E\u2027", true);
// Des tokens temporaires pour travailler sur le token suivant le token courant.
StringTokenizer tmpTokens = null;
// Le token courant
String token = null;
// Le token suivant le token courant
String nextToken = null;
// On commence le parsing
linearParserEvent.setToken(LinearParserEvent.START_EXPRESSION, null);
fireLinearParserEvent(linearParserEvent);
while (theTokens.hasMoreTokens()) {
token = theTokens.nextToken();
nbTokenUsed++;
//if (token.equals("[")){System.out.println(linearParserEvent.toString());}
 
if (token.equals(" "))
continue;
//linearParserEvent.setToken(LinearParserEvent.RESERVED,token);
else if (token.equals("\u2192"))
linearParserEvent.setToken(LinearParserEvent.RESERVED, "\u2192");
else if (token.equals("\u21D4"))
linearParserEvent.setToken(LinearParserEvent.RESERVED, "\u21D4");
else if (token.equals("\u211E"))
linearParserEvent.setToken(LinearParserEvent.RESERVED, "\u211E");
else if (token.equals("+"))
linearParserEvent.setToken(LinearParserEvent.ADDITION, token);
else if (token.equals("-"))
linearParserEvent.setToken(LinearParserEvent.SUBSTRACTION, token);
else if (token.equals("*"))
linearParserEvent.setToken(LinearParserEvent.MULTIPLICATION, "\u2027");
else if (token.equals("\u2027"))
linearParserEvent.setToken(LinearParserEvent.RESERVED, "\u2027");
else if (token.equals("/"))
linearParserEvent.setToken(LinearParserEvent.DIVISION, token);
else if (token.equals("^"))
linearParserEvent.setToken(LinearParserEvent.POWER, token);
else if (token.equals("("))
linearParserEvent.setToken(LinearParserEvent.OPEN_PAREN, token);
else if (token.equals(")"))
linearParserEvent.setToken(LinearParserEvent.CLOSE_PAREN, token);
else if (token.equals("{"))
linearParserEvent.setToken(LinearParserEvent.OPEN_CURLY, token);
else if (token.equals("}"))
linearParserEvent.setToken(LinearParserEvent.CLOSE_CURLY, token);
else if (token.equals(","))
linearParserEvent.setToken(LinearParserEvent.SEPARATOR, null);
// no check on [] because n-th root syntax: sqrt[3](123) --> sqrt*[*3*]*(123)
// else if (token.equals("["))
// linearParserEvent.setToken(LinearParserEvent.OPEN_BRACKET, token);
// //linearParserEvent.setToken(LinearParserEvent.RESERVED, token);
// else if (token.equals("]"))
// linearParserEvent.setToken(LinearParserEvent.CLOSE_BRACKET, token);
// //linearParserEvent.setToken(LinearParserEvent.RESERVED, token);
else if (token.equals("_"))
linearParserEvent.setToken(LinearParserEvent.UNDERSCRIPT, token);
else if (token.equals("<") || token.equals(">")) {
// On re-tokenize l'expression pour récupérer l'élement suivant le token
// (à défaut d'autre chose.... :o( )
tmpTokens = new StringTokenizer(expression, "+-/*^_()=<>;, {}\\?!\u2192\u21D4\u211E\u2027", true );
for (int i = 0; i < nbTokenUsed + 1; i++) {
try {
nextToken = tmpTokens.nextToken();
}
catch (NoSuchElementException e) {
nextToken = null;
}
}
 
if (token.equals("<")) {
if (nextToken != null ) {
if (nextToken.equals("=")) {
theTokens.nextToken();
nbTokenUsed++;
linearParserEvent.setToken(LinearParserEvent.LESSEQUAL, "<=");
}
else if (nextToken.equals(">")) {
theTokens.nextToken();
nbTokenUsed++;
linearParserEvent.setToken(LinearParserEvent.UNEQUAL, "<>");
}
else
linearParserEvent.setToken(LinearParserEvent.LESS, token);
}
else
linearParserEvent.setToken(LinearParserEvent.LESS, token);
}
else {
if (nextToken != null ) {
if (nextToken.equals("=")) {
theTokens.nextToken();
nbTokenUsed++;
linearParserEvent.setToken(LinearParserEvent.GREATEREQUAL, ">=");
}
else
linearParserEvent.setToken(LinearParserEvent.GREATER, token);
}
else
linearParserEvent.setToken(LinearParserEvent.GREATER, token);
}
}
else if (token.equals("="))
linearParserEvent.setToken(LinearParserEvent.EQUAL, token);
else if (token.equals("\\"))
linearParserEvent.setToken(LinearParserEvent.SPECIALIZED, token);
else if (token.equals("?"))
linearParserEvent.setToken(LinearParserEvent.SPECIALIZED, token);
else if (token.equals("!"))
linearParserEvent.setToken(LinearParserEvent.SPECIALIZED, "fact");
else {
if (NumberUtils.isNumber(token)) {
if (NumberUtils.isFloat(token))
linearParserEvent.setToken(LinearParserEvent.FLOAT, token);
else
linearParserEvent.setToken(LinearParserEvent.INTEGER, token);
}
else {
// On a saisi des lettres. Il faut qu'on regarde si à la suite de ces
// lettres, il n'y a pas comme token suivant une parenthèse. Si tel est le cas,
// c'est que l'on a voulu saisir une fonction.
 
// On re-tokenize l'expression pour récupérer l'élement suivant le token
// (à défaut d'autre chose.... :o( )
tmpTokens = new StringTokenizer(expression, "+-/*^_()=<>;, {}\\?!\u2192\u21D4\u211E\u2027", true );
for (int i = 0; i < nbTokenUsed + 1; i++) {
try {
nextToken = tmpTokens.nextToken();
}
catch (NoSuchElementException e) {
nextToken = null;
}
}
 
if (nextToken != null) {
if (nextToken.equals("(")) {
// C'est une fonction
linearParserEvent.setToken(LinearParserEvent.FUNCTION , token);
// On passe outre le token suivant, i.e. la parenthèse ouvrante.
theTokens.nextToken();
nbTokenUsed++;
}
else {
String str1 = resourcesManager.getResourceString(token);
if (str1 == null)
// C'est une variable.
linearParserEvent.setToken(LinearParserEvent.VARIABLE, token);
else
linearParserEvent.setToken(LinearParserEvent.RESERVED, token);
}
}
else {
String str2 = resourcesManager.getResourceString(token);
if (str2 == null)
// C'est une variable.
linearParserEvent.setToken(LinearParserEvent.VARIABLE, token);
else
linearParserEvent.setToken(LinearParserEvent.RESERVED,token);
}
}
}
fireLinearParserEvent(linearParserEvent);
}
// On a fini le parsing
linearParserEvent.setToken(LinearParserEvent.END_EXPRESSION, null);
fireLinearParserEvent(linearParserEvent);
}
public static void main(String args[]) {
LinearParserListener l = new LinearParserListener() {
public void consumeLinearParserEvent(LinearParserEvent linearParserEvent) {
System.out.println(linearParserEvent.toString());
}
};
LinearParser lp = new LinearParser();
lp.addLinearParserListener(l);
lp.parse("1+2+23+C+in+pi+x_8");
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/Jome.java
0,0 → 1,347
/*
$Id: Jome.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome;
 
import java.awt.*;
import java.util.Vector;
import java.io.*;
 
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.ctrlview.events.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.*;
import fr.ove.openmath.jome.ctrlview.bidim.images.ImageLoader;
import fr.ove.openmath.jome.ctrl.linear.*;
 
public class Jome extends Container {
/**
* The formula.
*/
private Formula formula;
 
/**
* fr.ove.openmath.jome display.
*/
Display jomeDisplay;
 
/**
* The default display of the formula.
*/
FormulaDisplay formulaDisplay;
 
/**
* The graphic context.
*/
private GraphicContext graphicContext = new GraphicContext(
new Font("Times New Roman", Font.PLAIN, 14),
Color.black,
Color.white,
Color.yellow);
 
LinearParser linearParser = new LinearParser();
 
/*********************/
/* Les constructeurs */
/*********************/
 
/**
* The default constructor.
*/
public Jome() {
super();
setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
super.setFont(graphicContext.getFont());
 
// Création de la formule (modèle)
formula = new Formula();
 
linearParser.addLinearParserListener(formula);
 
// Création du gestionnaire de la sélection
SelectionManager selectionManager = new SelectionManager();
 
// Création du display par défaut de la formule (vue + contrôle)
formulaDisplay = new FormulaDisplay();
formulaDisplay.setGraphicContext(graphicContext);
formulaDisplay.addControlListener(formula);
formulaDisplay.setShiftX(10);
formulaDisplay.setShiftY(10);
formula.addModelListener(formulaDisplay);
 
// Création du display de jome.
// C'est également un display, qui va contenir le display (par défaut)
// de la formule.
jomeDisplay = new BidimDisplay(graphicContext);
jomeDisplay.drawBounds();
OneFormulaLayout layout = new OneFormulaLayout();
layout.initDisplay(jomeDisplay);
jomeDisplay.setLayout(layout);
jomeDisplay.addSelectionEventListener(selectionManager);
// On ajoute le display (par défaut) de la formule dans le display de fr.ove.openmath.jome
jomeDisplay.add(formulaDisplay);
 
// On ajoute de display de jome dans l'instance (i.e. en JOME)
add(jomeDisplay);
 
// On créé la formule.
setLinear("");
}
 
/**********************************************/
/* Méthodes nécessaires à cause de l'héritage */
/**********************************************/
 
/**
* Returns the preferred size of the fr.ove.openmath.jome.
*/
public Dimension getPreferredSize() {
return jomeDisplay.getPreferredSize();
}
 
/**
* The paint method.
* @param g where the formula is painted.
*/
public void paint(Graphics g) {
Color oldColor = g.getColor();
Color color = getBackground();
if (color != null) {
g.setColor(color);
Dimension size = getSize();
g.fillRect(0, 0, size.width, size.height);
g.setColor(oldColor);
}
 
super.paint(g);
}
 
/*************************/
/* Gestion de la formule */
/*************************/
 
/**
* Creates a formula from the specified maple-like expression.
* @param exp the specified maple-like expression.
*/
public void setLinear(String exp) {
linearParser.parse(exp);
jomeDisplay.invalidate();
jomeDisplay.setComputeAttributes(true);
validate();
repaint();
}
 
/**
* Returns the linear expression of the formula.
*/
public String getLinear() {
return formula.createLinear("");
}
 
/***************************/
/* Gestion de la sélection */
/***************************/
 
/**
* Returns the linear expression of the selection.
*/
public String getLinearSelection() {
return formulaDisplay.getLinearSelection();
}
 
 
/*********************************************************************/
/* Décalage de l'affichage de la formule à l'intérieur de la fenêtre */
/*********************************************************************/
 
/**
* Sets a horizontal shift to the display of the formula.
* @param shiftY the vertical shift.
*/
public void setShiftX(int shiftX) {
shiftX = (shiftX < 1) ? 1 : shiftX;
formulaDisplay.setShiftX(shiftX);
jomeDisplay.invalidate();
jomeDisplay.setComputeAttributes(true);
validate();
repaint();
}
 
/**
* Returns the horizontal shift.
* @return the horizontal shift.
*/
public int getShiftX() {
return formulaDisplay.getShiftX();
}
 
/**
* Sets a vertical shift to the display of the formula.
* @param shiftY the vertical shift.
*/
public void setShiftY(int shiftY) {
shiftY = (shiftY < 1) ? 1 : shiftY;
formulaDisplay.setShiftY(shiftY);
jomeDisplay.invalidate();
jomeDisplay.setComputeAttributes(true);
validate();
repaint();
}
 
/**
* Returns the vertical shift.
* @return the vertical shift.
*/
public int getShiftY() {
return formulaDisplay.getShiftY();
}
 
 
/**************************************/
/* Manipulation du contexte graphique */
/**************************************/
 
/**
* Sets a new font to the context.
* @param font the new font.
*/
public void setFont(Font font) {
graphicContext.setFont(font);
formulaDisplay.setFont(font);
jomeDisplay.invalidate();
jomeDisplay.setComputeAttributes(true);
validate();
 
super.setFont(font);
}
 
/**
* Sets a new color to the context.
* @param color the new color.
*/
public void setForegroundColor(Color foregroundColor) {
graphicContext.setForegroundColor(foregroundColor);
repaint();
}
 
/**
* Returns the foreground color used.
*/
public Color getForegroundColor() {
return graphicContext.getForegroundColor();
}
 
/**
* Sets a new background color for the display.
* @param background the color used as background for the display.
*/
public void setBackgroundColor(Color backgroundColor) {
graphicContext.setBackgroundColor(backgroundColor);
repaint();
}
 
/**
* Returns the background color used.
*/
public Color getBackgroundColor() {
return graphicContext.getBackgroundColor();
}
 
/**
* Sets a new selection color to the context.
* @param selectionColor the new color.
*/
public void setSelectionColor(Color selectionColor) {
graphicContext.setSelectionColor(selectionColor);
repaint();
}
 
/**
* Returns the selection color used.
*/
public Color getSelectionColor() {
return graphicContext.getSelectionColor();
}
 
/**
* Sets if we draw the bounds of fr.ove.openmath.jome.
* @param drawBounds <CODE>true</CODE> if we want the bounds to be drawn.
* <CODE>false</CODE> otherwise.
*/
public void setDrawBounds(boolean drawBounds) {
if (drawBounds)
jomeDisplay.drawBounds();
else
jomeDisplay.dontDrawBounds();
}
 
/**
* Retuns <CODE>true</CODE> if we want the bounds to be drawn.
* <CODE>false</CODE> otherwise.
*/
public boolean getDrawBounds() {
return jomeDisplay.weDrawBounds();
}
 
/**************************************************/
/* Iconification/Désiconification de la sélection */
/**************************************************/
 
/**
* Iconifies the selection.
*/
public void iconifySelection() {
formulaDisplay.iconify();
}
 
/**
* Uniconifies the selected icons.
*/
public void uniconifySelectedIcons() {
formulaDisplay.uniconify();
}
 
/**
* Uniconifies all icons in the expression.
*/
public void uniconifyAllIcons() {
formulaDisplay.uniconifyAll();
}
 
/**
* Substitutes the selection by the specified friendly name.
* @param the name for the substitution
*/
public void substitute(String name) {
if ((name != null) && !name.equals(""))
formulaDisplay.substitute(name);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/JomeBeanInfo.java
0,0 → 1,94
/*
$Id: JomeBeanInfo.java,v 1.4 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome;
 
import java.beans.*;
import java.beans.SimpleBeanInfo;
//import symantec.itools.beans.*;
 
public class JomeBeanInfo extends java.beans.SimpleBeanInfo
{
public JomeBeanInfo()
{
}
 
/**
* Gets a BeanInfo for the superclass of this bean.
* @return BeanInfo[] containing this bean's superclass BeanInfo
*/
public BeanInfo[] getAdditionalBeanInfo()
{
try
{
BeanInfo[] bi = new BeanInfo[1];
bi[0] = Introspector.getBeanInfo(beanClass.getSuperclass());
return bi;
}
catch (IntrospectionException e)
{
throw new Error(e.toString());
}
}
 
/**
* Gets the SymantecBeanDescriptor for this bean.
* @return an object of type SymantecBeanDescriptor
* @see symantec.itools.beans.SymantecBeanDescriptor
*/
public BeanDescriptor getBeanDescriptor()
{
BeanDescriptor bd = new BeanDescriptor(beanClass);
bd.setValue("CAN_ADD_CHILD",new Boolean(true));
 
return bd;
}
 
/**
* Gets an image that may be used to visually represent this bean
* (in the toolbar, on a form, etc).
* @param iconKind the type of icon desired, one of: BeanInfo.ICON_MONO_16x16,
* BeanInfo.ICON_COLOR_16x16, BeanInfo.ICON_MONO_32x32, or BeanInfo.ICON_COLOR_32x32.
* @return an image for this bean
* @see BeanInfo#ICON_MONO_16x16
* @see BeanInfo#ICON_COLOR_16x16
* @see BeanInfo#ICON_MONO_32x32
* @see BeanInfo#ICON_COLOR_32x32
*/
public java.awt.Image getIcon(int nIconKind)
{
java.awt.Image img = null;
if (nIconKind == BeanInfo.ICON_COLOR_16x16)
img = loadImage("IconJOME_16.gif");
if (nIconKind == BeanInfo.ICON_COLOR_32x32)
img = loadImage("IconJOME_16_32.gif");
return img;
}
 
private final static Class beanClass = Jome.class;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/VerticalLayout.java
0,0 → 1,125
/*
$Id: VerticalLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
 
/**
* A layout manager that lays components vertically.
*
* @author © 1998 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public abstract class VerticalLayout extends DisplayLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int height = 0;
int width = 0;
int ascent;
int descent;
Display tmp;
int count = displayToLay.getComponentCount();
for ( int i = 0; i < count; i++ ) {
tmp = (Display) displayToLay.getComponent(i);
tmp.setSize(tmp.getPreferredSize());
}
for (int i = 0; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
width = Math.max(width, tmp.getWidth() + tmp.getShiftX());
height += tmp.getHeight() + tmp.getShiftY();
}
// Possibles changements à effectuer pour ne pas mettre la
// la ligne de référence au milieu de la BBox
ascent = ( (height%2) == 0 ) ? (height / 2) : (height / 2) + 1 ;
descent = ( (height%2) == 0 ) ? ascent : ascent - 1 ;
displayToLay.setAscent(ascent);
displayToLay.setDescent(descent);
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
 
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
 
// ***************************************************
// *** Implémentation de l'interface LayoutManager ***
 
/*
* Lays out the container in the specified panel.
* @param parent the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
int x, y;
Display display, previous;
 
// Ca c'est parce que c'est le layout manager de la formule. Et comme personne ne dit au container
// contenant la formule, que la taille de la formule a besoin d'être recalculée, il faut bien le
// faire qque part. Chaque display informe son père qu'il doit être recalculé, mais la formule ne
// le fait pas pour le sien.
parent.setSize(parent.getPreferredSize());
int count = parent.getComponentCount();
for ( int i = 0; i < count; i++ ) {
display = (Display) parent.getComponent(i);
display.setSize(display.getPreferredSize());
x = display.getShiftX();
 
if ( i == 0 )
y = display.getShiftY();
else {
previous = (Display) parent.getComponent(i-1);
y = previous.getY() + previous.getHeight() + display.getShiftY();
}
display.setLocation(x, y);
// On place maintenant les éventuels display enfants du display courant
display.doLayout();
}
}
 
// *** Fin de l'interface LayoutManager ***
// ****************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BracketLayout.java
0,0 → 1,66
/*
$Id: BracketLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
 
/**
* A layout manager that lays components to be displayed between parenthesize.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public class BracketLayout extends EnclosingLayout {
/**
* Returns the opening
*/
public SymbolDisplay createOpening() {
SymbolDisplay bracket = new SymbolDisplay(displayToLay.getGraphicContext(),
new BracketSymbol(true,
displayToLay.getFontMetrics(displayToLay.getFont()).getHeight() / 4,
displayToLay));
// Le display de la parenthèse est le display d'un opérateur (on peut le considérer comme tel)
bracket.setIsSymbolOperatorDisplay(true);
return bracket;
}
/**
* Returns the closing
*/
public SymbolDisplay createClosing() {
SymbolDisplay bracket = new SymbolDisplay(displayToLay.getGraphicContext(),
new BracketSymbol(false,
displayToLay.getFontMetrics(displayToLay.getFont()).getHeight() / 4,
displayToLay));
// Le display de la parenthèse est le display d'un opérateur (on peut le considérer comme tel)
bracket.setIsSymbolOperatorDisplay(true);
return bracket;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SubstitutionLayout.java
0,0 → 1,101
/*
$Id: SubstitutionLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.Vector;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.StringDisplay;
import fr.ove.openmath.jome.ctrlview.bidim.SubstitutedDisplayManager;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
 
/**
* A layout manager that lays display of substitued displays.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 04/08/1999
*/
public class SubstitutionLayout extends AbstractStringLayout implements SubstitutedDisplayManager {
/**
* The list of the displays that have been iconified.
*/
private Vector substitutedDisplay = new Vector();
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
}
 
/*
* Adds an substituted display to the list.
*/
public void addSubstitutedDisplay(Display display) {
substitutedDisplay.addElement(display);
}
/*
* Removes a substituted display to the list.
* @param display the display to remove.
*/
public void removeSubstitutedDisplay(Display display) {
substitutedDisplay.removeElement(display);
}
/*
* Removes a substituted display at the specified rank to the list.
* @param rank the specified rank.
*/
public void removeSubstitutedDisplay(int rank) {
substitutedDisplay.removeElementAt(rank);
}
/**
* Returns the substituted display at the specified rank.
* @param rank the specified rank.
*/
public Display getSubstitutedDisplay(int rank) {
return (Display) substitutedDisplay.elementAt(rank);
}
/**
* Returns the number of substituted displays.
*/
public int getNbSubstitutedDisplay() {
return substitutedDisplay.size();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/Localisable.java
0,0 → 1,80
/*
$Id: Localisable.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.Point;
 
/**
* Interface that must implement all objects that want to be located.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/06/1999
*/
public interface Localisable {
/**
* Sets the x-location of the instance.
* @param x the x-location of the instance.
*/
public void setX(int x);
/**
* Returns the x-location of the instance.
*/
public int getX();
/**
* Sets the y-location of the instance.
* @param y the y-location of the instance.
*/
public void setY(int y);
/**
* Returns the y-location of the instance.
*/
public int getY();
/**
* Sets the location of the instance.
* @param x the x-location of the instance.
* @param y the y-location of the instance.
*/
public void setLocation(int x, int y);
/**
* Sets the location of the instance.
* @param location the location of the instance.
*/
public void setLocation(Point location);
/**
* Returns the location of the instance.
* @return A <CODE>Point</CODE> representing the location of the instance.
*/
public Point getLocation();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BidimDisplayAllocator.java
0,0 → 1,134
/*
$Id: BidimDisplayAllocator.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* This class instanciates the right display according to the specified formula
* tree sturcture.
* This is an abstract class. It must be inherited to be specialized.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 01/07/1999
*/
 
public class BidimDisplayAllocator extends DisplayAllocator {
/**
* The display layout allocator.
*/
private static BidimLayoutAllocator layoutAllocator = new BidimLayoutAllocator();
/**
* The resources manager for the displays
*/
private static BidimResourcesManager resourcesManager = new BidimResourcesManager("fr.ove.openmath.jome.ctrlview.bidim.resources");
/**
* Instanciates and creates the right display according to the specified
* formula tree structure.
* @param fts the formula tree structure which need a display.
*/
public Display allocateDisplay(GraphicContext graphicContext, FormulaTreeStructure fts) {
Display display = null;
String ftsId = fts.getResourceIdentifier();
String idDisplay = resourcesManager.getIdDisplay(ftsId);
// Si il y a un problème de display, alors on met le display par défaut
idDisplay = (idDisplay == null) ? "default" : idDisplay;
//System.out.println("ftsId = " + ftsId + "\t\t idDisplay = " + idDisplay);
if (idDisplay.equals("constant")) {
// Allocation d'un StringDisplay
display = new StringDisplay(graphicContext, ((Constant) fts).getValue(), false);
// Le display créé écoute la fts qui lui correspond
display.addControlListener(fts);
// Et vice et versa.
fts.addModelListener(display);
}
else if (idDisplay.equals("symbol")) {
// Allocation d'un SymbolDisplay
display = new SymbolDisplay(graphicContext);
// Allocation dudit symbole
ImageSymbol symbol = new ImageSymbol(/*fts.getSymbolName*/fts.getValue(), display);
// Affection du symbole
((SymbolDisplay) display).setSymbol(symbol);
// Le display créé écoute la fts qui lui correspond
display.addControlListener(fts);
// Et vice et versa.
fts.addModelListener(display);
}
else if (idDisplay.equals("icon")) {
if (((Icon) fts).isSubstitution()) {
// Allocation d'un SubstitutionDisplay
display = new SubstitutionDisplay(graphicContext, ((Icon) fts).getIconName());
}
else {
// Allocation d'un SymbolDisplay
display = new IconDisplay(graphicContext);
// Allocation de l'icone
ImageSymbol icon = new ImageSymbol(fts.getIconName(), display);
// Affection du symbole (i.e. de l'icone)
((SymbolDisplay) display).setSymbol(icon);
}
// Le display créé écoute la fts qui lui correspond
display.addControlListener(fts);
// Et vice et versa.
fts.addModelListener(display);
}
else {
// Dans tous les autres cas, allocation d'un BidimDisplay
display = new BidimDisplay(graphicContext);
// Le display créé écoute la fts qui lui correspond
display.addControlListener(fts);
// Et vice et versa.
fts.addModelListener(display);
// Allocation du layout manager qui va bien
String layoutName = resourcesManager.getLayoutManager(ftsId);
layoutName = (layoutName == null) ? resourcesManager.getLayoutManager("defaultLM") : layoutName;
//System.out.println("layoutName = " + layoutName);
DisplayLayout layout = layoutAllocator.allocateLayout(layoutName);
display.setLayout(layout);
layout.initDisplay(display);
}
return display;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ArrayLayout.java
0,0 → 1,66
/*
$Id: SigmaLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components to place them as the different elements of a
* sum.<BR>
* The different elements are contained in the display in the following order :
* <UL>
* <LI>the symbol sigma.</LI>
* <LI>the expression.</LI>
* <LI>the lower bound.</LI>
* <LI>the upper bound.</LI>
*</UL>
*
* Bounds are optional elements.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public class ArrayLayout extends MapsArrayLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
SymbolDisplay array = new SymbolDisplay(displayToLay.getGraphicContext(),
new ImageSymbol("Array", displayToLay));
// Le display de la somme est le display d'un opérateur (on peut le considérer comme tel)
array.setIsSymbolOperatorDisplay(true);
return array;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringInfixOperatorLayout.java
0,0 → 1,53
/*
$Id: StringInfixOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager for an infix operator which symbol can be rendered as a string (e.g. +, *)
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public abstract class StringInfixOperatorLayout extends InfixOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), fts.getTheOperator(), true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringUnderOperatorLayout.java
0,0 → 1,53
/*
$Id: StringUnderOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of the operator whose symbol is located under its operand.<BR>
* The symbol is represented as a simple string
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class StringUnderOperatorLayout extends UnderOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), fts.getTheOperator(), true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/EnclosingLayout.java
0,0 → 1,260
/*
$Id: EnclosingLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.behaviour.*;
 
/**
* A layout manager that lays components to be displayed between something.<BR>
* Obviously, what is called something will be parenthesis, braces, ....
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public abstract class EnclosingLayout extends HorizontalLayout {
/**
* The opening of the enclosure
*/
private SymbolDisplay opening;
/**
* The closing of the enclosure
*/
private SymbolDisplay closing;
/**
* Returns the opening
*/
public SymbolDisplay getOpening() {
return opening;
}
/**
* Returns the closing
*/
public SymbolDisplay getClosing() {
return closing;
}
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
FormulaTreeStructure fts = (FormulaTreeStructure) displayToLay.getListener();
if (((Maskable) fts).isVisible()) {
opening = createOpening();
 
// On met un listener à l'opening
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
opening.addControlListener(fts);
this.displayToLay.add(opening);
closing = createClosing();
closing.addControlListener(fts);
this.displayToLay.add(closing);
}
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
if (((Maskable) displayToLay.getListener()).isVisible()) {
// La validité de la sélection est triviale.
// Si l'une ou l'autre des parenthèse est sélectionnée, alors on sélectionne
// tout.
if (opening.isSelected() || closing.isSelected()) {
// Sélectionne le display.
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute nos parenthèses
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
}
 
// On a vérifié la validité de la sélection de la puissance. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (displayToLay.getParent() instanceof Display) {
display = (Display) displayToLay.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
 
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
Display tmp;
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// Si les parenthèses sont sélectionnées, alors il faut les déselectionner.
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
 
if (((Maskable) displayToLay.getListener()).isVisible()) {
if (display == opening)
closing.setNotSelected();
else
opening.setNotSelected();
// L'opérande est mis dans la liste des sélectionnés
selEvt.setAction(SelectionEvent.ADD, (Display) father.getComponent(2));
father.fireSelectionEvent(selEvt);
}
 
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
 
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
 
// On met à jour l'affichage.
father.repaint();
}
 
}
 
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Display display = null;
 
if (((Maskable) displayToLay.getListener()).isVisible()) {
Displayable openingSymbol = opening.getSymbol();
Displayable closingSymbol = closing.getSymbol();
// On met la hauteur à 0, pour que dans tous les cas, le super.computeAttributes() ne soit pas
// biaisée par une éventuelle nouvelle taille des éléments qui composent la liste.
// Comme c'est plus loin qu'on leur fixe la taille....
openingSymbol.setHeight(0);
opening.setHeight(0);
closingSymbol.setHeight(0);
closing.setHeight(0);
// même remarque que ci-dessus
opening.setAttributes(0, 0, 0, 0);
closing.setAttributes(0, 0, 0, 0);
((Display) displayToLay.getComponent(2)).setShiftX(0);
Dimension dim = super.computeAttributes();
// Par contre, par rapport à comment est calculée la taille display, dim comprend
// déjà la largeur de opening et closing
openingSymbol.setAscent(displayToLay.getAscent());
openingSymbol.setDescent(displayToLay.getDescent());
openingSymbol.setHeight(displayToLay.getHeight());
opening.setComputeAttributes(true);
opening.invalidate();
opening.setSize(opening.getPreferredSize());
 
closingSymbol.setAscent(displayToLay.getAscent());
closingSymbol.setDescent(displayToLay.getDescent());
closingSymbol.setHeight(displayToLay.getHeight());
closing.setComputeAttributes(true);
closing.invalidate();
closing.setSize(closing.getPreferredSize());
// Cette taille là correspond au décalage qu'il faut appliquer à closing
closing.setShiftX(dim.width - 2*closing.getWidth());
// Mais il faut l'enlever au display du milieu qui doit être contre l'opening (because HonrizontalLayout)
((Display) displayToLay.getComponent(2)).setShiftX(-closing.getShiftX() - closing.getWidth());
return dim;
}
else
return super.computeAttributes();
}
 
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
// ############################################
// ### Les différentes méthodes abstraites ###
// ############################################
/**
* Returns the opening
*/
public abstract SymbolDisplay createOpening();
/**
* Returns the closing
*/
public abstract SymbolDisplay createClosing();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/VarDiffLayout.java
0,0 → 1,178
/*
$Id: VarDiffLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components for the variables of differentiation.<BR>
* We assume the display laid out contains what should be a variable for the visualisation of a differentiation,
* i.e. a variable (differentiation of first order) or a power of a variable (differentiation of higher order).<BR>
* According to the type of differentiation, either the symbol "d" is added (differentiation) or the symbol delta (the
* greek letter) is added (partial differentiation) to the display laid out, for correct rendering.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/10/1999
*/
public class VarDiffLayout extends HorizontalLayout {
/**
* <CODE>true</CODE> if we are dealing with a partial derivative. <CODEW>false</CODE> otherwise.
*/
private boolean isPartial;
/**
* The constructor.
* @param isPartial <CODE>true</CODE> if we have a partial differentiation. <CODE>false</CODE> otherwise.
*/
public VarDiffLayout(boolean isPartial) {
this.isPartial = isPartial;
}
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
 
FormulaTreeStructure fts = (FormulaTreeStructure) this.displayToLay.getListener();
Display d;
// Si dériveé partielle, on ajoute un SymbolDisplay avec un delta. Sinon, un StringDisplay avec un "d"
if (isPartial) {
d = new SymbolDisplay(this.displayToLay.getGraphicContext(), new ImageSymbol("delta", this.displayToLay));
// Le display est le display d'un opérateur (on peut le considérer comme tel)
d.setIsSymbolOperatorDisplay(true);
}
else {
d = new StringDisplay(this.displayToLay.getGraphicContext(), "d", true);
}
this.displayToLay.add(d, d, 0);
// On met un listener au display du d/delta
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
d.addControlListener(fts);
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// La validité de la sélection est triviale.
// Si un des displays est sélectionné alors on sélectionne tout.
Display d = (Display) displayToLay.getComponent(0);
Display v = (Display) displayToLay.getComponent(1);
if (d.isSelected() || v.isSelected()) {
// Sélectionne le display.
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute os parenthèses
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
 
// On a vérifié la validité de la sélection de la puissance. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
//if (!(display.getListener() instanceof Formula))
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
Display tmp;
SelectionEvent selEvt = new SelectionEvent(father);
// En fait, comme quand "d/delta" ou la variable (puissance ou pas) est sélectionné on sélectionne tout,
// quand on désélectionne l'un ou l'autre, on désélectionne tout.
if (father.isSelected()) {
father.deselect();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
//if (!(display.getListener() instanceof Formula))
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/VerticalCenteredLayout.java
0,0 → 1,133
/*
$Id: VerticalCenteredLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
 
/**
* A layout manager that lays components vertically.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public abstract class VerticalCenteredLayout extends DisplayLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int height = 0;
int width1 = 0;
int width2 = 0;
int width = 0;
int ascent;
int descent;
Display tmp;
updateLevel(displayToLay.getLevel());
int count = displayToLay.getComponentCount();
for (int i = 0; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
tmp.setSize(tmp.getPreferredSize());
}
for (int i = 0; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
width = (tmp.getWidth() / 2);
width1 = Math.max( width - tmp.getShiftX(),
width1 );
width = ((tmp.getWidth() % 2) == 0 ) ? width : (width + 1);
width2 = Math.max( width + tmp.getShiftX(),
width2 );
height += tmp.getAscent() + tmp.getDescent() + tmp.getShiftY();
}
// Possibles changements à effectuer pour ne pas mettre la
// la ligne de référence au milieu de la BBox
ascent = ( (height%2) == 0 ) ? (height / 2) : (height / 2) + 1 ;
descent = ( (height%2) == 0 ) ? ascent : ascent - 1 ;
displayToLay.setAscent(ascent);
displayToLay.setDescent(descent);
displayToLay.setSize(width1 + width2 , height);
displayToLay.setComputeAttributes(false);
return new Dimension(width1 + width2 , height);
}
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
 
// ***************************************************
// *** Implémentation de l'interface LayoutManager ***
 
/*
* Lays out the container in the specified panel.
* @param parent the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
int x, y;
Display display, previous;
int count = parent.getComponentCount();
for ( int i = 0; i < count; i++ ) {
display = (Display) parent.getComponent(i);
display.setSize(display.getPreferredSize());
x = (((Display) parent).getWidth() / 2) -
(display.getWidth() / 2) +
display.getShiftX();
if ( i == 0 )
y = display.getShiftY();
else {
previous = (Display) parent.getComponent(i-1);
y = previous.getY() + previous.getHeight() + display.getShiftY();
}
display.setLocation(x, y);
// On place maintenant les éventuels display enfants du display courant
display.doLayout();
}
}
 
// *** Fin de l'interface LayoutManager ***
// ****************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/RootLayout.java
0,0 → 1,386
/*
$Id: RootLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
import fr.ove.utils.FontInfo;
 
/**
* A layout manager that lays the display of the nth-root.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 22/07/1999
*/
public class RootLayout extends HorizontalLayout {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
 
FormulaTreeStructure fts = (FormulaTreeStructure) this.displayToLay.getListener();
// On ajoute le tick de la racine dans la liste des display
SymbolDisplay tick = new SymbolDisplay(this.displayToLay.getGraphicContext(), new SqrtTick());
// Le display du tick de la racine est le display d'un opérateur (on peut le considérer comme tel)
tick.setIsSymbolOperatorDisplay(true);
this.displayToLay.add(tick);
// On met un listener au tick.
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
tick.addControlListener(fts);
 
// On ajoute la barre de la racine dans la liste des display
SymbolDisplay bar = new SymbolDisplay(this.displayToLay.getGraphicContext(), new Bar());
// Le display de la barre de la racine est le display d'un opérateur (on peut le considérer comme tel)
bar.setIsSymbolOperatorDisplay(true);
this.displayToLay.add(bar);
 
// On met un listener à la barre de la racine.
// Idem remarque ci-dessus.
bar.addControlListener(fts);
this.displayToLay.computeAncestorsAttributes();
}
/**
* Updates the level of the display that is layed out.<BR>
* @param level the level put to the display
*/
public void updateLevel(int level) {
Display tmp;
// Pour éviter de refaire le calcul plusieurs fois....
if (displayToLay.getUpdateLevel()) {
// On met à jour le niveau du display géré par le LM.
displayToLay.setLevel(level);
displayToLay.setUpdateLevel(false);
int i = 0;
int count = displayToLay.getComponentCount();
// Si le nombre de composant est 4, alors on a affaire au display d'une racine n-ième.
// (sinon, c'et le display d'une racine carrée)
// On fait en sorte que la puissance de la racine soit en première position dans display,
// sinon, à l'affichage, elle va être en partie masquée par le display du tick.
if (count == 4) {
// On regarde si le premier display est celui d'un opérateur (celui du tick en fait)
// Si c'est le cas, il faut déplacer le display de la puissance.
if (((Display) displayToLay.getComponent(0)).isSymbolOperatorDisplay()) {
tmp = (Display) displayToLay.getComponent(3);
// De part l'implémentation du add(tmp, tmp, 0), tmp va être enlevé de la liste
// des listeners qu'il écoute. Chose qu'on ne veut pas.
displayToLay.removeFromListListeners(false);
displayToLay.add(tmp, tmp, 0);
// On se remet dans la cas classique où la suppression de display entraînera sa suppression
// dans la liste des listeners qu'il écoute.
displayToLay.removeFromListListeners(true);
displayToLay.adjustRank();
}
// On réduit la taille de la puissance de 1
tmp = (Display) displayToLay.getComponent(0);
((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
tmp.setUpdateLevel(false);
// On incrémente l'indice i, pour que dans la boucle qui suit, on parte bien du display
// du tick
i++;
}
// le tick, la barre de la racine, et l'élément sous la racine
// ont le niveau du display qui les contient
for (; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
((DisplayLayout) tmp.getLayout()).updateLevel(level);
tmp.setUpdateLevel(false);
}
}
}
 
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// La validité de la sélection est triviale.
// Si un des displays du dessin de la racine est sélectionné alors on sélectionne tout.
// Si l'élément sous la racine et le numéro de la racine ont chacun des éléments sélectionnés
Display tick, bar;
int count = displayToLay.getComponentCount();
if (count == 4) {
tick = (Display) displayToLay.getComponent(1);
bar = (Display) displayToLay.getComponent(2);
}
else {
tick = (Display) displayToLay.getComponent(0);
bar = (Display) displayToLay.getComponent(1);
}
if (tick.isSelected() || bar.isSelected()) {
// Sélectionne le display.
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute os parenthèses
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
else {
if (count == 4) {
Display nthRoot = (Display) displayToLay.getComponent(0);
Display arg = (Display) displayToLay.getComponent(3);
if (nthRoot.gotSelectedElements() && arg.gotSelectedElements()) {
// Sélectionne le display.
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute os parenthèses
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
}
}
// On a vérifié la validité de la sélection de la racine. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null) // Si fts est la racine de la formule alors la sélection à déjà été validée
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
SelectionEvent selEvt = new SelectionEvent(father);
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
Display tick, bar, arg;
Display nthRoot = null;
if (father.getComponentCount() == 4) {
nthRoot = (Display) father.getComponent(0);
tick = (Display) father.getComponent(1);
bar = (Display) father.getComponent(2);
arg = (Display) father.getComponent(3);
}
else {
tick = (Display) father.getComponent(0);
bar = (Display) father.getComponent(1);
arg = (Display) father.getComponent(2);
}
if ((display == tick) || (display == bar)) {
// Comme on ne sait pas de qui on vient, on désélectionne les 2
tick.setNotSelected();
bar.setNotSelected();
// On considère que le comportement par défaut et de sélectionner l'argument de la racine.
// Même si on est dans le cas d'une racine n-ième (on désélectionne donc le numéro de la racine)
selEvt.setAction(SelectionEvent.ADD, arg);
father.fireSelectionEvent(selEvt);
if (nthRoot != null)
nthRoot.deselect();
}
else if (display == arg) {
tick.setNotSelected();
bar.setNotSelected();
if (nthRoot != null) {
selEvt.setAction(SelectionEvent.ADD, nthRoot);
father.fireSelectionEvent(selEvt);
}
}
else { // ben forcément, display == nthRoot
tick.setNotSelected();
bar.setNotSelected();
selEvt.setAction(SelectionEvent.ADD, arg);
father.fireSelectionEvent(selEvt);
}
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null) // Si fts est la racine de la formule alors la désélection à déjà été validée
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
 
}
 
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
updateLevel(displayToLay.getLevel());
int width = 0;
int height = 0;
int thickness = FontInfo.getLineThickness(displayToLay, displayToLay.getFont());
Display arg;
SymbolDisplay barDisplay, tickDisplay;
Bar bar;
SqrtTick tick;
int count = displayToLay.getComponentCount();
if (count == 4) {
tickDisplay = (SymbolDisplay) displayToLay.getComponent(1);
barDisplay = (SymbolDisplay) displayToLay.getComponent(2);
arg = (Display) displayToLay.getComponent(3);
}
else {
tickDisplay = (SymbolDisplay) displayToLay.getComponent(0);
barDisplay = (SymbolDisplay) displayToLay.getComponent(1);
arg = (Display) displayToLay.getComponent(2);
}
// On calcule la taille du display de l'élément sous la racine
arg.invalidate();
arg.setComputeAttributes(true);
((DisplayLayout) arg.getLayout()).computeAttributes();
arg.setSize(arg.getPreferredSize());
// On calcule la taille du display de la barre de la racine
bar = (Bar) barDisplay.getSymbol();
bar.setHeight(thickness);
bar.setWidth(arg.getWidth() + 4);
barDisplay.invalidate();
barDisplay.setComputeAttributes(true);
barDisplay.setSize(barDisplay.getPreferredSize());
// On met un décalage vertical au display de la barre pour qu'il se trouve au dessus du display
// de l'argument.
barDisplay.setShiftY(-arg.getAscent() - barDisplay.getDescent() );
// On met un décalage horizontal au display de l'argument pour que son c^té gauche soit aligné
// au display de la barre.
arg.setShiftX(-bar.getWidth());
// On calcule la taille du display du "tick" de la racine
tick = (SqrtTick) tickDisplay.getSymbol();
tick.setThickness(thickness);
tick.setHeight(arg.getHeight() + thickness);
tick.setWidth(displayToLay.getFontMetrics(displayToLay.getFont()).stringWidth("A"));
tick.setAscent(arg.getAscent() + thickness);
tick.setDescent(arg.getDescent());
tickDisplay.invalidate();
tickDisplay.setComputeAttributes(true);
tickDisplay.setSize(tickDisplay.getPreferredSize());
int ascent;
if (count == 4) {
// On a le display d'une racine n-ième.
// On s'occupe du display de la puissance de la racine.
Display nthRoot = (Display) displayToLay.getComponent(0);
nthRoot.setSize(nthRoot.getPreferredSize());
// On fixe maintenant les décalages nécessaires à chacun des display pour leur bon
// positionnement.
nthRoot.setShiftY(-(int) Math.round(0.42f * (float) tickDisplay.getAscent()) - nthRoot.getDescent());
tickDisplay.setShiftX(-tickDisplay.getWidth() / 2);
width += nthRoot.getWidth() + (tickDisplay.getWidth()/2) + barDisplay.getWidth();
ascent = Math.max(nthRoot.getAscent() - nthRoot.getShiftY(), tickDisplay.getAscent());
}
else {
width += tickDisplay.getWidth() + barDisplay.getWidth();
ascent = tickDisplay.getAscent();
}
height += ascent + arg.getDescent();
displayToLay.setSize(width, height);
displayToLay.setAscent(ascent);
displayToLay.setDescent(arg.getDescent());
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
 
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BidimLayoutAllocator.java
0,0 → 1,54
/*
$Id: BidimLayoutAllocator.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.io.Serializable;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.FormulaTreeStructure;
import fr.ove.utils.Factory;
 
/**
* This class instanciates the right layout manager according to the display which
* calls the method.
* This is an abstract class. It must be inherited to be specialized.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 01/07/1999
*/
 
public class BidimLayoutAllocator extends LayoutAllocator {
/**
* Instanciates the right layout manager whose name is specified.
* @param layoutName the (class) name of the layout manager.<BR>
* The name is fully qualified, i.e. packageName.className
*/
public DisplayLayout allocateLayout(String layoutName) {
return (DisplayLayout) Factory.getClassInstance(layoutName);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/Mfd2SubstitutionLayout.java
0,0 → 1,144
/*
$Id: Mfd2SubstitutionLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components horizontally and inserts between
* them, the display of the operator that the layout manager lays.<BR>
* For example, if this layout manager lays an equality, it will insert
* between the components (i.e. operands) the display of the symbol "=",
* and so on, for all the relational operators.<BR>
*
* @author © 1999 DIRAT Laurent
* @version 2.0 17/12/1999
*/
public class Mfd2SubstitutionLayout extends HorizontalLayout {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
// On ajoute un display d'opérateur.
SymbolDisplay arrow = new SymbolDisplay(this.displayToLay.getGraphicContext(), new ImageSymbol("LeftArrow", this.displayToLay));
// On met un listener à l'opérateur.
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
arrow.addControlListener(this.displayToLay.getListener());
arrow.setIsSymbolOperatorDisplay(true);
this.displayToLay.add(arrow);
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Dimension dim = super.computeAttributes();
Display arrow = (Display) displayToLay.getComponent(0);
Display left = (Display) displayToLay.getComponent(1);
Display right = (Display) displayToLay.getComponent(2);
arrow.setShiftX(left.getShiftX() + left.getWidth());
left.setShiftX(-(arrow.getShiftX() + arrow.getWidth()));
right.setShiftX(arrow.getWidth());
return dim;
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
Display tmp;
Display listDisplay[] = new Display[2]; // y en a 2 (en ne comptant pas celui de la flèche)
for (int i = 0; i < 3; i++) {
tmp = (Display) displayToLay.getComponent(i);
if (!tmp.isSymbolOperatorDisplay()) {
// A voir !!!!!
// Mais il semblerai que bon, sinon à la (re)construction du display il se base
// sur des anciennes valeurs, et donc pas tarrible niveau affichage.
tmp.setLocation(0, 0);
listDisplay[((FormulaTreeStructure) tmp.getListener()).getRank()] = tmp;
}
}
// Pour que la flèche soient gardée, on la met temporairement comme un display "classique".
// Autrement dit, ce n'est plus un display d'opérateur.
((Display) displayToLay.getComponent(0)).setIsSymbolOperatorDisplay(false);
// ATTENTION : ici, on enlève les displays fils de display, mais on ne les enlève pas de la liste
// des listeners de la fts qu'il sont en train d'écouter. Exception faite pour les displays d'opérateur.
displayToLay.removeAllDisplays();
// On remet la flèche dans un état qui est le sien, i.e. display d'opérateur.
((Display) displayToLay.getComponent(0)).setIsSymbolOperatorDisplay(true);
for (int i = 0; i < 2; i++)
displayToLay.add(listDisplay[i]);
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/HorizontalLayout.java
0,0 → 1,122
/*
$Id: HorizontalLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components horyzontally.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public abstract class HorizontalLayout extends DisplayLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int ascent = 0;
int descent = 0;
Display tmp;
int width = 0;
int height = 0;
updateLevel(displayToLay.getLevel());
 
int count = displayToLay.getComponentCount();
for (int i = 0; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
tmp.setSize(tmp.getPreferredSize());
width += tmp.getWidth() + tmp.getShiftX();
ascent = Math.max(tmp.getAscent() - tmp.getShiftY(),
ascent);
descent = Math.max(tmp.getDescent() + tmp.getShiftY(),
descent);
}
 
displayToLay.setAscent(Math.max( 0, ascent ));
displayToLay.setDescent(Math.max( 0, descent));
height += displayToLay.getAscent() + displayToLay.getDescent();
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
 
return new Dimension(width, height);
}
 
 
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
 
// ***************************************************
// *** Implémentation de l'interface LayoutManager ***
 
 
/*
* Lays out the container in the specified panel.
* @param parent the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
int x, y;
Display display, previous;
int count = parent.getComponentCount();
for (int i = 0; i < count; i++) {
display = (Display) parent.getComponent(i);
display.setSize(display.getPreferredSize());
 
if (i == 0)
x = display.getShiftX();
else {
previous = (Display) parent.getComponent(i-1);
x = previous.getX() + previous.getWidth() + display.getShiftX();
}
 
y = ((Display) parent).getAscent() - display.getAscent() + display.getShiftY();
 
display.setLocation(x, y);
 
// On place maintenant les éventuels display enfants du display courant
display.doLayout();
}
}
 
// *** Fin de l'interface LayoutManager ***
// ****************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/Line.java
0,0 → 1,224
/*
$Id: Line.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.io.Serializable;
 
/**
* A line.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 22/07/1999
*/
public class Line implements Serializable {
/**
* The starting point of the line.
*/
private Point p1;
/**
* The ending point of the line.
*/
private Point p2;
/**
* The thickness of the line.
*/
private int thickness;
/**
* The alignment of the drawing of the line.
* <UL>
* <LI> LEFT : the thickness of the line is distributed to the left of the line</LI>
* <LI> RIGHT : the thickness of the line is distributed to the right of the line</LI>
* <LI> CENTER : the thickness of the line is distributed in equitably on both sides of the line </LI>
* </UL>
* Be carefull of the position of the points. The line goes from P1 to P2.
*/
private byte alignment;
private Polygon line;
/**
* The constructor.<BR>
* Constructs the line [(0,0),(0,0)], with a thickness of 1.
*/
public Line() {
this(new Point(), new Point(), 1, CENTER);
}
/**
* The constructor.<BR>
* @param p1 the starting point of the line
* @param p2 the ending point of the line
* @param thickness the thickness of the line
* @param alignment the alignment of the line
*/
public Line(Point p1, Point p2, int thickness, byte alignment) {
this.p1 = p1;
this.p2 = p2;
this.thickness = thickness;
this.alignment = alignment;
computeLine();
}
/**
* Sets a new starting point.
* @param p1 the starting point of the line
*/
public void setP1(Point p1) {
this.p1 = p1;
computeLine();
}
/**
* Returns the starting point of the line.
*/
public Point getP1() {
return p1;
}
/**
* Sets a new ending point.
* @param p2 the ending point of the line
*/
public void setP2(Point p2) {
this.p2 = p2;
computeLine();
}
/**
* Returns the ending point of the line.
*/
public Point getP2() {
return p2;
}
/**
* Sets a new alingment.
* @param alignment the alignment of the line
*/
public void setAlignment(byte alignment) {
this.alignment = alignment;
}
/**
* Returns the alignement of the line.
*/
public int getAlignment() {
return alignment;
}
/**
* Sets the thickness of the line.
* @param thickness the thickness of the line
*/
public void setThickness(int thickness) {
this.thickness = thickness;
computeLine();
}
/**
* Returns the thickness of the line.
*/
public int getThickness() {
return thickness;
}
/**
* Draws the line.
* @param g the graphics in which the line has to be drawn.
*/
public void draw(Graphics g) {
g.fillPolygon(line);
}
/**
* Returns the <CODE>Polygon</CODE> which represents the line.
*/
public Polygon getLine() {
return line;
}
private void computeLine() {
line = new Polygon();
Point vectDir = new Point(p2.x - p1.x, p2.y - p1.y);
float ortho_x = -vectDir.y;
float ortho_y = vectDir.x;
// On normalise ortho
float norme = (float) Math.sqrt(ortho_x*ortho_x + ortho_y*ortho_y);
ortho_x = (ortho_x/norme)*((float) thickness);
ortho_y = (ortho_y/norme)*((float) thickness);
int x, y;
switch(alignment) {
case RIGHT :
line.addPoint(p1.x, p1.y);
line.addPoint(p2.x, p2.y);
line.addPoint((int) Math.round(((int) p2.x) - ortho_x), (int) Math.round(((int) p2.y) - ortho_y));
line.addPoint((int) Math.round(((int) p1.x) - ortho_x), (int) Math.round(((int) p1.y) - ortho_y));
break;
case CENTER :
float half_x = ortho_x/2.0f;
float half_y = ortho_y/2.0f;
line.addPoint((int) Math.round(((int) p1.x) - half_x), (int) Math.round(((int) p1.y) - half_y));
line.addPoint((int) Math.round(((int) p2.x) - half_x), (int) Math.round(((int) p2.y) - half_y));
line.addPoint((int) Math.round(((int) p2.x) + half_x), (int) Math.round(((int) p2.y) + half_y));
line.addPoint((int) Math.round(((int) p1.x) + half_x), (int) Math.round(((int) p1.y) + half_y));
break;
case LEFT :
line.addPoint(p1.x, p1.y);
line.addPoint(p2.x, p2.y);
line.addPoint((int) Math.round(((int) p2.x) + ortho_x), (int) Math.round(((int) p2.y) + ortho_y));
line.addPoint((int) Math.round(((int) p1.x) + ortho_x), (int) Math.round(((int) p1.y) + ortho_y));
break;
}
}
/**
* The different alignements of the line.
*/
/**
* The thickness of the line is distributed to the left of the line
*/
public static final byte LEFT = 0;
/**
* The thickness of the line is distributed in equitably on both sides of the line
*/
public static final byte CENTER = 1;
/**
* The thickness of the line is distributed to the right of the line
*/
public static final byte RIGHT = 2;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/AbstractStringLayout.java
0,0 → 1,92
/*
$Id: AbstractStringLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.StringDisplay;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
 
/**
* A layout manager that lays strings.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 23/06/98
*/
public abstract class AbstractStringLayout extends DisplayLayout {
/**
* Updates the level of the display that is layed out.<BR>
* @param level the level put to the display
*/
public void updateLevel(int level) {
if (displayToLay.getUpdateLevel()) {
displayToLay.setLevel(level);
displayToLay.scaleDisplay();
displayToLay.setUpdateLevel(false);
displayToLay.setSize(computeAttributes());
}
}
 
/**
* Computes the size of the display and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
FontMetrics fm = displayToLay.getFontMetrics(displayToLay.getFont());
displayToLay.setAscent(fm.getAscent());
displayToLay.setDescent(fm.getDescent());
int width = fm.stringWidth(((AbstractStringDisplay) displayToLay).getString()) + 2;
int height = displayToLay.getAscent() + displayToLay.getDescent();
displayToLay.setSize(width, height);
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
 
/*
* Lays out the container in the specified panel.
* @param parent the component which needs to be laid out.
*/
public void layoutContainer(Container parent) {
return;
}
 
 
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// En fait, celui là ne sera jamais reconstruit.
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/CurlyLayout.java
0,0 → 1,66
/*
$Id: CurlyLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
 
/**
* A layout manager that lays components to be displayed between curly braces.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public class CurlyLayout extends EnclosingLayout {
/**
* Returns the opening
*/
public SymbolDisplay createOpening() {
SymbolDisplay curly = new SymbolDisplay(displayToLay.getGraphicContext(),
new CurlySymbol(true,
displayToLay.getFontMetrics(displayToLay.getFont()).getHeight() / 4,
displayToLay));
// Le display de l'accolade est le display d'un opérateur (on peut le considérer comme tel)
curly.setIsSymbolOperatorDisplay(true);
return curly;
}
/**
* Returns the closing
*/
public SymbolDisplay createClosing() {
SymbolDisplay curly = new SymbolDisplay(displayToLay.getGraphicContext(),
new CurlySymbol(false,
displayToLay.getFontMetrics(displayToLay.getFont()).getHeight() / 4,
displayToLay));
// Le display de l'accolade est le display d'un opérateur (on peut le considérer comme tel)
curly.setIsSymbolOperatorDisplay(true);
return curly;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SigmaLayout.java
0,0 → 1,66
/*
$Id: SigmaLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components to place them as the different elements of a
* sum.<BR>
* The different elements are contained in the display in the following order :
* <UL>
* <LI>the symbol sigma.</LI>
* <LI>the expression.</LI>
* <LI>the lower bound.</LI>
* <LI>the upper bound.</LI>
*</UL>
*
* Bounds are optional elements.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public class SigmaLayout extends MapsToSigmaLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
SymbolDisplay sigma = new SymbolDisplay(displayToLay.getGraphicContext(),
new ImageSymbol("Sigma", displayToLay));
// Le display de la somme est le display d'un opérateur (on peut le considérer comme tel)
sigma.setIsSymbolOperatorDisplay(true);
return sigma;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SubstitutedDisplayManager.java
0,0 → 1,68
/*
$Id: SubstitutedDisplayManager.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.Display;
 
/**
* Interface to implement to manage the substitution of displays.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 04/08/1999
*/
public interface SubstitutedDisplayManager {
/*
* Adds a substituted display to the list.
* @param display the display to add
*/
public void addSubstitutedDisplay(Display display);
/*
* Removes a substituted display to the list.
* @param display the display to remove.
*/
public void removeSubstitutedDisplay(Display display);
/*
* Removes a substituted display at the specified rank to the list.
* @param rank the specified rank.
*/
public void removeSubstitutedDisplay(int rank);
/**
* Returns the substituted display at the specified rank.
* @param rank the specified rank.
*/
public Display getSubstitutedDisplay(int rank);
/**
* Returns the number of substituted displays.
*/
public int getNbSubstitutedDisplay();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ImagePostfixedUnaryOperatorLayout.java
0,0 → 1,63
/*
$Id: ImagePostfixedUnaryOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* This layout manager lays prefixed unary operators.<BR>
* The symbol of the operator can be rendered as an image
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public class ImagePostfixedUnaryOperatorLayout extends PostfixedUnaryOperatorLayout {
/**
* The symbol we have to insert between each component if necessary.
*/
private ImageSymbol symbolOperator = null;
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
if (symbolOperator == null) {
Operator fts = (Operator) displayToLay.getListener();
//symbolOperator = new ImageSymbol(fts.getTheOperator(), displayToLay);
symbolOperator = new ImageSymbol(fts.getResourceIdentifier(), displayToLay);
}
// On créé un display pour l'opérateur.
SymbolDisplay operatorDisplay = new SymbolDisplay(displayToLay.getGraphicContext(), symbolOperator);
operatorDisplay.setIsSymbolOperatorDisplay(true);
return operatorDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SuperposedOperatorLayout.java
0,0 → 1,187
/*
$Id: SuperposedOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
import fr.ove.utils.FontInfo;
 
/**
* Layout manager that lays the display of an operator whose symbol is superposed to its operand.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public abstract class SuperposedOperatorLayout extends VerticalCenteredLayout implements OperatorDisplayCreator {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
// C'est strictement la même chose, sauf que VerticalCenteredLayout place l'ascent comme étant la moitié
// de la hauteur du display. Or dans le cas qui nous occupe, l'ascent du display doit ce trouver sur celui
// de l'opérande
Dimension dim = super.computeAttributes();
displayToLay.setAscent(((Display) displayToLay.getComponent(0)).getShiftY() +
((Display) displayToLay.getComponent(0)).getHeight() +
((Display) displayToLay.getComponent(1)).getShiftY() +
((Display) displayToLay.getComponent(1)).getAscent());
displayToLay.setDescent(displayToLay.getHeight() - displayToLay.getAscent());
return dim;
}
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
// On récupère le fts associé (listener) au display.
FormulaTreeStructure fts = (FormulaTreeStructure) displayToLay.getListener();
Display displayOperator = createOperatorDisplay();
// On met un listener à l'opérateur.
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
displayOperator.addControlListener(fts);
// On ajoute le display d'opérateur en première position
// A priori, display ne contient rien, donc un add(displayOperator) suffit.
this.displayToLay.add(displayOperator);
this.displayToLay.computeAncestorsAttributes();
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// La validité de la sélection est triviale.
// Si l'opérateur est sléectionné, alors on sélectionne tout.
Display displayOperator = (Display) displayToLay.getComponent(0);
if (displayOperator.isSelected()) {
// Sélectionne le display.
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute os parenthèses
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
 
// On a vérifié la validité de la sélection de la puissance. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
SelectionEvent selEvt = new SelectionEvent(father);
// Si l'opérateur est sélectionné, alors il faut le déselectionner.
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
Display displayOperator = (Display) displayToLay.getComponent(0);
Display argument = (Display) displayToLay.getComponent(1);
if (display == displayOperator) {
displayOperator.setNotSelected();
selEvt.setAction(SelectionEvent.ADD, argument);
father.fireSelectionEvent(selEvt);
}
else {
displayOperator.setNotSelected();
argument.deselect();
}
 
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
 
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/IntegralLayout.java
0,0 → 1,375
/*
$Id: IntegralLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components to place them as an integral.<BR>
* The different elements (when complete) are contained in the display in the following order :
* <UL>
* <LI>the lower bound.</LI>
* <LI>the symbol integral.</LI>
* <LI>the upper bound.</LI>
* <LI>the expression.</LI>
* <LI>the integrand.</LI>
*</UL>
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public class IntegralLayout extends HorizontalLayout {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
 
SymbolDisplay integral = new SymbolDisplay(this.displayToLay.getGraphicContext(),
new ImageSymbol("Integrale", this.displayToLay));
// Le display de l'intégrale est le display d'un opérateur (on peut le considérer comme tel)
integral.setIsSymbolOperatorDisplay(true);
this.displayToLay.add(integral);
integral.addControlListener((FormulaTreeStructure) this.displayToLay.getListener());
}
/**
* Updates the level of the display that is layed out.<BR>
* @param level the level put to the display
*/
public void updateLevel(int level) {
Display tmp;
StringDisplay varIntDisplay;
VariableOrNumber varInt;
// Pour éviter de refaire le calcul plusieurs fois....
if (displayToLay.getUpdateLevel()) {
// On met à jour le niveau du display géré par le LM.
displayToLay.setLevel(level);
displayToLay.setUpdateLevel(false);
int i = 0;
int count = displayToLay.getComponentCount();
// Si le nombre de composant est au moins 4, alors on a affaire à une intégrale où au moins une
// borne est spécifiée (la borne inférieure)
// On fait en sorte qu'elle soit en première position dans display,
// sinon, à l'affichage, elle va être en partie masquée par le display de l'intégrale.
if (count > 3) {
// On regarde si le premier display est celui d'un opérateur (celui de l'intégrale en fait)
// Si c'est le cas, il faut déplacer le display de la borne inf.
if (((Display) displayToLay.getComponent(0)).isSymbolOperatorDisplay()) {
tmp = (Display) displayToLay.getComponent(3);
// De part l'implémentation du add(tmp, tmp, 0), tmp va être enlevé de la liste
// des listeners qu'il écoute. Chose qu'on ne veut pas.
displayToLay.removeFromListListeners(false);
displayToLay.add(tmp, tmp, 0);
// On se remet dans la cas classique où la suppression de display entraînera sa suppression
// dans la liste des listeners qu'il écoute.
displayToLay.removeFromListListeners(true);
displayToLay.adjustRank();
}
// On réduit la taille de la borne inf. de 1
tmp = (Display) displayToLay.getComponent(0);
((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
tmp.setUpdateLevel(false);
// On incrémente l'indice i, pour que dans la boucle qui suit, on parte bien du display
// du tick
i++;
// Le display de la variable d'intégration est en 4-ième position
tmp = (Display) displayToLay.getComponent(3);
varIntDisplay = (StringDisplay) tmp.getComponent(0);
if (count > 4) {
// C'est la borne supérieure. On réduit sa taille de 1
tmp = (Display) displayToLay.getComponent(4);
((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
tmp.setUpdateLevel(false);
count--;
}
}
else {
// Le display de la variable d'intégration est en 3-ième position
tmp = (Display) displayToLay.getComponent(2);
varIntDisplay = (StringDisplay) tmp.getComponent(0);
}
// On récupère la fts de la variable d'intégration.
// Si c'est un template, alors pas besoin de rajouter le d. Sinon, on le rajoute
varInt = (VariableOrNumber) varIntDisplay.getListener();
if (!varInt.isTemplate())
varIntDisplay.setString("d" + varInt.getValue());
// le symbole de l'intégrale, l'intégrande et la variable d'intégration (en fait le d"x")
// ont le niveau du display qui les contient
for (; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
((DisplayLayout) tmp.getLayout()).updateLevel(level);
tmp.setUpdateLevel(false);
}
}
}
 
/**
* Checks the validity of the selection.
* @param display the display to select.
*/
public void validateSelection() {
int count = displayToLay.getComponentCount();
Display symbol, expression, varInt;
if (count > 3) {
symbol = (Display) displayToLay.getComponent(1);
expression = (Display) displayToLay.getComponent(2);
varInt = (Display) displayToLay.getComponent(3);
}
else {
symbol = (Display) displayToLay.getComponent(0);
expression = (Display) displayToLay.getComponent(1);
varInt = (Display) displayToLay.getComponent(2);
}
if ((symbol.isSelected()) || (varInt.isSelected()))
displayToLay.select();
else if (count > 3) {
Display lower = (Display) displayToLay.getComponent(0);
Display upper;
if (lower.gotSelectedElements()) {
if (expression.gotSelectedElements())
displayToLay.select();
else if (count > 4) {
upper = (Display) displayToLay.getComponent(4);
if (upper.gotSelectedElements())
displayToLay.select();
}
}
else if (count > 4) {
upper = (Display) displayToLay.getComponent(4);
if (upper.gotSelectedElements()) {
if (expression.gotSelectedElements())
displayToLay.select();
}
}
}
// Quand on est ici, si display est sélectionné, alors c'est qu'on a validé un des tests
// ci-dessus. On doit alors mettre à jour le gestionnaire de sélections, et y ajouter display
if (displayToLay.isSelected()) {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute notre intégrale.
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
 
// On a vérifié la validité de la sélection de l'intégrale. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null) // Si fts est la racine de la formule alors la sélection à déjà été validée
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
Display tmp;
SelectionEvent selEvt = new SelectionEvent(father);
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
int count = father.getComponentCount();
Display expression;
if (count > 3)
expression = (Display) father.getComponent(2);
else
expression = (Display) father.getComponent(1);
if (display != expression) {
// quand on désélectionne un élément de l'intégrale, autre que l'expression, l'expression
// reste sélectionnée.
selEvt.setAction(SelectionEvent.ADD, expression);
father.fireSelectionEvent(selEvt);
}
if (count > 3) {
((Display) father.getComponent(0)).deselect();
((Display) father.getComponent(1)).setNotSelected();
((Display) father.getComponent(3)).deselect();
if (count > 4)
((Display) father.getComponent(4)).deselect();
}
else {
((Display) father.getComponent(0)).setNotSelected();
((Display) father.getComponent(2)).deselect();
}
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
 
}
 
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int ascent = 0;
int descent = 0;
 
updateLevel(displayToLay.getLevel());
 
int width = 0;
int height = 0;
SymbolDisplay symbol;
Display expression, integrand;
int gap = 4;
int count = displayToLay.getComponentCount();
if (count > 3) {
symbol = (SymbolDisplay) displayToLay.getComponent(1);
expression = (Display) displayToLay.getComponent(2);
integrand = (Display) displayToLay.getComponent(3);
}
else {
symbol = (SymbolDisplay) displayToLay.getComponent(0);
expression = (Display) displayToLay.getComponent(1);
integrand = (Display) displayToLay.getComponent(2);
}
symbol.setSize(symbol.getPreferredSize());
expression.setSize(expression.getPreferredSize());
integrand.setSize(integrand.getPreferredSize());
int width1 = symbol.getWidth();
width += expression.getWidth() + integrand.getWidth();
ascent = Math.max(expression.getAscent(), symbol.getAscent());
descent = Math.max(expression.getDescent(), symbol.getDescent());
if (count > 3) {
Display lower = (Display) displayToLay.getComponent(0);
lower.setSize(lower.getPreferredSize());
lower.setShiftY((int) Math.round(symbol.getDescent()*0.2f) + lower.getAscent());
lower.setShiftX((int) Math.round(symbol.getWidth()*0.55f));
//width1 += lower.getWidth();
width1 = Math.max(symbol.getWidth(), lower.getShiftX() + lower.getWidth());
descent = Math.max(lower.getShiftY() + lower.getDescent() + gap, descent);
symbol.setShiftX(-lower.getWidth() - lower.getShiftX());
if (count > 4) {
Display upper = (Display) displayToLay.getComponent(4);
upper.setSize(upper.getPreferredSize());
width1 = Math.max(width1, symbol.getWidth() + upper.getWidth());
int decalage = width1 - symbol.getWidth();
upper.setShiftX(-(decalage + width/* - gap*/));
upper.setShiftY((int) Math.round(-symbol.getAscent()*0.6f) - upper.getDescent());
ascent = Math.max(-upper.getShiftY() + upper.getAscent() + gap, ascent);
}
}
expression.setShiftX(width1 - symbol.getWidth() + gap);
displayToLay.setAscent(ascent);
displayToLay.setDescent(descent);
width += width1/* + expression.getWidth()*/ + 2*gap;
height += ascent + descent;
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SqrtTick.java
0,0 → 1,94
/*
$Id: SqrtTick.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayableImpl;
import fr.ove.openmath.jome.ctrlview.bidim.Line;
 
 
/**
* The "tick" of the square root
*
* @author © 1999 DIRAT Laurent
* @version 2.0 22/07/1999
*/
public class SqrtTick extends DisplayableImpl {
/**
* The thickness of the tick
*/
private int thickness;
/**
* The elements of the drawing of the tick
*/
private Line line1;
private Line line2;
/**
* Sets the thickness of the drawing.
* @param thickness the thickness of the drawing.
*/
public void setThickness(int thickness) {
this.thickness = thickness;
}
/**
* Returns the thickness of the drawing.
*/
public int getThickness() {
return thickness;
}
/**
* The paint method of the object to display.
* @param g the drawing area of the symbol.
*/
public void paint(Graphics g) {
int height = getHeight();
int width = getWidth();
g.fillRect(0, (int) Math.round(0.48f * (float) height), (int) Math.round(0.2f * (float) width), thickness);
 
line1 = new Line(new Point((int) Math.round(0.1f * (float) width), (int) Math.round(0.48f * (float) height)),
new Point((int) Math.round(0.4f * (float) width), height),
thickness, Line.RIGHT);
line1.draw(g);
line2 = new Line(new Point((int) Math.round(0.4f * (float) width), height),
new Point(width - (int) Math.round(0.2f * (float) width), 0),
thickness, Line.CENTER);
line2.draw(g);
g.drawLine((int) Math.round(0.4f * (float) width), height, width - (int) Math.round(0.2f * (float) width), 0);
g.fillRect(width - (int) Math.round(0.2f * (float) width), 0, (int) Math.round(0.2f * (float) width), thickness);
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ImageBetweenOperatorLayout.java
0,0 → 1,66
/*
$Id: ImageBetweenOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of an operator whose symbol is located between its 2 operands.<BR>
* Rendering is done vertically, the first operand on top, the symbol in the middle and the second operand
* under the 2 previous.<BR>
* The symbol is rendered with an image.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class ImageBetweenOperatorLayout extends BetweenOperatorLayout {
/**
* The symbol we have to insert between each component if necessary.
*/
private ImageSymbol symbolOperator = null;
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
if (symbolOperator == null) {
Operator fts = (Operator) displayToLay.getListener();
//symbolOperator = new ImageSymbol(fts.getTheOperator(), displayToLay);
symbolOperator = new ImageSymbol(fts.getResourceIdentifier(), displayToLay);
}
// On créé un display pour l'opérateur.
SymbolDisplay operatorDisplay = new SymbolDisplay(displayToLay.getGraphicContext(), symbolOperator);
operatorDisplay.setIsSymbolOperatorDisplay(true);
return operatorDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/resources_en.properties
0,0 → 1,163
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
# Resources file for the rendering of the expression:
# The syntax is the following :
#
# modelId = idDisplay:layoutManager
#
# modelId is the identifier of the model (formula tree structure node) we want to display. The identifier we find
# in this resources file should (probably must) match the ones present in the resources file for the formula tree
# structure model.
#
# idDisplay is the identifier of the display which will be in charge of displaying the corresponding element of the
# expression. The kind of display is fully determine, and the value this field must take is one of the following :
#
# constant : for elements which are rendered as a string (variables names, numbers, ...)
# symbol : for elements which are rendered as an image (pi, greek letters, special symbols, ...)
# icon : for iconified parts of the expression
# default : for the operators in general (i.e. displays containing other displays (operands displays))
#
# layoutManager is the layout manager in charge of the positioning of the operand and the rendering of the symbol
# operator when needed. This field is ONLY required when idDisplay = default. The 3 others are specific displays
# then the layout manager is automatically set. So, this field can be omitted.
# This field represents the fully qualified name of the class (package name attached) to instanciate.
#
 
VARIABLE = constant
INTEGER = constant
FLOAT = constant
? = constant
 
ADDITION = default:fr.ove.openmath.jome.ctrlview.bidim.BasicStringInfixOperatorLayout
UNARYMINUS = default:fr.ove.openmath.jome.ctrlview.bidim.StringLeftAssocPrefixedUnaryOperatorLayout
UNARYPLUS = default:fr.ove.openmath.jome.ctrlview.bidim.StringLeftAssocPrefixedUnaryOperatorLayout
MULTIPLICATION = default:fr.ove.openmath.jome.ctrlview.bidim.BasicStringInfixOperatorLayout
DIVISION = default:fr.ove.openmath.jome.ctrlview.bidim.FractionLayout
POWER = default:fr.ove.openmath.jome.ctrlview.bidim.SuperscriptLayout
 
EQUAL = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
UNEQUAL = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
LESS = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
LESSEQUAL = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
GREATER = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
GREATEREQUAL = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
 
UNDERSCRIPT = default:fr.ove.openmath.jome.ctrlview.bidim.UnderscriptLayout
SLOT = default:fr.ove.openmath.jome.ctrlview.bidim.SlotLayout
 
ICON = icon
#subst = default:fr.ove.openmath.jome.ctrlview.bidim.SubstitutionLayout
 
OPEN_PAREN = default:fr.ove.openmath.jome.ctrlview.bidim.BracketLayout
OPEN_BRACKET = default:fr.ove.openmath.jome.ctrlview.bidim.IntervalLayout
CLOSE_BRACKET = default:fr.ove.openmath.jome.ctrlview.bidim.IntervalLayout
# jm.evers
langle = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
rangle = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
lbracket = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
rbracket = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
neq = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
div = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
and = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
or = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
mapsto = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
cup = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
rightarrow = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
array = default:fr.ove.openmath.jome.ctrlview.bidim.ArrayLayout
 
#
in = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
notin = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
union = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
intersect = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
 
defaultFunction = default:fr.ove.openmath.jome.ctrlview.bidim.FunctionLayout
abs = default:fr.ove.openmath.jome.ctrlview.bidim.AbsoluteLayout
conj = default:fr.ove.openmath.jome.ctrlview.bidim.ConjugateLayout
int = default:fr.ove.openmath.jome.ctrlview.bidim.IntegralLayout
root = default:fr.ove.openmath.jome.ctrlview.bidim.RootLayout
sqrt = default:fr.ove.openmath.jome.ctrlview.bidim.RootLayout
sum = default:fr.ove.openmath.jome.ctrlview.bidim.SigmaLayout
prod = default:fr.ove.openmath.jome.ctrlview.bidim.ProductLayout
lambda = default:fr.ove.openmath.jome.ctrlview.bidim.LambdaExpLayout
diff = default:fr.ove.openmath.jome.ctrlview.bidim.DifferentiationLayout
request = default:fr.ove.openmath.jome.ctrlview.bidim.RequestLayout
entry = default:fr.ove.openmath.jome.ctrlview.bidim.RequestLayout
OPEN_CURLY = default:fr.ove.openmath.jome.ctrlview.bidim.HorizontalListLayout
vlist = default:fr.ove.openmath.jome.ctrlview.bidim.VerticalListLayout
subst = default:fr.ove.openmath.jome.ctrlview.bidim.VerticalListLayout
substElem = default:fr.ove.openmath.jome.ctrlview.bidim.Mfd2SubstitutionLayout
 
# Only used when no layout manager has been found. Specified a default layout manager.
defaultLM = default:fr.ove.openmath.jome.ctrlview.bidim.FunctionLayout
 
C = symbol
N = symbol
Q = symbol
R = symbol
Z = symbol
infty = symbol
 
 
E = constant
I = constant
 
true = constant
false = constant
 
pi = symbol
delta = symbol
gamma = symbol
alpha = symbol
alfa = symbol
beta = symbol
chi = symbol
epsilon = symbol
eta = symbol
iota = symbol
kappa = symbol
mu = symbol
nabla = symbol
nu = symbol
omega = symbol
phi = symbol
psi = symbol
rho = symbol
sigma = symbol
tau = symbol
theta = symbol
upsilon = symbol
zeta = symbol
xi = symbol
 
fact = default:fr.ove.openmath.jome.ctrlview.bidim.StringPostfixedUnaryOperatorLayout
rat = default:fr.ove.openmath.jome.ctrlview.bidim.FractionLayout
cc = default:fr.ove.openmath.jome.ctrlview.bidim.BracketLayout
cp = default:fr.ove.openmath.jome.ctrlview.bidim.SlotLayout
 
lim = default:fr.ove.openmath.jome.ctrlview.bidim.LimitLayout
 
#o = default:fr.ove.openmath.jome.ctrlview.bidim.StringBinaryInfixOperatorLayout
o = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/DifferentiationLayout.java
0,0 → 1,260
/*
$Id: DifferentiationLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components for the denominator of a differentiation.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/10/1999
*/
public class DifferentiationLayout extends HorizontalLayout {
private boolean arrangeDisplay = true; // Au premier calcul, il faudra arranger les displays correctement
private Display fracDisplay = null;
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
Differentiation diff = (Differentiation) this.displayToLay.getListener();
diff.computeOrder();
// Allocation d'un display, qui va correspondre à la partie fraction de la représentation
fracDisplay = new BidimDisplay(displayToLay.getGraphicContext());
// On met un listener à fracDisplay
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
fracDisplay.addControlListener(diff);
// On lui met dont un FractionLayout
FractionLayout layout = new FractionLayout();
layout.initDisplay(fracDisplay);
fracDisplay.setLayout(layout);
// On l'ajoute comme fils à display
this.displayToLay.add(fracDisplay);
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
Display derivator = (Display) displayToLay.getComponent(0);
Display func = (Display) displayToLay.getComponent(1);
// Si le display de ce qui est la partie fraction de la dérivée (derivator) est sélectionnée,
// alors on sélectionne tout.
// Si la function et dérivator ont qque chose de sélectionné, alors on sélectionne tout.
if (derivator.isSelected() || (func.gotSelectedElements() && derivator.gotSelectedElements())) {
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute l'instance dans la liste des sélectionnés
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
// On a vérifié la validité de la sélection de l'opérateur. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (displayToLay.getParent() instanceof Display) {
display = (Display) displayToLay.getParent();
//if (!(display.getListener() instanceof Formula))
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
// father est le display de l'opérateur unaire.
Display father = displayToLay;
Display tmp;
SelectionEvent selEvt = new SelectionEvent(father);
// Si l'opérateur en entier est sélectionné, il faut le désélectionner
if (father.isSelected()) {
father.deselect();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
// Si display est l'opérateur (on vient de déselectionner l'opérateur), alors
// on ajoute l'opérande dans la liste des sélectionnés.
if (display == displayToLay.getComponent(0)) {
((Display) displayToLay.getComponent(1)).select();
selEvt.setAction(SelectionEvent.ADD, (Display) displayToLay.getComponent(1));
father.fireSelectionEvent(selEvt);
}
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
//((DisplayLayout) father.getLayout()).validateDeselection((Display) display.getParent());
if (!(father.getListener() instanceof Formula))
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
VarDiffLayout varDiffLayout;
updateLevel(displayToLay.getLevel());
//if (arrangeDisplay) {
if (displayToLay.getComponentCount() > 3) {
// Dans l'ordre, displayToLay contient [fracDisplay, numFrac, fct, var1, var2, ...]
// Il faut mettre numFrac, comme fils de fracDisplay (qui à ce stade ne contient que le display
// de la barre de fraction.
// Il faut creer un display avec comme layout DenominatorDiffLayout, et y ajouter tous les vari.
// Ensuite, ajouter ce display à fracDisplay.
// On obtient donc displayToLay = [fracDisplay, fct]
// avec fracDisplay = [barDisplay, numFrac, [var1, var2, ...]]
// Le display de chacun des vari est en fait le display d'un slot. On remplace le SlotLayout, par
// un VarDiffLayout, pour que le "d" (ou le delta) soit rajouté devant.
Display d;
d = (Display) displayToLay.getComponent(1);
// fracDisplay.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
fracDisplay.add(d);
d.setDoRemoveFromListListeners(true);
//displayToLay contient [fracDisplay, fct, var1, var2, ...]
int count = displayToLay.getComponentCount();
Differentiation diff = (Differentiation) displayToLay.getListener();
if (count == 3) {
// Ca veut dire que l'on a une dérivée du premier ordre : [fracDisplay, fct, var1]
// On a juste à mettre le display de var1 dans fracDisplay
d = (Display) displayToLay.getComponent(2);
// On modifie le layout, qui doit être un slotLayout, par un VarDiffLayout.
varDiffLayout = new VarDiffLayout(diff.isPartial());
varDiffLayout.initDisplay(d);
d.setLayout(varDiffLayout);
// fracDisplay.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
fracDisplay.add(d);
d.setDoRemoveFromListListeners(true);
}
else {
// Ca veut dire que l'on a une dérivée d' ordre > 1 : [fracDisplay, fct, var1, var2, ...]
// Il faut créer un display pour le dénominateur
Display den = new BidimDisplay(displayToLay.getGraphicContext());
// On met un listener à den
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
den.addControlListener(diff);
DenominatorDiffLayout denLayout = new DenominatorDiffLayout();
denLayout.initDisplay(den);
den.setLayout(denLayout);
for (int i = 2; i < displayToLay.getComponentCount(); ) {
d = (Display) displayToLay.getComponent(i);
// On modifie le layout, qui doit être un slotLayout, par un VarDiffLayout.
varDiffLayout = new VarDiffLayout(diff.isPartial());
varDiffLayout.initDisplay(d);
d.setLayout(varDiffLayout);
// den.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
den.add(d);
// On remet le comportement de suppression par défault.
d.setDoRemoveFromListListeners(true);
}
// On ajoute maintenant le dénominateur dans fracDisplay
fracDisplay.add(den);
}
}
// On a donc displayToLay = [fracDisplay, fct]
// avec fracDisplay = [barDisplay, numFrac, [var1, var2, ...]]
((Display) displayToLay.getComponent(1)).setShiftX(5);
Dimension dim = super.computeAttributes();
return new Dimension(dim.width + 5, dim.height);
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SeparatorOperatorLayout.java
0,0 → 1,72
/*
$Id: SeparatorOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.*;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager for an infix operator which symbol is ",".<BR>
* In fact, his is not an operator. This layout manager will only serve for specific operators
* which need to separate their operands with "," (e.g. lists, enumeration, ...)
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class SeparatorOperatorLayout extends StringInfixOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
// Ce n'est pas un opérateur en tant que tel, donc pas de fts associé, on spécifie donc directement
// ce qui est censé représenter l'opérateur : ","
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(),",", true);
stringDisplay.setIsSymbolOperatorDisplay(true);
return stringDisplay;
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
// Pour le moment, on fait rien
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
// Pour le moment, on fait rien
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BidimResourcesManager.java
0,0 → 1,65
/*
$Id: BidimResourcesManager.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.utils.CachingResourcesManager;
 
/**
* The resources manager for the rendering formula.<BR>
* The different resources take the following syntax : (see the resources files for more details)
* modelId = idDisplay:layoutManager
*
* @author © 2000 DIRAT Laurent
* @version 2.0 03/01/2000
*/
public class BidimResourcesManager extends CachingResourcesManager {
/**
* The Constructor.
* @param resourcesName the name of the resources file.
*/
public BidimResourcesManager(String resourcesName) {
super(resourcesName);
}
/**
* Returns the display identificator of the specified property.
* @param property the specified property
*/
public String getIdDisplay(String property) {
return accessResource(property, 0);
}
/**
* Returns the class name of the layout manager corresponding to the specified property.
* @param property the specified property
*/
public String getLayoutManager(String property) {
return accessResource(property, 1);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ProductLayout.java
0,0 → 1,66
/*
$Id: ProductLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components to place them as the different elements of a
* product.<BR>
* The different elements are contained in the display in the following order :
* <UL>
* <LI>the symbol product.</LI>
* <LI>the expression.</LI>
* <LI>the lower bound.</LI>
* <LI>the upper bound.</LI>
*</UL>
*
* Bounds are optional elements.
*
* @author © 2000 DIRAT Laurent
* @version 2.0 21/02/2000
*/
public class ProductLayout extends MapsToSigmaLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
SymbolDisplay product = new SymbolDisplay(displayToLay.getGraphicContext(),
new ImageSymbol("Product", displayToLay));
// Le display de la somme est le display d'un opérateur (on peut le considérer comme tel)
product.setIsSymbolOperatorDisplay(true);
return product;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/LayoutAllocator.java
0,0 → 1,49
/*
$Id: LayoutAllocator.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.io.Serializable;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
 
/**
* This class instanciates the right layout manager according to the specified display.
* This is an abstract class. It must be inherited to be specialized.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 27/06/1999
*/
 
public abstract class LayoutAllocator implements Serializable {
/**
* Instanciates the right layout manager whose name is specified.
* @param layoutName the (class) name of the layout manager.<BR>
* The name is fully qualified, i.e. packageName.className
*/
public abstract DisplayLayout allocateLayout(String layoutName);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BasicStringInfixOperatorLayout.java
0,0 → 1,365
/*
$Id: BasicStringInfixOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.*;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager for an infix operator which symbol can be rendered as a string (e.g. +, *)
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public class BasicStringInfixOperatorLayout extends StringInfixOperatorLayout {
/**
* Inserts, if necessary, a display of the operator symbol that the display
* laid by the instance represents.
*/
protected void insertOperatorDisplay() {
Display current, next, displayOperator;
FormulaTreeStructure fatherFts = (FormulaTreeStructure) displayToLay.getListener();
FormulaTreeStructure fts;
int nbComponent = displayToLay.getComponentCount();
// On parcourre tous les components présents dans le display.
for (int i = 1; i < nbComponent; i++) {
// la référence sur le component courant
current = (Display) displayToLay.getComponent(i - 1);
// la référence sur le suivant
next = (Display) displayToLay.getComponent(i);
// Si le courant est un display d'opérateur alors on continue
if (current.isSymbolOperatorDisplay())
continue;
// Si le suivant n'est pas un display d'opérateur alors 2 cas
if (!next.isSymbolOperatorDisplay()) {
// La seule distinction qu'il faut faire à ce stade là, c'est le cas où next
// est le diplay d'un - unaire. Si c'est le cas, on n'insère pas de display.
fts = (FormulaTreeStructure) next.getListener();
if (fts.isOperator()) {
String ope = ((Operator) fts).getTheOperator();
if (ope.equals("-"))
continue;
}
// On ajoute un display d'opérateur.
displayOperator = createOperatorDisplay();
displayToLay.add(displayOperator, displayOperator, i);
// On met un listener à l'opérateur.
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
displayOperator.addControlListener(fatherFts);
i++;
nbComponent++;
}
}
// Mise à jour des rangs des displays
displayToLay.adjustRank();
// Mise à jour du nombre de components présents dans le display.
prevNbComponent = displayToLay.getComponentCount();
// On n'a plus besoin d'insérer des displays d'opérateur.
insertOperatorDisplay = false;
// On fait en sorte que la mise à niveau des displays (opérateurs) soit faite.
displayToLay.setUpdateLevel(true);
// On a rajouté un display, on demande le recalcul de tous les ancêtres
// de l'instance.
displayToLay.computeAncestorsAttributes();
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
Display childDisplay;
DisplayLayout childLayout;
SelectionEvent selEvt = new SelectionEvent(displayToLay);
int nbChild = displayToLay.getComponentCount();
// On parcourre la liste des displays, et on regarde sur chacun des dispays s'il faut sélectionner
// un de ses voisins.
for (int i = 0; i < nbChild; i++) {
childDisplay = (Display) displayToLay.getComponent(i);
childLayout = (DisplayLayout) childDisplay.getLayout();
// On regarde ici s'il faut sélectionner le display à gauche de childLayout
// Si ledit display n'est pas sélectionner, on le sélectionne.
if (childLayout.selectLeftDisplay() && (i > 0)) {
childDisplay = (Display) displayToLay.getComponent(i-1);
if (!childDisplay.isSelected())
childDisplay.select();
}
 
// On regarde ici s'il faut sélectionner le display à droite de childLayout
// Si ledit display n'est pas sélectionner, on le sélectionne.
if (childLayout.selectRightDisplay() && (i < (nbChild - 1))) {
childDisplay = (Display) displayToLay.getComponent(i+1);
if (!childDisplay.isSelected())
childDisplay.select();
// On a sélectionné le display à la position i+1, donc on incrémente ici i,
// pour que dans le for, le i soit encore incrémenté et que l'on se positionne
// ainsi sur un display suivant, non sélectionné
i++;
}
}
// On parcourre la liste des displays et on regarde si les displays à gauche et à droite du display
// courant ont des éléments sélectionnés. Si c'est le cas et que le display courant est un display
// d'opérateur et qu'il n'est pas sélectionné, alors on sélectionne le display à gauche, le displa
// d'opérateur et le display à droite.
// Ex: (...) + (...), dans chacune des parenthèses, un élément est sélectionné, on sélectionne tout
Display prev;
Display next;
for (int i = 1; i < (nbChild - 1); i++) {
prev = (Display) displayToLay.getComponent(i-1);
childDisplay = (Display) displayToLay.getComponent(i);
next = (Display) displayToLay.getComponent(i+1);
if (prev.gotSelectedElements() && next.gotSelectedElements()) {
//if ((childDisplay instanceof StringDisplay) && !childDisplay.isSelected()) {
if (childDisplay.isSymbolOperatorDisplay() && !childDisplay.isSelected()) {
if (!prev.isSelected())
prev.select();
childDisplay.select();
if (!next.isSelected())
next.select();
}
}
}
// On créé maintenant une liste contenant tous les displays qui ont été sélectionnés au cours des
// opérations précédentes.
Vector list = new Vector();
for (int i = 0; i < nbChild; i++) {
childDisplay = (Display) displayToLay.getComponent(i);
if (childDisplay.gotSelectedElements())
list.addElement(childDisplay);
}
 
if (list.size() > 0) {
if ((list.size() == nbChild) && !(displayToLay.getListener() instanceof Formula) && !(displayToLay.getListener() instanceof Slot)) {
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
 
displayToLay.setSelected();
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
else if (list.size() != 1) {
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
 
for (Enumeration e = list.elements(); e.hasMoreElements(); ) {
childDisplay = (Display) e.nextElement();
if (!childDisplay.isSelected())
childDisplay.select();
selEvt.setAction(SelectionEvent.ADD, childDisplay);
displayToLay.fireSelectionEvent(selEvt);
}
}
}
// On a une sélection valide dans le display layed.
// On demande la validation au niveau de son père.
// En principe, à cause du test sur le fait d'avoir une Formula, pas besoin
// d'avoir le test juste suivant. A surveiller.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
//if (!(display.getListener() instanceof Formula))
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
display.repaint(); // faut voir, parce que autant de repaint que de display ?????????
}
 
 
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
Display tmp;
SelectionEvent selEvt = new SelectionEvent(father);
int rank = display.getRank();
 
// Premier cas: father (i.e. le display géré par l'instance) est sélectionné.
if (father.isSelected()) {
// On l'enlève de la liste des displays sélectionnés.
father.setNotSelected();
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
 
// Comme on arrive dans cette méthode par display, display a été déjà désélectionné.
// De plus, ce LM gère principalement (voire que) des displays N-aires dont il s'agit
// la plupart du temps d'une succession de displays opérandes entre lesquels se trouvent
// des displays opérateur (ex: + ou *).
// Donc, s'ils existent, on doit alors désélectionner le display précédent et le display
// suivant... display. (d'où récupération du rang de display au début)
 
// On s'occupe du display précédant... display.
if (rank > 0) {
if (!(display.getListener() instanceof UnaryMinus)) {
// Il existe un display avant... display, donc on prend garde de le désélectionner,
// s'il était sélectionné.
tmp = ((Display) father.getComponent(rank-1));
if (tmp.isSelected()) {
// On désélectionne donc ledit display.
tmp.deselect();
 
// Maintenant, on regarde s'il existe un display précédent celui que l'on vient
// de désélectionner, qui est un display d'opérateur et qui est sélectionné.
// Si c'est le cas, on le désélectionne.
if (rank > 1) {
tmp = ((Display) father.getComponent(rank-2));
if (tmp.isSymbolOperatorDisplay() && tmp.isSelected())
tmp.deselect();
}
}
}
}
 
// On s'occupe du display suivant... display.
if (rank < (father.getComponentCount()-1)) {
// Il existe un display après... display, donc on prend garde de le désélectionner,
// s'il était sélectionné.
tmp = ((Display) father.getComponent(rank+1));
// Il faut faire attention dans le cas d'une addition où il y aurait un opérateur unaire.
// (Normalement seulement un UnaryMinus). Dans le cas le plus simple, une soustraction: a-b
// Si a-b est sélectionné et que l'on arrive ici parce on a désélectionné a, alors -b doit rester
// sélectionné. D'où ce cas particulier supplémentaire.
if (!(tmp.getListener() instanceof UnaryMinus)) {
if (tmp.isSelected()) {
tmp.deselect();
 
// Maintenant, on regarde s'il existe un display suivant celui que l'on vient
// de désélectionner, qui est un display d'opérateur et qui est sélectionné.
// Si c'est le cas, on le désélectionne.
if (rank < (father.getComponentCount()-2)) {
tmp = ((Display) father.getComponent(rank+2));
if (tmp.isSymbolOperatorDisplay() && tmp.isSelected())
tmp.deselect();
}
}
}
else
((LeftAssocPrefixedUnaryOperatorLayout) tmp.getLayout()).setSelectLeftDisplay(false);
}
// On parcourre la liste des display de father et on ajoute dans la liste des sélectionnés,
// ... les sélectionnés.
for (int i = 0; i < father.getComponentCount(); i++) {
tmp = (Display) father.getComponent(i);
if (tmp.isSelected()) {
selEvt.setAction(SelectionEvent.ADD, tmp);
father.fireSelectionEvent(selEvt);
}
}
// On regarde maintenant au niveau supérieur, si la désélection de father génère
// une désélection qui est valide.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
}
// Deuxième cas: father (i.e. le display géré par l'instance) n'est pas sélectionné.
// Mais, il en a des sélectionnés, puisque display fait partie de sa descendance.
else {
// Et bien, on fait exactement la même chose que précédemment, à la différence importante
// que là, les displays sélectionnés font partie de la liste des displays sélectionnés.
// Il faut donc les y enlever.
if (rank > 0) {
if (!(display.getListener() instanceof UnaryMinus)) {
tmp = ((Display) father.getComponent(rank-1));
if (tmp.isSelected()) {
tmp.deselect();
selEvt.setAction(SelectionEvent.REMOVE, tmp);
father.fireSelectionEvent(selEvt);
 
if (rank > 1) {
tmp = ((Display) father.getComponent(rank-2));
if (tmp.isSymbolOperatorDisplay() && tmp.isSelected()) {
tmp.deselect();
selEvt.setAction(SelectionEvent.REMOVE, tmp);
father.fireSelectionEvent(selEvt);
}
}
}
}
}
 
if (rank < (father.getComponentCount()-1)) {
tmp = ((Display) father.getComponent(rank+1));
// Il faut faire attention dans le cas d'une addition où il y aurait un opérateur unaire.
// (Normalement seulement un UnaryMinus). Dans le cas le plus simple, une soustraction: a-b
// Si a-b est sélectionné et que l'on arrive ici parce on a désélectionné a, alors -b doit rester
// sélectionné. D'où ce cas particulier supplémentaire.
if (!(tmp.getListener() instanceof UnaryMinus)) {
if (tmp.isSelected()) {
tmp.deselect();
 
// Maintenant, on regarde s'il existe un display suivant celui que l'on vient
// de désélectionner, qui est un display d'opérateur et qui est sélectionné.
// Si c'est le cas, on le désélectionne.
if (rank < (father.getComponentCount()-2)) {
tmp = ((Display) father.getComponent(rank+2));
if (tmp.isSymbolOperatorDisplay() && tmp.isSelected())
tmp.deselect();
}
}
}
else
((LeftAssocPrefixedUnaryOperatorLayout) tmp.getLayout()).setSelectLeftDisplay(false);
}
}
 
// Comme toujours, on contrôle maintenant, avec les éventuels displays sélectionnés restant,
// si la sélection est valide.
validateSelection();
// On met à jour le display.
father.repaint();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringBinaryInfixOperatorLayout.java
0,0 → 1,51
/*
$Id: StringBinaryInfixOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager for a binary infix operator which symbol can be rendered a simple string
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public class StringBinaryInfixOperatorLayout extends BinaryInfixOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), fts.getTheOperator(), true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/EnumerationLayout.java
0,0 → 1,106
/*
$Id: EnumerationLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager for enumeration<BR>
*
* @author © 1999 DIRAT Laurent
* @version 2.0 17/12/1999
*/
public class EnumerationLayout extends BracketLayout {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay); // Par cet appel, on ajoute dans displayToLay les accolades
// On va maintenant y rajouter un display, dans lequel on va mettre tous les displays correspondants
// aux éléments de la liste, display à qui on va affecter un SeparatorOperatorLayout, qui va se charger
// d'afficher les éléments de la liste de manière horizontale avec chacun des éléments séparés par une
// virgule (un séparateur)
Display elementsDisplay = new BidimDisplay(displayToLay.getGraphicContext());
// On met un listener à elementsDisplay
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
elementsDisplay.addControlListener((FormulaTreeStructure) displayToLay.getListener());
SeparatorOperatorLayout layout = new SeparatorOperatorLayout();
layout.initDisplay(elementsDisplay);
elementsDisplay.setLayout(layout);
// On l'ajoute comme fils à display
this.displayToLay.add(elementsDisplay);
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
updateLevel(displayToLay.getLevel());
if (displayToLay.getComponentCount() > 3) {
// Dans l'ordre, displayToLay contient [opening, closing, elementsDisplay, var1, var2, ...]
// Il faut mettre tous les vari dans elementsDisplay.
Display elementsDisplay = (Display) displayToLay.getComponent(2);
Display d;
for (int i = 3; i < displayToLay.getComponentCount(); ) {
d = (Display) displayToLay.getComponent(i);
// elementsDisplay.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
elementsDisplay.add(d);
// On remet le comportement de suppression par défault.
d.setDoRemoveFromListListeners(true);
}
}
return super.computeAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/resources.properties
0,0 → 1,163
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
# Resources file for the rendering of the expression:
# The syntax is the following :
#
# modelId = idDisplay:layoutManager
#
# modelId is the identifier of the model (formula tree structure node) we want to display. The identifier we find
# in this resources file should (probably must) match the ones present in the resources file for the formula tree
# structure model.
#
# idDisplay is the identifier of the display which will be in charge of displaying the corresponding element of the
# expression. The kind of display is fully determine, and the value this field must take is one of the following :
#
# constant : for elements which are rendered as a string (variables names, numbers, ...)
# symbol : for elements which are rendered as an image (pi, greek letters, special symbols, ...)
# icon : for iconified parts of the expression
# default : for the operators in general (i.e. displays containing other displays (operands displays))
#
# layoutManager is the layout manager in charge of the positioning of the operand and the rendering of the symbol
# operator when needed. This field is ONLY required when idDisplay = default. The 3 others are specific displays
# then the layout manager is automatically set. So, this field can be omitted.
# This field represents the fully qualified name of the class (package name attached) to instanciate.
#
 
VARIABLE = constant
INTEGER = constant
FLOAT = constant
? = constant
 
ADDITION = default:fr.ove.openmath.jome.ctrlview.bidim.BasicStringInfixOperatorLayout
UNARYMINUS = default:fr.ove.openmath.jome.ctrlview.bidim.StringLeftAssocPrefixedUnaryOperatorLayout
UNARYPLUS = default:fr.ove.openmath.jome.ctrlview.bidim.StringLeftAssocPrefixedUnaryOperatorLayout
MULTIPLICATION = default:fr.ove.openmath.jome.ctrlview.bidim.BasicStringInfixOperatorLayout
DIVISION = default:fr.ove.openmath.jome.ctrlview.bidim.FractionLayout
POWER = default:fr.ove.openmath.jome.ctrlview.bidim.SuperscriptLayout
 
EQUAL = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
UNEQUAL = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
LESS = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
LESSEQUAL = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
GREATER = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
GREATEREQUAL = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
 
UNDERSCRIPT = default:fr.ove.openmath.jome.ctrlview.bidim.UnderscriptLayout
SLOT = default:fr.ove.openmath.jome.ctrlview.bidim.SlotLayout
 
ICON = icon
#subst = default:fr.ove.openmath.jome.ctrlview.bidim.SubstitutionLayout
 
OPEN_PAREN = default:fr.ove.openmath.jome.ctrlview.bidim.BracketLayout
OPEN_BRACKET = default:fr.ove.openmath.jome.ctrlview.bidim.IntervalLayout
CLOSE_BRACKET = default:fr.ove.openmath.jome.ctrlview.bidim.IntervalLayout
# jm.evers
langle = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
rangle = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
lbracket = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
rbracket = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
neq = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
div = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
and = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
or = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
mapsto = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
cup = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
rightarrow = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
array = default:fr.ove.openmath.jome.ctrlview.bidim.ArrayLayout
 
#
in = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
notin = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
union = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
intersect = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
 
defaultFunction = default:fr.ove.openmath.jome.ctrlview.bidim.FunctionLayout
abs = default:fr.ove.openmath.jome.ctrlview.bidim.AbsoluteLayout
conj = default:fr.ove.openmath.jome.ctrlview.bidim.ConjugateLayout
int = default:fr.ove.openmath.jome.ctrlview.bidim.IntegralLayout
root = default:fr.ove.openmath.jome.ctrlview.bidim.RootLayout
sqrt = default:fr.ove.openmath.jome.ctrlview.bidim.RootLayout
sum = default:fr.ove.openmath.jome.ctrlview.bidim.SigmaLayout
prod = default:fr.ove.openmath.jome.ctrlview.bidim.ProductLayout
lambda = default:fr.ove.openmath.jome.ctrlview.bidim.LambdaExpLayout
diff = default:fr.ove.openmath.jome.ctrlview.bidim.DifferentiationLayout
request = default:fr.ove.openmath.jome.ctrlview.bidim.RequestLayout
entry = default:fr.ove.openmath.jome.ctrlview.bidim.RequestLayout
OPEN_CURLY = default:fr.ove.openmath.jome.ctrlview.bidim.HorizontalListLayout
vlist = default:fr.ove.openmath.jome.ctrlview.bidim.VerticalListLayout
subst = default:fr.ove.openmath.jome.ctrlview.bidim.VerticalListLayout
substElem = default:fr.ove.openmath.jome.ctrlview.bidim.Mfd2SubstitutionLayout
 
# Only used when no layout manager has been found. Specified a default layout manager.
defaultLM = default:fr.ove.openmath.jome.ctrlview.bidim.FunctionLayout
 
C = symbol
N = symbol
Q = symbol
R = symbol
Z = symbol
infty = symbol
 
 
E = constant
I = constant
 
true = constant
false = constant
 
pi = symbol
delta = symbol
gamma = symbol
alpha = symbol
alfa = symbol
beta = symbol
chi = symbol
epsilon = symbol
eta = symbol
iota = symbol
kappa = symbol
mu = symbol
nabla = symbol
nu = symbol
omega = symbol
phi = symbol
psi = symbol
rho = symbol
sigma = symbol
tau = symbol
theta = symbol
upsilon = symbol
zeta = symbol
xi = symbol
 
fact = default:fr.ove.openmath.jome.ctrlview.bidim.StringPostfixedUnaryOperatorLayout
rat = default:fr.ove.openmath.jome.ctrlview.bidim.FractionLayout
cc = default:fr.ove.openmath.jome.ctrlview.bidim.BracketLayout
cp = default:fr.ove.openmath.jome.ctrlview.bidim.SlotLayout
 
lim = default:fr.ove.openmath.jome.ctrlview.bidim.LimitLayout
 
#o = default:fr.ove.openmath.jome.ctrlview.bidim.StringBinaryInfixOperatorLayout
o = default:fr.ove.openmath.jome.ctrlview.bidim.ImageBinaryInfixOperatorLayout
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/OverOperatorLayout.java
0,0 → 1,46
/*
$Id: OverOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.Bar;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
import fr.ove.utils.FontInfo;
 
/**
* Layout manager that lays the display of the operator whose symbol is located over its operand (e.g. like conjugate)
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public abstract class OverOperatorLayout extends SuperposedOperatorLayout {
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringPrefixedUnaryOperatorLayout.java
0,0 → 1,52
/*
$Id: StringPrefixedUnaryOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* This layout manager lays prefixed unary operators.<BR>
* The symbol of the operator can be rendered as a simple string
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public class StringPrefixedUnaryOperatorLayout extends UnaryOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), fts.getTheOperator(), true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ImageOverOperatorLayout.java
0,0 → 1,64
/*
$Id: ImageOverOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of the operator whose symbol is located over its operand.<BR>
* The symbol is represented as a simple string
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class ImageOverOperatorLayout extends OverOperatorLayout {
/**
* The symbol we have to insert between each component if necessary.
*/
private ImageSymbol symbolOperator = null;
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
if (symbolOperator == null) {
Operator fts = (Operator) displayToLay.getListener();
//symbolOperator = new ImageSymbol(fts.getTheOperator(), displayToLay);
symbolOperator = new ImageSymbol(fts.getResourceIdentifier(), displayToLay);
}
// On créé un display pour l'opérateur.
SymbolDisplay operatorDisplay = new SymbolDisplay(displayToLay.getGraphicContext(), symbolOperator);
operatorDisplay.setIsSymbolOperatorDisplay(true);
return operatorDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringLeftAssocPrefixedUnaryOperatorLayout.java
0,0 → 1,52
/*
$Id: StringLeftAssocPrefixedUnaryOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* This layout manager lays prefixed unary operators.<BR>
* The symbol of the operator can be rendered as a simple string (e.g. +, -)
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public class StringLeftAssocPrefixedUnaryOperatorLayout extends LeftAssocPrefixedUnaryOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), fts.getTheOperator(), true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/LambdaExpLayout.java
0,0 → 1,185
/*
$Id: LambdaExpLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components of a function.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 20/07/1999
*/
public class LambdaExpLayout extends HorizontalLayout {
private boolean arrangeDisplay = true; // Au premier calcul, il faudra arranger les displays correctement
private Display enumeration = null;
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
// La fts associée au display
LambdaExpression fts = (LambdaExpression) this.displayToLay.getListener();
GraphicContext gc = this.displayToLay.getGraphicContext();
// Display temporaire pour manipulations
Display displayElems = null;
if (!fts.isJustFunction()) {
if (fts.getNbChildren() > 2) {
// Alors il faut qu'on ajoute un display supplémentaire, qui contiendra les variables liées
// du bind. Ce display aura un EnumerationLayout.
enumeration = new BidimDisplay(gc);
enumeration.addControlListener(fts);
EnumerationLayout layout = new EnumerationLayout();
layout.initDisplay(enumeration);
enumeration.setLayout(layout);
this.displayToLay.add(enumeration);
}
// Le symbole de la flèche
SymbolDisplay arrow = new SymbolDisplay(gc, new ImageSymbol("RightArrow", this.displayToLay));
// Le display de la somme est le display d'un opérateur (on peut le considérer comme tel)
arrow.setIsSymbolOperatorDisplay(true);
this.displayToLay.add(arrow);
arrow.addControlListener(fts);
}
// De part la méthode d'allocation des displays, si fts.isJustFunction() est vrai, alors display n'a
// pour le moment pas de fils.
// Si fts.getNbChildren() > 2, alors display contient, dans cet ordre [enumeration, arrow].
// Sinon, display contient seulement [arrow]
// Donc selon les cas, après allocation complète, display sera de la forme :
// [ftc, var1, var2,....] : il faut donc virer les var* (puisqu'en fait <=> fts.isJustFunction() == true)
// [arrow, fct, var1] : juste faire un shiftX pour que affichage soit de la forme [var1, arrow, fct]
// [enumeration, arrow, fct, var1, var2, ...] : il faut mettre les var* comme fils de enumeration
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
updateLevel(displayToLay.getLevel());
LambdaExpression fts = (LambdaExpression) displayToLay.getListener();
if (displayToLay.getComponentCount() > 3) {
//if (arrangeDisplay) {
if (!fts.isJustFunction()) {
if (fts.getNbChildren() > 2) {
// On enlève tous les displays correspondant en fait aux variables, de displayToLay,
// pour le mettre comme fils à enumeration
//Display enumeration = (Display) displayToLay.getComponent(0);
Display d;
for (int i = 3; i < displayToLay.getComponentCount(); ) {
d = (Display) displayToLay.getComponent(i);
// enumeration.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
enumeration.add(d);
// On remet le comportement de suppression par défault.
d.setDoRemoveFromListListeners(true);
}
}
}
else {
// On enlève tous les displays correspondant en fait aux variables.
for (int i = 1; i < displayToLay.getComponentCount(); )
displayToLay.remove(i);
}
arrangeDisplay = false;
}
Dimension dim = super.computeAttributes();
if ((!fts.isJustFunction()) && (fts.getNbChildren() == 2)) {
// en fait un truc du style lambda(sin(x), x), displayToLay est de a forme [arrow, sin(x), x]
// faut faire en sorte qsue ce soit affiché [x, arrow, sin(x)]
((Display) displayToLay.getComponent(0)).setShiftX(((Display) displayToLay.getComponent(2)).getWidth());
((Display) displayToLay.getComponent(2)).setShiftX(-dim.width);
}
return dim;
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// Il y a besoin de reconstruire le display, seulement lorsque nous avons un lambda expression avec
// une variable. Au départ, display est de la forme [arrow, fct, var]. L'iconification modifie
// display de telle sorte qu'il devient [arrow, var, icon].
// Pour que cela colle avec le computeAttributes() il faut remettre dans l'ordre [arrox, icon, var]
LambdaExpression fts = (LambdaExpression) displayToLay.getListener();
if (!fts.isJustFunction() && (fts.getNbChildren() == 2)) {
Display variable = (Display) displayToLay.getComponent(1);
// On l'enlève mais on ne veut pas l'enlever de la liste des listeners dont elle fait partie
variable.setDoRemoveFromListListeners(false);
displayToLay.remove(variable);
// On remet le comportement par défaut
variable.setDoRemoveFromListListeners(true);
// On rajoute la variable à la fin de display
displayToLay.add(variable);
int count = displayToLay.getComponentCount();
for (int i = 0; i < count; i++)
((Display) displayToLay.getComponent(i)).setShiftX(0);
}
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/FormulaDisplay.java
0,0 → 1,209
/*
$Id: FormulaDisplay.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.Vector;
import fr.ove.openmath.jome.ctrlview.events.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.*;
import fr.ove.openmath.jome.ctrlview.bidim.images.ImageLoader;
import fr.ove.openmath.jome.model.*;
 
/**
* The bidimensional display of the elements of the formula.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 17/12/1999
*/
 
public class FormulaDisplay extends BidimDisplay {
/**
* The image loader.
*/
private static ImageLoader loader;
/**
* The default constructor.
*/
public FormulaDisplay() {
super(new GraphicContext());
// On affecte le layout manager d'une formule.
OneFormulaLayout layout = new OneFormulaLayout();
layout.initDisplay(this);
super.setLayout(layout);
// Création du gestionnaire de la sélection
SelectionManager selectionManager = new SelectionManager();
addSelectionEventListener(selectionManager);
// On charge les icones
loader = new ImageLoader(this);
}
/**
* Registers another listener to be informed of changes of the display.
* @param controlListener a listener to add.
*/
public void addControlListener(ControlListener controlListener) {
// ben ça, ça marche pas encore comme voulu !!!
// au moins dans café.
super.addControlListener(controlListener);
buildDisplay();
invalidate();
setComputeAttributes(true);
validate();
repaint();
}
/**
* Returns the preferred size of the display.
*/
public Dimension getPreferredSize() {
Dimension prefSize;
if (getComponentCount() == 0)
// si y a rien à afficher, on fixe une taille quelconque pour voir qque chose
prefSize = new Dimension(/*100, 50*/10, 10);
else
prefSize = super.getPreferredSize();
return prefSize;
}
/**
* Sets the layout manager for the display.<BR>
* In fact does nothing because the instance has its own display and must only have the one it has.
* Overrinden just to prevent unwanted manipulation.
* @param mgr the specified layout manager
*/
public void setLayout(LayoutManager lm) {
}
/***************************/
/* Gestion de la sélection */
/***************************/
 
/**
* Returns the linear expression of the selection.
*/
public String getLinearSelection() {
FormulaTreeStructure ftsSelection = getFtsSelection();
if (ftsSelection == null)
return "";
else
return ftsSelection.createLinear("");
}
 
/**
* Returns the selected displays.<BR>
* Display of symbol operator are not in this list.
*/
private Vector getSelection() {
SelectionEvent selectionEvent = new SelectionEvent(this);
 
// On récupère la taille de la sélection.
Integer selectionSize = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION_SIZE, selectionSize);
fireSelectionEvent(selectionEvent);
selectionSize = (Integer) selectionEvent.getArgument();
// Si différente de 0, il y a qque chose à récupérer.
if (selectionSize.intValue() != 0) {
// On récupère la sélection entière.
Vector selection = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION, selection);
fireSelectionEvent(selectionEvent);
selection = (Vector) selectionEvent.getArgument();
// On créé la liste des éléments à récupérer. (on enlève les displays
// d'opérateurs parasites, et aux displays qui restent, on récupère
// la fts dont ils sont le display).
Display selectionDisplay;
FormulaTreeStructure fts;
Vector toGet = new Vector();
for (int i = 0; i < selectionSize.intValue(); i++) {
selectionDisplay = (Display) selection.elementAt(i);
if (!selectionDisplay.isSymbolOperatorDisplay()) {
// On récupère le fts associé au display.
fts = (FormulaTreeStructure) selectionDisplay.getListener();
// On l'ajoute à la liste des fts à iconifier
toGet.addElement(fts);
}
}
 
return toGet;
}
return null;
}
/**
* Returns the formula tree structure associated with the selected displays.<BR>
* Returns <CODE>null</CODE> if there is no selected displays.
* For example, let us assume that the formula is a+b+c, and a and c are selected.
* The fts returned is the fts of a+c.
* @param selection the list of selected displays.
*/
private FormulaTreeStructure getFtsSelection() {
FormulaTreeStructure ftsSelection = null;
Vector selection = getSelection();
if (selection != null) {
ftsSelection = (FormulaTreeStructure) selection.elementAt(0);
if ((selection.size() == 1) &&
(!ftsSelection.isIcon() || (ftsSelection.isIcon() && (((Icon) ftsSelection).getNbIconified() == 1)))) {
ftsSelection = (FormulaTreeStructure) ftsSelection.clone();
}
else {
FormulaTreeStructure childFts = null;
// On récupère le père dans la FTS du premier élément sélectionné
// pour savoir à quel type d'opération on a affaire.
ftsSelection = (FormulaTreeStructure) ftsSelection.getFather();
ftsSelection = (FormulaTreeStructure) ftsSelection.duplicate();
int count = selection.size();
for (int i = 0; i < count; i++) {
childFts = (FormulaTreeStructure) selection.elementAt(i);
childFts = (FormulaTreeStructure) childFts.clone();
ftsSelection.addChild(childFts);
}
}
}
return ftsSelection;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/MapsArrayLayout.java
0,0 → 1,273
/*
$Id: MapsArrayLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
modified MapsToSigmaLayout.java
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components to place them as the different elements like the operator
* sum does.<BR>
* The different elements are contained in the display in the following order :
* <UL>
* <LI>the symbol of the operator.a blank gif...</LI>
* <LI>the lower bound.</LI>
* <LI>the upper bound.</LI>
*</UL>
*
* Bounds are optional elements.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public abstract class MapsArrayLayout extends HorizontalLayout implements OperatorDisplayCreator {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
Display array = createOperatorDisplay();
array.addControlListener(this.displayToLay.getListener());
this.displayToLay.add(array);
}
/**
* Updates the level of the display that is layed out.<BR>
* @param level the level put to the display
*/
public void updateLevel(int level) {
Display tmp;
if (displayToLay.getUpdateLevel()) {
displayToLay.updateChildrenLevel();
// On met à jour le niveau du display géré par le LM.
displayToLay.setLevel(level);
displayToLay.setUpdateLevel(false);
// Le symbole a le même niveau que le display
tmp = (Display) displayToLay.getComponent(0);
((DisplayLayout) tmp.getLayout()).updateLevel(level);
tmp.setUpdateLevel(false);
int count = displayToLay.getComponentCount();
if (count > 1) {
// La borne inférieure a le niveau du dispay +1
tmp = (Display) displayToLay.getComponent(1);
((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
tmp.setUpdateLevel(false);
if (count > 2) {
// La borne supérieure a le niveau du dispay +1
tmp = (Display) displayToLay.getComponent(2);
((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
tmp.setUpdateLevel(false);
}
}
}
}
 
/**
* Checks the validity of the selection.
* @param display the display to select.
*/
public void validateSelection() {
Display symbol = (Display) displayToLay.getComponent(0);
//Display expression = (Display) displayToLay.getComponent(1);
//symbool=0 onder=1 boven=2
int count = displayToLay.getComponentCount();
// Si le symbole est sélectionné, on sélectionne tout le display
if (symbol.isSelected())
displayToLay.select();
else if (count > 1) {
Display lower = (Display) displayToLay.getComponent(1);
Display upper;
if (lower.gotSelectedElements()) {
if (count > 2) {
upper = (Display) displayToLay.getComponent(2);
if (upper.gotSelectedElements())
displayToLay.select();
}
}
}
// Quand on est ici, si display est sélectionné, alors c'est qu'on a validé un des tests
// ci-dessus. On doit alors mettre à jour le gestionnaire de sélections, et y ajouter display
if (displayToLay.isSelected()) {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute notre puissance.
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
 
// On a vérifié la validité de la sélection de la puissance. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
//if (!(display.getListener() instanceof Formula))
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
SelectionEvent selEvt = new SelectionEvent(father);
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
int count = father.getComponentCount();
((Display) father.getComponent(0)).setNotSelected();// On désélectionne le symbole.
if (count > 1) {
((Display) father.getComponent(1)).deselect();// On désélectionne la borne inf.
if (count > 2)
((Display) father.getComponent(2)).deselect();// On désélectionne la borne sup.
}
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
 
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int ascent = 0;
int descent = 0;
 
updateLevel(displayToLay.getLevel());
 
int width = 0;
int height = 0;
Display symbol, lower, upper;
int gap = 0;
// On calcule la taille du symbole
symbol = (Display) displayToLay.getComponent(0);
symbol.setSize(symbol.getPreferredSize());
int width1 = symbol.getWidth();
int count = displayToLay.getComponentCount();
if (count > 1) {
// On calcule la taille de la borne inférieure
lower = (Display) displayToLay.getComponent(1);
lower.setSize(lower.getPreferredSize());
lower.setShiftY(symbol.getDescent() + lower.getAscent() + gap);
width1 = Math.max(lower.getWidth(), width1);
if (count > 2 ) {
// On calcule la taille de la borne supérieure
upper = (Display) displayToLay.getComponent(2);
upper.setSize(upper.getPreferredSize());
width1 = Math.max(upper.getWidth(), width1);
upper.setShiftX(-(lower.getWidth() + upper.getWidth()) / 2);
upper.setShiftY(-(symbol.getAscent() + upper.getDescent() + gap));
ascent = symbol.getAscent() + upper.getHeight() + gap;
}
else {
ascent = symbol.getAscent();
}
symbol.setShiftX((width1 - symbol.getWidth()) / 2);
lower.setShiftX(-(symbol.getWidth() + lower.getWidth())/2 );
descent = symbol.getDescent() + lower.getHeight() + gap;
}
else {
ascent = symbol.getAscent();
descent = symbol.getDescent();
}
displayToLay.setAscent(ascent);
displayToLay.setDescent(descent);
width += width1 + 4*gap; // 1 gap entre symbole et expression, et 3 après expression
height += ascent + descent;
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
//Faudra faire ce qui faut !!!!
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/FormulaDisplayBeanInfo.java
0,0 → 1,94
/*
$Id: FormulaDisplayBeanInfo.java,v 1.4 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.beans.*;
import java.beans.SimpleBeanInfo;
//import symantec.itools.beans.*;
 
public class FormulaDisplayBeanInfo extends java.beans.SimpleBeanInfo
{
public FormulaDisplayBeanInfo()
{
}
 
/**
* Gets a BeanInfo for the superclass of this bean.
* @return BeanInfo[] containing this bean's superclass BeanInfo
*/
public BeanInfo[] getAdditionalBeanInfo()
{
try
{
BeanInfo[] bi = new BeanInfo[1];
bi[0] = Introspector.getBeanInfo(beanClass.getSuperclass());
return bi;
}
catch (IntrospectionException e)
{
throw new Error(e.toString());
}
}
 
/**
* Gets the SymantecBeanDescriptor for this bean.
* @return an object of type SymantecBeanDescriptor
* @see symantec.itools.beans.SymantecBeanDescriptor
*/
public BeanDescriptor getBeanDescriptor()
{
BeanDescriptor bd = new BeanDescriptor(beanClass);
bd.setValue("CAN_ADD_CHILD",new Boolean(true));
 
return bd;
}
 
/**
* Gets an image that may be used to visually represent this bean
* (in the toolbar, on a form, etc).
* @param iconKind the type of icon desired, one of: BeanInfo.ICON_MONO_16x16,
* BeanInfo.ICON_COLOR_16x16, BeanInfo.ICON_MONO_32x32, or BeanInfo.ICON_COLOR_32x32.
* @return an image for this bean
* @see BeanInfo#ICON_MONO_16x16
* @see BeanInfo#ICON_COLOR_16x16
* @see BeanInfo#ICON_MONO_32x32
* @see BeanInfo#ICON_COLOR_32x32
*/
public java.awt.Image getIcon(int nIconKind)
{
java.awt.Image img = null;
if (nIconKind == BeanInfo.ICON_COLOR_16x16)
img = loadImage("Icon_Bidim_16.gif");
if (nIconKind == BeanInfo.ICON_COLOR_32x32)
img = loadImage("Icon_Bidim_32.gif");
return img;
}
 
private final static Class beanClass = FormulaDisplay.class;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/FactorialLayout.java
0,0 → 1,54
/*
$Id: FactorialLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of the factorial operator
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public class FactorialLayout extends StringPostfixedUnaryOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), "!", true);
stringDisplay.setIsSymbolOperatorDisplay(true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ScriptLayout.java
0,0 → 1,188
/*
$Id: ScriptLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components horyzontally, but the last one in the
* list, is treated as a superscript or an underscript in the inherited classes.
* (There is a shift calculated)
*
* @author © 1999 DIRAT Laurent
* @version 2.0 19/07/1999
*/
public abstract class ScriptLayout extends HorizontalLayout {
/**
* Updates the level of the display that is layed out.<BR>
* @param level the level put to the display
*/
public void updateLevel(int level) {
Display tmp;
// Pour éviter de refaire le calcul plusieurs fois....
if (displayToLay.getUpdateLevel()) {
// On met le niveau adéquat
displayToLay.setLevel(level);
// On scale le display en fonction du niveau
displayToLay.scaleDisplay();
// On n'a plus besoin de mettre à jour le niveau de l'instance
displayToLay.setUpdateLevel(false);
// Le premier display fils possède le même niveau que son père.
tmp = (Display) displayToLay.getComponent(0);
((DisplayLayout) tmp.getLayout()).updateLevel(level);
// Le deuxième display fils possède le même niveau que la base + 1.
// (on applique une réduction de taille)
tmp = (Display) displayToLay.getComponent(1);
((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
}
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// La validité de la sélection est triviale.
// Si un des éléments de la puissance est sélectionné, alors la sélection
// de l'autre élément entraîne la sélection de toute la puissance.
Display base = (Display) displayToLay.getComponent(0);
Display script = (Display) displayToLay.getComponent(1);
if (base.gotSelectedElements() && script.gotSelectedElements()) {
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute notre puissance.
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
// On a vérifié la validité de la sélection de la puissance. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
// Ex : on a l'expression A+B^C et on a A déjà sélectionné. On sélectionne C.
// D'un pt de vue sémantique (oui, on va dire ça comme ça) A et C ne peuvent
// être sélectionnés séparément. Tout doit être sélectionné. Et ça, c'est la
// validation de la sélection qui va le déterminer. oufff....
Display display = displayToLay;
if (displayToLay.getParent() instanceof Display) {
display = (Display) displayToLay.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null) // Si fts n'est pas la racine de la formule, on valide la sélection
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display tmp;
SelectionEvent selEvt = new SelectionEvent(displayToLay);
if (displayToLay.isSelected()) {
// On désélectionne la puissance
displayToLay.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
// Si la puissance toute entière était sélectionnée, donc présente dans la liste
// des éléments sélectionné. Ce n'est pas le cas de la base et de l'exposant.
// Donc en fonction de cela, il faut y ajouter l'élément adéquat
if (((Display) displayToLay.getComponent(0)).isSelected())
// On a demandé la désélection en cliquant sur l'exposant, ce qui revient
// à sélectionner uniquement la base.
// On l'ajoute donc dans la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.ADD, (Display) displayToLay.getComponent(0));
else
// On a demandé la désélection en cliquant sur la base, ce qui revient
// à sélectionner uniquement l'exposant.
// On l'ajoute donc dans la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.ADD, (Display) displayToLay.getComponent(1));
 
displayToLay.fireSelectionEvent(selEvt);
 
// Comme pour la sélection, on contrôle la validité de la désélection.
Display father = displayToLay;
if (displayToLay.getParent() instanceof Display) {
father = (Display) displayToLay.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
Display tmp;
Display base = null;
Display script = null;
// On parcourre la liste des displays pour trouver qui est qui.
for (int i = 0; i < 2; i++) {
tmp = (Display) displayToLay.getComponent(i);
// On fait les initialisations qui s'imposent pour le bon repositionnement de chacun.
tmp.setLocation(0,0);
if (((FormulaTreeStructure) tmp.getListener()).getRank() == 0)
base = tmp;
else
script = tmp;
}
// On a retrouvé qui est qui, on reconstruit le display pour tout mettre
// à la bonne position.
displayToLay.removeAllDisplays();
displayToLay.add(base);
displayToLay.add(script);
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/LeftAssocPrefixedUnaryOperatorLayout.java
0,0 → 1,149
/*
$Id: LeftAssocPrefixedUnaryOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* This layout manager lays prefixed unary operators.<BR>
* Basically, unary + and unary - because these operators have the particularity to select the operand located
* to its left when selected.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public abstract class LeftAssocPrefixedUnaryOperatorLayout extends UnaryOperatorLayout {
/**
* Do we have to select the display to the left of the one the instance lays ?
*/
private boolean selectLeftDisplay;
/**
* Returns <CODE>true</CODE> if during the selection, the display which is located
* to the left of the display that the instance lays, must be selected too.
* <CODE>false</CODE> otherwise.
*/
public boolean selectLeftDisplay() {
// On est dans les opérateurs unaires, donc si le display tout entier
// est sélectionné, alors cela revient à avoir sélectionné l'opérateur,
// et donc il faut sélectionner le display de gauche dans la liste de
// display de son père.
if (displayToLay.isSelected())
return selectLeftDisplay;
else
return false;
}
/**
* Sets if the display to the left of that laid by the instance have to be selected
* or not.
* @param selectLeftDisplay <CODE>true</CODE> if the left display have to be selected.
* <CODE>false</CODE> otherwise.
*/
public void setSelectLeftDisplay(boolean selectLeftDisplay) {
this.selectLeftDisplay = selectLeftDisplay;
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// La validité de la sélection est triviale.
// Si le display de l'opérateur ou si le display de l'opérande est
// sélectionné, on sélectionne tout le display.
Display op = (Display) displayToLay.getComponent(0);
Display opRand = (Display) displayToLay.getComponent(1);
if (op.isSelected() || opRand.isSelected()) {
selectLeftDisplay = op.isSelected() ? true : false;
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute l'instance dans la liste des sélectionnés
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
// On a vérifié la validité de la sélection de l'opérateur. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (displayToLay.getParent() instanceof Display) {
display = (Display) displayToLay.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
// father est le display de l'opérateur unaire.
Display father = displayToLay;
Display tmp;
SelectionEvent selEvt = new SelectionEvent(father);
// Si l'opérateur en entier est sélectionné, il faut le désélectionner
if (father.isSelected()) {
selectLeftDisplay = false;
father.deselect();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/VerticalListLayout.java
0,0 → 1,65
/*
$Id: VerticalListLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager for vertical list operator.<BR>
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public class VerticalListLayout extends VerticalLayout {
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
}
 
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringLayout.java
0,0 → 1,80
/*
$Id: StringLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.StringDisplay;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
 
/**
* A layout manager that lays strings.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 23/06/98
*/
public class StringLayout extends AbstractStringLayout {
/**
* Returns <CODE>true</CODE> if during the selection, the display which is located
* to the left of the display that lays the instance, must be selected too.
* <CODE>false</CODE> otherwise.
*/
public boolean selectLeftDisplay() {
if (displayToLay.isSelected() && displayToLay.isSymbolOperatorDisplay())
return true;
else
return false;
}
/**
* Returns <CODE>true</CODE> if during the selection, the display which is located
* to the right of the display that lays the instance, must be selected too.
* <CODE>false</CODE> otherwise.
*/
public boolean selectRightDisplay() {
if (displayToLay.isSelected() && displayToLay.isSymbolOperatorDisplay())
return true;
else
return false;
}
 
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/OneFormulaLayout.java
0,0 → 1,156
/*
$Id: OneFormulaLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays the display of a formula.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 22/07/1999
*/
public class OneFormulaLayout extends DisplayLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int width = 10; // Ca c'est parce que c'est la taille préferée du display de la formule
int height = 10; // faudra voir de modifier ça de manière plus propre.
if (displayToLay.getComponentCount() != 0) {
updateLevel(displayToLay.getLevel());
Display display = (Display) displayToLay.getComponent(0);
display.setSize(display.getPreferredSize());
width = 2*display.getShiftX() + display.getWidth();
height = 2*display.getShiftY() + display.getHeight();
 
displayToLay.setAscent(display.getShiftY() + display.getAscent());
displayToLay.setDescent(height - display.getAscent());
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
}
return new Dimension(width , height);
}
/**
* Selects the display (and its children if any)
* @param the display to select.
*/
public void selectDisplay() {
Display display = (Display) displayToLay.getComponent(0);
display.select();
SelectionEvent selEvt = new SelectionEvent(display);
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
display.fireSelectionEvent(selEvt);
selEvt.setAction(SelectionEvent.ADD, display);
display.fireSelectionEvent(selEvt);
}
 
 
/**
* Deselects the display.
* @param the display to deselect.
*/
public void deselectDisplay() {
Display display = (Display) displayToLay.getComponent(0);
display.deselect();
SelectionEvent selEvt = new SelectionEvent(display);
selEvt.setAction(SelectionEvent.PURGE, null);
display.fireSelectionEvent(selEvt);
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
}
 
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
 
// ***************************************************
// *** Implémentation de l'interface LayoutManager ***
 
 
/*
* Lays out the container in the specified panel.
* @param parent the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
// Ca c'est parce que c'est le layout manager de la formule. Et comme personne ne dit au container
// contenant la formule, que la taille de la formule a besoin d'être recalculée, il faut bien le
// faire qque part. Chaque display informe son père qu'il doit être recalculé, mais la formule ne
// le fait pas pour le sien.
parent.setSize(parent.getPreferredSize());
if (parent.getComponentCount() != 0) {
// On est obligé de faire ce test car comme lorsque la formule est "vide", on ne met pas template,
// parent ne contient aucun display fils.
Display display = (Display) parent.getComponent(0);
display.setSize(display.getPreferredSize());
display.setLocation(display.getShiftX(), display.getShiftY());
 
// On place maintenant les éventuels display enfants du display courant
display.doLayout();
}
}
 
// *** Fin de l'interface LayoutManager ***
// ****************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/DenominatorDiffLayout.java
0,0 → 1,67
/*
$Id: DenominatorDiffLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components for the denominator of a differentiation.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/10/1999
*/
public class DenominatorDiffLayout extends HorizontalLayout {
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
// On verra après
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
// On verra après
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/UnaryOperatorLayout.java
0,0 → 1,155
/*
$Id: UnaryOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* This layout manager lays unary operators.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public abstract class UnaryOperatorLayout extends HorizontalLayout implements OperatorDisplayCreator {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
// On récupère le fts associé (listener) au display.
FormulaTreeStructure fts = (FormulaTreeStructure) displayToLay.getListener();
Display displayOperator = createOperatorDisplay();
// On met un listener à l'opérateur.
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
displayOperator.addControlListener(fts);
// On ajoute le display d'opérateur en première position
//display.add(stringDisplay, stringDisplay, 0);
// A priori, display ne contient rien, donc un add(stringDisplay) suffit.
this.displayToLay.add(displayOperator);
this.displayToLay.computeAncestorsAttributes();
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// La validité de la sélection est triviale.
// Si le display de l'opérateur ou si le display de l'opérande est
// sélectionné, on sélectionne tout le display.
Display op = (Display) displayToLay.getComponent(0);
Display opRand = (Display) displayToLay.getComponent(1);
if (op.isSelected() || opRand.isSelected()) {
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute l'instance dans la liste des sélectionnés
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
// On a vérifié la validité de la sélection de l'opérateur. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (displayToLay.getParent() instanceof Display) {
display = (Display) displayToLay.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
// father est le display de l'opérateur unaire.
Display father = displayToLay;
Display tmp;
SelectionEvent selEvt = new SelectionEvent(father);
// Si l'opérateur en entier est sélectionné, il faut le désélectionner
if (father.isSelected()) {
father.deselect();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BidimDisplay.java
0,0 → 1,236
/*
$Id: BidimDisplay.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.BidimDisplayAllocator;
 
/**
* The bidimensional display of the elements of the formula.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 01/07/1999
*/
 
public class BidimDisplay extends Display {
/**
* The constructor.
* @param graphicContext the graphic context of the display.
*/
public BidimDisplay(GraphicContext graphicContext) {
super(graphicContext);
if (getDisplayAllocator() == null)
setDisplayAllocator(new BidimDisplayAllocator());
}
/**
* Paints the display.
* @param g where we paint the display.
*/
public void paint(Graphics g) {
Color old = g.getColor();
Rectangle bounds = getBounds();
GraphicContext gc = getGraphicContext();
if (isSelected())
g.setColor(gc.getSelectionColor());
else
g.setColor(gc.getBackgroundColor());
g.fillRect(0, 0, bounds.width, bounds.height);
g.setColor(gc.getForegroundColor());
if (weDrawBounds())
g.drawRect(0, 0, bounds.width -1, bounds.height - 1);
/*
// on trace la baseline
g.setColor(Color.red);
g.drawLine(0, getAscent(), bounds.width, getAscent());
*/
g.setColor(old);
super.paint(g);
}
// *****************************************************
// Implémentation de l'interface ModelListenerController
/**
* Consumes (i.e. treats) the event received from the model.
* @param modelEvent the event to consume.
*/
public void consumeModelEvent(ModelEvent modelEvent) {
FormulaTreeStructure fts = null;
int action = modelEvent.getAction();
switch (action) {
case ModelEvent.ADD :
// On ajoute un dispay.
// On récupère le FTS dont on doit ajouter, et par là même, créer le display
// qui lui est associé.
fts = (FormulaTreeStructure) modelEvent.getArgument();
Display newDisplay = buildDisplay(fts.getRank());
if (fts.isIcon()) {
SubstitutedDisplayManager iconLM = (SubstitutedDisplayManager) newDisplay.getLayout();
// On se trouve dans un cas particulier où, ajouter le display de l'icone
// entraîne des modifications sur le display qui le contient (i.e. l'instance courante).
// Il faut éliminer tous les displays dont les fts sont iconifiées.
FormulaTreeStructure iconifiedFts = null;
Display iconifiedDisplay = null;
int nbIconified = ((Icon) fts).getNbIconified();
for (int i = 0; i < nbIconified; i++) {
// Prend une fts iconifiée
iconifiedFts = ((Icon) fts).getIconified(i);
// On recherche le display qui lui est associé
int count = getComponentCount();
for (int j = 0; j < count; j++) {
iconifiedDisplay = (Display) getComponent(j);
if (iconifiedDisplay.isDisplay(iconifiedFts))
break;
}
if (iconifiedDisplay != null) {
// On en garde une trace en l'ajoutant dans le LM.
// Utile pour la désiconification.
iconLM.addSubstitutedDisplay(iconifiedDisplay);
// On l'enlève du père, mais on ne veut pas qu'il soit supprimé
// de la liste des listeners qu'il écoute
iconifiedDisplay.setDoRemoveFromListListeners(false);
remove(iconifiedDisplay);
iconifiedDisplay = null;
}
}
// On reconstruit le father pour que l'ordre des displays qui le composent
// corresponde à l'odre des fts dont ils sont les displays.
((DisplayLayout) getLayout()).rebuildDisplay();
}
 
break;
case ModelEvent.UPDATE :
Container container = this;
//container.invalidate();
while (container.getParent() != null)
container = container.getParent();
container.validate();
break;
case ModelEvent.REBUILD :
//System.out.println("ModelEvent.REBUILD : on rebuild le display");
// Dans un premier temps, on regarde si la reconstruction du display n'a pas
// été demandée lors d'une désiconification. Donc, on parcourt la liste des
// displays contenus dans l'instance courante pour vérifier si chacun est
// associé à un élément de la FTS. Si tel est le cas, on peut demander la
// reconstruction du display. Sinon, on est dans le cas de la désiconification,
// et donc il faut rajouter dans la liste des displays de l'instance courante
// tous les displays qui ont été préalablement iconifiés.
FormulaTreeStructure theFts = (FormulaTreeStructure) getListener();
FormulaTreeStructure theFtsChild = null;
Display theFtsChildDisplay = null;
int nbDisplay = getComponentCount();
// On parcourt la liste des displays.
for (int i = 0; i < nbDisplay; i++) {
theFtsChildDisplay = (Display) getComponent(i);
theFtsChild = (FormulaTreeStructure) theFtsChildDisplay.getListener();
// Si theFtsChild est une icone et qu'elle n'appartient à la liste des fils de son père
// (ça veut donc dire qu'on l'a supprimée lors d'une désiconification), on désiconifie
if (theFtsChild.isIcon() && !theFts.hasChild(theFtsChild)) {
Display displaySubstituted;
SubstitutedDisplayManager theIconLM = (SubstitutedDisplayManager) theFtsChildDisplay.getLayout();
// Tous les displays qui étaient iconifés sont rajoutés à l'instance courante.
for (int j = 0; j < theIconLM.getNbSubstitutedDisplay(); j++) {
displaySubstituted = theIconLM.getSubstitutedDisplay(j);
add(displaySubstituted);
// Lors de l'iconification, quand on supprime le display iconifié, on ne veut
// pas qu'il soit enlevé de la liste des listeners qu'il écoute.
// Par contre, quand on revient là, on se remet dans l'état par défaut qui est
// que l'on veut les supprimer de la liste des listeners.
displaySubstituted.setDoRemoveFromListListeners(true);
}
// On enlève le display de l'icon
remove(theFtsChildDisplay);
// On réajuste le nombre de displays contenus dans l'instance courante.
nbDisplay = getComponentCount();
// Idem pour l'index. Puisqu'on a enlevé un display, si on ne décrémente
// pas i, on va en sauter 1.
i--;
}
}
// On regarde si tous les éléments de la fts ont des displays associés.
// Sinon, il faut leur en construire un.
int count = theFts.getNbChildren();
boolean buildDisplay = true;
for (int i = 0; i < count; i++) {
buildDisplay = true;
theFtsChild = (FormulaTreeStructure) theFts.getChild(i);
for (int j = 0; j < nbDisplay; j++) {
theFtsChildDisplay = (Display) getComponent(j);
if (theFtsChildDisplay.isDisplay(theFtsChild)) {
buildDisplay = false;
break;
}
}
if (buildDisplay) {
buildDisplay(theFtsChild.getRank());
}
}
// Maintenant on peut reconstruire le display, en fait le bon réagencement des
// displays contenus dans l'instance.
((DisplayLayout) getLayout()).rebuildDisplay();
break;
case ModelEvent.CREATE :
buildDisplay();
invalidate();
setComputeAttributes(true);
validate();
repaint();
break;
case ModelEvent.CLEAR :
removeAll();
}
}
// *** Fin de l'interface ModelListenerController ***
// **************************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/DisplayableImpl.java
0,0 → 1,337
/*
$Id: DisplayableImpl.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.io.Serializable;
import fr.ove.openmath.jome.ctrlview.bidim.GraphicContext;
import fr.ove.openmath.jome.ctrlview.bidim.Sizable;
import fr.ove.openmath.jome.ctrlview.bidim.Localisable;
 
/**
* An implementation of the <CODE>Displayable</CODE> interface.<BR>
* Nevertheless, it is an abstract class, because we don't know a priori
* how to paint it. This will be one of the tasks of the inherited classes.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/06/1999
*/
public abstract class DisplayableImpl implements Displayable, Serializable {
/**
* The bounds of the instance. We keep location and size information.
*/
private Rectangle bounds;
/**
* Distance between the top of the bounding box of the element to display
* and its baseline.
*/
private int ascent;
 
/**
* Distance between the bottom of the bounding box of the element to display
* and its baseline.
*/
private int descent;
 
/**
* An horizontal shift.
*/
private int shiftX;
 
/**
* A vertical shift.
*/
private int shiftY;
/**
* The graphic context of the displayable object.
*/
private GraphicContext graphicContext;
/**
* The default constructor.<BR>
* By default, all the parameters equal to 0.
*/
public DisplayableImpl() {
this(new Rectangle(), 0, 0, 0, 0);
}
/**
* The constructor.
* @param bounds the bounds of the instance.
* @param ascent the ascent of the instance.
* @param descent the descent of the instance.
* @param shiftX the horizontal shift of the instance.
* @param shiftY the vertical shift of the instance.
*/
public DisplayableImpl(Rectangle bounds, int ascent, int descent, int shiftX, int shiftY) {
this.bounds = bounds;
this.ascent = ascent;
this.descent = descent;
this.shiftX = shiftX;
this.shiftY = shiftY;
}
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
// *************************************************
// *** Implémentation de l'interface Displayable ***
/**
* Sets the ascent.
* @param ascent the new ascent value.
*/
public void setAscent(int ascent) {
this.ascent = ascent;
}
/**
* Returns the ascent.
* @return the ascent.
*/
public int getAscent() {
return ascent;
}
/**
* Sets the descent.
* @param descent the new descent value.
*/
public void setDescent(int descent) {
this.descent = descent;
}
/**
* Returns the descent.
* @return the descent.
*/
public int getDescent() {
return descent;
}
/**
* Sets the horizontal shift.
* @param shiftX the new horizontal shift value.
*/
public void setShiftX(int shiftX) {
this.shiftX = shiftX;
}
/**
* Returns the horizontal shift.
* @return the horizontal shift.
*/
public int getShiftX() {
return shiftX;
}
/**
* Sets the vertical shift.
* @param shiftY the new vertical shift value.
*/
public void setShiftY(int shiftY) {
this.shiftY = shiftY;
}
/**
* Returns the vertical shift.
* @return the vertical shift.
*/
public int getShiftY() {
return shiftY;
}
/**
* Sets all the attributes.
* @param ascent the new ascent value.
* @param descent the new descent value.
* @param shiftX the new horizontal shift value.
* @param shiftY the new vertical shift value.
*/
public void setAttributes(int ascent, int descent, int shiftX, int shiftY) {
this.ascent = ascent;
this.descent = descent;
this.shiftX = shiftX;
this.shiftY = shiftY;
}
/**
* Sets the graphic context of the instance.
* @param graphicContext the graphic context.
*/
public void setGraphicContext(GraphicContext graphicContext) {
// contrairement à la création d'un display, il n'y a pas allocation mais maintient d'une référence
// sur graphicContext, qui est en fait le contexte graphique du display (dans notre cas précis) qui
// va afficher l'objet.
this.graphicContext = graphicContext;
}
/**
* Returns the graphic context of the instance.
*/
public GraphicContext getGraphicContext() {
return graphicContext;
}
// *** Fin de l'interface Displayable ***
// **************************************
// *************************************************
// *** Implémentation de l'interface Localisable ***
/**
* Sets the x-location of the instance.
* @param x the x-location of the instance.
*/
public void setX(int x) {
bounds.x = x;
}
/**
* Returns the x-location of the instance.
*/
public int getX() {
return bounds.x;
}
/**
* Sets the y-location of the instance.
* @param y the y-location of the instance.
*/
public void setY(int y) {
bounds.y = y;
}
/**
* Returns the y-location of the instance.
*/
public int getY() {
return bounds.y;
}
/**
* Sets the location of the instance.
* @param x the x-location of the instance.
* @param y the y-location of the instance.
*/
public void setLocation(int x, int y) {
bounds.setLocation(x, y);
}
/**
* Sets the location of the instance.
* @param location the location of the instance.
*/
public void setLocation(Point location) {
bounds.setLocation(location);
}
/**
* Returns the location of the instance.
* @return A <CODE>Point</CODE> representing the location of the instance.
*/
public Point getLocation() {
return bounds.getLocation();
}
// *** Fin de l'interface Localisable ***
// **************************************
// *********************************************
// *** Implémentation de l'interface Sizable ***
/**
* Returns the width of the instance.
*/
public int getWidth() {
return bounds.width;
}
/**
* Sets the width of the instance.
* @param width the width of the instance
*/
public void setWidth(int width) {
bounds.width = width;
}
/**
* Returns the height of the instance.
*/
public int getHeight() {
return bounds.height;
}
/**
* Sets the height of the instance.
* @param height the height of the instance
*/
public void setHeight(int height) {
bounds.height = height;
}
/**
* Returns the size of the instance.
*/
public Dimension getSize() {
return bounds.getSize();
}
/**
* Sets the size of the instance.
* @param width the width of the instance.
* @param height the height of the instance
*/
public void setSize(int width, int height) {
bounds.setSize(width, height);
}
/**
* Sets the size of the instance.
* @param size the size of the instance.
*/
public void setSize(Dimension size) {
bounds.setSize(size);
}
// Le comportement par défaut est que la taille de bounds est la taille préférée.
/**
* Returns the preferred size of the instance.
*/
public Dimension getPreferredSize() {
return bounds.getSize();
}
// *** Fin de l'interface sizable ***
// **********************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/AbstractStringDisplay.java
0,0 → 1,179
/*
$Id: AbstractStringDisplay.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import fr.ove.utils.NumberUtils;
import fr.ove.openmath.jome.ctrlview.bidim.StringLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.GraphicContext;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The display of a String.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 04/08/1999
*/
public abstract class AbstractStringDisplay extends BidimDisplay {
/**
* The string that the display represents.
*/
private String string;
/**
* The constructor.
* @param graphicContext the graphic context of the display.
* @param string the string to display
*/
public AbstractStringDisplay(GraphicContext graphicContext, String string) {
super(graphicContext);
this.string = string;
}
/**
* Sets a new string to the display.
* @param string the string to set.
*/
public void setString( String string ) {
this.string = string;
}
/**
* Returns the string to display.
* @return the string.
*/
public String getString() {
return string;
}
/**
* Scales the display.
*/
public void scaleDisplay() {
//System.out.println("string : " + string +" Level = " + getLevel());
setTheFont(getGraphicContext().scaleFont(getLevel()));
// Il faut que le layout manager recalcule les attributs du display.
setComputeAttributes(true);
// Ceci est nécessaire pour que ce soit le layout manager qui retourne
// la preferredSize du display, et donc qu'il y ait recalcul des attributs.
// Sinon, le container considère qu'il a une taille valide, et donc retourne
// comme preferredSize, la précédente, sans qu'il demande le recalcul au LM.
invalidate();
}
 
/**
* Paints the display.
* @param g where we paint the display.
*/
public void paint(Graphics g) {
super.paint(g);
Color old = g.getColor();
Font oldFont = g.getFont();
Rectangle bounds = getBounds();
if (isSelected())
g.setColor(getSelectionColor());
else
g.setColor(getBackgroundColor());
g.fillRect(0, 0, bounds.width /*- 1*/, bounds.height /*- 1*/);
g.setColor(getForegroundColor());
g.setFont(getFont());
if (weDrawBounds())
g.drawRect(0, 0, bounds.width - 1, bounds.height - 1);
if ( string.equals("*") )
g.drawString(string, 1, getHeight());
else if ( string.equals("-") )
g.drawString(string, 1, getAscent() - (int) Math.round(getDescent()*(40.0f/100.0f)));
else
g.drawString(string, 1, getAscent());
/*
// on trace la baseline
g.setColor(Color.red);
g.drawLine(0, getAscent(), bounds.width, getAscent());
*/
g.setColor(old);
g.setFont(oldFont);
}
/**
* Returns the insertion position for the moving of displays.
* @param mouseX the mouse position.
*/
public int computeInsertionPosition(int mouseX) {
int insertionPosition;
// Si l'instance courante est un display d'opérateur, alors la position
// d'insertion est la position de l'opérande dont le display suit l'instance
// courante.
if (isSymbolOperatorDisplay()) {
Display display = (Display) getParent();
display = (Display) display.getComponent(getRank() + 1); // On est sûr de pouvoir prendre rank+1
// puisque si on est sur une display d'opérateur, au pire on a un template.
insertionPosition = ((FormulaTreeStructure) display.getListener()).getRank();
}
else {
// On regarde la position de la souris.
// Si elle est inférieure à la moitié de la largeur de l'instance, alors
// la position d'insertion est la position de l'opérande dont l'instance est
// le display. Sinon, la position d'insertion est la position de l'opérande
// dont l'instance l'instance est le display + 1.
if (mouseX <= (getWidth() / 2))
insertionPosition = ((FormulaTreeStructure) getListener()).getRank();
else
insertionPosition = ((FormulaTreeStructure) getListener()).getRank() + 1;
// Pas de pb de test pour savoir si on n'est pas sur le dernier opérande
// puisqu'on est obligé dans ce cas de retourner le nbre réel + 1 pour dire
// effectivement que l'on insère à la dernière position.
}
// On retourne la position d'insertion calculée.
return insertionPosition;
}
public void ToString() {
super.ToString();
System.out.println(" string = " + string);
}
 
public void whoAmI() {
System.out.println("I am the StringDisplay : " + string);
System.out.println("My level is " + getLevel());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SuperscriptLayout.java
0,0 → 1,109
/*
$Id: SuperscriptLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components horyzontally, but the last one in the
* list, is treated as a superscript (there is an upward shitf).
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public class SuperscriptLayout extends ScriptLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int ascent = 0;
int descent = 0;
int width = 0;
int height = 0;
Display base, exponent;
int decalage = 0;
base = (Display) displayToLay.getComponent(0);
base.setSize(base.getPreferredSize());
width += base.getWidth() + base.getShiftX();
exponent = (Display) displayToLay.getComponent(1);
 
if (base.getLayout() instanceof SuperscriptLayout)
((DisplayLayout) exponent.getLayout()).updateLevel(((Display) base.getComponent(1)).getLevel()+ 1);
else
((DisplayLayout) exponent.getLayout()).updateLevel(base.getLevel()+ 1);
exponent.setSize(exponent.getPreferredSize());
if (base.getLayout() instanceof SuperscriptLayout) {
Display exp_base = (Display) base.getComponent(1);
decalage = computeExponentShift(exp_base, exponent);
}
else
decalage = computeExponentShift(base, exponent);
/* ############################# */
base.setShiftY(0); // ATTENTION : rajout !!!!!!
/* ############################# */
 
exponent.setShiftY(-decalage);
width += exponent.getWidth() + exponent.getShiftX();
displayToLay.setDescent(base.getDescent());
displayToLay.setAscent(decalage + exponent.getAscent());
height += displayToLay.getAscent() + displayToLay.getDescent();
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
/**
* Computes the shift of the script display.
* @param base the base of the script.
* @param script the script of the script.
*/
private /*public*/ int computeExponentShift(Display base, Display script) {
if (base instanceof StringDisplay)
return (int) (Math.round(base.getAscent()*0.3)) + script.getDescent() -
base.getShiftY();
else
return (int) (Math.round(base.getAscent()*0.7)) + script.getDescent() -
base.getShiftY();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/MapsToSigmaLayout.java
0,0 → 1,310
/*
$Id: MapsToSigmaLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components to place them as the different elements like the operator
* sum does.<BR>
* The different elements are contained in the display in the following order :
* <UL>
* <LI>the symbol of the operator.</LI>
* <LI>the expression.</LI>
* <LI>the lower bound.</LI>
* <LI>the upper bound.</LI>
*</UL>
*
* Bounds are optional elements.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public abstract class MapsToSigmaLayout extends HorizontalLayout implements OperatorDisplayCreator {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
Display sigma = createOperatorDisplay();
sigma.addControlListener(this.displayToLay.getListener());
this.displayToLay.add(sigma);
}
/**
* Updates the level of the display that is layed out.<BR>
* @param level the level put to the display
*/
public void updateLevel(int level) {
Display tmp;
if (displayToLay.getUpdateLevel()) {
displayToLay.updateChildrenLevel();
// On met à jour le niveau du display géré par le LM.
displayToLay.setLevel(level);
displayToLay.setUpdateLevel(false);
// Le symbole a le même niveau que le display
tmp = (Display) displayToLay.getComponent(0);
((DisplayLayout) tmp.getLayout()).updateLevel(level);
tmp.setUpdateLevel(false);
// L'expression de la somme a le même niveau que le display
tmp = (Display) displayToLay.getComponent(1);
((DisplayLayout) tmp.getLayout()).updateLevel(level);
tmp.setUpdateLevel(false);
int count = displayToLay.getComponentCount();
if (count > 2) {
// La borne inférieure a le niveau du dispay +1
tmp = (Display) displayToLay.getComponent(2);
((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
tmp.setUpdateLevel(false);
 
if (count > 3) {
// La borne supérieure a le niveau du dispay +1
tmp = (Display) displayToLay.getComponent(3);
((DisplayLayout) tmp.getLayout()).updateLevel(level+1);
tmp.setUpdateLevel(false);
}
}
}
}
 
/**
* Checks the validity of the selection.
* @param display the display to select.
*/
public void validateSelection() {
Display symbol = (Display) displayToLay.getComponent(0);
Display expression = (Display) displayToLay.getComponent(1);
int count = displayToLay.getComponentCount();
// Si le symbole est sélectionné, on sélectionne tout le display
if (symbol.isSelected())
displayToLay.select();
else if (count > 2) {
Display lower = (Display) displayToLay.getComponent(2);
Display upper;
if (lower.gotSelectedElements()) {
if (expression.gotSelectedElements())
displayToLay.select();
else if (count > 3) {
upper = (Display) displayToLay.getComponent(3);
if (upper.gotSelectedElements())
displayToLay.select();
}
}
else if (count > 3) {
upper = (Display) displayToLay.getComponent(3);
if (upper.gotSelectedElements()) {
if (expression.gotSelectedElements())
displayToLay.select();
}
}
}
// Quand on est ici, si display est sélectionné, alors c'est qu'on a validé un des tests
// ci-dessus. On doit alors mettre à jour le gestionnaire de sélections, et y ajouter display
if (displayToLay.isSelected()) {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute notre puissance.
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
 
// On a vérifié la validité de la sélection de la puissance. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
//if (!(display.getListener() instanceof Formula))
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
SelectionEvent selEvt = new SelectionEvent(father);
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
Display expression = (Display) father.getComponent(1);
int count = father.getComponentCount();
if (display != expression) {
// quand on désélectionne un élément de la somme, autre que l'expression, l'expression
// reste sélectionnée.
selEvt.setAction(SelectionEvent.ADD, expression);
father.fireSelectionEvent(selEvt);
}
((Display) father.getComponent(0)).setNotSelected();// On désélectionne le symbole.
if (count > 2) {
((Display) father.getComponent(2)).deselect();// On désélectionne la borne inf.
if (count > 3)
((Display) father.getComponent(3)).deselect();// On désélectionne la borne sup.
}
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
 
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int ascent = 0;
int descent = 0;
 
updateLevel(displayToLay.getLevel());
 
int width = 0;
int height = 0;
Display symbol, lower, expression, upper;
int gap = 2;
// On calcule la taille du symbole
symbol = (Display) displayToLay.getComponent(0);
symbol.setSize(symbol.getPreferredSize());
// On calcule la taille de l'expression de la somme
expression = (Display) displayToLay.getComponent(1);
expression.setSize(expression.getPreferredSize());
int width1 = symbol.getWidth();
int count = displayToLay.getComponentCount();
if (count > 2) {
// On calcule la taille de la borne inférieure
lower = (Display) displayToLay.getComponent(2);
lower.setSize(lower.getPreferredSize());
lower.setShiftY(symbol.getDescent() + lower.getAscent() + gap);
width1 = Math.max(lower.getWidth(), width1);
if (count > 3 ) {
// On calcule la taille de la borne supérieure
upper = (Display) displayToLay.getComponent(3);
upper.setSize(upper.getPreferredSize());
width1 = Math.max(upper.getWidth(), width1);
upper.setShiftX(-(lower.getWidth() + upper.getWidth()) / 2);
upper.setShiftY(-(symbol.getAscent() + upper.getDescent() + gap));
ascent = symbol.getAscent() + upper.getHeight() + gap;
}
else {
ascent = symbol.getAscent();
}
symbol.setShiftX((width1 - symbol.getWidth()) / 2);
expression.setShiftX(gap + (width1 - symbol.getWidth())/2);
lower.setShiftX(-(symbol.getWidth() + lower.getWidth())/2 - (expression.getWidth() + expression.getShiftX()));
descent = symbol.getDescent() + lower.getHeight() + gap;
}
else {
ascent = symbol.getAscent();
descent = symbol.getDescent();
}
displayToLay.setAscent(ascent);
displayToLay.setDescent(descent);
width += width1 + expression.getWidth() + 4*gap; // 1 gap entre symbole et expression, et 3 après expression
height += ascent + descent;
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
//Faudra faire ce qui faut !!!!
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/GraphicContext.java
0,0 → 1,212
/*
$Id: GraphicContext.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
 
/**
* The graphic context of each part of the formula to display.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 22/06/98
*/
public class GraphicContext implements java.io.Serializable {
/**
* The font used.
*/
private Font font;
/**
* The size of the font used.
*/
private int sizeRef; // Serves as the reference font size for font scales.
/**
* The color used to display the part of the formula.
*/
private Color foregroundColor;
/**
* The color used to display the background of the formula.
*/
private Color backgroundColor;
/**
* The color used to hilight the selected part.
*/
private static Color selectionColor;
/**
* How many times the scale factor is apply to reduce the font size.
*/
private int nbTime = 0;
/**
* The default constructor.<BR>
* The default is :
* <UL>
* <LI> a Times New Roman font, regular, with a size of 14 </LI>
* <LI> the foreground color set to black </LI>
* <LI> the background color set to white </LI>
* <LI> the selection color set to yellow </LI>
* </UL>
*/
public GraphicContext() {
this(new Font("Times New Roman", Font.PLAIN, 14), Color.black, Color.white, Color.yellow);
}
/**
* The Constructor.
*
* @param font the font used to display all the text elements.
* @param color the color used to display all the text elements.
* @param background the color used as background for the display.
* @param selectionColor the color of all the selected elements.
*/
public GraphicContext(Font font, Color foregroundColor, Color backgroundColor, Color selectionColor) {
this.font = font;
sizeRef = font.getSize();
this.foregroundColor = foregroundColor;
this.backgroundColor = backgroundColor;
this.selectionColor = selectionColor;
}
/**
* The constructor by copy.
* @param gc the graphic context to copy.
*/
public GraphicContext(GraphicContext gc) {
font = gc.getFont();
sizeRef = gc.getSizeRef();
foregroundColor = gc.getForegroundColor();
backgroundColor = gc.getBackgroundColor();
selectionColor = gc.getSelectionColor();
}
// ### The getters ###
/**
* Returns the font used in the graphic context.
*/
public Font getFont() {
return font;
}
/**
* Returns the reference size of the font.
*/
public int getSizeRef() {
return sizeRef;
}
/**
* Returns the color used by the graphic context.
*/
public Color getForegroundColor() {
return foregroundColor;
}
/**
* Returns the background for the display.
*/
public Color getBackgroundColor() {
return backgroundColor;
}
/**
* Returns the color used in the graphic context to hilight the selection.
* @return the color.
*/
public Color getSelectionColor() {
return selectionColor;
}
// ### The setters ###
/**
* Sets a new font to the context.
* @param font the new font.
*/
public void setFont(Font font) {
this.font = font;
sizeRef = font.getSize();
}
/**
* Sets a new color to the context.
* @param color the new color.
*/
public void setForegroundColor(Color foregroundColor) {
this.foregroundColor = foregroundColor;
}
/**
* Sets a new background color for the display.
* @param background the color used as background for the display.
*/
public void setBackgroundColor(Color backgroundColor) {
this.backgroundColor = backgroundColor;
}
/**
* Sets a new selection color to the context.
* @param selectionColor the new color.
*/
public void setSelectionColor(Color selectionColor) {
this.selectionColor = selectionColor;
}
/**
* Scales the current font.
* @param nbTime how many the scale factor is applied.
* @return the font scaled.
*/
public Font scaleFont(int nbTime) {
if (this.nbTime != nbTime) {
String name = font.getName();
int style = font.getStyle();
int size = sizeRef;
this.nbTime = nbTime;
for (int i = 0; i < nbTime; i++) {
size = (int) Math.round( ((float) size) * 0.7f );
if (size < 10)
break;
}
size = (size < 10) ? 10 : size;
font = new Font(name, style, size);
}
return font;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/HorizontalListLayout.java
0,0 → 1,108
/*
$Id: HorizontalListLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager for horizontal list operator.<BR>
* If the list operator is set as as visible list, curly brackets are displayed on both
* sides of the list elements.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class HorizontalListLayout extends CurlyLayout {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay); // Par cet appel, on ajoute dans displayToLay les accolades
// On va maintenant y rajouter un display, dans lequel on va mettre tous les displays correspondants
// aux éléments de la liste, display à qui on va affecter un SeparatorOperatorLayout, qui va se charger
// d'afficher les éléments de la liste de manière horizontale avec chacun des éléments séparés par une
// virgule (un séparateur)
Display elementsDisplay = new BidimDisplay(displayToLay.getGraphicContext());
// On met un listener à elementsDisplay
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
elementsDisplay.addControlListener((FormulaTreeStructure) displayToLay.getListener());
SeparatorOperatorLayout layout = new SeparatorOperatorLayout();
layout.initDisplay(elementsDisplay);
elementsDisplay.setLayout(layout);
// On l'ajoute comme fils à display
this.displayToLay.add(elementsDisplay);
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
updateLevel(displayToLay.getLevel());
if (displayToLay.getComponentCount() > 3) {
// Dans l'ordre, displayToLay contient [opening, closing, elementsDisplay, var1, var2, ...]
// Il faut mettre tous les vari dans elementsDisplay.
Display elementsDisplay = (Display) displayToLay.getComponent(2);
Display d;
for (int i = 3; i < displayToLay.getComponentCount(); ) {
d = (Display) displayToLay.getComponent(i);
// elementsDisplay.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
elementsDisplay.add(d);
// On remet le comportement de suppression par défault.
d.setDoRemoveFromListListeners(true);
}
}
return super.computeAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/LeftMiddlePar.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/Product.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/RightMiddleCurl.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/RightTopCurl.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/Infinity.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/LeftMiddleCurl.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/RightMiddlePar.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/langle.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/RightTopPar.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/mapsto.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/LeftBarCurl.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/LeftArrow.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/eq.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/longrightarrow.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/Pi.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/rangle.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/Array.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/or.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/LeftTopPar.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/div.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/LeftBottomPar.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/lbracket.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/cup.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/RightArrow.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/RightBarCurl.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/RightBottomCurl.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/rbracket.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/Sigma.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/and.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/Rond.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/LeftTopCurl.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/LeftBottomCurl.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/RightBottomPar.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/symbols/Integrale.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/ImageLoader.java
0,0 → 1,307
/*
$Id: ImageLoader.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim.images;
 
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.io.*;
import fr.ove.openmath.jome.ctrlview.bidim.images.*;
import fr.ove.utils.ByteVector;
 
/**
* This class is a little tool to load images.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 17/02/99
*/
public class ImageLoader implements Serializable {
/**
* The hashtable which contains all the images loaded.
*/
private static Hashtable allImages;
// On utilise un mediatracker pour pouvoir attendre que toutes les
// images soient chargées avant de rendre la main.
private static MediaTracker tracker;
// On récupère la toolkit par défaut pour créer les images.
private static Toolkit toolkit;
private static Class theClass;
/**
* The image resources manager.
*/
private static ImagesResourcesManager imagesResourcesManager = new ImagesResourcesManager("fr.ove.openmath.jome.ctrlview.bidim.images.ImagesResources");
/**
* The Constructor.<BR>
* This constructor is used in the case of an application, and not an applet such
* as the precedent does.
* @param component the component which needs the images to load.
*/
public ImageLoader(Component component) {
theClass = getClass();
 
// On utilise un mediatracker pour pouvoir attendre que toutes les
// images soient chargées avant de rendre la main.
tracker = new MediaTracker(component);
allImages = new Hashtable(10); // On crée la table de Hashcode
// On récupère la toolkit par défaut pour créer les images.
toolkit = Toolkit.getDefaultToolkit();
// On charge les parenthèses pour que ce soit un peu plus rapide (c'est a priori
// les images les plus suceptibles d'être chargées)
getImage("LeftTopPar");
getImage("LeftMiddlePar");
getImage("LeftBottomPar");
getImage("RightTopPar");
getImage("RightMiddlePar");
getImage("RightBottomPar");
}
 
/**
* Returns the image with the specified name.
* @param name the name of the desired image.
* @return the desired image.
*/
public static Image getImage(String name) {
Image image = (Image) allImages.get(name);
 
if (image == null)
image = setImage(name);
 
return image;
}
/**
* Returns the height factor to apply to the orignal size of the wanted image.
* @param idImage the identifier of the wanted image
*/
public static float getHeightFactor(String idImage) {
float heightFactor = 1.0f;
try {
String height = imagesResourcesManager.getHeightFactor(idImage);
if (height != null)
heightFactor = Float.valueOf(height).floatValue();
}
catch (NumberFormatException fne) {
System.out.println("height factor is not a valid number.");
}
catch (Exception e) {
System.out.println("height factor is not a valid number."); // erreur d'un autre type
}
return heightFactor;
}
/**
* Returns the baseline of the wanted image. If the returned value equals -1n the baseline corresponds
* the one of the current font.
* @param idImage the identifier of the wanted image
*/
public static float getBaseline(String idImage) {
float baseline = -1.0f; // Si -1, alors la baseline est celle de la police courante.
try {
String base = imagesResourcesManager.getBaseline(idImage);
if (base != null)
baseline = Float.valueOf(base).floatValue();
}
catch (NumberFormatException fne) {
System.out.println("baseline has not a valid number.");
}
catch (Exception e) {
System.out.println("baseline has not a valid number."); // erreur d'un autre type
}
return baseline;
}
/**
* @param idImage the identifier of the wanted image
*/
public static float getTopInset(String idImage) {
float inset = 0.0f;
try {
String srtInset = imagesResourcesManager.getTopInset(idImage);
if (srtInset != null)
inset = Float.valueOf(srtInset).floatValue();
}
catch (NumberFormatException fne) {
System.out.println("top inset has not a valid number.");
}
catch (Exception e) {
System.out.println("top inset has not a valid number."); // erreur d'un autre type
}
return inset;
}
/**
* @param idImage the identifier of the wanted image
*/
public static float getBottomInset(String idImage) {
float inset = 0.0f;
try {
String srtInset = imagesResourcesManager.getBottomInset(idImage);
if (srtInset != null)
inset = Float.valueOf(srtInset).floatValue();
}
catch (NumberFormatException fne) {
System.out.println("bottom inset has not a valid number.");
}
catch (Exception e) {
System.out.println("bottom inset has not a valid number."); // erreur d'un autre type
}
return inset;
}
/**
* @param idImage the identifier of the wanted image
*/
public static float getLeftInset(String idImage) {
float inset = 0.0f;
try {
String srtInset = imagesResourcesManager.getLeftInset(idImage);
if (srtInset != null)
inset = Float.valueOf(srtInset).floatValue();
}
catch (NumberFormatException fne) {
System.out.println("left inset has not a valid number.");
}
catch (Exception e) {
System.out.println("left inset has not a valid number."); // erreur d'un autre type
}
return inset;
}
/**
* @param idImage the identifier of the wanted image
*/
public static float getRightInset(String idImage) {
float inset = 0.0f;
try {
String srtInset = imagesResourcesManager.getRightInset(idImage);
if (srtInset != null)
inset = Float.valueOf(srtInset).floatValue();
}
catch (NumberFormatException fne) {
System.out.println("right inset has not a valid number.");
}
catch (Exception e) {
System.out.println("right inset has not a valid number."); // erreur d'un autre type
}
return inset;
}
/**
* Checks if there exist an image with the specified identifier.
* @param idImage the identifier of the wanted image
*/
public static boolean exists(String idImage) {
return (imagesResourcesManager.getImageName(idImage) == null);
}
/**
* Loads the image with the specified name and put it in the hashtable with the specified key.
* @param name the name of theimage to load
* @param key the key of the image in the hastable
* @return the desired image
*/
private static Image loadImage(String name, String key) throws Exception {
Image image = null;
java.io.InputStream iStream = theClass.getResourceAsStream(name);
try {
int read;
ByteVector byteImage = new ByteVector();
while ((read = iStream.read()) != -1) {
byteImage.addElement((byte) read);
if (iStream.available() == 0)
break;
}
image = toolkit.createImage(byteImage.getBytes());
iStream.close();
}
catch (IOException e){
System.out.println("Impossible to read image : IO problems");
e.printStackTrace();
}
catch (Exception e){
System.out.println("Impossible to create image");
e.printStackTrace();
}
if (image != null) {
allImages.put(key, image);
tracker.addImage(image, 0);
// On attend que toutes les images soient chargées.
try {
tracker.waitForAll();
}
catch (InterruptedException e) {
System.out.print(e.toString());
}
if (tracker.isErrorAny())
throw new Exception("Impossible to load image");
}
return image;
}
private static Image setImage(String name) {
Image image = null;
try {
String imgName = imagesResourcesManager.getImageName(name);
if (imgName == null)
image = getImage("undef");
else
image = loadImage(imgName, name);
return image;
}
catch (Exception e) {
e.printStackTrace();
return image;
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/ImagesResources.properties
0,0 → 1,158
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
# Resources file for images in the expression :
# The syntax is the following :
#
# imageId = imageName:heightFactor:baseline:tInset:bInset:lInset:rInset
#
# imageId is the identificator of the desired image
#
# imageName is the name of the image, with an eventual subdirectory, which is relative to the package name
# of the image loader (all the images are located in subdectorie whose root is the package name of the imaghe loader)
# For example, if the image Image.gif is located in a subdirectory called subdir, this field has the subdir/Image.gif
# value.
#
# heightFactor is a factor to apply to the height of the original height of the image for rendering. The default height
# for an image is the height of the glyph of the current font. In some cases, for example specific symbols of operators,
# we want the symbol to be greater than the text elements of the expression (e.g. the sigma symbol for the sum is
# greater than the elements constituting it). This field determine how bigger is the symbol.
# If we want the image to be as high as the current font is, this field has 1.0 as value.
#
# baseline represents a virtual line to align the image with all the elements of the expression. It is expressed as a
# percentage of the height of the image, so its value have to be between 0.0 and 1.0.
# In some cases, we don't have to specify a particular baseline value (because as the height of the image is set by
# default to the height of the font, the baseline is the one of the font or because for it is calculating before
# rendering). Fore these cases, a null value should be set.
#
# tInset, bInset, lInset, rInset represent respectively a top, bottom, left and right insets to take
# into account around the image. This allows to have some space around the image inside the display
# which renders it.
 
# The different icons
 
#jm.evers
#imageId = imageName:heightFactor:baseline:tInset:bInset:lInset:rInset
langle = symbols/langle.gif:1:0.82:0:0:0.1:0.1
rangle = symbols/rangle.gif:1:0.82:0:0:0.1:0.1
lbracket = symbols/lbracket.gif:1:0.82:0:0:0.1:0.1
rbracket = symbols/rbracket.gif:1:0.82:0:0:0.1:0.1
or = symbols/or.gif:0.6:1:0:0:0.1:0.1
and = symbols/and.gif:0.6:1:0:0:0.1:0.1
cup = symbols/cup.gif:0.6:0.8:0:0:0.1:0.1
div = symbols/div.gif:0.6:0.8:0:0:0.1:0.1
mapsto = symbols/mapsto.gif:0.6:0.8:0:0:0.1:0.1
rightarrow = symbols/longrightarrow.gif:0.5:0.8:0:0:0.1:0.1
 
 
ADDITION_Ico = icons/ButtonAddition.gif:1:null:0.02:0.02:0.02:0.02
MULTIPLICATION_Ico = icons/ButtonMultiplication.gif:1:null:0.02:0.02:0.02:0.02
UNARYPLUS_Ico = icons/ButtonPlusUnaire.gif:1:null:0.02:0.02:0.02:0.02
UNARYMINUS_Ico = icons/ButtonMoinsUnaire.gif:1:null:0.02:0.02:0.02:0.02
DIVISION_Ico = icons/ButtonDivision.gif:1:null:0.02:0.02:0.02:0.02
POWER_Ico = icons/ButtonSuperscript.gif:1:null:0.02:0.02:0.02:0.02
OPEN_PAREN = icons/ButtonParenthese.gif:1:null:0.02:0.02:0.02:0.02
root_Ico = icons/ButtonRacineCaree.gif:1:null:0.02:0.02:0.02:0.02
sum_Ico = icons/ButtonSigma.gif:1:null:0.02:0.02:0.02:0.02
 
# For those who don't have a defined icon yet
undef = icons/ButtonInterrogation.gif:1:null:0.02:0.02:0.02:0.02
 
# The images for relational operators
EQUAL = relation/eq.gif:1:0.82:0:0:0.3:0.3
UNEQUAL = relation/neq.gif:1:0.82:0:0:0.3:0.3
LESS = relation/lt.gif:1:0.82:0:0:0.3:0.3
LESSEQUAL = relation/leq2.gif:1:0.82:0:0:0.3:0.3
GREATER = relation/gt.gif:1:0.82:0:0:0.3:0.3
GREATEREQUAL = relation/geq2.gif:1:0.82:0:0:0.3:0.3
 
# The different symbols
infty = symbols/Infinity.gif:1:0.82:0:0:0.1:0.1
 
# For the creation of the open parenthesis
LeftTopPar = symbols/LeftTopPar.gif:1:null
LeftMiddlePar = symbols/LeftMiddlePar.gif:1:null
LeftBottomPar = symbols/LeftBottomPar.gif:1:null
 
# For the creation of the close parenthesis
RightTopPar = symbols/RightTopPar.gif:1:null
RightMiddlePar = symbols/RightMiddlePar.gif:1:null
RightBottomPar = symbols/RightBottomPar.gif:1:null
 
# For the creation of the open curly brace
LeftTopCurl = symbols/LeftTopCurl.gif:1:null
LeftMiddleCurl = symbols/LeftMiddleCurl.gif:1:null
LeftBottomCurl = symbols/LeftBottomCurl.gif:1:null
LeftBarCurl = symbols/LeftBarCurl.gif:1:null
 
# For the creation of the close curly brace
RightTopCurl = symbols/RightTopCurl.gif:1:null
RightMiddleCurl = symbols/RightMiddleCurl.gif:1:null
RightBottomCurl = symbols/RightBottomCurl.gif:1:null
RightBarCurl =symbols/RightBarCurl.gif:1:null
 
Array = symbols/Array.gif:1:0.5
Integrale = symbols/Integrale.gif:1.5:0.68
Sigma = symbols/Sigma.gif:1.5:0.68
Product = symbols/Product.gif:1.5:0.68
pi = symbols/Pi.gif:1:0.72:0:0:0.1:0.1
RightArrow = symbols/RightArrow.gif:1.5:0.68:0:0:0.3:0.3
LeftArrow = symbols/LeftArrow.gif:1.5:0.68:0:0:0.3:0.3
 
# The sets operator and sets symbols.
C = sets/MathC.gif:1:0.82:0:0:0.1:0.1
N = sets/MathN.gif:1:0.82:0:0:0.1:0.1
Q = sets/MathQ.gif:1:0.82:0:0:0.1:0.1
R = sets/MathR.gif:1:0.82:0:0:0.1:0.1
Z = sets/MathZ.gif:1:0.82:0:0:0.1:0.1
in = sets/In.gif:1:0.82:0:0:0.3:0.3
notin = sets/NotIn.gif:1:0.82:0:0:0.3:0.3
union = sets/Union.gif:1:0.82:0:0:0.3:0.3
intersect = sets/Intersect.gif:1:0.82:0:0:0.3:0.3
o = symbols/Rond.gif:1:0.82
lim = symbols/RightArrow.gif:1.5:0.68:0:0:0.3:0.3
 
# The greek alphabet (some letters at least)
delta = alphabet/d_grec.gif:1:0.72:0:0:0.1:0.1
gamma = alphabet/g_grec.gif:1:0.72:0:0:0.1:0.1
alfa = alphabet/alpha.gif:1:0.72:0:0:0.1:0.1
alpha = alphabet/alpha.gif:1:0.72:0:0:0.1:0.1
beta = alphabet/beta.gif:1:0.72:0:0:0.1:0.1
chi = alphabet/chi.gif:1:0.72:0:0:0.1:0.1
epsilon = alphabet/epsilon.gif:1:0.72:0:0:0.1:0.1
eta = alphabet/eta.gif:1:0.72:0:0:0.1:0.1
iota = alphabet/iota.gif:1:0.72:0:0:0.1:0.1
kappa = alphabet/kappa.gif:1:0.72:0:0:0.1:0.1
mu = alphabet/mu.gif:1:0.72:0:0:0.1:0.1
nabla = alphabet/nabla.gif:1:0.72:0:0:0.1:0.1
nu = alphabet/nu.gif:1:0.72:0:0:0.1:0.1
omega = alphabet/omega.gif:1:0.72:0:0:0.1:0.1
phi = alphabet/phi.gif:1:0.72:0:0:0.1:0.1
psi = alphabet/psi.gif:1:0.72:0:0:0.1:0.1
rho = alphabet/rho.gif:1:0.72:0:0:0.1:0.1
tau = alphabet/tau.gif:1:0.72:0:0:0.1:0.1
theta = alphabet/theta.gif:1:0.72:0:0:0.1:0.1
upsilon = alphabet/upsilon.gif:1:0.72:0:0:0.1:0.1
zeta = alphabet/zeta.gif:1:0.72:0:0:0.1:0.1
sigma = alphabet/sigma.gif:1:0.72:0:0:0.1:0.1
xi = alphabet/xi.gif:1:0.72:0:0:0.1:0.1
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/ImagesResourcesManager.java
0,0 → 1,129
/*
$Id: ImagesResourcesManager.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim.images;
 
import fr.ove.utils.CachingResourcesManager;
 
/**
* The resources manager for the images.<BR>
* The syntax for the resources is : imgId = imgName:heightFactor:baseline
* (Look at the resources file to get full signification of the different fields)
*
* @author © 2000 DIRAT Laurent
* @version 2.0 04/01/2000
*/
public class ImagesResourcesManager extends CachingResourcesManager {
/**
* The Constructor.
* @param resourcesName the name of the resources file.
*/
public ImagesResourcesManager(String resourcesName) {
super(resourcesName);
}
/**
* Returns the name of the image corresponding to the property
* @param property the specified property
*/
public String getImageName(String property) {
return accessResource(property, 0);
}
/**
* Returns the height factor to apply to the orignal size of the image corresponding to the property
* @param property the specified property
*/
public String getHeightFactor(String property) {
String heightFactor = accessResource(property, 1);
if ((heightFactor != null) && heightFactor.equals("null"))
heightFactor = null;
return heightFactor;
}
/**
* Returns the baseline of the image corresponding to the property
* @param property the specified property
*/
public String getBaseline(String property) {
String baseline = accessResource(property, 2);
if ((baseline != null) && baseline.equals("null"))
baseline = null;
return baseline;
}
/**
* Returns the top inset of the image corresponding to the property
* @param property the specified property
*/
public String getTopInset(String property) {
String inset = accessResource(property, 3);
if ((inset != null) && inset.equals("null"))
inset = null;
return inset;
}
/**
* Returns the bottom inset of the image corresponding to the property
* @param property the specified property
*/
public String getBottomInset(String property) {
String inset = accessResource(property, 4);
if ((inset != null) && inset.equals("null"))
inset = null;
return inset;
}
/**
* Returns the left inset of the image corresponding to the property
* @param property the specified property
*/
public String getLeftInset(String property) {
String inset = accessResource(property, 5);
if ((inset != null) && inset.equals("null"))
inset = null;
return inset;
}
/**
* Returns the right inset of the image corresponding to the property
* @param property the specified property
*/
public String getRightInset(String property) {
String inset = accessResource(property, 6);
if ((inset != null) && inset.equals("null"))
inset = null;
return inset;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/ImagesResources_en.properties
0,0 → 1,158
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
# Resources file for images in the expression :
# The syntax is the following :
#
# imageId = imageName:heightFactor:baseline:tInset:bInset:lInset:rInset
#
# imageId is the identificator of the desired image
#
# imageName is the name of the image, with an eventual subdirectory, which is relative to the package name
# of the image loader (all the images are located in subdectorie whose root is the package name of the imaghe loader)
# For example, if the image Image.gif is located in a subdirectory called subdir, this field has the subdir/Image.gif
# value.
#
# heightFactor is a factor to apply to the height of the original height of the image for rendering. The default height
# for an image is the height of the glyph of the current font. In some cases, for example specific symbols of operators,
# we want the symbol to be greater than the text elements of the expression (e.g. the sigma symbol for the sum is
# greater than the elements constituting it). This field determine how bigger is the symbol.
# If we want the image to be as high as the current font is, this field has 1.0 as value.
#
# baseline represents a virtual line to align the image with all the elements of the expression. It is expressed as a
# percentage of the height of the image, so its value have to be between 0.0 and 1.0.
# In some cases, we don't have to specify a particular baseline value (because as the height of the image is set by
# default to the height of the font, the baseline is the one of the font or because for it is calculating before
# rendering). Fore these cases, a null value should be set.
#
# tInset, bInset, lInset, rInset represent respectively a top, bottom, left and right insets to take
# into account around the image. This allows to have some space around the image inside the display
# which renders it.
 
# The different icons
 
#jm.evers
#imageId = imageName:heightFactor:baseline:tInset:bInset:lInset:rInset
langle = symbols/langle.gif:1:0.82:0:0:0.1:0.1
rangle = symbols/rangle.gif:1:0.82:0:0:0.1:0.1
lbracket = symbols/lbracket.gif:1:0.82:0:0:0.1:0.1
rbracket = symbols/rbracket.gif:1:0.82:0:0:0.1:0.1
or = symbols/or.gif:0.6:1:0:0:0.1:0.1
and = symbols/and.gif:0.6:1:0:0:0.1:0.1
cup = symbols/cup.gif:0.6:0.8:0:0:0.1:0.1
div = symbols/div.gif:0.6:0.8:0:0:0.1:0.1
mapsto = symbols/mapsto.gif:0.6:0.8:0:0:0.1:0.1
rightarrow = symbols/longrightarrow.gif:0.5:0.8:0:0:0.1:0.1
 
 
ADDITION_Ico = icons/ButtonAddition.gif:1:null:0.02:0.02:0.02:0.02
MULTIPLICATION_Ico = icons/ButtonMultiplication.gif:1:null:0.02:0.02:0.02:0.02
UNARYPLUS_Ico = icons/ButtonPlusUnaire.gif:1:null:0.02:0.02:0.02:0.02
UNARYMINUS_Ico = icons/ButtonMoinsUnaire.gif:1:null:0.02:0.02:0.02:0.02
DIVISION_Ico = icons/ButtonDivision.gif:1:null:0.02:0.02:0.02:0.02
POWER_Ico = icons/ButtonSuperscript.gif:1:null:0.02:0.02:0.02:0.02
OPEN_PAREN = icons/ButtonParenthese.gif:1:null:0.02:0.02:0.02:0.02
root_Ico = icons/ButtonRacineCaree.gif:1:null:0.02:0.02:0.02:0.02
sum_Ico = icons/ButtonSigma.gif:1:null:0.02:0.02:0.02:0.02
 
# For those who don't have a defined icon yet
undef = icons/ButtonInterrogation.gif:1:null:0.02:0.02:0.02:0.02
 
# The images for relational operators
EQUAL = relation/eq.gif:1:0.82:0:0:0.3:0.3
UNEQUAL = relation/neq.gif:1:0.82:0:0:0.3:0.3
LESS = relation/lt.gif:1:0.82:0:0:0.3:0.3
LESSEQUAL = relation/leq2.gif:1:0.82:0:0:0.3:0.3
GREATER = relation/gt.gif:1:0.82:0:0:0.3:0.3
GREATEREQUAL = relation/geq2.gif:1:0.82:0:0:0.3:0.3
 
# The different symbols
infty = symbols/Infinity.gif:1:0.82:0:0:0.1:0.1
 
# For the creation of the open parenthesis
LeftTopPar = symbols/LeftTopPar.gif:1:null
LeftMiddlePar = symbols/LeftMiddlePar.gif:1:null
LeftBottomPar = symbols/LeftBottomPar.gif:1:null
 
# For the creation of the close parenthesis
RightTopPar = symbols/RightTopPar.gif:1:null
RightMiddlePar = symbols/RightMiddlePar.gif:1:null
RightBottomPar = symbols/RightBottomPar.gif:1:null
 
# For the creation of the open curly brace
LeftTopCurl = symbols/LeftTopCurl.gif:1:null
LeftMiddleCurl = symbols/LeftMiddleCurl.gif:1:null
LeftBottomCurl = symbols/LeftBottomCurl.gif:1:null
LeftBarCurl = symbols/LeftBarCurl.gif:1:null
 
# For the creation of the close curly brace
RightTopCurl = symbols/RightTopCurl.gif:1:null
RightMiddleCurl = symbols/RightMiddleCurl.gif:1:null
RightBottomCurl = symbols/RightBottomCurl.gif:1:null
RightBarCurl =symbols/RightBarCurl.gif:1:null
 
Array = symbols/Array.gif:1:0.5
Integrale = symbols/Integrale.gif:1.5:0.68
Sigma = symbols/Sigma.gif:1.5:0.68
Product = symbols/Product.gif:1.5:0.68
pi = symbols/Pi.gif:1:0.72:0:0:0.1:0.1
RightArrow = symbols/RightArrow.gif:1.5:0.68:0:0:0.3:0.3
LeftArrow = symbols/LeftArrow.gif:1.5:0.68:0:0:0.3:0.3
 
# The sets operator and sets symbols.
C = sets/MathC.gif:1:0.82:0:0:0.1:0.1
N = sets/MathN.gif:1:0.82:0:0:0.1:0.1
Q = sets/MathQ.gif:1:0.82:0:0:0.1:0.1
R = sets/MathR.gif:1:0.82:0:0:0.1:0.1
Z = sets/MathZ.gif:1:0.82:0:0:0.1:0.1
in = sets/In.gif:1:0.82:0:0:0.3:0.3
notin = sets/NotIn.gif:1:0.82:0:0:0.3:0.3
union = sets/Union.gif:1:0.82:0:0:0.3:0.3
intersect = sets/Intersect.gif:1:0.82:0:0:0.3:0.3
o = symbols/Rond.gif:1:0.82
lim = symbols/RightArrow.gif:1.5:0.68:0:0:0.3:0.3
 
# The greek alphabet (some letters at least)
delta = alphabet/d_grec.gif:1:0.72:0:0:0.1:0.1
gamma = alphabet/g_grec.gif:1:0.72:0:0:0.1:0.1
alfa = alphabet/alpha.gif:1:0.72:0:0:0.1:0.1
alpha = alphabet/alpha.gif:1:0.72:0:0:0.1:0.1
beta = alphabet/beta.gif:1:0.72:0:0:0.1:0.1
chi = alphabet/chi.gif:1:0.72:0:0:0.1:0.1
epsilon = alphabet/epsilon.gif:1:0.72:0:0:0.1:0.1
eta = alphabet/eta.gif:1:0.72:0:0:0.1:0.1
iota = alphabet/iota.gif:1:0.72:0:0:0.1:0.1
kappa = alphabet/kappa.gif:1:0.72:0:0:0.1:0.1
mu = alphabet/mu.gif:1:0.72:0:0:0.1:0.1
nabla = alphabet/nabla.gif:1:0.72:0:0:0.1:0.1
nu = alphabet/nu.gif:1:0.72:0:0:0.1:0.1
omega = alphabet/omega.gif:1:0.72:0:0:0.1:0.1
phi = alphabet/phi.gif:1:0.72:0:0:0.1:0.1
psi = alphabet/psi.gif:1:0.72:0:0:0.1:0.1
rho = alphabet/rho.gif:1:0.72:0:0:0.1:0.1
tau = alphabet/tau.gif:1:0.72:0:0:0.1:0.1
theta = alphabet/theta.gif:1:0.72:0:0:0.1:0.1
upsilon = alphabet/upsilon.gif:1:0.72:0:0:0.1:0.1
zeta = alphabet/zeta.gif:1:0.72:0:0:0.1:0.1
sigma = alphabet/sigma.gif:1:0.72:0:0:0.1:0.1
xi = alphabet/xi.gif:1:0.72:0:0:0.1:0.1
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/gtn.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/gt.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/geq.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/geq2.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/lt.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/leq.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/leq2.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/neq.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/relation/eq.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/MathQ.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/MathR.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/MathC.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/Intersect.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/Include.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/MathZ.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/In.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/MathN.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/NotIn.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/sets/Union.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/ImagesResources.java
0,0 → 1,3
package fr.ove.openmath.jome.ctrlview.bidim.images;
public class ImagesResources{
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/theta.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/pi.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/epsilon.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/eta.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/beta.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/nabla.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/xi.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/phi.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/lambda.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/mu.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/gamma.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/nu.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/d_grec.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/alpha.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/g_grec.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/omega.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/rho.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/delta.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/tau.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/upsilon.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/psi.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/kappa.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/iota.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/sigma.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/zeta.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/chi.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/alphabet/mugif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/images/ImagesResources_en.java
0,0 → 1,3
package fr.ove.openmath.jome.ctrlview.bidim.images;
public class ImagesResources_en{
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringPostfixedUnaryOperatorLayout.java
0,0 → 1,52
/*
$Id: StringPostfixedUnaryOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* This layout manager lays prefixed unary operators.<BR>
* The symbol of the operator can be rendered as a simple string (e.g. ! for factorial)
*
* @author © 1999 DIRAT Laurent
* @version 2.0 16/12/1999
*/
public class StringPostfixedUnaryOperatorLayout extends PostfixedUnaryOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), fts.getTheOperator(), true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SquaredBracketSymbol.java
0,0 → 1,113
/*
$Id: SquaredBracketSymbol.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayableImpl;
import fr.ove.utils.FontInfo;
 
/**
* The bracket symbol for rendering interval. (i.e. symbol [ or ])
*
* @author © 1999 DIRAT Laurent
* @version 2.0 06/09/1999
*/
public class SquaredBracketSymbol extends DisplayableImpl {
/**
* The character (i.e. '[' or ']') represented by the instance
* By default, the instance represents '['.
*/
private char character;
/**
* The thickness of the line to draw the symbol.
*/
private int thickness;
/**
*
*/
private Component component;
/**
* The constructor.
* @param character the associated character (i.e. '[' or ']') to the instance
**/
public SquaredBracketSymbol(char character, Component component) {
this.character = character;
this.component = component;
}
/**
* The constructor.
* @param character the string representation of the associated character (i.e. '[' or ']') to the instance
**/
public SquaredBracketSymbol(String character, Component component) {
this.character = character.charAt(0);
this.component = component;
}
/**
* Sets the thickness of the line to draw the symbol
* @param thickness the thickness to draw the symbol
*/
public void setThickness(int thickness) {
this.thickness = thickness;
}
/**
* Returns the preferred size of the display.
*/
public Dimension getPreferredSize() {
return new Dimension(FontInfo.getStringWidth(component, getGraphicContext().getFont(), "[") + 6, getHeight());
}
public Dimension getSize() {
return getPreferredSize();
}
/**
* The paint method of the object to display.
* @param g the drawing area of the symbol.
*/
public void paint(Graphics g) {
Dimension size = getSize();
// La barre horizontale du haut
g.fillRect(0+3, 0, size.width-6, thickness);
// La barre horizontale du bas
g.fillRect(0+3, size.height - thickness, size.width-6, thickness);
// La barre verticale
if (character == '[')
g.fillRect(0+3, 0, thickness, size.height);
else
g.fillRect(size.width - thickness - 3, 0, thickness, size.height);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/Sizable.java
0,0 → 1,84
/*
$Id: Sizable.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.Dimension;
 
/**
* Interface that must implement all objects that want to be sized.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/06/1999
*/
public interface Sizable {
/**
* Returns the width of the instance.
*/
public int getWidth();
/**
* Sets the width of the instance.
* @param width the width of the instance
*/
public void setWidth(int width);
/**
* Returns the height of the instance.
*/
public int getHeight();
/**
* Sets the height of the instance.
* @param height the height of the instance
*/
public void setHeight(int height);
/**
* Returns the size of the instance.
*/
public Dimension getSize();
/**
* Sets the size of the instance.
* @param width the width of the instance.
* @param height the height of the instance
*/
public void setSize(int width, int height);
/**
* Sets the size of the instance.
* @param size the size of the instance.
*/
public void setSize(Dimension size);
/**
* Returns the preferred size of the instance.
*/
public Dimension getPreferredSize();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/Displayable.java
0,0 → 1,116
/*
$Id: Displayable.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.GraphicContext;
import fr.ove.openmath.jome.ctrlview.bidim.Localisable;
import fr.ove.openmath.jome.ctrlview.bidim.Sizable;
 
/**
* An implementation of the <CODE>Displayable</CODE> interface.<BR>
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/06/1999
*/
public interface Displayable extends Localisable, Sizable {
/**
* Sets the ascent.
* @param ascent the new ascent value.
*/
public void setAscent(int ascent);
/**
* Returns the ascent.
* @return the ascent.
*/
public int getAscent();
/**
* Sets the descent.
* @param descent the new descent value.
*/
public void setDescent(int descent);
/**
* Returns the descent.
* @return the descent.
*/
public int getDescent();
/**
* Sets the horizontal shift.
* @param shift the new horizontal shift value.
*/
public void setShiftX(int shiftX);
/**
* Returns the horizontal shift.
* @return the horizontal shift.
*/
public int getShiftX();
/**
* Sets the vertical shift.
* @param shiftY the new vertical shift value.
*/
public void setShiftY(int shiftY);
/**
* Returns the vertical shift.
* @return the vertical shift.
*/
public int getShiftY();
/**
* Sets all the attributes.
* @param ascent the new ascent value.
* @param descent the new descent value.
* @param shiftX the new horizontal shift value.
* @param shiftY the new vertical shift value.
*/
public void setAttributes(int ascent, int descent, int shiftX, int shiftY);
/**
* Sets the graphic context of the instance.
* @param graphicContext the graphic context.
*/
public void setGraphicContext(GraphicContext graphicContext);
/**
* Returns the graphic context of the instance.
*/
public GraphicContext getGraphicContext();
/**
* The paint method of the object to display.
* @param g the drawing area of the symbol.
*/
public void paint(Graphics g);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringBetweenOperatorLayout.java
0,0 → 1,55
/*
$Id: StringBetweenOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of an operator whose symbol is located between its 2 operands.<BR>
* Rendering is done vertically, the first operand on top, the symbol in the middle and the second operand
* under the 2 previous.<BR>
* The symbol is rendered with a simple string.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class StringBetweenOperatorLayout extends BetweenOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), fts.getTheOperator(), true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ImageInfixOperatorLayout.java
0,0 → 1,62
/*
$Id: ImageInfixOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager for an infix operator which symbol can be rendered as an image.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public abstract class ImageInfixOperatorLayout extends InfixOperatorLayout {
/**
* The symbol we have to insert between each component if necessary.
*/
private ImageSymbol symbolOperator = null;
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
if (symbolOperator == null) {
Operator fts = (Operator) displayToLay.getListener();
//symbolOperator = new ImageSymbol(fts.getTheOperator(), displayToLay);
symbolOperator = new ImageSymbol(fts.getResourceIdentifier(), displayToLay);
}
// On créé un display pour l'opérateur.
SymbolDisplay operatorDisplay = new SymbolDisplay(displayToLay.getGraphicContext(), symbolOperator);
operatorDisplay.setIsSymbolOperatorDisplay(true);
return operatorDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ImageUnderOperatorLayout.java
0,0 → 1,64
/*
$Id: ImageUnderOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of the operator whose symbol is located under its operand.<BR>
* The symbol is represented as a simple string
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class ImageUnderOperatorLayout extends UnderOperatorLayout {
/**
* The symbol we have to insert between each component if necessary.
*/
private ImageSymbol symbolOperator = null;
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
if (symbolOperator == null) {
Operator fts = (Operator) displayToLay.getListener();
//symbolOperator = new ImageSymbol(fts.getTheOperator(), displayToLay);
symbolOperator = new ImageSymbol(fts.getResourceIdentifier(), displayToLay);
}
// On créé un display pour l'opérateur.
SymbolDisplay operatorDisplay = new SymbolDisplay(displayToLay.getGraphicContext(), symbolOperator);
operatorDisplay.setIsSymbolOperatorDisplay(true);
return operatorDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BinaryInfixOperatorLayout.java
0,0 → 1,132
/*
$Id: BinaryInfixOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager for an binary infix operator.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public abstract class BinaryInfixOperatorLayout extends InfixOperatorLayout {
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// La validité de la sélection est triviale.
// Si les opérandes sont sélectionnés ou ont un élément sélectionné, ou si l'opérateur
// est sélectionnée, alors on sélectionne tout.
Display left = (Display) displayToLay.getComponent(0);
Display ope = (Display) displayToLay.getComponent(1);
Display right = (Display) displayToLay.getComponent(2);
if ((left.gotSelectedElements() && right.gotSelectedElements()) ||
(ope.isSelected())) {
// Sélectionne le display.
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute l'opération
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
 
// On a vérifié la validité de la sélection de la puissance. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (displayToLay.getParent() instanceof Display) {
display = (Display) displayToLay.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
SelectionEvent selEvt = new SelectionEvent(father);
// Si l'opération est sélectionnée, alors il faut la déselectionner.
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
Display left = (Display) father.getComponent(0);
Display ope = (Display) father.getComponent(1);
Display right = (Display) father.getComponent(2);
if (display == left) {
ope.setNotSelected();
selEvt.setAction(SelectionEvent.ADD, right);
father.fireSelectionEvent(selEvt);
}
else if (display == right) {
ope.setNotSelected();
selEvt.setAction(SelectionEvent.ADD, left);
father.fireSelectionEvent(selEvt);
}
else {
left.deselect();
ope.setNotSelected();
right.deselect();
}
 
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/resources_en.java
0,0 → 1,4
package fr.ove.openmath.jome.ctrlview.bidim;
 
public abstract class resources_en{
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/PostfixedUnaryOperatorLayout.java
0,0 → 1,63
/*
$Id: PostfixedUnaryOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
 
/**
* This layout manager lays postfixed unary operators.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public abstract class PostfixedUnaryOperatorLayout extends UnaryOperatorLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Display dOperator = (Display) displayToLay.getComponent(0);
Display dOperand = (Display) displayToLay.getComponent(1);
// Initialisation des shift* pour ne pas introduire de faux paramètres.
dOperator.setAttributes(dOperator.getAscent(), dOperator.getDescent(), 0, 0);
dOperand.setAttributes(dOperand.getAscent(), dOperand.getDescent(), 0, 0);
// Calcul des attributs de manière classique...
Dimension dim = super.computeAttributes();
// ...sauf que l'opérateur, il faut le faire passer derrière
dOperator.setShiftX(dim.width - dOperator.getWidth());
dOperand.setShiftX(-dOperator.getShiftX() - dOperator.getWidth());
return dim;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BracketSymbol.java
0,0 → 1,151
/*
$Id: BracketSymbol.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.awt.image.ImageObserver;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.images.ImageLoader;
 
 
/**
* The bracket.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 19/07/1999
*/
public class BracketSymbol extends DisplayableImpl {
/**
* The initial images which are parts of the representation of the bracket.<BR>
* The bracket is made of 3 parts : top, middle and bottom.<BR>
* The top and bottom are unique during the rendering, and according to the height of the
* bracketted display, mutiple instance of the middle are displayed to give the right size
* to the brackets.
*/
private Image topInit;
private Image middleInit;
private Image bottomInit;
/**
* The scale images of the initials ones.
*/
private Image top;
private Image middle;
private Image bottom;
/**
* The height of the top and the bottom of the symbol.
*/
private int heightExtremities;
/**
* Object to be notified as more of the image is converted.
*/
ImageObserver observer;
/**
* The constructor.
* @param isLeftBracket <CODE>true<CODE> if the instance represents a left bracket. <CODE>false</CODE>
* otherwise.
* @param heightExtremities the height of the extremities of the bracket.
* @param observer the object to be notified as more of the image is converted.
*/
public BracketSymbol(boolean isLeftBracket, int heightExtremities, ImageObserver observer) {
if (isLeftBracket) {
topInit = ImageLoader.getImage("LeftTopPar");
middleInit = ImageLoader.getImage("LeftMiddlePar");
bottomInit = ImageLoader.getImage("LeftBottomPar");
}
else {
topInit = ImageLoader.getImage("RightTopPar");
middleInit = ImageLoader.getImage("RightMiddlePar");
bottomInit = ImageLoader.getImage("RightBottomPar");
}
 
this.heightExtremities = heightExtremities;
this.observer = observer;
}
/**
* The paint method of the object to display.
* @param g the drawing area of the symbol.
*/
public void paint(Graphics g) {
int height = getHeight();
// On dessine la partie supérieure de la parenthèse
g.drawImage(top, 0, 0, observer);
// On dessine la partie centrale de la parenthèse
for (int i = heightExtremities; i < height - heightExtremities; i += heightExtremities)
g.drawImage(middle, 0, i, observer);
// On dessine la partie inférieure de la parenthèse
g.drawImage(bottom, 0, height - heightExtremities, observer);
}
/**
* Returns the preferred size of the display.
*/
public Dimension getPreferredSize() {
MediaTracker tracker = new MediaTracker((Component) observer);
// Le -1 signifie que la largeur sera proportionnelle à la hauteur.
top = topInit.getScaledInstance(-1, heightExtremities, Image.SCALE_SMOOTH);
tracker.addImage(top, 0);
bottom = bottomInit.getScaledInstance(-1, heightExtremities, Image.SCALE_SMOOTH);
tracker.addImage(bottom, 0);
middle = middleInit.getScaledInstance(-1, heightExtremities, Image.SCALE_SMOOTH);
tracker.addImage(middle, 0);
// On attend que toutes les images soient chargées.
try { tracker.waitForAll(); }
catch (InterruptedException e) {
System.out.print(e.toString());
}
// Une fois que toutes les images ont été chargées, on les enlèves du media tracker.
tracker.removeImage(top);
tracker.removeImage(middle);
tracker.removeImage(bottom);
 
return new Dimension(top.getWidth(observer), getHeight());
}
/**
* Sets the graphic context of the instance.
* @param graphicContext the graphic context.
*/
public void setGraphicContext(GraphicContext graphicContext) {
super.setGraphicContext(graphicContext);
// Surcharge de cette méthode pour que l'on puisse récupérer en fonction du contexte graphique
// du symbole, la hauteur des extrémité de la parenthèse.
FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(graphicContext.getFont());
heightExtremities = fm.getHeight() / 2;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/DisplayLayout.java
0,0 → 1,283
/*
$Id: DisplayLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.io.Serializable;
import java.lang.IllegalArgumentException;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
 
/**
* A layout manager.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public abstract class DisplayLayout implements LayoutManager2, Serializable , Cloneable {
/**
* The display laid out by the instance.
*/
protected Display displayToLay = null;
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
this.displayToLay = displayToLay;
}
/**
* Returns <CODE>true</CODE> if during the selection, the display which is located
* to the left of the display that the instance lays, must be selected too.
* <CODE>false</CODE> otherwise.
*/
public boolean selectLeftDisplay() {
return false;
}
/**
* Returns <CODE>true</CODE> if during the selection, the display which is located
* to the right of the display that the instance lays, must be selected too.
* <CODE>false</CODE> otherwise.
*/
public boolean selectRightDisplay() {
return false;
}
/**
* Selects the display (and its children if any)
* @param the display to select.
*/
public void selectDisplay() {
displayToLay.select();
SelectionEvent selEvt = new SelectionEvent(displayToLay);
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
Display display = displayToLay;
if (displayToLay.getParent() instanceof Display) {
display = (Display) displayToLay.getParent();
((DisplayLayout) display.getLayout()).validateSelection();
}
}
 
 
/**
* Deselects the display.
* @param the display to deselect.
*/
public void deselectDisplay() {
displayToLay.deselect();
 
SelectionEvent selEvt = new SelectionEvent(displayToLay);
selEvt.setAction(SelectionEvent.REMOVE, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
if (displayToLay.getParent() instanceof Display) {
Display display = (Display) displayToLay.getParent();
((DisplayLayout) display.getLayout()).validateDeselection(displayToLay);
}
}
/**
* Updates the level of the display laid out.
* @param display the display laid out
* @param level the level put to the display.
*/
public void updateLevel(int level) {
Display tmp;
if (displayToLay.getUpdateLevel()) {
// On met le niveau adéquat
displayToLay.setLevel(level);
// On scale le display en fonction du niveau
displayToLay.scaleDisplay();
// On n'a plus besoin de mettre à jour le niveau de l'instance
displayToLay.setUpdateLevel(false);
// Le comportement par défaut est que les displays enfant de l'instance courante
// ont le même niveau que leur père.
int count = displayToLay.getComponentCount();
for (int i = 0; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
((DisplayLayout) tmp.getLayout()).updateLevel(level);
}
}
}
// ############################################
// ### Les différentes méthodes abstraites ###
// ############################################
/**
* Checks the validity of the selection.
*/
public abstract void validateSelection();
/**
* Checks the validity of the deselection.<BR>
* @param display the display which just has been deselected.
*/
public abstract void validateDeselection(Display display);
/**
* The display needs to be rebuilt. We do this.
*/
public abstract void rebuildDisplay();
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @param display the display laid by the instance
* @return the size of the display.
*/
public abstract Dimension computeAttributes();
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
// ***************************************************
// *** Implémentation de l'interface LayoutManager ***
/**
* Adds the specified component with the specified name to
* the layout.
* @param name the component name
* @param comp the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
}
 
/**
* Removes the specified component from the layout.
* @param comp the component ot be removed
*/
public void removeLayoutComponent(Component comp) {
}
 
/**
* Calculates the minimum size dimensions for the specified
* panel given the components in the specified parent container.
* @param parent the component to be laid out
* @see #preferredLayoutSize
*/
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
/**
* Calculates the preferred size dimensions for the specified
* panel given the components in the specified parent container.
* @param parent the component to be laid out
*
* @see #minimumLayoutSize
*/
public Dimension preferredLayoutSize(Container parent) {
if (((Display) parent).getComputeAttributes())
return computeAttributes();
else
return parent.getSize();
}
// *** Fin de l'interface LayoutManager ***
// ****************************************
// ****************************************************
// *** Implémentation de l'interface LayoutManager2 ***
 
/**
* Adds the specified component to the layout, using the specified
* constraint object.
* @param comp the component to be added
* @param constraints where/how the component is added to the layout.
*/
public void addLayoutComponent(Component comp, Object constraints) {
if (!(constraints instanceof Display))
throw new IllegalArgumentException("The component to add must be a Display instance !!!");
}
 
/**
* Returns the maximum size of this component.
* @see java.awt.Component#getMinimumSize()
* @see java.awt.Component#getPreferredSize()
* @see LayoutManager
*/
public Dimension maximumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
 
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentX(Container target) {
return 0.0f;
}
 
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentY(Container target) {
return 0.0f;
}
 
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
*/
public void invalidateLayout(Container target) {
}
// *** Fin de l'interface LayoutManager ***
// ****************************************
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SymbolLayout.java
0,0 → 1,125
/*
$Id: SymbolLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.StringDisplay;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays symbols.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 09/07/1999
*/
public class SymbolLayout extends DisplayLayout {
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
SelectionEvent selEvt = new SelectionEvent(father);
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
}
}
 
/**
* Computes the size of the display and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Displayable symbol = ((SymbolDisplay) displayToLay).getSymbol();
symbol.setGraphicContext(displayToLay.getGraphicContext());
Dimension dim = symbol.getPreferredSize();
 
displayToLay.setSize(dim);
displayToLay.setAscent(symbol.getAscent());
displayToLay.setDescent(symbol.getDescent());
displayToLay.setComputeAttributes(false);
return dim;
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// En fait, celui là ne sera jamais reconstruit.
}
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
 
// ***************************************************
// *** Implémentation de l'interface LayoutManager ***
 
/*
* Lays out the container in the specified panel.
* @param parent the component which needs to be laid out.
*/
public void layoutContainer(Container parent) {
}
 
// *** Fin de l'interface LayoutManager ***
// ****************************************
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/Bar.java
0,0 → 1,67
/*
$Id: Bar.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayableImpl;
 
/**
* The fraction bar to display with a fraction.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 08/07/1999
*/
public class Bar extends DisplayableImpl {
// La barre de fraction correspond en fait à la taille de DisplayableImpl.
// La longueur correpond à la largeur.
// L'épaisseur correspond à la hauteur
/**
* Sets the height of the instance.
* @param height the height of the instance
*/
public void setHeight(int height) {
super.setHeight(height);
// Mais là, en plus, on calcule l'ascent et le descent
// car en fait, c'est la hauteur (l'épaisseur) de la barre de fraction
// Qui détermine leur valeur
//setAscent(height / 2);
setAscent(((height % 2) == 0) ? (height / 2) - 1 : height / 2);
setDescent(height - getAscent());
}
/**
* The paint method of the object to display.
* @param g the drawing area of the symbol.
*/
public void paint(Graphics g) {
Dimension size = getSize();
g.fillRect(0, 0, size.width, size.height);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/Display.java
0,0 → 1,1466
/*
$Id: Display.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.behaviour.*;
import fr.ove.openmath.jome.ctrlview.events.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.*;
 
/**
* The display elements of the formula.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 27/06/1999
*/
public abstract class Display extends Container implements Displayable, Colorizable, Selectable, Iconifiable, ModelListenerController {
/**
* Distance between the top of the bounding box of the element to display
* and its baseline.
*/
private int ascent;
 
/**
* Distance between the bottom of the bounding box of the element to display
* and its baseline.
*/
private int descent;
 
/**
* An horizontal shift.
*/
private int shiftX = 0;
 
/**
* A vertical shift.
*/
private int shiftY = 0;
 
/**
* Indicates whether the symbol is selected or not.
*/
protected boolean isSelected = false;
/**
* Indicates the level of reduction for the font.
* (Usefull for superscripts, underscripts, ....)
*/
private int level = 0;
/**
* Indicates if the level needs to be updated.
*/
private boolean updateLevel = true;
/**
* Indicates if we draw the bounds of the display or not.
*/
private boolean weDrawBounds = false;
/**
* The graphic context of the display.
*/
private GraphicContext graphicContext;
/**
* Indicates if the display need to be computed.
*/
private boolean computeAttributes = true;
/**
* The rank of the container in the set of children of its parent.
*/
private int rank = 0;
/**
* The selection manager of the display.
*/
private static SelectionEventListener selectionManager = null;
/**
* The list of listeners of the instance
*/
private ControlListener listener;
/**
* Are we in drag'n drop mode ??
*/
protected boolean dragNDrop;
/**
* To indicate if the instance represents the display of the symbol of an operator.<BR>
* For example, the display of the operator "+", display that is automatically inserted
* during the rendering of the formula.
*/
private boolean isSymbolOperatorDisplay = false;
/**
* To indicate if, when the instance is removed from its father, it has to be removed from the
* list of listeners it is listening to.<BR>
* The default is <CODE>true<CODE>. In fact, it is in special cases the value equals to <CODE>false<CODE>.
* These special cases are mainly moves of the instance in its father (e.g. add(comp, comp, index) calls
* a remove(...) method, which automatically removes the instance from the list of listeners it is listening
* to. And we don't want that)
*/
private boolean doRemoveFromListListeners = true;
/**
* The display allocator for the building of the visualisation of the formula.<BR>
* REMINDER : Don't forget to set the right allocator in the constructor of the inherited class.
*/
private static DisplayAllocator displayAllocator = null;
/**
* The constructor.
* @param graphicContext the graphic context of the display.
*/
public Display(GraphicContext graphicContext) {
super();
this.graphicContext = new GraphicContext(graphicContext);
setFont(graphicContext.getFont());
setForeground(graphicContext.getForegroundColor());
setBackground(graphicContext.getBackgroundColor());
addMouseListener(
new MouseAdapter() {
public void mousePressed(MouseEvent e) {
SelectionEvent selEvt = new SelectionEvent(Display.this);
if (e.isControlDown()) {
if (!isSelected) {
DisplayLayout displayLayout = (DisplayLayout) getLayout();
if (displayLayout instanceof OneFormulaLayout) {
Display formulaDisplay = (Display) getComponent(0);
if (formulaDisplay.isSelected())
displayLayout.deselectDisplay();
else {
displayLayout.selectDisplay();
setCursor(new Cursor(Cursor.HAND_CURSOR));
}
}
else {
displayLayout.selectDisplay();
setCursor(new Cursor(Cursor.HAND_CURSOR));
}
 
repaint();
}
else {
((DisplayLayout) getLayout()).deselectDisplay();
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 
repaint();
}
}
else if (e.isShiftDown())
iconify();
else if (e.isAltDown())
uniconify();
}
public void mouseEntered(MouseEvent e) {
if (isSelected)
setCursor(new Cursor(Cursor.HAND_CURSOR));
else
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
public void mouseReleased(MouseEvent e) {
int mouseX = e.getX();
if (dragNDrop) {
moveSelectedDisplays(mouseX);
dragNDrop = false;
repaint();
}
}
 
}
);
addMouseMotionListener(
new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
if (isSelected) {
dragNDrop = true;
setCursor(new Cursor(Cursor.MOVE_CURSOR));
}
}
public void mouseMoved(MouseEvent e) {
if (isSelected)
setCursor(new Cursor(Cursor.HAND_CURSOR));
else
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
);
}
// *******************
// Display information
// *******************
/**
* Returns <CODE>true</CODE> if the instance is a display of the specified
* formula tree structure. <CODE>false</CODE> otherwise.
*/
public boolean isDisplay(FormulaTreeStructure fts) {
// On recupère la liste de tous les listeners de fts
Vector listeners = fts.getListeners();
return listeners.contains(this);
}
// ***************************************
// About the display as one of an operator
// ***************************************
/**
* Sets if the instance represents the display of the symbol of an operator.
* @param isSymbolOperatordisplay <CODE>true</CODE> if the instance represents
* the display of the symbol of an operator. <CODE>false</CODE> otherwise.
*/
public void setIsSymbolOperatorDisplay(boolean isSymbolOperatorDisplay) {
this.isSymbolOperatorDisplay = isSymbolOperatorDisplay;
}
/**
* @return <CODE>true</CODE> if the instance represents the display of the symbol
* of an operator. <CODE>false</CODE> otherwise.
*/
public boolean isSymbolOperatorDisplay() {
return isSymbolOperatorDisplay;
}
// *************************
// The bounds of the display
// *************************
/**
* The bounds of the display have to be drawn.
*/
public void drawBounds() {
weDrawBounds = true;
}
/**
* The bounds of the display don't have to be drawn.
*/
public void dontDrawBounds() {
weDrawBounds = false;
}
/**
* Checks if the bound must be drawn or not.
* @return <CODE>true</CODE> if we have to draw the bounds of the
* display. <CODE>false</CODE> otherwise.
*/
public boolean weDrawBounds() {
return weDrawBounds;
}
// ************************
// The level of the display
// ************************
/**
* Sets the level of the display
* @param level the level of the display.
*/
public void setLevel(int level) {
this.level = level;
}
/**
* Returns the level of the display
*/
public int getLevel() {
return level;
}
 
/**
* Increments the level value.
*/
public void incLevel() {
level++;
}
/**
* Decrements the level value.
*/
public void decLevel() {
level--;
}
/**
* Sets the level to be updated.
* @param updateLevel <CODE>true</CODE> if the display level need to be
* updated. <CODE>false</CODE> otherwise.
*/
public void setUpdateLevel(boolean updateLevel) {
this.updateLevel = updateLevel;
if (updateLevel) {
int count = getComponentCount();
for (int i = 0; i < count; i++)
((Display) getComponent(i)).setUpdateLevel(updateLevel);
}
}
/**
* Checks if we need to update the level of the display.
* @return <CODE>true</CODE> if needed. <CODE>false</CODE> otherwise.
*/
public boolean getUpdateLevel() {
return updateLevel;
}
/**
* Recurses into the tree of the display to inform the ancestors of the instance
* that they need to update their level
*/
public void updateAncestorsLevel() {
Container parent = getParent();
while (parent instanceof Display) {
((Display) parent).setUpdateLevel(true);
parent = parent.getParent();
}
}
/**
* Recurses into the tree of the display to inform the children of the instance
* that they need to update their level
*/
public void updateChildrenLevel() {
Display childDisplay;
int count = getComponentCount();
for (int i = 0; i < count; i++) {
childDisplay = (Display) getComponent(i);
childDisplay.setUpdateLevel(true);
childDisplay.updateChildrenLevel();
}
}
// ************************************
// The management of display attributes
// ************************************
/**
* Sets the attributes to be computed.
* @param computeAttributes <CODE>true</CODE> if the display attributes need to be
* computed. <CODE>false</CODE> otherwise.
*/
public void setComputeAttributes(boolean computeAttributes) {
this.computeAttributes = computeAttributes;
}
 
/**
* Checks if we need to compute the display.
* @return <CODE>true</CODE> if needed. <CODE>false</CODE> otherwise.
*/
public boolean getComputeAttributes() {
return computeAttributes;
}
/**
* Recurses into the tree of the display to inform the ancestors of the instance
* that they need to compute their attributes.
*/
public void computeAncestorsAttributes() {
computeAttributes = true;
Container parent = getParent();
while (parent instanceof Display) {
((Display) parent).setComputeAttributes(true);
parent = parent.getParent();
}
}
/**
* Recurses into the tree of the display to inform the children of the instance
* that they need to compute their attributes.
*/
public void computeChildrenAttributes() {
computeAttributes = true;
int count = getComponentCount();
for (int i = 0; i < count; i++)
((Display) getComponent(i)).computeChildrenAttributes();
}
// ***********************
// The rank of the display
// ***********************
/**
* Sets the rank of the display.
* @param rank the rank.
*/
public void setRank(int rank) {
this.rank = rank;
}
/**
* Returns the rank of the display.
*/
public int getRank() {
return rank;
}
/**
* Adjusts the rank of its children.
*/
public void adjustRank() {
int count = getComponentCount();
for (int i = 0; i < count; i++)
((Display) getComponent(i)).setRank(i);
}
// *********************
// Display manipulations
// *********************
/**
* Removes all the displays of the instance. <BR>
* The fundamental difference with removeAll is in that case, the displays removed are not
* removed form the list of listeners of the formula tree structure they are listening to.
*/
public void removeAllDisplays() {
Display display;
int count = getComponentCount();
for (int i = 0; i < count; ) {
display = (Display) getComponent(i);
// Si c'est le display d'un opérateur, alors on l'enlève de la liste et en plus, on l'enlève
// de la liste des listeners de la fts qu'il écoutait.
// Le remove surchargé.
// si ce n'est pas le cas, on ne fait que le supprimer des fils de l'instance.
if (display.isSymbolOperatorDisplay)
//remove(display);
remove(i);
else
//super.remove(display);
super.remove(i);
count--;
}
}
/**
* Scales the display.
*/
public void scaleDisplay() {
setTheFont(graphicContext.scaleFont(level));
setComputeAttributes(true);
int count = getComponentCount();
for (int i = 0; i < count; i++)
((Display) getComponent(i)).scaleDisplay();
// On regarde si le display de l'instance est le display d'une icone.
// Si tel est le cas, il faut que l'on scale les displays iconifiés.
FormulaTreeStructure fts = (FormulaTreeStructure) getListener();
if ((fts != null) && fts.isIcon()) {
SubstitutedDisplayManager layout = (SubstitutedDisplayManager) getLayout();
count = layout.getNbSubstitutedDisplay();
for (int i = 0; i < count; i++)
layout.getSubstitutedDisplay(i).scaleDisplay();
}
}
/**
* Moves the selected displays to the mouse position.
* @param mouseX the mouse position.
*/
public void moveSelectedDisplays(int mouseX) {
SelectionEvent selectionEvent = new SelectionEvent(this);
 
// On récupère la taille de la sélection.
Integer selectionSize = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION_SIZE, selectionSize);
fireSelectionEvent(selectionEvent);
selectionSize = (Integer) selectionEvent.getArgument();
// Si différente de 0, on peut faire du drag'n drop de qque chose.
if (selectionSize.intValue() != 0) {
// On récupère la sélection entière.
Vector selection = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION, selection);
fireSelectionEvent(selectionEvent);
selection = (Vector) selectionEvent.getArgument();
Display display = (Display) selection.elementAt(0);
// On récupère le fts associé au display.
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
// On récupère l'opérateur dont les display sont les opérandes.
fts = (FormulaTreeStructure) fts.getFather();
// On fonction du type de cet opérateur, on permet ou pas le drag'n
// drop.
if (!fts.getAreOperandsMovable())
return; // Pour ces opérateur là, on ne permet pas le drag'n drop.
 
// Il faut maintenant savoir où on va dropper la sélection.
// On récupère le display de l'opérateur, et on cherche cette position
display = (Display) display.getParent();
// On ajuste la position de la souris pour qu'on soit en coordonnée relative
// dans le repère de display.
// ATTENTION : l'instance courante est celle qui a reçu le mouseDragged. Elle
// a reçu également le mouseReleased. Ce qui fait que le mouseX est une coordonnée
// relative à l'instance. Donc, pour ramener notre coordonnée relativement à display
// il faut rajouter la coordonnée de l'instance.
Display tmp = this;
while (tmp != display) {
mouseX += tmp.getX();
tmp = (Display) tmp.getParent();
}
// On regarde si la position de la souris ainsi calculée est toujours contenue
// dans le display. Si ce n'est pas le cas, on se trouve dans un cas particulier.
int insertionPosition;
if (mouseX <= 0) {
// On a droppé à gauche de display, on insère donc au début de celui-ci
// Cela revient à dropper sur le premier display de la liste.
tmp = (Display) display.getComponentAt(1, display.getAscent());
insertionPosition = tmp.computeInsertionPosition(1);
}
else if (mouseX >= display.getWidth()) {
// On a droppé à droite de display, on insère donc à la fin de celui-ci
// Cela revient dropper sur le dernier display de la liste.
tmp = (Display) display.getComponentAt(display.getWidth() - 1, display.getAscent());
insertionPosition = tmp.computeInsertionPosition(display.getWidth() - 1 - tmp.getX());
}
else {
// On a droppé qque part dans display. On récupère ce display.
tmp = (Display) display.getComponentAt(mouseX, display.getAscent());
insertionPosition = tmp.computeInsertionPosition(mouseX - tmp.getX());
}
// On créé la liste des opérandes à permuter
Vector operands = new Vector();
for (Enumeration e = selection.elements(); e.hasMoreElements(); ) {
tmp = (Display) e.nextElement();
// Si l'on n'a pas affaire à un display d'operateur, alors on ajoute l'operande
// dans la liste.
if (!tmp.isSymbolOperatorDisplay()) {
tmp.deselect();
operands.addElement(tmp.getListener());
}
}
// On fait la permutation
// Faut-il rajouter l'événement pour rester dans la philosophie ???
fts.moveOperands(operands, insertionPosition);
// On purge la liste de sélection
selectionEvent.setAction(SelectionEvent.PURGE, null);
fireSelectionEvent(selectionEvent);
}
}
 
/**
* Returns the insertion position for the moving of displays.
* @param mouseX the mouse position.
*/
public int computeInsertionPosition(int mouseX) {
int insertionPosition;
// On regarde la position de la souris.
// Si elle est inférieure à la moitié de la largeur de l'instance, alors
// la position d'insertion est la position de l'opérande dont l'instance est
// le display. Sinon, la position d'insertion est la position de l'opérande
// dont l'instance est le display + 1.
if (mouseX <= (getWidth() / 2))
insertionPosition = ((FormulaTreeStructure) listener).getRank();
else
insertionPosition = ((FormulaTreeStructure) listener).getRank() + 1;
// Pas de pb de test pour savoir si on n'est pas sur le dernier opérande
// puisqu'on est obligé dans ce cas de retourner le nbre réel + 1 pour dire
// effectivement que l'on insère à la dernière position.
 
// On retourne la position d'insertion calculée.
return insertionPosition;
}
// ******************
// Display allocation
// ******************
/**
* Sets the display allocator.
* @param displayAllocator the display allocator
*/
public void setDisplayAllocator(DisplayAllocator displayAllocator) {
this.displayAllocator = displayAllocator;
}
/**
* Returns the display allocator.
* @return the display allocator, or <CODE>null</CODE> if none has been specified.
*/
public DisplayAllocator getDisplayAllocator() {
return displayAllocator;
}
/**
* Builds the display of the formula tree structure.<BR>
* This method has to be called when a formula tree structure has been created and the
* displays have not been associated yet.<BR>
* As a prerequesit, the instance which call this method MUST have a corresponding instance
* (a listener) in the formula tree structure (i.e. the formula tree structure we want to display).<BR>
*/
public void buildDisplay() {
Display childDisplay;
FormulaTreeStructure fts, ftsChild;
int count;
// On récupère l'élément de la FTS donc l'instance est le display.
fts = (FormulaTreeStructure) getListener();
if (fts != null) { // Bon malgrè le prérequis, on fait le test quand même
count = fts.getNbChildren();
// On parcourre la liste des fils de la fts, pour leur associer le display qui va bien
for (int i = 0; i < count; i++) {
ftsChild = (FormulaTreeStructure) fts.getChild(i);
// Allocation du display
childDisplay = displayAllocator.allocateDisplay(graphicContext, ftsChild);
// Chacun écoute l'autre
//childDisplay.addControlListener(ftsChild);
//ftsChild.addModelListener(childDisplay);
// On ajoute le nouveau display comme fils à l'instance
add(childDisplay);
// On descend dans la fts pour poursuivre la construction des display
childDisplay.buildDisplay();
}
}
}
/**
* Builds the display of the part of the formula tree structure at the specified index.<BR>
* This method has to be called when a new part of the formula tree structure has been created
* and the displays have not been associated yet. (modification of the formula expression, and then
* we only ask to build displays of the new part, and only them)<BR>
* As a prerequesit, the instance which calls this method MUST have a corresponding instance
* (a listener) in the formula tree structure (i.e. the formula tree structure we want to display)
* @param indexFts the index of the fts which needs displays to be associated, in the list of "sub-fts"
* of the corresponding fts of the instance (ouf !!!).<BR>
* <CODE>indexFts</CODE> must be less than the number of elements of the correponding fts, and
* greater or equal than 0.
* @return the new display created.
*/
public Display buildDisplay(int indexFts) {
Display childDisplay = null;
FormulaTreeStructure fts, ftsChild;
int count;
// On récupère l'élément de la FTS donc l'instance est le display.
fts = (FormulaTreeStructure) getListener();
if (fts != null) {
count = fts.getNbChildren();
if ((indexFts >= 0) && (indexFts < count)) {
ftsChild = (FormulaTreeStructure) fts.getChild(indexFts);
// Allocation du display
childDisplay = displayAllocator.allocateDisplay(graphicContext, ftsChild);
// Le display que l'on ajoute est au même niveau que celui du père
// (rappel: niveau = nb de fois que la réduction de taille doit être appliquée,
// par exemple pour les exposants.) C'est le layout manager qui s'occupe de
// faire la réduction si nécessaire.
childDisplay.setLevel(getLevel());
// Chacun écoute l'autre
childDisplay.addControlListener(ftsChild);
ftsChild.addModelListener(childDisplay);
// On ajoute le nouveau display comme fils à l'instance
add(childDisplay);
// On descend dans la fts pour poursuivre la construction des display
childDisplay.buildDisplay();
}
}
return childDisplay;
}
// ############################
// ### Méthodes surchargées ###
// ############################
/**
* Adds a child display to the instance. The child is added as the last child of the
* set of children of the instance.
* @param display the display to add.
*/
public void add(Display display) {
super.add(display, display);
display.setRank(getComponentCount() - 1);
}
/**
* Removes from the instance the display at the specified index.
* @param index the specified index.
*/
public void remove(int index) {
try {
Display display = (Display) getComponent(index);
if (display.doRemoveFromListListeners())
// On enlève maintenant le display supprimé de la liste des listeners de la fts
// qu'il écoutait
display.removeFromListListeners();
// On enlève le display de la liste
super.remove(index);
// On réajuste maintenant le rank des fils de l'instance
adjustRank();
}
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Trying to remove display with a wrong index");
e.printStackTrace();
}
}
/**
* Removes the specified display to the instance.
* @param display the display to remove.
*
public void remove(Display display) {
super.remove(display);
// On enlève maintenant le display supprimé de la liste des listeners de la fts
// qu'il écoutait
display.removeFromListListeners();
// On réajuste maintenant le rank des fils de l'instance
adjustRank();
}
*/
/**
* Removes all the displays of the instance.
*/
public void removeAll() {
/*
for (int i = 0; i < getComponentCount(); i++)
remove(i);
*/
for (int i = 0; i < getComponentCount(); )
remove(i);
computeAncestorsAttributes();
}
/**
* Sets if during the removal of the instance from the its father, we remove it from the list of
* listeners it is listening to.
* @param doRemoveFromListListeners <CODE>true<CODE> if we remove the instance from the list of listeners.
* <CODE>false</CODE> otherwise.
*/
protected void setDoRemoveFromListListeners(boolean doRemoveFromListListeners) {
this.doRemoveFromListListeners = doRemoveFromListListeners;
}
/**
* Returns <CODE>true<CODE> if we remove the instance from the list of listeners.
* <CODE>false</CODE> otherwise.
*/
protected boolean doRemoveFromListListeners() {
return doRemoveFromListListeners;
}
/**
* Sets if during the manipulation of children of the instance, the children manipulated have to be
* removed from the list od listeners.
* @param doRemoveFromListListeners <CODE>true<CODE> if we remove the children manipulated from the list
* of listeners. <CODE>false</CODE> otherwise.
*/
protected void removeFromListListeners(boolean doRemoveFromListListeners) {
int count = getComponentCount();
for (int i = 0; i < count; i++)
((Display) getComponent(i)).doRemoveFromListListeners = doRemoveFromListListeners;
}
/**
* Removes the instance from the list of listeners of the formula tree structure it
* is listening to.
*/
private void removeFromListListeners() {
// On récupère la fts associée au display enlevé et on lui enlève display
// de la liste de ses listeners.
FormulaTreeStructure fts = (FormulaTreeStructure) getListener();
fts.removeModelListener(this);
removeControlListener(fts);
// Il faut maintenant que l'on fasse la même chose avec les displays fils
int count = getComponentCount();
for (int i = 0; i < count; i++)
((Display) getComponent(i)).removeFromListListeners();
}
/**
* Sets a new font to the context.
* @param font the new font.
*/
public void setFont(Font font) {
setTheFont(font);
graphicContext.setFont(font);
int count = getComponentCount();
// On parcourre tous les displays fils et ont leur affecte la nouvelle font.
for (int i = 0; i < count; i++)
((Display) getComponent(i)).setFont(font);
// On calcule la taille de la nouvelle font utilisée en fonction du niveau
// du display.
scaleDisplay();
// On indique au layout manager que la taille du display (container) n'est plus
// valide.
invalidate();
// On regarde si le display de l'instance est le display d'une icone.
// Si tel est le cas, il faut que l'on mette la nouvelle font aux displays iconifiés.
FormulaTreeStructure fts = (FormulaTreeStructure) getListener();
if ((fts != null) && fts.isIcon()) {
SubstitutedDisplayManager layout = (SubstitutedDisplayManager) getLayout();
count = layout.getNbSubstitutedDisplay();
for (int i = 0; i < count; i++)
layout.getSubstitutedDisplay(i).setFont(font);
}
}
protected void setTheFont(Font font) {
super.setFont(font);
}
/**
* Substitutes the selection by the specified friendly name.
* @param the name for the substitution
*/
public void substitute(String name) {
SelectionEvent selectionEvent = new SelectionEvent(this);
 
// On récupère la taille de la sélection.
Integer selectionSize = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION_SIZE, selectionSize);
fireSelectionEvent(selectionEvent);
selectionSize = (Integer) selectionEvent.getArgument();
// Si différent de 0, il y a qque chose à substituer.
if (selectionSize.intValue() != 0) {
// On récupère la sélection entière.
Vector selection = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION, selection);
fireSelectionEvent(selectionEvent);
selection = (Vector) selectionEvent.getArgument();
// On créé la liste des éléments à iconifier. (on enlève les displays
// d'opérateurs parasites, et aux displays qui restent, on récupère
// la fts dont ils sont le display).
Display display;
FormulaTreeStructure fts;
Vector toIconify = new Vector();
for (int i = 0; i < selectionSize.intValue(); i++) {
display = (Display) selection.elementAt(i);
if (!display.isSymbolOperatorDisplay()) {
// On désélectionne le display
display.deselect();
// On récupère le fts associé au display.
fts = (FormulaTreeStructure) display.getListener();
// On l'ajoute à la liste des fts à iconifier
toIconify.addElement(fts);
}
}
// On purge la sélection
selectionEvent.setAction(SelectionEvent.PURGE, null);
fireSelectionEvent(selectionEvent);
// On rajoute comme premier élément à toIconify le nom de la substitution
toIconify.insertElementAt(name, 0);
// On envoie l'événement au modèle pour lui dire qu'il faut faire la substitution
ControlEvent controlEvent = new ControlEvent(this);
controlEvent.setAction(ControlEvent.SUBSTITUTE, toIconify);
fireControlEvent(controlEvent);
}
}
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
// *************************************************
// *** Implémentation de l'interface Displayable ***
/**
* Sets the ascent.
* @param ascent the new ascent value.
*/
public void setAscent(int ascent) {
this.ascent = ascent;
}
 
/**
* Returns the ascent.
* @return the ascent.
*/
public int getAscent() {
return ascent;
}
 
/**
* Sets the descent.
* @param descent the new descent value.
*/
public void setDescent(int descent) {
this.descent = descent;
}
 
/**
* Returns the descent.
* @return the descent.
*/
public int getDescent() {
return descent;
}
/**
* Sets the horizontal shift.
* @param shift the new horizontal shift value.
*/
public void setShiftX(int shiftX) {
this.shiftX = shiftX;
}
 
/**
* Returns the horizontal shift.
* @return the horizontal shift.
*/
public int getShiftX() {
return shiftX;
}
 
/**
* Sets the vertical shift.
* @param shiftY the new vertical shift value.
*/
public void setShiftY(int shiftY) {
this.shiftY = shiftY;
}
 
/**
* Returns the vertical shift.
* @return the vertical shift.
*/
public int getShiftY() {
return shiftY;
}
/**
* Sets all the attributes.
* @param ascent the new ascent value.
* @param descent the new descent value.
* @param shiftX the new horizontal shift value.
* @param shiftY the new vertical shift value.
*/
public void setAttributes(int ascent, int descent, int shiftX, int shiftY) {
this.ascent = ascent;
this.descent = descent;
this.shiftX = shiftX;
this.shiftY = shiftY;
}
/**
* Sets the graphic context to the display.
* @param contextGraphic the graphic context.
*/
public void setGraphicContext(GraphicContext graphicContext) {
this.graphicContext = graphicContext;
}
/**
* Returns the graphic context of the display.
*/
public GraphicContext getGraphicContext() {
return graphicContext;
}
// *** Fin de l'interface Displayable ***
// **************************************
// *************************************************
// *** Implémentation de l'interface Localisable ***
/**
* Sets the x-location of the instance.
* @param x the x-location of the instance.
*/
public void setX(int x) {
setLocation(x, getLocation().y);
}
/**
* Returns the x-location of the display.
*/
public int getX() {
return getLocation().x;
}
/**
* Sets the y-location of the instance.
* @param y the y-location of the instance.
*/
public void setY(int y) {
setLocation(getLocation().x, y);
}
/**
* Returns the y-location of the display.
*/
public int getY() {
return getLocation().y;
}
// *** Fin de l'interface Localisable ***
// **************************************
// *********************************************
// *** Implémentation de l'interface Sizable ***
/**
* Sets the width of the instance.
* @param width the width of the instance
*/
public void setWidth(int width) {
setSize(width, getSize().height);
}
/**
* Returns the width of the display.
*/
public int getWidth() {
return getSize().width;
}
/**
* Sets the height of the instance.
* @param height the height of the instance
*/
public void setHeight(int height) {
setSize(getSize().width, height);
}
/**
* Returns the height of the display.
*/
public int getHeight() {
return getSize().height;
}
// *** Fin de l'interface sizable ***
// **********************************
// ****************************************
// Implémentation de l'interface Selectable
/**
* Selects the display. Selects the instance and its children if any.
*/
public void select() {
if (!isSelected) {
isSelected = true;
int count = getComponentCount();
for (int i = 0; i < count; i++)
((Display) getComponent(i)).select();
}
}
/**
* Deselects the display. Deselects the instance and its children if any.
*/
public void deselect() {
if (isSelected) {
isSelected = false;
int count = getComponentCount();
for (int i = 0; i < count; i++)
((Display) getComponent(i)).deselect();
}
}
/**
* Sets the display as selected.
*/
public void setSelected() {
isSelected = true;
}
 
/**
* Sets the display as not selected.
*/
public void setNotSelected() {
isSelected = false;
}
/**
* Checks if the display is selected or not.
* @return <CODE>true</CODE> if the display is selected.
* <CODE>false</CODE> otherwise.
*/
public boolean isSelected() {
return isSelected;
}
/**
* Returns <CODE>true</CODE> if the display have components selected or is selected.<BR>
* <CODE>false</CODE> otherwise.
*/
public boolean gotSelectedElements() {
if (isSelected)
return true;
int count = getComponentCount();
for (int i = 0; i < count; i++)
if (((Display) getComponent(i)).gotSelectedElements())
return true;
return false;
}
// *** Fin de l'interface Selectable ***
// *************************************
// *****************************************
// Implémentation de l'interface Colorisable
/**
* Sets a new color to the context.
* @param foregroundColor the new color.
*/
public void setForegroundColor(Color foregroundColor) {
graphicContext.setForegroundColor(foregroundColor);
}
/**
* Returns the color used by the graphic context.
*/
public Color getForegroundColor() {
return graphicContext.getForegroundColor();
}
/**
* Sets a new color to the context.
* @param backgroundColor the new color.
*/
public void setBackgroundColor(Color backgroundColor) {
graphicContext.setBackgroundColor(backgroundColor);
}
/**
* Returns the color used by the graphic context.
*/
public Color getBackgroundColor() {
return graphicContext.getBackgroundColor();
}
/**
* Sets a new selection color to the context.
* @param selectionColor the new color.
*/
public void setSelectionColor(Color selectionColor) {
graphicContext.setSelectionColor(selectionColor);
}
 
/**
* Returns the color used in the graphic context to hilight the selection.
*/
public Color getSelectionColor() {
return graphicContext.getSelectionColor();
}
// *** Fin de l'interface Colorisable ***
// **************************************
// *****************************************
// Implémentation de l'interface Iconifiable
// Même si en fait ce n'est pas un display que l'on va iconifier, on implémente l'interface
// iconifiable, parce que c'est à partir de là que le processus d'iconification va être lancé,
// notamment en parcourant la liste de tous les display sélectionnés, potentiellement iconifiables.
/**
* Associates an icon name to the instance.
*
* @param iconName the name of the icon
*/
public void setIconName(String iconName) {
// on ne fait rien, ce n'est pas un display que l'on va iconifier.
}
 
/**
* Returns the name of the icon associated to the instance.
*
* @returns The name of the icon, or <CODE>null</CODE> if there is no name
* associated.
*/
public String getIconName() {
return null; // ce n'est pas un display que l'on va iconifier.
}
/**
* @return <CODE>true</CODE> if the instance is an icon. <CODE>false</CODE> otherwise.
*/
public boolean isIcon() {
return false; // ce n'est pas un display que l'on va iconifier.
}
/**
* Iconifies all the selected elements of the formula.
*/
public void iconify() {
SelectionEvent selectionEvent = new SelectionEvent(this);
 
// On récupère la taille de la sélection.
Integer selectionSize = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION_SIZE, selectionSize);
fireSelectionEvent(selectionEvent);
selectionSize = (Integer) selectionEvent.getArgument();
// Si différente de 0, il y a qque chose à iconifier.
if (selectionSize.intValue() != 0) {
// On récupère la sélection entière.
Vector selection = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION, selection);
fireSelectionEvent(selectionEvent);
selection = (Vector) selectionEvent.getArgument();
// On créé la liste des éléments à iconifier. (on enlève les displays
// d'opérateurs parasites, et aux displays qui restent, on récupère
// la fts dont ils sont le display).
Display display;
FormulaTreeStructure fts;
Vector toIconify = new Vector();
for (int i = 0; i < selectionSize.intValue(); i++) {
display = (Display) selection.elementAt(i);
if (!display.isSymbolOperatorDisplay()) {
// On désélectionne le display
display.deselect();
// On récupère le fts associé au display.
fts = (FormulaTreeStructure) display.getListener();
// On l'ajoute à la liste des fts à iconifier
toIconify.addElement(fts);
}
}
// On purge la sélection
selectionEvent.setAction(SelectionEvent.PURGE, null);
fireSelectionEvent(selectionEvent);
// On envoie l'événement au modèle pour lui dire qu'il faut iconifier
ControlEvent controlEvent = new ControlEvent(this);
controlEvent.setAction(ControlEvent.ICONIFY, toIconify);
fireControlEvent(controlEvent);
}
}
 
/**
* Uniconifies all the selected icons which are in the formula.
*/
public void uniconify() {
SelectionEvent selectionEvent = new SelectionEvent(this);
// On récupère la taille de la sélection.
Integer selectionSize = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION_SIZE, selectionSize);
fireSelectionEvent(selectionEvent);
selectionSize = (Integer) selectionEvent.getArgument();
// Si différente de 0, il y a éventuellement qque chose à désiconifier.
if (selectionSize.intValue() != 0) {
// On récupère la sélection entière.
Vector selection = null;
selectionEvent.setAction(SelectionEvent.GET_SELECTION, selection);
fireSelectionEvent(selectionEvent);
selection = (Vector) selectionEvent.getArgument();
selectionEvent.setAction(SelectionEvent.PURGE, null);
fireSelectionEvent(selectionEvent);
// On parcourt la liste de sélection, et si l'on a affaire à une icone
// on la désiconifie.
Display display = null;
FormulaTreeStructure fts = null;
for (int i = 0; i < selectionSize.intValue(); i++) {
display = (Display) selection.elementAt(i);
// On désélectionne le display.
display.deselect();
// On récupère le fts associé au display.
fts = (FormulaTreeStructure) display.getListener();
if (fts.isIcon()) {
display.computeAncestorsAttributes();
// On envoie un événement pour dire au modèle qu'il doit
// déisconifier fts.
ControlEvent controlEvent = new ControlEvent(this);
controlEvent.setAction(ControlEvent.UNICONIFY, fts);
fireControlEvent(controlEvent);
}
}
}
}
/**
* Uniconifies all the selected icons.<BR>
* If the icons contains other icons, these are uniconified. There is a
* recursion process.
*/
public void uniconifyAll() {
ControlEvent controlEvent = new ControlEvent(this);
controlEvent.setAction(ControlEvent.UNICONIFY_ALL, null);
fireControlEvent(controlEvent);
}
/**
* Sets the istance as iconifiable.
* @param isIconifiable <CODE>true</CODE> if the instance is iconifiable.
* <CODE>false</CODE> otherwise.
*/
public void setIsIconifiable(boolean isIconifiable) {
// Ce n'est pas un display que l'on va iconifier
}
/**
* Returns <CODE>true</CODE> if the instance is iconifiable.
* <CODE>false</CODE> otherwise.
*/
public boolean isIconifiable() {
// Ce n'est pas un display que l'on va iconifier
return false;
}
// *** Fin de l'interface Iconifiable ***
// **************************************
// *****************************************************
// Implémentation de l'interface ModelListenerController
/**
* Registers another listener to be informed of changes of the display.
* @param controlListener a listener to add.
*/
public void addControlListener(ControlListener controlListener) {
listener = controlListener;
}
 
/**
* Removes all the listeners.
*/
public void removeAllControlListener() {
listener = null;
}
/**
* Removes a listener.
* @param controlListener a listener to remove.
*/
public void removeControlListener(ControlListener controlListener) {
listener = null;
}
/**
* Fires a Control event to registered listeners.
* @param controlEvent event encapsulating relevant information.
*/
public void fireControlEvent(ControlEvent controlEvent) {
listener.consumeControlEvent(controlEvent);
}
/**
* Returns the listener of the dispay. (i.e. a fts)
*/
public ControlListener getListener() {
return listener;
}
 
// *** Fin de l'interface ModelListenerController ***
// **************************************************
// Selection management.
/**
* Registers another listener to be informed of changes of the display.
* @param selectionEventListener a listener to add.
*/
public void addSelectionEventListener(SelectionEventListener selectionEventListener) {
selectionManager = selectionEventListener;
}
/**
* Removes a listener.
* @param selectionEventListener listener to remove.
*/
public void removeSelectionEventListener(SelectionEventListener selectionEventListener) {
if (selectionEventListener == selectionManager)
selectionManager = null;
}
/**
* Fires a SelectionEvent event to registered listeners.
* @param selectionEvent event encapsulating relevant information.
*/
public void fireSelectionEvent(SelectionEvent selectionEvent) {
selectionManager.consumeSelectionEvent(selectionEvent);
}
/**
* For debugg only !!!!
*/
 
public void ToString() {
System.out.println(super.toString());
System.out.println("\t x = " + getX() + " y = " + getY());
System.out.println("\t ascent = " + ascent + " descent = " + descent);
System.out.println("\t width = " + getWidth() + " height = " + getHeight());
}
public void whoAmI() {
System.out.println("I am a " + getClass().getName() + " with the " + getLayout().getClass().getName() + " manager");
System.out.println("My level is " + level);
System.out.println("My children are :");
for (int i = 0; i < getComponentCount(); i++)
((Display) getComponent(i)).whoAmI();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/selection/events/SelectionEvent.java
0,0 → 1,129
/*
$Id: SelectionEvent.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim.selection.events;
 
import java.util.EventObject;
 
/**
* The event to send to all objects that implements the interface SlectionEventListener
* and which want to maintain a list of selected elements.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 30/06/98
*/
public class SelectionEvent extends EventObject {
/**
* The action to execute by sending the event.
*/
private int action;
 
/**
* The object which has been selected.
*/
private Object argument;
 
/**
* The constructor.
* @param src the object which produces this event.
*/
public SelectionEvent(Object src) {
super(src);
}
 
/**
* Sets the action to execute and its argument.
* @param action the action.
* @param argument the argument.<BR>
* In the case of the actions GET_SELECTION and GET_SELECTION_SIZE,
* arguments will serve as well as the return value
*/
public void setAction(int action, Object argument) {
this.action = action;
this.argument = argument;
}
 
/**
* Returns the action associated with the event.
*/
public int getAction() {
return action;
}
 
/**
* Returns the action argument.
*/
public Object getArgument() {
return argument;
}
/**
* Sets the action argument.
* @param argument the action argument.
*/
public void setArgument(Object argument) {
this.argument = argument;
}
 
/**
* The different actions associated with the event.<BR>
*/
 
/**
* This action tells the selections manager to remove all the elements it has.
*/
public static final int PURGE = 0;
 
/**
* This action tells the selections manager to remove an element. (which will be
* given to him)
*/
public static final int REMOVE = 1;
 
/**
* This action tells the selections manager to add an element. (which will be
* given to him)
*/
public static final int ADD = 2;
 
/**
* This action tells the selections manager to give the number of selected
* elements
*/
public static final int GET_SELECTION_SIZE = 3;
 
/**
* This action tells the selections manager to give all the selected elements
*/
public static final int GET_SELECTION = 4;
 
/**
* For debugg only. To list all the selected elements.
*/
public static final int LIST = 10;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/selection/events/SelectionEventListener.java
0,0 → 1,47
/*
$Id: SelectionEventListener.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim.selection.events;
 
import java.util.EventListener;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
 
/**
* The interface that an object which want to maintain a list of selected elements
* must implement.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 30/06/98
*/
public interface SelectionEventListener extends EventListener {
/**
* Consumes (i.e. treats) the event received.
* @param selectionEvent the event to consume.
*/
public void consumeSelectionEvent(SelectionEvent selectionEvent);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/selection/SelectionManager.java
0,0 → 1,87
/*
$Id: SelectionManager.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim.selection;
 
import java.util.Vector;
import java.util.Enumeration;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEventListener;
 
 
/**
* This class manages a list of selected elements.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 30/06/98
*/
public class SelectionManager implements SelectionEventListener {
/**
* The list of selected elements.
*/
private Vector selected;
 
/**
* The constructor.
*/
public SelectionManager() {
selected = new Vector();
}
 
/**
* Consumes (i.e. treats) the event received.
* @param selectionEvent the event to consume.
*/
public void consumeSelectionEvent(SelectionEvent selectionEvent) {
switch (selectionEvent.getAction()) {
case SelectionEvent.PURGE :
selected.setSize(0);
selected.trimToSize();
break;
case SelectionEvent.REMOVE :
selected.removeElement(selectionEvent.getArgument());
break;
case SelectionEvent.ADD :
selected.addElement(selectionEvent.getArgument());
break;
case SelectionEvent.GET_SELECTION_SIZE :
selectionEvent.setArgument(new Integer(selected.size()));
break;
case SelectionEvent.GET_SELECTION :
selectionEvent.setArgument(selected.clone());
break;
case SelectionEvent.LIST :
// For debugg only !!!
System.out.println(" I've got "+ selected.size() + " selected elements");
for (Enumeration e = selected.elements(); e.hasMoreElements(); )
((Display) e.nextElement()).whoAmI();
break;
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ImageSymbol.java
0,0 → 1,148
/*
$Id: ImageSymbol.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.awt.image.ImageObserver;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.images.ImageLoader;
 
/**
* The Displayable implementation of an image symbol.
*
* @author © 2000 DIRAT Laurent
* @version 2.0 05/01/2000
*/
public class ImageSymbol extends DisplayableImpl {
/**
* The image identifier
*/
private String imgId;
/**
* The initial image.
* The reason of this field is we need to create an instance of the image
* which will have a size proportional with the characters of the formula. Because
* all the characters don't have the same size (exponents for example), we
* need to keep a reference of the initial size of the icon, to compute
* correctly its real size for displaying.
*/
private Image symbolInit;
private Image symbol;
/**
* Object to be notified as more of the image is converted.
*/
private ImageObserver observer;
private Insets insets = new Insets(0, 0, 0, 0);
/**
* The constructor.
* @param imgId the image identifier of the symbol.
* @param observer the object to be notified as more of the image is converted.
*/
public ImageSymbol(String imgId, ImageObserver observer) {
symbolInit = ImageLoader.getImage(imgId);
this.observer = observer;
this.imgId = imgId;
}
/**
* Sets the graphic context in which the object is.
* @param graphicContext the object graphic context.
* Actually, this methods gives information to the object, notably when its preferred
* size is required. If the context has changed, the displayable object must be informed.
* However, in the most part of the time, the whole graphic context won't be necessary
* stored, but only specific and usefull data.
*/
public void setGraphicContext(GraphicContext graphicContext) {
super.setGraphicContext(graphicContext);
FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(graphicContext.getFont());
float heightFactor = ImageLoader.getHeightFactor(imgId);
int fontHeight = fm.getHeight();
insets.top = Math.round(ImageLoader.getTopInset(imgId)*fontHeight);
insets.bottom = Math.round(ImageLoader.getBottomInset(imgId)*fontHeight);
insets.left = Math.round(ImageLoader.getLeftInset(imgId)*fontHeight);
insets.right = Math.round(ImageLoader.getRightInset(imgId)*fontHeight);
setHeight((int) Math.round(fontHeight*heightFactor + insets.top + insets.bottom));
float baseline = ImageLoader.getBaseline(imgId);
int ascent;
if (baseline == -1) {
// C'est la baseline de la police courante.
// Par contre, dans le cas d'un éventuel facteur de taille, l'ascent s'en trouve aussi
// modifié
ascent = (int) Math.round(fm.getAscent()*heightFactor);
}
else
ascent = (int) Math.round(fontHeight*heightFactor*baseline);
setAscent(ascent + insets.top);
setDescent(getHeight() - ascent);
}
 
/**
* The paint method of the object to display.
* @param g the drawing area of the symbol.
*/
public void paint(Graphics g) {
g.drawImage(symbol, insets.left, insets.top, observer);
}
/**
* Returns the preferred size of the display.
*/
public Dimension getPreferredSize() {
MediaTracker tracker = new MediaTracker((Component) observer);
// Le -1 signifie que la largeur sera proportionnelle à la hauteur.
symbol = symbolInit.getScaledInstance(-1, getHeight()- insets.top - insets.bottom, Image.SCALE_SMOOTH);
tracker.addImage(symbol, 0);
// On attend que toutes les images soient chargées.
try {
tracker.waitForAll();
}
catch (InterruptedException e) {
System.out.print(e.toString());
}
tracker.removeImage(symbol);
return new Dimension(symbol.getWidth(observer) + insets.left + insets.right, getHeight());
}
/**
* Returns the image of the symbol.
*/
public Image getSymbol() {
return symbol;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/resources.java
0,0 → 1,4
package fr.ove.openmath.jome.ctrlview.bidim;
 
public abstract class resources{
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/AbsoluteLayout.java
0,0 → 1,124
/*
$Id: AbsoluteLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
import fr.ove.utils.FontInfo;
 
/**
* Layout manager that lays the display of the absolute value operator
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class AbsoluteLayout extends EnclosingLayout {
/**
* Returns the opening
*/
public SymbolDisplay createOpening() {
SymbolDisplay bar = new SymbolDisplay(displayToLay.getGraphicContext(), new Bar());
// Le display de la barre est le display d'un opérateur (on peut le considérer comme tel)
bar.setIsSymbolOperatorDisplay(true);
return bar;
}
/**
* Returns the closing
*/
public SymbolDisplay createClosing() {
return createOpening();
}
 
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Display display = null;
 
// On calcule la taille de l'élement en valeur absolue
display = (Display) displayToLay.getComponent(2);
display.setSize(display.getPreferredSize());
// On met un petit décalage horizontal pour que la barre de gauche ne soit pas collée au terme
display.setShiftX(2);
int width = display.getShiftX() + display.getWidth();
int height = display.getShiftY() + display.getHeight();
int ascent = display.getAscent();
int descent = display.getDescent();
int thickness = FontInfo.getLineThickness(displayToLay, displayToLay.getFont());
// Maintenant, on peut fixer la hauteur des barres, qui est la hauteur du composant
// qu'elles contiennent, et l'ascent, qui est celui du composant qu'elles contiennent.
SymbolDisplay opening = getOpening();
Bar bar = (Bar) opening.getSymbol();
bar.setHeight(display.getHeight());
bar.setWidth(thickness);
bar.setAscent(ascent);
bar.setDescent(descent);
opening.setComputeAttributes(true);
opening.invalidate();
opening.setSize(opening.getPreferredSize());
 
width += opening.getWidth();
SymbolDisplay closing = getClosing();
bar = (Bar) closing.getSymbol();
bar.setHeight(display.getHeight());
bar.setWidth(thickness);
bar.setAscent(ascent);
bar.setDescent(descent);
closing.setComputeAttributes(true);
closing.invalidate();
closing.setSize(closing.getPreferredSize());
// On met un petit décalage horizontal pour que la barre de droite ne soit pas collée au terme
closing.setShiftX(2);
 
width += closing.getShiftX() + closing.getWidth();
displayToLay.setAscent(ascent);
displayToLay.setDescent(descent);
displayToLay.setSize(width, height);
displayToLay.setComputeAttributes(false);
// Cette taille là correspond au décalage qu'il faut appliquer à closing
closing.setShiftX(width - 2*closing.getWidth());
// Mais il faut l'enlever au display du milieu qui doit être contre l'opening (because HonrizontalLayout)
display.setShiftX(display.getShiftX() - closing.getShiftX() - closing.getWidth());
return new Dimension(width, height);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringOverOperatorLayout.java
0,0 → 1,53
/*
$Id: StringOverOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of the operator whose symbol is located over its operand.<BR>
* The symbol is represented as a simple string
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class StringOverOperatorLayout extends OverOperatorLayout {
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), fts.getTheOperator(), true);
return stringDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/LimitLayout.java
0,0 → 1,283
/*
$Id: LimitLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components for the limit operator.
*
* @author © 2000 DIRAT Laurent
* @version 2.0 25/02/2000
*/
public class LimitLayout extends HorizontalLayout {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
KaryOperator limit = (KaryOperator) this.displayToLay.getListener();
// Allocation d'un display, qui va correspondre à la partie "lim" de la représentation
Display display = new BidimDisplay(displayToLay.getGraphicContext());
// On met un listener à display
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
display.addControlListener(limit);
// On lui met dont un SymbolLimLayout
DisplayLayout layout = new SymbolLimLayout();
layout.initDisplay(display);
display.setLayout(layout);
// On l'ajoute comme fils à display
this.displayToLay.add(display);
// On met un display pour l'affichage de lim
StringDisplay lim = new StringDisplay(this.displayToLay.getGraphicContext(), "lim", true);
// idem
lim.addControlListener(limit);
display.add(lim);
// On met un display pour l'affichage de qui tend vers quoi
Display towards = new BidimDisplay(displayToLay.getGraphicContext());
towards.addControlListener(limit);
// On lui met un
layout = new ImageBinaryInfixOperatorLayout();
layout.initDisplay(towards);
towards.setLayout(layout);
display.add(towards);
}
/**
* Updates the level of the display that is layed out.<BR>
* @param level the level put to the display
*/
public void updateLevel(int level) {
// Pour éviter de refaire le calcul plusieurs fois....
if (displayToLay.getUpdateLevel()) {
super.updateLevel(level);
// sauf que l'affichage de quoi tend vers quoi est a un niveu supérieur
Display towards = (Display) displayToLay.getComponent(0);
towards = (Display) towards.getComponent(1);
towards.setUpdateLevel(true);
((DisplayLayout) towards.getLayout()).updateLevel(level+1);
towards = null;
}
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
/*
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
Display derivator = (Display) displayToLay.getComponent(0);
Display func = (Display) displayToLay.getComponent(1);
// Si le display de ce qui est la partie fraction de la dérivée (derivator) est sélectionnée,
// alors on sélectionne tout.
// Si la function et dérivator ont qque chose de sélectionné, alors on sélectionne tout.
if (derivator.isSelected() || (func.gotSelectedElements() && derivator.gotSelectedElements())) {
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute l'instance dans la liste des sélectionnés
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
// On a vérifié la validité de la sélection de l'opérateur. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (displayToLay.getParent() instanceof Display) {
display = (Display) displayToLay.getParent();
//if (!(display.getListener() instanceof Formula))
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
*/
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
/*
// father est le display de l'opérateur unaire.
Display father = displayToLay;
Display tmp;
SelectionEvent selEvt = new SelectionEvent(father);
// Si l'opérateur en entier est sélectionné, il faut le désélectionner
if (father.isSelected()) {
father.deselect();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
// Si display est l'opérateur (on vient de déselectionner l'opérateur), alors
// on ajoute l'opérande dans la liste des sélectionnés.
if (display == displayToLay.getComponent(0)) {
((Display) displayToLay.getComponent(1)).select();
selEvt.setAction(SelectionEvent.ADD, (Display) displayToLay.getComponent(1));
father.fireSelectionEvent(selEvt);
}
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
//((DisplayLayout) father.getLayout()).validateDeselection((Display) display.getParent());
if (!(father.getListener() instanceof Formula))
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
*/
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Display towards = (Display) displayToLay.getComponent(0);
towards = (Display) towards.getComponent(1);
if (displayToLay.getComponentCount() > 2) {
// Dans l'ordre, displayToLay contient [[lim, []], fct, var, borne]
// Il faut mettre var et borne, comme fils au display frère de lim.
// Ce display a un LM qui rajoutera une --> entre var et borne.
// On aura donc [[lim, [var, rightArrow, borne]], fct]
Display d;
d = (Display) displayToLay.getComponent(2);
// towards.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
towards.add(d);
d.setDoRemoveFromListListeners(true);
//displayToLay contient [[lim [var]], fct, borne]
d = (Display) displayToLay.getComponent(2);
// towards.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
towards.add(d);
d.setDoRemoveFromListListeners(true);
//displayToLay contient [[lim [var, borne]], fct]
}
((Display) displayToLay.getComponent(1)).setShiftX(5);
updateLevel(displayToLay.getLevel());
Dimension dim = super.computeAttributes();
return new Dimension(dim.width + 5, dim.height);
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
 
 
class SymbolLimLayout extends VerticalCenteredLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Dimension dim = super.computeAttributes();
displayToLay.setAscent(((Display) displayToLay.getComponent(0)).getAscent());
displayToLay.setDescent(displayToLay.getHeight() - displayToLay.getAscent());
return dim;
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
// To Do !!!!
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
// To Do !!!!
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ConjugateLayout.java
0,0 → 1,103
/*
$Id: ConjugateLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.Bar;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
import fr.ove.utils.FontInfo;
 
/**
* Layout manager that lays the display of the conjugate operator
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class ConjugateLayout extends OverOperatorLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
SymbolDisplay displayBar = null;
Bar bar = null;
updateLevel(displayToLay.getLevel());
// On est dans le cas particulier d'un symbol qui ne connais pas sa taille à l'avance.
// Pour que cela puisse fonctionner correctement avec les autres displays, il faut qu'on
// lui precise sa preferred size.
// On met sa longueur à 0 pour éviter les élargissements infinis lors des différents retaillages
// dus aux désiconifications.
displayBar = (SymbolDisplay) displayToLay.getComponent(0);
bar = (Bar) displayBar.getSymbol();
bar.setWidth(0);
bar.setHeight(FontInfo.getLineThickness(displayToLay, displayToLay.getFont())); // la hauteur fixe aussi ascent et descent
displayBar.setComputeAttributes(true);
displayBar.setShiftY(2);
// On calcule les attributs des display enfants comme si
// on avait affaire à un VerticalCenteredLayout
Dimension dim = super.computeAttributes();
// La différence réside en le calcul supplémentaire de la taille de la
// barre que l'on ne peut fixer après avoir calculé la largeur de l'argument
bar.setWidth(dim.width + 2);
displayBar.setSize(bar.getSize());
displayToLay.setAscent(((Display) displayToLay.getComponent(0)).getShiftY() +
((Display) displayToLay.getComponent(0)).getHeight() +
((Display) displayToLay.getComponent(1)).getShiftY() +
((Display) displayToLay.getComponent(1)).getAscent());
displayToLay.setDescent(displayToLay.getHeight() - displayToLay.getAscent());
displayToLay.setSize(dim);
 
displayToLay.setComputeAttributes(false);
return dim;
}
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
SymbolDisplay bar = new SymbolDisplay(displayToLay.getGraphicContext(), new Bar());
// Le display de la barre est le display d'un opérateur (on peut le considérer comme tel)
bar.setIsSymbolOperatorDisplay(true);
return bar;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/IconDisplay.java
0,0 → 1,87
/*
$Id: IconDisplay.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* The display of a symbol.
*
* @author © 2000 DIRAT Laurent
* @version 2.0 05/01/2000
*/
public class IconDisplay extends SymbolDisplay {
/**
* The constructor.<BR>
* Instanciate a new display, with no displayable symbol associated. The symbol has to be set
* by hand.
* @param graphicContext the graphic context of the display.
*/
public IconDisplay(GraphicContext graphicContext) {
super(graphicContext);
IconLayout layout = new IconLayout();
layout.initDisplay(this);
setLayout(layout);
}
/**
* Builds the display of the formula tree structure.<BR>
* This method has to be called when a formula tree structure has been created and the
* displays have not been associated yet.<BR>
* As a prerequesit, the instance which call this method MUST have a corresponding instance
* (a listener) in the formula tree structure (i.e. the formula tree structure we want to display).<BR>
*
public void buildDisplay() {
Display childDisplay;
FormulaTreeStructure ftsChild;
Icon fts;
int count;
SubstitutedDisplayManager iconLM = (SubstitutedDisplayManager) getLayout();
// On récupère l'élément de la FTS donc l'instance est le display.
fts = (Icon) getListener();
if (fts != null) { // Bon malgrè le prérequis, on fait le test quand même
count = fts.getNbIconified();
// On parcourre la liste des fils de la fts, pour leur associer le display qui va bien
for (int i = 0; i < count; i++) {
ftsChild = (FormulaTreeStructure) fts.getIconified(i);
// Allocation du display
childDisplay = getDisplayAllocator().allocateDisplay(getGraphicContext(), ftsChild);
// On ajoute le nouveau display dans la liste des displays iconifiés
iconLM.addSubstitutedDisplay(childDisplay);
// On descend dans la fts pour poursuivre la construction des display
childDisplay.buildDisplay();
}
}
}
*/
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SlotLayout.java
0,0 → 1,167
/*
$Id: SlotLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays the display of a slot.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 22/07/1999
*/
public class SlotLayout extends DisplayLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
updateLevel(displayToLay.getLevel());
Display display = (Display) displayToLay.getComponent(0);
display.setSize(display.getPreferredSize());
int width = display.getShiftX() + display.getWidth();
int height = display.getShiftY() + display.getHeight();
 
displayToLay.setAscent(display.getShiftY() + display.getAscent());
displayToLay.setDescent(height - display.getAscent());
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
return new Dimension(width , height);
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
Display childDisplay = (Display) displayToLay.getComponent(0);
if (childDisplay.isSelected()) {
displayToLay.setSelected();
SelectionEvent selEvt = new SelectionEvent(displayToLay);
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute notre puissance.
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
// Puisque le slot n'est juste qu'un display ne possédant aucune propriété particulière,
// sa sélection est automatiquement valide, on regarde au niveau de son père.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null) // Si fts est la racine de la formule alors la sélection à déjà été validée
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
SelectionEvent selEvt = new SelectionEvent(father);
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
//if (!(display.getListener() instanceof Formula))
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null) // Si fts est la racine de la formule alors la désélection à déjà été validée
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
 
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
 
// ***************************************************
// *** Implémentation de l'interface LayoutManager ***
 
 
/*
* Lays out the container in the specified panel.
* @param parent the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
// Ca c'est parce que c'est le layout manager de la formule. Et comme personne ne dit au container
// contenant la formule, que la taille de la formule a besoin d'être recalculée, il faut bien le
// faire qque part. Chaque display informe son père qu'il doit être recalculé, mais la formule ne
// le fait pas pour le sien.
parent.setSize(parent.getPreferredSize());
 
Display display = (Display) parent.getComponent(0);
display.setSize(display.getPreferredSize());
display.setLocation(display.getShiftX(), display.getShiftY());
 
// On place maintenant les éventuels display enfants du display courant
display.doLayout();
}
 
// *** Fin de l'interface LayoutManager ***
// ****************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/IntervalLayout.java
0,0 → 1,185
/*
$Id: IntervalLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
import fr.ove.utils.FontInfo;
 
/**
* Temporaire
*
* @author © 1999 DIRAT Laurent
* @version 2.0 06/09/1999
*/
public class IntervalLayout extends EnclosingLayout {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay); // Par cet appel, on ajoute dans displayToLay les crochets
// On va maintenant y rajouter un display, dans lequel on va mettre les displays correspondants
// aux bornes de l'intervalle, display à qui on va affecter un SeparatorOperatorLayout, qui va se charger
// d'afficher entre chacun des éléments une virgule (un séparateur)
Display boundsDisplay = new BidimDisplay(displayToLay.getGraphicContext());
// On met un listener à boundsDisplay
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
boundsDisplay.addControlListener((FormulaTreeStructure) displayToLay.getListener());
SeparatorOperatorLayout layout = new SeparatorOperatorLayout();
layout.initDisplay(boundsDisplay);
boundsDisplay.setLayout(layout);
// On l'ajoute comme fils à display
this.displayToLay.add(boundsDisplay);
}
/**
* Returns the opening
*/
public SymbolDisplay createOpening() {
// On récupère le fts associé (listener) au display.
KaryOperator fts = (KaryOperator) displayToLay.getListener();
SymbolDisplay bracket = new SymbolDisplay(displayToLay.getGraphicContext(),
new SquaredBracketSymbol(fts.getTheOperator(), displayToLay));
// Le display de l'accolade est le display d'un opérateur (on peut le considérer comme tel)
bracket.setIsSymbolOperatorDisplay(true);
return bracket;
}
/**
* Returns the closing
*/
public SymbolDisplay createClosing() {
// On récupère le fts associé (listener) au display.
KaryOperator fts = (KaryOperator) displayToLay.getListener();
SymbolDisplay bracket = new SymbolDisplay(displayToLay.getGraphicContext(),
new SquaredBracketSymbol(fts.getEnding(), displayToLay));
// Le display de l'accolade est le display d'un opérateur (on peut le considérer comme tel)
bracket.setIsSymbolOperatorDisplay(true);
return bracket;
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Display display = null;
if (displayToLay.getComponentCount() > 3) {
Display boundsDisplay = (Display) displayToLay.getComponent(2);
Display d;
for (int i = 3; i < displayToLay.getComponentCount(); ) {
d = (Display) displayToLay.getComponent(i);
// elementsDisplay.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
boundsDisplay.add(d);
// On remet le comportement de suppression par défault.
d.setDoRemoveFromListListeners(true);
}
}
SymbolDisplay leftBracket = (SymbolDisplay) displayToLay.getComponent(0);
SquaredBracketSymbol leftSymbol = (SquaredBracketSymbol) leftBracket.getSymbol();
SymbolDisplay rightBracket = (SymbolDisplay) displayToLay.getComponent(1);
SquaredBracketSymbol rightSymbol = (SquaredBracketSymbol) rightBracket.getSymbol();
// On met la hauteur à 0, pour que dans tous les cas, le super.computeAttributes() ne soit pas
// biaisée par une éventuelle nouvelle taille des éléments qui composent la liste.
// Comme c'est plus loin qu'on leur fixe la taille....
leftSymbol.setHeight(0);
rightSymbol.setHeight(0);
Dimension dim = super.computeAttributes();
// Par contre, par rapport à comment est calculée la taille des accolades, dim comprend
// déjà la taille des accolades
int ascent = displayToLay.getAscent();
int descent = displayToLay.getDescent();
int height = displayToLay.getHeight();
int thickness = FontInfo.getLineThickness(displayToLay, displayToLay.getFont());
leftSymbol.setAscent(ascent);
leftSymbol.setDescent(descent);
leftSymbol.setHeight(height);
leftSymbol.setThickness(thickness);
leftBracket.setComputeAttributes(true);
leftBracket.invalidate();
leftBracket.setSize(leftBracket.getPreferredSize());
 
rightSymbol.setAscent(ascent);
rightSymbol.setDescent(descent);
rightSymbol.setHeight(height);
rightSymbol.setThickness(thickness);
rightBracket.setComputeAttributes(true);
rightBracket.invalidate();
rightBracket.setSize(rightBracket.getPreferredSize());
// Cette taille là correspond au décalage qu'il faut appliquer à la dernière accolade
rightBracket.setShiftX(dim.width - 2*rightBracket.getWidth());
// Mais il faut l'enlever au premier terme de la liste qui doit être contre la première
// accolade (because HonrizontalLayout)
((Display) displayToLay.getComponent(2)).setShiftX(-rightBracket.getShiftX() - rightBracket.getWidth());
return dim;
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/FunctionLayout.java
0,0 → 1,139
/*
$Id: FunctionLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager for rendering functions.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 17/12/1999
*/
public class FunctionLayout extends UnaryOperatorLayout {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay); // Par cet appel, on ajoute dans displayToLay le display du nom de la fonction
// On va maintenant y rajouter un display, dans lequel on va mettre tous les displays correspondants
// aux arguments de la fonction, display à qui on va affecter un EnumerationOperatorLayout, qui va se charger
// d'afficher les arguments de la function de manière horizontale avec chacun des arguments séparés par une
// virgule (un séparateur)
Display argumentsDisplay = new BidimDisplay(displayToLay.getGraphicContext());
// On met un listener à argumentsDisplay
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
argumentsDisplay.addControlListener((FormulaTreeStructure) this.displayToLay.getListener());
EnumerationLayout layout = new EnumerationLayout();
layout.initDisplay(argumentsDisplay);
argumentsDisplay.setLayout(layout);
// On l'ajoute comme fils à display
this.displayToLay.add(argumentsDisplay);
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
updateLevel(displayToLay.getLevel());
if (displayToLay.getComponentCount() > 2) {
// Dans l'ordre, displayToLay contient [displayOperator, argumentsDisplay, var1, var2, ...]
// Il faut mettre tous les vari dans argumentsDisplay.
Display argumentsDisplay = (Display) displayToLay.getComponent(1);
Display d;
for (int i = 2; i < displayToLay.getComponentCount(); ) {
d = (Display) displayToLay.getComponent(i);
// argumentsDisplay.add(d) appelle un displayToLay.remove(d).
// remove(d), enlève également d de la liste des listeners de l'objet (fts) qu'il écoutait.
// Ce qu'on ne veut pas, puisqu'il s'agit d'un simple déplacement de display.
d.setDoRemoveFromListListeners(false);
argumentsDisplay.add(d);
// On remet le comportement de suppression par défault.
d.setDoRemoveFromListListeners(true);
}
}
return super.computeAttributes();
}
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
Operator fts = (Operator) displayToLay.getListener();
// On créé un display pour l'opérateur.
// Attention, fts.getOperatorName() retourne le nom de la fonction, mais "(" y est collée.
// Il faut donc la supprimer.
String funcName = fts.getTheOperator();
funcName = funcName.substring(0, funcName.length()-1);
StringDisplay stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), funcName, true);
stringDisplay.setIsSymbolOperatorDisplay(true);
return stringDisplay;
/*
Display operatorDisplay;
if (ImageLoader.exists(funcName)) {
SpecialSymbolView symbolOperator = new SpecialSymbolView(funcName, displayToLay);
operatorDisplay = new SymbolDisplay(displayToLay.getGraphicContext(), symbolOperator);
operatorDisplay.setIsSymbolOperatorDisplay(true);
}
else
operatorDisplay = new StringDisplay(displayToLay.getGraphicContext(), funcName, true);
return operatorDisplay;
// En fait, si au nom de la fonction est associée une image (e.g. alpha), alors le nom de la func
// est représenté par l'image.
*/
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/CurlySymbol.java
0,0 → 1,171
/*
$Id: CurlySymbol.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.awt.image.ImageObserver;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.images.ImageLoader;
 
 
/**
* The curly bracket.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 19/07/1999
*/
public class CurlySymbol extends DisplayableImpl {
/**
* The initial images which are parts of the representation of the curly bracket.<BR>
* The curly bracket is made of 4 parts : top, middle, bottom and bar.<BR>
* The top, middle and bottom are unique during the rendering, and according to the height of the
* bracketted display, mutiple instance of the bar are displayed to give the right size
* to the curly bracket.
*/
private Image topInit;
private Image middleInit;
private Image bottomInit;
private Image barInit;
/**
* The scale images of the initials ones.
*/
private Image top;
private Image middle;
private Image bottom;
private Image bar;
/**
* The height of the top and the bottom of the symbol.
*/
private int heightExtremities;
/**
* Object to be notified as more of the image is converted.
*/
ImageObserver observer;
/**
* The constructor.
* @param isLeftBracket <CODE>true<CODE> if the instance represents a left bracket. <CODE>false</CODE>
* otherwise.
* @param heightExtremities the height of the extremities of the bracket.
* @param observer the object to be notified as more of the image is converted.
*/
public CurlySymbol(boolean isLeftBracket, int heightExtremities, ImageObserver observer) {
if (isLeftBracket) {
topInit = ImageLoader.getImage("LeftTopCurl");
middleInit = ImageLoader.getImage("LeftMiddleCurl");
bottomInit = ImageLoader.getImage("LeftBottomCurl");
barInit = ImageLoader.getImage("LeftBarCurl");
}
else {
topInit = ImageLoader.getImage("RightTopCurl");
middleInit = ImageLoader.getImage("RightMiddleCurl");
bottomInit = ImageLoader.getImage("RightBottomCurl");
barInit = ImageLoader.getImage("RightBarCurl");
}
 
this.heightExtremities = heightExtremities;
this.observer = observer;
}
/**
* The paint method of the object to display.
* @param g the drawing area of the symbol.
*/
public void paint(Graphics g) {
int height = getHeight();
// On dessine la partie supérieure de l'accolade
g.drawImage(top, 3, 0, observer);
// On dessine les "barres", i.e. la partie que l'on va faire croitre pour ajuster correctement
// la taille de l'accolade
for (int i = heightExtremities; i < height - heightExtremities; i += heightExtremities)
g.drawImage(bar, 3, i, observer);
// On dessine la partie inférieure de l'accolade
g.drawImage(bottom, 3, height - heightExtremities, observer);
// On dessine la partie centrale de l'accolade
// On essaie de faire en sorte que le milieu de l'accolade se trouve un peu au dessus de la baseline
// Par exemple, aligné avec le +. La barre horizontale du + se trouve grosso modo à la moitié de
// son ascent. Il se trouve que c'est la hauteur de middle.
g.drawImage(middle, 3, getAscent() - middle.getHeight(observer), observer);
}
/**
* Returns the preferred size of the display.
*/
public Dimension getPreferredSize() {
MediaTracker tracker = new MediaTracker((Component) observer);
// La hauteur de la partie du milieu est égale à environ 2 fois les extrémités.
// Le -1 signifie que la largeur sera proportionnelle à la hauteur.
top = topInit.getScaledInstance(-1, heightExtremities, Image.SCALE_SMOOTH);
tracker.addImage(top, 0);
middle = middleInit.getScaledInstance(-1, heightExtremities*2, Image.SCALE_SMOOTH);
tracker.addImage(middle, 0);
bottom = bottomInit.getScaledInstance(-1, heightExtremities, Image.SCALE_SMOOTH);
tracker.addImage(bottom, 0);
bar = barInit.getScaledInstance(-1, heightExtremities, Image.SCALE_SMOOTH);
tracker.addImage(bar, 0);
// On attend que toutes les images soient chargées.
try { tracker.waitForAll(); }
catch (InterruptedException e) {
System.out.println(e.toString());
}
tracker.removeImage(top);
tracker.removeImage(middle);
tracker.removeImage(bottom);
tracker.removeImage(bar);
 
return new Dimension(top.getWidth(observer) + 6, getHeight());
}
/**
* Sets the graphic context in which the object is.
* @param graphicContext the object graphic context.
* Actually, this methods gives information to the object, notably when its preferred
* size is required. If the context has changed, the displayable object must be informed.
* However, in the most part of the time, the whole graphic context won't be necessary to
* be stored, but only specific and usefull data.
*/
public void setGraphicContext(GraphicContext graphicContext) {
super.setGraphicContext(graphicContext);
// Surcharge de cette méthode pour que l'on puisse récupérer en fonction du contexte graphique
// du symbole, la hauteur des extrémité de l'accolade.
FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(graphicContext.getFont());
heightExtremities = fm.getHeight() / 4;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/IconLayout.java
0,0 → 1,86
/*
$Id: IconLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.Vector;
import fr.ove.openmath.jome.ctrlview.bidim.SymbolDisplay;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.SubstitutedDisplayManager;
 
/**
* A layout manager for the display of of an icon
*
* @author © 1999 DIRAT Laurent
* @version 2.0 19/07/1999
*/
public class IconLayout extends SymbolLayout implements SubstitutedDisplayManager {
/**
* The list of the displays that have been substituted.
*/
private Vector substitutedDisplay = new Vector();
/*
* Adds an substituted display to the list.
*/
public void addSubstitutedDisplay(Display display) {
substitutedDisplay.addElement(display);
}
/*
* Removes a substituted display to the list.
* @param display the display to remove.
*/
public void removeSubstitutedDisplay(Display display) {
substitutedDisplay.removeElement(display);
}
/*
* Removes a substituted display at the specified rank to the list.
* @param rank the specified rank.
*/
public void removeSubstitutedDisplay(int rank) {
substitutedDisplay.removeElementAt(rank);
}
/**
* Returns the substituted display at the specified rank.
* @param rank the specified rank.
*/
public Display getSubstitutedDisplay(int rank) {
return (Display) substitutedDisplay.elementAt(rank);
}
/**
* Returns the number of substituted displays.
*/
public int getNbSubstitutedDisplay() {
return substitutedDisplay.size();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/RequestLayout.java
0,0 → 1,278
/*
$Id: RequestLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
*
* @author © 1999 DIRAT Laurent
* @version 2.0 17/12/1999
*/
public class RequestLayout extends HorizontalLayout {
/**
* Do we need to insert separator display ?
*/
private boolean insertSeparatorDisplay = true;
/**
* The number of the components al ready present before an other insertion
* or removal. This is necessary to keep in mind this, in order to know if
* we must parse the list of components to check if we have to insert symbol
* display or not.
*/
private int prevNbComponent = 0;
private String opeSymbol;
private Display displaySlot = null;
/**
* Inserts, if necessary, a display of the operator symbol that the display
* laid by the instance represents.
*/
public void insertOperatorDisplay() {
Display current, next;
FormulaTreeStructure fatherFts = (FormulaTreeStructure) displayToLay.getListener();
FormulaTreeStructure fts;
StringDisplay stringDisplay;
int nbComponent = displayToLay.getComponentCount();
if (nbComponent > 1) {
if (fatherFts.getResourceIdentifier().equals("request"))
opeSymbol = new String(" with ");
else
opeSymbol = new String(" if ");
stringDisplay = new StringDisplay(displayToLay.getGraphicContext(), opeSymbol, true);
stringDisplay.addControlListener(fatherFts);
displayToLay.add(stringDisplay, stringDisplay, 1);
nbComponent++;
}
// Mise à jour du nombre de components présents dans le display.
prevNbComponent = displayToLay.getComponentCount();
// On n'a plus besoin d'insérer des displays d'opérateur.
insertSeparatorDisplay = false;
// On a rajouté un display, on demande le recalcul de tous les ancêtres
// de l'instance.
displayToLay.computeAncestorsAttributes();
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int ascent = 0;
int descent = 0;
//Always add the container's insets!
Insets insets = displayToLay.getParent().insets();
int width = insets.left + insets.right;
int height = insets.top + insets.bottom;
Display tmp;
int count = displayToLay.getComponentCount();
Slot slot;
Constant cte;
int stop = 2;
if (count == 1) {
if (displaySlot != null) {
slot = (Slot) displaySlot.getListener();
if (slot.getChild(0) instanceof Constant) {
cte = (Constant) slot.getChild(0);
if (!cte.isTemplate()) {
displayToLay.add(displaySlot);
stop = 2;
}
}
else
stop = 1;
}
}
else if (count == 2) {
displaySlot = (Display) displayToLay.getComponent(1);
slot = (Slot) displaySlot.getListener();
if (slot.getChild(0) instanceof Constant) {
cte = (Constant) slot.getChild(0);
if (cte.isTemplate()) {
displayToLay.remove(displaySlot);
stop = 1;
}
}
else
stop = 2;
}
// On regarde si le nombre de component dans le display a chnagé depuis
// la dernière fois. Si oui, il faut contrôler s'il ne faut pas ajouter
// des display d'opérateur.
if (insertSeparatorDisplay || (prevNbComponent != ((Display) displayToLay).getComponentCount()))
insertOperatorDisplay();
updateLevel(displayToLay.getLevel());
count = displayToLay.getComponentCount();
stop = (count > 1) ? 2 : 1;
// Ca va de la condition au with ou if selon le type
for (int i = 0; i < stop; i++) {
tmp = (Display) displayToLay.getComponent(i);
tmp.setSize(tmp.getPreferredSize());
width += tmp.getWidth() + tmp.getShiftX();
ascent = Math.max(tmp.getAscent() - tmp.getShiftY(),
ascent);
descent = Math.max(tmp.getDescent() + tmp.getShiftY(),
descent);
}
if (count == 3) {
tmp = (Display) displayToLay.getComponent(2);
tmp.setSize(tmp.getPreferredSize());
height = (int) Math.max(((Display) displayToLay.getComponent(0)).getHeight(),
((Display) displayToLay.getComponent(2)).getHeight());
width += tmp.getWidth() + tmp.getShiftX();
displayToLay.setAscent(Math.max( ((Display) displayToLay.getComponent(0)).getAscent(),
((Display) displayToLay.getComponent(2)).getAscent() ));
}
else {
height = ((Display) displayToLay.getComponent(0)).getHeight();
int shiftY = ((Display) displayToLay.getComponent(0)).getDescent();
//count = displayToLay.getComponentCount();
for (int i = 2; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
tmp.setSize(tmp.getPreferredSize());
if (i == 2) {
if (count > 3) {
// On fait en sorte que cet élément commence à 20 pixels du bord gauche du display le contenant
tmp.setShiftX(-width + 20 );
shiftY += tmp.getAscent()+ 10;
tmp.setShiftY(shiftY);
}
else
width += tmp.getWidth();
}
else {
tmp.setShiftX(-((Display) displayToLay.getComponent(i-1)).getWidth());
shiftY += ((Display) displayToLay.getComponent(i-1)).getDescent() + tmp.getAscent()+ 5;
tmp.setShiftY(shiftY);
}
width = Math.max(width, 20 + tmp.getWidth());
if (i == (count - 1))
height = shiftY + tmp.getHeight();
}
displayToLay.setAscent(Math.max( 0, ((Display) displayToLay.getComponent(0)).getAscent() ));
}
displayToLay.setSize(width , height);
displayToLay.setDescent(height - displayToLay.getAscent());
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
 
/*
* Lays out the container in the specified panel.
* @param parent the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
// On regarde si le nombre de component dans le display a chnagé depuis
// la dernière fois. Si oui, il faut contrôler s'il ne faut pas ajouter
// des display d'opérateur.
if (insertSeparatorDisplay || (prevNbComponent != ((Display) parent).getComponentCount()))
insertOperatorDisplay();
super.layoutContainer(parent);
}
 
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
Display tmp;
int nbDisplay = ((FormulaTreeStructure) displayToLay.getListener()).getNbChildren();
Display listDisplay[] = new Display[nbDisplay];
for (int i = 0; i < displayToLay.getComponentCount(); i++) {
tmp = (Display) displayToLay.getComponent(i);
if (!tmp.isSymbolOperatorDisplay()) {
// A voir !!!!!
// Mais il semblerai que bon, sinon à la (re)construction du display il se base
// sur des anciennes valeurs, et donc pas tarrible niveau affichage.
tmp.setLocation(0, 0);
listDisplay[((FormulaTreeStructure) tmp.getListener()).getRank()] = tmp;
}
}
// ATTENTION : ici, on enlève les displays fils de display, mais on ne les enlève pas de la liste
// des listeners de la fts qu'il sont en train d'écouter. Exception faite pour les displays d'opérateur.
displayToLay.removeAllDisplays();
for (int i = 0; i < nbDisplay; i++)
displayToLay.add(listDisplay[i]);
// On a reconstruit le display, il faut maintenant insérer les displays d'opérateur.
insertSeparatorDisplay = true;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/InfixOperatorLayout.java
0,0 → 1,160
/*
$Id: InfixOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.util.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components horizontally and inserts between
* them, the display of the operator that the layout manager lays.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public abstract class InfixOperatorLayout extends HorizontalLayout implements OperatorDisplayCreator {
/**
* Do we need to insert an operator display ?
*/
protected boolean insertOperatorDisplay = true;
/**
* The number of the components already present before an other insertion
* or removal. This is necessary to keep in mind this, in order to know if
* we must parse the list of components to check if we have to insert symbol
* display or not.
*/
protected int prevNbComponent = 0;
/**
* Inserts a display of the operator symbol that the display
* laid by the instance represents.
*/
protected void insertOperatorDisplay() {
Display current, next, displayOperator;
FormulaTreeStructure fatherFts = (FormulaTreeStructure) displayToLay.getListener();
FormulaTreeStructure fts;
int nbComponent = displayToLay.getComponentCount();
// On parcourre tous les components présents dans le display.
for (int i = 1; i < nbComponent; i++) {
// la référence sur le component courant
current = (Display) displayToLay.getComponent(i - 1);
// la référence sur le suivant
next = (Display) displayToLay.getComponent(i);
// Si le courant est un display d'opérateur alors on continue
if (current.isSymbolOperatorDisplay())
continue;
// Si le suivant n'est pas un display d'opérateur alors 2 cas
if (!next.isSymbolOperatorDisplay()) {
// On ajoute un display d'opérateur.
displayOperator = createOperatorDisplay();
displayToLay.add(displayOperator, displayOperator, i);
// On met un listener à l'opérateur.
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
displayOperator.addControlListener(fatherFts);
i++;
nbComponent++;
}
}
// Mise à jour des rangs des displays
displayToLay.adjustRank();
// Mise à jour du nombre de components présents dans le display.
prevNbComponent = displayToLay.getComponentCount();
// On n'a plus besoin d'insérer des displays d'opérateur.
insertOperatorDisplay = false;
// On fait en sorte que la mise à niveau des displays (opérateurs) soit faite.
displayToLay.setUpdateLevel(true);
// On a rajouté un display, on demande le recalcul de tous les ancêtres
// de l'instance.
displayToLay.computeAncestorsAttributes();
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
// On regarde si le nombre de component dans le display a changé depuis
// la dernière fois. Si oui, il faut contrôler s'il ne faut pas ajouter
// des display d'opérateur.
if (insertOperatorDisplay || (prevNbComponent != displayToLay.getComponentCount()))
insertOperatorDisplay();
return super.computeAttributes();
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
Display tmp;
int nbDisplay = ((FormulaTreeStructure) displayToLay.getListener()).getNbChildren();
Display listDisplay[] = new Display[nbDisplay];
int count = displayToLay.getComponentCount();
for (int i = 0; i < count; i++) {
tmp = (Display) displayToLay.getComponent(i);
if (!tmp.isSymbolOperatorDisplay()) {
// A voir !!!!!
// Mais il semblerai que bon, sinon à la (re)construction du display il se base
// sur des anciennes valeurs, et donc pas terrible niveau affichage.
tmp.setLocation(0, 0);
listDisplay[((FormulaTreeStructure) tmp.getListener()).getRank()] = tmp;
}
}
// ATTENTION : ici, on enlève les displays fils de display, mais on ne les enlève pas de la liste
// des listeners de la fts qu'il sont en train d'écouter. Exception faite pour les displays d'opérateur.
displayToLay.removeAllDisplays();
for (int i = 0; i < nbDisplay; i++)
displayToLay.add(listDisplay[i]);
// On a reconstruit le display, il faut maintenant insérer les displays d'opérateur.
insertOperatorDisplay = true;
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/UnderOperatorLayout.java
0,0 → 1,72
/*
$Id: UnderOperatorLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of the operator whose symbol is located under its operand
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public abstract class UnderOperatorLayout extends SuperposedOperatorLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
// La différence réside dans le fait qu'il faut faire en sorte que le display de l'opérateur soit affiché
// en dessous de l'opérande
Dimension dim = super.computeAttributes();
Display displayOperator = (Display) displayToLay.getComponent(0);
Display operand = (Display) displayToLay.getComponent(1);
int ascent = operand.getAscent();
displayToLay.setAscent(ascent);
displayToLay.setDescent(dim.height - ascent);
 
// Cette taille là correspond au décalage qu'il faut appliquer à la barre de fraction
displayOperator.setShiftY(operand.getHeight());
// Mais il faut l'enlever au display du numérateur
operand.setShiftY(-displayOperator.getShiftY() - displayOperator.getHeight());
displayToLay.setComputeAttributes(false);
return dim;
 
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SymbolDisplay.java
0,0 → 1,158
/*
$Id: SymbolDisplay.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.Displayable;
import fr.ove.openmath.jome.ctrlview.bidim.SymbolLayout;
 
/**
* The display of a symbol.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 09/07/1999
*/
public class SymbolDisplay extends BidimDisplay {
/**
* the symbol to display.
*/
private Displayable symbol;
/**
* The constructor.
* @param graphicContext the graphic context of the display.
* @param symbol The displayable symbol of the display.
*/
public SymbolDisplay(GraphicContext graphicContext, Displayable symbol) {
this(graphicContext);
this.symbol = symbol;
symbol.setGraphicContext(graphicContext);
}
/**
* The constructor.<BR>
* Instanciate a new display, with no displayable symbol associated. The symbol has to be set
* by hand.
* @param graphicContext the graphic context of the display.
*/
public SymbolDisplay(GraphicContext graphicContext) {
super(graphicContext);
SymbolLayout layout = new SymbolLayout();
layout.initDisplay(this);
setLayout(layout);
}
/**
* Sets a new symbol to the display.
* @param symbol the symbol to set.
*/
public void setSymbol(Displayable symbol) {
this.symbol = symbol;
symbol.setGraphicContext(getGraphicContext());
}
/**
* Returns the symbol which is in the dispay.
*/
public Displayable getSymbol() {
return symbol;
}
 
/**
* Paints the display.
* @param g where we paint the display.
*/
public void paint(Graphics g) {
super.paint(g);
Color old = g.getColor();
Rectangle bounds = getBounds();
if (isSelected()) {
g.setColor(getSelectionColor());
g.fillRect(0, 0, bounds.width - 1, bounds.height - 1);
}
g.setColor(getForegroundColor());
if (weDrawBounds())
g.drawRect(0, 0, bounds.width - 1, bounds.height - 1);
symbol.paint(g);
g.setColor(old);
}
/**
* Scales the display.
*/
public void scaleDisplay() {
setTheFont(getGraphicContext().scaleFont(getLevel()));
// Il faut que le layout manager recalcule les attributs du display.
setComputeAttributes(true);
// Ceci est nécessaire pour que ce soit le layout manager qui retourne
// la preferredSize du display, et donc qu'il y ait recalcul des attributs.
// Sinon, le container considère qu'il a une taille valide, et donc retourne
// comme preferredSize, la précédente, sans qu'il demande le recalcul au LM.
invalidate();
// On affecte au symbol le nouveau contexte graphique du display, en fait la réduction de font
// effectuée.
// On fait ce test à cause de la construction. Quand on construit le display, on fait un scaleDisplay.
// (au niveau de Display) Or, scaleDisplay (de l'instance donc), est applelé avant que le symbole ne soit
// affecté dans leconstructeur.
if (symbol != null)
symbol.setGraphicContext(getGraphicContext());
}
/**
* Sets all the attributes.
* @param ascent the new ascent value.
* @param descent the new descent value.
* @param shiftX the new horizontal shift value.
* @param shiftY the new vertical shift value.
*/
public void setAttributes(int ascent, int descent, int shiftX, int shiftY) {
super.setAttributes(ascent, descent, shiftX, shiftY);
symbol.setAscent(ascent);
symbol.setDescent(descent);
symbol.setShiftX(shiftX);
symbol.setShiftY(shiftY);
}
/**
* Sets the graphic context of the instance.
* @param graphicContext the graphic context.
*/
public void setGraphicContext(GraphicContext graphicContext) {
super.setGraphicContext(graphicContext);
symbol.setGraphicContext(graphicContext);
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/StringDisplay.java
0,0 → 1,146
/*
$Id: StringDisplay.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import fr.ove.utils.NumberUtils;
import fr.ove.openmath.jome.ctrlview.bidim.StringLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.GraphicContext;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The display for variables and numbers.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 04/08/1999
*/
public class StringDisplay extends AbstractStringDisplay {
/**
* The constructor.
* @param graphicContext the graphic context of the display.
* @param string the string to display
* @param isSymbolOperatorDisplay <CODE>true</CODE> if the instance is the display of an operator.
* <CODE>false</CODE> otherwise.
*/
public StringDisplay(GraphicContext graphicContext, String string, boolean isSymbolOperatorDisplay ) {
super(graphicContext, string);
setIsSymbolOperatorDisplay(isSymbolOperatorDisplay);
StringLayout layout = new StringLayout();
layout.initDisplay(this);
setLayout(layout);
addMouseListener(
new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
if (!isSymbolOperatorDisplay()) {
if (getListener() instanceof VariableOrNumber) {
VariableOrNumber listener = (VariableOrNumber) getListener();
if (listener.isNumber() && !listener.isInteger()) {
// On a affaire à un float
String value = listener.getValue();
//if (!value.equals(StringDisplay.this.getString())) {
if (!value.equals(getString())) {
setString(value);
invalidate();
computeAncestorsAttributes();
Container container = StringDisplay.this;
while (container.getParent() != null)
container = container.getParent();
container.validate();
container.repaint();
}
}
}
}
}
public void mouseExited(MouseEvent e) {
if (!isSymbolOperatorDisplay()) {
if (getListener() instanceof VariableOrNumber) {
VariableOrNumber listener = (VariableOrNumber) getListener();
if (listener.isNumber() && !listener.isInteger()) {
// On a affaire à un float
String value = listener.getValue();
String newString = NumberUtils.formatDouble(value);
if (!newString.equals(value)) {
setString(newString);
StringDisplay.this.invalidate();
StringDisplay.this.computeAncestorsAttributes();
Container container = StringDisplay.this;
while (container.getParent() != null)
container = container.getParent();
container.validate();
container.repaint();
}
}
}
}
}
}
);
}
/**
* Consumes (i.e. treats) the event received from the model.
* @param modelEvent the event to consume.
*/
public void consumeModelEvent(ModelEvent modelEvent) {
// En principe, c'est le seul événement que doit recevoir ce type de display
// De plus, forcément, le display représenté n'est pas le display d'un opérateur.
switch (modelEvent.getAction()) {
case ModelEvent.UPDATE :
//System.out.println("ModelEvent.UPDATE : on update le StringDisplay");
VariableOrNumber src = (VariableOrNumber) modelEvent.getSource();
// On met à jour le display.
// Ca c'est pour la troncature de l'affichage d'une nombre flottant dépassant
// 2 chiffres après la virgule
if (!isSymbolOperatorDisplay()) {
if (src.isNumber() && !src.isInteger())
// On a affaire à un float
setString(NumberUtils.formatDouble(src.getValue()));
else
setString(src.getValue());
}
else
setString(src.getValue());
 
computeAncestorsAttributes();
invalidate();
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SquaredBracketLayout.java
0,0 → 1,62
/*
$Id: SquaredBracketLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
 
/**
* A layout manager that lays components to be displayed between squared brackets.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public class SquaredBracketLayout extends EnclosingLayout {
/**
* Returns the opening
*/
public SymbolDisplay createOpening() {
SymbolDisplay bracket = new SymbolDisplay(displayToLay.getGraphicContext(),
new SquaredBracketSymbol("[", displayToLay));
// Le display du crochet est le display d'un opérateur (on peut le considérer comme tel)
bracket.setIsSymbolOperatorDisplay(true);
return bracket;
}
/**
* Returns the closing
*/
public SymbolDisplay createClosing() {
SymbolDisplay bracket = new SymbolDisplay(displayToLay.getGraphicContext(),
new SquaredBracketSymbol("]", displayToLay));
// Le display du crochet est le display d'un opérateur (on peut le considérer comme tel)
bracket.setIsSymbolOperatorDisplay(true);
return bracket;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ImageBinaryInfixOperatorLayout.java
0,0 → 1,63
/*
$Id: ImageBinaryInfixOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager for a binary infix operator which symbol can be rendered as an image (e.g. the in operator which
* rendered as a kind of big E, which will be an image)
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public class ImageBinaryInfixOperatorLayout extends BinaryInfixOperatorLayout {
/**
* The symbol we have to insert between each component if necessary.
*/
private ImageSymbol symbolOperator = null;
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
if (symbolOperator == null) {
Operator fts = (Operator) displayToLay.getListener();
//symbolOperator = new ImageSymbol(fts.getTheOperator(), displayToLay);
symbolOperator = new ImageSymbol(fts.getResourceIdentifier(), displayToLay);
}
// On créé un display pour l'opérateur.
SymbolDisplay operatorDisplay = new SymbolDisplay(displayToLay.getGraphicContext(), symbolOperator);
operatorDisplay.setIsSymbolOperatorDisplay(true);
return operatorDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/UnderscriptLayout.java
0,0 → 1,96
/*
$Id: UnderscriptLayout.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.HorizontalLayout;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* A layout manager that lays components horyzontally, but the last one in the
* list, is treated as a underscript (there is an downward shitf).
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public class UnderscriptLayout extends ScriptLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
int ascent = 0;
int descent = 0;
int width = 0;
int height = 0;
Display base, indice;
int decalage = 0;
base = (Display) displayToLay.getComponent(0);
base.setSize(base.getPreferredSize());
width += base.getWidth() + base.getShiftX();
indice = (Display) displayToLay.getComponent(1);
 
if (base.getLayout() instanceof UnderscriptLayout)
((DisplayLayout) indice.getLayout()).updateLevel(((Display) base.getComponent(1)).getLevel()+ 1);
else
((DisplayLayout) indice.getLayout()).updateLevel(base.getLevel()+ 1);
indice.setSize(indice.getPreferredSize());
if (base.getLayout() instanceof UnderscriptLayout) {
Display ind_base = (Display) base.getComponent(1);
decalage = ind_base.getDescent() + ind_base.getShiftY();
}
else
decalage = base.getDescent();
 
/* ############################# */
base.setShiftY(0); // ATTENTION : rajout !!!!!!
/* ############################# */
indice.setShiftY(decalage);
width += indice.getWidth() + indice.getShiftX();
displayToLay.setAscent(base.getAscent());
displayToLay.setDescent(decalage + indice.getDescent());
height += displayToLay.getAscent() + displayToLay.getDescent();
displayToLay.setSize(width , height);
displayToLay.setComputeAttributes(false);
return new Dimension(width, height);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/OperatorDisplayCreator.java
0,0 → 1,45
/*
$Id: OperatorDisplayCreator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
 
/**
* The interface to implement for classes that want to create on the fly specific
* operator display.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 14/12/1999
*/
public interface OperatorDisplayCreator {
/**
* Returns the display of an operator
*/
public Display createOperatorDisplay();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/ImagePrefixedUnaryOperatorLayout.java
0,0 → 1,63
/*
$Id: ImagePrefixedUnaryOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.*;
 
/**
* This layout manager lays prefixed unary operators.<BR>
* The symbol of the operator can be rendered as an image
*
* @author © 1999 DIRAT Laurent
* @version 2.0 13/12/1999
*/
public class ImagePrefixedUnaryOperatorLayout extends UnaryOperatorLayout {
/**
* The symbol we have to insert between each component if necessary.
*/
private ImageSymbol symbolOperator = null;
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
if (symbolOperator == null) {
Operator fts = (Operator) displayToLay.getListener();
//symbolOperator = new ImageSymbol(fts.getTheOperator(), displayToLay);
symbolOperator = new ImageSymbol(fts.getResourceIdentifier(), displayToLay);
}
// On créé un display pour l'opérateur.
SymbolDisplay operatorDisplay = new SymbolDisplay(displayToLay.getGraphicContext(), symbolOperator);
operatorDisplay.setIsSymbolOperatorDisplay(true);
return operatorDisplay;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/SubstitutionDisplay.java
0,0 → 1,83
/*
$Id: SubstitutionDisplay.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import fr.ove.utils.NumberUtils;
import fr.ove.openmath.jome.ctrlview.bidim.StringLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.GraphicContext;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The display for subsitution of parts of a expression with frienfly name.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 04/08/1999
*/
public class SubstitutionDisplay extends AbstractStringDisplay {
/**
* The constructor.
* @param graphicContext the graphic context of the display.
* @param string the string to display
*/
public SubstitutionDisplay(GraphicContext graphicContext, String string) {
super(graphicContext, string);
Font font = getFont();
font = new Font(font.getName(), Font.BOLD, font.getSize());
setFont(font);
SubstitutionLayout layout = new SubstitutionLayout();
layout.initDisplay(this);
setLayout(layout);
}
/**
* Consumes (i.e. treats) the event received from the model.
* @param modelEvent the event to consume.
*/
public void consumeModelEvent(ModelEvent modelEvent) {
// En principe, c'est le seul événement que doit recevoir ce type de display
// De plus, forcément, le display représenté n'est pas le display d'un opérateur.
switch (modelEvent.getAction()) {
case ModelEvent.UPDATE :
//System.out.println("ModelEvent.UPDATE : on update le StringDisplay");
Icon src = (Icon) modelEvent.getSource();
// On met à jour le display.
setString(src.getIconName());
 
computeAncestorsAttributes();
invalidate();
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/FractionLayout.java
0,0 → 1,97
/*
$Id: FractionLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.DisplayLayout;
import fr.ove.openmath.jome.ctrlview.bidim.Display;
import fr.ove.openmath.jome.ctrlview.bidim.Bar;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
import fr.ove.utils.FontInfo;
 
/**
* A layout manager that lays components to be displayed as a fraction.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public class FractionLayout extends BetweenOperatorLayout {
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
SymbolDisplay displayBar = null;
Bar fractionBar = null;
updateLevel(displayToLay.getLevel());
// On est dans le cas particulier d'un symbol qui ne connait pas sa taille à l'avance.
// Pour que cela puisse fonctionner correctement avec les autres displays, il faut qu'on
// lui precise sa preferred size.
// On met sa longueur à 0 pour éviter les élargissements infinis lors des différents retaillages
// dus aux désiconifications. (On rajoute 8 pixels à sa largeur un peu plus bas)
displayBar = (SymbolDisplay) displayToLay.getComponent(0);
displayBar.setWidth(0);
fractionBar = (Bar) displayBar.getSymbol();
fractionBar.setWidth(0);
fractionBar.setHeight(FontInfo.getLineThickness(displayToLay, displayToLay.getFont())); // la hauteur fixe aussi ascent et descent
displayBar.setComputeAttributes(true);
// On calcule les attributs des display enfants comme si
// on avait affaire à un VerticalCenteredLayout
Dimension dim = super.computeAttributes();
// La différence réside en le calcul supplémentaire de la taille de la
// de fraction que l'on ne peut fixer après avoir calculé la largeur
// du numérateur et du dénominateur
fractionBar.setWidth(dim.width + 8);
displayBar.setSize(fractionBar.getSize());
dim.width = displayBar.getWidth();
displayToLay.setSize(dim);
return dim;
}
/**
* Returns the display of the operator
*/
public Display createOperatorDisplay() {
SymbolDisplay fractionBar = new SymbolDisplay(displayToLay.getGraphicContext(), new Bar());
// Le display de la barre de fraction est le display d'un opérateur (on peut le considérer comme tel)
fractionBar.setIsSymbolOperatorDisplay(true);
return fractionBar;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/BetweenOperatorLayout.java
0,0 → 1,238
/*
$Id: BetweenOperatorLayout.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.*;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.ctrlview.bidim.selection.events.SelectionEvent;
import fr.ove.openmath.jome.model.*;
 
/**
* Layout manager that lays the display of an operator whose symbol is located between its 2 operands.<BR>
* Rendering is done vertically, the first operand on top, the symbol in the middle and the second operand
* under the 2 previous.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 15/12/1999
*/
public abstract class BetweenOperatorLayout extends VerticalCenteredLayout implements OperatorDisplayCreator {
/**
* According to the operator, the layout manager has to add some components (e.g. brackets, ...)
* or has to perform some "re-oganisation" before rendering.<BR>
* As soon as the layout manager is set to the display, this mehtod MUST be called with the display laid out
* as parameter. This method serves as well as a registering method. So all sub-classes of the instance MUST
* call super.initDisplay(displayToLay).
* @param displayToLay the display laid by the instance
*/
public void initDisplay(Display displayToLay) {
super.initDisplay(displayToLay);
Display operatorDisplay = createOperatorDisplay();
 
// On met un listener au display de l'opérateur
// En fait, il n'y en a pas besoin, dans le sens où il n'y a pas spécifiquement de fts qui
// écoute le comportement de ce display. Néanmoins, il s'avère nécessaire qu'il en ait
// un, par exemple lors de l'iconification, car c'est le display qui reçoit la demande
// d'iconification qui envoie l'événement correspondant à la FTS. Or si ce display n'a pas
// d'écouteur, alors pb. Par cohérence, l'écouteur du display d'opérateur, est le fts qui
// représente cette opération. Par contre, la fts en question, n'écoute pas le display
// d'opérateur.
operatorDisplay.addControlListener((FormulaTreeStructure) displayToLay.getListener());
this.displayToLay.add(operatorDisplay);
}
/**
* Checks the validity of the selection.
*/
public void validateSelection() {
SelectionEvent selEvt = new SelectionEvent(displayToLay);
 
// La validité de la sélection est triviale.
// Si les 2 opérandes sont sélectionnés, ou si le symbole de l'opérateur est sélectionné,
// alors on sélectionne tout.
Display operatorDisplay = (Display) displayToLay.getComponent(0);
Display operand1 = (Display) displayToLay.getComponent(1);
Display operand2 = (Display) displayToLay.getComponent(2);
if ((operand1.gotSelectedElements() && operand2.gotSelectedElements()) ||
(operatorDisplay.isSelected())) {
// Sélectionne le display.
displayToLay.select();
// On purge la liste des éléments sélectionnés.
selEvt.setAction(SelectionEvent.PURGE, null);
displayToLay.fireSelectionEvent(selEvt);
// On y ajoute os parenthèses
selEvt.setAction(SelectionEvent.ADD, displayToLay);
displayToLay.fireSelectionEvent(selEvt);
}
 
// On a vérifié la validité de la sélection de la puissance. On doit maitenant
// la contrôler au niveau supérieur, au niveau du père.
Display display = displayToLay;
if (display.getParent() instanceof Display) {
display = (Display) display.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) display.getListener();
if (fts.getFather() != null)
((DisplayLayout) display.getLayout()).validateSelection();
}
 
// On met à jour l'affichage.
display.repaint();
}
/**
* Checks the validity of the deselection.
* @param display the display to deselect.
*/
public void validateDeselection(Display display) {
Display father = displayToLay;
SelectionEvent selEvt = new SelectionEvent(father);
// Si la fraction est sélectionnée, alors il faut la déselectionner.
if (father.isSelected()) {
father.setNotSelected();
// On enlève le display père de la liste des display sélectionnés.
selEvt.setAction(SelectionEvent.REMOVE, father);
father.fireSelectionEvent(selEvt);
Display operatorDisplay = (Display) father.getComponent(0);
Display operand1 = (Display) father.getComponent(1);
Display operand2 = (Display) father.getComponent(2);
if (display == operand1) {
operatorDisplay.setNotSelected();
selEvt.setAction(SelectionEvent.ADD, operand2);
father.fireSelectionEvent(selEvt);
}
else if (display == operand2) {
operatorDisplay.setNotSelected();
selEvt.setAction(SelectionEvent.ADD, operand1);
father.fireSelectionEvent(selEvt);
}
else {
operand1.deselect();
operatorDisplay.setNotSelected();
operand2.deselect();
}
 
// Comme pour la sélection, on contrôle la validité de la désélection.
if (father.getParent() instanceof Display) {
father = (Display) father.getParent();
FormulaTreeStructure fts = (FormulaTreeStructure) father.getListener();
if (fts.getFather() != null)
((DisplayLayout) father.getLayout()).validateDeselection(displayToLay);
}
// Hé oui, on contrôle la validité de la sélection... dans une désélection.
// Toujours le même pb, est-ce que le nouvel état de la sélection (après
// désélection donc) est syntaxiquement cohérent ?
validateSelection();
// On met à jour l'affichage.
father.repaint();
}
}
/**
* Computes the size of the display according to its children size (if any),
* and its different attributes.
* @return the size of the display.
*/
public Dimension computeAttributes() {
Display displayOperator = (Display) displayToLay.getComponent(0);
Display topOperand = (Display) displayToLay.getComponent(1);
Display bottomOperand = (Display) displayToLay.getComponent(2);
// Initialisation de ces paramètres pour annuler les (éventuelles) précédentes valeurs prises.
displayOperator.setShiftY(0);
topOperand.setShiftY(0);
bottomOperand.setShiftY(0);
 
// On calcule les attributs des display enfants comme si on avait affaire à un VerticalCenteredLayout.
// La différece réside dans le fait qu'il faut faire en sorte que le display de l'opérateur soit affiché
// entre les opérandes
Dimension dim = super.computeAttributes();
 
// Cette taille là correspond au décalage qu'il faut appliquer à la barre de fraction
displayOperator.setShiftY(topOperand.getHeight());
// Mais il faut l'enlever au display du numérateur
topOperand.setShiftY(-displayOperator.getShiftY() - displayOperator.getHeight());
bottomOperand.setShiftY(displayOperator.getHeight());
// On met la baseline de la fraction sur celle de la barre de fraction + qque broutilles qui
// correspondent à où se trouve la barre horizontale du +
int ascent = displayToLay.getFontMetrics(displayToLay.getFont()).getAscent();
ascent = (int) Math.round(((float) ascent)*0.388f);
ascent += topOperand.getShiftY() + topOperand.getHeight() +
displayOperator.getShiftY() + displayOperator.getAscent();
displayToLay.setAscent(ascent);
displayToLay.setDescent(dim.height - ascent);
displayToLay.setComputeAttributes(false);
return dim;
}
/**
* The display needs to be rebuilt. We do this.
*/
public void rebuildDisplay() {
Display tmp;
Display listDisplay[] = new Display[2];
for (int i = 1; i <= 2; i++) {
tmp = (Display) displayToLay.getComponent(i);
tmp.setLocation(0,0);
listDisplay[((FormulaTreeStructure) tmp.getListener()).getRank()] = tmp;
}
// On garde un référence sur le display du symbole l'opérateur
tmp = (Display) displayToLay.getComponent(0);
// On fait en sorte que temporairement ce display ne soit pas considéré comme un
// display d'opérateur, sinon il serait supprimé de la liste des listeners de la fts,
// chose qu'on ne veut pas puisque qu'on va le remettre à sa place.
tmp.setIsSymbolOperatorDisplay(false);
// ATTENTION : ici, on enlève les displays fils de display, mais on ne les enlève pas de la liste
// des listeners de la fts qu'il sont en train d'écouter.
displayToLay.removeAllDisplays();
// On remet tmp comme étant un display d'opérateur
tmp.setIsSymbolOperatorDisplay(true);
// On le rajoute dans displayToLay à sa position (la première)
displayToLay.add(tmp);
for (int i = 0; i < 2; i++)
displayToLay.add(listDisplay[i]);
// La taille des displays est probablement différente de ceux qui étaient
// précédemment. On demande alors le recalcul des display ancêtres.
displayToLay.computeAncestorsAttributes();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/Colorizable.java
0,0 → 1,72
/*
$Id: Colorizable.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.awt.Color;
 
/**
* Interface that must implement all objects that want to be colored.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/06/1999
*/
public interface Colorizable {
/**
* Sets the foreground color of the instance.
* @param foregroundColor the new color.
*/
public void setForegroundColor(Color foregroundColor);
/**
* Returns the foreground color of the instance.
*/
public Color getForegroundColor();
/**
* Sets the background color of the instance.
* @param backgroundColor the new color.
*/
public void setBackgroundColor(Color backgroundColor);
/**
* Returns the background color of the instance.
*/
public Color getBackgroundColor();
/**
* Sets the selection color of the instance.
* @param selectionColor the new color.
*/
public void setSelectionColor(Color selectionColor);
/**
* Returns the selection color of the instance.
*/
public Color getSelectionColor();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/bidim/DisplayAllocator.java
0,0 → 1,51
/*
$Id: DisplayAllocator.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.bidim;
 
import java.io.Serializable;
import fr.ove.openmath.jome.ctrlview.bidim.*;
import fr.ove.openmath.jome.model.FormulaTreeStructure;
 
/**
* This class instanciates the right display according to the specified formula
* tree sturcture.
* This is an abstract class. It must be inherited to be specialized.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 01/07/1999
*/
 
public abstract class DisplayAllocator implements Serializable {
/**
* Instanciates and creates the right display according to the specified
* formula tree structure.
* @param fts the formula tree structure which need a display.
*/
public abstract Display allocateDisplay(GraphicContext graphicContext, FormulaTreeStructure fts);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/events/ControlListener.java
0,0 → 1,47
/*
$Id: ControlListener.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.events;
 
import java.util.EventListener;
import fr.ove.openmath.jome.ctrlview.events.ControlEvent;
 
/**
* The interface that an object which want to be alerted of the control actions
* must implement.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 09/07/98
*/
public interface ControlListener extends EventListener {
/**
* Consumes (i.e. treats) the event received.
* @param controlEvent the event to consume.
*/
public void consumeControlEvent(ControlEvent controlEvent);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/ctrlview/events/ControlEvent.java
0,0 → 1,128
/*
$Id: ControlEvent.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.ctrlview.events;
 
import java.util.EventObject;
 
/**
* The event to send to all objects that implements the interface ControlListener
* and which want to execute the control actions.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 09/07/98
*/
public class ControlEvent extends EventObject {
/**
* The action to execute with the event.
*/
private int action;
 
/**
* The argument of the action to execute.
*/
private Object argument;
 
/**
* The constructor.
* @param src the object which produces this event.
*/
public ControlEvent(Object src) {
super(src);
}
 
/**
* Sets the action and its argument, if necessary, to execute to the event.
* @param action the action to execute.
* @param argument the action argument. If the action don't need
* an argument, it must be sets to <CODE>null</CODE>.
*/
public void setAction(int action, Object argument) {
this.action = action;
this.argument = argument;
}
 
/**
* Returns the action associated with the event.
*/
public int getAction() {
return action;
}
 
/**
* Returns the argument of the action.
*/
public Object getArgument() {
return argument;
}
 
/**
* The different actions associated with the event.<BR>
*/
 
/**
* Add the element which produces the event.
*/
public static final int ADD = 0;
 
/**
* Remove the element which produces the event.
*/
public static final int REMOVE = 1;
 
/**
* Iconify the element which produces the event.
*/
public static final int ICONIFY = 2;
 
/**
* Uniconify the element which produces the event.
*/
public static final int UNICONIFY = 3;
 
/**
* Recursive iconification
*/
public static final int UNICONIFY_ALL = 4;
 
/**
* Substitue the selection by a friendly name.
*/
public static final int SUBSTITUTE = 5;
 
/**
* Ask the OpenMath object of the formula.
*/
public static final int GIVE_OPENMATH = 6;
 
/*
* Ask the maple-like expression of the formula.
*/
public static final int GIVE_MAPLE = 7;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/processor/ProcessorImpl.java
0,0 → 1,181
/*
$Id: ProcessorImpl.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.processor;
 
import fr.ove.openmath.jome.model.Formula;
 
/**
* An implementation of a @see Processor.<BR>
* The method <CODE>doProcess</CODE> does nothing. Subclasses have to,
* at least, override it to provide the desired processing.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 17/08/2000
*/
public class ProcessorImpl implements Processor {
/**
* The formula to process.
*/
private Formula formula;
/**
* To check if we have to update the display of the formula.<BR>
* The default is false.
*/
private boolean updateDisplay = false;
/**
* The processing to execute.<BR>
* The default corresponds to <CODE>ProcessorImpl.COMPUTE_AND_ICONIFY</CODE>.
*/
private int processingId = COMPUTE_AND_ICONIFY;
/**
* The level form which the processing starts.
*/
private int level = 0;
/**
* The constructor.
* @param formula the formula to process.
*/
public ProcessorImpl(Formula formula) {
this.formula = formula;
}
/**
* Does processing.<BR>
* !! Method to override by subclasses !!
*/
public void doProcess() {}
/**
* Sets the formula to processs.
*/
public void setFormula(Formula formula) {
this.formula = formula;
}
/**
* Returns the formula to process.
*/
public Formula getFormula() {
return formula;
}
/**
* Specifies if, after processing the formula, the display has to be
* updated.
* @param updateDisplay <CODE>true</CODE> if the display needs update.
* <CODE>false</CODE> otherwise.
*/
public void setUpdateDisplay(boolean updateDisplay) {
this.updateDisplay = updateDisplay;
}
/**
* Checks if, after processing the formula, the display has to be
* updated.
* @returns <CODE>true</CODE> if the display needs update.
* <CODE>false</CODE> otherwise.
*/
public boolean getUpdateDisplay() {
return updateDisplay;
}
/**
* Initialisation of the processor.
* !! Method to override by subclasses !!
* The default is just setting the processing Id to be COMPUTE_AND_ICONIFY;
*/
public void init() {
setProcessingId(COMPUTE_AND_ICONIFY);
}
/**
* Sets the processing to execute.
* @param processingId the processing Id.
*/
public void setProcessingId(int processingId) {
this.processingId = processingId;
}
/**
* Returns the current processing to execute.
*/
public int getProcessingId() {
return processingId;
}
/**
* Sets the level from which the processing starts.
* @param level the level.
*/
public void setLevel(int level) {
this.level = level;
}
/**
* Returns the level from which the processing starts.
*/
public int getLevel() {
return level;
}
/**
* The different processing to apply to the formula
*/
/**
* Compute the the necessaru stuff for the iconifcation of the formula.
*/
public static final int COMPUTE = 1;
/**
* Iconify the formula according to the iconification level fixed.<BR>
* We assume the necessary computation for the iconification of the formula was previously done.<BR>
* This is a simple iconification process. Subtrees of iconfied ones are not iconified.
*/
public static final int SIMPLE_ICONIFICATION = 2;
/**
* Iconify the formula according to the iconification level fixed.<BR>
* We assume the necessary computation for the iconification of the formula was previously done.<BR>
* This is a recursive iconification process. Subtrees of iconfied ones are also iconified.
*/
public static final int RECURSIVE_ICONIFICATION = 3;
/**
* Compute and iconify (recursivly) the formula according to the iconification level fixed.<BR>
* This is the default behaviour.
*/
public static final int COMPUTE_AND_ICONIFY = 4;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/processor/DepthProcessor.java
0,0 → 1,260
/*
$Id: DepthProcessor.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.processor;
 
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import java.util.*;
import java.awt.*;
 
/**
* A processor for the depth of the formula.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 21/08/2000
*/
public class DepthProcessor extends ProcessorImpl implements DepthProcessorInterface {
/**
* The maximal depth of the formula.
*/
private int maxDepthValue = 0;
/**
* The constructor.
* @param formula the formula to process.
*/
public DepthProcessor(Formula formula) {
super(formula);
}
/**
* Sets the depth level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see setLevel of the @see Processor interface.
* @param depthLevel the depth level.
*/
public void setDepthLevel(int depthLevel) {
setLevel(depthLevel);
}
/**
* Returns the depth level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see getLevel of the @see Processor interface.
*/
public int getDepthLevel() {
return getLevel();
}
/**
* Returns the max depth value of the formula
*/
public int getMaxDepthValue() {
return maxDepthValue;
}
/**
* Does processing.
*/
public void doProcess() {
Formula formula = getFormula();
if (formula != null) {
switch (getProcessingId()) {
case COMPUTE :
// En fait le calcul de la profondeur est fait à la construction de la formule.
// donc rien de particulier à faire ici, si ce n'est affecter la valeur de la
// profondeur max de l'arbre de la formule.
maxDepthValue = 0; // initialisation
computeMaxDepthValue(formula); // calcul.
break;
case SIMPLE_ICONIFICATION :
// Iconifie les parties de la formule qui ont une profondeur supérieure
// à celle spécifiée.
setUpdateDisplay(true);
iconifyTheFTS(formula, getLevel());
setUpdateDisplay(false);
break;
case RECURSIVE_ICONIFICATION :
// Iconifie les parties de la formule qui ont une profondeur supérieure
// à celle spécifiée. Iconification récursive.
setUpdateDisplay(true);
iconifyAllTheFTS(formula, getLevel());
setUpdateDisplay(false);
break;
case COMPUTE_AND_ICONIFY :
// En fait le calcul de la profondeur est fait à la construction de la formule.
// donc rien de particulier à faire ici, si ce n'est affecter la valeur de la
// profondeur max de l'arbre de la formule.
maxDepthValue = 0; // initialisation
computeMaxDepthValue(formula); // calcul.
// Iconifie les parties de la formule qui ont une profondeur supérieure
// à celle spécifié. Iconification récursive.
// Le defaut est que l'on icionifie à une valeur correspondant à peu près à la
// moitié de la profondeur de l'arbre.
setLevel(maxDepthValue / 2);
iconifyAllTheFTS(formula, getLevel());
}
}
}
/**
* Iconifies the descendance of the instance which has a depth greater
* than the specified.
* @param depth the specified depth value.
*/
private void iconifyTheFTS(FormulaTreeStructure fts, int depth) {
// On parcourt tous les enfants de l'instance et on descend dans toute l'arboresnce
// jusqu'au feuilles. (DFS) Arrivée à la feuille, on teste la valeur de la profondeur et si
// elle est spérieure à celle spécifiée, on iconifie.
// On réitère le process sur tous les enfants.
FormulaTreeStructure child = null;
/*
if (fts.getNbChildren() > 0) {
for (Enumeration e = fts.getChildren().elements(); e.hasMoreElements(); ) {
child = (FormulaTreeStructure) e.nextElement();
if (child.getDepth() < depth)
iconifyTheFTS(child, depth);
else
if (child.getNbChildren() > 0) // Si child n'est pas une feuille (i.e. constante), on iconifie
iconify(child, depth);
}
}
*/
if (fts.isIcon()) {
FormulaTreeStructure father = (FormulaTreeStructure) fts.getFather();
fts.uniconify();
// On envoie maintenant un événement comme quoi il faut reconstruire
// l'affichage.
ModelEvent modelEvent = new ModelEvent(father);
modelEvent.setAction(ModelEvent.REBUILD, null);
father.fireModelEvent(modelEvent);
iconifyTheFTS(father, depth);
}
if (fts.getDepth() < depth) {
if (fts.getNbChildren() > 0) {
for (Enumeration e = fts.getChildren().elements(); e.hasMoreElements(); )
iconifyTheFTS((FormulaTreeStructure) e.nextElement(), depth);
}
}
else {
if (fts.getNbChildren() > 0)
iconify(fts, depth);
}
}
/**
* Iconifies all the descendance of the instance which has a Strahler number lower
* than the specified.
* @param depth the specified Strahler number.
*/
private void iconifyAllTheFTS(FormulaTreeStructure fts, int depth) {
// On parcourt tous les enfants de l'instance et on descend dans toute l'arboresnce
// jusqu'au feuilles. (DFS) Arrivée à la feuille, on teste la valeur du strahler et si
// elle est inférieure à celle spécifiée, on iconifie.
// On réitère le process sur tous les enfants.
if (fts.getNbChildren() > 0) {
for (Enumeration e = fts.getChildren().elements(); e.hasMoreElements(); )
iconifyAllTheFTS((FormulaTreeStructure) e.nextElement(), depth);
 
if (fts.getDepth() >= depth)
iconify(fts, depth);
}
}
/**
* Iconifie the instance if it has a Strahler number lower than the specified.
* @param depth the specified Strahler number
*/
private void iconify(FormulaTreeStructure fts, int depth) {
if (fts.getFather() != null) {
Icon icon = new Icon(fts);
// On ajoute notre instance à iconifier dans Icon (<=> on iconfie l'instance)
icon.addIconified(fts);
// On insère maintenant notre icon à la place de fts.
// On prend le père de l'instance.
FormulaTreeStructure father = (FormulaTreeStructure) fts.getFather();
// On insère notre icone à la place de l'instance
father.addChild(icon, fts.getRank());
// On enlève l'instance de la liste des enfants de father.
father.removeChild(fts);
if (getUpdateDisplay()) {
// On ajoute un display pour notre icon.
ModelEvent modelEvent = new ModelEvent(father);
modelEvent.setAction(ModelEvent.ADD, icon);
father.fireModelEvent(modelEvent);
}
}
}
/**
* Computes the max depth value of the formula
*/
private void computeMaxDepthValue(FormulaTreeStructure fts) {
if (fts.getNbChildren() > 0) {
for (Enumeration e = fts.getChildren().elements(); e.hasMoreElements(); )
computeMaxDepthValue((FormulaTreeStructure) e.nextElement());
}
maxDepthValue = (int) Math.max(fts.getDepth(), maxDepthValue);
}
public static void main(String args[]) {
String exp = "1+2/3*(4+3/5)^2+2/((3+5^9)*(1+2+3))";
Formula formula = new Formula();
formula.setDoProcessing(true);
DepthProcessor p = new DepthProcessor(formula);
//p.setLevel(3);
formula.setProcessor(p);
fr.ove.openmath.jome.ctrlview.bidim.FormulaDisplay display = new fr.ove.openmath.jome.ctrlview.bidim.FormulaDisplay();
formula.addModelListener(display);
display.addControlListener(formula);
java.awt.Frame f = new java.awt.Frame();
f.setLayout(new java.awt.BorderLayout());
f.setBounds(50, 50, 250, 80);
f.add("Center", display);
f.setVisible(true);
fr.ove.openmath.jome.ctrl.linear.LinearParser linearParser = new fr.ove.openmath.jome.ctrl.linear.LinearParser();
linearParser.addLinearParserListener(formula);
linearParser.parse(exp);
System.out.println("la formule saisie est : \t\t" + exp);
System.out.println("la formule construite est : \t\t" + formula.getLinear());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/processor/WidthDepthProcessor.java
0,0 → 1,205
/*
$Id: WidthDepthProcessor.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.processor;
 
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import java.util.*;
 
/**
* A Width-Depth processor.<BR>
* It is a mix bettween a Width processor (@see WidthProcessor) and a Depth processor
* (@see DepthProcessor).<BR>
* The iconification of the formula operates in 2 phases :
* <OL>
* <LI>iconification of a certain amount of operands of the operators whose number
* of operands is greater than a specified value</LI>
* <LI>iconification of the subtree of the formula tree structure whose depth is greater than
* than the specified value<LI>
* </OL>
*
* @author © 2000 DIRAT Laurent
* @version 1.0 22/08/2000
*/
public class WidthDepthProcessor extends ProcessorImpl implements WidthProcessorInterface, DepthProcessorInterface {
/**
* The depth processor.
*/
private DepthProcessor depth;
/**
* The width processor.
*/
private WidthProcessor width;
/**
* The constructor.
* @param formula the formula to process.
*/
public WidthDepthProcessor(Formula formula) {
super(formula);
depth = new DepthProcessor(formula);
width = new WidthProcessor(formula);
}
/**
* Does processing.
*/
public void doProcess() {
Formula formula = getFormula();
if (formula != null) {
width.setProcessingId(getProcessingId());
width.doProcess();
depth.setProcessingId(getProcessingId());
depth.doProcess();
/*
switch (getProcessingId()) {
case COMPUTE :
width.setProcessingId(COMPUTE);
width.doProcess();
depth.setProcessingId(COMPUTE);
depth.doProcess();
break;
case SIMPLE_ICONIFICATION :
width.setProcessingId(SIMPLE_ICONIFICATION);
width.doProcess();
depth.setProcessingId(SIMPLE_ICONIFICATION);
depth.doProcess();
break;
case RECURSIVE_ICONIFICATION :
width.setProcessingId(RECURSIVE_ICONIFICATION);
width.doProcess();
depth.setProcessingId(RECURSIVE_ICONIFICATION);
depth.doProcess();
break;
case COMPUTE_AND_ICONIFY :
width.setProcessingId(COMPUTE_AND_ICONIFY);
width.doProcess();
depth.setProcessingId(COMPUTE_AND_ICONIFY);
depth.doProcess();
}
*/
}
}
/**
* Sets the level from which the processing starts.<BR>
* The level correspond for both width and depth processor.
* @param level the level.
*/
public void setLevel(int level) {
width.setLevel(level);
depth.setLevel(level);
}
// #########################################
// ### Interface DepthProcessorInterface ###
// #########################################
/**
* Sets the depth level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see setLevel of the @see Processor interface.
* @param depthLevel the depth level.
*/
public void setDepthLevel(int depthLevel) {
depth.setLevel(depthLevel);
}
/**
* Returns the depth level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see getLevel of the @see Processor interface.
*/
public int getDepthLevel() {
return depth.getLevel();
}
/**
* Returns the max depth value calculated.
*/
public int getMaxDepthValue() {
return depth.getMaxDepthValue();
}
// #########################################
// ### Interface WidthProcessorInterface ###
// #########################################
/**
* Sets the width level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see setLevel of the @see Processor interface.
* @param widthLevel the width level.
*/
public void setWidthLevel(int widthLevel) {
width.setLevel(widthLevel);
}
/**
* Returns the width level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see getLevel of the @see Processor interface.
*/
public int getWidthLevel() {
return width.getLevel();
}
/**
* Sets the number of children viewed.
* @param the number of children viewed.
*/
public void setView(int view) {
width.setView(view);
}
/**
* Returns the number of children viewed.
*/
public int getView() {
return width.getView();
}
/**
* Returns the list of widths calculated.
*/
public Vector getWidthList() {
return width.getWidthList();
}
/**
* Returns the biggest width calculated.
*/
public int getBiggestWidth() {
return width.getBiggestWidth();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/processor/DepthProcessorInterface.java
0,0 → 1,57
/*
$Id: DepthProcessorInterface.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.processor;
 
/**
* The interface to implement to be depth processor.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 21/08/2000
*/
public interface DepthProcessorInterface extends Processor {
/**
* Sets the depth level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see setLevel of the @see Processor interface.
* @param depthLevel the depth level.
*/
public void setDepthLevel(int depthLevel);
/**
* Returns the depth level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see getLevel of the @see Processor interface.
*/
public int getDepthLevel();
/**
* Returns the max depth value calculated.
*/
public int getMaxDepthValue();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/processor/Processor.java
0,0 → 1,98
/*
$Id: Processor.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.processor;
 
import fr.ove.openmath.jome.model.Formula;
 
/**
* The interface to implement if a class wants to be considered
* as a processor of the model of the formula (@see fr.ove.openmath.jome.model.Formula)
*
* @author © 2000 DIRAT Laurent
* @version 1.0 16/08/2000
*/
public interface Processor {
/**
* Does processing.
*/
public void doProcess();
/**
* Sets the formula to processs
*/
public void setFormula(Formula formula);
/**
* Returns the formula to process.
*/
public Formula getFormula();
/**
* Specifies if, after processing the formula, the display has to be
* updated.
* @param updateDisplay <CODE>true</CODE> if the display needs update.
* <CODE>false</CODE> otherwise.
*/
public void setUpdateDisplay(boolean updateDisplay);
/**
* Checks if, after processing the formula, the display has to be
* updated.
* @returns <CODE>true</CODE> if the display needs update.
* <CODE>false</CODE> otherwise.
*/
public boolean getUpdateDisplay();
/**
* Initialisation of the processor.
*/
public void init();
/**
* Sets the processing to execute.
* @param processingId the processing Id.
*/
public void setProcessingId(int processingId);
/**
* Returns the current processing to execute.
*/
public int getProcessingId();
/**
* Sets the level from which the processing starts.
* @param level the level.
*/
public void setLevel(int level);
/**
* Returns the level from which the processing starts.
*/
public int getLevel();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/processor/WidthProcessor.java
0,0 → 1,312
/*
$Id: WidthProcessor.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.processor;
 
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import java.util.*;
import java.awt.*;
 
/**
* A processor for the width of the formula.<BR>
* What is called width corresponds to the number of operand of an operator. (i.e. the number
* of children of a node in the formula tree stucture.<BR>
* The processor only displays a specified amount of operand of an operator whose number of operands
* is greater than a specified value. The other operands are iconified.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 21/08/2000
*/
public class WidthProcessor extends ProcessorImpl implements WidthProcessorInterface {
/**
* The list of widths numbers in the formula.
*/
private Vector widthList = new Vector();
/**
* Check if the current list of Strahler numbers in the formula is valid or not.
*/
private boolean isListValid = false;
/**
* The number of children viewed.<BR>
* Should be a positive value. If equals to -1, then all children have to be displayed.
* This is the default value.
*/
private int view = -1;
/**
* The constructor.
*/
public WidthProcessor(Formula formula) {
super(formula);
}
/**
* Sets the width level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see setLevel of the @see Processor interface.
* @param widthLevel the width level.
*/
public void setWidthLevel(int widthLevel) {
setLevel(widthLevel);
}
/**
* Returns the width level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see getLevel of the @see Processor interface.
*/
public int getWidthLevel() {
return getLevel();
}
/**
* Sets the number of children viewed.
* @param the number of children viewed.
*/
public void setView(int view) {
this.view = view;
}
/**
* Returns the number of children viewed.
*/
public int getView() {
return view;
}
/**
* Returns the list of widths of the formula.
*/
public Vector getWidthList() {
if (!isListValid) {
buildWidthList(getFormula());
isListValid = true;
}
return widthList;
}
/**
* Returns the biggest width of the formula.
*/
public int getBiggestWidth() {
return ((Integer) widthList.lastElement()).intValue();
}
/**
* Does processing.
*/
public void doProcess() {
Formula formula = getFormula();
if (formula != null) {
switch (getProcessingId()) {
case COMPUTE :
// La liste des Strahler n'est (a priori) plus à jour.
buildWidthList(formula);
break;
case SIMPLE_ICONIFICATION :
// Iconifie les parties de la formule qui ont un nombre de Strahler inférieur
// à celui spécifié.
setUpdateDisplay(true);
iconifyTheFTS(formula, getLevel());
setUpdateDisplay(false);
break;
case RECURSIVE_ICONIFICATION :
// Iconifie les parties de la formule qui ont un nombre de Strahler inférieur
// à celui spécifié. Iconification récursive.
setUpdateDisplay(true);
iconifyAllTheFTS(formula, getLevel());
setUpdateDisplay(false);
break;
case COMPUTE_AND_ICONIFY :
// La liste des Strahler n'est (a priori) plus à jour.
buildWidthList(formula);
// Iconifie les parties de la formule qui ont un nombre de Strahler inférieur
// à celui spécifié. Iconification récursive.
// Le defaut est que l'on icionifie à une valeur correspondant à peu près à la
// valeur moyenne du Strahler max calculé.
int width = getBiggestWidth() / 2;
// Maintenant on regarde dans la liste des width, le width valide immédiatement
// supérieur à la valeur correpsondant à la moitié du plus grand.
int count = widthList.size();
int tmp;
for (int i = 0; i < count; i++ ) {
tmp = ((Integer) widthList.elementAt(i)).intValue();
if (tmp > width) {
width = tmp;
break;
}
}
setLevel(width);
view = width / 2; // On ne visualise que la moitié de fils de l'opérateur
iconifyAllTheFTS(formula, width);
}
}
}
/**
* Iconifies the descendance of the instance which has a widht number greater
* than the specified.
* @param width the specified width.
*/
private void iconifyTheFTS(FormulaTreeStructure fts, int width) {
// On parcourt tous les enfants de l'instance et on descend dans toute l'arboresnce
// jusqu'au feuilles. (DFS) Arrivée à la feuille, on teste la valeur du strahler et si
// elle est inférieure à celle spécifiée, on iconifie.
// On réitère le process sur tous les enfants.
FormulaTreeStructure child = null;
int ftsWidth = fts.getNbChildren();
if ((ftsWidth > 0) && (ftsWidth >= width))
iconify(fts, width);
int count = fts.getNbChildren();
for (int i = 0; i < count; i++)
iconifyTheFTS((FormulaTreeStructure) fts.getChild(i), width);
}
/**
* Iconifies all the descendance of the instance which has a width greater
* than the specified.
* @param width the specified width.
*/
private void iconifyAllTheFTS(FormulaTreeStructure fts, int width) {
// On parcourt tous les enfants de l'instance et on descend dans toute l'arboresnce
// jusqu'au feuilles. (DFS) Arrivée à la feuille, on teste la valeur du strahler et si
// elle est inférieure à celle spécifiée, on iconifie.
// On réitère le process sur tous les enfants.
int ftsWidth = fts.getNbChildren();
if (ftsWidth > 0) {
for (Enumeration e = fts.getChildren().elements(); e.hasMoreElements(); )
iconifyAllTheFTS((FormulaTreeStructure) e.nextElement(), width);
if (ftsWidth >= width)
iconify(fts, width);
}
}
/**
* Iconifie the instance if it has a width greater than the specified.
* @param width the specified width.
*/
private void iconify(FormulaTreeStructure fts, int width) {
int count = fts.getNbChildren();
Icon icon = new Icon(fts);
// On ajoute notre instance à iconifier dans Icon (<=> on iconfie l'instance)
FormulaTreeStructure child;
// On ajout notre icone
fts.addChild(icon);
/**
for (int i = view; i < count; ) {
child = (FormulaTreeStructure) fts.getChild(i);
icon.addIconified(child);
//fts.removeChild(child);
count--;
}*/
for (int i = view; i < count; i++)
icon.addIconified((FormulaTreeStructure) fts.getChild(i));
for (int i = view; i < count; ) {
fts.removeChild((FormulaTreeStructure) fts.getChild(i));
count--;
}
if (getUpdateDisplay()) {
// On ajoute un display pour notre icon.
ModelEvent modelEvent = new ModelEvent(fts);
modelEvent.setAction(ModelEvent.ADD, icon);
fts.fireModelEvent(modelEvent);
}
}
/**
* Builds the list of widths of the formula.
*/
private void buildWidthList(FormulaTreeStructure fts) {
int width = fts.getNbChildren();
if (width > 1)
addNewWidth(width);
for (int i = 0; i < width; i++)
buildWidthList((FormulaTreeStructure) fts.getChild(i));
}
/**
* Adds the specified width value in the list if necessary
* @param width the width value to add
*/
private void addNewWidth(int width) {
int currentWidth;
if (widthList.size() == 0)
widthList.addElement(new Integer(width));
else {
for (int i = 0; i < widthList.size(); i++) {
currentWidth = ((Integer) widthList.elementAt(i)).intValue();
if (width == currentWidth)
return;
else if (width < currentWidth) {
widthList.insertElementAt(new Integer(width), i);
return;
}
}
widthList.addElement(new Integer(width));
}
}
public static void main(String args[]) {
String exp = "a*z*e*r*r*t*(t+2+2+2+2+2+2+2+6+6+6+6+6+6)*1*6*6*6*6*6*6+2+3+4+5+6+7+8+9+10+11+12+13+14";
Formula formula = new Formula();
formula.setDoProcessing(true);
WidthProcessor p = new WidthProcessor(formula);
formula.setProcessor(p);
fr.ove.openmath.jome.ctrlview.bidim.FormulaDisplay display = new fr.ove.openmath.jome.ctrlview.bidim.FormulaDisplay();
formula.addModelListener(display);
display.addControlListener(formula);
java.awt.Frame f = new java.awt.Frame();
f.setLayout(new java.awt.BorderLayout());
f.setBounds(50, 50, 250, 80);
f.add("Center", display);
f.setVisible(true);
fr.ove.openmath.jome.ctrl.linear.LinearParser linearParser = new fr.ove.openmath.jome.ctrl.linear.LinearParser();
linearParser.addLinearParserListener(formula);
linearParser.parse(exp);
System.out.println("la formule saisie est : \t\t" + exp);
System.out.println("la formule construite est : \t\t" + formula.getLinear());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/processor/WidthProcessorInterface.java
0,0 → 1,77
/*
$Id: WidthProcessorInterface.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.processor;
 
import java.util.Vector;
 
/**
* The interface to implement to be a width processor.<BR>
* A width processor manages to display a certain amount of children (the view)
* of an element whose number of children (the width) is greater than a specified level.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 21/08/2000
*/
public interface WidthProcessorInterface extends Processor {
/**
* Sets the width level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see setLevel of the @see Processor interface.
* @param widthLevel the width level.
*/
public void setWidthLevel(int widthLevel);
/**
* Returns the width level form which the processing will be considering.<BR>
* For convenience only, in most cases this method is equivalent to the
* @see getLevel of the @see Processor interface.
*/
public int getWidthLevel();
/**
* Sets the number of children viewed.
* @param the number of children viewed.
*/
public void setView(int view);
/**
* Returns the number of children viewed.
*/
public int getView();
/**
* Returns the list of widths calculated.
*/
public Vector getWidthList();
/**
* Returns the biggest width calculated.
*/
public int getBiggestWidth();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/UnaryPostfixedOperator.java
0,0 → 1,94
/*
$Id: UnaryPostfixedOperator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
 
/**
* @author © 2000 DIRAT Laurent
* @version 2.1 24/02/2000
*/
public class UnaryPostfixedOperator extends Operator {
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
VariableOrNumber template;
// On cherche la position d'insertion de notre operateur
current = findLocation(current);
// On ajoute l'opérateur comme fils à l'opérateur courant
current.addChild(this);
 
if ((current.getFather() == null) && (current.getNbChildren() == 1))
addChild(new VariableOrNumber());
else {
FormulaTreeStructure fts = (FormulaTreeStructure) current.getChild(getRank() - 1);
// à cause des priorités sur les opérateurs, on ajoute comme fils l'opérateur
// dont le rang est juste inférieur à notre instance
addChild(fts);
// on enlève l'opérateur qu'on a fait "descendre", de la liste
// de son précédent père (son grand père maintenant)
current.removeChild(fts);
}
FormulaTreeStructure child = (FormulaTreeStructure) getChild(0);
if (child.getResourceIdentifier().equals("OPEN_PAREN"))
((Bracket) child).setIsVisible(true); // Dans le cas où la ! est fille d'une division, les parenthèses
// auront été rendues invisibles d'abord.
 
// On retourne la reférence de l'instance.
return this;
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
linear = ((FormulaTreeStructure) getChild(0)).createLinear(linear);
linear += getTheOperator();
return linear;
}
 
/**
* Evaluates the instance.
*/
public String evaluate() {
return ((FormulaTreeStructure) getChild(0)).evaluate() + getTheOperator();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/LambdaExpression.java
0,0 → 1,93
/*
$Id: LambdaExpression.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The lambda expression object.<BR>
* The first child corresponds to the function. The next child(ren) to the bound variable(s).
*
* @author © 1999 DIRAT Laurent
* @version 2.0 11/10/1999
*/
public class LambdaExpression extends Function /*NaryOperator2*/ {
private boolean gotoVariable = true;
/**
* Indicator for the rendrering.<BR>
* Is only function displayed ?<BR>
* In other words, if we got the lambda expression coresponding to lambda(sin(x)+cos(y), x, y), if
* its values equals <CODE>true</CODE>, the rendering will be something like (x, y) -> sin(x)+cos(y).
* Otherwise, the rendering will simply be sin(x)+cos(y). (we just function is rendered).<BR>
*/
private boolean justFunction = false;
/**
* Returns <CODE>true</CODE> if only the is displayed.
* <CODE>false</CODE> otherwise.
*/
public boolean isJustFunction() {
return justFunction;
}
/**
* Sets if just the function is rendered or not.
* @param justFunction <CODE>true</CODE> if we only want the function to be displayed. <CODE>false</CODE> otherwise.
*/
public void setJustFunction(boolean justFunction) {
this.justFunction = justFunction;
}
 
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
current = super.insert(current);
super.addElement();
return current;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
if (gotoVariable) {
gotoVariable = false;
return (FormulaTreeStructure) getChild(1).getChild(0);
}
else
return super.addElement();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/NamedBinaryOperator.java
0,0 → 1,55
/*
$Id: NamedBinaryOperator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* The same as @see BinaryOperator but the difference is the name of the operator is made of letters. And if the
* operator is glued to its operands during parsing, the name of the operator could not be detected. So space before
* and after the name of the operator are necessary.<BR>
* So, the only difference with @see BinaryOperator is the spaces added around the name of the operator when exporting
* the linear form.
*
* @author © 2000 DIRAT Laurent
* @version 2.0 12/01/2000
*/
public class NamedBinaryOperator extends BinaryOperator {
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
linear = ((FormulaTreeStructure) getChild(0)).createLinear(linear);
linear += " " + getTheOperator() + " ";
linear = ((FormulaTreeStructure) getChild(1)).createLinear(linear);
return linear;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Formula.java
0,0 → 1,315
/*
$Id: Formula.java,v 1.4 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import java.awt.*;
 
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.processor.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
import fr.ove.openmath.jome.model.evaluation.*;
import fr.ove.openmath.jome.behaviour.Modifiable;
import fr.ove.openmath.jome.ctrl.linear.events.*;
import fr.ove.utils.Factory;
 
/**
* The formula.<BR>
* The root of the formula tree structure.
*
* @author © 2000 DIRAT Laurent
* @version 2.0 28/06/99
*/
public class Formula extends FormulaTreeStructure implements LinearParserListener {
/**
* The current insertion position in the formula (tree structure).
*/
public FormulaTreeStructure current;
/**
* The OpenMath formater for exportation of the formula as an OpenMath object
*/
/**
* The MathML formater for exportation of the formula as a MathML object
*/
// On maintient une pile qui va contenir les instances qui ont besoin d'être "fermées".
// Par exemple les parenthèses, les listes, ...
// Nécessaire de faire ça à cause des inclusions mutuelles d'opérateurs du même type.
private Stack openingStack = new Stack();
/**
* Flag to deal with a possible processing of the model of the formula before rendering.<BR>
* The default is <CODE>false</CODE>, i.e. we want the formula to be displayed
* normally (no processing).
*/
private boolean doProcessing = false;
/**
* The processor which will process the model of the formula before rendering if wanted.<BR>
* By default, no processor is set. One processor has to added when desired.
*/
private Processor processor = null;
 
/**
* The Constructor.
*/
public Formula () {
setResourceIdentifier("FORMULA");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("formulaPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("formulaPriorities"));
current = this;
}
/**
* To check is the instance is an operator.
* @return <CODE>true</CODE> if it is an operator. <CODE>false</CODE> otherwise.
*/
public boolean isOperator() {
return false;
}
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).<BR>
* At the moment, we can't insert a formula in an another formula.
* @param current the current insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// On ne devrait pas insérer de formule !!
// A voir, peut être utile pour le drag'n drop d'une nouvelle formule;
return null;
}
 
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
if (getNbChildren() > 0)
linear = ((FormulaTreeStructure) getChild(0)).createLinear(linear);
return linear;
}
/**
* clears the formula.
*/
public void clear() {
// On enlève tous les enfants de la FTS.
removeAll();
// On remet la position courante d'insertion sur la racine de la FTS
current = this;
}
/**
* Returns the linear expression of the formula.
*/
public String getLinear() {
return createLinear("");
}
 
/**
* Returns the OpenMath representation of the formula.
*/
/**
* Returns the MathML representation of the formula.
*/
/**
* Evaluates the instance.
*/
public String evaluate() {
if (getNbChildren() > 0)
return ((FormulaTreeStructure) getChild(0)).evaluate();
else
return "";
}
/**
* Treats the event received.
* @param linearParserEvent the event received.
*/
public void consumeLinearParserEvent(LinearParserEvent linearParserEvent) {
int identifier = linearParserEvent.getIdentifier();
String value = linearParserEvent.getValue();
ModelEvent modelEvent;
switch (identifier) {
case LinearParserEvent.START_EXPRESSION :
clear();
openingStack.setSize(0);
modelEvent = new ModelEvent(this);
modelEvent.setAction(ModelEvent.CLEAR, null);
fireModelEvent(modelEvent);
break;
case LinearParserEvent.END_EXPRESSION :
// Le modèle de la formule est entièrement construit.
// On regarde d'abord les éventuels traitements à effectuer sur le modèle
// avant la construction des displays.
if (doProcessing && (processor != null)) {
// Initialisation du processeur si besoin est.
processor.init();
processor.doProcess();
}
modelEvent = new ModelEvent(this);
modelEvent.setAction(ModelEvent.CREATE, null);
fireModelEvent(modelEvent);
break;
default :
String strIdentifier = linearParserEvent.getIdentifierAsString();
String className = resourcesManager.getClassName(strIdentifier);
FormulaTreeStructure newFts = null;
 
if (className.equals("null")) {
if (identifier == linearParserEvent.SEPARATOR) {
//current = current.goTo(FormulaTreeStructure.SLOT_AS_OPERATOR_PRIORITY);
current = current.goTo(resourcesManager.getAsOperatorPriority("slotPriorities"));
// current est maintenant une instance de Slot, on récupère son père pour lui
// ajouter un nouvel élément.
NaryOperator2 currentFather = (NaryOperator2) current.getFather();
current = currentFather.addElement();
}
else {
// Alors c'est forcément un linearParserEvent.CLOSE_*
if (!openingStack.isEmpty()) {
current = (FormulaTreeStructure) openingStack.pop();
// Et remonte encore d'un cran à cause des priorités des opérateurs
// (surtout en ce qui concerne les parenthèses)
current = (FormulaTreeStructure) current.getFather();
}
}
}
else {
if (className.equals("refine")) {
String[] properties = resourcesManager.getResourceStrings(value);
if (properties.length != 0)
strIdentifier = value; // On a trouvé qque chose correspondant à value
else {
if (identifier == linearParserEvent.RESERVED)
// Il n'existe pas de mot réservé défini dans le modèle correspondant à value.
// On considère donc value comme une variable.
strIdentifier = "VARIABLE";
else
// Si ce n'est pas un mot réservé, c'est une fonction.
// Il n'existe pas de fonction spéciale définie correspondant à value.
// On considère donc value comme une fonction par défaut ayant pour nom value.
strIdentifier = "defaultFunction";
}
}
newFts = (FormulaTreeStructure) Factory.getClassInstance(resourcesManager.getClassName(strIdentifier));
newFts.setResourceIdentifier(strIdentifier);
String prioritiesId = resourcesManager.getPrioritiesIdentifier(strIdentifier);
newFts.setAsOperatorPriority(resourcesManager.getAsOperatorPriority(prioritiesId));
newFts.setAsOperandPriority(resourcesManager.getAsOperandPriority(prioritiesId));
if (value != null)
newFts.setValue(value);
Integer arity = resourcesManager.getArity(strIdentifier);
if (arity != null)
((KaryOperator) newFts).setOperatorArity(arity.intValue());
switch (identifier) {
case LinearParserEvent.FUNCTION :
case LinearParserEvent.OPEN_PAREN :
case LinearParserEvent.OPEN_BRACKET :
case LinearParserEvent.OPEN_CURLY :
openingStack.push(newFts);
}
current = newFts.insert(current);
}
}
}
/**
* Sets if we had to process the instance before rendering.
* @param doProcessing <CODE>true</CODE> if the instance needs a processing.
* <CODE>false</CODE> otherwise.
*/
public void setDoProcessing(boolean doProcessing) {
this.doProcessing = doProcessing;
}
/**
* Returns <CODE>true</CODE> if the instance needs a processing.
* <CODE>false</CODE> otherwise.
*/
public boolean getDoProcessing() {
return doProcessing;
}
/**
* Sets the processor of the instance.
* @param processor the processor.
*/
public void setProcessor(Processor processor) {
this.processor = processor;
}
/**
* Returns the processor of the instance.
*/
public Processor getProcessor() {
return processor;
}
/**
* Processes the instance
*/
public void doProcess() {
if (doProcessing && (processor != null))
processor.doProcess();
}
public static void main(String args[]) {
String exp = "sum(i^n,0,sum(i^n,0,5))t";
Formula formula = new Formula();
fr.ove.openmath.jome.ctrl.linear.LinearParser linearParser = new fr.ove.openmath.jome.ctrl.linear.LinearParser();
linearParser.addLinearParserListener(formula);
linearParser.parse(exp);
System.out.println("la formule saisie est : \t\t" + exp);
System.out.println("la formule construite est : \t\t" + formula.getLinear());
try {
Thread.sleep(5000);
}
catch (Exception e) {
e.printStackTrace();
}
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/resources2.properties
0,0 → 1,218
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
#
# identifier = className:operatorPriorities:operatorArity
# operatorPriorities = asOperatorPriority:asOperandPriority
#
# identifier is the identifier of the resource. Corresponds to what the control (i.e. the control part of the MVC
# pattern, so in our case, the parser(s)) send to the model to build it. See the parser for explanation of the
# different of the different tokens and their use.
#
# className is the class to instanciate. The class name is fully qualified and then contains the name of the package
# where the class is.
#
# asOperatorPriority is the priority of the operator when it is considered as an operator (i.e. we are inserting
# operand(s) to the operator in the formula tree structure). Its value is a number.
#
# asOperandPriority is the priority of the operator when it is considered as an operand. (i.e we are inserting the
# operator in the formula tree structure). Its value is a number.
#
# operatorArity is the operator arity. This field is in fact only used for K-ary operators, the class to
# instanciate is then fr.ove.openmath.jome.model.KaryOperator. (more generally, all subclasses of KaryOperator)
# Of course, its value is a positive number. In all the other cases, this field is omitted.
#
# Two specific keywords are defined for each field.
# refine when the element we want to insert is not completely defined for its token. It is the case for FUNCTION,
# RESERVED and SPECIALIZED.
# The function term contains all operators whose linear syntax is name(...). According to the name of the function,
# we have to ...refine all the field to instanciate the correct object. The same for the to others.
# null when the token received not used as an identifier of a class to instanciate to insert in the formula tree
# structure (e.g. CLOSE_PAREN, SEPRATOR,...) or when the value has no importance.
 
formulaPriorities = 0:0
slotPriorities = 0:1000
bracketPriorities = 5:1000
binaryPriorities = 10:10
unaryPlusPriorities = 100:102
unaryMinusPriorities = 100:101
plusPriorities = 100:100
timesPriorities = 200:200
dividePriorities = 300:301
powerPriorities = 500:450
factorialPriorities = 1000:900
constantPriorities = 1000:1000
rondPriorities = 10:11
 
# not directly instanciated (private)
UNARYPLUS = fr.ove.openmath.jome.model.UnaryOperator:unaryPlusPriorities
UNARYMINUS = fr.ove.openmath.jome.model.UnaryOperator:unaryMinusPriorities
SLOT = fr.ove.openmath.jome.model.Slot:slotPriorities
ICON = fr.ove.openmath.jome.model.Icon:constantPriorities
 
# The formula (the most prioritary of all)
FORMULA = fr.ove.openmath.jome.model.Formula:formulaPriorities
 
# Constants
VARIABLE = fr.ove.openmath.jome.model.Variable:constantPriorities
INTEGER = fr.ove.openmath.jome.model.AnInteger:constantPriorities
FLOAT = fr.ove.openmath.jome.model.AFloat:constantPriorities
 
# N-ary operators (of "first" kind)
ADDITION = fr.ove.openmath.jome.model.Addition:plusPriorities
SUBSTRACTION = fr.ove.openmath.jome.model.Substraction:plusPriorities
MULTIPLICATION = fr.ove.openmath.jome.model.Multiplication:timesPriorities
 
# Binary operators
DIVISION = fr.ove.openmath.jome.model.BinaryOperator:dividePriorities
POWER = fr.ove.openmath.jome.model.BinaryOperator:powerPriorities
EQUAL = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
UNEQUAL = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
LESS = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
LESSEQUAL = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
GREATER = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
GREATEREQUAL = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
UNDERSCRIPT = fr.ove.openmath.jome.model.BinaryOperator:powerPriorities
 
# RESPECT space before and after the name of the operator, otherwise when linear exportation
# operands will be attached.
in = fr.ove.openmath.jome.model.NamedBinaryOperator:binaryPriorities
notin = fr.ove.openmath.jome.model.NamedBinaryOperator:binaryPriorities
union = fr.ove.openmath.jome.model.NamedBinaryOperator:binaryPriorities
 
langle = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
rangle = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
lbracket = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
rbracket = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
cup = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
neq = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
mapsto = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
and = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
or = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
rightarrow = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
 
alpha = fr.ove.openmath.jome.model.Constant:constantPriorities
alfa = fr.ove.openmath.jome.model.Constant:constantPriorities
beta = fr.ove.openmath.jome.model.Constant:constantPriorities
chi = fr.ove.openmath.jome.model.Constant:constantPriorities
epsilon = fr.ove.openmath.jome.model.Constant:constantPriorities
eta = fr.ove.openmath.jome.model.Constant:constantPriorities
gamma = fr.ove.openmath.jome.model.Constant:constantPriorities
iota = fr.ove.openmath.jome.model.Constant:constantPriorities
kappa = fr.ove.openmath.jome.model.Constant:constantPriorities
mu = fr.ove.openmath.jome.model.Constant:constantPriorities
nabla = fr.ove.openmath.jome.model.Constant:constantPriorities
nu = fr.ove.openmath.jome.model.Constant:constantPriorities
omega = fr.ove.openmath.jome.model.Constant:constantPriorities
phi = fr.ove.openmath.jome.model.Constant:constantPriorities
psi = fr.ove.openmath.jome.model.Constant:constantPriorities
rho = fr.ove.openmath.jome.model.Constant:constantPriorities
tau = fr.ove.openmath.jome.model.Constant:constantPriorities
theta = fr.ove.openmath.jome.model.Constant:constantPriorities
upsilon = fr.ove.openmath.jome.model.Constant:constantPriorities
zeta = fr.ove.openmath.jome.model.Constant:constantPriorities
sigma = fr.ove.openmath.jome.model.Constant:constantPriorities
xi = fr.ove.openmath.jome.model.Constant:constantPriorities
# Functions (in general, so need refinements)
FUNCTION = refine
 
# Functions refinements
defaultFunction = fr.ove.openmath.jome.model.Function:constantPriorities
 
abs = fr.ove.openmath.jome.model.Function:constantPriorities
conj = fr.ove.openmath.jome.model.Function:constantPriorities
 
# N-ary operators (of "second" kind)
set = fr.ove.openmath.jome.model.Function:constantPriorities
 
request = fr.ove.openmath.jome.model.Function:constantPriorities
entry = fr.ove.openmath.jome.model.Function:constantPriorities
 
lambda = fr.ove.openmath.jome.model.LambdaExpression:constantPriorities
subst = fr.ove.openmath.jome.model.Mfd2Substitution:constantPriorities
diff = fr.ove.openmath.jome.model.Differentiation:constantPriorities
 
# K-ary operators
int = fr.ove.openmath.jome.model.Integral:constantPriorities:4
sum = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:3
array = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:3
prod = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:3
root = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:2
sqrt = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:1
lim = fr.ove.openmath.jome.model.Limit:constantPriorities:3
 
# Les mots réservés
RESERVED = refine
 
pi = fr.ove.openmath.jome.model.Constant:constantPriorities
C = fr.ove.openmath.jome.model.Constant:constantPriorities
N = fr.ove.openmath.jome.model.Constant:constantPriorities
Q = fr.ove.openmath.jome.model.Constant:constantPriorities
R = fr.ove.openmath.jome.model.Constant:constantPriorities
Z = fr.ove.openmath.jome.model.Constant:constantPriorities
delta = fr.ove.openmath.jome.model.Constant:constantPriorities
I = fr.ove.openmath.jome.model.StringLowerCaseConstant:constantPriorities
E = fr.ove.openmath.jome.model.StringLowerCaseConstant:constantPriorities
infty = fr.ove.openmath.jome.model.Constant:constantPriorities
true = fr.ove.openmath.jome.model.Variable:constantPriorities
false = fr.ove.openmath.jome.model.Variable:constantPriorities
 
 
# Les délimiteurs
OPEN_PAREN = fr.ove.openmath.jome.model.Bracket:bracketPriorities
CLOSE_PAREN = null
 
OPEN_BRACKET = fr.ove.openmath.jome.model.Bracket:constantPriorities
CLOSE_BRACKET = null
// Revoir en fonction des listes horizontales ou verticales
OPEN_CURLY = fr.ove.openmath.jome.model.Liste:constantPriorities
CLOSE_CURLY = null
vlist = fr.ove.openmath.jome.model.Function:constantPriorities
 
# Les séparateurs
SEPARATOR = null
 
 
# Les opérateurs spécialisés
SPECIALIZED = refine
 
# Raffinement pour les opérateurs spécialisés
? = fr.ove.openmath.jome.model.RequestVariable:constantPriorities
fact = fr.ove.openmath.jome.model.Factorial:factorialPriorities
 
 
# Add-ons
delta = fr.ove.openmath.jome.model.Constant:constantPriorities
gamma = fr.ove.openmath.jome.model.Constant:constantPriorities
 
#rondPriorities = 11:10
 
o = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
 
gcd = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:2
quotient = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:2
rem = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:2
cc = fr.ove.openmath.jome.model.ComplexCartesian:constantPriorities:1
cp = fr.ove.openmath.jome.model.ComplexPolar:constantPriorities:1
 
rat = fr.ove.openmath.jome.model.Rational:constantPriorities:2
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/NaryOperator2.java
0,0 → 1,154
/*
$Id: NaryOperator2.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class NaryOperator2 extends Operator {
/**
* The ending of the linear syntax of the operator represented by the instance.
* The default is the closing bracket.
*/
private String ending = ")";
/**
* Returns the ending of the operator.
*/
public String getEnding() {
return ending;
}
/**
* Sets the ending of the operator.
* @param the ending of the operator.
*/
public void setEnding(String ending) {
this.ending = ending;
}
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
ModelEvent modelEvent;
if ((current.getFather() == null) && (current.getNbChildren() == 0)) {
// On est dans ce cas là, seulement au tout début de la saisie de la
// formule. On est obligé de faire ce test à cause de la multiplication
// implicite avec les parenthèses (Ex: (a+b)c ==> (a+b)*c, dans ce cas là,
// current.getNbChildren() est != de 0)
//On insère directement à la position courante
current.addChild(this);
}
else if ((current.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("constantPriorities")) &&
current.isTemplate()) {
// Le cas classique (on va même dire normal !!!)
// La position d'insertion est un template.
// On doit remplacer le template par l'instance courante
int rank = current.getRank();
FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
father.addChild(this, rank);
father.removeChild(current);
}
else {
// On est dans aucun des cas précédents, on créé donc une
// multiplication implicite.
current = (new Multiplication()).insert(current);
current = insert(current);
return current;
}
// Maintenant, on va rajouter un slot comme élément de l'opérateur
Slot aSlot = new Slot();
addChild(aSlot);
aSlot.setNextSlot(this);
// ...puis un template comme élément de ce slot
VariableOrNumber template = new VariableOrNumber();
aSlot.addChild(template);
return template;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
Slot aSlot = new Slot();
addChild(aSlot);
// ...puis un template comme élément de ce slot
VariableOrNumber template = new VariableOrNumber();
aSlot.addChild(template);
aSlot.setNextSlot(this);
((Slot) getChild(getNbChildren()-2)).setNextSlot(template);
return template;
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
FormulaTreeStructure child;
// Là encore, avec ce genre d'opérateur, la saisie se fait globalement comme la saisie
// d'une fonction. Ex : sum(i=0,n,i^n).
// Ou alors c'est qque chose qui est encadré par des symboles par exemple une liste {1, 2, 3}.
// Donc, l'opérateur est ce qui "ouvre" la syntaxe et l'ending, ce qui "ferme" la syntaxe.
linear += getTheOperator();
for (int i = 0; i < getNbChildren(); i++) {
child = (FormulaTreeStructure) getChild(i);
if (i == 0)
linear += child.createLinear(linear);
else {
linear += "," + child.createLinear(linear);
}
}
return linear + ending;
}
 
/**
* Evaluates the instance.
*/
public String evaluate() {
return "";
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/FormulaBeanInfo.java
0,0 → 1,94
/*
$Id: FormulaBeanInfo.java,v 1.4 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.beans.*;
import java.beans.SimpleBeanInfo;
//import symantec.itools.beans.*;
 
public class FormulaBeanInfo extends java.beans.SimpleBeanInfo
{
public FormulaBeanInfo()
{
}
 
/**
* Gets a BeanInfo for the superclass of this bean.
* @return BeanInfo[] containing this bean's superclass BeanInfo
*/
public BeanInfo[] getAdditionalBeanInfo()
{
try
{
BeanInfo[] bi = new BeanInfo[1];
bi[0] = Introspector.getBeanInfo(beanClass.getSuperclass());
return bi;
}
catch (IntrospectionException e)
{
throw new Error(e.toString());
}
}
 
/**
* Gets the SymantecBeanDescriptor for this bean.
* @return an object of type SymantecBeanDescriptor
* @see symantec.itools.beans.SymantecBeanDescriptor
*/
public BeanDescriptor getBeanDescriptor()
{
BeanDescriptor bd = new BeanDescriptor(beanClass);
bd.setValue("CAN_ADD_CHILD",new Boolean(true));
 
return bd;
}
 
/**
* Gets an image that may be used to visually represent this bean
* (in the toolbar, on a form, etc).
* @param iconKind the type of icon desired, one of: BeanInfo.ICON_MONO_16x16,
* BeanInfo.ICON_COLOR_16x16, BeanInfo.ICON_MONO_32x32, or BeanInfo.ICON_COLOR_32x32.
* @return an image for this bean
* @see BeanInfo#ICON_MONO_16x16
* @see BeanInfo#ICON_COLOR_16x16
* @see BeanInfo#ICON_MONO_32x32
* @see BeanInfo#ICON_COLOR_32x32
*/
public java.awt.Image getIcon(int nIconKind)
{
java.awt.Image img = null;
if (nIconKind == BeanInfo.ICON_COLOR_16x16)
img = loadImage("Icon_Model_16.gif");
if (nIconKind == BeanInfo.ICON_COLOR_32x32)
img = loadImage("Icon_Model_32.gif");
return img;
}
 
private final static Class beanClass = Formula.class;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Rational.java
0,0 → 1,64
/*
$Id: Rational.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
*
* @author © 1999 DIRAT Laurent
* @version 2.0 28/06/1999
*/
public class Rational extends KaryOperator {
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
current = super.insert(current);
super.addElement();
return current;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
FormulaTreeStructure denominator = (FormulaTreeStructure) getChild(1).getChild(0);
if (denominator.isTemplate())
return denominator;
else
return this;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Differentiation.java
0,0 → 1,204
/*
$Id: Differentiation.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The differentiation operator.<BR>
* The first child corresponds to the function. The next child(ren) to the bound variable(s).
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class Differentiation extends Function {
private boolean gotoVariable = true;
/**
* <CODE>true</CODE> if the instance represents a partial differentiation.
* <CODE>false</CODE> otherwise.
*/
private boolean isPartial = false;
/**
* The order of the differentiation
*/
private int order = 1;
/**
* Returns <CODE>true</CODE> if the instance represents a partial differentiation.
* <CODE>false</CODE> otherwise.
*/
public boolean isPartial() {
return isPartial;
}
/**
* Sets if the instance repressents a partial differentiation
* @param isPartial <CODE>true</CODE> if the instance represents a partial differentiation.
* <CODE>false</CODE> otherwise.
*/
public void setIsPartial(boolean isPartial) {
this.isPartial = isPartial;
}
 
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
current = super.insert(current);
if (isPartial) {
Constant delta = new Constant();
delta.setResourceIdentifier("delta");
delta.setValue("delta");
current = delta.insert(current);
}
else
current = (new Variable("d")).insert(current);
current = super.addElement();
super.addElement();
return current;
}
/**
* Computes the order of the differentiation.
*/
public void computeOrder() {
Hashtable ht = new Hashtable();
FormulaTreeStructure fts, degree;
String varName;
for (int i = 2; i < getNbChildren(); i++) {
fts = (FormulaTreeStructure) getChild(i).getChild(0);
if (!fts.isOperator()) {
// donc on dit que c'est une variable
varName = ((VariableOrNumber) fts).getValue();
degree = (FormulaTreeStructure) ht.get(varName);
if (degree == null) {
degree = new Addition();
degree.addChild(new AnInteger("1"));
ht.put(varName, degree);
}
else
degree.addChild(new AnInteger("1"));
}
else {
// donc on dit que c'est une ^
varName = ((VariableOrNumber) fts.getChild(0)).getValue();
degree = (FormulaTreeStructure) ht.get(varName);
if (degree == null) {
degree = new Addition();
degree.addChild((FormulaTreeStructure) fts.getChild(1).clone());
ht.put(varName, degree);
}
else
degree.addChild((FormulaTreeStructure) fts.getChild(1).clone());
}
}
if (ht.size() > 1) {
isPartial = true;
fts = (FormulaTreeStructure) getChild(0);
fts.removeChild(0);
Constant delta = new Constant();
delta.setResourceIdentifier("delta");
delta.setValue("delta");
fts.addChild(delta);
}
fts = new Addition();
for (Enumeration e = ht.elements(); e.hasMoreElements(); )
fts.addChild((FormulaTreeStructure) e.nextElement());
String order_s = fts.evaluate();
try {
order = Integer.parseInt(order_s);
}
catch(NumberFormatException nfe) {
order = 0;
}
if (!order_s.equals("1")) {
fts = (FormulaTreeStructure) getChild(0).getChild(0);
fts = (new Superscript()).insert(fts);
fts = (new Variable(order_s)).insert(fts);
}
}
/**
* Returns the order of the differentiation.
* @return an positive number if the order is a numeric evaluation, 0 otherwise.
*/
public int getOrder() {
return order;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
if (gotoVariable) {
gotoVariable = false;
return (FormulaTreeStructure) getChild(2).getChild(0);
}
else
return super.addElement();
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
FormulaTreeStructure child;
// même chose que super.createLinear(String linear), sauf que l'indice de boucle part de 1,
// au lieu de 0. (le premier fils correspondant à l'ordre de la dérivée, qui n'intervient pas dans la
// syntaxe)
linear += getTheOperator();
for (int i = 1; i < getNbChildren(); i++) {
child = (FormulaTreeStructure) getChild(i);
if (i == 1)
linear += child.createLinear(linear);
else {
linear += "," + child.createLinear(linear);
}
}
return linear + getEnding();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/AnInteger.java
0,0 → 1,57
/*
$Id: AnInteger.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.openmath.jome.model.VariableOrNumber;
 
/**
* Integer elements in the formula.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/09/1999
*/
public class AnInteger extends VariableOrNumber {
/**
* The default constructor.<BR>
* Constructs a integer with no value. A default constuctor is needed for dynamic instantiation.
* The value must be set after instantiation.
*/
public AnInteger() {
this("");
}
/**
* The constructor.<BR>
* Contstructs an integer with the specified string value.
* @param value the integer value.
*/
public AnInteger(String value) {
super("INTEGER", value, true, true);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Limit.java
0,0 → 1,81
/*
$Id: Limit.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
*
* @author © 1999 DIRAT Laurent
* @version 2.0 28/06/1999
*/
public class Limit extends KaryOperator {
/*
*
*/
private boolean gotoVariable = true;
/*
*
*/
private boolean gotoBound = false;
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
current = super.insert(current);
super.addElement();
super.addElement();
return current;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
if (gotoVariable) {
gotoVariable = false;
gotoBound = true;
return (FormulaTreeStructure) getChild(1).getChild(0);
}
else if (gotoBound) {
gotoBound = false;
return (FormulaTreeStructure) getChild(2).getChild(0);
}
else
return super.addElement();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/resources2_en.java
0,0 → 1,3
package fr.ove.openmath.jome.model;
public class resources2_en{
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Substraction.java
0,0 → 1,142
/*
$Id: Substraction.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* The operator "-", which is the binary substraction.
* Because the substraction is defines as the addition of the opposite,
* <CODE>@see Substraction</CODE> doesn't represent a node in the formula tree structure.
* During its creation, it's in fact a <CODE>@see Addition</CODE> instance which is created
* and serves as a node in the formula tree structure, and an <CODE>@see UnaryMinus</CODE>
* instance is added as a child.
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/200
*/
public class Substraction extends BinaryOperator {
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param current the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// On cherche la position d'insertion de notre "-"
current = findLocation(current);
int currentAsOperandPriority = current.getAsOperandPriority();
int currentAsOperatorPriority = current.getAsOperatorPriority();
if (currentAsOperatorPriority == getAsOperandPriority()) {
// On a déjà tapé dans la formule un "-", on va donc insérer un nouveau
// "-" dans le précédent ==> cas particuliers.
if ((currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryPlusPriorities")) ||
(currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryMinusPriorities"))) {
// Si on est en précense de ce cas là, la position d'insertion est
// sur un op. unaire ("+" ou "-"). Il faut récupérer le père de l'op.
// en question, i.e. une instance d'Addition que l'on a inséré auparavant
// dansla FST.
FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
// Si notre position d'insertion est un "+" unaire, alors on va l'éliminer
// pour ne garder que son opérande. Ainsi, au lieu d'avoir +a-b, on aura a-b.
if (currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryPlusPriorities")) {
FormulaTreeStructure operand = (FormulaTreeStructure) current.getChild(0);
int rank = current.getRank();
father.addChild(operand, rank);
father.removeChild(current);
}
// On ajoute notre op. "-".
// (Rappel : "-" unaire à cause de la def. de la soustraction)
father = (new UnaryMinus()).insert(father);
// On retourne la reférence de notre dernier point d'insertion.
return father;
}
// Là, on est dans le cas où l'on a tapé une série de "+" ou de "-", et donc
// la position d'insertion est une instance d'Addition que l'on a inséré
// auparavant dans la FST. (tjrs le même rappel quand aux defs.)
current = (new UnaryMinus()).insert(current);
// On retourne la reférence de notre dernier point d'insertion.
return current;
}
else { // Première entrée d'une soustraction (et même, aucune addition n'a été
// saisie auparavant)
// On ajoute une instance d'Addition comme fils à l'opérateur courant
FormulaTreeStructure addition = new Addition();
current.addChild(addition);
if (current.getNbChildren() > 1) {
// Il faut que l'on fasse la distinction entre le fait de vouloir saisir une soustraction
// ou un moins unaire.
// Donc on vient d'ajouter une instance d'addition à current.
// Si on est là, 2 solutions, le fils de current qui a pour rank, le rank de
// l'instance d'addition -1 :
// * est un template ==> on saisi un moins unaire
// * n'est pas un template ==> on saisi une soustraction
FormulaTreeStructure fts = (FormulaTreeStructure) current.getChild(addition.getRank() - 1);
// Quelque soit le cas, on enlève fts de current.
// Dans le cas du moins unaire, (fts est un template) un template sera rajouté avec
// l'insertion du UnaryMinus
// Dans le cas de la soustraction, fts sera ajouté à l'instance d'addition
current.removeChild(fts);
if (!((fts.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("constantPriorities")) &&
fts.isTemplate())) {
// Donc, c'est une soustraction, fts est l'élement à qui on va soustraire qque chose.
// On l'ajoute donc comme fils (en fait ce sera la premier) à l'instance d'addition.
addition.addChild(fts);
}
// Par définition de la soustraction, on ajoute un opérateur "-"
// unaire comme fils à l'instance d'Addition.
addition = (new UnaryMinus()).insert(addition);
// On retourne la référence de notre dernier point d'insertion
return addition;
}
else { // on est dans le cas du moins unaire
// On ajoute un opérateur "-" unaire comme fils à l'instance d'Addition.
addition = (new UnaryMinus()).insert(addition);
// On retourne la reférence de notre dernier point d'insertion.
return addition;
}
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/E.java
0,0 → 1,52
/*
$Id: E.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* The number exp(1).<BR>
*
* @author © 2000 DIRAT Laurent
* @version 2.0 25/02/2000
*/
public class E extends StringLowerCaseConstant {
/**
* The Constructor.
*/
public E() {
setResourceIdentifier("E");
setValue("E");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("constantPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("constantPriorities"));
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Node.java
0,0 → 1,500
/*
$Id: Node.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import java.io.Serializable;
 
 
/**
* Definition of a N-ary tree structure.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 23/06/1999
*/
public abstract class Node implements Serializable, Cloneable {
/**
* The father of the instance in the tree structure
*/
private Node father;
 
/**
* The children of the instance in the tree structure
*/
private Vector children;
 
/**
* The rank of the instance in the set of its father's children
*/
private int rank;
/**
* The strahler number of the node
*/
private int nbStrahler;
/**
* The depth of the node in the tree structure.
* It corresponds in fact at the number of its ancestors. (so root.depth == 0)
*/
private int depth;
 
/**
* The Constructor.
*/
public Node() {
father = null;
rank = 0;
nbStrahler = 1;
depth = 0;
}
 
// ### The Accessors ###
 
/**
* Returns the father of the instance.
*
* @return the father of the node.
*/
public Node getFather() {
return father;
}
 
/**
* Returns the rank of the instance in the set of its father's children
*
* @return the rank of the node.
*/
public int getRank() {
return rank;
}
 
/**
* Returns the child of the instance at the specified rank.
*
* @param rank the specified rank.
* @return the child at the specified rank.
*/
public Node getChild(int rank) {
Node child = null;
if (children != null) {
try {
child = (Node) children.elementAt(rank);
}
catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
return child;
}
 
/**
* Returns the number of children of the instance.
*/
public int getNbChildren() {
int size = 0;
if (children != null)
size = children.size();
return size;
}
 
/**
* Returns the list of children of the instance.
*
* @return the list of children
*/
public Vector getChildren() {
return children;
}
 
// ### The Modifiers ###
 
/**
* Sets a father to instance.
*
* @param father the father to set
*/
public void setFather(Node father) {
this.father = father;
depth = father.depth + 1;
// On met à jour maintenant la profondeur des fils éventuels.
if (children != null)
adjustChildrenDepth();
}
 
/**
* Adds a child to the instance.<BR>
* The child added is the last of the list.
*
* @param child the child to add.
*/
public void addChild(Node child) {
if (children == null)
children = new Vector(0, 1);
children.addElement(child);
child.setFather(this);
adjustRank();
}
 
/**
* Adds a child to the instance.<BR>
* The child is added at the specified rank.
*
* @param child the child to add.
* @param rank the specified rank.
*/
public void addChild(Node child, int rank) {
if (children == null)
children = new Vector(0, 1);
children.insertElementAt(child, rank);
child.setFather(this);
adjustRank();
}
/**
* Removes the child of the current node at the specified rank.
*
* @param rank the rank of the child to remove.
*/
public void removeChild(int rank) {
if (children != null) {
children.removeElementAt(rank);
adjustRank();
}
}
 
/**
* Removes the specified child of the instance.
*
* @param node the child to remove.
*/
public void removeChild(Node node) {
if (children != null) {
children.removeElement(node);
adjustRank();
}
}
/**
* Remove all the children of the instance.
*/
public void removeAll() {
if (children != null) {
int count = children.size();
for (int i = 0; i < count; i++)
((Node) children.elementAt(rank)).father = null;
children.setSize(0);
children.trimToSize();
}
}
/**
* Sets the rank of the children of the instance.
*/
private void adjustRank() {
int i = 0;
 
for (Enumeration e = children.elements(); e.hasMoreElements(); i++)
((Node) e.nextElement()).rank = i;
}
/**
* Changes the rank of the instance.
*
* @param rank the new rank.
*/
private void changeRank(int rank) {
int oldRank = this.rank;
//Node father = this.father;
 
if (rank > father.getNbChildren()) {
rank = father.getNbChildren() + 1;
father.addChild(this); // On ajoute en dernier
}
else {
if (rank < 0)
rank = 0;
father.addChild(this, rank);
}
 
// On élimine le noeud courant situé à l'ancienne position
if (rank < oldRank)
father.removeChild(oldRank + 1); // l'insertion s'est faite avant, donc le fils courant est décalé de 1
else
father.removeChild(oldRank);
}
/**
* Moves the specified list of the instance children to the specified
* rank. The first child in the list has its rank setted to the specified
* one, the second to the first+1, ...and so on.
* @param list the list of the instance children.
* @param rank the specified rank.
*/
public void moveChildren(Vector list, int rank) {
// Puisque list contient des fils de l'instance, on peut partir du prérequis que
// children est non null.
int NbChildren = children.size();
Node child = null;
Node first = null;
for (int i = 0; i < list.size(); i++) {
child = (Node) list.elementAt(i);
if (i == 0)
first = child;
if (rank > NbChildren)
child.changeRank(rank + (i+1));
else {
child.changeRank(rank);
rank = first.getRank() + (i+1);
}
}
}
/**
* Checks if the specified node is a child of the current instance.
* @param node the specified node.
* @return <CODE>true</CODE> if the specified node is a child of the current
* instance. <CODE>false</CODE> otherwise.
*/
public boolean hasChild(Node node) {
boolean hasChild = false;
if (children != null)
hasChild = children.contains(node);
return hasChild;
}
/**
* Clones (copies) the instance.<BR>
* Make a deep clone, i.e. the children of the instance are also cloned.<BR>
* Nevertheless, the father of the clone is set to <CODE>null</CODE>.
*/
public synchronized Object clone(){
Node theClone = null;
try {
//return super.clone();
// On clone l'instance.
theClone = (Node) super.clone();
// Le père du clone est null
theClone.father = null;
if (children != null) {
// On clone les enfants
Vector theChildren = new Vector();
int count = children.size();
for (int i = 0; i < count; i++)
theChildren.addElement(((Node) children.elementAt(i)).clone());
theClone.children = theChildren;
}
} catch (CloneNotSupportedException e) {
System.out.println("clone failed !!");
}
return theClone;
}
/**
* Duplicates (copies) the instance.<BR>
* The difference with clone, is a deep copy is not performed.<BR>
* The father of the duplicate is set to <CODE>null</CODE>.
*/
public synchronized Object duplicate(){
Node theClone = null;
try {
// On clone l'instance.
theClone = (Node) super.clone();
// Le père du clone est null
theClone.father = null;
// Pas de fils
theClone.children = new Vector();
} catch (CloneNotSupportedException e) {
System.out.println("duplicate failed !!");
}
return theClone;
}
/*
* ############################################
* ### Les différents paramètres de l'arbre ###
* ############################################
*/
/*
* La profondeur de l'arbre
*/
/**
* Returns the depth of the node.
*/
public int getDepth() {
return depth;
}
/**
* Compute the depth of the node.
*/
public void computeDepth() {
int theDepth = 0;
Node theFather = father;
while (theFather != null) {
theDepth++;
theFather = theFather.father;
}
depth = theDepth;
// On met à jour maintenant la profondeur des fils éventuels.
if (children != null)
adjustChildrenDepth();
}
/**
* Adjusts the depth of the children of the node.
*/
private void adjustChildrenDepth() {
Node child = null;
int count = children.size();
for (int i = 0; i < count; i++) {
child = (Node) children.elementAt(i);
//child.depth++;
child.depth = depth + 1;
// On met à jour maintenant la profondeur des fils éventuels.
if (child.children != null)
child.adjustChildrenDepth();
}
}
/*
* Le nombre de Strahler
*/
/**
* Returns the strahler number of the node.
*/
public int getNbStrahler() {
return nbStrahler;
}
/**
* Sets the Strahler number of the instance.<BR>
* !!! ATTENTION !!! : should not be called at any time.
* Just specific cases only, above all, when you know what you are doing.
* @param nbStrahler the Strahler number value to set.
*/
public void setNbStrahler(int nbStrahler) {
this.nbStrahler = nbStrahler;
}
/**
* Computes the strahler number of the node.
* Prerequisite : the strahler number of the children of the instance are computed.
*/
private void computeNodeNbStrahler() {
// Si children == null, alors ça veut dire que l'instance est une feuille, et donc le
// Strahler est déjà initialisé à 1.
if (children != null) {
int count = children.size();
if (count == 0)
// ça c'est au cas où des manipulations sur l'arbre, mais normalement, pas de soucis.
nbStrahler = 1;
else if (count == 1)
nbStrahler = ((Node) children.elementAt(0)).nbStrahler;
else {
int max = 0;
int min = Integer.MAX_VALUE;
int tmpStrahler;
for (int i = 0; i < count; i++) {
tmpStrahler = ((Node) children.elementAt(i)).nbStrahler;
min = (min < tmpStrahler) ? min : tmpStrahler;
max = (max > tmpStrahler) ? max : tmpStrahler;
}
int tabLength = max - min + 1;
int tabValue[] = new int[tabLength];
for (int i = 0; i < tabLength; i++)
tabValue[i] = 0;
for (int i = 0; i < count; i++)
tabValue[((Node) children.elementAt(i)).nbStrahler - min] += 1;
int free = max - 1;
tmpStrahler = max + tabValue[tabLength - 1] - 1;
int requiered;
for (int i = tabLength - 2; i >= 0; i--) {
if (tabValue[i] == 0)
continue;
requiered = i + min + tabValue[i] - 1;
if (free > requiered)
free -= tabValue[i];
else {
tmpStrahler += requiered - free;
free = i + min - 1;
}
}
nbStrahler = tmpStrahler;
}
}
}
/**
* Computes the strahler number of the tree whose the instance is the root
*/
public void computeNbStrahler() {
if (children != null) {
int count = children.size();
for (int i = 0; i < count; i++)
((Node) children.elementAt(i)).computeNbStrahler();
computeNodeNbStrahler();
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/StringLowerCaseConstant.java
0,0 → 1,48
/*
$Id: StringLowerCaseConstant.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.openmath.jome.model.FormulaTreeStructure;
import fr.ove.openmath.jome.model.events.ModelEvent;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class StringLowerCaseConstant extends Constant {
// Juste pour des cas spéciaux qui font que la syntaxe linéaire de la constante est faite en majucules,
// par exemple e (exp(1)) et i (i^2 = -1) alors que l'affichage de la constante est fait en minuscules.
/**
* Returns the value.
*/
public String getValue() {
return (super.getValue()).toLowerCase();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Mfd2Substitution.java
0,0 → 1,67
/*
$Id: Mfd2Substitution.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The substitution model of the symbol, with the same name, in the Mfd2 cd.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 28/10/1999
*/
public class Mfd2Substitution extends Function {
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// Surchage le la méthode insert(..) car on ne veut pas qu'un template soit inséré,
// mais une instance de SubstitutionElement.
// C'est en qques sorte SubstitutionElement qui se charge de l'aspet 2n-aire de la chose.
// Donc insertion classique...
current = super.insert(current);
// ...mais à la place du template, on met un SubstitutionElement
return (new Mfd2SubstitutionElement()).insert(current);
}
/**
* Adds a new SubstitutionElement to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
// Pareil que pour insert, on veut un SubstitutionElement à la place d'un template
FormulaTreeStructure current = super.addElement();
return (new Mfd2SubstitutionElement()).insert(current);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Variable.java
0,0 → 1,57
/*
$Id: Variable.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.openmath.jome.model.VariableOrNumber;
 
/**
* Variable elements in the formula.
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class Variable extends VariableOrNumber {
/**
* The default constructor.<BR>
* Constructs a variable with no name. A default constuctor is needed for dynamic instantiation.
* The name of hte variable must be set after instantiation
*/
public Variable() {
this("");
}
/**
* The constructor.<BR>
* Contstructs a variable with the specified name.
* @param varName the name of the variable.
*/
public Variable(String varname) {
super("VARIABLE", varname, false, false);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/evaluation/Evaluator.java
0,0 → 1,151
/*
$Id: Evaluator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.evaluation;
 
public final class Evaluator {
public static String evaluate(String operand1, String operand2, String anOperator) {
String oper1 = removeBrackets(operand1);
String oper2 = removeBrackets(operand2);
double result;
if (anOperator.equals("+")) {
if (isNumber(oper1) && isNumber(oper2))
return cutDecimal((Double.valueOf(oper1)).doubleValue() + (Double.valueOf(oper2)).doubleValue());
else
// Si la seconde opérande est un -, alors il ne faudra pas insérer le + entre les 2
anOperator = (oper2.charAt(0) == '-') ? "" : anOperator;
}
else if (anOperator.equals("-")) {
if (isNumber(oper1) && isNumber(oper2))
return cutDecimal((Double.valueOf(oper1)).doubleValue() - (Double.valueOf(oper2)).doubleValue());
}
else if (anOperator.equals("*")) {
if (isNumber(oper1) && isNumber(oper2))
return cutDecimal((Double.valueOf(oper1)).doubleValue() * (Double.valueOf(oper2)).doubleValue());
}
else if (anOperator.equals("/")) {
if (isNumber(oper1) && isNumber(oper2))
return cutDecimal((Double.valueOf(oper1)).doubleValue() / (Double.valueOf(oper2)).doubleValue());
}
else if (anOperator.equals("^")) {
if (isNumber(oper1) && isNumber(oper2))
return cutDecimal(Math.pow((Double.valueOf(oper1)).doubleValue(), (Double.valueOf(oper2)).doubleValue()));
}
return operand1 + anOperator + operand2;
}
public static String evaluate(String function, String argument) {
function = function.toLowerCase();
argument = removeBrackets(argument);
if (function.equals("sin")) {
if (isNumber(argument))
return cutDecimal(Math.sin((Double.valueOf(argument)).doubleValue()));
}
if (function.equals("arcsin")) {
if (isNumber(argument))
return cutDecimal(Math.asin((Double.valueOf(argument)).doubleValue()));
}
if (function.equals("cos")) {
if (isNumber(argument))
return cutDecimal(Math.cos((Double.valueOf(argument)).doubleValue()));
}
if (function.equals("arccos")) {
if (isNumber(argument))
return cutDecimal(Math.acos((Double.valueOf(argument)).doubleValue()));
}
if (function.equals("tan")) {
if (isNumber(argument))
return cutDecimal(Math.tan((Double.valueOf(argument)).doubleValue()));
}
if (function.equals("arctan")) {
if (isNumber(argument))
return cutDecimal(Math.atan((Double.valueOf(argument)).doubleValue()));
}
if (function.equals("sqrt")) {
if (isNumber(argument))
return cutDecimal(Math.sqrt((Double.valueOf(argument)).doubleValue()));
}
return function + "(" + argument + ")";
}
public static int type(String argument) {
 
argument = removeBrackets(argument);
if (isNumber(argument))
return 0;
else
return 1;
}
/**
* Analyzes a token and determines whether it is a number or not.<BR>
*
* @param token the token to analyze.
* @return <CODE>true</CODE> if the token is a number. <CODE>false</CODE> otherwise.
*/
private static boolean isNumber(String token) {
char oneChar;
token = removeBrackets(token);
for (int i = 0; i < token.length(); i++) {
oneChar = token.charAt(i);
if (!Character.isDigit(oneChar) && (oneChar != '.'))
if (!((i == 0) && (oneChar == '-')))
return false;
}
return true;
}
/**
*
*/
private static String removeBrackets(String token) {
if ((token.charAt(0) == '(') && (token.charAt(token.length() - 1) == ')'))
return token.substring(1, token.length() - 1);
else
return token;
}
/**
*
*/
private static String cutDecimal(double value) {
if ((value - Math.floor(value)) < 10e-5)
return "" + (int) Math.floor(value);
else
return "" + value;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/I.java
0,0 → 1,52
/*
$Id: I.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* The complex number i.<BR>
*
* @author © 2000 DIRAT Laurent
* @version 2.0 25/02/2000
*/
public class I extends StringLowerCaseConstant {
/**
* The Constructor.
*/
public I() {
setResourceIdentifier("I");
setValue("I");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("constantPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("constantPriorities"));
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/resources2_en.properties
0,0 → 1,218
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
#
# identifier = className:operatorPriorities:operatorArity
# operatorPriorities = asOperatorPriority:asOperandPriority
#
# identifier is the identifier of the resource. Corresponds to what the control (i.e. the control part of the MVC
# pattern, so in our case, the parser(s)) send to the model to build it. See the parser for explanation of the
# different of the different tokens and their use.
#
# className is the class to instanciate. The class name is fully qualified and then contains the name of the package
# where the class is.
#
# asOperatorPriority is the priority of the operator when it is considered as an operator (i.e. we are inserting
# operand(s) to the operator in the formula tree structure). Its value is a number.
#
# asOperandPriority is the priority of the operator when it is considered as an operand. (i.e we are inserting the
# operator in the formula tree structure). Its value is a number.
#
# operatorArity is the operator arity. This field is in fact only used for K-ary operators, the class to
# instanciate is then fr.ove.openmath.jome.model.KaryOperator. (more generally, all subclasses of KaryOperator)
# Of course, its value is a positive number. In all the other cases, this field is omitted.
#
# Two specific keywords are defined for each field.
# refine when the element we want to insert is not completely defined for its token. It is the case for FUNCTION,
# RESERVED and SPECIALIZED.
# The function term contains all operators whose linear syntax is name(...). According to the name of the function,
# we have to ...refine all the field to instanciate the correct object. The same for the to others.
# null when the token received not used as an identifier of a class to instanciate to insert in the formula tree
# structure (e.g. CLOSE_PAREN, SEPRATOR,...) or when the value has no importance.
 
formulaPriorities = 0:0
slotPriorities = 0:1000
bracketPriorities = 5:1000
binaryPriorities = 10:10
unaryPlusPriorities = 100:102
unaryMinusPriorities = 100:101
plusPriorities = 100:100
timesPriorities = 200:200
dividePriorities = 300:301
powerPriorities = 500:450
factorialPriorities = 1000:900
constantPriorities = 1000:1000
rondPriorities = 10:11
 
# not directly instanciated (private)
UNARYPLUS = fr.ove.openmath.jome.model.UnaryOperator:unaryPlusPriorities
UNARYMINUS = fr.ove.openmath.jome.model.UnaryOperator:unaryMinusPriorities
SLOT = fr.ove.openmath.jome.model.Slot:slotPriorities
ICON = fr.ove.openmath.jome.model.Icon:constantPriorities
 
# The formula (the most prioritary of all)
FORMULA = fr.ove.openmath.jome.model.Formula:formulaPriorities
 
# Constants
VARIABLE = fr.ove.openmath.jome.model.Variable:constantPriorities
INTEGER = fr.ove.openmath.jome.model.AnInteger:constantPriorities
FLOAT = fr.ove.openmath.jome.model.AFloat:constantPriorities
 
# N-ary operators (of "first" kind)
ADDITION = fr.ove.openmath.jome.model.Addition:plusPriorities
SUBSTRACTION = fr.ove.openmath.jome.model.Substraction:plusPriorities
MULTIPLICATION = fr.ove.openmath.jome.model.Multiplication:timesPriorities
 
# Binary operators
DIVISION = fr.ove.openmath.jome.model.BinaryOperator:dividePriorities
POWER = fr.ove.openmath.jome.model.BinaryOperator:powerPriorities
EQUAL = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
UNEQUAL = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
LESS = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
LESSEQUAL = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
GREATER = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
GREATEREQUAL = fr.ove.openmath.jome.model.BinaryOperator:binaryPriorities
UNDERSCRIPT = fr.ove.openmath.jome.model.BinaryOperator:powerPriorities
 
# RESPECT space before and after the name of the operator, otherwise when linear exportation
# operands will be attached.
in = fr.ove.openmath.jome.model.NamedBinaryOperator:binaryPriorities
notin = fr.ove.openmath.jome.model.NamedBinaryOperator:binaryPriorities
union = fr.ove.openmath.jome.model.NamedBinaryOperator:binaryPriorities
 
langle = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
rangle = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
lbracket = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
rbracket = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
cup = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
neq = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
mapsto = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
and = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
or = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
rightarrow = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
 
alpha = fr.ove.openmath.jome.model.Constant:constantPriorities
alfa = fr.ove.openmath.jome.model.Constant:constantPriorities
beta = fr.ove.openmath.jome.model.Constant:constantPriorities
chi = fr.ove.openmath.jome.model.Constant:constantPriorities
epsilon = fr.ove.openmath.jome.model.Constant:constantPriorities
eta = fr.ove.openmath.jome.model.Constant:constantPriorities
gamma = fr.ove.openmath.jome.model.Constant:constantPriorities
iota = fr.ove.openmath.jome.model.Constant:constantPriorities
kappa = fr.ove.openmath.jome.model.Constant:constantPriorities
mu = fr.ove.openmath.jome.model.Constant:constantPriorities
nabla = fr.ove.openmath.jome.model.Constant:constantPriorities
nu = fr.ove.openmath.jome.model.Constant:constantPriorities
omega = fr.ove.openmath.jome.model.Constant:constantPriorities
phi = fr.ove.openmath.jome.model.Constant:constantPriorities
psi = fr.ove.openmath.jome.model.Constant:constantPriorities
rho = fr.ove.openmath.jome.model.Constant:constantPriorities
tau = fr.ove.openmath.jome.model.Constant:constantPriorities
theta = fr.ove.openmath.jome.model.Constant:constantPriorities
upsilon = fr.ove.openmath.jome.model.Constant:constantPriorities
zeta = fr.ove.openmath.jome.model.Constant:constantPriorities
sigma = fr.ove.openmath.jome.model.Constant:constantPriorities
xi = fr.ove.openmath.jome.model.Constant:constantPriorities
# Functions (in general, so need refinements)
FUNCTION = refine
 
# Functions refinements
defaultFunction = fr.ove.openmath.jome.model.Function:constantPriorities
 
abs = fr.ove.openmath.jome.model.Function:constantPriorities
conj = fr.ove.openmath.jome.model.Function:constantPriorities
 
# N-ary operators (of "second" kind)
set = fr.ove.openmath.jome.model.Function:constantPriorities
 
request = fr.ove.openmath.jome.model.Function:constantPriorities
entry = fr.ove.openmath.jome.model.Function:constantPriorities
 
lambda = fr.ove.openmath.jome.model.LambdaExpression:constantPriorities
subst = fr.ove.openmath.jome.model.Mfd2Substitution:constantPriorities
diff = fr.ove.openmath.jome.model.Differentiation:constantPriorities
 
# K-ary operators
int = fr.ove.openmath.jome.model.Integral:constantPriorities:4
sum = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:3
array = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:3
prod = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:3
root = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:2
sqrt = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:1
lim = fr.ove.openmath.jome.model.Limit:constantPriorities:3
 
# Les mots réservés
RESERVED = refine
 
pi = fr.ove.openmath.jome.model.Constant:constantPriorities
C = fr.ove.openmath.jome.model.Constant:constantPriorities
N = fr.ove.openmath.jome.model.Constant:constantPriorities
Q = fr.ove.openmath.jome.model.Constant:constantPriorities
R = fr.ove.openmath.jome.model.Constant:constantPriorities
Z = fr.ove.openmath.jome.model.Constant:constantPriorities
delta = fr.ove.openmath.jome.model.Constant:constantPriorities
I = fr.ove.openmath.jome.model.StringLowerCaseConstant:constantPriorities
E = fr.ove.openmath.jome.model.StringLowerCaseConstant:constantPriorities
infty = fr.ove.openmath.jome.model.Constant:constantPriorities
true = fr.ove.openmath.jome.model.Variable:constantPriorities
false = fr.ove.openmath.jome.model.Variable:constantPriorities
 
 
# Les délimiteurs
OPEN_PAREN = fr.ove.openmath.jome.model.Bracket:bracketPriorities
CLOSE_PAREN = null
 
OPEN_BRACKET = fr.ove.openmath.jome.model.Bracket:constantPriorities
CLOSE_BRACKET = null
// Revoir en fonction des listes horizontales ou verticales
OPEN_CURLY = fr.ove.openmath.jome.model.Liste:constantPriorities
CLOSE_CURLY = null
vlist = fr.ove.openmath.jome.model.Function:constantPriorities
 
# Les séparateurs
SEPARATOR = null
 
 
# Les opérateurs spécialisés
SPECIALIZED = refine
 
# Raffinement pour les opérateurs spécialisés
? = fr.ove.openmath.jome.model.RequestVariable:constantPriorities
fact = fr.ove.openmath.jome.model.Factorial:factorialPriorities
 
 
# Add-ons
delta = fr.ove.openmath.jome.model.Constant:constantPriorities
gamma = fr.ove.openmath.jome.model.Constant:constantPriorities
 
#rondPriorities = 11:10
 
o = fr.ove.openmath.jome.model.NamedBinaryOperator:rondPriorities
 
gcd = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:2
quotient = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:2
rem = fr.ove.openmath.jome.model.KaryOperator:constantPriorities:2
cc = fr.ove.openmath.jome.model.ComplexCartesian:constantPriorities:1
cp = fr.ove.openmath.jome.model.ComplexPolar:constantPriorities:1
 
rat = fr.ove.openmath.jome.model.Rational:constantPriorities:2
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/FormulaResourcesManager.java
0,0 → 1,117
/*
$Id: FormulaResourcesManager.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.utils.CachingResourcesManager;
 
/**
* The resources manager for the formula.<BR>
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class FormulaResourcesManager extends CachingResourcesManager {
/**
* Constructor
* @param resourcesName the name of the resources file. <BR> he name is specified without the ".properties"
* extension. If the property file is located in a package, the fully qualified name (e.g. my.package.filename)
* must be used.
*/
public FormulaResourcesManager(String resourcesName) {
super(resourcesName);
}
/**
* Returns the class name corresponding to the specified property.
* @param property the specified property
*/
public String getClassName(String property) {
return accessResource(property, 0);
}
/**
* Returns the arity resource corresponding to the specified property.
* @param property the specified property
*/
public Integer getArity(String property) {
String arity = accessResource(property, 2);
Integer value = null; // On choisi un Integer putôt qu'un int pour des retours possibles de null
if (arity != null) {
try {
value = Integer.valueOf(arity);
}
catch (NumberFormatException fne) {
System.out.println("Wrong operator arity : " + property);
}
}
return value;
}
public String getPrioritiesIdentifier(String property) {
return accessResource(property, 1);
}
/**
* Returns the as operator resource corresponding to the specified property.
* @param property the specified property
*/
public int getAsOperatorPriority(String property) {
String priority = accessResource(property, 0);
int value = 0;
try {
value = Integer.valueOf(priority).intValue();
}
catch (NumberFormatException fne) {
System.out.println("Wrong specification of as operator priority : " + priority);
}
return value;
}
/**
* Returns the as operand resource corresponding to the specified property.
* @param property the specified property
*/
public int getAsOperandPriority(String property) {
String priority = accessResource(property, 1);
int value = 0;
try {
value = Integer.valueOf(priority).intValue();
}
catch (NumberFormatException fne) {
System.out.println("Wrong specification of as operand priority : " + priority);
}
return value;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Operator.java
0,0 → 1,88
/*
$Id: Operator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* @author © 1999 DIRAT Laurent
* @version 2.0 24/06/1999
*/
public abstract class Operator extends FormulaTreeStructure {
/**
* The operator name
*/
private String value;
 
/**
* Returns the name of the operator.
*/
public String getTheOperator() {
return value;
}
/**
* Sets the name of the operator.
* @param theOperator the name of the operator.
*/
public void setTheOperator(String theOperator) {
value = theOperator;
}
/**
* To check is the instance is an operator.
* @return <CODE>true</CODE> if it is an operator. <CODE>false</CODE> otherwise.
*/
public boolean isOperator() {
return true;
}
// *****************************************
// Implémentation de l'interface Modifiable
/**
* Sets the value.
*/
public void setValue(String value) {
this.value = value;
}
/**
* Returns the value.
*/
public String getValue() {
return value;
}
// *** Fin de l'interface Modifiable ***
// *************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Multiplication.java
0,0 → 1,58
/*
$Id: Multiplication.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* The operator "*", which is the binary multiplication.
* (In fact, for implementation needs, we consider it as an n-ary operator)<BR>
*
* <CODE>Multiplication</CODE> represents a node in the formula tree.
* Its children are the operands of the operation.
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class Multiplication extends NaryOperator {
/**
* The Constructor.
*/
public Multiplication() {
setResourceIdentifier("MULTIPLICATION");
setValue("");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("timesPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("timesPriorities"));
setAreOperandsMovable(true);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/RequestVariable.java
0,0 → 1,59
/*
$Id: RequestVariable.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.openmath.jome.model.VariableOrNumber;
 
/**
* Variable elements in the formula.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/09/1999
*/
public class RequestVariable extends VariableOrNumber {
/**
* The default constructor.<BR>
* Constructs a variable with no name. A default constuctor is needed for dynamic instantiation.
* The name of the variable must be set after instantiation
*/
public RequestVariable() {
setIsRequestVariable(true);
}
/**
*
*/
public void setValue(String value) {
// surcharge, parce que tant que l'instance est un template, on veut que la valeur soit
// [?] (la manière dont sont représentés les templates), plutôt que ? (la manière dont est
// saisie une request variable.
if (!isTemplate())
super.setValue(value);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Mfd2SubstitutionElement.java
0,0 → 1,120
/*
$Id: Mfd2SubstitutionElement.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The elements of an Mfd2substitution object.<BR>
* It is an operator of arity 2.
* <P>
* In fact, this object _MUST_ be instanciate by the Mfd2Substitution object, and only by it.
* Independently of the Mfd2Substitution object, the instance doesn't make any sense.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 27/10/1999
*/
public class Mfd2SubstitutionElement extends KaryOperator {
private boolean gotoVariable = true;
private boolean addNewInstance = false;
/**
* The Constructor.
*
*/
public Mfd2SubstitutionElement() {
// le nom du Cd et le nom du symbol sont mis a "" car l'instance ne correspond à aucun symbol dans
// un cd. L'instance est juste un constituant d'un opérateur correspondant à un symbol dans un cd
// Même remarque en ce qui concerne la forme linéaire (nom opérateur et ending).
//super("substElem", "", 2, "", "");
setResourceIdentifier("substElem");
setTheOperator("");
setOperatorArity(2);
setEnding("");
}
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// Surcharge car on insère un template supplémentaire pour coller à l'arité du symbol
current = super.insert(current);
super.addElement();
return current;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
// surchage car :
// * si gotoVariable, le addElement correspond à se positionner sur le second template
// * si addNewInstance, alors ça veut dire que l'on veut ajouter un autre élément (i.e. instance)
// C'est dû au fait que l'instance gère l'aspet 2n-aire d'un opérateur (dont l'instance est un
// opérande) dont la saisie est la même que pour une opérateur n-aire.
if (gotoVariable) {
gotoVariable = false;
addNewInstance = true;
return (FormulaTreeStructure) getChild(1).getChild(0);
}
else if (addNewInstance) {
// On veut ajouter un autre élement, donc il faut remonter sur le grand-père (car en fait
// le père est un Slot) et ajouter un élément au père.
addNewInstance = false;
return ((Mfd2Substitution) getFather().getFather()).addElement();
}
else
return super.addElement(); // normalement ne devrait pas être appelé, sinon non respect arité.
}
 
/**
* The Creation of the corresponding OpenMath object.
*
* @param OM_Object the OpenMath object.
* @param start start point for writing the OpenMath syntax for good presentation/indentation.
* @param indent the size of the indentation.
* @return the corresponding OpenMath object.
*
public String createOpenMath(String OM_Object, String start, String indent) {
// En fait, l'instance ne sera instancié que par Mfd2Substitution qui à vraiment un correspondance
// avec un objet OM.
// Donc surcharge, puisque l'instance n'a pas de CD, et on retourne seulement les objets contenus
// succéssivement.
OM_Object = ((FormulaTreeStructure) getChild(0)).createOpenMath(OM_Object, start+indent, indent);
OM_Object = ((FormulaTreeStructure) getChild(1)).createOpenMath(OM_Object, start+indent, indent);
return OM_Object;
}
*/
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/VariableOrNumber.java
0,0 → 1,214
/*
$Id: VariableOrNumber.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* Elements in the formula such as variables (letters) and numbers.<BR>
* <CODE>VariableOrNumber</CODE> represents a node in the formula tree.
* Terminal node, so leaves.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 24/06/1999
*/
public class VariableOrNumber extends Constant {
/**
* To check if the Constant is a number or not.
*/
private boolean isNumber;
/**
* To check if the number represented by the Constant is an integer or a float.
* So if the value is <CODE>true</CODE>, it's an integer; Otherwise, it's a float.
*/
private boolean isInteger;
/**
* To indicate that we have a constant with a specific signification.<BR>
* In this particular case, it's a request variable (from the mfd2 CD). <BR>
* By default, it is not a request variable.
*/
private boolean isRequestVariable = false; // à voir plus tard mais probablement à virer.
 
/**
* The default constructor.<BR>
* Constructs a template.
*/
public VariableOrNumber() {
this("VARIABLE", "[?]", false, false);
setIsTemplate(true);
}
/**
* The Constructor.
*
* @param value the value of the constant.
* @param isNumber to set if the constant is a number or not.
* @param isInteger to set, if the constant is a numbern if it is an integer or a float.
*/
public VariableOrNumber(String resourceIdentifier, String value, boolean isNumber, boolean isInteger) {
super();
setResourceIdentifier(resourceIdentifier);
setValue(value);
this.isNumber = isNumber;
this.isInteger = isInteger;
}
/**
* Sets the constant as a number.
* @param isNumber <CODE>true</CODE> if it is a number.<CODE>false</CODE>
* otherwise.
*/
public void setIsNumber(boolean isNumber) {
this.isNumber = isNumber;
}
/**
* Returns <CODE>true</CODE> if it is a number.<BR>
* <CODE>false</CODE> otherwise.
*/
public boolean isNumber() {
return isNumber;
}
/**
* Sets the constant, which is a number, as an integer or as a float.
* @param isInteger <CODE>true</CODE> if it is an integer.<CODE>false</CODE>
* if it is a float.
*/
public void setIsInteger(boolean isInteger) {
this.isInteger = isInteger;
}
/**
* Returns <CODE>true</CODE> if it is an integer.<CODE>false</CODE>
* if it is a float.
*/
public boolean isInteger() {
return isInteger;
}
 
/**
* Sets the constant as a request variable.
*/
public void setIsRequestVariable(boolean isRequestVariable) {
this.isRequestVariable = isRequestVariable;
}
/**
* Returns <CODE>true</CODE> if it is a request variable.<BR>
* <CODE>false</CODE> otherwise.
*/
public boolean isRequestVariable() {
return isRequestVariable;
}
 
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
if (isTemplate()) {
if (isRequestVariable)
return super.insert(current);
// Si l'instance que l'on doit insérer est un template, alors on l'insère
// directement à la position courante (heuu... on sait ce qu'on fait ;o) )
current.addChild(this);
return this;
}
else { // L'instance n'est pas un template.
if (current.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("constantPriorities")) {
// A ce stade 2 solutions. Soit :
// * current est un template, alors encore 2 possibilités. Soit :
// - current est une request variable, alors si l'instance est une variable, c'est qu'on
// est en train de saisir sa valeur. Sinon, c'est une erreur syntaxique, on remplace
// la request variable, par l'instance.
// - current n'est pas une request variable, on remplace current par l'instance
// * current n'est pas un template, il faut donc créer une multiplication implicite.
if (current.isTemplate()) {
if (((VariableOrNumber) current).isRequestVariable && !isNumber) {
current.setIsTemplate(false);
((VariableOrNumber) current).setValue(getValue());
return current;
}
else {
FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
father.addChild(this, current.getRank());
father.removeChild(current);
return this;
}
}
else {// on créé donc une multiplication implicite.
current = (new Multiplication()).insert(current);
current = insert(current);
return current;
}
}
else { // On est dans le cas de l'insertion courante d'une constante dans la FTS
if ((current.getFather() == null) && (current.getNbChildren() == 0)) {
// On est dans ce cas là, seulement au tout début de la saisie de la
// formule. On est obligé de faire ce test à cause de la multiplication
// implicite avec les parenthèses (Ex: (a+b)c ==> (a+b)*c, dans ce cas là,
// current.getNbChildren() est != de 0)
//On insère directement à la position courante
current.addChild(this);
return this;
}
else { // On est dans aucun des cas précédents, on créé donc une
// multiplication implicite.
current = (new Multiplication()).insert(current);
current = insert(current);
return current;
}
}
}
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
if (isRequestVariable)
linear += "?";
if (!isTemplate())
linear += getValue();
return linear;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/BinaryOperator.java
0,0 → 1,116
/*
$Id: BinaryOperator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* @author © 1999 DIRAT Laurent
* @version 2.0 25/06/1999
*/
public class BinaryOperator extends Operator {
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
VariableOrNumber template;
// On cherche la position d'insertion de notre operateur
current = findLocation(current);
// Pas de problème de priorité pour ce type d'opérateur.
// On doit juste savoir si current est une instance de Formula pour gérer le cas
// particulier où, la formule vide, on veut saisir un tel opérateur et donc insertion
// des templates adequat ==> [?] ope [?].
// On ajoute l'opérateur comme fils à l'opérateur courant
current.addChild(this);
 
if ((current.getFather() == null) && (current.getNbChildren() == 1)) {
template = new VariableOrNumber();
addChild(template); // On ajoute le premier template.
}
else {
FormulaTreeStructure fts = (FormulaTreeStructure) current.getChild(getRank() - 1);
// à cause des priorités sur les opérateurs, on ajoute comme fils l'opérateur
// dont le rang est juste inférieur à notre instance
addChild(fts);
// On doit faire attention à quel type d'opérateur on a affaire.
// Si fts est les parenthèse, elles ne sont pas visibles si l'instance courante est une fraction.
// Dans les autres cas, elles le sont.
int prio = fts.getAsOperatorPriority();
if (prio == resourcesManager.getAsOperatorPriority("bracketPriorities")) {
prio = getAsOperatorPriority();
if (prio == resourcesManager.getAsOperatorPriority("dividePriorities"))
((Bracket) fts).setIsVisible(false);
else
((Bracket) fts).setIsVisible(true);
}
// on enlève l'opérateur qu'on a fait "descendre", de la liste
// de son précédent père (son grand père maintenant)
current.removeChild(fts);
}
 
// On ajoute un template à la division
template = new VariableOrNumber();
addChild(template);
 
// On retourne la reférence de notre dernier point d'insertion.
return template;
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
linear = ((FormulaTreeStructure) getChild(0)).createLinear(linear);
linear += getTheOperator();
linear = ((FormulaTreeStructure) getChild(1)).createLinear(linear);
return linear;
}
 
/**
* Evaluates the instance.
*/
public String evaluate() {
return Evaluator.evaluate(((FormulaTreeStructure) getChild(0)).evaluate(),
((FormulaTreeStructure) getChild(1)).evaluate(),
getTheOperator());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/ComplexCartesian.java
0,0 → 1,97
/*
$Id: ComplexCartesian.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
*
* @author © 1999 DIRAT Laurent
* @version 2.0 28/06/1999
*/
public class ComplexCartesian extends KaryOperator {
/*
* Pour savoir si on est dans le cas où il faut positionner current sur la partie imaginaire ou pas
*/
private boolean gotoImaginary = true;
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
current = super.insert(current);
FormulaTreeStructure realPart = current;
realPart.setIsTemplate(false);
current = (new Addition()).insert(current);
realPart.setIsTemplate(true);
// Construction de la partie imaginaire.
current = (new I()).insert(current);
current = (new Multiplication()).insert(current);
current = (new VariableOrNumber()).insert(current);
return realPart;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
if (gotoImaginary) {
gotoImaginary = false;
FormulaTreeStructure imaginay = (FormulaTreeStructure) getChild(0); // le slot
imaginay = (FormulaTreeStructure) imaginay.getChild(0); // l'addition
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la multiplication
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la partie imaginaire
return imaginay;
}
else
return this;
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
FormulaTreeStructure imaginay = (FormulaTreeStructure) getChild(0); // le slot
imaginay = (FormulaTreeStructure) imaginay.getChild(0); // l'addition
FormulaTreeStructure realPart = (FormulaTreeStructure) imaginay.getChild(0);
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la multiplication
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la partie imaginaire
linear = realPart.createLinear(linear + getTheOperator());
linear = imaginay.createLinear(linear + ",");
return linear + ")";
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/UnaryPlus.java
0,0 → 1,77
/*
$Id: UnaryPlus.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.FormulaTreeStructure;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The operator "+", which is the unary plus.<BR>
*
* <CODE>UnaryPlus</CODE> represents a node in the formula tree.<BR>
* Its children are the operands of the operation.
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class UnaryPlus extends UnaryOperator {
/**
* The Constructor.
*/
public UnaryPlus() {
setResourceIdentifier("UNARYPLUS");
setValue("+");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("unaryPlusPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("unaryPlusPriorities"));
}
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// Le seul moment où l'on fait appel à cet opérateur, c'est pour la saisie d'un
// plus unaire, et donc où l'on a une instance de Addition qui est en fait notre
// point d'insertion courant, i.e. current.
// On peut ajouter l'instance courante telle qu'elle.
current.addChild(this);
// On insère notre template dans le FTS
VariableOrNumber template = new VariableOrNumber();
addChild(template);
 
// On retourne la reférence de notre dernier point d'insertion.
return template;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Factorial.java
0,0 → 1,61
/*
$Id: Factorial.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
 
/**
* The factorial operator
*
* @author © 2000 DIRAT Laurent
* @version 2.1 24/02/2000
*/
public class Factorial extends UnaryPostfixedOperator {
/**
* The constructor.
*/
public Factorial() {
super();
setTheOperator("!");
}
/**
* Set the specified value
* @param the value to set.
*/
public void setValue(String value) {
// Surcharge et on ne fait rien car le nom de l'opérateur est spécifé dans le constructeur.
// C'est nécessaire parce que danslefchier de ressources, il semble qu'il y ait des pb avec "!"
// comme identificateur. D'où l'identificateur "fact".
// Si pas surcharge, le nom de lopérateur sera "fact" et non "!" comme attendu.
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Integral.java
0,0 → 1,77
/*
$Id: Integral.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
*
* @author © 1999 DIRAT Laurent
* @version 2.0 28/06/1999
*/
public class Integral extends KaryOperator {
/*
* Pour savoir si on est dans le cas où il faut positionner current sur la variable d'intégration
* où si on doit effectivement ajouter un nouvel élement (la borne inf au moins).
* A la création de l'instance, on ajoute un template pour l'intégrande, mais aussi un pour la
* variable d'intégration (on aura [?]d[?]). Donc, quand on va tomber sur un séparateur et donc
* que l'on va faire un addElement(), il faudra savoir si on va sur la variable d'intégration où
* s'il faut effectivement ajouter la borne inf. Donc par défaut, la valeur est true.
*/
private boolean gotoVariable = true;
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
current = super.insert(current);
super.addElement();
// On récupère l'élément du second slot (le dx), pour rajouter le d justement.
VariableOrNumber dx = (VariableOrNumber) getChild(1).getChild(0);
dx.setValue("d" + dx.getValue());
return current;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
if (gotoVariable) {
gotoVariable = false;
return (FormulaTreeStructure) getChild(1).getChild(0);
}
else
return super.addElement();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/ComplexPolar.java
0,0 → 1,102
/*
$Id: ComplexPolar.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
*
* @author © 1999 DIRAT Laurent
* @version 2.0 28/06/1999
*/
public class ComplexPolar extends KaryOperator {
/*
* Pour savoir si on est dans le cas où il faut positionner current sur la partie imaginaire ou pas
*/
private boolean gotoImaginary = true;
/**
* Inserts the instance in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
current = super.insert(current);
FormulaTreeStructure realPart = current;
current = (new Multiplication()).insert(current);
// Construction de la partie imaginaire.
current = (new E()).insert(current);
current = (new Superscript()).insert(current);
current = (new Bracket()).insert(current);
current = (new I()).insert(current);
current = (new Multiplication()).insert(current);
current = (new VariableOrNumber()).insert(current);
return realPart;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
if (gotoImaginary) {
gotoImaginary = false;
FormulaTreeStructure imaginay = (FormulaTreeStructure) getChild(0); // le slot
imaginay = (FormulaTreeStructure) imaginay.getChild(0); // la multiplication
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la puissance
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la parenthèse
imaginay = (FormulaTreeStructure) imaginay.getChild(0); // la partie multiplication
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la partie imaginaire
return imaginay;
}
else
return this;
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
FormulaTreeStructure imaginay = (FormulaTreeStructure) getChild(0); // le slot
imaginay = (FormulaTreeStructure) imaginay.getChild(0); // la multiplication
FormulaTreeStructure realPart = (FormulaTreeStructure) imaginay.getChild(0);
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la puissance
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la parenthèse
imaginay = (FormulaTreeStructure) imaginay.getChild(0); // la multiplication
imaginay = (FormulaTreeStructure) imaginay.getChild(1); // la partie imaginaire
linear = realPart.createLinear(linear + getTheOperator());
linear = imaginay.createLinear(linear + ",");
return linear + ")";
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/AFloat.java
0,0 → 1,57
/*
$Id: AFloat.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.openmath.jome.model.VariableOrNumber;
 
/**
* Float elements in the formula.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 29/09/1999
*/
public class AFloat extends VariableOrNumber {
/**
* The default constructor.<BR>
* Constructs a float with no value. A default constuctor is needed for dynamic instantiation.
* The value must be set after instantiation.
*/
public AFloat() {
this("");
}
/**
* The constructor.<BR>
* Contstructs an float with the specified string value.
* @param value the float value.
*/
public AFloat(String value) {
super("FLOAT", value, true, false);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/FormulaTreeStructure.java
0,0 → 1,653
/*
$Id: FormulaTreeStructure.java,v 1.4 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.utils.*;
import fr.ove.openmath.jome.behaviour.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.ctrlview.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public abstract class FormulaTreeStructure extends Node implements ControlListener, Iconifiable, fr.ove.utils.Comparable, Maskable, Modifiable {
/**
* To check if we consider the instance as a template or not. <BR>
* (usefull for the building of the formula tree structure).
* By default, the new intance create is not a template.
*/
private boolean isTemplate = false;
/**
* The priority of the instance considered as an operator.
*/
private int asOperatorPriority;
 
/**
* The priority of the instance considered as an operand.
*/
private int asOperandPriority;
/**
* The list of listeners of the instance
*/
private Vector listeners = new Vector();
/**
* Flag to set if we allow the move of the children (so operands) of the instance.<BR>
* In other word, says some kind of commutativity of the operator.<BR>
* The default is <CODE>false</CODE> because only "few" operators have this property.
*/
private boolean areOperandsMovable = false;
/**
* The resources manager
*/
static FormulaResourcesManager resourcesManager = new FormulaResourcesManager("fr.ove.openmath.jome.model.resources2");
/**
* theresource indentifier of the instance
*/
private String resourceIdentifier;
// ***********************************
// Gestion des listeners de l'instance
/**
* Registers another listener to be informed of changes of the FTS.
* @param modelListener a listener to add.
*/
public void addModelListener(ModelListener modelListener) {
listeners.addElement(modelListener);
}
 
/**
* Removes a listener.
* @param modelListener a listener to remove.
*/
public void removeModelListener(ModelListener modelListener) {
listeners.removeElement(modelListener);
}
 
/**
* Removes all the listeners.
*/
public void removeAllModelListener() {
listeners.setSize(0);
}
 
/**
* Fires a ModelEvent event to registered listeners.
* @param modelEvent event encapsulating relevant information.
*/
public void fireModelEvent(ModelEvent modelEvent) {
for (int i = 0; i < listeners.size(); i++)
((ModelListener)listeners.elementAt(i)).consumeModelEvent(modelEvent);
}
/**
* Returns all the registered listener of the instance.
*/
public Vector getListeners() {
return listeners;
}
 
// **** fin de la gestion des listeners ****
// *****************************************
 
/**
* Sets the resource identifier of the instance.
* @param the resource identifier.
*/
public void setResourceIdentifier(String resourceIdentifier) {
this.resourceIdentifier = resourceIdentifier;
}
/**
* Returns the resource identifier of the instance.
*/
public String getResourceIdentifier() {
return resourceIdentifier;
}
/**
* Sets the as operator priority
* @param asOperatorPriority the priority
*/
public void setAsOperatorPriority(int asOperatorPriority) {
this.asOperatorPriority = asOperatorPriority;
}
/**
* Returns the priority of the instance viewed as an operator.
* @return the priority of the instance viewed as an operator.
*/
public int getAsOperatorPriority() {
return asOperatorPriority;
}
 
/**
* Sets the as operand priority
* @param asOperandPriority the priority
*/
public void setAsOperandPriority(int asOperandPriority) {
this.asOperandPriority = asOperandPriority;
}
/**
* Returns the priority of the instance viewed as an operand.
* @return the priority of the instance viewed as an operand.
*/
public int getAsOperandPriority() {
return asOperandPriority;
}
/**
* Returns <CODE>true</CODE> if it is a template.<BR>
* <CODE>false</CODE> otherwise.
*/
public boolean isTemplate() {
return isTemplate;
}
 
/**
* Sets the instance as a template.
*/
public void setIsTemplate(boolean isTemplate) {
this.isTemplate = isTemplate;
}
/**
* Returns the node (operator), which is the position in the formula tree, where the
* instance have to be inserted.
*
* @param current the current insert position in the formula tree.
* @return the insert position in the formula tree for the instance.
*/
public FormulaTreeStructure findLocation(FormulaTreeStructure current) {
//while (this.asOperandPriority < current.asOperatorPriority)
while (asOperandPriority < current.getAsOperatorPriority())
current = (FormulaTreeStructure) current.getFather();
 
return current;
}
 
/**
* Returns the father of the node which, from the current instance, have the specified
* priority.
*
* @param priority the specified priority.
* @return the desired father.
*/
public FormulaTreeStructure goTo(int priority) {
FormulaTreeStructure current = this;
 
// Si le test est vrai, c'est qu'on est déjà sur un tel noeud.
// On retourne un noeud identique placé au-dessus dans l'arbre
int prio = current.asOperatorPriority;
if (current.asOperatorPriority == priority)
current = (FormulaTreeStructure) current.getFather();
 
while ((current.asOperatorPriority != priority) &&
(((FormulaTreeStructure)current.getFather()).asOperatorPriority != 0))
current = (FormulaTreeStructure) current.getFather();
 
return (FormulaTreeStructure) current.getFather();
}
/*
* Sets if we allow the move of the children (so operands) of the instance.
* @param areOperandsMovable <CODE>true</CODE> if the operands are movable.
* <CODE>false</CODE> otherwise.
*/
public void setAreOperandsMovable(boolean areOperandsMovable) {
this.areOperandsMovable = areOperandsMovable;
}
/*
* Returns if we allow the move of the children (so operands) of the instance.
* @return <CODE>true</CODE> if the operands are movable. <CODE>false</CODE> otherwise.
*/
public boolean getAreOperandsMovable() {
return areOperandsMovable;
}
/**
* Moves the specified list of the instance children to the specified
* rank. The first child in the list has its rank setted to the specified
* one, the second to the first+1, ...and so on.
* @param list the list of the instance operands to move.
* @param rank the specified rank.
*/
public void moveOperands(Vector list, int rank) {
// On fait la permutation dans la FTS
moveChildren(list, rank);
ModelEvent modelEvent = new ModelEvent(this);
// On a fait les déplacements nécéssaires, on reconstruit le display
modelEvent.setAction(ModelEvent.REBUILD, null);
// On envoie l'événement.
fireModelEvent(modelEvent);
// On envoie maintenant un événement comme quoi il faut mettre à
// jour l'affichage.
modelEvent.setAction(ModelEvent.UPDATE, null);
// On envoie l'événement.
fireModelEvent(modelEvent);
}
// #################################################
// ### Implémentation des différentes interfaces ###
// #################################################
// ****************************************
// Implémentation de l'interface Comparable
/**
* Tests if the instance is equal to the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isEqual(fr.ove.utils.Comparable toCompare) {
// On verra plus tard
return false;
}
/**
* Tests if the instance is greater than the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isGreater(fr.ove.utils.Comparable toCompare) {
// On s'en fout, seule l'égalité nous intéresse
return false;
}
/**
* Tests if the instance is greater or equal than the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isGreaterOrEqual(fr.ove.utils.Comparable toCompare) {
// On s'en fout, seule l'égalité nous intéresse
return false;
}
/**
* Tests if the instance is lesser than the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isLesser(fr.ove.utils.Comparable toCompare) {
// On s'en fout, seule l'égalité nous intéresse
return false;
}
/**
* Tests if the instance is lesser or equal than the specified one.
* @param toCompare the instance to compare with the current instance.
*/
public boolean isLesserOrEqual(fr.ove.utils.Comparable toCompare) {
// On s'en fout, seule l'égalité nous intéresse
return false;
}
// *** Fin de l'interface Comparable ***
// *************************************
// *****************************************
// Implémentation de l'interface Iconifiable
/**
* Associates an icon name to the instance.
* @param iconName the name of the icon
*/
public void setIconName(String iconName) {
// On ne fait rien, c'est dans les classes dérivées qu'on va implémenter getIconName().
// Ca évite de stocker une String pour pas grand chose.
}
/**
* Returns the name of the icon associated to the instance.<BR>
* The icon name is the name of the ressource identifier where "_Ico" added to the end.
* @returns The name of the icon, or <CODE>null</CODE> if there is no name
* associated.
*/
public String getIconName() {
return resourceIdentifier + "_Ico"; //resourcesManager.getIconName(resourceIdentifier);
}
/**
* @return <CODE>true</CODE> if the instance is an icon. <CODE>false</CODE> otherwise.
*/
public boolean isIcon() {
return false;
}
/**
* Iconifies the instance.
*/
public void iconify() {
if (isIconifiable()) {
Icon icon = new Icon(this);
// On ajoute l'instance à iconifier dans Icon (<=> on iconfie l'instance)
icon.addIconified(this);
// On insère maintenant notre icon à la place de l'instance.
icon.insert(this);
}
}
/**
* Uniconifies the instance.
*/
public void uniconify() {
// Par défaut on ne fait rien, on ne peut désiconifier qu'une icone
}
/**
* Uniconifies all the iconified parts of the instance.
*/
public void uniconifyAll() {
if (getNbChildren() != 0) {
boolean rebuildDisplay = false;
// On parcourre tous les enfants de l'instance et si on trouve une icone, on la
// désiconifie
FormulaTreeStructure fts = null;
/*
for (Enumeration e = getChildren().elements(); e.hasMoreElements(); ) {
fts = (FormulaTreeStructure) e.nextElement();
if (fts.isIcon()) {
fts.uniconify();
rebuildDisplay = true;
}
}
*/
for (int i = 0; i < getNbChildren(); i++) {
fts = (FormulaTreeStructure) getChild(i);
if (fts.isIcon()) {
fts.uniconify();
rebuildDisplay = true;
i = -1; // On repart à zéro car la désiconification a pu en refaire apparaître.
}
}
// l'instance n'a plus de d'icone fille, on s'occupe de la descendance
for (Enumeration e = getChildren().elements(); e.hasMoreElements(); )
((FormulaTreeStructure) e.nextElement()).uniconifyAll();
// Reconstruction du display que si y a eu désiconification
if (rebuildDisplay) {
// On part du principe que si l'on a une icone, c'est que l'on a le display qui lui est
// associé, donc reconstruction du display.
// Faire gaffe à appeler le ModelEvent.UPDATE quand nécessaire
// On envoie maintenant un événement comme quoi il faut reconstruire
// l'affichage.
ModelEvent modelEvent = new ModelEvent(this);
modelEvent.setAction(ModelEvent.REBUILD, null);
fireModelEvent(modelEvent);
}
}
}
/**
* Sets the instance as iconifiable.
* @param isIconifiable <CODE>true</CODE> if the instance is iconifiable.
* <CODE>false</CODE> otherwise.
*/
public void setIsIconifiable(boolean isIconifiable) {
// On ne fait rien, les classes héritières retourneront la valeur qui leur correspond.
// On évite de stocker un booléen pour pas grand chose puisque peu ne seront pas iconifiables
}
/**
* Returns <CODE>true</CODE> if the instance is iconifiable.
* <CODE>false</CODE> otherwise.
*/
public boolean isIconifiable() {
return true; // Très peu ne sont pas iconifiables. Les concernés surchargeront cette méthode.
}
// *** Fin de l'interface Iconifiable ***
// **************************************
// *********************************************
// Implémentation de l'interface ControlListener
/**
* Consumes (i.e. treats) the event received.
* @param controlEvent the event to consume.
*/
public void consumeControlEvent(ControlEvent controlEvent) {
ModelEvent modelEvent;
int action = controlEvent.getAction();
FormulaTreeStructure fts = null;
switch (action) {
case ControlEvent.ADD :
//System.out.println("ControlEvent.ADD : on ajoute un nouveau display");
break;
case ControlEvent.REMOVE :
//System.out.println("ControlEvent.REMOVE : on enleve un display");
break;
case ControlEvent.ICONIFY :
//System.out.println("ControlEvent.ICONIFY : on iconifie");
Vector toIconify = (Vector) controlEvent.getArgument();
Icon icon = null;
if (toIconify.size() == 1) {
fts = (FormulaTreeStructure) toIconify.elementAt(0);
// une seule fts à iconifier.
if (fts.isIconifiable()) {
// Ce n'est pas déjà une icone et fts est iconifiable, on peut en créer une.
icon = new Icon(fts);
// On ajoute notre fts à iconifier dans Icon (<=> on iconfie fts)
icon.addIconified(fts);
// On insère maintenant notre icon à la place de fts.
icon.insert(fts);
}
// fts = icon.father pour que l'on puisse ajouter le display de notre icone dans icon.father
fts = (FormulaTreeStructure) icon.getFather();
}
else {
// Plusieurs fts sont à iconifier. Il faut donc récupérer la fts
// dont elles sont les filles, pour pouvoir créer l'icone adéquate.
fts = (FormulaTreeStructure) ((FormulaTreeStructure) toIconify.elementAt(0)).getFather();
// On crée une nouvelle icone
icon = new Icon(fts);
// On ajoute maintenant tous les fts à iconifier.
int countToIconify = toIconify.size();
for (int i = 0; i < countToIconify; i++)
icon.addIconified((FormulaTreeStructure) toIconify.elementAt(i));
// On insère maintenant notre icon à la place de la 1-ère fts.
icon.insert(icon.getIconified(0));
}
// On ajoute un display pour notre icon.
modelEvent = new ModelEvent(fts);
modelEvent.setAction(ModelEvent.ADD, icon);
fts.fireModelEvent(modelEvent);
// On met à jour l'affichage de la fts.
modelEvent.setAction(ModelEvent.UPDATE, null);
fts.fireModelEvent(modelEvent);
break;
case ControlEvent.UNICONIFY :
//System.out.println("ControlEvent.UNICONIFY : on desiconifie");
Icon anIcon = (Icon) controlEvent.getArgument();
fts = (FormulaTreeStructure) anIcon.getFather();
anIcon.uniconify();
// On envoie maintenant un événement comme quoi il faut reconstruire
// l'affichage.
modelEvent = new ModelEvent(fts);
modelEvent.setAction(ModelEvent.REBUILD, null);
fts.fireModelEvent(modelEvent);
// On envoie maintenant un événement comme quoi il faut mettre à
// jour l'affichage.
modelEvent.setAction(ModelEvent.UPDATE, null);
// On envoie l'événement.
fts.fireModelEvent(modelEvent);
break;
case ControlEvent.UNICONIFY_ALL :
// On remonte dans la FTS jusqu'à tomber sur la racine de la formule.
fts = this;
while (fts.getFather() != null)
fts = (FormulaTreeStructure) getFather();
// On est sur la racine de la formule.
// A partir de là, on demande de tout désiconifier
fts.uniconifyAll();
// On envoie maintenant un événement comme quoi il faut mettre à
// jour l'affichage.
modelEvent = new ModelEvent(fts);
modelEvent.setAction(ModelEvent.UPDATE, null);
// On envoie l'événement.
fts.fireModelEvent(modelEvent);
break;
case ControlEvent.SUBSTITUTE :
//System.out.println("ControlEvent.ICONIFY : on iconifie");
// ### ATTENTION, le premier élément sera le nom pour la substitution
Vector toSubstitute = (Vector) controlEvent.getArgument();
fts = (FormulaTreeStructure) toSubstitute.elementAt(1);
// On crée une nouvelle icone
Icon substitution = new Icon((String) toSubstitute.elementAt(0));
// On ajoute maintenant tous les fts à iconifier.
int countToIconify = toSubstitute.size();
if ((countToIconify == 2) && !fts.isIconifiable())
break;
for (int i = 1; i < countToIconify; i++)
substitution.addIconified((FormulaTreeStructure) toSubstitute.elementAt(i));
 
// On insère maintenant notre icon à la place de la 1-ère fts.
substitution.insert(fts);
 
// fts = substitution.father pour que l'on puisse ajouter le display de notre icone
// dans substitution.father
fts = (FormulaTreeStructure) substitution.getFather();
 
// On ajoute un display pour notre icon.
modelEvent = new ModelEvent(fts);
modelEvent.setAction(ModelEvent.ADD, substitution);
fts.fireModelEvent(modelEvent);
// On met à jour l'affichage de la fts.
modelEvent.setAction(ModelEvent.UPDATE, null);
fts.fireModelEvent(modelEvent);
break;
}
}
 
// *** Fin de l'interface ControlListener ***
// ******************************************
// **************************************
// Implémentation de l'interface Maskable
/**
* Sets the instance as vissible or not.
* @param isVisible <CODE>true</CODE> if the instance is visible. <CODE>false</CODE> otherwise.
*/
public void setIsVisble(boolean isVisible) {
// Ne fait rien par défaut. Tout les opérateurs sont visibles à de rares exceptions près.
// Ce sont ces exceptions qui maintiendront cette propriété correctement en la surchargeant
}
 
/**
* Checks if the instance is visible.
* @returns <CODE>true</CODE> if the instance is visible. <CODE>false</CODE> otherwise.
*/
public boolean isVisible() {
// Tout les opérateurs sont visibles à de rares exceptions près.
// Ce sont ces exceptions qui maintiendront cette propriété correctement en la surchargeant
return true;
}
// *** Fin de l'interface Maskable ***
// ***********************************
// *****************************************
// Implémentation de l'interface Modifiable
/**
* Sets the value.
*/
public void setValue(String value) {
}
/**
* Returns the value.
*/
public String getValue() {
return null;
}
// *** Fin de l'interface Modifiable ***
// *************************************
// ############################################
// ### Les différentes méthodes abstraites ###
// ############################################
/**
* To check is the instance is an operator.
* @return <CODE>true</CODE> if it is an operator. <CODE>false</CODE> otherwise.
*/
public abstract boolean isOperator();
/**
* Inserts the instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param current the current insertion position.
* @return the new insertion position.
*/
public abstract FormulaTreeStructure insert(FormulaTreeStructure current);
/**
* The Creation of the corresponding linear expression of the formula.
*/
public abstract String createLinear(String linear);
 
/**
* Evaluates the instance.
*/
public abstract String evaluate();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/UnaryOperator.java
0,0 → 1,104
/*
$Id: UnaryOperator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
 
/**
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class UnaryOperator extends Operator {
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// On recherche la position d'insertion de notre instance.
current = findLocation(current);
 
if (current.getFather() == null) {
// On commence la saisie de la formule, on ajoute l'instance courante telle
// qu'elle dansla formule.
current.addChild(this);
 
}
else { // 2 possibilités s'offrent à nous !!!
if ((current.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("constantPriorities")) &&
current.isTemplate()) {
// Le cas classique (on va même dire normal !!!)
// La position d'insertion est un template.
// On doit remplacer le template par l'instance courante (nos parenthèses)
int rank = current.getRank();
FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
father.addChild(this, rank);
father.removeChild(current);
}
else {
// Le cas pas classique
// La position d'insertion n'est pas un template.
// On créé une multiplication implicite.
current = (new Multiplication()).insert(current);
// On insère nos parenthèses
current = insert(current);
// On retourne le dernier point d'insertion.
return current;
}
}
 
// On ajoute un template à notre opérateur.
VariableOrNumber template = new VariableOrNumber();
addChild(template);
 
// On retourne le dernier point d'insertion.
return template;
 
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
linear += getTheOperator();
linear = ((FormulaTreeStructure) getChild(0)).createLinear(linear);
return linear;
}
 
/**
* Evaluates the instance.
*/
public String evaluate() {
return getTheOperator() + ((FormulaTreeStructure) getChild(0)).evaluate();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/UnaryMinus.java
0,0 → 1,77
/*
$Id: UnaryMinus.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.FormulaTreeStructure;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The operator "-", which is the unary minus.<BR>
*
* <CODE>UnaryMinus</CODE> represents a node in the formula tree.<BR>
* Its children are the operands of the operation.
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class UnaryMinus extends UnaryOperator {
/**
* The Constructor.
*/
public UnaryMinus() {
setResourceIdentifier("UNARYMINUS");
setValue("-");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("unaryMinusPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("unaryMinusPriorities"));
}
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// Le seul moment où l'on fait appel à cet opérateur, c'est pour la saisie d'une
// soustaction ou d'un moins unaire, et donc où l'on a une instance de Addition qui est en fait notre
// point d'insertion courant, i.e. current.
// On peut ajouter l'instance courante telle qu'elle.
current.addChild(this);
// On insère notre template dans le FTS
VariableOrNumber template = new VariableOrNumber();
addChild(template);
 
// On retourne la reférence de notre dernier point d'insertion.
return template;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Bracket.java
0,0 → 1,181
/*
$Id: Bracket.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.FormulaTreeStructure;
import fr.ove.openmath.jome.model.events.ModelEvent;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* The operator bracket.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 25/06/1999
*/
public class Bracket extends UnaryOperator {
private boolean isVisible = true;
/**
* The Constructor.
*/
public Bracket() {
setResourceIdentifier("OPEN_PAREN");
setValue("(");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("bracketPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("bracketPriorities"));
}
/**
* Returns the father of the node which, from the current instance, have the specified
* priority.
*
* @param priority the specified priority.
* @return the desired father.
*/
public FormulaTreeStructure goTo(int priority) {
FormulaTreeStructure current = this;
 
// Si le test est vrai, c'est qu'on est déjà sur un tel noeud.
// Cela veut dire que l'on est en train de fermer des parenthèses successives
// Ex: ((2+3))
// Ce qui c'est passé: on a eu un goto avec la première ). On se retrouve alors
// sur le noeud représentant les secondes parenthèses, c'est à dire l'instance courante.
// Donc l'appel de ce goto a pour but de fermer les parenthèses représentées par l'instance
// courante. On retourne donc simplement le père. Sinon, on remonte.
if (current.getAsOperatorPriority() == priority)
return (FormulaTreeStructure) current.getFather();
else
current = (FormulaTreeStructure) current.getFather();
 
while ((current.getAsOperatorPriority() != priority) &&
(((FormulaTreeStructure)current.getFather()).getAsOperatorPriority() != 0))
current = (FormulaTreeStructure) current.getFather();
 
return current;
}
 
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// On recherche la position d'insertion de notre instance.
current = findLocation(current);
 
if (current.getFather() == null) {
// On commence la saisie de la formule, on ajoute l'instance courante telle
// qu'elle dansla formule.
current.addChild(this);
 
}
else { // 2 possibilités s'offrent à nous !!!
if ((current.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("constantPriorities")) &&
current.isTemplate()) {
// Le cas classique (on va même dire normal !!!)
// La position d'insertion est un template.
// On doit remplacer le template par l'instance courante (nos parenthèses)
int rank = current.getRank();
FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
father.addChild(this, rank);
father.removeChild(current);
 
// On regarde quel est le type de father. Si c'est une Fraction, les parenthèses
// ne sont pas visibles.
if (father.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("dividePriorities"))
isVisible = false;
}
else {
// Le cas pas classique
// La position d'insertion n'est pas un template.
// On créé une multiplication implicite.
current = (new Multiplication()).insert(current);
// On insère nos parenthèses
current = insert(current);
// On retourne le dernier point d'insertion.
return current;
}
}
 
// On ajoute un template à nos parenthèses.
VariableOrNumber template = new VariableOrNumber();
addChild(template);
 
// On retourne le dernier point d'insertion.
return template;
 
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
linear += "(" + ((FormulaTreeStructure) getChild(0)).createLinear("") + ")";
 
return linear;
}
 
/**
* Evaluates the instance.
*/
public String evaluate() {
return "(" + ((FormulaTreeStructure) getChild(0)).evaluate() + ")";
}
 
/**
* Returns <CODE>true</CODE> if the brackets have to be displayed.
* <CODE>false</CODE> otherwise.
*/
public boolean isVisible() {
return isVisible;
}
 
/**
* Sets if the brackets have to be displayed or not.
* @param isVisible <CODE>true</CODE> if we want it. <CODE>false</CODE> otherwise.
*/
public void setIsVisible(boolean isVisible) {
this.isVisible = isVisible;
}
/**
* Returns the name of the icon associated to the instance.<BR>
* The icon name is the name of the ressource identifier where "_Ico" added to the end.
* @returns The name of the icon, or <CODE>null</CODE> if there is no name
* associated.
*/
public String getIconName() {
// On surcharge cette méthode pour que l'icône de la parenthèse soit en fait l'icône
// de ce qu'elle contient.
return ((FormulaTreeStructure) getChild(0)).getIconName();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Liste.java
0,0 → 1,91
/*
$Id: Liste.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
*
* @author © 1999 DIRAT Laurent
* @version 2.0 28/06/1999
*/
public class Liste extends NaryOperator2 {
/**
* Is the "enclosure" of the list visible ?
*/
private boolean isVisible = true;
/**
* Is the list displayed vertically or horizontally ?
*/
private boolean isVertical = false;
/**
* The Constructor.
*
*/
public Liste() {
setTheOperator("{");
setEnding("}");
}
/**
* Returns <CODE>true</CODE> if the curly brackets around the elements have to be displayed.
* <CODE>false</CODE> otherwise.
*/
public boolean isVisible() {
return isVisible;
}
/**
* Sets if the curly brackets around the elements have to be displayed.
* @param isVisible <CODE>true</CODE> if we want it. <CODE>false</CODE> otherwise.
*/
public void setIsVisible(boolean isVisible) {
this.isVisible = isVisible;
}
 
/**
* Returns <CODE>true</CODE> if the list is displayed vertically.
* <CODE>false</CODE> otherwise.
*/
public boolean isVertical() {
return isVertical;
}
/**
* Sets if the list is displayed vertically.
* @param isVertical <CODE>true</CODE> if we want it. <CODE>false</CODE> otherwise.
*/
public void setIsVertical(boolean isVertical) {
this.isVertical = isVertical;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Slot.java
0,0 → 1,146
/*
$Id: Slot.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
 
/**
* This class represents the kind of child K-ary will have.
*
* @author © 1999 DIRAT Laurent
* @version 1.0 24/02/1999
*/
public final class Slot extends FormulaTreeStructure {
// Y a de fortes chances pour qu'on ne surclasse jamais Slot.
FormulaTreeStructure nextSlot;
/**
* The Constructor.
*
*/
public Slot() {
setResourceIdentifier("SLOT");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("slotPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("slotPriorities"));
}
public FormulaTreeStructure getNextSlot() {
return nextSlot;
}
public void setNextSlot(FormulaTreeStructure nextSlot) {
this.nextSlot = nextSlot;
}
// En fait, vu l'usage, toutes les méthodes des éléments de la fts ne servent pas.
// Seules les valeurs de l'instance vue comme opérateur ou comme opérande sont utiles
// pour la construction de la fts.
 
// Obligé ici de surcharger cette méthode pour palier les cas pathologiques de, je suis
// déjà sur une instance de Slot (exemple, on a une fonction comme fils a un slot, le goto
// correpondant à la fermeture de la parenthèse de la fonction, nous a mis comme position
// courante d'insertion, le slot. Si en suivant, on met un séparateur (donc on veut ajouter
// un autre slot) il faut que l'on reste sur l'instance. A priori on ne va jamais aller plus
// haut dans la fts qu'un slot en passant par un goTo. Donc si cette méthode est appelée, c'est
// que la position courante d'insertion est l'instance, donc on ne fait rien, la position
// courante d'insertion reste la même.
public FormulaTreeStructure goTo(int priority) {
return this;
}
 
/**
* Inserts the icon (node) in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// On s'en fout.
return null;
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
return ((FormulaTreeStructure) getChild(0)).createLinear("");
}
/**
* Evaluates the instance.
*/
public String evaluate() {
return ((FormulaTreeStructure) getChild(0)).evaluate();
}
/**
* To check is the instance is an operator.
* @return <CODE>true</CODE> if it is an operator. <CODE>false</CODE> otherwise.
*/
public boolean isOperator() {
return false;
}
// *****************************************
// Implémentation de l'interface Iconifiable
/**
* Returns the name of the icon associated to the instance.
*
* @returns The name of the icon, or <CODE>null</CODE> if there is no name
* associated.
*/
public String getIconName() {
return ((FormulaTreeStructure) getChild(0)).getIconName();
}
 
// *** Fin de l'interface Iconifiable ***
// **************************************
// *****************************************
// Implémentation de l'interface Modifiable
/**
* Sets the value.
*/
public void setValue(String value) {
}
/**
* Returns the value.
*/
public String getValue() {
return null;
}
// *** Fin de l'interface Modifiable ***
// *************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/KaryOperator.java
0,0 → 1,87
/*
$Id: KaryOperator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
/**
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class KaryOperator extends NaryOperator2 {
/**
* The arity of the operator. (in fact the number max of operands the operator must have)
*/
private int operatorArity;
/**
* Sets the operator arity
*/
public void setOperatorArity(int operatorArity) {
this.operatorArity = operatorArity;
}
/**
* Returns the operator arity
*/
public int getOperatorArity() {
return operatorArity;
}
/**
* Adds a new element (template) to the end of the list.
* Returns the new element.
*/
public FormulaTreeStructure addElement() {
if (getNbChildren() < operatorArity)
return super.addElement();
else
return this;
// faudra faire des exceptions pour dire que l'arité n'est pas respéctée
}
// *****************************************
// Implémentation de l'interface Modifiable
/**
* Sets the value.
*/
public void setValue(String value) {
setTheOperator(value + "(");
}
/**
* Returns the value.
*/
public String getValue() {
return getTheOperator();
}
// *** Fin de l'interface Modifiable ***
// *************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Superscript.java
0,0 → 1,57
/*
$Id: Superscript.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* The operator "^".<BR>
*
* <CODE>Superscript</CODE> represents a node in the formula tree.
* Its children are the operands of the operation.
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class Superscript extends NaryOperator {
/**
* The Constructor.
*/
public Superscript() {
setResourceIdentifier("POWER");
setValue("^");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("powerPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("powerPriorities"));
setAreOperandsMovable(false);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/events/ModelListener.java
0,0 → 1,47
/*
$Id: ModelListener.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.events;
 
import java.util.EventListener;
import fr.ove.openmath.jome.model.events.ModelEvent;
 
/**
* The interface that an object which want to be alerted of the changes of the model
* must implement.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 09/07/98
*/
public interface ModelListener extends EventListener {
/**
* Consumes (i.e. treats) the event received from the model.
* @param modelEvent the event to consume.
*/
public void consumeModelEvent(ModelEvent modelEvent);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/events/ModelListenerController.java
0,0 → 1,60
/*
$Id: ModelListenerController.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.events;
 
import java.util.EventListener;
import fr.ove.openmath.jome.model.events.ModelEvent;
import fr.ove.openmath.jome.ctrlview.events.*;
 
/**
* The interface that an object which want to be alerted of the changes of the model
* and want to control at the same time, must implement.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 29/07/98
*/
public interface ModelListenerController extends ModelListener {
/**
* Registers another listener to be informed of some changes.
* @param controlListener a listener to add.
*/
public void addControlListener(ControlListener controlListener);
/**
* Removes a listener.
* @param controlListener a listener to remove.
*/
public void removeControlListener(ControlListener controlListener);
/**
* Fires a Control event to registered listeners.
* @param controlEvent event encapsulating relevant information.
*/
public void fireControlEvent(ControlEvent controlEvent);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/events/ModelEvent.java
0,0 → 1,139
/*
$Id: ModelEvent.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model.events;
 
import java.util.EventObject;
 
/**
* The event to send to all objects that implements the interface ModelListener
* and which want to be alerted of changes of the model they are listening to.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 09/07/98
*/
public class ModelEvent extends EventObject {
/**
* The action to execute with the event.
*/
private int action;
 
/**
* The argument of the action to execute.
*/
private Object argument;
 
/**
* The constructor.
* @param src the object which produces this event.
*/
public ModelEvent(Object src) {
super(src);
}
 
/**
* Sets the action and its argument, if necessary, to execute to the event.
* @param action the action to execute.
* @param argument the action argument. If the action don't need
* an argument, it must be sets to <CODE>null</CODE>.
*/
public void setAction(int action, Object argument) {
this.action = action;
this.argument = argument;
}
 
/**
* Returns the action associated with the event.
*/
public int getAction() {
return action;
}
 
/**
* Returns the argument of the action.
*/
public Object getArgument() {
return argument;
}
 
/**
* The different actions associated with the event.<BR>
*/
 
/**
* Add the element which produces the event.
*/
public static final int ADD = 0;
 
/**
* Remove the element which produces the event.
*/
public static final int REMOVE = 1;
 
/**
* Remove the element which produces the event.
*/
public static final int MOVE = 2;
 
/**
* Create the display for the instance which produces the event.
*/
public static final int CREATE = 10;
/*
* Clear the display
*/
public static final int CLEAR = 6;
// Revoir les événements, update devrait devenir un truc du style
// refresh ou repaint, puisque on l'utilise pour le réaffichage,
// et rebuild, plutôt update, puisque c'est pour reconstruire le
// display, et donc en fait une mise à jour.
 
/**
* Update the element which produces the event.
*/
public static final int UPDATE = 3;
 
/**
* Rebuild the element which produces the event.
*/
public static final int REBUILD = 7;
 
/**
* Give the OpenMath object of the formula.
*/
public static final int HERE_IS_OPENMATH = 4;
 
/*
* Give the maple-like expression of the formula.
*/
public static final int HERE_IS_MAPLE = 5;
 
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/NaryOperator.java
0,0 → 1,155
/*
$Id: NaryOperator.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class NaryOperator extends Operator {
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
VariableOrNumber template;
// On cherche la position d'insertion de notre opérateur
current = findLocation(current);
 
if (current.getAsOperatorPriority() == getAsOperandPriority()) {
// On a déjà tapé dans la formule un opérateur de ce genre, on va donc seulement insérer
// un template.
template = new VariableOrNumber();
current.addChild(template);
// On retourne la reférence de notre dernier point d'insertion.
return template;
}
else {
// On est dans le cas où on commence à saisir un tel opérateur.
// On ajoute l'opérateur comme fils à l'opérateur courant
current.addChild(this);
// On teste s'il on est dans le cas où l'on a déjà tapé qque chose dans
// la formule. Si non, current est forcément de type Formula, par conséquent
// on est dans le cas particulier où cela doit produire [?]*[?] puisque
// normalement on ne devrait, dans ce cas là, pas pouvoir taper de "*"
if ((current.getFather() == null) && (current.getNbChildren() == 1)) {
template = new VariableOrNumber();
addChild(template); // On ajoute le premier template.
}
else {
FormulaTreeStructure fts = (FormulaTreeStructure) current.getChild(getRank() - 1);
// à cause des priorités sur les opérateurs, on ajoute comme fils l'opérateur
// dont le rang est juste inférieur à notre "*"
addChild(fts);
// on enlève l'opérateur qu'on a fait "descendre", de la liste
// de son précédent père (son grand père maintenant)
current.removeChild(fts);
}
// On ajoute un template à la multiplication
template = new VariableOrNumber();
addChild(template);
// On retourne la reférence de notre dernier point d'insertion.
return template;
}
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
FormulaTreeStructure child;
for (int i = 0; i < getNbChildren(); i++) {
child = (FormulaTreeStructure) getChild(i);
if (i == 0)
linear = child.createLinear(linear);
else {
linear += getTheOperator();
linear = child.createLinear(linear);
}
}
return linear;
}
/**
* Evaluates the instance.
*/
public String evaluate() {
Vector evaluations = new Vector();
// On commence par évaluer tous les fils de l'instance
for (Enumeration e = getChildren().elements(); e.hasMoreElements(); )
evaluations.addElement(((FormulaTreeStructure) e.nextElement()).evaluate());
int nbEvaluations = evaluations.size();
String anEvaluation, currEvaluation;
// Maintenant, on parcourre toutes les évaluations calculées et on essaye de leur appliquer
// l'opérateur courant
for (int i = 1; i < nbEvaluations; i++) {
currEvaluation = (String) evaluations.elementAt(i);
for (int j = 0; j < i; j++) {
anEvaluation = (String) evaluations.elementAt(j);
if (Evaluator.type(currEvaluation) == Evaluator.type(anEvaluation)) {
evaluations.insertElementAt(Evaluator.evaluate(anEvaluation, currEvaluation, getTheOperator()), j);
evaluations.removeElement(anEvaluation);
evaluations.removeElement(currEvaluation);
i--;
nbEvaluations--;
break;
}
}
}
// On a appliqué l'opérateur courant, on retourne maintenant le résultat, en prenant soin
// d'intercaler des opérateur entre les évaluations si nécessaire
String result = (String) evaluations.firstElement();
for (int i = 1; i < nbEvaluations; i++)
result += getTheOperator() + (String) evaluations.elementAt(i);
 
return result;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Function.java
0,0 → 1,61
/*
$Id: Function.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.openmath.jome.model.FormulaTreeStructure;
import fr.ove.openmath.jome.model.events.ModelEvent;
import fr.ove.openmath.jome.model.evaluation.*;
import fr.ove.openmath.jome.behaviour.Modifiable;
 
/**
*
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class Function extends NaryOperator2 {
// *****************************************
// Implémentation de l'interface Modifiable
/**
* Sets the value.
*/
public void setValue(String value) {
setTheOperator(value + "(");
}
/**
* Returns the value.
*/
public String getValue() {
return getTheOperator();
}
// *** Fin de l'interface Modifiable ***
// *************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Icon.java
0,0 → 1,312
/*
$Id: Icon.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.ctrlview.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* This is an fictive operator which replaces a real part (real in a syntactical
* mathematical meaning) of the formula by an icon.<BR>
*
* <CODE>Icon</CODE> represents a node in the formula tree structure.<BR>
* Its children are the iconified parts of the formula.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 23/07/98
*/
public class Icon extends FormulaTreeStructure {
/**
* The icon name.
*/
private String iconName = null; // Le nom de l'icone
/**
* The list of iconified elements of the formula.
*/
private Vector iconified = new Vector();
/**
* The rank in the FTS of the iconified elements.
*/
private Vector rankOfIconified = new Vector(); // On en a besoin si on veut lors de la déisconification
// essayer de garder la position initiale de chaque élément iconifié. En effet, à chaque fois
// que l'on supprime/ajoute un élément de/dans la FTS, le rang des éléments est mis à jour, et
// comme iconified est une liste qui contient des références sur des éléments de la FTS, quand
// le rang des éléments de la FTS est mis à jour, le rang des éléments de iconified est mis à
// jour également. Donc on perd la "VRAI" position initiale.
/**
* Sets if the icon represents a substitution or not.<BR>
* The default is no, this means that the iconification process is an "automatic" one,
* i.e. the icon represents what is iconified.<BR>
* The substitution is when the user want to replace a selection by a friendly term.
* (Ex : Let a+b be EXP, the expression a+b+c becomes EXP+c)
*/
private boolean isSubstitution = false;
/**
* The Constructor.<BR>
* @param toIconify the element (or part of the element, according to the case) to iconify
* in order to get the information for the icon name
*
*/
public Icon(FormulaTreeStructure toIconify) {
this(toIconify.getIconName());
isSubstitution = false;
}
/**
* The Constructor.
* @param iconName the name of the icon
*/
public Icon(String iconName) {
setResourceIdentifier("ICON");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("constantPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("constantPriorities"));
isSubstitution = true;
this.iconName = iconName;
}
/**
* Inserts the icon (node) in the formula tree structure.<BR>
* @param current the position in the formula tree where the operator is to be insert.
* @return the new current position int hte formula tree.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// La méthode utilisée pour l'insertion de l'icon est la même, mais
// son comportement diffère dans l'ensemble de celui des autres fts.
// En effet current est la position d'insertion, puisque c'est à sa
// place, que l'instance courante va être insérée.
// De plus la valeur de retour n'est pas utilisée.
// On prend le père de current pou l'insertion.
FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
// On récupère le rank de current (i.e. la position d'insertion dans father)
int rank = current.getRank();
// On insère notre icone (i.e l'instance courante)
father.addChild(this, rank);
// On parcourre toutes les fts inconifiées pour les enlever de father.
for (int i = 0; i < iconified.size(); i++)
father.removeChild((FormulaTreeStructure) iconified.elementAt(i));
return null;
}
/**
* To check is the instance is an operator.
* @return <CODE>true</CODE> if it is an operator. <CODE>false</CODE> otherwise.
*/
public boolean isOperator() {
return false;
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
// Si le nombre d'éléments iconifiés est 1, alors on concatène la forme linéaire de cet élément
// Sinon, c'est qu'on a iconifié plusieurs opérandes d'une opération. On doit concaténer la
// forme linéaire de cette sous-expression.
int nbIconified = iconified.size();
if (nbIconified == 1)
linear = getIconified(0).createLinear(linear);
else {
FormulaTreeStructure father = (FormulaTreeStructure) getIconified(0).getFather();
// On duplique le father pour avoir la méthode createLinear
father = (FormulaTreeStructure) father.duplicate();
// On ajoute à father les éléments iconifiés
for (int i = 0; i < nbIconified; i++)
father.addChild(getIconified(i));
// On récupère la sous-expression
linear = father.createLinear(linear);
}
return linear;
}
/**
* Sets if the instance represents a substitution or not.
* @param isSubstitution <CODE>true</CODE> if the instance is a substitution.
* <CODE>false</CODE> otherwise.
*/
public void setIsSubstitution(boolean isSubstitution) {
this.isSubstitution = isSubstitution;
}
/**
* Returns <CODE>true</CODE> if the instance is a substitution.
* <CODE>false</CODE> otherwise.
*/
public boolean isSubstitution() {
return isSubstitution;
}
// On a redéfini une liste d'opérateur fils (les opérateurs iconifiés) malgrè le fait que
// l'on étende FormulaTreeStructure pour éviter que l'insertion ne change le rang d'un
// opérateur parmi les fils de son père pour que, lors de la désiconification, il se retrouve
// à la même place. De plus, le fait de rajouter des fils comme si Icon était un opérateur
// entraînerai la poursuite de la recherche dans l'arbre alors que l'on ne
// souhaite pas, cela poserait des problèmes lors de l'affichage.
/*
* Adds into the list of the fts to iconify, a fts ... to iconify.
* @param fts a formula tree structure to iconify.
*/
public void addIconified(FormulaTreeStructure fts) {
iconified.addElement(fts);
// On conserve le rang dans la FTS
rankOfIconified.addElement(new Integer(fts.getRank()));
}
/**
* Returns the number of iconified operators.
* @return the number of iconified operators.
*/
public int getNbIconified() {
return iconified.size();
}
/**
* Returns the formula tree structure at the specified rank in the list of the fts to iconify.
* @param rank a rank into the list of fts to iconify.
* @return the fts at the specified rank.
*/
public FormulaTreeStructure getIconified(int rank) {
return (FormulaTreeStructure) iconified.elementAt(rank);
}
/**
* Returns the rank in the formula tree structure of the iconified element at the specified
* rank in the list of iconified elments, before iconification.
* @param rank a rank into the list of fts to iconify.
* @return the rank in the FTS of the fts at the specified rank.
*/
public int getRankOfIconified(int rank) {
return ((Integer) rankOfIconified.elementAt(rank)).intValue();
}
/**
* Evaluates the instance.
*/
public String evaluate() {
// A voir ce qu'on fait pour plus tard
return "";
}
 
// *****************************************
// Implémentation de l'interface Iconifiable
/**
* @return <CODE>true</CODE> if the instance is an icon. <CODE>false</CODE> otherwise.
*/
public boolean isIcon() {
return true;
}
/**
* Associates an icon name to the instance.
* @param iconName the name of the icon
*/
public void setIconName(String iconName) {
this.iconName = iconName;
}
/**
* Returns the name of the icon associated to the instance.
*
* @returns The name of the icon, or <CODE>null</CODE> if there is no name
* associated.
*/
public String getIconName() {
if (!isSubstitution) {
// Si le nombre d'éléments iconifiés est 1, alors le nom de l'icone est le nom
// de l'élément à iconifier.
// Sinon, c'est qu'on a à iconifier plusieurs opérandes d'une opération, donc le nom
// de l'icone correspond à celui de cette opération, donc au nom du père de l'instance.
if (iconified.size() == 1)
iconName = getIconified(0).getIconName();
else
iconName = ((FormulaTreeStructure) getFather()).getIconName();
}
return iconName;
}
/**
* Returns <CODE>true</CODE> if the instance is iconifiable.
* <CODE>false</CODE> otherwise.
*/
public boolean isIconifiable() {
return false; // On n'iconifie pas une icone !!!
}
/**
* Iconifies the instance.
*/
public void iconify() {
// On n'iconifie pas une icone
}
/**
* Uniconifies the instance.
*/
public void uniconify() {
FormulaTreeStructure father = (FormulaTreeStructure) getFather();
// On enlève notre icon (i.e. l'instance).
father.removeChild(this);
// On parcourre la liste des fts iconifiées pour les réinsérer à leur position
// avant iconification. (heuu... ce sera leur ancienne position si aucune modif.
// de father n'a été faite, of course.)
int fatherNbChildren = father.getNbChildren();
int countIconified = iconified.size();
FormulaTreeStructure iconifiedFts = null;
int rankOfIconifiedFts;
for (int i = 0; i < countIconified; i++) {
iconifiedFts = (FormulaTreeStructure) iconified.elementAt(i);
rankOfIconifiedFts = getRankOfIconified(i);
if (rankOfIconifiedFts > fatherNbChildren)
father.addChild(iconifiedFts);
else
father.addChild(iconifiedFts, rankOfIconifiedFts);
// On a ajouté une fts anciennement iconifiée, on incrémente donc le nbre
// d'enfant du père
fatherNbChildren++;
}
}
// *** Fin de l'interface Iconifiable ***
// **************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Constant.java
0,0 → 1,149
/*
$Id: Constant.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import fr.ove.openmath.jome.model.FormulaTreeStructure;
import fr.ove.openmath.jome.model.events.ModelEvent;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* @author © 2000 DIRAT Laurent
* @version 2.1 10/01/2000
*/
public class Constant extends FormulaTreeStructure {
/**
* The value.
*/
private String value = "";
 
/**
* The Constructor.
*
*/
public Constant() {
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("constantPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("constantPriorities"));
}
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param ope the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
ModelEvent modelEvent;
FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
 
if ((current.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("constantPriorities")) &&
current.isTemplate()) {
// Normalement dans ce cas, current est un template, on le remplace sans état d'âme.
father.addChild(this);
father.removeChild(current);
 
return this;
}
else { // On est dans le cas de l'insertion courante d'une constante dans la FTS
if ((current.getFather() == null) && (current.getNbChildren() == 0)) {
// On est dans ce cas là, seulement au tout début de la saisie de la
// formule. On est obligé de faire ce test à cause de la multiplication
// implicite avec les parenthèses (Ex: (a+b)c ==> (a+b)*c, dans ce cas là,
// current.getNbChildren() est != de 0)
//On insère directement à la position courante
current.addChild(this);
return this;
}
else { // On est dans aucun des cas précédents, on créé donc une
// multiplication implicite.
current = (new Multiplication()).insert(current);
current = insert(current);
return current;
}
}
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
return linear + value;
}
 
/**
* Evaluates the instance.
*/
public String evaluate() {
return value;
}
/**
* To check is the instance is an operator.
* @return <CODE>true</CODE> if it is an operator. <CODE>false</CODE> otherwise.
*/
public boolean isOperator() {
return false;
}
// *****************************************
// Implémentation de l'interface Modifiable
/**
* Sets the value.
*/
public void setValue(String value) {
this.value = value;
}
/**
* Returns the value.
*/
public String getValue() {
return value;
}
// *** Fin de l'interface Modifiable ***
// *************************************
// *****************************************
// Implémentation de l'interface Iconifiable
/**
* Returns <CODE>true</CODE> if the instance is iconifiable.
* <CODE>false</CODE> otherwise.
*/
public boolean isIconifiable() {
return false; // L'instance n'est pas iconifiable
}
// *** Fin de l'interface Iconifiable ***
// **************************************
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/Addition.java
0,0 → 1,228
/*
$Id: Addition.java,v 1.3 2003/02/18 11:48:47 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.jome.model;
 
import java.util.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.model.events.*;
import fr.ove.openmath.jome.model.evaluation.*;
 
/**
* The operator "+".<BR>
*
* <CODE>Addition</CODE> represents a node in the formula tree.
* Its children are the operands of the operation.
*
* @author © 1999 DIRAT Laurent
* @version 2.0 25/06/1999
*/
public class Addition extends NaryOperator {
/**
* The Constructor.
*/
public Addition() {
setResourceIdentifier("ADDITION");
setValue("+");
setAsOperatorPriority(resourcesManager.getAsOperatorPriority("plusPriorities"));
setAsOperandPriority(resourcesManager.getAsOperandPriority("plusPriorities"));
setAreOperandsMovable(true);
}
/**
* Inserts the operator instance in the formula tree, from the current insertion position.
* (checks the priorities and goes up in the tree if necessary).
*
* @param current the current insertion position.
* @return the new insertion position.
*/
public FormulaTreeStructure insert(FormulaTreeStructure current) {
// On cherche la position d'insertion de notre "+"
current = findLocation(current);
int currentAsOperandPriority = current.getAsOperandPriority();
int currentAsOperatorPriority = current.getAsOperatorPriority();
 
if (currentAsOperatorPriority == getAsOperandPriority()) {
// On a déjà tapé dans la formule un "+", on va donc insérer un nouveau
// "+" dans le précédent ==> cas particuliers.
if ((currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryPlusPriorities")) ||
(currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryMinusPriorities"))) {
// Si on est en précense de ce cas là, la position d'insertion est
// sur un op. unaire ("+" ou "-"). Il faut récupérer le père de l'op.
// en question, i.e. une instance d'Addition que l'on a inséré auparavant
// dansla FST.
FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
if (currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryPlusPriorities")) {
FormulaTreeStructure operand = (FormulaTreeStructure) current.getChild(0);
// si en fait, notre position d'insertion est un "+" unaire, on enlève
// notre opérateur unaire pour ne garder que son opérande.
// Ex: on avait +a, on tape "+", on génère a+[?] où [?] est le template.
int rank = current.getRank();
father.addChild(operand, rank);
father.removeChild(current);
}
 
// On insère notre template.
VariableOrNumber template0 = new VariableOrNumber();
father.addChild(template0);
// On retourne la reférence de notre dernier point d'insertion.
return template0;
}
// On est dans le cas classique de la saisie d'une suite "+", on insère
// notre template dans la FTS.
VariableOrNumber template = new VariableOrNumber();
current.addChild(template);
// On retourne la reférence de notre dernier point d'insertion.
return template;
}
else {
// On est dans le cas où on commence à saisir une addition.
// On ajoute l'opérateur "+" comme fils à l'opérateur courant.
// Pour gérer le fait que l'on puisse taper un "+" binaire ou unaire,
// notre opérateur "+" unaire de notre FTS (UnaryPlus) sera ajouté comme
// fils à l'instance courante. D'où l'ajout systématique suivant à la position
// d'insertion. La distinction de cas singuliers est faite au test suivant.
current.addChild(this);
// Ce test est nécessaire pour savoir si on est dans le cas du "+" binaire
// ou du "+" unaire.
if (current.getNbChildren() > 1) {
// Il faut que l'on fasse attention pour savoir si l'on veut entrer un "+" unaire ou pas.
// Donc on vient d'ajouter notre instance comme fils a current.
// Si on est là, 2 solutions, le fils de current qui a pour rank, le rank de l'instance -1 :
// * est un template ==> on saisi un plus unaire
// * n'est pas un template ==> on saisi une addition
FormulaTreeStructure fts = (FormulaTreeStructure) current.getChild(getRank() - 1);
// Quelque soit le cas, on enlève fts de current.
// Dans le cas du plus unaire, (fts est un template) un template sera rajouté avec
// l'insertion du UnaryPlus
// Dans le cas de l'addition, fts sera ajouté à notre instance
current.removeChild(fts);
if ((fts.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("constantPriorities")) &&
fts.isTemplate()) {
// On ajoute un opérateur "+" unaire comme fils à notre instance
current = this;
current = (new UnaryPlus()).insert(current);
// On retourne la référence de notre dernier point d'insertion
return current;
}
else {
addChild(fts);
// On ajoute un template à l'addition
VariableOrNumber template = new VariableOrNumber();
addChild(template);
// On retourne la référence de notre dernier point d'insertion
return template;
}
}
else { // on est dans le cas du "+" unaire
// Comme dit précédemment, on ajoute un opérateur "+" unaire comme
// fils à l'instance courante.
current = this;
current = (new UnaryPlus()).insert(current);
// On retourne la référence de notre dernier point d'insertion
return current;
}
}
}
/**
* The Creation of the corresponding linear expression of the formula.
*/
public String createLinear(String linear) {
FormulaTreeStructure child;
for (int i = 0; i < getNbChildren(); i++) {
child = (FormulaTreeStructure) getChild(i);
if (i == 0)
linear = child.createLinear(linear);
else {
if (!((child instanceof UnaryPlus) || (child instanceof UnaryMinus)))
linear += "+";
linear = child.createLinear(linear);
}
}
return linear;
}
/**
* Evaluates the instance.
*/
public String evaluate() {
Vector evaluations = new Vector();
// On commence par évaluer tous les fils de l'instance
for (Enumeration e = getChildren().elements(); e.hasMoreElements(); )
evaluations.addElement(((FormulaTreeStructure) e.nextElement()).evaluate());
int nbEvaluations = evaluations.size();
String anEvaluation, currEvaluation;
// Maintenant, on parcourre toutes les évaluations calculées et on essaye de leur appliquer
// l'opérateur courant
for (int i = 1; i < nbEvaluations; i++) {
currEvaluation = (String) evaluations.elementAt(i);
for (int j = 0; j < i; j++) {
anEvaluation = (String) evaluations.elementAt(j);
if (Evaluator.type(currEvaluation) == Evaluator.type(anEvaluation)) {
evaluations.insertElementAt(Evaluator.evaluate(anEvaluation, currEvaluation, "+"), j);
evaluations.removeElement(anEvaluation);
evaluations.removeElement(currEvaluation);
i--;
nbEvaluations--;
break;
}
}
}
// On a appliqué l'opérateur courant, on retourne maintenant le résultat, en prenant soin
// d'intercaler des opérateur entre les évaluations si nécessaire
String result = (String) evaluations.firstElement();
for (int i = 1; i < nbEvaluations; i++) {
anEvaluation = (String) evaluations.elementAt(i);
if (anEvaluation.charAt(0) == '-')
result += anEvaluation;
else
result += "+" + anEvaluation;
}
return result;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/jome/model/resources2.java
0,0 → 1,3
package fr.ove.openmath.jome.model;
public class resources2{
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/exceptions/ErrorMessageException.java
0,0 → 1,135
/*
$Id: ErrorMessageException.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.exceptions;
 
/**
* An exception to subclass to alerts application of errors or to specialize
* the treatment of the symbol that causes the thrown of that kind of instance.<BR>
* This class must be subclassed (it is an abstract class) to set the adequat error
* message and the possible details according to the symbol.
*
* @author © 1998 DIRAT Laurent
* @version 1.0 13/04/99
*/
public abstract class ErrorMessageException extends RuntimeException {
/**
* The error symbol which cause this exception
*/
private String symbol;
/**
* The error message
*/
private String errorMessage;
/**
* The details to send with the message
*/
private Object details;
/**
* Do we have to throw the exception again ?
*/
private boolean throwAgain = false;
 
/**
* The constructor.
* @param symbol The symbol which throws the instance.
*/
public ErrorMessageException(String symbol) {
this(symbol, null);
}
 
/**
* The constructor.
* @param symbol The symbol which throws the instance.
* @param details the details of the exception
*/
public ErrorMessageException(String symbol, Object details) {
this.symbol = symbol;
this.details = details;
}
/**
* Returns the symbols which throws the instance
*/
public String getSymbol() {
return symbol;
}
/**
* Sets the symbol which throws the instance
*/
public void setSymbol(String symbol) {
this.symbol = symbol;
}
 
/**
* Returns the details of the exception
*/
public Object getDetails() {
return details;
}
/**
* Sets the details of the exception
*/
public void setDetails(Object details) {
this.details = details;
}
/**
* Sets <CODE>true</CODE> if we've got to throw the exception.<BR>
* <CODE>false</CODE> otherwise.
*/
public void setThrowAgain(boolean throwAgain) {
this.throwAgain = throwAgain;
}
/**
* Returns if we've got to throw the exception.
*/
public boolean getThrowAgain() {
return throwAgain;
}
/**
* Sets the error message
*/
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
/**
* Returns the error message
*/
public String getErrorMessage() {
return errorMessage;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/MathView/src/fr/ove/openmath/exceptions/ControlException.java
0,0 → 1,80
/*
$Id: ControlException.java,v 1.3 2003/02/18 11:48:46 sander Exp $
*/
 
 
/*
Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
For further information on the GNU Lesser General Public License,
see: http://www.gnu.org/copyleft/lesser.html
For further information on this library, contact: mainline@essi.fr
*/
 
 
package fr.ove.openmath.exceptions;
 
import fr.ove.openmath.exceptions.*;
 
/**
* Specific Control exception to specialize treatment of errors according
* to the symbol that thrown it.
*
* @author © 1999 DIRAT Laurent
* @version 1.0 28/05/99
*/
public class ControlException extends ErrorMessageException {
/**
* The constructor.
* @param symbol The symbol which thrown the instance.
*/
public ControlException(String symbol) {
this(symbol, null);
}
 
/**
* The constructor.
* @param symbol the symbol which thrown the instance.
* @param details the details of the exception
*/
public ControlException(String symbol, Object details) {
super(symbol, details);
 
if (symbol.equals("unhandledSymbol"))
setErrorMessage("Symbol Unhandled by the Application");
else if (symbol.equals("unknownSymbol"))
setErrorMessage("The Symbol does not Exist in the Specified CD");
else if (symbol.equals("unknownCD"))
setErrorMessage("The Specified CD is not Handled by the Application");
else if (symbol.equals("algorithm"))
setErrorMessage("Operation not or Partially Implemented");
else if (symbol.equals("limitation"))
setErrorMessage("Implementation Limitation");
else if (symbol.equals("unexpected"))
setErrorMessage("Unexpected Problem");
else if (symbol.equals("system"))
setErrorMessage("System Error");
else if (symbol.equals("terminated"))
setErrorMessage("Communication Terminted. Server Shutted Down");
else if (symbol.equals("commandOk"))
setErrorMessage("Command Successfully Executed");
else if (symbol.equals("encodingError"))
setErrorMessage("Lexical and/or Syntactic Error Detected");
else if (symbol.equals("semanticError"))
setErrorMessage("Semantic Error Detected");
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Pento/src/draai.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/Pento/src/Pento.java
0,0 → 1,389
 
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
added a public function ReadApplet() and some applet-params
Applet returns String S=number_of_squares+","+used_squares+","+used_objects+","+total_perimeter_of_all_objects;
<html>
<body>
<script language="javascript" type="text/javascript">
function lees(){
var input=document.applets[0].ReadApplet();
alert(input);
}
</script>
<applet id="MathView" code="Pento.class" codebase="." archive="Pento.jar" width="640" height="480">
<param name="objects" value="0,1:1,0,0,0,1:0,0,0,0,0:1,1,1,1,1@1,1,1,1,1:0,1,1,1,0@1,1,1:0,1,1:0,0,1@1,1,1,1@1:1:1">
<param name="helptext" value="what ever">
</applet>
<p>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:lees();">
</body>
</html>
*/
 
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
 
public class Pento extends Applet implements Runnable{
private static final long serialVersionUID = -4039349014715451389L;
Font small_font = new Font("Serif",Font.BOLD,16);FontMetrics small_fm = getFontMetrics(small_font);int small_height = small_fm.getHeight()+20;
int collision=0;int gebruikte_vierkantjes=0;int aantal_vierkantjes=60;int used_objects=0;int teller=0;
int figuur_nummer;String objects="";String helptext="";public Image plaatje;
int mtd[][] = new int[100][140];
int ttd[][] = new int[5][5],ttds[][] = new int[5][5];
int ttn,tts = 0;
int std[] = new int[12];
int pd[][][] = {
{{0,0,0,0,0},{0,0,0,0,0},{1,1,1,1,1},{0,0,0,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,0,0},{0,1,1,1,1},{0,1,0,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,0,0},{0,1,1,1,1},{0,0,1,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,0,0},{0,0,1,1,1},{0,1,1,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,0,0},{0,1,1,1,0},{0,1,1,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,1,0},{0,0,1,1,0},{0,1,1,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,1,1,1,0},{0,0,1,0,0},{0,0,1,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,0,0},{0,1,1,1,0},{0,1,0,1,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,1,0},{0,1,1,1,0},{0,1,0,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,1,1,0,0},{0,0,1,1,0},{0,0,1,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,1,0,0},{0,1,1,1,0},{0,0,1,0,0},{0,0,0,0,0}},
{{0,0,0,0,0},{0,0,0,1,0},{0,0,0,1,0},{0,1,1,1,0},{0,0,0,0,0}},
};
int pdl=pd.length;
Color pc[] = new Color[12],bc;
int cd[][] = {{250,0,0},{0,250,0},{0,0,250},{250,250,0},{250,0,250},{0,250,250},{150,100,0},{150,0,100},{100,150,0},{100,0,150},{0,100,150},{0,150,100}};
int dx,dy,pn;
int mx,my,mcx,mcy;
Thread th = null;
Image os;
Graphics og;
 
public void init(){
plaatje = getImage(getCodeBase(), "draai.gif");
setBackground(Color.white);
os = createImage(680,420);
og = os.getGraphics();
for(int j1 = 0;j1 < 14;j1 ++){
mtd[0][j1] = -1;mtd[1][j1] = -1;mtd[8][j1] = -1;mtd[9][j1] = -1;
}
for(int j2 = 0;j2 < 10;j2 ++){
mtd[j2][0] = -1;mtd[j2][1] = -1;mtd[j2][12] = -1;mtd[j2][13] = -1;
}
for(int k = 0;k < 12;k ++){
std[k] = 1;
pc[k] = new Color(cd[k][0],cd[k][1],cd[k][2]);
}
bc = new Color(225,225,225);
 
addMouseListener(
new MouseAdapter(){
public void mousePressed(MouseEvent e){
dx = e.getX() ; dy = e.getY() ;
 
if((dx > 40) && (dx < 640) && (dy > 260) && (dy < 420)){
pn = ((dx - 40) / 100) + ((dy - 260) / 80) * 6;
 
if((std[pn] == 1)){
if(tts == 0){
tts = 1 ; ttn = pn ; std[pn] = 0;
D_in(pn);
}else{
std[ttn] = 1 ; ttn = pn ; std[pn] = 0;
D_in(pn);
}
}else{
if(tts == 1){
std[ttn] = 1 ; tts = 0 ;
D_in(-1);
}
}
repaint();
}
 
if((dx > 440) && (dx < 640) && (dy > 20) && (dy < 220)){
if(tts == 1){
for(int f1 = 0;f1 < 5;f1 ++){
for(int f2 = 0;f2 < 5;f2 ++){
ttds[f1][4 - f2] = ttd[f2][f1];
}
}
for(int g1 = 0;g1 < 5;g1 ++){
for(int g2 = 0;g2 < 5;g2 ++){
ttd[g2][g1] = ttds[g2][g1];
}
}
repaint();
}
}
collision=0;
if((dx > 20) && (dx < 420) && (dy > 20) && (dy < 260)){
dx = (e.getX() - 20) / 40 ; dy = (e.getY() -20) / 40;
if(tts == 1){
C_dp();
repaint();
}else{
if(mtd[dy + 2][dx + 2] > 0){
ttn = mtd[dy + 2][dx + 2] - 1;
tts = 1;
B_dp();
repaint();
}
}
}
}
}
);
 
addMouseMotionListener(
new MouseMotionAdapter(){
public void mouseMoved(MouseEvent e){
mx = (e.getX() - 20) / 40 ; my = (e.getY() -20) / 40;
if((mx > -1) && (mx < 10) && (my > -1) && (my < 6)){
if((mx != mcx) || (my != mcy)){
mcx = mx;mcy = my;
repaint();
}
}
}
}
);
 
}
 
public void paint(Graphics g){
objects=getParameter("objects");
if(objects!=null && objects.length()>0){
pd = StringToIntArray(objects);
pdl=pd.length;
}
og.setColor(Color.white);
og.fillRect(0,0,680,420);
gebruikte_vierkantjes=0;
for(int lx = 0;lx < 10;lx ++){
for(int ly = 0;ly < 6;ly ++){
if(mtd[ly + 2][lx + 2] == 0){
og.setColor(bc);
}else{
og.setColor(pc[mtd[ly + 2][lx + 2] - 1]);
gebruikte_vierkantjes++;
}
og.fillRect(lx * 40 + 20,ly * 40 + 20,40,40);
og.setColor(Color.blue);
og.draw3DRect(lx * 40 + 20,ly * 40 + 20,40,40,true);
}
}
 
for(int tx = 0;tx < 5;tx ++){
for(int ty = 0;ty < 5;ty ++){
if(ttd[ty][tx] == 0){
og.setColor(bc);
}else{
og.setColor(pc[ttn]);
}
og.fillRect(tx * 40 + 440,ty * 40 + 60,40,40);
og.setColor(Color.blue);
og.draw3DRect(tx * 40 + 440,ty * 40 + 60,40,40,true);
}
}
 
for(int sn = 0;sn < pdl ;sn ++){
if(std[sn] == 1){
for(int d1 = 0;d1 < 5;d1 ++){
for(int d2 = 0;d2 < 5;d2 ++){
if(pd[sn][d2][d1] == 1){
og.setColor(pc[sn]);
og.fillRect(d1 * 20 + (sn % 6) * 100 + 40,d2 * 20 + (sn / 6) * 80 + 240,20,20);
og.setColor(Color.black);
og.draw3DRect(d1 * 20 + (sn % 6) * 100 + 40,d2 * 20 + (sn / 6) * 80 + 240,20,20,true);
}
}
}
}
}
 
if((tts == 1) && (mx > -1) && (mx < 10) && (my > -1) && (my < 6)){
for(int q1 = 0;q1 < 5;q1 ++){
for(int q2 = 0;q2 < 5;q2 ++){
if(ttd[q2][q1] == 1){
if(((mx + q1 - 2) > -1) && ((mx + q1 - 2) < 10) && ((my + q2 - 2) > -1) && ((my + q2 - 2) < 6)){
if(collision==0){og.setColor(Color.lightGray);}else{og.setColor(Color.gray);}
og.drawRect(40 * (mx + q1 - 2) + 20,40 * (my + q2 - 2) + 20,40,40);
og.fillRect(40 * (mx + q1 - 2) + 20,40 * (my + q2 - 2) + 20,40,40);
}
}
}
}
}
g.drawImage(os,0,0,this );
helptext=getParameter("helptext");
if(helptext!=null && helptext.length()>0){og.setColor(Color.black);g.drawString(helptext,20,small_height);}
g.drawImage(plaatje, 500, 0, this);
}
//// einde graphics
///// converteer applet param String naar Array: 0,0,0,0,1:1,0,0,0,1:0,0,0,0,0:1,1,1,1,1 @ 1,1,1,1,1:0,1,1,1,0
 
public int[][][] StringToIntArray(String tmp0){
aantal_vierkantjes=0;
int array[][][] = new int[12][5][5];String tmp1="0";String tmp2="0";String tmp3="0";
int a = 0;int b = 0;int c = 0;
StringTokenizer q = new StringTokenizer(tmp0, "@");
int ma=q.countTokens();int mb=0;int mc=0;
if( ma > 12 ){ ma = 12;}
for( a = 0 ; a<ma ; a++){
tmp1=q.nextToken();
StringTokenizer r = new StringTokenizer(tmp1,":");
mb=r.countTokens();
for(b = 0 ; b<5 ; b++){
if ( b < mb ){ tmp2=r.nextToken(); } else { tmp2="0,0,0,0,0";}
StringTokenizer t = new StringTokenizer(tmp2,",");
mc=t.countTokens();
for ( c = 0 ; c<5 ; c++){
if( c < mc){ tmp3=t.nextToken(); if(tmp3.equals("1")){ array[a][b][c]=1;aantal_vierkantjes++; } else { array[a][b][c]=0;}}
else { array[a][b][c]=0; }
}
}
}
return array;
}
 
//// einde "converteer applet param String naar Array"
 
///
public void D_in(int nn){
for(int k1 = 0;k1 < 5;k1 ++){
for(int k2 = 0;k2 < 5;k2 ++){
if(nn == -1){
ttd[k2][k1] = 0;
}else{
ttd[k2][k1] = pd[nn][k2][k1];
}
}
}
}
 
public void C_dp(){
int fg = 1;collision=0;
for(int c1 = 0;c1 < 5;c1 ++){
for(int c2 = 0;c2 < 5;c2 ++){
if((ttd[c2][c1] == 1) && (mtd[dy + c2][dx + c1] != 0)){
fg = 0;collision=1;
}
}
}
if(fg == 1){
used_objects++;
for(int d1 = 0;d1 < 5;d1 ++){
for(int d2 = 0;d2 < 5;d2 ++){
if(ttd[d2][d1] == 1){
mtd[dy + d2][dx + d1] = ttn + 1;
}
}
}
D_in(-1);
tts = 0;ttn = 0;
}
}
 
public void B_dp(){
for(int p1 = 0;p1 < 10;p1 ++){
for(int p2 = 0;p2 < 6;p2 ++){
if(mtd[p2 + 2][p1 + 2] == ttn + 1){
mtd[p2 + 2][p1 + 2] = 0;
}
}
}
for(int p3 = 0;p3 < 5;p3 ++){
for(int p4 = 0;p4 < 5;p4 ++){
ttd[p4][p3] = pd[ttn][p4][p3];
}
}
used_objects--;
}
public void start(){
if(th == null){
th = new Thread(this);
th.start();
}
}
 
public void stop(){
th = null;
}
 
public void run(){
while (th != null){
try {
Thread.sleep(20);
}
catch (InterruptedException e){ }
}
}
public void update( Graphics g )
{
paint( g ) ;
}
 
// leest applet met javascript...bereken de omtrek...
public String ReadApplet(){
int border[][]=new int[20][20];
int c1;int c2;int t=0;int r=0;
// c1 vertikaal van boven->beneden c2 horizontaal van links naar rechts
for( c1 = 0; c1 < 20 ;c1++){
for( c2 = 0; c2 < 20 ;c2++){
if(mtd[c2][c1] > 0){t=0;
if( (mtd[c2][c1-1] < 1) && (mtd[c2][c1+1] < 1) ){t=t+2;}else{if( (mtd[c2][c1-1] < 1) || (mtd[c2][c1+1] < 1) ){t=t+1;}}
if( (mtd[c2-1][c1] < 1) && (mtd[c2+1][c1] < 1) ){t=t+2;}else{if( (mtd[c2-1][c1] < 1) || (mtd[c2+1][c1] < 1) ){t=t+1;}}
border[c2][c1]=t;
}
}
for( c2 = 20; c2 < 0 ;c2--){
if(mtd[c2][c1] > 0){r=0;
if( (mtd[c2][c1-1] < 1) && (mtd[c2][c1+1] < 1) ){r=r+2;}else{if( (mtd[c2][c1-1] < 1) || ( mtd[c2][c1+1] < 1) ){r=r+1;}}
if( (mtd[c2-1][c1] < 1) && (mtd[c2+1][c1] < 1) ){r=r+2;}else{if( (mtd[c2-1][c1] < 1) || ( mtd[c2+1][c1] < 1) ){r=r+1;}}
border[c2][c1]=r+border[c2][c1];
}
}
}
int cnt=0;
for( c1=0 ; c1<20 ; c1++ ){
for( c2=0 ; c2<20 ; c2++ ){
cnt=cnt+border[c2][c1];
}
}
//String S="total_squares="+aantal_vierkantjes+",used_squares="+gebruikte_vierkantjes+"used_objects="+used_objects+",perimeter="+cnt;
String S=aantal_vierkantjes+","+gebruikte_vierkantjes+","+used_objects+","+cnt;
return S;
}
// einde "public String ReadApplet()"
public int readparm(String S){
int s=0;String c="";
if(S.equals("interactive")){
s=1;c=getParameter(S);if(c!=null && c.length()>0){ if (c.equals("0")){s = 0;}}
}
if(S.equals("cols")){
s=10;c=getParameter("cols");
if(c!=null && c.length()>0){
s = Integer.parseInt(c, 10);
if(s>10){s=10;}
if(s<3){s=3;}
}
}
if(S.equals("rows")){
s=6;c=getParameter("rows");
if(c!=null && c.length()>0){
s = Integer.parseInt(c, 10);
if(s>6){s=6;}
if(s<3){s=3;}
}
}
return s;
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/Pento/build.xml
0,0 → 1,68
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for Pento.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="Pento" default="jar" basedir=".">
 
<description>Pento build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
<exec executable="/bin/sh">
<arg line="-c 'cp ${source-dir}/*.gif ${build}/'"/>
</exec>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create Pento jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/Pento.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="Pento"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="Pento"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="Pento">
<attribute name="Specification-Title" value="Pento"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="Pento"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/build.xml
0,0 → 1,65
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for Rekenmachien.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="Rekenmachien" default="jar" basedir=".">
 
<description>Rekenmachien build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create Rekenmachien jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/Rekenmachien.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="Rekenmachien"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="Rekenmachien"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="Rekenmachien">
<attribute name="Specification-Title" value="Rekenmachien"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="Rekenmachien"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/1.html
0,0 → 1,36
 
<html>
<head></head>
<body>
<script language="javascript" type="text/javascript">
function READTHIS(){
var input=document.getElementById("calculator").ReadApplet();
if(input.indexOf("error")!=-1){
alert(input);
}
else
{
alert("the applet will send:\n"+input);
}
}
</script>
<center>
<applet id="calculator" codebase="dist" code="Rekenmachien.class" archive="Rekenmachien.jar" width="120" height="60">
<!-- defaults should be OK ... but if needed override with these params -->
<param name="frame_xsize" value="300"> <!-- xsize of popup frame -->
<param name="frame_ysize" value="240"> <!-- ysize of popup frame -->
<param name="location_x" value="300"> <!-- x location of popup frame -->
<param name="location_y" value="300"> <!-- y location of popup frame -->
<param name="decimals" value="6"> <!-- precision: number of decimals -->
<param name="fontsize1" value="10"> <!-- input fontsize -->
<param name="fontsize2" value="10"> <!-- output / remarks fontsize -->
<param name="fontsize3" value="16"> <!-- popup frame fontsize -->
<param name="language" value="en"> <!-- en,nl,fr,de -->
<param name="pencolor1" value="10,3,2"> <!-- input foreground color -->
<param name="pencolor2" value="10,3,2"> <!-- input foreground color -->
<param name="bgcolor1" value="200,250,255"> <!-- input background color -->
<param name="bgcolor2" value="245,255,255"> <!-- canvas background color -->
</applet>
<input type="button" name="Send" value="Send" onclick="javascript:READTHIS();">
</body>
</html>
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/GraphWindow.java
0,0 → 1,76
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
*/
import java.applet.*;
import javax.swing.*;
import java.awt.*;
import org.javia.arity.Symbols;
import org.javia.arity.SyntaxException;
 
 
public class GraphWindow extends javax.swing.JFrame {
 
public void plotfunction(String fun) {
Symbols symbols=new Symbols();
int c=0;
xmin=-5;
xmax=5;
xpix=getSize().width;
ypix=getSize().height;
dx=xmax-xmin;
steps=(int)(10*(dx));
xdata=new double[steps+10];
ydata=new double[steps+10];
ymax=1.0;ymin=-1.0;String Y;double y;
for (double x = xmin ; x < xmax ; x=x+0.1) {
Y=fun.replaceAll("x","("+x+")");
try { y=symbols.eval( Y );} catch (SyntaxException e ) {y=0.0;System.out.println("error "+e); }
if(y>ymax){ymax=y;}
if(y<ymin){ymin=y;}
xdata[c]=(double) (x*(xpix/(dx)) - xmin*xpix/(dx));
ydata[c]=y;
c++;
}
ymax=1.2*ymax;
ymin=1.2*ymin;
dy=(ymax - ymin);
if(dy==0){dy=100.0;}
for(c=0;c<steps;c++){
ydata[c]=(double) (ydata[c]*(-0.6)*(ypix)/(dy) + (0.6*ypix)*ymax/(dy)) + 0.3*ypix;
}
repaint();
}
public void paint(Graphics g){
g.setColor(bgcolor3);
g.fillRect(0,0,xpix,ypix);
g.setColor(Color.red);
for(int c=0;c<steps-1;c++){
g.drawLine((int)xdata[c], (int)ydata[c], (int)xdata[c+1], (int)ydata[c+1]);
}
g.setColor(Color.blue);
g.drawLine(0,(int)((0.6*ypix)*ymax/(dy) + 0.3*ypix),xpix,(int)((0.6*ypix)*ymax/(dy) + 0.3*ypix));
g.drawLine((int)(-1*xmin*xpix/dx),0,(int)(-1*xmin*xpix/(dx)),ypix );
}
double[] xdata;
double[] ydata;
int xpix;
int ypix;
double xmax;
double xmin;
double ymax;
double ymin;
double dy;
double dx;
int steps;
Color bgcolor3=new Color(164,235,60);
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/Rekenmachien.java
0,0 → 1,595
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
 
Used as small but fairly powerfull calculator in WIMS
No memory, no buttons: a single input line.
Capable of sending the result -via javascript- to WIMS.
Read Arity documentation for capabilities and Copyright/License.
This little program has no copyrights. Ofcourse.
todo: finish a functionplotter using the Arity-lib. [funcionality triggered by params]
 
Example:
<html>
<head></head>
<body>
<script language="javascript" type="text/javascript">
function READTHIS(){
var input=document.getElementById("calculator").ReadApplet(){
if(input.indexOf("error")!=-1){
alert(input);
}
else
{
alert("the applet will send:\n"+input);
}
}
</script>
<center>
<applet id="calculator" code="Rekenmachien.class" archive="Rekenmachien.jar" width="120" height="60">
<param name="decimals" value="6"> <!-- precision: number of decimals -->
<!-- defaults should be OK ... but if needed override with these params -->
<param name="frame_xsize" value="300"> <!-- xsize of popup frame -->
<param name="frame_ysize" value="240"> <!-- ysize of popup frame -->
<param name="location_x" value="300"> <!-- x location of popup frame -->
<param name="location_y" value="300"> <!-- y location of popup frame -->
<param name="fontsize1" value="10"> <!-- input fontsize -->
<param name="fontsize2" value="10"> <!-- output / remarks fontsize -->
<param name="fontsize3" value="16"> <!-- popup frame fontsize -->
<param name="language" value="en"> <!-- en,nl,fr,de -->
<param name="pencolor1" value="10,3,2"> <!-- input foreground color -->
<param name="pencolor2" value="10,3,2"> <!-- input foreground color -->
<param name="bgcolor1" value="200,250,255"> <!-- input background color -->
<param name="bgcolor2" value="245,255,255"> <!-- canvas background color -->
</applet>
<input type="button" name="Send" value="Send" onclick="javascript:READTHIS();">
</body>
</html>
*/
 
 
import java.awt.*;
import java.applet.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import java.text.DecimalFormat;
import org.javia.arity.Symbols;
import org.javia.arity.SyntaxException;
 
public class Rekenmachien extends JApplet {
GraphWindow graphwindow = new GraphWindow();
InputWindow inputwindow = new InputWindow();
private JTextField input; /* need javax.swing JTextField : no tooltips for TextField !! */
private JTextField output;
private JTextField remarks;
boolean visible=false;
Font myfont1,myfont2,myfont3;
int font_size1=12,font_size2=12,font_size3=14;
int frame_x=300,frame_y=240,x0=300,y0=300,rounding=6;
int R1=225,G1=255,B1=255;
double precision=0.000001;
DecimalFormat decformat;
Color pencolor1,pencolor2,bgcolor1,bgcolor2;
String rem1="\u2023 Mathematical error";
String rem2="\u2023 Nonsense Error";
String rem3="\u2023 calculator";
String rem4="\u2023 done";
String rem5="\u2023 ln(e)=1 log(10)=1";
String rem6="\u2023 Usage [click open/close]";
String rem7="\u2023 Please wait...";
String rem8;
String rem9="\u2023 precision";
String rem10;
String rem11="\u2023 You could also erase this text...\n and type in your formula or calculation...\n Press Enter to start calculations.";
 
public void init(){
initparams();
initfonts();
inittextareas();
setLayout(new GridLayout(3, 1));
initpopups();
initlisteners();
}
public void initlisteners(){
// enter and arrow_down is accepted for starting the calculation in the input field
input.addKeyListener( new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
if(evt.getKeyCode() == evt.VK_ENTER || evt.getKeyCode() == evt.VK_DOWN ){
repaint();
}
}
});
 
inputwindow.textarea.addKeyListener( new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
if(evt.getKeyCode() == evt.VK_ENTER || evt.getKeyCode() == evt.VK_DOWN ){
repaint();
}
}
});
// remarks area accepts mouse_click to set the GraphWindow frame visible/invisible
remarks.addMouseListener( new MouseAdapter(){
public void mousePressed(MouseEvent e){
if(visible){
inputwindow.setVisible(false);
visible=false;
}
else
{
inputwindow.setVisible(true);
visible=true;
}
}
});
}
public void inittextareas(){
input=new JTextField(font_size1);
output=new JTextField(font_size2);
remarks=new JTextField(font_size2);
input.setForeground(pencolor1);
output.setForeground(pencolor2);
remarks.setForeground(pencolor2);
input.setBackground(bgcolor1);
output.setBackground(bgcolor2);
remarks.setBackground(bgcolor2);
input.setFont(myfont1);
output.setFont(myfont2);
remarks.setFont(myfont2);
add(input);add(output);add(remarks);
input.setText("? ");
output.setText("\u2023 ");
remarks.setText(rem6);
// only a tooltip over the remark inputfield
remarks.setToolTipText(rem8);
input.setCaretPosition(2);
}
public void initpopups(){
inputwindow.setSize(frame_x,frame_y);
inputwindow.setLocation(x0,y0);
inputwindow.textarea.setFont(myfont3);
inputwindow.textarea.setBackground(bgcolor1);
inputwindow.panel1.setBackground(bgcolor1);
graphwindow.setSize(frame_x,frame_y);
graphwindow.setLocation(x0+20,y0+20);
}
public void initfonts(){
myfont1 = new Font("Helvetica", Font.BOLD, font_size1);
myfont2 = new Font("Helvetica", Font.BOLD, font_size2);
myfont3 = new Font("Helvetica", Font.BOLD, font_size3);
}
 
public void initparams(){
String param="";
param=getParameter("language");
if(param!=null && param.length()>0){
if(param.equalsIgnoreCase("nl")){
rem1="\u2023 Wiskundige fout";
rem2="\u2023 Onzinnige invoer";
rem3="\u2023 rekenmachine";
rem4="\u2023 klaar";
rem5="\u2023 ln(e)=1 log(10)=1";
rem6="\u2023 info [klik open & dicht]";
rem7="\u2023 even geduld...";
rem9="\u2023 precisie";
rem11="\u2023 Je mag deze tekst ook wissen...\n en dit venster gebruiken voor de berekening \n en druk \"enter\" om je berekening te starten";
}
else
{
if(param.equalsIgnoreCase("de")){
rem1="\u2023 Mathematik Fehler";
rem2="\u2023 Nonsense Fehler";
rem3="\u2023 Taschenrechner";
rem4="\u2023 fertig";
rem5="\u2023 ln(e)=1 log(10)=1";
rem6="\u2023 info [click open & close]";
rem7="\u2023 einen moment...";
rem9="\u2023 precision";
rem11="\u2023 You could also erase this text...\n and type in your formula or calculation...\n Press Enter to start calculations.";
}
else
{
if(param.equalsIgnoreCase("fr")){
rem1="\u2023 Erreur mathematique";
rem2="\u2023 Nonsense Erreur";
rem3="\u2023 calculateur";
rem4="\u2023 fini";
rem5="\u2023 ln(e)=1 log(10)=1";
rem6="\u2023 info [click open & close]";
rem7="\u2023 Please wait...";
rem9="\u2023 precision";
rem11="\u2023 You could also erase this text...\n and type in your formula or calculation...\n Press Enter to start calculations.";
}
}
}
}
 
// display precision
param=getParameter("decimals");
if(param!=null && param.length()>0){
rounding =Integer.parseInt(param, 10);
precision=(double) 1/(Math.pow(10,rounding));
}
String numformat="#.";
for(int n=0;n<rounding;n++){
numformat=numformat+"#";
}
decformat = new DecimalFormat(numformat);
 
// very slow java tooltip text: multiline through HTML
rem8="<html><body bgcolor=white><ul><li>\u2023"+rem9+": \u00B1 "+precision+"</li><li>6*(123/4+1234/5)/(7+9)</li><li>(123^(4/3)+5)/6</li><li>sqrt(123/4)/5</li><li>sqrt[3](1234)</li><li>sin(2*pi)</li><li>sinh(pi)</li><li>log(123)/log(10)</li><li>ln(e)=log(e)=1</li></ul>";
rem10=rem9+": \u00B1 "+precision+"\n\u2023 sqrt[3](1234) \n\u2023 sin(2*pi) \n\u2023 sinh(pi) \n\u2023 log(123)/log(10) [ ln(e) == log(e) = 1 ]\n"+rem11;
// adjust the GraphWindow frame...
param=getParameter("frame_xsize");
if(param!=null && param.length()>0){frame_x = Integer.parseInt(param, 10);}
param=getParameter("frame_ysize");
if(param!=null && param.length()>0){frame_y = Integer.parseInt(param, 10);}
param=getParameter("location_x");
if(param!=null && param.length()>0){x0 = Integer.parseInt(param, 10);}
param=getParameter("location_y");
if(param!=null && param.length()>0){y0 = Integer.parseInt(param, 10);}
// adjust the fonts
param=getParameter("fontsize1");
if(param!=null && param.length()>0){font_size1 = Integer.parseInt(param, 10);}
param=getParameter("fontsize2");
if(param!=null && param.length()>0){font_size2 = Integer.parseInt(param, 10);}
param=getParameter("fontsize3");
if(param!=null && param.length()>0){font_size3 = Integer.parseInt(param, 10);}
// adjust the pen colours
param=getParameter("pencolor1"); // foreground color of inputfield "input"
if (param != null && param.length()>0){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R1 = rgb;}
else if(a == 1){G1 = rgb;}
else if(a == 2){B1 = rgb;}
}
pencolor1=new Color(R1,G1,B1);
}
param=getParameter("pencolor2"); // foreground color of inputfield "input"
if (param != null && param.length()>0){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R1 = rgb;}
else if(a == 1){G1 = rgb;}
else if(a == 2){B1 = rgb;}
}
pencolor2=new Color(R1,G1,B1);
}
// adjust the background colours
param=getParameter("bgcolor1"); // Background color of inputfield "input"
if (param != null && param.length()>0){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R1 = rgb;}
else if(a == 1){G1 = rgb;}
else if(a == 2){B1 = rgb;}
}
bgcolor1=new Color(R1,G1,B1);
}
param=getParameter("bgcolor2"); // Background color of canvas
if (param != null && param.length()>0){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R1 = rgb;}
else if(a == 1){G1 = rgb;}
else if(a == 2){B1 = rgb;}
}
bgcolor2=new Color(R1,G1,B1);
}
}
// plot a function
public void plot(String S){
remarks.setText("\u2023 function plot"); /* not really fine ; will need some work... */
input.setText("? ");
output.setText("\u2023 ?");
if(S.indexOf("=") != -1){
S=S.substring(S.indexOf("=")+1);
}
//System.out.println(S);
graphwindow.plotfunction(S);
graphwindow.setVisible(true);
}
 
// the actual calculation starts here:
public void calculate(String S){
S=replace(S,"?","");
S=RawMath(S);
if(S.length()>1){
String remark="";
S=replace(S,",",".");
S=replace(S,"**","^");
S=S.toLowerCase();
S=replace(S,"sqr(","sqrt(");/* common error */
if(S.indexOf("sqrt[") != -1){S=sqrtn(S);} /* sqrt[3](4) = 4^(1/3) ... */
if(S.indexOf("log[") != -1){S=logn(S);} /* log[3](4) = log(4)/log(3) ... */
for(int s=0;s<3;s++){/* arity lib throws errors +-5-+3------23 etc */
S=replace(S,"+-","-");
S=replace(S,"-+","-");
S=replace(S,"--","+");
S=replace(S,"++","+");
}
if(S != null){
if(S.indexOf("x")!=-1 || S.indexOf("y")!=-1 ){ /* function to plot */
plot(S);
}
else
{ double result=0.0D;/* double is needed for Arity libs */
Symbols symbols=new Symbols(); /* Arity */
String ex[]=S.split("=");
String out="";
try {
result=symbols.eval(ex[ex.length-1]); /* try to call arity for evaluation */
if(result == Double.POSITIVE_INFINITY){out="\u221E";}
else
if(result == Double.NEGATIVE_INFINITY){out="-\u221E";}
else
if(result == Double.NaN){out="NaN (Not A Number)";}
else
if(result == Math.PI){out="-\u03C0";}
else
if(result == Math.E){out="e";}
else
out=truncate(result);
output.setText("\u2023 "+out);remarks.setText(rem4+remark);
} catch (SyntaxException e) {output.setText("\u2023 ?");remarks.setText(rem1+remark);}
}
}
else
{
output.setText(rem2);
remarks.setText(rem4+remark);
}
}
else
{
output.setText("\u2023 ");
remarks.setText(rem6);
}
input.setText("? ");
input.setCaretPosition(2); /* first 2 positions are: ? [space] */
}
 
public String RawMath(String i){
i=i.toLowerCase();
i=i.replace(" ","");
i=i.replace("**","^");
if(i.indexOf("e+")!=-1){i=i.replace("e+","*10^");}
if(i.indexOf("e-")!=-1){i=i.replace("e-","*10^-");}
i=i.replace("**","*");
String[] fun={"sin","cos","tan","log","ln","pi","e"};
String[] cons={"pi","e","0","1","2","3","4","5","6","7","8","9"};
for(int p=0;p<fun.length;p++){
for( int d=0;d<cons.length;d++){
while(i.indexOf(cons[d]+""+fun[p])!=-1){
i=i.replace(cons[d]+""+fun[p],cons[d]+"*"+fun[p]);
}
while(i.indexOf(fun[p]+""+cons[d])!=-1){
i=i.replace(fun[p]+""+cons[d],fun[p]+"*"+cons[d]);
}
}
}
if(i.indexOf("(")!=-1){
for(int p=0;p<cons.length;p++){
if(i.indexOf(cons[p]+"(")!=-1){
i=i.replace(cons[p]+"(",cons[p]+"*(");
}
if(i.indexOf(")"+cons[p])!=-1){
i=i.replace(")"+cons[p],")*"+cons[p]);
}
}
i=i.replace(")(",")*(");
}
if(i.indexOf("e")!=-1){
while(i.indexOf("e")!=-1){
i=i.replace("e","2.718281828459045");
}
}
if(i.indexOf("pi")!=-1){
while(i.indexOf("pi")!=-1){
i=i.replace("pi","3.141592653589793");
}
}
 
if(i.indexOf("log(")!=-1 || i.indexOf("ln(")!=-1){i=ConvertLog(i);}
return i;
}
public String ConvertLog(String t){
int begin=t.indexOf("log(");
if(begin==-1){t=replace(t,"ln","log");return t;}
int tot;int Got;int Wait;int End;char chr;int s;
String value;String L;String R;
while (begin >= 0){
begin=t.indexOf("log(");
tot=t.length();
Wait=0;Got=0;End=0;
for(s=begin+3;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='('){Wait=Wait+1;}
if(chr==')'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
//System.out.println("begin="+begin+" end="+End);
value=t.substring(begin+4,End);
L="log("+value+")";R="(@("+value+")/(@(10)))";
t=replace(t,L,R);
}
t=replace(t,"@","log");
t=replace(t,"ln","log");
//System.out.println("corrected log() -> log10() "+t);
return t;
}
 
public void paint(Graphics g){
String S=input.getText();
String SS=inputwindow.textarea.getText();
if(SS.length() > S.length()){S=SS;inputwindow.textarea.setText("");}
calculate(S);
}
 
public static String replace(String source, String pattern, String replace){ /* java 1.4 lacks decent replace() */
if (source!=null){
final int len = pattern.length();
StringBuffer sb = new StringBuffer();
int found = -1;
int start = 0;
while( (found = source.indexOf(pattern, start) ) != -1){
sb.append(source.substring(start, found));
sb.append(replace);
start = found + len;
}
sb.append(source.substring(start));
return sb.toString();
}
else
{
return "";
}
}
 
public String ReadApplet(){ /* interface for sending the answer through javascript to WIMS */
String reply=output.getText();
String tmp[]=reply.split("\u2023");
if( tmp[1].length() == 0){
remarks.setText(rem2);
return "error";
}
else
{
return " "+tmp[1];
}
}
 
private String sqrtn(String t){/* function to replace sqrt[g](n) by n^(1/g) */
int begin=t.indexOf("sqrt[");
String org=t;
int tot;int Got;int Wait;int End;char chr;int s;int restart;
String value;String exp;String val;String L;String R;int cnt=0;
while (begin >= 0){
cnt++;if(cnt>1000){remarks.setText("sqrt[]() syntax error");}
tot=t.length();Wait=0;Got=0;End=0;
for(s=begin+4;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='['){Wait=Wait+1;}
if(chr==']'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
restart=End;
exp=t.substring(begin+5,End);
Wait=0;Got=0;End=0;
for(s=restart;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='('){Wait=Wait+1;}
if(chr==')'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
val=t.substring(restart+2,End);
R="("+val+")^(1/("+exp+"))";L="sqrt["+exp+"]("+val+")";
t=replace(t,L,R);
begin=t.indexOf("sqrt[");
}
return t;
}
 
private String logn(String t){/* function to replace sqrt[g](n) by n^(1/g) */
int begin=t.indexOf("log[");
String org=t;
int tot;int Got;int Wait;int End;char chr;int s;int restart;
String value;String exp;String val;String L;String R;int cnt=0;
while (begin >= 0){
cnt++;if(cnt>1000){remarks.setText("log[]() syntax error");}
tot=t.length();Wait=0;Got=0;End=0;
for(s=begin+3;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='['){Wait=Wait+1;}
if(chr==']'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
restart=End;
exp=t.substring(begin+4,End);
Wait=0;Got=0;End=0;
for(s=restart;s<tot;s++){
if(End==0){
chr=t.charAt(s);
if(chr=='('){Wait=Wait+1;}
if(chr==')'){Got=Got+1;}
if(Got!=0){if(Wait==Got){End=s;}}
}
}
val=t.substring(restart+2,End);
R="(log("+val+"))/(log("+exp+"))";L="log["+exp+"]("+val+")";
t=replace(t,L,R);
begin=t.indexOf("log[");
}
return t;
}
 
public String getAppletInfo(){
return "Java Calculator\n \u2023 using \"Arity\" library\n \u2023 normal arithmetics \n \u2023 sin(),cos(),tan(),sinh(),etc() \n \u2023 sqrt() sqrt[n]() log() \n \u2023 javascript communication [WIMS] \n \u2023 precision adjustable [\u00B1 "+precision+"]\nJ.M. Evers 10/2008";
}
 
public String truncate(double t){
String r = decformat.format(precision*(Math.round(t/precision)));
return r;
}
public void start(){}
public void stop(){}
 
public void run(){}
 
}
 
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/InputWindow.java
0,0 → 1,26
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
*/
import java.applet.*;
import javax.swing.*;
 
public class InputWindow extends javax.swing.JFrame {
public InputWindow() {
panel1 = new javax.swing.JPanel();
textarea=new JTextArea();
panel1.add(textarea);
getContentPane().add(panel1);
pack();
}
 
public javax.swing.JPanel panel1;
public JTextArea textarea;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Symbol.java
0,0 → 1,66
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Symbol {
static final int CONST_ARITY = -3;
 
private String name;
private int arity;
 
byte op;
Function fun;
double value = 0;
 
Symbol(String name, int arity, byte op) {
setKey(name, arity);
this.op = op;
}
 
Symbol(String name, Function fun) {
setKey(name, fun.arity());
this.fun = fun;
}
 
Symbol(String name, double value) {
setKey(name, CONST_ARITY);
this.value = value;
}
 
static Symbol newEmpty(Symbol s) {
return new Symbol(s.name, s.arity, (byte)0);
}
 
boolean isEmpty() {
return op == 0 && fun == null && value == 0;
}
 
Symbol setKey(String name, int arity) {
this.name = name;
this.arity = arity;
return this;
}
 
public boolean equals(Object other) {
Symbol symbol = (Symbol) other;
return name.equals(symbol.name) && arity == symbol.arity;
}
 
public int hashCode() {
return name.hashCode() + arity;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/SyntaxException.java
0,0 → 1,50
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Thrown when the expression can't be compiled, because it's either not
well-formed (e.g. "1+"), or because some simbols aren't defined (e.g. "foo+2").
*/
public class SyntaxException extends Exception {
/**
The expression which caused the error.
*/
public String expression;
 
/**
Explicative message (cause of error).
*/
public String message;
 
/**
The position inside expression where the error occured.
*/
public int position;
 
public String toString() {
return "SyntaxException: " + message
+ " in '" + expression
+ "' at position " + position;
}
 
SyntaxException set(String str, int pos) {
message = str;
position = pos;
return this;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/ArityException.java
0,0 → 1,28
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Thrown when a {@link Function} is evaluated with a wrong number of arguments
(when the number of arguments is not equal to the function's arity).
*/
 
public class ArityException extends Exception {
public ArityException(String mes) {
super(mes);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/FunctionAndName.java
0,0 → 1,32
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
This class is needed because we want to return both a function and its name.
(work-around for java not supporting multi-value return)
*/
 
public class FunctionAndName {
public Function function;
public String name;
 
public FunctionAndName(Function fun, String name) {
this.function = fun;
this.name = name;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Compiler.java
0,0 → 1,76
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Compiles a textual arithmetic expression to a {@link Function}.<p>
*/
class Compiler {
private final SyntaxException exception = new SyntaxException();
private final Lexer lexer = new Lexer(exception);
private final RPN rpn = new RPN(exception);
private final DeclarationParser declParser = new DeclarationParser(exception);
private final OptCodeGen codeGen = new OptCodeGen(exception);
private final SimpleCodeGen simpleCodeGen = new SimpleCodeGen(exception);
private final Declaration decl = new Declaration();
 
double eval(Symbols symbols, String expression) throws SyntaxException {
rpn.setConsumer(simpleCodeGen.setSymbols(symbols));
lexer.scan(expression, rpn);
return simpleCodeGen.getValue();
}
 
FunctionAndName compile(Symbols symbols, String source) throws SyntaxException {
Function fun = null;
decl.parse(source, lexer, declParser);
if (decl.arity == DeclarationParser.UNKNOWN_ARITY) {
try {
double value = eval(symbols, decl.expression);
fun = new Constant(value);
} catch (SyntaxException e) {
if (e != SimpleCodeGen.HAS_ARGUMENTS) {
throw e;
}
// fall-through (see below)
}
}
if (fun == null) { // either decl.arity was set, or an ArityException happened above
symbols.pushFrame();
symbols.addArguments(decl.args);
try {
rpn.setConsumer(codeGen.setSymbols(symbols));
lexer.scan(decl.expression, rpn);
} finally {
symbols.popFrame();
}
int arity = decl.arity;
if (arity == DeclarationParser.UNKNOWN_ARITY) {
arity = codeGen.intrinsicArity;
}
fun = codeGen.getFun(arity);
 
/*
if (decl.name != null && addDefinition) {
symbols.addDefinition(decl.name, fun, decl.arity==DeclarationParser.UNKNOWN_ARITY);
}
*/
}
 
return new FunctionAndName(fun, decl.name);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/FunctionStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class FunctionStack {
private Function[] data = new Function[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(Function b) {
if (size >= data.length) {
Function[] newData = new Function[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
Function[] toArray() {
Function[] trimmed = new Function[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/MoreMath.java
0,0 → 1,183
/*
* Copyright (C) 2006-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
 
package org.javia.arity;
 
class MoreMath extends BaseMath {
private static final double LOG2E = 1.4426950408889634074;
 
public static final double asinh(double x) {
return (x < 0) ? -asinh(-x) : log(x + x + 1/(Math.sqrt(x*x + 1) + x));
}
public static final double acosh(double x) {
return log(x + x - 1/(Math.sqrt(x*x - 1) + x));
}
 
public static final double atanh(double x) {
return (x < 0) ? -atanh(-x) : 0.5 * log(1. + (x + x)/(1 - x));
}
 
public static final double trunc(double x) {
return x >= 0 ? Math.floor(x) : Math.ceil(x);
}
 
public static final double gcd(double x, double y) {
//double remainder = y;
if (Double.isNaN(x) || Double.isNaN(y) ||
Double.isInfinite(x) || Double.isInfinite(y)) {
return Double.NaN;
}
x = Math.abs(x);
y = Math.abs(y);
double save;
while (y > 1e-12) {
save = y;
y = x % y;
x = save;
//Log.log(y);
}
return x > 1e-10 ? x : 0;
}
public static final double lgamma(double x) {
double tmp = x + 5.2421875; //== 607/128. + .5;
return 0.9189385332046727418 //LN_SQRT2PI, ln(sqrt(2*pi))
+ log(
0.99999999999999709182 +
57.156235665862923517 / ++x +
-59.597960355475491248 / ++x +
14.136097974741747174 / ++x +
-0.49191381609762019978 / ++x +
.33994649984811888699e-4 / ++x +
.46523628927048575665e-4 / ++x +
-.98374475304879564677e-4 / ++x +
.15808870322491248884e-3 / ++x +
-.21026444172410488319e-3 / ++x +
.21743961811521264320e-3 / ++x +
-.16431810653676389022e-3 / ++x +
.84418223983852743293e-4 / ++x +
-.26190838401581408670e-4 / ++x +
.36899182659531622704e-5 / ++x
)
+ (tmp-4.7421875)*log(tmp) - tmp
;
}
 
static final double FACT[] = {
1.0,
40320.0,
2.0922789888E13,
6.204484017332394E23,
2.631308369336935E35,
8.159152832478977E47,
1.2413915592536073E61,
7.109985878048635E74,
1.2688693218588417E89,
6.1234458376886085E103,
7.156945704626381E118,
1.8548264225739844E134,
9.916779348709496E149,
1.0299016745145628E166,
1.974506857221074E182,
6.689502913449127E198,
3.856204823625804E215,
3.659042881952549E232,
5.5502938327393044E249,
1.3113358856834524E267,
4.7147236359920616E284,
2.5260757449731984E302,
};
 
public static final double factorial(double x) {
if (x < 0) { // x <= -1 ?
return Double.NaN;
}
if (x <= 170) {
if (Math.floor(x) == x) {
int n = (int)x;
double extra = x;
switch (n & 7) {
case 7: extra *= --x;
case 6: extra *= --x;
case 5: extra *= --x;
case 4: extra *= --x;
case 3: extra *= --x;
case 2: extra *= --x;
case 1: return FACT[n >> 3] * extra;
case 0: return FACT[n >> 3];
}
}
}
return exp(lgamma(x));
}
 
public static final double comb(double n, double k) {
if (n < 0 || k < 0) { return Double.NaN; }
if (n < k) { return 0; }
if (Math.floor(n) == n && Math.floor(k) == k) {
k = Math.min(k, n-k);
if (n <= 170 && 12 < k && k <= 170) {
return factorial(n)/factorial(k)/factorial(n-k);
} else {
double r = 1, diff = n-k;
for (double i = k; i > .5 && r < Double.POSITIVE_INFINITY; --i) {
r *= (diff+i)/i;
}
return r;
}
} else {
return exp(lgamma(n) - lgamma(k) - lgamma(n-k));
}
}
 
public static final double perm(double n, double k) {
if (n < 0 || k < 0) { return Double.NaN; }
if (n < k) { return 0; }
if (Math.floor(n) == n && Math.floor(k) == k) {
if (n <= 170 && 10 < k && k <= 170) {
return factorial(n)/factorial(n-k);
} else {
double r = 1, limit = n-k+.5;
for (double i = n; i > limit && r < Double.POSITIVE_INFINITY; --i) {
r *= i;
}
return r;
}
} else {
return exp(lgamma(n) - lgamma(n-k));
}
}
 
public static final double log2(double x) {
return log(x) * LOG2E;
}
 
private static final boolean isPiMultiple(double x) {
return x % Math.PI == 0;
}
 
public static final int intLog10(double x) {
//an alternative implem is using a for loop.
return (int)Math.floor(log10(x));
//return (int)log10(x);
}
 
public static final double intExp10(int exp) {
return Double.parseDouble("1E" + exp);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Util.java
0,0 → 1,149
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Contains static helper methods for formatting double values.
*/
public class Util {
/*
private static String replace(String str, String what, String repl) {
int pos = str.indexOf(what);
while (pos != -1) {
str = str.substring(0, pos) + repl + str.substring(pos + what.length());
pos = str.indexOf(what);
}
//Log.log("replaced: '"+str+"'");
return str;
}
*/
 
/** Returns a number which is an approximation of v (within maxError)
and which has fewer digits in base-10).
@param value the value to be approximated
@param maxError the maximum deviation from value
@return an approximation with a more compact base-10 representation.
*/
public static double shortApprox(double value, double maxError) {
final double v = Math.abs(value);
final double tail = MoreMath.intExp10(MoreMath.intLog10(Math.abs(maxError)));
final double ret = Math.floor(v/tail +.5)*tail;
return (value < 0) ? -ret : ret;
}
 
/**
Returns an approximation with no more than maxLen chars.
@param str the value to truncate (e.g. "-2.898983455E20")
@param maxLen the maximum number of characters in the returned string
@return a truncation no longer then maxLen (e.g. "-2.8E20" for maxLen=7).
*/
public static String sizeTruncate(String str, int maxLen) {
int ePos = str.lastIndexOf('E');
String tail = (ePos != -1) ? str.substring(ePos) : "";
int tailLen = tail.length();
int maxHeadLen = maxLen - tailLen;
return str.substring(0, Math.min(str.length()-tailLen, maxHeadLen)) + tail;
}
 
/**
Rounds by dropping roundingDigits of double precision
(similar to 'hidden precision digits' on calculators),
and formats to String.
@param v the value to be converted to String
@param roundingDigits the number of 'hidden precision' digits (e.g. 2).
@return a String representation of v
*/
public static String doubleToString(double v, int roundingDigits) {
if (roundingDigits > 13) {
roundingDigits = 0;
}
int roundingStart = roundingDigits == 0 ? 17 : 15 - roundingDigits;
 
String str = Double.toString(Math.abs(v));
StringBuffer buf = new StringBuffer(str);
int ePos = str.lastIndexOf('E');
int exp = (ePos != -1) ? Integer.parseInt(str.substring(ePos + 1)) : 0;
if (ePos != -1) {
buf.setLength(ePos);
}
int len = buf.length();
 
//remove dot
int dotPos;
for (dotPos = 0; dotPos < len && buf.charAt(dotPos) != '.';) ++dotPos;
exp += dotPos;
if (dotPos < len) {
buf.deleteCharAt(dotPos);
--len;
}
 
//round
for (int p = 0; p < len && buf.charAt(p) == '0'; ++p) {
++roundingStart;
}
 
if (roundingStart < len) {
if (buf.charAt(roundingStart) >= '5') {
int p;
for (p = roundingStart-1; p >= 0 && buf.charAt(p)=='9'; --p) {
buf.setCharAt(p, '0');
}
if (p >= 0) {
buf.setCharAt(p, (char)(buf.charAt(p)+1));
} else {
buf.insert(0, '1');
++roundingStart;
++exp;
}
}
buf.setLength(roundingStart);
}
 
//re-insert dot
if ((exp < -5) || (exp > 10)) {
buf.insert(1, '.');
--exp;
} else {
for (int i = len; i < exp; ++i) {
buf.append('0');
}
buf.insert((exp<0)? 0 : exp, '.');
for (int i = exp; i <= 0; ++i) {
buf.insert(0, '0');
}
exp = 0;
}
len = buf.length();
//remove trailing dot and 0s.
int tail;
for (tail = len-1; tail >= 0 && buf.charAt(tail) == '0'; --tail) {
buf.deleteCharAt(tail);
}
if (tail >= 0 && buf.charAt(tail) == '.') {
buf.deleteCharAt(tail);
}
 
if (exp != 0) {
buf.append('E').append(exp);
}
if (v < 0) {
buf.insert(0, '-');
}
return buf.toString();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/SimpleCodeGen.java
0,0 → 1,99
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/* Non-optimizing Code Generator
Reads tokens in RPN (Reverse Polish Notation) order,
and generates VM opcodes,
without any optimization.
*/
 
class SimpleCodeGen extends TokenConsumer {
private CompiledFunction compiledFunction = new CompiledFunction();
static final SyntaxException HAS_ARGUMENTS = new SyntaxException();
 
ByteStack code = new ByteStack();
DoubleStack consts = new DoubleStack();
FunctionStack funcs = new FunctionStack();
 
//String argNames[];
Symbols symbols;
 
SyntaxException exception;
 
SimpleCodeGen(SyntaxException exception) {
this.exception = exception;
}
 
SimpleCodeGen setSymbols(Symbols symbols) {
this.symbols = symbols;
return this;
}
 
//@Override
void start() {
code.clear();
consts.clear();
funcs.clear();
}
void push(Token token) throws SyntaxException {
byte op;
switch (token.id) {
case Lexer.NUMBER:
op = VM.CONST;
consts.push(token.value);
break;
case Lexer.CONST:
case Lexer.CALL:
Symbol symbol = symbols.lookup(token.name, token.arity);
if (symbol == null) {
throw exception.set("undefined '" + token.name + "' with arity " + token.arity, token.position);
}
if (symbol.op > 0) { // built-in
op = symbol.op;
if (op >= VM.LOAD0 && op <= VM.LOAD4) {
throw HAS_ARGUMENTS.set("eval() on implicit function", exception.position);
}
} else if (symbol.fun != null) { // function call
op = VM.CALL;
funcs.push(symbol.fun);
} else { // variable reference
op = VM.CONST;
consts.push(symbol.value);
}
break;
default:
op = token.vmop;
if (op <= 0) {
throw new Error("wrong vmop: " + op);
}
}
code.push(op);
}
double getValue() {
compiledFunction.init(0, code.toArray(), consts.toArray(), funcs.toArray());
try {
return compiledFunction.eval();
} catch (ArityException e) {
throw new Error("" + e); //never
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/UnitTest.java
0,0 → 1,345
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class EvalCase {
String expr;
double result;
static final double ERR = -2, FUN = -3;
 
EvalCase(String expr, double result) {
this.expr = expr;
this.result = result;
}
}
 
class TestEval {
static EvalCase cases[] = {
new EvalCase(".", 0),
new EvalCase("1+.", 1),
new EvalCase("1", 1),
new EvalCase("\u03c0", Math.PI),
new EvalCase("2\u00d73", 6), //2*3
new EvalCase("1+\u221a9*2", 7), //1+sqrt(9)*2
new EvalCase("3\u221a 4", 6), //3*sqrt(4)
new EvalCase("\u221a16sin(2\u03c0/4)", 4), //sqrt(16)*sin(2pi/4)
new EvalCase("1+", EvalCase.ERR),
new EvalCase("1+1", 2),
new EvalCase("1+-1", 0),
new EvalCase("-0.5", -.5),
new EvalCase("+1e2", 100),
new EvalCase("-2^3!", -64),
new EvalCase("(-2)^3!", 64),
new EvalCase("-2^1^2", -2),
new EvalCase("--1", 1),
new EvalCase("-3^--2", -9),
new EvalCase("1+2)(2+3", 15),
new EvalCase("1+2)!^-2", 1./36),
new EvalCase("sin(0)", 0),
new EvalCase("cos(0)", 1),
new EvalCase("sin(-1--1)", 0),
new EvalCase("-(2+1)*-(4/2)", 6),
new EvalCase("-.5E-1", -.05),
new EvalCase("1E1.5", EvalCase.ERR),
new EvalCase("2 3 4", 24),
new EvalCase("pi", Math.PI),
new EvalCase("e", Math.E),
new EvalCase("sin(pi/2)", 1),
new EvalCase("f=sin(2x)", EvalCase.FUN),
new EvalCase("f(pi/2)", 0),
new EvalCase("a=3", 3),
new EvalCase("b=a+1", 4),
new EvalCase("f(x, y) = x*(y+1)", EvalCase.FUN),
new EvalCase("f(a, b-a)", 6),
new EvalCase(" f(a pi/4)", -1),
new EvalCase("f ( 1 + 1 , a+1)", 10),
new EvalCase("g(foo) = f (f(foo, 1)pi/2)", EvalCase.FUN),
new EvalCase("g(.5*2)", 0),
new EvalCase("NaN", Double.NaN),
new EvalCase("Inf", Double.POSITIVE_INFINITY),
new EvalCase("Infinity", Double.POSITIVE_INFINITY),
new EvalCase("-Inf", Double.NEGATIVE_INFINITY),
new EvalCase("0/0", Double.NaN)
};
 
private static boolean equal(double a, double b) {
return Math.abs(a-b) < 1E-15 ||
Double.doubleToLongBits(a) == Double.doubleToLongBits(b);
}
 
static boolean testEval() throws ArityException {
final String spaces = " ";
boolean allOk = true;
Symbols symbols = new Symbols();
for (int i = 0; i < cases.length; ++i) {
EvalCase c = cases[i];
String strResult;
boolean ok;
try {
double actual;
if (Symbols.isDefinition(c.expr)) {
FunctionAndName fan = symbols.compile(c.expr);
symbols.define(fan);
Function f = fan.function;
actual = f.arity()==0 ? f.eval() : EvalCase.FUN;
strResult = (f.arity()==0 ? Util.doubleToString(actual, 1) : f.toString());
} else {
actual = symbols.eval(c.expr);
strResult = Util.doubleToString(actual, 1);
}
ok = equal(c.result, actual);
} catch (SyntaxException e) {
strResult = e.toString();
ok = c.result == EvalCase.ERR;
}
System.out.println((ok ? "" : "failed (expected " + c.result + "): ")
+ c.expr
+ spaces.substring(0, Math.max(15-c.expr.length(), 0)) + " = "
+ strResult);
if (!ok) {
allOk = false;
}
}
return allOk;
}
}
 
 
class FormatCase {
public FormatCase(int rounding, double v, String s) {
this.rounding = rounding;
this.val = v;
this.res = s;
}
public int rounding;
public double val;
public String res;
}
 
class TestFormat {
static FormatCase cases[] = {
new FormatCase(0, 0.1, "0.1"),
new FormatCase(0, 0.12, "0.12"),
new FormatCase(0, 0.001, "0.001"),
new FormatCase(0, 0.0012, "0.0012"),
new FormatCase(0, 0.0000001, "1E-7"),
new FormatCase(0, 0.00000012, "1.2E-7"),
new FormatCase(0, 0.123456789012345, "0.123456789012345"),
 
new FormatCase(0, 0, "0"),
new FormatCase(0, 1, "1"),
new FormatCase(0, 12, "12"),
new FormatCase(0, 1234567890., "1234567890"),
new FormatCase(0, 1000000000., "1000000000"),
new FormatCase(0, 1.23456789012345, "1.23456789012345"),
new FormatCase(0, 12345.6789012345, "12345.6789012345"),
new FormatCase(0, 1234567890.12345, "1234567890.12345"),
new FormatCase(0, 123456789012345., "1.23456789012345E14"),
new FormatCase(0, 100000000000000., "1E14"),
new FormatCase(0, 120000000000000., "1.2E14"),
new FormatCase(0, 100000000000001., "1.00000000000001E14"),
 
new FormatCase(2, 0.1, "0.1"),
new FormatCase(2, 0.00000012, "1.2E-7"),
new FormatCase(1, 0.123456789012345, "0.12345678901235"),
 
new FormatCase(2, 0, "0"),
new FormatCase(1, 1.23456789012345, "1.2345678901235"),
new FormatCase(2, 1.23456789012345, "1.234567890123"),
new FormatCase(0, 12345.6789012345, "12345.6789012345"),
new FormatCase(1, 1234567890.12345, "1234567890.1235"),
new FormatCase(2, 123456789012345., "1.234567890123E14"),
new FormatCase(1, 100000000000001., "1E14"),
 
new FormatCase(0, 12345678901234567., "1.2345678901234568E16"),
new FormatCase(1, 12345678901234567., "1.2345678901235E16"),
 
new FormatCase(0, 99999999999999999., "1E17"),
new FormatCase(0, 9999999999999999., "1E16"),
new FormatCase(0, 999999999999999., "9.99999999999999E14"),
new FormatCase(1, 999999999999999., "1E15"),
new FormatCase(1, 999999999999994., "9.9999999999999E14"),
 
new FormatCase(1, MoreMath.log2(1+.00002), "00000.28853612282487")
};
 
static boolean testFormat() {
boolean ret = true;
for (int i = 0; i < cases.length; ++i) {
FormatCase c = cases[i];
double v = Double.parseDouble(c.res);
if (c.rounding == 0 && v != c.val) {
System.out.println("wrong test? " + c.res + " " + v + " " + c.val);
}
String res = Util.doubleToString(c.val, c.rounding);
if (!res.equals(c.res)) {
System.out.println("Expected '" + c.res + "', got '" + res + "'. " + Double.toString(c.val));
ret = false;
}
int nKeep = c.rounding == 0 ? 17 : 15 - c.rounding;
//System.out.println("" + Double.toString(c.val) + " " + Util.round(c.val, nKeep) + " " + c.res + ", got " + res);
}
return ret;
}
}
 
/**
Runs unit-tests.<p>
Usage: java -jar arity.jar
*/
public class UnitTest {
/**
Takes a single command-line argument, an expression; compiles and prints it.<p>
Without arguments, runs the unit tests.
@throws SyntaxException if there are errors compiling the expression.
*/
public static void main(String argv[]) throws SyntaxException, ArityException {
int size = argv.length;
if (size == 0) {
runUnitTests();
profile();
} else if (size == 1 && argv[0].equals("-profile")) {
profile();
} else {
Symbols symbols = new Symbols();
for (int i = 0; i < size; ++i) {
FunctionAndName fan = symbols.compile(argv[i]);
symbols.define(fan);
}
profile(symbols, argv[size-1]);
}
}
 
static void profile(Symbols symbols, String str) throws SyntaxException, ArityException {
Function f = symbols.compile(str).function;
System.out.println("\n" + str + ": " + f);
 
Runtime runtime = Runtime.getRuntime();
 
runtime.gc();
/*
long m1 = runtime.freeMemory();
for (int i = 0; i < 200; ++i) {
symbols.compile(str);
}
long m2 = runtime.freeMemory();
System.out.println("compilation memory: " + (m1 - m2)/200 + " bytes");
*/
runtime.gc();
long t1 = System.currentTimeMillis();
for (int i = 0; i < 1000; ++i) {
symbols.compile(str);
}
long t2 = System.currentTimeMillis();
System.out.println("compilation time: " + (t2 - t1) + " us");
double args[] = new double[f.arity()];
/*
runtime.gc();
m1 = runtime.freeMemory();
f.eval(args);
m2 = runtime.freeMemory();
if (m2 != m1) {
System.out.println("execution memory: " + (m1 - m2) + " bytes");
}
*/
runtime.gc();
t1 = System.currentTimeMillis();
for (int i = 0; i < 100000; ++i) {
f.eval(args);
}
t2 = System.currentTimeMillis();
long delta = t2 - t1;
System.out.println("execution time: " + (delta > 100 ? ""+delta/100.+" us" : ""+delta+" ns"));
}
 
private static final String profileCases[] = {
//"1+1",
"(100.5 + 20009.999)*(7+4+3)/(5/2)^3!)*2",
"fun1(x)=(x+2)*(x+3)",
"otherFun(x)=(fun1(x-1)*x+1)*(fun1(2-x)+10)",
"log(x+30.5, 3)^.7*sin(x+.5)"
};
 
private static void profile() {
String cases[] = profileCases;
Symbols symbols = new Symbols();
try {
for (int i = 0; i < cases.length; ++i) {
symbols.define(symbols.compile(cases[i]));
profile(symbols, cases[i]);
}
} catch (Exception e) {
throw new Error("" + e);
}
}
 
static void runUnitTests() {
checkCounter = 0;
 
cheq(MoreMath.log(-1), Double.NaN);
cheq(MoreMath.log(-0.03), Double.NaN);
cheq(MoreMath.intLog10(-0.03), 0);
cheq(MoreMath.intLog10(0.03), -2);
cheq(MoreMath.intExp10(3), 1000);
cheq(MoreMath.intExp10(-1), 0.1);
cheq(Util.shortApprox( 1.235, 0.02), 1.24);
cheq(Util.shortApprox( 1.235, 0.4), 1.2000000000000002);
cheq(Util.shortApprox(-1.235, 0.02), -1.24);
cheq(Util.shortApprox(-1.235, 0.4), -1.2000000000000002);
 
check(TestFormat.testFormat());
try {
check(TestEval.testEval());
} catch (ArityException e) {
System.out.println(""+e);
}
 
if (!allOk) {
System.out.println("\n*** Some tests FAILED ***\n");
System.exit(1);
} else {
System.out.println("\n*** All tests passed OK ***\n");
}
}
 
static void cheq(double v1, double v2) {
++checkCounter;
if (v1 != v2 && !(Double.isNaN(v1) && Double.isNaN(v2))) {
allOk = false;
//Log.log("check equal " + checkCounter + " failed: " + v1 + " " + v2);
}
}
static void check(boolean cond) {
++checkCounter;
if (!cond) {
allOk = false;
//Log.log("check " + checkCounter + " failed");
}
}
 
static boolean allOk = true;
static int checkCounter = 0;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Lexer.java
0,0 → 1,176
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Lexer {
static final int
ADD = 1,
SUB = 2,
MUL = 3,
DIV = 4,
MOD = 5,
UMIN = 6,
POWER = 7,
FACT = 8,
NUMBER = 9,
CONST = 10,
CALL = 11,
COMMA = 12,
LPAREN = 13,
RPAREN = 14,
END = 15,
SQRT = 16;
static final Token
TOK_ADD = new Token(ADD, 3, Token.LEFT, VM.ADD),
TOK_SUB = new Token(SUB, 3, Token.LEFT, VM.SUB),
 
TOK_MUL = new Token(MUL, 4, Token.LEFT, VM.MUL),
TOK_DIV = new Token(DIV, 4, Token.LEFT, VM.DIV),
TOK_MOD = new Token(MOD, 4, Token.LEFT, VM.MOD),
 
TOK_UMIN = new Token(UMIN, 5, Token.PREFIX, VM.UMIN),
 
TOK_POWER = new Token(POWER, 6, Token.RIGHT, VM.POWER),
TOK_FACT = new Token(FACT, 7, Token.SUFIX, VM.FACT),
TOK_SQRT = new Token(SQRT, 8, Token.PREFIX, VM.SQRT),
 
TOK_LPAREN = new Token(LPAREN, 1, Token.PREFIX, 0),
TOK_RPAREN = new Token(RPAREN, 2, 0, 0),
TOK_COMMA = new Token(COMMA, 1, 0, 0),
TOK_END = new Token(END, 0, 0, 0),
 
TOK_NUMBER = new Token(NUMBER, 20, 0, 0),
TOK_CONST = new Token(CONST, 20, 0, 0);
 
private static final String WHITESPACE = " \n\r\t";
private static final char END_MARKER = '$';
private char[] input = new char[32];
private int pos;
private SyntaxException exception;
 
Lexer(SyntaxException exception) {
this.exception = exception;
init("");
}
 
void scan(String str, TokenConsumer consumer) throws SyntaxException {
init(str);
consumer.start();
Token token;
do {
int savePos = pos;
token = nextToken();
token.position = savePos;
consumer.push(token);
} while (token != TOK_END);
}
 
void init(String str) {
exception.expression = str;
int len = str.length();
if (input.length < len + 1) {
input = new char[len+1];
}
str.getChars(0, len, input, 0);
input[len] = END_MARKER;
pos = 0;
}
 
Token nextToken() throws SyntaxException {
while (WHITESPACE.indexOf(input[pos]) != -1) {
++pos;
}
 
char c = input[pos];
int begin = pos++;
 
switch (c) {
case '!': return TOK_FACT;
case END_MARKER: return TOK_END;
case '%': return TOK_MOD;
case '(': return TOK_LPAREN;
case ')': return TOK_RPAREN;
case '*': return TOK_MUL;
case '+': return TOK_ADD;
case ',': return TOK_COMMA;
case '-': return TOK_SUB;
case '/': return TOK_DIV;
}
if (c == '^') {
return TOK_POWER;
}
 
int p = pos;
if (('0' <= c && c <= '9') || c == '.') {
while (('0' <= c && c <= '9') || c == '.' || c == 'E' || c == 'e') {
if ((c == 'E' || c == 'e') && input[p] == '-') { //accept '-' only after E
++p;
}
c = input[p++];
}
pos = p-1;
String nbStr = String.valueOf(input, begin, p-1-begin);
try {
// parse single dot as 0
if (nbStr.equals(".")) {
return TOK_NUMBER.setValue(0);
} else {
double numberValue = Double.parseDouble(nbStr);
return TOK_NUMBER.setValue(numberValue);
}
} catch (NumberFormatException e) {
throw exception.set("invalid number '" + nbStr + "'", begin);
}
} else if (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z')) {
do {
c = input[p++];
} while (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
('0' <= c && c <= '9'));
String nameValue = String.valueOf(input, begin, p-1-begin);
while (WHITESPACE.indexOf(c) != -1) {
c = input[p++];
}
if (c == '(') {
pos = p;
return (new Token(CALL, 0, Token.PREFIX, 0)).setAlpha(nameValue);
} else {
pos = p-1;
return TOK_CONST.setAlpha(nameValue);
}
} else if ((c >= '\u0391' && c <= '\u03a9') || (c >= '\u03b1' && c <= '\u03c9')) {
return TOK_CONST.setAlpha(""+c);
} else {
switch (c) {
case '^':
return TOK_POWER;
case '\u00d7':
return TOK_MUL;
case '\u00f7':
return TOK_DIV;
case '\u2212':
return TOK_SUB;
case '\u221a':
return TOK_SQRT;
default:
throw exception.set("invalid character '" + c + "'", begin);
}
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Token.java
0,0 → 1,71
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Token {
//kind
static final int
PREFIX = 1,
LEFT = 2,
RIGHT = 3,
SUFIX = 4;
 
final int priority;
final int assoc;
final int id;
final byte vmop;
 
double value = 0; //for NUMBER only
String name = null; //for CONST & CALL
int arity;
int position; //pos inside expression
 
Token(int id, int priority, int assoc, int vmop) {
this.id = id;
this.priority = priority;
this.assoc = assoc;
this.vmop = (byte)vmop;
arity = id == Lexer.CALL ? 1 : Symbol.CONST_ARITY;
}
Token setPos(int pos) {
this.position = pos;
return this;
}
 
Token setValue(double value) {
this.value = value;
return this;
}
 
Token setAlpha(String alpha) {
name = alpha;
return this;
}
 
public String toString() {
switch (id) {
case Lexer.NUMBER:
return "" + value;
case Lexer.CALL:
return name + '(' + arity + ')';
case Lexer.CONST:
return name;
}
return "" + id;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/VM.java
0,0 → 1,117
// This file is automatically generated by the build.py script. Do not edit!
 
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class VM {
 
public static final byte
RESERVED = 0,
CONST = 1,
CALL = 2,
ADD = 3,
SUB = 4,
MUL = 5,
DIV = 6,
MOD = 7,
RND = 8,
UMIN = 9,
POWER = 10,
FACT = 11,
SQRT = 12,
CBRT = 13,
EXP = 14,
LOG = 15,
SIN = 16,
COS = 17,
TAN = 18,
ASIN = 19,
ACOS = 20,
ATAN = 21,
SINH = 22,
COSH = 23,
TANH = 24,
ASINH = 25,
ACOSH = 26,
ATANH = 27,
ABS = 28,
FLOOR = 29,
CEIL = 30,
SIGN = 31,
MIN = 32,
MAX = 33,
GCD = 34,
COMB = 35,
PERM = 36,
LOAD0 = 37,
LOAD1 = 38,
LOAD2 = 39,
LOAD3 = 40,
LOAD4 = 41,
BYTECODE_END = 42;
 
public static final String[] opcodeName = {
"reserved",
"const",
"call",
"add",
"sub",
"mul",
"div",
"mod",
"rnd",
"umin",
"power",
"fact",
"sqrt",
"cbrt",
"exp",
"log",
"sin",
"cos",
"tan",
"asin",
"acos",
"atan",
"sinh",
"cosh",
"tanh",
"asinh",
"acosh",
"atanh",
"abs",
"floor",
"ceil",
"sign",
"min",
"max",
"gcd",
"comb",
"perm",
"load0",
"load1",
"load2",
"load3",
"load4",
"bytecode_end"
};
 
public static final byte[] builtinArity =
{-1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1};
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/BaseMath.java
0,0 → 1,65
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
 
package org.javia.arity;
 
// This class is a replacement for BaseMath.java to be used on Java 1.5 and later
class BaseMath {
public static final double atan(double x) {
return Math.atan(x);
}
public static final double asin(double x) {
return Math.asin(x);
}
 
public static final double acos(double x) {
return Math.acos(x);
}
 
public static final double exp(double x) {
return Math.exp(x);
}
 
public static final double log(double x) {
return Math.log(x);
}
 
public static final double sinh(double x) {
return Math.sinh(x);
}
 
public static final double cosh(double x) {
return Math.cosh(x);
}
 
public static final double tanh(double x) {
return Math.tanh(x);
}
 
public static final double cbrt(double x) {
return Math.cbrt(x);
}
public static final double pow(double x, double y) {
return Math.pow(x, y);
}
 
public static final double log10(double x) {
return Math.log10(x);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Declaration.java
0,0 → 1,50
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Declaration {
private static final String NO_ARGS[] = {};
String name;
String args[];
int arity;
String expression;
 
void parse(String source, Lexer lexer, DeclarationParser declParser) throws SyntaxException {
int equalPos = source.indexOf('=');
String decl;
 
if (equalPos == -1) {
decl = null;
expression = source;
name = null;
args = NO_ARGS;
arity = DeclarationParser.UNKNOWN_ARITY;
} else {
decl = source.substring(0, equalPos);
expression = source.substring(equalPos + 1);
lexer.scan(decl, declParser);
name = declParser.name;
args = declParser.argNames();
arity = declParser.arity;
}
/*
if (arity == DeclarationParser.UNKNOWN_ARITY) {
args = IMPLICIT_ARGS;
}
*/
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Function.java
0,0 → 1,94
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Abstract base class for functions.<p>
A function has an arity (the number of arguments), and a way for evaluation
given the values of the arguments.<p>
Derive from this class to create user-defined functions.
 
<h3>Thread safety</h3>
Assuming the user didn't subclass Function to define user functions,
the compiled Functions are thread-safe
(the same Function instance can be evaluated from multiple threads without locking).<p>
 
Whatsmore, parallel evaluations of the same instance from multiple threads are not
serialized (good).<p>
 
If the user subclasses Function, he is responsible for the thread-safety of
his user-defined Functions.
*/
 
abstract public class Function {
private int cachedArity = -1;
 
/**
Gives the arity of this function.
@return the arity (the number of arguments). Arity >= 0.
*/
public int arity() {
if (cachedArity == -1) {
cachedArity = 0;
for (int i = 0; i < 5; ++i) {
double args[] = new double[i];
try {
eval(args);
cachedArity = i;
break;
} catch (ArityException e) {
//ignore, continue
}
}
}
return cachedArity;
}
 
/**
Evaluates an arity-0 function (a function with no arguments).
@return the value of the function
*/
public double eval() throws ArityException {
throw new ArityException("Didn't expect 0 args");
}
 
public double eval(double x) throws ArityException {
throw new ArityException("Didn't expect 1 args");
}
 
public double eval(double x, double y) throws ArityException {
throw new ArityException("Didn't expect 2 args");
}
 
/**
Evaluates the function given the argument values.
@param args array containing the arguments.
@return the value of the function
@throws ArityException if args.length != arity.
*/
public double eval(double args[]) throws ArityException {
switch (args.length) {
case 0:
return eval();
case 1:
return eval(args[0]);
case 2:
return eval(args[0], args[1]);
}
throw new ArityException("unexpected " + args.length + " args");
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/OptCodeGen.java
0,0 → 1,108
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/* Optimizing Code Generator
Reads tokens in RPN (Reverse Polish Notation) order,
and generates VM opcodes,
doing constant-folding optimization.
*/
 
class OptCodeGen extends SimpleCodeGen {
double stack[] = new double[CompiledFunction.MAX_STACK_SIZE];
int sp = -1;
 
double traceConsts[] = new double[1];
Function traceFuncs[] = new Function[1];
byte traceCode[] = new byte[1];
CompiledFunction tracer = new CompiledFunction(0, traceCode, traceConsts, traceFuncs);
 
int intrinsicArity;
OptCodeGen(SyntaxException e) {
super(e);
}
 
//@Override
void start() {
super.start();
sp = -1;
intrinsicArity = 0;
}
 
//@Override
void push(Token token) throws SyntaxException {
byte op;
switch (token.id) {
case Lexer.NUMBER:
op = VM.CONST;
traceConsts[0] = token.value;
break;
case Lexer.CONST:
case Lexer.CALL:
Symbol symbol = symbols.lookup(token.name, token.arity);
if (symbol == null) {
throw exception.set("undefined '" + token.name + "' with arity " + token.arity, token.position);
}
if (symbol.op > 0) { // built-in
op = symbol.op;
if (op >= VM.LOAD0 && op <= VM.LOAD4) {
int arg = op - VM.LOAD0;
if (arg + 1 > intrinsicArity) {
intrinsicArity = arg + 1;
}
}
} else if (symbol.fun != null) { // function call
op = VM.CALL;
traceFuncs[0] = symbol.fun;
} else { // variable reference
op = VM.CONST;
traceConsts[0] = symbol.value;
}
break;
default:
op = token.vmop;
if (op <= 0) {
throw new Error("wrong vmop: " + op);
}
}
int oldSP = sp;
traceCode[0] = op;
if (op != VM.RND) {
sp = tracer.execWithoutCheck(stack, sp);
} else {
stack[++sp] = Double.NaN;
}
 
//constant folding
if (!Double.isNaN(stack[sp]) || op == VM.CONST) {
code.pop(oldSP + 1 - sp);
consts.pop(oldSP + 1 - sp);
consts.push(stack[sp]);
op = VM.CONST;
} else if (op == VM.CALL) {
funcs.push(traceFuncs[0]);
}
code.push(op);
}
 
CompiledFunction getFun(int arity) {
return new CompiledFunction(arity, code.toArray(), consts.toArray(), funcs.toArray());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Symbols.java
0,0 → 1,264
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
 
/**
The collection of names (<em>symbols</em>) used for parsing an expression
(the context in which the parsing takes place).<p>
 
Each symbol maps to either a {@link Function} or a constant.<p>
 
A symbol is identified by the pair (name, arity).
So a constant and a function with the same name,
or two function with the same name but with different arity
are distinct symbols.<p>
 
Symbols functions as a stack of <em>frames</em>:
when you pop the topmost frame, all the symbols added in that frame dissapear
(i.e. all the modifications done between the push and the pop are lost).<p>
 
Example:
<pre>
<code>
Symbols symbols = new Symbols();
symbols.eval("1+1"); //doesn't update symbols
symbols.define(symbols.compile("f(x)=x^2")); //updates symbols
</code>
</pre>
<p>
 
<h3>Thread safety</h3>
The Symbols class is thread-safe
(the same Symbols instance can be used by multiple threads without locking).<p>
 
The compile() methods are synchronized, so parallel compile() calls on the same Symbols
instance are serialized.
*/
 
public class Symbols {
/**
Constructs a Symbols containing the built-in symbols (such as sin, log).
*/
public Symbols() {
for (int i = 0; i < builtin.length; ++i) {
Symbol s = builtin[i];
symbols.put(s, s);
}
try {
for (int i = 0; i < defines.length; ++i) {
define(compile(defines[i]));
}
} catch (SyntaxException e) {
throw new Error(""+e); //never
}
}
 
/**
@param source the expression
@return true if the expression is a definition (i.e. contains a '=').<p>
These are definitions: "a=1+1"; "f(k)=2^k"<p>
These are not definitions: "1+1"; "x+1"
*/
public static boolean isDefinition(String source) {
return source.indexOf('=') != -1;
}
 
/**
Evaluates a simple expression (such as "1+1") and returns its value.
@throws SyntaxException in these cases:
<ul>
<li> the expression is not well-formed
<li> the expression is a definition (such as "a=1+1")
<li> the expression is an implicit function (such as "x+1")
</ul>
*/
public synchronized double eval(String expression) throws SyntaxException {
return getCompiler().eval(this, expression);
}
 
/**
Compiles an expression in the context of this Symbols.
Does not modify the symbols.
<p>
 
An expression is one of these cases (@see Symbols.isDefinition()):
<ul>
<li> constant value: 1+1
<li> implicit function: x+1
<li> constant definition: a=1+1
<li> function definition with explicit arguments: f(a)=a+1
<li> function definition with implicit arguments: f=x+1
</ul>
<p>
 
@param source the expression; may contain '=' to denote a definition (with a name).
@return the function together with its eventual name.<p>
 
If this is not a definition (e.g. "1+1", "x^2"), the name is null.<p>
If the expression is a constant (e.g. "1+1", "a=2"),
the returned Function is an instance of {@link Constant}.
 
@throws SyntaxException if there are errors compiling the expression.
*/
public synchronized FunctionAndName compile(String source) throws SyntaxException {
return getCompiler().compile(this, source);
}
 
/**
Adds a new function symbol to the top-most frame of this Symbols.
@param name the name of the function (e.g. "sin")
@param function the function to which the name maps
*/
synchronized public void define(String name, Function function) {
if (function instanceof Constant) {
addConstant(name, ((Constant) function).eval());
} else {
add(new Symbol(name, function));
}
}
 
/**
Adds a new function symbol to the top-most frame of this Symbols.
@param funAndName structure containing the function and its name
*/
synchronized public void define(FunctionAndName funAndName) {
if (funAndName.name != null) {
define(funAndName.name, funAndName.function);
}
}
 
/**
Adds a new constant symbol to the top-most frame of this Symbols.
@param name the name of the constant (e.g. "pi")
@param value the value of the constant
*/
synchronized public void addConstant(String name, double value) {
add(new Symbol(name, value));
}
 
/**
Pushes a new top frame.<p>
 
All modifications (defining new symbols) happen in the top-most frame.
When the frame is pop-ed the modifications that happened in it are reverted.
*/
synchronized public void pushFrame() {
frames.push(delta);
delta = null;
}
 
/**
Pops the top frame.<p>
 
All the modifications done since this frame was pushed are reverted.
@throws EmptyStackException if there were fewer <code>pushFrame</code> than <code>popFrame</code>.
*/
synchronized public void popFrame() {
if (delta != null) {
for (int i = delta.size() - 1; i >= 0; --i) {
Symbol previous = (Symbol) delta.elementAt(i);
if (previous.isEmpty()) {
symbols.remove(previous);
} else {
symbols.put(previous, previous);
}
}
}
delta = (Vector) frames.pop();
}
 
 
 
//--- non-public below
 
private final static Symbol builtin[];
private static Symbol shell = new Symbol(null, 0);
private static ThreadLocal compilers = new ThreadLocal();
private static Compiler getCompiler() {
Compiler compiler;
if ((compiler = (Compiler) compilers.get()) == null) {
compilers.set(compiler = new Compiler());
}
return compiler;
}
 
private Hashtable symbols = new Hashtable(); //Hashtable<Symbol, Symbol>
private Vector delta = null; //Vector<Symbol>
private Stack frames = new Stack(); //Stack<Vector>
 
static {
Vector vect = new Vector();
int arity;
for (byte i = 0; i < VM.BYTECODE_END; ++i) {
if ((arity = VM.builtinArity[i]) >= 0) {
vect.addElement(new Symbol(VM.opcodeName[i], arity, i));
}
}
 
final String IMPLICIT_ARGS[] = {"x", "y", "z"};
for (byte i = 0; i < IMPLICIT_ARGS.length; ++i) {
vect.addElement(new Symbol(IMPLICIT_ARGS[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
}
 
vect.addElement(new Symbol("pi", Math.PI));
vect.addElement(new Symbol("\u03c0", Math.PI));
vect.addElement(new Symbol("e", Math.E));
 
vect.addElement(new Symbol("Inf", Double.POSITIVE_INFINITY));
vect.addElement(new Symbol("Infinity", Double.POSITIVE_INFINITY));
vect.addElement(new Symbol("NaN", Double.NaN));
 
int size = vect.size();
builtin = new Symbol[size];
vect.copyInto(builtin);
}
 
private static final String defines[] = {
"ln(x) = log(x)",
"log2(x) = log(x) * 1.4426950408889634074", //*log2(e)
"log10(x) = log(x) * 0.43429448190325182765", //*log10(e)
"lg(x) = log10(x)",
"lb(x) = log2(x)",
"log(x, base) = log(x) / log(base)"
};
void addArguments(String args[]) {
for (int i = 0; i < args.length; ++i) {
add(new Symbol(args[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
}
}
 
void add(Symbol s) {
Object previous = symbols.put(s, s);
if (delta == null) {
delta = new Vector();
}
delta.addElement(previous != null ? previous : Symbol.newEmpty(s));
}
 
synchronized Symbol lookup(String name, int arity) {
return (Symbol) symbols.get(shell.setKey(name, arity));
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/ByteStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class ByteStack {
private byte[] data = new byte[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(byte b) {
if (size >= data.length) {
byte[] newData = new byte[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
byte[] toArray() {
byte[] trimmed = new byte[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/Constant.java
0,0 → 1,30
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
public class Constant extends Function {
private double value;
 
public Constant(double value) {
this.value = value;
}
 
//@Override
public double eval() {
return value;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/TokenConsumer.java
0,0 → 1,24
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
abstract class TokenConsumer {
void start() {
}
 
abstract void push(Token token) throws SyntaxException;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/RPN.java
0,0 → 1,161
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Stack;
import java.util.EmptyStackException;
 
/* Reverse Polish Notation
reads tokens in normal infix order (e.g.: 1 + 2)
and outputs them in Reverse Polish order (e.g.: 1 2 +).
See Dijkstra's Shunting Yard algorithm:
http://en.wikipedia.org/wiki/Shunting_yard_algorithm
*/
class RPN extends TokenConsumer {
Stack stack = new Stack();
int prevTokenId = 0;
TokenConsumer consumer;
SyntaxException exception;
 
RPN(SyntaxException exception) {
this.exception = exception;
}
 
void setConsumer(TokenConsumer consumer) {
this.consumer = consumer;
}
 
//@Override
void start() {
stack.removeAllElements();
prevTokenId = 0;
consumer.start();
}
 
private Token top() {
return stack.empty() ? null : (Token) stack.peek();
}
 
private void popHigher(int priority) throws SyntaxException {
Token t = top();
while (t != null && t.priority >= priority) {
consumer.push(t);
//code.push(t);
stack.pop();
t = top();
}
}
 
static final boolean isOperand(int id) {
return
id == Lexer.FACT ||
id == Lexer.RPAREN ||
id == Lexer.NUMBER ||
id == Lexer.CONST;
}
 
void push(Token token) throws SyntaxException {
int priority = token.priority;
int id = token.id;
switch (id) {
case Lexer.NUMBER:
case Lexer.CONST:
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
consumer.push(token);
break;
/*
case Lexer.CALL:
case Lexer.LPAREN:
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
stack.push(token);
break;
*/
case Lexer.RPAREN: {
if (prevTokenId == Lexer.CALL) {
top().arity--;
} else if (!isOperand(prevTokenId)) {
throw exception.set("unexpected ) or END", token.position);
}
 
popHigher(priority);
Token t = top();
if (t != null) {
if (t.id == Lexer.CALL) {
consumer.push(t);
} else if (t != Lexer.TOK_LPAREN) {
throw exception.set("expected LPAREN or CALL", token.position);
}
stack.pop();
}
break;
}
case Lexer.COMMA: {
if (!isOperand(prevTokenId)) {
throw exception.set("misplaced COMMA", token.position);
}
popHigher(priority);
Token t = top();
if (t==null || t.id != Lexer.CALL) {
throw exception.set("COMMA not inside CALL", token.position);
}
t.arity++;
//code.push(stack.pop());
break;
}
case Lexer.END: {
Token t = Lexer.TOK_RPAREN;
t.position = token.position;
do {
push(t);
} while (top() != null);
break;
}
default: //operators, CALL, LPAREN
if (token.assoc == Token.PREFIX) {
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
stack.push(token);
break;
}
if (!isOperand(prevTokenId)) {
if (id == Lexer.SUB) {
//change SUB to unary minus
token = Lexer.TOK_UMIN;
stack.push(token);
break;
} else if (id == Lexer.ADD) {
// ignore, keep prevTokenId unchanged
return;
}
throw exception.set("operator without operand", token.position);
}
popHigher(priority + (token.assoc == Token.RIGHT ? 1 : 0));
stack.push(token);
}
prevTokenId = token.id;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/DoubleStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class DoubleStack {
private double[] data = new double[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(double b) {
if (size >= data.length) {
double[] newData = new double[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
double[] toArray() {
double[] trimmed = new double[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/DeclarationParser.java
0,0 → 1,88
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Vector;
 
class DeclarationParser extends TokenConsumer {
static final String NO_ARGS[] = new String[0];
static final int UNKNOWN_ARITY = -2;
static final int MAX_ARITY = 5;
String name;
int arity = UNKNOWN_ARITY;
Vector args = new Vector();
 
private SyntaxException exception;
 
DeclarationParser(SyntaxException e) {
this.exception = e;
}
 
//@Override
void start() {
name = null;
args.setSize(0);
}
 
//@Override
void push(Token token) throws SyntaxException {
switch (token.id) {
case Lexer.CALL:
if (name == null) {
name = token.name;
arity = 0;
} else {
throw exception.set("repeated CALL in declaration", token.position);
}
break;
 
case Lexer.CONST:
if (name == null) {
name = token.name;
arity = UNKNOWN_ARITY;
} else if (arity >= 0) {
args.addElement(token.name);
++arity;
if (arity > MAX_ARITY) {
throw exception.set("Arity too large " + arity, token.position);
}
} else {
throw exception.set("Invalid declaration", token.position);
}
break;
 
case Lexer.RPAREN:
case Lexer.COMMA:
case Lexer.END:
break;
 
default:
throw exception.set("invalid token in declaration", token.position);
}
}
String[] argNames() {
if (arity > 0) {
String argNames[] = new String[arity];
args.copyInto(argNames);
return argNames;
} else {
return NO_ARGS;
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Rekenmachien/src/org/javia/arity/CompiledFunction.java
0,0 → 1,253
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Random;
 
class CompiledFunction extends Function {
//static final int INI_STACK_SIZE = 16;
static final int MAX_STACK_SIZE = 128; //if stack ever grows above this likely something is wrong
private static Random random = new Random();
 
private double consts[];
private Function funcs[];
private byte code[];
private int arity; // >= 0
 
private static final ThreadLocal stacks = new ThreadLocal();
 
CompiledFunction(int arity, byte[] code, double[] consts, Function funcs[]) {
init(arity, code, consts, funcs);
}
 
/* This empty constructor is used only by SimpleCodeGen,
which calls init() explicitly later.
*/
CompiledFunction() {
init(0, null, null, null);
}
 
void init(int arity, byte[] code, double[] consts, Function funcs[]) {
this.arity = arity;
this.code = code;
this.consts = consts;
this.funcs = funcs;
}
 
public int arity() {
return arity;
}
 
public String toString() {
StringBuffer buf = new StringBuffer();
int cpos = 0, fpos = 0;
if (arity != 0) {
buf.append("arity ").append(arity).append("; ");
}
for (int i = 0; i < code.length; ++i) {
byte op = code[i];
buf.append(VM.opcodeName[op]);
if (op == VM.CONST) {
buf.append(' ').append(consts[cpos++]);
} else if (op == VM.CALL) {
++fpos;
//buf.append(" {").append(funcs[fpos++].toString()).append('}');
}
buf.append("; ");
}
if (cpos != consts.length) {
buf.append("\nuses only ").append(cpos).append(" consts out of ").append(consts.length);
}
if (fpos != funcs.length) {
buf.append("\nuses only ").append(fpos).append(" funcs out of ").append(funcs.length);
}
return buf.toString();
}
 
private void checkArity(int nArgs) throws ArityException {
if (arity() != nArgs) {
throw new ArityException("Expected " + arity() + " arguments, got " + nArgs);
}
}
 
private double[] getStack() {
double stack[];
if ((stack = (double[]) stacks.get()) == null) {
stacks.set(stack = new double[MAX_STACK_SIZE]);
}
return stack;
}
static final double NO_ARGS[] = new double[0];
public double eval() throws ArityException {
return eval(NO_ARGS);
}
 
public double eval(double x) throws ArityException {
checkArity(1);
double stack[] = getStack();
stack[0] = x;
exec(stack, 0);
return stack[0];
}
 
public double eval(double x, double y) throws ArityException {
checkArity(2);
double stack[] = getStack();
stack[0] = x;
stack[1] = y;
exec(stack, 1);
return stack[0];
}
 
public double eval(double args[]) throws ArityException {
checkArity(args.length);
double stack[] = getStack();
if (args.length > 0) {
System.arraycopy(args, 0, stack, 0, args.length);
}
exec(stack, args.length - 1);
return stack[0];
}
 
void exec(double s[], int p) {
int finalP = execWithoutCheck(s, p);
int expected = p - arity + 1;
if (finalP != expected) {
throw new Error("stack pointer after exec: expected " +
expected + ", got " + finalP);
}
}
int execWithoutCheck(double s[], int p) {
byte[] code = this.code;
int initialSP = p;
int constp = 0;
int funp = 0;
final double angleFactor = 1; // 1/Calc.cfg.trigFactor;
// arguments, read from stack on exec entry
// we don't use an array in order to avoid the dynamic allocation (new)
// @see Compiler.MAX_ARITY
double a0, a1, a2, a3, a4;
a0 = a1 = a2 = a3 = a4 = Double.NaN;
switch (arity) {
case 5: a4 = s[p--];
case 4: a3 = s[p--];
case 3: a2 = s[p--];
case 2: a1 = s[p--];
case 1: a0 = s[p--];
}
 
//int expectedExitSP = p+1;
int codeLen = code.length;
for (int pc = 0; pc < codeLen; ++pc) {
switch (code[pc]) {
case VM.CONST: s[++p] = consts[constp++]; break;
case VM.CALL: {
Function f = funcs[funp++];
if (f instanceof CompiledFunction) {
p = ((CompiledFunction) f).execWithoutCheck(s, p);
} else {
int arity = f.arity();
p -= arity;
try {
double result;
switch (arity) {
case 0:
result = f.eval();
break;
case 1:
result = f.eval(s[p+1]);
break;
case 2:
result = f.eval(s[p+1], s[p+2]);
break;
default:
double args[] = new double[arity];
System.arraycopy(s, p+1, args, 0, arity);
result = f.eval(args);
}
s[++p] = result;
} catch (ArityException e) {
throw new Error(""+e); //never
}
}
break;
}
case VM.RND: s[++p] = random.nextDouble(); break;
case VM.ADD: s[--p] += s[p+1]; break;
case VM.SUB: s[--p] -= s[p+1]; break;
case VM.MUL: s[--p] *= s[p+1]; break;
case VM.DIV: s[--p] /= s[p+1]; break;
case VM.MOD: s[--p] %= s[p+1]; break;
case VM.POWER: s[--p] = MoreMath.pow(s[p], s[p+1]); break;
case VM.UMIN: s[p] = -s[p]; break;
case VM.FACT: s[p] = MoreMath.factorial(s[p]); break;
case VM.SIN: s[p] = Math.sin(s[p] * angleFactor); break;
case VM.COS: s[p] = Math.cos(s[p] * angleFactor); break;
case VM.TAN: s[p] = Math.tan(s[p] * angleFactor); break;
case VM.ASIN: s[p] = MoreMath.asin(s[p]) / angleFactor; break;
case VM.ACOS: s[p] = MoreMath.acos(s[p]) / angleFactor; break;
case VM.ATAN: s[p] = MoreMath.atan(s[p]) / angleFactor; break;
case VM.EXP: s[p] = MoreMath.exp(s[p]); break;
case VM.LOG: s[p] = MoreMath.log(s[p]); break;
case VM.SQRT: s[p] = Math.sqrt(s[p]); break;
case VM.CBRT: s[p] = MoreMath.cbrt(s[p]); break;
case VM.SINH: s[p] = MoreMath.sinh(s[p]); break;
case VM.COSH: s[p] = MoreMath.cosh(s[p]); break;
case VM.TANH: s[p] = MoreMath.tanh(s[p]); break;
case VM.ASINH: s[p] = MoreMath.asinh(s[p]); break;
case VM.ACOSH: s[p] = MoreMath.acosh(s[p]); break;
case VM.ATANH: s[p] = MoreMath.atanh(s[p]); break;
case VM.ABS: s[p] = Math.abs(s[p]); break;
case VM.FLOOR: s[p] = Math.floor(s[p]); break;
case VM.CEIL: s[p] = Math.ceil(s[p]); break;
case VM.SIGN: s[p] = s[p] > 0 ? 1 : s[p] < 0 ? -1 : 0; break;
case VM.MIN: s[--p] = Math.min(s[p], s[p+1]); break;
case VM.MAX: s[--p] = Math.min(s[p], s[p+1]); break;
case VM.GCD: s[--p] = MoreMath.gcd(s[p], s[p+1]); break;
case VM.COMB: s[--p] = MoreMath.comb(s[p], s[p+1]); break;
case VM.PERM: s[--p] = MoreMath.perm(s[p], s[p+1]); break;
case VM.LOAD0: s[++p] = a0; break;
case VM.LOAD1: s[++p] = a1; break;
case VM.LOAD2: s[++p] = a2; break;
case VM.LOAD3: s[++p] = a3; break;
case VM.LOAD4: s[++p] = a4; break;
default:
throw new Error("Unknown opcode " + code[pc]);
}
}
return p;
/*
if (p != expectedExitSP) {
throw new Error("stack pointer after exec: expected " + expectedExitSP +
" , got " + p);
}
*/
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko-II/src/PlinkoBoard.java
0,0 → 1,652
/*
Copyright 2004-2006 David P. Little
license:
Unless otherwise stated, the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
Modified for wims interactive usage with permission of the author.
J.M. Evers
*/
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
 
public class PlinkoBoard extends JPanel implements Runnable, KeyListener, MouseListener, MouseMotionListener
{
double COUNT;
double TOTAL;
double TOTAL_SQUARES;
long HIST[];
float MAX;
double PINS[][][];
double DIST;
double BALL_RAD;
int PIN_RAD;
int BINS;
int R;
int W;
int H;
int BALL_COUNT;
int BOTTOM_MARGIN;
double SIDE_MARGIN;
PlinkoBall FIRST_BALL;
int RIGHT;
double PERCENT;
int CURRENT_BIN;
static double DYS[][];
static Color COLORS[];
Image IMAGES[];
Thread thread;
boolean active;
Image background;
Image image;
Graphics2D graphics;
PlinkoNegativeBinomial plinko;
 
static
{
COLORS = (new Color[] {
Color.red, Color.magenta, Color.orange, Color.yellow, Color.green, Color.blue, Color.cyan
});
}
// jm.evers: defining a few things
int maximum_balls;int start_number=0;int showstats=0;
 
public PlinkoBoard(PlinkoNegativeBinomial plinkonegativebinomial)
{
BOTTOM_MARGIN = 5;
CURRENT_BIN = 0;
plinko = plinkonegativebinomial;
setup();
newHist();
FIRST_BALL = null;
BALL_COUNT = 0;
active = false;
DYS = new double[12][];
for(double d = 0.0D; d < 12D; d++)
{
DYS[(int)d] = new double[(int)d];
for(double d1 = 0.0D; d1 < d; d1++)
{
DYS[(int)d][(int)d1] = (PlinkoBall.A * d1 * d1) / (d * d) + (PlinkoBall.B * d1) / d;
}
 
}
 
addKeyListener(this);
addMouseListener(this);
// jm.evers: if the applet is in an wims exercise...read appletparam and start buckets_number with 1 instead of 0
maximum_balls=(int)plinko.total_balls - 1;
if(plinko.wims_exercise == false){ showstats = 1;}else{ start_number=1; }
}
 
public void setup()
{
W = getWidth();
H = getHeight();
PlinkoNegativeBinomial _tmp = plinko;
BINS = ((Integer)PlinkoNegativeBinomial.bins.getValue()).intValue();
PlinkoNegativeBinomial _tmp1 = plinko;
R = ((Integer)PlinkoNegativeBinomial.strk.getValue()).intValue();
CURRENT_BIN = Math.min(CURRENT_BIN, BINS - 1);
RIGHT = 0;
PERCENT = 0.0D;
DIST = Math.min((double)(H - 100 - BOTTOM_MARGIN) / (double)(BINS + R), (double)(W - 10) / (double)BINS);
SIDE_MARGIN = ((double)W - (double)BINS * DIST) / 2D;
PIN_RAD = (int)DIST / 9 + 1;
BALL_RAD = Math.max((2D * DIST) / 7D, 2D) + 1.0D;
IMAGES = new Image[COLORS.length];
for(int i = 0; i < COLORS.length; i++)
{
IMAGES[i] = getBall(BALL_RAD, COLORS[i]);
}
 
PINS = new double[R + 1][][];
for(int j = 0; j < R; j++)
{
PINS[j] = new double[200][2];
for(int l = 0; l < 150; l++)
{
PINS[j][l][0] = DIST * (double)((l - j) + R) + SIDE_MARGIN;
PINS[j][l][1] = DIST * (double)(l + j + 1);
}
 
}
 
PINS[R] = new double[200][2];
for(int k = 0; k < 200; k++)
{
PINS[R][k][0] = DIST * ((double)k + 0.5D) + SIDE_MARGIN;
PINS[R][k][1] = (double)(H - 30) - BALL_RAD;
}
 
}
 
public static Image getBall(double d, Color color)
{
BufferedImage bufferedimage = new BufferedImage((int)(2D * d + 2D), (int)(2D * d + 2D), 2);
double ad[] = new double[3];
double ad1[] = new double[3];
double ad2[] = {
-5D, 5D, 10D
};
double d1 = Math.sqrt(150D);
for(int k1 = 0; k1 < (int)(2D * d + 2D); k1++)
{
for(int l1 = 0; l1 < (int)(2D * d + 2D); l1++)
{
if((d - (double)k1) * (d - (double)k1) + (d - (double)l1) * (d - (double)l1) <= (d - 1.0D) * (d - 1.0D))
{
ad[0] = ((double)k1 - d) / d;
ad[1] = (d - (double)l1) / d;
ad[2] = Math.sqrt(1.0D - ad[0] * ad[0] - ad[1] * ad[1]);
double d2 = (ad[0] * ad2[0] + ad[1] * ad2[1] + ad[2] * ad2[2]) / Math.sqrt(ad2[0] * ad2[0] + ad2[1] * ad2[1] + ad2[2] * ad2[2]);
d2 = (1.0D + d2) / 2D;
double d4 = Math.pow(d2, 20D);
int i = (int)((double)color.getRed() * (d2 - d4) + d4 * 255D);
int k = (int)((double)color.getGreen() * (d2 - d4) + d4 * 255D);
int i1 = (int)((double)color.getBlue() * (d2 - d4) + d4 * 255D);
bufferedimage.setRGB(k1, l1, 0xff000000 + (i << 16) + (k << 8) + i1);
continue;
}
if((d - (double)k1) * (d - (double)k1) + (d - (double)l1) * (d - (double)l1) > (d + 1.0D) * (d + 1.0D))
{
continue;
}
int j = 0;
int l = 0;
int j1 = 0;
for(double d6 = -0.33000000000000002D; d6 < 0.5D; d6 += 0.33000000000000002D)
{
for(double d7 = -0.33000000000000002D; d7 < 0.5D; d7 += 0.33000000000000002D)
{
double d3;
double d5;
if((d - ((double)k1 + d6)) * (d - ((double)k1 + d6)) + (d - ((double)l1 + d7)) * (d - ((double)l1 + d7)) <= d * d)
{
ad[0] = (((double)k1 + d7) - d) / d;
ad[1] = (d - ((double)l1 + d7)) / d;
ad[2] = Math.sqrt(1.0D - ad[0] * ad[0] - ad[1] * ad[1]);
d3 = (ad[0] * ad2[0] + ad[1] * ad2[1] + ad[2] * ad2[2]) / d1;
d3 = (1.0D + d3) / 2D;
d5 = Math.pow(d3, 20D);
} else
{
d3 = 1.0D;
d5 = 1.0D;
}
j += (int)((double)color.getRed() * (d3 - d5) + d5 * 255D);
l += (int)((double)color.getGreen() * (d3 - d5) + d5 * 255D);
j1 += (int)((double)color.getBlue() * (d3 - d5) + d5 * 255D);
}
 
}
 
j /= 9;
l /= 9;
j1 /= 9;
bufferedimage.setRGB(k1, l1, (255 - (j + l + j1) / 3 << 24) + (j << 16) + (l << 8) + j1);
}
 
}
 
return bufferedimage;
}
 
public void newHist()
{
COUNT = 0.0D;
TOTAL = 0.0D;
TOTAL_SQUARES = 0.0D;
MAX = 0.0F;
PERCENT = 0.0D;
HIST = new long[101];
}
// @begin jm.evers :preparing a data string for javascript: must be of type string: arrays always give trouble on IE...
public String ReadData(){
String reply="";
// Rest is the number of balls that falls to "the right" of the last [max] bin
double total=0.0D;
double sum=0.0D;
for(int i=0;i<HIST.length;i++){
total=total + HIST[i];
if(i < plinko.bins_num){
if(i != 0){
reply=reply+","+HIST[i];
}
else
{
reply=""+HIST[0];
}
sum=sum+HIST[i];
}
}
int Rest=(int) ( total - sum );
reply=reply+","+Rest;
return reply;
}
// @end
 
public void run()
{
while(BALL_COUNT > 0)
{
repaint();
try
{
Thread.sleep(50L);
}
catch(InterruptedException interruptedexception) { }
}
repaint();
active = false;
plinko.active = false;
PlinkoNegativeBinomial _tmp = plinko;
PlinkoNegativeBinomial.strk.setEnabled(true);
}
 
public void kill()
{
FIRST_BALL = null;
if(plinko.start.getText().equals("Start"))
{
active = false;
plinko.active = false;
PlinkoNegativeBinomial _tmp = plinko;
PlinkoNegativeBinomial.strk.setEnabled(true);
}
}
// jm.evers
public void LimitReached(){
plinko.active = true;
FIRST_BALL=null;
plinko.toggleStart();
}
 
public void dropBall(boolean flag)
{
BALL_COUNT++;
//@begin jm.evers : I don't know of another/better way to get the system to stop at a given [param] number of balls...
//System.out.println("COUNT ="+COUNT+ "....maximum_balls ="+maximum_balls);
if(COUNT >= maximum_balls ){LimitReached();}
//@end
if(FIRST_BALL == null)
{
FIRST_BALL = new PlinkoBall();
FIRST_BALL.sound = flag;
} else
{
FIRST_BALL.previousBall = new PlinkoBall();
FIRST_BALL.previousBall.sound = flag;
FIRST_BALL.previousBall.nextBall = FIRST_BALL;
FIRST_BALL = FIRST_BALL.previousBall;
}
try
{
Thread.sleep(0L);
}
catch(InterruptedException interruptedexception) { }
if(!active)
{
active = true;
thread = new Thread(this);
thread.start();
}
}
 
public void paintComponent(Graphics g)
{
W = getWidth();
H = getHeight();
if(background == null || background.getWidth(this) != W || background.getHeight(this) != H || image == null || image.getWidth(this) != W || image.getHeight(this) != H)
{
setup();
background = createImage(W, H);
drawBackground(W, H);
image = createImage(W, H);
graphics = (Graphics2D)image.getGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
graphics.drawImage(background, 0, 0, this);
for(PlinkoBall plinkoball = FIRST_BALL; plinkoball != null; plinkoball = plinkoball.nextBall)
{
graphics.drawImage(IMAGES[plinkoball.spaz], (int)(plinkoball.X - BALL_RAD), (int)((plinkoball.Y - 2D * BALL_RAD - (double)PIN_RAD) + 1.0D), this);
increment(plinkoball);
}
 
drawHist(graphics);
drawStats(graphics);
g.drawImage(image, 0, 0, this);
}
 
public void increment(PlinkoBall plinkoball)
{
if(plinkoball.t == plinkoball.C && plinkoball.ROW < R)
{
plinkoball.t = 0;
plinkoball.DIR = 0;
PlinkoNegativeBinomial _tmp = plinko;
// @begin jm.evers: reading controls or applet param...plinko.chance is parameter
if(plinko.wims_exercise == false){
if ( Math.random() < ((Double)PlinkoNegativeBinomial.prob.getValue()).doubleValue() ) plinkoball.DIR = 1;
}
else
{
if ( Math.random() < plinko.chance ){ plinkoball.DIR = 1;}
}
// @end
plinkoball.ROW += 1 - plinkoball.DIR;
plinkoball.COL += plinkoball.DIR;
PlinkoNegativeBinomial _tmp1 = plinko;
plinkoball.C = 11 - ((Integer)PlinkoNegativeBinomial.rate.getValue()).intValue();
if(plinkoball.sound)
{
PlinkoNegativeBinomial.ping.play();
}
}
double d = (DIST * (double)plinkoball.t * (double)(2 * plinkoball.DIR - 1)) / (double)plinkoball.C;
if(plinkoball.ROW == 0 && plinkoball.COL == 0)
{
plinkoball.X = PINS[0][0][0];
plinkoball.Y = (PINS[0][0][1] - DIST) + (DIST * (double)plinkoball.t * (double)plinkoball.t) / (double)(plinkoball.C * plinkoball.C);
} else
if(plinkoball.ROW < R)
{
plinkoball.X = DIST * (double)((plinkoball.COL - plinkoball.ROW - 2 * plinkoball.DIR) + 1 + R) + d + SIDE_MARGIN;
plinkoball.Y = DIST * ((double)(plinkoball.COL + plinkoball.ROW) - DYS[plinkoball.C][plinkoball.t]);
} else
{
plinkoball.X = PINS[R - 1][plinkoball.COL][0] + d;
plinkoball.X = Math.max(plinkoball.X, (PINS[R][plinkoball.COL][0] - DIST / 2D) + BALL_RAD + 1.0D);
d = Math.abs(d);
PlinkoBall _tmp2 = plinkoball;
PlinkoBall _tmp3 = plinkoball;
plinkoball.Y = PINS[plinkoball.ROW - 1][plinkoball.COL][1] - d * ((PlinkoBall.A * d) / DIST + PlinkoBall.B);
if(plinkoball.Y > (double)(H - BOTTOM_MARGIN - PIN_RAD))
{
if(plinkoball.previousBall != null && plinkoball.nextBall != null)
{
plinkoball.previousBall.nextBall = plinkoball.nextBall;
plinkoball.nextBall.previousBall = plinkoball.previousBall;
} else
if(plinkoball.previousBall != null && plinkoball.nextBall == null)
{
plinkoball.previousBall.nextBall = null;
} else
if(plinkoball.previousBall == null && plinkoball.nextBall != null)
{
plinkoball.nextBall.previousBall = null;
FIRST_BALL = plinkoball.nextBall;
} else
{
FIRST_BALL = null;
PlinkoNegativeBinomial _tmp4 = plinko;
PlinkoNegativeBinomial.strk.setEnabled(true);
}
BALL_COUNT--;
updateHist(plinkoball.COL);
if(plinkoball.sound)
{
PlinkoNegativeBinomial.click.play();
}
}
}
plinkoball.t++;
}
 
public void updateHist(int i)
{
HIST[Math.min(i, 100)]++;
COUNT++;
TOTAL += i;
TOTAL_SQUARES += i * i;
if((float)HIST[Math.min(i, 100)] > MAX)
{
MAX = HIST[Math.min(i, 100)];
}
if(i <= RIGHT)
{
PERCENT++;
}
}
 
public void drawStats(Graphics g)
{
if(showstats == 1){ // jm.evers : we do not show calculated results in an exercise...just the balls per Bin.
plinko.count.setText(plinko.label_count + (int)COUNT);
plinko.current_bin.setText(plinko.label_bin+ CURRENT_BIN);
plinko.current_bin_count.setText(plinko.label_bin_count + HIST[CURRENT_BIN]);
if(COUNT > 0.0D)
{
double d = TOTAL / COUNT;
plinko.mean.setText(plinko.label_mean + (float)d);
plinko.variance.setText(plinko.label_variance + (float)(TOTAL_SQUARES / COUNT - d * d));
plinko.current_bin_prob.setText(plinko.label_bin_probability + (float)((double)(int)((double)(0x186a0L * HIST[CURRENT_BIN]) / COUNT) / 1000D) + "%");
if(RIGHT == 0)
{
plinko.confidence.setText(plinko.label_confidence + (float)((double)(int)((100000D * PERCENT) / COUNT) / 1000D) + "% of the balls landed in bin " + RIGHT + ".");
} else
{
plinko.confidence.setText(plinko.label_confidence + (float)((double)(int)((100000D * PERCENT) / COUNT) / 1000D) + "% of the balls landed in bins 0 through " + RIGHT + ".");
}
} else
{
plinko.mean.setText(plinko.label_mean);
plinko.variance.setText(plinko.label_variance);
plinko.current_bin_prob.setText(plinko.label_bin_probability);
plinko.confidence.setText(plinko.label_confidence);
}
}
else
{
// just the total COUNT and "balls per active bin"
plinko.count.setText(plinko.label_count+ (int)COUNT);
plinko.current_bin.setText(plinko.label_bin + (CURRENT_BIN+1));
plinko.current_bin_count.setText(plinko.label_bin_count + HIST[CURRENT_BIN]);
}
}
 
public void drawHist(Graphics2D graphics2d)
{
W = getWidth();
H = getHeight();
for(int i = 0; i < BINS; i++)
{
double d;
double d1;
if(i == BINS - 1)
{
d = PINS[R][i][0] - DIST / 2D;
d1 = PINS[R][i][0] + DIST / 2D;
} else
{
d = PINS[R][i][0] - DIST / 2D;
d1 = PINS[R][i + 1][0] - DIST / 2D;
}
long l = HIST[i];
if(MAX > 100F)
{
l = (int)((100D * (double)l) / (double)MAX);
}
graphics2d.setColor(new Color(255, 0, 0, 175));
if(i <= RIGHT)
{
graphics2d.setColor(new Color(0, 255, 0, 175));
}
java.awt.geom.Rectangle2D.Double double1 = new java.awt.geom.Rectangle2D.Double(d, (long)H - l - (long)BOTTOM_MARGIN, d1 - d, l);
graphics2d.fill(double1);
graphics2d.setColor(Color.black);
graphics2d.setStroke(new BasicStroke(1.0F));
graphics2d.draw(double1);
}
 
graphics2d.setColor(Color.black);
graphics2d.setStroke(new BasicStroke(3F));
graphics2d.draw(new java.awt.geom.Line2D.Double(PINS[R][CURRENT_BIN][0] - DIST / 2D, (H - BOTTOM_MARGIN) + 3, PINS[R][CURRENT_BIN][0] + DIST / 2D, (H - BOTTOM_MARGIN) + 3));
}
 
public void drawBackground()
{
drawBackground(getWidth(), getHeight());
}
 
public void drawBackground(int i, int j)
{
Graphics2D graphics2d = (Graphics2D)background.getGraphics();
graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics2d.setColor(Color.white);
graphics2d.fillRect(0, 0, i, j);
graphics2d.setColor(Color.black);
Image image1 = getBall(PIN_RAD, Color.black);
for(int l = 0; l < R; l++)
{
double ad[] = PINS[l][0];
for(int k = 0; k < 1000 && (ad[1] + (double)k * DIST) - (double)PIN_RAD < (double)j; k++)
{
graphics2d.drawImage(image1, (int)((ad[0] - (double)PIN_RAD) + (double)k * DIST), (int)((ad[1] - (double)PIN_RAD) + (double)k * DIST), this);
}
 
}
 
graphics2d.setFont(new Font("Helvetica", 1, Math.min((int)(2D * DIST) / 3, 50)));
FontMetrics fontmetrics = graphics2d.getFontMetrics();
graphics2d.draw(new java.awt.geom.Line2D.Double(0.0D, j - BOTTOM_MARGIN, i, j - BOTTOM_MARGIN));
//jm.evers Bins start with number 1 for highschools...
String s="";
for(int i1 = 0; i1 < BINS; i1++)
{
double ad1[] = PINS[R][i1];
s = ""+(i1+start_number);
graphics2d.setColor(Color.darkGray);
graphics2d.drawString(s, (int)(ad1[0] - (double)(fontmetrics.stringWidth(s) / 2)), (j - 100 - BOTTOM_MARGIN) + Math.min((int)(2D * DIST) / 3, 50));
graphics2d.setColor(Color.black);
graphics2d.draw(new java.awt.geom.Line2D.Double(ad1[0] - DIST / 2D, j - 100 - BOTTOM_MARGIN, ad1[0] - DIST / 2D, j - BOTTOM_MARGIN));
}
 
double ad2[] = PINS[R][BINS - 1];
graphics2d.draw(new java.awt.geom.Line2D.Double(ad2[0] + DIST / 2D, j - 100 - BOTTOM_MARGIN, ad2[0] + DIST / 2D, j - BOTTOM_MARGIN));
repaint();
}
 
public void updatePercent()
{
RIGHT = CURRENT_BIN;
PERCENT = 0.0D;
for(int i = 0; i <= RIGHT; i++)
{
PERCENT += HIST[i];
}
 
}
 
public void keyTyped(KeyEvent keyevent)
{
}
 
public void keyPressed(KeyEvent keyevent)
{
int i = keyevent.getKeyCode();
char c = keyevent.getKeyChar();
if(c >= '0' && c <= '4')
{
int j = c - 48;
int k = 1;
for(int l = 0; l < j; l++)
{
k *= 10;
}
 
for(int i1 = 0; i1 < k; i1++)
{
dropBall(k == 1);
}
 
} else
if(i == 37)
{
CURRENT_BIN--;
if(CURRENT_BIN < 0)
{
CURRENT_BIN = BINS - 1;
}
updatePercent();
repaint();
} else
if(i == 39)
{
CURRENT_BIN++;
if(CURRENT_BIN > BINS - 1)
{
CURRENT_BIN = 0;
}
updatePercent();
repaint();
} else
if(i != 10)
{
if(c == ' ')
{
plinko.toggleStart();
} else
if(c != '\024' && c != '\003')
{
if(c != '\030');
}
}
}
 
public void keyReleased(KeyEvent keyevent)
{
}
 
public void mouseReleased(MouseEvent mouseevent)
{
}
 
public void mouseEntered(MouseEvent mouseevent)
{
}
 
public void mouseExited(MouseEvent mouseevent)
{
}
 
public void mouseClicked(MouseEvent mouseevent)
{
requestFocus();
Point point = mouseevent.getPoint();
if((double)point.x > PINS[R][0][0] - DIST / 2D && (double)point.x < PINS[R][BINS - 1][0] + DIST / 2D && point.y > H - 100 - BOTTOM_MARGIN && point.y < H - BOTTOM_MARGIN)
{
CURRENT_BIN = (int)(((double)point.x - PINS[R][0][0]) / DIST + 0.5D);
updatePercent();
repaint();
}
}
 
public void mousePressed(MouseEvent mouseevent)
{
}
 
public void mouseDragged(MouseEvent mouseevent)
{
}
 
public void mouseMoved(MouseEvent mouseevent)
{
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko-II/src/PlinkoBall.java
0,0 → 1,47
/*
Copyright 2004-2006 David P. Little
license:
Unless otherwise stated, the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
Modified for wims interactive usage with permission of the author.
J.M. Evers
*/
import java.awt.Color;
import javax.swing.JSpinner;
 
public class PlinkoBall
{
 
public PlinkoBall()
{
sound = false;
spaz = (int)((double)PlinkoBoard.COLORS.length * Math.random());
color = PlinkoBoard.COLORS[spaz];
nextBall = null;
previousBall = null;
ROW = 0;
COL = 0;
DIR = 0;
t = 0;
C = 11 - ((Integer)PlinkoNegativeBinomial.rate.getValue()).intValue();
}
 
static final double A = -2D - Math.sqrt(3D);
static final double B = 1.0D + Math.sqrt(3D);
Color color;
PlinkoBall nextBall;
PlinkoBall previousBall;
double X;
double Y;
int ROW;
int COL;
int DIR;
int C;
int t;
int spaz;
boolean sound;
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko-II/src/PlinkoNegativeBinomial.java
0,0 → 1,406
/*
Copyright 2004-2006 David P. Little
license:
Unless otherwise stated, the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
Modified for wims interactive usage with permission of the author.
J.M. Evers
*/
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
 
public class PlinkoNegativeBinomial extends JApplet implements Runnable, ActionListener, ChangeListener, WindowListener
{
static JSpinner bins;
static JSpinner strk;
static JSpinner rate;
static JSpinner prob;
JLabel count;
JLabel mean;
JLabel variance;
JLabel current_bin;
JLabel current_bin_count;
JLabel current_bin_prob;
JLabel confidence;
JButton start;
JButton clear;
JButton close;
PlinkoBoard plinkoboard;
Thread thread;
boolean active;
JFrame frame;
SplashPanel splash;
static AudioClip click;
static AudioClip ping;
// @begin jm.evers: declaring a few things
boolean wims_exercise = false;
int bins_num=11;
int speed=1;
int total_balls=100000;
double chance=0.5;
int frame_x=650;
int frame_y=600;
int font_size=14;
int R=1;
String title="Binomial Distribution";
String click_text="CLICK ANYWHERE TO BEGIN";
String start_text="START";
String stop_text="STOP";
String clear_text="CLEAR";
String close_text="CLOSE";
String label_count="Count: ";
String label_mean="Mean: ";
String label_variance="Variance: ";
String label_bin="Bin: ";
String label_bins="Bins: ";
String label_speed="Speed: ";
String label_probability="Probability: ";
String label_bin_count="Bin Count: ";
String label_bin_probability="Bin Probability: ";
String label_confidence="Confidence Interval: ";
String some_text=" % of the balls landed in bin ";
String through=" through ";
String label_controls=" Controls ";
String label_statistics="Statistics";
// @end jm.evers: declaring a few things
 
 
 
public PlinkoNegativeBinomial()
{
active = false;
}
 
public void init()
{
//@begin jm.evers: introducing a few Applet params , used for tailoring the exercise.
String s=getParameter("wims_exercise");
if(s!=null){
if(s.equalsIgnoreCase("yes") || s.equals("1")){
wims_exercise = true;
s=getParameter("balls");
if(s!=null && s.length()>0){total_balls = Integer.parseInt(s, 10);}
s=getParameter("chance");
if(s!=null && s.length()>0){chance = Double.parseDouble(s);}
s=getParameter("bins");
if(s!=null && s.length()>0){bins_num = Integer.parseInt(s, 10);}
s=getParameter("speed");
if(s!=null && s.length()>0){speed = Integer.parseInt(s, 10);}
s=getParameter("xsize");
if(s!=null && s.length()>0){frame_x = Integer.parseInt(s, 10);}
s=getParameter("ysize");
if(s!=null && s.length()>0){frame_y = Integer.parseInt(s, 10);}
s=getParameter("title");
if(s!=null && s.length()>0){title=s;}
s=getParameter("font_size");
if(s!=null && s.length()>0){font_size = Integer.parseInt(s, 10);}
s=getParameter("R");
if(s!=null && s.length()>0){R = Integer.parseInt(s, 10);}
 
}
}
s=getParameter("language");
if(s!=null && s.length()>0){
if(s.equalsIgnoreCase("nl")){
click_text="KLIK HIER OM TE BEGINNEN";
start_text="START";
stop_text="STOP";
clear_text="WISSEN";
close_text="SLUITEN";
label_count="Aantal: ";
label_mean="Gemiddeld: ";
label_variance="Variantie: ";
label_bin="Bakje: ";
label_bins="Bakjes: ";
label_speed="Snelheid: ";
label_bin_count="Ballen/bakje: ";
label_probability="Kans: ";
label_bin_probability="Kans per bakje: ";
label_confidence="Betrouwbaarheids interval: ";
some_text=" % van de ballen in bakje: ";
through=" t/m ";
String label_controls=" Menu ";
String label_statistics="Statistiek";
}
if(s.equalsIgnoreCase("fr")){
click_text="CLIQUEZ ICI";
start_text="COMMENCER";
stop_text="PAUSE";
clear_text="EFFACER";
close_text="FERMER";
label_count="Quantit\u00E9 : ";
label_mean="Moyenne : ";
label_variance="Variance: ";
label_bin="Panier : ";
label_bins="Paniers : ";
label_speed="Vitesse : ";
label_bin_count="Balles dans ce panier : ";
label_bin_probability="% de balles dans ce panier : ";
label_probability="Probabilit\u00E9 : ";
label_confidence="Intervalle de confiance : ";
some_text=" % de balles dans le panier ";
through=" through ";
label_controls="Menu";
label_statistics="Statistiques";
}
if(s.equalsIgnoreCase("de")){
click_text="Klicken Sie hier um zu starten";
start_text="START";
stop_text="STOP";
clear_text="CLEAR";
close_text="CLOSE";
label_count="Zahl: ";
label_mean="Mean: ";
label_variance="Variance: ";
label_bin="Behälter: ";
label_bins="Behälter: ";
label_speed="Geschwindigkeit : ";
label_bin_count="Zahl/Behälter: ";
label_bin_probability="Wahrscheinlichkeit in Behälter: ";
label_probability="Wahrscheinlichkeit: ";
label_confidence="Wahrscheinlichkeits Intervall: ";
some_text=" % der Kugeln fällt in Behälter ";
through=" bis ";
String label_controls=" Menu ";
String label_statistics="Statistik";
}
}
//@end jm.evers: introducing a few Applet params , used for tailoring the exercise.
 
setBackground(Color.white);
frame = new JFrame();
frame.setVisible(false);
frame.setSize(frame_x, frame_y);
frame.setLocation(0,0);
frame.setTitle( title );
Font font = new Font( "Helvetica", Font.BOLD, font_size );
JPanel jpanel = new JPanel();
JLabel jlabel = new JLabel("R:", 2);
if(wims_exercise == false){
jpanel.add(jlabel);
}
strk = new JSpinner(new SpinnerNumberModel( R , 1, 50, 1));
if(wims_exercise == false){
jpanel.add(strk);
}
jlabel = new JLabel(label_bins, 2);
if(wims_exercise == false){
jpanel.add(jlabel);
}
bins = new JSpinner(new SpinnerNumberModel(bins_num, 2, 100, 1));
if(wims_exercise == false){
jpanel.add(bins);
}
jlabel = new JLabel(label_probability, 2);
if(wims_exercise == false){
jpanel.add(jlabel);
}
prob = new JSpinner(new SpinnerNumberModel(chance, 0.0D, 100D, 0.01D));
SpinnerNumberModel spinnernumbermodel = (SpinnerNumberModel)prob.getModel();
spinnernumbermodel.setMaximum(new Double(1.0D));
if(wims_exercise == false){
jpanel.add(prob);
}
jlabel = new JLabel(label_speed, 2);
if(wims_exercise == false){
jpanel.add(jlabel);
}
rate = new JSpinner(new SpinnerNumberModel(speed, 1, 10, 1));
if(wims_exercise == false){jpanel.add(rate);
}
JPanel jpanel1 = new JPanel();
jpanel1.add(start = new JButton(start_text));
start.setDefaultCapable(true);
frame.getRootPane().setDefaultButton(start);
jpanel1.add(clear = new JButton(clear_text));
jpanel1.add(close = new JButton(close_text));
close.setDefaultCapable(false);
JPanel jpanel2 = new JPanel(new BorderLayout());
jpanel2.add("West", jpanel);
jpanel2.add("South", jpanel1);
jpanel2.add("South", jpanel1);
jpanel2.setBorder(BorderFactory.createTitledBorder(jpanel2.getBorder(), label_controls, 1, 2, new Font("Helvetica", 1, font_size)));
JPanel jpanel3 = new JPanel(new GridLayout(2, 3));
jpanel3.add(count = new JLabel(label_count));
jpanel3.add(current_bin = new JLabel(label_bin));
jpanel3.add(current_bin_count = new JLabel(label_bin_count));
JPanel jpanel4 = new JPanel(new GridLayout(1, 1));
JPanel jpanel5 = new JPanel(new BorderLayout());
jpanel5.add("Center", jpanel3);
jpanel5.add("South", jpanel4);
jpanel5.setBorder(BorderFactory.createTitledBorder(jpanel5.getBorder(),label_statistics, 1, 2, new Font("Helvetica", 1, font_size)));
JPanel jpanel6 = new JPanel(new BorderLayout());
jpanel6.add("Center", jpanel5);
JLabel jlabel1 = new JLabel("");
jlabel1.setPreferredSize(new Dimension(15, 15));
jpanel6.add("South", jlabel1);
if(wims_exercise == false){
jpanel3.add(mean = new JLabel(label_mean));
jpanel3.add(variance = new JLabel(label_variance));
jpanel3.add(current_bin_prob = new JLabel(label_bin_probability));
jpanel4.add(confidence = new JLabel(label_confidence));
}
 
Container container = frame.getContentPane();
container.setLayout(new BorderLayout(10, 10));
container.add("Center", plinkoboard = new PlinkoBoard(this));
container.add("North", jpanel2);
container.add("South", jpanel6);
start.addActionListener(this);
clear.addActionListener(this);
close.addActionListener(this);
strk.addChangeListener(this);
bins.addChangeListener(this);
rate.addChangeListener(this);
prob.addChangeListener(this);
plinkoboard.requestFocus();
frame.addWindowListener(this);
getContentPane().add(splash = new SplashPanel(this));
click = getAudioClip(getCodeBase(), "sounds/click.au");
ping = getAudioClip(getCodeBase(), "sounds/ping.au");
}
 
public void showFrame()
{
frame.setVisible(true);
}
 
public void start()
{
if(!frame.isVisible())
{
splash.start();
}
}
 
public void stop()
{
splash.active = false;
frame.setVisible( false );
splash.start();
}
 
public void run()
{
while(active)
{
plinkoboard.dropBall(false);
try
{
Thread.sleep(105 - 10 * ((Integer)rate.getValue()).intValue());
}
catch(InterruptedException interruptedexception) { }
}
}
 
public void toggleStart()
{
if(active)
{
active = false;
start.setText(start_text);
} else
{
active = true;
strk.setEnabled(false);
thread = new Thread(this);
thread.start();
start.setText(stop_text);
}
}
 
public void actionPerformed(ActionEvent actionevent){
Object obj = actionevent.getSource();
if(obj == close){ stop();}
if(obj == start){ toggleStart();}
if(obj == clear){
if(plinkoboard.FIRST_BALL == null){
plinkoboard.newHist();
}
else
{
plinkoboard.FIRST_BALL = null;
if(!active){
strk.setEnabled(true);
}
}
plinkoboard.repaint();
}
plinkoboard.requestFocus();
}
 
public void stateChanged(ChangeEvent changeevent)
{
Object obj = changeevent.getSource();
if(obj == strk)
{
count.setText("0");
plinkoboard.setup();
plinkoboard.newHist();
plinkoboard.drawBackground();
} else
if(obj == bins)
{
plinkoboard.setup();
plinkoboard.drawBackground();
} else
if(obj != rate && obj == prob)
{
plinkoboard.updatePercent();
plinkoboard.repaint();
}
}
 
public void windowActivated(WindowEvent windowevent)
{
}
 
public void windowClosed(WindowEvent windowevent)
{
}
 
public void windowClosing(WindowEvent windowevent)
{
splash.start();
active = false;
start.setText(start_text);
}
 
public void windowDeactivated(WindowEvent windowevent)
{
}
 
public void windowDeiconified(WindowEvent windowevent)
{
}
 
public void windowIconified(WindowEvent windowevent)
{
}
 
public void windowOpened(WindowEvent windowevent)
{
}
 
public String getAppletInfo(){
return "Written by Dr. P. Little \n http://www.math.psu.edu/dlittle/java/probability/plinko/index.html" ;
}
// jm.evers: returns a string to a javascript function ReadApplet(); [must be a string, and not an array ... IE trouble]
// the string will be send -along with the "student reply" to the questions at hand- to the WIMS server;
public String ReadApplet(){
String s=plinkoboard.ReadData();
return s;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko-II/src/SplashPanel.java
0,0 → 1,284
/*
Copyright 2004-2006 David P. Little
license:
Unless otherwise stated, the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
Modified for wims interactive usage with permission of the author.
J.M. Evers
*/
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
 
public class SplashPanel extends JPanel
implements MouseListener, Runnable
{
 
public SplashPanel(PlinkoNegativeBinomial plinkonegativebinomial)
{
BINS = 20;
BOTTOM_MARGIN = 5;
newBackground = true;
active = true;
FUDGE = 200;
setBackground(Color.white);
addMouseListener(this);
plinko = plinkonegativebinomial;
for(int i = 0; i < 25; i++)
{
dropBall();
FIRST_BALL.ROW = 10 + (int)(10D * Math.random());
FIRST_BALL.COL = (int)((double)FIRST_BALL.ROW * Math.random());
FIRST_BALL.C = 10;
FIRST_BALL.t = i % 11;
}
 
start();
}
 
public void start()
{
active = true;
thread = new Thread(this);
thread.start();
}
 
public void run()
{
while(active)
{
if(Math.random() < 0.40000000000000002D)
{
dropBall();
FIRST_BALL.ROW = 11;
FIRST_BALL.COL = (int)((double)FIRST_BALL.ROW * Math.random());
FIRST_BALL.C = 10;
}
repaint();
try
{
Thread.sleep(100L);
}
catch(InterruptedException interruptedexception) { }
}
}
 
public void dropBall()
{
if(FIRST_BALL == null)
{
FIRST_BALL = new PlinkoBall();
} else
{
FIRST_BALL.previousBall = new PlinkoBall();
FIRST_BALL.previousBall.nextBall = FIRST_BALL;
FIRST_BALL = FIRST_BALL.previousBall;
}
}
 
public void setup()
{
if(h - (double)BOTTOM_MARGIN < h / 2D)
{
DIST = (h - (double)BOTTOM_MARGIN) / (double)BINS;
} else
{
DIST = (w - 10D) / (double)(2 * BINS);
}
PIN_RAD = (int)DIST / 9 + 1;
BALL_RAD = Math.max((2D * DIST) / 7D, 2D) + 1.0D;
IMAGES = new Image[PlinkoBoard.COLORS.length];
for(int i = 0; i < PlinkoBoard.COLORS.length; i++)
{
IMAGES[i] = PlinkoBoard.getBall(BALL_RAD, PlinkoBoard.COLORS[i]);
}
 
PINS = new Point[BINS][];
for(int j = 0; j < BINS; j++)
{
PINS[j] = new Point[j + 1];
for(int l = 0; l <= j; l++)
{
PINS[j][l] = new Point((int)(DIST * (double)(2 * l - j) + w / 2D) - FUDGE / 2, (int)(DIST * (double)(j + 1)) - (FUDGE - 15));
}
 
}
 
for(int k = 0; k < BINS; k++)
{
PINS[BINS - 1][k] = new Point((int)(DIST * (double)((2 * k - BINS) + 1) + w / 2D), (int)(h - 30D - BALL_RAD));
}
 
}
 
public void paintComponent(Graphics g)
{
w = getWidth();
h = getHeight();
w = Math.max(getWidth(), getHeight()) + FUDGE;
h = w;
Graphics2D graphics2d = (Graphics2D)g;
graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if(background == null || (double)background.getWidth(this) != h || (double)background.getHeight(this) != w)
{
setup();
background = createImage((int)w, (int)h);
drawBackground((int)w, (int)h);
}
graphics2d.drawImage(background, 0, 0, this);
for(PlinkoBall plinkoball = FIRST_BALL; plinkoball != null; plinkoball = plinkoball.nextBall)
{
g.drawImage(IMAGES[plinkoball.spaz], (int)(plinkoball.X - BALL_RAD), (int)((plinkoball.Y - 2D * BALL_RAD - (double)PIN_RAD) + 1.0D), this);
if(active)
{
increment(plinkoball);
}
}
 
w = getWidth();
h = getHeight();
graphics2d.setColor(new Color(128, 128, 128, 220));
graphics2d.setFont(new Font("Helvetica", 1, plinko.font_size));
String s =plinko.click_text;
// "CLICK ANYWHERE TO BEGIN";
graphics2d.drawString(s, (int)(w - (double)graphics2d.getFontMetrics().stringWidth(s) - 5D), (int)(h - 5D));
}
 
public void increment(PlinkoBall plinkoball)
{
if(plinkoball.t == plinkoball.C && plinkoball.ROW < BINS - 2)
{
plinkoball.ROW++;
plinkoball.COL += plinkoball.DIR;
plinkoball.t = 0;
plinkoball.DIR = 0;
if(Math.random() < 0.5D)
{
plinkoball.DIR = 1;
}
plinkoball.C = 10;
}
double d = (DIST * (double)plinkoball.t * (double)(2 * plinkoball.DIR - 1)) / (double)plinkoball.C;
if(plinkoball.ROW < 0)
{
plinkoball.X = PINS[0][0].x;
d = Math.abs(d);
plinkoball.Y = ((double)PINS[0][0].y - DIST) + (DIST * (double)plinkoball.t * (double)plinkoball.t) / (double)(plinkoball.C * plinkoball.C);
} else
if(plinkoball.ROW < BINS - 2)
{
plinkoball.X = (double)PINS[plinkoball.ROW][plinkoball.COL].x + d;
d = Math.abs(d);
plinkoball.Y = (double)PINS[plinkoball.ROW][plinkoball.COL].y - DIST * PlinkoBoard.DYS[plinkoball.C][plinkoball.t];
} else
{
plinkoball.X = (double)PINS[plinkoball.ROW][plinkoball.COL].x + d;
if(d > 0.0D)
{
plinkoball.X = Math.min(plinkoball.X, ((double)PINS[plinkoball.ROW][plinkoball.COL].x + 2D * DIST) - BALL_RAD);
} else
{
plinkoball.X = Math.max(plinkoball.X, ((double)PINS[plinkoball.ROW][plinkoball.COL].x - 2D * DIST) + BALL_RAD + 1.0D);
}
d = Math.abs(d);
PlinkoBall _tmp = plinkoball;
PlinkoBall _tmp1 = plinkoball;
plinkoball.Y = (double)PINS[plinkoball.ROW][plinkoball.COL].y - d * ((PlinkoBall.A * d) / DIST + PlinkoBall.B);
}
plinkoball.t++;
if(plinkoball.Y > h - (double)BOTTOM_MARGIN - (double)PIN_RAD)
{
if(plinkoball.previousBall != null && plinkoball.nextBall != null)
{
plinkoball.previousBall.nextBall = plinkoball.nextBall;
plinkoball.nextBall.previousBall = plinkoball.previousBall;
} else
if(plinkoball.previousBall != null && plinkoball.nextBall == null)
{
plinkoball.previousBall.nextBall = null;
} else
if(plinkoball.previousBall == null && plinkoball.nextBall != null)
{
plinkoball.nextBall.previousBall = null;
FIRST_BALL = plinkoball.nextBall;
} else
{
FIRST_BALL = null;
}
BALL_COUNT--;
}
}
 
public void drawBackground(int i, int j)
{
Graphics2D graphics2d = (Graphics2D)background.getGraphics();
graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics2d.setColor(Color.white);
graphics2d.fillRect(0, 0, i, j);
graphics2d.setColor(Color.black);
Image image = PlinkoBoard.getBall(PIN_RAD, Color.black);
for(int k = 0; k < BINS - 1; k++)
{
for(int l = 0; l <= k; l++)
{
Point point = PINS[k][l];
graphics2d.drawImage(image, point.x - PIN_RAD, point.y - PIN_RAD, this);
}
 
}
 
repaint();
}
 
public void mouseClicked(MouseEvent mouseevent)
{
active = false;
plinko.showFrame();
}
 
public void mouseEntered(MouseEvent mouseevent)
{
}
 
public void mouseExited(MouseEvent mouseevent)
{
}
 
public void mousePressed(MouseEvent mouseevent)
{
}
 
public void mouseReleased(MouseEvent mouseevent)
{
}
 
PlinkoNegativeBinomial plinko;
double w;
double h;
int TOTAL;
int HIST[];
double MAX;
Point PINS[][];
double DIST;
double BALL_RAD;
int PIN_RAD;
int BINS;
PlinkoBall FIRST_BALL;
int BALL_COUNT;
int BOTTOM_MARGIN;
private static final int hx = 15;
private static final int hy = 15;
private static final int bgGrey = 192;
Image IMAGES[];
boolean newBackground;
boolean active;
Thread thread;
Image background;
Graphics2D backGraphics;
int FUDGE;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko-II/README
0,0 → 1,154
This Applet is written by:
David Little [© 2004 David P. Little]
 
Mathematics Department
Penn State University
Eberly College of Science
University Park, PA 16802
Office: 403 McAllister
Phone: (814) 865-3329
Fax: (814) 865-3735
e-mail:dlittle@psu.edu
 
See:
http://www.math.psu.edu/dlittle/java/probability
 
 
 
 
----- INFO ---------
 
Plinko and the Negative Binomial Distribution
A Bernoulli trial is an experiment that results in a success with probability p
and a failure with probability 1-p.
A random variable is said to have a Negative Binomial Distribution with
parameter r if it is the result of recording the number of successes before
the rth failure in repeated Bernoulli trials. The Geometric Distribution is
the special case of a Negative Binomial Distribution with r=1.
 
In the Applet below, we have represented repeated independent Bernoulli trials
by a single ball falling through an array of pins.
Each time a ball falls onto a pin, it will bounce to the right (i.e. a success)
with probability p or to the left (i.e. a failure) with probability 1-p.
After the ball falls through the array, it lands in a bin labeled by
the corresponding number of successes.
 
Click on a bin to see its corresponding total and probability.
Alternatively, use the left and right arrow buttons to scroll through the bins.
Also displayed is a confidence interval centered on the theoretical expected bin.
Bins that are included in this confidence interval are highlighted in green
 
----- USAGE ---------
 
© 2004 David P. Little
Download this applet for off-line viewing (includes source code)
 
 
© 2004-2006 David P. Little
Unless otherwise stated,
the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
 
----- asking approval by email
 
Dear Mr. D. Little,
In search of a suitable GALTON board applet for usage in Highschool mathteaching, I "stumbled" across Your very nice PLINKO applet.
My question is: am I allowed use Your applet for teaching ?
[e.g. incorporating it in "interactive math-teaching modules" of a WIMS server http://wims.math.leidenuniv.nl/wims/wims.cgi?lang=en ]
Kind regards,
J.M. Evers
Highschool Mathteacher
The Netherlands
 
----- reply by Dr. D. Little
 
Absolutely! I would be very happy for you to use the applet for teaching.
If you plan to include it on a webpage, I only ask that you include a
reference to me being the author (e.g., include a link back to my
webpage). Enjoy!
 
Best,
David
 
------ WIMS USAGE -------
 
2/2009 J.M. Evers:
 
To use the applet as part of an interactive WIMS exercise,
the source code had to be slightly modified.
 
see http://wims.math.leidenuniv.nl/wims/wims.cgi?lang=en&module=H4/stat/stat-1.nl&cmd=intro
 
Changes:
 
1) Introducing a few applet params to tailor the behaviour of the applet
by dynamic wims_variables and reading the generated data
from the applet with a javascript function.
 
These statistical data will be send to the wims-server for evaluation and
grading.
 
If the "wims_exercise" applet parameter is not set [ or "no" or "0" ] ,
the applet is identical to the original applet ! And all other params are "silently ignored".
 
 
2) Furthermore some text is translated to Dutch [nl] ,German [de] and French [fr] to be able
use the applet in multi-language exercises.
If no language param is set or not nl,de,fr : the language is English
 
3) And a "Close" button is added to the frame [to close the popup-window]
 
4) Bin numbering starts with "1" instead of "0" , if the applet <param name="wims_exercise" value="1">
 
5) All balls that fall to the right of the last bin will be collected/summed in the last item if the "applet reply"
a typical applet reply: 23,45,23,12,47
meaning:
bin 1: 23
bin 2: 45
bin 3: 23
bin 4: 12
rest : 47
----------- +
total balls = 150
 
------ Credits to the author
 
Credits to the author are available in Schaersvoorde WIMS exercises:
1) in the applet info
2) in the specific wims-exercises using the applet
3) a link to the website of the author is available in the exercise [js:onmouseover()]
 
 
Example:
<html>
<body>
<script language="javascript" type="text/javascript">
function getdata(){
var input=document.getElementById("plinko-II").ReadApplet();
alert("data to send:"+input);
document.getElementById("plinko-II").stop();
}
</script>
<applet id="plinko-II" code="PlinkoNegativeBinomial.class" code="Plinko.class" width="260" height="100">
<param name="wims_exercise" value="yes">
<!-- if wims_exercise = 0 , the applet will show it's original configuation and behaviour -->
<param name="R" value="1">
<!-- R is the number of Pin rows -->
<param name="xsize" value="800">
<param name="ysize" value="600">
<param name="fontsize" value="16">
<param name="bins" value="6">
<!-- bins is the number of baskets -->
<param name="chance" value="0.5">
<param name="speed" value="1">
<param name="title" value="Applet by Dr. P. Little">
<param name="language" value="fr">
<!-- en , nl , de ,fr -->
<param name="balls" value="100">
<!-- after this amount of balls the applet will stop : however if the window is changed/moved this will not work :) -->
</applet>
<p>
<input type="button" name="READ" value="READ" onclick="javascript:getdata();">
</body>
</html>
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko-II/build.xml
0,0 → 1,65
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for Plinko-II.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="Plinko-II" default="jar" basedir=".">
 
<description>Plinko-II build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create Plinko-II jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/Plinko-II.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="Plinko-II"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="Plinko-II"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="Plinko-II">
<attribute name="Specification-Title" value="Plinko-II"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="Plinko-II"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko-II/1.html
0,0 → 1,34
<HTML>
<HEAD>
<BODY bgcolor=white vlink="blue">
 
<script language="javascript" type="text/javascript">
function lees(){
var input=document.getElementById("plinko-II").ReadApplet();
alert(input);
document.getElementById("plinko-II").destroy();
}
</script>
<CENTER>
<APPLET codebase="dist" archive="Plinko-II.jar" id="plinko-II" CODE="PlinkoNegativeBinomial.class" WIDTH=200 HEIGHT=100>
<param name="wims_exercise" value="1">
<!-- if wims_exercise = 0 , the applet will show it's original configuation and behaviour -->
<param name="R" value="2">
<!-- R is the number of Pin rows -->
<param name="xsize" value="800">
<param name="ysize" value="600">
<param name="fontsize" value="16">
<param name="bins" value="4">
<param name="chance" value="0.5">
<param name="speed" value="1">
<param name="title" value="Applet by Prof. P. Little">
<param name="language" value="fr">
<param name="balls" value="100">
</APPLET>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:lees();">
</BODY>
</HTML>
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/build.xml
0,0 → 1,63
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for jcmsource.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="jcmsource" default="jar" basedir=".">
 
<description>jcmsource build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create jcmsource jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/jcm1.0-config.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="jcmsource"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="jcmsource"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="jcmsource">
<attribute name="Specification-Title" value="jcmsource"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="jcmsource"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/SecantTangent.java
0,0 → 1,287
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
// The SecantTangent applet shows the graph of a function with two points
// marked on the function. The tangent to the graph is drawn at the first
// of these points. A second line is drawn between the two points.
// Both of the points can be dragged by the user. Alternatively, the
// x-coords of the points can be typed into input boxes.
 
import java.awt.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
 
public class SecantTangent extends GenericGraphApplet {
 
 
private Function func; // The function that is graphed.
 
VariableInput x1Input = new VariableInput(); // x-coord where tangent is drawn.
VariableInput x2Input = new VariableInput(); // x-coord for other point of secant.
 
protected void setUpParameterDefaults() {
parameterDefaults = new java.util.Hashtable();
String varName = getParameter("Variable","x");
parameterDefaults.put("Function", " e ^ " + varName);
}
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
super.setUpCanvas(); // Do the common setup: Add the axes and
 
// When setUpCanvas is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function".
if (functionInput != null)
func = functionInput.getFunction(xVar);
else {
String def = getParameter("Function");
Function f = new SimpleFunction( parser.parse(def), xVar );
func = new WrapperFunction(f);
}
Graph1D graph = new Graph1D(func);
Color color = getColorParam("GraphColor",Color.black);
graph.setColor(color);
// Create two DraggablePoint objects, which will be the points on the canvas
// that the user can drag. The x-coordinate of drag1 will be tied later to
// x1Input, so that either drag1 or x1Input can be used for setting the
// values of the point. Same for drag2 and x2Input.
Color tangentColor = getColorParam("TangentColor", Color.red);
Color secantColor = getColorParam("SecantColor",new Color(0,200,0));
DraggablePoint drag1 = new DraggablePoint(); // point where tangent is drawn
DraggablePoint drag2 = new DraggablePoint(); // other point on secant line
drag1.clampY(func); // Both points are clamped to move along the function.
drag2.clampY(func);
drag1.setColor(tangentColor);
drag1.setGhostColor(lighten(tangentColor));
drag2.setColor(secantColor);
drag2.setGhostColor(lighten(secantColor));
 
 
// Create the tangent line and the secant line.
 
DrawGeometric secant = new DrawGeometric(DrawGeometric.INFINITE_LINE_ABSOLUTE,
drag1.getXVar(), drag1.getYVar(),
drag2.getXVar(), drag2.getYVar());
secant.setColor(secantColor);
TangentLine tangent = new TangentLine(drag1.getXVar(), func);
tangent.setColor(tangentColor);
canvas.add(drag1);
canvas.add(drag2);
canvas.add(tangent);
canvas.add(secant);
canvas.add(graph);
// Create a DrawString to display the slopes of the tangent and secant.
Value tangentSlope = new ValueMath(func.derivative(1), drag1.getXVar());
Value secantSlope = new ValueMath( new ValueMath(drag2.getYVar(), drag1.getYVar(), '-'),
new ValueMath(drag2.getXVar(), drag1.getXVar(), '-'),
'/');
DrawString info;
if ( "no".equalsIgnoreCase(getParameter("ShowTangentSlope","yes")) ) {
info = new DrawString( "Secant Slope = #",
DrawString.TOP_LEFT,
new Value[] { secantSlope } );
}
else {
info = new DrawString( "Secant Slope = #\nTangent Slope = #",
DrawString.TOP_LEFT,
new Value[] { secantSlope, tangentSlope } );
}
info.setFont(new Font("Monospaced",Font.PLAIN,10));
info.setNumSize(7);
info.setColor(getColorParam("SlopeTextColor", Color.black));
info.setBackgroundColor(getColorParam("SlopeTextBackground",Color.white));
info.setFrameWidth(1);
canvas.add(info);
// Create input boxes and add them to the bottom of the applet
Panel xIn = new Panel(); // not a JCMPanel, since I don't want the input boxes to be controlled
// by the main controller anyway.
xIn.setBackground(getColorParam("PanelColor",Color.lightGray));
xIn.setLayout(new GridLayout(1,4,3,3));
xIn.add(new Label("Tangent at " + xVar.getName() + " = ", Label.RIGHT));
xIn.add(x1Input);
xIn.add(new Label("Secant to " + xVar.getName() + " = ", Label.RIGHT));
xIn.add(x2Input);
// Put the inputs at the bottom of the inputPanel, if there is one, otherwise
// at the bottom of the mainPanel
if (inputPanel == null)
mainPanel.add(xIn, BorderLayout.SOUTH);
else
inputPanel.add(xIn, BorderLayout.SOUTH);
 
// Set up controllers. I want to arrange things so that the controls that position the
// two points on the graph do not cause the graph to be recomputted when they are changed.
 
Controller dragControl = new Controller(); // A controller to respond to dragging
mainController.remove(canvas);
mainController.add(graph);
mainController.add(dragControl); // Things in dragController should be recomputed when graph is changed
 
dragControl.add(x1Input); // dragControl checks the contents of the x-inputs
dragControl.add(x2Input); // and recomputes everything except the graph.
dragControl.add(drag1);
dragControl.add(drag2);
dragControl.add(tangent);
dragControl.add(secant);
dragControl.add(info);
 
drag1.setOnUserAction(dragControl); // dragControl.compute() is called when the
drag2.setOnUserAction(dragControl); // user drags one of the points or types
x1Input.setOnTextChange(dragControl); // in one of the x-input boxes.
x2Input.setOnTextChange(dragControl);
 
// By adding Tie's to dragControll, we make sure that the positions of the
// draggable points are synchronized with the contents of the x-input boxes.
 
dragControl.add(new Tie((Tieable)drag1.getXVar(), x1Input));
dragControl.add(new Tie((Tieable)drag2.getXVar(), x2Input));
// Get initial values for draggable points
double[] d1 = getNumericParam("X1");
double x1 = (d1 != null && d1.length == 1)? d1[0] : 0;
x1Input.setVal(x1);
drag1.setLocation(x1,0); // y-value will be changed to make the point lie on the curve
double[] d2 = getNumericParam("X2");
double x2 = (d2 != null && d2.length == 1)? d2[0] : 1;
x2Input.setVal(x2);
drag2.setLocation(x2,0);
 
} // end setUpCanvas()
 
private Color lighten(Color c) { // for making "Ghost" color of draggable point
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
int nr, ng, nb;
if (r <= 200 || g <= 200 || b <= 200) {
nb = 255 - (255 - b) / 3;
ng = 255 - (255 - g) / 3;
nr = 255 - (255 - r) / 3;
}
else {
nb = b / 2;
ng = g / 2;
nr = r / 2;
}
return new Color(nr,ng,nb);
}
 
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the SecantTangent applet, the example string should contain
// an expression that defines the function to be graphed. This can optionally
// be followed by a semicoloon and a list of fourto six numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// fifth number, if present, gives the x-coord where the tangent line
// is drawn. The sixth number gives the x-coord of the second point
// on the secant line.
int pos = example.indexOf(";");
 
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
if (pos > 0) { // get limits from example text
String limitsText = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(limitsText, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
if (toks.countTokens() > 0) { // Get point for tangent line
try {
Double d = new Double(toks.nextToken());
x1Input.setVal( d.doubleValue() );
}
catch (NumberFormatException e) {
}
}
if (toks.countTokens() > 0) { // Get other point for secant line
try {
Double d = new Double(toks.nextToken());
x2Input.setVal( d.doubleValue() );
}
catch (NumberFormatException e) {
}
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
// Also, in this case, func is a "WrapperFunction". Set the
// definition of that WrapperFunction to be the same as f
try {
Function f = new SimpleFunction( parser.parse(example), xVar );
((WrapperFunction)func).setFunction(f);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
 
 
} // end class SimpleGraph
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/RiemannSums.java
0,0 → 1,289
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
// The SimpleGraph applet is a configurable applet that displays the graph of
// a single function of one variable and computes a Riemann sum for that
// function.
 
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
 
public class RiemannSums extends GenericGraphApplet {
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private Variable intervals; // Gives the number of intervals.
private VariableInput intCtInput; // For letting the user enter the number of intervals.
private Choice methodChoice; // Gives the method to be used: Left Endpoint, ..., Trapezoid.
 
private Function func; // The function that is graphed.
private Graph1D graph; // The graph of the function.
private RiemannSumRects sums;
 
public void itemStateChanged(ItemEvent evt) {
// React when user changes the summation method.
if (evt.getSource() == methodChoice) {
sums.setMethod(methodChoice.getSelectedIndex());
mainController.compute();
}
else
super.itemStateChanged(evt);
}
protected void setUpParameterDefaults() { // Override to give a different default function
parameterDefaults = new java.util.Hashtable();
String func = " 3 / (1 + " + getParameter("Variable","x") + "^2)";
parameterDefaults.put("Function",func);
parameterDefaults.put("ComputeButtonName","Compute!");
}
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
// When setUpCanvas is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function".
if (functionInput != null)
func = functionInput.getFunction(xVar);
else {
String def = getParameter("Function", " abs(" + xVar.getName() + ") ^ " + xVar.getName());
Function f = new SimpleFunction( parser.parse(def), xVar );
func = new WrapperFunction(f);
}
graph = new Graph1D(func);
Color color = getColorParam("GraphColor");
if (color != null)
graph.setColor(color);
// Get the data for the RiemannSumRects object. Create it (along with other
// associated objects) and add it to the canvas.
double[] intCtD = getNumericParam("IntervalCount");
if (intCtD == null || intCtD.length < 1)
intCtD = new double[] { 5 };
else if (Double.isNaN(intCtD[0]) || intCtD[0] < 1 || intCtD[0] > 5000)
intCtD[0] = 5;
int intCt = (int)(intCtD[0]+0.5);
if ("yes".equalsIgnoreCase( getParameter("UseIntervalInput", "yes") )){
intCtInput = new VariableInput(null, "" + intCt);
intCtInput.setInputStyle(VariableInput.INTEGER);
intCtInput.setMin(1);
intCtInput.setMax(5000);
intervals = intCtInput.getVariable();
}
else
intervals = new Variable(null,intCt);
int method = RiemannSumRects.LEFTENDPOINT;
 
String methodStr = getParameter("Method");
if (methodStr != null && methodStr.trim().length() > 0) {
switch (methodStr.trim().charAt(0)) {
case 'L': case 'l': method = RiemannSumRects.LEFTENDPOINT; break;
case 'R': case 'r': method = RiemannSumRects.RIGHTENDPOINT; break;
case 'M': case 'm': method = RiemannSumRects.MIDPOINT; break;
case 'C': case 'c': method = RiemannSumRects.CIRCUMSCRIBED; break;
case 'I': case 'i': method = RiemannSumRects.INSCRIBED; break;
case 'T': case 't': method = RiemannSumRects.TRAPEZOID; break;
}
}
if ("yes".equalsIgnoreCase( getParameter("UseMethodInput", "yes") )) {
methodChoice = new Choice();
methodChoice.add("Left Endpoint");
methodChoice.add("Right Endpoint");
methodChoice.add("Midpoint");
methodChoice.add("~Circumscribed");
methodChoice.add("~Inscribed");
methodChoice.add("Trapezoid");
methodChoice.select(method);
methodChoice.addItemListener(this);
}
sums = new RiemannSumRects(func,intervals);
sums.setMethod(method);
canvas.add(sums);
Color c = getColorParam("RectColor");
if (c != null)
sums.setColor(c);
c = getColorParam("OutlineColor");
if (c != null)
sums.setOutlineColor(c);
super.setUpCanvas(); // Do the common setup: Add the axes, for example.
canvas.getCoordinateRect().setGap(10); // Extra space around edges.
canvas.add(graph); // Add the graph to the canvas.
// Add a DrawString to the canvas to show the value of the sum.
 
DrawString ds = new DrawString("sum = #", DrawString.TOP_LEFT,
new Value[] { sums.getValueObject(RiemannSumRects.CURRENT_METHOD) } );
ds.setBackgroundColor(getColorParam("TextBackground",Color.white));
ds.setColor(getColorParam("TextColor",Color.black));
ds.setFrameWidth(1);
canvas.add(ds);
mainController.add(ds);
mainController.add(sums);
if (intCtInput != null)
intCtInput.setOnUserAction(mainController);
canvas.getCoordinateRect().setOnChange(mainController);
 
} // end setUpCanvas()
 
protected void setUpMainPanel() {
// Override this method to add the methodChoice menu and interval count inputs, if any,
// to the panel. (They were created in the setUpCanvas method.)
super.setUpMainPanel(); // Do the common setup
if (methodChoice == null && intCtInput == null)
return;
JCMPanel panel = new JCMPanel();
panel.setLayout(new FlowLayout());
panel.setBackground(getColorParam("PanelBackground",Color.lightGray));
if (intCtInput != null) {
panel.add(new Label("Intervals:"));
panel.add(intCtInput);
}
if (methodChoice != null) {
panel.add(new Label("Method:"));
panel.add(methodChoice);
}
if (inputPanel == null)
mainPanel.add(panel, BorderLayout.SOUTH);
else {
inputPanel.setBackground(getColorParam("PanelBackground",Color.lightGray));
inputPanel.add(panel, BorderLayout.SOUTH);
}
} // end setUpMainPanel()
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For this applet, the example string should contain
// an expression that defines the function to be graphed.
// This can optionally be followed by a semicoloon and a list of four or five
// numbers. The first four numbers give the x- and y- limes to be used for the
// example. The fifth number, if present, gives the interval count.
// After the numbers, there can be another semicolon
// and the name of the summation method to be used.
 
int pos = example.indexOf(";");
 
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
if (pos > 0) { // get limits, method from example text
String limitsText = example.substring(pos+1);
example = example.substring(0,pos);
pos = limitsText.indexOf(";");
if (pos > 0) { // data includes a method name.
String methodStr = limitsText.substring(pos+1).trim();
limitsText = limitsText.substring(0,pos);
if (methodStr.length() > 0) {
int method;
switch (methodStr.charAt(0)) {
case 'L': case 'l': method = RiemannSumRects.LEFTENDPOINT; break;
case 'R': case 'r': method = RiemannSumRects.RIGHTENDPOINT; break;
case 'M': case 'm': method = RiemannSumRects.MIDPOINT; break;
case 'C': case 'c': method = RiemannSumRects.CIRCUMSCRIBED; break;
case 'I': case 'i': method = RiemannSumRects.INSCRIBED; break;
case 'T': case 't': method = RiemannSumRects.TRAPEZOID; break;
default: method = -1;
}
if (method >= 0) {
sums.setMethod(method);
if (methodChoice != null)
methodChoice.select(method);
}
}
}
StringTokenizer toks = new StringTokenizer(limitsText, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
if (toks.countTokens() > 0) {
// get number of intervals
try {
Double d = new Double(toks.nextToken());
double intCtD = d.doubleValue();
if (intCtD < 1)
intCtD = 1;
else if (intCtD > 5000)
intCtD = 5000;
intervals.setVal((int)(intCtD + 0.5));
}
catch (NumberFormatException e) {
}
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
// Also, in this case, func is a "WrapperFunction". Set the
// definition of that WrapperFunction to be the same as f
try {
Function f = new SimpleFunction( parser.parse(example), xVar );
((WrapperFunction)func).setFunction(f);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
 
 
} // end class RiemannSums
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/Evaluator.java
0,0 → 1,266
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
import edu.hws.jcm.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.functions.*;
 
import java.awt.*;
import java.awt.event.*;
import java.util.StringTokenizer;
import java.applet.Applet;
 
/**
* An Evaluator applet lets the user enter the values of one or more variables,
* and it displayes the values of one or more expressions that can involve those
* variables. The expression values are updated continuously as the user types.
*/
 
public class Evaluator extends Applet implements ActionListener {
 
private Frame frame; // If non-null, a separate window.
private String frameTitle; // Title for the separate window.
private Button launchButton; // If non-null, then clicking this buttons opens a separate window.
private String launchButtonName; // Name for the launch button.
 
/**
* The init() method is called by the system to set up the applet.
* If the applet does not appear as a button, then init() creates the main panel of the applet
* and calls setUpMainPanel to set it up.
*/
public void init() {
frameTitle = getParameter("FrameTitle"); // Get title to be used for separate window, if any.
if (frameTitle == null) {
frameTitle = "Calculator";
int pos = frameTitle.lastIndexOf('.');
if (pos > -1)
frameTitle = frameTitle.substring(pos+1);
}
setLayout(new BorderLayout());
int height = getSize().height;
launchButtonName = getParameter("LaunchButtonName");
if ( (height > 0 && height <= 35) || launchButtonName != null) {
// Use a separater window and only show a button in the applet.
if (launchButtonName == null)
launchButtonName = "Launch " + frameTitle;
launchButton = new Button(launchButtonName);
add(launchButton, BorderLayout.CENTER);
launchButton.addActionListener(this);
}
else {
// Show the main panel in the applet, not in a separate window.
add(makeMainPanel(), BorderLayout.CENTER);
}
}
 
/*
* Create the main panel of the applet.
*/
public JCMPanel makeMainPanel() {
// Get values of color params.
Color background = getColorParam("BackgroundColor", Color.gray);
Color labelBackground = getColorParam("LabelBackground", new Color(225,225,225));
Color labelForeground = getColorParam("LabelForeground", new Color(0,0,200));
Color answerBackground = getColorParam("AnswerBackground", labelBackground);
Color answerForeground = getColorParam("AnswerForeground", Color.red);
Color inputBackground = getColorParam("InputBackground", Color.white);
Color inputForeground = getColorParam("InputForeground", Color.black);
 
// Create the panel and subpanel. The left subpanel will hold labes for the
// variables and expressions. The right subpanel will hold the variable input
// boxes and expression values.
 
JCMPanel panel = new JCMPanel(5);
panel.setBackground(background);
panel.setInsetGap(3);
setLayout(new BorderLayout());
add(panel,BorderLayout.CENTER);
JCMPanel left = new JCMPanel(0,1,3);
panel.add(left, BorderLayout.CENTER);
JCMPanel right = new JCMPanel(0,1,3);
panel.add(right, BorderLayout.EAST);
// Create a parser and configure it to allow factorials and summations.
Parser parser = new Parser();
parser.addOptions(Parser.FACTORIAL);
parser.add( new SummationParser() );
// Create the variable input boxes, using variable names given by
// applet parameters. If no names are provided in applet parameters,
// use one variable named "x". Add the Variables from the variable inputs
// to the parser so that they can be used in expressions.
int ct = 0;
String variableName = getParameter("Variable");
if (variableName == null) {
variableName = getParameter("Variable1");
if (variableName == null) {
variableName = "x";
}
else
ct = 1;
}
String firstVar = variableName;
while (variableName != null) {
String valString = "0";
variableName = variableName.trim();
int pos = variableName.indexOf(" ");
if (pos > 0) {
// If there is anything in the string after the variable name, use it as the variable value.
valString = variableName.substring(pos+1).trim();
variableName = variableName.substring(0,pos);
}
Label lab = new Label(" Input: " + variableName + " = ", Label.RIGHT);
lab.setBackground(labelBackground);
lab.setForeground(labelForeground);
left.add(lab);
VariableInput v = new VariableInput(variableName,valString,parser);
v.setBackground(inputBackground);
v.setForeground(inputForeground);
v.setThrowErrors(false);
v.setOnTextChange(panel.getController());
v.setOnUserAction(panel.getController());
right.add(v);
ct++;
variableName = getParameter("Variable" + ct);
}
// Get the expressions to be evalueated from applet parameters and add evaluators
// to the applet. If not expressions are provided in applet parameters, use
// one expression, "log2(x)".
ct = 0;
String function = getParameter("Expression");
if (function == null) {
function = getParameter("Expression1");
if (function == null)
function = "log2(" + firstVar + ")";
else
ct = 1;
}
while (function != null) {
Label lab = new Label(" " + function + " = ", Label.RIGHT);
lab.setBackground(labelBackground);
lab.setForeground(labelForeground);
left.add(lab);
try {
DisplayLabel d = new DisplayLabel("#", parser.parse(function));
d.setBackground(answerBackground);
d.setForeground(answerForeground);
d.setAlignment(Label.CENTER);
right.add(d);
}
catch (ParseError e) {
right.add(new Label("invalid function"));
}
ct++;
function = getParameter("Expression" + ct);
}
return panel;
 
} // end makeMainPanel()
 
/**
* Respond when user clicks a button; not meant to be called directly.
* This opens and closes the separate window.
*/
synchronized public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == launchButton && launchButton != null) {
launchButton.setEnabled(false);
if (frame == null) {
frame = new Frame(frameTitle);
frame.add(makeMainPanel());
frame.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
frame.dispose();
}
public void windowClosed(WindowEvent evt) {
frameClosed();
}
} );
frame.pack();
frame.setLocation(50,50);
frame.show();
launchButton.setLabel("Close Window");
launchButton.setEnabled(true);
}
else {
frame.dispose();
}
}
}
synchronized private void frameClosed() {
// respond when separate window closes.
frame = null;
launchButton.setLabel(launchButtonName);
launchButton.setEnabled(true);
}
/**
* Get The value of an applet parameter that specifies a color. The color can be specfied
* as a list of three numbers in the range 0 to 255 or by one of the standard color names
* ("black", "red", "blue", "green", "yellow", "cyan", "magenta", "gray", "darkgray",
* "lightgray", "pink", "orange", "white"). Color names are not case sensitive.
*
* @param paramName The name of the applet parameter.
* @param defaultColor The value to be returned if getParameter(paramName) is null or is not a valid color.
*/
protected Color getColorParam(String paramName, Color defaultColor) {
String data = getParameter(paramName);
if (data == null || data.trim().length() == 0)
return defaultColor;
data = data.trim();
if (Character.isLetter(data.charAt(0))) {
for (int i = 0; i < colorNames.length; i++)
if (data.equalsIgnoreCase(colorNames[i]))
return colors[i];
return defaultColor;
}
else {
StringTokenizer tokenizer = new StringTokenizer(data," \t,;");
int count = tokenizer.countTokens();
if (count < 3)
return defaultColor;
double[] nums = new double[3];
for (int i = 0; i < 3; i++) {
try {
Double d = new Double(tokenizer.nextToken());
nums[i] = d.doubleValue();
}
catch (NumberFormatException e) {
return defaultColor;
}
}
if (nums[0] < 0 || nums[0] > 255 || nums[1] < 0 || nums[1] > 255 || nums[2] < 0 || nums[2] > 255)
return defaultColor;
return new Color((int)Math.round(nums[0]), (int)Math.round(nums[1]), (int)Math.round(nums[2]));
}
}
private String[] colorNames = { "black", "red", "blue", "green", "yellow",
"cyan", "magenta", "gray", "darkgray",
"lightgray", "pink", "orange", "white" };
private Color[] colors = { Color.black, Color.red, Color.blue, Color.green, Color.yellow,
Color.cyan, Color.magenta, Color.gray, Color.darkGray,
Color.lightGray, Color.pink, Color.orange, Color.white };
 
} // end class evaluator
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/SilentFamiliesOfGraphs.java
0,0 → 1,319
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
// An applet belonging to the class SilentFamiliesOfGraphs displays a graph
// of a function that can depend on one or more parameters. The values of
// the parameters are controlled by the user using sliders at the bottom of
// the applet.
 
 
import java.awt.*;
import java.applet.Applet;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
import java.net.*;
import java.io.*;
 
 
public class SilentFamiliesOfGraphs extends GenericGraphApplet {
 
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private Function func; // The function that is graphed.
private Graph1D graph; // The graph of the function.
private Vector sliders; // Elements of this vector are the VariableSlider
// objects that represent the parameter values.
// The sliders are created in the setUpParser() method.
 
 
 
protected void setUpParser() { // Override this to add VariableSliders to parser.
// Get the data for the sliders from applet params named "Parameter", "Parameter1", ...
// The sliders are created and the variables are added to the parser by the
// addParameter() method, which is defined below.
sliders = new Vector();
int ct = 0;
String param = getParameter("Parameter");
if (param == null) {
ct++;
param = getParameter("Parameter" + ct);
}
while (true) {
if (param == null)
break;
addParameter(param);
ct++;
param = getParameter("Parameter" + ct);
}
// If no parameters were specified in applet params, create one with name "k".
if (sliders.size() == 0)
addParameter("k");
super.setUpParser(); // Call this last so function definitions
// in applet params can use the parameter names
// that have just been added to the parser
// (even though it's probably not a good idea).
// Note that this also defines the independent variable,
// whose name is given by the applet param "Variable"
// and which is referred to as xVar in this program.
VariableSlider slide = (VariableSlider)sliders.elementAt(0);
String def = getParameter("Function", "sin(" + slide.getName() + " * " + xVar.getName() + ")");
parameterDefaults = new Hashtable(); // I want to set a different default value for
// the "Function" applet param.
parameterDefaults.put("Function",def);
} // end setUpParser()
 
 
private void addParameter(String data) {
// Create a VariableSlider from the information in name and add it to the
// Vector of sliders. The data must contain the name of the variable
// associated with the slider. The name can be followed by a ";" and up to
// three numbers. (If there is no ";", a space after the name will do.)
// The numbers can be separated by commas, spaces, or tabs. The first
// number gives the minimum value on the slider, the second gives the maximum,
// and the third gives the initial value of the slider variable.
 
double min = -5, max = 5, val = 0; // min, max, and value for slider
 
data = data.trim();
int pos = data.indexOf(';');
if (pos < 0)
pos = data.indexOf(' ');
String name; // The name of the parameter
 
if (pos < 0) {
// If there is no space or ";", the data is just the name of the variable.
name = data;
}
else {
// Get the name from the front of the data, then look for min, max, and val.
String nums = data.substring(pos+1);
name = data.substring(0,pos).trim();
StringTokenizer toks = new StringTokenizer(nums," ,\t");
try {
if (toks.hasMoreElements())
min = (new Double(toks.nextToken())).doubleValue();
if (toks.hasMoreElements())
max = (new Double(toks.nextToken())).doubleValue();
if (toks.hasMoreElements())
val = (new Double(toks.nextToken())).doubleValue();
}
catch (NumberFormatException e) {
min = -5;
max = 5;
val = 0;
}
}
// Create the slider, adding the associated variable to the parser, and set its value.
VariableSlider slide = new VariableSlider(name, new Constant(min), new Constant(max), parser);
slide.setVal(val);
sliders.addElement(slide); // Save the slider in the array of sliders for later use.
} // end setUpParser();
 
 
protected void setUpBottomPanel() { // Overridden to add the sliders at the bottom of the applet.
 
super.setUpBottomPanel(); // Do the default setup.
 
// Create a panel holding all the sliders, with a display label for each slider to show its value.
 
JCMPanel sliderPanel = new JCMPanel();
sliderPanel.setLayout(new GridLayout(0,1,3,3));
sliderPanel.setBackground(getColorParam("PanelBackground", Color.lightGray));
for (int i = 0; i < sliders.size(); i++) {
JCMPanel p = new JCMPanel();
VariableSlider slide = (VariableSlider)sliders.elementAt(i);
p.add(slide, BorderLayout.CENTER);
p.add(new DisplayLabel(" " + slide.getName() + " = # ", new Value[] { slide.getVariable() } ),
BorderLayout.EAST);
sliderPanel.add(p);
slide.setOnUserAction(mainController);
}
// If there is a functionInput box, then the SOUTH position of the mainPanel already contains
// the inputPanel that contains that box. If so, add the new panel to the SOUTH position of
// the inputPanel. (This is a good place, in general, to put extra input objects.)
// If there is no inputPanel, then the SOUTH position of the mainPanel is empty, so put
// the newly created panel there.
if (inputPanel != null)
inputPanel.add(sliderPanel, BorderLayout.SOUTH);
else
mainPanel.add(sliderPanel, BorderLayout.SOUTH);
 
} // end setUpBottomPanel()
 
 
 
protected void setUpCanvas() { // Overridden to add the graph to the canvas.
 
super.setUpCanvas(); // Do the default setup.
 
// When setUpCanvas() is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function" (or use sin(k*x) if none is specified).
 
if (functionInput != null)
func = functionInput.getFunction(xVar);
else {//jm.evers 1/2010 load a file from url
String def;
try{
String data = getParameter("File");
def = load(data);
def = def.replaceAll("\\n","");
//System.out.println("loaded "+def);
} catch(Exception e){
System.out.println("could not load parameter File");
def = getParameter("Function"); // default value is set in setUpParser()
}
func = new SimpleFunction( parser.parse(def), xVar );
}
 
// Create a graph of the function and add it to the canvas.
graph = new Graph1D(func);
graph.setColor(getColorParam("GraphColor", Color.magenta));
canvas.add(graph);
 
} // end setUpCanvas
 
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the SilentFamiliesOfGraphs applet, the example string should contain
// an expression that defines the function to be graphed. This can optionally
// be followed by a semicolon and a list of four or more numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// remaining numbers occur in groups of three and specify the minimumn,
// maximum and values of the parameters, in the
// same order that they were encountered in the setUpParser() method.
int pos = example.indexOf(";");
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
 
if (pos > 0) {
// Get limits from example text.
String nums = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(nums, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
}
int i = 0;
while (i < sliders.size() && toks.hasMoreElements()) {
// Look for a value for the i-th slider.
try {
double min = (new Double(toks.nextToken())).doubleValue();
double max = (new Double(toks.nextToken())).doubleValue();
double d = (new Double(toks.nextToken())).doubleValue();
VariableSlider slider = ((VariableSlider)sliders.elementAt(i));
slider.setMin(new Constant(min));
slider.setMax(new Constant(max));
slider.setVal(d);
}
catch (Exception e) {
}
i++;
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
try {
func = new SimpleFunction( parser.parse(example), xVar );
graph.setFunction(func);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
 
// jm.evers; handy functions, not invented here :(
public static byte [] loadURL(URL url) throws IOException {
int bufSize = 1024 * 2;
byte [] buf = new byte[bufSize];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(url.openStream());
int n;
while ((n = in.read(buf)) > 0){
bout.write(buf, 0, n);
}
try { in.close(); } catch (Exception ignored) { }
return bout.toByteArray();
}
 
public static String loadFile(String fname) throws IOException {
byte[] bytes = loadURL(new URL("file:" + fname));
return new String(bytes);
}
 
public static String load(String fileOrURL) throws IOException {
try {
URL url = new URL(fileOrURL);
return new String(loadURL(url));}
catch (Exception e) { return loadFile(fileOrURL);}
}
} // end class SilentFamiliesOfGraphs
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/AnimatedGraph.java
0,0 → 1,307
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
// An applet belonging to the class AnimatedGraph displays a graph
// of a function that can depend on a parameter. The value of the
// parameter can be "animated" so that it ranges from one value ot
// another over a sequence of frames.
 
import java.awt.*;
import java.applet.Applet;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
 
public class AnimatedGraph extends GenericGraphApplet {
 
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private Function func; // The function that is graphed.
private Graph1D graph; // The graph of the function.
private Animator animator; // Animates the graph
private Variable kVar; // The parameter variable
private VariableInput kMin, kMax, kIntervals; // min, max, and number of intervals for the animator. Might be null.
 
 
protected void setUpParser() { // Override this to create the animator and add its variable to the parser.
int options = Animator.START_STOP_BUTTON | Animator.PAUSE_BUTTON | Animator.LOOP_CHOICE;
if ( ! "no".equalsIgnoreCase(getParameter("UseNextAndPrev","yes")) )
options |= Animator.PREV_BUTTON | Animator.NEXT_BUTTON;
animator = new Animator(options);
kVar = animator.getValueAsVariable( getParameter("Parameter","k") );
parser.add(kVar);
super.setUpParser();
 
parameterDefaults = new Hashtable();
String defaultFunction = xVar.getName() + " / (" + kVar.getName() + " - " + xVar.getName() + "^2)";
parameterDefaults.put("Function",defaultFunction);
if (! "no".equalsIgnoreCase(getParameter("UseAnimatorInputs")))
parameterDefaults.put("TwoLimitsColumns","yes"); // change default if we need space for animator inputs
} // end setUpParser()
 
protected void setUpBottomPanel() { // Overridden to add the sliders at the bottom of the applet.
 
super.setUpBottomPanel(); // Do the default setup.
// If there is a functionInput box, then the SOUTH position of the mainPanel already contains
// the inputPanel that contains that box. If so, add the animator to the SOUTH position of
// the inputPanel. (This is a good place, in general, to put extra input objects.)
// If there is no inputPanel, then the SOUTH position of the mainPanel is empty, so put
// the animator there.
if (inputPanel != null)
inputPanel.add(animator, BorderLayout.SOUTH);
else
mainPanel.add(animator, BorderLayout.SOUTH);
 
} // end setUpBottomPanel()
 
 
 
protected void setUpCanvas() { // Overridden to add the graph to the canvas and do other chores.
 
super.setUpCanvas(); // Do the default setup.
 
// When setUpCanvas() is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function" (or use sin(k*x) if none is specified).
 
if (functionInput != null)
func = functionInput.getFunction(xVar);
else {
String def = getParameter("Function"); // default value is set in setUpParser()
func = new SimpleFunction( parser.parse(def), xVar );
}
 
// Create a graph of the function and add it to the canvas.
graph = new Graph1D(func);
graph.setColor(getColorParam("GraphColor", Color.magenta));
canvas.add(graph);
// Set up the min, max, and intervals property of the animator
if (! "no".equalsIgnoreCase(getParameter("UseAnimatorInputs"))) {
kMin = new VariableInput(kVar.getName() + "Start",getParameter("ParameterMin","-2"));
kMax = new VariableInput(kVar.getName() + "End",getParameter("ParameterMax","2"));
kIntervals = new VariableInput("Intervals", getParameter("Intervals","25"));
kIntervals.setInputStyle(VariableInput.INTEGER);
kIntervals.setMin(1);
kIntervals.setMax(1000);
kMin.setOnUserAction(mainController);
kMax.setOnUserAction(mainController);
kIntervals.setOnUserAction(mainController);
animator.setMin(kMin);
animator.setMax(kMax);
animator.setIntervals(kIntervals);
if (limitsPanel != null) {
// componets will be added to limitsPanel in setUpLimitsPanel()
mainController.add(kMin); // This is not done automatically, since they are in a limits panel
mainController.add(kMax);
mainController.add(kIntervals);
}
else {
JCMPanel ap = new JCMPanel(9,0);
ap.setBackground(getColorParam("PanelBackground", Color.lightGray));
ap.add(new Label(kMin.getName()));
ap.add(kMin);
ap.add(new Label());
ap.add(new Label(kMax.getName()));
ap.add(kMax);
ap.add(new Label());
ap.add(new Label(kIntervals.getName()));
ap.add(kIntervals);
ap.add(new Label());
mainPanel.add(ap,BorderLayout.EAST);
}
}
else {
try {
animator.setMin( (new Double(getParameter("ParameterMin","-2"))).doubleValue() );
animator.setMax( (new Double(getParameter("ParameterMax","2"))).doubleValue() );
animator.setIntervals( (int)Math.round((new Double(getParameter("Intervals","25"))).doubleValue()) );
}
catch (NumberFormatException e) {
}
}
animator.setOnChange(mainController);
 
// Add a DrawString to show the current value of the parameter
 
if ( ! "no".equalsIgnoreCase(getParameter("ShowParameter","yes")) ) {
DrawString param = new DrawString(kVar.getName() + " = #", DrawString.BOTTOM_LEFT, new Value[] { kVar });
param.setBackgroundColor(canvas.getBackground());
Color c = getColorParam("ParameterColor",Color.black);
param.setColor(c);
canvas.add(param);
}
 
} // end setUpCanvas
 
 
protected void setUpLimitsPanel() {
super.setUpLimitsPanel();
if (limitsPanel != null && kMin != null) { // add animator inputs to limits panel
limitsPanel.addComponentPair(kMin,kMax);
limitsPanel.addComponent(kIntervals);
}
}
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the AnimatedGraph applet, the example string should contain
// an expression that defines the function to be graphed. This can optionally
// be followed by a semicolon and a list of four to nine numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// next three numbers specify the minimum value for the parameter, the
// maximum number, and the number of intervals in the animation.
// The eigth number, if present, specifies the starting loop style
// for the animation with the following code: 0 for once-through,
// 1 for loop, and 2 for back-and-forth. The ninth number, if
// present, tells whether to start the animation immediately upon
// loading. If it is 1, the animation is started. If it is
// not specified or is any value other than 1, the animation is not started.
animator.stop();
int pos = example.indexOf(";");
boolean startAnimation = false;
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
 
if (pos > 0) {
// Get limits from example text.
String nums = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(nums, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
}
if (toks.hasMoreTokens()) {
try {
double d = (new Double(toks.nextToken())).doubleValue();
if (kMin == null)
animator.setMin(d);
else
kMin.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
double d = (new Double(toks.nextToken())).doubleValue();
if (kMax == null)
animator.setMax(d);
else
kMax.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
if (kIntervals == null)
animator.setIntervals(d);
else
kIntervals.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
animator.setLoopStyle(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
startAnimation = (d == 1);
}
catch (NumberFormatException e) {
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
try {
func = new SimpleFunction( parser.parse(example), xVar );
graph.setFunction(func);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
if (startAnimation) {
try { // insert a small delay before animation starts
synchronized(this) {
wait(250);
}
}
catch (InterruptedException e) {
}
animator.start();
}
} // end doLoadExample()
public void stop() { // stop animator when applet is stopped
animator.stop();
super.stop();
}
} // end class FamiliesOfGraphs
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/GenericGraphApplet.java
0,0 → 1,848
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.awt.*;
import edu.hws.jcm.functions.*;
 
/**
* GenericGraphApplet serves as a base class for applets that have a DisplayCanvas in the CENTER of
* a BorderLayout and that are configurable by a large number of applet parameters. This base class
* sets up the basic structure of the applet and processes many applet parameters. Most of the
* work is done in methods that can be overridden in subclasses. If the height of
* the applet is greater than 100 and if the applet parameter "LaunchButtonName" is not defined,
* then the main panel of the applet appears in the applet itself. Otherwise,
* the applet appears as a button. Clicking the button opens the main panel of the
* applet in a separate, resizable frame.
*/
 
public class GenericGraphApplet extends Applet implements ActionListener, ItemListener {
 
/**
* The parser which is used for parsing input from the functionInput box.
*/
protected Parser parser;
 
/**
* The main panel of the applet, containing a display canvas and other components.
*/
protected JCMPanel mainPanel;
 
/**
* The Controller from the mainPanel.
*/
protected Controller mainController;
 
/**
* The canvas for displaying axes, graphs, etc.
*/
protected DisplayCanvas canvas;
 
/**
* Controls the limits of the x- and y-coordinates on the canvas.
*/
protected LimitControlPanel limitsPanel;
 
/**
* An input box for inputting an expression.
*/
protected ExpressionInput functionInput;
/**
* The variable that is created and added to the parser. The default name of this
* variable is "x", but that can be changed using the "Variable" applet param.
* The variable is created in the setUpParser() method.
*/
protected Variable xVar;
 
/**
* A panel containing the functionInput. It appears at the bottom of the main panel.
*/
protected JCMPanel inputPanel;
 
/**
* A panel containing examples specified in applet parameters, if any. It appears
* at the top of the main panel.
*/
protected JCMPanel exampleMenuPanel;
 
/**
* A button that the user presses to recompute the display. (Ths user can also just
* press return in one of the input boxes.)
*/
protected Button computeButton;
/**
* The string that is used as the title of the frame, if the applet appears as
* a launch button. This title is also used on the launch button, unless the
* applet parameter "LaunchButtonName" has a value. This is set in the init() method.
*/
protected String frameTitle;
/**
* The default size for the frame when the applet runs a launch button.
* Can be overidden by the FrameSize applet param.
*/
protected int[] defaultFrameSize = { 550, 400} ;
/**
* A hash table that, if non-null, can hold values for applet params. While this is
* not set to a non-null value in this class, its value can be set in the setUpAppletDefaults()
* method. The values in this hash table will be returned by the getParameter() method
* when no value is provided in the applet. For example, this class uses a default value
* of "s" vor the the param "Variable". A subclass could put a different value in the
* parameterDefaults hash table, and this value will be used in preference to "x".
*/
protected Hashtable parameterDefaults;
/**
* The init() method is called by the system to set up the applet.
* If the applet does not appear as a button, then init() creates the main panel of the applet
* and calls setUpMainPanel to set it up. If any error occurs during calls to setUpParser(),
* setUpExampleMenu(), or setUpMainPanel(), then the applet will just show an error message,
* and stack trace will be printed to standard output.
*/
public void init() {
setUpParameterDefaults();
frameTitle = getParameter("FrameTitle");
if (frameTitle == null) {
frameTitle = this.getClass().getName();
int pos = frameTitle.lastIndexOf('.');
if (pos > -1)
frameTitle = frameTitle.substring(pos+1);
}
setLayout(new BorderLayout());
int height = getSize().height;
launchButtonName = getParameter("LaunchButtonName");
if ( (height > 0 && height < 100) || launchButtonName != null) {
if (launchButtonName == null)
launchButtonName = "Launch " + frameTitle;
launchButton = new Button(launchButtonName);
add(launchButton, BorderLayout.CENTER);
launchButton.addActionListener(this);
}
else {
mainPanel = new JCMPanel();
try {
setUpMainPanel();
add(mainPanel, BorderLayout.CENTER);
}
catch (Exception e) {
System.out.println("Error while opening applet:");
e.printStackTrace();
TextArea message = new TextArea("An error occurred while setting up the applet:\n\n");
message.append(e.toString());
add(message, BorderLayout.CENTER);
}
}
}
/**
* This method is called to set up the main panel of the applet. The main panel object, of type JCMPanel,
* already exists in the variable mainPanel when it is called. It begins by calling setUpParser()
* and setUpExampleMenu(). This method processes applet parameters
* "Insets", "BackgroundColor", and "ForegroundColor" to set the gap and colors of the panel. It
* creates a DisplayCanvas and, if the applet parameter "UseLimitsPanel" is not equal to "no", it
* creates a LimitControlPanel. The coordinate limits are set using the "Limits" applet param, if
* presetn. This method assigns the Controller from the mainPanel to the member variable
* mainController. It then calls setUpBottomPanel(), setUpTopPanel(), setUpCanvas(), addCanvasBorder(),
* and, if there is a limits panel, setUpLimitsPanel(), in that order. Finally, if the value
* of the applet parameter "LoadFirstExample" is not "no", and if any examples were specifed, then
* the first ewxample is loaded.
*/
protected void setUpMainPanel() {
parser = new Parser(null,0);
setUpParser();
setUpExampleMenu();
double[] gap = getNumericParam("Insets");
if (gap == null || gap.length == 0 || gap[0] < 0 || gap[0] > 50)
mainPanel.setInsetGap(3);
else
mainPanel.setInsetGap( (int)Math.round(gap[0]) );
Color color;
color = getColorParam("BackgroundColor", Color.gray);
mainPanel.setBackground(color);
color = getColorParam("ForegroundColor", Color.black);
mainPanel.setForeground(color);
canvas = new DisplayCanvas();
double[] limits = getNumericParam("Limits");
if (limits != null && limits.length >= 4)
canvas.getCoordinateRect().setLimits(limits);
if ( "yes".equalsIgnoreCase(getParameter("UseLimitsPanel", "yes")) ) {
String h = getParameter("XName");
if (h == null)
h = getParameter("Variable","x");
String v =getParameter("YName","y");
limitsPanel = new LimitControlPanel( h+"min", h+"max", v+"min", v+"max", 0, false );
}
mainController = mainPanel.getController();
setUpBottomPanel();
setUpTopPanel();
setUpCanvas();
addCanvasBorder();
if ( limitsPanel != null )
setUpLimitsPanel();
String loadDefault = (loadExampleButton == null)? "yes" : "no";
if (exampleStrings != null && exampleStrings.size() > 0 &&
! "no".equalsIgnoreCase(getParameter("LoadFirstExample",loadDefault)))
doLoadExample( (String)exampleStrings.elementAt(0) );
}
/**
* This method is called by mainPanel() to set up the display canvas and add it to the
* main panel. The canvas already exists in the member variable canvas when this
* method is called. This method adds only a set of axes to the canvas, sets the
* mainController to report errors using the canvas, and adds the canvas to the
* CENTER of the main panel. This method processes applet parameters "UsePanner",
* "CanvasColor", "UseMouseZoom", and "UseOffscreenCanvas". Typically, this
* method will be overridden in subclasses to add more Drawable items to the
* canvas. In this case, super.setUpCanvas() should be called first.
*/
protected void setUpCanvas() {
Color color;
color = getColorParam("CanvasColor");
if (color != null)
canvas.setBackground(color);
if (! "no".equalsIgnoreCase(getParameter("UsePanner", "no")) )
canvas.add(new Panner());
if ( ! "no".equalsIgnoreCase(getParameter("UseGrid", "no")) ) {
Grid g = new Grid();
color = getColorParam("GridColor");
if (color != null)
g.setColor(color);
canvas.add(g);
}
canvas.add(makeAxes());
if ( ! "no".equalsIgnoreCase(getParameter("UseMouseZoom", "no")) )
canvas.setHandleMouseZooms(true);
if ( "yes".equalsIgnoreCase(getParameter("UseOffscreenCanvas", "yes")) )
canvas.setUseOffscreenCanvas(true);
mainController.setErrorReporter(canvas);
mainPanel.add(canvas, BorderLayout.CENTER);
}
/**
* Construct a set of Axes, based on applet params "AxesColor", "AxesLightColor",
* "XLabel", "YLabel", "LabelColor".
*/
protected Axes makeAxes() {
Axes axes = new Axes();
Color color = getColorParam("AxesColor");
if (color != null)
axes.setAxesColor(color);
color = getColorParam("AxesLightColor");
if (color != null)
axes.setLightAxesColor(color);
String str = getParameter("XLabel");
if (str != null)
axes.setXLabel(str);
str = getParameter("YLabel");
axes.setYLabel(str);
color = getColorParam("LabelColor");
if (color != null)
axes.setLabelColor(color);
return axes;
}
/**
* This method is called by setUpMainPanel() to add a border to the canvas (since the border is typically
* the last thing that should be added, on top of anything else in the canvas. It processes the
* applet parameters "BorderWidth" and "BorderColor". If the border width is zero, no border is added.
* (The default width is 2.)
*/
protected void addCanvasBorder() {
int borderWidth;
double[] bw = getNumericParam("BorderWidth");
if (bw == null || bw.length == 0 || bw[0] > 25)
borderWidth = 2;
else
borderWidth = (int)Math.round(bw[0]);
if (borderWidth > 0)
canvas.add( new DrawBorder( getColorParam("BorderColor", Color.black), borderWidth ) );
}
/**
* This method checks the applet parameter "UseFunctionInput". If the value is anything but "no",
* then a panel is created that contains an ExpressionInput (stored in the member variable functionInput)
* and possibly a ComputeButton and lable for the input box. This panel is a JCMPanel using BorderLayout.
* In is stored in the member variable inputPanel and is added to the SOUTH position of the mainPanel.
* The method also processes applet parameters "Function", "UseComputeButton", "ComputeButtonName", and
* "FunctionLabel". The ComputeButton, if it exists, is stored in the member variable computeButton.
* Note that nothing at all is done by this method if the value of the applet parameter "UseFunctionInput" is no.
*
*/
protected void setUpBottomPanel() {
if ( "yes".equalsIgnoreCase(getParameter("UseFunctionInput", "yes")) ) {
String func = getParameter("Function");
String varName = xVar.getName();
if (func == null)
func = "abs(" + varName + " ) ^ " + varName;
functionInput = new ExpressionInput(func,parser);
inputPanel = new JCMPanel();
inputPanel.setBackground( getColorParam("PanelBackground", Color.lightGray) );
inputPanel.add(functionInput, BorderLayout.CENTER);
if ( "yes".equalsIgnoreCase(getParameter("UseComputeButton", "yes")) ) {
String cname = getParameter("ComputeButtonName", "New Function");
computeButton = new Button(cname);
inputPanel.add(computeButton, BorderLayout.EAST);
computeButton.addActionListener(this);
}
String flabel = getParameter("FunctionLabel");
if (flabel == null)
flabel = " f(" + varName + ") = ";
if ( ! "none".equalsIgnoreCase(flabel) )
inputPanel.add(new Label(flabel), BorderLayout.WEST);
mainPanel.add(inputPanel, BorderLayout.SOUTH);
functionInput.setOnUserAction(mainPanel.getController());
}
}
/**
* This method sets up the limit control panel and adds it to the main panel. The limit control panel
* already exists when this method is called and is stored in the member variable limitsPanel. The
* applet parameters "TwoLimitsColumns", "UseSetLimitsButton", "UseZoomButtons", "UseEqualizeButtons",
* "UseRestoreButton", "PanelBackground", and "LimitsOnLeft" are processed. The limits panel is
* set to report its errors using the display canvas.
*/
protected void setUpLimitsPanel() {
limitsPanel.addCoords(canvas);
if ( ! "no".equalsIgnoreCase(getParameter("TwoLimitsColumns", "no")) )
limitsPanel.setUseTwoColumnsIfPossible(true);
int buttons = 0;
if ( "yes".equalsIgnoreCase(getParameter("UseSetLimitsButton", "yes")) )
buttons |= LimitControlPanel.SET_LIMITS;
if ( ! "no".equalsIgnoreCase(getParameter("UseZoomButtons", "no")) )
buttons |= LimitControlPanel.ZOOM_IN | LimitControlPanel.ZOOM_OUT;
if ( ! "no".equalsIgnoreCase(getParameter("UseEqualizeButton", "no")) )
buttons |= LimitControlPanel.EQUALIZE;
if ( ! "no".equalsIgnoreCase(getParameter("UseRestoreButton", "no")) )
buttons |= LimitControlPanel.RESTORE;
if (buttons != 0)
limitsPanel.addButtons(buttons);
limitsPanel.setBackground( getColorParam("PanelBackground", Color.lightGray) );
if ( ! "yes".equalsIgnoreCase(getParameter("LimitsOnLeft", "no")))
mainPanel.add(limitsPanel, BorderLayout.EAST);
else
mainPanel.add(limitsPanel, BorderLayout.WEST);
limitsPanel.setErrorReporter(canvas);
}
 
/**
* This method is called by setUpMainPanel() to add a panel at the top of the applet.
* If there is an example menu, then the panel containing that menu is added to the
* NORTH position of the main panel. Otherwise, the value of the applet parameter
* named "PanelTitle" is checked. If this value exists, it is placed in a label at the top of the panel.
* The color of the text on the label is given by the valur of the applet parameter
* "TitleColor" (default is new Color(200,0,0)).
*/
protected void setUpTopPanel() {
if (exampleMenuPanel != null)
mainPanel.add(exampleMenuPanel, BorderLayout.NORTH);
else {
String title = getParameter("PanelTitle");
if (title != null) {
Label titleLabel = new Label(title, Label.CENTER);
titleLabel.setForeground( getColorParam("TitleForeground", new Color(200,0,0)) );
titleLabel.setBackground( getColorParam("TitleBackground", Color.lightGray) );
titleLabel.setFont( new Font("Serif", Font.PLAIN, 14) );
mainPanel.add(titleLabel, BorderLayout.NORTH);
}
}
}
/**
* This method processes applet parameters that specify examples for the applet and adds them
* to a menu of examples. If any examples exist, they are placed in a menu and a panel
* is created to hold the menu. The panel is stored in the instance variable exampleMenuPanel,
* which is used in the setUpTopPanel() method. This method is called by init(). If you don't
* want to process examples, you could override it to do nothing. If you do want to process
* examples, you have to override the doLoadExample() method to process a string from the menu.
* Examples are specified in applet parameters named "Example", "Example1", "Example2", ....
* The value should consist of a name for the example (which appears in the menu) followed by
* a ";" followed by a string that defines the example. The string that defines the example
* is passed to the doLoadExample() method when the user loads the example.
*/
protected void setUpExampleMenu() {
Vector strings = new Vector();
Vector names = new Vector();
int ct = 0;
String paramName = "Example";
String param = getParameter(paramName);
if (param == null) {
ct++;
paramName = "Example" + ct;
param = getParameter(paramName);
}
while (true) {
if (param == null)
break;
int pos = param.indexOf(';');
if (pos < 0) {
strings.addElement(param);
names.addElement(param);
}
else {
strings.addElement(param.substring(pos+1));
names.addElement(param.substring(0,pos));
}
ct++;
paramName = "Example" + ct;
param = getParameter(paramName);
}
if (strings.size() == 0)
return;
exampleStrings = strings;
exampleStrings.trimToSize();
exampleMenuPanel = new JCMPanel();
if ("yes".equalsIgnoreCase(getParameter("UseLoadButton","yes"))) {
loadExampleButton = new Button("Load Example: ");
loadExampleButton.setBackground(Color.lightGray);
loadExampleButton.addActionListener(this);
}
Component list;
if (names.size() == 1)
list = new Label( (String)names.elementAt(0), Label.CENTER );
else {
exampleMenu = new Choice();
list = exampleMenu;
for (int i = 0; i < names.size(); i++)
exampleMenu.add( (String)names.elementAt(i) );
if (loadExampleButton == null)
exampleMenu.addItemListener(this);
}
list.setBackground(Color.white);
exampleMenuPanel.add(list, BorderLayout.CENTER);
if (loadExampleButton != null)
exampleMenuPanel.add(loadExampleButton, BorderLayout.WEST);
}
 
/**
* This method is called by setUpMainPanel() to set up the parser to be used in the applet.
* When it is called, a parser already esists and is stored in the member variable
* named parser. This method configures the parser according to the values of
* the applet parameters "StandardFunctions", "Booleans", "OptionalStars", "OptionalParens",
* and "Factorials". It then looks for function defintions in applet parameters named
* "Define", "Define1", "Define2", ...., and if any are found the functions are added
* to the parser so that they can be used in expressions. A function definition can
* take a form such as "g(x)=x^2" or "fred(s,t) = 3*s + sin(t)", for example, or it
* can be defined by a table of values. A table function is defined using the
* syntax decribed in the parseTableFuncDef() method. Finally, a variable is
* created and added to the parser using the value of the applet param "Variable",
* with "x" as the default variable name.
*/
protected void setUpParser() {
if ( "yes".equalsIgnoreCase(getParameter("StandardFunctions", "yes")) )
parser.addOptions(Parser.STANDARD_FUNCTIONS);
if ( "yes".equalsIgnoreCase(getParameter("Booleans", "yes")) )
parser.addOptions(Parser.BOOLEANS);
if ( ! "no".equalsIgnoreCase(getParameter("OptionalStars", "no")) )
parser.addOptions(Parser.OPTIONAL_STARS);
if ( ! "no".equalsIgnoreCase(getParameter("OptionalParens", "no")) )
parser.addOptions(Parser.OPTIONAL_PARENS);
if ( ! "no".equalsIgnoreCase(getParameter("Factorials", "no")) )
parser.addOptions(Parser.FACTORIAL);
if ( "yes".equalsIgnoreCase(getParameter("Summations", "yes")) )
parser.add(new SummationParser());
String str = getParameter("Define");
if (str != null)
define(str);
int ct = 1;
while (true) {
str = getParameter("Define" + ct);
if (str == null)
break;
define(str);
ct++;
}
xVar = new Variable( getParameter("Variable", "x") );
parser.add( xVar );
}
/**
* This method is called when the user loads an example from the example menu (if any).
* The parameter is the string that defines the example. By default, this method does
* nothhing. It should be overridden to load the example.
*/
protected void doLoadExample(String example) {
}
/**
* This method, which is empty in the GenericGraphApplet class, can be defined in a subclass
* to set default values for applet params that are different from the ones provided in
* this class. The method should create a new HashTable, assign it to the instance
* variable parameterDefaults, and then add name/value pairs to the hash table. This
* method is called at the very beginning of the init() method.
*/
protected void setUpParameterDefaults() {
}
/**
* Override the standard applet method getParameter(String) so that when no param value
* is provided in the applet tag, and if parameterDefaults is non-null, it will check for a value
* the parameterDefaults. (The parameterDefaults instance variable can be defined in the
* setUpParameterDefaults() method.)
*/
public String getParameter(String paramName) {
String val = super.getParameter(paramName);
if (val == null && parameterDefaults != null)
val = (String)parameterDefaults.get(paramName);
return val;
}
/**
* Get the value of an applet parameter, but return a default if the value is null.
*
* @param paramName The name of the applet parameter.
* @param defaultValue The value to be returned if getParameter(paramName) is null.
*/
protected String getParameter(String paramName, String defaultValue) {
String val = getParameter(paramName);
return val == null ? defaultValue : val;
}
/**
* Get The value of an applet parameter that consists of a list of numbers.
* The parameter value, if any, is parsed and returned as array of double values.
* The numbers can be separated by commas, spaces, tabs, or semicolons. If there
* is a parse error, null is returned.
*/
protected double[] getNumericParam(String paramName) {
return getNumericParam(paramName, null);
}
 
/**
* Get The value of an applet parameter that consists of a list of numbers.
* The parameter value, if any, is parsed and returned as array of double values.
* The numbers can be separated by commas, spaces, tabs, or semicolons.
*
* @param paramName The name of the applet parameter.
* @param defaultValue The value to be returned if getParameter(paramName) is null or is not a valid list of numbers.
*/
protected double[] getNumericParam(String paramName, double[] defaults) {
String data = getParameter(paramName);
if (data == null)
return defaults;
StringTokenizer tokenizer = new StringTokenizer(data," \t,;");
int count = tokenizer.countTokens();
if (count == 0)
return defaults;
double[] numbers = new double[count];
for (int i = 0; i < count; i++) {
try {
Double d = new Double(tokenizer.nextToken());
numbers[i] = d.doubleValue();
}
catch (NumberFormatException e) {
return defaults;
}
}
return numbers;
}
/**
* Get The value of an applet parameter that specifies a color. The color can be specfied
* as a list of three numbers in the range 0 to 255 or by one of the standard color names
* ("black", "red", "blue", "green", "yellow", "cyan", "magenta", "gray", "darkgray",
* "lightgray", "pink", "orange", "white"). Color names are not case sensitive. If
* the value of the applet parameter is null does not specify a legal color, then
* the return value is null.
*/
protected Color getColorParam(String data) {
return getColorParam(data,null);
}
/**
* Get The value of an applet parameter that specifies a color. The color can be specfied
* as a list of three numbers in the range 0 to 255 or by one of the standard color names
* ("black", "red", "blue", "green", "yellow", "cyan", "magenta", "gray", "darkgray",
* "lightgray", "pink", "orange", "white"). Color names are not case sensitive.
*
* @param paramName The name of the applet parameter.
* @param defaultColor The value to be returned if getParameter(paramName) is null or is not a valid color.
*/
protected Color getColorParam(String paramName, Color defaultColor) {
String data = getParameter(paramName);
if (data == null || data.trim().length() == 0)
return defaultColor;
data = data.trim();
if (Character.isLetter(data.charAt(0))) {
for (int i = 0; i < colorNames.length; i++)
if (data.equalsIgnoreCase(colorNames[i]))
return colors[i];
return defaultColor;
}
else {
double[] nums = getNumericParam(paramName,null);
if (nums == null || nums.length < 3)
return defaultColor;
if (nums[0] < 0 || nums[0] > 255 || nums[1] < 0 || nums[1] > 255 || nums[2] < 0 || nums[2] > 255)
return defaultColor;
return new Color((int)Math.round(nums[0]), (int)Math.round(nums[1]), (int)Math.round(nums[2]));
}
}
 
// ------------------ Implementation details --------------------------------
 
/**
* Releases the resources used by the display canvas when the applet is stopped.
*/
public void stop() {
if (canvas != null && frame == null)
canvas.releaseResources();
}
/**
* Closes the frame (if any) when the applet is destroyed.
*/
public synchronized void destroy() {
if (frame != null)
frame.dispose();
}
 
private Choice exampleMenu;
private Button loadExampleButton;
private Button launchButton;
private String launchButtonName;
private Frame frame;
private Vector exampleStrings;
private String[] colorNames = { "black", "red", "blue", "green", "yellow",
"cyan", "magenta", "gray", "darkgray",
"lightgray", "pink", "orange", "white" };
private Color[] colors = { Color.black, Color.red, Color.blue, Color.green, Color.yellow,
Color.cyan, Color.magenta, Color.gray, Color.darkGray,
Color.lightGray, Color.pink, Color.orange, Color.white };
private void define(String str) {
// Parse a function definition string from one of the applet parameters named
// "Define", "Define1", "Define2", ...
String funcDef = str;
String name, def;
String[] paramNames;
int pos;
try {
pos = funcDef.indexOf("=");
if (pos < 0)
throw new ParseError("Missing \"=\"", null);
def = funcDef.substring(pos+1).trim();
funcDef = funcDef.substring(0,pos);
if (def.toLowerCase().startsWith("table")) {
name = funcDef;
pos = name.indexOf("(");
if (pos > 0)
name = name.substring(0,pos).trim();
TableFunction tf = parseTableFuncDef(def);
tf.setName(name);
parser.add(tf);
}
else {
pos = funcDef.indexOf("(");
if (pos < 0)
throw new ParseError("Missing \"(\"", null);
name = funcDef.substring(0,pos).trim();
if (name.length() == 0)
throw new ParseError("Missing function name", null);
funcDef = funcDef.substring(pos+1);
pos = funcDef.indexOf(")");
if (pos < 0)
throw new ParseError("Missing \")\"", null);
funcDef = funcDef.substring(0,pos).trim();
if (funcDef.length() == 0)
throw new ParseError("Missing parameter names", null);
StringTokenizer toks = new StringTokenizer(funcDef,",");
int ct = toks.countTokens();
paramNames = new String[ct];
for (int i = 0; i < ct; i++)
paramNames[i] = toks.nextToken();
new ExpressionFunction(name, paramNames, def, parser);
}
}
catch (ParseError e) {
throw new IllegalArgumentException("Error parsing function \"" + str + "\":" + e.getMessage());
}
}
/**
* Create a TableFunction from a string. The string can start with the word "table",
* which is ignored. The next item can optionally be one of the table styles "smooth",
* "linear", or "step". The default is "smooth". Then values must be specified. If the
* next word is "intervals", it can be followed by numbers giving the number of
* intervals, the minumum x, and the maximum x, and the y-values for up to (intervals+1) points
* evenly distributed between xmin and xmax (unassigned y-values will be zero).
* If no data is specified, a table function with
* 6 intervals between xmin = -5 and xmax = 5 and all y-values zero is created.
* If "intervals" is not specified, the
* remaining items are numbers giving pairs of (x,y)-values. Items can be separated
* spaces, tabs, and commas. A ParseError will be thrown if the data is illegal.
*/
protected TableFunction parseTableFuncDef(String def) {
try {
TableFunction func = new TableFunction();
StringTokenizer toks = new StringTokenizer(def, " \t,");
String tok = null;
if (toks.hasMoreTokens()) {
tok = toks.nextToken();
if (tok.equalsIgnoreCase("table") && toks.hasMoreTokens())
tok = toks.nextToken();
}
if ("step".equalsIgnoreCase(tok)) {
func.setStyle(TableFunction.STEP);
if (toks.hasMoreTokens())
tok = toks.nextToken();
}
else if ("linear".equalsIgnoreCase(tok)) {
func.setStyle(TableFunction.PIECEWISE_LINEAR);
if (toks.hasMoreTokens())
tok = toks.nextToken();
}
else if ("smooth".equalsIgnoreCase(tok) && toks.hasMoreTokens()) {
if (toks.hasMoreTokens())
tok = toks.nextToken();
}
boolean useIntervals = "intervals".equalsIgnoreCase(tok);
if (useIntervals && toks.hasMoreTokens())
tok = toks.nextToken();
double[] nums = new double[toks.countTokens() + 1];
try {
nums[0] = (new Double(tok)).doubleValue();
}
catch (NumberFormatException e) {
throw new ParseError("Unexpected token \"" + tok + "\".",null);
}
try {
for (int i = 1; i < nums.length; i++)
nums[i] = (new Double(toks.nextToken())).doubleValue();
}
catch (NumberFormatException e) {
throw new ParseError("Illegal number.", null);
}
if (useIntervals) {
int ct = (nums.length == 0)? 6 : (int)Math.round(nums[0]);
if (ct < 1 || ct > 500)
ct = 6;
double xmin = (nums.length < 2)? -5 : nums[1];
double xmax = (nums.length < 3)? xmin + 10 : nums[2];
if (xmax <= xmin)
throw new ParseError("xmax in table must be greater than xmin", null);
func.addIntervals(ct,xmin,xmax);
for (int i = 3; i < nums.length && (i-3) <= ct; i++) {
if (i-3 < ct)
func.setY(i-3,nums[i]);
}
}
else {
if (nums.length < 4)
throw new ParseError("At least two points must be provided for table function.", null);
if (nums.length % 2 == 1)
throw new ParseError("Can't define an table function with an odd number of values.", null);
for (int i = 0; i < nums.length/2; i++) {
func.addPoint(nums[2*i],nums[2*i+1]);
}
}
return func;
}
catch (Exception e) {
throw new ParseError("Error while parsing table function: " + e.getMessage(), null);
}
}
/**
* Respond when user clicks a button; not meant to be called directly.
*/
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == computeButton && computeButton != null)
mainController.compute();
else if (source == launchButton && launchButton != null)
doLaunchButton();
else if (source == loadExampleButton && exampleStrings != null) {
if (exampleStrings.size() == 1)
doLoadExample( (String)exampleStrings.elementAt(0) );
else
doLoadExample( (String)exampleStrings.elementAt(exampleMenu.getSelectedIndex()) );
}
}
/**
* Respond when user chooses an example from the example menu. (This will only
* happen if the param UseLoadButton is not set to "yes".)
*/
public void itemStateChanged(ItemEvent evt) {
if (evt.getSource() == exampleMenu)
doLoadExample( (String)exampleStrings.elementAt(exampleMenu.getSelectedIndex()) );
}
private synchronized void doLaunchButton() {
launchButton.setEnabled(false);
if (frame == null) {
frame = new Frame(frameTitle);
mainPanel = new JCMPanel();
try {
setUpMainPanel();
frame.add(mainPanel, BorderLayout.CENTER);
}
catch (Throwable e) {
System.out.println("Error while opening window:");
e.printStackTrace();
TextArea message = new TextArea("An error occurred while setting up this window:\n\n");
message.append(e.toString());
frame.add(message, BorderLayout.CENTER);
}
frame.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
frame.dispose();
}
public void windowClosed(WindowEvent evt) {
frameClosed();
}
} );
double[] frameSize = getNumericParam("FrameSize");
if (frameSize == null || frameSize.length < 2 || frameSize[0] < 100
|| frameSize[0] > 800 || frameSize[1] < 100 || frameSize[1] > 600)
frame.setSize(defaultFrameSize[0], defaultFrameSize[1]);
else
frame.setSize((int)Math.round(frameSize[0]), (int)Math.round(frameSize[1]));
frame.setLocation(50,50);
frame.show();
launchButton.setLabel("Close Window");
launchButton.setEnabled(true);
}
else {
frame.dispose();
}
}
private synchronized void frameClosed() {
frame = null;
launchButton.setLabel(launchButtonName);
launchButton.setEnabled(true);
mainPanel = null;
canvas = null;
limitsPanel = null;
inputPanel = null;
exampleMenuPanel = null;
loadExampleButton = null;
computeButton = null;
parser = null;
}
} // end class GenericGraphApplet
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/SilentParametric.java
0,0 → 1,487
/* jm.evers 10/2009
 
This is just a copy of Parametric.java ; added a param "showAll"
<param name="showAll" value="0/no"> will show the graph and no input controls
Any other values will revert to Parametric.java behaviour.
The evalues used to generate the parametric figure are however
still easy to be read by pupils looking at the page source...
example:
<html>
<body>
<applet archive="./jcm.jar" code="SilentParametric.class" width="640" height="360">
<param name="showAll" value="no"><!-- yes will give user inputs -->
<param name="FrameTitle" value="Parametric Curves">
<param name="UseGrid" value="yes">
<param name="Limits" value="-1.5,1.5,-1.5,1.5">
<param name="UseMouseZoom" value="no">
<param name="UsePanner" value="no">
<param name="UseFunctionInput" value="no">
<param name="UseParamInputs" value="no">
<param name="UseRestoreButton" value="yes">
<param name="UseEqualizeButton" value="yes">
<param name="SetLimitsButton" value="yes">
<param name="UseZoomButtons" value="yes">
 
<param name="LoopStyle" value="2"><!-- 0,1,2 0=once,1=restart,2=back and forth-->
<param name="File" value="http://localhost/test.data">
<!--
or define functions through params:
<param name="Function" value="sin(1/2*t)">
<param name="Function2" value="sin(2*t)">
-->
<param name="FunctionLabel" value="x(t)">
<param name="FunctionLabel2" value="y(t)">
<param name="TracerIntervals" value="150">
<param name="ParameterMin" value="0">
<param name="ParameterMax" value="2*pi/(1/2)">
<param name="PanelBackground" value="255 235 245">
<param name="UseComputeButton" value="no">
<param name="TwoLimitsColumns" value="no">
<param name="UseLimitsPanel" value="no">
<param namr="Insets" value="no">
<param name="BackgroundColor" value="255 235 245">
</applet>
</body>
</html>
*/
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
// The ParametricCurve applet is a configurable applet that displays a parametric
// curve defined by two functions of a parameter t. There can be a "Tracer" button
// on the applet. When the user clicks this button, a crosshair is moved along
// the curve from beginning to end.
 
import java.awt.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import java.util.Hashtable;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
import java.net.*;
import java.io.*;
 
 
public class SilentParametric extends GenericGraphApplet {
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private Function xFunc,yFunc; // The functions that are graphed.
private ParametricCurve graph; // The graph of the function.
private Animator tracer; // for tracing the curve by moving a crosshair along it
private Crosshair crosshair; // Crosshair used for tracing the graph
private VariableInput tMin,tMax; // for inputting limits on t
private VariableInput tIntervals; // for inutting the number of intervals into which the t-range is divided
private ExpressionInput functionInput2; // for inputting yFunc; xFunc is input in functionInput
public String tMaxString="2";
public String tMinString="-2";
protected void setUpParameterDefaults() {
parameterDefaults = new Hashtable();
parameterDefaults.put("TwoLimitsColumns", "yes");
parameterDefaults.put("Variable","t");
parameterDefaults.put("XName","x"); // we need this so that xmin and xmax boxes are labeled correctly;
// without it, the name would come from the variable name, t, instead of x
parameterDefaults.put("FunctionLabel", " " + getParameter("XName") + "(" + getParameter("Variable") + ") = ");
parameterDefaults.put("FunctionLabel2", " " + getParameter("YName","y") + "(" + getParameter("Variable") + ") = ");
}
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
super.setUpCanvas(); // Do the common setup: Add the axes and
 
// When setUpCanvas is called, the function inputs already exist, if they are
// to be used, since they are created in setUpBopttomPanel(), which is called
// before setUpCanvas(). If functionInput exists, add a graph of the functions
// from functionInput and functionInput2 to the canvas. If not, create a graph
// of the functions specified by the parameters named "Function" and "Function2".
if (functionInput != null) {
xFunc = functionInput.getFunction(xVar);
yFunc = functionInput2.getFunction(xVar);
}
else {
String xFuncDef = " cos(" + xVar.getName() + ") + cos(3*" + xVar.getName() + ")";
String yFuncDef = " sin(4*" + xVar.getName() + ") - sin(2*" + xVar.getName() + ")";
String file = getParameter("File");
// jm.evers begin
if(file != null){
//System.out.println("fetching data from "+file);
String newdata="";
try{ newdata = load(file);
// scheme: function1,function2,min,max
StringTokenizer t = new StringTokenizer(newdata, ",");
if(t.countTokens() != 4) {System.out.println("scheme is: function1,function2,min,max");}
else {
xFuncDef = t.nextToken();
yFuncDef = t.nextToken();
tMinString = t.nextToken();
tMaxString = t.nextToken();
}
} catch(Exception e){System.out.println("Could not read data from "+file);}
}
else
{
xFuncDef = getParameter("Function", xFuncDef);
yFuncDef = getParameter("Function2", yFuncDef);
}
// jm.evers end
Function f = new SimpleFunction( parser.parse(xFuncDef), xVar );
xFunc = new WrapperFunction(f);
f = new SimpleFunction( parser.parse(yFuncDef), xVar );
yFunc = new WrapperFunction(f);
}
graph = new ParametricCurve(xFunc,yFunc);
Color color = getColorParam("CurveColor");
if (color != null)
graph.setColor(color);
// if inputs are desired to control the parameter on the curve, set them up here
if ("no".equalsIgnoreCase(getParameter("UseParamInputs","yes"))) {
tMin = new VariableInput(xVar.getName() + "Start",tMinString);
tMax = new VariableInput(xVar.getName() + "End",tMaxString);
tIntervals = new VariableInput("Intervals", getParameter("Intervals","500"));
tIntervals.setInputStyle(VariableInput.INTEGER);
tIntervals.setMin(1);
tIntervals.setMax(5000);
tMin.setOnUserAction(mainController);
tMax.setOnUserAction(mainController);
tIntervals.setOnUserAction(mainController);
graph.setTMin(tMin);
graph.setTMax(tMax);
graph.setIntervals(tIntervals);
// jm.evers begin
String s = getParameter("showAll");
boolean showAll=true;
if(s.equalsIgnoreCase("no") || s.equalsIgnoreCase("0")){showAll=false;}
// jm.evers end
if(showAll){
if (limitsPanel != null) {
// componets will be added to limitsPanel in setUpLimitsPanel()
mainController.add(tMin); // This is not done automatically, since they are in a limits panel
mainController.add(tMax);
mainController.add(tIntervals);
}
else {
JCMPanel ap = new JCMPanel(9,0);
ap.setBackground(getColorParam("PanelBackground", Color.lightGray));
ap.add(new Label(tMin.getName()));
ap.add(tMin);
ap.add(new Label());
ap.add(new Label(tMax.getName()));
ap.add(tMax);
ap.add(new Label());
ap.add(new Label(tIntervals.getName()));
ap.add(tIntervals);
ap.add(new Label());
mainPanel.add(ap,BorderLayout.EAST);
}
}
}
else {
try {
graph.setTMin( new Constant((new Double(tMinString)).doubleValue()) );
graph.setTMax( new Constant((new Double(tMaxString)).doubleValue()) );
graph.setIntervals( new Constant((new Double(getParameter("Intervals","500"))).doubleValue()) );
}
catch (NumberFormatException e) {
}
}
 
// If the applet is configured to have a tracer button, create it and add the crosshair to the canvas
 
if (! "no".equalsIgnoreCase( getParameter("UseTracer","yes") ) ) {
tracer = new Animator();
String loopstyle=getParameter("LoopStyle");
if(loopstyle != null){
if(loopstyle.equals("0")){tracer.setLoopStyle(0);}
else
if(loopstyle.equals("1")){tracer.setLoopStyle(1);}
else
if(loopstyle.equals("2")){tracer.setLoopStyle(2);}
else
tracer.setLoopStyle(2);
}
tracer.setMin(graph.getTMin());
tracer.setMax(graph.getTMax());
tracer.setUndefinedWhenNotRunning(true);
tracer.setStartButtonName("Trace Curve!");
double[] d = getNumericParam("TracerIntervals");
int ints;
if (d == null || d.length != 1)
ints = 100;
else
ints = (int)Math.round(d[0]);
if (ints <= 0)
tracer.setIntervals(graph.getIntervals());
else
tracer.setIntervals(ints);
Variable v = tracer.getValueAsVariable();
crosshair = new Crosshair( new ValueMath(xFunc,v), new ValueMath(yFunc,v) );
crosshair.setLineWidth(3);
crosshair.setColor(getColorParam("CrosshairColor",Color.gray));
canvas.add(crosshair);
if (inputPanel != null) {
inputPanel.add(tracer,BorderLayout.WEST);
}
else if (limitsPanel == null) {
Panel p = new Panel();
p.add(tracer);
mainPanel.add(p,BorderLayout.SOUTH);
}
// if inputPanel is null but limitsPanel is not null, the tracer will be
// added to the limit control panel in setUpLimitsPanel()
}
 
canvas.add(graph); // Finally, add the graph to the canvas.
 
} // end setUpCanvas()
 
protected void setUpLimitsPanel() {
super.setUpLimitsPanel();
if (limitsPanel != null && tMin != null) { // add parameter inputs to limits panel
limitsPanel.addComponentPair(tMin,tMax);
limitsPanel.addComponent(tIntervals);
}
if (inputPanel == null && tracer != null && limitsPanel != null) {
limitsPanel.addComponent(tracer);
}
}
protected void setUpBottomPanel() { // override this to make a panel containing inputs for two functions
if ( ! "no".equalsIgnoreCase(getParameter("UseFunctionInput", "yes")) ) {
inputPanel = new JCMPanel();
inputPanel.setBackground( getColorParam("PanelBackground", Color.lightGray) );
Panel in = new JCMPanel(2,1);
inputPanel.add(in,BorderLayout.CENTER);
if ( ! "no".equalsIgnoreCase(getParameter("UseComputeButton", "yes")) ) {
String cname = getParameter("ComputeButtonName", "New Functions");
computeButton = new Button(cname);
inputPanel.add(computeButton, BorderLayout.EAST);
computeButton.addActionListener(this);
}
 
String varName = getParameter("Variable");
String def = getParameter("Function");
if (def == null)
def = "cos(" + varName + ") + cos(3*" + varName + ")";
functionInput = new ExpressionInput(def,parser);
String label = getParameter("FunctionLabel");
if ("none".equalsIgnoreCase(label))
in.add(functionInput);
else {
Panel p = new JCMPanel();
p.add(functionInput,BorderLayout.CENTER);
p.add( new Label(label), BorderLayout.WEST );
in.add(p);
}
def = getParameter("Function2");
if (def == null)
def = "sin(4*" + varName + ") - sin(2*" + varName + ")";
functionInput2 = new ExpressionInput(def,parser);
label = getParameter("FunctionLabel2");
if ("none".equalsIgnoreCase(label))
in.add(functionInput2);
else {
Panel p = new JCMPanel();
p.add(functionInput2,BorderLayout.CENTER);
p.add( new Label(label), BorderLayout.WEST );
in.add(p);
}
mainPanel.add(inputPanel, BorderLayout.SOUTH);
functionInput.setOnUserAction(mainController);
functionInput2.setOnUserAction(mainController);
}
}
 
protected void setUpMainPanel() { // Override to set up controller for tracer, if there is one
super.setUpMainPanel(); // Do the common setup
 
if ( tracer == null ) {
return; // If the applet is not configured to use a trace button, there is nothing to do.
}
 
Controller traceController = new Controller(); // A controler that will only recompute the crosshair position
traceController.add(tracer);
traceController.add(crosshair);
tracer.setOnChange(traceController);
 
} // end setUpMainPanel()
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the Parametric applet, the example string should contain
// two expression that defines the curve to be graphed, separated
// by a semicolon. This can optionally
// be followed by another semicolon and a list of four to seven numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// next three numbers specify the minimum value for the parameter, the
// maximum value, and the number of intervals into which the range of
// parameter values is divided.
if (tracer != null)
tracer.stop();
int pos = example.indexOf(";");
if (pos == -1)
return; // illegal example -- must have two functions
String example2 = example.substring(pos+1);
example = example.substring(0,pos);
pos = example2.indexOf(";");
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
 
if (pos > 0) {
// Get limits from example2 text.
String nums = example2.substring(pos+1);
example2 = example2.substring(0,pos);
StringTokenizer toks = new StringTokenizer(nums, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
}
if (toks.hasMoreTokens()) {
try {
double d = (new Double(toks.nextToken())).doubleValue();
if (tMin == null) {
graph.setTMin(new Constant(d));
if (tracer != null)
tracer.setMin(d);
}
else
tMin.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
double d = (new Double(toks.nextToken())).doubleValue();
if (tMax == null) {
graph.setTMax(new Constant(d));
if (tracer != null)
tracer.setMax(d);
}
else
tMax.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
if (tIntervals == null) {
if (tracer != null && tracer.getIntervals() == graph.getIntervals())
tracer.setIntervals(d);
graph.setIntervals(new Constant(d));
}
else
tIntervals.setVal(d);
}
catch (NumberFormatException e) {
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
functionInput2.setText(example2);
}
else {
// If there is no user input, set the function in the graph directly.
try {
Function f = new SimpleFunction( parser.parse(example), xVar );
((WrapperFunction)xFunc).setFunction(f);
Function g = new SimpleFunction( parser.parse(example2), xVar );
((WrapperFunction)yFunc).setFunction(g);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
 
public void stop() { // stop animator when applet is stopped
if (tracer != null)
tracer.stop();
super.stop();
}
 
// jm.evers; handy functions, not invented here :(
public static byte [] loadURL(URL url) throws IOException {
int bufSize = 1024 * 2;
byte [] buf = new byte[bufSize];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(url.openStream());
int n;
while ((n = in.read(buf)) > 0){
bout.write(buf, 0, n);
}
try { in.close(); } catch (Exception ignored) { }
return bout.toByteArray();
}
 
public static String loadFile(String fname) throws IOException {
byte[] bytes = loadURL(new URL("file:" + fname));
return new String(bytes);
}
 
public static String load(String fileOrURL) throws IOException {
try {
URL url = new URL(fileOrURL);
return new String(loadURL(url));}
catch (Exception e) { return loadFile(fileOrURL);}
}
}
// end class Parametric
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/ScatterPlotApplet.java
0,0 → 1,343
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
 
import edu.hws.jcm.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.draw.*;
 
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.applet.Applet;
 
/**
* A ScatterPlotApplet shows a scatter plot of data from a DataTableInput.
* The user can enter the data in a two-column table that is shown in
* the applet. It is also possible to configure the applet with a menu
* of file names. These files, which must be in the same directory as
* the Web page on which the applet appears, will appear in a menu.
* A file can contain data for the table, with two numbers per line.
* When the user loads the file, the data replaces the data in the table.
*/
 
public class ScatterPlotApplet extends Applet implements ActionListener {
 
private Frame frame; // If non-null, a separate window.
private String frameTitle; // Title for the separate window.
private Button launchButton; // If non-null, then clicking this buttons opens a separate window.
private String launchButtonName; // Name for the launch button.
private DataTableInput table; // The table for input of data.
private ScatterPlot scatterPlot; // The scatter plot of the data.
private DisplayCanvas canvas; // The DisplayCanvas on which the plot is drawn.
private Button loadFileButton; // When clicked, a data file is loaded.
private Choice fileMenu; // Pop-up menu containing names of functions.
private String[] fileNames; // Names of data files associated with menu entries.
private Controller mainController; // Controller from the main JCMPanel.
 
/**
* The init() method is called by the system to set up the applet.
* If the applet does not appear as a button, then init() creates the main panel of the applet
* and calls setUpMainPanel to set it up.
*/
public void init() {
frameTitle = getParameter("FrameTitle"); // Get title to be used for separate window, if any.
if (frameTitle == null) {
frameTitle = "Scatter Plots";
int pos = frameTitle.lastIndexOf('.');
if (pos > -1)
frameTitle = frameTitle.substring(pos+1);
}
setLayout(new BorderLayout());
int height = getSize().height;
launchButtonName = getParameter("LaunchButtonName");
if ( (height > 0 && height <= 50) || launchButtonName != null) {
// Use a separater window and only show a button in the applet.
if (launchButtonName == null)
launchButtonName = "Launch " + frameTitle;
launchButton = new Button(launchButtonName);
add(launchButton, BorderLayout.CENTER);
launchButton.addActionListener(this);
}
else {
// Show the main panel in the applet, not in a separate window.
add(makeMainPanel(), BorderLayout.CENTER);
}
}
 
/*
* Create the main panel of the applet.
*/
public Panel makeMainPanel() {
// Make the main panel
JCMPanel panel = new JCMPanel(2);
mainController = panel.getController();
panel.setBackground(new Color(0,0,180));
panel.setInsetGap(2);
setLayout(new BorderLayout());
// Make a DataInputTable with two columns
table = new DataTableInput(null, 2);
table.setColumnName(0, getParameter("ColumnName1", "X"));
table.setColumnName(1, getParameter("ColumnName2", "Y"));
table.setThrowErrors(true);
if ( "yes".equalsIgnoreCase(getParameter("ShowColumnTitles","yes")))
table.setShowColumnTitles(true);
if ( "yes".equalsIgnoreCase(getParameter("ShowRowNumbers","yes")))
table.setShowRowNumbers(true);
// Make input boxes for getting expressions that can include
// the variables associated with the table. Initially, the
// expressions are just the column names.
 
Parser parser = new Parser();
table.addVariablesToParser(parser);
ExpressionInput input1 = new ExpressionInput(table.getColumnName(0),parser);
input1.setOnUserAction(mainController);
ExpressionInput input2 = new ExpressionInput(table.getColumnName(1),parser);
input2.setOnUserAction(mainController);
// Make a scatter plot that graphs the first expressiong vs. the second expression.
 
scatterPlot = new ScatterPlot(table, input1.getExpression(), input2.getExpression());
if ( ! "yes".equalsIgnoreCase(getParameter("ShowRegressionLine","yes")))
scatterPlot.setShowRegressionLine(false);
if ( ! "yes".equalsIgnoreCase(getParameter("MissingValueIsError","yes")))
scatterPlot.setMissingValueIsError(false);
// Create the display canvas where the scater plot will be shown.
 
canvas = new DisplayCanvas();
canvas.add(new Axes());
canvas.add(scatterPlot);
mainController.setErrorReporter(canvas);
// A compute button to recompute everything.
ComputeButton computeButton = new ComputeButton("Update Display");
computeButton.setOnUserAction(mainController);
computeButton.setBackground(Color.lightGray);
// A menu of files that can be loaded. If no filenames are provided as
// applet parameters, then menu is null.
Panel menu = makefileMenu();
// Lay out the components in the applet.
JCMPanel inputPanel = null;
Panel bottom = null; //might not be a JCMPanel
if ( "yes".equalsIgnoreCase(getParameter("UseExpressionInputs","yes"))) {
inputPanel = new JCMPanel(1,2);
inputPanel.setBackground(Color.lightGray);
JCMPanel leftInput = new JCMPanel();
leftInput.add(new Label(" Plot: "), BorderLayout.WEST);
leftInput.add(input1, BorderLayout.CENTER);
inputPanel.add(leftInput);
JCMPanel rightInput = new JCMPanel();
rightInput.add(new Label(" versus: "), BorderLayout.WEST);
rightInput.add(input2, BorderLayout.CENTER);
inputPanel.add(rightInput);
bottom = new JCMPanel(new BorderLayout(12,3));
bottom.add(inputPanel, BorderLayout.CENTER);
bottom.add(computeButton, BorderLayout.EAST);
}
if ( scatterPlot.getShowRegressionLine() && "yes".equalsIgnoreCase(getParameter("ShowStats","yes")) ) {
// Make a display label to show some statistics about the data.
DisplayLabel dl = new DisplayLabel(
"Slope = #; Intercept = #; Correlation = #",
new Value[] { scatterPlot.getValueObject(ScatterPlot.SLOPE),
scatterPlot.getValueObject(ScatterPlot.INTERCEPT),
scatterPlot.getValueObject(ScatterPlot.CORRELATION) }
);
dl.setAlignment(Label.CENTER);
dl.setBackground(Color.lightGray);
dl.setForeground(new Color(200,0,0));
dl.setFont(new Font("Serif",Font.PLAIN,14));
if (bottom != null)
bottom.add(dl, BorderLayout.SOUTH);
else {
bottom = new JCMPanel(new BorderLayout(12,3));
bottom.add(dl, BorderLayout.CENTER);
bottom.add(computeButton, BorderLayout.EAST);
}
}
if (bottom == null) {
if (menu != null)
menu.add(computeButton, BorderLayout.EAST);
else {
bottom = new Panel();
bottom.add(computeButton);
}
}
panel.add(canvas, BorderLayout.CENTER);
panel.add(table, BorderLayout.WEST);
if (bottom != null)
panel.add(bottom, BorderLayout.SOUTH);
if (menu != null)
panel.add(menu, BorderLayout.NORTH);
else {
String title = getParameter("PanelTitle");
if (title != null) {
Label pt = new Label(title, Label.CENTER);
pt.setBackground(Color.lightGray);
pt.setForeground(new Color(200,0,0));
pt.setFont(new Font("Serif",Font.PLAIN,14));
panel.add(pt, BorderLayout.NORTH);
}
}
return panel;
} // end makeMainPanel()
private Panel makefileMenu() {
// If the applet tag contains params named "File", "File1", "File2", ..., use
// their values to make a file menu. If the value of the param contains a ";",
// then the first part, up to the ";", goes into the menu and the second part
// is the name of the file. If there is no ";", then the entire value is
// shown in the menu and is also used as the name of the file. The actual
// files must be in the same directory as the Web page that contains the applet.
Vector names = new Vector();
fileMenu = new Choice();
String file = getParameter("File");
int ct = 1;
if (file == null) {
file = getParameter("File1");
ct = 2;
}
while (file != null) {
file = file.trim();
int pos = file.indexOf(";");
String menuEntry;
if (pos == -1)
menuEntry = file;
else {
menuEntry = file.substring(0,pos).trim();
file = file.substring(pos+1).trim();
}
names.addElement(file);
fileMenu.add(menuEntry);
file = getParameter("File" + ct);
ct++;
}
if (names.size() == 0) {
fileMenu = null;
return null;
}
else {
fileNames = new String[names.size()];
for (int i = 0; i < names.size(); i++)
fileNames[i] = (String)names.elementAt(i);
Panel p = new Panel();
p.setBackground(Color.lightGray);
p.setLayout(new BorderLayout(5,5));
p.add(fileMenu,BorderLayout.CENTER);
loadFileButton = new Button("Load Data File: ");
loadFileButton.addActionListener(this);
p.add(loadFileButton,BorderLayout.WEST);
fileMenu.setBackground(Color.white);
return p;
}
}
private void doLoadFile(String name) {
// Load the file from the same directory as the Web page and put the data
// from the file into the table. The file should contain two numbers on
// each line.
InputStream in;
try {
URL url = new URL(getDocumentBase(), name);
in = url.openStream();
}
catch (Exception e) {
canvas.setErrorMessage(null,"Unable to open file named \"" + name + "\": " + e);
return;
}
Reader inputReader = new InputStreamReader(in);
try {
table.readFromStream(inputReader);
inputReader.close();
}
catch (Exception e) {
canvas.setErrorMessage(null,"Unable to get data from file \"" + name + "\": " + e.getMessage());
return;
}
mainController.compute();
}
 
/**
* Respond when user clicks a button; not meant to be called directly.
* This opens and closes the separate window.
*/
synchronized public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (loadFileButton != null && source == loadFileButton) {
doLoadFile( fileNames[fileMenu.getSelectedIndex()] );
}
else if (source == launchButton && launchButton != null) {
// Open or close separate frame.
launchButton.setEnabled(false);
if (frame == null) {
frame = new Frame(frameTitle);
frame.add(makeMainPanel());
frame.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
frame.dispose();
}
public void windowClosed(WindowEvent evt) {
frameClosed();
}
} );
frame.pack();
frame.setLocation(50,50);
frame.show();
launchButton.setLabel("Close Window");
launchButton.setEnabled(true);
}
else {
frame.dispose();
}
}
}
synchronized private void frameClosed() {
// respond when separate window closes.
frame = null;
launchButton.setLabel(launchButtonName);
launchButton.setEnabled(true);
}
/**
* Return the applet parameter with a given param name, but if no
* such applet param exists, return a default value instead.
*/
protected String getParameter(String paramName, String defaultValue) {
String val = getParameter(paramName);
return (val == null)? defaultValue : val;
}
} // end class ScatterPlotApplet
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/SimpleGraph.java
0,0 → 1,261
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
// The SimpleGraph applet is a configurable applet that displays the graph of
// a single function of one variable. Optionally, a point can be marked on
// the graph. The user can control the location of the point.
 
import java.awt.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
 
public class SimpleGraph extends GenericGraphApplet {
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private VariableInput xInput; // Contains the x-coordinate of the marked point.
 
private Function func; // The function that is graphed.
private Graph1D graph; // The graph of the function.
 
private DrawGeometric point; // An oval that marks the selected point on the graph.
private DrawGeometric vLine; // A line from the point to the x-axis.
private DrawGeometric hLine; // A line from the point to the y-axis.
 
 
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
super.setUpCanvas(); // Do the common setup: Add the axes and
 
// When setUpCanvas is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function".
if (functionInput != null)
func = functionInput.getFunction(xVar);
else {
String def = getParameter("Function", " abs(" + xVar.getName() + ") ^ " + xVar.getName());
Function f = new SimpleFunction( parser.parse(def), xVar );
func = new WrapperFunction(f);
}
graph = new Graph1D(func);
Color color = getColorParam("GraphColor");
if (color != null)
graph.setColor(color);
// If the applet is configured to mark a point on the graph, create the point and
// the lines from the point to the x- and y-axes and add them to the canvas before
// the graph. The properties of these objects have to be set later, in setUpMainPanel(),
// because the input objects that they depend on don't exist when this method is
// called. However, I want to add them to the canvas here so they will lie behind the
// graph and behind the border of the canvas (which is added after setUpCanvas() is
// executed).
 
if (! "no".equalsIgnoreCase( getParameter("ShowPoint","yes") ) ) {
vLine = new DrawGeometric();
hLine = new DrawGeometric();
point = new DrawGeometric();
canvas.add(vLine);
canvas.add(hLine);
canvas.add(point);
}
 
canvas.add(graph); // Finally, add the graph to the canvas.
 
} // end setUpCanvas()
 
protected void setUpMainPanel() { // Override to handle the point marked on the graph
super.setUpMainPanel(); // Do the common setup
 
if ( "no".equalsIgnoreCase( getParameter("ShowPoint","yes") ) ) {
return; // If the applet is not configured to show a point, there is nothing to do.
}
// Create two input objects, a VariableInput and a VariableSlider. The values of
// the two inputs will be synchronized with each other using a "Tie". The
// minimum and maximum values represented on the slider are given by the
// the minimum and maximum x-coordinates on the CoordinateRect. This will restrict
// the x-coodinate of the point that is marked on the graph to the range of
// x-values actually shown on the screen.
xInput = new VariableInput(); // An input box for the x-coord of the marked point
xInput.setInputStyle(VariableInput.REAL); // Allow only real numbers (not constant expressions)
CoordinateRect coords = canvas.getCoordinateRect();
VariableSlider xSlider = new VariableSlider( coords.getValueObject(CoordinateRect.XMIN), coords.getValueObject(CoordinateRect.XMAX) );
Value yValue = new ValueMath(func,xSlider); // Represents the y-value of the marked point.
DisplayLabel yDisplay = new DisplayLabel(" y = #", yValue); // Shows the y-value of the point
 
// Create a panel to contain the input objects.
JCMPanel panel = new JCMPanel(1,3);
panel.setBackground(getColorParam("PanelBackground",Color.lightGray));
JCMPanel subpanel = new JCMPanel();
String varName = getParameter("Variable","x");
subpanel.add(new Label(" " + varName + " = ", Label.CENTER), BorderLayout.WEST);
subpanel.add(xInput, BorderLayout.CENTER);
panel.add(xSlider);
panel.add(subpanel);
panel.add(yDisplay);
// If there is a functionInput box, then the SOUTH position of the mainPanel already contains
// the inputPanel that contains that box. If so, add the new panel to the SOUTH position of
// the inputPanel. (This is a good place, in general, to put extra input objects.)
// If there is no inputPanel, then the SOUTH position of the mainPanel is empty, so put
// the newly created panel there. Also, set the background color for the input panel from
// from the PanelBackground applet param. (This is already done for inputPanel, if it exists.)
if (inputPanel == null)
mainPanel.add(panel, BorderLayout.SOUTH);
else {
inputPanel.setBackground(getColorParam("PanelBackground",Color.lightGray));
inputPanel.add(panel, BorderLayout.SOUTH);
}
 
// Set up all the data for the point and the lines from the point to the axes.
// The objects where created in setUpCanvas() and added to the canvas.
 
hLine.setPoints(new Constant(0),yValue,xSlider,yValue);
hLine.setPoints(new Constant(0),yValue,xSlider,yValue);
point.setShape(DrawGeometric.CROSS);
point.setPoints(xSlider,yValue,5,5);
point.setLineWidth(3);
vLine.setPoints(xSlider,new Constant(0),xSlider,yValue);
Color c = getColorParam("LineColor", Color.lightGray);
vLine.setColor(c);
hLine.setColor(c);
c = getColorParam("DotColor", Color.gray);
point.setColor(c);
 
// Now, I have to set a Controller to respond to changes in the input objects.
// I could just use the mainController, but then the data for the graph would
// be recomputed whenever the user changes the x-coordinate of the marked point.
// For effieciency, I will use a separate Controller that only recomputes the
// data for the point (not the graph) when the inputs change.
Controller cc = new Controller();
 
xInput.setOnTextChange(cc); // cc responds when user types in the input box
xSlider.setOnUserAction(cc); // cc responds when the user drags the slider
coords.setOnChange(cc); // cc responds when the coordinate limits change;
// this is necessary because the minimum and
// maximum values on the slider have to be checked.
 
cc.add( xInput ); // Check whether the values have changed.
cc.add( xSlider );
 
cc.add( new Tie(xSlider,xInput) ); // synchronize values of input box and slider
 
cc.add( hLine ); // Recompute the values for the point and lines.
cc.add( vLine );
cc.add( point );
 
cc.add( yDisplay ); // Recompute the value displayed on the yDisplay label.
 
mainController.add(cc); // When the mainController recomputes (because function has
// been changed, all the stuff controlled by cc also has
// to be checked.
mainController.remove(canvas); // The mainController should not recompute the contents
// of the canvas (which it would do by default).
mainController.add(graph); // But the mainController should recompute the graph.
 
} // end setUpMainPanel()
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the SimpleGraph applet, the example string should contain
// an expression that defines the function to be graphed. This can optionally
// be followed by a semicoloon and a list of four or five numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// fifth number, if present, gives the x-coord of the marked point
// on the graph.
int pos = example.indexOf(";");
 
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
if (pos > 0) { // get limits from example text
String limitsText = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(limitsText, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
if (toks.countTokens() > 0 && xInput != null) {
// get x-coord of marked point from example text
try {
Double d = new Double(toks.nextToken());
xInput.setVal( d.doubleValue() );
}
catch (NumberFormatException e) {
}
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
// Also, in this case, func is a "WrapperFunction". Set the
// definition of that WrapperFunction to be the same as f
try {
Function f = new SimpleFunction( parser.parse(example), xVar );
((WrapperFunction)func).setFunction(f);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
 
 
} // end class SimpleGraph
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/MultiGraph.java
0,0 → 1,441
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
 
import java.awt.*;
import java.applet.Applet;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
// The MultiApplet can display the graphs of several functions, in different colors.
// By default, there is only one function, but you can configure the applet to
// use more than one function with applet params.
// The definitions of these functions can, optionally, use parameters whose
// values are controled by sliders at the bottom of the applet.
 
public class MultiGraph extends GenericGraphApplet {
 
 
private Vector sliders; // Elements of this vector are the VariableSlider
// objects that represent the parameter values.
// The sliders are created in the setUpParser() method.
private ExprIn[] inputs; // The function input boxes (or null if inputs aren't used)
private Graph1D[] graphs; // The graphs of the functions, in the case function input boxes are NOT used
private int functionCt; // Number of functions -- size of inputs or graphs array
private Color[] graphColors = { Color.magenta, new Color(0,180,0),
Color.red, new Color(0,200,200),
Color.orange, Color.gray, Color.blue, Color.pink };
 
 
private static class ColorPatch extends Canvas {
// a canvas with a preferred size
ColorPatch(Color c) {
setBackground(c);
}
public Dimension getPreferredSize() {
return new Dimension(25,10);
}
public void paint(Graphics g) {
g.drawRect(0,0,getSize().width-1,getSize().height-1);
}
}
private static class ExprIn extends ExpressionInput {
// Doesn't throw an error if empty, just sets function in graph to null
Graph1D graph; // Graph associated with this function input.
Function func; // The function of x defined by this graph.
ExprIn(String definition, Parser p, Graph1D g, Variable v) {
super(definition,p);
graph = g;
func = getFunction(v);
if (definition.trim().length() > 0)
graph.setFunction(func);
}
public void checkInput() { // (will be called during constructor -- hence the funny bit with checking if graphe is null)
if (!hasChanged)
return;
String text = getText().trim();
if (text.length() == 0) { // set graph's function to null so it doesn't have to do any computations.
if (graph != null)
graph.setFunction(null);
hasChanged = false;
}
else {
super.checkInput();
if (graph != null)
graph.setFunction(func);
}
}
}
 
protected void setUpParser() { // Override this to add VariableSliders to parser.
// Get the data for any sliders from applet params named "Parameter", "Parameter1", ...
// The sliders are created and the variables are added to the parser by the
// addParameter() method, which is defined below.
sliders = new Vector();
int ct = 0;
String param = getParameter("Parameter");
if (param == null) {
ct++;
param = getParameter("Parameter" + ct);
}
while (true) {
if (param == null)
break;
addParameter(param);
ct++;
param = getParameter("Parameter" + ct);
}
super.setUpParser(); // Call this last so function definitions
// in applet params can use the parameter names
} // end setUpParser()
 
 
private void addParameter(String data) {
// Create a VariableSlider from the information in name and add it to the
// Vector of sliders. The data must contain the name of the variable
// associated with the slider. The name can be followed by a ";" and up to
// three numbers. (If there is no ";", a space after the name will do.)
// The numbers can be separated by commas, spaces, or tabs. The first
// number gives the minimum value on the slider, the second gives the maximum,
// and the third gives the initial value of the slider variable.
 
double min = -5, max = 5, val = 0; // min, max, and value for slider
 
data = data.trim();
int pos = data.indexOf(';');
if (pos < 0)
pos = data.indexOf(' ');
String name; // The name of the parameter
 
if (pos < 0) {
// If there is no space or ";", the data is just the name of the variable.
name = data;
}
else {
// Get the name from the front of the data, then look for min, max, and val.
String nums = data.substring(pos+1);
name = data.substring(0,pos).trim();
StringTokenizer toks = new StringTokenizer(nums," ,\t");
try {
if (toks.hasMoreElements())
min = (new Double(toks.nextToken())).doubleValue();
if (toks.hasMoreElements())
max = (new Double(toks.nextToken())).doubleValue();
if (toks.hasMoreElements())
val = (new Double(toks.nextToken())).doubleValue();
}
catch (NumberFormatException e) {
min = -5;
max = 5;
val = 0;
}
}
// Create the slider, adding the associated variable to the parser, and set its value.
VariableSlider slide = new VariableSlider(name, new Constant(min), new Constant(max), parser);
slide.setVal(val);
sliders.addElement(slide); // Save the slider in the array of sliders for later use.
} // end setUpParser();
private void getColors() { // get graph colors from color parameters, if any.
Vector vec = new Vector();
int ct = 0;
Color c = getColorParam("GraphColor");
if (c == null) {
ct++;
c = getColorParam("GraphColor" + ct);
}
while (true) {
if (c == null)
break;
vec.addElement(c);
ct++;
c = getColorParam("GraphColor" + ct);
}
if (vec.size() > 0) {
graphColors = new Color[vec.size()];
for (int i = 0; i < vec.size(); i++)
graphColors[i] = (Color)vec.elementAt(i);
}
}
private Vector getFunctions() { // Read applet parms "Function", "Funcion1", ...
// Return a vector containing the function definition strings
Vector functions = new Vector();
int ct = 0;
String c = getParameter("Function");
if (c == null) {
ct++;
c = getParameter("Function" + ct);
}
while (true) {
if (c == null)
break;
functions.addElement(c);
ct++;
c = getParameter("Function" + ct);
}
if (functions.size() == 0)
functions.addElement( " abs( " + xVar.getName() + ") ^ " + xVar.getName() );
double[] d = getNumericParam("FunctionCount");
if (d == null || d.length == 0 || d[0] <= 0.5)
functionCt = functions.size();
else {
functionCt = (int)Math.round(d[0]);
if (functionCt < functions.size()) { // use number of functions specified as functionCt
functionCt = functions.size();
}
else { // make extra empty functions to bring total up to functionCt
int extra = functionCt - functions.size();
for (int i = 0; i < extra; i++)
functions.addElement("");
}
}
return functions;
}
 
private Panel makeFunctionInput(Vector functions, int funcNum) {
// make input box for specified function
// also adds the input box to the inputs[] array
Graph1D graph = new Graph1D();
graph.setColor(graphColors[funcNum % graphColors.length]);
ExprIn in = new ExprIn((String)functions.elementAt(funcNum),parser,graph,xVar);
in.setOnUserAction(mainController);
JCMPanel p = new JCMPanel();
p.add(in,BorderLayout.CENTER);
String name;
if (functions.size() > 1)
name = " " + getParameter("FunctionName","f") + (funcNum+1) + "(" + xVar.getName() + ") = ";
else
name = " " + getParameter("FunctionName","f") + "(" + xVar.getName() + ") = ";
p.add(new Label(name), BorderLayout.WEST);
if (graphColors.length > 1 && functions.size() > 1)
p.add(new ColorPatch( graphColors[funcNum % graphColors.length] ), BorderLayout.EAST);
inputs[funcNum] = in;
return p;
}
 
 
protected void setUpBottomPanel() {
// Overridden to create an appropriate input panel
 
// Create a panel holding all the function inputs and
// sliders, with a display label for each slider to show its value.
boolean funcInput = "yes".equalsIgnoreCase(getParameter("UseFunctionInput","yes"));
if ( funcInput && "yes".equalsIgnoreCase(getParameter("UseComputeButton", "yes")) ) { // make the compute button
String cname = getParameter("ComputeButtonName", "New Functions");
computeButton = new Button(cname);
computeButton.addActionListener(this);
}
Panel firstPanel = null; // To help find a place for the compute button
getColors();
Vector functions = getFunctions();
 
if (!funcInput && sliders.size() == 0) // nothing to put in the input panel
return;
 
JCMPanel panel = new JCMPanel();
if (! "no".equalsIgnoreCase(getParameter("TwoInputColumns","no")))
panel.setLayout(new GridLayout(0,2,12,3));
else
panel.setLayout(new GridLayout(0,1,3,3));
panel.setBackground(getColorParam("PanelBackground", Color.lightGray));
 
if (funcInput) { // make an input box for each function and add it to the panel
inputs = new ExprIn[functions.size()];
for (int i = 0; i < functions.size(); i++) {
Panel p = makeFunctionInput(functions,i);
if (firstPanel == null)
firstPanel = p;
panel.add(p);
}
}
else { // just make graphs from the function definition strings.
graphs = new Graph1D[functions.size()];
for (int i = 0; i < functions.size(); i++) {
graphs[i] = new Graph1D();
graphs[i].setColor(graphColors[ i % graphColors.length ]);
String def = ((String)functions.elementAt(i)).trim();
if (def.length() > 0) { // if the definition string is empty, leave graph's function undefined
Function f = new SimpleFunction( parser.parse(def), xVar );
graphs[i].setFunction(f);
}
}
}
 
for (int i = 0; i < sliders.size(); i++) { // add sliders to the input panel
JCMPanel p = new JCMPanel();
VariableSlider slide = (VariableSlider)sliders.elementAt(i);
p.add(slide, BorderLayout.CENTER);
p.add(new DisplayLabel(" " + slide.getName() + " = # ", new Value[] { slide.getVariable() } ),
BorderLayout.EAST);
panel.add(p);
slide.setOnUserAction(mainController);
}
if (computeButton != null) { // find a place for the compute button!
if (functions.size() == 1)
firstPanel.add(computeButton, BorderLayout.EAST);
else if (limitsPanel == null) {
Panel p = new Panel();
p.add(computeButton);
panel.add(p);
}
// otherwise, add it at the end of setUpLimitPanel();
}
mainPanel.add(panel, BorderLayout.SOUTH);
} // end setUpBottomPanel()
 
protected void setUpLimitsPanel() { // add compute button if it hasn't been put somewhere else
super.setUpLimitsPanel();
if (limitsPanel != null && computeButton != null && functionCt != 1)
limitsPanel.addComponent(computeButton);
}
 
protected void setUpCanvas() { // Overridden to add the graph to the canvas.
 
super.setUpCanvas(); // Do the default setup.
 
// set up bottom panel has already been defined
// add the graphs to the canvas
if (graphs != null) {
for (int i = 0; i < graphs.length; i++)
canvas.add(graphs[i]);
}
else {
for (int i = 0; i < inputs.length; i++)
canvas.add(inputs[i].graph);
}
 
} // end setUpCanvas
 
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the FamiliesOfGraphs applet, the example string should contain
// an expression that defines the function to be graphed. This must
// be followed by a semicolon and list of zero or more numbers.
// Then there is another semicolon and one or more function definitions,
// separated by semicolons. You can have as many function
// definitions as you have functions in your applet setup.
// (Note that having the numbers before the
// functions is different from the format of examples in all the
// other configurable applets. This is to allow more than one function.) Note that even if you leave
// out the numbers, you still need two semicolons. The list of numbers has the following meaning:
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// remaining numbers occur in groups of three. Each group give the maximum, minimum, and value of a parameters that was defined
// with the "Parameter", "Parameter1", ... applet params.
int pos = example.indexOf(";");
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
 
if (pos > 0) {
// Get limits from example text.
String nums = example.substring(0,pos);
example = example.substring(pos+1);
StringTokenizer toks = new StringTokenizer(nums, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
}
int i = 0;
while (i < sliders.size() && toks.hasMoreElements()) {
// Look for a value for the i-th slider.
try {
double min = (new Double(toks.nextToken())).doubleValue();
double max = (new Double(toks.nextToken())).doubleValue();
double d = (new Double(toks.nextToken())).doubleValue();
VariableSlider slider = ((VariableSlider)sliders.elementAt(i));
slider.setMin(new Constant(min));
slider.setMax(new Constant(max));
slider.setVal(d);
}
catch (Exception e) {
}
i++;
}
}
// Set up the example data and recompute everything.
StringTokenizer toks = new StringTokenizer(example,";");
int funcNum = 0;
while (funcNum < functionCt) {
if (toks.hasMoreElements()) { // define the function using definition from example text
String def = toks.nextToken();
if (graphs != null) {
try {
graphs[funcNum].setFunction(new SimpleFunction( parser.parse(def), xVar ));
}
catch (ParseError e) {
graphs[funcNum].setFunction(null);
}
}
else
inputs[funcNum].setText(def);
}
else { // function is undefined
if (graphs != null)
graphs[funcNum].setFunction(null);
else
inputs[funcNum].setText("");
}
funcNum++;
}
 
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
} // end class MultiGraph
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/DataPlotApplet.java
0,0 → 1,353
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
import edu.hws.jcm.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.draw.*;
//
import java.util.StringTokenizer;
import edu.hws.jcm.awt.*;
import edu.hws.jcm.functions.*;
//
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.applet.Applet;
 
/**
* A DataPlotApplet shows a data plot of data from a DataTableInput.
* The user can enter the data in a two-column table that is shown in
* the applet. It is also possible to configure the applet with a menu
* of file names. These files, which must be in the same directory as
* the Web page on which the applet appears, will appear in a menu.
* A file can contain data for the table, with two numbers per line.
* When the user loads the file, the data replaces the data in the table.
*/
 
public class DataPlotApplet extends GenericGraphApplet implements ActionListener {
 
private Frame frame; // If non-null, a separate window.
private String frameTitle; // Title for the separate window.
private Button launchButton; // If non-null, then clicking this buttons opens a separate window.
private String launchButtonName; // Name for the launch button.
private DataTableInput table; // The table for input of data.
private DataPlot dataPlot; // The data plot of the data.
private DisplayCanvas canvas; // The DisplayCanvas on which the plot is drawn.
private Button loadFileButton; // When clicked, a data file is loaded.
private Choice fileMenu; // Pop-up menu containing names of functions.
private String[] fileNames; // Names of data files associated with menu entries.
private Controller mainController; // Controller from the main JCMPanel.
 
/**
* The init() method is called by the system to set up the applet.
* If the applet does not appear as a button, then init() creates the main panel of the applet
* and calls setUpMainPanel to set it up.
*/
public void init() {
 
frameTitle = getParameter("FrameTitle"); // Get title to be used for separate window, if any.
if (frameTitle == null) {
frameTitle = "Data Plots";
int pos = frameTitle.lastIndexOf('.');
if (pos > -1)
frameTitle = frameTitle.substring(pos+1);
}
setLayout(new BorderLayout());
int height = getSize().height;
launchButtonName = getParameter("LaunchButtonName");
if ( (height > 0 && height <= 50) || launchButtonName != null) {
// Use a separater window and only show a button in the applet.
if (launchButtonName == null)
launchButtonName = "Launch " + frameTitle;
launchButton = new Button(launchButtonName);
add(launchButton, BorderLayout.CENTER);
launchButton.addActionListener(this);
}
else {
// Show the main panel in the applet, not in a separate window.
add(makeMainPanel(), BorderLayout.CENTER);
}
}
 
/*
* Create the main panel of the applet.
*/
public Panel makeMainPanel() {
// Make the main panel
 
JCMPanel panel = new JCMPanel(2);
mainController = panel.getController();
panel.setBackground(new Color(0,0,180));
panel.setInsetGap(2);
setLayout(new BorderLayout());
// Make a DataInputTable with two columns
table = new DataTableInput(null, 2);
table.setColumnName(0, getParameter("ColumnName1", "X"));
table.setColumnName(1, getParameter("ColumnName2", "Y"));
table.setThrowErrors(true);
if ( "yes".equalsIgnoreCase(getParameter("ShowColumnTitles","yes")))
table.setShowColumnTitles(true);
if ( "yes".equalsIgnoreCase(getParameter("ShowRowNumbers","yes")))
table.setShowRowNumbers(true);
// Make input boxes for getting expressions that can include
// the variables associated with the table. Initially, the
// expressions are just the column names.
 
Parser parser = new Parser();
table.addVariablesToParser(parser);
ExpressionInput input1 = new ExpressionInput(table.getColumnName(0),parser);
input1.setOnUserAction(mainController);
ExpressionInput input2 = new ExpressionInput(table.getColumnName(1),parser);
input2.setOnUserAction(mainController);
// Make a data plot that graphs the first expressiong vs. the second expression.
 
dataPlot = new DataPlot(table, input1.getExpression(), input2.getExpression());
if ( ! "yes".equalsIgnoreCase(getParameter("ShowRegressionLine","yes")))
dataPlot.setShowRegressionLine(false);
if ( ! "yes".equalsIgnoreCase(getParameter("MissingValueIsError","yes")))
dataPlot.setMissingValueIsError(false);
// Create the display canvas where the scater plot will be shown.
 
 
canvas = new DisplayCanvas();
Axes axes = new Axes();
canvas.add(axes);
// canvas.add(new Axes());
canvas.add(dataPlot);
mainController.setErrorReporter(canvas);
//evers
 
if ( ! "no".equalsIgnoreCase(getParameter("UseGrid", "no")) ) {
Grid g = new Grid();
canvas.add(g);
}
// A compute button to recompute everything.
ComputeButton computeButton = new ComputeButton("Vernieuwen");
computeButton.setOnUserAction(mainController);
computeButton.setBackground(Color.lightGray);
// A menu of files that can be loaded. If no filenames are provided as
// applet parameters, then menu is null.
Panel menu = makefileMenu();
// Lay out the components in the applet.
JCMPanel inputPanel = null;
Panel bottom = null; //might not be a JCMPanel
if ( "yes".equalsIgnoreCase(getParameter("UseExpressionInputs","yes"))) {
inputPanel = new JCMPanel(1,2);
inputPanel.setBackground(Color.lightGray);
JCMPanel leftInput = new JCMPanel();
leftInput.add(new Label(" Plot: "), BorderLayout.WEST);
leftInput.add(input1, BorderLayout.CENTER);
inputPanel.add(leftInput);
JCMPanel rightInput = new JCMPanel();
rightInput.add(new Label(" versus: "), BorderLayout.WEST);
rightInput.add(input2, BorderLayout.CENTER);
inputPanel.add(rightInput);
bottom = new JCMPanel(new BorderLayout(12,3));
bottom.add(inputPanel, BorderLayout.CENTER);
bottom.add(computeButton, BorderLayout.EAST);
}
if ( dataPlot.getShowRegressionLine() && "yes".equalsIgnoreCase(getParameter("ShowStats","yes")) ) {
// Make a display label to show some statistics about the data.
DisplayLabel dl = new DisplayLabel(
"Helling = #; Intercept = #; Correlatie = #",
new Value[] { dataPlot.getValueObject(DataPlot.SLOPE),
dataPlot.getValueObject(DataPlot.INTERCEPT),
dataPlot.getValueObject(DataPlot.CORRELATION) }
);
dl.setAlignment(Label.CENTER);
dl.setBackground(Color.lightGray);
dl.setForeground(new Color(200,0,0));
dl.setFont(new Font("Serif",Font.PLAIN,14));
if (bottom != null)
bottom.add(dl, BorderLayout.SOUTH);
else {
bottom = new JCMPanel(new BorderLayout(12,3));
bottom.add(dl, BorderLayout.CENTER);
bottom.add(computeButton, BorderLayout.EAST);
}
}
if (bottom == null) {
if (menu != null)
menu.add(computeButton, BorderLayout.EAST);
else {
bottom = new Panel();
bottom.add(computeButton);
}
}
panel.add(canvas, BorderLayout.CENTER);
panel.add(table, BorderLayout.WEST);
if (bottom != null)
panel.add(bottom, BorderLayout.SOUTH);
if (menu != null)
panel.add(menu, BorderLayout.NORTH);
else {
String title = getParameter("PanelTitle");
if (title != null) {
Label pt = new Label(title, Label.CENTER);
pt.setBackground(Color.lightGray);
pt.setForeground(new Color(200,0,0));
pt.setFont(new Font("Serif",Font.PLAIN,14));
panel.add(pt, BorderLayout.NORTH);
}
}
return panel;
} // end makeMainPanel()
private Panel makefileMenu() {
// If the applet tag contains params named "File", "File1", "File2", ..., use
// their values to make a file menu. If the value of the param contains a ";",
// then the first part, up to the ";", goes into the menu and the second part
// is the name of the file. If there is no ";", then the entire value is
// shown in the menu and is also used as the name of the file. The actual
// files must be in the same directory as the Web page that contains the applet.
Vector names = new Vector();
fileMenu = new Choice();
String file = getParameter("File");
int ct = 1;
if (file == null) {
file = getParameter("File1");
ct = 2;
}
while (file != null) {
file = file.trim();
int pos = file.indexOf(";");
String menuEntry;
if (pos == -1)
menuEntry = file;
else {
menuEntry = file.substring(0,pos).trim();
file = file.substring(pos+1).trim();
}
names.addElement(file);
fileMenu.add(menuEntry);
file = getParameter("File" + ct);
ct++;
}
if (names.size() == 0) {
fileMenu = null;
return null;
}
else {
fileNames = new String[names.size()];
for (int i = 0; i < names.size(); i++)
fileNames[i] = (String)names.elementAt(i);
Panel p = new Panel();
p.setBackground(Color.lightGray);
p.setLayout(new BorderLayout(5,5));
p.add(fileMenu,BorderLayout.CENTER);
loadFileButton = new Button("datafile: ");
loadFileButton.addActionListener(this);
p.add(loadFileButton,BorderLayout.WEST);
fileMenu.setBackground(Color.white);
return p;
}
}
private void doLoadFile(String name) {
// Load the file from the same directory as the Web page and put the data
// from the file into the table. The file should contain two numbers on
// each line.
InputStream in;
try {
URL url = new URL(getDocumentBase(), name);
in = url.openStream();
}
catch (Exception e) {
canvas.setErrorMessage(null,"Unable to open file named \"" + name + "\": " + e);
return;
}
Reader inputReader = new InputStreamReader(in);
try {
table.readFromStream(inputReader);
inputReader.close();
}
catch (Exception e) {
canvas.setErrorMessage(null,"Unable to get data from file \"" + name + "\": " + e.getMessage());
return;
}
mainController.compute();
}
 
/**
* Respond when user clicks a button; not meant to be called directly.
* This opens and closes the separate window.
*/
synchronized public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (loadFileButton != null && source == loadFileButton) {
doLoadFile( fileNames[fileMenu.getSelectedIndex()] );
}
else if (source == launchButton && launchButton != null) {
// Open or close separate frame.
launchButton.setEnabled(false);
if (frame == null) {
frame = new Frame(frameTitle);
frame.add(makeMainPanel());
frame.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
frame.dispose();
}
public void windowClosed(WindowEvent evt) {
frameClosed();
}
} );
frame.pack();
frame.setLocation(50,50);
frame.show();
launchButton.setLabel("Sluit Venster");
launchButton.setEnabled(true);
}
else {
frame.dispose();
}
}
}
synchronized private void frameClosed() {
// respond when separate window closes.
frame = null;
launchButton.setLabel(launchButtonName);
launchButton.setEnabled(true);
}
/**
* Return the applet parameter with a given param name, but if no
* such applet param exists, return a default value instead.
*/
protected String getParameter(String paramName, String defaultValue) {
String val = getParameter(paramName);
return (val == null)? defaultValue : val;
}
} // end class DataPlotApplet
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/EpsilonDelta.java
0,0 → 1,325
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
import java.awt.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
/**
* An applet for exploring the epsilon-delta definition of a limit.
*/
public class EpsilonDelta extends GenericGraphApplet {
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private VariableInput xInput;
private VariableInput epsilonInput;
private VariableInput deltaInput;
private VariableInput limitInput;
private VariableSlider xSlider;
private VariableSlider epsilonSlider;
private VariableSlider deltaSlider;
private VariableSlider limitSlider;
 
private Controller subController;
private Variable xValue, limitValue;
 
private Function func; // The function that is graphed.
private Graph1D graph; // The graph of the function.
 
protected void setUpBottomPanel() {
super.setUpBottomPanel();
subController = new Controller();
mainController.add(subController);
JCMPanel inputs = new JCMPanel(3);
subController.add(inputs);
inputs.setBackground(getColorParam("PanelBackground", Color.lightGray));
if (inputPanel == null)
mainPanel.add(inputs,BorderLayout.SOUTH);
else
inputPanel.add(inputs,BorderLayout.SOUTH);
JCMPanel left = new JCMPanel(0,1,2);
JCMPanel right = new JCMPanel(0,1,2);
JCMPanel middle = new JCMPanel(0,1,2);
inputs.add(middle, BorderLayout.CENTER);
inputs.add(left, BorderLayout.WEST);
inputs.add(right, BorderLayout.EAST);
double[] a = getNumericParam("AValue");
double avalue = (a == null || a.length < 1)? 0 : a[0];
if ("yes".equalsIgnoreCase(getParameter("UseAInput","yes"))) {
xSlider = new VariableSlider();
xInput = new VariableInput();
xInput.setVal(avalue);
xSlider.setVal(avalue);
xInput.setThrowErrors(false);
subController.add(new Tie(xSlider, xInput));
xValue = xInput.getVariable();
left.add(new Label("limit at a = ",Label.RIGHT));
middle.add(xSlider);
right.add(xInput);
}
else {
xValue = new Variable();
xValue.setVal(avalue);
}
a = getNumericParam("LimitValue");
double Lvalue = (a == null || a.length < 1)? 1 : a[0];
if ("yes".equalsIgnoreCase(getParameter("UseLimitInput","yes"))) {
limitSlider = new VariableSlider();
limitInput = new VariableInput();
limitInput.setVal(Lvalue);
limitSlider.setVal(Lvalue);
limitInput.setThrowErrors(false);
subController.add(new Tie(limitSlider, limitInput));
limitValue = limitInput.getVariable();
left.add(new Label(" test limit L = ",Label.RIGHT));
middle.add(limitSlider);
right.add(limitInput);
}
else {
limitValue = new Variable();
limitValue.setVal(Lvalue);
}
a = getNumericParam("EpsilonValue");
double epsilonValue = (a == null || a.length < 1)? 0.25 : a[0];
epsilonSlider = new VariableSlider(new Constant(0), new Constant(2));
epsilonInput = new VariableInput();
epsilonInput.setVal(epsilonValue);
epsilonSlider.setVal(epsilonValue);
epsilonInput.setThrowErrors(false);
subController.add(new Tie(epsilonSlider, epsilonInput));
left.add(new Label("epsilon = ", Label.RIGHT));
middle.add(epsilonSlider);
right.add(epsilonInput);
a = getNumericParam("DeltaValue");
double deltaValue = (a == null || a.length < 1)? 1 : a[0];
deltaSlider = new VariableSlider(new Constant(0), new Constant(2));
deltaInput = new VariableInput();
deltaInput.setVal(deltaValue);
deltaSlider.setVal(deltaValue);
deltaInput.setThrowErrors(false);
subController.add(new Tie(deltaSlider, deltaInput));
left.add(new Label("delta = ", Label.RIGHT));
middle.add(deltaSlider);
right.add(deltaInput);
}
 
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
// When setUpCanvas is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function".
if (functionInput != null)
func = functionInput.getFunction(xVar);
else {
String def = getParameter("Function", "abs(" + xVar.getName() + ") ^ " + xVar.getName());
Function f = new SimpleFunction( parser.parse(def), xVar );
func = new WrapperFunction(f);
}
graph = new Graph1D(func);
graph.setColor(getColorParam("GraphColor", Color.black));
Value xMinusDelta = new ValueMath(xValue, deltaInput, '-');
Value xPlusDelta = new ValueMath(xValue, deltaInput, '+');
Value limitMinusEpsilon = new ValueMath(limitValue, epsilonInput, '-');
Value limitPlusEpsilon = new ValueMath(limitValue, epsilonInput, '+');
Value xmin = canvas.getCoordinateRect().getValueObject(CoordinateRect.XMIN);
Value xmax = canvas.getCoordinateRect().getValueObject(CoordinateRect.XMAX);
Value ymin = canvas.getCoordinateRect().getValueObject(CoordinateRect.YMIN);
Value ymax = canvas.getCoordinateRect().getValueObject(CoordinateRect.YMAX);
if (xSlider != null) {
xSlider.setMin(xmin);
xSlider.setMax(xmax);
}
if (limitSlider != null) {
limitSlider.setMin(ymin);
limitSlider.setMax(ymax);
}
DrawGeometric deltaBox = new DrawGeometric(DrawGeometric.RECT_ABSOLUTE, xMinusDelta, ymin, xPlusDelta, ymax);
deltaBox.setFillColor(new Color(225,255,225));
deltaBox.setLineWidth(0);
DrawGeometric epsilonBox = new DrawGeometric(DrawGeometric.RECT_ABSOLUTE, xmin, limitMinusEpsilon, xmax, limitPlusEpsilon);
epsilonBox.setFillColor(new Color(255,230,230));
epsilonBox.setLineWidth(0);
DrawGeometric overlap = new DrawGeometric(DrawGeometric.RECT_ABSOLUTE, xMinusDelta, limitMinusEpsilon, xPlusDelta,limitPlusEpsilon);
overlap.setFillColor(new Color(255,255,225));
overlap.setColor(Color.yellow);
DrawGeometric xLine = new DrawGeometric(DrawGeometric.LINE_ABSOLUTE, xValue, ymin, xValue, ymax);
xLine.setColor(new Color(130,255,130));
DrawGeometric limitLine = new DrawGeometric(DrawGeometric.LINE_ABSOLUTE, xmin, limitValue, xmax, limitValue);
limitLine.setColor(new Color(255,150,150));
canvas.add(deltaBox);
canvas.add(epsilonBox);
canvas.add(overlap);
canvas.add(xLine);
canvas.add(limitLine);
DrawString ds = new DrawString("a = #\nL = #\nf(a) = #", DrawString.TOP_LEFT,
new Value[] { xValue, limitValue, new ValueMath(func,xValue) });
ds.setBackgroundColor(Color.white);
ds.setFrameWidth(1);
subController.add(ds);
subController.add(deltaBox);
subController.add(epsilonBox);
subController.add(overlap);
subController.add(xLine);
subController.add(limitLine);
mainController.remove(canvas);
mainController.add(graph);
canvas.getCoordinateRect().setOnChange(mainController);
deltaSlider.setOnUserAction(subController);
epsilonSlider.setOnUserAction(subController);
deltaInput.setOnTextChange(subController);
epsilonInput.setOnTextChange(subController);
subController.add(deltaSlider);
subController.add(epsilonSlider);
subController.add(deltaInput);
subController.add(epsilonInput);
if (xInput != null) {
xSlider.setOnUserAction(subController);
xInput.setOnTextChange(subController);
subController.add(xSlider);
subController.add(xInput);
}
if (limitInput != null) {
limitSlider.setOnUserAction(subController);
limitInput.setOnTextChange(subController);
subController.add(limitSlider);
subController.add(limitInput);
}
 
super.setUpCanvas(); // Do the common setup: Add the axes, grid, etc
 
canvas.add(graph);
canvas.add(ds);
} // end setUpCanvas()
 
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// After the function definition, there can be a semicolon and
// up to ten numbers (numbers can be separated by spaces and/or commas).
// The first four numbers specify the limits on the coordinate rect.
// .
int pos = example.indexOf(";");
 
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
if (pos > 0) { // get limits from example text
String limitsText = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(limitsText, " ,");
double nums[] = new double[toks.countTokens()];
for (int i = 0; i < nums.length; i++) {
try {
nums[i] = (new Double(toks.nextToken())).doubleValue();
}
catch (Exception e) {
nums[i] = Double.NaN;
}
}
for (int i = 0; i < 4; i++)
if (nums.length >= i && !Double.isNaN(nums[i]))
limits[i] = nums[i];
if (nums.length > 4 && !Double.isNaN(nums[4]))
xValue.setVal( nums[4] );
else
xValue.setVal((limits[0]+limits[1])/2);
if (nums.length > 5 && !Double.isNaN(nums[5]))
limitValue.setVal( nums[5] );
else
limitValue.setVal((limits[0]+limits[1])/2);
if (nums.length > 8 && !Double.isNaN(nums[8]))
epsilonSlider.setMax( new Constant(nums[8]) );
else
epsilonSlider.setMax(new Constant(Math.abs(limits[2]-limits[3])/2));
if (nums.length > 9 && !Double.isNaN(nums[9]))
deltaSlider.setMax( new Constant(nums[9]) );
else
deltaSlider.setMax(new Constant(Math.abs(limits[0]-limits[1])/2));
if (nums.length > 6 && !Double.isNaN(nums[6])) {
epsilonInput.setVal( nums[6] );
epsilonSlider.setVal( nums[6] );
}
else {
epsilonInput.setVal(Math.abs(limits[2]-limits[3])/8);
epsilonSlider.setVal(Math.abs(limits[2]-limits[3])/8);
}
if (nums.length > 7 && !Double.isNaN(nums[7])) {
deltaInput.setVal( nums[7] );
deltaSlider.setVal( nums[7] );
}
else {
deltaInput.setVal(Math.abs(limits[0]-limits[1])/8);
deltaSlider.setVal(Math.abs(limits[0]-limits[1])/8);
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
// Also, in this case, func is a "WrapperFunction". Set the
// definition of that WrapperFunction to be the same as f
try {
Function f = new SimpleFunction( parser.parse(example), xVar );
((WrapperFunction)func).setFunction(f);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
 
} // end class EpsilonDelta
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/FamiliesOfGraphs.java
0,0 → 1,282
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
// An applet belonging to the class FamiliesOfGraphs displays a graph
// of a function that can depend on one or more parameters. The values of
// the parameters are controlled by the user using sliders at the bottom of
// the applet.
 
 
import java.awt.*;
import java.applet.Applet;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
 
public class FamiliesOfGraphs extends GenericGraphApplet {
 
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private Function func; // The function that is graphed.
private Graph1D graph; // The graph of the function.
private Vector sliders; // Elements of this vector are the VariableSlider
// objects that represent the parameter values.
// The sliders are created in the setUpParser() method.
 
 
 
protected void setUpParser() { // Override this to add VariableSliders to parser.
// Get the data for the sliders from applet params named "Parameter", "Parameter1", ...
// The sliders are created and the variables are added to the parser by the
// addParameter() method, which is defined below.
sliders = new Vector();
int ct = 0;
String param = getParameter("Parameter");
if (param == null) {
ct++;
param = getParameter("Parameter" + ct);
}
while (true) {
if (param == null)
break;
addParameter(param);
ct++;
param = getParameter("Parameter" + ct);
}
// If no parameters were specified in applet params, create one with name "k".
if (sliders.size() == 0)
addParameter("k");
super.setUpParser(); // Call this last so function definitions
// in applet params can use the parameter names
// that have just been added to the parser
// (even though it's probably not a good idea).
// Note that this also defines the independent variable,
// whose name is given by the applet param "Variable"
// and which is referred to as xVar in this program.
VariableSlider slide = (VariableSlider)sliders.elementAt(0);
String def = getParameter("Function", "sin(" + slide.getName() + " * " + xVar.getName() + ")");
parameterDefaults = new Hashtable(); // I want to set a different default value for
// the "Function" applet param.
parameterDefaults.put("Function",def);
} // end setUpParser()
 
 
private void addParameter(String data) {
// Create a VariableSlider from the information in name and add it to the
// Vector of sliders. The data must contain the name of the variable
// associated with the slider. The name can be followed by a ";" and up to
// three numbers. (If there is no ";", a space after the name will do.)
// The numbers can be separated by commas, spaces, or tabs. The first
// number gives the minimum value on the slider, the second gives the maximum,
// and the third gives the initial value of the slider variable.
 
double min = -5, max = 5, val = 0; // min, max, and value for slider
 
data = data.trim();
int pos = data.indexOf(';');
if (pos < 0)
pos = data.indexOf(' ');
String name; // The name of the parameter
 
if (pos < 0) {
// If there is no space or ";", the data is just the name of the variable.
name = data;
}
else {
// Get the name from the front of the data, then look for min, max, and val.
String nums = data.substring(pos+1);
name = data.substring(0,pos).trim();
StringTokenizer toks = new StringTokenizer(nums," ,\t");
try {
if (toks.hasMoreElements())
min = (new Double(toks.nextToken())).doubleValue();
if (toks.hasMoreElements())
max = (new Double(toks.nextToken())).doubleValue();
if (toks.hasMoreElements())
val = (new Double(toks.nextToken())).doubleValue();
}
catch (NumberFormatException e) {
min = -5;
max = 5;
val = 0;
}
}
// Create the slider, adding the associated variable to the parser, and set its value.
VariableSlider slide = new VariableSlider(name, new Constant(min), new Constant(max), parser);
slide.setVal(val);
sliders.addElement(slide); // Save the slider in the array of sliders for later use.
} // end setUpParser();
 
 
protected void setUpBottomPanel() { // Overridden to add the sliders at the bottom of the applet.
 
super.setUpBottomPanel(); // Do the default setup.
 
// Create a panel holding all the sliders, with a display label for each slider to show its value.
 
JCMPanel sliderPanel = new JCMPanel();
sliderPanel.setLayout(new GridLayout(0,1,3,3));
sliderPanel.setBackground(getColorParam("PanelBackground", Color.lightGray));
for (int i = 0; i < sliders.size(); i++) {
JCMPanel p = new JCMPanel();
VariableSlider slide = (VariableSlider)sliders.elementAt(i);
p.add(slide, BorderLayout.CENTER);
p.add(new DisplayLabel(" " + slide.getName() + " = # ", new Value[] { slide.getVariable() } ),
BorderLayout.EAST);
sliderPanel.add(p);
slide.setOnUserAction(mainController);
}
// If there is a functionInput box, then the SOUTH position of the mainPanel already contains
// the inputPanel that contains that box. If so, add the new panel to the SOUTH position of
// the inputPanel. (This is a good place, in general, to put extra input objects.)
// If there is no inputPanel, then the SOUTH position of the mainPanel is empty, so put
// the newly created panel there.
if (inputPanel != null)
inputPanel.add(sliderPanel, BorderLayout.SOUTH);
else
mainPanel.add(sliderPanel, BorderLayout.SOUTH);
 
} // end setUpBottomPanel()
 
 
 
protected void setUpCanvas() { // Overridden to add the graph to the canvas.
 
super.setUpCanvas(); // Do the default setup.
 
// When setUpCanvas() is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function" (or use sin(k*x) if none is specified).
 
if (functionInput != null)
func = functionInput.getFunction(xVar);
else {
String def = getParameter("Function"); // default value is set in setUpParser()
func = new SimpleFunction( parser.parse(def), xVar );
}
 
// Create a graph of the function and add it to the canvas.
graph = new Graph1D(func);
graph.setColor(getColorParam("GraphColor", Color.magenta));
canvas.add(graph);
 
} // end setUpCanvas
 
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the FamiliesOfGraphs applet, the example string should contain
// an expression that defines the function to be graphed. This can optionally
// be followed by a semicolon and a list of four or more numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// remaining numbers occur in groups of three and specify the minimumn,
// maximum and values of the parameters, in the
// same order that they were encountered in the setUpParser() method.
int pos = example.indexOf(";");
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
 
if (pos > 0) {
// Get limits from example text.
String nums = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(nums, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
}
int i = 0;
while (i < sliders.size() && toks.hasMoreElements()) {
// Look for a value for the i-th slider.
try {
double min = (new Double(toks.nextToken())).doubleValue();
double max = (new Double(toks.nextToken())).doubleValue();
double d = (new Double(toks.nextToken())).doubleValue();
VariableSlider slider = ((VariableSlider)sliders.elementAt(i));
slider.setMin(new Constant(min));
slider.setMax(new Constant(max));
slider.setVal(d);
}
catch (Exception e) {
}
i++;
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
try {
func = new SimpleFunction( parser.parse(example), xVar );
graph.setFunction(func);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
} // end class FamiliesOfGraphs
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/SilentAnimatedGraph.java
0,0 → 1,343
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
// An applet belonging to the class AnimatedGraph displays a graph
// of a function that can depend on a parameter. The value of the
// parameter can be "animated" so that it ranges from one value ot
// another over a sequence of frames.
 
import java.awt.*;
import java.applet.Applet;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
import java.net.*;
import java.io.*;
 
public class SilentAnimatedGraph extends GenericGraphApplet {
 
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private Function func; // The function that is graphed.
private Graph1D graph; // The graph of the function.
private Animator animator; // Animates the graph
private Variable kVar; // The parameter variable
private VariableInput kMin, kMax, kIntervals; // min, max, and number of intervals for the animator. Might be null.
 
 
protected void setUpParser() { // Override this to create the animator and add its variable to the parser.
int options = Animator.START_STOP_BUTTON | Animator.PAUSE_BUTTON | Animator.LOOP_CHOICE;
if ( ! "no".equalsIgnoreCase(getParameter("UseNextAndPrev","yes")) )
options |= Animator.PREV_BUTTON | Animator.NEXT_BUTTON;
animator = new Animator(options);
kVar = animator.getValueAsVariable( getParameter("Parameter","k") );
parser.add(kVar);
super.setUpParser();
 
parameterDefaults = new Hashtable();
String defaultFunction = xVar.getName() + " / (" + kVar.getName() + " - " + xVar.getName() + "^2)";
parameterDefaults.put("Function",defaultFunction);
if (! "no".equalsIgnoreCase(getParameter("UseAnimatorInputs")))
parameterDefaults.put("TwoLimitsColumns","yes"); // change default if we need space for animator inputs
} // end setUpParser()
 
protected void setUpBottomPanel() { // Overridden to add the sliders at the bottom of the applet.
 
super.setUpBottomPanel(); // Do the default setup.
// If there is a functionInput box, then the SOUTH position of the mainPanel already contains
// the inputPanel that contains that box. If so, add the animator to the SOUTH position of
// the inputPanel. (This is a good place, in general, to put extra input objects.)
// If there is no inputPanel, then the SOUTH position of the mainPanel is empty, so put
// the animator there.
if (inputPanel != null)
inputPanel.add(animator, BorderLayout.SOUTH);
else
mainPanel.add(animator, BorderLayout.SOUTH);
 
} // end setUpBottomPanel()
 
 
 
protected void setUpCanvas() { // Overridden to add the graph to the canvas and do other chores.
 
super.setUpCanvas(); // Do the default setup.
 
// When setUpCanvas() is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function" (or use sin(k*x) if none is specified).
if (functionInput != null){
func = functionInput.getFunction(xVar);
}
else
{//jm.evers 1/2010 load a file from url
String def;
try{
String data = getParameter("File");
def = load(data);
def = def.replaceAll("\\n","");
System.out.println("loaded "+def);
}
catch(Exception e){
System.out.println("could not load parameter File");
def = getParameter("Function"); // default value is set in setUpParser()
}
func = new SimpleFunction( parser.parse(def), xVar );
}
 
graph = new Graph1D(func);
graph.setColor(getColorParam("GraphColor", Color.magenta));
canvas.add(graph);
// Set up the min, max, and intervals property of the animator
if (! "no".equalsIgnoreCase(getParameter("UseAnimatorInputs"))) {
kMin = new VariableInput(kVar.getName() + "Start",getParameter("ParameterMin","-2"));
kMax = new VariableInput(kVar.getName() + "End",getParameter("ParameterMax","2"));
kIntervals = new VariableInput("Intervals", getParameter("Intervals","25"));
kIntervals.setInputStyle(VariableInput.INTEGER);
kIntervals.setMin(1);
kIntervals.setMax(1000);
kMin.setOnUserAction(mainController);
kMax.setOnUserAction(mainController);
kIntervals.setOnUserAction(mainController);
animator.setMin(kMin);
animator.setMax(kMax);
animator.setIntervals(kIntervals);
if (limitsPanel != null) {
// componets will be added to limitsPanel in setUpLimitsPanel()
mainController.add(kMin); // This is not done automatically, since they are in a limits panel
mainController.add(kMax);
mainController.add(kIntervals);
}
else {
JCMPanel ap = new JCMPanel(9,0);
ap.setBackground(getColorParam("PanelBackground", Color.lightGray));
ap.add(new Label(kMin.getName()));
ap.add(kMin);
ap.add(new Label());
ap.add(new Label(kMax.getName()));
ap.add(kMax);
ap.add(new Label());
ap.add(new Label(kIntervals.getName()));
ap.add(kIntervals);
ap.add(new Label());
mainPanel.add(ap,BorderLayout.EAST);
}
}
else {
try {
animator.setMin( (new Double(getParameter("ParameterMin","-2"))).doubleValue() );
animator.setMax( (new Double(getParameter("ParameterMax","2"))).doubleValue() );
animator.setIntervals( (int)Math.round((new Double(getParameter("Intervals","25"))).doubleValue()) );
}
catch (NumberFormatException e) {
}
}
animator.setOnChange(mainController);
 
// Add a DrawString to show the current value of the parameter
 
if ( ! "no".equalsIgnoreCase(getParameter("ShowParameter","yes")) ) {
DrawString param = new DrawString(kVar.getName() + " = #", DrawString.BOTTOM_LEFT, new Value[] { kVar });
param.setBackgroundColor(canvas.getBackground());
Color c = getColorParam("ParameterColor",Color.black);
param.setColor(c);
canvas.add(param);
}
 
} // end setUpCanvas
 
 
protected void setUpLimitsPanel() {
super.setUpLimitsPanel();
if (limitsPanel != null && kMin != null) { // add animator inputs to limits panel
limitsPanel.addComponentPair(kMin,kMax);
limitsPanel.addComponent(kIntervals);
}
}
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the SilentAnimatedGraph applet, the example string should contain
// an expression that defines the function to be graphed. This can optionally
// be followed by a semicolon and a list of four to nine numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// next three numbers specify the minimum value for the parameter, the
// maximum number, and the number of intervals in the animation.
// The eigth number, if present, specifies the starting loop style
// for the animation with the following code: 0 for once-through,
// 1 for loop, and 2 for back-and-forth. The ninth number, if
// present, tells whether to start the animation immediately upon
// loading. If it is 1, the animation is started. If it is
// not specified or is any value other than 1, the animation is not started.
animator.stop();
int pos = example.indexOf(";");
boolean startAnimation = false;
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
 
if (pos > 0) {
// Get limits from example text.
String nums = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(nums, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
}
if (toks.hasMoreTokens()) {
try {
double d = (new Double(toks.nextToken())).doubleValue();
if (kMin == null)
animator.setMin(d);
else
kMin.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
double d = (new Double(toks.nextToken())).doubleValue();
if (kMax == null)
animator.setMax(d);
else
kMax.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
if (kIntervals == null)
animator.setIntervals(d);
else
kIntervals.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
animator.setLoopStyle(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
startAnimation = (d == 1);
}
catch (NumberFormatException e) {
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
try {
func = new SimpleFunction( parser.parse(example), xVar );
graph.setFunction(func);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
if (startAnimation) {
try { // insert a small delay before animation starts
synchronized(this) {
wait(250);
}
}
catch (InterruptedException e) {
}
animator.start();
}
} // end doLoadExample()
public void stop() { // stop animator when applet is stopped
animator.stop();
super.stop();
}
 
// jm.evers; handy functions, not invented here :(
public static byte [] loadURL(URL url) throws IOException {
int bufSize = 1024 * 2;
byte [] buf = new byte[bufSize];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(url.openStream());
int n;
while ((n = in.read(buf)) > 0){
bout.write(buf, 0, n);
}
try { in.close(); } catch (Exception ignored) { }
return bout.toByteArray();
}
 
public static String loadFile(String fname) throws IOException {
byte[] bytes = loadURL(new URL("file:" + fname));
return new String(bytes);
}
 
public static String load(String fileOrURL) throws IOException {
try {
URL url = new URL(fileOrURL);
return new String(loadURL(url));}
catch (Exception e) { return loadFile(fileOrURL);}
}
} // end class FamiliesOfGraphs
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/Derivatives.java
0,0 → 1,412
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
// Draws the graph of a function and its first derivative (and optionally
// its second derivative). It shows the tangent line to the graph and
// marks the corresponding point on the graph of the derivative. The
// user controls the position of the tangent line with a slider and/or
// a number-input box. A formula for the derivative can be displayed
// at the bototm of the applet.
 
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
 
public class Derivatives extends GenericGraphApplet {
 
private String functionName; // name of the fuction beging graphed, 'f' by default; used in labels etc
private Function func; // The function that is graphed.
private Function deriv; // derivative of func
private Expression derivExpression; // The Expression that defines the derivative
private Function deriv2; // if non-null, second derivative of func
private Controller subController = new Controller(); // Respond to changes in x-coord input; won't redraw graph
 
private VariableInput xInput; // x-coord of point of tangency
private class ExprLbl extends Label implements Computable {
// A class for displaying the formula for deriv
String label;
ExprLbl(String label) {
this.label = label;
compute();
}
public void compute() {
setText(label + derivExpression.toString());
}
}
protected void setUpParameterDefaults() { // I don't want to use abs(x)^x as the default function, since it's derivative is so funny
parameterDefaults = new java.util.Hashtable();
parameterDefaults.put("Function", " tan(" + getParameter("Variable","x") + ")");
}
protected void setUpMainPanel() { // add a bunch of extra components at the end
super.setUpMainPanel();
// now that limitsPanel has been set up, add the two extra coordinate rects to it
if (limitsPanel != null) {
limitsPanel.addCoords(canvas.getCoordinateRect(1));
if (deriv2 != null)
limitsPanel.addCoords(canvas.getCoordinateRect(2));
}
else { // CoordinateRects must synchronize with each other
Tie coordTie = new Tie(canvas.getCoordinateRect(0),canvas.getCoordinateRect(1));
if (deriv2 != null)
coordTie.add(canvas.getCoordinateRect(2));
canvas.getCoordinateRect(0).setSyncWith(coordTie);
canvas.getCoordinateRect(1).setSyncWith(coordTie);
if (deriv2 != null)
canvas.getCoordinateRect(2).setSyncWith(coordTie);
}
// Add controls at the bottom of the panel for setting the value of x.
// Also add the derivative formula, if it's supposed to be displayed
Value xMin = canvas.getCoordinateRect().getValueObject(CoordinateRect.XMIN);
Value xMax = canvas.getCoordinateRect().getValueObject(CoordinateRect.XMAX);
canvas.getCoordinateRect().setOnChange(subController);
VariableSlider xSlider = new VariableSlider(xMin,xMax);
xSlider.setOnUserAction(subController);
xInput.setOnTextChange(subController);
subController.add(xSlider);
subController.add(xInput);
subController.add( new Tie(xSlider,xInput) );
Panel p = new Panel();
p.setLayout(new BorderLayout(5,5));
p.add(xInput.withLabel(), BorderLayout.WEST);
p.add(xSlider, BorderLayout.CENTER);
// If there is no limits panel, make it possible to add a RestoreLimits button to the input panel
if (limitsPanel == null && ! "no".equalsIgnoreCase(getParameter("UseRestoreButton","no"))) {
// add button to left of slider
Button res = new Button("Restore Limits");
p.add(res, BorderLayout.EAST);
res.setBackground(Color.lightGray);
res.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvas.getCoordinateRect(0).restore();
canvas.getCoordinateRect(1).restore();
if (deriv2 != null)
canvas.getCoordinateRect(2).restore();
}
});
}
 
if ("yes".equalsIgnoreCase(getParameter("ShowFormula", "yes"))) { // add derivative formula
Panel s = new Panel();
s.setLayout(new GridLayout(2,1,3,3));
s.add(p);
ExprLbl lbl = new ExprLbl(" " + functionName + "'(" + xVar.getName() + ") = ");
mainController.add(lbl);
s.add(lbl);
p = s;
}
if (inputPanel == null) {
// Add the control panel directly to the main panel
p.setBackground(getColorParam("PanelBackground",Color.lightGray));
mainPanel.add(p,BorderLayout.SOUTH);
}
else {
// Add control panel to bottom of input panel.
inputPanel.add(p,BorderLayout.SOUTH);
}
 
} // end setUpMainPanel
 
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
// I don't call super.setUpCanvas(), since
// the canvas in this case is quite a bit different
// from the standard one.
 
boolean showSecond = ! "no".equalsIgnoreCase(getParameter("SecondDerivative","no"));
 
xInput = new VariableInput(xVar.getName(), getParameter("X","1"));
if (functionInput != null) {
func = functionInput.getFunction(xVar);
derivExpression = functionInput.getExpression().derivative(xVar);
}
else {
String def = getParameter("Function");
Expression exp = parser.parse(def);
Function f = new SimpleFunction( exp, xVar );
derivExpression = exp.derivative(xVar);
func = new WrapperFunction(f);
}
Graph1D graph = new Graph1D(func);
Color color = getColorParam("GraphColor",Color.black);
graph.setColor(color);
deriv = func.derivative(1);
Graph1D derivGraph = new Graph1D(deriv);
derivGraph.setColor(color);
Graph1D deriv2Graph = null;
if (showSecond) {
deriv2 = deriv.derivative(1);
deriv2Graph = new Graph1D(deriv2);
deriv2Graph.setColor(color);
}
 
// Set up 2 or 3 coordinate retcs
if (showSecond) {
canvas.addNewCoordinateRect(0, 1.0/3.0, 0, 1);
canvas.addNewCoordinateRect(1.0/3.0, 2.0/3.0, 0, 1);
canvas.addNewCoordinateRect(2.0/3.0, 1, 0, 1);
}
else {
canvas.addNewCoordinateRect(0, 0.5, 0, 1);
canvas.addNewCoordinateRect(0.5, 1, 0, 1);
}
 
// do the type of stuff that's usually done in super.setUpCanvas
color = getColorParam("CanvasColor");
if (color != null)
canvas.setBackground(color);
if (! "no".equalsIgnoreCase(getParameter("UsePanner", "no")) ) {
canvas.add(new Panner(),0);
canvas.add(new Panner(),1);
if (showSecond)
canvas.add(new Panner(),2);
}
if ( ! "no".equalsIgnoreCase(getParameter("UseGrid", "no")) ) {
Grid g = new Grid();
color = getColorParam("GridColor");
if (color != null)
g.setColor(color);
canvas.add(g,0);
g = new Grid();
color = getColorParam("GridColor");
if (color != null)
g.setColor(color);
canvas.add(g,1);
if (showSecond) {
g = new Grid();
color = getColorParam("GridColor");
if (color != null)
g.setColor(color);
canvas.add(g,2);
}
}
canvas.add(makeAxes(),0);
canvas.add(makeAxes(),1);
if (showSecond)
canvas.add(makeAxes(),2);
if ( ! "no".equalsIgnoreCase(getParameter("UseMouseZoom", "no")) )
canvas.setHandleMouseZooms(true);
if ( "yes".equalsIgnoreCase(getParameter("UseOffscreenCanvas", "yes")) )
canvas.setUseOffscreenCanvas(true);
mainController.setErrorReporter(canvas);
mainPanel.add(canvas, BorderLayout.CENTER);
// add graphs, tangent lines etc.
canvas.add(graph,0);
canvas.add(derivGraph,1);
if (showSecond)
canvas.add(deriv2Graph,2);
Color tangentColor = getColorParam("TangentColor", Color.red);
Color tangentColor2 = getColorParam("TangentColor2", new Color(0, 180, 0));
mainController.remove(canvas);
mainController.add(graph);
mainController.add(derivGraph);
if (showSecond)
mainController.add(deriv2Graph);
subController = new Controller();
mainController.add(subController);
TangentLine tan = new TangentLine(xInput, func);
Crosshair cross = new Crosshair(xInput,deriv);
tan.setColor(tangentColor);
cross.setColor(tangentColor);
canvas.add(tan, 0);
canvas.add(cross, 1);
subController.add(tan);
subController.add(cross);
if (showSecond) {
tan = new TangentLine(xInput, deriv);
cross = new Crosshair(xInput, deriv2);
tan.setColor(tangentColor2);
cross.setColor(tangentColor2);
canvas.add(tan, 1);
canvas.add(cross, 2);
subController.add(tan);
subController.add(cross);
}
 
functionName = getParameter("FunctionName", "f");
 
String yName = getParameter("YName","y");
Color textColor = getColorParam("TextColor",Color.black);
Color bgColor = getColorParam("TextBackground",Color.white);
DrawString str;
if ("yes".equalsIgnoreCase(getParameter("ShowGraphLabels","yes"))) {
str = new DrawString(yName + " = " + functionName + "(" + xVar.getName() + ")");
str.setColor(textColor);
str.setBackgroundColor(bgColor);
str.setFrameWidth(1);
canvas.add(str,0);
str = new DrawString(yName + " = " + functionName + " ' (" + xVar.getName() + ")");
str.setColor(textColor);
str.setBackgroundColor(bgColor);
str.setFrameWidth(1);
canvas.add(str,1);
if (showSecond) {
str = new DrawString(yName + " = " + functionName + " ' ' (" + xVar.getName() + ")");
str.setColor(textColor);
str.setBackgroundColor(bgColor);
str.setFrameWidth(1);
canvas.add(str,2);
}
}
if ("yes".equalsIgnoreCase(getParameter("ShowValues","yes"))) {
str = new DrawString(functionName + "(#) = #", DrawString.BOTTOM_LEFT, new Value[] { xInput, new ValueMath(func,xInput) });
str.setColor(textColor);
str.setBackgroundColor(bgColor);
str.setFrameWidth(1);
str.setNumSize(7);
canvas.add(str,0);
subController.add(str);
str = new DrawString(functionName + " ' (#) = #", DrawString.BOTTOM_LEFT, new Value[] { xInput, new ValueMath(deriv,xInput) });
str.setColor(textColor);
str.setBackgroundColor(bgColor);
str.setFrameWidth(1);
str.setNumSize(7);
canvas.add(str,1);
subController.add(str);
if (showSecond) {
str = new DrawString(functionName + " ' ' (#) = #", DrawString.BOTTOM_LEFT, new Value[] { xInput, new ValueMath(deriv2,xInput) });
str.setColor(textColor);
str.setBackgroundColor(bgColor);
str.setFrameWidth(1);
str.setNumSize(7);
canvas.add(str,2);
subController.add(str);
}
}
 
} // end setUpCanvas()
protected void addCanvasBorder() { // override to add the border to each coordinate rect, and make default width equal to 1
int borderWidth;
double[] bw = getNumericParam("BorderWidth");
if (bw == null || bw.length == 0 || bw[0] > 25)
borderWidth = 2;
else
borderWidth = (int)Math.round(bw[0]);
if (borderWidth > 0) {
canvas.add( new DrawBorder( getColorParam("BorderColor", Color.black), borderWidth ), 0 );
canvas.add( new DrawBorder( getColorParam("BorderColor", Color.black), borderWidth ), 1 );
if (deriv2 != null)
canvas.add( new DrawBorder( getColorParam("BorderColor", Color.black), borderWidth ), 2 );
}
}
 
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the SecantTangent applet, the example string should contain
// an expression that defines the function to be graphed. This can optionally
// be followed by a semicoloon and a list of four or five numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// fifth number, if present, gives the x-coord where the tangent line
// is drawn initially.
int pos = example.indexOf(";");
 
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
if (pos > 0) { // get limits from example text
String limitsText = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(limitsText, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
if (toks.countTokens() > 0) { // Get point for tangent line
try {
Double d = new Double(toks.nextToken());
xInput.setVal( d.doubleValue() );
}
catch (NumberFormatException e) {
}
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
// Also, in this case, func is a "WrapperFunction". Set the
// definition of that WrapperFunction to be the same as f
try {
Expression exp = parser.parse(example);
derivExpression = exp.derivative(xVar);
Function f = new SimpleFunction( exp, xVar );
((WrapperFunction)func).setFunction(f);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
canvas.getCoordinateRect(1).setRestoreBuffer();
if (deriv2 != null)
canvas.getCoordinateRect(0).setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
 
 
} // end class SimpleGraph
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/Parametric.java
0,0 → 1,373
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
// The ParametricCurve applet is a configurable applet that displays a parametric
// curve defined by two functions of a parameter t. There can be a "Tracer" button
// on the applet. When the user clicks this button, a crosshair is moved along
// the curve from beginning to end.
 
import java.awt.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import java.util.Hashtable;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
 
 
public class Parametric extends GenericGraphApplet {
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private Function xFunc,yFunc; // The functions that are graphed.
private ParametricCurve graph; // The graph of the function.
private Animator tracer; // for tracing the curve by moving a crosshair along it
private Crosshair crosshair; // Crosshair used for tracing the graph
private VariableInput tMin,tMax; // for inputting limits on t
private VariableInput tIntervals; // for inutting the number of intervals into which the t-range is divided
private ExpressionInput functionInput2; // for inputting yFunc; xFunc is input in functionInput
protected void setUpParameterDefaults() {
parameterDefaults = new Hashtable();
parameterDefaults.put("TwoLimitsColumns", "yes");
parameterDefaults.put("Variable","t");
parameterDefaults.put("XName","x"); // we need this so that xmin and xmax boxes are labeled correctly;
// without it, the name would come from the variable name, t, instead of x
parameterDefaults.put("FunctionLabel", " " + getParameter("XName") + "(" + getParameter("Variable") + ") = ");
parameterDefaults.put("FunctionLabel2", " " + getParameter("YName","y") + "(" + getParameter("Variable") + ") = ");
}
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
super.setUpCanvas(); // Do the common setup: Add the axes and
 
// When setUpCanvas is called, the function inputs already exist, if they are
// to be used, since they are created in setUpBopttomPanel(), which is called
// before setUpCanvas(). If functionInput exists, add a graph of the functions
// from functionInput and functionInput2 to the canvas. If not, create a graph
// of the functions specified by the parameters named "Function" and "Function2".
if (functionInput != null) {
xFunc = functionInput.getFunction(xVar);
yFunc = functionInput2.getFunction(xVar);
}
else {
String xFuncDef = " cos(" + xVar.getName() + ") + cos(3*" + xVar.getName() + ")";
String yFuncDef = " sin(4*" + xVar.getName() + ") - sin(2*" + xVar.getName() + ")";
xFuncDef = getParameter("Function", xFuncDef);
yFuncDef = getParameter("Function2", yFuncDef);
Function f = new SimpleFunction( parser.parse(xFuncDef), xVar );
xFunc = new WrapperFunction(f);
f = new SimpleFunction( parser.parse(yFuncDef), xVar );
yFunc = new WrapperFunction(f);
}
graph = new ParametricCurve(xFunc,yFunc);
Color color = getColorParam("CurveColor");
if (color != null)
graph.setColor(color);
// if inputs are desired to control the parameter on the curve, set them up here
if ("no".equalsIgnoreCase(getParameter("UseParamInputs","yes"))) {
tMin = new VariableInput(xVar.getName() + "Start",getParameter("ParameterMin","-2"));
tMax = new VariableInput(xVar.getName() + "End",getParameter("ParameterMax","2"));
tIntervals = new VariableInput("Intervals", getParameter("Intervals","200"));
tIntervals.setInputStyle(VariableInput.INTEGER);
tIntervals.setMin(1);
tIntervals.setMax(5000);
tMin.setOnUserAction(mainController);
tMax.setOnUserAction(mainController);
tIntervals.setOnUserAction(mainController);
graph.setTMin(tMin);
graph.setTMax(tMax);
graph.setIntervals(tIntervals);
if (limitsPanel != null) {
// componets will be added to limitsPanel in setUpLimitsPanel()
mainController.add(tMin); // This is not done automatically, since they are in a limits panel
mainController.add(tMax);
mainController.add(tIntervals);
}
else {
JCMPanel ap = new JCMPanel(9,0);
ap.setBackground(getColorParam("PanelBackground", Color.lightGray));
ap.add(new Label(tMin.getName()));
ap.add(tMin);
ap.add(new Label());
ap.add(new Label(tMax.getName()));
ap.add(tMax);
ap.add(new Label());
ap.add(new Label(tIntervals.getName()));
ap.add(tIntervals);
ap.add(new Label());
mainPanel.add(ap,BorderLayout.EAST);
}
}
else {
try {
graph.setTMin( new Constant((new Double(getParameter("ParameterMin","-2"))).doubleValue()) );
graph.setTMax( new Constant((new Double(getParameter("ParameterMax","2"))).doubleValue()) );
graph.setIntervals( new Constant((new Double(getParameter("Intervals","25"))).doubleValue()) );
}
catch (NumberFormatException e) {
}
}
 
// If the applet is configured to have a tracer button, create it and add the crosshair to the canvas
 
if (! "no".equalsIgnoreCase( getParameter("UseTracer","yes") ) ) {
tracer = new Animator();
tracer.setMin(graph.getTMin());
tracer.setMax(graph.getTMax());
tracer.setUndefinedWhenNotRunning(true);
tracer.setStartButtonName("Trace Curve!");
double[] d = getNumericParam("TracerIntervals");
int ints;
if (d == null || d.length != 1)
ints = 100;
else
ints = (int)Math.round(d[0]);
if (ints <= 0)
tracer.setIntervals(graph.getIntervals());
else
tracer.setIntervals(ints);
Variable v = tracer.getValueAsVariable();
crosshair = new Crosshair( new ValueMath(xFunc,v), new ValueMath(yFunc,v) );
crosshair.setLineWidth(3);
crosshair.setColor(getColorParam("CrosshairColor",Color.gray));
canvas.add(crosshair);
if (inputPanel != null) {
inputPanel.add(tracer,BorderLayout.WEST);
}
else if (limitsPanel == null) {
Panel p = new Panel();
p.add(tracer);
mainPanel.add(p,BorderLayout.SOUTH);
}
// if inputPanel is null but limitsPanel is not null, the tracer will be
// added to the limit control panel in setUpLimitsPanel()
}
 
canvas.add(graph); // Finally, add the graph to the canvas.
 
} // end setUpCanvas()
 
protected void setUpLimitsPanel() {
super.setUpLimitsPanel();
if (limitsPanel != null && tMin != null) { // add parameter inputs to limits panel
limitsPanel.addComponentPair(tMin,tMax);
limitsPanel.addComponent(tIntervals);
}
if (inputPanel == null && tracer != null && limitsPanel != null) {
limitsPanel.addComponent(tracer);
}
}
protected void setUpBottomPanel() { // override this to make a panel containing inputs for two functions
if ( ! "no".equalsIgnoreCase(getParameter("UseFunctionInput", "yes")) ) {
inputPanel = new JCMPanel();
inputPanel.setBackground( getColorParam("PanelBackground", Color.lightGray) );
Panel in = new JCMPanel(2,1);
inputPanel.add(in,BorderLayout.CENTER);
if ( ! "no".equalsIgnoreCase(getParameter("UseComputeButton", "yes")) ) {
String cname = getParameter("ComputeButtonName", "New Functions");
computeButton = new Button(cname);
inputPanel.add(computeButton, BorderLayout.EAST);
computeButton.addActionListener(this);
}
 
String varName = getParameter("Variable");
String def = getParameter("Function");
if (def == null)
def = "cos(" + varName + ") + cos(3*" + varName + ")";
functionInput = new ExpressionInput(def,parser);
String label = getParameter("FunctionLabel");
if ("none".equalsIgnoreCase(label))
in.add(functionInput);
else {
Panel p = new JCMPanel();
p.add(functionInput,BorderLayout.CENTER);
p.add( new Label(label), BorderLayout.WEST );
in.add(p);
}
def = getParameter("Function2");
if (def == null)
def = "sin(4*" + varName + ") - sin(2*" + varName + ")";
functionInput2 = new ExpressionInput(def,parser);
label = getParameter("FunctionLabel2");
if ("none".equalsIgnoreCase(label))
in.add(functionInput2);
else {
Panel p = new JCMPanel();
p.add(functionInput2,BorderLayout.CENTER);
p.add( new Label(label), BorderLayout.WEST );
in.add(p);
}
mainPanel.add(inputPanel, BorderLayout.SOUTH);
functionInput.setOnUserAction(mainController);
functionInput2.setOnUserAction(mainController);
}
}
 
protected void setUpMainPanel() { // Override to set up controller for tracer, if there is one
super.setUpMainPanel(); // Do the common setup
 
if ( tracer == null ) {
return; // If the applet is not configured to use a trace button, there is nothing to do.
}
 
Controller traceController = new Controller(); // A controler that will only recompute the crosshair position
traceController.add(tracer);
traceController.add(crosshair);
tracer.setOnChange(traceController);
 
} // end setUpMainPanel()
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the Parametric applet, the example string should contain
// two expression that defines the curve to be graphed, separated
// by a semicolon. This can optionally
// be followed by another semicolon and a list of four to seven numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// next three numbers specify the minimum value for the parameter, the
// maximum value, and the number of intervals into which the range of
// parameter values is divided.
if (tracer != null)
tracer.stop();
int pos = example.indexOf(";");
if (pos == -1)
return; // illegal example -- must have two functions
String example2 = example.substring(pos+1);
example = example.substring(0,pos);
pos = example2.indexOf(";");
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
 
if (pos > 0) {
// Get limits from example2 text.
String nums = example2.substring(pos+1);
example2 = example2.substring(0,pos);
StringTokenizer toks = new StringTokenizer(nums, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
}
if (toks.hasMoreTokens()) {
try {
double d = (new Double(toks.nextToken())).doubleValue();
if (tMin == null) {
graph.setTMin(new Constant(d));
if (tracer != null)
tracer.setMin(d);
}
else
tMin.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
double d = (new Double(toks.nextToken())).doubleValue();
if (tMax == null) {
graph.setTMax(new Constant(d));
if (tracer != null)
tracer.setMax(d);
}
else
tMax.setVal(d);
}
catch (NumberFormatException e) {
}
}
if (toks.hasMoreTokens()) {
try {
int d = (int)Math.round((new Double(toks.nextToken())).doubleValue());
if (tIntervals == null) {
if (tracer != null && tracer.getIntervals() == graph.getIntervals())
tracer.setIntervals(d);
graph.setIntervals(new Constant(d));
}
else
tIntervals.setVal(d);
}
catch (NumberFormatException e) {
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
functionInput2.setText(example2);
}
else {
// If there is no user input, set the function in the graph directly.
try {
Function f = new SimpleFunction( parser.parse(example), xVar );
((WrapperFunction)xFunc).setFunction(f);
Function g = new SimpleFunction( parser.parse(example2), xVar );
((WrapperFunction)yFunc).setFunction(g);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
 
public void stop() { // stop animator when applet is stopped
if (tracer != null)
tracer.stop();
super.stop();
}
 
 
 
} // end class Parametric
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/SilentSimpleGraph.java
0,0 → 1,301
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
//12/1/2010
// jm.evers added param "file" //
// jm.evers multigraphs: x^2,sqrt(x),sin(1/x)
// the moving point is on first graph.
import java.awt.*;
import java.applet.Applet;
import java.net.*;
import java.io.*;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
public class SilentSimpleGraph extends GenericGraphApplet {
 
// Declare some private variables that are created in one method in
// this class and used in a second method.
 
private VariableInput xInput; // Contains the x-coordinate of the marked point.
private Vector functies;
private Color[] graphColors = { Color.magenta, new Color(0,180,0),Color.red, new Color(0,200,200),Color.orange, Color.gray, Color.blue, Color.pink };
private Function func; // The function that is graphed.
private Graph1D[] graphs;
private Graph1D graph;
private DrawGeometric point; // An oval that marks the selected point on the graph.
private DrawGeometric vLine; // A line from the point to the x-axis.
private DrawGeometric hLine; // A line from the point to the y-axis.
 
 
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
super.setUpCanvas(); // Do the common setup: Add the axes and
 
// When setUpCanvas is called, the functionInput already exists, if one is
// to be used, since it is created in setUpBopttomPanel(), which is called
// before setUpCanvas. If functionInput exists, add a graph of the function
// from functionInput to the canvas. If not, create a graph of the function
// specified by the parameter named "Function".
functies = new Vector();
if (functionInput != null){
func = functionInput.getFunction(xVar);
functies.add(func);
} else {
//jm.evers 1/2010 load a file from url
String def;
try{
String data = getParameter("File");
def = load(data);
def = def.replaceAll("\\n","");
StringTokenizer toks = new StringTokenizer(def, ",");
int cnt = toks.countTokens();
for(int i=0; i<cnt;i++){
String tmp = toks.nextToken();
func = new SimpleFunction( parser.parse(tmp), xVar );
//func = new WrapperFunction(f);
functies.add(func);
}
} catch(Exception e){System.out.println("could not load parameter File");
def = getParameter("Function", " abs(" + xVar.getName() + ") ^ " + xVar.getName());
func = new SimpleFunction( parser.parse(def), xVar );
//func = new WrapperFunction(f);
//functies.add(func);
functies.add(func);
}
}
graphs = new Graph1D[functies.size()];
for (int i = 0; i < functies.size(); i++) {
graphs[i] = new Graph1D();
graphs[i].setColor(graphColors[ i % graphColors.length ]);
graphs[i].setFunction((Function)functies.elementAt(i));
if(i==0){
if (! "no".equalsIgnoreCase( getParameter("ShowPoint","yes"))){
vLine = new DrawGeometric();
hLine = new DrawGeometric();
point = new DrawGeometric();
canvas.add(vLine);
canvas.add(hLine);
canvas.add(point);
}
}
canvas.add(graphs[i]);
}
 
} // end setUpCanvas()
 
protected void setUpMainPanel() { // Override to handle the point marked on the graph
super.setUpMainPanel(); // Do the common setup
 
if ( "no".equalsIgnoreCase( getParameter("ShowPoint","yes") ) ) {
return; // If the applet is not configured to show a point, there is nothing to do.
}
// Create two input objects, a VariableInput and a VariableSlider. The values of
// the two inputs will be synchronized with each other using a "Tie". The
// minimum and maximum values represented on the slider are given by the
// the minimum and maximum x-coordinates on the CoordinateRect. This will restrict
// the x-coodinate of the point that is marked on the graph to the range of
// x-values actually shown on the screen.
xInput = new VariableInput(); // An input box for the x-coord of the marked point
xInput.setInputStyle(VariableInput.REAL); // Allow only real numbers (not constant expressions)
CoordinateRect coords = canvas.getCoordinateRect();
VariableSlider xSlider = new VariableSlider( coords.getValueObject(CoordinateRect.XMIN),
coords.getValueObject(CoordinateRect.XMAX) );
Value yValue = new ValueMath(func,xSlider); // Represents the y-value of the marked point.
DisplayLabel yDisplay = new DisplayLabel(" y = #", yValue); // Shows the y-value of the point
// Create a panel to contain the input objects.
JCMPanel panel = new JCMPanel(1,3);
panel.setBackground(getColorParam("PanelBackground",Color.lightGray));
JCMPanel subpanel = new JCMPanel();
String varName = getParameter("Variable","x");
subpanel.add(new Label(" " + varName + " = ", Label.CENTER), BorderLayout.WEST);
subpanel.add(xInput, BorderLayout.CENTER);
panel.add(xSlider);
panel.add(subpanel);
panel.add(yDisplay);
// If there is a functionInput box, then the SOUTH position of the mainPanel already contains
// the inputPanel that contains that box. If so, add the new panel to the SOUTH position of
// the inputPanel. (This is a good place, in general, to put extra input objects.)
// If there is no inputPanel, then the SOUTH position of the mainPanel is empty, so put
// the newly created panel there. Also, set the background color for the input panel from
// from the PanelBackground applet param. (This is already done for inputPanel, if it exists.)
if (inputPanel == null)
mainPanel.add(panel, BorderLayout.SOUTH);
else {
inputPanel.setBackground(getColorParam("PanelBackground",Color.lightGray));
inputPanel.add(panel, BorderLayout.SOUTH);
}
 
// Set up all the data for the point and the lines from the point to the axes.
// The objects where created in setUpCanvas() and added to the canvas.
 
hLine.setPoints(new Constant(0),yValue,xSlider,yValue);
hLine.setPoints(new Constant(0),yValue,xSlider,yValue);
point.setShape(DrawGeometric.CROSS);
point.setPoints(xSlider,yValue,5,5);
point.setLineWidth(3);
vLine.setPoints(xSlider,new Constant(0),xSlider,yValue);
Color c = getColorParam("LineColor", Color.lightGray);
vLine.setColor(c);
hLine.setColor(c);
c = getColorParam("DotColor", Color.gray);
point.setColor(c);
 
// Now, I have to set a Controller to respond to changes in the input objects.
// I could just use the mainController, but then the data for the graph would
// be recomputed whenever the user changes the x-coordinate of the marked point.
// For effieciency, I will use a separate Controller that only recomputes the
// data for the point (not the graph) when the inputs change.
Controller cc = new Controller();
 
xInput.setOnTextChange(cc); // cc responds when user types in the input box
xSlider.setOnUserAction(cc); // cc responds when the user drags the slider
coords.setOnChange(cc); // cc responds when the coordinate limits change;
// this is necessary because the minimum and
// maximum values on the slider have to be checked.
 
cc.add( xInput ); // Check whether the values have changed.
cc.add( xSlider );
 
cc.add( new Tie(xSlider,xInput) ); // synchronize values of input box and slider
 
cc.add( hLine ); // Recompute the values for the point and lines.
cc.add( vLine );
cc.add( point );
 
cc.add( yDisplay ); // Recompute the value displayed on the yDisplay label.
 
mainController.add(cc); // When the mainController recomputes (because function has
// been changed, all the stuff controlled by cc also has
// to be checked.
mainController.remove(canvas); // The mainController should not recompute the contents
// of the canvas (which it would do by default).
mainController.add(graph); // But the mainController should recompute the graph.
 
} // end setUpMainPanel()
 
 
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the SilentSimpleGraph applet, the example string should contain
// an expression that defines the function to be graphed. This can optionally
// be followed by a semicoloon and a list of four or five numbers.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The
// fifth number, if present, gives the x-coord of the marked point
// on the graph.
int pos = example.indexOf(";");
 
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
if (pos > 0) { // get limits from example text
String limitsText = example.substring(pos+1);
example = example.substring(0,pos);
StringTokenizer toks = new StringTokenizer(limitsText, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
if (toks.countTokens() > 0 && xInput != null) {
// get x-coord of marked point from example text
try {
Double d = new Double(toks.nextToken());
xInput.setVal( d.doubleValue() );
}
catch (NumberFormatException e) {
}
}
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
}
else {
// If there is no user input, set the function in the graph directly.
// Also, in this case, func is a "WrapperFunction". Set the
// definition of that WrapperFunction to be the same as f
try {
Function f = new SimpleFunction( parser.parse(example), xVar );
((WrapperFunction)func).setFunction(f);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
} // end doLoadExample()
// jm.evers; handy functions, not invented here :(
public static byte [] loadURL(URL url) throws IOException {
int bufSize = 1024 * 2;
byte [] buf = new byte[bufSize];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(url.openStream());
int n;
while ((n = in.read(buf)) > 0){
bout.write(buf, 0, n);
}
try { in.close(); } catch (Exception ignored) { }
return bout.toByteArray();
}
 
public static String loadFile(String fname) throws IOException {
byte[] bytes = loadURL(new URL("file:" + fname));
return new String(bytes);
}
 
public static String load(String fileOrURL) throws IOException {
try {
URL url = new URL(fileOrURL);
return new String(loadURL(url));}
catch (Exception e) { return loadFile(fileOrURL);}
}
} // end class SilentSimpleGraph
 
 
//////////////////////////////////////////////////
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/functions/CubicSegment.java
0,0 → 1,114
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.functions;
 
 
/**
* This non-public class is for use with TableFunctions. It defines one segment
* of a TableFunction whose style is TableFunction.SMOOTH. A cubic segment is
* a segment of a cubic polynomial. It is defined by six numbers: two x-coordinates,
* the y-value at each x-coordinate, and the derivative at each x-coordinate.
*/
class CubicSegment {
 
private double x1,x2, // x-ccords at endpoints with x1 < x2
y1,y2, // y-coords at endpoints
d1,d2; // derivatives at endpoints
private double a,b,c,d; // coefficients in a(x-x1)^3 + b(x-x1)^2(x-x2) + ...
 
CubicSegment() {
}
 
CubicSegment(double x1, double x2, double y1, double y2, double d1, double d2) {
setData(x1, x2, y1, y2, d1, d2);
}
void setData(double nx1, double nx2, double ny1, double ny2, double nd1, double nd2) {
double temp;
if (nx1 == nx2)
throw new IllegalArgumentException("Attempt to make CubicSegment of length 0");
if (nx1 > nx2) {
temp = nx1; nx1 = nx2; nx2 = temp;
temp = ny1; ny1 = ny2; ny2 = temp;
temp = nd1; nd1 = nd2; nd2 = temp;
}
x1 = nx1;
x2 = nx2;
y1 = ny1;
y2 = ny2;
d1 = nd1;
d2 = nd2;
temp = (x2 - x1);
a = y2/(temp*temp*temp);
b = d2/(temp*temp) - 3*a;
temp = -temp;
d = y1/(temp*temp*temp);
c = d1/(temp*temp) - 3*d;
}
void setDerivativesFromNeighbors(double leftX, double leftY, double rightX, double rightY) {
double nd1,nd2;
if (!Double.isNaN(leftX) && leftX < x1)
nd1 = (y2 - leftY) / (x2 - leftX);
else
nd1 = (y2 - y1) / (x2 - x1);
if (!Double.isNaN(rightX) && rightX > x2)
nd2 = (rightY - y1) / (rightX - x1);
else
nd2 = (y2 - y1) / (x2 - x1);
setData(x1,x2,y1,y2,nd1,nd2);
}
double value(double x) { // should have x1 <= x <= x2, but not required
return derivativeValue(x,0);
}
double derivativeValue(double x, int derivativeOrder) {
// Assume derivativeOrder >= 0.
// This function, unlike value() returns the value that represents the
// one-sided limit at the endpoint, even if that endpoint is not
// in the domain.
switch (derivativeOrder) {
case 0:
double t1 = x - x1;
double t2 = t1*t1;
double t3 = t2*t1;
double s1 = x - x2;
double s2 = s1*s1;
double s3 = s2*s1;
return a*t3 + b*t2*s1 + c*t1*s2 + d*s3;
case 1:
return ((3*a+b)*(x-x1)*(x-x1) + 2*(b+c)*(x-x1)*(x-x2) + (3*d+c)*(x-x2)*(x-x2));
case 2:
return 2*( (3*a+2*b+c)*(x-x1) + (3*d+2*c+b)*(x-x2) );
case 3:
return 6*(2*a+b+c);
default:
return 0;
}
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/functions/SummationParser.java
0,0 → 1,199
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
 
package edu.hws.jcm.functions;
 
import edu.hws.jcm.data.*;
 
 
/**
* The SummationParser class makes it possible to use summations such as sum(i,1,5,x^i) in a Parser.
* The summation psedu-function has four parameters: (1) The summation variable, which must be an identifier;
* (2) The lower limit for the summation, given as an expression; (3) The upper limit for the
* summation, given as an expression; and (4) The expression that is summed. The values of
* the lower and upper limit expressions are rounded to the nearest integer. The expression in
* the fourth parameter can (and presumably will) use the summation variable (as well as other
* identifiers known to the parser).
*
* <p>To use summations with a Parser p, just say p.add(new SummationParser()). It's unlikely that
* you will ever need to do anything else with SummationParsers.
* If you want to use a name other than "sum", you can change the name after creating the
* SummationParser object but before adding it to a parser. (Note, by the way, that parsers by default do not do
* factorials. If you want a parser that recognizes factorials, you could do something
* like p = new Parser(Parser.DEFAULT_OPTIONS | Parser.FACTORIAL).)
*
*/
public class SummationParser implements ParserExtension {
 
/* A name is required by the MathObject interface, which ParserExtension extends. The name
is what is used to indicate a summation in an expression. The name should not be changed
after the SummationParser is added to a Parser. */
 
private String name = "sum";
 
/**
* Set the name, which will be used in place of "sum" in expressions. This should not
* be done after the SummationParser has been added to a Parser. The default name is "sum".
*/
public void setName(String name) {
this.name = name;
}
/**
* Get the name, which will be used in place of "sum" in expressions.
*/
public String getName() {
return name;
}
 
/**
* When the name of this ParserExtension is encountered by a parser with which
* the extension is registered, the parser calls this routine to parse the
* summation subexpression. The subexpression has the form
* (<variable>,<lower-limit>,<upper-limit>,<expression>). This method is
* not meant to be called directly
*/
public void doParse(Parser parser, ParserContext context) {
int tok = context.next();
String open = context.tokenString;
if (tok == ParserContext.OPCHARS &&
( open.equals("(") || (open.equals("[") && (context.options & Parser.BRACKETS) != 0)
|| (open.equals("{") && (context.options & Parser.BRACES) != 0) )) {
String close = open.equals("(") ? ")" : (open.equals("[") ? "]" : "}");
tok = context.next(); // Must be an identifier.
if (tok != ParserContext.IDENTIFIER)
throw new ParseError("Expected the summation variable as the first argument of " + name + ".", context);
String varName = context.tokenString;
tok = context.next();
if (tok != ParserContext.OPCHARS || ! context.tokenString.equals(","))
throw new ParseError("Exprected a comma after the index variable, " + varName +".", context);
parser.parseExpression(context);
tok = context.next();
if (tok != ParserContext.OPCHARS || ! context.tokenString.equals(","))
throw new ParseError("Exprected a comma after the lower limit expression for " + name + ".", context);
parser.parseExpression(context);
tok = context.next();
if (tok != ParserContext.OPCHARS || ! context.tokenString.equals(","))
throw new ParseError("Exprected a comma after the upper limit expression for " + name + ".", context);
Variable v = new Variable(varName);
context.mark(); // Temporoarily add the summation variable to the symbol table.
context.add(v);
ExpressionProgram saveProg = context.prog;
context.prog = new ExpressionProgram(); // Compile the expression into a new program.
parser.parseExpression(context);
tok = context.next();
if (tok != ParserContext.OPCHARS || ! context.tokenString.equals(close))
throw new ParseError("Expected a \"" + close + "\" at the end of the paramter list for " + name + ".", context);
context.revert(); // Restore the state of the ParserContext.
saveProg.addCommandObject(new Cmd(v,context.prog));
context.prog = saveProg;
}
else
throw new ParseError("Parentheses required around parameters of summation.", context);
} // end doParse()
 
private static class Cmd implements ExpressionCommand {
// When a summation occurs in an expression, it is represented in the compiled ExpressionProgram
// by an object belonging to this class.
private Variable sumVar; // The summation variable.
private ExpressionProgram sumExpr; // The expression that is summed
Cmd(Variable v, ExpressionProgram e) {
// Constructor.
sumVar = v;
sumExpr = e;
}
 
public void apply(StackOfDouble stack, Cases cases) {
// This routine is called when an ExpressionCommand object is encountered during
// the evaluation of an ExpressionProgram. The stack may contain results of
// previous commands in the program. In this case, the command is a summation
// and the stack contains the upper and lower limits summation limits.
double upper = Math.round(stack.pop()) + 0.1; // Get summation limits.
double lower = Math.round(stack.pop());
if (Double.isNaN(upper) && Double.isNaN(lower) || upper - lower > 1000000)
stack.push(Double.NaN);
double sum = 0;
for (double x = lower; x <= upper; x++) { // Compute the sum.
sumVar.setVal(x);
sum += sumExpr.getVal();
}
stack.push(sum); // Leave the sum on the stack.
}
 
public void compileDerivative(ExpressionProgram prog, int myIndex, ExpressionProgram deriv, Variable wrt) {
// The ExpressionCommand occurs in the program prog at the index indicated by myIndex.
// Add commands to deriv that will evaluate the derivative of this command with respect to
// the variable wrt. Note that the "Cmd" object is preceded in the program by commands that
// compute the lower and upper limits of the summation.
if (!sumExpr.dependsOn(wrt))
deriv.addConstant(0);
else {
int upper = prog.extent(myIndex - 1); // Size of expression giving the upper limit.
prog.copyExpression(myIndex - 1 - upper,deriv); // Copy lower limit exression to deriv.
prog.copyExpression(myIndex - 1,deriv); // Copy upper limit expression to deriv.
deriv.addCommandObject( new Cmd(sumVar, (ExpressionProgram)sumExpr.derivative(wrt)) );
}
}
public int extent(ExpressionProgram prog, int myIndex) {
// The ExpressionCommand occurs in the program prog at the index indicated by myIndex.
// Return the total number of indices in prog occupied by this command and the commands
// that generate data used by this command. In this case, that means the commands that
// compute the upper and lower limits of the summatio, plus this Cmd object.
int upper = prog.extent(myIndex - 1); // Extent of upper limit expression in prog.
int lower = prog.extent(myIndex - 1 - upper); // Extent of lower limit expression in prog.
return upper + lower + 1; // Upper + lower limits + this object.
}
public boolean dependsOn(Variable x) {
// Return true if this command depends on the value of x, false otherwise.
// That is, when apply() is called, can the result depend on the value of x?
return sumExpr.dependsOn(x);
}
public void appendOutputString(ExpressionProgram prog, int myIndex, StringBuffer buffer) {
// The ExpressionCommand occurs in the program prog at the index indicated by myIndex.
// Add a print string representation of the sub-expression represented by this command
// (including any previous commands in the program that generate data used by this
// command).
int upper = prog.extent(myIndex - 1);
buffer.append("sum(");
buffer.append(sumVar.getName());
buffer.append(", ");
prog.appendOutputString(myIndex - 1 - upper,buffer);
buffer.append(", ");
prog.appendOutputString(myIndex - 1, buffer);
buffer.append(", ");
buffer.append(sumExpr.toString());
buffer.append(")");
}
} // end nested class Cmd
 
} // end SumParserExtension
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/functions/TableFunction.java
0,0 → 1,635
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.functions;
import edu.hws.jcm.data.*;
 
/**
* A TableFunction is a function that is specified by a table of (x,y)-points.
* Values are interpolated between the specified x-values. This can be done
* in several differnt ways; the method that is used is controlled by the
* "Style" property. Since a TableFunction extends FunctionParserExtension,
* a TableFunction can be added to a Parser (provided it has a name), and
* it can then be used in expressions parsed by that parser. Note that this
* class is meant to be used for functions that are defined by a fairly
* small number of points, since each function evaluation involves a linear
* search through the list of x-values of the defining points.
*/
public class TableFunction extends FunctionParserExtension {
 
/**
* If the style of the function is set to SMOOTH,
* then cubic interpolation is used to find the value
* of the functions for x-values between the points that define the function.
*/
public static final int SMOOTH = 0;
/**
* If the style of the function is set to PIECEWISE_LINEAR,
* then linear interpolation is used to find the value
* of the functions for x-values between the points that define the function.
*/
public static final int PIECEWISE_LINEAR = 1;
 
/**
* If the style of the function is set to STEP, then the function is
* piecewise constant, and the value of the function at x is taken
* from the nearest point in the list of points that define the function.
*/
public static final int STEP = 2;
 
/**
* If the style of the function is set to STEP_LEFT, then the function is
* piecewise constant, and the value of the function at x is taken
* from the nearest point to the left in the list of points that define the function.
*/
 
public static final int STEP_LEFT = 3;
 
/**
* If the style of the function is set to STEP_RIGHT, then the function is
* piecewise constant, and the value of the function at x is taken
* from the nearest point to the right in the list of points that define the function.
*/
public static final int STEP_RIGHT = 4;
 
 
private int style; // Type of function, given by one of the above constants.
private double[] xCoords = new double[10]; // x-coordinates, in increasing order
private double[] yCoords = new double[10]; // the corresponding y-coordinates
private CubicSegment[] segments; // interpolation data for SMOOTH style
private int pointCt; // number of points (possibly less than xCoords.length)
/**
* Create a TableFunction with SMOOTH style and no points.
*/
public TableFunction() {
this(SMOOTH);
}
/**
* Create a TableFunction with specified style and no points.
*
* @param style The style for the function: SMOOTH, PIECEWISE_LINEAR, STEP,
* STEP_LEFT, or STEP_RIGHT.
*/
public TableFunction(int sytle) {
this.style = style;
if (style == SMOOTH)
segments = new CubicSegment[9];
}
/**
* Copy data from another TableFunction, except that the name of the funcion is
* not duplicated. The new TableFunction is nameless.
*/
public void copyDataFrom(TableFunction source) {
xCoords = (double[])source.xCoords.clone();
yCoords = (double[])source.yCoords.clone();
style = -1; // Force setStyle to compute data for SMOOTH style.
setStyle(source.style);
}
/**
* Set the style of this TableFunction, to specify how values are interpolated
* between points on the curve.
*
* @param style One of the style constants SMOOTH, PIECEWISE_LINEAR, STEP,
* STEP_LEFT, STEP_RIGHT. Other values are ignored.
*/
public void setStyle(int style) {
if (style == this.style || style < 0 || style > 4)
return;
this.style = style;
if (style == SMOOTH) {
segments = new CubicSegment[xCoords.length - 1];
for (int i = 0; i < pointCt-1; i++)
segments[i] = new CubicSegment(xCoords[i],xCoords[i+1],yCoords[i],yCoords[i+1],0,0);
for (int i = 0; i < pointCt-1; i++)
interpolateDerivatives(i);
}
else {
segments = null;
}
}
/**
* Get the style of this TableFunction, which specifies how values are
* interpolated between points on the curve.
*
* @return The style of this TableFunction. This is one of the constants
* SMOOTH, PIECEWISE_LINEAR, STEP, STEP_LEFT, or STEP_RIGHT.
*/
public int getStyle() {
return style;
}
/**
* Add points to the table. The x-coordinates of the points are taken from
* the xCoords array. The y-coordinate for the i-th point is yCoords[i], if
* an i-th position exists in this array. Otherwise, the y-coordinate is
* is zero. (Note that if xCoords[i] duplicates an x-value already in
* the table, then no new point is added but the corresponging y-value is changed.)
*
* @param xCoords A list of x-coordinates to be added to the table. If this is
* null, then nothing is done.
* @param yCoords The value of yCoords[i], if it exists, is the y-coordinate
* corresponding to xCoords[i]. Otherwise, the y-coordinate is undefined.
* This can be null, in which case all y-coordinates are zero.
*/
public void addPoints(double[] xCoords, double[] yCoords) {
if (xCoords == null)
return;
int ct = xCoords.length;
if (yCoords == null)
ct = 0;
else if (yCoords.length < ct)
ct = yCoords.length;
for (int i = 0; i < ct; i++)
addPoint(xCoords[i], yCoords[i]);
for (int i = ct; i < xCoords.length; i++)
addPoint(xCoords[i],0);
}
/**
* Add points to the table. The number of points added is intervals + 1.
* The x-coordinates are evenly spaced between xmin and xmax. The y-coordinates
* are zero.
*
* @param intervals The number of intervals. The number of points added is intervals + 1.
* The value should be at least 1. If not, nothing is done.
* @param xmin The minimim x-coordinate for added points.
* @param xmax The maximum x-coodinate for added points. Should be greater than
* xmin, for efficiency, but no error occurs if it is not.
*/
public void addIntervals(int intervals, double xmin, double xmax) {
if (intervals < 1)
return;
double dx = (xmax - xmin) / intervals;
for (int i = 0; i < intervals; i++)
addPoint(xmin + i*dx, 0);
addPoint(xmax, 0);
}
/**
* Add a point with the specified x and y coordinates. If a point with the
* given x coordinate already exists in the table, then no new point is added,
* but the associated y-value is changed.
* (If x is Double.NaN, then no change is made and the return value is -1.)
*
* @param x The x-coordinate of the point to be added or modified.
* @param y The y-coordinate of the point.
* @return the position of the point in the list of points, where the first point is at position zero.
*/
public int addPoint(double x, double y) {
if (Double.isNaN(x))
return -1;
int pos = 0;
while (pos < pointCt && xCoords[pos] < x)
pos++;
if (pos < pointCt && xCoords[pos] == x) {
yCoords[pos] = y;
}
else {
if (pointCt == xCoords.length) {
double[] temp = new double[2*xCoords.length];
System.arraycopy(xCoords,0,temp,0,xCoords.length);
xCoords = temp;
temp = new double[2*yCoords.length];
System.arraycopy(yCoords,0,temp,0,yCoords.length);
yCoords = temp;
if (style == SMOOTH) {
CubicSegment[] temps = new CubicSegment[xCoords.length - 1];
System.arraycopy(segments,0,temps,0,pointCt - 1);
segments = temps;
}
}
for (int i = pointCt; i > pos; i--) {
xCoords[i] = xCoords[i-1];
yCoords[i] = yCoords[i-1];
}
xCoords[pos] = x;
yCoords[pos] = y;
if (style == SMOOTH && pointCt > 0) {
if (pos == pointCt)
segments[pointCt - 1] = new CubicSegment();
else {
for (int i = pointCt-1; i > pos; i--)
segments[i] = segments[i-1];
segments[pos] = new CubicSegment();
}
}
pointCt++;
}
if (style == SMOOTH && pointCt > 0) { // make sure segment data is OK for segments that depend on (x,y)
if (pos > 0)
segments[pos-1].setData(xCoords[pos-1],xCoords[pos],yCoords[pos-1],yCoords[pos],0,0);
if (pos < pointCt-1)
segments[pos].setData(xCoords[pos],xCoords[pos+1],yCoords[pos],yCoords[pos+1],0,0);
for (int i = pos - 2; i <= pos + 1; i++)
interpolateDerivatives(i);
}
return pos;
}
private void interpolateDerivatives(int pos) {
// Compute correct derivatives for segments[pos] from data in coordinate arrays.
if (pos < 0 || pos > pointCt - 2)
return;
// pointCt must be >= 2
if (pointCt == 2) // pos must be 0
segments[0].setDerivativesFromNeighbors(Double.NaN,0,Double.NaN,0);
else if (pos == 0)
segments[0].setDerivativesFromNeighbors(Double.NaN,0,xCoords[2],yCoords[2]);
else if (pos == pointCt - 2)
segments[pointCt-2].setDerivativesFromNeighbors(xCoords[pointCt-3],yCoords[pointCt-3],Double.NaN,0);
else
segments[pos].setDerivativesFromNeighbors(xCoords[pos-1],yCoords[pos-1],xCoords[pos+2],yCoords[pos+2]);
}
/**
* Gets the number of points in the table.
*/
public int getPointCount() {
return pointCt;
}
/**
* Get the x-coordinate in the i-th point, where the first point
* is number zero. Throws an IllegalArgumentException if i is
* less than zero or greater than or equal to the number of points.
*/
public double getX(int i) {
if (i >= 0 && i < pointCt)
return xCoords[i];
else
throw new IllegalArgumentException("Point index out of range: " + i);
}
/**
* Get the y-coordinate in the i-th point, where the first point
* is number zero. Throws an IllegalArgumentException if i is
* less than zero or greater than or equal to the number of points.
*/
public double getY(int i) {
if (i >= 0 && i < pointCt)
return yCoords[i];
else
throw new IllegalArgumentException("Point index out of range: " + i);
}
/**
* Set the y-coordinate in the i-th point to y, where the first point
* is number zero. Throws an IllegalArgumentException if i is
* less than zero or greater than or equal to the number of points.
*/
public void setY(int i, double y) {
if (i >= 0 && i < pointCt)
yCoords[i] = y;
else
throw new IllegalArgumentException("Point index out of range: " + i);
if (style == SMOOTH) {
if (i > 0)
segments[i-1].setData(xCoords[i-1],xCoords[i],yCoords[i-1],yCoords[i],0,0);
if (i < pointCt - 1)
segments[i].setData(xCoords[i],xCoords[i+1],yCoords[i],yCoords[i+1],0,0);
for (int j = i-2; j <= i+1; j++)
interpolateDerivatives(j);
}
}
/**
* If there is a point in the list with x-coordinate x, then this function returns
* the index of that point in the list (where the index of the first point is zero).
* If there is no such point, then -1 is returned.
*/
public int findPoint(double x) {
int i = 0;
while (i < pointCt) {
if (x == xCoords[i])
return i;
else if (x > xCoords[i])
i++;
else
break;
}
return -1;
}
/**
* Removes the i-th point from the list of points. Throws an IllegalArgumentException if i is
* less than zero or greater than or equal to the number of points.
*/
public void removePointAt(int i) {
if (i < 0 || i >= pointCt)
throw new IllegalArgumentException("Point index out of range: " + i);
pointCt--;
for (int j = i; j < pointCt; j++) {
xCoords[j] = xCoords[j+1];
yCoords[j] = yCoords[j+1];
}
if (style == SMOOTH) {
style = -1; // force recompute of data
setStyle(SMOOTH);
}
}
/**
* Remove all points. The resulting function is undefined everywhere.
*/
public void removeAllPoints() {
pointCt = 0;
xCoords = new double[10];
yCoords = new double[10];
}
/**
* Get the value of the function at x, using interpolation if x lies between
* two x-coordinates in the list of points that define the function. If x is
* outside the range of x-coords in the table, the value of the function is Double.NaN.
*/
public double getVal(double x) {
return computeValue(x,null,0);
}
private double computeValue(double x, Cases cases, int derivativeLevel) {
// Find the value of the function or one of its derivatives at x.
// If cases is not null, then a value is added to cases to help
// with continuity computations.
if (Double.isNaN(x))
return Double.NaN;
if (pointCt == 0 || x < xCoords[0] || x > xCoords[pointCt-1])
return Double.NaN;
if (pointCt == 1) {
if (derivativeLevel > 0)
return Double.NaN;
else {
if (cases == null)
cases.addCase(0);
return yCoords[0];
}
}
int casenum;
double ans;
int seg = 0;
switch (style) {
case STEP: {
while (seg < pointCt - 1 && x > (xCoords[seg] + xCoords[seg+1])/2)
seg++;
casenum = seg;
if (derivativeLevel == 0)
ans = yCoords[seg];
else if (x < (xCoords[seg] + xCoords[seg+1])/2 || seg == pointCt - 1 || yCoords[seg] == yCoords[seg + 1])
ans = 0;
else
ans = Double.NaN;
break;
}
case STEP_RIGHT: {
while (seg < pointCt-1 && x > xCoords[seg])
seg++;
casenum = seg;
if (derivativeLevel == 0)
ans = yCoords[seg];
else if (x < xCoords[seg] || seg >= pointCt - 1 || yCoords[seg] == yCoords[seg+1])
ans = 0;
else
ans = Double.NaN;
break;
}
case STEP_LEFT: {
while (seg < pointCt-1 && x >= xCoords[seg+1])
seg++;
casenum = seg;
if (derivativeLevel == 0)
ans = yCoords[seg];
else if (x > xCoords[seg] || seg == 0 || yCoords[seg] == yCoords[seg-1])
ans = 0;
else
ans = Double.NaN;
break;
}
case PIECEWISE_LINEAR: {
while (seg < pointCt-1 && x > xCoords[seg])
seg++;
casenum = seg;
if (x == xCoords[seg]) {
if (derivativeLevel == 0)
ans = yCoords[seg];
else if (seg == 0) {
if (derivativeLevel == 1)
ans = (yCoords[1] - yCoords[0]) / (xCoords[1] - xCoords[0]);
else
ans = 0;
}
else if (seg == pointCt-1) {
if (derivativeLevel == 1)
ans = (yCoords[pointCt-1] - yCoords[pointCt-2]) / (xCoords[pointCt-1] - xCoords[pointCt-2]);
else
ans = 0;
}
else {
double leftslope = (yCoords[seg] - yCoords[seg-1]) / (xCoords[seg] - xCoords[seg-1]);
double rightslope = (yCoords[seg] - yCoords[seg+1]) / (xCoords[seg] - xCoords[seg+1]);
if (Math.abs(leftslope - rightslope) < 1e-12) {
if (derivativeLevel == 1)
ans = leftslope;
else
ans = 0;
}
else
ans = Double.NaN;
}
}
else { // x < xCoords[seg] && x > xCoords[seg-1]
if (derivativeLevel == 0) {
ans = yCoords[seg-1] + ((yCoords[seg] - yCoords[seg-1]) / (xCoords[seg] - xCoords[seg-1]))*(x - xCoords[seg-1]);
}
else if (derivativeLevel == 1) {
ans = (yCoords[seg] - yCoords[seg-1]) / (xCoords[seg] - xCoords[seg-1]);
}
else
ans = 0;
}
break;
}
default: { // SMOOTH
while (seg < pointCt-2 && x > xCoords[seg+1])
seg++;
casenum = seg;
if (x == xCoords[seg+1] && seg < pointCt-2 && seg > 0) {
if (derivativeLevel == 0)
ans = yCoords[seg+1];
else if (derivativeLevel == 1)
ans = segments[seg].derivativeValue(x,1);
else {
double leftslope = segments[seg-1].derivativeValue(x,2);
double rightslope = segments[seg].derivativeValue(x,2);
if (Math.abs(leftslope - rightslope) < 1e-12)
ans = segments[seg].derivativeValue(x,derivativeLevel);
else
ans = Double.NaN;
}
}
else { // x < xCoords[seg] && x > xCoords[seg-1]
ans = segments[seg].derivativeValue(x,derivativeLevel);
}
}
}
if (cases != null)
cases.addCase(casenum);
return ans;
}
//---------------- Methods from the Function class -----------------
/**
* Get the value of the function at the specified parameter value.
*
* @params param should be an array of length 1 holding the argument of the function.
* However if the length is greater than one, the extra arguments are simply ignored.
* @cases if cases is non-null, a case value is stored here, for help in continuity computations.
*/
public double getValueWithCases(double[] params, Cases cases) {
return computeValue(params[0],cases,0);
}
/**
* Get the value of the function at the specified parameter value.
*
* @partam param should be an array of length 1 holding the argument of the function.
* However if the length is greater than one, the extra arguments are simply ignored.
*/
public double getVal(double[] params) {
return computeValue(params[0], null, 0);
}
/**
* Compute the derivative of this function. The value of the parameter, wrt, must be 1 or an
* IllegalArguemntException will be thrown.
*/
public Function derivative(int wrt) {
if (wrt != 1)
throw new IllegalArgumentException("Attempt to take the derivative of a function of one argument with respect to argument number " + wrt);
return new Deriv(this);
}
/**
* Returns null.
* It really should be the constant function zero, but I don't expect this ever to be
* called. Since dependsOn(wrt) returns false, it will never be called within the JCM system.
*/
public Function derivative(Variable wrt) {
return null;
}
/**
* Returns false.
*/
public boolean dependsOn(Variable wrt) {
return false;
}
/**
* Returns the arity of the function, which is 1.
*/
public int getArity() {
return 1;
}
/**
* Override method apply() from interface FunctionParserExtension, to handle cases properly.
* Not meant to be called directly.
*/
public void apply(StackOfDouble stack, Cases cases) {
double x = stack.pop();
stack.push(computeValue(x,cases,0));
}
//---------------- For creating derivatives ------------------------
private static class Deriv extends FunctionParserExtension {
// An object of this class represents a derivative function
// of a TableFunction.
 
TableFunction derivativeOf; // The function from which this function is derived.
 
int derivativeLevel; // The order of the derivative.
Deriv(Deriv f) {
derivativeLevel = f.derivativeLevel + 1;
derivativeOf = f.derivativeOf;
}
Deriv(TableFunction f) {
derivativeLevel = 1;
derivativeOf = f;
}
public String getName() { // Name comes from the name of the function.
String name = derivativeOf.getName();
for (int i = 0; i < derivativeLevel; i++)
name += "'";
return name;
}
public void setName(String name) {
}
public double getValueWithCases(double[] params, Cases cases) {
return derivativeOf.computeValue(params[0],cases,derivativeLevel);
}
public double getVal(double[] params) {
return derivativeOf.computeValue(params[0],null,derivativeLevel);
}
public Function derivative(int wrt) {
if (wrt != 1)
throw new IllegalArgumentException("Attempt to take the derivative of a function of one argument with respect to argument number " + wrt);
return new Deriv(this);
}
public Function derivative(Variable wrt) {
return null;
}
public boolean dependsOn(Variable wrt) {
return false;
}
public int getArity() {
return 1;
}
 
public void apply(StackOfDouble stack, Cases cases) {
double x = stack.pop();
stack.push(derivativeOf.computeValue(x,cases,derivativeLevel));
}
} // end class Deriv
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/functions/TableFunctionInput.java
0,0 → 1,668
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.functions;
 
import java.awt.*;
import java.awt.event.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
import edu.hws.jcm.draw.*;
 
 
/**
* A TableInputFunction is a Panel that can be used to define a TableFunction
* or to edit an existing TableFunction. To fetch the function currently
* displayed in the panel, call copyOfCurrentFunction(). To edit a function,
* call startEdit() to install the function. Then call cancelEdit() or
* finishEdit() to finish the editing. The panel displays both the graph
* of the function and a list of points that define the function. The user
* can drag the points on the graph up and down to change the y-values.
* Points can be added or modified by typing in their x- and y-coordinates.
* A point can be deleted by clicking it in the list of points and then
* clicking on the button labeled "Delete Point".
*/
public class TableFunctionInput extends Panel
implements ItemListener, ActionListener, MouseListener, MouseMotionListener {
private VariableInput xInput, yInput; // Components of the GUI.
private DisplayCanvas canvas;
private List pointList;
private Button clearButton, deleteButton, addButton;
private Checkbox[] styleCheckbox = new Checkbox[5];
private CheckboxGroup styleGroup;
private Controller onChange; // If non-null, the compute() method of the controller
// is called when the user edits a point.
private TableFunction function; // The function displayed.
private TableFunction editFunction; // If non-null, the function passed to startEdit.
 
 
/**
* Create a TableFunctionInput panel. Initially, the function in the
* panel has no points and so is undefined everywhere. The panel needs
* to be fairly large!
*/
public TableFunctionInput() {
xInput = new VariableInput();
xInput.addActionListener(this);
yInput = new VariableInput();
yInput.addActionListener(this);
pointList = new List();
pointList.setBackground(Color.white);
pointList.setFont(new Font("Monospaced",Font.PLAIN,12));
pointList.addItemListener(this);
clearButton = new Button("Remove All Points");
clearButton.addActionListener(this);
deleteButton = new Button("Delete Point");
deleteButton.setEnabled(false);
deleteButton.addActionListener(this);
addButton = new Button("Add/Modify Point");
addButton.addActionListener(this);
styleGroup = new CheckboxGroup();
styleCheckbox[0] = new Checkbox("Smooth", true, styleGroup);
styleCheckbox[1] = new Checkbox("Piecewise Linear", false, styleGroup);
styleCheckbox[2] = new Checkbox("Step (nearest value)", false, styleGroup);
styleCheckbox[3] = new Checkbox("Step (value from left)", false, styleGroup);
styleCheckbox[4] = new Checkbox("Step (value from right)", false, styleGroup);
for (int i = 0; i < 5; i++)
styleCheckbox[i].addItemListener(this);
canvas = new DisplayCanvas( new CoordinateRect(-1,1,-1,1) );
canvas.add(new Axes());
canvas.addMouseListener(this);
canvas.addMouseMotionListener(this);
function = new TableFunction();
canvas.add(new Draw());
Font labelFont = new Font("Serif", Font.BOLD, 12);
Label lab1 = new Label("Input Area");
lab1.setForeground(Color.red);
lab1.setFont(labelFont);
Label lab2 = new Label("Type of Function", Label.CENTER);
lab2.setForeground(Color.red);
lab2.setFont(labelFont);
Label lab3 = new Label("Table of Values", Label.CENTER);
lab3.setForeground(Color.red);
lab3.setFont(labelFont);
Panel topLeft = new Panel();
topLeft.setLayout(new FlowLayout(FlowLayout.CENTER, 10000,3));
Panel topRight = new Panel();
topRight.setLayout(new GridLayout(6,1,3,3));
Panel bottomLeft = new Panel();
bottomLeft.setLayout(new BorderLayout());
Panel top = new Panel();
top.setLayout(new BorderLayout(3,3));
top.add(topLeft,BorderLayout.CENTER);
top.add(topRight,BorderLayout.EAST);
setLayout(new BorderLayout(3,3));
add(top,BorderLayout.NORTH);
add(bottomLeft, BorderLayout.WEST);
add(canvas, BorderLayout.CENTER);
setBackground(Color.darkGray);
topLeft.setBackground(Color.lightGray);
topRight.setBackground(Color.lightGray);
bottomLeft.setBackground(Color.lightGray);
Panel inputBar = new Panel();
inputBar.add(new Label("x = "));
inputBar.add(xInput);
inputBar.add(new Label(" y = "));
inputBar.add(yInput);
Panel buttonBar = new Panel();
buttonBar.setLayout(new GridLayout(1,2,3,3));
buttonBar.add(deleteButton);
buttonBar.add(clearButton);
topLeft.add(lab1);
topLeft.add(inputBar);
topLeft.add(addButton);
topLeft.add(new Label("(Press RETURN in X to move to Y)"));
topLeft.add(new Label("(Press RETURN in Y to add/modify point)"));
 
topRight.add(lab2);
for (int i = 0; i < 5; i++)
topRight.add(styleCheckbox[i]);
bottomLeft.add(pointList, BorderLayout.CENTER);
bottomLeft.add(lab3, BorderLayout.NORTH);
bottomLeft.add(buttonBar, BorderLayout.SOUTH);
} // end constructor
//------------------- Methods for modifying an existing function --------------
/**
* Install a function to be edited. The data from the function is
* copied into the panel, and a pointer to the function is retained.
* Note that the function itself is not changed by any editing that
* the user does. To commit the changes made by the user to the
* actual function, you must call finishEdit(). If f is null,
* the effect is to start with a new, empty function.
*/
public void startEdit(TableFunction f) {
editFunction = f;
revertEditFunction(); // Installs data from function.
}
/**
* If a function has been specified using startEdit(), and neither
* finishEdit() nor cancelEdit have been called, then this method
* will discard the current data in and replace it with data from
* the edit function. If there is no edit function, then the data
* is simply discarded. (That is, the data reverts to an empty point list.)
*/
public void revertEditFunction() {
if (editFunction == null) {
clearAllPoints();
return;
}
function.copyDataFrom(editFunction);
pointList.removeAll();
int pointCt = function.getPointCount();
for (int i = 0; i < pointCt; i++)
pointList.add(makePointString(function.getX(i),function.getY(i)));
styleGroup.setSelectedCheckbox(styleCheckbox[function.getStyle()]);
checkCanvas();
if (onChange != null)
onChange.compute();
}
/**
* If an edit function has been specified (by startEdit()), this function copies the
* data form the TableFunctionInput into that function, and returns a
* pointer to that function. This ends the edit session, and the internally stored
* pointer to the edit function is discarded. If no edit function has been specified
* then a new TableFunction is created with the data from the panel, and a
* pointer to the new function is returned. This does not clear the data
* in the TableFunctionInput panel.
*/
public TableFunction finishEdit() {
TableFunction func;
if (editFunction == null)
func = copyOfCurrentFunction();
else {
editFunction.copyDataFrom(function);
func = editFunction;
editFunction = null;
}
return func;
}
/**
* Discards the internal pointer to the edit function (specified by startEdit()),
* if any. This does not clear the data in the TableFunctionInput panel.
*/
public void cancelEdit() {
editFunction = null;
}
 
/**
* Create a new TableFunction containing the data that is currently
* in the TableFunctionInput panel, and return a pointer to that new function.
*/
public TableFunction copyOfCurrentFunction() {
TableFunction copy = new TableFunction();
copy.copyDataFrom(function);
copy.setName(function.getName());
return copy;
}
/**
* Specify a controller whose compute() method will be called whenever
* the user edits the data in this TableFunctionInput panel. (Note that
* when the user edits the function by dragging a point, the Controller
* is only called once at the end of the drag.) If the specified
* Controller is null, then no notification takes place.
*/
public void setOnChange(Controller c) {
onChange = c;
}
/**
* Get the Controller that is notified when the user edits the data
* in this panel. The return value can be null (the default), indicating
* that no notification takes place.
*/
public Controller getOnChange() {
return onChange;
}
private void deletePoint() {
// delete point selected in the point list, if any
int index = pointList.getSelectedIndex();
if (index >= 0) {
pointList.remove(index);
function.removePointAt(index);
checkCanvas();
if (onChange != null)
onChange.compute();
}
deleteButton.setEnabled(false);
}
private void clearAllPoints() {
// remove all points, leaving an empty point list
function.removeAllPoints();
pointList.removeAll();
deleteButton.setEnabled(false);
if (onChange != null)
onChange.compute();
checkCanvas();
}
private void addPoint() {
// add the point whose coords are specified in the x and y input boxes;
// if the x-value already exits, then the corresponding y-value is changed.
double x,y;
try {
xInput.checkInput();
x = xInput.getVal();
}
catch (JCMError e) {
canvas.setErrorMessage(null,"The input for x does is not a legal real number.");
xInput.requestFocus();
xInput.selectAll();
return;
}
try {
yInput.checkInput();
y = yInput.getVal();
}
catch (JCMError e) {
canvas.setErrorMessage(null,"The input for y does is not a legal real number.");
yInput.requestFocus();
yInput.selectAll();
return;
}
String str = makePointString(x,y);
int index = function.findPoint(x);
if (index >= 0 && y == function.getY(index)) {
xInput.requestFocus();
xInput.selectAll();
return;
}
int newindex = function.addPoint(x,y);
if (index >= 0)
pointList.replaceItem(str,index);
else
pointList.addItem(str,newindex);
deleteButton.setEnabled(pointList.getSelectedIndex() != -1);
checkCanvas();
if (onChange != null)
onChange.compute();
xInput.requestFocus();
xInput.selectAll();
}
private String makePointString(double x, double y) {
// Make a string representing (x,y), using exactly 11 spaces for each number.
String X = NumUtils.realToString(x);
String Y = NumUtils.realToString(y);
if (X.length() < 11)
X = " ".substring(0,11 - X.length()) + X;
if (Y.length() < 11)
Y = " ".substring(0,11 - Y.length()) + Y;
return X + " " + Y;
}
private void selectPoint() {
// React when user selects a point in the list of points.
int index = pointList.getSelectedIndex();
if (index >= 0) {
xInput.setVal(function.getX(index));
yInput.setVal(function.getY(index));
yInput.requestFocus();
yInput.selectAll();
}
deleteButton.setEnabled(index >= 0);
}
private void changeStyle() {
// React when user changes style of function.
int newstyle = 0;
Checkbox selected = styleGroup.getSelectedCheckbox();
for (int i = 1; i < 5; i++)
if (selected == styleCheckbox[i])
newstyle = i;
if (function.getStyle() == newstyle)
return;
function.setStyle(newstyle);
canvas.doRedraw();
if (onChange != null)
onChange.compute();
}
private void checkCanvas() {
// Adjust limits on canvas, if necessary, and redraw it.
int ct = function.getPointCount();
double newXmin = -1, newXmax = 1, newYmin = -1, newYmax = 1;
if (ct > 0) {
if (ct == 1) {
newXmin = function.getX(0);
if (Math.abs(newXmin) < 10000) {
newXmax = newXmin + 1;
newXmin -= 1;
}
else {
newXmax = newXmin - Math.abs(newXmin)/10;
newXmin -= Math.abs(newXmin)/10;
}
}
else {
newXmin = function.getX(0);
newXmax = function.getX(ct - 1);
}
newYmin = function.getY(0);
newYmax = newYmin;
for (int i = 1; i < ct; i++) {
double y = function.getY(i);
if (y < newYmin)
newYmin = y;
else if (y > newYmax)
newYmax = y;
}
double size = Math.abs(newYmin - newYmax);
if (size < 1e-10 && Math.abs(newYmin) < 10000 && Math.abs(newYmax) < 10000) {
newYmax += 1;
newYmin -= 1;
}
else {
newYmax += size*0.15;
newYmin -= size*0.15;
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
double curSize = Math.abs(coords.getYmin() - coords.getYmax());
double newSize = Math.abs(newYmax - newYmin);
if (newXmax != coords.getXmax() || newXmin != coords.getXmin()
|| newSize > 1.3*curSize || newSize < 0.5*curSize
|| newYmax > coords.getYmax() - 0.1*curSize
|| newYmin < coords.getYmin() + 0.1*curSize)
coords.setLimits(newXmin,newXmax,newYmin,newYmax);
canvas.doRedraw();
}
/**
* Leave a 3-pixel gap around the edges of the panel. Not meant to be called directly.
*/
public Insets getInsets() {
return new Insets(3,3,3,3);
}
/**
* React when user clicks one of the buttons or presses return in one
* of the input boxes. Not meant to be called directly.
*/
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == deleteButton)
deletePoint();
else if (source == clearButton)
clearAllPoints();
else if (source == xInput) {
yInput.requestFocus();
yInput.selectAll();
}
else
addPoint();
}
/**
* React when user clicks on a point in the list of points or clicks one
* of the radio buttons for specifying the style of the function.
* Not meant to be called directly.
*/
public void itemStateChanged(ItemEvent evt) {
if (evt.getSource() == pointList)
selectPoint();
else
changeStyle();
}
//-------------------- Dragging --------------------------
private int dragPoint = -1; // -1 if no point is being dragged;
// Otherwise, the index of the point being dragged.
private int startX, startY; // Point where mouse was clicked at start of drag.
private int prevY; // Previous position of mouse during dragging.
 
private boolean moved; // Becomes true once the clicked point has actually
// been dragged a bit. If the mouse is released before
// the point is moved at least 3 pixels, then the associated
// y-value is not changed.
/**
* Method required by the MouseListener interface. Defined here to
* support dragging of points on the function's graph. Not meant to be called directly.
*/
public void mousePressed(MouseEvent evt) {
dragPoint = -1;
moved = false;
int ct = function.getPointCount();
CoordinateRect coords = canvas.getCoordinateRect(0);
for (int i = 0; i < ct; i++) {
int x = coords.xToPixel(function.getX(i));
int y = coords.yToPixel(function.getY(i));
if (evt.getX() >= x-3 && evt.getX() <= x+3 && evt.getY() >= y-3 && evt.getY() <= y+3) {
startX = evt.getX();
prevY = startY = evt.getY();
pointList.deselect(pointList.getSelectedIndex());
pointList.select(i);
selectPoint();
dragPoint = i;
return;
}
}
}
/**
* Method required by the MouseListener interface. Defined here to
* support dragging of points on the function's graph. Not meant to be called directly.
*/
public void mouseReleased(MouseEvent evt) {
if (dragPoint == -1)
return;
if (!moved) {
dragPoint = -1;
return;
}
mouseDragged(evt);
pointList.replaceItem(makePointString(function.getX(dragPoint),function.getY(dragPoint)), dragPoint);
pointList.select(dragPoint);
dragPoint = -1;
if (onChange != null)
onChange.compute();
}
/**
* Method required by the MouseListener interface. Defined here to
* support dragging of points on the function's graph. Not meant to be called directly.
*/
public void mouseDragged(MouseEvent evt) {
if (dragPoint == -1 || prevY == evt.getY())
return;
if (!moved && Math.abs(evt.getY() - startY) < 3)
return;
moved = true;
int y = evt.getY();
CoordinateRect coords = canvas.getCoordinateRect(0);
if (y < coords.getTop() + 4)
y = coords.getTop() + 4;
else if (y > coords.getTop() + coords.getHeight() - 4)
y = coords.getTop() + coords.getHeight() - 4;
if (Math.abs(evt.getX() - startX) > 72)
y = startY;
if (y == prevY)
return;
prevY = y;
function.setY(dragPoint, coords.pixelToY(prevY));
yInput.setVal(function.getY(dragPoint));
canvas.doRedraw();
}
/**
* Empty method, required by the MouseListener interface.
*/
public void mouseClicked(MouseEvent evt) { }
 
/**
* Empty method, required by the MouseMotionListener interface.
*/
public void mouseEntered(MouseEvent evt) { }
 
/**
* Empty method, required by the MouseMotionListener interface.
*/
public void mouseExited(MouseEvent evt) { }
 
/**
* Empty method, required by the MouseMotionListener interface.
*/
public void mouseMoved(MouseEvent evt) { }
//--------------------------------------------------------
private class Draw extends Drawable{
// An object of this nested class is added to the canvas
// of the TableFunctionInput panel. It is responsible for
// drawing the function.
public void draw(Graphics g, boolean coordsChanged) {
int ct = function.getPointCount();
if (ct == 0)
return;
g.setColor(Color.magenta);
int xInt,yInt, aInt, bInt;
double x,y, a,b;
switch (function.getStyle()) {
case TableFunction.SMOOTH: {
if (ct > 1) { try {
x = function.getX(0);
y = function.getVal(x);
xInt = coords.xToPixel(x);
yInt = coords.yToPixel(y);
int limit = coords.xToPixel(function.getX(ct-1));
aInt = xInt;
while (aInt < limit) {
aInt += 3;
if (aInt > limit)
aInt = limit;
a = coords.pixelToX(aInt);
b = function.getVal(a);
bInt = coords.yToPixel(b);
g.drawLine(xInt,yInt,aInt,bInt);
xInt = aInt;
yInt = bInt;
} } catch (Exception e) { e.printStackTrace(); }
}
break;
}
case TableFunction. PIECEWISE_LINEAR: {
x = function.getX(0);
xInt = coords.xToPixel(x);
y = function.getY(0);
yInt = coords.yToPixel(y);
for (int i = 1; i < ct; i++) {
a = function.getX(i);
aInt = coords.xToPixel(a);
b = function.getY(i);
bInt = coords.yToPixel(b);
g.drawLine(xInt,yInt,aInt,bInt);
xInt = aInt;
yInt = bInt;
}
break;
}
case TableFunction.STEP: {
x = function.getX(0);
xInt = coords.xToPixel(x);
for (int i = 0; i < ct; i++) {
if (i < ct - 1) {
double nextX = function.getX(i+1);
a = (x + nextX)/2;
x = nextX;
}
else
a = x;
aInt = coords.xToPixel(a);
y = function.getY(i);
yInt = coords.yToPixel(y);
g.drawLine(xInt,yInt,aInt,yInt);
xInt = aInt;
}
break;
}
case TableFunction.STEP_LEFT: {
x = function.getX(0);
xInt = coords.xToPixel(x);
for (int i = 1; i < ct; i++) {
a = function.getX(i);
aInt = coords.xToPixel(a);
y = function.getY(i-1);
yInt = coords.yToPixel(y);
g.drawLine(xInt,yInt,aInt,yInt);
xInt = aInt;
}
break;
}
case TableFunction.STEP_RIGHT: {
x = function.getX(0);
xInt = coords.xToPixel(x);
for (int i = 1; i < ct; i++) {
a = function.getX(i);
aInt = coords.xToPixel(a);
y = function.getY(i);
yInt = coords.yToPixel(y);
g.drawLine(xInt,yInt,aInt,yInt);
xInt = aInt;
}
break;
}
}
for (int i = 0; i < ct; i++) {
x = function.getX(i);
y = function.getY(i);
xInt = coords.xToPixel(x);
yInt = coords.yToPixel(y);
g.fillOval(xInt-2,yInt-2,5,5);
}
}
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/functions/FunctionParserExtension.java
0,0 → 1,254
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.functions;
 
import edu.hws.jcm.data.*;
 
/**
* An object belonging to a concrete subclass of FunctionParserExtesion is a
* mathematical function that can be registered with a Parser and then used in
* strings that are parsed by that parser. (See the Function inteface
* for more information.)
*
* <p>Since a FunctionParserExtension object implements the ParserExtension interface, it
* has a name and can be registered with a Parser. When the parser
* encounters the name of a function in a string, it turns control
* of the parsing process over to the function. When a Function
* occurs in an ExpressionProgram, the Function is responsible for
* evaluating itself and for differentiating itself. This functionality
* is defined in the abstract class FunctionParserExtension. The
* concrete subclasses of FunctionParserExtension represent actual
* functions. They must implement the five methods defined
* in the Function interface, but most of the parser- and expression-related
* behavior can probably be inherited from this class. (This is good, since
* the programming is rather tricky.)
*
* <p>(The point of all this is that Parsers and Expressions can deal
* with Functions, even though there is no reference to Functions in
* the Parser or ExpressionProgram classes. Everything is done
* through the ParserExtension interface.)
*/
abstract public class FunctionParserExtension implements Function, ParserExtension, ExpressionCommand {
 
/**
* The name of this MathObject, possibly null.
*/
protected String name;
private boolean parensCanBeOptional; // This variable applies only to functions of
// arity 1. It affects the parsing of references
// to the function, and then only if the
// OPTIONAL_PARENS option is set in the parser.
// If both this variable and OPTIONAL_PARENS
// are set, then parentheses are optional
// around the argument of the function.
/**
* Call this function with b = true if this is a function of one variable
* and you want it to behave like a standard function in that parentheses
* can be optional around the argument of the function. For the parentheses
* to be treated as optional, the option Parser.OPTIONAL_PARENS must ALSO
* be set in the parser. As an example, if you wanted to define the function
* sinh and allow the syntax "sinh x", you would turn this option on in
* the Function and turn OTPTIONAL_PARENS on in the Parser.
*
* @param b set whether parenthesis are optional in one variable functions.
*/
public void setParensCanBeOptional( boolean b ) {
parensCanBeOptional = b;
}
//------ Methods from the MathObject interfaces ----------
/**
* Set the name of this object. It is not a good idea to do this
* if the object has been registered with a Parser.
*/
public void setName(String name) {
this.name = name;
}
/**
* Get the name of this MathObject.
*/
public String getName() {
return name;
}
//----------------- Method from the ParserExtension interface -----------
/**
* If this ParserExtension is registered with a parser and the parser
* encounters the name of the function in the string it is parsing,
* then the parser will call this routine. This routine parses
* the function's parameter list and generates the code for evaluating
* the function, applied to those parameters. When this routine is
* called, the name of the function has already been read. The code
* that is generated consists of code to evalueate each of the parameters,
* leaving the results on the stack, followed by an application of the
* function.
*
* @param parser parser that is parsing the string.
* @param context the ParseContext in effect at the time this method is called.
*/
public void doParse(Parser parser, ParserContext context) {
int tok = context.next();
String open = context.tokenString;
if (tok == ParserContext.OPCHARS &&
( open.equals("(") || (open.equals("[") && (context.options & Parser.BRACKETS) != 0)
|| (open.equals("{") && (context.options & Parser.BRACES) != 0) )) {
String close = open.equals("(") ? ")" : (open.equals("[") ? "]" : "}");
for (int i = 0; i < getArity(); i++) {
if (parser.parseExpression(context))
throw new ParseError("An argument of a function cannot be a logical-valued expression.", context);
tok = context.next();
if (i == getArity()-1) {
if (tok == ParserContext.OPCHARS && context.tokenString.equals(","))
throw new ParseError("Too many parameters for function \"" + getName() + "\".", context);
if (tok != ParserContext.OPCHARS || !context.tokenString.equals(close))
throw new ParseError("Expected a \"" + close + "\" at the end of the paramter list for function \"" + getName() + "\".", context);
}
else {
if (tok != ParserContext.OPCHARS || ! context.tokenString.equals(","))
throw new ParseError("Exprected a comma followed by another argument for function \"" + getName() + "\".", context);
}
}
}
else if (getArity() == 1 && (context.options & Parser.OPTIONAL_PARENS) != 0 && parensCanBeOptional) {
if (parser.parseTerm(context))
throw new ParseError("The argument of a function must be a numerical expression.", context);
}
else
throw new ParseError("Parentheses required around parameter list of function \"" + getName() + "\".", context);
context.prog.addCommandObject(this);
}
//--------------- Methods from the ExpressionCommand interface ----------
/**
* Evaluate the function applied to argument values popped from the stack,
* and leave the result on the stack. The argument values have already been
* computed and placed on the stack when this is called. They should be
* popped off the stack in reverse order. This general method can't deal
* properly with "cases", so it will probably have to be overridden in
* subclasses.
*/
public void apply(StackOfDouble stack, Cases cases) {
double[] d = new double[getArity()];
for (int i = getArity() - 1; i >= 0; i--)
d[i] = stack.pop();
stack.push( getVal(d) );
}
/**
* The function object occurs as a command at index myIndex in prog. The commands for computing
* its arguments can be found in prog in positions preceding myIndex. Generate commands for computing
* the derivative of the function reference with respect to the Variable wrt and add them to the deriv program. The
* computation of the derivative uses the chain rule.
*
* @param prog program this function object occurs in.
* @param myIndex index at which this function occurs.
* @param deriv commands for computing the derivative are placed here.
* @param wrt the derivative is taken with respect to this Variable.
*/
public void compileDerivative(ExpressionProgram prog, int myIndex, ExpressionProgram deriv, Variable wrt) {
int[] opIndex = new int[getArity()];
int size = 1;
for (int i = 0; i < getArity(); i++) { // Find the indices in prog of the arguments of the function.
opIndex[getArity()-i-1] = myIndex - size;
if (i < getArity()-1)
size += prog.extent(myIndex-size);
}
boolean output = false; // Becomes true after fist term is output.
if (dependsOn(wrt)) {
output = true;
for (int i = 0; i < opIndex.length; i++)
prog.copyExpression(opIndex[i],deriv);
deriv.addCommandObject((FunctionParserExtension)derivative(wrt));
}
for (int i = 0; i < getArity(); i++) {
if (prog.dependsOn(opIndex[i],wrt)) {
for (int j = 0; j < opIndex.length; j++)
prog.copyExpression(opIndex[j],deriv);
deriv.addCommandObject((FunctionParserExtension)derivative(i+1));
prog.compileDerivative(opIndex[i], deriv, wrt);
deriv.addCommand(ExpressionProgram.TIMES);
if (output)
deriv.addCommand(ExpressionProgram.PLUS);
output = true;
}
}
if (!output)
prog.addConstant(0);
}
/**
* Return the number of commands in prog that are part of this function reference,
* including the space occupied by the commands that compute the values of the
* function's arguments.
*
* @param prog program to check commands against.
* @param myIndex index in program.
* @return the number of commands in prog that are part of this function reference.
*/
public int extent(ExpressionProgram prog, int myIndex) {
int size = 1; // Allow for the function itself.
for (int i = 0; i < getArity(); i++)
size = size + prog.extent(myIndex - size); // Add on the size of the next argument.
return size;
}
/**
* Append a string representation of the function and its arguments to the buffer
*
* @param prog program whose string representation is being generated.
* @param myIndex index of this ExpressionCommand in prog.
* @param buffer string representation is placed here.
*/
public void appendOutputString(ExpressionProgram prog, int myIndex, StringBuffer buffer) {
int[] opIndex = new int[getArity()];
int size = 1;
for (int i = 0; i < getArity(); i++) { // Find the locations in prog of the arguemnts of the function.
opIndex[getArity()-i-1] = myIndex - size;
if (i < getArity()-1)
size += prog.extent(myIndex-size);
}
String name = getName();
buffer.append(name == null ? "(unnamed function)" : name);
buffer.append('(');
for (int i = 0; i < getArity(); i++) {
prog.appendOutputString(opIndex[i],buffer);
if (i < getArity()-1) {
buffer.append(", ");
}
}
buffer.append(')');
}
 
} // end class FunctionParserExtesion
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/functions/TableFunctionGraph.java
0,0 → 1,451
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.functions;
 
import java.awt.*;
import java.awt.event.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
import edu.hws.jcm.draw.*;
 
 
/**
* A TableFunctionGraph is a Drawable object that can be added to a CoordinateRect (or DisplayCanvas).
* It draws the graph of a specified TableFunction.
* A TableFunction is a function and can also be graphed by an object of the class edu.hws.jcm.draw.Graph1D.
* However, a TableFunctionGraph offers the option of showing the points from the table that defines
* the function as small disks (true by default) and the option of making the graph "interactive" so
* that the user can drag the points (false by default).
*/
public class TableFunctionGraph extends Drawable implements MouseListener, MouseMotionListener {
private TableFunction function; // The function that is drawn.
private boolean showPoints; // Are the points from the table shown as little disks?
private boolean interactive; // Can user drag points?
private Computable onDrag; // If interactive is true and onDrag is not null, then this
// Computable's compute() method is called each time a
// point moves as the user drags it.
private Computable onFinishDrag; // If interactive is true and onFinishDraw is not null, then this
// Computable's compute() method is called when the user
// finishes a drag operation (if the point is actually moved).
private Color color; // non-null color of the graph.
/**
* Create a TableFunctionGraph that initially draws no function. A function can be set
* later with setFunction.
*/
public TableFunctionGraph() {
this(null);
}
/**
* Create a TableFunctionGraph to draw the specified TableFunction.
*/
public TableFunctionGraph(TableFunction function) {
this.function = function;
this.color = Color.magenta;
showPoints = true;
}
/**
* Set the function whose graph is drawn by this TableFunctionGraph. If the value is null,
* nothing is drawn
*/
public void setFunction(TableFunction function) {
this.function = function;
needsRedraw();
}
/**
* Get the TableFunction whose graph is drawn by this TableFunctionGraph. If the value is null,
* then no graph is drawn.
*/
public TableFunction getFunction() {
return function;
}
 
/**
* Specify a controller whose compute() method will be called repeatedly
* as the user drags one of the points from the table function. This only
* applies if the "interactive" property is true.
*/
public void setOnDrag(Computable c) {
onDrag = c;
}
/**
* Get the Computable that is notified as the user drags a point.
*/
public Computable getOnDrag() {
return onDrag;
}
/**
* Specify a controller whose compute() method will be called once
* when the user finishes dragging one of the points from the table function.
* This only applies if the "interactive" property is true.
*/
public void setOnFinishDrag(Computable c) {
onFinishDrag = c;
}
/**
* Get the Computable that is notified when the user finishes dragging a point.
*/
public Computable getOnFinishDrag() {
return onFinishDrag;
}
/**
* Set the value of the interactive property, which is true if the user can
* modify the function by dragging the points from the table. The default is false.
*/
public void setInteractive(boolean interactive) {
if (this.interactive == interactive)
return;
if (this.interactive && canvas != null) {
canvas.removeMouseListener(this);
canvas.removeMouseMotionListener(this);
}
this.interactive = interactive;
if (this.interactive && canvas != null) {
canvas.addMouseListener(this);
canvas.addMouseMotionListener(this);
}
}
/**
* Get the value of the interactive property, which is true if the user can
* modify the function by dragging the points from the table.
*/
public boolean getInteractive() {
return interactive;
}
/**
* Set the showPoints property, which determines whether the points
* from the table that defines the function are visible as little
* disks. The default is true;
*/
public void setShowPoints(boolean show) {
showPoints = show;
needsRedraw();
}
 
/**
* Get the showPoints property, which determines whether the points
* from the table that defines the function are visible as little
* disks.
*/
public boolean getShowPoints() {
return showPoints;
}
 
 
/**
* Set the color that is used for drawing the graph. The defalt is magenta.
* If the specified Color value is null, the call to setColor is ignored.
*/
public void setColor(Color c) {
if (c != null) {
color = c;
needsRedraw();
}
}
 
/**
* Get the non-null color that is used for drawing the graph.
*/
public Color getColor() {
return color;
}
/**
* Sets the values of member variables canvas and coords. This is
* designed to be called only by the CoordinateRect class. This overrides
* Drawable.setOwnerData();
*/
protected void setOwnerData(DisplayCanvas canvas, CoordinateRect coords) {
if (interactive && this.canvas != null) {
canvas.removeMouseListener(this);
canvas.removeMouseMotionListener(this);
}
super.setOwnerData(canvas,coords);
if (interactive && this.canvas != null) {
canvas.addMouseListener(this);
canvas.addMouseMotionListener(this);
}
}
/**
* Provided as a convenience. If the function for this TableFunctionGraph is non-null,
* its style is set to the specified style, and the graph is redrawn. The parameter
* should be one of the constants TableFunction.SMOOTH, TableFunction.PIECEWISE_LINEAR,
* TableFunction.STEP, TableFunction.STEP_LEFT, or TableFunction.STEP_RIGHT.
*/
public void setFunctionStyle(int style) {
if (function != null && function.getStyle() != style) {
function.setStyle(style);
needsRedraw();
}
}
/**
* Override the draw() method from class Drawable to draw the function.
* This is not meant to be called directly.
*/
public void draw(Graphics g, boolean coordsChanged) {
if (function == null || coords == null)
return;
int ct = function.getPointCount();
if (ct == 0)
return;
int startPt; // The index of first point from the table that we have to consider
int endPt; // The index of the last point from the table that we have to consider
double xmin = coords.pixelToX(coords.getLeft());
double xmax = coords.pixelToX(coords.getLeft() + coords.getWidth());
if (function.getX(0) > xmax || function.getX(ct-1) < xmin)
return;
startPt = 0;
while (startPt < ct-1 && function.getX(startPt+1) <= xmin)
startPt++;
endPt = ct-1;
while (endPt > 1 && function.getX(endPt-1) >= xmax)
endPt--;
double x,y, a,b; // usually, two consecutive points on curve
int xInt,yInt, aInt, bInt; // usually, pixel coordinates for the two points.
g.setColor(color);
switch (function.getStyle()) {
case TableFunction.SMOOTH: {
if (endPt > startPt) {
x = function.getX(startPt);
y = function.getVal(x);
xInt = coords.xToPixel(x);
yInt = coords.yToPixel(y);
double limit = xmax;
if (function.getX(endPt) < limit)
limit = function.getX(endPt);
coords.xToPixel(function.getX(ct-1));
aInt = xInt;
while (x < limit) {
aInt += 3;
a = coords.pixelToX(aInt);
if (a > limit)
a = limit;
b = function.getVal(a);
bInt = coords.yToPixel(b);
g.drawLine(xInt,yInt,aInt,bInt);
x = a;
xInt = aInt;
yInt = bInt;
}
}
break;
}
case TableFunction. PIECEWISE_LINEAR: {
x = function.getX(startPt);
xInt = coords.xToPixel(x);
y = function.getY(startPt);
yInt = coords.yToPixel(y);
for (int i = startPt+1; i <= endPt; i++) {
a = function.getX(i);
aInt = coords.xToPixel(a);
b = function.getY(i);
bInt = coords.yToPixel(b);
g.drawLine(xInt,yInt,aInt,bInt);
xInt = aInt;
yInt = bInt;
}
break;
}
case TableFunction.STEP: {
x = function.getX(startPt);
xInt = coords.xToPixel(x);
for (int i = startPt; i <= endPt; i++) {
if (i < endPt) {
double nextX = function.getX(i+1);
a = (x + nextX)/2;
x = nextX;
}
else
a = x;
aInt = coords.xToPixel(a);
y = function.getY(i);
yInt = coords.yToPixel(y);
g.drawLine(xInt,yInt,aInt,yInt);
xInt = aInt;
}
break;
}
case TableFunction.STEP_LEFT: {
x = function.getX(startPt);
xInt = coords.xToPixel(x);
for (int i = startPt+1; i <= endPt; i++) {
a = function.getX(i);
aInt = coords.xToPixel(a);
y = function.getY(i-1);
yInt = coords.yToPixel(y);
g.drawLine(xInt,yInt,aInt,yInt);
xInt = aInt;
}
break;
}
case TableFunction.STEP_RIGHT: {
x = function.getX(startPt);
xInt = coords.xToPixel(x);
for (int i = startPt+1; i <= endPt; i++) {
a = function.getX(i);
aInt = coords.xToPixel(a);
y = function.getY(i);
yInt = coords.yToPixel(y);
g.drawLine(xInt,yInt,aInt,yInt);
xInt = aInt;
}
break;
}
}
if (!showPoints)
return;
for (int i = startPt; i <= endPt; i++) {
x = function.getX(i);
y = function.getY(i);
xInt = coords.xToPixel(x);
yInt = coords.yToPixel(y);
g.fillOval(xInt-2,yInt-2,5,5);
}
} // end draw();
 
 
//-------------------- Dragging --------------------------
private int dragPoint = -1; // -1 if no point is being dragged;
// Otherwise, the index of the point being dragged.
private int startX, startY; // Point where mouse was clicked at start of drag.
private int prevY; // Previous position of mouse during dragging.
 
private boolean moved; // Becomes true once the clicked point has actually
// been dragged a bit. If the mouse is released before
// the point is moved at least 3 pixels, then the associated
// y-value is not changed.
/**
* Method required by the MouseListener interface. Defined here to
* support dragging of points on the function's graph. Not meant to be called directly.
*/
public void mousePressed(MouseEvent evt) {
dragPoint = -1;
if (function == null || getVisible() == false || canvas == null || coords == null || evt.isConsumed())
return;
if (evt.isShiftDown() || evt.isMetaDown() || evt.isControlDown() || evt.isAltDown())
return;
moved = false;
int ct = function.getPointCount();
for (int i = 0; i < ct; i++) {
int x = coords.xToPixel(function.getX(i));
int y = coords.yToPixel(function.getY(i));
if (evt.getX() >= x-3 && evt.getX() <= x+3 && evt.getY() >= y-3 && evt.getY() <= y+3) {
startX = evt.getX();
prevY = startY = evt.getY();
dragPoint = i;
evt.consume();
return;
}
}
}
/**
* Method required by the MouseListener interface. Defined here to
* support dragging of points on the function's graph. Not meant to be called directly.
*/
public void mouseReleased(MouseEvent evt) {
if (dragPoint == -1)
return;
evt.consume();
if (!moved) {
dragPoint = -1;
return;
}
mouseDragged(evt);
dragPoint = -1;
if (onFinishDrag != null)
onFinishDrag.compute();
}
/**
* Method required by the MouseListener interface. Defined here to
* support dragging of points on the function's graph. Not meant to be called directly.
*/
public void mouseDragged(MouseEvent evt) {
if (dragPoint == -1 || prevY == evt.getY())
return;
evt.consume();
if (!moved && Math.abs(evt.getY() - startY) < 3)
return;
moved = true;
int y = evt.getY();
if (y < coords.getTop() + 4)
y = coords.getTop() + 4;
else if (y > coords.getTop() + coords.getHeight() - 4)
y = coords.getTop() + coords.getHeight() - 4;
if (Math.abs(evt.getX() - startX) > 72)
y = startY;
if (y == prevY)
return;
prevY = y;
function.setY(dragPoint, coords.pixelToY(prevY));
needsRedraw();
if (onDrag != null)
onDrag.compute();
}
/**
* Empty method, required by the MouseListener interface.
*/
public void mouseClicked(MouseEvent evt) { }
 
/**
* Empty method, required by the MouseMotionListener interface.
*/
public void mouseEntered(MouseEvent evt) { }
 
/**
* Empty method, required by the MouseMotionListener interface.
*/
public void mouseExited(MouseEvent evt) { }
 
/**
* Empty method, required by the MouseMotionListener interface.
*/
public void mouseMoved(MouseEvent evt) { }
 
} // end class TableFunctionGraph
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/functions/ExpressionFunction.java
0,0 → 1,261
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.functions;
 
import edu.hws.jcm.data.*;
 
/**
* An ExpressionFunction is a Function that is created from an expression and a list
* of variables that serve as the parameter(s) of the function. (This is essentially
* a lambda operation, forming a function such as "lambda(x,y) (x^2+y^2)")
*
* Since an ExpressionFunction is a FunctionParserExtension, functions defined
* from this class can be added to a Parser and then used in expressions parsed
* by that parser.
*/
public class ExpressionFunction extends FunctionParserExtension {
private Expression definition; // Expression that defines the function.
private Variable[] params; // Variable(s) that act as the parameters.
/**
* Constuct a function of one parameter, named "x", by parsing the String, def,
* to get the definition of the function. A standard Parser, with
* default options and knowledge only of "pi", "e" and the standard functions
* is used. The variable "x" is also added to this parser while the function is being parsed.
*
* @param name Name of function. This should not be null if the function is to be used in a Parser.
* @param def contains definition of the function, as a function of "x".
*/
public ExpressionFunction(String name, String def) {
this(name, new String[] { "x" }, def, null);
}
/**
* Constuct a function of one or more parameters by parsing the String, def,
* to get the definition of the function. The given parser is used to
* parse the definition, so the definition can refer to objects registered
* with the parser (such as other variables or functions). Furthermore, if
* both name and parser are non-null, then the function is registered with
* the parser so that it can then be used in expressions parsed by the
* parser. (It's possible to have a function of zero arguements. In that case, the
* function serves as a "named expression".)
*
* @param name Name of function.
* @param paramNames Names of the parameters of the function. The lenght of this array determines the arity of the function.
* @param def The definition of the function, in terms of the parameters from the paramNames array.
* @param parser Used to parse the definition. If this is null, a standard parser is used. The
* paramaters are temporarily added onto the parser while the function definition is being parsed.
*/
public ExpressionFunction(String name, String[] paramNames, String def, Parser parser) {
setName(name);
if (paramNames == null)
params = new Variable[0];
else {
params = new Variable[ paramNames.length ];
for (int i = 0; i < paramNames.length; i++)
params[i] = new Variable(paramNames[i]);
}
redefine(def,parser);
if (parser != null && name != null)
parser.add(this);
}
/**
* Construct a function from a list of variables that serve as parameters and an expression that,
* presumably, can include those variables. WARNING: When the function is
* evaluated, the values of the parameter variables can change, so you should
* probably not use variables that are being used elsewhere in your program.
*/
public ExpressionFunction(String name, Variable[] params, Expression definition) {
setName(name);
this.params = (params == null)? new Variable[0] : params;
this.definition = definition;
}
private ExpressionFunction() {
// This default constructor is used in the derivative() method, but is
// not meant to be used from outside this class, since it doesn't properly
// iniitialize the state of the member variables.
}
/**
* Set the definition of this function by parsing the given string,
* using a default parser. The definition is in terms of the parameter
* names originally provided in the constructor.
*/
public void redefine(String def) {
redefine(def,null);
}
/**
* Set the definition of this function, using the specified parser (or a default
* parser if parser is null). The definition is in terms of the parameter
* names originally provided in the constructor. (This routine does
* not register the function with the parser, but if it was already
* registered with the parser, it stays registered with the new
* definition.) Note that changing the definition of the function
* effectively changes the definition of any other expression that
* refers to this function.
*/
public void redefine(String def, Parser parser) {
if (parser == null)
parser = new Parser();
else
parser = new Parser(parser);
for (int i = 0; i < params.length; i++)
parser.add(params[i]);
definition = parser.parse(def);
}
/**
* Return the expression that defines this function, as a string.
*/
public String getDefinitionString() {
return definition.toString();
}
/**
* Return a string that describes this function, such as "function f(x,y) given by x^2 - y^2".
*/
public String toString() {
StringBuffer b = new StringBuffer();
b.append( name == null? "unnamed function of (" : "function " + name + "(" );
for (int i = 0; i < params.length; i++) {
b.append(params[i].getName());
if (i < params.length - 1)
b.append(",");
}
b.append(") given by ");
b.append(definition.toString());
return b.toString();
}
//------- Methods from the Function interface --------------------
/**
* Return the number of arguments of this function.
*/
public int getArity() {
return params.length;
}
 
/**
* Find the value of the function at the argument values
* given by arguments[0], arguments[1], ... The length
* of the array argument should be equal to the arity of
* the function. If not, an IllegalArgumentException is
* thrown.
*/
public double getVal( double[] arguments ) {
return getValueWithCases(arguments, null);
}
/**
* Find the value of the function at the argument values
* given by arguments[0], arguments[1], ... The length
* of the array argument should be equal to the arity of
* the function. If not, an IllegalArgumentException is
* thrown. Store information about "cases" that occur in
* the evaluation in the second parameter, if that parameter is non-null.
*/
public double getValueWithCases( double[] arguments, Cases cases ) {
synchronized (params) {
if (arguments == null) {
if (params.length > 0)
throw new IllegalArgumentException("Internal Error: Number of arguments provided to function does not match its arity.");
}
else if (arguments.length != params.length)
throw new IllegalArgumentException("Internal Error: Number of arguments provided to function does not match its arity.");
else {
for (int i = 0; i < params.length; i++)
params[i].setVal(arguments[i]);
}
return definition.getValueWithCases(cases);
}
}
/**
* Return the derivative of the function with repect to
* argument number wrt, where the arguments are numbered 1, 2, 3,....
* For a function of one variable, call derivative(1) to find its derivative.
* If arity > 1, this is effectively a partial derivative. If wrt is
* not in the legal range, an IllegalArgumentException is thrown.
*/
public Function derivative(int wrt) {
if (wrt <= 0 || wrt > getArity())
throw new IllegalArgumentException("Internal Error: Attempt to take the derivative of a function of "
+ getArity() + " variables with respect to argument number " + wrt + ".");
ExpressionFunction deriv = new ExpressionFunction();
if (name != null) {
if (getArity() == 1)
deriv.setName(getName() + "'");
else
deriv.setName("D" + wrt + "[" + getName() + "]");
}
deriv.params = params;
deriv.definition = (Expression)definition.derivative(params[wrt-1]);
return deriv;
}
/**
* Return the derivative of the function with respect to the
* variable x. This will be non-zero if x occurs somehow in
* the definition of x: For example, f(y) = sin(x*y);
*/
public Function derivative(Variable x) {
ExpressionFunction deriv = new ExpressionFunction();
if (name != null)
deriv.setName("D" + x.getName() + "[" + getName() + "]");
deriv.params = params;
deriv.definition = (Expression)definition.derivative(x);
return deriv;
}
/**
* Return true if the definition of this function depends
* in some way on the variable x. (Note that a function does
* NOT depend on its parameter variables!)
*/
public boolean dependsOn(Variable x) {
return definition.dependsOn(x);
}
 
//----------- A method from ParserExtension class --------------
 
/**
* Find the value of the function applied to arguments popped
* from the stack, and push the result back onto the stack.
* (Overrides general method inherited from FunctionParserExtension.
* This is done for efficiency and because the general method
* can't deal properly with "cases".) Not meant to be called directly
*/
public void apply(StackOfDouble stack, Cases cases) {
for (int i = getArity() - 1; i >= 0; i--)
params[i].setVal(stack.pop());
stack.push( definition.getValueWithCases(cases) );
}
} // end class ExpressionFunction
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/functions/WrapperFunction.java
0,0 → 1,180
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.functions;
 
import edu.hws.jcm.data.*;
 
/**
* A WrapperFunction contains another function and delegates to it
* all calls to methods from the Function interface, except for calls
* to setName() and getName(). (It maintains its own name, which can
* be different from the name of the wrapped Function.) This has at least two
* uses: A WrapperFunction is a FunctionParserExtension, so it can
* be added to a parser and then used in expressions parsed in that
* parser. Second, the function that is wrapped inside the WrapperFunction
* object can be changed by a call to the setFunction() method.
* This makes it possible to have a single function that can be used,
* for example, in ValueMath objects and Graph1D's, whose definition
* can be changed at will. Note that it is NOT legal to change the
* arity of the function when calling the setFunction() method.
*/
public class WrapperFunction extends FunctionParserExtension {
 
private Function func; // The non-null function.
private double[] params; // For use in evaluating the function in the apply() method;
// has length equal to func.getArity();
private int serialNumber; // serial number goes up when function def is changed;
// this is used in the check() method for synchronizing derivatives.
private WrapperFunction derivativeOf; // If non-null, then this function is a
// derivative of the specified function.
private Variable derivativeVar; // If non-null, then the derivative was taken w.r.t. this variable
private int derivativeIndex; // If derivativeVar is null, this is the argument
// number with respect to which the derivative was taken.
/**
* Create a WrapperFunction object containing a specified function.
*
* @param f The non-null function that will be contained in the WrapperFunction.
*/
public WrapperFunction(Function f) {
setFunction(f);
serialNumber = 0;
}
private void check() {
// Called if this function is the derivative of another wrapper function to see
// if the serial number of the parent function has changed. If so, the derivative is
// recomputed.
if (derivativeOf == null || derivativeOf.serialNumber == serialNumber)
return;
serialNumber = derivativeOf.serialNumber;
if (derivativeVar != null)
func = derivativeOf.derivative(derivativeVar);
else
func = derivativeOf.derivative(derivativeIndex);
}
/**
* Set the function that is contained in this WrapperFunction.
*
* @param f The non-null function to be used in this WrapperFunction object.
* It must have the same arity as the current function.
*/
public void setFunction(Function f) {
if (f == null)
throw new IllegalArgumentException("Function supplied to WrapperFunction object can't be null.");
if (func != null && f.getArity() != func.getArity())
throw new IllegalArgumentException("Attempt to change the arity of a WrapperFunction.");
if (derivativeOf != null)
throw new IllegalArgumentException("Can't change the definition of a function that is a derivative of another function.");
func = f;
params = new double[f.getArity()];
serialNumber++;
}
/**
* Return the function that is currently wrapped in this WrapperFunction.
*/
public Function getFunction() {
return func;
}
 
/**
* Return the number of arguments of this function.
*/
public int getArity() {
return func.getArity();
}
/**
* Find the value of the function at the argument value
* argument[0], .... The number of arguments should match
* the arity of the function.
*/
public double getVal( double[] arguments ) {
check();
return func.getValueWithCases(arguments,null);
}
/**
* Find the value of the function at the argument values
* argument[0],.... Information about "cases" is stored in
* the Cases parameter, if it is non-null. See the Cases
* class for more information.
*/
public double getValueWithCases( double[] arguments, Cases cases ) {
check();
return func == null? 1 : func.getValueWithCases(arguments,cases);
}
 
/**
* Return the derivative of the function with repect to
* argument number wrt, where arguments are numbered starting from 1.
*/
public Function derivative(int wrt) {
check();
WrapperFunction deriv = new WrapperFunction(func.derivative(wrt));
deriv.derivativeOf = this;
deriv.derivativeIndex = wrt;
deriv.serialNumber = serialNumber;
return deriv;
}
/**
* Return the derivative of the function with respect to the
* variable x (where x is NOT one of the parameters of the function).
*/
public Function derivative(Variable x) {
check();
WrapperFunction deriv = new WrapperFunction(func.derivative(x));
deriv.derivativeOf = this;
deriv.derivativeVar = x;
deriv.serialNumber = serialNumber;
return deriv;
}
/**
* Return true if the definition of this function depends
* in some way on the variable x. (Note that the function does
* NOT depend on the variables that are being used as its parameters!)
*/
public boolean dependsOn(Variable x) {
check();
return func.dependsOn(x);
}
 
/**
* Evaluate the function applied to argument values popped from the stack,
* and leave the result on the stack. This is not meant to be called
* directly.
*/
public void apply(StackOfDouble stack, Cases cases) {
check();
for (int i = params.length - 1; i >= 0; i--)
params[i] = stack.pop();
stack.push( getValueWithCases(params, cases) );
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/SymbolTable.java
0,0 → 1,133
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
import java.util.Hashtable;
 
/**
* A symbol table contains MathObjects, associating them
* with their names. To support scoping (for example), a symbol
* table can have a parent symbol table. If a symbol is not found
* in the table itself, the search procedes to its parent.
* MathObjects in the parent are hidden by MathObjects of
* the same name in a SymbolTable.
* Note that a NullPointerException error will occur if an
* attempt is made to add a MathObject with a null name to a
* SymbolTable.
* A MathObject should not be renamed while it is registered
* in a SymbolTable.
* Note that a Parser has an associated SymbolTable. I expect
* SymbolTables to be used only through Parsers.
*/
public class SymbolTable implements java.io.Serializable {
 
private Hashtable symbols; // Objects are stored here and in the parent.
private SymbolTable parent; // Parent symbol table, possibly null.
/**
* Construct a symbol table with null parent.
*/
SymbolTable() {
this(null);
}
 
/**
* Construct a symbol table with specified parent.
*/
SymbolTable(SymbolTable parent) {
this.parent = parent;
symbols = new Hashtable();
}
 
/**
* Returns the parent symbol table of this symbol table.
*/
SymbolTable getParent() {
return parent;
}
 
/**
* Look up the object with the given name, if any.
* If not found, return null. (If the name is not found
* in the HashTable, symbols, the search is delegated to
* the parent.) If the name is null, then
* null is returned.
*/
synchronized public MathObject get(String name) {
if (name == null)
return null;
Object sym = symbols.get(name);
if (sym != null)
return (MathObject)sym;
else if (parent != null)
return parent.get(name);
else
return null;
}
 
/**
* Adds sym to the SymbolTable, associating it with its name.
*/
synchronized public void add(MathObject sym) {
if (sym == null)
throw new NullPointerException("Can't put a null symbol in SymbolTable.");
add(sym.getName(), sym);
}
 
/**
* Adds the given MathObject, sym, to the symbol table,
* associating it with the given name (which is probably
* the name of the symbol or that name transformed to lower
* case, but it doesn't have to be).
* If the same name is already in use in the HashTable
* then the new object replaces the current object.
* Note that if the name is defined in the parent
* symbol table, then the old object is hidden, not
* removed from the parent. If sym is null or if
* sym's name is null, than a NullPointerException is
* thrown.
*/
synchronized public void add(String name, MathObject sym) {
if (sym == null)
throw new NullPointerException("Can't put a null symbol in SymbolTable.");
else if (name == null)
throw new NullPointerException("Can't put unnamed MathObject in SymbolTable.");
symbols.put(name,sym);
}
 
/**
* Remove the object with the given name from the symbol table,
* but NOT from the parent symbol table. No error occurs
* if the name is not in the table or if name is null.
* If an object of the same name occurs in the parent,
* this routine will un-hide it.
*/
synchronized public void remove(String name) {
if (name != null)
symbols.remove(name);
}
 
} // end class SymbolTable
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/MathObject.java
0,0 → 1,45
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A MathObject is just an object that has setName and getName methods.
* MathObjects can be registered with a Parser (meaning that they are
* stored in the SymbolTable associated with the Parser, and can
* be used in expressions parsed by the Parser).
*/
public interface MathObject extends java.io.Serializable {
/**
* Get the name of this object.
*/
public String getName();
/**
* Set the name of this object. This should not be done if
* the MathObject is registered with a Parser.
*/
public void setName(String name);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/NumUtils.java
0,0 → 1,171
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* This class provides a few static functions for converting real numbers
* to strings and strings to real numbers. It should probalby be reimplemented
* to use the standard NumberFormat class for converting real to string.
*/
public class NumUtils {
 
/**
* Return the real number represented by the String s,
* or return Double.NaN if s does not represent a legal
* real number.
*/
public static double stringToReal(String s) {
try {
Double d = new Double(s);
return d.doubleValue();
}
catch (NumberFormatException e) {
return Double.NaN;
}
}
 
/**
* Return a string representation of the real number
* x occupying, if possible, at most 10 spaces.
*/
public static String realToString(double x) {
return realToString(x,10);
}
/**
* Goal is to return a reasonable string representation
* of x, using at most width spaces. (If the parameter width is
* unreasonably big or small, its value is adjusted to
* lie in the range 6 to 25.)
*
* @param x value to create string representation of.
* @param width maximum number of spaces used in string representation, if possible.
* @return a string representation for x. If x is Double.NaN, "undefined" is returned.
* If x is infinite, "INF" or "-INF" is returned.
*/
public static String realToString(double x, int width) {
width = Math.min(25, Math.max(6,width));
if (Double.isNaN(x))
return "undefined";
if (Double.isInfinite(x))
if (x < 0)
return "-INF";
else
return "INF";
String s = String.valueOf(x);
if (Math.rint(x) == x && Math.abs(x) < 5e15 && s.length() <= (width+2))
return String.valueOf( (long)x ); // return string without trailing ".0"
if (s.length() <= width)
return s;
boolean neg = false;
if (x < 0) {
neg = true;
x = -x;
width--;
s = String.valueOf(x);
}
long maxForNonExp = 5*(long)Math.pow(10,width-2);
if (x >= 0.0005 && x <= maxForNonExp && (s.indexOf('E') == -1 && s.indexOf('e') == -1)) {
s = round(s,width);
s = trimZeros(s);
}
else if (x > 1) { // construct exponential form with positive exponent
long power = (long)Math.floor(Math.log(x)/Math.log(10));
String exp = "E" + power;
int numlength = width - exp.length();
x = x / Math.pow(10,power);
s = String.valueOf(x);
s = round(s,numlength);
s = trimZeros(s);
s += exp;
}
else { // constuct exponential form with negative argument
long power = (long)Math.ceil(-Math.log(x)/Math.log(10));
String exp = "E-" + power;
int numlength = width - exp.length();
x = x * Math.pow(10,power);
s = String.valueOf(x);
s = round(s,numlength);
s = trimZeros(s);
s += exp;
}
if (neg)
return "-" + s;
else
return s;
}
private static String trimZeros(String num) {
// Helper function for realToString.
// Remove trailing zeros if num contains a decimal point, and
// remove the decimal point as well if all following digits are zero
if (num.indexOf('.') >= 0 && num.charAt(num.length() - 1) == '0') {
int i = num.length() - 1;
while (num.charAt(i) == '0')
i--;
if (num.charAt(i) == '.')
num = num.substring(0,i);
else
num = num.substring(0,i+1);
}
return num;
}
private static String round(String num, int length) {
// Helper function for realToString.
// Round off num to the given field width
if (num.indexOf('.') < 0)
return num;
if (num.length() <= length)
return num;
if (num.charAt(length) >= '5' && num.charAt(length) != '.') {
char[] temp = new char[length+1];
int ct = length;
boolean rounding = true;
for (int i = length-1; i >= 0; i--) {
temp[ct] = num.charAt(i);
if (rounding && temp[ct] != '.') {
if (temp[ct] < '9') {
temp[ct]++;
rounding = false;
}
else
temp[ct] = '0';
}
ct--;
}
if (rounding) {
temp[ct] = '1';
ct--;
}
// ct is -1 or 0
return new String(temp,ct+1,length-ct);
}
else
return num.substring(0,length);
}
 
} // end class NumUtils
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/ConditionalExpression.java
0,0 → 1,137
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A "conditional expression" is an expression using the "?" operator, such as "(x > 0)? x : -x"
* or "x <> 3 ? 1 / (x - 3)". Note that the second case, which follows the ":", is optional.
* If not present, the expression has the value Double.NaN when the boolean condition evaluates
* to false. A ConditionalExpression object is generated by a parser when it encounters a
* "?" operator in the string it is parsing (provided the BOOLEANS option is turned on in that parser).
* <p>A ConditionalExpression object holds the two expressions that are the cases in a conditional expression.
* Note that the boolean condition is NOT stored in the ConditionalExpression object; it is part of
* the ExpressionProgram for the expression in which the conditional expression occurs.
* A ConditionalExpression is an ExpressionCommand, meaning that it can occur in an ExpressionProgram.
* When the apply() method in this class is called, the boolean condition has already been evaluated,
* and the result is on the top of the stack. The ConditionalExpression will look at this result
* and replace it with the value of one of the two expressions that it contains.
* <p>It is unlikely that there will be any reason for anyone to use or understand this class,
* except possibly as an example of an ExpressionCommand.
*/
public class ConditionalExpression implements ExpressionCommand {
 
private ExpressionProgram trueCase; // Expression to be evaluated if condition is true.
private ExpressionProgram falseCase; // Expression to be evaluated if condition is false.
// This can be null, representing the value Double.NaN.
 
/**
* Create a ConditionalExpression object containing the two given expressions.
* trueCase must not be null, but falseCase can be null.
*/
public ConditionalExpression(ExpressionProgram trueCase, ExpressionProgram falseCase) {
this.trueCase = trueCase;
this.falseCase = falseCase;
}
 
// ---------------- Methods from the ExpressionCommand interface -------------------------
 
/**
* Apply this ConditionalExpression to the stack.
* (Get the top item from the stack. If it is non-zero (representing a boolean
* value of true), evaluate trueCase and put it's value on the stack. Otherwise,
* evaluate falseCase and put its value on the stack. If cases is non-null, record
* case values for the boolean condition and for the expression that is evaluated.)
*/
public void apply(StackOfDouble stack, Cases cases) {
double test = stack.pop();
if (cases != null)
cases.addCase((int)test);
if (test != 0)
stack.push(trueCase.getValueWithCases(cases));
else if (falseCase != null)
stack.push(falseCase.getValueWithCases(cases));
else
stack.push(Double.NaN);
}
/**
* Add commands to deriv that evaluate the derivative of this conditional expression with
* respect to the variable wrt. Assume that the ConditionalExpression Object
* occurs in the program prog at index myIndex.
* (The derivative of a conditional expression is another conditional expression.
* The boolean test for the derivative is the same as the test for this expression,
* so copy that test onto deriv. Than add a new ConditionalExpression object to deriv
* whose trueCase is the derivative of this.trueCase and whose falseCase is the derivative of
* this.falseCase.)
*/
public void compileDerivative(ExpressionProgram prog, int myIndex, ExpressionProgram deriv, Variable wrt) {
prog.copyExpression(myIndex-1,deriv);
ExpressionProgram trueDeriv = (ExpressionProgram)trueCase.derivative(wrt);
ExpressionProgram falseDeriv = (falseCase == null)? null : (ExpressionProgram)falseCase.derivative(wrt);
deriv.addCommandObject( new ConditionalExpression( trueDeriv, falseDeriv ) );
}
 
/**
* Assume that this ConditionalExpression object occurs in prog at index myIndex.
* Compute the total number of commands in prog used by the conditional expression,
* including the boolean test, which occurs in prog at position myIndex-1.
* (The number of commands in prog used by the conditional expression is 1 (for the
* ConditionalExpression object itself) plus the number of commands in the
* boolean condition.)
*/
public int extent(ExpressionProgram prog, int myIndex) {
return 1 + prog.extent(myIndex-1);
}
/**
* Returns true if x occurs in either the trueCase or the falseCase expression.
*/
public boolean dependsOn(Variable x) {
return trueCase.dependsOn(x) || (falseCase != null && falseCase.dependsOn(x));
}
 
/**
* Append the string representation of the expression (including the boolean
* condition) to the buffer. Assume that this ConditionalExpression occurs as
* a command in prog at index myIndex (so the boolean condition starts at index myIndex-1).
*/
public void appendOutputString(ExpressionProgram prog, int myIndex, StringBuffer buffer) {
buffer.append('(');
prog.appendOutputString(myIndex-1,buffer);
buffer.append(") ? (");
buffer.append(trueCase.toString());
buffer.append(')');
if (falseCase != null) {
buffer.append(" : (");
buffer.append(falseCase.toString());
buffer.append(')');
}
}
 
} // end class ConditionalExpression
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/ParseError.java
0,0 → 1,49
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* Represents a syntax error that is found while a string is being parsed.
*/
public class ParseError extends RuntimeException {
 
/**
* The parsing context that was in effect
* at the time the error occurred. This includes
* the string that was being processed and the
* position in the string where the error occured.
* These values are context.data and context.pos.
*/
public ParserContext context;
/**
* Create a new ParseError with a given error message and parsing context.
*/
public ParseError(String message, ParserContext context) {
super(message);
this.context = context;
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/Variable.java
0,0 → 1,117
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A Variable is a Value object whose value can be changed. Usually, a Variable will have
* a name, although that is not required unless tha Variable is going to be
* registered with a Parser. A Variable can be used as a Value, an Expression,
* or an ExpressionCommand. Since it is an ExpressionCommand, it can occur
* as a command in an ExpressionProgram. In that case, it simply represents a variable
* that occurs as part of an expression.
* <p>
* This class implements the Expression, ExpressionCommand, MathObject,
* and Value interfaces (since Constant implements them).
* <p>
* Most methods in interfaces Value, Exprssion, ExpressionCommand, and MathObject
* are inherited from class Constant. The following four methods override
* methods inherited from that class:
* public Expression derivative(Variable wrt);
* public void compileDerivative(ExpressionProgram prog, int myIndex, ExpressionProgram deriv, Variable wrt);
* public boolean dependsOn(Variable x); and
* public String toString().
*/
public class Variable extends Constant {
 
/**
* Create an unnamed Variable with initial value 0.
*/
public Variable() {
super(0);
}
/**
* Create a Variable with the given name and with initial value zero.
* (The name can be null.)
*/
public Variable(String name) {
super(name,0);
}
/**
* Create a Variable with the given name and given initial value.
* (The name can be null.)
*/
public Variable(String name, double value) {
super(name,value);
}
/**
* Set the value of this Variable to the specified value.
*/
public void setVal(double value) {
this.value = value;
}
/**
* Return the derivative of this Variable with respect to the
* Variable wrt. The answer is 1 if wrt is this Variable.
* Otherwise, the answer is 0.
* @param wrt "with respect to", i.e., the variable with respect to which to
* take the derivative.
* @return a constant: 1 if wrt is this Variable, 0 otherwise.
*/
public Expression derivative(Variable wrt) {
return new Constant( (wrt == this)? 1 : 0 );
}
/**
* Add a command to deriv to evaluate the derivative of this Variable with respect to the
* Variable wrt. The derivative is a command for pushing either 1 or 0, depending on whether
* wrt is this Variable or some other Variable. This is not meant to be called directly.
*/
public void compileDerivative(ExpressionProgram prog, int myIndex, ExpressionProgram deriv, Variable wrt) {
deriv.addConstant( (wrt == this)? 1 : 0 );
}
/**
* Check whether the value of this variable depends on the value of x. This
* is true if x is this Variable, false otherwise.
*/
public boolean dependsOn(Variable x) {
return this == x;
}
 
/**
* Return a print string representing this variable. The string is the
* name of the variable, if it has one. If not, the string "(unnamed variable)"
*/
public String toString() {
String s = getName();
return (s == null)? "(unnamed variable)" : s;
}
 
} // end class Variable
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/Function.java
0,0 → 1,85
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A Function is a mathematical real-valued function of zero or more
* real-valued arguments. The number of arguments is called the arity
* of the function.
*/
abstract public interface Function extends java.io.Serializable {
 
/**
* Return the number of arguments of this function. This must
* be a non-negative integer.
*/
public int getArity();
 
/**
* Find the value of the function at the argument values
* given by arguments[0], arguments[1], ... The length
* of the array, arguments, should be equal to the arity of
* the function.
*/
public double getVal( double[] arguments );
 
/**
* Find the value of the function at the argument values
* given by arguments[0], arguments[1], ... The length
* of the array argument should be equal to the arity of
* the function. Information about "cases" is stored in
* the Cases parameter, if it is non-null. See the Cases
* class for more information.
*/
public double getValueWithCases( double[] arguments, Cases cases );
 
/**
* Return the derivative of the function with repect to
* argument number wrt. For example, derivative(1) returns
* the derivative function with respedt to the first argument.
* Note that argements are numbered starting from 1.
*/
public Function derivative(int wrt);
/**
* Return the derivative of the function with respect to the
* variable x. This will be non-zero only if x occurs somehow in
* the definition of x: For example, f(y) = sin(x*y);
* (This routine is required for the general function-differentiating
* code in the class FunctionParserExtension.)
*/
public Function derivative(Variable x);
/**
* Return true if the defintion of this function depends
* in some way on the variable x. If not, it's assumed
* that the derivative w.r.t. x of the function, applied to any
* arguments that do not themselves depend on x, is zero.
* (This routine is required for the general function-differentiating
* code in the class FunctionParserExtension.)
*/
public boolean dependsOn(Variable x);
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/StackOfDouble.java
0,0 → 1,94
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A standard stack of values of type double, which can grow to arbitrary size.
*/
public class StackOfDouble implements java.io.Serializable {
 
private double[] data; // Contents of stack.
private int top; // Number of items on stack.
 
/**
* Create an initially empty stack. It initially has space allocated for one item.
*/
public StackOfDouble() {
data = new double[1];
}
 
/**
* Create an empty stack that initially has space for initialSize items pre-allocated.
* If initialSize <= 0, an initialSize of 1 is used.
*/
public StackOfDouble(int initialSize) {
data = new double[initialSize > 0 ? initialSize : 1];
}
 
/**
* Add x to top of stack.
*/
public void push(double x) {
if (top >= data.length) {
double[] temp = new double[2*data.length];
System.arraycopy(data,0,temp,0,data.length);
data = temp;
}
data[top++] = x;
}
 
/**
* Remove and return the top item on the stack.
* Will throw an exception of type java.util.EmptyStackException
* if the stack is empty when pop() is called.
*/
public double pop() {
if (top == 0)
throw new java.util.EmptyStackException();
return data[--top];
}
 
/**
* Return true if and only if the stack contains no items.
*/
public boolean isEmpty() {
return (top == 0);
}
 
/**
* Clear all items from the stack.
*/
public void makeEmpty() {
top = 0;
}
/**
* Return the number of items on the stack.
*/
public int size() {
return top;
}
 
} // end class StackOfDouble
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/ValueMath.java
0,0 → 1,86
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A ValueMath object is an easy way to create Value objects that are computed
* from other Value objects. For example, "new ValueMath(a,b,'+')" is an
* object whose value is obtained by adding the values of a and b.
*/
public class ValueMath implements Value {
 
private Function f; // If non-null, this is a value of the form f(params);
// If null, it's of the form x + y, x - y, ...
private double[] param;
private Value x,y;
private char op;
/**
* Create a ValueMath object whose value is computed by applying an arithmetic
* operator the values of x and y.
* @param op The arithmetic operator that is to be applied to x and y. This should
* be one of the characters '+', '-', '*', '/', or '^'. (No error is
* thrown if another character is provided. It will be treated as a '/').
*/
public ValueMath(Value x, Value y, char op) {
this.x = x;
this.y = y;
this.op = op;
}
/**
* Create a ValueMath object whose value is computed as f(x).
*/
public ValueMath(Function f, Value x) {
if (f.getArity() != 1)
throw new IllegalArgumentException("Internal Error: The function in a ValueMath object must have arity 1.");
this.f = f;
this.x = x;
param = new double[1];
}
/**
* Get the value of this object.
*/
public double getVal() {
if (f != null) {
param[0] = x.getVal();
return f.getVal(param);
}
else {
double a = x.getVal();
double b = y.getVal();
switch (op) {
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/': return a/b;
case '^': return Math.pow(a,b);
default: throw new IllegalArgumentException("Internal Error: Unknown math operator.");
}
}
}
 
} // end class ValueMath
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/ExpressionProgram.java
0,0 → 1,945
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* An ExprssionProgram represents a mathematical expression such as "3" or "sin(x^2)", stored
* in the form of a program for a stack machine. The program consists of a sequence of
* commands that, when executed, will compute the value of the expression.
*
* <p>Each command is encoded as an integer. There are three types of commands that can
* occur: (1) A negative integer must be one of the 36 constant values PLUS, MINUS,..., CUBERT.
* These constants represent unary and binary operators and standard functions. (2) An integer in the range
* 0 <= n < 0x3FFFFFFF encodes an operation of the form "push a constant onto the stack".
* The constant that is being pushed is encoded as an index in the array "constant",
* which is a private member of this class that holds all the constants that
* occur in this ExpressionProgram. (3) An integer >= 0x3FFFFFFF represents
* an ExpressionCommand object. When 0x3FFFFFFF is subtracted from the integer, the
* result is an index into the array "command", which is a private member of this
* class that holds all the ExpressionCommands that occur in this
* ExpressionProgram.
*/
public class ExpressionProgram implements Expression {
 
/**
* Code for a unary or binary operator or a standard function.
*/
public static final int
PLUS = -1, MINUS = -2, TIMES = -3,
DIVIDE = -4, POWER = -5, EQ = -6,
NE = -7, LT = -8, GT = -9,
LE = -10, GE = -11, AND = -12,
OR = -13, NOT = -14, UNARY_MINUS = -15,
FACTORIAL = -16, SIN = -17, COS = -18,
TAN = -19, COT = -20, SEC = -21,
CSC = -22, ARCSIN = -23, ARCCOS = -24,
ARCTAN = -25, ABS = -26, SQRT = -27,
EXP = -28, LN = -29, LOG2 = -30,
LOG10 = -31, TRUNC = -32, ROUND = -33,
FLOOR = -34, CEILING = -35,
CUBERT = -36;
/**
* If this is non-null, it is used as the print string
* for this expression in the toString() method. (When an
* expression is created by a Parser by parsing a string,
* the parse stores that string in this variable.)
*/
public String sourceString;
private int[] prog = new int[1]; // Contains the commands that make up this program.
// (Constants and ExpressionCommands are encoded as
// positive numbers, while negative numbers are
// opCodes from the above list of constants.)
// This array expands as necessary.
 
private int progCt; // The number of commands in prog.
 
//--------------------- Methods for creating the program ------------------------------
/**
* Default constructor creates an initially empty program.
*/
public ExpressionProgram() {
}
 
/**
* Adds com as the next command in the program. Among other things, for example, com can
* be a Variable or Constant. In that case, the meaning of the command is the stack
* operation "push (value of com)".
*
* @param com added as next command in the program.
*/
public void addCommandObject(ExpressionCommand com) {
int loc = findCommand(com);
addCommandCode(loc + 0x3FFFFFFF);
}
/**
* Add the number d as the next command in the program. The meaning of this command is
* actually the stack operation "push d".
*
* @param d added as next command in program.
*/
public void addConstant(double d) {
int loc = findConstant(d);
addCommandCode(loc);
}
/**
* Add a command code to the program, where code is one of the opCode constants
* that are public final members of this class, from CUBERT to PLUS. Each code
* represents either a binary or unary operator or a standard function that operates on the stack by
* poping its argument(s) from the stack, perfroming the operation, and pushing
* the result back onto the stack.
*/
public void addCommand(int code) {
if (code >= 0 || code < CUBERT)
throw new IllegalArgumentException("Internal Error. Illegal command code.");
addCommandCode(code);
}
/**
* To save space, cut the arrays that holds the program data down to the actual
* amount of data that they contain. This should be called after the complete
* program has been generated.
*/
public void trim() {
if (progCt != prog.length) {
int[] temp = new int[progCt];
System.arraycopy(prog,0,temp,0,progCt);
prog = temp;
}
if (commandCt != command.length) {
ExpressionCommand[] temp = new ExpressionCommand[commandCt];
System.arraycopy(command,0,temp,0,commandCt);
command = temp;
}
if (constantCt != constant.length) {
double[] temp = new double[constantCt];
System.arraycopy(constant,0,temp,0,constantCt);
constant = temp;
}
}
private void addCommandCode(int code) { // System.out.println("Add code " + code + " " + progCt);
if (progCt == prog.length) {
int[] temp = new int[ prog.length * 2 ];
System.arraycopy(prog,0,temp,0,progCt);
prog = temp;
}
prog[progCt++] = code;
}
 
 
//------------------- Methods for evaluating the program -----------------------
private Cases cases; // If this is non-null while the expression is being evaluated, then
// information about "cases" is recorded in it as the evaluation is
// done. See the Cases class for more information.
 
private StackOfDouble stack = new StackOfDouble();
// An ExpressionProgram is a program for a stack machien. This is the
// stack that is used when the program is executed.
/**
* Run the ExprssionProgram and return the value that it computes.
*/
synchronized public double getVal() {
cases = null;
return basicGetValue();
}
/**
* Run the ExprssionProgram and return the value that it computes.
* If the Cases object, c, is non-null, then information about "cases" is recorded in c.
* This information can be used to help detect possible "discontinuities"
* between two evaluations. See the Cases class for more information.
*/
synchronized public double getValueWithCases(Cases c) {
cases = c;
double d = basicGetValue();
cases = null;
return d;
}
private double basicGetValue() {
// Run the program and return its value.
stack.makeEmpty();
for (int pc = 0; pc < progCt; pc++) {
int code = prog[pc];
if (code < 0) {
double ans = applyCommandCode(code);
if (Double.isNaN(ans) || Double.isInfinite(ans)) {
if (cases != null)
cases.addCase(0);
return Double.NaN;
}
stack.push(ans);
}
else if (code < 0x3FFFFFFF) {
stack.push(constant[code]);
}
else {
command[code-0x3FFFFFFF].apply(stack,cases);
}
}
if (stack.size() != 1)
throw new IllegalArgumentException("Internal Error: Improper stack state after expression evaluation.");
double val = stack.pop();
if (cases != null)
cases.addCase( Double.isNaN(val) ? 0 : 1 );
return val;
}
private void addCase(int c) {
// If the member variable cases is not null, record c as the next item of case information in cases.
if (cases != null)
cases.addCase(c);
}
/**
* Apply the stack operation represented by code (a number < 0) to the stack.
*/
protected double applyCommandCode(int code) {
double ans;
if (code < OR)
ans = eval(code,stack.pop());
else
ans = eval(code,stack.pop(),stack.pop());
return ans;
}
private double eval(int commandCode, double x) {
// Compute the value of the unary operator represented by commandCode, when
// applied to the value x.
switch (commandCode) {
case NOT: return (x == 0)? 1 : 0;
case UNARY_MINUS: return -x;
case FACTORIAL: return factorial(x);
case SIN: return Math.sin(x);
case COS: return Math.cos(x);
case TAN: addCase((int)Math.floor((x-Math.PI/2.0)/Math.PI)); return Math.tan(x);
case COT: addCase((int)Math.floor(x/Math.PI)); return Math.cos(x)/Math.sin(x);
case SEC: addCase((int)Math.floor((x-Math.PI/2.0)/Math.PI)); return 1/Math.cos(x);
case CSC: addCase((int)Math.floor(x/Math.PI)); return 1/Math.sin(x);
case ARCSIN: return Math.asin(x);
case ARCCOS: return Math.acos(x);
case ARCTAN: return Math.atan(x);
case ABS: addCase((x > 0)? 1 : ( (x < 0)? -1 : 0 )); return Math.abs(x);
case SQRT: return (x < 0)? Double.NaN : Math.sqrt(x);
case EXP: return Math.exp(x);
case LN: return (x <= 0)? Double.NaN : Math.log(x);
case LOG2: return (x <= 0)? Double.NaN : Math.log(x)/Math.log(2);
case LOG10: return (x <= 0)? Double.NaN : Math.log(x)/Math.log(10);
case TRUNC: addCase((int)x); return (long)x;
case ROUND: addCase((int)Math.floor(x+0.5)); return Math.floor(x+0.5);
case FLOOR: addCase((int)Math.floor(x)); return Math.floor(x);
case CEILING: addCase((int)Math.floor(x)); return Math.ceil(x);
case CUBERT: addCase((x > 0)? 1 : -1); return (x >= 0)? Math.pow(x,1.0/3.0) : -Math.pow(-x,1.0/3.0);
default: return Double.NaN;
}
}
private double factorial(double x) {
// Compute x!. x is rounded to the nearest integer. If x > 170, then the
// answer is too big to represent in a value of type double, so the value
// is given as Double.NaN.
if (x <= -0.5 || x > 170.5) {
addCase(-1);
return Double.NaN;
}
int n = (int)x;
addCase(n);
double ans = 1;
for (int i = 1; i <= n; i++)
ans *= i;
return ans;
}
 
private double eval(int commandCode, double y, double x) {
// Compute the value of the unary operator represented by commandCode, when
// applied to the values x and y. (Note that the second operand comes
// first in the parameter list, since that is the way they were popped
// off the stack.)
switch (commandCode) {
case PLUS: return x+y;
case MINUS: return x-y;
case TIMES: return x*y;
case DIVIDE: addCase( (y > 0)? 1 : ( (y < 0)? -1 : 0 ) ); return x/y;
case POWER: return Math.pow(x,y);
case EQ: return (x == y) ? 1 : 0;
case NE: return (x != y) ? 1 : 0;
case GT: return (x > y) ? 1 : 0;
case LT: return (x < y) ? 1 : 0;
case GE: return (x >= y) ? 1 : 0;
case LE: return (x <= y) ? 1 : 0;
case AND: return ((x != 0) && (y != 0)) ? 1 : 0;
case OR: return ((x != 0) || (y != 0)) ? 1 : 0;
default: return Double.NaN;
}
}
 
//------------- Getting the print string of this expression ------------------------
/**
* If a source string has been saved, use it as the print string. (When a Parser creates
* an expression by parsing a string, it saves the source string in the ExpressionProgram.)
* Otherwise, construct the print string based on the commands in the program.
*/
public String toString() {
if (sourceString != null)
return sourceString;
else {
StringBuffer buffer = new StringBuffer();
appendOutputString(progCt-1,buffer);
return buffer.toString();
}
}
 
/**
* Add a string representing part of the expression to the output buffer.
* You probably are only interested in this if you write a ParserExtension
* or ExpressionCommand.
* (The command at position index in the program represents a
* subexpression. It could be a constant or a variable, for example,
* which is complete subexpression in itself. Or it could be the
* final operator in a larger subexpression. In that case, the operands,
* which are located in lower positions in the program, are considered to
* be part of the expression. This routine appends a print string
* for the entire subexpression to the buffer. When this is called
* with index = progCt-1 (the last command in the program), it processes
* the entire program.
* Note that the hard part here is deciding when to put in parentheses.
* This is done based on the precedence of the operators. The result is not always pretty.
*/
public void appendOutputString(int index, StringBuffer buffer) {
if (prog[index] >= 0x3FFFFFFF) {
command[prog[index] - 0x3FFFFFFF].appendOutputString(this,index,buffer);
}
else if (prog[index] >= 0) {
buffer.append(NumUtils.realToString(constant[prog[index]]));
}
else if (prog[index] >= OR) {
int op2 = index-1; // Position of command representing the second operand.
int op1 = op2 - extent(op2); // Position of command representing the first operand.
if (precedence(prog[op1]) < precedence(prog[index]) ||
(prog[index] == POWER && precedence(prog[op1]) == precedence(prog[index]))) {
buffer.append('(');
appendOutputString(op1,buffer);
buffer.append(')');
}
else
appendOutputString(op1,buffer);
switch (prog[index]) {
case PLUS: buffer.append(" + "); break;
case MINUS: buffer.append(" - "); break;
case TIMES: buffer.append("*"); break;
case DIVIDE: buffer.append("/"); break;
case POWER: buffer.append("^"); break;
case AND: buffer.append(" AND "); break;
case OR: buffer.append(" OR "); break;
case EQ: buffer.append(" = "); break;
case NE: buffer.append(" <> "); break;
case GE: buffer.append(" >= "); break;
case LE: buffer.append(" <= "); break;
case GT: buffer.append(" > "); break;
case LT: buffer.append(" < "); break;
}
if (prog[op2] == UNARY_MINUS ||
precedence(prog[op2]) < precedence(prog[index]) ||
((prog[index] == MINUS || prog[index] == DIVIDE) && precedence(prog[op2]) == precedence(prog[index]))) {
buffer.append('(');
appendOutputString(op2,buffer);
buffer.append(')');
}
else
appendOutputString(op2,buffer);
}
else if (prog[index] <= SIN) {
buffer.append(StandardFunction.standardFunctionName(prog[index]));
buffer.append('(');
appendOutputString(index-1,buffer);
buffer.append(')');
}
else if (prog[index] == UNARY_MINUS) {
buffer.append('-');
if (precedence(prog[index-1]) <= precedence(UNARY_MINUS)) {
buffer.append('(');
appendOutputString(index-1,buffer);
buffer.append(')');
}
else
appendOutputString(index-1,buffer);
}
else if (prog[index] == NOT) {
buffer.append("NOT (");
appendOutputString(index-1,buffer);
buffer.append(')');
}
else if (prog[index] == FACTORIAL) {
if (prog[index-1] >= 0 &&
(prog[index-1] < 0x3FFFFFFF ||
command[prog[index-1] - 0x3FFFFFFF] instanceof Variable ||
command[prog[index-1] - 0x3FFFFFFF] instanceof Constant)) {
appendOutputString(index-1,buffer);
}
else {
buffer.append('(');
appendOutputString(index-1,buffer);
buffer.append(')');
}
buffer.append('!');
}
}
private int precedence(int opcode) {
// Return the precedence of the operator. This is used
// by the prceding method to decide when parentheses are needed.
if (opcode >= 0) {
if (opcode >= 0x3FFFFFFF && (command[opcode-0x3FFFFFFF] instanceof ConditionalExpression))
return 0;
else
return 7;
}
else switch (opcode) {
case FACTORIAL:
case OR:
case AND: return 1;
case GE:
case LE:
case GT:
case EQ:
case NE:
case LT: return 2;
case PLUS:
case MINUS:
case UNARY_MINUS: return 3;
case TIMES:
case DIVIDE: return 4;
case POWER: return 6;
default: return 7;
}
}
 
//----------------------- Methods for computing the derivative -------------------------
 
/**
* Compute the derivative of this expression with respect to the Variable wrt.
* The value returned is actually an ExpressionProgram.
*/
public Expression derivative(Variable wrt) {
ExpressionProgram deriv = new ExpressionProgram();
compileDerivative(progCt-1,deriv,wrt);
deriv.trim();
return deriv;
}
/**
* The command at position index in the program represents a subexpression of
* the whole expression. This routine adds commands to deriv for computing the
* derivative of that subexpression with respect to the variable wrt.
* You probably are not interested in this unless you write a ParserExtension
* or an ExpressionCommand.
*/
public void compileDerivative(int index, ExpressionProgram deriv, Variable wrt) {
if (!dependsOn(index,wrt))
deriv.addConstant(0);
else if (prog[index] >= 0x3FFFFFFF)
command[prog[index]-0x3FFFFFFF].compileDerivative(this,index,deriv,wrt);
else if (prog[index] >= 0)
deriv.addConstant(0);
else if (prog[index] >= POWER) {
int indexOp2 = index - 1;
int indexOp1 = indexOp2 - extent(indexOp2);
doBinDeriv(prog[index],indexOp1,indexOp2,deriv,wrt);
}
else if (prog[index] <= SIN) {
doFuncDeriv(prog[index],index-1,deriv,wrt);
}
else if (prog[index] == UNARY_MINUS) {
compileDerivative(index-1,deriv,wrt);
deriv.addCommand(UNARY_MINUS);
}
else if (prog[index] == FACTORIAL) {
deriv.addConstant(Double.NaN);
}
else if (prog[index] >= NOT)
throw new IllegalArgumentException("Internal Error: Attempt to take the derivative of a logical-valued expression.");
else
throw new IllegalArgumentException("Internal Error: Unknown opcode.");
}
/**
* The command at position index in the program represents a subexpression of
* the whole expression. This routine finds and returns the number of commands
* in the program that are part of that subexpression. That is, the subexpresssion
* occupies the part of the program between index - extent + 1 and index.
* You probably are not interested in this unless you write a ParserExtension
* or an ExpressionCommand.
*/
public int extent(int index) {
if (prog[index] <= NOT)
return 1 + extent(index-1);
else if (prog[index] < 0) {
int extentOp1 = extent(index - 1); // Extent of second operand (which is on top in the program).
int extentOp2 = extent(index - 1 - extentOp1); // Extent of second operand.
return extentOp1 + extentOp2 + 1;
}
else if (prog[index] < 0x3FFFFFFF)
return 1;
else
return command[prog[index]-0x3FFFFFFF].extent(this,index);
}
/**
* The command at position index in the program represents a subexpression of
* the whole expression. This routine copies the commands for the entire
* subexpression to the destination program.
* You probably are not interested in this unless you write a ParserExtension
* or an ExpressionCommand.
*/
public void copyExpression(int index, ExpressionProgram destination) {
int size = extent(index);
for (int i = index-size+1; i <= index; i++) {
if (prog[i] < 0)
destination.addCommand(prog[i]);
else if (prog[i] >= 0x3FFFFFFF)
destination.addCommandObject(command[prog[i]-0x3FFFFFFF]);
else
destination.addConstant(constant[prog[i]]);
}
}
/**
* The command at position index in the program represents a subexpression of
* the whole expression. If that subexpression includes some dependence on
* the variable x, then true is returned. If the subexpression is constant
* with respect to the variable x, then false is returned.
* You probably are not interested in this unless you write a ParserExtension
* or an ExpressionCommand.
*/
public boolean dependsOn(int index, Variable x) {
int size = extent(index);
for (int i = index-size+1; i <= index; i++) {
if (prog[i] >= 0x3FFFFFFF) {
ExpressionCommand c = command[prog[i]-0x3FFFFFFF];
if (c == x || c.dependsOn(x))
return true;
}
}
return false;
}
/**
* Checks whether the expression as a whole has any dependence on the variable x.
*/
public boolean dependsOn(Variable x) {
return dependsOn(progCt - 1, x);
}
private void doBinDeriv(int opCode, int op1, int op2, ExpressionProgram deriv, Variable wrt) {
// Add commands to deriv to compute the derivative of a subexpression of this program
// with respect to the variable wrt, where the main operation in the subexpression is
// the binary operator opCode, the position of the first operand of the operator is
// at the index op1 in the program, and the position of second operand is op2.
switch (opCode) {
case PLUS:
if (!dependsOn(op1,wrt))
compileDerivative(op2,deriv,wrt);
else if (!dependsOn(op2,wrt))
compileDerivative(op1,deriv,wrt);
else {
compileDerivative(op1,deriv,wrt);
compileDerivative(op2,deriv,wrt);
deriv.addCommand(PLUS);
}
break;
case MINUS:
if (!dependsOn(op1,wrt)) {
compileDerivative(op2,deriv,wrt);
deriv.addCommand(UNARY_MINUS);
}
else if (!dependsOn(op2,wrt))
compileDerivative(op1,deriv,wrt);
else {
compileDerivative(op1,deriv,wrt);
compileDerivative(op2,deriv,wrt);
deriv.addCommand(MINUS);
}
break;
case TIMES: {
int cases = 0;
if (dependsOn(op2,wrt)) {
copyExpression(op1,deriv);
if (prog[op2] < 0x3FFFFFFF || command[prog[op2]-0x3FFFFFFF] != wrt) {
compileDerivative(op2,deriv,wrt);
deriv.addCommand(TIMES);
}
cases++;
}
if (dependsOn(op1,wrt)) {
copyExpression(op2,deriv);
if (prog[op1] < 0x3FFFFFFF || command[prog[op1]-0x3FFFFFFF] != wrt) {
compileDerivative(op1,deriv,wrt);
deriv.addCommand(TIMES);
}
cases++;
}
if (cases == 2)
deriv.addCommand(PLUS);
}
break;
case DIVIDE:
if (!dependsOn(op2,wrt)) {
compileDerivative(op1,deriv,wrt);
copyExpression(op2,deriv);
deriv.addCommand(DIVIDE);
}
else if (!dependsOn(op1,wrt)) {
copyExpression(op1,deriv);
deriv.addCommand(UNARY_MINUS);
copyExpression(op2,deriv);
deriv.addConstant(2);
deriv.addCommand(POWER);
deriv.addCommand(DIVIDE);
if (prog[op2] < 0x3FFFFFFF || command[prog[op2]-0x3FFFFFFF] != wrt) {
compileDerivative(op2,deriv,wrt);
deriv.addCommand(TIMES);
}
}
else {
copyExpression(op2,deriv);
if (prog[op1] < 0x3FFFFFFF || command[prog[op1]-0x3FFFFFFF] != wrt) {
compileDerivative(op1,deriv,wrt);
deriv.addCommand(TIMES);
}
copyExpression(op1,deriv);
if (prog[op2] < 0x3FFFFFFF || command[prog[op2]-0x3FFFFFFF] != wrt) {
compileDerivative(op2,deriv,wrt);
deriv.addCommand(TIMES);
}
deriv.addCommand(MINUS);
copyExpression(op2,deriv);
deriv.addConstant(2);
deriv.addCommand(POWER);
deriv.addCommand(DIVIDE);
}
break;
case POWER:
if (!dependsOn(op2,wrt)) {
copyExpression(op2,deriv);
copyExpression(op1,deriv);
if ( prog[op2] >= 0 && prog[op2] < 0x3FFFFFFF) {
if (constant[prog[op2]] != 2) {
deriv.addConstant(constant[prog[op2]] - 1);
deriv.addCommand(POWER);
}
}
else if (prog[op2] == UNARY_MINUS && prog[op2-1] >= 0 && prog[op2-1] < 0x3FFFFFFF) {
deriv.addConstant( constant[prog[op2-1]] + 1 );
deriv.addCommand(UNARY_MINUS);
deriv.addCommand(POWER);
}
else {
copyExpression(op2,deriv);
deriv.addConstant(1);
deriv.addCommand(MINUS);
deriv.addCommand(POWER);
}
deriv.addCommand(TIMES);
if (prog[op1] < 0x3FFFFFFF || command[prog[op1]-0x3FFFFFFF] != wrt) {
compileDerivative(op1,deriv,wrt);
deriv.addCommand(TIMES);
}
}
else if (!dependsOn(op1,wrt)) {
copyExpression(op1,deriv);
copyExpression(op2,deriv);
deriv.addCommand(POWER);
if ( ! (prog[op1] >= 0x3FFFFFFF && command[prog[op1]-0x3FFFFFFF] instanceof Constant
&& ((Constant)command[prog[op1]-0x3FFFFFFF]).getVal() == Math.E) ) {
copyExpression(op1,deriv);
deriv.addCommand(LN);
deriv.addCommand(TIMES);
}
if (prog[op2] < 0x3FFFFFFF || command[prog[op2]-0x3FFFFFFF] != wrt) {
compileDerivative(op2,deriv,wrt);
deriv.addCommand(TIMES);
}
}
else {
copyExpression(op1,deriv);
copyExpression(op2,deriv);
deriv.addCommand(POWER);
boolean eq = true;
int ext1 = extent(op1);
int ext2 = extent(op2);
if (ext1 != ext2)
eq = false;
else
for (int i = 0; i < ext1; i++)
if (prog[op1-i] != prog[op2-i]) {
eq = false;
break;
}
if (eq)
deriv.addConstant(1);
else {
copyExpression(op2,deriv);
copyExpression(op1,deriv);
deriv.addCommand(DIVIDE);
}
if (prog[op1] < 0x3FFFFFFF || command[prog[op1]-0x3FFFFFFF] != wrt) {
compileDerivative(op1,deriv,wrt);
deriv.addCommand(TIMES);
}
copyExpression(op1,deriv);
deriv.addCommand(LN);
if (prog[op2] < 0x3FFFFFFF || command[prog[op2]-0x3FFFFFFF] != wrt) {
compileDerivative(op2,deriv,wrt);
deriv.addCommand(TIMES);
}
deriv.addCommand(PLUS);
deriv.addCommand(TIMES);
}
break;
}
}
 
private void doFuncDeriv(int opCode, int op, ExpressionProgram deriv, Variable wrt) {
// Add commands to deriv to compute the derivative of a subexpression of this program
// with respect to the variable wrt, where the main operation in the subexpression is
// the standard function represented by opCode, and the position of the operand of the
// standard function is at the index op in the program.
/* if (opCode == TRUNC || opCode == ROUND || opCode == FLOOR || opCode == CEILING) {
// I'm pretending that the derivative is zero, even though it's undefined at
// certain values.
deriv.addConstant(0);
return;
}
*/
switch (opCode) {
case FLOOR:
case CEILING:
case TRUNC:
case ROUND:
copyExpression(op,deriv);
if (opCode == ROUND) {
deriv.addConstant(0.5);
deriv.addCommand(PLUS);
}
deriv.addCommand(ROUND);
copyExpression(op,deriv);
if (opCode == ROUND) {
deriv.addConstant(0.5);
deriv.addCommand(PLUS);
}
deriv.addCommand(NE);
if (opCode == TRUNC) {
copyExpression(op,deriv);
deriv.addConstant(0);
deriv.addCommand(EQ);
deriv.addCommand(OR);
}
ExpressionProgram zero = new ExpressionProgram();
zero.addConstant(0);
deriv.addCommandObject( new ConditionalExpression(zero , null) );
return;
case SIN:
copyExpression(op,deriv);
deriv.addCommand(COS);
break;
case COS:
copyExpression(op,deriv);
deriv.addCommand(SIN);
deriv.addCommand(UNARY_MINUS);
break;
case TAN:
copyExpression(op,deriv);
deriv.addCommand(SEC);
deriv.addConstant(2);
deriv.addCommand(POWER);
break;
case COT:
copyExpression(op,deriv);
deriv.addCommand(CSC);
deriv.addConstant(2);
deriv.addCommand(POWER);
deriv.addCommand(UNARY_MINUS);
break;
case SEC:
copyExpression(op,deriv);
deriv.addCommand(SEC);
copyExpression(op,deriv);
deriv.addCommand(TAN);
deriv.addCommand(TIMES);
break;
case CSC:
copyExpression(op,deriv);
deriv.addCommand(CSC);
copyExpression(op,deriv);
deriv.addCommand(COT);
deriv.addCommand(TIMES);
deriv.addCommand(UNARY_MINUS);
break;
case ARCSIN:
case ARCCOS:
deriv.addConstant(1);
if (opCode == ARCCOS)
deriv.addCommand(UNARY_MINUS);
deriv.addConstant(1);
copyExpression(op,deriv);
deriv.addConstant(2);
deriv.addCommand(POWER);
deriv.addCommand(MINUS);
deriv.addCommand(SQRT);
deriv.addCommand(DIVIDE);
break;
case ARCTAN:
deriv.addConstant(1);
deriv.addConstant(1);
copyExpression(op,deriv);
deriv.addConstant(2);
deriv.addCommand(POWER);
deriv.addCommand(PLUS);
deriv.addCommand(DIVIDE);
break;
case ABS: {
ExpressionProgram pos = new ExpressionProgram();
ExpressionProgram neg = new ExpressionProgram();
compileDerivative(op,pos,wrt);
compileDerivative(op,neg,wrt);
neg.addCommand(UNARY_MINUS);
ExpressionProgram negTest = new ExpressionProgram();
copyExpression(op,negTest);
negTest.addConstant(0);
negTest.addCommand(LT);
negTest.addCommandObject( new ConditionalExpression(neg,null) );
copyExpression(op,deriv);
deriv.addConstant(0);
deriv.addCommand(GT);
deriv.addCommandObject( new ConditionalExpression( pos, negTest ) );
}
return;
case SQRT:
deriv.addConstant(1);
deriv.addConstant(2);
copyExpression(op,deriv);
deriv.addCommand(SQRT);
deriv.addCommand(TIMES);
deriv.addCommand(DIVIDE);
break;
case EXP:
copyExpression(op,deriv);
deriv.addCommand(EXP);
break;
case LN:
case LOG2:
case LOG10:
ExpressionProgram d = new ExpressionProgram();
d.addConstant(1);
copyExpression(op,d);
d.addCommand(DIVIDE);
if (opCode != LN) {
d.addConstant( (opCode == LOG2)? 2 : 10);
d.addCommand(LN);
d.addCommand(DIVIDE);
}
copyExpression(op,deriv);
deriv.addConstant(0);
deriv.addCommand(GT);
deriv.addCommandObject( new ConditionalExpression(d,null) );
break;
case CUBERT:
deriv.addConstant(1);
deriv.addConstant(3);
copyExpression(op,deriv);
deriv.addConstant(2);
deriv.addCommand(POWER);
deriv.addCommand(CUBERT);
deriv.addCommand(TIMES);
deriv.addCommand(DIVIDE);
break;
}
if (prog[op] < 0x3FFFFFFF || command[prog[op]-0x3FFFFFFF] != wrt) {
compileDerivative(op,deriv,wrt);
deriv.addCommand(TIMES);
}
}
 
//--------- private stuff for storing constants and ExpressionCommands ----------
 
private double[] constant = new double[1]; // Holds all the constants that have been added
// to this ExpressionProgram. In a program, a
// constant is represented by an index into this
// array.
private int constantCt; // The number of values in the constant array.
private ExpressionCommand[] command = new ExpressionCommand[1]; // Holds all the ExpressionCommands that have been added
// to this ExpressionProgram. In a program, an
// ExpressionCommand is represented by an index into this
// array, with 0x3FFFFFFF added to the index to give
// a number >= 0x3FFFFFFF.
private int commandCt; // The number of items in the command array.
 
private int findConstant(double d) {
// Find the index of d in the constant array, adding it if it is not already there.
// The array will be expanded if necessary.
for (int i = 0; i < constantCt; i++)
if (constant[i] == d) {
return i;}
if (constantCt == constant.length) {
double[] temp = new double[ constant.length * 2 ];
System.arraycopy(constant,0,temp,0,constantCt);
constant = temp;
}
constant[constantCt++] = d;
return constantCt - 1;
}
 
private int findCommand(ExpressionCommand com) {
// Find the index of com in the command array, adding it if it is not already there.
// The array will be expanded if necessary.
for (int i = 0; i < commandCt; i++)
if (command[i] == com)
return i;
if (commandCt == command.length) {
ExpressionCommand[] temp = new ExpressionCommand[ command.length * 2 ];
System.arraycopy(command,0,temp,0,commandCt);
command = temp;
}
command[commandCt++] = com;
return commandCt - 1;
}
} // end class ExpressionProgram
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/Constant.java
0,0 → 1,170
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A Constant is a Value that represents a constant real number. (The value doesn't have to
* be constant in sub-classes, since the member that stores the value is protected, not private.)
* A Constant doesn't necessarily need a name. If the name is null, then the print string for the
* Constant is the value of the constant. If it has a non-null name, then the print string
* is the name. (Note that, as for any MathObject, if the name is null, than the Constant can't
* be added to a Parser.) Constant objects are used to represent the mathematical constants
* pi and e.
* A Constant is both an Expression and an ExpressionCommand. Since it is an ExpressionCommand,
* it can occur as a command in an ExpressionProgram. In that case, it simply represens a named constant
* occurs in an expression.
*/
public class Constant implements Expression, ExpressionCommand, MathObject {
// Also implements Value, which is a subinterface of Expression.
 
private String name; // This Constant's name, possibly null.
 
/**
* The value of this Constant.
*/
protected double value;
/**
* Create an unnamed Constant with the given value and null name.
*/
public Constant(double value) {
this.value = value;
}
/**
* Create a Constant with the given name and value.
* The name can be null.
*/
public Constant(String name, double value) {
setName(name);
this.value = value;
}
// -------------------- Methods from the MathObject interface -------------------------
/**
* Return the name of this Constant. It can be null.
*/
public String getName() {
return name;
}
 
/**
* Set the name of this Constant. (Note that this should not be done
* if the Constant has been registered with a Parser.)
*/
public void setName(String name) {
this.name = name;
}
 
// -------------- Method from the Value interface (inherited through Expression) ------
/**
* Return the value of this Constant.
*/
public double getVal() {
return value;
}
 
// ----------------------- Methods from the Expression interface ---------------------
/**
* Return the value of the Constant. Since a constant is continuous function,
* there is only one "case", so no case information needs to be recorded in cases.
*/
public double getValueWithCases(Cases cases) {
return value;
}
 
/**
* Return the derivative of this Constant with respect to the variable wrt.
* The derivative is another Constant with value zero.
*/
public Expression derivative(Variable wrt) {
return new Constant(0);
}
 
/**
* Return the print string representing this Constant. The string is the
* name of the constant, if that is non-null. Otherwise, it is the value
* of the constant.
*/
public String toString() {
if (name == null)
return NumUtils.realToString(value);
else
return name;
}
 
// -------------------- Methods from the ExpressionCommand interface -----------------
 
/**
* Apply the Constant to the stack. This is done by pushing the value of
* the constant onto the stack. The evaluation of a constant doesn't have any
* "cases", so there is no need to record any information in cases.
*/
public void apply(StackOfDouble stack, Cases cases) {
stack.push(getVal()); // Feb 3, 2001 -- changed this from "stack.push(value)", which caused problems with sub-classes!
}
 
/**
* Add a commands to deriv to evaluate the derivative of this Constant with respect to the
* variable. The derivative is 0, so the only command is the constant 0 (which really
* represents the stack operation "push 0"). The program and the position of the Constant
* in that program are irrelevant.
*/
public void compileDerivative(ExpressionProgram prog, int myIndex, ExpressionProgram deriv, Variable wrt) {
deriv.addConstant(0);
}
 
/**
* Return the number of locations that this Constant uses in the program.
* The value is always 1, since the constant is a complete sub-expression
* in itself.
*/
public int extent(ExpressionProgram prog, int myIndex) {
return 1;
}
/**
* Retrun false, since the value of this Constant is independent of the value of x.
*/
public boolean dependsOn(Variable x) {
return false;
}
/**
* Append the print string for this Constant to the buffer. (The values of prog and
* myIndex are irrelevant.)
*/
public void appendOutputString(ExpressionProgram prog, int myIndex, StringBuffer buffer) {
buffer.append(toString());
}
} // end class Constant
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/ParserExtension.java
0,0 → 1,53
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A ParserExtension can be defined to add new capabilities to a
* standard Parser. Examples include user-defined functions and
* summations (using a notation of the form "sum(i, 0, n, x^n/i!)").
* A ParserExtension is a MathObject, so it has a name and can be
* registered with a Parser. When the Parser encounters the name
* in a string, it turns control of the parsing process over to
* the ParserExtension, which must parse any necessary arguments
* and generate any ExpressionProgram commands.
*
*/
public interface ParserExtension extends MathObject {
/**
* Parses the part of an expression string associated with this ParserExtension.
* This method must add commands to context.prog that will generate exactly ONE
* number on the stack when they are executed. Parsing routines from the Parse class,
* such as parseFactor and parseExpression, can be called
* to parse sub-parts of the string. The name of the command
* has already been read from the ParseContext when doParse() is called.
* (At the time this is called, context.tokenString is the
* name under which this ParserExtension was registered with the
* Parser. This makes it possible to register the same ParserExtension
* under several names, with each name represnting a different
* meaning.)
*/
public void doParse(Parser parser, ParserContext context);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/Parser.java
0,0 → 1,642
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A Parser can take a string and compile it into an ExpressionProgram.
* MathObjects, such as variables and functions, can be registered with
* the Parser. This means that the Parser will recognize them in the
* strings that it parses. There are a few options that can be set to
* control certain aspects of the parsing. If a string does not have
* the correct syntax for an expression, then the Parser will throw a
* ParseError when it tries to parse that string. A Parser can have a
* parent. It inherits any MathObjects registered with its parent, but
* a MathObject registered with a Parser will hide any MathObject of
* the same name that is registered with its parent.
* Every parser recognizes the constants pi and e and the operators
* +, -, *, /, ^, and **. The ** operator is a synonym for ^, the
* exponentiation operator. Both unary and binary + and - are recognized.
* The exponentiation operator is right associative. The others are
* left associative.
*/
public class Parser implements java.io.Serializable {
 
/**
* An option that can be set for this parser.
* If enabled, identifiers are case-sensitive.
* For example, Sin, sin, and SIN will be
* treated as separate identifiers. It really
* only makes sense to enable this at the time the
* Parser is first constructed.
*/
public static final int CASE_SENSITIVE = 1;
 
/**
* An that can be set for this parser.
* If enabled, mutltiplication can be indicated
* implicitely, as well as with a "*". For
* example, 2x will mean 2*x.
*/
public static final int OPTIONAL_STARS = 2;
/**
* An option that can be set for this parser.
* If enabled, spaces are not required to separate
* identifiers. This only has an effect if one of
* OPTIONAL_STARS or OPTIONAL_PARENS is also enabled.
* For example, xsin(x) will be read as x*sin(x),
* and sine will be read as sin(e).
*/
public static final int OPTIONAL_SPACES = 4;
 
/**
* An option that can be set for this parser.
* If enabled, brackets, [ and ], can be used for grouping.
*/
public static final int BRACKETS = 8;
/**
* An option that can be set for this parser.
* If enabled, braces, { and }, can be used for grouping.
*/
public static final int BRACES = 16;
 
/**
* An option that can be set for this parser.
* If enabled, the "?" operator can be used in expressions, along with the
* logical operators &, |, ~, =, <, >, <>, <=, >=.
* The words "and", "or", and "not" can be used
* in place of &, |, and ~. These words are
* treated in a case-insensitive way, even if
* the CASE_SENSITIVE option is on. When this
* option is set, it is legal to call the
* parseLogical method to parse a boolean-valued
* expression. This option is enabled by default.
*/
public static final int BOOLEANS = 32;
 
/**
* An option that can be set for this parser.
* If enabled, the factorial operator, !, is recognized.
*/
public static final int FACTORIAL = 64;
/**
* An option that can be set for this parser.
* The character "_", which can usually
* be used just like a letter, is
* not allowed in identifers.
*/
public static final int NO_UNDERSCORE_IN_IDENTIFIERS = 128;
/**
* An option that can be set for this parser.
* Digits 0 through 9, which can usually be
* used in an identifier after the first
* character, are not allowed in identifiers.
*/
public static final int NO_DIGITS_IN_IDENTIFIERS = 256;
 
/**
* An option that can be set for this parser.
* If enabled, parentheses are optional around
* the parameter of a standard function. If the
* parentheses are omited, then the argument is
* the term that follows the function name.
* For example, "sin x + 1" means "sin(x) + 1"
* while "sin x * cos x" means "sin( x*cos(x) )".
*/
public static final int OPTIONAL_PARENS = 512;
 
/**
* An option that can be set for this parser.
* When enabled, the standard functions are
* registered with the parser. This option
* is enabled by default. The standard
* functions are: sin, cos, tan, cot, sec,
* csc, arcsin, arccos, arctan, exp, ln,
* log2, log10, sqrt, cubert, abs, round,
* floor, ceiling, trunc.
*/
public static final int STANDARD_FUNCTIONS = 1024;
/**
* The default options set that is used for
* a newly created Parser, if none is specified
* in the Constructor. It includes the options BOOLEANS and STANDARD_FUNCTIONS.
*/
public static final int DEFAULT_OPTIONS = BOOLEANS | STANDARD_FUNCTIONS;
/**
* The set of options that have been enabled for this parser.
*/
protected int options;
/**
* The symbol table that contains the MathObjects
* that have been registered with this parser.
*/
protected SymbolTable symbols;
/**
* Construct a Parser with no parent and with the default options,
* BOOLEANS and STANDARD_FUNCTIONS.
*/
public Parser() {
this(null,DEFAULT_OPTIONS);
}
/**
* Create a Parser with the specified parent. The options for this
* parser are inherited from the parent, if parent is non-null.
* If parent is null, the option set is empty.
*/
public Parser(Parser parent) {
this(parent,0);
}
/**
* Create a Parser with the spedified option set and with no parent.
*/
public Parser(int options) {
this(null,options);
}
/**
* Create a Parser with the specified parent. The options for this
* parser consist of the option set from the parent, together with
* any additional options in the specified options set.
*
* @param parent parent of this Parser, possibly null.
* @param options additional options, in addition to ones inherited from parent.
*/
public Parser(Parser parent, int options) {
if (parent == null) {
symbols = new SymbolTable();
symbols.add(new Constant("e",Math.E));
symbols.add(new Constant("pi",Math.PI));
}
else {
symbols = new SymbolTable(parent.symbols);
this.options = parent.options;
}
addOptions(options);
}
/**
* Add the options in the option set newOptions to this Parser's option set.
* The value of newOptions can be one of the option constants defined in this
* class, such as OPTIONAL_STARS, or it can consist of several option constants
* OR-ed together.
*
*/
public void addOptions(int newOptions) {
if ( ((newOptions & STANDARD_FUNCTIONS) != 0) && ((options & STANDARD_FUNCTIONS) == 0) ) {
for (int opCode = ExpressionProgram.CUBERT; opCode <= ExpressionProgram.SIN; opCode++)
symbols.add( new StandardFunction(opCode) );
}
options = options | newOptions;
}
/**
* Parse the string str and create the corresponding expression.
* The expression must be numeric-valued, not logical. There can't
* be any extra characters in str after the expression. If a syntax
* error is found, a ParseError will be thrown.
*
* @param str String to parse.
* @return the expression defined by the string.
*/
public ExpressionProgram parse(String str) {
ParserContext context = new ParserContext(str,options,symbols);
// The ParserContext holds all the information relevant to the
// parsing of str, including str itself and the ExpressionProgram
// that is being generated. See the ParserContext class for more info.
if (str == null)
throw new ParseError("Can't parse a null string.", context);
if (context.look() == ParserContext.END_OF_STRING)
throw new ParseError("Can't parse an empty string.", context);
boolean isBool;
if ( (options & BOOLEANS) != 0 )
isBool = parseLogicalExpression(context);
else
isBool = parseExpression(context);
if (context.look() != ParserContext.END_OF_STRING)
throw new ParseError("Extra data found after the end of a complete legal expression.",context);
if (isBool)
throw new ParseError("Found a logical-valued expression instead of a numeric expression.",context);
context.prog.trim();
context.prog.sourceString = str;
return context.prog;
}
/**
* Parse the String, str, and create a corresponding logical-valued expression.
* The expression must be logical-valued, such as "x > 0", not numeric. There can't
* be any extra characters in str after the expression. If a syntax
* error is found, a ParseError will be thrown. It is not legal to call this
* method if the BOOLEANS option is not set.
*
* @param str String to parse.
* @return the logical-valued expression defined by str.
*/
public ExpressionProgram parseLogical(String str) {
if ( (options & BOOLEANS) == 0 )
throw new IllegalArgumentException("Internal Error: Attempt to parse a logical-valued expression, but BOOLEANS option is not turned on.");
ParserContext context = new ParserContext(str,options,symbols);
if (str == null)
throw new ParseError("Can't parse a null string.", context);
if (context.look() == ParserContext.END_OF_STRING)
throw new ParseError("Can't parse an empty string.", context);
boolean isBool = parseLogicalExpression(context);
if (context.look() != ParserContext.END_OF_STRING)
throw new ParseError("Extra data found after the end of a complete legal expression.",context);
if (!isBool)
throw new ParseError("Found a numeric-valued expression instead of a logical expression.",context);
context.prog.trim();
return context.prog;
}
//---------- Wrapper functions for accessing the symbol table --------------
/**
* Get the MathObject that has been registered with the parser
* under the given name. If the CASE_SENSITIVE option is not set,
* names are converted to lower case for the purpose of
* registering and retrieving registered objects.
*/
public MathObject get(String name) {
if ( (options & Parser.CASE_SENSITIVE) != 0 )
return symbols.get(name);
else
return symbols.get(name.toLowerCase());
}
/**
* Register the MathObject with the Parser, associating it with its
* name. An error will occur if the name is null. If the CASE_SENSITIVE
* option is not set, names are converted to lower case for the purpose of
* registering and retrieving registered objects.
*/
public void add(MathObject sym) {
if ( (options & Parser.CASE_SENSITIVE) != 0 )
symbols.add(sym);
else
symbols.add(sym.getName().toLowerCase(), sym);
}
/**
* Deregister the MathObject with the given name, if there is one
* registered with the Parser. If the name is not registered, nothing
* happens and no error occurs.
*
* @param name MathObject to deregister.
*/
public void remove(String name) {
if (name == null)
return;
else if ( (options & Parser.CASE_SENSITIVE) != 0 )
symbols.remove(name);
else
symbols.remove(name.toLowerCase());
}
// ------------------------- The parsing code -------------------------
// The remaining routines in this class implement a recursive descent parser
// for expressions. These routines would be private, except that it might
// be necessary for a ParserExtension to call them. The ParserContext parameter
// holds information such as the string that is being parsed and the ExpressionProgram
// that is being generated. See the ParseContext class for more information.
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
public boolean parseLogicalExpression(ParserContext context) {
boolean isBool = parseLogicalTerm(context);
int tok = context.look();
if (tok == ParserContext.OPCHARS && context.tokenString.equals("&") && !isBool)
throw new ParseError("The AND operator can only be used with logical expressions.",context);
while (tok == ParserContext.OPCHARS && context.tokenString.equals("&")) {
context.next();
if (!parseLogicalTerm(context))
throw new ParseError("The AND operator can only be used with logical expressions.",context);
context.prog.addCommand(ExpressionProgram.AND);
tok = context.look();
}
if (tok == ParserContext.OPCHARS && context.tokenString.equals("?")) {
if (!isBool)
throw new ParseError("The conditional operator, ?, can only be applied to a logical-valued expression.",context);
ExpressionProgram trueCase, falseCase;
ExpressionProgram saveProg = context.prog;
context.next();
trueCase = new ExpressionProgram();
context.prog = trueCase;
if (parseLogicalExpression(context))
throw new ParseError("The cases in a conditional expression cannot be logical-valued expressions.",context);
tok = context.look();
if (tok == ParserContext.OPCHARS && context.tokenString.equals(":")) {
context.next();
falseCase = new ExpressionProgram();
context.prog = falseCase;
if (parseLogicalExpression(context))
throw new ParseError("The cases in a conditional expression cannot be logical-valued expressions.",context);
}
else
falseCase = null;
context.prog = saveProg;
context.prog.addCommandObject( new ConditionalExpression(trueCase, falseCase) );
return false;
}
else
return isBool;
}
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
public boolean parseLogicalTerm(ParserContext context) {
boolean isBool = parseLogicalFactor(context);
int tok = context.look();
if (tok == ParserContext.OPCHARS && context.tokenString.equals("|") && !isBool)
throw new ParseError("The OR operator can only be used with logical expressions.",context);
while (tok == ParserContext.OPCHARS && context.tokenString.equals("|")) {
context.next();
if (!parseLogicalFactor(context))
throw new ParseError("The OR operator can only be used with logical expressions.",context);
context.prog.addCommand(ExpressionProgram.OR);
tok = context.look();
}
return isBool;
}
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
public boolean parseLogicalFactor(ParserContext context) {
int tok = context.look();
int notCt = 0;
while (tok == ParserContext.OPCHARS && context.tokenString.equals("~")) {
context.next();
tok = context.look();
notCt++;
}
boolean isBool = parseRelation(context);
if (notCt > 0 && !isBool)
throw new ParseError("The NOT operator can only be used with logical expressions.",context);
if (notCt % 2 == 1)
context.prog.addCommand(ExpressionProgram.NOT);
return isBool;
}
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
public boolean parseRelation(ParserContext context) {
boolean isBool = parseExpression(context);
int tok = context.look();
if (tok != ParserContext.OPCHARS)
return isBool;
int rel = 0;
if (context.tokenString.equals("="))
rel = ExpressionProgram.EQ;
else if (context.tokenString.equals("<"))
rel = ExpressionProgram.LT;
else if (context.tokenString.equals(">"))
rel = ExpressionProgram.GT;
else if (context.tokenString.equals("<="))
rel = ExpressionProgram.LE;
else if (context.tokenString.equals(">="))
rel = ExpressionProgram.GE;
else if (context.tokenString.equals("<>"))
rel = ExpressionProgram.NE;
if (rel == 0)
return isBool;
if (isBool)
throw new ParseError("A relational operator can only be used with numerical expressions.",context);
context.next();
if (parseExpression(context))
throw new ParseError("A relational operator can only be used with numerical expressions.",context);
tok = context.look();
if (tok == ParserContext.OPCHARS &&
( context.tokenString.equals("=") || context.tokenString.equals("<") || context.tokenString.equals(">") ||
context.tokenString.equals("<=") || context.tokenString.equals(">=") || context.tokenString.equals("<>")) )
throw new ParseError("It is illegal to string together relations operators; use \"AND\" instead.",context);
context.prog.addCommand(rel);
return true;
}
 
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
public boolean parseExpression(ParserContext context) {
boolean neg = false;
int tok = context.look();
if (tok == ParserContext.OPCHARS && (context.tokenString.equals("+") || context.tokenString.equals("-"))) {
neg = (context.tokenString.equals("-"));
context.next();
}
boolean isBool = parseTerm(context);
if (neg) {
if (isBool)
throw new ParseError("A unary + or - cannot be applied to a logical expression.",context);
context.prog.addCommand(ExpressionProgram.UNARY_MINUS);
}
tok = context.look();
if (tok == ParserContext.OPCHARS && (context.tokenString.equals("+") || context.tokenString.equals("-")) && isBool)
throw new ParseError("A + or - operator cannot be applied to logical operands.",context);
while (tok == ParserContext.OPCHARS && (context.tokenString.equals("+") || context.tokenString.equals("-"))) {
context.next();
int opcode = (context.tokenString.equals("+")? ExpressionProgram.PLUS : ExpressionProgram.MINUS);
if (parseTerm(context))
throw new ParseError("A + or - operator cannot be applied to logical operands.",context);
context.prog.addCommand(opcode);
tok = context.look();
}
return isBool;
}
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
public boolean parseTerm(ParserContext context) {
boolean implicitStar = false;
boolean isBool = parsePrimary(context);
int tok = context.look();
String ts = context.tokenString;
implicitStar = !isBool && (options & OPTIONAL_STARS) != 0 &&
(tok == ParserContext.NUMBER || tok == ParserContext.IDENTIFIER ||
(tok == ParserContext.OPCHARS &&
(ts.equals("(") || ts.equals("[") || ts.equals("{"))));
if (tok == ParserContext.OPCHARS && (ts.equals("*") || ts.equals("/")) && isBool)
throw new ParseError("A * or / operator cannot be applied to logical operands.",context);
while (implicitStar || tok == ParserContext.OPCHARS && (ts.equals("*") || ts.equals("/"))) {
if (!implicitStar)
context.next();
int opcode = (implicitStar || ts.equals("*")? ExpressionProgram.TIMES : ExpressionProgram.DIVIDE);
if (parsePrimary(context))
throw new ParseError("A * or / operator cannot be applied to logical operands.",context);
context.prog.addCommand(opcode);
tok = context.look();
ts = context.tokenString;
implicitStar = !isBool && (options & OPTIONAL_STARS) != 0 &&
(tok == ParserContext.NUMBER || tok == ParserContext.IDENTIFIER ||
(tok == ParserContext.OPCHARS &&
(ts.equals("(") || ts.equals("[") || ts.equals("{"))));
}
return isBool;
}
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
public boolean parsePrimary(ParserContext context) {
boolean isBool = parseFactor(context);
int tok = context.look();
if (tok == ParserContext.OPCHARS && context.tokenString.equals("^")) {
if (isBool)
throw new ParseError("The exponentiation operator cannot be applied to logical operands.",context);
context.next();
if (parsePrimary(context))
throw new ParseError("The exponentiation operator cannot be applied to logical operands.",context);
context.prog.addCommand(ExpressionProgram.POWER);
}
return isBool;
}
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
public boolean parseFactor(ParserContext context) {
boolean isBool = false;
int tok = context.next();
if (tok == ParserContext.NUMBER)
context.prog.addConstant(context.tokenValue);
else if (tok == ParserContext.IDENTIFIER)
parseWord(context);
else if (tok == ParserContext.END_OF_STRING)
throw new ParseError("Data ended in the middle of an incomplete expression.",context);
else if (tok != ParserContext.OPCHARS)
throw new ParseError("Internal error: Unknown token type.",context);
else if (context.tokenString.equals("("))
isBool = parseGroup( '(', ')' , context );
else if (context.tokenString.equals("[") && ((options & Parser.BRACKETS) != 0))
isBool = parseGroup( '[', ']' , context );
else if (context.tokenString.equals("{") && ((options & Parser.BRACES) != 0))
isBool = parseGroup( '{', '}' , context );
else if (context.tokenString.equals("}") && ((options & Parser.BRACES) != 0))
throw new ParseError("Misplaced right brace with no matching left brace.",context);
else if (context.tokenString.equals("]") && ((options & Parser.BRACKETS) != 0))
throw new ParseError("Misplaced right bracket with no matching left bracket.",context);
else if (context.tokenString.equals(")"))
throw new ParseError("Misplaced right parenthesis with no matching left parenthesis.",context);
else
throw new ParseError("Illegal or misplaced character \"" + context.tokenString.charAt(0) + "\"",context);
if ( (options & FACTORIAL) != 0 ) {
tok = context.look();
while (tok == ParserContext.OPCHARS && context.tokenString.equals("!")) {
if (isBool)
throw new ParseError("The factorial operator cannot be applied to a logical value.",context);
context.next();
context.prog.addCommand(ExpressionProgram.FACTORIAL);
tok = context.look();
}
}
return isBool;
}
// Helper routine for parsePrimary. If a ParserExtension needs to call this,
// it should look ahead to make sure there is a (, [, or { and then call
// parsePrimary.
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
private boolean parseGroup(char open, char close, ParserContext context) {
boolean isBool = (options & Parser.BOOLEANS) == 0 ? parseExpression(context) : parseLogicalExpression(context);
int tok = context.look();
if (tok == ParserContext.OPCHARS && context.tokenString.equals("" + close))
context.next();
else
throw new ParseError("Missing \"" + close + "\" to match a previous \"" + open + "\".",context);
return isBool;
}
// Helper routine for parsePrimary. If a ParserExtension needs to call this,
// it should look ahead to make sure there is an identifier and then call
// parsePrimary.
/**
* Called as part of the parsing process. From outside this class, this would
* probably be called only by a ParserExtension.
*/
private void parseWord(ParserContext context) {
if (context.tokenObject == null)
throw new ParseError("Unknown word \"" + context.tokenString + "\" encountered in an expression.", context);
if (context.tokenObject instanceof Variable || context.tokenObject instanceof Constant)
context.prog.addCommandObject((ExpressionCommand)context.tokenObject);
else if (context.tokenObject instanceof StandardFunction) {
StandardFunction f = (StandardFunction)context.tokenObject;
int tok = context.look();
if (tok == ParserContext.OPCHARS &&
( context.tokenString.equals("(")
|| ( context.tokenString.equals("[") && ((options & BRACKETS) != 0) )
|| ( context.tokenString.equals("{") && ((options & BRACES) != 0) ) ) ) {
context.next();
boolean isBool;
if (context.tokenString.equals("("))
isBool = parseGroup('(',')',context);
else if ( context.tokenString.equals("[") )
isBool = parseGroup('[',']',context);
else
isBool = parseGroup('{','}',context);
if (isBool)
throw new ParseError("The argument of a function must be a numerical expression.", context);
}
else {
if ( (options & OPTIONAL_PARENS) == 0 )
throw new ParseError("Parentheses required around argument of standard function \"" + f.getName() + "\".", context);
if (parseTerm(context))
throw new ParseError("The argument of a function must be a numerical expression.", context);
}
context.prog.addCommand(f.getOpCode());
}
else if ( context.tokenObject instanceof ParserExtension)
((ParserExtension)context.tokenObject).doParse(this, context);
else if (! ( context.tokenObject instanceof ExpressionCommand ))
throw new ParseError("Unexpected word \"" + context.tokenObject.getName() + "\" encountered in an expression.", context);
else
throw new ParseError("Unimplemented word \"" + context.tokenObject.getName() + "\" encountered in an expression.", context);
}
} // end class Parser
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/Cases.java
0,0 → 1,81
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* An object of type Cases stores a list of "case values" that is generated
* while an expression is being evaluated using the routine Expression.getValuesWithCases().
* This information can be used as a heuristic (i.e. a fudge) to help detect
* a possible discontinuity between two evaluations of the expression. Suppose
* that the expression is evaluated twice, with some change of variable values
* between the two evaluations. If the variables' values are not changed too much,
* and if the Cases objects generated by the two evaluations are equal (as determined
* by the "equals" method defined in this class), then it is likely that
* there is no discontinuity. (However, this is not perfect. The discontinuity
* in 1/x^2 won't be detected since the case value generated by 1/f(x) only
* checks the sign of f(x), and the denominator of 1/x^2 is positive on both
* sides of x=0. If you want to be more paranoid, check both the expression
* and its derivative.) (I really don't like this very much, but it can be used to draw
* pretty good graphs in general.)
*/
public class Cases {
private int[] cases = new int[1]; // Array of values that have been added with addCase(value).
private int caseCt; // Number of items stored in cases array.
 
/**
* Remove all the cases that have been added with addCase().
* This makes it possible to reuse this object in another
* call to Expression.getValueWithCases().
*/
public void clear() {
caseCt = 0;
}
 
/**
* Add a new case value to the list stored in this object.
*/
public void addCase(int value) {
if (caseCt == cases.length) {
int[] temp = new int[2*caseCt];
System.arraycopy(cases,0,temp,0,caseCt);
cases = temp;
}
cases[caseCt++] = value;
}
 
/**
* Test whether c contains exactly the same list of case
* values as this Cases object does.
*/
public boolean equals(Cases c) {
if (c.caseCt != caseCt)
return false;
for (int i = 0; i < caseCt; i++)
if (c.cases[i] != cases[i])
return false;
return true;
}
 
} // end class Cases
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/ExpressionCommand.java
0,0 → 1,96
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* An ExpressionCommand can occur as a command in an ExpressionProgram. ExpressionCommands
* exists so that ExprssionPrograms can be extened to include new types of operations beyond
* the basic operations (such as PLUS and SIN) which are represented by constants in the
* ExpressionProgram class. Examples include ConditionalExpressions and user-defined functions.
* This interface is not meant for casual programmers. It is for programmers who want to
* extend the notion of Expression in an orginal way.
*
*/
public interface ExpressionCommand extends java.io.Serializable {
 
/**
* This routine is called when an ExpressionCommand object is encountered during
* the evaluation of an ExpressionProgram. The stack may contain results of
* previous commands in the program. For example, for a ConditionalExpression, it
* contains the value of the boolean condition, and for a user-defined function,
* it contains the values of the arguments of the function. When apply() is called,
* the ExpressionCommand should perform any stack operations that are necessary
* to evaluate itself. For example, a user-defined function would remove its arguments
* from the stack and replace them with the value of the function at those arguments.
* If cases is non-null, then any case information generated during the evaluation
* should be recorded in cases. (See the Cases class for more information.)
*
* @param stack contains results of previous commands in the program.
* @param cases if non-null, any case information generated during evaluation should be recorded here.
*/
public void apply(StackOfDouble stack, Cases cases);
 
/**
* The ExpressionCommand occurs in the program prog at the index indicated by myIndex.
* Add commands to deriv that will evaluate the derivative of this command with respect to
* the variable wrt. prog and myIndex are provided so that this routine will have access
* to any commands in prog that generate data used by this command (for example, the commands
* that evaluate the arguments of a user-defined function).
*
* @param prog program in which ExpressionCommand occurs.
* @param myIndex point at which ExpressionCommand occurs in the ExpressionProgram.
* @param deriv the derivative of the ExpressionPorgram prog, which is in the process of being computed.
Commands should added to deriv that will compute the derivative of this ExpressionCommand.
* @param wrt commands are added to deriv with respect to this Variable.
*/
public void compileDerivative(ExpressionProgram prog, int myIndex, ExpressionProgram deriv, Variable wrt);
/**
* The ExpressionCommand occurs in the program prog at the index indicated by myIndex.
* Return the total number of indices in prog occupied by this command and the commands
* that generate data used by this command.
*
* @param prog ExpressionProgram in which this ExpressionCommand occurs.
* @param myIndex index at which ExpressionCommand occurs in prog.
* @return total number of indices in prog occupied by this command and commands that generate data used by this command.
*/
public int extent(ExpressionProgram prog, int myIndex);
/**
* Return true if this command depends on the value of x, false otherwise.
* That is, when apply() is called, can the result depend on the value of x?
*/
public boolean dependsOn(Variable x);
 
/**
* The ExpressionCommand occurs in the program prog at the index indicated by myIndex.
* Add a print string representation of the sub-expression represented by this command
* (including any previous commands in the program that generate data used by this
* command).
*/
public void appendOutputString(ExpressionProgram prog, int myIndex, StringBuffer buffer);
 
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/SimpleFunction.java
0,0 → 1,152
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* An object belonging to this class is a function of one or more variables.
* It is defined by an expression, e, and a list of variables, which presumably
* can occur in e. The value of the function at arguments x1,x2,... is obtained by
* assigning the x's as the values of the variables and then evaluating
* the expression e.
*
* <p>Note: When the function is evaluated, the values of the variables that act
* as its parameters are saved and the variables are set to the values of the actual parameters
* provided for the function. After the evaluation, the saved values are restored.
* Usually, this is OK, but if setting the value of the variable has a side effect
* (such as changing the position of a VariableSlider), it could be a problem.
* So, don't use the variables associated with VariableSliders or VariableInputs
* in SimpleFunctions.
*
* <p>Note: A SimpleFunction is not a MathObject and does not have a name.
* It cannot be added to a Parser. If you want to do somethign like that,
* use an ExpressionFunction (defined in package edu.hws.jcm.functions).
*/
public class SimpleFunction implements Function {
 
private Expression e; // The expression that defines the function.
private Variable[] v; // The variables, presumably used in the expression,
// which acts as the parameter of the function.
private String name; // The name of the function.
private double[] save; // For saving values of variables when the function
// is evaluated.
/**
* Create the function of one variable such that the value
* of the function at x is obtained by temporarily assigning x as the
* value of the variable v and then evaluating e. e and v
* should be non-null (or errors will result when the function
* is used. Note that evaluating the function will temporarily
* change the value of the variable.
*/
public SimpleFunction(Expression e, Variable v) {
this(e, new Variable[] { v });
}
/**
* Create a function. The arity of the function is
* the length of the array v. The value of the function
* at a given list of arguments is obtained by temporarily
* assigning the arguement values to the variables, and then
* returning the value of the expression. e and v should
* be non-null. Note that evaluating the function will
* temporarily change the values of the variables.
*/
public SimpleFunction(Expression e, Variable[] v) {
this.e = e;
this.v = v;
save = new double[v.length];
}
/**
* Return the number of arguments of this function.
*/
public int getArity() {
return v.length;
}
/**
* Find the value of the function at the argument values
* argument[0], argument[1].... (If not enough arguments are supplied,
* an ArrayIndexOutOfBoundsException will be thrown. Extra
* arguments are ignored.)
*/
public double getVal( double[] arguments ) {
return getValueWithCases(arguments,null);
}
/**
* Find the value of the function at the argument values
* argument[0], argument[1].... Information about "cases" is stored in
* the Cases parameter, if it is non-null. See the Cases
* class for more information.
*/
public double getValueWithCases( double[] arguments, Cases cases ) {
for (int i = 0; i < v.length; i++) {
save[i] = v[i].getVal();
v[i].setVal(arguments[i]);
}
double val = e.getValueWithCases(cases);
for (int i = 0; i < v.length; i++)
v[i].setVal(save[i]);
return val;
}
 
/**
* Return the derivative of the function with repect to
* argument number wrt, where arguments are numbered starting from 1.
*/
public Function derivative(int wrt) {
if (wrt < 1 || wrt > v.length)
throw new IllegalArgumentException("Internal Error. Function does not have an argument number " + wrt);
return new SimpleFunction(e.derivative(v[wrt-1]),v);
}
/**
* Return the derivative of the function with respect to the
* variable x. (Note that the derivative w.r.t one of the variables
* that are being used as the parameter of this function is ZERO!)
* To get the derivative with respect to the i-th parameter variable,
* call derivative(i).
*/
public Function derivative(Variable x) {
for (int i = 0; i < v.length; i++)
if (x == v[i])
return new SimpleFunction(new Constant(0),v);
return new SimpleFunction(e.derivative(x),v);
}
/**
* Return true if the definition of this function depends
* in some way on the variable x. (Note that the function does
* NOT depend on the variables that are being used as its parameters!)
*/
public boolean dependsOn(Variable x) {
for (int i = 0; i < v.length; i++)
if (x == v[i])
return false;
return e.dependsOn(x);
}
} // end class SimpleFunction
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/Expression.java
0,0 → 1,73
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* An Expression represents a mathematical expression such as "x+1" or
* "3" or "sin(x*ln(x)-3*abs(x/4))". An expression has a value, which
* can depend on the values of variables that occur in the expression.
* An expression can be differenetiated with respect to a variable. It has
* a print string representation. This interface is implemented by
* the classes Constant, Variable, and ExpressionProgram, for example.
* The Expression interface
* represents all the properties of expressions that you are likely to need
* to know about, unless you want to write a new kind of ExpressionCommand.
*/
public interface Expression extends Value {
 
// The method "public double getVal()" is inherited from the Value interface.
// It returns the current value of this expression.
 
/**
* Compute and return the value of this expression. If cases is non-null,
* then data is stored in cases that can be used to check for possible
* discontinuities between one evaluation and the next. See the class
* Cases for more information.
*/
public double getValueWithCases(Cases cases);
 
/**
* Return an Expression that represents the derivative of
* this expression with respect to the variable wrt.
* (Note that if the expression contains other variables
* besides wrt, this is actually a partial derivative.)
*/
public Expression derivative(Variable wrt);
 
/**
* Checks whether the expression has any dependence on the variable x.
*/
public boolean dependsOn(Variable x);
 
/**
* Get a print string representation of this expression. (Of course,
* every object defines toString(). It is included here to remind you
* that classes that implement the Expression interface should have
* a print string representation that looks like a mathematical
* expression.)
*/
public String toString();
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/ParserContext.java
0,0 → 1,366
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* A ParserContext holds all the state data for a parsing operation, including the
* string that is being parsed, a pointer to the current position in that string,
* and the most recently parsed token from the string. The ParserContext object
* does the tokenization. Token types are retrieved by calling look() and
* next(). Attributes of the token are then available in the member variables
* tokenString, tokenObject, and tokenValue. You will probably only use this
* if you write a ParserExtension.
*/
public class ParserContext implements java.io.Serializable {
 
/**
* One of the possible token types returned by look() and next().
* Represents the end of the string
* that is being parsed.
*/
public static final int END_OF_STRING = 1;
/**
* One of the possible token types returned by look() and next().
* Indicates aht the token is a number. The numerical value
* of the token is in the tokenValue member variable.
*/
public static final int NUMBER = 2;
/**
* One of the possible token types returned by look() and next().
* The token is a word. If there is a
* MathObject in the symbol table associated
* with this word, then that object is in the
* tokenObject member variable. If not, tokenObject is null.
*/
public static final int IDENTIFIER = 3;
/**
* One of the possible token types returned by look() and next().
* Any other token besides end-of-string, number, or word.
* The only information about
* the token is the tokenString member variable. For some special operators
* (<> <= <=), the tokenString has two characters, but
* generally it has only one. Note that ** is translated
* to ^. Also, the special tokens "and", "or", and "not"
* are translated to type OPCHARS with tokenString
* equal to "&", "|", or "~" (but only if options & BOOLEANS is != 0).
*/
public static final int OPCHARS = 4;
private static final int NONE = 0; // A special value for token that is used internally to
// mean that the current token has been consumed by next()
// so that when look() or next() is called again, a new
// token has to be read. (Note that this is the initial value
// of token.)
/**
* The string that is being parsed.
*/
public String data;
/**
* Current position in that string, indicating how many
* characters have been consumed.
*/
public int pos;
/**
* The ExpressionProgram that is being generated as the string
* is parsed. Note that while parsing a ConditionalExpression, the
* value of prog is temporarily changed. ParserExtensions might
* want to do something similar.
*/
public ExpressionProgram prog;
 
/**
* The most recently read token type, or NONE if that token
* has been consumed by a call to next(). The value NONE is never
* returned by look() or next().
*/
public int token;
 
/**
* The substring of the parse string that corresponds to the most recently
* read token. This can change when look() or next() is called.
*/
public String tokenString;
/**
* If the most recently read token was of type IDENTIFIER, then
* this is the corresponding MathObject from the symbol table,
* or null if the identifier is not in the symbol table.
*/
public MathObject tokenObject;
/**
* If the most recently read token was of type NUMBER, then
* this is its numerical value.
*/
public double tokenValue;
/**
* The options from the Parser. Some of these options
* affect tokenization, such as whether BOOLEANS is enabled.
*/
public int options;
 
/**
* The Parser's symbol table, which is used for looking up
* tokens of type IDENTIFIER.
*/
protected SymbolTable symbols;
private StringBuffer tokBuf = new StringBuffer(); // Used in the readToken method. (Created
// once for efficiency.)
/**
* Create a ParserContext for parsing the data String, using the
* specified options and symbol table. A new ExpressionProgram
* is created to hold the program that will be generated from
* the string.
*/
public ParserContext(String data, int options, SymbolTable symbols) {
this.data = data;
this.options = options;
this.symbols = symbols;
prog = new ExpressionProgram();
}
 
//---------- Wrapper functions for accessing the symbol table --------------
/** MathObjects added to the symbol table after a call to mark() will
* be removed by a later, matching call to revert(). In the meantime,
* older symbols of the same name will only be hidden, not replaced,
* so they will still be there after the revert. It is important that
* a call to this routine is followed by a later call to revert! No
* error checking is done to make sure that this is true.
*/
public void mark() { // ADDED SEPTEMBER 23, 2000
symbols = new SymbolTable(symbols);
}
/* After a call to mark(), revert() must be called to restore the
* state of the symbol table.
*/
public void revert() { // ADDED SEPTEMBER 23, 2000
symbols = symbols.getParent();
}
/**
* Get the MathObject associated with name in the symbol table.
*/
public MathObject get(String name) {
if ( (options & Parser.CASE_SENSITIVE) != 0 )
return symbols.get(name);
else
return symbols.get(name.toLowerCase());
}
/**
* Add a new MathObject to the symbol table.
*/
public void add(MathObject sym) {
if ( (options & Parser.CASE_SENSITIVE) != 0 )
symbols.add(sym);
else
symbols.add(sym.getName().toLowerCase(), sym);
}
//---------------------------- Tokenization ---------------------------------
/**
* Consume one token from the string. The token type is returned.
* After this is called, attributes of the token can be obtained
* from the public member variables tokenString, tokenObject,
* and tokenValue. Note that the END_OF_STRING token is never
* really consumed and can be returned multiple times. Can
* throw a ParseError in the case of an illegal numeric token.
*/
public int next() {
int tok = look();
if (token != END_OF_STRING)
token = NONE;
return tok;
}
/**
* Look ahead at the next token in the data string, without consuming it.
* Successive calls to look() will return the same token. (The token
* must be consumed by a call to next().) The token type is returned.
* After a call to look(), attributes of the token can be obtained
* from the public member variables tokenString, tokenObject,
* and tokenValue. Can throw a ParseError in the case of an illegal
* numeric token.
*/
public int look() {
if (token == NONE) {
// Token has been consumed. Read a new token.
while (pos < data.length() && (data.charAt(pos) == ' ' || data.charAt(pos) == '\t'))
pos++;
if (pos >= data.length()) {
token = END_OF_STRING;
tokenString = null;
}
else
readToken();
}
return token;
}
/**
* Read the next token from the data string, and set the values of token, tokenString,
* tokenNumber, and tokenObject appropriately.
* When this is called, we know that pos < data.length and data.charAt(pos)
* is not blank or tab.
*/
private void readToken() {
char ch = data.charAt(pos); // The first character of the token. This determines the token type.
int savePosition = pos; // The starting position in data string.
tokBuf.setLength(0);
if (Character.isLetter(ch) || ( ch == '_' && ( (options & Parser.NO_UNDERSCORE_IN_IDENTIFIERS) == 0) )) {
token = IDENTIFIER;
while ( Character.isLetter(ch) ||
( ch == '_' && ((options & Parser.NO_UNDERSCORE_IN_IDENTIFIERS) == 0) ) ||
( Character.isDigit(ch) && ((options & Parser.NO_DIGITS_IN_IDENTIFIERS) == 0) ) ) {
tokBuf.append(ch);
pos++;
if (pos >= data.length())
break;
ch = data.charAt(pos);
}
tokenString = tokBuf.toString();
tokenObject = null;
for (int i = tokenString.length(); i > 0; i--) {
// Tricky programming: If the OPTIONAL_SPACES option is not set,
// then this for loop is executed only once, because of the break
// at the end. Therefor, only the complete string is tested as
// being a known identifier. If the option is off, then
// each prefix of the string is tested, the process ending with
// the longest prefix that is a known identifier. However, if
// no prefix is a known word, then the entire string is reported
// as an unknown identifier.
String str = tokenString.substring(0,i);
if ( ((options & Parser.BOOLEANS) != 0) ) {
// If BOOLEANS is enabled, the special words "and", "or", "not" are
// converted to operators. Case is ignored. Note that when BOOLEANS
// is enabled, it is impossible to have MathObjects named "and", "or",
// "And", "AND", etc. (That is, such MathObjects are hidden if they exist.)
if (str.equalsIgnoreCase("and")) {
token = OPCHARS;
tokenString = "&";
pos = savePosition + 3;
return;
}
else if (str.equalsIgnoreCase("or")) {
token = OPCHARS;
tokenString = "|";
pos = savePosition + 2;
return;
}
else if (str.equalsIgnoreCase("not")) {
token = OPCHARS;
tokenString = "~";
pos = savePosition + 3;
return;
}
}
if ( get(str) != null ) {
tokenString = str;
tokenObject = get(tokenString);
pos = savePosition + i;
break;
}
if ( ((options & Parser.OPTIONAL_SPACES) == 0) )
break;
}
}
else if (Character.isDigit(ch) || (ch == '.' && pos < data.length()-1 && Character.isDigit(data.charAt(pos+1)))) {
token = NUMBER;
while (pos < data.length() && Character.isDigit(data.charAt(pos)))
tokBuf.append(data.charAt(pos++));
if (pos < data.length() && data.charAt(pos) == '.') {
tokBuf.append(data.charAt(pos++));
while (pos < data.length() && Character.isDigit(data.charAt(pos)))
tokBuf.append(data.charAt(pos++));
}
if (pos < data.length() && (data.charAt(pos) == 'e' || data.charAt(pos) == 'E')) {
savePosition = pos;
tokBuf.append(data.charAt(pos++));
if (pos < data.length() && (data.charAt(pos) == '+' || data.charAt(pos) == '-'))
tokBuf.append(data.charAt(pos++));
if ( pos >= data.length() || (!Character.isDigit(data.charAt(pos))) ) {
if ( (options & Parser.OPTIONAL_STARS) == 0 )
throw new ParseError("Illegal number, '" + tokBuf.toString() + "'. No digits in exponential part.",this);
else
pos = savePosition;
}
else {
while (pos < data.length() && Character.isDigit(data.charAt(pos)))
tokBuf.append(data.charAt(pos++));
}
}
tokenString = tokBuf.toString();
double d = NumUtils.stringToReal(tokenString);
if (Double.isInfinite(d))
throw new ParseError("The number '" + tokBuf.toString() + "' is outside the range of legal numbers.",this);
if (Double.isNaN(d))
throw new ParseError("The string '" + tokBuf.toString() + "' is not a legal number.",this);
tokenValue = d;
}
else {
token = OPCHARS;
tokenString = "" + ch;
pos++;
if (pos < data.length()) {
// Check for two-character operators.
char nextch = data.charAt(pos);
switch (ch) {
case '*':
if (nextch == '*') { // "**" is an alternative to "^".
tokenString = "^";
pos++;
}
break;
case '=':
if (nextch == '<' || nextch == '>')
tokenString = data.charAt(pos++) + tokenString;
break;
case '<':
if (nextch == '=' || nextch == '>')
tokenString += data.charAt(pos++);
break;
case '>':
if (nextch == '=')
tokenString += data.charAt(pos++);
else if (nextch == '<')
tokenString = data.charAt(pos++) + tokenString;
break;
}
}
}
}
} // end class ParserContext
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/StandardFunction.java
0,0 → 1,126
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
 
/**
* This class exists to associate standard functions, such as sin and abs, with
* their names. Note that the functions are actually implemented in the
* ExprsssionProgram class, where they are only represented by numerical operation
* codes. An object of type StandardFunction contains a name and the operation
* code of the associated standard function. A static routine, standardFunctionName,
* gives the name associated with each operation code.
*/
public class StandardFunction implements MathObject {
 
private String name; // The name of this standard function.
private int code; // The operation code for this function, from class ExpressionProgram.
/**
* Create a StandardFunction object to represent the standard
* function with the given operation code, where opCode is one
* of the codes for standard functions defined in class ExpressionProgram.
* The name is the one associated with the opCode by the
* static function standardFunctionName() in this class. An error
* will occur if opCode is not one of the valid standard function
* operation codes.
*/
public StandardFunction(int opCode) {
this(standardFunctionName(opCode),opCode);
}
/**
* Create a StandardFunction object to represent the standard
* function with the given operation code, where opCode is one
* of the codes for stadard functions defined in class ExpressionProgram.
* Use the specified name for the standard function. This allows you
* to make alternative names, such as "log" instead of "log10". An error
* will occur if opCode is not one of the valid standard function
* operation codes.
*/
public StandardFunction(String name, int opCode) {
setName(name);
code = opCode;
}
/**
* Return the operation code for this standard function.
*/
public int getOpCode() {
return code;
}
 
 
//----------------------- Methods from interface MathObject --------------------
/**
* Return the name of this StandardFunction oject.
*/
public String getName() {
return name;
}
/**
* Change the name of this StandardFunction. This shouldn't be done
* if this object is registered with a Parser.
*/
public void setName(String name) {
this.name = name;
}
//-------------------------------------------------------------------------------
/**
* Return the usual name for the standard function with the
* specified opCode. The opcodes are defined in the ExpressionProgram class.
* Will throw an IllegalArgumentException if the specified oPcode is
* not the opcode for any standard function.
*/
public static String standardFunctionName(int opCode) {
switch (opCode) {
case ExpressionProgram.SIN: return "sin";
case ExpressionProgram.COS: return "cos";
case ExpressionProgram.TAN: return "tan";
case ExpressionProgram.COT: return "cot";
case ExpressionProgram.SEC: return "sec";
case ExpressionProgram.CSC: return "csc";
case ExpressionProgram.ARCSIN: return "arcsin";
case ExpressionProgram.ARCCOS: return "arccos";
case ExpressionProgram.ARCTAN: return "arctan";
case ExpressionProgram.ABS: return "abs";
case ExpressionProgram.SQRT: return "sqrt";
case ExpressionProgram.EXP: return "exp";
case ExpressionProgram.LN: return "ln";
case ExpressionProgram.LOG2: return "log2";
case ExpressionProgram.LOG10: return "log10";
case ExpressionProgram.TRUNC: return "trunc";
case ExpressionProgram.ROUND: return "round";
case ExpressionProgram.FLOOR: return "floor";
case ExpressionProgram.CEILING: return "ceiling";
case ExpressionProgram.CUBERT: return "cubert";
default: throw new IllegalArgumentException("Internal Error: Unknown standard function code.");
}
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/data/Value.java
0,0 → 1,38
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.data;
/**
* An object of type Value has a real-number value that can be retrieved by
* calling the getVal() method.
* This is a central interface, since Value objects are used throughout the
* JCM system where a real number is needed.
*/
public interface Value extends java.io.Serializable
{
/**
* Gets the current value of this object.
*/
public double getVal();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/InputObject.java
0,0 → 1,59
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
/**
* An InputObject represents some sort of value that can be changed
* by, for example, user interaction with a GUI element. The value can
* actually change only when the checkInput() method is called. Generally,
* an InputObject is a GUI element with an associated MathObject such as
* a Variable or Expression. For example, a VariableInput is a text-input
* box where the user can enter the value of a Variable. However, the
* input is only checked and the value of the variable can only change
* when the VariableInput's checkInput() method is called. The checkInput()
* method is generally meant to be called by a Controller object. The
* checkInput() method should throw a JCMError if an error occurs.
* See the Controller class for more information.
*
* @author David Eck
*/
public interface InputObject extends java.io.Serializable {
 
/**
* Check and possibly change the value associated with this InputObject.
*/
public void checkInput();
/**
* This method was introduced to provide a common interface for setting
* a Controller that is to be notified when there is a change in the
* InputObject. (This was introduced late in development, to be used
* by edu.hws.jcm.awt.JCMPanel.gatherInputs(). In all the standard
* classes that implement the InputObject interface, this method
* simply calls a setOnChange or setOnUserAction method.)
*/
public void notifyControllerOnChange(Controller c);
 
} // end interface InputObject
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/VariableSlider.java
0,0 → 1,530
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import edu.hws.jcm.data.*;
import java.awt.*;
import java.awt.event.*;
 
/**
* A VariableSlider is a slider (implemented as a Scrollbar) whose
* position represents the value of an associated variable.
* The range of values represented by the slider is given by a pair of
* Value objects. They can be specified in the constructor or later with the
* setMin and setMax methods. A VariableSlider has an associated variable
* that represents the value of the slider. Note that the value of the variable
* can change only when the setInput() or checkInput() method is called.
* If you want the value of the variable to track the position
* of the slider as it is is manipulated by the user, add the slider to
* a Controller and set the Controller as the Slider's "onUserAction" property.
* This allows other objects that depend on the values of the slider to
* be recomputed by the controller when the value changes, as long as they
* are also registered with the Controller.
*
* <p>Some points to note:
*
* 1) setVal() can set a value outside the range from min to max,
* which will persist until the next time checkInput()
* or setVal() is called again.
* 2) If the value of min or max changes, the value of this variable
* will not change EXCEPT that it is clamped to the range between min and max.
* 3) Min does not have to be less than max.
* 4) The checkInput() routine only sets the needValueCheck flag to true.
* (The setVal() and getVal() routines both set this flag to false.) This "lazy evaluation" is used because
* checkInput() can't compute the new value itself. (The max and min
* might depend on Values that are themselves about to change when some
* other object's checkInput() mehtod is called.)
* 5) getVal() returns the current value, as stored in the variable,
* UNLESS needValueCheck is true. In that case, it recomputes
* the value first. getSerialNumber() works similarly.
* 6) A VariableSlider never throws JCMErrors. If an error occurs when min
* or max is evaluated, the value of the variable associated with this VariableSlider
* becomes undefined. (The point is, it doesn't generate any errors of its own.
* The error would be caused by other InputObjects which should throw
* their own errors when their checkInput() methods are called.)
*/
public class VariableSlider extends Scrollbar implements InputObject, Tieable, Value {
/**
* The variable associated with this VariableSlider.
* VS is a nested private class, defined below.
*/
protected VS variable;
/**
* The Values that specify the range of values represented
* by the slider. min does not have to be less than max.
*/
protected Value min, max;
private Controller onUserAction; // If this is non-null, the compute() method
// of onUserAction is called when the user
// changes the position of the slider.
 
/**
* If this is true, then the value of the
* variable associated with this slider is
* an integer. Furthermore, the number of
* intervals on the slider is set to be
* the same as the range of possible values
* (unless this range is too big).
*/
protected boolean integerValued;
 
/**
* The number of possible value of the scrollbar
* (Unless integerValued is true.)
*/
protected int intervals;
 
/**
* This increases every time the value of the variable changes.
*/
protected long serialNumber;
 
/**
* This is set to true when checkInput() is called
* to indicate that the min and max values must be
* checked the next time getVal() is called.
*/
protected boolean needsValueCheck;
 
/**
* This is the position of the scrollbar the last time
* getVal() or setVal() was called. It is used to check
* whether the user has repositioned the slider.
*/
protected int oldPosition;
 
/**
* The values found for min and max the last time
* checkInput() was called.
*/
protected double minVal = Double.NaN, maxVal;
 
/**
* Create a horizontal variable slider with no name and with a default
* value range of -5 to 5.
*/
public VariableSlider() {
this(null,null,null,null);
}
/**
* Create a horizontal variable slider with no name and with the
* specified range of values. If min is null, a default
* value -5 is used. If max is null, a default value 5 is used.
*/
public VariableSlider(Value min, Value max) {
this(null,min,max,null);
}
 
/**
* Create a horizontal variable slider with the given name and range of
* values, and register it with the given parser (but only if
* both name and p are non-null). If min is null, a default
* value -5 is used. If max is null, a default value 5 is used.
*/
public VariableSlider(String name, Value min, Value max, Parser p) {
this(name,min,max,p,-1,Scrollbar.HORIZONTAL);
}
 
/**
* Create a variable slider with the given name and range of
* values, and register it with the given parser (but only if
* both name and p are non-null). The "intervals" parameter specifes
* how many different positions there are on the slider. (The value
* of the scrollbar ranges from 0 to intervals.) If intervals is <= 0,
* it will be set to 1000. If it is between 1 and 9, it will be set to 10.
* The orientation must be either Scrollbar.HORIZONTAL or Scrollbar.VERTICAL.
* It specifies whether this is a horizontal or vertical scrollbar.
* If min is null, a default value -5 is used. If max is null, a default
* value 5 is used.
*
* @param name name for this VariableSlider.
* @param min minimum value for slider.
* @param max maximum value for slider.
* @param p register VariableSlider with this Parser.
* @param intervals discrete positions on slider.
* @param orientation Scrollbar.HORIZONTAL or Scrollbar.VERTICAL.
*/
public VariableSlider(String name, Value min, Value max, Parser p, int intervals, int orientation) {
super(orientation);
setBackground(Color.lightGray);
setMin(min);
setMax(max);
if (intervals <= 0)
intervals = 1000;
if (intervals <= 10)
intervals = 10;
this.intervals = intervals;
int visible = (intervals / 50) + 3;
if (intervals < 100)
setBlockIncrement(1);
else
setBlockIncrement(intervals/100);
setValues(intervals/2,visible,0,intervals+visible);
variable = new VS(name);
if (name != null)
super.setName(name);
if (p != null && name != null)
p.add(variable);
needsValueCheck = true; // Force getVal() to compute a new value for the variable.
oldPosition = -1;
getVal();
}
 
/**
* Set the name of the associated variable. You shouldn't do this
* if it has been added to a parser. If name is non-null, then
* the name of this Component is also set to the specified name.
*/
public void setName(String name) {
variable.setName(name);
if (name != null)
super.setName(name);
}
 
/**
* A convenience method that registers this VariableSlider's variable
* with p (but only if both p and the name of the variable are non-null).
*/
public void addTo(Parser p) {
if (p != null && variable.getName() != null)
p.add(variable);
}
/**
* Return the variable associated with this VariableSlider.
*/
public Variable getVariable() {
return variable;
}
 
/**
* If set to true, restrict the values of the variable associated with this
* slider to be integers. Furthermore, the number of intervals on the
* scrollbar will be set to be the same as the size of the range from
* min to max (unless this range is too big). The setVal()
* method can still set the value of the variable to be a non-integer.
*/
public void setIntegerValued(boolean b) {
integerValued = b;
if (b && !Double.isNaN(minVal) && !Double.isNaN(maxVal))
checkIntegerLimits(minVal,maxVal);
needsValueCheck = true;
}
/**
* Return a boolean which is true if the VariableSlider restricts ranges of values to integers, false otherwise.
*/
public boolean getIntegerValued() {
return integerValued;
}
 
/**
* Set the value that the variable has when the slider is at the left (or
* bottom) of the scrollbar. If v is null, -5 is used as the default value.
*/
public void setMin(Value v) {
min = (v == null)? new Constant(-5) : v;
}
 
/**
* Set the value that the variable has when the slider is at the right (or
* top) of the scrollbar. If v is null, 5 is used as the default value.
*/
public void setMax(Value v) {
max = (v == null)? new Constant(5) : v;
}
 
/**
* Get the Value object that gives the value of the variable when the slider is
* at the left (or bottom) of the scrollbar. The Value is always non-null.
*/
public Value getMin() {
return min;
}
 
/**
* Get the Value object that gives the value of the variable when the slider is
* at the right (or top) of the scrollbar. The Value is always non-null.
*/
public Value getMax() {
return max;
}
 
/**
* If the Controller, c, is non-null, then its compute method will be called whenever
* the user adjusts the position of the scroll bar.
*/
public void setOnUserAction(Controller c) {
onUserAction = c;
enableEvents(AWTEvent.ADJUSTMENT_EVENT_MASK);
}
 
/**
* Method required by InputObject interface; in this class, it simply calls
* setOnUserAction(c). This is meant to be called by JCMPanel.gatherInputs().
*/
public void notifyControllerOnChange(Controller c) {
setOnUserAction(c);
}
 
/**
* Return the Controller, if any, that is notified when the user
* adjusts the position of the scroll bar.
*/
public Controller getOnUserAction() {
return onUserAction;
}
/**
* Return this object's serial number, which is increased every time the
* value changes.
*/
public long getSerialNumber() {
if (needsValueCheck)
getVal(); // Make sure the value/serialNumber data is up-to-date.
return serialNumber;
}
 
/**
* Change the value and serial number of this object to match
* those of newest. See the Tie class for more information.
* This is not meant to be called directly
*/
public void sync(Tie tie, Tieable newest) {
if (newest != this) {
if (! (newest instanceof Value) )
throw new IllegalArgumentException("Internal Error: A VariableSlider can only sync with Value objects.");
setVal(((Value)newest).getVal());
serialNumber = newest.getSerialNumber();
}
}
 
/**
* Get the value of this VariableSlider. (If needsValueCheck is
* true, then the value is recomputed. Otherwise, the current
* value is returned.)
*/
public double getVal() {
if (needsValueCheck) {
double newMinVal = Double.NaN;
double newMaxVal = Double.NaN;
boolean maxMinChanged = false;
double value = variable.getVariableValue(); // Current value of the variable.
try { // Compute new max/min values.
newMinVal = min.getVal();
newMaxVal = max.getVal();
if (!Double.isNaN(newMinVal) && !Double.isNaN(newMaxVal) && (newMinVal != minVal || newMaxVal != maxVal)) {
if (integerValued)
checkIntegerLimits(newMinVal,newMaxVal);
minVal = newMinVal;
maxVal = newMaxVal;
maxMinChanged = true;
}
}
catch (JCMError e) { // don't allow error to propagate
}
if (Double.isNaN(minVal) || Double.isNaN(maxVal) || Double.isInfinite(minVal) || Double.isInfinite(maxVal)) {
variable.setVariableValue(Double.NaN);
if (!Double.isNaN(value))
serialNumber++; // Value has changed.
setValue(0);
}
else if (oldPosition != getValue()) { // Position of scroll bar has been changed by user,
// so compute a new value for the variable.
double newVal = minVal + ((maxVal-minVal)*getValue())/intervals;
newVal = clamp(newVal, minVal, maxVal);
if (integerValued)
newVal = Math.round(newVal);
if (newVal != value) {
variable.setVariableValue(newVal);
serialNumber++;
}
}
else if (!Double.isNaN(value) && maxMinChanged) {
// Max/min have changed, but user has not changed scroll bar position.
// Change the value only if that is necessary to clamp it to the min/max range.
// Possibly, we have to change the position of the scroll.
double newVal = clamp(value,minVal,maxVal);
if (newVal != value) {
variable.setVariableValue(newVal);
serialNumber++;
}
if (minVal != maxVal) {
int pos = (int)( (value - minVal)/(maxVal - minVal)*intervals );
setValue(pos);
}
}
oldPosition = getValue();
needsValueCheck = false;
}
return variable.getVariableValue();
}
 
/**
* Set the value of the variable to x. If possible, set the
* value on the scroll bar to match.
*/
public void setVal(double x) {
try {
double minVal = min.getVal();
double maxVal = max.getVal();
if (Double.isNaN(x) || Double.isNaN(minVal) || Double.isNaN(maxVal) ||
Double.isInfinite(x) || Double.isInfinite(minVal) || Double.isInfinite(maxVal)) {
}
else {
if (integerValued) {
minVal = Math.round(minVal);
maxVal = Math.round(maxVal);
}
double xpos = clamp(x,minVal,maxVal);
int pos = (int)((xpos-minVal)/(maxVal-minVal)*intervals);
setValue(pos);
}
}
catch (JCMError e) {
}
variable.setVariableValue(x);
needsValueCheck = false;
oldPosition = getValue();
serialNumber++;
}
// ------------------ Some implementation details -------------------------
/**
* From the InputObject interface. This will force the slider to recompute
* its max and min values, and possibly clamp its value between these two
* extremes) the next time the value or serial number is checked. This is
* ordinarily called by a Controller.
*/
public void checkInput() {
needsValueCheck = true;
}
/**
* Modify getPreferredSize to return a width of
* 200, if the scrollbar is horzontal, or a height
* of 200, if it is vertical. This is not meant to
* be called directly.
*/
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
if (getOrientation() == Scrollbar.HORIZONTAL)
return new Dimension(200, d.height);
else
return new Dimension(d.width,200);
}
private void checkIntegerLimits(double minVal, double maxVal) {
// Called if integerValued is true to set values on scrollbar.
int oldpos = getValue();
minVal = Math.round( minVal );
maxVal = Math.round( maxVal );
double value = Math.round(variable.getVariableValue());
double range = Math.abs(minVal-maxVal);
if (range > 0 && range != intervals) {
intervals = (int)Math.min(range,10000);
double v = clamp(value, minVal, maxVal);
int pos = (int)((v-minVal)/(maxVal-minVal)*intervals);
int visible = (intervals / 50) + 3;
if (intervals < 10)
setBlockIncrement(1);
else if (intervals < 100)
setBlockIncrement(intervals/10);
else
setBlockIncrement(10+intervals/100);
setValues(pos,visible,0,intervals+visible);
}
if (oldpos == oldPosition)
oldPosition = getValue();
else
oldPosition = -1;
}
 
private double clamp(double val, double minVal, double maxVal) {
// Utility routine used by setVal and getVal. If val is
// between minVal and maxVal, it returns val. Otherwise,
// it returns one of the endpoints, minVal or maxVal.
// minVal can be greater than maxVal.
double newVal = val;
if (minVal < maxVal) {
if (newVal < minVal)
newVal = minVal;
else if (newVal > maxVal)
newVal = maxVal;
}
else {
if (newVal < maxVal)
newVal = maxVal;
else if (newVal > minVal)
newVal = minVal;
}
return newVal;
}
 
/**
* Overridden to call onUserAction.compute() if onUserAction is non-null.
* This is not meant to be called directly.
*/
public void processAdjustmentEvent(AdjustmentEvent evt) {
if (onUserAction != null)
onUserAction.compute();
super.processAdjustmentEvent(evt);
}
private class VS extends Variable {
// A modified Variable class in which the getVal and
// setVal methods are redirected to calls to the
// getVal and setVal methods in the VariableSlider
// class. The methods getVariableValue and setVariableValue
// provide access to the original getVal and setVal of
// the variable class.
VS(String name) {
super(name);
}
public double getVal() {
return VariableSlider.this.getVal();
}
public void setVal(double x) {
VariableSlider.this.setVal(x);
}
void setVariableValue(double x) {
super.setVal(x);
}
double getVariableValue() {
return super.getVal();
}
}
} // end class VariableSlider
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/JCMPanel.java
0,0 → 1,175
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import edu.hws.jcm.data.*;
import java.awt.*;
import java.awt.event.*;
 
/**
* A JCMPanel is a Panel with an associated Controller. When an InputObject or
* Computable is added to the JCMPanel, it is automatically added to the controller.
* When a sub-JCMPanel is added, the Controller of the sub-panel is "attatched" to
* the controller of the main panel so that objects in the sub-panel will also
* be controlled by the Controller of the main panel. So, if you build an
* interface entirely from JCMPanels, a lot of the control setup is done
* automatically. Note that to make this work, you will need
* a "mainPanel" that fills the entire window or applet (or at least the part that
* holds JCM components). You should also call the gatherInputs() method of
* the main JCMPanel after it is completely set up, so that changes in input objects
* will cause the panel's controller to be notified, or, alternatively, you
* can register the Controller by hand with InputObjects so that the
* Controller will be notified when they change.
*
* <p>The disadvantage of this is that all the data used in the interface is recomputed,
* even if the input objects that they depend on have not changed. For example.
* if the user changes the value in a VarialbleInput, all the points on a graph
* will be recomputed even if the function has not changed. The alternative is
* to use regular Panels for all or part of the interface and configure some
* Controllers by hand.
*
*/
public class JCMPanel extends Panel {
 
private int insetGap; // Size of gap, in pixels, around the edges of the
// Panel, where the background color shows through.
private Controller controller; // The controller associated with this panel.
/**
* Create a JCMPanel that uses a given layout manager.
*
* @param layout layout manager to use. (This could be null.)
*/
public JCMPanel(LayoutManager layout) {
enableEvents(ContainerEvent.CONTAINER_EVENT_MASK);
setLayout(layout);
}
 
/**
* Create a JCMPanel that uses a BorderLayout with horizontal and veritcal
* gaps of 3 pixels.
*/
public JCMPanel() {
this(3);
}
 
/**
* Create a JCMPanel that uses a BorderLayout with horizontal and vertical
* gaps of "gap" pixels.
*
* @param gap inset gap to use.
*/
public JCMPanel(int gap) {
this(new BorderLayout(gap,gap));
}
 
/**
* Create a JCMPanel that uses a GridLayout with the specified number of rows
* and columns and with horizontal and veritcal gaps of 3 pixels between components.
*
* @param rows number of rows in the GridLayout.
* @param columns number of columns in the GridLayout.
*/
public JCMPanel(int rows, int columns) {
this(rows,columns,3);
}
 
/**
* Create a JCMPanel that uses a GridLayout with the specified number of rows
* and columns and with horizontal and vertical gaps of "gap" pixels.
*
* @param rows number of rows in the GridLayout.
* @param columns number of columns in the GridLayout.
* @param gap number of pixels between rows and columns
*/
public JCMPanel(int rows, int columns, int gap) {
this(new GridLayout(rows,columns,gap,gap));
}
 
/**
* Set the size of the "Insets" for this JCMPanel. This is the gap, in pixels, around the edges of the
* Panel, where the background color shows through.
*
* @param x inset gap to use.
*/
public void setInsetGap(int x) {
insetGap = x;
}
/**
* Called by the system to determine how much of a gap to leave
* on each edge of the panel. Not meant to be called directly
*/
public Insets getInsets() {
return new Insets(insetGap,insetGap,insetGap,insetGap);
}
/**
* Return the controller associated with this JCMPanel.
*/
public Controller getController() {
if (controller == null)
controller = new Controller();
return controller;
}
/**
* This method will set all the input objects in this JCMPanel
* and in sub-JCMPanels, as well as any other input objects that have been
* added to the panels' Controllers, to notify the Controller of this JCMPanel
* when they change. It does this by calling setOnUserAction(c) -- or
* a corresponding method -- for each input object c. This is meant to
* be used, ordinarily, at the end of an applet's init() method, as
* an alternative to adding each of the input objects to the controller
* by hand.
*/
public void gatherInputs() {
Controller c = getController();
c.notifyControllerOnChange(c);
}
/**
* Called by the system when a component is added to or removed from
* this panel. This takes care of automatically adding and removing
* things from this Panel's Controller. This is not meant to be called directly
*/
public void processContainerEvent(ContainerEvent evt) {
Component child = evt.getChild();
if (child instanceof JCMPanel) {
if (evt.getID() == ContainerEvent.COMPONENT_ADDED)
getController().add(((JCMPanel)child).getController());
else if (evt.getID() == ContainerEvent.COMPONENT_REMOVED)
getController().remove(((JCMPanel)child).getController());
}
else if (child instanceof Computable || child instanceof InputObject) {
if (evt.getID() == ContainerEvent.COMPONENT_ADDED)
getController().add(child);
else if (evt.getID() == ContainerEvent.COMPONENT_REMOVED)
getController().remove(child);
}
}
} // end class JCMPanel
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/Computable.java
0,0 → 1,39
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
/**
* A Computable is an object that performs some sort of computation or
* action when its compute() method is called. The compute() method is
* meant to be called (usually) by a Controller. See the Controller class for more
* information.
*/
public interface Computable {
/**
* Perform the computation or action associated with this
* Computable object.
*/
public void compute();
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/DataTableInput.java
0,0 → 1,1470
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import edu.hws.jcm.data.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import java.io.*;
 
 
/**
* A DataTableInput lets the user input a grid of real numbers arranged
* in rows and columns. Each column has a name, and rows are numberd
* starting from 1. The column names and row numbers can be
* displayed, optionally. By default, a new row is added automatically
* if the user moves down out of the last row by pressing return
* or down-arrow, provided the last row is non-empty. Rows can also be
* added programmatically. Columns are usually added in the constructor,
* but they can also be added later. If the user leaves a cell
* at a time when the content of that cell does not represent a legal
* number, then the message "bad input" will be displayed in the cell.
* <p>A DataTableInput can be given a name and can then be added to a parser.
* The parser will then recognize the name of the table. In an expression, the table name
* can be followed by a ".", then one of the column names from table, then
* an expression in parentheses. This represents a reference to the number in
* one of the cells in the table. The expression gives the number of
* the row, where rows are numbered starting from 1. For example:
* "data.A(3)" represents the third number in column "A" in a table
* named data. The table name and "." can also be followed by the word "sum" and
* an expression in parentheses. An expression used in this way
* can include references to the column names in the table and to
* the special value "rowNumber". The value of expression is computed
* for each row in the table and the sum of the values is computed. In the expression that
* is being summed, a column name represents the
* number in that column and rowNumber represents the number of
* the row. For example: "data.sum(A^2)". Finally, the "." can be
* followed by the word "count". "count" can, optionally be followed
* by an empty pair of parentheses. This represents the number of
* rows. For example: "data.count". Empty rows at the bottom
* of the table are ignored in both "sum" and "count".
* <p>Note that rows are numbered starting from 1 because row numbers
* can be visible to the user, who shouldn't be subjected to zero-based
* numbering. However, columns are always numbered from zero.
*/
public class DataTableInput extends Panel implements ParserExtension {
 
private String objectName; // The name of the DataTableObject
 
private Vector rows; // Vector of double[]. Each entry holds
// the values in a row of a table. An
// entry is null for an empty row.
private Vector rowStrings; // Row values as Strings. The string "bad input"
// means that the string in the cell does not
// represent a legal number
private String[] columnName; // The name to be used to refer to the column
// in expressions. Also used as a label at the
// top of the column.
private int columnCount; // Number of columns
private int currentRow = 1; // The number of the "currentRow" which is
// specified in the setCurrentRowNumber() method.
private double emptyCellValue = Double.NaN; // An empty cell is considered to have this value.
 
private boolean throwErrors = false; // Should an error be thrown when getValue(col,row)
// sees "bad input" in the cell. If not, then the
// value is considered to be Double.NaN.
private boolean autoAddRows = true; // If this is true, an empty row is added
// when the user presses enter or hits
// down-arrow while in the last row, if that row
// is empty.
private boolean showColumnTitles; // If true, column names are shown above the columns
 
private boolean showRowNumbers; // If true, row numbers are shown to left of each row
 
private DisplayPanel canvas; // Where the table appears; nested class DisplayPanel is defined below.
private long serialNumber; // This is incremented each time the table changes.
 
private Color labelBackground = new Color(220,220,220); // Colors of various things.
private Color cellBackground = new Color(255,255,220);
private Color blankBackground = Color.gray;
private Color gridColor = Color.blue;
/**
* Create a DataTableInput with no columns. Columns can be added later
* using the addColumn() methods. The table initially has no name.
*/
public DataTableInput() {
this(null,0);
}
 
/**
* Create a table with the specified column names. If columnNames
* is null, the number of columns is zero. The name can be null, if you
* don't need a name for the table. The length of the array determines
* the number of columns in the table.
*/
public DataTableInput(String name, String[] columnNames) {
this(name,columnNames == null ? 0 : columnNames.length);
if (columnNames != null)
for (int i = 0; i < columnNames.length; i++)
setColumnName(i,columnNames[i]);
}
/**
* Create a table with the specified number of columns,
* named "A", "B", etc. The name can be null, if you
* don't need a name for the table. The number of columns can be zero.
*/
public DataTableInput(String name, int columns) {
if (columns < 0)
columns = 0;
setName(name);
rowStrings = new Vector();
rows = new Vector();
rowStrings.addElement(null);
rows.addElement(null);
columnName = new String[columns];
for (int i = 0; i < columns; i++)
columnName[i] = "" + (char)( (int)'A' + i );
canvas = new DisplayPanel();
setLayout(new BorderLayout());
setBackground(Color.lightGray);
add(canvas,BorderLayout.CENTER);
add(canvas.vScroll,BorderLayout.EAST);
columnCount = columns;
}
 
//------------------------- Data access and variables
/**
* Required by the ParserExtension interface and not meant to be called directly.
* This is called by a parser if it encounters the name of the table in an
* expression. It parses the complete table reference, such as "data.A(3)"
* or "data.sum(A^2)".
*/
public void doParse(Parser parser, ParserContext context) {
int tok = context.next();
if (tok != ParserContext.OPCHARS || !context.tokenString.equals("."))
throw new ParseError("Expected a '.' after the name of a data table.",context);
tok = context.next();
if (tok != ParserContext.IDENTIFIER)
throw new ParseError("Expected 'sum', 'count', or the name of a column after data table name.", context);
String commandName = context.tokenString;
int command = -10;
for (int i = 0; i < columnCount; i++)
if (commandName.equalsIgnoreCase(getColumnName(i))) {
command = i;
break;
}
if (command == -10) {
if (commandName.equalsIgnoreCase("sum"))
command = -1;
else if (commandName.equalsIgnoreCase("count"))
command = -2;
}
if (command == -10)
throw new ParseError("Unrecognized table command \""+ commandName + "\".", context);
if (command == -2) {
if (context.look() == ParserContext.OPCHARS && context.tokenString.equals("(")) {
context.next();
if (context.next() != ParserContext.OPCHARS || !context.tokenString.equals(")"))
throw new ParseError("Missing right parenthesis; \"count\" does not take a parameter.", context);
}
context.prog.addCommandObject(new DTEC(-2,null));
return;
}
if (context.next() != ParserContext.OPCHARS || !context.tokenString.equals("("))
throw new ParseError("Expected a left parentheses after table command \"" + commandName + "\".", context);
ExpressionProgram saveProg = context.prog;
ExpressionProgram tableProg = new ExpressionProgram();
context.prog = tableProg;
if (command == -1) {
context.mark();
for (int i = 0; i < columnCount; i++)
context.add(getColumnVariable(i));
context.add(getRowNumberVariable());
}
parser.parseExpression(context);
context.prog = saveProg;
if (context.next() != ParserContext.OPCHARS || !context.tokenString.equals(")"))
throw new ParseError("Missing right parenthesis.", context);
context.prog.addCommandObject(new DTEC(command,tableProg));
if (command == -1)
context.revert();
}
/**
* Return the number of rows in the table, ignoring empty rows at the bottom
* of the table. Note that an empty row that precedes some non-empty row
* is included in the count.
*/
public int getNonEmptyRowCount() {
int rowCt = rows.size();
while (rowCt > 0 && rows.elementAt(rowCt-1) == null)
rowCt--;
return rowCt;
}
 
/**
* Get the number in the specified row and column. Rows are numberd starting
* from 1, but columns are numbered starting from zero. If the specified
* cell does not exist in the table, Double.NaN is returned. If the cell is empty,
* emptyCellValue is returned. If the content of the cell does not define
* a legal real number, then the action depends on the value of the missingValueIsError
* property: If this property is true, then a JCMError is thrown; if it is
* false, then Double.NaN is returned.
*/
public double getCellContents(int row, int col) {
if (row < 1 || row > rows.size() || col < 0 || col > columnCount)
return Double.NaN;
return canvas.getValue(col,row);
}
/**
* Put the given real number, val, in the cell in the specified row
* and column, where rows are numbered starting from 1 and columns are
* numbered starting from zero. This is ignored if the specified row
* and column do not exist in the table.
*/
public void setCellContents(int row, int col, double val) {
if (row < 1 || row > rows.size() || col < 0 || col > columnCount)
return;
canvas.setValue(col,row,val);
}
/**
* Set the current row in the table. If the parameter is less than 1, the current
* row is set to 1.
* (The table keeps track of a "current row number", which is always greater than
* or equal to 1. This row number is used when a column variable or row number
* variable is evaluated. These variables can be added to a parser using the
* addVariablesToParser method, and can then be used in expressions parsed by
* that parser. When the row number variable, which is named rowNumber, is
* evaluated, its value is the current row number in the table. When a column
* variable is evaluated, its value is the number in the cell in the associated
* column and in the current row. The setCurrentRowNumber() method, in combination
* with the getNonEmptyRowCount() method allow you to iterate through the rows
* of the table and evaluate the expression for each row.)
*/
public void setCurrentRowNumber(int i) {
currentRow = (i < 1)? 1 : i;
}
/**
* Return the current row number.
*/
public int getCurrentRowNumber() {
return currentRow;
}
/**
* Return a column variable for the specified column, where columns are
* numbered starting from 1. The value of this variable is the number
* in the specified column and in the current row of the table (as set
* by the setCurrentRowNumber() method.) The name of the variable is
* the name of the column. This method is protected since variables are
* not meant to be used as regular variables. But they can be added to
* a Parser by calling the addVariablesToParser() method.)
*/
protected Variable getColumnVariable(final int columnNum) {
if (columnNum < 0 || columnNum >= columnCount)
throw new IllegalArgumentException("Column number out of range.");
return new Variable(getColumnName(columnNum),0) {
public void setVal(double v) {
if (currentRow < rows.size())
canvas.setValue(columnNum,currentRow,v);
super.setVal(v);
}
public double getVal(){
if (currentRow > rows.size())
return Double.NaN;
else
return canvas.getValue(columnNum,currentRow);
}
};
}
/**
* Get a variable that represents the current row number in the table,
* as set by the setCurrentRowNumber() method. The name of the
* variable is rowNumber.
*/
protected Variable getRowNumberVariable() {
return new Variable("rowNumber",0) {
public void setVal(double v) {
int val = (int)(v + 0.5);
if (val < 1 || val > getNonEmptyRowCount())
val = getNonEmptyRowCount() + 1;
currentRow = val;
super.setVal(val);
}
public double getVal(){
return currentRow;
}
};
}
/**
* Add a row number variable (from the getRowNumberVariable() method) and
* a column variable for each column (from the getColumnVariable() method)
* to the parser. The parser will then be able to parse expressions that
* refer to these variables. The value of such an expression depends on
* the current row number, as set by setCurrentRowNumber().
*/
public void addVariablesToParser(Parser p) {
p.add(getRowNumberVariable());
for (int i = 0; i < columnCount; i++) {
p.add(getColumnVariable(i));
}
}
/**
* Get the serial number of the table. This is incremented each time the
* table changes in any way.
*/
public long getSerialNumber() {
return serialNumber;
}
//-------------------------
/**
* Set the throwErrors property. If this is true, then a JCMError is thrown when
* an attempt is made to use the value of a cell that contains an invalid String.
* Note that referring to an empty cell is not an error. The default value is true.
*/
public void setThrowErrors(boolean throwErr){
throwErrors = throwErr;
}
/**
* Get the value of the throwErrors property, which determines whether an error
* is thrown when an attempt is made to refer to the value of a cell that
* contains an invalid string.
*/
public boolean getThrowErrors(){
return throwErrors;
}
/**
* Set the value that should be returned when the value of an empty cell is
* requested. The default value is Double.NaN. Another plausible value, in
* some circumstances, would be zero.
*/
public void setEmptyCellValue(double val){
emptyCellValue = val;
}
/**
* Get the value that is represented by an empty cell.
*/
public double getEmptyCellValue() {
return emptyCellValue;
}
 
/**
* If the value of autoAddRows is true, then an empty row is added to the table
* automatically when the user attempts to move down from the last row of
* the table, provided that the last row is non-empty (so there can only be
* one auto-added row at a time). If the user leaves this row while it is
* still empty, it will automatically be deleted. The default value is true.
*/
public void setAutoAddRows(boolean auto) {
// Set the autoAddRows property.
autoAddRows = auto;
canvas.lastRowAutoAdded = false;
}
/**
* Get the value of the autoAddRows property, which determines whether empty
* rows are automatically added to the bottom of the table when needed.
*/
public boolean getAutoAddRows() {
return autoAddRows;
}
/**
* Set the name of this DataTableInput. This is only needed if the table is
* to be added to a parser. The name should be a legal identifier.
*/
public void setName(String name) {
objectName = name;
}
/**
* Get the name of the DataInputTable (which might be null).
*/
public String getName() {
return objectName;
}
/**
* Set the name of column number i, where columns are numbered starting
* from zero. If column variables are to be used or if
* the DataTableInput itself is to be added to a parser, then the name should
* be a legal identifier. If the showColumnTitles property is set to true,
* then column names are shown at the top of the table.
*/
public void setColumnName(int i, String name) {
if (name != null)
columnName[i] = name;
}
/**
* Get the name of column number i, where columns are numbered starting from zero.
*/
public String getColumnName(int i) {
return columnName[i];
}
/**
* Add the specified number of empty rows at the bottom of the table. If you
* want a table with a fixed number of rows, add them with this method and
* set the autoAddRows property to false.
*/
public void addRows(int rowCt) {
canvas.addRows(rowCt,rows.size());
}
/**
* Insert a row before the row that contains the cell that the user is editing.
*/
public void insertRow() {
canvas.addRows(1,canvas.activeRow);
}
/**
* Delete the row that contains the cell that the user is editing. However,
* if that is the only row in the table, just make the row empty.
*/
public void deleteCurrentRow() {
if (canvas.activeRow == rows.size() - 1 && rows.size() > 1) {
canvas.setActive(canvas.activeRow-1,canvas.activeColumn);
rows.removeElementAt(canvas.activeRow + 1);
rowStrings.removeElementAt(canvas.activeRow + 1);
}
else {
rows.removeElementAt(canvas.activeRow);
rowStrings.removeElementAt(canvas.activeRow);
}
if (rows.size() == 0) {
rows.addElement(null);
rowStrings.addElement(null);
}
String[] vals = (String[])rowStrings.elementAt(canvas.activeRow);
if (vals == null || vals[canvas.activeColumn] == null)
canvas.input.setText("");
else
canvas.input.setText(vals[canvas.activeColumn]);
canvas.checkScroll();
canvas.repaint();
if (canvas.rowLabelCanvas != null)
canvas.rowLabelCanvas.repaint();
if (canvas.columnLabelCanvas != null)
canvas.columnLabelCanvas.repaint();
serialNumber++;
}
/**
* Remove all rows from the table, leaving just one empty row.
*/
public void clear() {
rows = new Vector();
rowStrings = new Vector();
rows.addElement(null);
rowStrings.addElement(null);
canvas.setActive(0,0);
canvas.checkScroll();
canvas.repaint();
if (canvas.rowLabelCanvas != null)
canvas.rowLabelCanvas.repaint();
if (canvas.columnLabelCanvas != null)
canvas.columnLabelCanvas.repaint();
serialNumber++;
}
/**
* Get the number of columns in the table.
*/
public int getColumnCount() {
return columnName.length;
}
/**
* Add a column at the right side of the table, with all cells initially
* empty. The name of the columns will be single letter such as 'A', 'B', ...
*/
public int addColumn() {
return addColumn(null);
}
/**
* Add a column with the specified name at the right side of the table, with all cells initially
* empty. This is inefficient if the table already contains a bunch of non-empty rows.
*/
public int addColumn(String name) {
int newSize = columnName.length + 1;
String[] newNames = new String[newSize];
for (int i = 0; i < columnName.length; i++)
newNames[i] = columnName[i];
if (name == null)
newNames[newSize-1] = "" + (char)( (int)'A' + newSize - 1 );
else
newNames[newSize-1] = name;
columnName = newNames;
int rowCt = rows.size();
for (int i = 0; i < rowCt; i++) {
if (rows.elementAt(i) != null) {
double[] oldRow = (double[])rows.elementAt(i);
double[] newRow = new double[newSize];
for (int j = 0; j < oldRow.length; j++)
newRow[j] = oldRow[j];
newRow[newSize - 1] = Double.NaN;
rows.setElementAt(newRow,i);
}
if (rowStrings.elementAt(i) != null) {
String[] oldRow = (String[])rows.elementAt(i);
String[] newRow = new String[newSize];
for (int j = 0; j < oldRow.length; j++)
newRow[j] = oldRow[j];
rowStrings.setElementAt(newRow,i);
}
}
if (canvas.hScroll != null)
canvas.checkScroll();
canvas.repaint();
if (canvas.columnLabelCanvas != null)
canvas.columnLabelCanvas.repaint();
columnCount = columnName.length;
serialNumber++;
return columnCount - 1;
}
/**
* Test whether the column name is shown at the top of each column.
*/
public boolean getShowColumnTitles() {
return showColumnTitles;
}
/**
* If set to true, then the column name is shown at the top of each column. The
* default value is false. This is meant to be called before the table has been
* shown on the screen, such as in the init() method of an applet. If you call it
* after the table has already been shown, you will have to validate the panel
* yourself.
*/
public void setShowColumnTitles(boolean show) {
if (show == showColumnTitles)
return;
showColumnTitles = show;
if (showColumnTitles) {
canvas.makeColumnLabelCanvas();
add(canvas.columnLabelCanvas, BorderLayout.NORTH);
}
else {
remove(canvas.columnLabelCanvas);
canvas.columnLabelCanvas = null;
}
}
/**
* Test whether row numbers are shown.
*/
public boolean getShowRowNumbers() {
return showRowNumbers;
}
/**
* If set to true, then the row number is shown at the left of each row. The
* default value is false. This is meant to be called before the table has been
* shown on the screen, such as in the init() method of an applet. If you call it
* after the table has already been shown, you will have to validate the panel
* yourself.
*/
public void setShowRowNumbers(boolean show) {
if (show == showRowNumbers)
return;
showRowNumbers = show;
if (showRowNumbers) {
canvas.makeRowLabelCanvas();
add(canvas.rowLabelCanvas, BorderLayout.WEST);
}
else {
remove(canvas.rowLabelCanvas);
canvas.rowLabelCanvas = null;
}
}
/**
* Returns the color that is used as a background for row numbers and column titles.
*/
public Color getLabelBackground() {
return labelBackground;
}
/**
* Set the color to be used as a background for row numbers and column titles.
* The default is a very light gray.
*/
public void setLabelBackground(Color color) {
if (color != null)
labelBackground = color;
}
/**
* Returns the color that is used as a background for cells in the table.
*/
public Color getCellBackground() {
return cellBackground;
}
/**
* Set the color to be used as a background for cells in the table.
* The default is a light yellow.
*/
public void setCellBackground(Color color) {
if (color != null)
cellBackground = color;
}
/**
* Returns the color that is used for blank areas in the table, below the
* rows of cells.
*/
public Color getBlankBackground() {
return blankBackground;
}
/**
* Get the color to be used as a background blank areas in the table, below the
* rows of cells. The default is a gray.
*/
public void setBlankBackground(Color color) {
if (color != null)
blankBackground = color;
}
/**
* Returns the color that is used for the lines between cells in the table.
*/
public Color getGridColor() {
return gridColor;
}
/**
* Get the color to be used for the lines between cells in the table.
* The default is a blue.
*/
public void setGridColor(Color color) {
if (color != null)
gridColor = color;
}
/**
* Read data for table from the specified Reader. One row is filled
* from each non-empty line of input. The line should contain
* numbers separated by spaces/tabs/commas. The word "undefined"
* can be used to represent an empty cell. Otherwise, if a non-number is
* encountered, an error occurs. If not enough numbers are
* found on a line, the extra columns are filled with empties. After
* filling all columns, extra data on the line is ignored.
* Data currently in the table is removed and replaced (if no error
* occurs during reading). In the case of an error, if throwErrors is
* true, then a JCMError is thrown; if throwErrors is false, no
* error is thrown, but the return value is false. If no error occurs,
* the return value is true. If an error occurs, the previous data
* in the table is left unchanged.
*/
public boolean readFromStream(Reader in) {
Vector newRows = new Vector();
int cols = columnCount;
try {
StreamTokenizer tokenizer = new StreamTokenizer(in);
tokenizer.resetSyntax();
tokenizer.eolIsSignificant(true);
tokenizer.whitespaceChars(',', ',');
tokenizer.whitespaceChars(' ', ' ');
tokenizer.whitespaceChars('\t', '\t');
tokenizer.wordChars('a','z');
tokenizer.wordChars('A','Z');
tokenizer.wordChars('0','9');
tokenizer.wordChars('.','.');
tokenizer.wordChars('+','+');
tokenizer.wordChars('-','-');
int token = tokenizer.nextToken();
while ( true ) {
while (token == StreamTokenizer.TT_EOL) // ignore empty lines
token = tokenizer.nextToken();
if (token == StreamTokenizer.TT_EOF)
break;
double[] row = new double[cols];
for (int i = 0; i < cols; i++) {
if (token == StreamTokenizer.TT_EOL || token == StreamTokenizer.TT_EOF)
row[i] = Double.NaN;
else if (token == StreamTokenizer.TT_WORD) {
if (tokenizer.sval.equalsIgnoreCase("undefined"))
row[i] = Double.NaN;
else {
try {
Double d = new Double(tokenizer.sval);
row[i] = d.doubleValue();
}
catch (NumberFormatException e) {
throw new IOException("Illegal non-numeric data (" +
tokenizer.sval + ") encountered.");
}
}
token = tokenizer.nextToken();
}
else
throw new IOException("Illegal non-numeric data encountered.");
}
newRows.addElement(row);
while (token != StreamTokenizer.TT_EOL && token != StreamTokenizer.TT_EOF)
token = tokenizer.nextToken();
}
if (rows.size() == 0)
throw new IOException("Empty data was found.");
}
catch (Exception e) {
if (throwErrors)
throw new JCMError("Error while reading data: " + e, this);
return false;
}
canvas.setActive(0,0);
rows = newRows;
rowStrings = new Vector();
for (int i = 0; i < rows.size(); i++) {
String[] s = new String[cols];
double[] d = (double[])rows.elementAt(i);
for (int col = 0; col < cols; col++)
if (Double.isNaN(d[col]))
s[col] = null;
else
s[col] = NumUtils.realToString(d[col]);
rowStrings.addElement(s);
}
canvas.input.setText( ((String[])rowStrings.elementAt(0))[0] );
if (canvas.hScroll != null)
canvas.hScroll.setValue(0);
canvas.vScroll.setValue(0);
canvas.checkScroll();
canvas.repaint();
if (canvas.rowLabelCanvas != null)
canvas.rowLabelCanvas.repaint();
if (canvas.columnLabelCanvas != null)
canvas.columnLabelCanvas.repaint();
serialNumber++;
return true;
}
 
//------------------------------ private nested classes -------------------------------
private class InputBox extends TextField {
// An object of type InputBox is used for user input
// of numbers in the table. There is only one input box
// and it moves around.
InputBox() {
super(12);
setBackground(Color.white);
setForeground(Color.black);
enableEvents(AWTEvent.KEY_EVENT_MASK + AWTEvent.MOUSE_EVENT_MASK);
}
public void processKeyEvent(KeyEvent evt) {
if (evt.getID() == KeyEvent.KEY_PRESSED) {
int ch = evt.getKeyCode();
char chr = evt.getKeyChar();
boolean use = (chr != 0 && Character.isDigit(chr) || chr == '.' || chr == 'E'
|| chr == '-' || chr == '+'
|| chr == 'e') || ch == KeyEvent.VK_DELETE ||
ch == KeyEvent.VK_BACK_SPACE;
boolean useControl = use || chr == 0;
if (!useControl || ch == KeyEvent.VK_ENTER || ch == KeyEvent.VK_DOWN
|| ch == KeyEvent.VK_UP || ch == KeyEvent.VK_TAB) {
if (ch == KeyEvent.VK_ENTER || ch == KeyEvent.VK_DOWN)
canvas.doRowDown();
else if (ch == KeyEvent.VK_UP)
canvas.doRowUp();
else if (ch == KeyEvent.VK_TAB)
canvas.doColumnRight();
else
Toolkit.getDefaultToolkit().beep();
evt.consume();
}
else if (ch == KeyEvent.VK_LEFT && getCaretPosition() == 0) {
canvas.doColumnLeft();
evt.consume();
}
else if (ch == KeyEvent.VK_RIGHT && getCaretPosition() == getText().length()) {
canvas.doColumnRight();
evt.consume();
}
}
super.processKeyEvent(evt);
}
public void processMouseEvent(MouseEvent evt) {
if (evt.getID() == MouseEvent.MOUSE_PRESSED)
canvas.ensureActiveVisible();
super.processMouseEvent(evt);
}
} // end nested class InputBox
private class DisplayPanel extends Panel
implements TextListener,MouseListener,AdjustmentListener,ComponentListener {
// An object of this class is the actual table seen by the user.
// The panel itself is just the grid of cells. The row and column
// labels and the scroll bars are variables in the DisplayPanel
// ojbect, but they are added to the containing Panel in the
// constructor for DataTableInput above.
 
InputBox input; // Text field for user input, from nested class defined above.
int activeRow = 0, activeColumn = 0; // Where the Input box is.
int rowHeight=-1, columnWidth; // Size of each cell. rowHeight = -1 indiacates
// the size is not yet known.
 
Scrollbar hScroll,vScroll; // for scrolling through the grid of cells.
 
Canvas rowLabelCanvas, columnLabelCanvas; // These canvasses hold the row
// and column lables and are displayed
// to the left of and above the grid of cells.
// They scroll along with the grid.
// They are null and are enabled by
// methods setShowRowNumbers and setShowColumnTitles
boolean lastRowAutoAdded; // True if last row was auto added.
// If the user leaves this row while
// it is still empty, it will be auto deleted.
// Empty rows added with the addRows() method
// are not deleted in this way.
 
DisplayPanel() {
setBackground(cellBackground);
input = new InputBox();
vScroll = new Scrollbar(Scrollbar.VERTICAL);
vScroll.setBackground(Color.lightGray);
input.addTextListener(this);
vScroll.addAdjustmentListener(this);
addMouseListener(this);
setLayout(null);
add(input);
addComponentListener(this);
}
void makeRowLabelCanvas() {
rowLabelCanvas = new Canvas() { // canvas for showing row labels
public void paint(Graphics g) {
int topRow = vScroll.getValue() / rowHeight;
int rowCt = getSize().height / rowHeight + 1;
int tableRows = rows.size();
FontMetrics fm = g.getFontMetrics();
int textOffset = (rowHeight + fm.getAscent()) / 2;
int vScrollVal = vScroll.getValue();
for (int i = topRow; i < rowCt + topRow && i < tableRows; i++) {
String rs = "" + (i+1);
int os = (getSize().width - fm.stringWidth(rs)) / 2;
g.drawString(rs,os,textOffset + rowHeight*i - vScrollVal);
}
}
public Dimension getPreferredSize() {
return new Dimension(35,50);
}
};
rowLabelCanvas.setBackground(labelBackground);
}
void makeColumnLabelCanvas() {
columnLabelCanvas = new Canvas() { // canvas for showing column labels
public void paint(Graphics g) {
int leftColumn = 0;
if (hScroll != null)
leftColumn = hScroll.getValue() / columnWidth;
int blank = (rowLabelCanvas == null)? 0 : 35; // width of rowLabelCanvas
int columnCt = (getSize().width-blank) / columnWidth + 1;
FontMetrics fm = g.getFontMetrics();
int textOffset = (getSize().height + fm.getAscent()) / 2;
int hScrollVal = hScroll == null ? 0 : hScroll.getValue();
for (int i = leftColumn; i < leftColumn + columnCt && i < columnCount; i++) {
String s = getColumnName(i);
int os = (columnWidth - fm.stringWidth(s)) / 2;
g.drawString(s,blank + i*columnWidth + os - hScrollVal,textOffset);
}
g.setColor(Color.gray);
g.fillRect(0,0,blank,getSize().height);
}
public Dimension getPreferredSize() {
return new Dimension(50,20);
}
};
columnLabelCanvas.setBackground(labelBackground);
}
public void addNotify() {
// Determine the size of a cell, which is based on the preferred size
// of the input box (which can't be determined until after the peer
// is added. (I hope this works on all platforms!)
super.addNotify();
if (rowHeight != -1)
return;
Dimension size = input.getPreferredSize();
rowHeight = size.height-1;
columnWidth = size.width-1;
input.setBounds(1,1,columnWidth+1,rowHeight+1);
}
public void update(Graphics g) {
// Don't fill in with background before painting.
paint(g);
}
public void paint(Graphics g) {
// Draw the grid of cells, in position based on scroll bar values.
int hScrollVal = (hScroll == null)? 0 : hScroll.getValue();
int vScrollVal = vScroll.getValue();
int width = getSize().width; // width and height of component
int height = getSize().height;
int tableWidth = columnCount*columnWidth + 2;
int tableHeight = rows.size()*rowHeight + 2;
int tableRows = rows.size(); // Number of rows in table
Rectangle clip = g.getClipBounds(); // Try to avoid uncessary painting by checking clip rect.
int topRow, rowCt, leftColumn, columnCt;
if (clip != null) { // change data about included rows, columns
topRow = (vScrollVal + clip.y) / rowHeight;
rowCt = clip.height / rowHeight + 1;
leftColumn = (hScrollVal + clip.x) / columnWidth;
columnCt = clip.width / columnWidth + 1;
}
else {
topRow = vScrollVal / rowHeight; // top visible row
rowCt = height / rowHeight + 1; // num of rows possibly visible
leftColumn = hScrollVal / columnWidth;// leftmost visible column
columnCt = width / columnWidth + 1; // num of columns visible
}
FontMetrics fm = g.getFontMetrics();
int textOffset = (rowHeight + fm.getAscent()) / 2; // from top of box to text baseline
for (int i = topRow; i < topRow + rowCt && i < tableRows; i++ ) {
String[] contents = (String[])rowStrings.elementAt(i);
for (int c = 0; c < columnCount; c++)
if (c != activeColumn || i != activeRow) {
g.setColor(cellBackground);
g.fillRect(1+c*columnWidth-hScrollVal,1+i*rowHeight-vScrollVal,columnWidth,rowHeight);
g.setColor(getForeground());
if (contents != null && contents[c] != null && contents[c].length() > 0) {
String s = contents[c];
g.drawString(s,c*columnWidth + 5 - hScrollVal, textOffset + i*rowHeight - vScrollVal);
}
}
}
if (width > tableWidth) {
g.setColor(blankBackground);
g.fillRect(tableWidth,0,width-tableWidth,height);
}
if (height > tableHeight) {
g.setColor(blankBackground);
g.fillRect(0,tableHeight,width,height-tableHeight);
}
g.setColor(gridColor);
g.drawRect(0,0,tableWidth, tableHeight);
g.drawRect(1,1, tableWidth - 2, tableHeight - 2);
for (int i = - 1; i < topRow + rowCt && i < tableRows; i++)
g.drawLine(0, 1 + (i+1)*rowHeight - vScrollVal, tableWidth - 1, 1 + (i+1)*rowHeight - vScrollVal);
for (int j = 0; j <= columnCount; j++)
g.drawLine(1 + j*columnWidth - hScrollVal, 0, 1 + j*columnWidth - hScrollVal, tableHeight - 1);
}
void setActive(int row, int column) {
// Move the input box to the specified row and column, and
// move the focus to the input box.
if (row != activeRow || column != columnWidth) {
int topOffset = vScroll.getValue();
int leftOffset = (hScroll == null)? 0 : hScroll.getValue();
int y = -topOffset + row*rowHeight + 1;
int x = -leftOffset + column*columnWidth + 1;
input.setLocation(x,y);
activeRow = row;
activeColumn = column;
String[] contents = (String[])rowStrings.elementAt(activeRow);
if (contents == null || contents[activeColumn] == null)
input.setText("");
else
input.setText(contents[activeColumn]);
}
ensureActiveVisible();
input.selectAll();
input.requestFocus();
}
void doRowDown() {
// Move active box down one row. Create a new row if in the
// last row, that row is non-empty, and autoAddRows is true.
int tableRows = rows.size();
if (activeRow == tableRows - 1 && autoAddRows && rows.elementAt(tableRows-1) != null) {
addRows(1,tableRows);
lastRowAutoAdded = true;
}
if (activeRow < rows.size() - 1)
setActive(activeRow+1,activeColumn);
else {
ensureActiveVisible();
input.requestFocus();
}
}
void doRowUp() {
// Move up one row. If leaving an empty row that was autoadded, delete it.
if (activeRow == 0)
return;
setActive(activeRow - 1, activeColumn);
if (autoAddRows && lastRowAutoAdded == true && activeRow == rows.size() - 2 && rows.elementAt(activeRow+1) == null) {
// delete empty row from bottom of table
rows.removeElementAt(rows.size() - 1);
rowStrings.removeElementAt(rowStrings.size() - 1);
checkScroll();
repaint();
if (rowLabelCanvas != null)
rowLabelCanvas.repaint();
input.requestFocus();
}
lastRowAutoAdded = false;
}
void doColumnRight() {
// Move active box right to the next column, possibly
// wrapping around to the first column.
int c = activeColumn + 1;
if (c >= columnCount)
c = 0;
setActive(activeRow,c);
}
void doColumnLeft() {
// Move active box left to the next column, possibly
// wrapping around to the last column.
int c = activeColumn - 1;
if (c < 0)
c = columnCount - 1;
setActive(activeRow,c);
}
void ensureActiveVisible() {
// Make sure that the entire input box is visible.
int x = columnWidth*activeColumn + 1;
int y = rowHeight*activeRow + 1;
int visibleLeft = (hScroll == null)? 0 : hScroll.getValue();
int visibleTop = vScroll.getValue();
int visibleRight = visibleLeft + getSize().width;
int visibleBottom = visibleTop + getSize().height;
int offsetX = 0;
int offsetY = 0;
if (x + columnWidth > visibleRight)
offsetX = -(x + columnWidth - visibleRight);
if (x < visibleLeft)
offsetX = visibleLeft - x;
if (y + rowHeight > visibleBottom)
offsetY = -(y + rowHeight - visibleBottom);
if (y < visibleTop)
offsetY = visibleTop - y;
if (offsetX == 0 && offsetY == 0)
return;
if (offsetX != 0) {
if (hScroll != null)
hScroll.setValue(visibleLeft - offsetX);
if (columnLabelCanvas != null)
columnLabelCanvas.repaint();
}
if (offsetY != 0) {
vScroll.setValue(visibleTop - offsetY);
if (rowLabelCanvas != null)
rowLabelCanvas.repaint();
}
input.setLocation(x - ( hScroll == null ? 0 : hScroll.getValue() ),y - vScroll.getValue());
repaint();
}
void addRows(int num, int before) {
// Add specified number of rows to table, before row
// number before. If before is after the last existing
// row, the rows are added at the end of the table.
serialNumber++;
if (num <= 0)
return;
if (before >= rows.size()) {
for (int i = 0; i < num; i++) {
rows.addElement(null);
rowStrings.addElement(null);
lastRowAutoAdded = false;
}
}
else {
if (before < 0)
before = 0;
for (int i = 0; i < num; i++) {
rows.insertElementAt(null,before);
rowStrings.insertElementAt(null,before);
}
if (activeRow >= before) { // data in active cell changes
String[] vals = (String[])rowStrings.elementAt(activeRow);
if (vals == null || vals[activeColumn] == null)
input.setText("");
else
input.setText(vals[activeColumn]);
}
}
checkScroll();
repaint();
if (rowLabelCanvas != null)
rowLabelCanvas.repaint();
}
void setValue(int column, int row, double value) {
// set the value in the column at given row and column.
// Note that row numbers start at 1 in this method!!
// Row and column numbers are assumed to be in legal range!!
String num = NumUtils.realToString(value);
setRowData(row-1,column,num,value);
if (column == activeColumn && row-1 == activeRow)
input.setText(num);
else {
repaintItem(row-1,column);
}
}
double getValue(int column, int row) {
// Get the value from the table in the given row and column.
// Note that row numbers start at 1 in this method!!
// Row and column numbers are assumed to be in legal range!!
if (rows.elementAt(row-1) == null)
return emptyCellValue;
else {
double d = ((double[])rows.elementAt(row-1))[column];
if ( ! Double.isNaN(d) )
return d;
else {
String val = ((String[])rowStrings.elementAt(row-1))[column];
if (val == null || val.length() == 0)
return emptyCellValue;
else // val is "bad input", the only other possibility if d is NaN
if (throwErrors)
throw new JCMError("Invalid numerical input in data table, column \""
+ getColumnName(column) + "\", row " + row + ".", this);
else
return Double.NaN;
}
}
}
public void textValueChanged(TextEvent txt) {
// From TextListener interface. When text in input box changes,
// change the stored string and stored value for that position to match.
String num = input.getText().trim();
if (num.length() == 0)
setRowData(activeRow,activeColumn,num,Double.NaN);
else {
double x;
try {
Double d = new Double(num);
x = d.doubleValue();
}
catch (NumberFormatException e) {
x = Double.NaN;
}
if (Double.isNaN(x))
setRowData(activeRow,activeColumn,"bad input",x);
else
setRowData(activeRow,activeColumn,num,x);
}
}
void setRowData(int row, int col, String num, double val) {
// puts num, val into rows, rowStrings vectors at position row,col
// Empty rows are always represented by null's in the rowVals
// and rowStrings vectores. This requires a bit of care.
serialNumber++;
double[] rowVals = (double[])rows.elementAt(row);
String[] rowStr = (String[])rowStrings.elementAt(row);
if (num.length() == 0) {
if (rowStr == null || rowStr[col] == null)
return;
rowStr[col] = null;
rowVals[col] = Double.NaN;
boolean empty = true;
for (int i = 0; i < rowStr.length; i++)
if (rowStr[i] != null) {
empty = false;
break;
}
if (empty) {
rows.setElementAt(null,row);
rowStrings.setElementAt(null,row);
}
}
else {
if (num.length() > 12)
num = NumUtils.realToString(val,12);
if (rowStr == null) {
int ct = columnCount;
rowVals = new double[ct];
rowStr = new String[ct];
for (int i = 0; i < ct; i++)
rowVals[i] = Double.NaN;
rows.setElementAt(rowVals,row);
rowStrings.setElementAt(rowStr,row);
}
rowStr[col] = num;
rowVals[col] = val;
}
}
protected void repaintItem(int row, int column) {
// forces a repaint for just the specified cell
int y = row*rowHeight - vScroll.getValue();
int x = column*columnWidth;
if (hScroll != null)
x -= hScroll.getValue();
repaint(x+1,y+1,columnWidth-1,rowHeight-1);
}
public void adjustmentValueChanged(AdjustmentEvent evt) {
// From the AdjustmentListener interface. React to
// change in scroll positions.
repaint();
if (evt.getSource() == vScroll) {
if (rowLabelCanvas != null)
rowLabelCanvas.repaint();
}
else {
if (columnLabelCanvas != null)
columnLabelCanvas.repaint();
}
int x = columnWidth*activeColumn + 1;
if (hScroll != null)
x -= hScroll.getValue();
int y = rowHeight*activeRow + 1 - vScroll.getValue();
input.setLocation(x,y);
}
 
public void mousePressed(MouseEvent evt) {
// From the MouseListener interface. Move the active
// cell to an input cell close to mouse click.
int hOffset = (hScroll == null)? 0 : hScroll.getValue();
int vOffset = vScroll.getValue();
int row = (evt.getY() + vOffset - 1) / rowHeight;
if (row < 0)
row = 0;
else if (row >= rows.size())
row = rows.size() - 1;
int col = (evt.getX() + hOffset - 1) / columnWidth;
if (col < 0)
col = 0;
else if (col >= columnCount)
col = columnCount - 1;
if (row == activeRow && col == activeColumn)
ensureActiveVisible(); // want to avoid doing selectAll if box doesn't move
else
setActive (row,col);
int emptyRow = rows.size() - 1;
if (!lastRowAutoAdded || emptyRow == row)
return;
lastRowAutoAdded = false;
if (rows.elementAt(emptyRow) != null)
return;
rows.removeElementAt(emptyRow);
rowStrings.removeElementAt(emptyRow);
checkScroll();
repaint();
if (rowLabelCanvas != null)
rowLabelCanvas.repaint();
}
public void componentResized(ComponentEvent evt) {
// From ComponentListener interface. Fix scroll bars after resize.
checkScroll();
}
void checkScroll() {
// Make sure scoll bars are OK after resize, adding rows, etc.
int width = DisplayPanel.this.getSize().width;
int height = DisplayPanel.this.getSize().height;
if (rowHeight == -1 || width <= 1)
return;
int tableWidth = columnWidth*columnCount + 2;
int tableHeight = rowHeight*rows.size() + 2;
int oldTop = vScroll.getValue();
int oldLeft = (hScroll == null)? 0 : hScroll.getValue();
boolean revalidate = false;
if (width >= tableWidth - 2) {
if (hScroll != null) {
int scrollHeight = hScroll.getPreferredSize().height;
DataTableInput.this.remove(hScroll);
hScroll = null;
height += scrollHeight;
revalidate = true;
}
}
else {
if (hScroll == null) {
hScroll = new Scrollbar(Scrollbar.HORIZONTAL);
hScroll.setBackground(Color.lightGray);
int scrollHeight = hScroll.getPreferredSize().height;
height -= scrollHeight;
DataTableInput.this.add(hScroll, BorderLayout.SOUTH);
hScroll.addAdjustmentListener(this);
revalidate = true;
}
if (oldLeft > tableWidth - width)
hScroll.setValues(tableWidth-width,width,0,tableWidth);
else
hScroll.setValues(oldLeft,width,0,tableWidth);
hScroll.setUnitIncrement(columnWidth / 4);
if (width > 1)
hScroll.setBlockIncrement((3*width)/4);
}
if (height >= tableHeight - 2) {
vScroll.setEnabled(false);
vScroll.setValues(0,1,0,1);
}
else {
if (oldTop > tableHeight - height)
vScroll.setValues(tableHeight-height,height,0,tableHeight);
else
vScroll.setValues(oldTop,height,0,tableHeight);
vScroll.setUnitIncrement(rowHeight);
if (height > 1)
vScroll.setBlockIncrement((3*height)/4);
vScroll.setEnabled(true);
}
int x = columnWidth*activeColumn + 1;
if (hScroll != null)
x -= hScroll.getValue();
int y = rowHeight*activeRow + 1 - vScroll.getValue();
input.setLocation(x,y);
if (revalidate)
DataTableInput.this.validate();
}
public Dimension getPreferredSize() {
if (rowHeight == -1)
return new Dimension(350,200);
else if (columnCount >= 4)
return new Dimension(4*columnWidth+2,6*rowHeight+2);
else
return new Dimension(columnCount*columnWidth+2,6*rowHeight+2);
}
 
public void mouseEntered(MouseEvent evt) {} // Other methods from listener interfaces.
public void mouseExited(MouseEvent evt) {}
public void mouseClicked(MouseEvent evt) {}
public void mouseReleased(MouseEvent evt) {}
public void componentHidden(ComponentEvent evt) {}
public void componentShown(ComponentEvent evt) {}
public void componentMoved(ComponentEvent evt) {}
} // end nested class Display Panel
private class DTEC implements ExpressionCommand {
// This is used in the doParse() method. When a reference to a DataInputTable
// is found by a parser, the doParse() method will add an object of this
// type to the ExpressionProgram that the parseris producing. A DTEC represents
// a sub-exprssion such as "data.A(3)" or "data.sum(A^2)"
ExpressionProgram prog; // The expression inside the parentheses
 
int command; // The column number for an expression such as "data.A(3)" which
// represents the value of a cell in column "A". For the sum
// function, command is -1. For the count funtion, it is -2.
DTEC(int command, ExpressionProgram prog) {
this.command = command;
this.prog = prog;
}
public void apply(StackOfDouble stack, Cases cases) {
if (command >= 0) { // Reference to a column. Value of prog gives row number.
double loc = prog.getVal();
if (Double.isNaN(loc) || loc < 0.5 || loc >= rows.size() + 0.5)
stack.push(Double.NaN);
else
stack.push(canvas.getValue(command,(int)(loc+0.5)));
}
else if (command == -1) { // sum of the prog expression for all rows in the table.
double sum = 0;
int top = getNonEmptyRowCount();
for (int row = 1; row <= top; row++) {
setCurrentRowNumber(row);
sum += prog.getVal();
}
stack.push(sum);
}
else if (command == -2) { // the count of rows in the table
stack.push(getNonEmptyRowCount());
}
}
public void compileDerivative(ExpressionProgram prog, int myIndex, ExpressionProgram deriv, Variable wrt) {
if (command != -1) {
deriv.addConstant(0);
}
else {
ExpressionProgram d = (ExpressionProgram)this.prog.derivative(wrt);
deriv.addCommandObject( new DTEC(command,d) );
}
}
public int extent(ExpressionProgram prog, int myIndex) {
return 1;
}
public boolean dependsOn(Variable x) {
if (command == -2)
return false;
else
return prog.dependsOn(x);
}
 
public void appendOutputString(ExpressionProgram prog, int myIndex, StringBuffer buffer) {
buffer.append(getName());
buffer.append('.');
if (command == -2)
buffer.append("count");
else if (command == -1)
buffer.append("sum");
else
buffer.append(getColumnName(command));
buffer.append("(");
if (command != -2)
buffer.append(this.prog.toString());
buffer.append(")");
}
} // end nested class DTEC
} // end class DataTableInput
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/Limits.java
0,0 → 1,50
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
/**
* The Limits interface is implemented by edu.hws.jcm.data.CoordinateRect
* and by other objects that can be "Tied" to a CoordinateRect, such as
* LimitControlPanel. This will be used to synchronize the (x,y)
* limits on the CoordinateRect with limit values obtained elsewhere.
* See the Tie class for more information.
*
* @author David Eck
*/
public interface Limits extends java.io.Serializable {
 
/**
* Return a 4-element array containing xmin, xmax, ymin, and ymax.
*/
public double[] getLimits();
/**
* Set the current limits.
*
* @param A 4-element array containing the new xmin, xmax, ymin, and ymax.
*/
public void setLimits(double[] limits);
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/DisplayLabel.java
0,0 → 1,242
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import java.awt.*;
import edu.hws.jcm.data.*;
 
/**
* A DisplayLabel is a label that can display numbers embedded in
* strings. The text for the label can include '#' characters, which
* are substituted by values of specified Value objects. (A doubled
* ## is interpreted as a single literal # to be displayed rather than
* substituted.) You should provide as many Values as there
* are #'s in the text. However, no errors are generated if this
* is not the case. Extra expressions are ignored; extra #'s are
* shown as "undefined" in the display. In fact, DisplayLabels
* do not ever generat JCMErrors. Note that Value objects include
* objects of type Constant, Variable, and Expression, for example. Value
* is just an interface defined in package edu.hws.jcm.data.
*
* <p>The values displayed in a DisplayLabel are recomputed when
* the Label's compute() method is called. Usually, this is
* done by a Controller that the DisplayLabel is registered with.
* See the Controller class for more information.
*/
public class DisplayLabel extends Label implements Computable {
 
/**
* Unsubstituted text for display.
*/
protected String text;
/**
* Desired maximum number of characters in displayed numbers.
*/
protected int numSize = 10;
 
/**
* Value objects whose values will be
* substituted for #'s in text.
*/
protected Value[] values;
 
/**
* Create a label with no expressions set up to display a
* single number. Initial value is "undefined"; Use the
* setValue() method to set the value to be displayed.
*/
public DisplayLabel() {
this(null,(Value[])null);
}
/**
* Convenience method for making a DisplayLabel with just one value to display.
*
* @param text Text to display. It shoud contain a single '#', which will be substituted by the value.
* @param val a Value object whose value is substituted for the # in the text.
*/
public DisplayLabel(String text, Value val) {
this(text, (val == null)? null : new Value[] { val });
}
 
/**
* Create a DisplayLabel to display one or more values.
* Text and vals can be null. If not, text should have
* as many (single) #'s as there are expressions. The
* values of the Value objects are substituted for the
* #'s in the display.
*
* @param text The text to display. If this is null, it is set to "#".
* @param vals The Value object(s) whose values are substituted for #'s in the text. If this is null,
* the values shoud be set later by calling the setValues() method.
*/
public DisplayLabel(String text, Value[] vals) {
this.text = (text == null)? "#" : text;
setValues(vals);
}
 
/**
* The compute method recalculates the displayed Values
* and changes the text of the label to show the new values.
* This is usually called by a Controller.
*/
public void compute() {
super.setText(getSubstitutedText());
}
 
/**
* Get the array of Value objects whose values are displayed
* in this DisplayLabel.
*/
public Value[] getValues() {
return values;
}
/**
* A convenience method that can be used when the display string contains
* just a single #. This sets the Value object whose value is substituted
* for that #.
*/
public void setValue(Value val) {
if (val == null)
values = null;
else
values = new Value[] { val };
super.setText(getSubstitutedText());
}
 
/**
* Set the array of Value objects whose values are displayed
* in this DisplayLabel, and change the display to show
* the new values. (The contents of the array, vals, are
* copied into a newly created array.)
*/
public void setValues(Value[] vals) {
if (vals == null)
values = null;
else {
values = new Value[vals.length];
System.arraycopy(vals,0,values,0,vals.length);
}
super.setText(getSubstitutedText());
}
 
/**
* Set the desired maximum number of characters in displayed numbers.
* Actual size might be larger. Value is clamped to the range
* 2 to 25.
*/
public void setNumSize(int size) {
numSize = Math.min(Math.max(size,2),25);
}
/**
* Return the desired maximum number of characters in displayed numbers.
*/
public int getNumSize() {
return numSize;
}
 
/**
* Return the basic text, including the #'s where Values
* are inserted in the displayed text. Note that the
* getText() method from the Label class will return the actual
* displayed text, including the substitited values.
*/
public String getBaseText() {
return text;
}
 
/**
* Compute the string that is obtained by substituting values for #'s in text.
* Will NOT throw any errors. (Any errors that occur when the
* Value objects are evaluated are caught and translated
* into "undefined" values.)
*/
private String getSubstitutedText() {
StringBuffer b = new StringBuffer();
int valCt = 0;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == '#') {
if (i != text.length() - 1 && text.charAt(i+1) == '#') {
b.append('#');
i++;
}
else if (values == null || valCt >= values.length)
b.append("undefined");
else {
try {
b.append(NumUtils.realToString(values[valCt].getVal(),numSize));
}
catch (JCMError e) {
b.append("undefined");
}
valCt++;
}
}
else
b.append(text.charAt(i));
}
return b.toString();
}
 
/**
* Set text for display -- text should include as many (single) #'s
* as there are values to display.
*/
public void setText(String text) {
this.text = text;
super.setText(getSubstitutedText());
}
 
/**
* Return the preferred size of this DisplayLabel.
* Allow space for up to numSize (or 8, whichever is larger) characters for
* each (single) # in the text. This is not meant to be called directly.
*/
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
int ct = 0; // Number of (single) #'1 in the text.
if (text == null || text.length() == 0)
ct = 1;
else {
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if (ch == '#')
if (i < text.length() - 1 && text.charAt(i+1) == '#')
i++;
else
ct++;
}
}
FontMetrics fm = getFontMetrics(getFont());
int perChar = fm.charWidth('0');
int w = 10 + (int)(perChar * Math.max(8,numSize) * ct + fm.stringWidth(text)); // allowing extra space for numbers
return new Dimension(w,size.height);
}
} // end class DisplayLabel
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/Tieable.java
0,0 → 1,60
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
/**
* A Tieable object has an associated serial number. The value of the serial
* should increase when the value of the object changes. A Tieable can "sync" with another
* Tieable, presumably by copying its serial number and other information.
* A given Tieable might only be able to synchronize with other Tiebles of
* certain types. If its sync() method is called with an object of the wrong
* type, it should probably thrown an IllegalArguemntException.
*
* See the "Tie" and "Controller" classes for information about how Tieable
* are used.
*
*/
public interface Tieable extends java.io.Serializable {
 
/**
* Get the serial number associated with this Tieable. If the
* value of this Tieable changes, then the serial number should
* increase.
*/
public long getSerialNumber();
 
/**
* This routine is called to tell this Tieable that the serial
* numbers of the Tieables that have been added to the Tie do not
* match. newest has a serial number that is at least as
* large as the serial number of any other Tieable in the Tie.
* This Tieable should synchronize its value and serial number
* with the "newest" Tieables.
* (Note: So far, I haven't found any reason to use
* the Tie parameter in this method! Maybe it should be removed.)
*/
public void sync(Tie tie, Tieable newest);
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/VariableInput.java
0,0 → 1,638
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import edu.hws.jcm.data.*;
import java.awt.*;
import java.awt.event.*;
 
/**
* A VariableInput is an input box into which the user can type a real
* number value, which becomes the value of an associated Variable.
* The value of the Variable can change only when the VariableInput's
* checkInput() method is called (usually by a Controller). See the Controller
* class for more information.
*
* <p>Whenever checkInput is called, an error of type JCMError
* might be generated. If throwErrors is true, this error is
* thrown; if it is false, the error is caught, the value
* of the variable is set to Double.NaN, and no error is thrown.
* The error message associated with the error can be retrieved by
* calling getErrorMessage(), if desired. (This value is null if
* no error occurred the last time checkInput was called.)
*
* <p>A VariableInput is a Value, so it can be used directly where
* a Value object is needed.
*
* <p>An VariableInput will ordinarily be registered with
* a Controller in TWO ways: It's added to a Controller
* with the Controller's add() method. This makes the Controller
* call the VariableInput's checkInput() method during the
* Controller's compute() method. Secondly, a Controller
* is set as the "onUserAction" property. This causes the
* Controller's compute() method to be called when the user
* presses return in the VariableInput box. This is optional--
* you might, for example, only want the Controller to compute()
* when a Compute button is pressed. You can also set the
* VariableInput's onTextChange property to a Controller
* that you want to compute every time the text in the box
* changes.
*
* <p>After the VariableInput is created, it is possible to specify the
* largest and smallest allowed values for the variable. It is also
* possible to specify what sytle of input is allowed. The style
* can be to allow any constant expression, constant real numbers only,
* or integers only. Set these parameters with setMin(), setMax(),
* and setInputStyle(). For setInputStyle(), the legal parameter
* values are VariableInput.EXPRESSION, VariableInput.REAL, and
* VariableInput.INTEGER. The default input style is EXPRESSION.
*
*/
public class VariableInput extends TextField implements InputObject, Tieable, Value {
 
/**
* The Variable that represents
* the value of this input box. (VI is
* a private nested class inside VariableInput.)
*/
protected VI variable;
 
/**
* True if an error should be thrown
* when checkInput() is calles and
* the contents do not define a
* legal number. True by default.
*/
protected boolean throwErrors;
 
/**
* Error message from the most recent
* time checkInput() as called.
* Null if there was no error.
*/
protected String errorMessage;
 
/**
* This serial number is increased
* each time the value of the variable
* changes.
*/
protected long serialNumber;
 
/**
* This is set to true if the text in the
* box has been changed since the last time
* the value of the variable was checked by checkInput().
*/
protected boolean hasChanged;
private Controller onUserAction; // If this is non-null, the compute() method
// of onUserAction is called when the user
// presses return in this input-box.
private Controller onTextChange; // If this is non-null, the compute() method
// of onTextChange is called when the text
// in this input box changes
/**
* Smallest allowable value.
*/
protected double minValue = -Double.MAX_VALUE;
 
/**
* Largest allowable value.
*/
protected double maxValue = Double.MAX_VALUE;
 
/**
* One of the constant values EXPRESSION, REAL, or
* INTEGER, specifying the style of input.
*/
protected int inputStyle = 0;
/**
* A constant for use in the setInputStyle() method. Any constant expression is allowed.
*/
public static final int EXPRESSION = 0;
 
/**
* A constant for use in the setInputStyle() method. Only real numbers are allowed.
*/
public static final int REAL = 1;
 
/**
* A constant for use in the setInputStyle() method. Only integers are allowed.
*/
public static final int INTEGER = 2;
 
/**
* Create an unnamed VariableInput with initial contents "0".
*/
public VariableInput() {
this(null,null);
}
 
/**
* Construct a VariableInput with the given name
* and initial String (which can both be null).
* If initialString is null, the string "0" is used.
* No error occurs in the constructor if the initialString
* does not represent a legal value (A string rather than a
* double is used for initialization since the initial
* content can be an expression such as "pi/2".)
* If name is not null, it is used as the name of
* the VariableInput component as well as the name
* of the associated variable.
*/
public VariableInput(String name, String initialString) {
super((initialString == null)? "0" : initialString, 12);
setBackground(Color.white);
variable = new VI(name);
if (name != null)
super.setName(name);
hasChanged = true;
variable.checkInput(); // Won't throw an error, since throwErrors is false.
enableEvents(AWTEvent.KEY_EVENT_MASK);
throwErrors = true;
}
 
/**
* Create a VariableInput just as in the constructor
* VariableInput(String,String). Then, if both parser and
* name are non-null, register the associated variable
* with the parser.
*/
public VariableInput(String name, String initialString, Parser parser) {
this(name, initialString);
addTo(parser);
}
 
/**
* Get the associated variable for the VariableInput box. You will need
* this, for example, if you want to register the variable with a Parser.
*/
public Variable getVariable() {
return variable;
}
/**
* Convenience method for creating a component containing
* this VariableInput together with a label of the form
* "<name> = ". This version uses default colors for the
* label, which are inherited from the containing
* component.
*/
public JCMPanel withLabel() {
return withLabel(null,null);
}
 
/**
* Convenience method for creating a component containing
* this VariableInput together with a label of the form
* "name = ". Uses the given background and foreground
* colors for the label and the panel. The colors can be
* null to use the defaults, which will be inherited from the
* containing Component.
*/
public JCMPanel withLabel(Color back, Color fore) {
Label label = new Label(" " + variable.getName() + " =");
JCMPanel panel = new JCMPanel();
if (back != null) {
panel.setBackground(back);
label.setBackground(back);
}
if (fore != null) {
panel.setForeground(fore);
label.setBackground(fore);
}
panel.add(label, BorderLayout.WEST);
panel.add(this, BorderLayout.CENTER);
return panel;
}
/**
* Set the name of the variable. This should not be called
* while the variable is registered with a Parser.
* The name of the VariableInput Component is also set to name,
* if the name is non=null.
*/
public void setName(String name) {
variable.setName(name);
if (name != null)
super.setName(name);
}
/**
* A convenience method that registers this VariableInput's variable
* with Parser p (but only if both p and the name of the variable are non-null).
*/
public void addTo(Parser p) {
if (p != null && variable.getName() != null)
p.add(variable);
}
/**
* If the Controller, c, is non-null, then its compute() method will be called whenever
* the user presses the return key while typing in this text-input box.
*/
public void setOnUserAction(Controller c) {
onUserAction = c;
enableEvents(AWTEvent.ACTION_EVENT_MASK);
}
/**
* Return the Controller, if any, that is notified when the user
* presses return in this text-input box.
*/
public Controller getOnUserAction() {
return onUserAction;
}
/**
* Method required by InputObject interface; in this class, it simply calls
* setOnUserAction(c). This is meant to be called by JCMPanel.gatherInputs().
*/
public void notifyControllerOnChange(Controller c) {
setOnUserAction(c);
}
 
/**
* If the Controller, cm is non-null, then its compute() method will be called whenever
* the text in this input box changes. Furthermore, the throwErrors
* property will be set to false, to avoid throwing multiple errors
* while the user is typing. (You can change it back to true if
* you want by calling setThrowErrors(true).)
*/
public void setOnTextChange(Controller c) {
onTextChange = c;
enableEvents(AWTEvent.TEXT_EVENT_MASK);
if (c != null)
throwErrors = false;
}
/**
* Return the Controller, if any, that is notified when the text
* in this input box changes
*/
public Controller getOnTextChange() {
return onTextChange;
}
 
/**
* Return the value of the associated variable, which might not
* reflect the value of the contents of the input box. The value
* of the variable changes only when the checkInput() method is called,
* or when the setVal() method is called.
* Call checkInput() first, if you want to be sure of getting the
* same value that is currently shown in the box.
*/
public double getVal() {
return variable.getVal();
}
/**
* Set the value of the associated variable.
* Also sets the content of the input box.
*/
public void setVal(double d) {
variable.setVal(d);
}
/**
* Set the throwErrors property. If the value is true, then
* an error will be thrown by the checkInput() method when the
* contents of the VariableInput box are not legal. Otherwise,
* no error is thrown; the value of the variable is just set
* to Double.NaN.
*/
public void setThrowErrors(boolean throwErrors) {
this.throwErrors = throwErrors;
}
 
/**
* Return the value of the throwErrors property.
*/
public boolean getThrowErrors() {
return throwErrors;
}
 
/**
* Specify the smallest allowed value for the content of this VariableInput box.
*/
public void setMin(double min) {
if (!Double.isNaN(min)) {
minValue = min;
hasChanged = true; // (force recheck of contents)
}
}
 
/**
* Return the minimum value that will be accepted in this VariableInput box.
*/
public double getMin() {
return minValue;
}
 
/**
* Specify the largest allowed value for the content of this VariableInput box.
*/
public void setMax(double max) {
if (!Double.isNaN(max)) {
maxValue = max;
hasChanged = true; // (force recheck of contents)
}
}
 
/**
* Return the maximum value that will be accepted in this VariableInput box.
*/
public double getMax() {
return maxValue;
}
/**
* Specify what types of things are allowed in the input box.
* The value of the parameter, style, must be one of the constants VariableInput.EXPRESSION,
* VariableInput.REAL, or VariableInput.INTEGER. If not, the call to setInputStyle is ignored.
*/
public void setInputStyle(int style) {
if (style == EXPRESSION || style == REAL || style == INTEGER) {
if (style != inputStyle) {
hasChanged = true;
inputStyle = style;
}
}
}
 
/**
* Return the input style, which determines what types of things
* are allowed in the input box. The returned value is one
* of the contstants EXPRESSION, REAL, or INTEGER
*/
public int getInputStyle() {
return inputStyle;
}
 
/**
* Get error message from previous call to checkInput().
* Returns null if there was no error.
*/
public String getErrorMessage() {
return errorMessage;
}
//--------------------- Implementation Details -------------------------------------------
 
/**
* Check whether the contents are valid, and change the value
* of the associated variable if the new contents do not match
* the current value. This might throw an error of type JCMError,
* if throwErrors is true. This is usually called by a Controller.
*/
public void checkInput() {
variable.checkInput();
}
/**
* Return this object's serial number, which increases whenever the
* value of the associated variable changes.
*/
public long getSerialNumber() {
return serialNumber;
}
 
/**
* Synchronize serial number and value with newest, unless
* this VariableInput is itself newest. This is required by
* the Tieable interface, and is usually called by an object of type Tie.
*/
public void sync(Tie tie, Tieable newest) {
if (newest == this)
return;
if (! (newest instanceof Value) )
throw new IllegalArgumentException("Internal Error: A VariableInput can only sync with Value objects.");
variable.setVal(((Value)newest).getVal());
serialNumber = newest.getSerialNumber();
}
 
private class VI extends Variable {
// This class is used to define a Variable object associated
// with this VariableInput.
VI(String name) {
super(name);
}
public void setVal(double d) {
// If d is different from the current value of the variable,
// set the value of the variable to d, set the displayed text,
// and increment the serial number of the variable.
double oldVal = this.getVal();
if ( !hasChanged && ((Double.isNaN(d) && Double.isNaN(oldVal)) || (d == oldVal)) )
return; // Value is not actually changing.
serialNumber++;
justSetText(NumUtils.realToString(d));
hasChanged = false;
errorMessage = null;
super.setVal(d);
}
void checkInput() {
// If the contents of the input box have changed, change
// the value of the variable to match. If this is an actual
// change in the value of the variable, then the serialNumber
// is incremented.
if (!hasChanged)
return;
errorMessage = null;
String content = getText();
try {
double d = convertInput(content);
double oldVal = this.getVal();
if ( (Double.isNaN(d) && Double.isNaN(oldVal)) || (d == oldVal) )
return; // Value is not actually changing.
serialNumber++;
super.setVal(d);
}
catch (JCMError e) {
if (!Double.isNaN(this.getVal()))
serialNumber++;
super.setVal(Double.NaN); // Value becomes undefined.
if (throwErrors)
throw e;
}
}
}
private transient Parser constantParser; // To be used to process constant expressions;
// will not know about any variables or user functions.
 
/**
* Convert a string into a real value. The parameter is taken from the input box when
* this method is called by VI.checkInput()
* Throw a JCMError if any error is found in the input.
*
* @param num String to be converted
* @return the real value.
*/
protected double convertInput(String num) {
double ans = Double.NaN; // The value.
if (inputStyle == EXPRESSION) {
if (constantParser == null)
constantParser = new Parser();
try {
Expression exp = constantParser.parse(num);
ans = exp.getVal();
}
catch (ParseError e) {
errorMessage = "Illegal constant expression: " + e.getMessage();
if (throwErrors) {
setCaretPosition(e.context.pos);
requestFocus();
}
}
}
else if (inputStyle == REAL) {
try {
Double d = new Double(num);
ans = d.doubleValue();
}
catch (NumberFormatException e) {
errorMessage = "Value is not a legal real number.";
if (throwErrors) {
requestFocus();
}
}
}
else { // inputStyle is INTEGER
try {
ans = Long.parseLong(num);
}
catch (NumberFormatException e) {
errorMessage = "Value is not a legal integer.";
if (throwErrors) {
requestFocus();
}
}
}
if (errorMessage == null) {
if (ans < minValue || ans > maxValue) {
errorMessage = "Value outside legal range. It should be ";
if (inputStyle == INTEGER)
errorMessage += "an integer ";
else if (inputStyle == REAL)
errorMessage += "a real number ";
if (minValue > -Double.MAX_VALUE && maxValue < Double.MAX_VALUE)
errorMessage += "between " + NumUtils.realToString(minValue) + " and " + NumUtils.realToString(maxValue);
else if (minValue > -Double.MAX_VALUE)
errorMessage += "greater than or equal to " + NumUtils.realToString(minValue);
else
errorMessage += "less than or equal to " + NumUtils.realToString(maxValue);
if (throwErrors) {
requestFocus();
}
}
}
if (errorMessage != null)
throw new JCMError(errorMessage,this);
return ans;
}
/**
* Override processKeyEvent to only allow characters
* that are legal in this VariableInput.
*
* @param evt used internally.
*/
public void processKeyEvent(KeyEvent evt) {
if (evt.getID() == KeyEvent.KEY_PRESSED) {
int ch = evt.getKeyCode();
char chr = evt.getKeyChar();
boolean use = (chr != 0 && Character.isDigit(chr)
|| chr == '-' || chr == '+')
|| ch == KeyEvent.VK_DELETE
|| ch == KeyEvent.VK_BACK_SPACE;
if (inputStyle != INTEGER)
use = use || chr == '.' || chr == 'e' || chr == 'E';
if (inputStyle == EXPRESSION)
use = use || Character.isLetter(chr)
|| chr == '(' || chr == ')' || chr == '*'
|| chr == '/' || chr == '^'
|| chr == ':' || chr == '?' || chr == '|'
|| chr == '&' || chr == '~' || chr == '='
|| chr == '<' || chr == '>' || chr == '!'
|| ch == KeyEvent.VK_SPACE;
boolean useControl = use || ch == KeyEvent.VK_TAB
|| ch ==KeyEvent.VK_ENTER || chr == 0;
if (!useControl) {
evt.consume();
Toolkit.getDefaultToolkit().beep();
}
else if (use) {
hasChanged = true;
}
}
super.processKeyEvent(evt);
}
/**
* This overrides the setText() method from the TextField class so that
* it will also force the contents to be checked the next time
* the checkInput() method is called.
*
* @param text change text to this.
*/
public void setText(String text) {
super.setText(text);
hasChanged = true;
}
private void justSetText(String text) {
// Call super.setText().
super.setText(text);
}
/**
* Overridden to call onUserAction.compute() if onUserAction is non-null.
* This is not meant to be called directly.
*/
public void processActionEvent(ActionEvent evt) {
if (onUserAction != null)
onUserAction.compute();
super.processActionEvent(evt);
}
/**
* Overridden to call onUserAction.compute() if onUserAction is non-null.
* This is not meant to be called directly.
*/
public void processTextEvent(TextEvent evt) {
hasChanged = true;
if (onTextChange != null)
onTextChange.compute();
super.processTextEvent(evt);
}
 
} // end class VariableInput
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/ComputeButton.java
0,0 → 1,83
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
import java.awt.*;
import java.awt.event.*;
 
/**
* A compute button is a button that can have an associated Controller.
* When the user clicks the button, the compute() method of the
* Controller is called. This class really just exists for convenience.
*/
public class ComputeButton extends Button {
 
private Controller onUserAction; // The Controller whose compute()
// method is called when the user clicks
// the button.
 
/**
* Create a Compute button labeled "Compute!".
*/
public ComputeButton() {
this("Compute!");
}
/**
* Create a Compute button displaying the given text.
*/
public ComputeButton(String label) {
super(label);
setBackground(Color.lightGray);
enableEvents(AWTEvent.ACTION_EVENT_MASK);
}
/**
* Set the controller whose compute() method is called
* when the user clicks this button.
*/
public void setOnUserAction(Controller c) {
onUserAction = c;
}
 
/**
* Return the controlller whose compute() method is
* called when the user clicks this button.
*/
public Controller getOnUserAction() {
return onUserAction;
}
/**
* This is called by the system when the user clicks the
* button. Not meant to be called directly.
*/
public void processActionEvent(ActionEvent evt) {
if (onUserAction != null)
onUserAction.compute();
super.processActionEvent(evt);
}
 
} // end class ComputeButton
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/MessagePopup.java
0,0 → 1,250
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
 
/**
* The class MessagePopup represents a Window that pops up to display an error
* message. A MessagePopup object is created by a "source" component. If
* that component is contained in a Frame, then the popup will be a modal dialog
* box with that Parent. If the component is not in a Frame (or is null), then an
* independent Frame is used. The message box is popped up when reportError() is
* called. It is closed either when the user clicks the OK button,
* or if clearErrorMessage() is called.
*/
public class MessagePopup implements ActionListener, ErrorReporter {
private String errorMessage;
private Controller errorSource;
private Component source;
private Window popup;
 
/**
* Create a MessagePopup with the give source component. If source is null, then
* an independent window will always be used to show the error message.
*/
public MessagePopup(Component source) {
this.source = source;
}
 
/**
* Show the given message in a dialog box or independent window,
* depending on whether the source component is contained in
* a Frame or not.
*
* @param c The Controller that calls this method, or null if it is not called by a Controller.
* (The Controller, if any, will be notified when the error message is cleared.)
* @param message The message to display.
*/
public void setErrorMessage(Controller c, String message) {
if (popup != null)
clearErrorMessage();
if (message == null)
return;
errorSource = c;
errorMessage = message;
Component parent = source;
while (parent != null && !(parent instanceof Frame))
parent = parent.getParent();
if (parent != null)
popup = new Dialog((Frame)parent,"Error Message",true); // modal dialog
else
popup = new Frame("Error Message"); // independent window
popup.setBackground(Color.white);
popup.add(new MC(message), BorderLayout.CENTER);
Panel buttonBar = new Panel();
buttonBar.setLayout(new FlowLayout(FlowLayout.RIGHT,10,10));
Button OK = new Button(" OK ");
OK.addActionListener(this);
buttonBar.add(OK);
popup.add(buttonBar, BorderLayout.SOUTH);
popup.pack();
if (parent == null)
popup.setLocation(100,80);
else
popup.setLocation(parent.getLocation().x+50,parent.getLocation().y+30);
popup.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
popup.dispose();
}
});
popup.show(); // make the dialog visible.
}
 
/**
* Get the currently displayed error message. The return value is null if no error message is being displayed.
*/
public String getErrorMessage() {
return errorMessage;
}
 
/**
* Clear the error message and close the window. This can be
* called from outside this class. It is called automatically
* when the user clicks the OK button or close box of the window
* that displays the error message.
*/
synchronized public void clearErrorMessage() {
if (popup == null)
return;
popup.dispose();
errorMessage = null;
if (errorSource != null)
errorSource.errorCleared();
errorSource = null;
popup = null;
}
 
/**
* Respond when user clicks OK. This is not meant to be called directly.
*/
public void actionPerformed(ActionEvent evt) {
clearErrorMessage();
}
 
/**
* The nested class MC (Message Canvas) displays the message passed
* to it in the constructor. Unless the message is very short,
* it will be broken into multiple lines.
*/
private static class MC extends Canvas {
private String message; // A copy of the message
// The following data is computed in makeStringList()
private Vector messageStrings; // The message broken up into lines.
private int messageWidth; // The width in pixels of the message display.
private int messageHeight; // The height in pixels of the message display.
private Font font; // The font that will be used to display the message.
private int lineHeight; // The height of one line in that font.
private int fontAscent; // The font ascent of the font (disance from the
// baseline to the top of a tall character.)
/**
* Constructor: store the message.
*
* @param message message to store.
*/
MC(String message) {
if (message == null)
this.message = ""; // this.message can't be null.
else
this.message = message;
}
 
/**
* Return the message size, as determined by makeStringList(), allowing
* space for a border around the message.
*
* @return the message size.
*/
public Dimension getPreferredSize() {
if (messageStrings == null)
makeStringList();
return new Dimension(messageWidth + 20, messageHeight + 20);
}
/**
* Display the message using data stored in instance variables.
*
* @param g the Graphics context.
*/
public void paint(Graphics g) {
if (messageStrings == null)
makeStringList();
int y = (getSize().height - messageHeight)/2 + fontAscent;
if (y < fontAscent)
y = fontAscent;
int x = (getSize().width - messageWidth)/2;
if (x < 0)
x = 0;
g.setFont(font);
for (int i = 0; i < messageStrings.size(); i++) {
g.drawString( (String)messageStrings.elementAt(i), x, y);
y += lineHeight;
}
}
/**
* Compute all the instance variables necessary for displaying
* the message. If the total width of the message in pixels
* would be more than 280, break it up into several lines.
*/
private void makeStringList() {
messageStrings = new Vector();
font = new Font("Dialog", Font.PLAIN, 12);
FontMetrics fm = getFontMetrics(font);
lineHeight = fm.getHeight() + 3;
fontAscent = fm.getAscent();
int totalWidth = fm.stringWidth(message);
if (totalWidth <= 280) {
messageStrings.addElement(message);
messageWidth = 280;
messageHeight = lineHeight;
}
else {
if (totalWidth > 1800)
messageWidth = Math.min(500, totalWidth/6);
else
messageWidth = 300;
int actualWidth = 0;
String line = " ";
String word = "";
message += " "; // this forces word == "" after the following for loop ends.
for (int i = 0; i < message.length(); i++) {
if (message.charAt(i) == ' ') {
if (fm.stringWidth(line + word) > messageWidth + 8) {
messageStrings.addElement(line);
actualWidth = Math.max(actualWidth,fm.stringWidth(line));
line = "";
}
line += word;
if (line.length() > 0)
line += ' ';
word = "";
}
else {
word += message.charAt(i);
}
}
if (line.length() > 0) {
messageStrings.addElement(line);
actualWidth = Math.max(actualWidth, fm.stringWidth(line));
}
messageHeight = lineHeight*messageStrings.size() - fm.getLeading();
messageWidth = Math.max(280,actualWidth);
}
}
} // end nested class MC
} // end class MessageDialog
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/Animator.java
0,0 → 1,940
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import edu.hws.jcm.data.*;
import java.awt.*;
import java.awt.event.*;
 
/**
* An Animator can change a value continuously, without user intervention, by running
* a separate Thread. By default, an animator appears as a "Start" button. When the
* button is pressed, the value of the animator starts counting 0, 1, 2, ... The button
* changes to a "Stop" button. When this is pressed, the value stops changing. A Controller
* can be set, by calling the setOnChange() method, to be notified whenever the value is
* changed. If this is done, then the value of the Animator will only change when its
* checkInput() method is called, so it should be added to a Controller which will call
* this method.
*
* <p>The getValueAsVariable() method can be called to get a Variable whose value is
* the value of the Animator. This variable can then be added to a Parser, so it can
* be used in expressions. An Animator is "Tieable", so it can share its value
* with another InputObject, such as a VariableSlider or a VariableIput.
*
* <p>There are many options: If maximum and minimum values are both specified, then the value
* of the Animator ranges between these values. By default, this interval is divided into
* 100 sub-intervals, so that there are 101 frames. However, the number of intervals can
* also be set. If no min or max is specified but a number of intervals is specified,
* then the value is an integer which ranges from 0 up to the specified number of intervals.
* If the number of frames is finite, then there are three possibities when the last
* frame is reached: The animation can stop; it can loop back to the the starting
* frame, or it can reverse direction and cycle back and forth. The behavior is controlled
* with the setLoopStyle() method.
*
* <p>An Animator is actually a Panel which can contain other controls in addition to or
* instead of the Start/Stop button. For example, it can contain a "Next" button or
* a pop-up menu to control the speed.
*
*/
public class Animator extends Panel
implements Value, Tieable, InputObject, ActionListener, ItemListener, Runnable {
 
/**
* Used to add a component to the Animator Panel; can be used in a constructor
* or in the addControl() method. Can also be used in the getControl() method
* to specify which component is to be retrieved.
*/
public static final int START_STOP_BUTTON = 1,
START_BUTTON = 2,
PAUSE_BUTTON = 4,
STOP_BUTTON = 8,
NEXT_BUTTON = 16,
PREV_BUTTON = 32,
SPEED_CHOICE = 64,
LOOP_CHOICE = 128;
/**
* Indicates that the components in the Animator panel are to be stacked vertically.
* (Can be used in a constructor and in the setOrientation method.)
*/
public static final int VERTICAL = 1;
 
/**
* Indicates that the components in the Animator panel are to be in a horizontal row.
* (Can be used in a constructor and in the setOrientation method.)
*/
public static final int HORIZONTAL = 0;
/**
* Represents a loop style in which the animation is played once. When the final frame
* is reached, the animation ends. Use in the setLoopStyle() method.
*/
public static final int ONCE = 0;
 
/**
* Represents a loop style in which the animation is played repeatedly. When the final frame
* is reached, the animation returns to the first frame. Use in the setLoopStyle() method.
*/
public static final int LOOP = 1;
 
/**
* Represents a loop style in which the animation is cycled back and forth. When the final frame
* is reached, the animation reverses direction. Use in the setLoopStyle() method.
*/
public static final int BACK_AND_FORTH = 2;
private Button startStopButton, startButton, stopButton,
pauseButton, nextButton, prevButton;
private Choice speedChoice, loopChoice;
private int orientation;
private String startButtonName = "Start";
private String stopButtonName = "Stop";
private volatile int loopStyle;
private boolean runningBackwards;
private volatile int millisPerFrame = 100;
private volatile int frame;
private int maxFrame;
private double value;
private volatile long serialNumber = 1;
private Computable onChange;
private Value min, max; // If both are non-null, give the max and min values of the animator.
private Value intervals; // If non-null, gives the number of sub-intervals. Number of frames is this value plus one.
private boolean needsValueCheck = true;
private double min_val, max_val; // Values of min and max.
private int intervals_val; // Value of intervals.
private static int START = 0, PAUSE = 1, NEXT = 2, PREV = 3, STOP = 4, RUN = 5; // possible values of thread status
private Thread runner;
private volatile int status = STOP;
private boolean undefinedWhenNotRunning;
/**
* Create a default Animator. If no changes are made by calling other methods, it will appear as
* a Start/Stop button. When Start is pressed, the value will count 0, 1, 2, 3, ..., until the Stop
* button is pressed. Restarting the animation starts the value again at zero.
*/
public Animator() {
this(START_STOP_BUTTON,HORIZONTAL);
}
/**
* Create an Animator containing the specified control. The parameter can consist of one or
* more of the following constants, or'ed together: START_STOP_BUTTON, START_BUTTON, STOP_BUTTON,
* PAUSE_BUTTON, NEXT_BUTTON, PREV_BUTTON, SPEED_CHOICE, LOOP_CHOICE. If no changes are made
* by calling other methods, the value of the Animator will be 0, 1, 2, 3, .... The components
* are arranged into one horizontal row, using a GridLayout.
*/
public Animator(int controls) {
this(controls,HORIZONTAL,null,null,null);
}
/**
* Create an Animator containing specified controls. (See the one-parameter constructor.)
* The second parameter should be one of the constants HORIZONTAL or VERTICAL, to specify
* how the components are arranged in the Animator panel.
*/
public Animator(int controls, int orientation) {
this(controls,orientation,null,null,null);
}
/** Create an Animator with specified controls, orienation, range limits and number of intervals
*
* @param controls Specify the controls to add to the Animator. Can consist of one or
* more of the following constants, or'ed together: START_STOP_BUTTON, START_BUTTON, STOP_BUTTON,
* PAUSE_BUTTON, NEXT_BUTTON, PREV_BUTTON, SPEED_CHOICE, LOOP_CHOICE.
* @param orientation How the controls are arranged in the panel. One of the constants VERTICAL or HORIZONTAL.
* @param min If BOTH min and max are non-null, they specify the range of values of the Animator.
* @param max If BOTH min and max are non-null, they specify the range of values of the Animator.
* @param intervals If non-null, specifies the number of intervals into which the range of values
* is divided. Note that the value will be rounded to the nearest integer and clamped to the
* range 0 to 100000. The number of frames is the number of intervals, plus one. If min and max are
* non-null and intervals is null, then a default value of 100 is used. If either min or max is
* null and intervals is non-null, then the Animator takes on the values 0, 1, 2, ..., intervals.
*/
public Animator(int controls, int orientation, Value min, Value max, Value intervals) {
this.min = min;
this.max = max;
this.intervals = intervals;
this.orientation = orientation;
if (orientation == VERTICAL)
setLayout(new GridLayout(0,1));
else
setLayout(new GridLayout(1,0));
for (int i = 1; i <= LOOP_CHOICE; i <<= 1)
if ( (i & controls) != 0 )
addControl(i);
}
//-------------- Accessor methods for public properties ------------------
/**
* Get one of controls associated with the Animator. Usually, these are displayed
* in the Animator panel, but you could get a control and add it to another panel if you
* want. Even if you do this, the control will still be managed by the Animator (which
* will respond to it and enable/disable it, for example). You might also want to get
* one of the Animator's buttons so that you can change its label. The value
* of the parameter should be one of the constants START_STOP_BUTTON, START_BUTTON, STOP_BUTTON,
* PAUSE_BUTTON, NEXT_BUTTON, PREV_BUTTON, SPEED_CHOICE, LOOP_CHOICE. If the parameter is
* not one of these values, then null is returned.
*/
public Component getControl(int controlCode) {
switch (controlCode) {
case START_STOP_BUTTON:
if (startStopButton == null) {
startStopButton = new Button(startButtonName);
startStopButton.setBackground(Color.lightGray);
startStopButton.addActionListener(this);
}
return startStopButton;
case START_BUTTON:
if (startButton == null) {
startButton = new Button(startButtonName);
startButton.setBackground(Color.lightGray);
startButton.addActionListener(this);
}
return startButton;
case STOP_BUTTON:
if (stopButton == null) {
stopButton = new Button(stopButtonName);
stopButton.setBackground(Color.lightGray);
stopButton.addActionListener(this);
stopButton.setEnabled(false);
}
return stopButton;
case PAUSE_BUTTON:
if (pauseButton == null) {
pauseButton = new Button("Pause");
pauseButton.setBackground(Color.lightGray);
pauseButton.addActionListener(this);
pauseButton.setEnabled(false);
}
return pauseButton;
case NEXT_BUTTON:
if (nextButton == null) {
nextButton = new Button("Next");
nextButton.setBackground(Color.lightGray);
nextButton.addActionListener(this);
}
return nextButton;
case PREV_BUTTON:
if (prevButton == null) {
prevButton = new Button("Prev");
prevButton.setBackground(Color.lightGray);
prevButton.addActionListener(this);
}
return prevButton;
case SPEED_CHOICE:
if (speedChoice == null) {
speedChoice = new Choice();
speedChoice.add("Fastest");
speedChoice.add("Fast");
speedChoice.add("Moderate");
speedChoice.add("Slow");
speedChoice.add("Slower");
speedChoice.select(2);
speedChoice.addItemListener(this);
}
return speedChoice;
case LOOP_CHOICE:
if (loopChoice == null) {
loopChoice = new Choice();
loopChoice.add("Play Once");
loopChoice.add("Loop");
loopChoice.add("Back and Forth");
loopChoice.addItemListener(this);
}
return loopChoice;
default:
return null;
}
}
/**
* Add one of the possible control buttons or pop-up menus to the Animator. The possible values
* of the parameter and their meanings are as follows:
* <p>START_STOP_BUTTON: When clicked, animation starts and name of button changes; when clicked again, animation stops.
* <p>START_BUTTON: When clicked, animation starts.
* <p>STOP_BUTTON: When clicked, animaton stops.
* <p>PAUSE_BUTTON: When clicked, animation is paused; this is different from stopping the animation since
* a paused animation can be resumed from the same point while a stopped animation can only be restarted
* from the beginning.
* <p>NEXT_BUTTON: When clicked, the animation advances one frame; this is disabled when the animation is running.
* <p>PREV_BUTTON: When clicked, the animation is moved back one frame; this is disabled when the animation is running.
* <p>SPEED_CHOICE: A pop-up menu whose value controls the speed at which the animation plays.
* <P>LOOP_CHOICE: A pop-up menu that controls the style of animation, that is, what happens when the
* animation reaches its final frame; values are Play Once, Loop, and Back and Forth.
* <p>If the parameter is not one of these constants, then nothing is done. Ordinarily, this
* will be called during initialization. (If you call it at some other time, you will have
* to validate the panel yourself.) The return value is the component that is added, or null
* if the parameter value is not legal.
*/
public Component addControl(int controlCode) {
Component c = getControl(controlCode);
if (c == null)
return null;
else {
add(c);
return c;
}
}
/**
* The name of the Start/Stop button is managed by the Animator, so changing it directly makes
* no sense. This method can be used to specify the label displayed by the Start/Stop button
* when the animation is NOT running. This name is also used for the Start button. This method
* should ordinarily be called during initialization. In any case, it should not be called while
* an animation is running, since it changes the name of the Start/Stop button to the specified value.
*/
public void setStartButtonName(String name) {
if (name != null) {
startButtonName = name;
if (startStopButton != null)
startStopButton.setLabel(name);
if (startButton != null)
startButton.setLabel(name);
}
}
/**
* The name of the Start/Stop button is managed by the Animator, so changing it directly makes
* no sense. This method can be used to specify the label displayed by the Start/Stop button
* when the animation IS running. This name is also used for the Stop button. This method
* should ordinarily be called during initialization. In any case, it should not be called while
* an animation is running, since it does not change the name of the Start/Stop button.
*/
public void setStopButtonName(String name) {
if (name != null) {
stopButtonName = name;
if (stopButton != null)
stopButton.setLabel(name);
}
}
/**
* Get the constant, VERTICAL or HORIZONTAL, that was used to specify whether the components
* in the animator are arranged veritcally or horizontally.
*/
public int getOrientation() {
return orientation;
}
 
/**
* Set the orientation of the components in the Animator panel. The parameter should be one
* of the constants HORIZONTAL or VERTICAL. This just sets the layout for the panel to
* be a GridLayout with one row or one column and validates the panel. You could also
* set the layout to be something else, such as a FlowLayout, using the setLayout() method.
*/
public void setOrientation(int orientation) {
if (orientation != this.orientation && (orientation == HORIZONTAL || orientation == VERTICAL)) {
this.orientation = orientation;
if (orientation == VERTICAL)
setLayout(new GridLayout(0,1));
else
setLayout(new GridLayout(1,0));
validate();
}
}
/**
* Get the Value object that specifies the final value of the Animator. This object can be null.
*/
public Value getMax() {
return max;
}
/**
* Set the Value object that gives the final value of the Animator. If both min and max are
* non-null, the value of the Animator ranges from min to max as the animation procedes. (It is not required
* that max be greater than min. They should probably be calles startVal and endVal.)
*/
public void setMax(Value max) {
this.max = max;
needsValueCheck = true;
}
/**
* A convenience method that simply calls setMax(new Constant(d)).
*/
public void setMax(double d) {
setMax(new Constant(d));
}
/**
* Get the Value object that specifies the starting value of the Animator. This object can be null.
*/
public Value getMin() {
return min;
}
/**
* Set the Value object that gives the starting value of the Animator. If both min and max are
* non-null, the value ranges from min to max as the animation procedes. (It is not required
* that max be greater than min.)
*/
public void setMin(Value min) {
this.min = min;
needsValueCheck = true;
}
/**
* A convenience method that simply calls setMin(new Constant(d)).
*/
public void setMin(double d) {
setMin(new Constant(d));
}
/**
* Get the Value object that specifies the number of frames in the animation. This can be null.
*/
public Value getIntervals() {
return intervals;
}
/**
* Set the Value object that specifies the number of frames in the animation. If non-null, then
* the value is rounded to the nearest integer and clamped to the range 1 to 100000. If it is
* null and min and max are non-null, then a default value of 100 is used. If it is null and
* min or max is null, then the number of frames is unlimited and the values taken on by the
* animator are 0, 1, 2, 3, ..., that is, the value of the animator is the frame number.
* If min or max is null and intervals is non-null, then the values taken on by the
* animator are 0, 1, 2, ..., intervals. Note that the number of frames is (intervals+1).
*/
public void setIntervals(Value intervals) {
this.intervals = intervals;
needsValueCheck = true;
}
/**
* A convenience method that simply calls setIntervals(new Constant(d)).
*/
public void setIntervals(int intervals) {
setIntervals(new Constant(intervals));
}
/**
* Get the nominal number of milliseconds per frame. The actual time between frames
* can be longer because of the work that is done processing the frame or on other tasks.
*/
public int getMillisPerFrame() {
return millisPerFrame;
}
/**
* Set the nominal number of milliseconds per frame. The actual time between frames
* can be longer because of the work that is done processing the frame or on other tasks.
* Values less than 5 are effectively equivalent to 5. Realistic values are 25 or more,
* but it depends on what system the program is running on and how complicated each frame is.
*/
public void setMillisPerFrame(int millis) {
millisPerFrame = millis;
}
/**
* Get the loop style, which determines what happens when the final frame of the animation is reached.
*/
public int getLoopStyle() {
return loopStyle;
}
 
/**
* Set the loop style, which determines what happens when the final frame of the animation is reached.
* The parameter can be one of the constants: ONCE (animation stops when final frame is reached),
* LOOP (animation cycles back to the first frame and continues from there); or BACK_AND_FORTH (animation reverses direction
* and cycles back and forth).
*/
public void setLoopStyle(int style) {
if (style >= 0 && style <= 2 && style != loopStyle) {
loopStyle = style;
if (loopChoice != null)
loopChoice.select(style);
runningBackwards = false;
}
}
/**
* Set the value of the animation. Note that the value does not have to be one of
* the values that would ordinarily occur in the animation. Of course, if the animation
* is running, then the new value won't be around for long since it will change as
* soon as the next frame comes up.
*/
synchronized public void setVal(double val) {
if (needsValueCheck)
checkValue(); // make sure min,max,intervals are evaluated if necessary
value = val;
serialNumber++;
needsValueCheck = false;
// Try to make the frame number match the value as closely as possible
if (!Double.isNaN(val)) {
if (min == null || max == null)
frame = (int)Math.round(val);
else if (!Double.isNaN(min_val) && !Double.isNaN(max_val) && min_val != max_val)
frame = (int)Math.round( (val - min_val)/(max_val - min_val) * maxFrame );
if (frame < 0)
frame = 0;
else if (maxFrame > 0 && frame > maxFrame)
frame = maxFrame;
}
}
/**
* Get the current value of the Animator.
*/
public double getVal() {
if (needsValueCheck)
checkValue();
return value;
}
/**
* Get a variable whose value is always equal to the value of the animator.
* The name of the variable will be k.
*/
public Variable getValueAsVariable() {
return getValueAsVariable("k");
}
/**
* Get a variable whose value is always equal to the value of the animator.
* The name of the variable is specified by the parameter.
*/
public Variable getValueAsVariable(String name) {
return new Variable(name) {
public void setVal(double val) {
Animator.this.setVal(val);
}
public double getVal() {
return Animator.this.getVal();
}
};
}
/**
* Get the Controller that is notified (by calling its compute() method) whenever
* the frame changes. This can be null.
*/
public Computable getOnChange() {
return onChange;
}
/**
* Set the Controller that is notified (by calling its compute() method) whenever
* the frame changes. If null, no Controller is notified. NOTE: Animators are
* different from InputObjects in that when onChange is null, the value of animator
* and its associated Variable will change without checkInput() being called.
* However, if the onChange is not null, then checkInput() must be called for
* the value to change. (So the Animation to be added to the Controller by
* calling the Controller's add() method. Then, the Controller will call
* the checkInput() method.)
*/
public void setOnChange(Computable onChange) {
this.onChange = onChange;
}
/**
* Method required by the InputObject interface. It just calls setOnChange(c).
* This is meant to be called by the gatherInputs() method in JCMPanel.
*/
public void notifyControllerOnChange(Controller c) {
setOnChange(c);
}
/**
* Get the value of the undefinedWhenNotRunning property.
*/
public boolean getUndefinedWhenNotRunning() {
return undefinedWhenNotRunning;
}
/**
* Set the value of the undefinedWhenNotRunning property. If this is true,
* then the value of the Animator is Double.NaN except when the animation is
* running (or paused), (or if it has been set by a call to the setVal() method).
* The default value is false.
*/
public void setUndefinedWhenNotRunning(boolean undefinedWhenNotRunning) {
this.undefinedWhenNotRunning = undefinedWhenNotRunning;
}
//--------------- play control --------------------------------------
/**
* Start the animation from the first frame, or continue it if it was paused.
* This is called when the Start button or Start/Stop button is pressed, but
* it could also be called directly.
*/
synchronized public void start() {
if (runner != null && runner.isAlive() && status == STOP){
// A previous run is stopping. Give it a chance to stop.
try {
wait(1000);
}
catch (InterruptedException e) {
}
if (runner != null && runner.isAlive()) {
runner.stop(); // bad form, but what choice do I have?
runner = null;
}
}
if (runner == null || !runner.isAlive()) {
runner = new Thread(this);
status = START;
runner.start();
}
else if (status != RUN) {
status = START;
notify();
}
}
/**
* Pause the animation, if it is running.
* This is called when the Pause button is pressed, but
* it could also be called directly.
*/
synchronized public void pause() {
if (status == RUN) {
status = PAUSE;
notify();
}
}
/**
* Advance the animation by one frame. This will start the animation from the
* first frame if it is stopped. This has no effect unless the animation is
* stopped or paused. This is called when the Next button pressed, but
* it could also be called directly.
*/
synchronized public void next() {
if (runner == null || !runner.isAlive()) {
runner = new Thread(this);
status = NEXT;
runner.start();
}
else if (status == PAUSE) {
status = NEXT;
notify();
}
}
/**
* Advance the animation BACK one frame. This will start the animation from the
* first frame if it is stopped. This has no effect unless the animation is
* stopped or paused. This is called when the Prev button pressed, but
* it could also be called directly.
*/
synchronized public void prev() {
if (runner == null || !runner.isAlive()) {
runner = new Thread(this);
status = PREV;
runner.start();
}
else if (status == PAUSE) {
status = PREV;
notify();
}
}
/**
* Stop the animation, if it is running or paused. This is called when the Stop button
* or the StartStop button is pressed, but it could also be called directly.
* NOTE: If the Animator is in an applet, then it is a good idea to call the stop()
* method of the Animator from the applet's destroy() method.
*/
synchronized public void stop() {
status = STOP;
if (runner == null || !runner.isAlive())
return;
notify();
}
//-----------------Implementation details --------------------------
 
/**
* Respond to button clicks. This is not meant to be called directly.
*/
synchronized public void actionPerformed(ActionEvent evt) {
Object src = evt.getSource();
if (src == null)
return;
if (src == startStopButton) {
if (status == RUN)
stop();
else
start();
}
else if (src == startButton) {
start();
}
else if (src == stopButton) {
stop();
}
else if (src == nextButton) {
next();
}
else if (src == prevButton) {
prev();
}
else if (src == pauseButton) {
pause();
}
}
/**
* Respond to clicks on pop-up menus. This is not meant to be called directly.
*/
synchronized public void itemStateChanged(ItemEvent evt) {
if (evt.getSource() == loopChoice && loopChoice != null) {
setLoopStyle(loopChoice.getSelectedIndex());
}
else if (evt.getSource() == speedChoice && speedChoice != null) {
switch (speedChoice.getSelectedIndex()) {
case 0: millisPerFrame = 0; break;
case 1: millisPerFrame = 30; break;
case 2: millisPerFrame = 100; break;
case 3: millisPerFrame = 500; break;
case 4: millisPerFrame = 2000; break;
}
}
}
/**
* Part of the IputObject interface. This is meant to be called by a Controller.
*/
public void checkInput() {
needsValueCheck = true;
}
/**
* Part of the Tieable interface. This is meant to be called by other Tieable objects
* as part of object synchronization.
*/
public long getSerialNumber() {
if (needsValueCheck)
checkValue();
return serialNumber;
}
/**
* Part of the Tieable interface. This is meant to be called by Tie objects
* as part of object synchronization.
*/
public void sync(Tie tie, Tieable newest) {
if (newest != this) {
if (! (newest instanceof Value) )
throw new IllegalArgumentException("Internal Error: An Animator can only sync with Value objects.");
setVal(((Value)newest).getVal());
serialNumber = newest.getSerialNumber();
}
}
synchronized private void checkValue() { // Recompute the value, which might have changed.
double newVal;
if (min != null)
min_val = min.getVal();
if (max != null)
max_val = max.getVal();
if (intervals == null)
intervals_val = 0;
else {
double d= intervals.getVal();
if (Double.isNaN(d) || d <= 0.5)
intervals_val = 0;
else if (d > 100000)
intervals_val = 100000;
else
intervals_val = (int)Math.round(d);
}
maxFrame = intervals_val;
if (min == null || max == null) { // value is frame number
newVal = frame;
}
else if (Double.isNaN(min_val) || Double.isNaN(max_val) || Double.isInfinite(min_val) || Double.isInfinite(max_val)) {
newVal = Double.NaN;
}
else if (intervals_val > 0) {
newVal = min_val + (frame*(max_val-min_val)) / intervals_val;
}
else { // Assume 100 intervals if
maxFrame = 100;
newVal = min_val + (frame*(max_val-min_val)) / 100;
}
if (undefinedWhenNotRunning && status == STOP)
newVal = Double.NaN;
value = newVal;
needsValueCheck = false;
}
private void doControlStatus(int status) {
// Enable/disable buttons according to Thread status.
// status should be START or STOP or PAUSE
if (startStopButton != null)
startStopButton.setLabel((status == START)? stopButtonName : startButtonName);
if (startButton != null)
startButton.setEnabled(status != START);
if (stopButton != null)
stopButton.setEnabled(status != STOP);
if (nextButton != null)
nextButton.setEnabled(status != START);
if (prevButton != null)
prevButton.setEnabled(status != START);
if (pauseButton != null)
pauseButton.setEnabled(status == START);
}
private void doAdvanceFrame(int amt) {
// Move on to next or previous frame.
// amt is +1 or -1
serialNumber++;
if (loopStyle == BACK_AND_FORTH && runningBackwards)
frame -= amt;
else
frame += amt;
if (frame < 0) {
if (loopStyle == LOOP)
frame = maxFrame; // might be 0, which is OK I guess
else if (loopStyle == BACK_AND_FORTH) {
frame = 1;
if (amt == 1)
runningBackwards = false;
else
runningBackwards = true;
}
else
frame = 0;
}
else if (maxFrame > 0 && frame > maxFrame) {
if (loopStyle == LOOP)
frame = 1; // Don't use 0, because usually frames 0 and maxFrame will be the same
else if (loopStyle == ONCE) {
frame = maxFrame;
status = STOP;
return; // exit at once
}
else { // loopStyle == BACK_AND_FORTH
frame = maxFrame - 1;
if (amt == 1)
runningBackwards = true;
else
runningBackwards = false;
}
}
if (onChange != null)
onChange.compute();
else
needsValueCheck = true;
}
/**
* The method that is run by the animation thread. This is not meant to be called directly.
*/
public void run() {
int localstatus = status;
long lastFrameTime = 0;
runningBackwards = false;
if (frame != 0 || undefinedWhenNotRunning) {
frame = 0;
serialNumber++;
lastFrameTime = System.currentTimeMillis();
if (onChange != null)
onChange.compute();
else
needsValueCheck = true;
if (status == PREV || status == NEXT)
status = PAUSE;
}
try {
while (true) {
synchronized(this) {
while (status == PAUSE) {
if (localstatus != PAUSE) {
doControlStatus(PAUSE);
localstatus = PAUSE;
}
try {
wait();
}
catch (InterruptedException e) {
}
}
if (status == STOP)
break;
localstatus = status;
if (needsValueCheck)
checkValue(); // make sure maxFrame is correct
}
if (localstatus == START) {
doControlStatus(START);
localstatus = status = RUN;
}
if (localstatus == RUN) {
long sinceLastFrame = System.currentTimeMillis() - lastFrameTime;
long waitTime = millisPerFrame - sinceLastFrame;
if (waitTime <= 5)
waitTime = 5;
try {
synchronized(this) {
wait(waitTime);
}
}
catch (InterruptedException e) {
}
lastFrameTime = System.currentTimeMillis();
if (status == RUN)
doAdvanceFrame(1);
}
else if (localstatus == NEXT) {
doAdvanceFrame(1);
if (status != STOP) // status can become stop in doAdvanceFrame
status = localstatus = PAUSE;
}
else if (localstatus == PREV) {
doAdvanceFrame(-1);
if (status != STOP) // status can become stop in doAdvanceFrame (but shouldn't happen here)
status = localstatus = PAUSE;
}
}
}
finally {
synchronized(this) {
status = STOP;
doControlStatus(STOP);
frame = 0;
serialNumber++;
if (onChange != null)
onChange.compute();
else
needsValueCheck = true;
runner = null;
notify(); // in case start() method is waiting for thread to end
}
}
}
} // class Animator
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/ErrorReporter.java
0,0 → 1,61
/*************************************************************************
* TT *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
/**
* To allow different styles of reporting errors, a
* Controller uses an ErrorReporter to report any
* errors that are thrown during its checkInput/compute
* cycle. The DisplayCanvas and MessagePopup classes
* implement this interface.
*
* @author David Eck
*/
public interface ErrorReporter {
 
/**
* Report the specifed message as an error. If source is non-null,
* then it is the Controller that called this routine. In that case,
* if the error reporter is capable of clearing its own error
* condition, it should call source.errorCleared() when it does so.
*
* @param source Controller that called this method (if non-null).
* @param message error message to report.
*/
public void setErrorMessage(Controller source, String message);
 
/**
* Clear the error reprort, if there is one.
*/
public void clearErrorMessage();
 
/**
* Get the error message that is currently being displayed, or
* return null if there is no error message.
*/
public String getErrorMessage();
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/ExpressionInput.java
0,0 → 1,454
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import edu.hws.jcm.data.*;
import java.awt.*;
import java.awt.event.*;
 
/**
* An ExpressionInput is an input box that allows the user
* input a mathematical expression. There is an associated
* object that belongs to the class Expression. The
* value of this object can change only when checkInput()
* is called. The checkInput() method is usually called by a Controller.
* <p>An ExpressionInput will ordinarily be registered with
* a Controller in TWO ways: It's added to a Controller
* with the Controller's add() method. This makes the Contrller
* call the ExpressionInput's checkInput() method during the
* Controller's compute() method. Secondly, the Controller
* is set as the "onUserAction" property. This causes the
* Controller's compute() method to be called when the user
* presses return in the ExpressionInput box. This is optional--
* you might, for example, only want the Controller to compute()
* when a Compute button is pressed. You can also set the
* ExpressionInput's onTextChange property to a Controller
* if you want it to compute every time the text in the box
* changes.
* <p>Use the function getFunction() if you want to
* use an ExpressionInput as a way of inputting a function.
*
*/
public class ExpressionInput extends TextField implements InputObject, Value {
 
/**
* The Expression associate with this input box.
* Class EI is a private nested class.
*/
protected EI expr;
 
/**
* A parser for parsing the user's input
* expression. If this is null,
* a default parser will be used and
* only constant expressions will
* be allowed.
*/
protected Parser parser;
 
/**
* True if the contents of the box have not
* changed since the last time the input was
* checked (by a call to checkInput()).
*/
protected boolean hasChanged;
 
/**
* True if an error should be thrown
* when checkInput() is called,
* but the content of the box is not
* a legal expression. Otherwise, the
* expression will become a constant
* expression with value Double.NaN.
*/
protected boolean throwErrors;
private Controller onUserAction; // If this is non-null, the compute() method
// of onUserAction is called when the user
// presses return in this input-box.
private Controller onTextChange; // If this is non-null, the compute() method
// of onTextChange is called when the text
// in this input box changes
/**
* Error message from the most recent
* time the input was checked by a
* call to checkInput(). If this is
* null, then no error occurred.
*/
protected String errorMessage;
private long serialNumber; // This goes up by one every time checkInput()
// is called and finds a change in the
// user's input;
 
 
/**
* Create a new ExpressionFunction with no associated parser. This can only
* be used to input constant expressions, unless you set a parser later with setParser().
*/
public ExpressionInput() {
this("",null);
}
/**
* Create an ExpressionInputBox with initial contents given by initialValue.
* (If initialValue is null, the empty string is used.) If p is not null,
* then p will be used to parse the contents of the box.
*
* @param initialValue initial contents of ExpressionInputBox.
* @param p if non-null, this parser will be used to parse contents of the ExpressionInputBox.
*/
public ExpressionInput(String initialValue, Parser p) {
super(30);
expr = new EI();
if (initialValue == null)
initialValue = "";
super.setText(initialValue);
setBackground(Color.white);
enableEvents(KeyEvent.KEY_EVENT_MASK);
setParser(p); // (Sets hasChanged to true, so checkInput() will actually check the input.)
checkInput(); // Won't throw an error, since throwErrors is false.
throwErrors = true;
}
 
/**
* Set the parser that is used to parse the user's input strings.
* If this is null, then a default parser is used that will
* only allow constant expressions.
*
* @param p parser to register with user's input strings.
*/
public void setParser(Parser p) {
parser = (p == null)? new Parser() : p;
hasChanged = true; // force re-compute when checkInput() is next called.
}
/**
* Get the Expression associated with this ExpressionInput.
*
*/
public Expression getExpression() {
return expr;
}
 
/**
* Get a function of one variable whose value at a real number
* x is computed by assigning x to the variable v and then
* returning the value of the expression associated with this
* ExpressionInput. Of couse, v should be one of the variables
* registered with the Parser for this ExpressionInput, or else
* in can never occur in the expression.
* Note that the value of the variable v changes TEMPORARILY
* when the function is evaluated. (So you should not use
* a variable where setting the value has a side effect,
* such as the variable associated with a SliderVariable.)
*
* @param v The function that is returned in a function of this variable.
*/
public Function getFunction(Variable v) {
return new SimpleFunction(expr,v);
}
/**
* Get a function of one or more variables whose value at arguments
* x1, x2, ... is computed by assigning the x's to the variables and then
* returning the value of the expression associated with this
* ExpressionInput. Of couse, each v[i] should be one of the variables
* registered with the Parser for this ExpressionInput.
* Note that the value of the variables change TEMPORARILY
* when the function is evaluated.
*
* @param v The function that is returned is a function of the variables in this array.
*/
public Function getFunction(Variable[] v) {
return new SimpleFunction(expr,v);
}
 
/**
* Return the current value of the expression associated with
* this ExpressionInput.
*/
public double getVal() {
return expr.getVal();
}
/**
* If the parameter c is non-null, then its compute method will be called whenever
* the user presses the return key while typing in this text-input box.
*/
public void setOnUserAction(Controller c) {
onUserAction = c;
enableEvents(AWTEvent.ACTION_EVENT_MASK);
}
 
/**
* Return the Controller, if any, that is notified when the user
* presses return in this text-input box.
*/
public Controller getOnUserAction() {
return onUserAction;
}
 
/**
* Method required by InputObject interface; in this class, it simply calls
* setOnUserAction(c). This is meant to be called by JCMPanel.gatherInputs().
*/
public void notifyControllerOnChange(Controller c) {
setOnUserAction(c);
}
 
/**
* If the parameter, c, is non-null, then its compute method will be called whenever
* the text in this input box changes. Furthermore, the throwErrors
* property will be set to false, to avoid throwing multiple errors
* while the user is typing. (You can change it back to true if
* you want by calling setThrowErrors(true).) It would only rarely make sense to
* use this feature.
*/
public void setOnTextChange(Controller c) {
onTextChange = c;
enableEvents(AWTEvent.TEXT_EVENT_MASK);
if (c != null)
throwErrors = false;
}
/**
* Return the Controller, if any, that is notified whenever the text
* in this input box changes
*/
public Controller getOnTextChange() {
return onTextChange;
}
 
/**
* Set the throwErrors property. When this is true, a JCMError can be thrown
* when checkInput() is called an a parse error is found in the contents of the input box.
* If throwErrors is false, no error is thrown. Instead,
* the expression is set to a constant expression with value Double.NaN.
*/
public void setThrowErrors(boolean throwErrors) {
this.throwErrors = throwErrors;
}
/**
* Return the value of the throwErrors property, which determines whether errors
* can be thrown when checkInput() is called.
*/
public boolean getThrowErrors() {
return throwErrors;
}
 
/**
* Get error message from previous call to checkInput().
* Returns null if and only if there was no error.
*/
public String getErrorMessage() {
return errorMessage;
}
//---------------- Some implementation details -------------------------------------------------
 
/**
* Get the expression from the box, maybe throw a JBCError
* if a ParseError occurs. This is meant to be called by a Controller, in general.
* The expression associated with this ExpressionInput can only change when this
* method is called; it DOES NOT change continuously as the user types.
*/
public void checkInput() {
if (!hasChanged)
return;
expr.serialNumber++;
String contents = getText();
try {
expr.exp = parser.parse(contents);
errorMessage = null;
hasChanged = false;
}
catch (ParseError e) {
expr.exp = null;
if (throwErrors) {
errorMessage = "Error in expression: " + e.getMessage();
setCaretPosition(e.context.pos);
requestFocus();
throw new JCMError(e.getMessage(),this);
}
else
errorMessage = "Error in expression at position " + e.context.pos + ": " + e.getMessage();
}
}
 
/**
* Set the text displayed in this input box. This overrides TextField.setText
* to make sure that the expression will be recomputed the next time
* checkInput() is called.
*/
public void setText(String str) {
super.setText(str);
hasChanged = true;
}
 
/**
* Override processKeyEvent to only allow characters
* that are legal in expressions. This is not meant to be called directly.
*/
public void processKeyEvent(KeyEvent evt) {
if (evt.getID() == KeyEvent.KEY_PRESSED) {
int ch = evt.getKeyCode();
char chr = evt.getKeyChar();
boolean use = (chr != 0 && (Character.isDigit(chr) || Character.isLetter(chr))
|| chr == '.' || chr == '(' || chr == ')'
|| chr == '-' || chr == '+' || chr == '*'
|| chr == '/' || chr == '^' || chr == ','
|| chr == ':' || chr == '?' || chr == '|'
|| chr == '&' || chr == '~' || chr == '='
|| chr == '<' || chr == '>' || chr == '!')
|| ch == KeyEvent.VK_DELETE || ch == KeyEvent.VK_SPACE
|| ch == KeyEvent.VK_BACK_SPACE;
boolean useControl = use || ch == KeyEvent.VK_TAB
|| ch ==KeyEvent.VK_ENTER || chr == 0;
if (!useControl) {
evt.consume();
Toolkit.getDefaultToolkit().beep();
}
else if (use)
hasChanged = true;
}
super.processKeyEvent(evt);
}
 
/**
* Overridden to call onUserAction.compute() if onUserAction is non-null.
* This is not meant to be called directly
*/
public void processActionEvent(ActionEvent evt) {
if (onUserAction != null)
onUserAction.compute();
super.processActionEvent(evt);
}
/**
* Overridden to call onUserAction.compute() if onUserAction is non-null.
* This is not meant to be called directly.
*/
public void processTextEvent(TextEvent evt) {
if (onTextChange != null)
onTextChange.compute();
super.processTextEvent(evt);
}
 
/**
* The expression associated with an ExpressionInput belongs to this class.
* So is any derivative of such a function. Note that derivatives
* must be recomputed when the expression changes. This is done
* via "lazy evaluation", that is, only when necessary. When
* a derivative is used, it tests whether it is out of date
* by comparing its serialNumber to the serial number of the
* expression that it is the derivative of. If they don't match,
* then the expression is recomputed and the serial number is updated.
* The serial number and defintion of the main expresssion is changed by
* checkInput() whenever the user's input has changed.
*/
protected class EI implements Expression {
/**
* The actual expression, or null if the
* expression is undefined. If this is a
* derivative of another EI, this will be
* recomputed as necessary when the expression is used
* in some way.
*/
ExpressionProgram exp;
 
/**
* This is null for the original expression input by the
* user. If this EI was formed by taking the derivative
* of anotehr EI, that EI is stored here.
*/
EI derivativeOf;
 
/**
* Which Variable is this a derivative with respect to?
* If derivativeOf is null, so is wrt.
*/
Variable wrt;
 
/**
* For the original expression input by the user, this
* goes up by one each time checkInput() is called and
* finds a change in the user's input. For derivative
* EI, this is the serial number of "derivativeOf" at
* the time this derivative expression was last computed.
*/
int serialNumber;
EI() {
serialNumber = -1; // Forces exp to be computed the first time it is needed.
}
public double getVal() {
checkForChanges();
if (exp == null)
return Double.NaN;
return exp.getVal();
}
public double getValueWithCases(Cases c) {
checkForChanges();
if (exp == null)
return Double.NaN;
return exp.getValueWithCases(c);
}
public String toString() {
checkForChanges();
if (exp == null)
return "(undefined)";
return exp.toString();
}
public Expression derivative(Variable wrt) {
EI deriv = new EI();
deriv.derivativeOf = this;
deriv.wrt = wrt;
return deriv;
}
public boolean dependsOn(Variable x) {
checkForChanges();
return exp.dependsOn(x);
}
void checkForChanges() {
if (derivativeOf != null) {
derivativeOf.checkForChanges();
if (serialNumber != derivativeOf.serialNumber) {
serialNumber = derivativeOf.serialNumber;
if (errorMessage != null)
exp = null;
else
exp = (ExpressionProgram)derivativeOf.exp.derivative(wrt);
}
}
}
} // end nested class EI
} // end class ExpressionInput
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/Tie.java
0,0 → 1,152
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import java.util.Vector;
import edu.hws.jcm.data.Value;
 
/**
* A Tie associates several Tieable objects. When the check() mehtod of the
* Tie is called, it determines which of the Tieables has the largest serial number.
* It then tells each Tieable to synchronize with that object. Ordinarily, the
* Tie is added to a Controller, which is responsible for calling the Tie's
* check() method.
*
* <p>This is meant to be used, for example, to Tie together two InputObjects to synchronize
* the values that they represent. For example, you might want a VariableSlider
* and a VariableInput to be alternative ways of inputting the same value. If so,
* you can put them in a Tie and add that Tie to any Controller that is set to
* respond to changes in the VariableSlider or VariableInput.
* The x- and y- variables of a MouseTracker are also Tieable objects, so you
* can synchronize the values of two MouseTrackers (in different CoordinateRects,
* presumably) and you can synchronize the value of a MouseTracker variable with
* a VariableInput or VariableSlider.
*
* <p>CoordinateRects and LimitControlPanels are also Tieable (to each other -- not
* to Value objects). This is used to allow the LimitControlPanel to synchronize
* with the Limits on the CoordinateRects that it controls. It could also
* synchronize the Limits on two CoordinateRects, even in the absense of a
* LimitControlPanel.
*
* @author David Eck
*/
public class Tie {
/**
* The Tieables in this Tie.
*/
protected Vector items = new Vector(2);
/**
* Create a Tie, initially containing no objects.
*/
public Tie() {
}
/**
* Create a Tie initally containing only the object item.
* item should be non-null.
*
* @param item the only initial item in this tieable.
*/
public Tie(Tieable item) {
add(item);
}
 
/**
* Create a Tie initially containing item1 and item2.
* The items should be non-null. The items will be
* synced with each other at the time the Tie is created.
*/
public Tie(Tieable item1, Tieable item2) {
add(item1);
add(item2);
}
 
/**
* Add item to the tie, and sync it with the items that are
* already in the Tie. It should be non-null. Note that synchronization
* of the objects is forced even if they all have the same serial number,
* since the values might not be the same when they are first added to
* the Tie.
*/
public void add(Tieable item) {
if (item != null) {
items.addElement(item);
forcecheck();
}
}
/**
* If this Tie contains more than one item, find the newest
* one and sync all the items with that item. If the serial
* numbers of all the items are already the same, nothing is
* done.
*/
public void check() {
int top = items.size();
if (top < 2)
return;
long maxSerialNumber = ((Tieable)items.elementAt(0)).getSerialNumber();
int indexOfMax = 0;
boolean outOfSync = false;
for (int i = 1; i < top; i++) {
long sn = ((Tieable)items.elementAt(i)).getSerialNumber();
if (sn != maxSerialNumber)
outOfSync = true;
if (sn > maxSerialNumber) {
maxSerialNumber = sn;
indexOfMax = i;
}
}
if (!outOfSync) // if serialnumbers are the same, no sync is necessary.
return;
Tieable newest = (Tieable)items.elementAt(indexOfMax);
for (int i = 0; i < top; i++)
((Tieable)items.elementAt(i)).sync(this, newest);
}
private void forcecheck() { // Synchronize the items in this Tie, even if serial numbers are the same.
int top = items.size();
if (top < 2)
return;
long maxSerialNumber = ((Tieable)items.elementAt(0)).getSerialNumber();
int indexOfMax = 0;
boolean outOfSync = false;
for (int i = 1; i < top; i++) {
long sn = ((Tieable)items.elementAt(i)).getSerialNumber();
if (sn != maxSerialNumber)
outOfSync = true;
if (sn > maxSerialNumber) {
maxSerialNumber = sn;
indexOfMax = i;
}
}
Tieable newest = (Tieable)items.elementAt(indexOfMax);
for (int i = 0; i < top; i++)
((Tieable)items.elementAt(i)).sync(this, newest);
}
} // end class Tie
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/Controller.java
0,0 → 1,369
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
import edu.hws.jcm.data.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
 
/**
* Controllers are the focus of all the action in the JCM system. A Controller can be
* set to listen for changes (generally changes in user input). This is done by
* registering the Controller with (usally) an InputObject. For example, if a Controller, c,
* is to respond when the user presses return in a VariableInput, v, then
* v.setOnUserAction(c) should be called to arrange to have the Controller listen
* for such actions. VariableSliders, ExpressionInputs, MouseTrackers, Animators have a similar
* methods. It is also possible to set the Controller to listen for events of
* type AdjustmentEvent, ActionEvent, TextEvent, or ItemEvent (but this feature is
* left over from an older version of JCM, and I'm not sure whether it's necessary).
* Whenever a Controller learns of some change, it will process any InputObjects,
* Ties, and Computables that have been registered with it.
*
* <p>InputObjects and Computables have to be added to a Controller to be processed,
* using the Controller's add method. (If you build your inteface out of JCMPanels,
* then this is done automatically.) (Note that an InputObject is added to a Controller
* to have its value checked -- This is separate from registering the Controller to
* listen for changes in the InputObject. Often, you have to do both.) The gatherInputs()
* method in class JCMPanel can be used to do most of this registration automaticaly.
*
* <p>A Tie that synchronizes two or more Values, to be effective, has to be added to a Controller.
* See the Tie class for inforamtion about what Ties are and how they are used.
*
* <p>A Controller can have an associated ErrorReporter, which is used to report any
* errors that occur during the processing. Currently, an ErrorReporter is either
* a DisplayCanvas or a MessagePopup.
*
* <p>A Controller can be added to another Controller, which then becomes a sub-controller.
* Whenever the main Controller hears some action, it also notifies all its sub-controllers
* about the action. Furthermore, it can report errors that occur in the sub-controllers,
* if they don't have their own error reporters. (Usually, you will just set an error
* reporter for the top-level Controller.)
**/
public class Controller implements java.io.Serializable, Computable, InputObject,
AdjustmentListener, ActionListener, TextListener, ItemListener {
/**
* Computable objects controlled by this controller. Note that Controllers
* are Computables, so this list can include sub-controllers.
*/
protected Vector computables;
 
/**
* InputObjects controlled by this controller. Note that Controllers
* are InputObjects, so this list can include sub-controllers.
*/
protected Vector inputs;
/**
* Ties that have been added to this controller.
*/
protected Vector ties;
/**
* Used for reporting errors that occur in the
* compute() method of this controller. If the errorReporter
* is null and if this controller has a parent,
* then the parent will report the error. If
* no ancestor has an errorReporter, the error
* message is written to standard output.
*/
protected ErrorReporter errorReporter;
/**
* The parent of this controller, if any.
* This is set automatically when one
* controller is added to another.
*/
protected Controller parent;
 
/**
* If non-null, this is an error message
* that has been reported and not yet cleared.
*/
protected String errorMessage;
/**
* Create a Controller.
*/
public Controller() {
}
 
/**
* Set the ErrorReporter used to report errors that occur when the
* compute() method of this Controller is executed.
*/
public void setErrorReporter(ErrorReporter r) {
errorReporter = r;
}
/**
* Get the ErrorReporter for this Controller. Return null if there is none.
*/
public ErrorReporter getErrorReporter() {
return errorReporter;
}
 
/**
* Add an object to be controlled by this controller. It should be of
* one or more of the types InputObject, Computable, Tie. If it is
* a Controller, then this Controller becomes its parent.
*/
public void add(Object obj) {
if (obj == null)
return;
if (obj instanceof Controller) {
Controller c = (Controller)obj;
if (c.parent != null)
c.parent.remove(this);
c.parent = this;
}
if (obj instanceof Computable) {
if (computables == null)
computables = new Vector();
computables.addElement(obj);
}
if (obj instanceof InputObject) {
if (inputs == null)
inputs = new Vector();
inputs.addElement(obj);
}
if (obj instanceof Tie) {
if (ties == null)
ties = new Vector();
ties.addElement(obj);
}
}
/**
* Remove the object from the controller (if present).
*/
public void remove(Object obj) {
if (obj == null)
return;
if (computables != null) {
computables.removeElement(obj);
if (computables.size() == 0)
computables = null;
}
if (inputs != null) {
inputs.removeElement(obj);
if (inputs.size() == 0)
inputs = null;
}
if (ties != null) {
ties.removeElement(obj);
if (ties.size() == 0)
ties = null;
}
if (obj instanceof Controller && ((Controller)obj).parent == this)
((Controller)obj).parent = null;
}
/**
* If this controller has a parent, remove it from its parent. (Then, a call to the
* former parent's compute() method will not call this controller's compute().)
*/
public void removeFromParent() {
if (parent != null)
parent.remove(this);
}
// ----------------- Listening for events ----------------------
/**
* Simply calls compute when the Controller hears an ActionEvent.
* This is not meant to be called directly.
*/
public void actionPerformed(ActionEvent evt) {
compute();
}
/**
* Simply calls compute when the Controller hears a TextEvent.
* This is not meant to be called directly.
*/
public void textValueChanged(TextEvent evt) {
compute();
}
/**
* Simply calls compute when the Controller hears an AdjustmantEvent.
* This is not meant to be called directly.
*/
public void adjustmentValueChanged(AdjustmentEvent evt) {
compute();
}
/**
* Simply calls compute when the Controller hears an ItemEvent.
* This is not meant to be called directly.
*/
public void itemStateChanged(ItemEvent evt) {
compute();
}
 
// -------------- Implementation and error-handling ----------------------
 
/**
* When an contoller computes, it first calls checkInput() for any
* InputOjects that it controls (including those in sub-controllers).
* It then handles any Ties. Finally,
* it calls the compute() method of any Computables. If an error
* occurs, it reports it. JCMErrors (which should represent errors
* on the part of the user) will generally only occur during the
* checkInput() phase. Internal, programmer errors can occur at
* any time and might leave the sytem in an unhappy state. They are
* reported as debugging aids for the programmer. When one occurs,
* a stack trace is printed to standard output.
*/
synchronized public void compute() {
try {
checkInput();
doTies();
clearErrorMessage();
doCompute();
}
catch (JCMError e) {
if (errorMessage == null || !errorMessage.equals(e.getMessage()))
reportError(e.getMessage());
}
catch (RuntimeException e) {
reportError("Internal programmer's error detected? " + e);
e.printStackTrace();
}
}
 
/**
* Call checkInput() of each InputObject. Can throw a JCMError.
* This is mostly meant to be called by Controller.compute().
* Note that this will recurse though any sub-controllers of
* this controller, so that when comput() is called,
* all the InputObjects in the sub-controllers
* are processed before ANY Tie or Computable is processed.
* Similarly, the Ties and Computables in the sub-controllers
* are processed in separate passes.
*/
public void checkInput() {
if (inputs != null) {
int top = inputs.size();
for (int i = 0; i < top; i++)
((InputObject)inputs.elementAt(i)).checkInput();
}
}
/**
* Check the Ties in this controller and its sub-controllers.
*/
protected void doTies() {
if (inputs != null) {
int top = inputs.size();
for (int i = 0; i < top; i++)
if (inputs.elementAt(i) instanceof Controller)
((Controller)inputs.elementAt(i)).doTies();
}
if (ties != null) {
int top = ties.size();
for (int i = 0; i < top; i++)
((Tie)ties.elementAt(i)).check();
}
}
/**
* Compute the Computables in this controller and its sub-controllers.
*/
protected void doCompute() {
if (computables != null) {
int top = computables.size();
for (int i = 0; i < top; i++) {
Object obj = computables.elementAt(i);
if (obj instanceof Controller)
((Controller)obj).doCompute();
else
((Computable)obj).compute();
}
}
}
/**
* Report the specified error message.
*/
public void reportError(String message) {
if (message == null)
clearErrorMessage();
if (errorReporter != null) {
errorReporter.setErrorMessage(this,message);
errorMessage = message;
}
else if (parent != null)
parent.reportError(errorMessage);
else {
errorMessage = message;
System.out.println("***** Error: " + errorMessage);
}
}
/**
* Clear the error message.
*/
protected void clearErrorMessage() {
if (errorReporter != null)
errorReporter.clearErrorMessage();
else if (parent != null)
parent.clearErrorMessage();
errorMessage = null;
}
/**
* Should be called by the ErrorReporter if the ErrorReporter clears the error itself.
* (This is only used to avoid repeatedly setting the same error message, during an
* animation for example.)
*/
public void errorCleared() {
errorMessage = null;
}
/**
* Method required by InputObject interface; in this class, calls the same method
* recursively on any input objects controlled by this controller. This is meant to
* be called by JCMPanel.gatherInputs().
*/
public void notifyControllerOnChange(Controller c) {
if (inputs != null) {
int top = inputs.size();
for (int i = 0; i < top; i++)
((InputObject)inputs.elementAt(i)).notifyControllerOnChange(c);
}
}
/**
* Calles notifyControllerOnChange(this). That is, it sets all the InputObjects in
* this Controller, and in subcontrollers, to notify this Controller when they change.
*/
public void gatherInputs() {
notifyControllerOnChange(this);
}
 
} // end class Controller
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/awt/JCMError.java
0,0 → 1,60
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.awt;
 
/**
* JCMErrors can be generated by objects belonging to various classes
* in edu.hws.jcm.awt and edu.hws.jcm.draw. A JCMError can have an
* associated object, which is generally a ParseContext, InputObject,
* or Computable.
*
* @author David Eck
*/
public class JCMError extends RuntimeException {
/**
* Object, possibly null, associated with this error.
*/
public Object object;
 
/**
* Create a JCMError with the given error message and no associated object.
*
* @param message the error message associated with this JCMError.
*/
public JCMError(String message) {
this(message,null);
}
 
/**
* Create a JCMError with the given error message and associated object.
*
* @param message the error message associated with this JCMError.
* @param object the object associated with this JCMError.
*/
public JCMError(String message, Object object) {
super(message);
this.object = object;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/ScatterPlot.java
0,0 → 1,568
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.draw;
 
import java.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
 
 
/**
* A ScatterPlot graphs data taken from a DataTableInput. The data
* in the form of a small plus sign at each (x,y) in the data.
* The x and y values can be taken directly from two specified
* columns in the table. They can also be computed by expressions
* that can use column names from the table as well as the special
* variable rowNumber. For example, if column names are X and Y,
* then it could plot sqrt(X) versus rowNumber*(X+Y).
* <p>Optionally, a ScatterPlot will also draw a regression line
* for the data. Certain statistical values about the data points
* are available as Value objects by calling the getValueObject()
* method.
*/
 
public class ScatterPlot extends Drawable implements Computable {
 
/**
* A constant that can be used in the getValueObject() method to
* indicate which statistic the object should represent.
*/
public static final int INTERCEPT = 0, SLOPE = 1, DATACT = 2, MISSINGCT = 3,
STANDARDERROR = 4, CORRELATION = 5;
private DataTableInput table; // The table from which the data for the plot is taken
private long lastTableSN; // serial number from table when getData() was last done
private boolean autoChangeLimits = true; // If true, then the limits on the coords will
// be changed so that the data pretty much
// fills the coordinate rect.
private int column1, column2; // Column numbers that specify which columns from
// the table will be plotted. These are ignored
// if exp1 and exp2 are non-null.
 
private Expression exp1, exp2; // Expressions that give data to be plotted, or
// null if column numbers are to be used.
 
private boolean showRegressionLine = true; // If true, a regression is drawn
private boolean missingValueIsError = true; // If true and if any of the data values is Double.NaN,
// then an error is thrown.
private double slope=Double.NaN; // Values of statistics.
private double intercept=Double.NaN;
private int dataCt;
private int missingCt;
private double correlation=Double.NaN;
private double standardError=Double.NaN;
private double[][] data; // The actual data values to be drawn (computed in getData())
private Color lineColor = Color.black; // Color of regression line.
private Color dataColor = Color.red; // Color of data points.
private static final int crossHalfSize = 2; // Size of one arm of the plus sign that is drawn
// to represent a data point.
/**
* Default constructor. A data table, at least, must be specified before anything can be drawn.
* The first two columns of the table will be plotted (once a table is specified).
*/
public ScatterPlot() {
this(null,0,1);
}
/**
* Create a scatter plot to plot data from the specified table. Initially, it is configured
* to plot data from the first two columns in the table.
*/
public ScatterPlot(DataTableInput table) {
this(table,0,1);
}
/**
* Create a scatter plot to plot data from two specified columns in a table.
* Columns are numbered starting from zero.
*/
public ScatterPlot(DataTableInput table, int column1, int column2) {
this.table = table;
this.column1 = column1;
this.column2 = column2;
}
/**
* Create scatter plot to plot specified expressions using data from a table.
* The expressions should include references to the column names from the table
* and can also refer to the special variable "rowNumber".
*/
public ScatterPlot(DataTableInput table, Expression exp1, Expression exp2) {
this.table = table;
this.exp1 = exp1;
this.exp2 = exp2;
column1 = 0;
column2 = 1;
}
/**
* Specify the table from which the plotted data is to be taken. The data from the
* first two columns of the table will be plotted, unless this is changed by
* calling setColumns() or setExpressions().
*/
public void setTable(DataTableInput table) {
if (table == this.table)
return;
this.table = table;
lastTableSN = 0;
column1 = 0;
column2 = 1;
checkData();
}
/**
* Get the DataTableInput from which the plotted data is obtained.
*/
public DataTableInput getTable() {
return table;
}
/**
* Specify that the data to be plotted should be taken from the specified
* columns in the table. Note that columns are numbered starting from zero.
* The parameters must be within the range of column numbers in the table.
*/
public void setColumns(int c1, int c2) {
column1 = c1;
column2 = c2;
exp1 = exp2 = null;
lastTableSN = 0; // force checkData to recompute
checkData();
}
/**
* Specify the data for the the plot is to be obtained by evaluating
* the two expressions that are given as parameters. Both expressions
* should be non-null. The expressions can only be created by a Parser
* to which the variables from the table have been added by calling
* the method DataTableInput.addVariablesToParser(). The expressions
* are evaluated once for each row in the table to obtain the data to be ploted. They can include
* references to the column names from the table and to the special
* variable "rowNumber", which represents the number of the current row.
*/
public void setExpressions(Expression exp1, Expression exp2) {
this.exp1 = exp1;
this.exp2 = exp2;
lastTableSN = 0; // force checkData to recompute
checkData();
}
/**
* If the parameter is true, then a regression line for the data is drawn.
* The default value is true.
*/
public void setShowRegressionLine(boolean line) {
if (line != showRegressionLine) {
showRegressionLine = line;
needsRedraw();
}
}
/**
* The return value tells whether a regression line is drawn.
*/
public boolean getShowRegressionLine() {
return showRegressionLine;
}
/**
* If the parameter is true, then a missing data value (an empty cell or
* an undefined value for one of the expressions) is considered to be an
* error, and a JCMError is thrown when it is encountered. If the value is
* false, missing data are ignored, and the value of MISSINGCT gives the
* number of points for which the data was missing. Note that invalid
* data (a cell that contains text that does not represent a number) is
* always considered to be an error. Also note that completely empty
* rows at the bottom of a DataTableInput are always ignored and are
* never considered to be an error.
* The default value of missingValueIsError is true, so that missing data
* is considered to be an error unless you turn off this option.
*/
public void setMissingValueIsError(boolean isError) {
missingValueIsError = isError;
}
 
/**
* The return value indicates whether missing data is considered to be
* an error.
*/
public boolean getMissingValueIsError() {
return missingValueIsError;
}
/**
* If the parameter is true, then the limits on the CoordinateRect that contains
* this ScatterPlot are automatically adjusted whenever the data is recomputed.
* The default value is true.
*/
public void setAutoChangeLimits(boolean set) {
autoChangeLimits = set;
}
 
/**
* The return value indicates whether the limits on the CoordinateRect are
* automatically adjusted when the data is recomputed.
*/
public boolean getAutoChangeLimits() {
return autoChangeLimits;
}
/**
* Get the color that is used to draw the points in the data.
*/
public Color getDataColor() {
return dataColor;
}
/**
* Set the color that is used to draw the points in the data.
* The default value is red.
*/
public void setDataColor(Color color) {
if (color != null)
dataColor = color;
}
/**
* Get the color that is used to draw the regression line.
*/
public Color getLineColor() {
return lineColor;
}
/**
* Set the color that is used to draw the regression line.
* The default value is black.
*/
public void setLineColor(Color color) {
if (color != null)
lineColor = color;
}
/**
* Get a Value that represents a statistic about the data that is shown
* in the scatter plot. The parameter specifies which statistic is represented.
* It can be one of the constants defined in this class: SLOPE (of regression line),
* INTERCEPT (y-intercept of regression line), DATACT (number of data points),
* MISSINGCT (number of missing data; alwasy zero if the missingValueIsError property
* is true), STANDARDERROR (standard error of regression line), and CORRELATION
* (correlation coefficient between first and second coordintes of data points).
*/
public Value getValueObject(int valueCode) {
if (valueCode < 0 || valueCode > 5)
throw new IllegalArgumentException("Unknown code (" + valueCode + ") for type of value object.");
return new SPV(valueCode);
}
/**
* Check data from table and recompute everything if it has changed.
*/
private void checkData() {
if (table != null && lastTableSN == table.getSerialNumber())
return;
try {
compute();
}
catch (JCMError e) {
canvas.setErrorMessage(null,e.getMessage());
}
}
/**
* Recompute the data for the scatter plot. This is generally
* not called directly.
*/
public void compute() {
double[] desiredLimits = getData();
if (table != null)
lastTableSN = table.getSerialNumber();
if (desiredLimits == null || !needsNewLimits(desiredLimits,coords))
needsRedraw();
else
coords.setLimits(desiredLimits);
}
/**
* Draw the data points and regression line. Not meant to be called directly.
*/
public void draw(Graphics g, boolean coordsChanged) {
g.setColor(dataColor);
if (table == null) {
g.drawString("No table has been specified.",20,27);
return;
}
if (column1 < 0 || column1 >= table.getColumnCount()
|| column2 < 0 || column2 >= table.getColumnCount()) {
g.drawString("Illegal column numbers.",20,27);
return;
}
if (data == null || data.length == 0) {
g.drawString("No data available.",20,27);
return;
}
checkData();
for (int i = 0; i < data.length; i++) {
int x = coords.xToPixel(data[i][0]);
int y = coords.yToPixel(data[i][1]);
g.drawLine(x-crossHalfSize,y,x+crossHalfSize,y);
g.drawLine(x,y-crossHalfSize,x,y+crossHalfSize);
}
if (showRegressionLine && !Double.isNaN(slope)) {
g.setColor(lineColor);
if (Double.isInfinite(slope)) {
int x = coords.xToPixel(data[0][0]);
g.drawLine(x,coords.getTop(),x,coords.getTop()+coords.getHeight());
}
else {
double x1 = coords.pixelToX(coords.getLeft());
double x2 = coords.pixelToX(coords.getLeft()+coords.getWidth());
double y1 = slope*x1 + intercept;
double y2 = slope*x2 + intercept;
g.drawLine(coords.xToPixel(x1), coords.yToPixel(y1)-1,
coords.xToPixel(x2), coords.yToPixel(y2)-1);
}
}
}
/**
* Get the data for the plot, and recompute the statistics.
* Also, compute the appropriate limits for the CoordinateRect.
* The return value represents these limits.
*/
private double[] getData() {
int rows = (table == null)? 0 : table.getNonEmptyRowCount();
double[] desiredLimits = null;
if ( table == null || rows == 0 || ( (exp1 == null || exp2 == null) &&
(column1 < 0 || column1 >= table.getColumnCount() ||
column2 < 0 || column2 >= table.getColumnCount()) ) ) {
data = new double[0][2];
dataCt = 0;
missingCt = 0;
slope = Double.NaN;
intercept = Double.NaN;
correlation = Double.NaN;
standardError = Double.NaN;
return null;
}
data = new double[rows][2];
dataCt = 0;
missingCt= 0;
if (exp1 == null || exp2 == null) {
for (int i = 0; i < rows; i++) {
double x = table.getCellContents(i+1,column1);
double y = table.getCellContents(i+1,column2);
if (Double.isNaN(x) || Double.isNaN(y) || Double.isInfinite(x) || Double.isInfinite(y)) {
if (missingValueIsError)
throw new JCMError("Missing data in row " + table.getCurrentRowNumber() + " of table.", this);
missingCt++;
}
else {
data[dataCt][0] = x;
data[dataCt][1] = y;
dataCt++;
}
}
}
else {
for (int i = 0; i < rows; i++) {
table.setCurrentRowNumber(i+1);
double x = exp1.getVal();
double y = exp2.getVal();
if (Double.isNaN(x) || Double.isNaN(y) || Double.isInfinite(x) || Double.isInfinite(y)) {
if (missingValueIsError)
throw new JCMError("Missing data or undefined expression value for row " + table.getCurrentRowNumber() + " of table.", this);
missingCt++;
}
else {
data[dataCt][0] = x;
data[dataCt][1] = y;
dataCt++;
}
}
}
if (dataCt < data.length) {
double[][] d = new double[dataCt][2];
for (int i = 0; i < dataCt; i++)
d[i] = data[i];
data = d;
}
getRegressionStats();
if (autoChangeLimits)
desiredLimits = computeDesiredLimits();
return desiredLimits;
}
private void getRegressionStats() {
// Compute statistics, based on data in data array.
if (dataCt == 0) {
slope = intercept = correlation = standardError = Double.NaN;
return;
}
boolean allSameX = true,
allSameY = true;
double sumx = data[0][0],
sumy = data[0][1],
sumxy = data[0][0]*data[0][1],
sumx2 = data[0][0]*data[0][0],
sumy2 = data[0][1]*data[0][1];
for (int i = 1; i < dataCt; i++) {
if (data[0][0] != data[i][0])
allSameX = false;
if (data[0][1] != data[i][1])
allSameY = false;
sumx += data[i][0];
sumy += data[i][1];
sumxy += data[i][0] * data[i][1];
sumx2 += data[i][0] * data[i][0];
sumy2 += data[i][1] * data[i][1];
}
double denomx = dataCt * sumx2 - sumx*sumx;
double denomy = dataCt * sumy2 - sumy*sumy;
double numer = dataCt * sumxy - sumx*sumy;
if (allSameX && allSameY) {
slope = 0;
intercept = data[0][1];
correlation = standardError = Double.NaN;
}
else if (allSameX) {
slope = Double.POSITIVE_INFINITY;
intercept = correlation = standardError = Double.NaN;
}
else if (denomx == 0) {
slope = intercept = correlation = standardError = Double.NaN;
}
else {
slope = numer / denomx;
intercept = (sumy - slope * sumx) / dataCt;
if (denomy == 0)
correlation = Double.NaN;
else
correlation = numer / Math.sqrt(denomx*denomy);
if (dataCt <= 2)
standardError = Double.NaN;
else {
double sum = 0;
for (int i = 0; i < dataCt; i++) {
double x = data[i][1] - (slope*data[i][0] + intercept);
sum += x*x;
}
standardError = Math.sqrt(sum/(dataCt-2));
}
}
}
private double[] computeDesiredLimits() {
// Compute desired limits, based on data in data array
if (data.length == 0)
return null;
double xmin=Double.MAX_VALUE, xmax=-Double.MAX_VALUE,
ymin=Double.MAX_VALUE, ymax=-Double.MAX_VALUE;
for (int i = 0; i < dataCt; i++) {
double x = data[i][0];
double y = data[i][1];
if (x > xmax)
xmax = x;
if (x < xmin)
xmin = x;
if (y > ymax)
ymax = y;
if (y < ymin)
ymin = y;
}
if (xmin > 0 && (xmax - xmin) > xmax/2)
xmin = 0;
if (ymin > 0 && (ymax - ymin) > ymax/2)
ymin = 0;
if (ymax < 0)
ymax = 0;
if (xmax < 0)
xmax = 0;
if (xmax == xmin) {
xmax += 1;
xmin -= 1;
}
else {
double spread = (xmax - xmin) / 15;
xmax += spread;
xmin -= spread;
}
if (ymax == ymin) {
ymax += 1;
ymin -= 1;
}
else {
double spread = (ymax - ymin) / 15;
ymax += spread;
ymin -= spread;
}
return new double[] { xmin, xmax, ymin, ymax };
}
private boolean needsNewLimits(double[] desiredLimits, CoordinateRect coords) {
// Check if limits should actually be changed; avoid changing them if
// they are close to the desired limits.
double[] limits = new double[] { coords.getXmin(), coords.getXmax(),
coords.getYmin(), coords.getYmax() } ;
return (desiredLimits[0] < limits[0]
|| desiredLimits[1] > limits[1]
|| desiredLimits[2] < limits[2]
|| desiredLimits[3] > limits[3]
|| (limits[1] - limits[0]) > 1.3*(desiredLimits[1] - desiredLimits[0])
|| (limits[3] - limits[2]) > 1.3*(desiredLimits[3] - desiredLimits[2])
|| (limits[1] - limits[0]) < (desiredLimits[1] - desiredLimits[0]) / 1.3
|| (limits[3] - limits[2]) < (desiredLimits[3] - desiredLimits[2]) / 1.3
);
}
private class SPV implements Value {
// Represents one of the value objects that can
// be returned by the getValueObject() method.
private int code; // Which statisitic does this Value represent?
SPV(int code) {
this.code = code;
}
public double getVal() {
checkData();
switch (code) {
case INTERCEPT: return intercept;
case SLOPE: return slope;
case DATACT: return dataCt;
case MISSINGCT: return missingCt;
case STANDARDERROR: return standardError;
default: return correlation;
}
}
}
 
} // end class ScatterPlot
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/MouseTracker.java
0,0 → 1,435
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.awt.*;
import edu.hws.jcm.data.*;
import java.awt.*;
import java.awt.event.*;
 
/**
* A MouseTracker can be added to a CoordinateRect in a DisplayCanvas to respond to user
* mouse actions in the rectangular area occupied by the CoordinateRect. Two
* Variable objects, which can be retrieved by calling getXVar() and getYVar(),
* represent the location of the most recent mouse action in terms of the coordinates
* of the CoordinateRect. Note that these variables are Tieable objects, so they
* can be synchronized with other means of inputting the same information.
* The default names of the variables, if you don't change them, are "xMouse"
* and "yMouse".
*
* <p>A MouseTracker is an InputObject. The values of the variables associated with the
* MouseTracker can change only when the checkInput() method is called (or when
* the setVal() method of the variable is called to set its value explicitely).
* If you want the value of the variables to track the mouse, you must
* add the MouseTracker (or the DisplayCanvas that contains it) to a Controller
* and set that Controller to listen for changes from the MouseTracker object by
* passing the Controller to the setOnUserAction() method of this class.
*
*/
 
public class MouseTracker extends Drawable implements MouseListener, MouseMotionListener, InputObject {
 
/**
* If true, the MouseTracker responds to both clicks and drags.
* If false, it responds only to clicks.
*/
protected boolean listenForDrags;
 
/**
* If true, the values of the associated variables are
* undefined except during the time that the user is
* clicking and dragging the mouse. This is ignored
* if listenForDrags is false.
*/
protected boolean undefinedWhenNotDragging;
 
/**
* If this is non-null, then its compute() method is called
* when the user clicks the mouse and, if listenForDrags is also
* true, when the user drags and releases the mouse.
*/
protected Controller onUserAction;
/**
* If thie is true, then the value of the variable associated with
* the x-ccordinate of the mouse is clamped to lie within the
* xmin and xmax of the coordinate rect.
*/
protected boolean clampX = true;
 
/**
* If thie is true, then the value of the variable associated with
* the y-ccordinate of the mouse is clamped to lie within the
* ymin and ymax of the coordinate rect.
*/
protected boolean clampY = true;
 
private MTVariable xVar, yVar; //The variables associated with this MouseTracker. The class MTVarible
// is a private nested class defined below.
 
private int xClick, yClick; //Pixel where the mose recent user mouse action occured.
private boolean inRect; //This is set to true while the user is dragging (if listenForDrags is true).
/**
* Create a MouseTracker that responds to both clicks and drags. The values of the
* associated variables remain defined even after the user stops dragging.
*/
public MouseTracker() {
this(true,false);
}
/**
* Creates a mouse tracker. The first parameter specifies whether the values of
* the variables change when the user drags the mouse, or only when the user clicks.
* The second parameter is only used if the first is true. It specifies whether
* the values of the variables become undefined after the user stops dragging the
* mouse.
*
*/
public MouseTracker(boolean listenForDrags, boolean undefinedWhenNotDragging) {
this.listenForDrags = listenForDrags;
this.undefinedWhenNotDragging = undefinedWhenNotDragging;
xVar = new MTVariable(true);
yVar = new MTVariable(false);
}
/**
* Get the variable whose value represents the x-coordinate of the MouseTracker.
* Note that this variable implements the Tieable interface, so can legally
* be type-cast to type Tieable. It can be tied to other objects that
* implement the Tieable and Value interfaces to synchronize their values.
*/
public Variable getXVar() {
return xVar;
}
/**
* Get the variable whose value represents the y-coordinate of the MouseTracker.
* Note that this variable implements the Tieable interface, so can legally
* be type-cast to type Tieable. It can be tied to other objects that
* implement the Tieable and Value interfaces to synchronize their values.
*/
public Variable getYVar() {
return yVar;
}
 
/**
* Sets the "listenForDrags" property of the MouseTracker.
* If set to true, then the MouseTracker responds to both clicks and drags if false,
* it responds only to clicks.
*
*/
public void setListenForDrags(boolean listen) {
if (listen != listenForDrags) {
listenForDrags = listen;
if (canvas != null) {
if (listen)
canvas.addMouseMotionListener(this);
else
canvas.removeMouseMotionListener(this);
}
}
}
/**
* Gets the "listenForDrags" property of the MouseTracker, which determines
* if the MouseTracker responds to both clicks and drags, or only to clicks.
*/
public boolean getListenForDrags() {
return listenForDrags;
}
/**
* Sets the "undefinedWhenNotDragging" property of the MouseTracker.
* This is ignored if the MouseTracker is not listening for drags.
* If set to true, the values of the variables associated with this
* variable become undefined when the user is not dragging.
*
*/
public void setUndefinedWhenNotDragging(boolean b) {
undefinedWhenNotDragging = b;
}
/**
* Gets the "undefinedWhenNotDragging" property of the MouseTracker.
*
*/
public boolean getUndefinedWhenNotDragging() {
return undefinedWhenNotDragging;
}
/**
* Set a Controller to respond to user mouse actions tracked
* by this MouseTracker. The MouseTracker should also be added
* to the Controller, so that the values of its variables will
* actually change when a user action occurs.
*
*/
public void setOnUserAction(Controller onUserAction) {
this.onUserAction = onUserAction;
}
/**
* Method required by InputObject interface; in this class, it simply calls
* setOnUserAction(c). This is meant to be called by JCMPanel.gatherInputs().
*/
public void notifyControllerOnChange(Controller c) {
setOnUserAction(c);
}
 
/**
* Get the Controller that responds when a user mouse action is detected by this MouseTracker.
*/
public Controller getOnUserAction() {
return onUserAction;
}
/**
* Set the "clampX" property of the MouseTracker.
* If set to true, which is the default, the value of
* the variable associated with the horizontal position of
* the mouse is clamped to lie within the containing
* CoordinateRect.
*
*/
public void setClampX(boolean clamp) {
clampX = clamp;
}
/**
* Get the "clampX" property of the MouseTracker.
*/
public boolean getClampX() {
return clampX;
}
/**
* Set the "clampY" property of the MouseTracker.
* If set to true, which is the default, the value of
* the variable associated with the vertical position of
* the mouse is clamped to lie within the containing
* CoordinateRect.
*
*/
public void setClampY(boolean clamp) {
clampY = clamp;
}
/**
* Get the "clampY" property of the MouseTracker.
*/
public boolean getClampY() {
return clampX;
}
//------------------ Implementation details --------------------------------------------
/**
* Set the values of the associated variables. This is part of the InputObject interface,
* and it is meant to be called by a Controller.
*/
public void checkInput() {
if (coords == null || (undefinedWhenNotDragging && !inRect)) { ;
xVar.setVal(Double.NaN);
yVar.setVal(Double.NaN);
}
else {
double newX, newY; // The new values.
newX = coords.pixelToX(xClick);
if (clampX) {
if (newX < coords.getXmin())
newX = coords.getXmin();
else if (newX > coords.getXmax())
newX = coords.getXmax();
}
xVar.setVal(newX);
newY = coords.pixelToY(yClick);
if (clampY) {
if (newY < coords.getYmin())
newY = coords.getYmin();
else if (newY > coords.getYmax())
newY = coords.getYmax();
}
yVar.setVal(newY);
}
}
/**
* A MouseTracker doesn't actually draw anything, but this method is required in
* a Drawable object.
*/
public void draw(Graphics g, boolean coordsChanged) {
}
/**
* This is called automatically by CoordinateRect when the
* MouseTracker is added to the CoordinateRect. It is not
* meant to be used directly.
*
*/
protected void setOwnerData(DisplayCanvas canvas, CoordinateRect coords) {
if (this.canvas != null) {
canvas.removeMouseListener(this);
canvas.removeMouseMotionListener(this);
}
this.canvas = canvas;
this.coords = coords;
canvas.addMouseListener(this);
if (listenForDrags)
canvas.addMouseMotionListener(this);
}
/**
* Responds when the user clicks the mouse in the rectangular
* area occupied by the CoordinateRect that contains this MouseTracker.
* Since the MouseTracker listens for clicks on the whole DisplayCanvas
* and the CoordinateRect might only occupy part of that, it is necessary
* to check whether the user click was in that rect. This is not meant to be called directly.
*
*/
public void mousePressed(MouseEvent evt) {
if (evt.isConsumed() || coords == null)
return;
inRect = (evt.getX() >= coords.getLeft() && evt.getX() <= coords.getLeft() + coords.getWidth()
&& evt.getY() >= coords.getTop() && evt.getY() <= coords.getTop() + coords.getHeight());
if (!inRect)
return;
evt.consume();
xClick = evt.getX();
yClick = evt.getY();
xVar.serialNumber++;
yVar.serialNumber++;
if (onUserAction != null)
onUserAction.compute();
}
/**
* Responds when the user releases the mouse. This is not meant to be called directly.
*
*/
public void mouseReleased(MouseEvent evt) {
if (inRect == false)
return;
inRect = false;
if (listenForDrags && undefinedWhenNotDragging) {
xVar.serialNumber++;
yVar.serialNumber++;
if (onUserAction != null)
onUserAction.compute();
}
}
 
/**
* Responds when the user drags the mouse. This is not meant to be called directly.
*
*/
public void mouseDragged(MouseEvent evt) {
if (listenForDrags && inRect) {
xClick = evt.getX();
yClick = evt.getY();
xVar.serialNumber++;
yVar.serialNumber++;
if (onUserAction != null)
onUserAction.compute();
}
}
/**
* Empty method, required by MouseListener interface.
*/
public void mouseClicked(MouseEvent evt) { }
/**
* Empty method, required by MouseMotionListener interface.
*/
public void mouseEntered(MouseEvent evt) { }
/**
* Empty method, required by MouseMotionListener interface.
*/
public void mouseExited(MouseEvent evt) { }
/**
* Empty method, required by MouseMotionListener interface.
*/
public void mouseMoved(MouseEvent evt) { }
 
 
//The class to which the variables associated with this MouseTracker belong.
private class MTVariable extends Variable implements Tieable {
//True for xVar; false for yVar.
private boolean isXVar;
//This object's serial number, which can
//change in MouseTracker.checkInput() as
//well as in the setVal() and sync() methods in this class.
long serialNumber;
//Create the variable.
MTVariable(boolean isXVar) {
super(isXVar? "xMouse" : "yMouse");
this.isXVar = isXVar;
super.setVal(Double.NaN);
}
//Set the value of the variable. Note that the
//value can be set to lie outside the coordinate rect,
//even if clampX and clampY are true. The next checkInput(),
//however, will apply the clamp.
public void setVal(double val) {
if (isXVar) {
if (coords != null) // set xClick to match the value.
xClick = coords.xToPixel(val);
}
else {
if (coords != null) // set yClick to match the value
yClick = coords.yToPixel(val);
}
super.setVal(val);
}
// Return this Tieable object's serial number.
public long getSerialNumber() {
return serialNumber;
}
//Synchronize values and serial numbers with newest.
public void sync(Tie tie, Tieable newest) {
if ( ! (newest instanceof Value) )
throw new IllegalArgumentException("Internal Error: A MouseTracker variable can only be tied to a Value object.");
if (newest != this) {
setVal(((Value)newest).getVal());
serialNumber = newest.getSerialNumber();
}
}
} // end nested class MTVariable
 
 
} // end class MouseTracker
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/CoordinateRect.java
0,0 → 1,789
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.awt.*;
import edu.hws.jcm.data.Value;
import java.awt.*;
import java.util.Vector;
 
/**
* A CoordinateRect represents a rectagular region in the xy-plane, specified
* by values xmin,xmax,ymin,ymax. The conditions ymin < ymax and xmin < xmax
* are enforced. (Values are swapped if necessary, and if min==max, they are
* reset to -1 and +1. If any of the values are set to an infinite or NaN
* value, then the coordinate rect won't display anything except the message
* "Error: undefined limits".)
* <P> When the Rect is mapped onto the screen, there can be a gap of a specified
* number of pixels between the min,max values and the edges of the rectangle
* on the screen. If the gap is non-zero, then the actual range of coordinates
* on the rect is larger than the range from the specifed min to max. (This is
* done mainly so I could have axes that don't quite reach the edges of the rect.)
* <P>A CoordinateRect maintains a list of Drawable items. When the Rect's
* draw() method is called, it calls the draw() method of each of the Drawable
* items it contains. When its compute() method is called, it calls the
* compute() method of any Drawable that is a Computable. When its checkInput()
* method is called, it calls the checkInput() method of any Drawable that is
* an InputObject.
* <P>A CoordinateRect represents a rectangular region in a DisplayCanvas.
* It has a reference to that Canvas, which is set automatically when it is
* added to the canvas. If the size, range, or gap on the CoordinateRect
* change, it will ask the Canvas to redraw the area it occupies.
*
* <P>The values of xmin, xmax, ymin, ymax are exported as Value objects,
* which can be used elsewhere in your program. The Value objects can
* be obtained by calling getValueObject(). If you do this, you should
* add the objects that depend on those values to a Controller and
* register the Controller to listen for changes from this CoordinateRect
* by calling the CoordinateRect.setOnChange(Controller) method.
*/
 
public class CoordinateRect implements Tieable, Limits, Computable, InputObject {
 
 
private double xmin,xmax,ymin,ymax; // Range of x and y values on the Rect (not counting the gap).
private int gap = 5; //Extra pixels around the edges, outside the specifed range of x,y values.
//Note: xmin,xmax,ymin,ymax are the limits on a rectangle that
//is inset from the drawing rect by gap pixels on each edge.
 
/**
* Drawable items contained in this CoordinateRect
*/
protected Vector drawItems = new Vector();
/**
* Set to true when one of the limits or the gap has changed.
*/
protected boolean changed;
 
private long serialNumber; // This value is increased whenever xmin,xmax,ymin,ymax,gap change
// or when the size of the rectangle in pixels changes.
/**
* This contains other Limit objects with which the CoordinateRect is
* synchronizing. This is ordinarily managed by a LimitControlPanel,
* so you don't have to worry about it. (However, you can also sync
* several CoordinateRects even in the absense of a LimitControlPanel.
* To do so, create the Tie that ties the CoordinateRect and pass it to
* the setSyncWith() method of each CoordinateRect. It is NOT necessary
* to add the Tie to a Controller. Synchronization is handled by the
* CoordinateRects themselves.
*/
protected Tie syncWith;
 
/**
* Create a CoordinateRect with default limits: -5, 5, -5, 5.
*/
public CoordinateRect() {
this(-5,5,-5,5);
}
/**
* Create a CoordinateRect with specified limits.
*/
public CoordinateRect(double xmin, double xmax, double ymin, double ymax) {
setLimits(xmin,xmax,ymin,ymax);
serialNumber = 0;
setRestoreBuffer(); // Restore buffer holds original limits, util it is reset
}
//--------- Methods for getting and setting xmin, xmax, ymin, ymax, and gap.------
 
/**
* Get the mimimum x-coordinate.
*/
public double getXmin() { return xmin; }
/**
* Get the maximum x-coordinate.
*/
public double getXmax() { return xmax; }
 
/**
* Get the mimimum y-coordinate.
*/
public double getYmin() { return ymin; }
 
/**
* Get the maximum x-coordinate.
*/
public double getYmax() { return ymax; }
 
/**
* Get the gap, in pixels, between the edges of
* the CoordinateRect and the limits specified by xmin, xmax, ymin, and ymax.
*/
public int getGap() {
return gap;
}
 
/**
* Set the gap. This is ignored if g is less than zero. This gap is the number of pixels
* between the edges of the CoordinateRect and the limits specified by xmin, xmax, ymin, and ymax.
* The default value is 5.
*
*/
public void setGap(int g) {
if (g >= 0 && gap!= g) {
int oldgap = gap;
gap = g;
changed = true;
serialNumber++;
needsRedraw();
}
}
 
/**
* Get an array containing the limits on the CoordinateRect in the order xmin, xmax, ymin, ymax.
*/
public double[] getLimits() {
return new double[] { xmin, xmax, ymin, ymax };
}
 
/**
* Set the limits on the CoordinteRect
*
* @param xmin the minimum x-coordinate on the CoordinateRect
* @param xmax the maximum x-coordinate on the CoordinateRect
* @param ymin the minimum y-coordinate on the CoordinateRect
* @param ymax the maximum y-coordinate on the CoordinateRect
*/
public void setLimits(double xmin, double xmax, double ymin, double ymax) {
double[] oldLimits = getLimits();
this.xmin = xmin;
this.xmax = xmax;
this.ymin = ymin;
this.ymax = ymax;
checkLimits();
double[] newLimits = getLimits();
if (oldLimits[0] == newLimits[0] && oldLimits[1] == newLimits[1] &&
oldLimits[2] == newLimits[2] && oldLimits[3] == newLimits[3])
return;
changed = true;
serialNumber++;
if (syncWith != null)
syncWith.check();
if (onChange != null)
onChange.compute();
needsRedraw();
}
 
/**
* Set the coordinate limits from array; extra elements in array are ignored.
* This is ignored if the array is null or has fewer than 4 members.
* The order of values in the array is xmin, xmax, ymin, ymax.
*
*/
public void setLimits(double[] d) {
if (d != null && d.length >= 4)
setLimits(d[0],d[1],d[2],d[3]);
}
/**
* Specify a controller to be notified when the limits on this
* CoordinateRect change.
*/
public void setOnChange(Controller c) {
onChange = c;
}
/**
* Get the controller that is notified when the limits on this
* CoordinateRect change. This can be null.
*/
public Controller getOnChange() {
return onChange;
}
/**
* Get a Value object representing one of the limits on this CoordinateRect.
* The parameter should be one of the constants CoordinateRect.XMIN,
* CoordinateRect.XMAX, CoordinateRect.YMIN, or CoordinateRect.YMAX.
* (If not, it is treated the same as YMAX).
*
*/
public Value getValueObject(final int which) {
return new Value() {
public double getVal() {
switch (which) {
case XMIN: return getXmin();
case XMAX: return getXmax();
case YMIN: return getYmin();
default: return getYmax();
}
}
};
}
 
/**
* Return the serial number of the CoordinateRect, which is incremented each time the limits change.
* Part of the Tieable interface.
* Not meant to be called directly.
*/
public long getSerialNumber() {
return serialNumber;
}
/**
* Set the Tie object that is used to synchronize this CoordinareRect with other objects.
* This is ordinarily called by a LimitControlPanel, so you don't have to worry about it.
*/
public void setSyncWith(Tie tie) {
syncWith = tie;
}
/**
* Part of the Tieable interface.
* Not meant to be called directly.
*/
public void sync(Tie tie, Tieable newest) {
if (newest != this) {
if ( !(newest instanceof Limits) )
throw new IllegalArgumentException("Internal programming error: A CoordinateRect can only be tied to a Limits object.");
double[] d = ((Limits)newest).getLimits();
if (d != null && d.length >= 4) {
double[] oldLimits = getLimits();
if (d[0] == oldLimits[0] && d[1] == oldLimits[1] && d[2] == oldLimits[2] && d[3] == oldLimits[3])
return;
xmin = d[0];
xmax = d[1];
ymin = d[2];
ymax = d[3];
checkLimits();
serialNumber = newest.getSerialNumber();
changed = true;
if (onChange != null)
onChange.compute();
needsRedraw();
}
}
}
 
private void checkLimits() { //Make sure limits satisfy constraints.
if (xmin == xmax) {
xmin -= 1;
xmax += 1;
}
else if (xmin > xmax) {
double temp = xmin;
xmin = xmax;
xmax = temp;
}
if (ymin == ymax) {
ymin -= 1;
ymax += 1;
}
if (ymin > ymax) {
double temp = ymin;
ymin = ymax;
ymax = temp;
}
}
// -------------- Value objects corresponding to xmin, xmax, ymin, ymax -------------
/**
* A constant for use with the getValueObject() method to specify which Value is to be returned.
* XMIN specifies that the Value is the minimum x-coordinate on the CoordinateRect.
*/
public final static int XMIN = 0;
/**
* A constant for use with the getValueObject() method to specify which Value is to be returned.
* XMAX specifies that the Value is the maximum x-coordinate on the CoordinateRect.
*/
public final static int XMAX = 1;
 
/**
* A constant for use with the getValueObject() method to specify which Value is to be returned.
* YMIN specifies that the Value is the minimum y-coordinate on the CoordinateRect.
*/
public final static int YMIN = 2;
 
/**
* A constant for use with the getValueObject() method to specify which Value is to be returned.
* YMAX specifies that the Value is the maximum y-coordinate on the CoordinateRect.
*/
public final static int YMAX = 3;
/**
* If non-null, this is the Controller that is notified when the limits change.
*/
protected Controller onChange;
// ---------------------- Methods for working with Pixels ----------------------
// Note: This stuff is only valid if the CoordinateRect is
// displayed in a Graphics context. I.E., after a call to draw();
// It is meant to be used by Drawables when their draw() methods are called.
 
private int left, top, width = -1, height = -1; // Not setable; these are valid only during drawing and are meant to be used
// by the Drawables in this Coorfdinate Rect.
/**
* Get the left edge of this CoordinateRect in the DisplayCanvas that contains it.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*/
public int getLeft() { return left; }
/**
* Get the width in pixels of this CoordinateRect in the DisplayCanvas that contains it.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*/
public int getWidth() { return width; }
/**
* Get the top edge of this CoordinateRect in the DisplayCanvas that contains it.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*/
public int getTop() { return top; }
/**
* Get the height in pixels of this CoordinateRect in the DisplayCanvas that contains it.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*/
public int getHeight() { return height; }
/**
* Return the width of one pixel in this coordinate system.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*
*/
public double getPixelWidth() {
return (xmax - xmin)/(width-2*gap-1);
}
/**
* Return the height of one pixel in this coordinate system.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*
*/
public double getPixelHeight() {
return (ymax - ymin)/(height-2*gap-1);
}
 
/**
* Convert an x-coodinate into a horizontal pixel coordinate.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*
*/
public int xToPixel(double x) {
int xInt = left + gap + (int)((x - xmin)/(xmax - xmin) * (width-2*gap-1));
if (xInt < -32000)
return -32000;
else if (xInt > 32000)
return 32000;
else
return xInt;
}
/**
* Convert a y-coodinate into a vertical pixel coordinate.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*
*/
public int yToPixel(double y) {
int yInt = top + gap + (int)((ymax - y)/(ymax - ymin) * (height-2*gap-1));
if (yInt < -32000)
return -32000;
else if (yInt > 32000)
return 32000;
else
return yInt;
}
/**
* Convert a horizontal pixel coordinate into an x-coordinate.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*
*/
public double pixelToX(int h) {
return xmin + ((h-left-gap)*(xmax-xmin)) / (width-2*gap-1);
}
/**
* Convert a vertical pixel coordinate into a y-coordinate.
* (This is only valid when the CoordinateRect has actually been displayed. It is meant
* mainly to be used by Drawables in this CoordinateRect.)
*
*/
public double pixelToY(int y) {
return ymax - ((y-top-gap)*(ymax-ymin)) / (height-2*gap-1);
}
// ---------------------- Save/Restore limits -------------------------
 
private double restore_xmin = Double.NaN, restore_xmax, restore_ymin, restore_ymax;
/**
* A CoordinateRect can store its current limits in a buffer. These limits
* can be restored by a call to this method. Only one level of
* save/restore is provided. If limits have not been saved, then nothing happens.
* The original limits on the CoordinateRect are saves automatically when
* the CoordinateRect is first created.
*
* @return an array containing new limits.
*/
public double[] restore() {
if (Double.isNaN(restore_xmin))
return null;
setLimits(restore_xmin,restore_xmax,restore_ymin,restore_ymax);
return getLimits();
}
/**
* A CoordinateRect can store its current limits in a buffer. This method
* clears that buffer.
*/
public void clearRestoreBuffer() {
restore_xmin = Double.NaN;
}
/**
* Save current limits in buffer. They can be restored later by a call
* to the restore() method. Only one level of
* save/restore is provided.
*/
public void setRestoreBuffer() {
if (badData())
return;
checkLimits();
restore_xmin = xmin;
restore_xmax = xmax;
restore_ymin = ymin;
restore_ymax = ymax;
}
/**
* Used to test if any of the limit data are infinite or NaN.
*/
private boolean badData() {
return Double.isNaN(xmin) || Double.isInfinite(xmin) || Double.isNaN(ymin) || Double.isInfinite(ymin) ||
Double.isNaN(xmax) || Double.isInfinite(xmax) || Double.isNaN(ymax) || Double.isInfinite(ymax);
}
 
// ----------- Zoom in and out ---------------
/**
* Change limits to zoom in by a factor of 2. A maximal zoom is enforced.
* The center of the rectangle does not move.
*
* @return an array of the new limits, or null if limits don't change.
*/
public double[] zoomIn() {
if (badData())
return getLimits();
double halfwidth = (xmax - xmin)/4.0;
double halfheight = (ymax - ymin)/4.0;
double centerx = (xmin + xmax)/2.0;
double centery = (ymin + ymax)/2.0;
if (Math.abs(halfheight) < 1e-100 || Math.abs(halfwidth) < 1e-100)
return null;
setLimits(centerx - halfwidth, centerx + halfwidth, centery - halfheight, centery + halfheight);
return getLimits();
}
/**
* Change limits to zoom out by a factor of 2. A maximal zoom is enforced.
* The center of the rectangle does not move.
*
* @return an array of the new limits, or null if limits don't change.
*/
public double[] zoomOut() {
if (badData())
return getLimits();
double halfwidth = (xmax - xmin);
double halfheight = (ymax - ymin);
double centerx = (xmin + xmax)/2.0;
double centery = (ymin + ymax)/2.0;
if (Math.abs(halfwidth) > 1e100 || Math.abs(halfheight) > 1e100)
return null;
setLimits(centerx - halfwidth, centerx + halfwidth, centery - halfheight, centery + halfheight);
return getLimits();
}
/**
* Change limits to zoom in by a factor of 2, centered on a specified point. A maximal zoom is enforced.
* The point does not move. Only valid when CoordinateRect is
* displayed in a rectangle on the screen.
*
* @param x the horizontal pixel coordinate of the center point of the zoom
* @param y the vertical pixel coordinate of the center point of the zoom
*
* @return an array of the new limits, or null if limits don't change.
*/
public double[] zoomInOnPixel(int x, int y) {
if (badData())
return getLimits();
double halfwidth = (xmax - xmin)/4.0;
double halfheight = (ymax - ymin)/4.0;
if (Math.abs(halfheight) < 1e-100 || Math.abs(halfwidth) < 1e-100)
return null;
double xclick = pixelToX(x);
double yclick = pixelToY(y);
double centerx = (xmin+xmax)/2;
double centery = (ymin+ymax)/2;
double newCenterx = (centerx+xclick)/2;
double newCentery = (centery+yclick)/2;
setLimits(newCenterx - halfwidth, newCenterx + halfwidth,
newCentery - halfheight, newCentery + halfheight);
return getLimits();
}
/**
* Change limits to zoom out by a factor of 2, centered on a specified point. A maximal zoom is enforced.
* The point (x,y) does not move. Valid only if CoordinateRect has been drawn.
*
* @param x the horizontal pixel coordinate of the center point of the zoom
* @param y the vertical pixel coordinate of the center point of the zoom
*
* @return an array of the new limits, or null if limits don't change.
*/
public double[] zoomOutFromPixel(int x, int y) {
if (badData())
return getLimits();
double halfwidth = (xmax - xmin);
double halfheight = (ymax - ymin);
if (Math.abs(halfwidth) > 1e100 || Math.abs(halfheight) > 1e100)
return null;
double xclick = pixelToX(x);
double yclick = pixelToY(y);
double centerx = (xmin+xmax)/2;
double centery = (ymin+ymax)/2;
double newCenterx = 2*centerx - xclick;
double newCentery = 2*centery - yclick;
setLimits(newCenterx - halfwidth, newCenterx + halfwidth,
newCentery - halfheight, newCentery + halfheight);
return getLimits();
}
/**
* Reset limits, if necessary, so scales on the axes are the same.
* Only valid of the CoordinateRect has been drawn.
*
* @return an array with the new limits, or null if limits don't change.
*/
public double[] equalizeAxes() {
if (badData())
return getLimits();
double w = xmax - xmin;
double h = ymax - ymin;
double pixelWidth = w / (width - 2*gap - 1);
double pixelHeight = h / (height - 2*gap - 1);
double newXmin, newXmax, newYmin, newYmax;
if (pixelWidth < pixelHeight) {
double centerx = (xmax + xmin) / 2;
double halfwidth = w/2 * pixelHeight/pixelWidth;
newXmax = centerx + halfwidth;
newXmin = centerx - halfwidth;
newYmin = ymin;
newYmax = ymax;
}
else if (pixelWidth > pixelHeight) {
double centery = (ymax + ymin) / 2;
double halfheight = h/2 * pixelWidth/pixelHeight;
newYmax = centery + halfheight;
newYmin = centery - halfheight;
newXmin = xmin;
newXmax = xmax;
}
else
return null;
setLimits(newXmin, newXmax, newYmin, newYmax);
return getLimits();
}
 
 
// ------------------------------ Drawing ----------------------------
private DisplayCanvas canvas; // The canvas in which this CoordinateRect is displayed. This is set
// automatically when the CoordinateRect is added to or removed from
// a DisplayCanvas, and it should not be changed.
/**
* This is meant to be called only by the DisplayCanvas class,
* when this CoordinateRect is added to ta DisplayCanvas.
*
*/
void setOwner(DisplayCanvas canvas) {
this.canvas = canvas;
}
private void needsRedraw() { //Notifies the canvas that the area occupied by this CoodinateRect
if (canvas != null) //needs to be redrawn.
canvas.doRedraw(this);
}
/**
* When this is called, the CoordinateRect will call the
* checkInput method of any Drawable it contains that is
* also an InputObject. This is ordinarly only called by a DisplayCanvas.
*/
public void checkInput() {
int ct = drawItems.size();
for (int i = 0; i < ct; i++)
if (drawItems.elementAt(i) instanceof InputObject)
((InputObject)drawItems.elementAt(i)).checkInput();
}
 
/**
* When this is called, the CoordinateRect will call the compute method
* of any Drawable it contains that is also a Computable.
* This is ordinarly only called by a DisplayCanvas.
*/
public void compute() {
int ct = drawItems.size();
for (int i = 0; i < ct; i++)
if (drawItems.elementAt(i) instanceof Computable)
((Computable)drawItems.elementAt(i)).compute();
}
 
/**
* Method required by InputObject interface; in this class, it calls the same method
* recursively on any input objects containted in this CoordinateRect. This is meant to
* be called by JCMPanel.gatherInputs().
*/
public void notifyControllerOnChange(Controller c) {
int ct = drawItems.size();
for (int i = 0; i < ct; i++)
if (drawItems.elementAt(i) instanceof InputObject)
((InputObject)drawItems.elementAt(i)).notifyControllerOnChange(c);
}
 
/**
* Add a drawable item to the CoordinateRect.
*
*/
synchronized public void add(Drawable d) {
if (d != null && !drawItems.contains(d)) {
d.setOwnerData(canvas,this);
drawItems.addElement(d);
}
}
/**
* Remove the given Drawable item, if present in this CoordinateRect.
*
*/
synchronized public void remove(Drawable d) {
if (d != null && drawItems.removeElement(d))
d.setOwnerData(null,null);
}
/**
* Returns the number of Drawable items that are in this CoordinateRect.
*/
public int getDrawableCount() {
return (drawItems == null)? 0 : drawItems.size();
}
/**
* Get the i-th Drawable in this Rect, or null if i is less than zero
* or greater than or equal to the number of items.
*
* @param i The number of the item to be returned, where the first item is number zero.
*/
public Drawable getDrawable(int i) {
if (drawItems != null && i >= 0 && i < drawItems.size())
return (Drawable)drawItems.elementAt(i);
else
return null;
}
/**
* Check whether a mouse click (as specified in the MouseEvent parameter) is
* a click on a Draggable item that wants to be dragged. If so, return that item. If not, return null.
* This is meant to be called only by DisplayCanvas.
*/
Draggable checkDraggables(java.awt.event.MouseEvent evt) {
int top = drawItems.size();
for (int i = top-1; i >= 0; i--)
if ( drawItems.elementAt(i) instanceof Draggable ) {
if ( ((Draggable)drawItems.elementAt(i)).startDrag(evt) )
return (Draggable)drawItems.elementAt(i);
}
return null;
}
/**
* Draw in rect with upperleft corner (0,0) and specified width,height.
* This is not ordinarily called directly.
*
*/
public void draw(Graphics g, int width, int height) {
draw(g,0,0,width,height);
}
/**
* Draw in specified rect. This is not ordinarily called directly.
*/
synchronized public void draw(Graphics g, int left, int top, int width, int height) {
if (badData()) {
g.setColor(Color.red);
g.drawRect(left,top,width-1,height-1);
g.drawString("(undefined limits)",left+6,top+15);
}
if (changed || this.left != left || this.top != top
|| this.width != width || this.height != height) {
this.width = width;
this.height = height;
this.left = left;
this.top = top;
checkLimits();
changed = true;
}
doDraw(g);
changed = false;
}
/**
* Draw all the Drawable items. This is called by the draw() method and is not
* meant to be called directly. However, it might be overridden in a subclass.
*
*/
protected void doDraw(Graphics g) {
int ct = drawItems.size();
for (int i = 0; i < ct; i++) {
Drawable d = (Drawable)drawItems.elementAt(i);
if (d.getVisible())
d.draw(g,changed);
}
}
} // end class CoordinateRect
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/VectorField.java
0,0 → 1,415
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
import java.awt.*;
import java.util.Vector;
 
/**
* A VectorField displays lines or arrows on a grid of points where the direction
* and/or lengths are given by two functions (f1(x,y),f2(x,y)). This is probably
* more useful as a "direction field" than as a "vector field."
*
*/
 
public class VectorField extends Drawable implements Computable {
 
/**
* One of the possible styles for displaying a VectorField: as a direction field shown as
* arrows of equal length. The point where the vector is computed is the tail of the arrow.
*/
public static final int ARROWS = 0;
/**
* One of the possible styles for displaying a VectorField: as a direction field shown as
* tangent lines. The point where the vector is computed is the center of the line.
*/
public static final int LINES = 1;
/**
* One of the possible styles for displaying a VectorField: as a vector field where a vector is shown as
* an arrow from (x,y) to (x+xFunc(x,y),y+xFunc(x,y)), except that a maximum length is imposed.
*/
public static final int CLAMPED_VECTORS = 2;
/**
* One of the possible styles for displaying a VectorField: as a field of tangent lines where the length
* of the line is proportional to the length of the vector.
*/
public static final int SCALED_LINES = 3;
/**
* One of the possible styles for displaying a VectorField: as a vector field where a vector is shown as
* an arrow with length proportional to the length of the vector. The lengths are scaled so that
* the longest arrow has length equal to the grid spacing.
*/
public static final int SCALED_VECTORS = 4;
 
private int style; // The style in which the vector field is drawn.
 
private Function xFunc, yFunc; // The vector field is (xFunc(x,y),yfunc(x,y)).
 
private Color graphColor = Color.lightGray; //Color of the vectors.
 
private boolean changed; // Used internally to indicate that data has to be recomputed.
 
 
private transient int[][] data; // Pre-computed data for the vectors.
private int pixelSpacing = 30; // Desired number of pixels between grid points, clamped to the range 5 to 200.
/**
* Create a VectorField object with nothing to graph. The functions and other values
* can be set later. The default display style is as a direction field of equal-length arrows.
*/
public VectorField() {
this(null,null,ARROWS);
}
/**
* Create a VectorField that will be displayed using the default style, as a direction field of
* equal-length arrows. If either of the functions is null, nothing will be displayed. If non-null,
* the functions must be functions of two variables.
*/
public VectorField(Function xFunc, Function yFunc) {
this(xFunc,yFunc,ARROWS);
}
/**
* Create a VectorField with the specified functions and style.
*
* @param xFunc A Function of two variables giving the x-component of the vector field. If this
* is null, then nothing will be drawn.
* @param yFunc A Function of two variables giving the y-component of the vector field. If this
* is null, then nothing will be drawn.
* @param style The style in which the direction field is drawn. This can be one of the
constants ARROWS (a direction field of equal-lenth arrows), LINES (equal length lines),
CLAMPED_VECTORS (vectors drawn at actual length, unless too long), SCALED_VECTORS (vectors scaled so longest has
length equal to the grid spacing), or SCALED_LINES (lines scaled so longest has length
equal to the grid spacing).
*/
public VectorField(Function xFunc, Function yFunc, int style) {
if ( (xFunc != null && xFunc.getArity() != 2) || (yFunc != null && yFunc.getArity() != 2) )
throw new IllegalArgumentException("Internal Error: The functions that define a vector must be functions of two variables.");
this.xFunc = xFunc;
this.yFunc = yFunc;
this.style = style;
changed = true;
}
/**
* Set the color to be used for drawing the vector field. The default color is light gray.
*/
public void setColor(Color c) {
if (c != null & !c.equals(graphColor)) {
graphColor = c;
needsRedraw();
}
}
/**
* Get the color that is used to draw the vector field.
*/
public Color getColor() {
return graphColor;
}
/**
* Sets the functions that give the components of the vector field. If either function is
* null, then nothing is drawn. If non-null, each function must be a function of two variables.
*/
synchronized public void setFunctions(Function dx, Function dy) {
setXFunction(dx);
setYFunction(dy);
}
/**
* Set the function that gives the x-component of the vector field. If this is
* null, then nothing is drawn. If non-null, it must be a function of two variables.
*/
synchronized public void setXFunction(Function dx) {
if (dx != null && dx.getArity() != 2)
throw new IllegalArgumentException("Internal Error: VectorField can only use functions of two variables.");
if (dx != xFunc) {
xFunc = dx;
changed = true;
needsRedraw();
}
}
/**
* Set the function that gives the y-component of the vector field. If this is
* null, then nothing is drawn. If non-null, it must be a function of two variables.
*/
synchronized public void setYFunction(Function dy) {
if (dy != null && dy.getArity() != 1)
throw new IllegalArgumentException("Internal Error: VectorField can only use functions of two variables.");
if (dy != yFunc) {
yFunc = dy;
changed = true;
needsRedraw();
}
}
/**
* Get the (possibly null) function that gives the x-component of the vector field.
*/
public Function getXFunction() {
return xFunc;
}
/**
* Get the (possibly null) function that gives the y-component of the vector field.
*/
public Function getYFunction() {
return yFunc;
}
/**
* Get the style in which the vector field is displayed.
*/
public int getStyle() {
return style;
}
/**
* Set the style in which the vector field is displayed. This should be one of the
* constants ARROWS, LINES, CLAMPED_VECTORS, SCALED_LINES, or SCALED_VECTORS.
*/
public void setStyle(int style) {
if (this.style != style) {
this.style = style;
changed = true;
needsRedraw();
}
}
/**
* Get the value of the pixelSpacing property, which determines the grid spacing for the vector field.
*/
public int getPixelSpacing() {
return pixelSpacing;
}
/**
* Set the value of the pixelSpacing property, which determines the grid spacing for the vector field.
* The value will be clamped to the range from 5 to 200. The default value is 30.
*/
public void setPixelSpacing(int spacing) {
if (spacing < 5)
spacing = 5;
else if (spacing > 200)
spacing = 200;
if (spacing != pixelSpacing) {
pixelSpacing = spacing;
changed = true;
needsRedraw();
}
}
//------------------ Implementation details -----------------------------
/**
* Recompute data for the vector field and make sure that the area of the display canvas
* that shows the vector field is redrawn. This method is ordinarily called by a
* Controller.
*/
synchronized public void compute() {
setup();
needsRedraw();
changed = false;
}
/**
* Draw the vector field (possibly recomputing the data if the CoordinateRect has changed).
*
*/
synchronized public void draw(Graphics g, boolean coordsChanged) {
if (changed || coordsChanged || data == null) {
setup();
changed = false;
}
if (data == null)
return;
g.setColor(graphColor);
boolean arrows = style == ARROWS || style == CLAMPED_VECTORS || style == SCALED_VECTORS;
for (int i = 0; i < data.length; i++) {
int[] c = data[i];
if (c[0] != Integer.MIN_VALUE) { // Otherwise, vector is undefined
g.drawLine(c[0],c[1],c[2],c[3]);
if (arrows && c[4] != Integer.MIN_VALUE) { // Otherwise, there is no arrowhead
g.drawLine(c[2],c[3],c[4],c[5]);
g.drawLine(c[2],c[3],c[6],c[7]);
}
}
}
}
// ------------------------- Computing the data for the vector field -----------------------
private void setup() {
if (xFunc == null || yFunc == null || coords == null) {
data = null; // Nothing will be drawn
return;
}
boolean arrows = style == ARROWS || style == CLAMPED_VECTORS || style == SCALED_VECTORS;
int xCt, yCt; // number of points in x and y directions.
double xStart, yStart; // Starting values for x,y, at lower left corner of grid.
double dx, dy; // Change in x and y between grid points.
double[] params = new double[2];
xCt = (coords.getWidth()) / pixelSpacing + 2;
yCt = (coords.getHeight()) / pixelSpacing + 2;
dx = pixelSpacing*coords.getPixelWidth();
dy = pixelSpacing*coords.getPixelHeight();
xStart = (coords.getXmax() + coords.getXmin() - xCt*dx)/2;
yStart = (coords.getYmax() + coords.getYmin() - yCt*dy)/2;
data = new int[xCt*yCt][arrows? 8 : 4];
double[][] xVec = new double[xCt][yCt]; // Vector field scaled so pixelsize is one unit.
double[][] yVec = new double[xCt][yCt];
double pixelWidth = coords.getPixelWidth();
double pixelHeight = coords.getPixelHeight();
double maxLength = 0;
for (int i = 0; i < xCt; i++) {
double x = xStart + i*dx;
params[0] = x;
for (int j = 0; j < yCt; j++) {
double y = yStart + j*dy;
params[1] = y;
xVec[i][j] = xFunc.getVal(params);
yVec[i][j] = yFunc.getVal(params);
if ( ! (Double.isNaN(xVec[i][j]) || Double.isNaN(yVec[i][j]) ||
Double.isInfinite(xVec[i][j]) || Double.isInfinite(yVec[i][j])) ) {
xVec[i][j] = xVec[i][j]/pixelWidth; // size in terms of pixels
yVec[i][j] = -yVec[i][j]/pixelHeight; // sign change because pixels are numbered from top down
double length = xVec[i][j]*xVec[i][j] + yVec[i][j]*yVec[i][j];
if (length > maxLength)
maxLength = length;
}
}
}
maxLength = Math.sqrt(maxLength);
int ct = 0; // which item of data are we working on?
for (int i = 0; i < xCt; i++) {
double x = xStart + i*dx;
int xInt = coords.xToPixel(x);
for (int j = 0; j < yCt; j++) {
double y = yStart + j*dy;
int yInt = coords.yToPixel(y);
int[] d = data[ct];
ct++;
if ( Double.isNaN(xVec[i][j]) || Double.isNaN(yVec[i][j]) ||
Double.isInfinite(xVec[i][j]) || Double.isInfinite(yVec[i][j]) ) {
d[i] = Integer.MIN_VALUE; // signal that vector is undefined at this point
}
else {
double length = Math.sqrt(xVec[i][j]*xVec[i][j] + yVec[i][j]*yVec[i][j]);
if (length < 1e-15 || (maxLength == 0 && (style == SCALED_LINES || style == SCALED_VECTORS))) { // no arrow.
d[0] = d[2] = xInt;
d[1] = d[3] = yInt;
if (arrows)
d[4] = Integer.MIN_VALUE;
}
else {
double sdx, sdy; // dx and dy scaled to a vector of right length
double alength; // length of arrow or line
boolean clamped = false;
switch (style) {
case ARROWS:
sdx = 0.8 * pixelSpacing * xVec[i][j]/length;
sdy = 0.8 * pixelSpacing * yVec[i][j]/length;
d[0] = xInt;
d[1] = yInt;
d[2] = (int)(xInt + sdx);
d[3] = (int)(yInt + sdy);
break;
case LINES:
sdx = 0.8 * pixelSpacing * xVec[i][j]/length/2;
sdy = 0.8 * pixelSpacing * yVec[i][j]/length/2;
d[0] = (int)(xInt - sdx);
d[1] = (int)(yInt - sdy);
d[2] = (int)(xInt + sdx);
d[3] = (int)(yInt + sdy);
break;
case CLAMPED_VECTORS:
alength = length;
if (alength > 0.9*pixelSpacing) {
alength = 0.9*pixelSpacing;
clamped = true;
}
sdx = xVec[i][j]/length*alength;
sdy = yVec[i][j]/length*alength;
d[0] = xInt;
d[1] = yInt;
d[2] = (int)(xInt + sdx);
d[3] = (int)(yInt + sdy);
break;
case SCALED_LINES:
alength = (length/maxLength)*pixelSpacing;
sdx = xVec[i][j]/length*alength/2;
sdy = yVec[i][j]/length*alength/2;
d[0] = (int)(xInt - sdx);
d[1] = (int)(yInt - sdy);
d[2] = (int)(xInt + sdx);
d[3] = (int)(yInt + sdy);
break;
case SCALED_VECTORS:
alength = (length/maxLength)*pixelSpacing;
sdx = xVec[i][j]/length*alength;
sdy = yVec[i][j]/length*alength;
d[0] = xInt;
d[1] = yInt;
d[2] = (int)(xInt + sdx);
d[3] = (int)(yInt + sdy);
break;
}
if (arrows) { // add an arrowhead
int d1 = (d[2] - d[0])/5;
int d2 = (d[3] - d[1])/5;
if (clamped || d1 == 0 && d2 == 0)
d[4] = Integer.MIN_VALUE; // no arrowhead
else {
d[4] = d[2] + d2 - d1;
d[5] = d[3] - d1 - d2;
d[6] = d[2] - d1 - d2;
d[7] = d[3] + d1 - d2;
}
}
}
}
}
}
} // end setup()
} // end class VectorField
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/TangentLine.java
0,0 → 1,51
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.data.*;
 
/**
* A Tangent line is a line that is tangent to the graph of a specified function of one argument
* at a specified value of its argument. If added to a CoordinateRect, it will appear
* as a line.
* A TangentLine is a Computable object, so should be added to a Controller to be
* recomputed when the Value or Function changes.
*
*/
public class TangentLine extends DrawGeometric {
 
/**
* Create a tangent line to the graph of a function.
*
* @param x The x-coordinate where the tangent is drawn.
* @param f The line is tangent to the graph of this function. This should be a function of one variable.
*/
public TangentLine(Value x, Function f) {
super(INFINITE_LINE_RELATIVE, x, new ValueMath(f,x), new Constant(1), new ValueMath(f.derivative(1), x));
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/DataPlot.java
0,0 → 1,587
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.draw;
 
import java.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
 
 
/**
* A DataPlot graphs data taken from a DataTableInput. The data
* in the form of a small plus sign at each (x,y) in the data.
* The x and y values can be taken directly from two specified
* columns in the table. They can also be computed by expressions
* that can use column names from the table as well as the special
* variable rowNumber. For example, if column names are X and Y,
* then it could plot sqrt(X) versus rowNumber*(X+Y).
* <p>Optionally, a DataPlot will also draw a regression line
* for the data. Certain statistical values about the data points
* are available as Value objects by calling the getValueObject()
* method.
*/
 
public class DataPlot extends Drawable implements Computable {
 
/**
* A constant that can be used in the getValueObject() method to
* indicate which statistic the object should represent.
*/
public static final int INTERCEPT = 0, SLOPE = 1, DATACT = 2, MISSINGCT = 3,
STANDARDERROR = 4, CORRELATION = 5;
private DataTableInput table; // The table from which the data for the plot is taken
private long lastTableSN; // serial number from table when getData() was last done
private boolean autoChangeLimits = true; // If true, then the limits on the coords will
// be changed so that the data pretty much
// fills the coordinate rect.
private int column1, column2; // Column numbers that specify which columns from
// the table will be plotted. These are ignored
// if exp1 and exp2 are non-null.
 
private Expression exp1, exp2; // Expressions that give data to be plotted, or
// null if column numbers are to be used.
 
private boolean showRegressionLine = true; // If true, a regression is drawn
private boolean missingValueIsError = true; // If true and if any of the data values is Double.NaN,
// then an error is thrown.
private double slope=Double.NaN; // Values of statistics.
private double intercept=Double.NaN;
private int dataCt;
private int missingCt;
private double correlation=Double.NaN;
private double standardError=Double.NaN;
private double[][] data; // The actual data values to be drawn (computed in getData())
private Color lineColor = Color.black; // Color of regression line.
private Color dataColor = Color.red; // Color of data points.
private static final int crossHalfSize = 2; // Size of one arm of the plus sign that is drawn
// to represent a data point.
/**
* Default constructor. A data table, at least, must be specified before anything can be drawn.
* The first two columns of the table will be plotted (once a table is specified).
*/
public DataPlot() {
this(null,0,1);
}
/**
* Create a data plot to plot data from the specified table. Initially, it is configured
* to plot data from the first two columns in the table.
*/
public DataPlot(DataTableInput table) {
this(table,0,1);
}
/**
* Create a data plot to plot data from two specified columns in a table.
* Columns are numbered starting from zero.
*/
public DataPlot(DataTableInput table, int column1, int column2) {
this.table = table;
this.column1 = column1;
this.column2 = column2;
}
/**
* Create data plot to plot specified expressions using data from a table.
* The expressions should include references to the column names from the table
* and can also refer to the special variable "rowNumber".
*/
public DataPlot(DataTableInput table, Expression exp1, Expression exp2) {
this.table = table;
this.exp1 = exp1;
this.exp2 = exp2;
column1 = 0;
column2 = 1;
}
/**
* Specify the table from which the plotted data is to be taken. The data from the
* first two columns of the table will be plotted, unless this is changed by
* calling setColumns() or setExpressions().
*/
public void setTable(DataTableInput table) {
if (table == this.table)
return;
this.table = table;
lastTableSN = 0;
column1 = 0;
column2 = 1;
checkData();
}
/**
* Get the DataTableInput from which the plotted data is obtained.
*/
public DataTableInput getTable() {
return table;
}
/**
* Specify that the data to be plotted should be taken from the specified
* columns in the table. Note that columns are numbered starting from zero.
* The parameters must be within the range of column numbers in the table.
*/
public void setColumns(int c1, int c2) {
column1 = c1;
column2 = c2;
exp1 = exp2 = null;
lastTableSN = 0; // force checkData to recompute
checkData();
}
/**
* Specify the data for the the plot is to be obtained by evaluating
* the two expressions that are given as parameters. Both expressions
* should be non-null. The expressions can only be created by a Parser
* to which the variables from the table have been added by calling
* the method DataTableInput.addVariablesToParser(). The expressions
* are evaluated once for each row in the table to obtain the data to be ploted. They can include
* references to the column names from the table and to the special
* variable "rowNumber", which represents the number of the current row.
*/
public void setExpressions(Expression exp1, Expression exp2) {
this.exp1 = exp1;
this.exp2 = exp2;
lastTableSN = 0; // force checkData to recompute
checkData();
}
/**
* If the parameter is true, then a regression line for the data is drawn.
* The default value is true.
*/
public void setShowRegressionLine(boolean line) {
if (line != showRegressionLine) {
showRegressionLine = line;
needsRedraw();
}
}
/**
* The return value tells whether a regression line is drawn.
*/
public boolean getShowRegressionLine() {
return showRegressionLine;
}
/**
* If the parameter is true, then a missing data value (an empty cell or
* an undefined value for one of the expressions) is considered to be an
* error, and a JCMError is thrown when it is encountered. If the value is
* false, missing data are ignored, and the value of MISSINGCT gives the
* number of points for which the data was missing. Note that invalid
* data (a cell that contains text that does not represent a number) is
* always considered to be an error. Also note that completely empty
* rows at the bottom of a DataTableInput are always ignored and are
* never considered to be an error.
* The default value of missingValueIsError is true, so that missing data
* is considered to be an error unless you turn off this option.
*/
public void setMissingValueIsError(boolean isError) {
missingValueIsError = isError;
}
 
/**
* The return value indicates whether missing data is considered to be
* an error.
*/
public boolean getMissingValueIsError() {
return missingValueIsError;
}
/**
* If the parameter is true, then the limits on the CoordinateRect that contains
* this DataPlot are automatically adjusted whenever the data is recomputed.
* The default value is true.
*/
public void setAutoChangeLimits(boolean set) {
autoChangeLimits = set;
}
 
/**
* The return value indicates whether the limits on the CoordinateRect are
* automatically adjusted when the data is recomputed.
*/
public boolean getAutoChangeLimits() {
return autoChangeLimits;
}
/**
* Get the color that is used to draw the points in the data.
*/
public Color getDataColor() {
return dataColor;
}
/**
* Set the color that is used to draw the points in the data.
* The default value is red.
*/
public void setDataColor(Color color) {
if (color != null)
dataColor = color;
}
/**
* Get the color that is used to draw the regression line.
*/
public Color getLineColor() {
return lineColor;
}
/**
* Set the color that is used to draw the regression line.
* The default value is black.
*/
public void setLineColor(Color color) {
if (color != null)
lineColor = color;
}
/**
* Get a Value that represents a statistic about the data that is shown
* in the data plot. The parameter specifies which statistic is represented.
* It can be one of the constants defined in this class: SLOPE (of regression line),
* INTERCEPT (y-intercept of regression line), DATACT (number of data points),
* MISSINGCT (number of missing data; alwasy zero if the missingValueIsError property
* is true), STANDARDERROR (standard error of regression line), and CORRELATION
* (correlation coefficient between first and second coordintes of data points).
*/
public Value getValueObject(int valueCode) {
if (valueCode < 0 || valueCode > 5)
throw new IllegalArgumentException("Unknown code (" + valueCode + ") for type of value object.");
return new SPV(valueCode);
}
/**
* Check data from table and recompute everything if it has changed.
*/
private void checkData() {
if (table != null && lastTableSN == table.getSerialNumber())
return;
try {
compute();
}
catch (JCMError e) {
canvas.setErrorMessage(null,e.getMessage());
}
}
/**
* Recompute the data for the data plot. This is generally
* not called directly.
*/
public void compute() {
double[] desiredLimits = getData();
if (table != null)
lastTableSN = table.getSerialNumber();
if (desiredLimits == null || !needsNewLimits(desiredLimits,coords))
needsRedraw();
else
coords.setLimits(desiredLimits);
}
/**
* Draw the data points and regression line. Not meant to be called directly.
*/
public void draw(Graphics g, boolean coordsChanged) {
g.setColor(dataColor);
if (table == null) {
g.drawString("No table has been specified.",20,27);
return;
}
if (column1 < 0 || column1 >= table.getColumnCount()
|| column2 < 0 || column2 >= table.getColumnCount()) {
g.drawString("Illegal column numbers.",20,27);
return;
}
if (data == null || data.length == 0) {
g.drawString("Druk op de knop voor de datafile .",20,27);
return;
}
checkData();
for (int i = 0; i < data.length ; i++) {
int x = coords.xToPixel(data[i][0]);
int y = coords.yToPixel(data[i][1]);
g.drawLine(x-crossHalfSize,y,x+crossHalfSize,y);
g.drawLine(x,y-crossHalfSize,x,y+crossHalfSize);
}
//evers
int xmax=0;
for (int i = 0; i < data.length - 1 ; i++) {
int x1 = coords.xToPixel(data[i][0]);
int y1 = coords.yToPixel(data[i][1]);
int x2 = coords.xToPixel(data[i+1][0]);
int y2 = coords.yToPixel(data[i+1][1]);
if(x2>x1 && x2>xmax){xmax=x2;}
g.drawLine(x1,y1,x2,y2);
}
xmax= coords.xToPixel(xmax);
g.drawString("Xmax=" + xmax,20,27);
 
//evers
 
 
if (showRegressionLine && !Double.isNaN(slope)) {
g.setColor(lineColor);
if (Double.isInfinite(slope)) {
int x = coords.xToPixel(data[0][0]);
g.drawLine(x,coords.getTop(),x,coords.getTop()+coords.getHeight());
}
else {
double x1 = coords.pixelToX(coords.getLeft());
double x2 = coords.pixelToX(coords.getLeft()+coords.getWidth());
double y1 = slope*x1 + intercept;
double y2 = slope*x2 + intercept;
g.drawLine(coords.xToPixel(x1), coords.yToPixel(y1)-1,
coords.xToPixel(x2), coords.yToPixel(y2)-1);
}
}
}
/**
* Get the data for the plot, and recompute the statistics.
* Also, compute the appropriate limits for the CoordinateRect.
* The return value represents these limits.
*/
private double[] getData() {
int rows = (table == null)? 0 : table.getNonEmptyRowCount();
double[] desiredLimits = null;
if ( table == null || rows == 0 || ( (exp1 == null || exp2 == null) &&
(column1 < 0 || column1 >= table.getColumnCount() ||
column2 < 0 || column2 >= table.getColumnCount()) ) ) {
data = new double[0][2];
dataCt = 0;
missingCt = 0;
slope = Double.NaN;
intercept = Double.NaN;
correlation = Double.NaN;
standardError = Double.NaN;
return null;
}
data = new double[rows][2];
dataCt = 0;
missingCt= 0;
if (exp1 == null || exp2 == null) {
for (int i = 0; i < rows; i++) {
double x = table.getCellContents(i+1,column1);
double y = table.getCellContents(i+1,column2);
if (Double.isNaN(x) || Double.isNaN(y) || Double.isInfinite(x) || Double.isInfinite(y)) {
if (missingValueIsError)
throw new JCMError("Missing data in row " + table.getCurrentRowNumber() + " of table.", this);
missingCt++;
}
else {
data[dataCt][0] = x;
data[dataCt][1] = y;
dataCt++;
}
}
}
else {
for (int i = 0; i < rows; i++) {
table.setCurrentRowNumber(i+1);
double x = exp1.getVal();
double y = exp2.getVal();
if (Double.isNaN(x) || Double.isNaN(y) || Double.isInfinite(x) || Double.isInfinite(y)) {
if (missingValueIsError)
throw new JCMError("Missing data or undefined expression value for row " + table.getCurrentRowNumber() + " of table.", this);
missingCt++;
}
else {
data[dataCt][0] = x;
data[dataCt][1] = y;
dataCt++;
}
}
}
if (dataCt < data.length) {
double[][] d = new double[dataCt][2];
for (int i = 0; i < dataCt; i++)
d[i] = data[i];
data = d;
}
getRegressionStats();
if (autoChangeLimits)
desiredLimits = computeDesiredLimits();
return desiredLimits;
}
private void getRegressionStats() {
// Compute statistics, based on data in data array.
if (dataCt == 0) {
slope = intercept = correlation = standardError = Double.NaN;
return;
}
boolean allSameX = true,
allSameY = true;
double sumx = data[0][0],
sumy = data[0][1],
sumxy = data[0][0]*data[0][1],
sumx2 = data[0][0]*data[0][0],
sumy2 = data[0][1]*data[0][1];
for (int i = 1; i < dataCt; i++) {
if (data[0][0] != data[i][0])
allSameX = false;
if (data[0][1] != data[i][1])
allSameY = false;
sumx += data[i][0];
sumy += data[i][1];
sumxy += data[i][0] * data[i][1];
sumx2 += data[i][0] * data[i][0];
sumy2 += data[i][1] * data[i][1];
}
double denomx = dataCt * sumx2 - sumx*sumx;
double denomy = dataCt * sumy2 - sumy*sumy;
double numer = dataCt * sumxy - sumx*sumy;
if (allSameX && allSameY) {
slope = 0;
intercept = data[0][1];
correlation = standardError = Double.NaN;
}
else if (allSameX) {
slope = Double.POSITIVE_INFINITY;
intercept = correlation = standardError = Double.NaN;
}
else if (denomx == 0) {
slope = intercept = correlation = standardError = Double.NaN;
}
else {
slope = numer / denomx;
intercept = (sumy - slope * sumx) / dataCt;
if (denomy == 0)
correlation = Double.NaN;
else
correlation = numer / Math.sqrt(denomx*denomy);
if (dataCt <= 2)
standardError = Double.NaN;
else {
double sum = 0;
for (int i = 0; i < dataCt; i++) {
double x = data[i][1] - (slope*data[i][0] + intercept);
sum += x*x;
}
standardError = Math.sqrt(sum/(dataCt-2));
}
}
}
private double[] computeDesiredLimits() {
// Compute desired limits, based on data in data array
if (data.length == 0)
return null;
double xmin=Double.MAX_VALUE, xmax=-Double.MAX_VALUE,
ymin=Double.MAX_VALUE, ymax=-Double.MAX_VALUE;
for (int i = 0; i < dataCt; i++) {
double x = data[i][0];
double y = data[i][1];
if (x > xmax)
xmax = x;
if (x < xmin)
xmin = x;
if (y > ymax)
ymax = y;
if (y < ymin)
ymin = y;
}
if (xmin > 0 && (xmax - xmin) > xmax/2)
xmin = 0;
if (ymin > 0 && (ymax - ymin) > ymax/2)
ymin = 0;
if (ymax < 0)
ymax = 0;
if (xmax < 0)
xmax = 0;
if (xmax == xmin) {
xmax += 1;
xmin -= 1;
}
else {
double spread = (xmax - xmin) / 15;
xmax += spread;
xmin -= spread;
}
if (ymax == ymin) {
ymax += 1;
ymin -= 1;
}
else {
double spread = (ymax - ymin) / 15;
ymax += spread;
ymin -= spread;
}
return new double[] { xmin, xmax, ymin, ymax };
 
}
private boolean needsNewLimits(double[] desiredLimits, CoordinateRect coords) {
// Check if limits should actually be changed; avoid changing them if
// they are close to the desired limits.
double[] limits = new double[] { coords.getXmin(), coords.getXmax(),
coords.getYmin(), coords.getYmax() } ;
return (desiredLimits[0] < limits[0]
|| desiredLimits[1] > limits[1]
|| desiredLimits[2] < limits[2]
|| desiredLimits[3] > limits[3]
|| (limits[1] - limits[0]) > 1.3*(desiredLimits[1] - desiredLimits[0])
|| (limits[3] - limits[2]) > 1.3*(desiredLimits[3] - desiredLimits[2])
|| (limits[1] - limits[0]) < (desiredLimits[1] - desiredLimits[0]) / 1.3
|| (limits[3] - limits[2]) < (desiredLimits[3] - desiredLimits[2]) / 1.3
);
}
private class SPV implements Value {
// Represents one of the value objects that can
// be returned by the getValueObject() method.
private int code; // Which statisitic does this Value represent?
SPV(int code) {
this.code = code;
}
public double getVal() {
checkData();
switch (code) {
case INTERCEPT: return intercept;
case SLOPE: return slope;
case DATACT: return dataCt;
case MISSINGCT: return missingCt;
case STANDARDERROR: return standardError;
default: return correlation;
}
}
}
 
} // end class DataPlot
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/Draggable.java
0,0 → 1,55
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
import java.awt.event.MouseEvent;
 
/**
* An interface that can be implemented by an object that can be dragged
* with the mouse.
*/
public interface Draggable {
 
/**
* Tell the object that a drag operation might be beginning.
* The Draggable object can decide whether it really wants
* to be dragged, based on the MouseEvent. It should return
* true to indicate that a drag should really be started, and
* false if it wants to ignore the MouseEvent.
*/
public boolean startDrag(MouseEvent evt);
/**
* Continue a drag that was started in startDrag(). Presumably
* the event is a mouseDragged event.
*/
public void continueDrag(MouseEvent evt);
/**
* Finish a draw that was started in startDrag(). Presumably
* the event is a mouseReleased event.
*/
public void finishDrag(MouseEvent evt);
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/RiemannSumRects.java
0,0 → 1,418
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import java.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
 
/**
* A RiemannSumRects calculates a Riemann sum for a function. It implements
* Computable and InputObject. You can specify and change the number of
* intervals in the sum, as well as the method used to calculate the sum.
* Functions exist to return Value objects for the sum using different
* computations. This class was written by Gabriel Weinstock, with some
* modifications by David Eck
*/
public class RiemannSumRects extends Drawable implements Computable {
 
private double[] rectHeights;
private int method;
private Color color = new Color(255, 255, 180);
private Color outlineColor = new Color(180,180,0);
private double []endpointVals, maxVals, minVals, midpointVals;
private Value intervalCount;
private Function func, deriv; // derivative is used in max/min computations
 
// store sum data here:
private double[] sum;
private double[] param = new double[1];
private boolean changed = true;
/**
* Summation method type.
*/
public static final int LEFTENDPOINT = 0, RIGHTENDPOINT = 1, MIDPOINT = 2,
CIRCUMSCRIBED = 3, INSCRIBED = 4, TRAPEZOID = 5;
/**
* For use in getValueObject(), to indicate whatever summation method is currently set for drawing.
*/
public static final int CURRENT_METHOD = -1;
/**
* Get the current color used to draw the rectangles
*/
public Color getColor() {
return color;
}
/**
* Set the color used to draw the rectangles. The default color is a light yellow.
*/
public void setColor(Color c) {
if (c != null) {
color = c;
needsRedraw();
}
}
/**
* Set the color that will be used to draw outlines around the rects. If this is null,
* then no outlines are drawn. The default is a medium-dark red that looks brownish next to the default yellow fill color.
*/
public void setOutlineColor(Color c) {
outlineColor = c;
needsRedraw();
}
/**
* Get the color that is used to draw outlines around the rects. If this is null, then
* no outlines are drawn.
*/
public Color getOutlineColor() {
return outlineColor;
}
/**
* Set the function whose Riemann sums are to be computed. If null, nothing is drawn.
* The function, if non-null, must have arity 1, or an IllegalArgumentException is thrown.
*/
public void setFunction(Function func) {
if (func != null && func.getArity() != 1)
throw new IllegalArgumentException("Function for Riemann sums must have arity 1.");
this.func = func;
deriv = (func == null)? null : func.derivative(1);
changed = true;
needsRedraw();
}
/**
* Returns the function whose Riemann sums are computed. Can be null.
*/
public Function getFuction() {
return func;
}
/**
* Set the method used to calculate the rectangles.
* @param m can be: LEFTENDPOINT, RIGHTENDPOINT, MIDPOINT, CIRCUMSCRIBED,
* INSCRIBED or TRAPEZOID (these are integers ranging from 0 to 5,
* respectively)
*/
public void setMethod(int m) {
method = m;
changed = true;
needsRedraw();
}
/**
* Return the current method used to find the rectangle sums
*/
public int getMethod() {
return method;
}
/**
* This is generally called by a Controller. Indicates that all data should be recomputed
* because input values that the data depends on might have changed.
*/
public void compute() {
changed = true;
needsRedraw();
}
/**
* Get the number of intervals used.
* @return a Value object representing the number of intervals
*/
public Value getIntervalCount() {
return intervalCount;
}
/**
* Set the interval count (the RiemannSumRects will be redrawn after this function
* is called). The value will be clamped to be a value between 1 and 5000.
* If the value is null, the default number of intervals, five, is used.
* @param c a Value object representing the interval count
*/
public void setIntervalCount(Value c) {
changed = true;
intervalCount = c;
needsRedraw();
}
/**
* Construct a RiemannSumRects object that initially has nothing to draw and that
* is set up to use the default number of intervals, 5.
*/
public RiemannSumRects() {
this(null,null);
}
 
/**
* Construct a new RiemannSumRects object.
* @param i a Value object representing the number of intervals. If null, five intervals are used.
* @param f a Function object used to derive the Riemann sum. If null, nothing is drawn.
*/
public RiemannSumRects(Function f, Value i) {
intervalCount = i;
func = f;
if (f != null)
deriv = func.derivative(1);
sum = new double[6];
method = LEFTENDPOINT;
}
/**
* Draw the Rieman sum rects. This is generally called by an object of class CoordinateRect
*/
public void draw(Graphics g, boolean coordsChanged) {
if (func == null || coords == null)
return;
if (changed || rectHeights == null || coordsChanged)
setSumData();
int intervals = ((method == 5 || method == 0 || method == 1) ?
(rectHeights.length - 1) : rectHeights.length);
double x = coords.getXmin();
double dx = (coords.getXmax() - x) / intervals;
int zero = coords.yToPixel(0);
g.setColor(color);
if(method == 5) // trapezoids
{
int []xp = new int[4];
int []yp = new int[4];
xp[1] = coords.xToPixel(x);
yp[0] = yp[1] = zero;
yp[2] = coords.yToPixel(rectHeights[0]);
for(int i = 0; i < intervals; i++)
{
x += dx;
xp[0] = xp[3] = xp[1];
xp[1] = xp[2] = coords.xToPixel(x);
yp[3] = yp[2];
yp[2] = coords.yToPixel(rectHeights[i + 1]);
g.fillPolygon(xp, yp, 4);
if (outlineColor != null) {
g.setColor(outlineColor);
g.drawPolygon(xp, yp, 4);
g.setColor(color);
}
}
}
else
{
int left = coords.xToPixel(x);
for(int i = 0; i < intervals; i++) {
int right = coords.xToPixel(x + dx);
int width = right - left + 1;
int top = coords.yToPixel(rectHeights[(method == 1)? i + 1 : i]);
int height = zero - top;
if(height > 0)
g.fillRect(left, top, width, height);
else if(height == 0)
g.drawLine(left, zero, left + width - 1, zero);
else
g.fillRect(left, zero, width, -height);
if (outlineColor != null) {
g.setColor(outlineColor);
if(height > 0)
g.drawRect(left, top, width, height);
else if(height == 0)
g.drawLine(left, zero, left + width - 1, zero);
else
g.drawRect(left, zero, width, -height);
g.setColor(color);
}
x += dx;
left = right;
}
}
}
private void setSumData() {
// Recompute all data.
changed = false;
double intCtD = (intervalCount == null)? 5 : (intervalCount.getVal()+0.5);
if (Double.isNaN(intCtD) || Double.isInfinite(intCtD))
intCtD = 5;
else if (intCtD < 0)
intCtD = 1;
else if (intCtD > 5000)
intCtD = 5000;
int intCt = (int)intCtD;
endpointVals = new double[intCt + 1];
maxVals = new double[intCt];
minVals = new double[intCt];
midpointVals = new double[intCt];
double x = coords.getXmin();
double dx = (coords.getXmax() - x) / intCt;
param[0] = x;
endpointVals[0] = func.getVal(param);
int ptsPerInterval = 200 / intCt;
double smalldx;
if(ptsPerInterval < 1)
{
ptsPerInterval = 1;
smalldx = dx;
}
else
smalldx = dx / ptsPerInterval;
 
boolean increasingleft;
boolean increasingright = deriv.getVal(param) > 0;
 
for(int i = 1; i <= intCt; i++)
{
x += dx;
param[0] = x;
endpointVals[i] = func.getVal(param);
param[0] = x - dx / 2;
midpointVals[i - 1] = func.getVal(param);
// maxmin stuff
double max, min;
max = min = endpointVals[i - 1];
for(int j = 1; j <= ptsPerInterval; j++) // looking for turning points in the interval
{
increasingleft = increasingright;
double xright = (x - dx) + j * smalldx;
param[0] = xright;
increasingright = deriv.getVal(param) > 0;
if(increasingleft != increasingright)
{
if(increasingleft)
{
double z = searchMax(xright - smalldx, xright, 1);
if(z > max)
max = z;
}
else
{
double z = searchMin(xright - smalldx, xright, 1);
if (z < min)
min = z;
}
}
}
if(endpointVals[i] > max)
max = endpointVals[i];
else if(endpointVals[i] < min)
min = endpointVals[i];
minVals[i - 1] = min;
maxVals[i - 1] = max;
}
double y = endpointVals[0];
double leftsum = 0, midpointsum = 0, rightsum = 0, maxsum = 0, minsum = 0;
for(int i = 0; i < intCt; i++)
{
leftsum += endpointVals[i];
midpointsum += midpointVals[i];
maxsum += maxVals[i];
minsum += minVals[i];
}
rightsum = leftsum - endpointVals[0] + endpointVals[intCt];
// calculate sums
sum[LEFTENDPOINT] = leftsum * dx;
sum[RIGHTENDPOINT] = rightsum * dx;
sum[MIDPOINT] = midpointsum * dx;
sum[CIRCUMSCRIBED] = maxsum * dx;
sum[INSCRIBED] = minsum * dx;
sum[TRAPEZOID] = (leftsum + rightsum) / 2 * dx;
setRectData();
}
private void setRectData() {
if (method == 3)
setRectHeights(maxVals);
else if(method == 4)
setRectHeights(minVals);
else if (method == 2)
setRectHeights(midpointVals);
else
setRectHeights(endpointVals);
}
 
private void setRectHeights(double[] e) {
rectHeights = e;
changed = true;
}
private double searchMin(double x1, double x2, int depth) {
// find an approximate minimum of func in the interval (x1,x2)
double mid = (x1 + x2) / 2;
param[0] = mid;
if(depth >= 13)
return func.getVal(param);
double slope = deriv.getVal(param);
if(slope < 0)
return searchMin(mid, x2, depth + 1);
else
return searchMin(x1, mid, depth + 1);
}
private double searchMax(double x1, double x2, int depth) {
// find an approximate maximum of func in the interval (x1,x2)
double mid = (x1 + x2) / 2;
param[0] = mid;
if(depth >= 13)
return func.getVal(param);
double slope = deriv.getVal(param);
if(slope > 0)
return searchMin(mid, x2, depth + 1);
else
return searchMin(x1, mid, depth + 1);
}
/**
* Gets a Value object that gives the value of the Riemann sum for the specified method.
* @return a Value object representing the sum for the given method
* @param which integer stating the method used to derive the sum; one of the
* constants LEFTENDPOINT, RIGHTENDPOINT, MIDPOINT,
* CIRCUMSCRIBED, INSCRIBED, TRAPEZOID, or CURRENT_METHOD.
*/
public Value getValueObject(final int which) {
return new Value() {
public double getVal() {
if (func == null || coords == null)
return Double.NaN;
if (changed)
setSumData();
if (which == CURRENT_METHOD)
return sum[method];
else
return sum[which];
}
};
}
} // end class RiemannSumRects
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/Drawable.java
0,0 → 1,125
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.draw;
 
import java.awt.Graphics;
 
/**
* A Drawable object can be added to a CoordinateRect, which is itself in
* a DisplayCanvas. Its purpose is, generally, to draw something in the
* rectangular area represented by the CoordinateRect. The drawing can
* use information in the CoordinateRect, which includes both the real
* number coordinates and the pixel coordinates of the rectangular area.
*/
abstract public class Drawable implements java.io.Serializable {
/**
* The CoordinateRect for the rectagular area where this
* Drawable is drawn. This is set automatically when the
* Drawable is added to a CoordingteRect and should not be
* changed. (It will be changed automatically if the
* Drawable is removed from the CoordinateRect.)
*/
protected CoordinateRect coords;
 
/**
* The canvas on which this Drawable is drawn. This is set
* automatically when the Drawable is added to a CoordinateRect
* and it should not be changed. (It will be changed automatically
* if the Drawable is removed from the CoordinateRect.)
*/
protected DisplayCanvas canvas;
private boolean visible = true; // If visible is false, then the CoordinateRect
// that manages this Drawable will ignore it.
// It will not call the draw() routine, so when
// draw is called, it can be assumed that the
// Drawable is visible.
/**
* Draw this drawable in the graphics context g. This is meant to
* be called only by the CoordinateRect, coords, that manages this Drawable.
* The coords contains information about the rectangular area in which
* this Drawable is displayed, both in terms of pixels and in terms
* of real (x,y)-coordinates.
* The value of coordsChanged is true if any of the values
* coords.getXmin(), coords.getXmax(), coords.getYmin(), coords.getYmax(),
* coords.getLeft(), coords.getRight(), coords.getTop(), coords.getBottom(),
* or coords.getGap() has changed. Drawables that depend only on this
* information can check the value of coordsChanged to see whether they
* need to update any previously computed member variables that
* depend on these values. This method is meant to be called only by the system.
*
* @param g The graphics context in which the Drawble is to be drawn. (The drawing
* can change the color in g, but should not permanently change font, painting mode, etc.
* Thus, every drawable is responsible for setting the color it wants to use.)
* @param coordsChanged Indicates whether the CoordinateRect has changed.
*/
abstract public void draw(Graphics g, boolean coordsChanged);
 
/**
* Return true if this Drawable is visible, false if it is hidden.
* A hidden Drawable is ignored by the CoordinateRect that manages it.
*/
public boolean getVisible() {
return visible;
}
/**
* Set the visibility of this Drawable. If show is false, then
* the Drawable is hidden. If it is true, the Drawable is shown.
*/
public void setVisible(boolean show) {
if (show != visible) {
visible = show;
needsRedraw();
}
}
 
/**
* This routine should be called if the appearance of the Drawable changes
* so that the rectangular area that it occupies has to be redrawn.
* The routine is generally meant to be called by the Drawable itself.
* It will notify the DisplayCanvas, canvas, that the CoordinateRect,
* coords, needs to be redrawn, where canvas and coords are the member
* variables in this class. If canvas is null, nothing happens, since
* presumably the Drawable is not displayed anywhere in that case.
*/
public void needsRedraw() {
if (canvas != null)
canvas.doRedraw(coords);
}
/**
* Sets the values of member variables canvas and coords. This is
* designed to be called only by the CoordinateRect class.
*/
protected void setOwnerData(DisplayCanvas canvas, CoordinateRect coords) {
this.canvas = canvas;
this.coords = coords;
}
} // end class Drawable
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/DraggablePoint.java
0,0 → 1,499
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.draw;
 
import java.awt.*;
import java.awt.event.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
 
/**
* A DraggablePoint can be added to a DisplayCanvas, where it appears as a small disk, square, or
* cross. (The visual style is a settable property.) This object can be dragged with the mouse,
* within the limits of the CoordinateRect that contains the DraggablePoint. Either the x- or
* y-value of the point can be clamped to a specified Value. Typically, the y-value might
* be given by some function of the x-value. In that case, the point is constrained to move
* along the graph of the function. Or the x- or y-value can be clamped to a constant to make
* the point move along a vertical or horizontal line. Two Variables are associated with
* the DraggablePoint. These Variables represent the x- and y- values of the point. Each Variable
* implements the Tieable interface, so it can be synchronized with other Tieable values such as
* a VariableIput or VariableSlider.
*/
 
public class DraggablePoint extends Drawable implements InputObject, Draggable {
 
/**
* A style constant that specifies the visual appearance of a DraggablePoint to be a disk.
*/
public static final int DISK = 0;
 
/**
* A style constant that specifies the visual appearance of a DraggablePoint to be a square.
*/
public static final int SQUARE = 1;
 
/**
* A style constant that specifies the visual appearance of a DraggablePoint to be a cross.
*/
public static final int CROSS = 2;
 
private int radius; // Radius of the point.
private Color color; // Color of the point.
private Color ghostColor; // Color used for point when it is undefined or outside the CoordinateRect.
private int style; // One of the above style constants, DISK by default.
private double xLoc, yLoc; // The current x- and y-values of the point.
private int xPosition, yPosition; // The pixel position of the point.
private boolean useGhost; // This is true if the point is a "ghost" (undefined or outside the CoordinateRect).
private DPV xVar, yVar; // The Variables that represent the x- and y-values; DPV is a private nested class, defined below.
private Controller onUserAction; // A Controller whose compute method is called when the user drags the point.
private Value clampX, clampY; // Values used to clamp the x- and y-values. Only one can be non-null.
 
/**
* Create a DraggablePoint with default values for style, radius, color. The point appears as a dark gray disk of radius 4.
*/
public DraggablePoint() {
this(DISK);
}
/**
* Create a DraggablePoint with specified visual style. Radius is 4, color is darkGray, and
* ghostColor is lightGray.
*
* @param style One of the style constants DraggablePoint.DISK, DraggablePoint.SQUARE, or DraggablePoint.CROSS.
*/
public DraggablePoint(int style) {
if (style >= 0 && style <= 2)
this.style = style;
setColor(Color.darkGray);
setGhostColor(Color.lightGray);
radius = 4;
xPosition = -10000;
xLoc = Double.NaN;
yLoc = Double.NaN;
xVar = new DPV(true);
yVar = new DPV(false);
}
/**
* Clamp the x-value of the point to v. That is, if v is not null, then whenever the location of the point
* changes, its x-value is modified to v.getVal(). Note that if v is non-null then any clamp Value
* specified for y will be cleared since x and y cannot both be clamped.
*/
public void clampX(Value v) {
clampX = v;
if (v != null)
clampY = null;
checkClamp();
needsRedraw();
}
/**
* Clamp the y-value of the point to v. That is, if v is not null, then whenever the location of the point
* changes, its y-value is modified to v.getVal(). Note that if v is non-null then any clamp Value
* specified for x will be cleared since x and y cannot both be clamped.
*/
public void clampY(Value v) {
clampY = v;
if (v != null)
clampX = null;
checkClamp();
needsRedraw();
}
/**
* Clamp the x-value of the point to the constant x, so that the point is constrained to a vertical line.
*/
public void clampX(double x) {
clampX(new Constant(x));
}
/**
* Clamp the y-value of the point to the constant y, so that the point is constrained to a horizontal line.
*/
public void clampY(double y) {
clampY(new Constant(y));
}
/**
* Clamp the x-value of the point to the function f, so that the point is constrained to move along the graph of x = f(y).
* f must be a function of one variable.
*/
public void clampX(Function f) {
if (f != null)
clampX(new ValueMath(f,xVar));
}
/**
* Clamp the y-value of the point to the function f, so that the point is constrained to move along the graph of y = f(x).
* f must be a function of one variable.
*/
public void clampY(Function f) {
if (f != null)
clampY(new ValueMath(f,xVar));
}
/**
* Get the radius used for drawing the point. The point's height and width are given by two times the radius.
*/
public int getRadius() {
return radius;
}
/**
* Set the radius that determines the size of the point when it is drawn.
* The point's height and width are given by two times the radius.
*/
public void setRadius(int r) {
if (r > 0) {
radius = r;
needsRedraw();
}
}
/**
* Set the visual style of the point. The style should be one of the constants
* DraggablePoint.DISK, DraggablePoint.SQUARE, or DraggablePoint.CROSS. If it is not,
* then nothing is done.
*/
public void setStyle(int style) {
if (style >= 0 && style <= 2) {
this.style = style;
needsRedraw();
}
}
/**
* Get the visual style of the point, which must be one of the constants
* DraggablePoint.DISK, DraggablePoint.SQUARE, or DraggablePoint.CROSS.
*/
public int getStyle() {
return style;
}
/**
* Get the variable that represents the current x-value of the point. (Note that this
* variable can be type-cast to type Tieable.)
*/
public Variable getXVar() {
return xVar;
}
/**
* Get the variable that represents the current y-value of the point. (Note that this
* variable can be type-cast to type Tieable.)
*/
public Variable getYVar() {
return yVar;
}
/**
* Get the color used for drawing the point.
*/
public Color getColor() {
return color;
}
/**
* Set the color to be used for drawing the point. If the specified Color value is
* null, then nothing is done.
*/
public void setColor(Color c) {
if (c != null) {
color = c;
needsRedraw();
}
}
/**
* Get the "ghostColor" of the point. This color is used for drawing the point when its x-value
* or y-value is undefined or outside the range of values on the CoordinateRect that contains
* the point. (This can happen because of clamping of values. It can also happen if the limits
* on the CoordinateRect are changed.)
*/
public Color getGhostColor() {
return ghostColor;
}
/**
* Set the ghoseColor to be used for drawing the point when it location is undefined or is outside the
* proper limits. If the specified Color value is null, then nothing is done.
*/
public void setGhostColor(Color c) {
if (c != null) {
ghostColor = c;
needsRedraw();
}
}
/**
* Set the Controller that is to be notified when the user drags the point. (The compute() method
* of the Controller is called.) If the Controller value is null, then no notification is done.
*/
public void setOnUserAction(Controller c) {
onUserAction = c;
}
/**
* Method required by InputObject interface; in this class, it simply calls
* setOnUserAction(c). This is meant to be called by JCMPanel.gatherInputs().
*/
public void notifyControllerOnChange(Controller c) {
setOnUserAction(c);
}
 
/**
* Get the Controller that is notified when the user drags the point. A null value means that
* no notification is done.
*/
public Controller getOnUserAction(Controller c) {
return onUserAction;
}
/**
* Move the point to (x,y), then "clamp" the value of x or y, if a clamp Value has been set.
*/
public void setLocation(double x, double y) {
xLoc = x;
yLoc = y;
xVar.setVariableValue(x);
yVar.setVariableValue(y);
xVar.serialNumber++;
yVar.serialNumber++;
checkClamp();
needsRedraw();
}
private void checkClamp() {
// Apply the clamping values.
if (clampX != null) {
xLoc = clampX.getVal();
xVar.setVariableValue(xLoc);
}
else if (clampY != null) {
yLoc = clampY.getVal();
yVar.setVariableValue(yLoc);
}
}
 
/**
* This method is required by the InputObject interface. In this case, it just applies the
* clamping Values if any are specified.
*/
public void checkInput() {
xVar.needsClamp = true;
yVar.needsClamp = true;
}
/**
* This method, from the Drawable interface, draws the point. It is not usually called directly.
*/
public void draw(Graphics g, boolean coordsChanged) {
if (coords == null)
return;
checkPosition();
if (useGhost)
g.setColor(getGhostColor());
else
g.setColor(color);
switch (style) {
case DISK:
g.fillOval(xPosition-radius,yPosition-radius,2*radius+1,2*radius+1);
break;
case SQUARE:
g.fillRect(xPosition-radius,yPosition-radius,2*radius+1,2*radius+1);
break;
case CROSS:
g.drawLine(xPosition-radius,yPosition,xPosition+radius,yPosition);
g.drawLine(xPosition,yPosition-radius,xPosition,yPosition+radius);
break;
}
}
private void checkPosition() {
// compute (xPosition, yPosition), the position where point is actually drawn
useGhost = false;
xVar.getVal(); // Forces recompute, if needsClamp
yVar.getVal();
if (Double.isNaN(xLoc) || Double.isNaN(yLoc)) {
if (xPosition == -10000) { // otherwise, use previous position
xPosition = coords.getLeft() + coords.getWidth()/2;
yPosition = coords.getTop() + coords.getHeight()/2;
}
useGhost = true;
}
else {
xPosition = coords.xToPixel(xLoc);
yPosition = coords.yToPixel(yLoc);
}
if (xPosition <= coords.getLeft()) {
useGhost = true;
xPosition = coords.getLeft() + 1;
}
else if (xPosition >= coords.getLeft() + coords.getWidth()) {
useGhost = true;
xPosition = coords.getLeft() + coords.getWidth() - 1;
}
if (yPosition <= coords.getTop()) {
useGhost = true;
yPosition = coords.getTop() + 1;
}
else if (yPosition >= coords.getTop() + coords.getHeight()) {
useGhost = true;
yPosition = coords.getTop() + coords.getHeight() - 1;
}
}
//------------------ Dragging the point ---------------------------
private boolean dragging; // True if the point is being dragged.
/**
* Check whether a mouse click (as specified in the MouseEvent parameter) is a
* click on this DraggablePoint. If so, return true, and start a drag operation.
* It is expected that the continueDrag() and finishDrag() will be called to
* complete the drag operation. This is only meant to be called from
* the checkDraggables() method in class CoordinateRect.
*/
public boolean startDrag(MouseEvent evt) {
dragging = false;
if (evt.isConsumed() || !getVisible() || coords == null)
return false;
checkPosition();
if (evt.getX() < xPosition - radius || evt.getX() >= xPosition + radius
|| evt.getY() < yPosition - radius || evt.getY() >= yPosition + radius)
return false;
dragging = true;
evt.consume();
return true;
}
/**
* Continue a drag operation begun in startDrag(). This is not meant to be called directly.
*/
public void continueDrag(MouseEvent evt) {
if (!dragging)
return;
int xInt = evt.getX();
int yInt = evt.getY();
double x = coords.pixelToX(evt.getX());
double y = coords.pixelToY(evt.getY());
if (x < coords.getXmin())
x = coords.getXmin();
else if (x > coords.getXmax())
x = coords.getXmax();
if (y < coords.getYmin())
y = coords.getYmin();
else if (y > coords.getYmax())
y = coords.getYmax();
setLocation(x,y);
if (Double.isNaN(xLoc) || Double.isNaN(yLoc)) {
xPosition = xInt;
yPosition = yInt;
}
if (onUserAction != null)
onUserAction.compute();
}
/**
* Finish a drag operation begun in startDrag(). This is not meant to be called directly.
*/
public void finishDrag(MouseEvent evt) {
dragging = false;
}
private class DPV extends Variable implements Tieable {
private boolean isXVar; // True for xVar; false for yVar.
long serialNumber; // This object's serial number.
boolean needsClamp; // Set to true by DraggablePoint().checkInput().
DPV(boolean isXVar) {
// Create the variable.
super(isXVar? "xDrag" : "yDrag");
this.isXVar = isXVar;
super.setVal(Double.NaN);
}
public double getVal() {
// Return the value, after applying clamping, if necessary.
// (It's done this way because checkInput() can't use values of
// other objects, but after it's called, any call to getVal()
// should return the new correct value.)
if (needsClamp) {
if (isXVar) {
if (clampX != null) {
xLoc = clampX.getVal();
setVariableValue(xLoc);
}
}
else {
if (clampY != null) {
yLoc = clampY.getVal();
setVariableValue(yLoc);
}
}
needsClamp = false;
}
return super.getVal();
}
 
public void setVal(double val) {
// Set the value of the variable, and set the point's
// location to reflect new value. (setLocation ups serial number
// and calls setVariableValue() to set the actual variable value.)
if (isXVar)
setLocation(val,yVar.getVal());
else
setLocation(xVar.getVal(),val);
}
void setVariableValue(double val) {
// Call the setVal() routine from the superclass.
super.setVal(val);
needsClamp = false;
}
public long getSerialNumber() {
// Return this Tieable object's serial number.
return serialNumber;
}
public void sync(Tie tie, Tieable newest) {
// Synchronize values and serial numbers with newest.
if ( ! (newest instanceof Value) )
throw new IllegalArgumentException("Internal Error: A MouseTracker variable can only be tied to a Value object.");
if (newest != this) {
setVal(((Value)newest).getVal());
serialNumber = newest.getSerialNumber();
}
}
}
 
} // end class DraggablePoint
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/DrawTemp.java
0,0 → 1,46
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import java.awt.Graphics;
 
/**
* An object that implements this interface can draw itself, using information
* from a CoordinateRect (in which it presumably appears). This interface is
* meant to be used with the method drawTemp() in edu.hws.jcm.draw.DisplayCanvas.
*/
public interface DrawTemp extends java.io.Serializable {
 
/**
* Draw this item in the specified graphics context, possibly using information
* from the specified CoordinateRect. Note that the drawTemp() method
* in class DisplayCanvas creates a new graphics context every time it
* is called, just for drawing this item.
*/
public void draw(Graphics g, CoordinateRect coords);
 
}
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/Panner.java
0,0 → 1,231
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import java.awt.*;
import java.awt.event.*;
import edu.hws.jcm.awt.Controller;
 
 
/**
* When a Panner object is added to a CoordinateRect, it becomes possible to
* "grab" the coordinate rectangle and pan it (that is, slide it around by
* moving it with the mouse). By default, the user must right-click-and-drag
* to pan the coordinates, but this can be changed by providing an argument to
* the constructor. It is possible to set a Controller to be notified each time
* the mouse moves while the user is dragging. Alternatively, or in addition,
* you can set a Controller to be notified when the user finishes dragging.
* However, for the most part this is unnecessary, since the Drawables in the
* CoordinateRect will for the most part redraw themselves properly when the
* limits on the CoordinateRect change. However, if you have Computable objects
* that depend on the coordinate limits, then they will need to be recomputed.
* (This will be the case if you use value objects returned by the
* getValueObject() method in the CoordinateRect class.)
* <p>A Panner, p, is inactive if its "visible" property has been set to false.
* (This is done by calling p.setVisible(false).)
*/
public class Panner extends Drawable implements MouseListener, MouseMotionListener {
 
private int modifiers; // Combination of MouseEvent.SHIFT_MASK, MouseEvent.CTRL_MASK,
// MouseEvent.META_MASK, and MouseEvent.ALT_MASK that must be
// present in the mouse-pressed event for a drag to start.
private Controller onUserAction; // notified each time the mouse moves during a drag
private Controller onFinishDrag; // notified when the user finishes a drag
/**
* Create a Panner object that will let the user pan the CoordinateRect
* that contains the Panner by
* right-clicking and dragging (or, on Macintosh, command-clicking).
*/
public Panner() {
this(MouseEvent.META_MASK);
}
/**
* Create a Panner object that will let the user click-and-drag to pan the CoordinateRect
* that contains the Panner. The mouse-pressed event must have the specfied set of
* modifiers set.
*
* @param modifiers If the value is zero, the user drags the CoordinateRect by clicking without
* pressing any modifier keys. Otherwise, the value should be a combination of
* one or more of the constants MouseEvent.SHIFT_MASK, MouseEvent.CTRL_MASK,
* MouseEvent.META_MASK, and MouseEvent.ALT_MASK, or'ed together. (Remember
* that right-clicking sets META_MASK and clicking with a middle mouse button
* sets ALT_MASK.)
*
*/
public Panner(int modifierSet) {
modifiers = modifierSet & (MouseEvent.SHIFT_MASK | MouseEvent.CTRL_MASK
| MouseEvent.META_MASK | MouseEvent.ALT_MASK);
}
/**
* Set a Controller that will be notified (by calling its compute method) whenever
* the user moves the mouse during a drag. If the value is null, no Controller is
* notified. Note that Drawables generally redraw themselvs correctly during the
* drag anyway, without any Controller being involved. Even if there are other
* things that need to be computed, it's probably better to compute them only once
* at the end of the drag. Do this by calling setOnFinishDrag() instead of this method.
*/
public void setOnUserAction(Controller c) {
onUserAction = c;
}
/**
* Get the Controller that is notified when the user moves the mouse during a drag.
* Returns null if no Controller is notified.
*/
public Controller getOnUserAction() {
return onUserAction;
}
/**
* Set a Controller that will be notified (by calling its compute method) whenever
* the user finishes a drag operation. If the value is null, no Controller is notified.
* You only need to do this if you have to recompute some object that depends on the
* coordinate limits of the CoordinateRect that contains this Panner object.
* Presumably, this will be an object that depends on one if the Value objects returned
* by the getValueObject() method in the CoordinatRect class.
*/
public void setOnFinishDrag(Controller c) {
onFinishDrag = c;
}
/**
* Get the Controller that is notified when the user finishs a drag.
* Returns null if no Controller is notified.
*/
public Controller getOnFinishDrag() {
return onFinishDrag;
}
/**
* Called when this object is added to a DisplayCanvas. Not meant to be called directly.
*/
protected void setOwnerData(DisplayCanvas canvas, CoordinateRect coords) {
// Called automatically when this object is added to canvas.
if (canvas != null) {
canvas.removeMouseListener(this);
canvas.removeMouseMotionListener(this);
}
super.setOwnerData(canvas,coords);
if (canvas != null) {
canvas.addMouseListener(this);
canvas.addMouseMotionListener(this);
}
}
 
/**
* Override the abstract draw() method from the Drawable class. This
* is defined to be empty since a Panner object has no visible representation.
*/
public void draw(Graphics g, boolean coordsChanged) {
}
private boolean dragging;
private int prevX, prevY;
 
/**
* Responds to a mouse-press. Not meant to be called directly.
*/
public void mousePressed(MouseEvent evt) {
dragging = false;
if (evt.isConsumed())
return;
if (!getVisible() || canvas == null || coords == null)
return;
if ( (evt.getModifiers() & modifiers) != modifiers )
return;
prevX = evt.getX();
prevY = evt.getY();
if (prevX < coords.getLeft() || prevX >= coords.getLeft() + coords.getWidth()
|| prevY < coords.getTop() || prevY >= coords.getTop() + coords.getHeight())
return;
evt.consume();
dragging = true;
}
 
/**
* Responds to a mouse-drag. Not meant to be called directly.
*/
public void mouseDragged(MouseEvent evt) {
if (!dragging)
return;
evt.consume();
if (evt.getX() == prevX && evt.getY() == prevY)
return;
double[] limits = coords.getLimits();
if (limits == null)
return;
double xOffset = (evt.getX() - prevX) * coords.getPixelWidth();
double yOffset = (evt.getY() - prevY) * coords.getPixelHeight();
coords.setLimits(limits[0] - xOffset, limits[1] - xOffset, limits[2] + yOffset, limits[3] + yOffset);
needsRedraw();
if (onUserAction != null)
onUserAction.compute();
prevX = evt.getX();
prevY = evt.getY();
}
 
/**
* Responds to a mouse-release. Not meant to be called directly.
*/
public void mouseReleased(MouseEvent evt) {
if (!dragging)
return;
evt.consume();
mouseDragged(evt);
dragging = false;
if (onFinishDrag != null)
onFinishDrag.compute();
}
/**
* Responds to a mouse-click. Not meant to be called directly.
* Defined to be empty in this class.
*/
public void mouseClicked(MouseEvent evt) { }
/**
* Responds when mouse moves. Not meant to be called directly.
* Defined to be empty in this class.
*/
public void mouseMoved(MouseEvent evt) { }
/**
* Responds to a mouse-enter event. Not meant to be called directly.
* Defined to be empty in this class.
*/
public void mouseEntered(MouseEvent evt) { }
 
/**
* Responds to a mouse-exit event. Not meant to be called directly.
* Defined to be empty in this class.
*/
public void mouseExited(MouseEvent evt) { }
 
} // end class Panner
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/DrawString.java
0,0 → 1,712
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
package edu.hws.jcm.draw;
 
import java.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
import java.util.StringTokenizer;
 
/**
* A DrawString object displays a string, possibly multi-line, in a DisplayCanvas,
* inside the rectangular region of a CoordinateRect. The location of the string
* can be specified in two ways. First, by giving the coordinates of a reference
* point together with a constant that says how the string is positioned with
* respect to that reference point. The coordintes are given as Value objects
* and the values are interepreted in the coordinate system of the CoordinateRect.
* The positioning object is one of the constants TOP_LEFT, TOP_CENTER, ...,
* BOTTOM_RIGHT defined in this class. This says where the REFERENCE POINT
* is -- at the top left of the string, at the top center, etc.
* <p>The second way to specify the position of the string is to set the reference
* point coordinates to null. In that case, the postioning constant gives
* the location of the STRING in the CorrdinateRect. A value of TOP_LEFT
* says that the string is in the top left corner of the rect, etc.
*
* <p>An array of Value objects can be specified to be displayed in the string.
* Their values are substituted for #'s in the string. (A double # in the string,
* however, is displayed as a literal single #.)
*
* <p>It is possible to set the color, font and justification of the string.
*
* <p>A DisplayString implements the Computable interface, so it can be added to
* a Controller. The values of the Value objects used by the string are recomputed
* only when its compute() method is called.
*/
 
public class DrawString extends Drawable implements Computable {
 
/**
* Specify string location in rect
*/
public static final int TOP_LEFT = 4*0 + 0,
TOP_CENTER = 4*0 + 1,
//value/4 gives vertical position
TOP_RIGHT = 4*0 + 2,
// value%4 gives horizontal position
CENTER_LEFT = 4*1 + 0,
CENTER_CENTER = 4*1 + 1,
CENTER_RIGHT = 4*1 + 2,
BOTTOM_LEFT = 4*2 + 0,
BOTTOM_CENTER = 4*2 + 1,
BOTTOM_RIGHT = 4*2 + 2;
 
/**
* For specifying justification of lines in multiline strings.
* (But can also be used as a synonym for CENTER_CENTER to specify the position of the string).
*/
public static final int CENTER = CENTER_CENTER;
 
/**
* For specifying justification of lines in multiline strings.
* (But can also be used as a synonym for TOP_LEFT to specify the position of the string).
*/
public static final int LEFT = TOP_LEFT;
 
/**
* For specifying justification of lines in multiline strings.
* (But can also be used as a synonym for TOP_RIGHT to specify the position of the string).
*/
public static final int RIGHT = TOP_RIGHT;
 
/**
* one of the constants defined in this class for specifying position
*/
protected int position;
/**
* String, possibly with \n and #'s. This is used as a base to get the actual string that is drawn.
*/
protected String baseString;
/**
* The actual lines to draw, derived from baseString.
*/
protected String[] strings;
/**
* Values to be substituted for #'s in the baseString.
*/
protected Value[] values;
/**
* xy-coords for drawing the string. If non-null then relative positioning is used.
* If null, then positioning is absolute.
*/
protected Value xPos,yPos;
/**
* Color of string. If null, black is used as the default.
*/
protected Color color;
/**
* Font for drawing string. If null, get font from graphics context.
*/
protected Font font;
/**
* If absolute positioning is used, then this gives a gap between the string and edge of rect.
* For relative positioning, this gives an offset from the value of xPos yPos.
*/
protected int offset = 3;
/**
* If true, the string is clamped to lie within the CoordinateRect.
*/
protected boolean clamp = true;
/**
* Left, right, or center justification of lines in the text.
*/
protected int justification = LEFT;
/**
* Maximum number of characters desired in numbers; actual number might actually be larger.
*/
protected int numSize = 10;
 
/**
* If backgroundColor is non-null, then a rectangle of this color is filled
* as a background for the string;
*/
protected Color backgroundColor;
/**
* If frameWidth is greater than zero, then a frame of this width is drawn around the
* string in the color given by frameColor.
*/
protected int frameWidth;
/**
* If frameWidth is greate than zero, then a frame is drawn around the string in this
* color. If the value is null, then the color will be the same as the color of the string.
*/
protected Color frameColor;
 
// In the following, note that str can contain \n to break up the
// string into multiple lines.
private double xRef,yRef; //Coordinates of reference point where string is drawn.
private boolean changed = true; // set to true when strings need to be recomputed
/**
* Create a DrawString object that initially has no string to draw.
*/
public DrawString() {
this(null,TOP_LEFT,(Value[])null);
}
/**
* Create a DrawString for drawing a black string in the top left corner of the coordinate rect.
*
* @param str The string to draw, which can contain \n's to indicate line breaks.
*/
public DrawString(String str) {
this(str,TOP_LEFT,(Value[])null);
}
/**
* Create a DrawString for drawing a black string in the position specified.
*
* @param str The string to draw, which can contain \n's to indicate line breaks.
* @param pos The positioning of the string in the coordinate rect. One of the positioning constants such as TOP_LEFT or BOTTOM_RIGHT.
*/
public DrawString(String str, int pos) {
this(str,pos,(Value[])null);
}
/**
* Create a DrawString for drawing a black string in the specified position.
* The number of #'s in the string should match values.length. The values
* are computed and substituted for the #'s.
*
* @param str The string to draw, which can contain \n's to indicate line breaks and #'s to be replaced by numeric values.
* @param pos The positioning of the string in the coordinate rect. One of the positioning constants such as TOP_LEFT or BOTTOM_RIGHT.
* @param values Value objects associated with #'s in the string.
*/
public DrawString(String str, int pos, Value[] values) {
position = pos;
this.values = values;
setString(str);
}
/**
* Create a string that is displayed at the reference point (xPos,yPos);
* The positioning constant, pos, gives the positioning relative to this point, if xPos or yPos is non-null.
*
* @param str The string to draw, which can contain \n's to indicate line breaks and #'s to be replaced by numeric values.
* @param pos The positioning of the string. One of the positioning constants such as TOP_LEFT or BOTTOM_RIGHT.
If xPos or yPos is non-nul, this is interpreted relative to their values.
* @param xPos x-coordinate relative to which the string is drawn (or null for absolute hoizontal positioning).
* @param yPos y-coordinate relative to which the string is drawn (or null for absolute vertical positioning).
* @param values Value objects associated with #'s in the string.
*/
public DrawString(String str, int pos, Value xPos, Value yPos, Value[] values) {
setReferencePoint(xPos,yPos);
position = pos;
this.values = values;
setString(str);
}
/**
* Set the color for the string. If c is null, Color.black is used.
*
*/
public void setColor(Color c) {
color = c;
needsRedraw();
}
/**
* Get the non-null color that is used for drawing the string.
*
*/
public Color getColor() {
return (color == null)? Color.black : color;
}
/**
* Set the font that is used for drawing this string. If f is null,
* then the font is obtained from the Graphics context in which the
* string is drawn.
*
*/
public void setFont(Font f) {
font = f;
needsRedraw();
}
/**
* Return the font that is used for drawing the string. If the return
* value is null, then the font is taken from the Graphics context.
*
*/
public Font getFont() {
return font;
}
/**
* Set the Values that are substituted for (single) #'s in the string.
* If the array of Values is null, then no substitution is done. The length of the array should match
* the number of #'s, but it is not an error if they do not match.
* Extra values will be ignored; extra #'s will be shown as "undefined".
*
*/
public void setValues(Value[] v) {
values = v;
changed = true;
needsRedraw();
}
/**
* Return the array of values that are substituted for #'s in the string.
*
*/
public Value[] getValues() {
return values;
}
/**
* Set the positioning of the string. The parameter should be one of the positioning
* contstants defined in this class, such as TOP_LEFT. (If it is not,
* TOP_LEFT is used by default.)
*
*/
public void setPositioning(int pos) {
position = pos;
needsRedraw();
}
/**
* Return the positioning, as set by setPositioning().
*
*/
public int getPositioning() {
return position;
}
/**
* Set the values of the (x,y) coordinates of the
* reference point for the stirng. If a value is null,
* absolute positioning is used. If a value is
* undefined, the string is not drawn.
*
*/
public void setReferencePoint(Value x, Value y) {
xPos = x;
yPos = y;
try {
if (xPos != null)
xRef = xPos.getVal();
if (yPos != null)
yRef = yPos.getVal();
}
catch (RuntimeException e) {
}
needsRedraw();
}
/**
* Return the Value object that gives the x-coordinate of the reference
* point of this string.
*
*/
public Value getXPos() {
return xPos;
}
/**
* Return the Value object that gives the y-coordinate of the reference
* point of this string.point of this string.
*
*/
public Value getYPos() {
return yPos;
}
/**
* Set the string that is displayed. Note that it can include '\n' to
* represent a line break, and it can contain #'s which will be replaced
* by computed values.
*
*/
public void setString(String str) {
baseString = str;
strings = null;
changed = true;
needsRedraw();
}
/**
* Get a copy of the display string (with \n's #'s, not with substitued values.)
*
*/
public String getString() {
return baseString;
}
/**
* Set the distance of the bounding box of the string from the reference
* point where it is drawn. The default value is 3.
*
*/
public void setOffset(int b) {
offset = b;
needsRedraw();
}
/**
* Get the distance of the bounding box of the string from the reference
* point where it is drawn.
*
*/
public int getOffset() {
return offset;
}
/**
* Set the "clamp" property of the DrawString.
* If set to true, the string will be clamped to lie entirely within the CoordinateRect
* (unless it doens't fit -- then it can stick out on the right and bottom).
* The default value is true.
*
*/
public void setClamp(boolean clamp) {
this.clamp = clamp;
needsRedraw();
}
/**
* Returns true if the string is set to be clamped to lie within the CoordinateRect.
*
*/
public boolean getClamp() {
return clamp;
}
/**
* Set the justification to be used if there are multiple lins in the string.
* Possible value are DrawString.LEFT, DrawString.RIGHT, and DrawString.CENTER.
*
*/
public void setJustification(int j) {
if (j == RIGHT || j == CENTER)
justification = j;
else
justification = LEFT;
needsRedraw();
}
/**
* Get the justification that is used for a multiple-line string. The value
* is one of the constants DrawString.LEFT, DrawString.RIGHT, or DrawString.CENTER
*/
public int getJustification() {
return justification;
}
/**
* Set the desired maximum number of characters in displayed numbers.
* Actual size might be larger. Value is clamped to the range
* 6 to 25.
*
*/
public void setNumSize(int size) {
numSize = Math.min(Math.max(size,6),25);
changed = true;
needsRedraw();
}
/**
* Return the desired maximum number of characters in displayed numbers.
*
*/
public int getNumSize() {
return numSize;
}
/**
* Get the color that is used to fill a rectangle on which the string is drawn. Null
* indicates that no rectangle is filled so the stuff in back of the string shows though.
* The default value is null.
*/
public Color getBackgroundColor() {
return backgroundColor;
}
/**
* Set the color that is used to fill a rectangle on which the string is drawn. If the
* value is null, no rectangle is filled and the string just overlays whatever is in back
* of it on the canvas.
*/
public void setBackgroundColor(Color color) {
backgroundColor = color;
needsRedraw();
}
/**
* Get the color that is used to draw a frame around the string. This is only done if the
* frameWidth property is greater than zero. If the value is null, the frame is the same color
* as the string.
*/
public Color getFrameColor() {
return frameColor;
}
/**
* Set the color that is used to draw a frame around the string. This is only done if the
* frameWidth property is greater than zero. If the value is null, the frame is the same color
* as the string.
*/
public void setFrameColor(Color color) {
frameColor = color;
needsRedraw();
}
/**
* Get the width, in pixels, of the frame that is drawn around the string.
* The default width is zero. The largest possible value is 25.
*/
public int getFrameWidth() {
return frameWidth;
}
/**
* Set the width, in pixels, of a frame to draw around the string. If the value is zero,
* no frame is drawn. The default value is zero. The the value is clamped
* to the range 0 to 25.
*/
public void setFrameWidth(int width) {
if (width < 0)
frameWidth = 0;
else if (width > 25)
frameWidth = 25;
else
frameWidth = width;
needsRedraw();
}
/**
* The compute method sets up the array of strings that is actually displayed.
* This is required by the Computable interface and is usually called by a
* Controller rather than directly.
*/
public void compute() {
changed = true;
needsRedraw();
}
 
private void getSubstitutedText() { //Get the strings obtained by substituting values for #'s in text.
changed = false;
if (xPos != null)
xRef = xPos.getVal();
if (yPos != null)
yRef = yPos.getVal();
if (values == null && strings != null) // no need to recompute, since there is no #-substitution to do.
return;
if (baseString == null || baseString.trim().length() == 0) {
strings = null;
return;
}
StringTokenizer tok = new StringTokenizer(baseString, "\n");
int count = tok.countTokens();
strings = new String[count];
if (values == null) {
for (int i = 0; i < count; i++)
strings[i] = tok.nextToken();
return;
}
StringBuffer b = new StringBuffer();
int expCt = 0;
for (int strNum = 0; strNum < count; strNum++) {
String text = tok.nextToken();
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == '#') {
if (i != text.length() - 1 && text.charAt(i+1) == '#') {
b.append('#');
i++;
}
else {
if (expCt < values.length) {
try {
b.append(NumUtils.realToString(values[expCt].getVal(),numSize));
}
catch (RuntimeException e) {
b.append("(error)");
}
expCt++;
}
else
b.append("undefined");
}
}
else
b.append(text.charAt(i));
}
strings[strNum] = b.toString();
b.setLength(0);
}
}
 
/**
* Draws the string.
*/
public void draw(Graphics g, boolean coordsChanged) {
 
if (changed)
getSubstitutedText();
if (strings == null)
return;
if (xPos != null && (Double.isNaN(xRef) || Double.isInfinite(xRef)))
return;
if (yPos != null && (Double.isNaN(yRef) || Double.isInfinite(yRef)))
return;
int trueOffset = offset; // offset allowing for frame and background
if (backgroundColor != null || frameWidth > 0)
trueOffset += 3;
trueOffset += frameWidth;
Font saveFont = null;
FontMetrics fm;
if (font != null) {
saveFont = g.getFont();
g.setFont(font);
fm = g.getFontMetrics(font);
}
else
fm = g.getFontMetrics(g.getFont());
int lineHeight = fm.getHeight();
 
int xmin = coords.getLeft();
int width = coords.getWidth();
int ymin = coords.getTop();
int height = coords.getHeight();
int xmax = xmin+width;
int ymax = ymin+height;
int stringWidth = 0;
for (int i = 0; i < strings.length; i++)
stringWidth = Math.max(stringWidth,fm.stringWidth(strings[i]));
int stringHeight = strings.length*lineHeight;
if (backgroundColor == null && frameWidth <= 0)
stringHeight = stringHeight - fm.getLeading() - fm.getDescent();
int xInt=0,yInt=0;
 
int hPos = position % 4;
int vPos = position / 4;
if (position < 0 || hPos > 2 || vPos > 2) { // Use TOP_LEFT as default, if position is not a legal value.
hPos = 0;
vPos = 0;
}
 
if (xPos == null) {
if (hPos == 0)
xInt = xmin + trueOffset;
else if (hPos == 1)
xInt = (xmin + xmax - stringWidth) / 2;
else
xInt = xmax - stringWidth - trueOffset;
}
else {
if (hPos == 0)
xInt = coords.xToPixel(xRef) + trueOffset;
else if (hPos == 1)
xInt = coords.xToPixel(xRef) - stringWidth / 2;
else
xInt = coords.xToPixel(xRef) - stringWidth - trueOffset;
}
if (yPos == null) {
if (vPos == 0)
yInt = ymin + trueOffset;
else if (vPos == 1)
yInt = (ymin + ymax - stringHeight) / 2;
else
yInt = ymax - stringHeight - trueOffset;
}
else {
if (vPos == 0)
yInt = coords.yToPixel(yRef) + trueOffset;
else if (vPos == 1)
yInt = coords.yToPixel(yRef) - stringHeight / 2;
else
yInt = coords.yToPixel(yRef) - stringHeight - trueOffset;
}
if (clamp) {
if (xInt + stringWidth > xmax)
xInt = xmax - stringWidth;
if (xInt < xmin)
xInt = xmin;
if (yInt + stringHeight > ymax)
yInt = ymax - stringHeight;
if (yInt < ymin)
yInt = ymin;
}
if (backgroundColor != null) {
g.setColor(backgroundColor);
g.fillRect(xInt-3, yInt-3, stringWidth+6, stringHeight+6);
}
if (frameWidth > 0) {
if (frameColor != null)
g.setColor(frameColor);
else if (color != null)
g.setColor(color);
else
g.setColor(Color.black);
for (int k = 1; k <= frameWidth; k++)
g.drawRect(xInt-3-k,yInt-3-k,stringWidth+5+2*k,stringHeight+5+2*k);
}
 
if (color != null)
g.setColor(color);
else
g.setColor(Color.black);
 
yInt += fm.getAscent();
for (int i = 0; i < strings.length; i++) {
int x = xInt;
if (justification == CENTER)
x = x + (stringWidth - fm.stringWidth(strings[i]))/2;
else if (justification == RIGHT)
x = x + stringWidth - fm.stringWidth(strings[i]);
g.drawString(strings[i],x,yInt);
yInt += lineHeight;
}
if (saveFont != null)
g.setFont(saveFont);
}
} // end class DrawString
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/Grid.java
0,0 → 1,158
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
import java.awt.*;
 
/**
* A Grid object draws a graph paper-like grid on a Canvas. The pixel width
* and height between adjacent grid lines is specified as a parameter to the
* constructer, or through the access methods "setXSP(double)" and
* "setYSP(double)". Note that the spacing will be scaled to between PIX_MIN
* and PIX_MAX (20 and 80, respectively, by default). The color of the grid
* lines can be set, and defaults to (220, 220, 220).
*
* <p>This class was written by Gabriel Weinstock (with some modifications by David Eck).
*/
public class Grid extends Drawable {
 
private Color gcol = new Color(220, 220, 220);
private double xsp, ysp;
private final int PIX_MAX = 80, PIX_MIN = 20;
/**
* Create a Grid object with x and y spacing 1.0. This does not mean that
* the actual spacing between grid lines will be 1. It will be some reasonable
* fraction or multiply of 1, with the value chosen to give a reasonable
* spacing between the grid lines.
*/
public Grid() {
this(1.0, 1.0);
}
/**
* Create a Grid object with spacing specified.
*/
public Grid(double xspace, double yspace) {
xsp = xspace; ysp = yspace;
}
/**
* Access method which returns the Color of the grid lines.
*/
public Color getColor() {
return gcol;
}
/**
* Method to set the Color used to draw grid lines.
*/
 
public void setColor(Color c)
{
if(c != null && !c.equals(gcol))
{
gcol = c;
needsRedraw();
}
}
 
/**
* Access method to return the x spacing used between grid lines.
*/
public double getXSP() { return xsp; }
/**
* Access method to return the y spacing used between grid lines
*/
public double getYSP() { return ysp; }
/**
* Method to set the x spacing between grid lines. This does not mean that
* the actual spacing between grid lines will be x. It will be some reasonable
* fraction or multiply of s, with the value chosen to give a reasonable
* spacing between the grid lines.
*/
public void setXSP(double x) { xsp = x; needsRedraw(); }
/**
* Method to set the y spacing between grid lines. This does not mean that
* the actual spacing between grid lines will be y. It will be some reasonable
* fraction or multiply of s, with the value chosen to give a reasonable
* spacing between the grid lines.
*/
public void setYSP(double y) { ysp = y; needsRedraw(); }
/**
* Draws the grid if an update is required. This is not usually called directly.
*
* @param g the Graphics context
* @param coordsch boolean describing whether coordinates have changed
*/
public void draw(Graphics g, boolean coordsch)
{
if(coords == null)
return;
double pixwidth = coords.getPixelWidth();
double pixheight = coords.getPixelHeight();
if (Double.isNaN(pixwidth) || Double.isNaN(pixheight) || Double.isInfinite(pixheight)
|| Double.isInfinite(pixwidth) || pixwidth == 0 || pixheight == 0)
return;
g.setColor(gcol);
// start by drawing vertical grid lines (starting with center):
if(xsp > 0)
{
double x = xsp;
while(x > (pixwidth * PIX_MAX))
x /= 10;
if (x < (pixwidth * PIX_MIN))
x *= 5;
if (x > (pixwidth * PIX_MAX))
x /= 2;
int j = (int) (Math.ceil(coords.getXmin() / x));
double i = j * x;
while(coords.xToPixel(i) < (coords.getWidth() + coords.getLeft()))
{
g.drawLine(coords.xToPixel(i), coords.getTop(), coords.xToPixel(i), coords.getTop() + coords.getHeight());
i += x;
}
}
// next draw horizontal grid lines
if(ysp > 0)
{
double y = ysp;
while(y > (pixheight * PIX_MAX))
y /= 10;
if (y < (pixheight * PIX_MIN))
y *= 5;
if (y > (pixheight * PIX_MAX))
y /= 2;
int j = (int) (Math.ceil(coords.getYmin() / y));
double i = j * y;
while(coords.yToPixel(i) > coords.getTop())
{
g.drawLine(coords.getLeft(), coords.yToPixel(i), coords.getLeft() + coords.getWidth(), coords.yToPixel(i));
i += y;
}
}
}
 
} // end class Grid
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/Graph1D.java
0,0 → 1,410
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
import java.awt.*;
import java.util.Vector;
 
/**
* A Graph1D represents the graph of a function of one variable, to be
* displayed in a given CoordinateRect. A Graph1D is a Computable.
* The data for the graph is recomputed when its compute() method is
* called. It will also be recomputed, before it is drawn, if the
* coordinate rect has changed in some way.
*/
 
public class Graph1D extends Drawable implements Computable {
 
 
private Function func; //The function that is graphed.
 
private Color graphColor = Color.magenta; //Color of the graph.
 
private boolean changed; //Used internally to indicate that data has to be recomputed.
 
 
private transient int[] xcoord, ycoord; //points on graph; xcoord[i] == Integer.MIN_VALUE
//for points where function is undefined.
/**
* Create a Graph1D with no function to graph. One can be set
* later with setFunction();
*/
public Graph1D() {}
/**
* Create a graph of the specified function.
*
* @param func The function to be graphed. If func is null, nothing is drawn.
* If func is non-null, it must be a function of one variable.
*/
public Graph1D(Function func) {
setFunction(func);
}
/**
* Set the color to be used for drawing the graph. The default color is magenta.
*/
public void setColor(Color c) {
if (c != null & !c.equals(graphColor)) {
graphColor = c;
needsRedraw();
}
}
/**
* Get the color that is used to draw the graph.
*/
public Color getColor() {
return graphColor;
}
/**
* Set the function to be graphed. If it is null, nothing is drawn.
* If it is non-null, it must be a function of one variable, or an error will occur.
*
*/
synchronized public void setFunction(Function f) {
if (f != null && f.getArity() != 1)
throw new IllegalArgumentException("Internal Error: Graph1D can only graph a function of one variable.");
if (f != func) {
func = f;
changed = true;
needsRedraw();
}
}
/**
* Get the (possibly null) function whose graph is drawn.
*/
public Function getFunction() {
return func;
}
//------------------ Implementation details -----------------------------
/**
* Recompute data for the graph and make sure that the area of the display canvas
* that shows the graph is redrawn. This method is ordinarily called by a
* Controller.
*/
synchronized public void compute() {
setup(coords);
needsRedraw();
}
/**
* Draw the graph (possibly recomputing the data if the CoordinateRect has changed).
* This is not usually called directly.
*
*/
synchronized public void draw(Graphics g, boolean coordsChanged) {
if (changed || coordsChanged || xcoord == null || ycoord == null) {
setup(coords);
changed = false;
}
if (xcoord.length == 0)
return;
g.setColor(graphColor);
int x = xcoord[0];
int y = ycoord[0];
for (int i = 1; i < xcoord.length; i++) {
if (xcoord[i] == Integer.MIN_VALUE) {
do {
i++;
} while (i < xcoord.length && xcoord[i] == Integer.MIN_VALUE);
if (i < xcoord.length) {
x = xcoord[i];
y = ycoord[i];
}
}
else {
int x2 = xcoord[i];
int y2 = ycoord[i];
g.drawLine(x,y,x2,y2);
x = x2;
y = y2;
}
}
}
// ------------------------- Computing the points on the graph -----------------------
private double absoluteYmax, onscreenymax, absoluteYmin, onscreenymin;
private final static int UNDEFINED = 0, ABOVE = 1, BELOW = 2, ONSCREEN = 3;
private double[] v = new double[1];
private Cases case1 = new Cases();
private Cases case2 = new Cases();
private double eval(double x, Cases c) {
v[0] = x;
if (c != null)
c.clear();
double y = func.getValueWithCases(v,c);
if (Double.isInfinite(y) || Double.isNaN(y))
return Double.NaN;
else if (y > absoluteYmax)
return absoluteYmax;
else if (y < absoluteYmin)
return absoluteYmin;
else
return y;
}
private int getStatus(double y) {
if (Double.isNaN(y))
return UNDEFINED;
else if (y > onscreenymax)
return ABOVE;
else if (y < onscreenymin)
return BELOW;
else
return ONSCREEN;
}
 
private void setup(CoordinateRect c) {
if (func == null || c == null) {
xcoord = ycoord = new int[0];
return;
}
Vector points = new Vector();
double pixelWidth = (c.getXmax() - c.getXmin()) / (c.getWidth()-2*c.getGap()-1);
onscreenymax = c.getYmax() + (100+c.getGap())*pixelWidth;
onscreenymin = c.getYmin() - (100+c.getGap())*pixelWidth;
absoluteYmax = c.getYmax() + 5000*pixelWidth;
absoluteYmin = c.getYmin() - 5000*pixelWidth;
double prevx, prevy, x, y, lastx;
int status, prevstatus;
int pixelx = c.getLeft();
int pixely;
int xHoldOffscreen = Integer.MIN_VALUE;
int yHoldOffscreen = 0;
int statusHoldOffscreen = 0;
 
x = c.pixelToX(pixelx);
y = eval(x,case1);
status = getStatus(y);
if (status == ONSCREEN) {
points.addElement(new Point(pixelx,c.yToPixel(y)));
}
else if (status != UNDEFINED) {
xHoldOffscreen = pixelx;
yHoldOffscreen = c.yToPixel(y);
statusHoldOffscreen = status;
}
int limitx = c.getLeft() + c.getWidth() -1;
while (pixelx < limitx) {
prevx = x;
prevy = y;
prevstatus = status;
pixelx += 3;
if (pixelx > limitx)
pixelx = limitx;
x = c.pixelToX(pixelx);
y = eval(x, case2);
status = getStatus(y);
if (status == UNDEFINED) {
if (prevstatus != UNDEFINED) {
if (prevstatus == ONSCREEN)
domainEndpoint(c,points,prevx,x,prevy,y,prevstatus,status,1);
else if (xHoldOffscreen != Integer.MIN_VALUE)
points.addElement(new Point(xHoldOffscreen,yHoldOffscreen));
xHoldOffscreen = Integer.MIN_VALUE;
points.addElement(new Point(Integer.MIN_VALUE,0));
}
}
else if (prevstatus == UNDEFINED) {
if (status == ONSCREEN) {
domainEndpoint(c,points,prevx,x,prevy,y,prevstatus,status,1);
points.addElement(new Point(pixelx,c.yToPixel(y)));
xHoldOffscreen = Integer.MIN_VALUE;
}
else {// note: status != UNDEFINED
xHoldOffscreen = pixelx;
yHoldOffscreen = c.yToPixel(y);
statusHoldOffscreen = status;
}
// xHoldOffscreen is already Integer.MIN_VALUE
}
else if (case1.equals(case2)) {
if (status == ONSCREEN) {
if (xHoldOffscreen != Integer.MIN_VALUE) {
points.addElement(new Point(xHoldOffscreen,yHoldOffscreen));
xHoldOffscreen = Integer.MIN_VALUE;
}
points.addElement(new Point(pixelx, c.yToPixel(y)));
}
else {
pixely = c.yToPixel(y);
if (xHoldOffscreen != Integer.MIN_VALUE) {
if (status != statusHoldOffscreen) { // one ABOVE, one BELOW
points.addElement(new Point(xHoldOffscreen,yHoldOffscreen));
points.addElement(new Point(pixelx,pixely));
points.addElement(new Point(Integer.MIN_VALUE,0));
}
}
else
points.addElement(new Point(pixelx,pixely)); // first jump to offscreen
xHoldOffscreen = pixelx;
yHoldOffscreen = pixely;
statusHoldOffscreen = status;
}
}
else { // discontinuity
if (prevstatus == ABOVE || prevstatus == BELOW) {
if (status == prevstatus) {
if (xHoldOffscreen != Integer.MIN_VALUE) { // should be false
points.addElement(new Point(xHoldOffscreen,yHoldOffscreen));
points.addElement(new Point(Integer.MIN_VALUE,0));
}
xHoldOffscreen = pixelx; // don't worry about offscreen discontinuity
yHoldOffscreen = c.yToPixel(y);
statusHoldOffscreen = status;
}
else if (status == ONSCREEN) { // possible visible discontinuity
if (xHoldOffscreen != Integer.MIN_VALUE) {
points.addElement(new Point(xHoldOffscreen,yHoldOffscreen));
xHoldOffscreen = Integer.MIN_VALUE;
}
discontinuity(c,points,prevx,x,prevy,y,prevstatus,status,1);
y = eval(x,case2); // reset cases, for next check
points.addElement(new Point(pixelx,c.yToPixel(y)));
}
else { // status == ABOVE or BELOW, opposit to prevstatus; just do a jump
if (xHoldOffscreen != Integer.MIN_VALUE)
points.addElement(new Point(xHoldOffscreen,yHoldOffscreen));
points.addElement(new Point(Integer.MIN_VALUE,0));
xHoldOffscreen = pixelx;
yHoldOffscreen = c.yToPixel(y);
statusHoldOffscreen = status;
}
}
else { // prevstatus is ONSCREEN; possible visible discontinuity
discontinuity(c,points,prevx,x,prevy,y,prevstatus,status,1);
y = eval(x,case2); // reset cases, for next check
if (status == ONSCREEN) {
points.addElement(new Point(pixelx,c.yToPixel(y)));
xHoldOffscreen = Integer.MIN_VALUE;
}
else {
xHoldOffscreen = pixelx;
yHoldOffscreen = c.yToPixel(y);
statusHoldOffscreen = status;
}
}
}
Cases temp = case2;
case2 = case1;
case1 = temp;
} // end while (pixel < limitx)
xcoord = new int[points.size()];
ycoord = new int[points.size()];
for (int i = 0; i < ycoord.length; i++) {
Point p = (Point)points.elementAt(i);
xcoord[i] = p.x;
ycoord[i] = p.y;
}
}
private static final int MAX_DEPTH = 10;
// Status of one endpoints is ONSCREEN; other is ABOVE,BELOW, or ONSCREEN
private void discontinuity(CoordinateRect c, Vector points, double x1, double x2, double y1, double y2,
int status1, int status2, int depth) {
//System.out.println("In discontinuity, depth = " + depth);
if (depth == MAX_DEPTH) {
points.addElement(new Point(c.xToPixel(x1),c.yToPixel(y1)));
points.addElement(new Point(Integer.MIN_VALUE,0));
points.addElement(new Point(c.xToPixel(x2),c.yToPixel(y2)));
}
else {
double xmid = (x1+x2)/2.0;
y1 = eval(x1,case1);
double ymid = eval(xmid,case2);
boolean cases1 = case1.equals(case2);
y2 = eval(x2,case1);
boolean cases2 = case1.equals(case2);
int statusmid = getStatus(ymid);
if (statusmid == UNDEFINED) { // hope it doesn't happen
if (status1 == ONSCREEN)
domainEndpoint(c,points,x1,xmid,y1,ymid,status1,statusmid,1);
points.addElement(new Point(Integer.MIN_VALUE,0));
if (status2 == ONSCREEN)
domainEndpoint(c,points,xmid,x2,ymid,y2,statusmid,status2,1);
}
else if (cases1 == false) {
discontinuity(c,points,x1,xmid,y1,ymid,status1,statusmid,depth+1);
if (cases2 == false) // double discontinuity
discontinuity(c,points,xmid,x2,ymid,y2,statusmid,status2,depth+1);
}
else if (cases2 == false)
discontinuity(c,points,xmid,x2,ymid,y2,statusmid,status2,depth+1);
else
System.out.println("Impossible error? no discontinuity found in discontinuity for " + x1 + ',' + x2);
}
}
//One of status1 and status2 is UNDEFINED, one is ONSCREEN.
//This always adds a point to points.
private void domainEndpoint(CoordinateRect c, Vector points, double x1, double x2, double y1, double y2,
int status1, int status2, int depth) {
//System.out.println("IN domainEndpoint, ......... depth = " + depth);
if (depth == MAX_DEPTH*2) {
if (status1 == ONSCREEN)
points.addElement(new Point(c.xToPixel(x1),c.yToPixel(y1)));
else // status2 == ONSCREEN
points.addElement(new Point(c.xToPixel(x2),c.yToPixel(y2)));
}
else {
double xmid = (x1+x2)/2.0;
double ymid = eval(xmid,null);
int statusmid = getStatus(ymid);
if (statusmid == ABOVE || statusmid == BELOW)
points.addElement(new Point(c.xToPixel(xmid),c.yToPixel(ymid)));
else if (statusmid == status1) // statusmid is ONSCREEN or UNDEFINED
domainEndpoint(c,points,xmid,x2,ymid,y2,statusmid,status2,depth+1);
else
domainEndpoint(c,points,x1,xmid,y1,ymid,status1,statusmid,depth+1);
}
}
} // end class Graph1D
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/DrawBorder.java
0,0 → 1,119
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import java.awt.Graphics;
import java.awt.Color;
 
/**
* A DrawBorder object is just a simple border around the edges of its CoordinateRect, with
* a specified width, in pixels, and a specified color.
*/
public class DrawBorder extends Drawable {
 
/**
* A non-null Color, giving the color of the bortder.
*/
protected Color color;
/**
* A non-negative integer giving the width of the border in pixels.
*/
protected int width;
/**
* Create a black border that is one pixel thick.
*/
public DrawBorder() {
this(Color.black,1);
}
/**
* Create a border with the spcified color and width. If the color is null,
* black is used. If the width is less than zero, a width of 1 is used.
* A border of width zero is invisible.
*
*/
public DrawBorder(Color color, int width) {
this.color = ((color == null)? Color.black : color);
this.width = ((width >= 0)? width : 1);
}
/**
* Get the color of the border.
*
*/
public Color getColor() {
return color;
}
/**
* Set the color of the border to the specified color. If the color is null, nothing is done.
*
*/
public void setColor(Color c) {
if (c != null && !c.equals(color)) {
color = c;
needsRedraw();
}
}
/**
* Get the width of the border, in pixels.
*
*/
public int getWidth() {
return width;
}
/**
* Set the width of the border to be w pixels. If w is negative,
* this is ignored. A border of witdth 0 is invisible.
*
* @param w the desired width for the border.
*/
public void setWidth(int w) {
if (w >= 0 && width != width) {
width = w;
}
}
 
/**
* Draw the border in the given graphics context. This is not ordinarily called directly.
*
*/
public void draw(Graphics g, boolean changed) {
if (coords == null || width == 0)
return;
g.setColor(color);
for (int i = 0; i < width; i++)
g.drawRect(coords.getLeft() + i, coords.getTop() + i,
coords.getWidth() - 2*i - 1, coords.getHeight() - 2*i - 1);
}
} // end class DrawBorder
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/ParametricCurve.java
0,0 → 1,465
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
import java.awt.*;
import java.util.Vector;
 
/**
* A ParametricCurve is defined by two functions, x(t) and y(t) of a variable, t,
* for t in a specified interval. The curve is simply defined as a sequence of line
* segments connecting points of the form (x(t),y(t)), except where one of the functions
* is undefined. Also, in some cases a
* discontinuity will be detected and no line will be drawn between two of the points.
*/
 
public class ParametricCurve extends Drawable implements Computable {
 
 
private Function xFunc, yFunc; //The functions of t that are graphed.
 
private Color graphColor = Color.magenta; //Color of the graph.
 
private boolean changed; // Used internally to indicate that data has to be recomputed.
 
 
private transient int[] xcoord, ycoord; //points on graph; xcoord[i] == Integer.MIN_VALUE
//for points where a gap occurs.
private Value tmin, tmax; // Value objects giving the minimum and maximum value of t.
private Value intervals; // Value object giving the number of intervals into which the
// interval (tmin,tmax) is to be divided.
private double tmin_val, tmax_val; // The values of tmin and tmax.
// (tmin_val is set to Double.NaN if any of the values are bad, and nothing is drawn.)
private int intervals_val; // The value of intervals.
/**
* Create a ParametricCurve with nothing to graph. The functions and other values
* can be set later.
*/
public ParametricCurve() {
this(null,null,null,null,null);
}
/**
* Create a parametric curve with x and y coordinates given by the specified functions
* of the parameter t. Defaults values are used for tmin, tmax, and the number of intervals.
* If either function is null, nothing is drawn.
*/
public ParametricCurve(Function xFunc, Function yFunc) {
this(xFunc,yFunc,null,null,null);
}
/**
* Create a parametric curve with the specified values.
*
* @param xFunc A Function of one variable giving the x-coordinate of points on the curve. If this
* is null, then nothing will be drawn.
* @param yFunc A Function of one variable giving the y-coordinate of points on the curve. If this
* is null, then nothing will be drawn.
* @param tmin A Value object giving one endpoint of the domain of the parameter. If this is null,
* the default value -5 is used.
* @param tmax A Value object giving the second endpoint of the domain of the parameter. If this is null,
* the default value 5 is used. Note that it is not required that tmax be greater than tmin.
* @param intervals A Value object giving the number of intervals into which the domain is subdivided.
* If this is null, the default value 200 is used. The number of points on the curve will be
* the number of intervals plus one (unless a function is undefined at some value of the parameter
* or if a discontinuity is detected). The number of intervals is clamped to the range 1 to 10000.
* Values outside this range would certainly be unreasonable.
*/
public ParametricCurve(Function xFunc, Function yFunc, Value tmin, Value tmax, Value intevals) {
if ( (xFunc != null && xFunc.getArity() != 1) || (yFunc != null && yFunc.getArity() != 1) )
throw new IllegalArgumentException("Internal Error: The functions that define a parametric curve must be functions of one variable.");
this.xFunc = xFunc;
this.yFunc = yFunc;
this.tmin = tmin;
this.tmax = tmax;
this.intervals = intervals;
changed = true;
}
/**
* Set the color to be used for drawing the graph.
*/
public void setColor(Color c) {
if (c != null & !c.equals(graphColor)) {
graphColor = c;
needsRedraw();
}
}
/**
* Get the color that is used to draw the graph.
*/
public Color getColor() {
return graphColor;
}
/**
* Sets the functions that gives the coordinates of the curve to be graphed. If either function is
* null, then nothing is drawn. If non-null, each function must be a function of one variable.
*/
synchronized public void setFunctions(Function x, Function y) {
setXFunction(x);
setYFunction(y);
}
/**
* Set the function that gives the x-coordinate of the curve to be graphed. If this is
* null, then nothing is drawn. If non-null, it must be a function of one variable.
*/
synchronized public void setXFunction(Function x) {
if (x != null && x.getArity() != 1)
throw new IllegalArgumentException("Internal Error: ParametricCurve can only graph functions of one variable.");
if (x != xFunc) {
xFunc = x;
changed = true;
needsRedraw();
}
}
/**
* Set the function that gives the y-coordinate of the curve to be graphed. If this is
* null, then nothing is drawn. If non-null, it must be a function of one variable.
*/
synchronized public void setYFunction(Function y) {
if (y != null && y.getArity() != 1)
throw new IllegalArgumentException("Internal Error: ParametricCurve can only graph functions of one variable.");
if (y != yFunc) {
yFunc = y;
changed = true;
needsRedraw();
}
}
/**
* Get the (possibly null) function that gives the x-coordinate of the curve.
*/
public Function getXFunction() {
return xFunc;
}
/**
* Get the (possibly null) function that gives the y-coordinate of the curve.
*/
public Function getYFunction() {
return yFunc;
}
/**
* Specify the number of subintervals into which the domain of the parametric curve is divided.
* The interval (tmin,tmax) is divided into subintervals. X and y coordinates of the parametric curve
* are computed at each endpoint of these subintervals, and then the points are connected by lines.
* If the parameter of this function is null, or if no interval count is ever specified, then a
* default value of 200 is used.
*/
public void setIntervals(Value intervalCount) {
intervals = intervalCount;
changed = true;
}
/**
* Get the value object, possibly null, that determines the number of points on the curve.
*/
public Value getIntervals() {
return intervals;
}
/**
* Set the Value objects that specify the domain of the paratmeter.
*/
public void setLimits(Value tmin, Value tmax) {
setTMin(tmin);
setTMax(tmax);
}
/**
* Get the Value object, possibly null, that gives the left endpoint of the domain of the parameter.
*/
public Value getTMin() {
return tmin;
}
/**
* Get the Value object, possibly null, that gives the right endpoint of the domain of the parameter.
*/
public Value getTMax() {
return tmax;
}
/**
* Set the Value object that gives the left endpoint of the domain of the parameter. If this is null,
* then a default value of -5 is used for the left endpoint. (Note: actually, it's not required that
* tmin be less than tmax, so this might really be the "right" endpoint.)
*/
public void setTMin(Value tmin) {
this.tmin = tmin;
changed = true;
}
/**
* Set the Value object that gives the right endpoint of the domain of the parameter. If this is null,
* then a default value of 5 is used for the right endpoint. (Note: actually, it's not required that
* tmin be less than tmax, so this might really be the "left" endpoint.)
*/
public void setTMax(Value tmax) {
this.tmax = tmax;
changed = false;
}
//------------------ Implementation details -----------------------------
/**
* Recompute data for the graph and make sure that the area of the display canvas
* that shows the graph is redrawn. This method is ordinarily called by a
* Controller.
*/
synchronized public void compute() {
setup();
needsRedraw();
changed = false;
}
/**
* Draw the graph (possibly recomputing the data if the CoordinateRect has changed).
* This is not usually called directly.
*
*/
synchronized public void draw(Graphics g, boolean coordsChanged) {
if (changed || coordsChanged || xcoord == null || ycoord == null) {
setup();
changed = false;
}
if (xcoord == null || xcoord.length == 0)
return;
g.setColor(graphColor);
int x = xcoord[0];
int y = ycoord[0];
for (int i = 1; i < xcoord.length; i++) {
if (xcoord[i] == Integer.MIN_VALUE) {
do {
i++;
} while (i < xcoord.length && xcoord[i] == Integer.MIN_VALUE);
if (i < xcoord.length) {
x = xcoord[i];
y = ycoord[i];
}
}
else {
int x2 = xcoord[i];
int y2 = ycoord[i];
g.drawLine(x,y,x2,y2);
x = x2;
y = y2;
}
}
}
// ------------------------- Computing the points on the graph -----------------------
private double[] v = new double[1];
private Cases case1x = new Cases();
private Cases case2x = new Cases();
private Cases case1y = new Cases();
private Cases case2y = new Cases();
private Cases case3x = new Cases();
private Cases case3y = new Cases();
private Vector points = new Vector(250);
private Point eval(double t, Cases xcases, Cases ycases) {
v[0] = t;
if (xcases != null)
xcases.clear();
if (ycases != null)
ycases.clear();
double x = xFunc.getValueWithCases(v,xcases);
double y = yFunc.getValueWithCases(v,ycases);
if (Double.isNaN(x) || Double.isNaN(y))
return null;
int xInt = coords.xToPixel(x);
int yInt = coords.yToPixel(y);
if (Math.abs(xInt) > 10000 || Math.abs(yInt) > 10000)
return null;
return new Point(xInt,yInt);
}
private void setup() {
if (xFunc == null || yFunc == null || coords == null) {
xcoord = ycoord = new int[0]; // Nothing will be drawn
return;
}
double intervals_val_d;
if (tmin == null)
tmin_val = -5;
else
tmin_val = tmin.getVal();
if (tmax == null)
tmax_val = 5;
else
tmax_val = tmax.getVal();
if (intervals == null)
intervals_val_d = 200;
else
intervals_val_d = intervals.getVal();
if (Double.isInfinite(tmin_val) || Double.isInfinite(tmax_val) || Double.isInfinite(intervals_val_d)
|| Double.isNaN(tmax_val) || Double.isNaN(intervals_val_d))
tmin_val = Double.NaN; // Signal that data is bad, so nothing will be drawn.
if (intervals_val_d < 1)
intervals_val = 1;
else if (intervals_val > 10000)
intervals_val = 10000;
else
intervals_val = (int)Math.round(intervals_val_d);
if (Double.isNaN(tmin_val)) { // data is bad, don't draw
xcoord = ycoord = new int[0];
return;
}
 
points.setSize(0);
double delta = (tmax_val - tmin_val) / intervals_val;
double prevx, prevy, x, y, lastT;
Point point, prevpoint;
double t = tmin_val;
prevpoint = eval(t,case1x,case1y);
if (prevpoint != null)
points.addElement(prevpoint);
 
for (int i = 1; i <= intervals_val; i++) {
t = tmin_val + i * delta;
point = eval(t,case2x,case2y);
if (point != null && prevpoint != null) {
if (!case1x.equals(case2x) || !case1y.equals(case2y))
// A discontinuity between two "onscreen" points.
discontinuity(prevpoint,tmin_val+(i-1)*delta,point,t,0);
else
points.addElement(point);
}
else if (prevpoint == null && point != null) {
becomesDefined(prevpoint,tmin_val+(i-1)*delta,point,t,0);
}
else if (prevpoint != null && point == null) {
becomesUndefined(prevpoint,tmin_val+(i-1)*delta,point,t,0);
}
 
prevpoint = point;
Cases temp = case1x;
case1x = case2x;
case2x = temp;
temp = case1y;
case1y = case2y;
case2y = temp;
} // end for
 
xcoord = new int[points.size()];
ycoord = new int[points.size()];
for (int i = 0; i < ycoord.length; i++) {
Point p = (Point)points.elementAt(i);
xcoord[i] = p.x;
ycoord[i] = p.y;
}
} // end setup();
 
private static int MAXDEPTH = 10; // maximum depth of recursion in the next three methods.
void discontinuity(Point p1, double t1, Point p2, double t2, int depth) {
// Both p1 and p2 are non-null; "cases" data at these two points does not agree;
// Original point p1 (from case depth=1) is in points vector. Case data for p1 and p2
// is contained in case1x,case1y and case2x,case2y respectively.
if (depth >= MAXDEPTH || (Math.abs(p1.x - p2.x) < 2 && Math.abs(p1.y - p2.y) < 2)) {
if (points.elementAt(points.size()-1) != p1)
points.addElement(p1);
if (depth >= MAXDEPTH)
points.addElement(new Point(Integer.MIN_VALUE,0));
points.addElement(p2);
return;
}
double t = (t1+t2)/2;
Point p = eval(t,case3x,case3y);
if (p == null) {
becomesUndefined(p1,t1,p,t,depth+1);
becomesDefined(p,t,p2,t2,depth+1);
}
else if (case3x.equals(case1x) && case3y.equals(case1y)) {
discontinuity(p,t,p2,t2,depth+1);
}
else if (case3x.equals(case2x) && case3y.equals(case2y)) {
discontinuity(p1,t1,p,t,depth+1);
}
else {
discontinuity(p1,t1,p,t,depth+2);
discontinuity(p,t,p2,t2,depth+2);
}
}
void becomesUndefined(Point p1, double t1, Point p2, double t2, int depth) {
// p1 is non-null; p2 is null. Original point p1 is in points vector.
if (depth >= MAXDEPTH) {
if (points.elementAt(points.size()-1) != p1)
points.addElement(p1);
points.addElement(new Point(Integer.MIN_VALUE,0));
return;
}
double t = (t1+t2)/2;
Point p = eval(t,null,null);
if (p == null)
becomesUndefined(p1,t1,p,t,depth+1);
else
becomesUndefined(p,t,p2,t2,depth+1);
}
void becomesDefined(Point p1, double t1, Point p2, double t2, int depth) {
// p1 is null; p2 is non-null
if (depth >= MAXDEPTH) {
if (points.size() > 0)
points.addElement(new Point(Integer.MIN_VALUE,0));
points.addElement(p2);
return;
}
double t = (t1+t2)/2;
Point p = eval(t,null,null);
if (p != null)
becomesDefined(p1,t1,p,t,depth+1);
else
becomesDefined(p,t,p2,t2,depth+1);
}
} // end class ParametricCurve
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/DrawGeometric.java
0,0 → 1,615
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.data.*;
import edu.hws.jcm.awt.*;
import java.awt.*;
 
/**
* A DrawGeometric object is a geometic figure such as a line or rectangle that can
* be drawn in a CoordinateRect. The data for the object always consists of four
* numbers, which are interpreted differenetly depending on the object. These numbers
* can be specified as Value objects. A DrawGeometric is a Computable, and the
* Values will be re-computed when its compute() method is called. It should be
* added to a Controller that can respond to any changes in the data that define
* the Values. If one of the Value objects has an undefined value, nothing will be drawn.
* <p>The type of object is given as one of the constants defined in this class:
* LINE_ABSOLUTE, OVAL_RELATIVE, CROSS, and so on. In the descriptions of these
* constants, x1, x2, y1, and y2 refer to the values of Value objects that provide data
* for the DrawGeomentric while h and v refer to int's that can be specified in place of
* x2 and y2 for certain types of figures. For those figures, h or v is used if
* x2 or y2, respectively, is null.
*
* @author David Eck
*/
 
 
public class DrawGeometric extends Drawable implements Computable {
 
/**
* Specifies a line segment from (x1,y1) to (x2,y2).
*/
public static final int LINE_ABSOLUTE = 0;
/**
* Specifies a line that extends through the points (x1,y1) and (x2,y2) and beyond.
*/
public static final int INFINITE_LINE_ABSOLUTE = 1;
/**
* Specifies a rectangle with corners at (x1,y1) and (x2,y2).
*/
public static final int RECT_ABSOLUTE = 2;
/**
* Specifies an oval that just fits in the rectangle with corners at (x1,y1) and (x2,y2).
*/
public static final int OVAL_ABSOLUTE = 3;
/**
* Specifies a line segment from (x1,y1) to (x1+x2,y1+y2), or to (x1+h,y1+v) if x2,y2 are null.
* (Note that h,v are given in terms of pixels while x1,x2,y1,y2 are given
* in terms of the CoordinateRect. If you use h,v, you get a line
* of a fixed size and direction.)
*/
public static final int LINE_RELATIVE = 4;
/**
* Specifies an infinite line through (x1,y1) and (x1+x2,y1+y2), or through (x1,y1) and (x1+h,y1+v) if x2,y2 are null.
*/
public static final int INFINITE_LINE_RELATIVE = 5;
/**
* Specifies a rectangle with one corner at (x1,y1), and with width given by x2, or h if
* if x2 is null, and with height given by y2, or by v if y2 is null.
*/
public static final int RECT_RELATIVE = 6;
/**
* Specifies an oval that just fits inside the rect specified by RECT_RELATIVE.
*/
public static final int OVAL_RELATIVE = 7;
/**
* Specifies a line segment centered on (x1,y1). The amount it extends in each direction
* is given by x2,y2 or by h,v
*/
public static final int LINE_CENTERED = 8;
/**
* Specifies a Rectangle centered on (x1,y1). The amount it extends in each direction
* is given by x2,y2 or by h,v. (Thus, x2 or h is the HALF-width and y2 or v is the HALF-height.)
*/
public static final int RECT_CENTERED = 9;
/**
* Specifies an oval that just fits inside the rect specified by RECT_CENTERED.
*/
public static final int OVAL_CENTERED = 10;
/**
* Specifies a cross centered on the point (x1,y1). Its arms extend horizontally
* by a distance of x2, or h, in each direction. Its vertical
* arms extend y2, or v, in each direction.
*/
public static final int CROSS = 11;
/**
* One of the constants such as OVAL_CENTERED, specifying the shape to be drawn
*/
protected int shape;
 
/**
* One of the Value objects that determine the shape that is drawn.
* The shape is specified by two points, (x1,y1) and (x2,y2).
* x1 must be non-null.
*/
protected Value x1;
 
/**
* One of the Value objects that determine the shape that is drawn.
* The shape is specified by two points, (x1,y1) and (x2,y2).
* x2 must be non-null
* for the "ABSOLUTE" shapes. (If not, they revert to
* "RELATIVE" shapes and use h,v as the offset values.)
*/
protected Value x2;
 
/**
* One of the Value objects that determine the shape that is drawn.
* The shape is specified by two points, (x1,y1) and (x2,y2).
* y1 must be non-null.
*/
protected Value y1;
 
/**
* One of the Value objects that determine the shape that is drawn.
* The shape is specified by two points, (x1,y1) and (x2,y2).
* y2 must be non-null
* for the "ABSOLUTE" shapes. (If not, they revert to
* "RELATIVE" shapes and use h,v as the offset values.)
*/
protected Value y2;
/**
* Integer that gives horizontal pixel offset from x1.
* This is only used if x2 is null.
*/
protected int h = 10;
/**
* Integer that gives vertical pixel offset fromy1.
* This is only used if y2 is null.
*/
protected int v = 10;
/**
* Value of x1. This is re-computed when the compute() method is called.
*/
protected double a = Double.NaN;
 
/**
* Value of y1. This is re-computed when the compute() method is called.
*/
protected double b;
 
/**
* Value of x2. This is re-computed when the compute() method is called.
*/
protected double c;
 
/**
* Value of y2. This is re-computed when the compute() method is called.
*/
protected double d;
/**
* Color of the shappe. Color will be black if this is null. For shapes that
* have "insides", such as rects, this is the color of the outline.
*/
protected Color color = Color.black;
/**
* Rects and ovals are filled with this color, if it is non-null.
* If this is null, only the outline of the shape is drawn.
*/
protected Color fillColor;
/**
* The width, in pixels, of lines, including the outlines
* of rects and ovals. It is restricted to being an integer
* in the range from 0 to 10. A value of 0 means that lines
* won't be drawn at all; this would only be useful for a filled
* shape that has a colored interior.
*/
protected int lineWidth = 1;
private boolean changed = true; // set to true when values have to be recomputed.
/**
* Create a DrawGeometric object. By default, it is a LINE_ABSOLUTE. However,
* nothing will be drawn as long as x1,y1,x2,y2 are null.
*/
public DrawGeometric() {}
/**
* Create a DrawGeometric with the specified shape and values for x1,x2,y1,y2
* Any of the shapes makes sense in this context.
*
* @param shape One of the shape constants such as LINE_ABSOLUTE or RECT_RELATIVE.
*/
public DrawGeometric(int shape, Value x1, Value y1, Value x2, Value y2) {
setShape(shape);
setPoints(x1,y1,x2,y2);
}
/**
* Create a DrawGeometric with a specified shape and values. The last two parameters
* give pixel offsets from x1,y1. The "ABSOLUTE" shapes don't make
* sense in this context. (They will be treated as the corresponding
* "RELATIVE" shapes.)
*
* @param shape One of the "RELATIVE" or "CENTERED" shape constants such as LINE_RELATIVE or OVAL_CENTERED or CROSS.
*/
public DrawGeometric(int shape, Value x1, Value y1, int h, int v) {
setShape(shape);
setPoints(x1,y1,h,v);
}
 
// ---------------- Routines for getting and setting properties --------------------------
/**
* Set the shape, which should be given as one of the shape constants such as LINE_ABSOLUTE or CROSS.
*/
public void setShape(int shape) {
if (shape < 0 || shape > CROSS)
throw new IllegalArgumentException("Internal error: Illegal value for shape of DrawGeometric object.");
this.shape = shape;
needsRedraw();
}
/**
* Set the Value objects that specify the two points that determine the shape.
* The first two parameters, x1 and y1, must be non-null.
*/
public void setPoints(Value x1, Value y1, Value x2, Value y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
compute();
}
/**
* Set the values that specify a point (x1,y1) and an offset (h,v) from that point.
* This only makes sense for RELATIVE shapes. The Value objects x1 and y1 must be non-null
*/
public void setPoints(Value x1, Value y1, int h, int v) {
this.x1 = x1;
this.y1 = y1;
this.x2 = null;
this.y2 = null;
this.h = h;
this.v = v;
compute();
}
/**
* Set the value that gives the x-coordinate of the first point that determines the shape.
* This must be non-null, or nothing will be drawn.
*/
public void setX1(Value x) {
x1 = x;
compute();
}
/**
* Get the value that gives the x-coordinate of the first point that determines the shape.
*/
public Value getX1() {
return x1;
}
 
 
/**
* Set the value that gives the x-coordinate of the second point that determines the shape.
* If this is null, then the value of h is used instead.
*/
public void setX2(Value x) {
x2 = x;
compute();
}
 
/**
* Get the value that gives the x-coordinate of the second point that determines the shape.
*/
public Value getX2() {
return x2;
}
 
/**
* Set the value that gives the y-coordinate of the first point that determines the shape.
* This must be non-null, or nothing will be drawn.
*/
public void setY1(Value y) {
y1 = y;
compute();
}
 
/**
* Get the value that gives the y-coordinate of the first point that determines the shape.
*/
public Value getY1() {
return y1;
}
 
/**
* Set the value that gives the y-coordinate of the second point that determines the shape.
* If this is null, then the value of v is used instead.
*/
public void setY2(Value y) {
y2 = y;
compute();
}
/**
* Get the value that gives the y-coordinate of the second point that determines the shape.
*/
public Value getY2() {
return y2;
}
 
/**
* Set the integer that gives the horizontal offset from (x1,y1).
* This only makes sense for RELATIVE shapes. This method also sets x2 to null,
* since the h value is only used when x2 is null.
*/
public void setH(int x) {
h = x;
x2 = null;
compute();
}
/**
* Get the horizontal offset from (x1,y1).
*/
public int getH() {
return h;
}
 
/**
* Set the integer that gives the vertical offset from (x1,y1).
* This only makes sense for RELATIVE shapes. This method also sets y2 to null,
* since the v value is only used when y2 is null.
*/
public void setV(int y) {
v = y;
y2 = null;
needsRedraw();
}
/**
* Get the vertical offset from (x1,y1).
*/
public int getV() {
return v;
}
 
/**
* Set the color that is used for drawing the shape. If the color is null, black is used.
* For shapes that have interiors, such as rects, this is only the color of the outline of the shaape.
*/
public void setColor(Color c) {
color = (c == null)? Color.black : c;
needsRedraw();
}
/**
* Get the non-null color that is used for drawing the shape.
*/
public Color getColor() {
return color;
}
/**
* Set the color that is used for filling ovals and rects. If the color is null, only the outline of the shape is drawn.
*/
public void setFillColor(Color c) {
fillColor = c;
needsRedraw();
}
/**
* Get the color that is used for filling ovals and rects. If null, no fill is done.
*/
public Color getFillColor() {
return fillColor;
}
/**
* Set the width, in pixels, of lines that are drawn. This is also used for outlines of rects and ovals.
*/
public void setLineWidth(int width) {
if (width != lineWidth) {
lineWidth = width;
if (lineWidth > 10)
lineWidth = 10;
else if (lineWidth < 0)
lineWidth = 0;
needsRedraw();
}
}
/**
* Get the width, in pixels, of lines that are drawn. This is also used for outlines of rects and ovals.
*/
public int getLineWidth() {
return lineWidth;
}
// ------------------------- Implementation details ------------------------------------
/**
* Recompute the values that define the size/postion of the DrawGeometric.
* This is ordinarily only called by a Controller.
*/
public void compute() {
changed = true;
needsRedraw();
}
private void doValues() {
if (x1 != null)
a = x1.getVal();
if (y1 != null)
b = y1.getVal();
if (x2 != null)
c = x2.getVal();
if (y2 != null)
d = y2.getVal();
changed = false;
}
/**
* Do the drawing. This is not meant to be called directly.
*/
public void draw(Graphics g, boolean coordsChanged) {
if (changed)
doValues();
if (coords == null || x1 == null || y1 == null ||
Double.isNaN(a) || Double.isNaN(b) ||
Double.isInfinite(a) || Double.isInfinite(b) )
return;
if (x2 != null && (Double.isNaN(c) || Double.isInfinite(c)))
return;
if (y2 != null && (Double.isNaN(d) || Double.isInfinite(d)))
return;
// Get the four real numbers that determine the shape, in terms of pixels.
double A,B,W,H;
A = xToPixelDouble(a);
B = yToPixelDouble(b);
if (x2 == null)
W = h;
else if (shape <= OVAL_ABSOLUTE)
W = xToPixelDouble(c) - A;
else
W = c/coords.getPixelWidth();
if (y2 == null)
H = -v;
else if (shape <= OVAL_ABSOLUTE)
H = yToPixelDouble(d) - B;
else
H = -d/coords.getPixelHeight();
if (shape == INFINITE_LINE_ABSOLUTE || shape == INFINITE_LINE_RELATIVE)
drawInfiniteLine(g, A, B, W, H);
else if (shape == CROSS)
drawCross(g, (int)A, (int)B, (int)(Math.abs(W)+0.5), (int)(Math.abs(H)+0.5));
else if (shape == LINE_RELATIVE || shape == LINE_ABSOLUTE)
drawLine(g, (int)A, (int)B, (int)(A+W), (int)(B+H));
else if (shape == LINE_CENTERED)
drawLine(g,(int)(A-Math.abs(W)+1),(int)(B-Math.abs(H)+1),(int)(A+Math.abs(W)),(int)(B+Math.abs(H)));
else if (shape <= OVAL_RELATIVE) {
if (W < 0) {
W = -W;
A = A - W;
}
if (H < 0) {
H = -H;
B = B - H;
}
drawShape(g, (int)A, (int)B, (int)(W+0.5), (int)(H+0.5));
}
else
drawShape(g,(int)(A-Math.abs(W)+1),(int)(B-Math.abs(H)+1),(int)(2* Math.abs(W)-0.5),(int)(2*Math.abs(H)-0.5));
}
private double xToPixelDouble(double x) {
return coords.getLeft() + coords.getGap() + ((x - coords.getXmin())/(coords.getXmax() - coords.getXmin()) * (coords.getWidth()-2*coords.getGap()-1));
}
private double yToPixelDouble(double y) {
return coords.getTop() + coords.getGap() + ((coords.getYmax() - y)/(coords.getYmax() - coords.getYmin()) * (coords.getHeight()-2*coords.getGap()-1));
}
private void drawLine(Graphics g, int x1, int y1, int x2, int y2) {
int width = Math.abs(x2 - x1);
int height = Math.abs(y2 - y1);
g.setColor( color );
if (width == 0 && height == 0)
g.drawLine(x1,y1,x1,y1);
else if (width > height) {
for (int i = 0; i < lineWidth; i++)
g.drawLine(x1,y1-lineWidth/2+i,x2,y2-lineWidth/2+i);
}
else {
for (int i = 0; i < lineWidth; i++)
g.drawLine(x1-lineWidth/2+i,y1,x2-lineWidth/2+i,y2);
}
}
/**
* Draws a rect or oval.
*
* @param x the top-left x value of the rect or the rect that contains the oval
* @param y the top-left y value of the rect or the rect that contains the oval
* @param width width of the rect
* @param height height of the rect
*/
private void drawShape(Graphics g, int x, int y, int width, int height) {
if (x > coords.getLeft() + coords.getWidth() || y > coords.getTop() + coords.getHeight()
|| x + width < coords.getLeft() || y + height < coords.getTop()) {
return;
}
if (fillColor != null) {
g.setColor(fillColor);
if (shape == RECT_ABSOLUTE || shape == RECT_RELATIVE || shape == RECT_CENTERED)
g.fillRect(x,y,width,height);
else
g.fillOval(x,y,width,height);
}
g.setColor( color );
if (shape == RECT_ABSOLUTE || shape == RECT_RELATIVE || shape == RECT_CENTERED) {
for (int i = 0; i < lineWidth; i++)
g.drawRect(x+i,y+i,width-2*i,height-2*i);
}
else {
for (int i = 0; i < lineWidth; i++)
g.drawOval(x+i,y+i,width-2*i,height-2*i);
}
}
 
private void drawCross(Graphics g, int x, int y, int width, int height) {
if (x - width> coords.getLeft() + coords.getWidth() || y - height > coords.getTop() + coords.getHeight()
|| x + width < coords.getLeft() || y + height < coords.getTop()) {
return;
}
int left = x - lineWidth/2;
int top = y - lineWidth/2;
g.setColor( color );
for (int i = 0; i < lineWidth; i++)
g.drawLine(x-width,top+i,x+width,top+i);
for (int i = 0; i < lineWidth; i++)
g.drawLine(left+i,y-height,left+i,y+height);
}
 
private void drawInfiniteLine(Graphics g, double x, double y, double dx, double dy) {
if (Math.abs(dx) < 1e-10 && Math.abs(dy) < 1e-10)
return;
g.setColor( color );
if (Math.abs(dy) > Math.abs(dx)) {
double islope = dx / dy;
int y1 = coords.getTop() - 5;
int y2 = coords.getTop() + coords.getHeight() + 5;
int x1 = (int)(islope*(y1 - y) + x);
int x2 = (int)(islope*(y2 - y) + x);
if (Math.abs(x1) < 20000 && Math.abs(x2) < 20000)
for (int i = 0; i < lineWidth; i++)
g.drawLine(x1-lineWidth/2+i,y1,x2-lineWidth/2+i,y2);
}
else {
double slope = dy / dx;
int x1 = coords.getLeft() - 5;
int x2 = coords.getLeft() + coords.getWidth() + 5;
int y1 = (int)(slope*(x1 - x) + y);
int y2 = (int)(slope*(x2 - x) + y);
if (Math.abs(y1) < 20000 && Math.abs(y2) < 20000)
for (int i = 0; i < lineWidth; i++)
g.drawLine(x1,y1-lineWidth/2+i,x2,y2-lineWidth/2+i);
}
}
 
 
} // end class DrawGeometric
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/Crosshair.java
0,0 → 1,55
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.data.*;
 
/**
* A Crosshair is a small cross, 15 pixels wide and high, that is drawn in
* a CoordinateRect at a specified point.
* A Crosshair is a Computable object, so should be added to a Controller to be
* recomputed when the coordinates of the point change.
*/
 
public class Crosshair extends DrawGeometric {
 
/**
* Create a cross that appears at the point with coordinates (x,y).
*/
public Crosshair(Value x, Value y) {
super(CROSS, x, y, 7, 7);
}
/**
* Create a cross that appears on the graph of the function y=f(x)
* at the point with coordinates (x,f(x)). f should be a function
* of one variable.
*/
public Crosshair(Value x, Function f) {
super(CROSS, x, new ValueMath(f,x), 7, 7);
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/LimitControlPanel.java
0,0 → 1,707
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import java.awt.*;
import java.util.Vector;
import java.awt.event.*;
import edu.hws.jcm.awt.*;
import edu.hws.jcm.data.*;
 
/**
* A LimitControlPanel has four input boxes for specifying the xmin, xmax, ymin, and ymax
* of a CoodinateRect. You can actually add more than one CoordinteRect to the LimitControlPanel.
* This will synchronize the coordinate systems on the all the CoordinateRects that is controlls.
*
* <p>A LimitControlPanel can also contain a number of standard buttons, such as buttons for
* zooming the coordinates in and out. The buttons are specfied using constants
* defined in this class. It is possible to obtain standard buttons so that they can
* be displayed outside the LimitControlPanel. Furthermore, it is also possible to add other components
* to the panel, using the addRange(), addComponent(), and addComponentPair() methods.
* (The standard add() method from the Component class is overridded to call
* addComponent().) Any VariableInput added to the LimitControl Panel will appear with its name
* as a label, just above the input box.
*
* <p>Ordinarily, all the components are just stacked up vertically. However, if
* you set the useTwoColumnsIfPossible property to true, then they will be in two columns, unless
* the width of the Panel is too small for two columns. Pairs of items added
* with addRange() or addComponentPair() will appear on the same row. An item
* added with addComponent() will appear on a row by itself. As for the standard
* buttons, the following pairs will appear together, IF they are added at the
* same time: SET_LIMITS and EQUALUIZE; ZOOM_IN and ZOOM_OUT; SAVE and RESTORE.
*
* <p>A LimitControlPanel can have an error reporter, which is used to report
* any errors that are found in the input boxes for xmin, xmax, ymin, ymax
* (or other VariableInputs added with addRange()). Except for these
* input boxes, other coponents are NOT checked for errors.
*/
 
public class LimitControlPanel extends Panel implements InputObject, Tieable, Limits, ActionListener {
 
/**
* A constant that can be used in the addButton() method to add a button to the LimitControlPanel.
* This represents a button that will set the limits using the values in the input boxes.
* (This is also done when the user presses return in one of the boxes.)
*/
public final static int SET_LIMITS = 1;
/**
* A constant that can be used in the addButton() method to add a button to the LimitControlPanel.
* This represents a button that will equalize the scales on the axes (of the first
* CoordinateRect that was added to this panel).
*/
public final static int EQUALIZE = 2;
/**
* A constant that can be used in the addButton() method to add a button to the LimitControlPanel.
* This represents a button that will zoom in on the center of the coordinate rect.
*/
public final static int ZOOM_IN = 4;
 
/**
* A constant that can be used in the addButton() method to add a button to the LimitControlPanel.
* This represents a button that will zoom out from the center of the coordinate rect.
*/
public final static int ZOOM_OUT = 8;
/**
* A constant that can be used in the addButton() method to add a button to the LimitControlPanel.
* This represents a button that will save the current limits, so they can be
* restored later with the restore button.
*/
public final static int SAVE = 16;
/**
* A constant that can be used in the addButton() method to add a button to the LimitControlPanel.
* This represents a button that will restore previously saved coordinates.
* The coords are those that were saved with the save button,
* or if none were saved in that way, then the original
* coordinates that the CoordinateRect had when it was created.
*/
public final static int RESTORE = 32;
/**
* A constant that can be used in the addButton() method to add all possible buttons to the LimitControlPanel.
*/
public final static int ALL_BUTTONS = 0x3F;
 
private final static String[] buttonNames = {
"Set Limits",
"Equalize Axes",
"Zoom In",
"Zoom Out",
"Save Limits",
"Restore Limits"
};
/**
* Set of installed buttons.
*/
protected int buttons;
/**
* Use two columns for display, if possible.
*/
protected boolean twoColumn;
 
/**
* The input boxes for the x- and y-value ranges.
*/
protected VariableInput xmin, xmax, ymin, ymax;
 
/**
* This is increased when the user changes the limits.
* (The -1 will make this LimitControlPanel get its limits
* from the first CoordinateRect that is added to it.)
* This variable is used to implement syncronization of limits
* with the limits on CoordinateRects.
*/
protected long serialNumber = -1;
/**
* A Tie holding this panel and the CoordinateRects that it controls.
*/
protected Tie syncWith;
 
/**
* For reporting errors in user input.
*/
protected ErrorReporter errorReporter;
/**
* The first CoordinateRect tied to this LimitControlPanel.
*/
protected CoordinateRect coords;
 
/**
* Vector of components and component pairs that have
* been added to this panel, including at least the xmin, xmax, ymin, ymax
* input boxes.
*/
protected Vector items = new Vector();
 
 
/**
* Create a LimitControlPanel containing input boxes labeled
* "xmin", "xmax", "ymin", "ymax" and a SET_LIMITS button. The
* components are shown in a single column.
*/
public LimitControlPanel() {
this("xmin","xmax","ymin","ymax",SET_LIMITS, false);
}
/**
* Create a LimitControlPanel containing input boxes labeled
* "xmin", "xmax", "ymin", "ymax" and whatever buttons are in the
* set specified by the first parameter.
*
* @param buttonsToAdd The set of buttons to be added to the panel. Can consist of one or
* more of the constants SET_LIMITS, EQUALIZE, ZOOM_IN, ZOOM_OUT, SAVE, and RESTORE,
* or'ed together.
* @param useTwoColumnsIfPossible If this is true, then the components in the panel will
* be arranged into two columns instead of one (assuming that there is room).
*/
public LimitControlPanel(int buttonsToAdd, boolean useTwoColumnsIfPossible) {
this("xmin","xmax","ymin","ymax",buttonsToAdd,useTwoColumnsIfPossible);
}
/**
* Create a LimitControlPanel containing input boxes labeled
* with the given names and containing whatever buttons are in the
* set buttonsToAdd. buttonsToAdd should be formed by or-ing together
* constants such as SET_LIMITS from this class. The last parameter
* specifies whether to show the components in two columns.
* @param xminName Name to be used as a label for the xmin input box.
* @param xmaxName Name to be used as a label for the xmax input box.
* @param yminName Name to be used as a label for the ymin input box.
* @param xmaxName Name to be used as a label for the ymax input box.
*
* @param buttonsToAdd The set of buttons to be added to the panel. Can consist of one or
* more of the constants SET_LIMITS, EQUALIZE, ZOOM_IN, ZOOM_OUT, SAVE, and RESTORE,
* or'ed together.
* @param useTwoColumnsIfPossible If this is true, then the components in the panel will
* be arranged into two columns instead of one (assuming that there is room).
*/
public LimitControlPanel(String xminName, String xmaxName, String yminName,
String ymaxName, int buttonsToAdd, boolean useTwoColumnsIfPossible) {
setLayout(null);
enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
xmin = new VariableInput(xminName,"-5");
xmax = new VariableInput(xmaxName,"5");
addRange(xmin,xmax);
ymin = new VariableInput(yminName,"-5");
ymax = new VariableInput(ymaxName,"5");
addRange(ymin,ymax);
addButtons(buttonsToAdd);
twoColumn = useTwoColumnsIfPossible;
}
/**
* Add a CoordinateRect to be controlled by this LimitControlPanel. When the user changes
* the limits in this LimitControlPanel, the limits are also changed on the CoordinateRect
* to match. If the limits on the CoordinateRect change for some other reason, then
* the limits in the panel are changed to match. If multiple CoordinateRects are added,
* the limits on all the CoordinateRects will be synchronized with each other and with
* the limits in the panel.
*/
public void addCoords(CoordinateRect coords) {
if (syncWith == null)
syncWith = new Tie(this);
syncWith.add(coords);
coords.setSyncWith(syncWith);
if (this.coords == null)
this.coords = coords;
}
/**
* Add the first CoordinateRect from the canvas to be controlled
* by this LimitControlPanel. (Just calls addCoords(canvas.getCoordinateRect()).)
*/
public void addCoords(DisplayCanvas canvas) {
addCoords(canvas.getCoordinateRect());
}
/**
* Set the ErrorReporter that is used to report errors in the
* user's input. Note that only the input boxes for
* xmin, xmax, ymin, and ymax and any VariableInputs
* added with the addRange() method are checked.
*
*/
public void setErrorReporter(ErrorReporter rep) {
errorReporter = rep;
}
/**
* Get the ErrorReporter that is used to report errors in the
* user's input. Note that only the input boxes for
* xmin, xmax, ymin, and ymax and any VariableInputs
* added with the addRange() method are checked.
*
*/
public ErrorReporter getErrorReporter() {
return errorReporter;
}
/**
* Set to true if you want the components to be shown in
* two columns (provided the panel is wide enough).
*
*/
public void setUseTwoColumnsIfPossible(boolean two) {
twoColumn = two;
}
/**
* Get the value of the "useTwoColumnsIfPossible" property of this panel.
*/
public boolean getUseTwoColumnsIfPossible() {
return twoColumn;
}
/**
* Add a component to the panel. If two-column format is used, it will
* be shown on a line by itself. Note that the component shouldn't be too
* wide, or it will make the Panel stretch. This component
* is NOT checked for input errors. If it is an input object
* or a computable, it should be added to a Controller. For an
* input object, some Controller should be set up to be notified when
* the value changes. (You have to do this by hand, even if you use JCMPanels!!)
*/
public void addComponent(Component c) {
super.add(c);
items.addElement(c);
}
/**
* Add two components to the panel. If two-column format is used, they will
* be shown on the same row. Note that the components shouldn't be too
* wide, or they will make the Panel stretch. These components
* are NOT checked for input errors. If they are input objects
* or computables, they should be added to another Controller. For an
* input object, some Controller should be set up to be notified when
* the value changes. (You have to do this by hand, even if you use JCMPanels!!)
*/
public void addComponentPair(Component c1, Component c2) {
super.add(c1);
super.add(c2);
items.addElement( new Component[] { c1, c2 } );
}
/**
* Add two VariableInputs to the panel. These ARE checked for input when
* the user presses return or clicks the SET_LIMITS button.
* Furthermore, it is checked that the value in the second input box is greater than
* the value in the first, and an error is reported if it is not.
* This method is used to add the xmin, xmax, ymin, and ymax
* boxes. It could possibly be used to add tmin and tmax boxes
* for the limits on the parameter of a parametric curve,
* for example.
*/
public void addRange(final VariableInput v1, final VariableInput v2) {
super.add(v1);
super.add(v2);
v1.addActionListener(this);
v2.addActionListener(this);
items.addElement( new Component[] { v1, v2, null } );
}
/**
* Add the buttons in buttonSet to the panel, if they are not
* already there. buttonSet should be formed by or-ing
* together some of the constants SET_LIMITS, ZOOM_IN, etc.
*/
public void addButtons(int buttonSet) {
if ( (buttonSet & SET_LIMITS) != 0 && (buttons & SET_LIMITS) == 0
&& (buttonSet & EQUALIZE) != 0 && (buttons & EQUALIZE) == 0 )
addComponentPair( makeButton(0), makeButton(1) );
else if ( (buttonSet & SET_LIMITS) != 0 && (buttons & SET_LIMITS) == 0 )
addComponent( makeButton(0) );
else if ( (buttonSet & EQUALIZE) != 0 && (buttons & EQUALIZE) == 0 )
addComponent( makeButton(1) );
if ( (buttonSet & ZOOM_IN) != 0 && (buttons & ZOOM_IN) == 0
&& (buttonSet & ZOOM_OUT) != 0 && (buttons & ZOOM_OUT) == 0 )
addComponentPair( makeButton(2), makeButton(3) );
else if ( (buttonSet & ZOOM_IN) != 0 && (buttons & ZOOM_IN) == 0 )
addComponent( makeButton(2) );
else if ( (buttonSet & ZOOM_OUT) != 0 && (buttons & ZOOM_OUT) == 0 )
addComponent( makeButton(3) );
if ( (buttonSet & SAVE) != 0 && (buttons & SAVE) == 0
&& (buttonSet & RESTORE) != 0 && (buttons & RESTORE) == 0 )
addComponentPair( makeButton(4), makeButton(5) );
else if ( (buttonSet & SAVE) != 0 && (buttons & SAVE) == 0 )
addComponent( makeButton(4) );
else if ( (buttonSet & RESTORE) != 0 && (buttons & RESTORE) == 0 )
addComponent( makeButton(5) );
buttons = buttons | buttonSet;
}
/**
* Get a Button corresponding to one of the six button types defined by the constants
* SET_LIMITS, EQUALIZE, ZOOM_IN, ZOOM_OUT, SAVE, and RESTORE in this class. The button
* can be added to a different panel, but it will still affect this LimitControlPanel in
* the usual way. It is possible to change the name of the button, and it will still
* work correctly. Each call to this method creates a new button, even if multiple buttons
* of the same type are created.
*
* @param buttonCode one of the constants from this class (SET_LIMITS, EQUALIZE, etc.) specifying
* one of the types of button for controlling limits. If the parameter is not one of
* these constants, and IllegalArgumentException will be thrown.
*/
public Button getButton(int buttonCode) {
int buttonNum;
if (buttonCode == SET_LIMITS)
buttonNum = 0;
else if (buttonCode == EQUALIZE)
buttonNum = 1;
else if (buttonCode == ZOOM_IN)
buttonNum = 2;
else if (buttonCode == ZOOM_OUT)
buttonNum = 3;
else if (buttonCode == SAVE)
buttonNum = 4;
else if (buttonCode == RESTORE)
buttonNum = 5;
else
throw new IllegalArgumentException("Unknown button code passed to getButton().");
Button b = makeButton(buttonNum);
b.setActionCommand(buttonNames[buttonNum]); // So command won't change if button name is changed.
return b;
}
// ---------------- Implementation details ------------------------------------------
private Button makeButton(int i) {
// Make one of the limit control buttons. Parameter is an index into the buttonNames
// array, not one of the constants SET_LIMITS, EQUALIZE, etc.
Button b = new Button(buttonNames[i]);
b.setBackground(Color.lightGray);
b.addActionListener(this);
return b;
}
/**
* Redefine this method from the Component class to make it a synonym for addComponent(c);
*/
public Component add(Component c) {
// Redefine this, in case someone uses it.
addComponent(c);
return c;
}
/**
* Method required by CheckInput interface. In this class, it does nothing because
* responses to inputs are handled by the LimitControlPanel itself.
*/
public void notifyControllerOnChange(Controller c) {
}
/**
* Check the input boxes in this panel. This is generally not meant to be
* called from outside this class, except by a Controller.
*/
public void checkInput() {
try {
boolean changed = false;
for (int i = 0; i < items.size(); i++) {
Object obj = items.elementAt(i);
if (obj instanceof Component[] && ((Component[])obj).length == 3) {
VariableInput v1 = (VariableInput)((Component[])obj)[0];
VariableInput v2 = (VariableInput)((Component[])obj)[1];
double x, x1, x2;
x = v1.getVal();
v1.checkInput();
x1 = v1.getVal();
if (x != x1)
changed = true;
x = v2.getVal();
v2.checkInput();
x2 = v2.getVal();
if (x != x2)
changed = true;
if (x1 >= x2)
throw new JCMError("The value of " + v2.getName() + " must be greater than the value of " +
v1.getName() + ".", v2);
}
}
if (errorReporter != null)
errorReporter.clearErrorMessage();
if (changed) {
serialNumber++;
if (syncWith != null)
syncWith.check();
}
}
catch (JCMError e) {
if (errorReporter != null)
errorReporter.setErrorMessage(null,e.getMessage());
else
System.out.println("***** Error: " + e.getMessage());
if (e.object instanceof TextField) {
((TextField)e.object).selectAll();
((TextField)e.object).requestFocus();
}
}
catch(RuntimeException e) {
if (errorReporter != null)
errorReporter.setErrorMessage(null,e.toString());
e.printStackTrace();
}
}
 
/**
* Part of the Tieable interface, and not meant to be called directly.
*/
public long getSerialNumber() {
return serialNumber;
}
/**
* Part of the Tieable interface, and not meant to be called directly.
*/
public void sync(Tie t, Tieable newest) {
if (newest == this)
return;
if ( ! (newest instanceof Tieable) )
throw new IllegalArgumentException("Internal Error: A LimitControlPanel can only sync with a Limits object.");
setLimits(((Limits)newest).getLimits());
serialNumber = newest.getSerialNumber();
}
/**
* Get the values in the xmin, xmax, ymin, and ymax input boxes. Note that this can
* throw a JCMError.
*/
public double[] getLimits() {
double[] limits = new double[4];
limits[0] = xmin.getVal();
limits[1] = xmax.getVal();
limits[2] = ymin.getVal();
limits[3] = ymax.getVal();
return limits;
}
/**
* Set the values in the xmin, xmax, ymin, and ymax input boxes.
*/
public void setLimits(double[] limits) {
if (limits == null || limits.length < 4)
throw new IllegalArgumentException("Internal Error: Not enough values supplied for setLimits.");
for (int i = 0; i < 4; i++)
if (Double.isNaN(limits[i]) || Double.isInfinite(limits[i]))
return;
boolean changed = false;
if (limits[0] != xmin.getVal()) {
changed = true;
xmin.setVal(limits[0]);
}
if (limits[1] != xmax.getVal()) {
changed = true;
xmax.setVal(limits[1]);
}
if (limits[2] != ymin.getVal()) {
changed = true;
ymin.setVal(limits[2]);
}
if (limits[3] != ymax.getVal()) {
changed = true;
ymax.setVal(limits[3]);
}
if (changed)
serialNumber++;
}
/**
* Handle a click on one of the standard buttons.
* Not meant to be called directly.
*/
public void actionPerformed(ActionEvent evt) {
String cmd = evt.getActionCommand();
if (evt.getSource() instanceof VariableInput || cmd.equals(buttonNames[0]))
checkInput();
else if (coords == null)
return;
else if (cmd.equals(buttonNames[1]))
coords.equalizeAxes();
else if (cmd.equals(buttonNames[2]))
coords.zoomIn();
else if (cmd.equals(buttonNames[3]))
coords.zoomOut();
else if (cmd.equals(buttonNames[4]))
coords.setRestoreBuffer();
else if (cmd.equals(buttonNames[5]))
coords.restore();
}
/**
* Draw the input box labels.
* Not meant to be called directly.
*/
public void paint(Graphics g) {
int n = getComponentCount();
for (int i = 0; i < n; i++) {
Component c = getComponent(i);
if (c instanceof VariableInput) {
Point topLeft = c.getLocation();
g.drawString( c.getName(), topLeft.x + 4, topLeft.y - 4 );
}
}
}
/**
* Compute the preferred size of this panel.
* Not meant to be called directly.
*/
public Dimension getPreferredSize() {
int width = 0;
int height = 5;
FontMetrics fm = getFontMetrics(getFont());
int lineHeight = (fm == null)? 12 : 4 + fm.getAscent();
for (int i = 0; i < items.size(); i++) {
Object obj = items.elementAt(i);
if (obj instanceof Component) {
Component c = (Component)obj;
Dimension d = c.getPreferredSize();
height += d.height + 5;
if (c instanceof VariableInput)
height += lineHeight;
if (d.width > width)
width = d.width;
}
else {
Component[] pair = (Component[])obj;
Dimension d1 = pair[0].getPreferredSize();
if (pair[0] instanceof VariableInput)
d1.height += lineHeight;
Dimension d2 = pair[1].getPreferredSize();
if (pair[1] instanceof VariableInput)
d2.height += lineHeight;
if (twoColumn) {
width = Math.max(width,d1.width+d2.width);
height = height + Math.max(d1.height,d2.height) + 5;
}
else {
height += d1.height + d2.height + 10;
width = Math.max(width,d1.width);
height = Math.max(height,d2.height) ;
}
}
}
return new Dimension(width + (twoColumn? 15 : 10), height);
}
/**
* Recompute component locations when the panel is resized.
* Not meant to be called directly.
*/
public void processComponentEvent(ComponentEvent evt) {
if (evt.getID() == ComponentEvent.COMPONENT_RESIZED) {
Dimension size = getSize();
Dimension preferredSize = getPreferredSize();
boolean two = twoColumn; // Do we really use two columns?
if (two && size.width < preferredSize.width - 20) {
two = false;
twoColumn = false;
preferredSize = getPreferredSize();
twoColumn = true;
}
int count = items.size();
if (!two)
for (int i = 0; i < items.size(); i++)
if (items.elementAt(i) instanceof Component[])
count++;
double scale, vspace;
if (size.height >= preferredSize.height) {
scale = 1;
vspace = 5 + (size.height - preferredSize.height)/(count+2);
if (vspace > 15)
vspace = 15;
}
else if (size.height >= preferredSize.height - 4*(count+2)) {
scale = 1;
vspace = (size.height - (preferredSize.height - 5*(count+2)))/(count+2);
}
else {
scale = (double)size.height / (preferredSize.height - 4*(count+2));
vspace = 1;
}
int hspace = (size.width - (preferredSize.width - (two? 15 : 10)))/(two? 3 : 2);
if (hspace < 1)
hspace = 1;
else if (hspace > 10)
hspace = 10;
double y = vspace;
int lineHeight = 4 + (getFontMetrics(getFont())).getAscent();
for (int i = 0; i < items.size(); i++) {
Object obj = items.elementAt(i);
if (obj instanceof Component) {
Component c = (Component)obj;
Dimension p = c.getPreferredSize();
if (c instanceof VariableInput)
y += lineHeight*scale;
if (p.width + 2*hspace < size.width - 10)
c.setBounds((size.width - p.width)/2, (int)y, p.width, (int)(p.height*scale));
else
c.setBounds(hspace, (int)y, p.width - 2*hspace, (int)(p.height*scale));
y += scale*(p.height) + vspace;
}
else {
Component[] pair = (Component[])obj;
Dimension d1 = pair[0].getPreferredSize();
Dimension d2 = pair[1].getPreferredSize();
if (two) {
if (pair[0] instanceof VariableInput || pair[1] instanceof VariableInput)
y += lineHeight*scale;
int h = (int)(scale*Math.max(d1.height,d2.height));
pair[0].setBounds(hspace,(int)y,(size.width-3*hspace)/2,h);
pair[1].setBounds(hspace*2+(size.width-3*hspace)/2,(int)y,(size.width-3*hspace)/2,h);
y += scale*Math.max(d1.height,d2.height) + vspace;
}
else {
if (pair[0] instanceof VariableInput)
y += lineHeight*scale;
pair[0].setBounds(hspace,(int)y,size.width-2*hspace,(int)(d1.height*scale));
y += d1.height*scale + vspace;
if (pair[1] instanceof VariableInput)
y += lineHeight*scale;
pair[1].setBounds(hspace,(int)y,size.width-2*hspace,(int)(d2.height*scale));
y += d2.height*scale + vspace;
}
}
}
}
super.processComponentEvent(evt);
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/Axes.java
0,0 → 1,556
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.data.NumUtils;
import java.awt.*;
 
/**
* A set of horizontal and vertical axes that look OK and
* have reasonable, labeled tick marks. The number and spacing of tick
* marks changes depending on the scale on the axes. (The heuristics
* for computing this could use some improvement.)
*/
public class Axes extends Drawable {
 
/**
* Creates axes with no names on the axes.
*/
public Axes() {
this(null,null);
}
/**
* Creates axes with given names on the axes.
*
* @param xlabel Label for x axis. If the value is null, no label is drawn.
* @param ylabel Label for y axis. If the value is null, no label is drawn.
*/
public Axes(String xLabel, String yLabel) {
this.xLabel = xLabel;
this.yLabel = yLabel;
}
/**
* A constant that can be used in the setYAxisPosition() method to indicate the placement of the y-axis.
* The axis is placed at the top of the CoordinateRect.
*/
public static final int TOP = 0;
 
/**
* A constant that can be used in the setYAxisPosition() method to indicate the placement of the y-axs.
* The axis is placed at the bottom of the CoordinateRect.
*/
public static final int BOTTOM = 1;
 
/**
* A constant that can be used in the setXAxisPosition() method to indicate the placement of the x-axis.
* The axis is placed at the left edge of the CoordinateRect.
*/
public static final int LEFT = 2;
 
/**
* A constant that can be used in the setXAxisPosition() method to indicate the placement of the x-axis.
* The axis is placed at the right edge of the CoordinateRect.
*/
public static final int RIGHT = 3;
 
/**
* A constant that can be used in the setXAxisPosition() and setYAxisPosition() methods to indicate the placement of the axes.
* The axis is placed in the center of the CoordinateRect.
*/
public static final int CENTER = 4;
 
/**
* A constant that can be used in the setXAxisPosition() and setYAxisPosition() methods to indicate the placement of the axes.
* The axis is placed at its true x- or y-position, if that lies within the range of values shown on the CoordinateRect.
* Otherwise, it is placed along an edge of the CoordinateRect. This is the default value for axis placement.
*/
public static final int SMART = 5;
 
private int xAxisPosition = SMART;
private int yAxisPosition = SMART;
private Color axesColor = new Color(0,0,180);
private Color lightAxesColor = new Color(180,180,255); // Used if real axis is outside the draw rect
private Color labelColor = Color.black;
private String xLabel = null;
private String yLabel = null;
//------------------ Methods for getting/setting properties ----------------
/**
* Get the color that is used for drawing the axes, when they are drawn in their true position.
*/
public Color getAxesColor() {
return axesColor;
}
/**
* Set the color that is used for drawing the axes, when they are drawn in their true position.
* The default is blue.
*/
public void setAxesColor(Color c) {
if (c != null && !c.equals(axesColor)) {
axesColor = c;
needsRedraw();
}
}
/**
* Get the color that is used for drawing an axis, when it is drawn along an edge of the CoordinateRect
* instead of in its proper x- or y-position.
*/
public Color getLightAxesColor() {
return lightAxesColor;
}
/**
* Get the color that is used for drawing an axis, when it is drawn along an edge of the CoordinateRect
* instead of in its proper x- or y-position. The default is a light blue.
*/
public void setLightAxesColor(Color c) {
if (c != null && !c.equals(lightAxesColor)) {
lightAxesColor = c;
needsRedraw();
}
}
 
/**
* Get the color that is used for drawing the labels on the x- and y-axes.
*/
public Color getLabelColor() {
return labelColor;
}
/**
* Set the color that is used for drawing the labels (usually the names of the variables) on the x- and y-axes.
* The default is black.
*/
public void setLabelColor(Color c) {
if (c != null && !c.equals(labelColor)) {
labelColor = c;
if (xLabel != null || yLabel != null)
needsRedraw();
}
}
 
/**
* Get the positioning constant that tells where the x-axis is drawn. This can be LEFT, RIGHT, CENTER, or SMART.
*/
public int getXAxisPosition() {
return xAxisPosition;
}
/**
* Set the positioning constant that tells where the x-axis is drawn. This can be LEFT, RIGHT, CENTER, or SMART.
* The default is SMART.
*/
public void setXAxisPosition(int pos) {
if ((pos == TOP || pos == BOTTOM || pos == CENTER || pos == SMART) && pos != xAxisPosition) {
xAxisPosition = pos;
needsRedraw();
}
}
 
/**
* Get the positioning constant that tells where the y-axis is drawn. This can be TOP, BOTTOM, CENTER, or SMART.
*/
public int getYAxisPosition() {
return yAxisPosition;
}
/**
* Set the positioning constant that tells where the y-axis is drawn. This can be TOP, BOTTOM, CENTER, or SMART.
* The default is SMART.
*/
public void setYAxisPosition(int pos) {
if ((pos == LEFT || pos == RIGHT || pos == CENTER || pos == SMART) && pos != yAxisPosition) {
yAxisPosition = pos;
needsRedraw();
}
}
 
/**
* Get the label that appears on the x-axis. If the value is null, no label appears.
*/
public String getXLabel() {
return xLabel;
}
/**
* Set the label that appears on the x-axis. If the value is null, no label appears. This is the default.
*/
public void setXLabel(String s) {
xLabel = s;
needsRedraw();
}
 
/**
* Get the label that appears on the y-axis. If the value is null, no label appears.
*/
public String getYLabel() {
return yLabel;
}
/**
* Set the label that appears on the y-axis. If the value is null, no label appears. This is the default.
*/
public void setYLabel(String s) {
yLabel = s;
needsRedraw();
}
 
//--------------------------------------------------------------------------
/**
* Draw the axes. This is not meant to be called directly.
*
*/
public void draw(Graphics g, boolean coordsChanged) {
if (coords == null)
return;
if (coordsChanged || xTicks == null
|| !g.getFont().equals(font)) { // The second test forces a setup() when the
// Axes object has been reloaded after serialization.
// The third test accounts for the fact that the
// font might have changed since the last time
// a setup() was done.
font = g.getFont();
FontMetrics fm = g.getFontMetrics(font);
setup(fm, coords.getXmin(), coords.getXmax(), coords.getYmin(), coords.getYmax(),
coords.getLeft(), coords.getTop(), coords.getWidth(), coords.getHeight(), coords.getGap());
}
doDraw(g, coords.getXmin(), coords.getXmax(), coords.getYmin(), coords.getYmax(),
coords.getLeft(), coords.getTop(), coords.getWidth(), coords.getHeight(), coords.getGap());
}
 
private void doDraw(Graphics g, double xmin, double xmax, double ymin, double ymax,
int left, int top, int width, int height, int gap) {
// Draw axes using data computed by setup(). The parameters come from the CoordinateRect.
if (xAxisPosition == SMART && (ymax < 0 || ymin > 0))
g.setColor(lightAxesColor);
else
g.setColor(axesColor);
g.drawLine(left + gap, xAxisPixelPosition, left + width - gap - 1, xAxisPixelPosition);
for (int i = 0; i < xTicks.length; i++) {
int a = (xAxisPixelPosition - 2 < top) ? xAxisPixelPosition : xAxisPixelPosition - 2;
int b = (xAxisPixelPosition + 2 >= top + height)? xAxisPixelPosition : xAxisPixelPosition + 2;
g.drawLine(xTicks[i], a, xTicks[i], b);
}
for (int i = 0; i < xTickLabels.length; i++)
g.drawString(xTickLabels[i], xTickLabelPos[i][0], xTickLabelPos[i][1]);
if (yAxisPosition == SMART && (xmax < 0 || xmin > 0))
g.setColor(lightAxesColor);
else
g.setColor(axesColor);
g.drawLine(yAxisPixelPosition, top + gap, yAxisPixelPosition, top + height - gap - 1);
for (int i = 0; i < yTicks.length; i++) {
int a = (yAxisPixelPosition - 2 < left) ? yAxisPixelPosition : yAxisPixelPosition - 2;
int b = (yAxisPixelPosition + 2 >= left + width)? yAxisPixelPosition : yAxisPixelPosition + 2;
g.drawLine(a, yTicks[i], b, yTicks[i]);
}
for (int i = 0; i < yTickLabels.length; i++)
g.drawString(yTickLabels[i], yTickLabelPos[i][0], yTickLabelPos[i][1]);
g.setColor(labelColor);
if (xLabel != null)
g.drawString(xLabel, xLabel_x, xLabel_y);
if (yLabel != null)
g.drawString(yLabel, yLabel_x, yLabel_y);
}
private transient int[] xTicks; // Data for drawing axes
private transient int[] yTicks;
private transient String[] xTickLabels;
private transient String[] yTickLabels;
private transient int[][] xTickLabelPos;
private transient int[][] yTickLabelPos;
private transient int xAxisPixelPosition, yAxisPixelPosition;
private transient int xLabel_x, xLabel_y, yLabel_x, yLabel_y;
private transient Font font;
private transient int ascent, descent, digitWidth;
void setup(FontMetrics fm, double xmin, double xmax, double ymin, double ymax,
int left, int top, int width, int height, int gap) {
// Set up all data for drawing the axes.
digitWidth = fm.charWidth('0');
ascent = fm.getAscent();
descent = fm.getDescent();
switch (xAxisPosition) {
case TOP:
xAxisPixelPosition = top + gap;
break;
case BOTTOM:
xAxisPixelPosition = top + height - gap - 1;
break;
case CENTER:
xAxisPixelPosition = top + height/2;
break;
case SMART:
if (ymax < 0)
xAxisPixelPosition = top + gap;
else if (ymin > 0)
xAxisPixelPosition = top + height - gap - 1;
else
xAxisPixelPosition = top + gap + (int)((height-2*gap - 1) * ymax / (ymax-ymin));
break;
}
switch (yAxisPosition) {
case LEFT:
yAxisPixelPosition = left + gap;
break;
case BOTTOM:
yAxisPixelPosition = left + width - gap - 1;
break;
case CENTER:
yAxisPixelPosition = left + width/2;
break;
case SMART:
if (xmax < 0)
yAxisPixelPosition = left + width - gap - 1;
else if (xmin > 0)
yAxisPixelPosition = left + gap;
else
yAxisPixelPosition = left + gap - (int)((width-2*gap - 1) * xmin / (xmax-xmin));
break;
}
if (xLabel != null) {
int size = fm.stringWidth(xLabel);
if (left + width - gap - size <= yAxisPixelPosition)
xLabel_x = left + gap;
else
xLabel_x = left + width - gap - size;
if (xAxisPixelPosition + 3 + ascent + descent + gap >= top + height)
xLabel_y = xAxisPixelPosition - 4;
else
xLabel_y = xAxisPixelPosition + 3 + ascent;
}
if (yLabel != null) {
int size = fm.stringWidth(yLabel);
if (yAxisPixelPosition + 3 + size + gap > left + width)
yLabel_x = yAxisPixelPosition - size - 3;
else
yLabel_x = yAxisPixelPosition + 3;
if (top + ascent + descent + gap > xAxisPixelPosition)
yLabel_y = top + height - gap - descent;
else
yLabel_y = top + ascent + gap;
}
double start = fudgeStart( ((xmax-xmin)*(yAxisPixelPosition - (left + gap)))/(width - 2*gap) + xmin,
0.05*(xmax-xmin) );
int labelCt = (width - 2*gap) / (10*digitWidth);
if (labelCt <= 2)
labelCt = 3;
else if (labelCt > 20)
labelCt = 20;
double interval = fudge( (xmax - xmin) / labelCt );
for (double mul = 1.5; mul < 4; mul += 0.5) {
if (fm.stringWidth(NumUtils.realToString(interval+start)) + digitWidth > (interval/(xmax-xmin))*(width-2*gap)) // overlapping labels
interval = fudge( mul*(xmax - xmin) / labelCt );
else
break;
}
double[] label = new double[50];
labelCt = 0;
double x = start + interval;
double limit = left + width;
if (xLabel != null && left + width - gap - fm.stringWidth(xLabel) > yAxisPixelPosition) // avoid overlap with xLabel
limit -= fm.stringWidth(xLabel) + gap + digitWidth;
while (labelCt < 50 && x <= xmax) {
if (left + gap + (width-2*gap)*(x-xmin)/(xmax-xmin) + fm.stringWidth(NumUtils.realToString(x))/2 > limit)
break;
label[labelCt] = x;
labelCt++;
x += interval;
}
x = start - interval;
limit = left;
if (xLabel != null && left + width - gap - fm.stringWidth(xLabel) <= yAxisPixelPosition) // avoid overlap with xLabel
limit += fm.stringWidth(xLabel) + digitWidth;
while (labelCt < 50 && x >= xmin) {
if (left + gap + (width-2*gap)*(x-xmin)/(xmax-xmin) - fm.stringWidth(NumUtils.realToString(x))/2 < limit)
break;
label[labelCt] = x;
labelCt++;
x -= interval;
}
xTicks = new int[labelCt];
xTickLabels = new String[labelCt];
xTickLabelPos = new int[labelCt][2];
for (int i = 0; i < labelCt; i++) {
xTicks[i] = (int)(left + gap + (width-2*gap)*(label[i]-xmin)/(xmax-xmin));
xTickLabels[i] = NumUtils.realToString(label[i]);
xTickLabelPos[i][0] = xTicks[i] - fm.stringWidth(xTickLabels[i])/2;
if (xAxisPixelPosition - 4 - ascent >= top)
xTickLabelPos[i][1] = xAxisPixelPosition - 4;
else
xTickLabelPos[i][1] = xAxisPixelPosition + 4 + ascent;
}
if(Math.abs(ymax-ymin)>100)
{
start = 0;
}
else
{
start = fudgeStart( ymax - ((ymax-ymin)*(xAxisPixelPosition - (top + gap)))/(height - 2*gap), 0.05*(ymax-ymin) );
}
labelCt = (height - 2*gap) / (5*(ascent+descent));
if (labelCt <= 2)
labelCt = 3;
else if (labelCt > 20)
labelCt = 20;
interval = fudge( (ymax - ymin) / labelCt );
labelCt = 0;
double y = start + interval;
limit = top + 8 + gap;
if (yLabel != null && top + gap + ascent + descent <= xAxisPixelPosition) // avoid overlap with yLabel
limit = top + gap + ascent + descent;
while (labelCt < 50 && y <= ymax) {
if (top + gap + (height-2*gap)*(ymax-y)/(ymax-ymin) - ascent/2 < limit)
break;
label[labelCt] = y;
labelCt++;
y += interval;
}
y = start - interval;
limit = top + height - gap - 8;
if (yLabel != null && top + gap + ascent + descent > xAxisPixelPosition) // avoid overlap with yLabel
limit = top + height - gap - ascent - descent;
while (labelCt < 50 && y >= ymin) {
if (top + gap + (height-2*gap)*(ymax-y)/(ymax-ymin) + ascent/2 > limit)
break;
label[labelCt] = y;
labelCt++;
y -= interval;
}
yTicks = new int[labelCt];
yTickLabels = new String[labelCt];
yTickLabelPos = new int[labelCt][2];
int w = 0; // max width of tick mark
for (int i = 0; i < labelCt; i++) {
yTickLabels[i] = NumUtils.realToString(label[i]);
int s = fm.stringWidth(yTickLabels[i]);
if (s > w)
w = s;
}
for (int i = 0; i < labelCt; i++) {
yTicks[i] = (int)(top + gap + (height-2*gap)*(ymax-label[i])/(ymax-ymin));
yTickLabelPos[i][1] = yTicks[i] + ascent/2;
if (yAxisPixelPosition - 4 - w < left)
yTickLabelPos[i][0] = yAxisPixelPosition + 4;
else
yTickLabelPos[i][0] = yAxisPixelPosition - 4 - fm.stringWidth(yTickLabels[i]);
}
} // end setup()
/**
* Translated directly from the Pascal version of xFunctions.
* Move x to a more "rounded" value; used for labeling axes.
*
* @param x the x coordinate used for labeling axes
* @return the rounded value of x
*/
double fudge (double x) {
int i, digits;
double y;
if (Math.abs(x) < 0.0005 || Math.abs(x) > 500000)
return x;
else if (Math.abs(x) < 0.1 || Math.abs(x) > 5000) {
y = x;
digits = 0;
if (Math.abs(y) >= 1) {
while (Math.abs(y) >= 8.75) {
y = y / 10;
digits = digits + 1;
}
}
else {
while (Math.abs(y) < 1) {
y = y * 10;
digits = digits - 1;
}
}
y = Math.round(y * 4) / 4;
if (digits > 0) {
for (int j = 0; j < digits; j++)
y = y * 10;
}
else if (digits < 0) {
for (int j = 0; j < -digits; j++)
y = y / 10;
}
return y;
}
else if (Math.abs(x) < 0.5)
return Math.round(10 * x) / 10.0;
else if (Math.abs(x) < 2.5)
return Math.round(2 * x) / 2.0;
else if (Math.abs(x) < 12)
return Math.round(x);
else if (Math.abs(x) < 120)
return Math.round(x / 10) * 10.0;
else if (Math.abs(x) < 1200)
return Math.round(x / 100) * 100.0;
else
return Math.round(x / 1000) * 1000.0;
}
private double fudgeStart(double a, double diff) {
// Adapted from the Pascal version of xFunctions.
// Tries to find a "rounded value" within diff of a.
if (Math.abs(Math.round(a) - a) < diff)
return Math.round(a);
for (double x = 10; x <= 100000; x *= 10) {
double d = Math.round(a*x) / x;
if (Math.abs(d - a) < diff)
return d;
}
return a;
}
 
 
} // end class Axes
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/edu/hws/jcm/draw/DisplayCanvas.java
0,0 → 1,935
/*************************************************************************
* *
* 1) This source code file, in unmodified form, and compiled classes *
* derived from it can be used and distributed without restriction, *
* including for commercial use. (Attribution is not required *
* but is appreciated.) *
* *
* 2) Modified versions of this file can be made and distributed *
* provided: the modified versions are put into a Java package *
* different from the original package, edu.hws; modified *
* versions are distributed under the same terms as the original; *
* and the modifications are documented in comments. (Modification *
* here does not include simply making subclasses that belong to *
* a package other than edu.hws, which can be done without any *
* restriction.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
package edu.hws.jcm.draw;
 
import edu.hws.jcm.awt.*;
import java.util.StringTokenizer;
import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
 
/**
* A DisplayCanvas is a drawing area that can contain one or more CoordinateRects.
* Each CoordinateRect can, in turn, contain Drawable items. If you only want
* one CoordinateRect that fills the whole canvas, you can for the most part
* ignore the CoordinateRect and work only with the canvas.
* The option of using an offscreen image for double buffering is provided.
* By default, this option is on.
* <p>If a DisplayCanvas is added to a
* Controller, then it will take care of calling the checkInput()
* and compute() methods of the InputObjects and Computables that
* it contains, so there is no need to add them individually to
* the Controller. If the DisplayCanvas is added to a JCMPanel, it
* is automatically added to the Controller for that JCMPanel.
* (On the other hand, if a DisplayCanvas is added to a Controller,
* this means that all the
* items in the DisplayCanvas will be recomputed, even if only some
* of them need to be.)
* <p>The canvas can display an error message that goes away
* when the canvas is clicked or when clearErrorMessage()
* is called. This allows the Canvas to be used as an
* ErrorReporter for a Controller or LimitControlPanel.
* <p>When any changes are made to the contents of the Canvas,
* doRedraw() must be called for those changes to take effect.
* Normally, doRedraw() is called by the CoordinateRect or by
* one of the Drawables in a CoordinateRect. Use doRedraw(CoordinateRect c)
* or doRedraw(int index) to redraw a single CoordinateRect. Note that
* repainting the canvas is not enough, because this will not automatically
* refresh the off-screen image.
*
*/
 
public class DisplayCanvas extends Canvas
implements ErrorReporter, InputObject, Computable {
 
 
private Vector coordinateRects;
// Contains all the CoordinateRects that have been added to this canvas.
// The elements are members of the private static nested class CRData.
private boolean useOffscreenCanvas = true; // If true, double buffering is used.
private boolean handleMouseZooms = false; // If true, clicking on a CoordinateRect
// will zoom in on the clicked point, or
// will zoom out if the shift key is down.
/**
* Create a DisplayCanvas with a white background containing no CoordinateRects.
*/
public DisplayCanvas() {
setBackground(Color.white);
enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
/**
* Create a DisplayCanvas with a white background and containing the
* specified CoordinateRect. The CoordinateRect fills the entire canvas.
*
* @param c The CoordinateRect that will fill the canvas. If c is null, no CoordinateRect is added to the canvas.
*/
public DisplayCanvas(CoordinateRect c) {
this();
if (c != null)
addCoordinateRect(c);
}
 
/**
* Release the memory used the by the off-screen image, if any, that is used for
* double-buffering. It's a good idea to call this if the DisplayCanvas is in
* an applet and the applet is stopped.
*/
public void releaseResources() {
OSC = null;
OSG = null;
}
 
/**
* Set the "handleMouseZooms" property of this DisplayCanvas. IF the value is true,
* then clicking on the canvas will zoom in on the point that is clicked and shift-clicking
* will zoom out from that point. Only the CoordinateRect, if any, that contains the point
* is zoomed. Furthermore, if the user clicks-and-drags, a rectangle
* is drawn. When the mouse is released, the interior of the rectangle is zoomed to fill
* the CoordinateRect. This property is false by default.
*/
public void setHandleMouseZooms(boolean handle) {
handleMouseZooms = handle;
}
/**
* Get the "handleMouseZooms" property of this DisplayCanvas, which determines whether the
* canvas reacts to mouse events by zooming the CoordinateRect that is clicked.
*/
public boolean getHandleMouseZooms() {
return handleMouseZooms;
}
/**
* Set the "useOffscreenCanvas" property of this DisplayCanvas. IF the value is true,
* an off-screen image is used for double buffering. This property is true by default.
*/
public boolean getUseOffscreenCanvas() {
return useOffscreenCanvas;
}
 
/**
* Get the "useOffscreenCanvas" property of this DisplayCanvas, which determines whether
* double-buffering is used.
*/
public void setUseOffscreenCanvas(boolean use) {
useOffscreenCanvas = use;
if (!use) {
OSC = null;
OSG = null;
}
}
// ----------- For managing CoordinateRects ------------------------
/**
* This private subclass of DisplayCanvas holds the data for one CoordinateRect
* contained in a DisplayCanvas.
*/
private static class CRData implements java.io.Serializable {
// Data for one coordinate rect
CoordinateRect coords;
double xmin, xmax, ymin, ymax;
// Values between 0 and 1 that
// specify the region of the canvas occupied by this
// CoordinateRect.
Color background; // Color to fill area with before drawing.
// If it's null, no fill is done. (The display color
// of the Canvas shows through.)
}
/**
* Add the specified Drawable item to the first CoordinateRect in this DisplayCanvas.
* If no CoordinateRect is associated with the canvas, one is created to fill the
* entire canvas.
*/
public void add(Drawable d) {
if (coordinateRects == null)
addCoordinateRect(new CoordinateRect());
CoordinateRect c = ((CRData)coordinateRects.elementAt(0)).coords;
c.add(d);
}
/**
* Add a Drawable item to one of the CoordinateRects associated with the Canvas.
*
* @param d The Drawable item to be added to a CoordinateRect
* @param coordRectIndex The index of the CoordinateRect, where the index of the first
* CoordinateRect that was added to the cavas is zero, the index of the second is one,
* and so on. A CoordinateRect with the specified index must already exist in the
* canvas, or an IllegalArgumentException is thrown.
*/
public void add(Drawable d, int coordRectIndex) {
if (coordinateRects == null || coordRectIndex < 0 || coordRectIndex >= coordinateRects.size())
throw new IllegalArgumentException("Internal programming error: CoordinateRect index (" + coordRectIndex + ")out of range.");
CoordinateRect c = ((CRData)coordinateRects.elementAt(coordRectIndex)).coords;
c.add(d);
}
 
/**
* Add the specified CoordinateRect to this DisplayCanvas, filling the entire canvas,
* and with background color equal to the background color of the canvas.
*
* @param c the CoordinateRect to be added. If null, an IllegalArgumentException is thrown.
*/
public void addCoordinateRect(CoordinateRect c) {
addCoordinateRect(c,0,1,0,1,null);
}
 
/**
* Add a CoordinateRect to the canvas, occupying a specified region of the canvas.
*
* @param coords The CoordinateRect to be added. If this is null, an IllegalArgumentExceptionis thrown.
* @param hmin Specifies the left edge of the CoordinateRect in the canvas, as a fraction of the size of the canvas.
* This must be in the range form 0 to 1, or an IllegalArgumentException is thrown.
* @param hmax Specifies the right edge of the CoordinateRect in the canvas, as a fraction of the size of the canvas.
* This must be in the range form 0 to 1 and must be strictly greater than hmin, or an IllegalArgumentException is thrown.
* @param vmin Specifies the top edge of the CoordinateRect in the canvas, as a fraction of the size of the canvas.
* This must be in the range form 0 to 1, or an IllegalArgumentException is thrown.
* @param vmax Specifies the bottom edge of the CoordinateRect in the canvas, as a fraction of the size of the canvas.
* This must be in the range form 0 to 1 and must be strictly greater than vmin, or an IllegalArgumentException is thrown.
* @param background The background color of the CoordinateRect. The CoordinateRect is filled with this color
* before the Drawables that it contains are drawn. If background is null, no filling takes place
* and the canvas shows through.
*/
public void addCoordinateRect(CoordinateRect coords, double hmin, double hmax,
double vmin, double vmax, Color background) {
if (hmin < 0 || hmin > 1 || hmax < 0 || hmax > 1 || hmin >= hmax ||
vmin < 0 || vmin > 1 || vmax < 0 || vmax > 1 || vmin >= vmax)
throw new IllegalArgumentException("Illegal values for area covered by CoordinateRect.");
if (coords == null)
throw new IllegalArgumentException("Can't add null CoordinateRect to DisplayCanvas.");
CRData c = new CRData();
c.coords = coords;
c.xmin = hmin;
c.xmax = hmax;
c.ymin = vmin;
c.ymax = vmax;
c.background = background;
if (coordinateRects == null)
coordinateRects = new Vector();
coordinateRects.addElement(c);
coords.setOwner(this);
}
/**
* Add a newly created CoordinateRect covering the specified section of
* the canvas. hmin, hmax, vmin, vmax must be in the range 0 to 1.
* The index of the new CoordinateRect is returned.
*/
public int addNewCoordinateRect(double hmin, double hmax, double vmin, double vmax) {
CoordinateRect c = new CoordinateRect();
addCoordinateRect(c,hmin,hmax,vmin,vmax,null);
return coordinateRects.size() - 1;
}
/**
* Add a newly created CoordinateRect covering the specified section of
* the canvas, with the specfied background color. hmin, hmax, vmin, vmax must be in the range 0 to 1.
* The index of the new CoordinateRect is returned.
*/
public int addNewCoordinateRect(double hmin, double hmax, double vmin, double vmax, Color background) {
CoordinateRect c = new CoordinateRect();
addCoordinateRect(c,hmin, hmax, vmin, vmax,background);
return coordinateRects.size() - 1;
}
/**
* Get the first CoordinateRect in this canvas. (If none exists, one is created and
* added to the canvas.)
*/
public CoordinateRect getCoordinateRect() {
return getCoordinateRect(0);
}
 
/**
* Get the i-th CoordinateRect in this DisplayCanvas. They are numbered staring from zero.
* If there is no i-th rect, null is returned, except that if there
* are NO coordinate rects and a request for rect 0 is received,
* then a new CoordinateRect is added to fill the entire canvas.
*/
public CoordinateRect getCoordinateRect(int i) {
if (i == 0 && (coordinateRects == null || coordinateRects.size() == 0))
addNewCoordinateRect(0,1,0,1);
if (coordinateRects == null || i < 0 || i >= coordinateRects.size())
return null;
else
return ((CRData)coordinateRects.elementAt(i)).coords;
}
/**
* Return CoordinateRect that contains the specified pixel, or
* null if there is none. The CoordinateRects are searched in
* reverse order, so that the "top" CoordinateRect at that point is
* returned. Note that this method only makes sense if the canvas
* has already been displayed.
* (Mostly, this is for internal use in this class.)
*/
public CoordinateRect findCoordinateRectAt(int pixelX, int pixelY) {
if (coordinateRects == null)
return null;
for (int i = coordinateRects.size() - 1; i >= 0; i--) {
CRData c = (CRData)coordinateRects.elementAt(i);
int width = getSize().width;
if (width <= 0)
return null;
int height = getSize().height;
int x = (int)(c.xmin*width);
int y = (int)(c.ymin*height);
int r = (int)(c.xmax*width);
int b = (int)(c.ymax*height);
if (pixelX >= x && pixelX < r && pixelY >= y && pixelY < b)
return c.coords;
}
return null;
}
/**
* Should be called whenever the contents of the canvas have changed and so
* it needs to need to be redrawn. (This causes the off-screen image to be redrawn.
* A simple call to repaint() does not do this.)
* If only one CoordinateRect needs to be repainted, you can call doRedraw(int i) or
* or doRedraw(CoordinateRect c), which can be more efficient than redrawing the whole canvas.
* If an error message is displayed, it will be cleared.
*/
synchronized public void doRedraw() {
// Should be called whenever the coordinate rects need to be repainted.
// If only one needs to be repainted, you can call doRedraw(int i) or
// or doRedraw(CoordinateRect c), which can be more efficient.
// If an error message is displayed, this will not take effect until
// the error message is cleared.
OSCvalid = false;
if (errorMessage != null)
clearErrorMessage(); // does repaint
else
repaint();
}
/**
* To be called when the contents of one of the CordinateRects have changed and so
* it needs to need to be redrawn. (This causes the off-screen image to be redrawn.
* A simple call to repaint() does not do this.)
* If an error message is displayed, it will be cleared.
*
* @param coordRectIndex The index of the CoordinateRect to be redrawn, where the first CoordinateRect is at index zero.
* If there is no such CoordinateRect, then nothing is done.
*/
synchronized public void doRedraw(int coordRectIndex) {
if (coordinateRects != null && coordRectIndex >= 0 && coordRectIndex < coordinateRects.size()) {
CRData c = (CRData)coordinateRects.elementAt(coordRectIndex);
OSCvalid = false;
if (errorMessage != null)
clearErrorMessage(); // does repaint
else {
int width = getSize().width;
int height = getSize().height;
int x = (int)(c.xmin*width);
int y = (int)(c.ymin*height);
int w = (int)(c.xmax*width) - x;
int h = (int)(c.ymax*height) - y;
repaint(x,y,w,h);
}
}
}
/**
* To be called when the contents of one of the CordinateRects have changed and so
* it needs to need to be redrawn. (This causes the off-screen image to be redrawn.
* A simple call to repaint() does not do this.)
* If an error message is displayed, it will be cleared.
*
* @param coords The CoordinateRect to be redrawn. If coords is not in this DisplayCanvas, nothing is done.
*/
synchronized public void doRedraw(CoordinateRect coords) {
int size = (coordinateRects == null)? -1 : coordinateRects.size();
for (int i = 0; i < size; i++)
if (((CRData)coordinateRects.elementAt(i)).coords == coords) {
doRedraw(i);
break;
}
}
 
//------------------- InputObject/Computable interfaces ---------------------
/**
* This is generally called by a Controller. It calls the checkInput() method of
* any InputObject displayed on this Canvas.
*/
synchronized public void checkInput() {
if (coordinateRects != null) {
int top = coordinateRects.size();
for (int i = 0; i < top; i++)
((CRData)coordinateRects.elementAt(i)).coords.checkInput();
}
}
/**
* This is generally called by a Controller. It calls the compute() method of
* any InputObject displayed on this Canvas.
*/
synchronized public void compute() {
if (coordinateRects != null) {
int top = coordinateRects.size();
for (int i = 0; i < top; i++)
((CRData)coordinateRects.elementAt(i)).coords.compute();
}
}
/**
* Method required by InputObject interface; in this class, calls the same method
* recursively on any CoordinateRects contained in this DisplayCanvas. This is meant to
* be called by JCMPanel.gatherInputs().
*/
public void notifyControllerOnChange(Controller c) {
if (coordinateRects != null) {
int top = coordinateRects.size();
for (int i = 0; i < top; i++)
((CRData)coordinateRects.elementAt(i)).coords.notifyControllerOnChange(c);
}
}
 
//-------------------- Error Reporter Stuff ------------------------------------
 
/**
* Get color that is used as a background when the canvas displays an error message.
*/
public Color getErrorBackground() {
return errorBackground;
}
/**
* Set color to be used as a background when the canvas displays an error message.
* The default is a light green. If the specified Color value is null, nothing is done.
*/
public void setErrorBackground(Color c) {
if (c != null)
errorBackground = c;
}
/**
* Get color that is used for the text when the canvas displays an error message.
*/
public Color getErrorForeground() {
return errorForeground;
}
/**
* Set color to be used for the text when the canvas displays an error message.
* The default is a dark green. If the specified Color value is null, nothing is done.
*/
public void setErrorForeground(Color c) {
if (c != null)
errorForeground = c;
}
 
/**
* Get the error message that is currently displayed on the canvas. If no error
* is displyed, the return value is null.
*/
synchronized public String getErrorMessage() {
return errorMessage;
}
 
/**
* Set an error message to be displayed on the canvas. This method is generally called by
* a Controller or a LimitControlPanel. If you call it directly, use null as the first parameter.
*
* @param c The Controller, if any, that is calling this routine. This controller will be notified
* when the error message is cleared. If the method is not being called by a contrller, this
* parameter should be set to null.
* @param message The error message to be displayed. If the value is null or is a blank string,
* the current message, if any, is cleared.
*/
synchronized public void setErrorMessage(Controller c, String message) {
if (message == null || message.trim().length() == 0) {
if (errorMessage != null) {
clearErrorMessage();
if (errorSource != c)
errorSource.errorCleared();
repaint();
}
}
else {
errorMessage = message.trim();
errorSource = c;
OSCvalid = false;
repaint();
}
}
 
/**
* Clear the error message, if any, that is currently displayed on the canvas.
*/
synchronized public void clearErrorMessage() {
if (errorMessage == null)
return;
errorMessage = null;
if (errorSource != null)
errorSource.errorCleared();
errorSource = null;
repaint();
}
 
// ---------------------- ErrorReporter Implementation ----------------------------
 
private Color errorBackground = new Color(220,255,220);
private Color errorForeground = new Color(0,120,0);
private String errorMessage;
private Controller errorSource;
private Draggable dragged; // The draggable object, if any, that is being dragged.
 
/**
* This has been overridden to handle the mouse zoom feature.
* Not meant to be called directly.
*/
public void processMouseEvent(MouseEvent evt) {
// If an error message is displayed, get rid of it and
// ignore the mouse click.
if (evt.getID() == MouseEvent.MOUSE_PRESSED) {
dragging = false; // Shouldn't be possible, but some old, buggy versions of Java made it so.
dragged = null;
if (errorMessage != null) {
if (errorSource != null)
errorSource.errorCleared();
errorSource = null;
errorMessage = null;
repaint();
evt.consume();
return;
}
CoordinateRect c = findCoords(evt);
if (c != null)
dragged = c.checkDraggables(evt);
if (dragged != null)
return;
if (handleMouseZooms && !(evt.getClickCount() > 1 || evt.isAltDown() || evt.isMetaDown() || evt.isControlDown())) {
super.processMouseEvent(evt);
if (!evt.isConsumed())
doMouseZoom_pressed(evt);
return;
}
}
else if (evt.getID() == MouseEvent.MOUSE_RELEASED && handleMouseZooms && dragged != null) {
dragged.finishDrag(evt);
dragged = null;
return;
}
else if (evt.getID() == MouseEvent.MOUSE_RELEASED && handleMouseZooms && dragging) {
doMouseZoom_released(evt);
return;
}
super.processMouseEvent(evt);
}
/**
* This has been overridden to handle the mouse zoom feature.
* Not meant to be called directly.
*/
public void processMouseMotionEvent(MouseEvent evt) {
if (dragged != null && evt.getID() == MouseEvent.MOUSE_DRAGGED)
dragged.continueDrag(evt);
else if (dragging && evt.getID() == MouseEvent.MOUSE_DRAGGED)
doMouseZoom_moved(evt);
else
super.processMouseMotionEvent(evt);
}
 
private void drawErrorMessage(Graphics g) {
if (errorMessage == null)
return;
 
Font font = new Font("Helvetica",Font.BOLD,12);
FontMetrics fm = g.getFontMetrics(font);
int width = getSize().width;
int height = getSize().height;
int lineHeight = fm.getHeight();
int leading = fm.getLeading();
int messageWidth = width - 80;
int left = 30;
int maxLines = (height - 60 - lineHeight) / lineHeight;
if (maxLines <= 0)
maxLines = 1;
StringTokenizer t = new StringTokenizer(errorMessage, " \t\r\n");
int lineCt = 0;
String[] errorMessageList = new String[maxLines];
String line = " "; // indent first line
while (t.hasMoreTokens()) {
String word = t.nextToken();
if (fm.stringWidth(word) > messageWidth) {
String w = "";
int dots = fm.stringWidth("...");
for (int c = 0; c < word.length(); c++) {
w += word.charAt(c);
if (fm.stringWidth(w) + dots > messageWidth)
break;
}
word = w;
}
String linePlusWord = line + " " + word;
if (fm.stringWidth(linePlusWord) > messageWidth) {
errorMessageList[lineCt] = line;
lineCt++;
if (lineCt == maxLines)
break;
line = word;
}
else {
line = linePlusWord;
}
}
if (lineCt < maxLines) {
errorMessageList[lineCt] = line;
lineCt++;
}
if (lineCt == 1)
errorMessageList[0] += " "; // for proper centering
int boxWidth = width - 60;
int boxHeight = (lineCt+1)*lineHeight + 50;
int top = height/2 - boxHeight/2;
if (top < 0)
top = 0;
g.setColor(getBackground());
g.fillRect(0,0,width,height);
g.setColor(errorBackground);
g.fillRect(left,top,boxWidth,boxHeight);
g.setColor(errorForeground);
g.drawRect(left,top,boxWidth,boxHeight);
g.drawRect(left+1,top+1,boxWidth-2,boxHeight-2);
g.drawLine(left,top + 23 + lineHeight, left + boxWidth - 2, top + 23 + lineHeight);
g.drawLine(left,top + 24 + lineHeight, left + boxWidth - 2, top + 24 + lineHeight);
g.setFont(font);
g.drawString("ERROR MESSAGE",width/2 - fm.stringWidth("(Error Message)")/2, top + 10 + lineHeight);
if (lineCt == 1)
g.drawString(errorMessageList[0], width/2 - fm.stringWidth(errorMessageList[0])/2, top + 35 + 2*lineHeight);
else {
for (int i = 0; i < lineCt; i++) {
g.drawString(errorMessageList[i], left + 10, top + 35 + (i+2)*lineHeight - leading);
}
}
} // end drawErrorMessage();
 
// ------------ Handle Mouse Zooming -----------------------------------------
private transient boolean dragging, draggingZoomWindow;
private transient CRData draggingInRect;
private transient int dragXmax, dragXmin, dragYmax, dragYmin;
private transient int lastX, lastY, startX, startY;
private CoordinateRect findCoords(MouseEvent evt) {
// Find coord rect containing the mouse.
int xMouse = evt.getX();
int yMouse = evt.getY();
int size = (coordinateRects == null)? -1 : coordinateRects.size();
int width = getSize().width;
int height = getSize().height;
for (int i = size-1; i >= 0; i--) {
CRData c = (CRData)coordinateRects.elementAt(i);
double xmin = (int)(c.xmin*width);
double ymin = (int)(c.ymin*height);
double xmax = (int)(c.xmax*width) - 1;
double ymax = (int)(c.ymax*height) - 1;
if (xMouse >= xmin && xMouse <= xmax && yMouse >= ymin && yMouse <= ymax)
return c.coords;
}
return null;
}
private synchronized void doMouseZoom_pressed(MouseEvent evt) {
// Called from processMouseEvent, above.
// Ignore multiple clicks and clicks with other than button 1
// and clicks modified with any key except shift.
if (evt.getClickCount() > 1 || evt.isAltDown() || evt.isMetaDown() || evt.isControlDown())
return;
int xMouse = evt.getX();
int yMouse = evt.getY();
int size = (coordinateRects == null)? -1 : coordinateRects.size();
int width = getSize().width;
int height = getSize().height;
for (int i = size-1; i >= 0; i--) {
CRData c = (CRData)coordinateRects.elementAt(i);
dragXmin = (int)(c.xmin*width);
dragYmin = (int)(c.ymin*height);
dragXmax = (int)(c.xmax*width) - 1;
dragYmax = (int)(c.ymax*height) - 1;
if (xMouse >= dragXmin && xMouse <= dragXmax && yMouse >= dragYmin && yMouse <= dragYmax) {
dragging = true;
draggingZoomWindow = false;
draggingInRect = c;
startX = xMouse;
startY = yMouse;
lastX = xMouse;
lastY = yMouse;
break;
}
}
}
private synchronized void doMouseZoom_released(MouseEvent evt) {
Graphics g = getGraphics();
putDragRect(g);
g.dispose();
CoordinateRect c = draggingInRect.coords;
if ( (Math.abs(lastX - startX) < 4 && Math.abs(lastY - startY) < 4)
|| Math.abs(startX - lastX) < 2 || Math.abs(startY - lastY) < 2 ) {
if (draggingZoomWindow)
return;
if (evt.isShiftDown())
c.zoomOutFromPixel(startX,startY);
else
c.zoomInOnPixel(startX,startY);
}
else {
c.setLimits( c.pixelToX(startX), c.pixelToX(lastX), c.pixelToY(startY), c.pixelToY(lastY) );
}
dragging = false;
}
private synchronized void doMouseZoom_moved(MouseEvent evt) {
Graphics g = getGraphics();
putDragRect(g);
lastX = evt.getX();
lastY = evt.getY();
putDragRect(g);
g.dispose();
}
private void putDragRect(Graphics g) { // (Assume dragging = true)
if (lastX < dragXmin)
lastX = dragXmin;
if (lastX > dragXmax)
lastX = dragXmax;
if (lastY < dragYmin)
lastY = dragYmin;
if (lastY > dragYmax)
lastY = dragYmax;
if ( (Math.abs(startX - lastX) < 4 && Math.abs(startY - lastY) < 4)
|| Math.abs(startX - lastX) < 2 || Math.abs(startY - lastY) < 2 )
return;
draggingZoomWindow = true;
Color bc = draggingInRect.background;
if (bc == null)
bc = getBackground();
g.setXORMode(bc);
if (bc.getRed() <= 100 && bc.getGreen() <= 100 && bc.getBlue() <= 150)
g.setColor(Color.white);
else
g.setColor(Color.black);
int x, y, w, h;
if (startX < lastX) {
x = startX;
w = lastX - startX;
}
else {
x = lastX;
w = startX - lastX;
}
if (startY < lastY) {
y = startY;
h = lastY - startY;
}
else {
y = lastY;
h = startY - lastY;
}
g.drawRect(x,y,w,h);
g.setPaintMode();
}
//--------- More implementation details... ----------------------------------
/**
* This has been overridden to return a default size of 350-by-350 pixels.
* Not usually called directly.
*/
public Dimension getPreferredSize() {
return new Dimension(350,350);
}
 
private transient Image OSC;
private transient Graphics OSG;
private transient boolean OSCvalid;
private transient int OSCwidth = -1, OSCheight = -1;
private void drawCoordinateRects(Graphics g, int width, int height, Rectangle clip) {
g.setColor(getBackground());
g.fillRect(0,0,width,height);
int count = (coordinateRects == null)? -1 : coordinateRects.size();
try {
for (int i = 0; i < count; i++) {
CRData c = (CRData)coordinateRects.elementAt(i);
Rectangle bounds = new Rectangle();
bounds.x = (int)(c.xmin*width);
bounds.y = (int)(c.ymin*height);
bounds.width = (int)(c.xmax*width) - bounds.x;
bounds.height = (int)(c.ymax*height) - bounds.y;
Rectangle clipThisRect = (clip == null)? bounds : bounds.intersection(clip);
if (clip == null || !clipThisRect.isEmpty()) {
g.setClip(clipThisRect);
if (c.background != null) {
g.setColor(c.background);
g.fillRect(bounds.x,bounds.y,bounds.width,bounds.height);
}
c.coords.draw(g,bounds.x,bounds.y,bounds.width,bounds.height);
}
}
}
finally {
g.setClip(clip);
}
}
/**
* This has been overridden to implemnt double-buffering.
* Not meant to be called directly.
*/
public void update(Graphics g) {
paint(g);
}
 
/**
* Draw the contents of the DisplayCanvas.
* Not usually called directly.
*/
synchronized public void paint(Graphics g) {
if (errorMessage == null) {
try {
checkOSC();
if (OSC != null)
g.drawImage(OSC,0,0,this);
else
drawCoordinateRects(g,getSize().width,getSize().height,g.getClipBounds());
if (dragging)
putDragRect(g);
}
catch (RuntimeException e) {
errorMessage = "Internal Error? (stack trace on System.out): " + e.toString();
e.printStackTrace();
g.setClip(0,0,getSize().width,getSize().height);
}
}
if (errorMessage != null) {
drawErrorMessage(g);
OSCvalid = false;
return;
}
}
/**
* Draws the specified item in the first CoordinateRect in this canvas.
* It is drawn on screen and on the off-screen canvas, if there is one.
* However, no information is kept about this item, so the drawing will
* disappear the next time the off-screen canvas is re-drawn (if there
* is an off-screen canvas) or the next time the canvas is repainted
* (is there is no off-screen canvas). If the canvas contains no
* CoordinateRect when this is called, a new one is added. Note that
* this method should only be called after the canvas has appeared on
* the screen.
*/
public void drawTemp(DrawTemp drawItem) {
if ( coordinateRects == null || coordinateRects.size() == 0)
addCoordinateRect(new CoordinateRect());
drawTemp(drawItem,0);
}
/**
* Draws the specified item in the specified CoordinateRect in this canvas.
* It is drawn on screen and on the off-screen canvas, if there is one.
* However, no information is kept about this item, so the drawing will
* disappear the next time the off-screen canvas is re-drawn (if there
* is an off-screen canvas) or the next time the canvas is repainted
* (is there is no off-screen canvas). Note that
* this method should only be called after the canvas has appeared on
* the screen.
*
* @param drawItem The non-null object that is to be drawn
* @param coordRectIndex The index of the CoordinateRect in which it
* is to be drawn, where the index of the fist CoordinateRect
* added to the canvas is zero, and so on. If there is
* no CoordinateRect with the specified index, an IllegalArgumentException
* is thrown.
*/
synchronized public void drawTemp(DrawTemp drawItem, int coordRectIndex) {
if (coordRectIndex < 0 || coordRectIndex >= coordinateRects.size())
throw new IllegalArgumentException("Invalid CoordinateRect index, " + coordRectIndex);
Graphics g = getGraphics();
if (g == null)
return;
CRData c = (CRData)coordinateRects.elementAt(coordRectIndex);
Rectangle bounds = new Rectangle();
bounds.x = (int)(c.xmin*getSize().width);
bounds.y = (int)(c.ymin*getSize().height);
bounds.width = (int)(c.xmax*getSize().width) - bounds.x;
bounds.height = (int)(c.ymax*getSize().height) - bounds.y;
g.setClip(bounds);
drawItem.draw(g,c.coords);
g.dispose();
if (useOffscreenCanvas && OSCvalid && OSC != null) {
g = OSC.getGraphics();
g.setClip(bounds);
drawItem.draw(g,c.coords);
g.dispose();
}
}
synchronized private void checkOSC() { // make off-screen image, if necessary
if (!useOffscreenCanvas || (OSCvalid == true && OSC != null &&
OSCwidth == getSize().width && OSCheight == getSize().height))
return;
int width = getSize().width;
int height = getSize().height;
if (OSC == null || width != OSCwidth || height != OSCheight) {
OSCvalid = false;
OSCwidth = width;
OSCheight = height;
try {
OSC = createImage(OSCwidth,OSCheight);
OSG = OSC.getGraphics();
}
catch (OutOfMemoryError e) {
OSC = null;
OSG = null;
}
}
if (OSC == null || OSCvalid)
return;
OSCvalid = true;
OSG.setClip(0,0,width,height);
drawCoordinateRects(OSG,width,height,null);
}
 
 
} // end class DisplayCanvas
 
/trunk/wims/src/Misc/authors/jm.evers/applets/jcm1.0-config/src/IntegralCurves.java
0,0 → 1,616
/*************************************************************************
* *
* This source code file, and compiled classes derived from it, can *
* be used and distributed without restriction, including for commercial *
* use. (Attribution is not required but is appreciated.) *
* *
* David J. Eck *
* Department of Mathematics and Computer Science *
* Hobart and William Smith Colleges *
* Geneva, New York 14456, USA *
* Email: eck@hws.edu WWW: http://math.hws.edu/eck/ *
* *
*************************************************************************/
 
 
// This applet displays a vector field (f1(x,y),f2(x,y)) and integral curves
// for that vector field (although the integral curve feature can be turned off
// with an applet param). The drawing of the curves is animated; they are
// drawn segment-by-segment. In the default setup, a curve is started when the
// user clicks on the canvas. A curve can also be started by entering the
// starting x and y coords in a pair of text input boxes and clicking a button.
 
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
 
 
 
public class IntegralCurves extends GenericGraphApplet {
 
private Variable yVar; // The seond variable, usually y.
private Function xFunc,yFunc; // The functions that give the components of the vector field
private ExpressionInput functionInput2; // For inputting yFunc.
private VectorField field; // The vector/direction field
 
private Animator animator; // for incrementally drawing integral curves.
private Vector curves = new Vector(); // Holds the integral curves
 
private VariableInput deltaT; // input the deltaT for the curve
double dt = 0.1; // The value of delat t in the case where there is no deltaT input box
private VariableInput xStart,yStart; // Starting point for curve
private Choice methodChoice; // select integration method
private Button startCurveButton; // user clicks to start curve from (x,y) in xStart, yStart input boxes
private Button clearButton; // clears curves
private Color curveColor; // color for integral curves
private Draw curveDrawer = new Draw(); // A DrawTemp object that draws one segment of the integral curves.
private double[] nextPoint = new double[2]; // Help in computing next point of integral curve.
private double[] params = new double[2]; // ditto
private static final int RK4 = 0, RK2 = 1, EULER = 2; // constants for integration methos
 
private class Curve { // holds the data for one integral curve
double dt;
int method;
double x,y; // point on the curve
double lastX = Double.NaN, lastY; // previous point, so we can draw a line.
}
private class Draw implements DrawTemp { // For drawing the next segment in each integral curve (as a DrawTemp)
public void draw(Graphics g, CoordinateRect coords) {
int size = curves.size();
g.setColor(curveColor);
for (int i = 0; i < size; i++) {
Curve c = (Curve)(curves.elementAt(i));
if (! (Double.isNaN(c.x) || Double.isNaN(c.y) || Double.isNaN(c.lastX) || Double.isNaN(c.lastY)) ) {
int x1 = coords.xToPixel(c.lastX);
int y1 = coords.yToPixel(c.lastY);
int x2 = coords.xToPixel(c.x);
int y2 = coords.yToPixel(c.y);
g.drawLine(x1,y1,x2,y2);
}
}
}
}
 
protected void setUpParser() {
// create the "y" variable; also set up some parameter defaults.
yVar = new Variable(getParameter("Variable2","y"));
parser.add(yVar);
super.setUpParser(); // sets up xVar, among other things.
parameterDefaults = new Hashtable();
parameterDefaults.put("FunctionLabel", " f1(" + xVar.getName() + "," + yVar.getName() + ") = ");
parameterDefaults.put("FunctionLabel2", " f2(" + xVar.getName() + "," + yVar.getName() + ") = ");
parameterDefaults.put("Function", " " + yVar.getName() + " - 0.1*" + xVar.getName());
parameterDefaults.put("Function2", " - " + xVar.getName() + " - 0.1*" + yVar.getName());
defaultFrameSize = new int[] { 580, 440 };
}
 
protected void setUpCanvas() { // Override this to add more stuff to the canvas.
super.setUpCanvas(); // Do the common setup: Add the axes and
// set up the vector field and add it to the canvas
if (functionInput != null) {
xFunc = functionInput.getFunction(new Variable[] {xVar,yVar});
yFunc = functionInput2.getFunction(new Variable[] {xVar,yVar});
}
else {
String xFuncDef = getParameter("Function");
String yFuncDef = getParameter("Function2");
Function f = new SimpleFunction( parser.parse(xFuncDef), new Variable[] {xVar,yVar} );
xFunc = new WrapperFunction(f);
f = new SimpleFunction( parser.parse(yFuncDef), new Variable[] {xVar,yVar} );
yFunc = new WrapperFunction(f);
}
String type = (getParameter("VectorStyle", "") + "A").toUpperCase();
int style = 0;
switch (type.charAt(0)) {
case 'A': style = VectorField.ARROWS; break;
case 'L': style = VectorField.LINES; break;
case 'S': style = VectorField.SCALED_VECTORS; break;
}
field = new VectorField(xFunc,yFunc,style);
Color color = getColorParam("VectorColor");
if (color != null)
field.setColor(color);
int space = (style == VectorField.LINES)? 20 : 30;
double[] d = getNumericParam("VectorSpacing");
if (d != null && d.length > 0 && d[0] >= 1)
space = (int)Math.round(d[0]);
field.setPixelSpacing(space);
 
canvas.add(field); // Finally, add the graph to the canvas.
 
curveColor = getColorParam("CurveColor", Color.magenta);
 
// add a mouse listener to the canvas for starting curves.
 
if ("yes".equalsIgnoreCase(getParameter("MouseStartsCurves","yes")) && "yes".equalsIgnoreCase(getParameter("DoCurves","yes")))
canvas.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
CoordinateRect coords = canvas.getCoordinateRect();
double x = coords.pixelToX(evt.getX());
double y = coords.pixelToY(evt.getY());
if (xStart != null)
xStart.setVal(x);
if (yStart != null)
yStart.setVal(y);
startCurve(x,y);
}
});
 
} // end setUpCanvas()
 
protected void setUpBottomPanel() {
// Override this to make a panel containing controls. This is complicated
// because it's possible to turn off a lot of the inputs with applet params.
// Check on the value of delta t, which has to be set even if there are no input controls.
double[] DT = getNumericParam("DeltaT");
if ( ! (DT == null || DT.length == 0 || DT[0] <= 0) )
dt = DT[0];
 
boolean doCurves = "yes".equalsIgnoreCase(getParameter("DoCurves","yes"));
boolean useInputs = "yes".equalsIgnoreCase(getParameter("UseFunctionInput","yes"));
if (!doCurves && !useInputs) // no input controls at all.
return;
 
// make the input panel
 
inputPanel = new JCMPanel();
inputPanel.setBackground( getColorParam("PanelBackground", Color.lightGray) );
mainPanel.add(inputPanel,BorderLayout.SOUTH);
 
// Make the function inputs and the compute button, if these are in the configuration.
 
JCMPanel in1 = null, in2 = null; // hold function inputs, if any
if (useInputs) {
if ( "yes".equalsIgnoreCase(getParameter("UseComputeButton", "yes")) ) {
String cname = getParameter("ComputeButtonName", "New Functions");
computeButton = new Button(cname);
computeButton.addActionListener(this);
}
functionInput = new ExpressionInput(getParameter("Function"),parser);
in1 = new JCMPanel();
in1.add(functionInput,BorderLayout.CENTER);
in1.add(new Label(getParameter("FunctionLabel")), BorderLayout.WEST);
functionInput.setOnUserAction(mainController);
functionInput2 = new ExpressionInput(getParameter("Function2"),parser);
in2 = new JCMPanel();
in2.add(functionInput2,BorderLayout.CENTER);
in2.add(new Label(getParameter("FunctionLabel2")), BorderLayout.WEST);
functionInput2.setOnUserAction(mainController);
}
// If we're not doing curves, all we have to do is put the function inputs in the inputPanel
if (!doCurves) {
Panel p = new JCMPanel(2,1,3);
p.add(in1);
p.add(in2);
inputPanel.add(p, BorderLayout.CENTER);
if (computeButton != null)
inputPanel.add(computeButton,BorderLayout.EAST);
return;
}
// Now we know that doCurves is true. First, make the animator and clear button
 
animator = new Animator(Animator.STOP_BUTTON);
animator.setStopButtonName("Stop Curves");
animator.setOnChange(new Computable() { // animator drives curves
public void compute() {
extendCurves();
}
});
mainController.add(new InputObject() { // curves must stop if main controller is triggered
public void checkInput() {
curves.setSize(0);
animator.stop();
}
public void notifyControllerOnChange(Controller c) {
}
});
clearButton = new Button("Clear");
clearButton.addActionListener(this);
 
// Make a panel to contain the xStart and yStart inputs, if they are in the configuration.
 
Panel bottom = null;
if ("yes".equalsIgnoreCase(getParameter("UseStartInputs","yes"))) {
xStart = new VariableInput();
xStart.addActionListener(this);
yStart = new VariableInput();
yStart.addActionListener(this);
bottom = new Panel(); // not a JCMPanel -- I don't want their contents checked automatically
startCurveButton = new Button("Start curve at:");
startCurveButton.addActionListener(this);
bottom.add(startCurveButton);
bottom.add(new Label(xVar.getName() + " ="));
bottom.add(xStart);
bottom.add(new Label(yVar.getName() + " ="));
bottom.add(yStart);
}
// Now, make a panel to contain the methodChoice and deltaT input if they are in the configuration.
// The animator and clear button will be added to this panel if it exists. If not, and if
// an xStart/yStart panel exists, then it will be added there. If neither exists,
// it goes in its own panel. The variable bottom ends up pointing to a panel that
// contains all the curve controls.
boolean useChoice = "yes".equalsIgnoreCase(getParameter("UseMethodChoice","yes"));
boolean useDelta = "yes".equalsIgnoreCase(getParameter("UseDeltaInput","yes"));
if (useChoice || useDelta) {
Panel top = new Panel(); // not a JCMPanel!
if (useDelta) {
top.add(new Label("dt ="));
deltaT = new VariableInput(null,""+dt);
top.add(deltaT);
}
if (useChoice) {
top.add(new Label("Method:"));
methodChoice = new Choice();
methodChoice.add("Runge-Kutta 4");
methodChoice.add("Runge-Kutta 2");
methodChoice.add("Euler");
top.add(methodChoice);
}
top.add(animator);
top.add(clearButton);
if (bottom == null)
bottom = top;
else {
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add(top, BorderLayout.NORTH);
p.add(bottom, BorderLayout.CENTER);
bottom = p;
}
}
else {
if (bottom == null)
bottom = new Panel();
bottom.add(animator);
bottom.add(clearButton);
}
// Add the panels "bottom" to the inputPanel, and ruturn
// if there are no function inputs.
inputPanel.add(bottom, BorderLayout.CENTER);
if (in1 == null)
return;
 
// Add the function inputs and compute button to the inputPanel
Panel in = new JCMPanel(1,2);
in.add(in1);
in.add(in2);
if (computeButton != null) {
Panel p = new JCMPanel();
p.add(in,BorderLayout.CENTER);
p.add(computeButton,BorderLayout.EAST);
in = p;
}
inputPanel.add(in,BorderLayout.NORTH);
} // end setUpBottomPanel()
 
 
public void actionPerformed(ActionEvent evt) {
// React if user presses return in xStart or yStart, or pass evt on to GenericGraphApplet
Object src = evt.getSource();
if (src == clearButton) {
canvas.clearErrorMessage();
curves.setSize(0);
animator.stop();
canvas.compute(); // force recompute of off-screen canvas!
}
else if (src == xStart || src == yStart || src == startCurveButton) {
// Start a curve from x and y values in xStart and yStart
canvas.clearErrorMessage();
double x=0, y=0;
try {
xStart.checkInput();
x = xStart.getVal();
yStart.checkInput();
y = yStart.getVal();
startCurve(x,y);
if (deltaT != null) {
deltaT.checkInput();
dt = deltaT.getVal();
if (dt <= 0) {
deltaT.requestFocus();
throw new JCMError("dt must be positive", deltaT);
}
}
}
catch (JCMError e) {
curves.setSize(0);
animator.stop();
canvas.setErrorMessage(null,"Illegal Data For Curve. " + e.getMessage());
}
}
else
super.actionPerformed(evt);
} // end actionPerfromed
public void startCurve(double x, double y) {
// Start an integral curve at the point (x,y)
synchronized (curves) {
if (deltaT != null) {
try {
deltaT.checkInput();
dt = deltaT.getVal();
if (dt <= 0) {
deltaT.requestFocus();
throw new JCMError("dt must be positive", deltaT);
}
}
catch (JCMError e) {
curves.setSize(0);
animator.stop();
canvas.setErrorMessage(null,"Illegal Data For Curve. " + e.getMessage());
return;
}
}
Curve c = new Curve();
c.dt = dt;
int method = (methodChoice == null)? RK4 : methodChoice.getSelectedIndex();
c.method = method;
c.x = x;
c.y = y;
curves.addElement(c);
animator.start();
}
}
public void extendCurves() {
// Add the next segment to each integral curve. This function
// is called repeatedly by the animator.
synchronized(curves) {
if (canvas == null || canvas.getCoordinateRect() == null) // can happen when frame closes
return;
while (canvas.getCoordinateRect().getWidth() <= 0) {
// need this at startup to make sure that the canvas has appeared on the screen
try {
Thread.sleep(200);
}
catch (InterruptedException e) {
}
}
int size = curves.size();
for (int i = 0; i < size; i++) {
Curve curve = (Curve)curves.elementAt(i);
curve.lastX = curve.x;
curve.lastY = curve.y;
nextPoint(curve.x, curve.y, curve.dt, curve.method);
curve.x = nextPoint[0];
curve.y = nextPoint[1];
}
CoordinateRect c = canvas.getCoordinateRect();
double pixelWidthLimit = 100000*c.getPixelWidth();
double pixelHeightLimit = 100000*c.getPixelHeight();
for (int i = size-1; i >= 0; i--) {
Curve curve = (Curve)curves.elementAt(i);
if (Double.isNaN(curve.x) || Double.isNaN(curve.y) ||
Math.abs(curve.x) > pixelWidthLimit ||
Math.abs(curve.y) > pixelWidthLimit) // stop processing this curve
curves.removeElementAt(i);
}
if (curves.size() > 0)
canvas.drawTemp(curveDrawer);
else {
animator.stop();
}
}
}
 
private void nextPoint(double x, double y, double dt, int method) {
// Find next point from (x,y) by applying specified method over time interval dt
switch (method) {
case EULER:
nextEuler(x,y,dt);
break;
case RK2:
nextRK2(x,y,dt);
break;
case RK4:
nextRK4(x,y,dt);
break;
}
}
private void nextEuler(double x, double y, double dt) {
params[0] = x;
params[1] = y;
double dx = xFunc.getVal(params);
double dy = yFunc.getVal(params);
nextPoint[0] = x + dt*dx;
nextPoint[1] = y + dt*dy;
}
private void nextRK2(double x, double y, double dt) {
params[0] = x;
params[1] = y;
double dx1 = xFunc.getVal(params);
double dy1 = yFunc.getVal(params);
double x2 = x + dt*dx1;
double y2 = y + dt*dy1;
params[0] = x2;
params[1] = y2;
double dx2 = xFunc.getVal(params);
double dy2 = yFunc.getVal(params);
nextPoint[0] = x + 0.5*dt*(dx1+dx2);
nextPoint[1] = y + 0.5*dt*(dy1+dy2);
}
private void nextRK4(double x, double y, double dt) {
params[0] = x;
params[1] = y;
double dx1 = xFunc.getVal(params);
double dy1 = yFunc.getVal(params);
double x2 = x + 0.5*dt*dx1;
double y2 = y + 0.5*dt*dy1;
params[0] = x2;
params[1] = y2;
double dx2 = xFunc.getVal(params);
double dy2 = yFunc.getVal(params);
double x3 = x + 0.5*dt*dx2;
double y3 = y + 0.5*dt*dy2;
params[0] = x3;
params[1] = y3;
double dx3 = xFunc.getVal(params);
double dy3 = yFunc.getVal(params);
double x4 = x + dt*dx3;
double y4 = y + dt*dy3;
params[0] = x4;
params[1] = y4;
double dx4 = xFunc.getVal(params);
double dy4 = yFunc.getVal(params);
nextPoint[0] = x + (dt / 6) * (dx1 + 2 * dx2 + 2 * dx3 + dx4);
nextPoint[1] = y + (dt / 6) * (dy1 + 2 * dy2 + 2 * dy3 + dy4);
}
protected void doLoadExample(String example) {
// This method is called when the user loads an example from the
// example menu (if there is one). It overrides an empty method
// in GenericGraphApplet.
// For the IntegrapCurves applet, the example string should contain
// two expression that defines the vector field, separated
// by a semicolon. This can optionally
// be followed by another semicolon and a list of numbers, separated by spaces and/or commas.
// The first four numbers give the x- and y-limits to be used for the
// example. If they are not present, then -5,5,-5,5 is used. The next number, if present,
// specifies a value for delta t. If there are more numbers, they should come in pairs.
// each pair specifies a point where a curve will be started when the
// example is loaded. There is a 0.5 second delay between loading and starting the
// curves to allow time for the redrawing (although it seems to block the redrawing, at least
// on some platforms).
if (animator != null) {
curves.setSize(0);
animator.stop();
}
int pos = example.indexOf(";");
if (pos == -1)
return; // illegal example -- must have two functions
String example2 = example.substring(pos+1);
example = example.substring(0,pos);
pos = example2.indexOf(";");
double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
StringTokenizer toks = null;
 
if (pos > 0) {
// Get limits from example2 text.
String nums = example2.substring(pos+1);
example2 = example2.substring(0,pos);
toks = new StringTokenizer(nums, " ,");
if (toks.countTokens() >= 4) {
for (int i = 0; i < 4; i++) {
try {
Double d = new Double(toks.nextToken());
limits[i] = d.doubleValue();
}
catch (NumberFormatException e) {
}
}
}
if (toks.hasMoreTokens()) {
double d = Double.NaN;
try {
d = (new Double(toks.nextToken())).doubleValue();
}
catch (NumberFormatException e) {
}
if (Double.isNaN(d) || d <= 0 || d > 100)
d = 0.1;
if (deltaT != null)
deltaT.setVal(d);
else
dt = d;
}
}
// Set up the example data and recompute everything.
 
if (functionInput != null) {
// If there is a function input box, put the example text in it.
functionInput.setText(example);
functionInput2.setText(example2);
}
else {
// If there is no user input, set the function in the graph directly.
try {
Function f = new SimpleFunction( parser.parse(example), xVar );
((WrapperFunction)xFunc).setFunction(f);
Function g = new SimpleFunction( parser.parse(example2), xVar );
((WrapperFunction)yFunc).setFunction(g);
}
catch (ParseError e) {
// There should't be parse error's in the Web-page
// author's examples! If there are, the function
// just won't change.
}
}
CoordinateRect coords = canvas.getCoordinateRect(0);
coords.setLimits(limits);
coords.setRestoreBuffer();
mainController.compute();
if (animator != null && toks != null) { // get any extra nums from the tokenizer and use them as starting points for curves
int ct = 2*(toks.countTokens()/2);
if (ct > 0) {
synchronized(curves) {
for (int i = 0; i < ct; i++) {
try {
double x = (new Double(toks.nextToken())).doubleValue();
double y = (new Double(toks.nextToken())).doubleValue();
startCurve(x,y);
}
catch (Exception e) {
}
}
if (curves.size() > 0) { // start the curves going
try {
Thread.sleep(500); // wait a bit to give the canvas time to start drawing itself.
}
catch (InterruptedException e) {
}
}
}
}
}
} // end doLoadExample()
 
public void stop() { // stop animator when applet is stopped
if (animator != null) {
curves.setSize(0);
animator.stop();
}
super.stop();
}
 
 
} // end class IntegralCurves
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/1.html
0,0 → 1,29
<html>
<head></head>
<body>
<script language="javascript" type="text/javascript">
function lees(){
var input=document.applets[0].ReadApplet();
alert(input);
document.applets[0].destroy();
}
</script>
<center>
<applet codebase="dist" archive="Plinko.jar" code="Plinko.class" width=220 height=100>
<param name="wims_exercise" value="1">
<param name="xsize" value="640">
<param name="ysize" value="480">
<param name="fontsize" value="12">
<param name="bins" value="10">
<param name="chance" value="0.5">
<param name="speed" value="10">
<param name="title" value="Applet by Dr. P. Little">
<param name="language" value="en">
<param name="balls" value="100">
</applet>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:lees();">
</body>
</html>
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/src/PlinkoBall.java
0,0 → 1,47
/*
Copyright 2004-2006 David P. Little
license:
Unless otherwise stated, the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
Modified for wims interactive usage with permission of the author.
J.M. Evers
*/
import java.awt.*;
import java.util.*;
 
 
public class PlinkoBall{
final static double A = -2.0 - Math.sqrt(3); // Ball follows the motion of
final static double B = 1.0 + Math.sqrt(3); // y = Ax^2 + Bx
Color color; // color of ball, choosen randomly from above list
PlinkoBall nextBall; // link to next ball in list
PlinkoBall previousBall; // link to previous ball in list
double X; // x-coordinate of location of ball
double Y; // y-coordinate of location of ball
int ROW;
int COL;
int DIR;
int C;
int t; // ranges from 0 to (10-rate), parametrizes the motion of ball
int spaz; //
//double dx;
boolean sound = false;
 
public PlinkoBall( ){
// pick a random color for the ball
spaz = (int)( PlinkoBoard.COLORS.length*Math.random() );
color = PlinkoBoard.COLORS[spaz];
 
nextBall = null;
previousBall = null;
 
ROW = -1;
COL = 0;
DIR = 0;
t = 0;
C = 11-((Integer)Plinko.rate.getValue()).intValue();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/src/SplashPanel.java
0,0 → 1,273
/*
Copyright 2004-2006 David P. Little
license:
Unless otherwise stated, the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
Modified for wims interactive usage with permission of the author.
J.M. Evers
*/
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
 
public class SplashPanel extends JPanel implements MouseListener,Runnable{
Plinko plinko;
double w;
double h;
int TOTAL; // total number of balls that have been dropped
int[] HIST; // number of balls in each bin;
double MAX; // maximum number of balls in a single bin
Point[][] PINS; // coordinates of pins (including one at the base of each bin)
double DIST; // vertical distance between pins
double BALL_RAD; // radius of ball
int PIN_RAD; // radius of pin
int BINS = 20; // total number of bins
PlinkoBall FIRST_BALL; // represents beginning of doubly linked list of plinko balls
int BALL_COUNT;
int BOTTOM_MARGIN = 5;
// private static byte[] data;
private final static int hx = 15;
private final static int hy = 15;
private final static int bgGrey = 192;
Image[] IMAGES;
boolean newBackground = true;
boolean active = true;
Thread thread;
public SplashPanel( Plinko plinko ){
setBackground( Color.white );
addMouseListener( this );
this.plinko = plinko;
for ( int i = 0; i<25; i++ ){
dropBall();
FIRST_BALL.ROW = 10+(int)(10*Math.random());
FIRST_BALL.COL = (int)(FIRST_BALL.ROW*Math.random());
FIRST_BALL.C = 10;
FIRST_BALL.t = i%11;
}
start();
}
 
public void start(){
active = true;
thread = new Thread(this);
thread.start();
}
 
 
public void run(){
while ( active ){
if ( Math.random() < 0.4 ){
dropBall();
FIRST_BALL.ROW = 11;
FIRST_BALL.COL = (int)(FIRST_BALL.ROW*Math.random());
FIRST_BALL.C = 10;
}
repaint();
try {Thread.sleep(100);} catch (InterruptedException e){}
}
}
 
 
public void dropBall(){
if ( FIRST_BALL == null ){
FIRST_BALL = new PlinkoBall();
} else {
FIRST_BALL.previousBall = new PlinkoBall();
FIRST_BALL.previousBall.nextBall = FIRST_BALL;
FIRST_BALL = FIRST_BALL.previousBall;
}
}
 
 
//Image backImage;
Image background;
Graphics2D backGraphics;
int FUDGE = 200;
 
public void setup(){
if(plinko.wims_exercise == true){ FUDGE = 100;}
if ( h-BOTTOM_MARGIN<h/2 ){
DIST = (double)(h-BOTTOM_MARGIN)/BINS;
} else {
DIST = (double)(w-10)/(2*BINS);
}
 
PIN_RAD = (int)DIST/9 + 1;
BALL_RAD = Math.max(2*DIST/7,2.0) + 1;
 
// create images of colored balls
IMAGES = new Image[ PlinkoBoard.COLORS.length ];
Graphics2D g;
int red;
int green;
int blue;
for ( int i=0; i<PlinkoBoard.COLORS.length; i++ ){
IMAGES[i] = PlinkoBoard.getBall( BALL_RAD, PlinkoBoard.COLORS[i] );
}
 
PINS = new Point[BINS][];
for (int i=0; i<BINS; i++){
PINS[i] = new Point[i+1];
for (int j=0; j<=i; j++){
PINS[i][j]= new Point((int)(DIST*(2*j-i)+w/2)-FUDGE/2,(int)(DIST*(i+1))-(FUDGE-15));
}
}
// pins at the base of each bin
for (int i=0; i<BINS; i++){
PINS[BINS-1][i]= new Point((int)(DIST*(2*i-BINS+1)+w/2),(int)(h-30-BALL_RAD));
}
}
 
 
public void paintComponent( Graphics graphics ){
// have a copy of the background on which to draw
w = getWidth();
h = getHeight();
w = Math.max( getWidth(),getHeight() ) + FUDGE;
h = w;
 
Graphics2D g = (Graphics2D)graphics;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
 
if ( background == null || background.getWidth(this) != h || background.getHeight(this) != w ){
setup();
background = createImage( (int)w, (int)h );
drawBackground((int)w,(int)h);
}
 
g.drawImage( background, 0, 0, this );
 
// run through all active balls and draw them on the image
PlinkoBall ball = FIRST_BALL;
 
int red;
int green;
int blue;
while ( ball != null ){
graphics.drawImage( IMAGES[ball.spaz], (int)(ball.X - BALL_RAD), (int)(ball.Y - 2*BALL_RAD - PIN_RAD + 1), this );
if ( active ) increment( ball );
ball = ball.nextBall;
}
//g.drawImage(image,0,0,this);
 
w = getWidth();
h = getHeight();
g.setColor( new Color( 128,128,128,220 ) );
g.setFont( new Font("Helvetica",Font.BOLD,plinko.font_size) );
//String str = "CLICK ANYWHERE TO BEGIN";
String str = plinko.click_text;
g.drawString( str, (int)(w-g.getFontMetrics().stringWidth(str)-5), (int)(h-5) );
}
 
 
public void increment( PlinkoBall ball ){
// if ball has landed on pin, reset t to 0 and pick a direction
if ( ball.t == ball.C && ball.ROW < BINS-2 ){
ball.ROW++;
ball.COL += ball.DIR;
ball.t = 0;
ball.DIR = 0;
if ( Math.random() < 0.5 ) ball.DIR = 1;
 
ball.C = 10;
//if ( C>1 ) C += spaz;
}
 
double dx = DIST*ball.t*(2*ball.DIR - 1)/ball.C;
 
if ( ball.ROW < 0 ){ // ball falling onto top pin
ball.X = PINS[0][0].x;
dx = Math.abs(dx);
ball.Y = PINS[0][0].y - DIST + DIST*ball.t*ball.t/(ball.C*ball.C);
} else if ( ball.ROW < BINS-2 ) {
ball.X = PINS[ball.ROW][ball.COL].x + dx;
dx = Math.abs(dx);
//Y = PlinkoBoard.PINS[ROW][COL].y - (int)(dx*(A*dx/PlinkoBoard.DIST+B));
ball.Y = PINS[ball.ROW][ball.COL].y - DIST*PlinkoBoard.DYS[ball.C][ball.t];
} else { // ball falling into bin
ball.X = PINS[ball.ROW][ball.COL].x + dx;
if ( dx>0 ){
ball.X = Math.min(ball.X,PINS[ball.ROW][ball.COL].x + 2*DIST - BALL_RAD );
} else {
ball.X = Math.max(ball.X,PINS[ball.ROW][ball.COL].x - 2*DIST + BALL_RAD + 1);
}
dx = Math.abs(dx);
ball.Y = PINS[ball.ROW][ball.COL].y - dx*(ball.A*dx/DIST+ball.B);
}
 
ball.t++;
 
if ( ball.Y > h - BOTTOM_MARGIN - PIN_RAD ){
if ( ball.previousBall != null && ball.nextBall != null){
ball.previousBall.nextBall = ball.nextBall;
ball.nextBall.previousBall = ball.previousBall;
} else if ( ball.previousBall != null && ball.nextBall == null ) {
ball.previousBall.nextBall = null;
} else if ( ball.previousBall == null && ball.nextBall != null ) {
ball.nextBall.previousBall = null;
FIRST_BALL = ball.nextBall;
} else {
FIRST_BALL = null;
//plinko.bins.setEnabled( true );
}
 
BALL_COUNT--;
}
}
public void drawBackground( int W, int H ){
Point p;
 
Graphics2D backgroundgraphics = (Graphics2D) background.getGraphics();
backgroundgraphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
backgroundgraphics.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
backgroundgraphics.setColor(Color.white);
backgroundgraphics.fillRect( 0, 0, W, H );
backgroundgraphics.setColor(Color.black);
Image img = PlinkoBoard.getBall( PIN_RAD, Color.black );
 
// draw pins
for (int i=0; i<BINS-1; i++){
for (int j=0;j<=i;j++){
p = PINS[i][j];
//backgroundgraphics.fillOval(p.x-PIN_RAD,p.y-PIN_RAD,2*PIN_RAD,2*PIN_RAD);
backgroundgraphics.drawImage(img, (int)(p.x-PIN_RAD),(int)(p.y-PIN_RAD),this );
}
}
repaint();
}
 
 
public void mouseClicked( MouseEvent me ){
active = false;
plinko.showFrame();
}
public void mouseEntered( MouseEvent me ){
}
 
 
public void mouseExited( MouseEvent me ){
}
 
 
public void mousePressed( MouseEvent me ){
}
 
 
public void mouseReleased(MouseEvent me){
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/src/sounds/ping.au
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/src/sounds/click.au
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/src/Plinko.java
0,0 → 1,386
/*
Copyright 2004-2006 David P. Little
license:
Unless otherwise stated, the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
 
Modified for wims interactive usage with permission of the author.
 
J.M. Evers
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
 
 
public class Plinko extends JApplet implements Runnable, ActionListener, ChangeListener, WindowListener{
static JSpinner bins;
static JSpinner rate;
static JSpinner prob;
JLabel count;
JLabel mean;
JLabel variance;
JLabel current_bin;
JLabel current_bin_count;
JLabel current_bin_prob;
JLabel confidence;
JButton start;
JButton clear;
JButton close;
PlinkoBoard plinkoboard;
Thread thread;
boolean active = false;
int countdown = 0;
JFrame frame;
SplashPanel splash;
static AudioClip click;
static AudioClip ping;
// jm.evers: declaring a few things
boolean wims_exercise = false;
int bins_num=11;
int speed=1;
int total_balls=100000;
double chance=0.5;
int frame_x=600;
int frame_y=600;
int font_size=14;
String title="Binomial Distribution";
String click_text="CLICK ANYWHERE TO BEGIN";
String start_text="START";
String stop_text="STOP";
String clear_text="CLEAR";
String close_text="CLOSE";
String label_count="Count: ";
String label_mean="Mean: ";
String label_variance="Variance: ";
String label_bin="Bin: ";
String label_bins="Bins: ";
String label_speed="Speed: ";
String label_probability="Probability: ";
String label_bin_count="Bin Count: ";
String label_bin_probability="Bin Probability: ";
String label_confidence="Confidence Interval: ";
String some_text=" % of the balls landed in bin ";
String through=" through ";
String label_controls=" Controls ";
String label_statistics="Statistics";
public void init(){
// jm.evers: introducing a few Applet params , used for tailoring the exercise.
String s=getParameter("wims_exercise");
if(s!=null){
if(s.equalsIgnoreCase("yes") || s.equals("1")){
wims_exercise = true;
s=getParameter("balls");
if(s!=null && s.length()>0){total_balls = Integer.parseInt(s, 10);}
s=getParameter("chance");
if(s!=null && s.length()>0){chance = Double.parseDouble(s);}
s=getParameter("bins");
if(s!=null && s.length()>0){bins_num = Integer.parseInt(s, 10);}
s=getParameter("speed");
if(s!=null && s.length()>0){speed = Integer.parseInt(s, 10);}
s=getParameter("xsize");
if(s!=null && s.length()>0){frame_x = Integer.parseInt(s, 10);}
s=getParameter("ysize");
if(s!=null && s.length()>0){frame_y = Integer.parseInt(s, 10);}
s=getParameter("title");
if(s!=null && s.length()>0){title=s;}
s=getParameter("font_size");
if(s!=null && s.length()>0){font_size = Integer.parseInt(s, 10);}
 
}
}
s=getParameter("language");
if(s!=null && s.length()>0){
if(s.equalsIgnoreCase("nl")){
click_text="KLIK HIER OM TE BEGINNEN";
start_text="START";
stop_text="STOP";
clear_text="WISSEN";
close_text="SLUITEN";
label_count="Aantal: ";
label_mean="Gemiddeld: ";
label_variance="Variantie: ";
label_bin="Bakje: ";
label_bins="Bakjes: ";
label_speed="Snelheid: ";
label_bin_count="Ballen/bakje: ";
label_probability="Kans: ";
label_bin_probability="Kans per bakje: ";
label_confidence="Betrouwbaarheids interval: ";
some_text=" % van de ballen in bakje: ";
through=" t/m ";
String label_controls=" Menu ";
String label_statistics="Statistiek";
}
if(s.equalsIgnoreCase("fr")){
click_text="CLIQUEZ ICI";
start_text="COMMENCER";
stop_text="PAUSE";
clear_text="EFFACER";
close_text="FERMER";
label_count="Quantit\u00E9 : ";
label_mean="Moyenne : ";
label_variance="Variance: ";
label_bin="Panier : ";
label_bins="Paniers : ";
label_speed="Vitesse : ";
label_bin_count="Balles dans ce panier : ";
label_bin_probability="% de balles dans ce panier : ";
label_probability="Probabilit\u00E9 : ";
label_confidence="Intervalle de confiance : ";
some_text=" % de balles dans le panier ";
through=" through ";
label_controls="Menu";
label_statistics="Statistiques";
}
if(s.equalsIgnoreCase("de")){
click_text="Klicken Sie hier um zu starten";
start_text="START";
stop_text="STOP";
clear_text="CLEAR";
close_text="CLOSE";
label_count="Zahl: ";
label_mean="Mean: ";
label_variance="Variance: ";
label_bin="Behälter: ";
label_bins="Behälter: ";
label_speed="Geschwindigkeit : ";
label_bin_count="Zahl/Behälter: ";
label_bin_probability="Wahrscheinlichkeit in Behälter: ";
label_probability="Wahrscheinlichkeit: ";
label_confidence="Wahrscheinlichkeits Intervall: ";
some_text=" % der Kugeln fällt in Behälter ";
through=" bis ";
String label_controls=" Menu ";
String label_statistics="Statistik";
}
}
setBackground(Color.white);
frame = new JFrame();
frame.setVisible(false);
frame.setSize(frame_x, frame_y);
frame.setLocation(0,0);
frame.setTitle( title );
Font font = new Font( "Helvetica", Font.BOLD, font_size );
GridBagLayout gridbaglayout = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
constraints.ipadx = 5;
constraints.ipady = 5;
constraints.insets = new Insets( 1,1,1,1 );
constraints.anchor = GridBagConstraints.CENTER;
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 1.0;
JPanel controls_west = new JPanel( );
JLabel label = new JLabel( label_bins,JLabel.LEFT );
controls_west.add( label );
bins = new JSpinner( new SpinnerNumberModel(bins_num,2,101,1) );
controls_west.add( bins );
label = new JLabel( label_probability,JLabel.LEFT );
controls_west.add( label );
prob = new JSpinner( new SpinnerNumberModel(0.50,0.00,100,0.01) );
SpinnerNumberModel model = (SpinnerNumberModel)prob.getModel();
model.setMaximum( new Double(1.00) );
controls_west.add( prob );
label = new JLabel( label_speed,JLabel.LEFT );
controls_west.add( label );
rate = new JSpinner( new SpinnerNumberModel(1,1,10,1) );
controls_west.add( rate );
JPanel controls_east = new JPanel();
controls_east.add( start = new JButton( start_text ) );
start.setDefaultCapable( true );
frame.getRootPane().setDefaultButton( start );
controls_east.add( clear = new JButton( clear_text ) );
controls_east.add( close = new JButton( close_text ) );
close.setDefaultCapable( false );
JPanel controls = new JPanel( new BorderLayout() );
controls.add( "East", controls_east );
JPanel statistics_center = new JPanel( new GridLayout(2,3) );
statistics_center.add( count = new JLabel( label_count ) );
statistics_center.add( mean = new JLabel( label_mean ) );
statistics_center.add( variance = new JLabel( label_variance ) );
statistics_center.add( current_bin = new JLabel( label_bin ) );
statistics_center.add( current_bin_count = new JLabel(label_bin_count ) );
statistics_center.add( current_bin_prob = new JLabel( label_bin_probability ) );
JPanel statistics_south = new JPanel( new GridLayout(1,1) );
statistics_south.add( confidence = new JLabel( label_confidence ) );
JPanel statistics = new JPanel( new BorderLayout() );
if(wims_exercise == false){
// hmmm...these controls are handed over to applet params...if applet is part of an interactive exercise.
controls.add( "West", controls_west );
controls.setBorder( BorderFactory.createTitledBorder( controls.getBorder(), label_controls, TitledBorder.LEFT, TitledBorder.TOP, new Font( "Helvetica", Font.BOLD, font_size) ) );
}
statistics.add( "Center", statistics_center );
statistics.add( "South", statistics_south );
statistics.setBorder( BorderFactory.createTitledBorder( statistics.getBorder(), label_statistics, TitledBorder.LEFT, TitledBorder.TOP, new Font( "Helvetica", Font.BOLD, font_size) ) );
 
JPanel south = new JPanel( new BorderLayout() );
south.add( "Center", statistics );
JLabel statusbar = new JLabel("");
statusbar.setPreferredSize( new Dimension(15,15) );
south.add( "South", statusbar );
Container contentpane = frame.getContentPane();
contentpane.setLayout(new BorderLayout(10,10));
contentpane.add( "Center", plinkoboard = new PlinkoBoard(this) );
contentpane.add( "North", controls );
contentpane.add( "South", south );
start.addActionListener( this );
clear.addActionListener( this );
close.addActionListener( this );
bins.addChangeListener( this );
rate.addChangeListener( this );
prob.addChangeListener( this );
 
plinkoboard.requestFocus();
frame.addWindowListener( this );
getContentPane().add( splash = new SplashPanel( this ) );
click = getAudioClip( getCodeBase(), "sounds/click.au" );
ping = getAudioClip( getCodeBase(), "sounds/ping.au" );
}
 
// jm.evers: returns a string to a javascript function ReadApplet(); [must be a string, and not an array ... IE trouble]
// the string will be send -along with the "student reply" to the questions at hand- to the WIMS server;
public String ReadApplet(){
String s=plinkoboard.ReadData();
return s;
}
 
public void showFrame(){
frame.setVisible( true );
}
 
public void stop(){
frame.setVisible( false );
splash.start();
}
 
public void run(){
//while ( active || countdown > 0 ){
while ( active ){
plinkoboard.dropBall( false );
//if ( countdown > 0 ) countdown--;
try {
//if ( countdown < 1)
if(wims_exercise){
Thread.sleep(105 - 10*( (int) speed ));
}
else
{
Thread.sleep(105 - 10*((Integer)rate.getValue()).intValue());
}
} catch (InterruptedException e){}
}
}
public void toggleStart(){
if ( active ){
active = false;
start.setText(start_text);
}
else
{
active = true;
bins.setEnabled( false );
thread = new Thread(this);
thread.start();
start.setText(stop_text);
}
}
 
public void actionPerformed( ActionEvent ae ){
Object obj = ae.getSource();
if (obj == start){toggleStart();plinkoboard.requestFocus();}
if( obj == clear ){
if ( plinkoboard.FIRST_BALL == null ){plinkoboard.newHist();}
else
{
plinkoboard.FIRST_BALL = null;
//plinkoboard.BALL_COUNT = 0;
if ( !active ){bins.setEnabled( true );}
}
plinkoboard.repaint();plinkoboard.requestFocus();
}
if(obj == close){stop();}
}
public void stateChanged( ChangeEvent ce ){
Object obj = ce.getSource();
if ( obj == bins ){
count.setText( "0" );
plinkoboard.setup( );
plinkoboard.newHist( );
plinkoboard.drawBackground();
} else if ( obj == rate ){
} else if ( obj == prob ){
plinkoboard.updatePercent();
plinkoboard.repaint();
}
}
 
public void windowActivated( WindowEvent we ){
//splash.start();
}
 
public void windowClosed( WindowEvent we ){
//splash.start();
}
 
public void windowClosing( WindowEvent we ){
//splash.start();
}
 
public void windowDeactivated( WindowEvent we ){
//splash.start();
}
 
public void windowDeiconified( WindowEvent we ){}
 
public void windowIconified( WindowEvent we ){}
 
public void windowOpened( WindowEvent we ){}
public String getAppletInfo(){
return "Written by Dr. P. Little \n http://www.math.psu.edu/dlittle/java/probability/plinko/index.html" ;
}
 
/*
public void keyTyped( KeyEvent ke ){
int code = ke.getKeyCode();
char key = ke.getKeyChar();
 
if ( key >= '0' && key <= '4' ){
int x = key - '0';
int n = 1;
for (int i=0; i<x; i++ ){
n *= 10;
}
for (int i=0; i<n; i++){
plinkoboard.dropBall();
}
} else if ( key == ' ' ){
toggleStart();
} else if (key==20){ //control t - toggle erasing
plinkoboard.toggleErase();
} else if (key==3){ //control c - clear screen
plinkoboard.newHist();
} else if (key==24){ //control x - kill all threads and clear screen
plinkoboard.kill();
} else if (key==16){ //control p - toggle displaying probabilities
//plinkoboard.toggleProbabilities();
}
}
 
public void keyPressed( KeyEvent ke ){
}
public void keyReleased( KeyEvent ke ){
}*/
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/src/PlinkoBoard.java
0,0 → 1,655
/*
Copyright 2004-2006 David P. Little
license:
Unless otherwise stated, the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
Modified for wims interactive usage with permission of the author.
J.M. Evers
*/
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
 
public class PlinkoBoard extends JPanel implements Runnable, KeyListener, MouseListener, MouseMotionListener{
 
double COUNT; // number of balls that have been dropped
double TOTAL; // total of bins
double TOTAL_SQUARES; // total of bins
long[] HIST; // number of balls in each bin;
float MAX; // maximum number of balls in a single bin
double[][][] PINS; // coordinates of pins (including one at the base of each bin)
double DIST; // vertical distance between pins
double BALL_RAD; // radius of ball
int PIN_RAD; // radius of pin
int BINS; // total number of bins
int W; // width of board
int H; // height of board
PlinkoBall FIRST_BALL; // represents beginning of doubly linked list of plinko balls
int BALL_COUNT;
int BOTTOM_MARGIN = 5;
// used in calculating confidence intervals
int LEFT;
int RIGHT;
double PERCENT;
int CURRENT_BIN = 0;
int showstats=0;
static double[][] DYS;
// jm.evers: defining a few things
int maximum_balls;String start_number="0";int incr=1;
static Color[] COLORS = { Color.red, Color.magenta, Color.orange, Color.yellow, Color.green, Color.blue, Color.cyan };
/* new Color(.45f,.40f,.86f), new Color(.36f,.53f,.95f),
new Color(.38f,.84f,.67f), new Color(.37f,.74f,.44f), new Color(.49f,.51f,.36f), new Color(.90f,.90f,.35f),
new Color(.99f,.75f,.34f), new Color(.85f,.27f,.42f), new Color(.73f,.34f,.76f), new Color(.51f,.33f,.82f),
new Color(.41f,.46f,.91f), new Color(.36f,.73f,.79f), new Color(.38f,.79f,.56f), new Color(.44f,.60f,.37f),
new Color(.70f,.71f,.35f), new Color(.99f,.91f,.34f), new Color(.99f,.58f,.34f), new Color(.94f,.38f,.34f),
new Color(.86f,.33f,.68f), new Color(.35f,.09f,.73f), new Color(.09f,.13f,.80f), new Color(.09f,.38f,.35f),
new Color(.18f,.55f,.13f), new Color(.55f,.74f,.11f), new Color(.99f,.92f,.09f), new Color(.99f,.69f,.09f),
new Color(.99f,.46f,.09f), new Color(.96f,.25f,.11f), new Color(.93f,.09f,.12f), new Color(.42f,.09f,.69f),
new Color(.27f,.09f,.78f), new Color(.09f,.29f,.51f), new Color(.09f,.46f,.20f), new Color(.36f,.64f,.12f),
new Color(.73f,.83f,.10f), new Color(.99f,.80f,.09f), new Color(.99f,.57f,.09f), new Color(.98f,.31f,.10f),
new Color(.94f,.12f,.11f), new Color(.16f,.10f,.06f), new Color(.36f,.24f,.14f), new Color(.55f,.38f,.21f),
new Color(.75f,.52f,.29f), new Color(.80f,.78f,.76f), new Color(.55f,.50f,.45f), new Color(.24f,.22f,.20f),
new Color(.76f,.76f,.80f), new Color(.45f,.45f,.55f), new Color(.20f,.20f,.24f)};*/
//BufferedImage[] IMAGES;
Image[] IMAGES;
Thread thread;
boolean active;
Image background;
Image image;
Graphics2D graphics;
Plinko plinko;
public PlinkoBoard( Plinko plinko ){
super();
this.plinko = plinko;
setup();
newHist();
 
FIRST_BALL = null;
BALL_COUNT = 0;
active = false;
 
DYS = new double[12][];
 
for ( double i=0.0; i<12.0; i++ ){
DYS[(int)i] = new double[ (int)i ];
for ( double j=0.0; j<i; j++ ){
DYS[(int)i][(int)j] = PlinkoBall.A*j*j/(i*i) + PlinkoBall.B*j/i;
}
}
 
addKeyListener( this );
addMouseListener( this );
// jm.evers: if the applet is in an wims exercise...read appletparam and start buckets_number with 1 instead of 0
maximum_balls=(int)plinko.total_balls - 1;
if(plinko.wims_exercise == false){ showstats = 1;}else{ start_number="1"; incr=2; }
}
 
public void setup(){
W = getWidth();
H = getHeight();
 
BINS = ((Integer)plinko.bins.getValue()).intValue();
CURRENT_BIN = BINS/2;
LEFT = BINS+1;
RIGHT = BINS;
PERCENT = 0;
 
if ( H-100-BOTTOM_MARGIN<W/2 ){
DIST = (double)(H-100-BOTTOM_MARGIN)/BINS;
} else {
DIST = (double)(W-10)/(2*BINS);
}
 
PIN_RAD = (int)DIST/9 + 1;
BALL_RAD = Math.max(2*DIST/7,2.0)+1;
// create images of colored balls
IMAGES = new Image[ COLORS.length ];
Graphics2D g;
int red;
int green;
int blue;
for ( int i=0; i<COLORS.length; i++ ){
IMAGES[i] = getBall( BALL_RAD, COLORS[i] );
/*
IMAGES[i] = new BufferedImage( (int)(2*BALL_RAD+2), (int)(2*BALL_RAD+2), BufferedImage.TYPE_INT_ARGB);
g = (Graphics2D)(IMAGES[i].getGraphics());
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
g.setBackground( new Color(0,0,0,255) );
 
red = COLORS[i].getRed();
green = COLORS[i].getGreen();
blue = COLORS[i].getBlue();
for ( float k=0; k<1; k=k+(float)(1/BALL_RAD) ){
g.setColor( new Color(red + (int)(k*k*(255-red)),green + (int)(k*k*(255-green)),blue + (int)(k*k*(255-blue))) );
g.fill( new Ellipse2D.Double( k*k*BALL_RAD/2, k*k*BALL_RAD/2, 2*(BALL_RAD-k*k*BALL_RAD), 2*(BALL_RAD-k*k*BALL_RAD) ) );
}
*/
}
 
PINS = new double[BINS][][];
for (int i=0; i<BINS; i++){
PINS[i] = new double[i+1][2];
for (int j=0; j<=i; j++){
//PINS[i][j] = new Point((int)(DIST*(2*j-i)+W/2),(int)(DIST*(i+1)));
PINS[i][j][0] = DIST*(2*j-i)+W/2;
PINS[i][j][1] = DIST*(i+1);
}
}
// pins at the base of each bin
for (int i=0; i<BINS; i++){
//PINS[BINS-1][i] = new Point((int)(DIST*(2*i-BINS+1)+W/2),(int)(H-30-BALL_RAD));
PINS[BINS-1][i][0] = DIST*(2*i-BINS+1)+W/2;
PINS[BINS-1][i][1] = H-30-BALL_RAD;
}
}
public static Image getBall( double R, Color color ){
BufferedImage image = new BufferedImage( (int)(2*R+2), (int)(2*R+2), BufferedImage.TYPE_INT_ARGB);
int red;
int grn;
int blu;
double[] n = new double[3];
double[] e = new double[3];
double[] l = {-5,5,10};
double ll = Math.sqrt(150);
double F;
double G;
 
for ( int i=0; i<(int)(2*R+2); i++ ){
for ( int j=0; j<(int)(2*R+2); j++ ){
if ( (R-i)*(R-i) + (R-j)*(R-j) <= (R-1)*(R-1) ){
// vector normal to sphere
n[0] = (i - R)/R;
n[1] = (R - j)/R;
n[2] = Math.sqrt(1 - n[0]*n[0] - n[1]*n[1]);
F = (n[0]*l[0] + n[1]*l[1] + n[2]*l[2])/Math.sqrt(l[0]*l[0] + l[1]*l[1] + l[2]*l[2]);
F = (1+F)/2;
G = Math.pow(F,20.0);
 
red = (int)(color.getRed()*(F-G) + G*255);
grn = (int)(color.getGreen()*(F-G) + G*255);
blu = (int)(color.getBlue()*(F-G) + G*255);
 
image.setRGB(i,j, (255<<24) + (red<<16) + (grn<<8) + blu );
} else if ( (R-i)*(R-i) + (R-j)*(R-j) <= (R+1)*(R+1) ){
red = 0;
grn = 0;
blu = 0;
for ( double di = -0.33; di<0.5; di+=0.33 ){
for ( double dj = -0.33; dj<0.5; dj+=0.33 ){
if ( (R-(i+di))*(R-(i+di)) + (R-(j+dj))*(R-(j+dj)) <= R*R ){
n[0] = (i + dj - R)/R;
n[1] = (R - (j+dj))/R;
n[2] = Math.sqrt(1 - n[0]*n[0] - n[1]*n[1]);
 
F = (n[0]*l[0] + n[1]*l[1] + n[2]*l[2])/ll;
F = (1+F)/2;
G = Math.pow(F,20.0);
} else {
F = 1;
G = 1;
}
red += (int)(color.getRed()*(F-G) + G*255);
grn += (int)(color.getGreen()*(F-G) + G*255);
blu += (int)(color.getBlue()*(F-G) + G*255);
 
}
}
red /= 9;
grn /= 9;
blu /= 9;
image.setRGB(i,j, ((255-(red+grn+blu)/3)<<24) + (red<<16) + (grn<<8) + blu );
}
}
}
return image;
}
public void newHist(){
COUNT = 0;
TOTAL = 0;
TOTAL_SQUARES = 0;
MAX = 0;
PERCENT = 0;
 
HIST = new long[ BINS ];
for (int i=0; i<BINS; i++){
HIST[i] = 0;
}
}
 
// jm.evers :preparing a data string for javascript: must be of type string: arrays always give trouble on IE...
public String ReadData(){
String reply="";
for(int i=0;i<HIST.length;i++){
if(i != 0){reply=reply+","+HIST[i];}else{reply=""+HIST[0];}
}
return reply;
}
public void LimitReached(){
plinko.active = true;
FIRST_BALL=null;
plinko.toggleStart();
}
 
public void run(){
while ( BALL_COUNT>0 ){
repaint();
try {Thread.sleep(50);} catch (InterruptedException e){}
}
repaint();
active = false;
plinko.active = false;
plinko.bins.setEnabled( true );
}
 
 
// under construction
public void kill(){
FIRST_BALL = null;
if ( plinko.start.getText().equals(plinko.start_text) ){
active = false;
plinko.active = false;
plinko.bins.setEnabled( true );
}
}
 
 
public void dropBall( boolean sound ){
BALL_COUNT++;
// jm.evers : I don't know of another/better way to get the system to stop at a given [param] number of balls...
if(COUNT == maximum_balls ){LimitReached();}
if ( FIRST_BALL == null ){
FIRST_BALL = new PlinkoBall();
FIRST_BALL.sound = sound;
} else {
FIRST_BALL.previousBall = new PlinkoBall();
FIRST_BALL.previousBall.sound = sound;
FIRST_BALL.previousBall.nextBall = FIRST_BALL;
FIRST_BALL = FIRST_BALL.previousBall;
}
 
try { Thread.sleep(0);} catch (InterruptedException e){}
if ( !active ){
active = true;
thread = new Thread(this);
thread.start();
}
}
 
public void paintComponent( Graphics g ){
// have a copy of the background on which to draw
W = getWidth();
H = getHeight();
 
if ( background == null || background.getWidth(this) != W || background.getHeight(this) != H || image == null || image.getWidth(this) != W || image.getHeight(this) != H ){
setup();
background = createImage( W, H );
drawBackground(W,H);
image = createImage( W, H );
graphics = (Graphics2D) image.getGraphics();
graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
graphics.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
}
 
graphics.drawImage( background, 0, 0, this );
 
// run through all active balls and draw them on the image
PlinkoBall ball = FIRST_BALL;
while ( ball != null ){
graphics.drawImage( IMAGES[ball.spaz], (int)(ball.X - BALL_RAD), (int)(ball.Y - 2*BALL_RAD - PIN_RAD + 1), this );
//if ( ball.t == ball.C && ball.ROW < BINS-2 ) Plinko.click.play();
//try {
increment( ball );
//} catch ( NullPointerException npe ) {
//}
ball = ball.nextBall;
}
drawHist( graphics );
// if(showstats==1){
drawStats( graphics );
// }
g.drawImage(image,0,0,this);
}
// under construction
public void drawNormal(){
}
public void increment( PlinkoBall ball ){
// if ball has landed on pin, reset t to 0 and pick a direction
if ( ball.t == ball.C && ball.ROW < BINS-2 ){
ball.ROW++;
ball.COL += ball.DIR;
ball.t = 0;
ball.DIR = 0;
// pick a new direction
// jm.evers: reading controls or applet param...plinko.chance is parameter
if(plinko.wims_exercise == false){
if ( Math.random() < ((Double)plinko.prob.getValue()).doubleValue() ) ball.DIR = 1;
}
else
{
if ( Math.random() < plinko.chance ){ ball.DIR = 1;}
}
 
// update speed
ball.C = 11-((Integer)plinko.rate.getValue()).intValue();
if ( ball.sound ) Plinko.ping.play();
}
 
double dx = (double)(DIST*ball.t*(2*ball.DIR - 1))/(double)(ball.C);
 
if ( ball.ROW < 0 ){
// ball falling onto top pin
ball.X = PINS[0][0][0];
dx = Math.abs(dx);
ball.Y = PINS[0][0][1] - DIST + DIST*ball.t*ball.t/(ball.C*ball.C);
} else if ( ball.ROW < BINS-2 ) {
ball.X = PINS[ball.ROW][ball.COL][0] + dx;
dx = Math.abs(dx);
ball.Y = PINS[ball.ROW][ball.COL][1] - DIST*DYS[ball.C][ball.t];
} else {
// ball falling into bin
// dx = DIST*ball.t*(2*ball.DIR - 1)/10.0;
ball.X = PINS[ball.ROW][ball.COL][0] + dx;
if ( dx>0 ){
ball.X = Math.min(ball.X,PINS[ball.ROW][ball.COL][0] + 2*DIST - BALL_RAD );
} else {
ball.X = Math.max(ball.X,PINS[ball.ROW][ball.COL][0] - 2*DIST + BALL_RAD + 1);
}
dx = Math.abs(dx);
ball.Y = PINS[ball.ROW][ball.COL][1] - dx*(ball.A*dx/DIST+ball.B);
}
 
ball.t++;
 
if ( ball.Y > H - BOTTOM_MARGIN - PIN_RAD ){
if ( ball.previousBall != null && ball.nextBall != null){
ball.previousBall.nextBall = ball.nextBall;
ball.nextBall.previousBall = ball.previousBall;
} else if ( ball.previousBall != null && ball.nextBall == null ) {
ball.previousBall.nextBall = null;
} else if ( ball.previousBall == null && ball.nextBall != null ) {
ball.nextBall.previousBall = null;
FIRST_BALL = ball.nextBall;
} else {
FIRST_BALL = null;
plinko.bins.setEnabled( true );
}
 
BALL_COUNT--;
updateHist(ball.COL+ball.DIR);
if ( ball.sound ) Plinko.click.play();
}
}
public void updateHist( int i ){
HIST[i]++;
COUNT++;
TOTAL += i;
TOTAL_SQUARES += i*i;
if ( HIST[i] > MAX) MAX = HIST[i];
if ( i>= LEFT && i <= RIGHT ){
PERCENT++;
}
}
 
public void drawStats(Graphics g){
//jm.evers : if in a wims_exercise we show a limited amount of statistical data...
if(showstats == 1){
plinko.count.setText(plinko.label_count+ (int)COUNT);
plinko.current_bin.setText(plinko.label_bin + CURRENT_BIN);
plinko.current_bin_count.setText(plinko.label_bin_count + HIST[CURRENT_BIN]);
if(COUNT > 0.0D){
double d = TOTAL / COUNT;
plinko.mean.setText(plinko.label_mean + (float)d);
plinko.variance.setText(plinko.label_variance + (float)(TOTAL_SQUARES / COUNT - d * d));
plinko.current_bin_prob.setText(plinko.label_bin_probability + (float)((double)(int)((double)(0x186a0L * HIST[CURRENT_BIN]) / COUNT) / 1000D) + "%");
if(LEFT < BINS){
if(LEFT == RIGHT){
plinko.confidence.setText(plinko.label_confidence + (float)((double)(int)((100000D * PERCENT) / COUNT) / 1000D) + plinko.some_text + LEFT + ".");
}
else
{
plinko.confidence.setText(plinko.label_confidence + (float)((double)(int)((100000D * PERCENT) / COUNT) / 1000D) + plinko.some_text + LEFT + plinko.through + RIGHT + ".");
}
}
else
{
plinko.confidence.setText(plinko.label_confidence );
}
}
else
{
plinko.mean.setText(plinko.label_mean );
plinko.variance.setText(plinko.label_variance);
plinko.current_bin_prob.setText(plinko.label_bin_probability);
plinko.confidence.setText(plinko.label_confidence);
}
}
else
{
// just the total COUNT and "balls per active bin"
plinko.count.setText(plinko.label_count+ (int)COUNT);
plinko.current_bin.setText(plinko.label_bin + (CURRENT_BIN+1));
plinko.current_bin_count.setText(plinko.label_bin_count + HIST[CURRENT_BIN]);
}
}
 
public void drawHist( Graphics2D g ){
long h;
double x0;
double x1;
String str;
W = getWidth();
H = getHeight();
Rectangle2D rect;
 
for (int i=0; i<BINS; i++){
if ( i==0 ){
x0 = PINS[BINS-1][0][0]-DIST;
x1 = PINS[BINS-2][0][0];
} else if ( i==BINS-1 ){
x0 = PINS[BINS-2][BINS-2][0];
x1 = PINS[BINS-1][BINS-1][0]+DIST;
} else {
x0 = PINS[BINS-2][i-1][0];
x1 = PINS[BINS-2][i][0];
}
 
//Draw bar
h = HIST[i];
if (MAX>100) h=(int)(100.0*h/MAX);
g.setColor( new Color(255,0,0,175) );
if ( i >= LEFT && i <= RIGHT ) g.setColor( new Color(0,255,0,175) );
rect = new Rectangle2D.Double(x0,H-h-BOTTOM_MARGIN,x1-x0,h);
g.fill( rect );
g.setColor(Color.black);
g.setStroke( new BasicStroke(1.0f) );
g.draw( rect );
}
// draw line under current bin
g.setColor( Color.black );
g.setStroke( new BasicStroke(3.0f) );
g.draw( new Line2D.Double(PINS[BINS-1][CURRENT_BIN][0]-DIST,H-BOTTOM_MARGIN+3,PINS[BINS-1][CURRENT_BIN][0]+DIST,H-BOTTOM_MARGIN+3) );
}
public void drawBackground(){
drawBackground( getWidth(), getHeight() );
}
 
 
public void drawBackground( int W, int H ){
double[] p;
 
Graphics2D backgroundgraphics = (Graphics2D) background.getGraphics();
backgroundgraphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
backgroundgraphics.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
backgroundgraphics.setColor(Color.white);
backgroundgraphics.fillRect( 0, 0, W, H );
backgroundgraphics.setColor(Color.black);
 
Image img = getBall( PIN_RAD, Color.black );
 
// draw pins
for (int i=0; i<BINS-1; i++){
for (int j=0;j<=i;j++){
p = PINS[i][j];
//backgroundgraphics.fill( new Ellipse2D.Double(p[0]-PIN_RAD,p[1]-PIN_RAD,2*PIN_RAD,2*PIN_RAD) );
backgroundgraphics.drawImage(img, (int)(p[0]-PIN_RAD),(int)(p[1]-PIN_RAD),this );
}
}
 
String s;
backgroundgraphics.setFont( new Font("Helvetica",Font.BOLD,Math.min((int)(4*DIST)/3,50)) );
FontMetrics fm = backgroundgraphics.getFontMetrics();
// draw lines and numbers
p = PINS[BINS-1][0];
backgroundgraphics.draw( new Line2D.Double( p[0]-DIST,H-100-BOTTOM_MARGIN,p[0]-DIST,H-BOTTOM_MARGIN) );
backgroundgraphics.setColor( Color.darkGray );
backgroundgraphics.drawString(start_number,(int)(p[0] - fm.stringWidth("0")/2), H-100-BOTTOM_MARGIN+Math.min((int)(4*DIST)/3, 50) );
for (int i=0; i<BINS-1; i++){
p = PINS[BINS-2][i];
s = ""+(i+incr);
backgroundgraphics.setColor( Color.darkGray );
backgroundgraphics.drawString(s,(int)(p[0] + DIST - fm.stringWidth(s)/2),H-100-BOTTOM_MARGIN+Math.min((int)(4*DIST)/3,50));
backgroundgraphics.setColor( Color.black );
backgroundgraphics.draw( new Line2D.Double( p[0],H-100-BOTTOM_MARGIN,p[0],H-BOTTOM_MARGIN) );
}
p = PINS[BINS-1][BINS-1];
backgroundgraphics.draw( new Line2D.Double(p[0]+DIST,H-100-BOTTOM_MARGIN,p[0]+DIST,H-BOTTOM_MARGIN) );
backgroundgraphics.draw( new Line2D.Double(0,H-BOTTOM_MARGIN,W,H-BOTTOM_MARGIN) );
repaint();
}
 
 
public void keyTyped( KeyEvent ke ){
}
public void keyPressed( KeyEvent ke ){
int code = ke.getKeyCode();
char key = ke.getKeyChar();
 
if ( key >= '0' && key <= '4' ){
int x = key - '0';
int n = 1;
for (int i=0; i<x; i++ ){
n *= 10;
}/*
plinko.countdown = n;
if ( !plinko.active ){
plinko.start();
plinko.bins.setEnabled( false );
plinko.thread = new Thread(plinko);
plinko.thread.start();
//start.setText("Stop");
}*/
for (int i=0; i<n; i++){
dropBall( n == 1 );
}
} else if ( code == 37 ){ // left arrow
CURRENT_BIN--;
if ( CURRENT_BIN<0 ) CURRENT_BIN = BINS - 1;
updatePercent();
repaint();
} else if ( code == 39 ){ // right arrow
CURRENT_BIN++;
if ( CURRENT_BIN>BINS-1 ) CURRENT_BIN = 0;
updatePercent();
repaint();
} else if ( code == KeyEvent.VK_ENTER ){ // return or enter
} else if ( key == ' ' ){
plinko.toggleStart();
} else if (key==20){ //control t - toggle erasing
} else if (key==3){ //control c - clear screen
} else if (key==24){ //control x - kill all threads
}
}
 
 
public void keyReleased( KeyEvent ke ){}
 
public void mouseReleased( MouseEvent me ){}
public void mouseEntered( MouseEvent me ){}
 
public void mouseExited( MouseEvent me ){}
public void updatePercent(){
double mean = (BINS-1)*((Double)plinko.prob.getValue()).doubleValue();
if ( CURRENT_BIN <= mean ){
LEFT = CURRENT_BIN;
RIGHT = (int)(2*mean) - LEFT;
} else {
RIGHT = CURRENT_BIN;
LEFT = (int)(2*mean) - RIGHT;
}
LEFT = Math.max( LEFT, 0 );
RIGHT = Math.min( RIGHT, BINS-1 );
PERCENT = 0;
for ( int i=LEFT; i<=RIGHT; i++ ){
PERCENT += HIST[i];
}
}
public void mouseClicked( MouseEvent me ){
requestFocus();
Point p = me.getPoint();
int bin;
if ( p.x + DIST> PINS[BINS-1][0][0] && p.x-DIST < PINS[BINS-1][BINS-1][0] && p.y> H-100-BOTTOM_MARGIN && p.y<H-BOTTOM_MARGIN){
bin = 0;
while ( bin<BINS-1 ){
if ( p.x + DIST < PINS[BINS-1][bin+1][0] ) break;
bin++;
}
CURRENT_BIN = bin;
updatePercent();
repaint();
}
}
 
 
public void mousePressed( MouseEvent me ){}
 
public void mouseDragged( MouseEvent me ){}
public void mouseMoved( MouseEvent me ){}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/README
0,0 → 1,117
This Plinko Applet is written by:
David Little [© 2004 David P. Little]
 
Mathematics Department
Penn State University
Eberly College of Science
University Park, PA 16802
Office: 403 McAllister
Phone: (814) 865-3329
Fax: (814) 865-3735
e-mail:dlittle@psu.edu
 
See:
http://www.math.psu.edu/dlittle/java/probability/plinko/index.html
 
 
----- INFO ---------
Plinko and the Binomial Distribution
A Bernoulli trial is an experiment that results in a success
with probability p and a failure with probability 1-p.
A random variable is said to have a Binomial Distribution if
it is the result of recording the number of successes in n independent Bernoulli trials.
 
In the Applet below, we have represented repeated independent Bernoulli trials by a single ball
falling through an array of pins. Each time a ball falls onto a pin, it will bounce to the right
(i.e. a success) with probability p or to the left (i.e. a failure) with probability 1-p.
After the ball falls through the array, it lands in a bin labeled by the corresponding number of successes.
 
Click on a bin to see its corresponding total and probability.
Alternatively, use the left and right arrow buttons to scroll through the bins.
Also displayed is a confidence interval centered on the theoretical expected bin.
Bins that are included in this confidence interval are highlighted in green.
 
* The name Plinko refers to a game played on The Price Is Right.
However, the game show version is played on a rectangular array of pins instead of a triangular array.
It would be more appropriate to call our applet Galton's board or a quincunx board,
however this is far more difficult to pronounce.
 
 
----- USAGE ---------
 
© 2004 David P. Little
Download this applet for off-line viewing (includes source code)
 
 
© 2004-2006 David P. Little
Unless otherwise stated,
the above applets were written by David Little.
They may be used without permission from the author for home and/or educational (non-profit) purposes only.
Any other use must be approved by the author.
 
------ WIMS USAGE -------
 
11/2010 J.M. Evers:
Corrected param flaw (speed could not be changed from default speed=1 )
 
7/2008 J.M. Evers:
 
To use the applet as part of an interactive WIMS exercise,
the source code had to be slightly modified.
 
see http://wims.math.leidenuniv.nl/wims/wims.cgi?lang=en&module=H4/stat/stat-1.nl&cmd=intro
 
Changes:
 
1) Introducing a few applet params to tailor the behaviour of the applet
by dynamic wims_variables and reading the generated data
from the applet with a javascript function.
 
These statistical data will be send to the wims-server for evaluation and
grading.
 
If the "wims_exercise" applet parameter is not set [ or "no" or "0" ] ,
the applet is identical to the original applet.
And all other params are "silently ignored".
 
 
2) Furthermore some text is translated to Dutch [nl] ,German [de] and French [fr] to be able
use the applet in multi-language exercises.
If no language param is set or not nl,de,fr : the language is English
 
3) And a "Close" button is added to the frame [to close the popup-window]
 
4) Bin numbering starts with "1" instead of "0" , if the applet <param name="wims_exercise" value="1">
 
Credits to the author are available:
- in the applet info
- in the specific wims-exercises using the applet
- a link to the website of the author is available in the exercise [js:onmouseover()]
 
 
Example:
<html>
<body>
<script language="javascript" type="text/javascript">
function getdata(){
var input=document.applets[0].ReadApplet();
alert("data to send:"+input);
document.applets[0].stop();
}
</script>
<APPLET CODE="Plinko.class" WIDTH=220 HEIGHT=100>
<param name="wims_exercise" value="yes">
<param name="xsize" value="440">
<param name="ysize" value="440">
<param name="fontsize" value="12">
<param name="bins" value="7">
<param name="chance" value="0.5">
<param name="speed" value="1">
<param name="title" value="Applet by Dr. P. Little">
<param name="language" value="en">
<param name="balls" value="55">
</APPLET>
<p>
<input type="button" name="READ" value="READ" onclick="javascript:getdata();">
</body>
</html>
/trunk/wims/src/Misc/authors/jm.evers/applets/Plinko/build.xml
0,0 → 1,69
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for Plinko.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="Plinko" default="jar" basedir=".">
 
<description>Plinko build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<mkdir dir="${build}/sounds"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
<exec executable="/bin/sh">
<arg line="-c 'cp ${source-dir}/sounds/*.au ${build}/sounds'"/>
</exec>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create Plinko jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/Plinko.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="Plinko"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="Plinko"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="Plinko">
<attribute name="Specification-Title" value="Plinko"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="Plinko"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/ChemInput/test.html
0,0 → 1,58
<html>
<body>
<script type="text/javascript">
function ReadThisTo(t){
var reply="";
if(t == 2){ reply = document.getElementById('MiniInputApplet').ReadHtml();}
else
if(t == 1){ reply = document.getElementById('MiniInputApplet').ReadAnswer();}
else {reply = document.getElementById('MiniInputApplet').ReadLatex();}
alert(reply.toString());
}
 
function ReadThis(t){
if(t == 2){ reply = document.getElementById('MiniInputApplet').ReadHtml();}
else
if(t == 1){ reply = document.getElementById('MiniInputApplet').ReadAnswer();}
else {reply = document.getElementById('MiniInputApplet').ReadLatex();}
alert(reply);
}
</script>
<applet id="ChemInput" name="ChemInput" code="ChemInputApplet.class" codebase="dist" archive="ChemInput.jar" width="140" height="40">
<param name="applettext" value="2C_{17}H_{35}CH_{2}OH + 54O_{2} \rightleftharpoons 36CO_{2} + 38H_{2}O"><!-- optional param, in "latex" -->
<param name="lang" value="nl"><!-- default en options nl,fr -->
<param name="fontsize" value="26"><!-- default 18 -->
<param name="frame_width" value="420"><!-- initial width of popup window ; is user resizable -->
<param name="frame_height" value="180"><!-- initial height of popup window ; is user resizable -->
<param name="pencolor" value="0,0,255,1"><!-- default black ; R,G,B,alpha -->
<param name="bgcolor1" value="250,240,240,0.2"><!-- canvas bgolor;default white ; R,G,B,alpha -->
<param name="bgcolor2" value="10,255,10,0.5"><!-- active typing bar; default green ;R,G,B,alpha -->
<param name="bgcolor3" value="250,240,225,0.2"><!-- menubbar color; default white ;R,G,B,alpha -->
<param name="chembuttons" value="1"><!-- Default 1/yes ; options 0/no ; shows a few arrows-->
<param name="navbuttons" value="1"><!-- Default 1/yes ; options 0/no ; shows a few navigation buttons -->
</applet
 
<applet id="MiniInputApplet" name="MiniInputApplet" code="MiniInputApplet.class" codebase="dist" archive="ChemInput.jar" width="440" height="40">
<param name="applettext" value="2C_{17}H_{35}CH_{2}OH + 54O_{2} \rightleftharpoons 36CO_{2} + 38H_{2}O">
<!-- optional param, in "latex" -->
<param name="lang" value="nl"><!-- default en options nl,fr -->
<param name="fontsize" value="16"><!-- default 18 -->
<param name="pencolor" value="0,0,255,1"><!-- default black ; R,G,B,alpha -->
<param name="bgcolor1" value="250,240,240,0.2"><!-- canvas bgolor;default white ; R,G,B,alpha -->
<param name="bgcolor2" value="10,255,10,0.5"><!-- active typing bar; default green ;R,G,B,alpha -->
<param name="bgcolor3" value="250,240,225,0.2"><!-- menubbar color; default white ;R,G,B,alpha -->
</applet
 
<p>
<input type="button" name="frame ascii" value="html" onclick="javascript:ReadThis(2);">
<input type="button" name="frame ascii" value="wims answer" onclick="javascript:ReadThis(1);">
<input type="button" name="frame Latex" value="Latex" onclick="javascript:ReadThis(0);">
<br>
<input type="button" name="embed ascii" value="html" onclick="javascript:ReadThisTo(2);">
<input type="button" name="embed ascii" value="wims answer" onclick="javascript:ReadThisTo(1);">
<input type="button" name="embed Latex" value="Latex" onclick="javascript:ReadThisTo(0);">
</body>
</html>
 
/trunk/wims/src/Misc/authors/jm.evers/applets/ChemInput/jarsign.sh
0,0 → 1,27
#!/bin/sh
 
# used for signing home_compiled new java-jars
 
echo "Give a name for the keystore
no spaces or strange charactera allowed !
"
 
read myname
mykey=".keystore"
myname="Schaersvoorde"
jar="ChemInput.jar"
 
 
if [ ! -e $mykey ] ; then
keytool -genkey -alias $myname
else
echo ".keystore file exists"
fi
 
if [ ! -e $myname.x509 ] ; then
keytool -export -alias $myname -rfc -file $myname.x509
else
echo "$myname.x509 file exists"
fi
jarsigner $jar $myname
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/ChemInput/src/ChemInputFrame.java
0,0 → 1,153
/*
 
*********************************************************************************
* J.M. Evers 19/11/2009*
* This is all amateur scriblings... So no copyrights.*
* This source code file, and compiled classes derived from it,*
* can be used and distributed without restriction, including for commercial use*
* No warrenty whatoever*
*********************************************************************************
 
*/
import java.awt.*;
import java.awt.event.*;
 
public class ChemInputFrame extends Frame implements ActionListener{
 
public static void main(String args[]){
new ChemInputFrame();
}
public ChemInputFrame(){
super(ChemInputApplet.Title);
setBackground(ChemInputApplet.bgcolor3);
canvas = new ChemInputCanvas();
add("Center", canvas);
setTitle(ChemInputApplet.Title);
getBounds();
 
Menu textMenu = new Menu(ChemInputApplet.Text, true);
// textMenu.add("HELP");
textMenu.add(ChemInputApplet.Clear);
textMenu.addSeparator();
textMenu.add(ChemInputApplet.Quit);
textMenu.addSeparator();
textMenu.add(ChemInputApplet.More);
textMenu.add(ChemInputApplet.Less);
textMenu.addActionListener(this);
Menu colorMenu = new Menu(ChemInputApplet.Color, true);
colorMenu.add("Red");
colorMenu.add("Blue");
colorMenu.add("Black");
colorMenu.addActionListener(this);
 
Menu manipMenu = new Menu("+/-", true);
manipMenu.add(ChemInputApplet.Insert);
manipMenu.add(ChemInputApplet.Up);
manipMenu.add(ChemInputApplet.Down);
manipMenu.add(ChemInputApplet.Left);
manipMenu.add(ChemInputApplet.Right);
manipMenu.addActionListener(this);
 
Menu chemMenu = new Menu(ChemInputApplet.Chemarrows, true);
chemMenu.add(ChemInputApplet.Arrow1);
chemMenu.add(ChemInputApplet.Arrow2);
chemMenu.addSeparator();
chemMenu.add(ChemInputApplet.Precip);
chemMenu.add(ChemInputApplet.Solid);
chemMenu.add(ChemInputApplet.Liquid);
chemMenu.add(ChemInputApplet.Gas);
chemMenu.add(ChemInputApplet.Precip);
chemMenu.addActionListener(this);
 
MenuBar mbar = new MenuBar();
if(ChemInputApplet.chembuttons && ChemInputApplet.navbuttons){
mbar.add(textMenu);
mbar.add(colorMenu);
mbar.add(manipMenu);
mbar.add(chemMenu);
}
else
{
if(ChemInputApplet.navbuttons){
mbar.add(textMenu);
mbar.add(colorMenu);
mbar.add(manipMenu);
}
else
{
if(ChemInputApplet.chembuttons){
mbar.add(chemMenu);
mbar.add(manipMenu);
}
}
}
setMenuBar(mbar);
setBounds(0, 0,ChemInputApplet.frame_x,ChemInputApplet.frame_y);
setResizable(true);
addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent evt){dispose();}});
//pack();
setVisible(true);
}
public void actionPerformed(ActionEvent evt){
String command = evt.getActionCommand();
if(command.equals("HELP [niet klaar]")){canvas.ShowHelp();}
else
if(command.equals(ChemInputApplet.Insert))
canvas.InsertKey("?", canvas.marked,true);
else
if(command.equals(ChemInputApplet.Up))
canvas.UpDownMarked(1,true);
else
if(command.equals(ChemInputApplet.Down))
canvas.UpDownMarked(-1,true);
else
if(command.equals(ChemInputApplet.Left))
canvas.LeftRightMarked(-1,true);
else
if(command.equals(ChemInputApplet.Right))
canvas.LeftRightMarked(1,true);
else
if(command.equals("Red")){canvas.pencolor = Color.red;canvas.update();}
else
if(command.equals("Blue")){canvas.pencolor = Color.blue;canvas.update();}
else
if(command.equals("Black")){canvas.pencolor = Color.black;canvas.update();}
else
if(command.equals(ChemInputApplet.Quit))
dispose();
else
if(command.equals(ChemInputApplet.Arrow1))
canvas.AppendSymbol(ChemInputApplet.Arrow1, 1);
else
if(command.equals(ChemInputApplet.Arrow2))
canvas.AppendSymbol(ChemInputApplet.Arrow2, 1);
else
if(command.equals(ChemInputApplet.Gas))
canvas.AppendSymbol("(g)",0);
else
if(command.equals(ChemInputApplet.Precip))
canvas.AppendSymbol("\u2193",0);
else
if(command.equals(ChemInputApplet.Solid))
canvas.AppendSymbol("(s)",0);
else
if(command.equals(ChemInputApplet.Liquid))
canvas.AppendSymbol("(aq)",0);
else
if(command.equals(ChemInputApplet.Clear))
canvas.clear();
else
if(command.equals(ChemInputApplet.More))
canvas.SwitchFont(6);
else
if(command.equals(ChemInputApplet.Less))
canvas.SwitchFont(-6);
 
}
ChemInputCanvas canvas;
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/ChemInput/src/ChemInputCanvas.java
0,0 → 1,452
/*
*********************************************************************************
* J.M. Evers 19/11/2009*
* This is all amateur scriblings... So no copyrights.*
* This source code file, and compiled classes derived from it,*
* can be used and distributed without restriction, including for commercial use*
* No warrenty whatoever*
*********************************************************************************
*/
 
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
 
class ChemInputCanvas extends Canvas implements MouseWheelListener,MouseListener, MouseMotionListener,KeyListener{
 
ChemInputCanvas(){
setBackground(ChemInputApplet.bgcolor1);
addMouseListener(this);
addKeyListener(this);
addMouseMotionListener(this);
addMouseWheelListener(this);
}
 
public synchronized void paint(Graphics g){
f = new Font("TimesRoman",Font.BOLD,newsize);
sf = new Font("TimesRoman",Font.BOLD,newsize - 6);
fm = g.getFontMetrics(f);
sfm = g.getFontMetrics(sf);
fh = fm.getHeight();
if(ChemInputApplet.once == false){
AppletText2Array(ChemInputApplet.applettext);
ChemInputApplet.once=true;
}
int wmax=getSize().width;
int hmax = getSize().height;
y0 = hmax/2;
g.clearRect(0,0,wmax,hmax);
int x1=0;
int y1;
int x2=getSize().width;
int y2;
if(marked !=-1){position=ChemInputApplet.CharPosition[marked];}
if(position == 2){y1=y0-fh;y2=fh/2;}
else
if(position == 0){y1=y0;y2=fh/2;}
else {y1=y0-fh/2;y2=fh/2;}
if(editing){
g.setColor(bgcolor2);
g.fillRect(x1,y1,x2,y2);
}
g.setColor(pencolor);
int w=0;
for(int i=0;i<ChemInputApplet.index;i++){
if(ChemInputApplet.CharArray[i] != null){
if(i == marked){g.setColor(Color.red);g.setFont(f);g.drawString("_",w,y1+fh);}
else{if(ChemInputApplet.CharArray[i].equals("?")){g.setColor(Color.red);}
else{g.setColor(pencolor);}}
if(ChemInputApplet.CharPosition[i] == 1){g.setFont(f);g.drawString(ChemInputApplet.CharArray[i],w,y0);}
else
if(ChemInputApplet.CharPosition[i] == 0){g.setFont(sf);g.drawString(ChemInputApplet.CharArray[i],w,y0 + fh/2);}
else
if(ChemInputApplet.CharPosition[i] == 2){g.setFont(sf);g.drawString(ChemInputApplet.CharArray[i],w,y0-fh/2);}
w=w+ChemInputApplet.CharWidth[i];
if(i == ChemInputApplet.index-1 && marked == -1){
g.setColor(Color.red);g.setFont(f);g.drawString("_",w,y1+fh/2);
}
}
}
}
public void update(){
if(ChemInputApplet.index > ChemInputApplet.max_chars - 4){ChemInputApplet.index = ChemInputApplet.max_chars - 4;}
repaint();
}
 
public String[] ForbiddenKeysChars={"!","~","`","@","#","$","%","&","|","\\","=","/","{","}"};
public int[] ForbiddenKeys={16,17,18,20,27,39,112,113,114,115,116,117,118,119,120};
public String[] AcceptedChars={"1","2","3","4","5","6","7","8","9","0","(",")"};
 
public void clear(){// niet vergeten applettxt in de arrays !
position=1;
marked=-1;
ChemInputApplet.once=false;
ChemInputApplet.CharArray = new String[ChemInputApplet.max_chars];
ChemInputApplet.CharPosition = new int[ChemInputApplet.max_chars];
ChemInputApplet.CharWidth = new int[ChemInputApplet.max_chars];
update();
ChemInputApplet.index=0;
}
public void SwitchFont(int s){
newsize=newsize + s;
update();
}
public void AppletText2Array(String text){
ChemInputApplet.once=true;
if(text.length() != 0){
text = ChemInputApplet.replace(text," ","");
text = ChemInputApplet.replace(text,"{","");
text = ChemInputApplet.replace(text,"\\rightarrow","\u21C4");
text = ChemInputApplet.replace(text,"\\leftrightarrow","\u2192");
text = ChemInputApplet.replace(text,"\\downarrow","\u2193");
int i;
for( i=0;i<text.length();i++){
if( text.charAt(i) == '^'){
i++;//remove ^
while(text.charAt(i) != '}' && i < text.length()){
ChemInputApplet.CharArray[i] = Character.toString(text.charAt(i));
ChemInputApplet.CharPosition[i] = 2;
ChemInputApplet.CharWidth[i] = sfm.charWidth(text.charAt(i));
i++;
}
}
else
if(text.charAt(i) == '_'){
i++;// remove _
while(text.charAt(i) != '}' && i < text.length()){
ChemInputApplet.CharArray[i] = Character.toString(text.charAt(i));
ChemInputApplet.CharPosition[i] = 0;
ChemInputApplet.CharWidth[i] = sfm.charWidth(text.charAt(i));
i++;
}
}
else
{
ChemInputApplet.CharArray[i] = Character.toString(text.charAt(i));
ChemInputApplet.CharPosition[i] = 1;
ChemInputApplet.CharWidth[i] = fm.charWidth(text.charAt(i));
}
}
marked = -1;
position = 1;
ChemInputApplet.index = i;
}
}
 
public synchronized void mousePressed(MouseEvent evt){
marked=-1;
int x = evt.getX();int y = evt.getY();int p=1;
if( y > y0 - 2*fh && y < y0 + 2*fh ){
if( y < y0 + fh && y > y0 + fh/4 ){ p = 0; } else { if ( y > y0 - 2*fh && y < y0 - fh/4){ p = 2;}}
int widthprogress=0;
for(int i=0; i<ChemInputApplet.index;i++){
if(x > widthprogress && x< widthprogress+ChemInputApplet.CharWidth[i]){
marked=i;
if(p!=1){ position=p;}else{position=ChemInputApplet.CharPosition[i];}
if(evt.getButton() == MouseEvent.BUTTON3 ){DeleteMarkedChar(marked);}
//if(evt.getButton() == MouseEvent.BUTTON2 || evt.getButton() == MouseEvent.BUTTON3 ){ProcessMarkedKey("?" ,155);}
repaint();
}
widthprogress = widthprogress + ChemInputApplet.CharWidth[i];
}
}
}
public void mouseWheelMoved(MouseWheelEvent evt){
position = NewPosition(-1*(evt.getWheelRotation()) , position);
if(marked!=-1){
ChemInputApplet.CharPosition[marked]=position;
}
update();
}
 
public synchronized void mouseDragged(MouseEvent evt){}
public synchronized void mouseReleased(MouseEvent evt){}
public void mouseEntered(MouseEvent mouseevent){editing=true;repaint();}
public void mouseExited(MouseEvent mouseevent){editing=false;repaint();}
public void mouseMoved(MouseEvent mouseevent){}
public void mouseClicked(MouseEvent mouseevent){}
 
public void keyPressed(KeyEvent e){
if(ChemInputApplet.index < ChemInputApplet.max_chars - 4){
//System.out.println("KEYCODE ="+e.getKeyCode());
int key = e.getKeyCode();
String key_char = Character.toString(e.getKeyChar());
if(marked == -1){ ProcessKey(key_char,key);}else{ProcessMarkedKey(key_char,key);}
repaint();
}else{ChemInputApplet.index=0;} //hhh
}
public void keyTyped(KeyEvent e ) {
}
public void keyReleased(KeyEvent e){
}
 
public void AppendKey(String key_char, int pos){
ChemInputApplet.CharPosition[ChemInputApplet.index] = pos;
ChemInputApplet.CharArray[ChemInputApplet.index] = key_char;
int w=0;// find length string
for(int i=0;i<key_char.length();i++){
if(pos == 0 || pos == 2){w=w+sfm.charWidth(key_char.charAt(i));}
else{w=w+fm.charWidth(key_char.charAt(i));}
}
if(pos == 0 || pos == 2){ ChemInputApplet.CharWidth[ChemInputApplet.index] = w;}
else { ChemInputApplet.CharWidth[ChemInputApplet.index] = w;}
ChemInputApplet.index++;
}
 
public void InsertKey(String key_char, int pos, boolean need_painting){
if(marked!=-1){
ChemInputApplet.index++;
for(int i=ChemInputApplet.index;i>marked;i--){
ChemInputApplet.CharArray[i]=ChemInputApplet.CharArray[i-1];
ChemInputApplet.CharPosition[i]=ChemInputApplet.CharPosition[i-1];
ChemInputApplet.CharWidth[i]=ChemInputApplet.CharWidth[i-1];
}
ChemInputApplet.CharArray[marked] = key_char;
ChemInputApplet.CharPosition[marked] = position;
if(position == 0 || position == 2){ ChemInputApplet.CharWidth[marked] = sfm.charWidth(key_char.charAt(0));}
else{ChemInputApplet.CharWidth[marked] = fm.charWidth(key_char.charAt(0));}
marked++;
}
if(need_painting){update();}
}
public void ProcessMarkedKey(String key_char ,int key){// only called if marked>-1
if(key == 37 ){LeftRightMarked(-1,false);}// linker pijl
else
if(key == 39 ){if(marked==ChemInputApplet.index-1){marked = -1;}else{LeftRightMarked(1,false);}}// rechter pijl
else
if( key == 38 || key == 33){UpDownMarked(1,false);}//up
else
if( key == 40 || key == 34){UpDownMarked(-1,false);}//down
else
if(key == 10 || key == 27){marked = -1;}// esc enter
if( (key == 8 || key == 127) && ChemInputApplet.index>0 ){DeleteMarkedChar(marked);position=1;marked--;}//backspace & delete on marked
else
if( (key == 8 || key == 127) && ChemInputApplet.index == 0 ){ position=1;marked=-1;ChemInputApplet.CharArray[0]=null; ChemInputApplet.CharPosition[0]=1;ChemInputApplet.CharWidth[0]=0;}//backspace & delete on marked
else
{
boolean found=false;
for(int i=0;i<AcceptedChars.length;i++){
if(AcceptedChars[i].equals(key_char) || key > 64 && key <91 || key == 45 || key == 61 ){found =true;}
}
if(found ==true){
///System.out.println("inserting="+key_char);
InsertKey(key_char,position,false);
}
}
}
 
public void AppendSymbol(String s, int pos){// VIA MUISKLIK + TOETSENBORD
if(marked != -1){InsertKey(s,pos,false);marked = -1;}else{AppendKey(s,pos);}
update();
}
public void UpDownMarked(int p , boolean need_painting ){
int i = NewPosition(p , position);
if(i != position){
position = i;
ChemInputApplet.CharPosition[marked] = position;
}
if(need_painting){update();}
}
 
public void LeftRightMarked(int p , boolean need_painting){
for(int i=0;i<ChemInputApplet.index;i++){
if(i == marked){
if( p == 1){ if(i<ChemInputApplet.index-1){i++;marked=i;}} else {if(i>0){marked=i-1;}}
}
}
if(need_painting){update();}
}
 
 
public void ProcessKey(String key_char ,int key){
boolean goodkey=true;
for(int i=0;i<ForbiddenKeysChars.length;i++){ if(key_char.equals(ForbiddenKeysChars[i]) && goodkey){ goodkey = false;} }
for(int i=0;i<ForbiddenKeys.length;i++){ if(key == ForbiddenKeys[i] && goodkey){ goodkey = false;} }
if(goodkey){
if( key == 33 ){ position = NewPosition(1 , position);}//pageup
else
if( key == 34 ){ position = NewPosition(-1 , position);}//pagedown
else
if( key == 36 ){marked = 0;}//home
else
if( key == 37 ){marked = ChemInputApplet.index-1;}//left arrow
else
if( key == 35 ){marked = ChemInputApplet.index-1;}//end
else
if( (key == 127 || key == 8) && ChemInputApplet.index>0){ChemInputApplet.index--; ChemInputApplet.CharArray[ChemInputApplet.index]=null; ChemInputApplet.CharPosition[ChemInputApplet.index]=1;ChemInputApplet.CharWidth[ChemInputApplet.index]=0;position=ChemInputApplet.CharPosition[ChemInputApplet.index];}
else
if( (key == 127 || key == 8) && ChemInputApplet.index==0){ position=1;marked=-1; ChemInputApplet.CharArray[0]=null; ChemInputApplet.CharPosition[0]=1;ChemInputApplet.CharWidth[0]=0;}
else
if( key == 38 || key == 94 ){ position = NewPosition(1 , position);}
else
if( key == 40 || key == 95 ){ position = NewPosition(-1 , position);}
else{
ChemInputApplet.CharArray[ChemInputApplet.index]=key_char;
ChemInputApplet.CharPosition[ChemInputApplet.index]=position;
if(position == 0 || position == 2){ChemInputApplet.CharWidth[ChemInputApplet.index]= sfm.charWidth(key_char.charAt(0)); } else { ChemInputApplet.CharWidth[ChemInputApplet.index]= fm.charWidth(key_char.charAt(0));}
ChemInputApplet.index++;
}
}
}
 
public int NewPosition(int P , int old){
int n = old + ( P );
if(n>2){n=2;}
else
if(n<0){n=0;}
return n;
}
public void DeleteMarkedChar(int c){
int m=0;
for(int i=ChemInputApplet.index-1;i>=0;i--){
if( i == c ){
ChemInputApplet.CharArray=DeleteStringItem(ChemInputApplet.CharArray,i);
ChemInputApplet.CharPosition=DeleteIntItem(ChemInputApplet.CharPosition,i);
ChemInputApplet.CharWidth=DeleteIntItem(ChemInputApplet.CharWidth,i);
ChemInputApplet.CharArray[ChemInputApplet.index-m]=null;
m++;
}
}
ChemInputApplet.index=ChemInputApplet.index-m;
}
public int[] DeleteIntItem(int[] array1, int del){
int m=0;
for(int i=0;i<array1.length-1;i++){
if(i >= del){
m=i+1;
array1[i]=array1[m];
}
}
return array1;
}
public String[] DeleteStringItem(String[] array1, int del){
int m=0;
for(int i=0;i<array1.length-1;i++){
if(i >= del){
m=i+1;
array1[i]=array1[m];
}
}
return array1;
}
 
public void ShowHelp(){
System.out.println("laat helptext zien");
}
 
public static String MakeText(){
String Text = "";//homebrew replace("","","") can't handle stringbuffer.toString()
for(int i=0;i<ChemInputApplet.max_chars;i++){
if(ChemInputApplet.CharArray[i] != null){
if(ChemInputApplet.CharPosition[i] == 1){Text=Text+ChemInputApplet.CharArray[i];}
else
if(ChemInputApplet.CharPosition[i] == 2 ){Text=Text+"^" ;
while(ChemInputApplet.CharPosition[i] == 2 && ChemInputApplet.CharArray[i]!=null){
Text=Text+ChemInputApplet.CharArray[i] ;
i++;
}
Text=Text+" ";
i=i-1;
}
else
if(ChemInputApplet.CharPosition[i] == 0 ){
while(ChemInputApplet.CharPosition[i] == 0 && ChemInputApplet.CharArray[i]!=null){
Text=Text+ChemInputApplet.CharArray[i] ;
i++;
}
Text=Text+" ";
i=i-1;
}
}
}
for(int p=1;p<10;p++){// Mn02 => MnO2
Text=ChemInputApplet.replace(Text,"0"+p,"O"+p);
}
return Text;
}
public static String MakeLaTeX(){
StringBuffer LaTeX = new StringBuffer();
for(int i=0;i<ChemInputApplet.max_chars;i++){
if(ChemInputApplet.CharArray[i] != null){
if(ChemInputApplet.CharPosition[i] == 1){LaTeX.append(ChemInputApplet.CharArray[i]);}
else
if(ChemInputApplet.CharPosition[i] == 2 ){LaTeX.append("^{") ;
while(ChemInputApplet.CharPosition[i] == 2 && ChemInputApplet.CharArray[i]!=null){
LaTeX.append(ChemInputApplet.CharArray[i]) ;
i++;
}
i=i-1;
LaTeX.append("}");
}
else
if(ChemInputApplet.CharPosition[i] == 0 ){LaTeX.append("_{");
while(ChemInputApplet.CharPosition[i] == 0 && ChemInputApplet.CharArray[i]!=null){
LaTeX.append(ChemInputApplet.CharArray[i]) ;
i++;
}
i=i-1;
LaTeX.append("}");
}
}
}
return LaTeX.toString();
}
 
public static String MakeHtml(){
StringBuffer Html = new StringBuffer();
for(int i=0;i<ChemInputApplet.max_chars;i++){
if(ChemInputApplet.CharArray[i] != null){
if(ChemInputApplet.CharPosition[i] == 1){Html.append(ChemInputApplet.CharArray[i]);}
else
if(ChemInputApplet.CharPosition[i] == 2 ){Html.append("<sup><font size=\"-1\">") ;
while(ChemInputApplet.CharPosition[i] == 2 && ChemInputApplet.CharArray[i]!=null){
Html.append(ChemInputApplet.CharArray[i]) ;
i++;
}
i=i-1;
Html.append("</font></sup>");
}
else
if(ChemInputApplet.CharPosition[i] == 0 ){Html.append("<sub><font size=\"-1\">");
while(ChemInputApplet.CharPosition[i] == 0 && ChemInputApplet.CharArray[i]!=null){
Html.append(ChemInputApplet.CharArray[i]) ;
i++;
}
i=i-1;
Html.append("</font></sub>");
}
}
}
return Html.toString();
}
 
public static int position=1;// 0,1,2 last edit
public int marked=-1;
public int newsize=ChemInputApplet.fontsize;
public static int y0;
public static FontMetrics fm;
public static FontMetrics sfm;
public static Font f;
public static Font sf;// small
public static int fh; //font height
boolean editing=false;
Color pencolor = ChemInputApplet.pencolor;
Color bgcolor1 = ChemInputApplet.bgcolor1;
Color bgcolor2 = ChemInputApplet.bgcolor2;
Color bgcolor3 = ChemInputApplet.bgcolor3;
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/ChemInput/src/ChemInputApplet.java
0,0 → 1,365
/*
 
*********************************************************************************
* J.M. Evers 19/11/2009*
* This is all amateur scriblings... So no copyrights.*
* This source code file, and compiled classes derived from it,*
* can be used and distributed without restriction, including for commercial use*
* No warrenty whatoever*
*********************************************************************************
 
Chemistry input applet for WIMS
 
Slightly based on ideas [and bits of code from...] http://web.uconn.edu/~cdavid
 
+ -
A chemical formula input like : H O + OH -> 2H O
3 2
And it's all amateur scriblings, no copyrights
 
Note: if the jar is not "signed" there will an annoying grey "bar" be visible with the text
"Java Applet Window". [in appletviewer this grey bar will probably be visible, anyway]
 
TODO: help & usage in onmouseover?
 
Example:
 
<html>
<body>
<script type="text/javascript">
function ReadThis(t){
var reply="";
if(t == 1){
reply = document.getElementById('ChemInput').ReadAnswer();
}
else
{
reply = document.getElementById('ChemInput').ReadLatex();
}
alert(reply);
}
</script>
<applet id="ChemInput" name="ChemInput" code="ChemInputApplet.class" archive="ChemInput.jar" width="120" height="40">
<param name="applettext" value="H_{3}O^{+} + OH^{-} \leftrightarrow "><!-- latex question ; default empty -->
<param name="lang" value="nl"><!-- default en options nl,fr -->
<param name="fontsize" value="18"><!-- default 18 -->
<param name="frame_width" value="420"><!-- initial width of popup window ; is user resizable -->
<param name="frame_height" value="180"><!-- initial height of popup window ; is user resizable -->
<param name="pencolor" value="0,0,255,0.8"><!-- default black ; R,G,B,alpha -->
<param name="bgcolor1" value="20,240,240,0.2"><!-- canvas color;default white ; R,G,B,alpha -->
<param name="bgcolor2" value="0,255,0,0.8"><!-- active typing bar; default green ;R,G,B,alpha -->
<param name="bgcolor3" value="255,255,255,0.8"><!-- menu color; default white ;R,G,B,alpha -->
<param name="chembuttons" value="1"><!-- Default 1/yes ; options 0/no ; shows a few arrows-->
<param name="navbuttons" value="1"><!-- Default 1/yes ; options 0/no ; shows a few navigation buttons -->
</applet
<p>
<input type="button" name="ascii" value="ascii" onclick="javascript:ReadThis(1);">
<input type="button" name="Latex" value="Latex" onclick="javascript:ReadThis(0);">
</body>
</html>
 
See "Schaersvoorde chemistry" WIMS modules for detailed usage
 
11/2010: added \rightleftharpoons arrow type
 
*/
 
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.awt.Color;
 
public class ChemInputApplet extends Applet implements ActionListener{
 
class ChemFrameListener extends WindowAdapter{
 
public synchronized void windowClosed(WindowEvent evt){
launchButton.setLabel(LaunchText);
launchButton.setEnabled(true);
chemInput = null;
}
 
ChemFrameListener(){}
}
 
 
public void init(){
//
String param="";
param = getParameter("lang");
if(param != null && param.length() == 2 ){
if(param.equalsIgnoreCase("nl")){
More="Groter lettertype";
Less="Kleiner lettertype";
Clear="Wissen";
Solid="vast";
Gas="gas";
Up="naar boven";
Down="naar beneden";
Precip="neerslag";
Liquid="opgelost";
LaunchText="Start Chemie Applet";
Chemarrows="Chemie";
Color="Kleur";
Text="Tekst";
CloseText="Sluit venster";
Title="Schaersvoorde Chemie Invoer Applet";
Insert="Invoegen";
Left="naar links";
Right="naar rechts";
}
else
{
if(param.equalsIgnoreCase("fr")){
More="larger font";
Less="smaller font";
Clear="Effacer";
Solid="solide";
Gas="gaz";
Up="Up";
Down="Down";
Precip="precipitation";
Liquid="liquide";
LaunchText="Start Chemie Applet";
Chemarrows="Chimie";
Color="Couleur";
Text="Texte";
CloseText="Fermer";
Title="WIMS Chimie Input Applet";
Insert="Inserer";
Left="Gauche";
Right="Droite`";
}
}
}
param=getParameter("applettext");
if(param != null && param.length() !=0){ applettext=filter1(param,"param2uni");}
 
param = getParameter("chembuttons");
if(param != null && param.length() != 0){ if(param.equalsIgnoreCase("no") || param.equals("0")){chembuttons = false; }}
 
param = getParameter("navbuttons");
if(param != null && param.length() != 0){ if(param.equalsIgnoreCase("no") || param.equals("0")){navbuttons = false; }}
param = getParameter("fontsize");
if(param != null && param.length() != 0){fontsize = Integer.parseInt(param);}
 
param = getParameter("frame_width");
if(param != null && param.length() != 0){frame_x = Integer.parseInt(param);}
 
param = getParameter("frame_height");
if(param != null && param.length() != 0){frame_y = Integer.parseInt(param);}
 
param=getParameter("pencolor");
if (param != null && param.length() != 0){pencolor = readColor(param);}
else pencolor=new Color(0,0,0);
 
param=getParameter("bgcolor1"); // bgcolor canvas
if (param != null && param.length() != 0){bgcolor1 = readColor(param);}
else bgcolor1=new Color(255,255,255);
 
param=getParameter("bgcolor2"); // bgcolor typeline
if (param != null && param.length() != 0){bgcolor2 = readColor(param);}
else bgcolor2=new Color(0,255,0);
 
param=getParameter("bgcolor3"); //bgcolor menu and button
if (param != null && param.length() != 0){bgcolor3 = readColor(param);}
else bgcolor1=new Color(255,255,255);
 
this.setBackground(bgcolor3);
setLayout(new BorderLayout());
launchButton = new Button(LaunchText);
add("Center", launchButton);
launchButton.addActionListener(this);
}
public Color readColor(String param){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;float rgb;R1=1.0f;G1=1.0f;B1=1.0f;alpha=0.5f;
//System.out.println("Color should be in R,G,B,alpha \n <param name=\"pencolor\" value=\"0,0,255,0.8\">");
for( int a=0; a<4 ; a++){
k=q.nextToken();
rgb=Float.parseFloat(k);
if(rgb<0){rgb=0.0f;}
if(rgb>255){rgb=1.0f;}
if(a == 0){R1 = (float)rgb/255;}
else if(a == 1){G1 = (float)rgb/255;}
else if(a == 2){B1 = (float)rgb/255;}
else if(a == 3){alpha = rgb;}
}
Color a = new Color(R1,G1,B1,alpha);
return a;
}
 
public boolean keyUp(Event event, int key){
return true;
}
public synchronized void actionPerformed(ActionEvent evt){
if(chemInput == null){
launchButton.setLabel(CloseText);
chemInput = new ChemInputFrame();
chemInput.addWindowListener(new ChemFrameListener());
}
else
{
launchButton.setLabel(LaunchText);
launchButton.setEnabled(false);
chemInput.dispose();
}
}
 
public synchronized void destroy(){
once=false;
CharArray = new String[max_chars];// no idea why this is the only way to remove the content of arrays...
CharPosition = new int[max_chars];
CharWidth = new int[max_chars];
if(chemInput != null){
chemInput.dispose();
chemInput = null;
}
}
 
public String ReadLatex(){
String reply = ChemInputCanvas.MakeLaTeX();
reply=filter1(reply,"uni2latex");
return reply;
}
 
public String ReadHtml(){
String reply = ChemInputCanvas.MakeHtml();
reply=filter1(reply,"uni2html");
return reply;
}
 
public String ReadAnswer(){
String reply = ChemInputCanvas.MakeText();
reply=filter1(reply,"uni2ascii");
return reply;
}
public static String replace(String source, String pattern, String replace){
if ( source!=null && pattern.length()!=0 ){
final int len = pattern.length();
StringBuffer sb = new StringBuffer();
int found = -1;
int start = 0;
while( (found = source.indexOf(pattern, start) ) != -1) {
sb.append(source.substring(start, found));
sb.append(replace);
start = found + len;
}
sb.append(source.substring(start));
return sb.toString();
}
else return "";
}
public String filter1(String S1 , String k ){
int p;String r1;String r2;
String d1[] = new String[]{"\\rightleftharpoons","->","=>","-->","==>","\\rightarrow","<->","<=>","<-->","<==>","\\leftrightarrow","\\downarrow","\\uparrow"};
String d2[] = new String[]{"\u21C4","\u2192","\u2192","\u2192","\u2192","\u2192","\u21C4","\u21C4","\u21C4","\u21C4","\u21C4","\u2193","\u2191"};
 
String d3[] = new String[]{" <-> "," -> "," -> "," -> "," -> "," -> "," <-> "," <-> "," <-> "," <-> "," <-> ","(s) ","(g) "};
 
String d4[] = new String[]{" \\rightleftharpoons "," \\rightarrow "," \\rightarrow "," \\rightarrow "," \\rightarrow "," \\rightarrow ",
" \\leftrightarrow "," \\leftrightarrow "," \\leftrightarrow "," \\leftrightarrow "," \\leftrightarrow ",
" \\downarrow "," \\uparrow "};
 
String d5[] = new String[]{"&nbsp;&lt;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;",
"&nbsp;&minus;&gt;&nbsp;","&nbsp;&gt;&minus;&gt;&nbsp;","&nbsp;&gt;&minus;&gt;&nbsp;","&nbsp;&gt;&minus;&gt;&nbsp;","&nbsp;&gt;&minus;&gt;&nbsp;",
"<sub>(s)</sub> ","<sub>(g)</sub>"};
int d=d1.length;
if(k.equals("param2uni")){// from ascii applettext-param to unicode applet
for ( p=0;p<d;p++){
r1=d1[p];
r2=d2[p];
S1=replace(S1,r1,r2);
}
}
else
{
if(k.equals("uni2ascii")){// from applet unicode to ascii [wims answer]
for ( p=0;p<d;p++){
r1=d2[p];
r2=d3[p];
S1=replace(S1,r1,r2);
}
}
else
{
if(k.equals("uni2latex")){// from applet unicode to latex [wims presentation presentation]
for ( p=0;p<d;p++){
r1=d2[p];
r2=d4[p];
S1=replace(S1,r1,r2);
}
}
else
{
if(k.equals("uni2html")){// from applet unicode to latex [wims presentation presentation]
for ( p=0;p<d;p++){
r1=d2[p];
r2=d5[p];
S1=replace(S1,r1,r2);
}
}
}
}
}
return S1;
}
 
 
 
public ChemInputApplet(){}
 
ChemInputFrame chemInput;
Button launchButton;
float R1,G1,B1,alpha;
public static boolean chembuttons = true;
public static boolean navbuttons = true;
public static boolean once = false;
public static int fontsize = 18;
public static int frame_x=420;
public static int frame_y=180;
public static String applettext="";
public static String Insert="Insert";
public static String Text="Text";
public static String Quit="Exit";
public static String Color="Color";
public static String Chemarrows="Chemistry";
public static String More="larger font";
public static String Less="smaller font";
public static String Solid="solid";
public static String Gas="gas";
public static String Clear="Clear";
public static String Arrow1="\u2192";
public static String Arrow2="\u21C4";
public static String Up="Up";
public static String Down="Down";
public static String Left="Left";
public static String Right="Right";
public static String Precip="Precipitate";
public static String Liquid="liquid";
public static String LaunchText="Launch Chemistry Applet";
public static String CloseText="Close Applet";
public static String error1="error empty answer ?";
public static String Title="WIMS chemistry input applet";
public static Color bgcolor1;
public static Color pencolor;
public static Color bgcolor2;
public static Color bgcolor3;
public static int max_chars = 200;
public static String[] CharArray = new String[max_chars];
public static int[] CharPosition = new int[max_chars];
public static int[] CharWidth = new int[max_chars];
public static int index=0;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/ChemInput/src/MiniInputApplet.java
0,0 → 1,722
/*
 
*********************************************************************************
* J.M. Evers 19/11/2009*
* This is all amateur scriblings... So no copyrights.*
* This source code file, and compiled classes derived from it,*
* can be used and distributed without restriction, including for commercial use*
* No warrenty whatoever*
*********************************************************************************
 
 
Chemistry input applet for WIMS
 
Slightly based on ideas [and bits of code from...] http://web.uconn.edu/~cdavid
 
+ -
A chemical formula input like : H O + OH -> 2H O
3 2
And it's all amateur scriblings, no copyrights
 
Note: if the jar is not "signed" there will an annoying grey "bar" be visible with the text
"Java Applet Window". [in appletviewer this grey bar will probably be visible, anyway]
 
TODO: help & usage in onmouseover?
 
Example:
 
<html>
<body>
<script type="text/javascript">
function ReadThis(t){
var reply="";
if(t == 1){
reply = document.getElementById('MiniInput').ReadAnswer();
}
else
{
reply = document.getElementById('MiniInput').ReadLatex();
}
alert(reply);
}
</script>
<applet id="MiniInput" name="MiniInput" code="MiniInputApplet.class" archive="MiniInput.jar" width="120" height="40">
<param name="applettext" value="H_{3}O^{+} + OH^{-} \leftrightarrow "><!-- latex question ; default empty -->
<param name="fontsize" value="18"><!-- default 18 -->
<param name="pencolor" value="0,0,255,0.8"><!-- default black ; R,G,B,alpha -->
<param name="bgcolor1" value="20,240,240,0.2"><!-- canvas color;default white ; R,G,B,alpha -->
<param name="bgcolor2" value="0,255,0,0.8"><!-- active typing bar; default green ;R,G,B,alpha -->
</applet
<p>
<input type="button" name="ascii" value="ascii" onclick="javascript:ReadThis(1);">
<input type="button" name="Latex" value="Latex" onclick="javascript:ReadThis(0);">
<ul>
<li>F1 increase fontsize</li>
<li>F2 decrease fontsize</li>
<li>F3 Rightarrow</li>
<li>F4 LeftRightarrow</li>
<li>F5 change pencolor</li>
<li>F6 change color background 1 </li>
<li>F7 change color background 2 </li>
<li>F8 delete all text : in case of param "applettext" this will de restored</li>
<li> -> will give Rightarrow</li>
</ul>
</body>
</html>
 
See "Schaersvoorde chemistry" WIMS modules for detailed usage
 
11/2010: added \rightleftharpoons arrow type
*/
 
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.awt.Color;
 
public class MiniInputApplet extends Applet implements KeyListener,MouseListener, MouseMotionListener, MouseWheelListener {
 
public void init(){
//
String param="";
param=getParameter("applettext");
if(param != null && param.length() !=0){ applettext=filter1(param,"param2uni");}
 
param = getParameter("fontsize");
if(param != null && param.length() != 0){fontsize = Integer.parseInt(param);}
 
param=getParameter("pencolor");
if (param != null && param.length() != 0){pencolor = readColor(param);}
else pencolor=new Color(0,0,0);
 
param=getParameter("bgcolor1"); // bgcolor canvas
if (param != null && param.length() != 0){bgcolor1 = readColor(param);}
else bgcolor1=new Color(255,255,255);
 
param=getParameter("bgcolor2"); // bgcolor typeline
if (param != null && param.length() != 0){bgcolor2 = readColor(param);}
else bgcolor2=new Color(0,255,0);
 
this.setBackground(bgcolor1);
addMouseListener(this);
addKeyListener(this);
addMouseMotionListener(this);
addMouseWheelListener(this);
 
 
}
public Color readColor(String param){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;float rgb;R1=1.0f;G1=1.0f;B1=1.0f;alpha=0.5f;
//System.out.println("Color should be in R,G,B,alpha \n <param name=\"pencolor\" value=\"0,0,255,0.8\">");
for( int a=0; a<4 ; a++){
k=q.nextToken();
rgb=Float.parseFloat(k);
if(rgb<0){rgb=0.0f;}
if(rgb>255){rgb=1.0f;}
if(a == 0){R1 = (float)rgb/255;}
else if(a == 1){G1 = (float)rgb/255;}
else if(a == 2){B1 = (float)rgb/255;}
else if(a == 3){alpha = rgb;}
}
Color a = new Color(R1,G1,B1,alpha);
return a;
}
 
public boolean keyUp(Event event, int key){
return true;
}
public String ReadLatex(){
String reply = MakeLaTeX();
reply=filter1(reply,"uni2latex");
return reply;
}
 
public String ReadHtml(){
String reply = MakeHtml();
reply=filter1(reply,"uni2html");
return reply;
}
 
public String ReadAnswer(){
String reply = MakeText();
reply=filter1(reply,"uni2ascii");
return reply;
}
public String replace(String source, String pattern, String replace){
if ( source!=null && pattern.length()!=0 ){
final int len = pattern.length();
StringBuffer sb = new StringBuffer();
int found = -1;
int start = 0;
while( (found = source.indexOf(pattern, start) ) != -1) {
sb.append(source.substring(start, found));
sb.append(replace);
start = found + len;
}
sb.append(source.substring(start));
return sb.toString();
}
else return "";
}
public String filter1(String S1 , String k ){
int p;String r1;String r2;
String d1[] = new String[]{"\\rightleftharpoons","->","=>","-->","==>","\\rightarrow","<->","<=>","<-->","<==>","\\leftrightarrow","\\downarrow","\\uparrow"};
String d2[] = new String[]{"\u21C4","\u2192","\u2192","\u2192","\u2192","\u2192","\u21C4","\u21C4","\u21C4","\u21C4","\u21C4","\u2193","\u2191"};
 
String d3[] = new String[]{" <-> "," -> "," -> "," -> "," -> "," -> "," <-> "," <-> "," <-> "," <-> "," <-> ","(s) ","(g) "};
 
String d4[] = new String[]{" \\rightleftharpoons "," \\rightarrow "," \\rightarrow "," \\rightarrow "," \\rightarrow "," \\rightarrow ",
" \\leftrightarrow "," \\leftrightarrow "," \\leftrightarrow "," \\leftrightarrow "," \\leftrightarrow ",
" \\downarrow "," \\uparrow "};
 
String d5[] = new String[]{"&nbsp;&lt;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;","&nbsp;&minus;&gt;&nbsp;",
"&nbsp;&minus;&gt;&nbsp;","&nbsp;&gt;&minus;&gt;&nbsp;","&nbsp;&gt;&minus;&gt;&nbsp;","&nbsp;&gt;&minus;&gt;&nbsp;","&nbsp;&gt;&minus;&gt;&nbsp;",
"<sub>(s)</sub> ","<sub>(g)</sub>"};
int d=d1.length;
if(k.equals("param2uni")){// from ascii applettext-param to unicode applet
for ( p=0;p<d;p++){
r1=d1[p];
r2=d2[p];
S1=replace(S1,r1,r2);
}
}
else
{
if(k.equals("uni2ascii")){// from applet unicode to ascii [wims answer]
for ( p=0;p<d;p++){
r1=d2[p];
r2=d3[p];
S1=replace(S1,r1,r2);
}
}
else
{
if(k.equals("uni2latex")){// from applet unicode to latex [wims presentation presentation]
for ( p=0;p<d;p++){
r1=d2[p];
r2=d4[p];
S1=replace(S1,r1,r2);
}
}
else
{
if(k.equals("uni2html")){// from applet unicode to latex [wims presentation presentation]
for ( p=0;p<d;p++){
r1=d2[p];
r2=d5[p];
S1=replace(S1,r1,r2);
}
}
}
}
}
return S1;
}
 
public synchronized void paint(Graphics g){
f = new Font("TimesRoman",Font.BOLD,fontsize);
sf = new Font("TimesRoman",Font.BOLD,fontsize-6);
fm = g.getFontMetrics(f);
sfm = g.getFontMetrics(sf);
fh = fm.getHeight();
if(once == false){
AppletText2Array(applettext);
once=true;
}
int wmax=getSize().width;
int hmax = getSize().height;
y0 = (hmax+fh)/2;
g.clearRect(0,0,wmax,hmax);
int x1=0;
int y1;
int x2=getSize().width;
int y2;
if(marked !=-1){position=CharPosition[marked];}
if(position == 2){y1=y0-fh;y2=fh/2;}
else
if(position == 0){y1=y0;y2=fh/2;}
else {y1=y0-fh/2;y2=fh/2;}
if(editing){
g.setColor(bgcolor2);
g.fillRect(x1,y1,x2,y2);
}
g.setColor(pencolor);
int w=0;
for(int i=0;i<index;i++){
if(CharArray[i] != null){
if(i == marked){
g.setColor(Color.red);g.setFont(f);g.drawString("_",w,y1+fh);
}
else
{
if(CharArray[i].equals("?")){
g.setColor(Color.red);
}
else
{
g.setColor(pencolor);
}
}
if(CharPosition[i] == 1){g.setFont(f);g.drawString(CharArray[i],w,y0);}
else
if(CharPosition[i] == 0){g.setFont(sf);g.drawString(CharArray[i],w,y0 + fh/2);}
else
if(CharPosition[i] == 2){g.setFont(sf);g.drawString(CharArray[i],w,y0-fh/2);}
w=w+CharWidth[i];
if(i == index-1 && marked == -1){
g.setColor(Color.red);g.drawString("_",w,y1+fh/2);
}
}
}
}
public void update(){
if(index > max_chars - 4){index = max_chars - 4;}
repaint();
}
 
public String[] ForbiddenKeysChars={"!","~","`","@","#","$","%","&","|","\\","=","/","{","}"};
public String[] AcceptedChars={"1","2","3","4","5","6","7","8","9","0","(",")"};
public int[] ForbiddenKeys={16,17,18,20,27,120,154,155};
public void clear(){// niet vergeten applettxt in de arrays !
//System.out.println("calling clear");
position=1;
marked=-1;
once=false;
CharArray = new String[max_chars];
CharPosition = new int[max_chars];
CharWidth = new int[max_chars];
update();
index=0;
}
public void SwitchFont(int s){
fontsize=fontsize + s;
update();
}
public void AppletText2Array(String text){
once=true;
if(text.length() != 0){
text = replace(text," ","");
text = replace(text,"{","");
text = replace(text,"\\rightarrow","\u21C4");
text = replace(text,"\\leftrightarrow","\u2192");
text = replace(text,"\\downarrow","\u2193");
int i;
for( i=0;i<text.length();i++){
if( text.charAt(i) == '^'){
i++;//remove ^
while(text.charAt(i) != '}' && i < text.length()){
CharArray[i] = Character.toString(text.charAt(i));
CharPosition[i] = 2;
CharWidth[i] = sfm.charWidth(text.charAt(i));
i++;
}
}
else
if(text.charAt(i) == '_'){
i++;// remove _
while(text.charAt(i) != '}' && i < text.length()){
CharArray[i] = Character.toString(text.charAt(i));
CharPosition[i] = 0;
CharWidth[i] = sfm.charWidth(text.charAt(i));
i++;
}
}
else
{
CharArray[i] = Character.toString(text.charAt(i));
CharPosition[i] = 1;
CharWidth[i] = fm.charWidth(text.charAt(i));
}
}
marked = -1;
position = 1;
index = i;
}
}
 
public synchronized void mousePressed(MouseEvent evt){
marked=-1;
int x = evt.getX();int y = evt.getY();int p=1;
if( y < y0 + fh && y > y0 + fh/4 ){ p = 0; } else { if ( y > y0 - 2*fh && y < y0 - fh/4){ p = 2;}}
int widthprogress=0;
for(int i=0; i<index;i++){
if(x > widthprogress && x< widthprogress+CharWidth[i]){
marked=i;
if(p!=1){ position=p;}else{position=CharPosition[i];}
if(evt.getButton() == MouseEvent.BUTTON3 ){DeleteMarkedChar(marked);}
//if(evt.getButton() == MouseEvent.BUTTON2 || evt.getButton() == MouseEvent.BUTTON3 ){ProcessMarkedKey("?" ,155);}
repaint();
}
widthprogress = widthprogress + CharWidth[i];
}
}
public void mouseWheelMoved(MouseWheelEvent evt){
position = NewPosition(-1*(evt.getWheelRotation()) , position);
if(marked!=-1){
CharPosition[marked]=position;
}
update();
}
 
public synchronized void mouseDragged(MouseEvent evt){}
public synchronized void mouseReleased(MouseEvent evt){}
public void mouseEntered(MouseEvent mouseevent){editing=true;repaint();}
public void mouseExited(MouseEvent mouseevent){editing=false;repaint();}
public void mouseMoved(MouseEvent mouseevent){}
public void mouseClicked(MouseEvent mouseevent){}
 
public void keyPressed(KeyEvent e){
if(index < max_chars - 4){
//System.out.println("KEYCODE ="+e.getKeyCode());
int key = e.getKeyCode();boolean found=false;
for(int i=0;i<ForbiddenKeys.length;i++){
if( key == ForbiddenKeys[i] && found==false){found=true;}
}
if(found == false){
String key_char = Character.toString(e.getKeyChar());
if(marked == -1){ ProcessKey(key_char,key);}else{ProcessMarkedKey(key_char,key);}
repaint();
}
}else{index=0;} //hahaha
}
public void keyTyped(KeyEvent e ) {
}
public void keyReleased(KeyEvent e){
}
 
public void AppendKey(String key_char, int pos){
CharPosition[index] = pos;
CharArray[index] = key_char;
int w=0;// find length string
for(int i=0;i<key_char.length();i++){
if(pos == 0 || pos == 2){w=w+sfm.charWidth(key_char.charAt(i));}
else{w=w+fm.charWidth(key_char.charAt(i));}
}
CharWidth[index] = w;
index++;
}
 
public void InsertKey(String key_char, int pos, boolean need_painting){
if(marked!=-1){
index++;
for(int i=index;i>marked;i--){
CharArray[i]=CharArray[i-1];
CharPosition[i]=CharPosition[i-1];
CharWidth[i]=CharWidth[i-1];
}
CharArray[marked] = key_char;
CharPosition[marked] = position;
if(position == 0 || position == 2){ CharWidth[marked] = sfm.charWidth(key_char.charAt(0));}
else{CharWidth[marked] = fm.charWidth(key_char.charAt(0));}
marked++;
}
if(need_painting){update();}
}
 
public void ProcessMarkedKey(String key_char ,int key){// only called if marked>-1
if(key == 116){CycleColor(0);}//F5 change pencolor
else
if(key == 117){CycleColor(1);}//F6 change bgcolor1
else
if(key == 118){CycleColor(2);}//F7 change bgcolor2
else
if(key == 119){clear();}//F8 delete all
else
if(key == 114){ key_char = "\u2192";InsertKey(key_char,position,false);}//F3 -->
else
if(key == 115){ key_char = "\u21C4";InsertKey(key_char,position,false);}//F4 <-->
else
if(key == 37 ){LeftRightMarked(-1,false);}// linker pijl
else
if(key == 39 ){if(marked==index-1){marked = -1;}else{LeftRightMarked(1,false);}}// rechter pijl
else
if( key == 38 || key == 33){UpDownMarked(1,false);}//up
else
if( key == 40 || key == 34){UpDownMarked(-1,false);}//down
else
if(key == 10 || key == 27){marked = -1;}// esc enter
if( (key == 8 || key == 127) && index>0 ){DeleteMarkedChar(marked);position=1;marked--;}//backspace & delete on marked
else
if( (key == 8 || key == 127) && index == 0 ){ position=1;marked=-1;CharArray[0]=null; CharPosition[0]=1;CharWidth[0]=0;}//backspace & delete on marked
else
{
boolean found=false;
for(int i=0;i<AcceptedChars.length;i++){
if(AcceptedChars[i].equals(key_char) || key > 64 && key <91 || key == 45 || key == 61 ){found =true;}
}
if(found ==true){
///System.out.println("inserting="+key_char);
InsertKey(key_char,position,false);
}
}
}
 
public void UpDownMarked(int p , boolean need_painting ){
int i = NewPosition(p , position);
if(i != position){
position = i;
CharPosition[marked] = position;
}
if(need_painting){update();}
}
 
public void LeftRightMarked(int p , boolean need_painting){
for(int i=0;i<index;i++){
if(i == marked){
if( p == 1){if( marked < index - 1){marked++;break;}} else {if(marked>1){marked--; break;}}
}
}
if(need_painting){update();}
}
public void CycleColor(int type){
if(R1==G1 && G1==B1){R1=0.0f;G1=0.0f;B1=0.0f;}//blue
R1=R1+0.1f;
if(R1>1.0){ R1=1.0f; // if red saturated increase green
G1=G1+0.1f;
if(G1>1.0){G1=1.0f;
B1=B1+0.1f;
if(B1>1.0){B1=1.0f;}
}
}
if(type == 0){pencolor = new Color(R1,G1,B1,(float)1.0);}
else
if(type == 1){bgcolor1 = new Color(R1,G1,B1,(float)1.0);this.setBackground(bgcolor1);}
else { bgcolor2 = new Color(R1,G1,B1,(float)1.0);}
}
 
 
public void ProcessKey(String key_char ,int key){
boolean goodkey=true;
for(int i=0;i<ForbiddenKeysChars.length;i++){ if(key_char.equals(ForbiddenKeysChars[i]) && goodkey){ goodkey = false;} }
if(goodkey){
if( key_char.equals(">") && index>2){if(CharArray[index-1].equals("-")){DeleteMarkedChar(index - 1); key_char = "\u2192";AppendKey(key_char,position);}}
else
if(key == 112){SwitchFont(6);} // F1 +6
else
if(key == 113){SwitchFont(-6);} // F2 -6
else
if(key == 114){ key_char = "\u2192";AppendKey(key_char,position);}//F3 -->
else
if(key == 115){ key_char = "\u21C4";AppendKey(key_char,position);}//F4 <-->
else
if(key == 116){CycleColor(0);}//F5 change pencolor
else
if(key == 117){CycleColor(1);}//F6 change bgcolor1
else
if(key == 118){CycleColor(2);}//F7 change bgcolor2
else
if(key == 119){clear();}//F8 delete all
else
if( key == 33 ){ position = NewPosition(1 , position);}//pageup
else
if( key == 34 ){ position = NewPosition(-1 , position);}//pagedown
else
if( key == 36 ){marked = 0;}//home
else
if( key == 37 ){marked = index-1;}//left arrow
else
if( key == 39 ){marked = index-1;}//left arrow
else
if( key == 35 ){marked = index;}//end
else
if(key == 10 || key == 27){marked = -1;position=1;index++;}// esc enter
else
if( (key == 127 || key == 8) && index>0){ index--; CharArray[index]=null; CharPosition[index]=1;CharWidth[index]=0;position=CharPosition[index];}
else
if( (key == 127 || key == 8) && index==0){ position=1;marked=-1; CharArray[0]=null; CharPosition[0]=1;CharWidth[0]=0;}
else
if( key == 38 || key == 94 ){ position = NewPosition(1 , position);}
else
if( key == 40 || key == 95 ){ position = NewPosition(-1 , position);}
else{
CharArray[index]=key_char;
CharPosition[index]=position;
if(position == 0 || position == 2){ CharWidth[index]= sfm.charWidth(key_char.charAt(0));}
else { CharWidth[index]= fm.charWidth(key_char.charAt(0));}
index++;
}
}
}
 
public int NewPosition(int P , int old){
int n = old + ( P );
if(n>2){n=2;}
else
if(n<0){n=0;}
return n;
}
public void DeleteMarkedChar(int c){
int m=0;
for(int i=index-1;i>=0;i--){
if( i == c ){
CharArray=DeleteStringItem(CharArray,i);
CharPosition=DeleteIntItem(CharPosition,i);
CharWidth=DeleteIntItem(CharWidth,i);
CharArray[index-m]=null;
CharPosition[index-m]=1;
CharWidth[index-m]=0;
m++;
}
}
index=index-m;
}
public int[] DeleteIntItem(int[] array1, int del){
int m=0;
for(int i=0;i<array1.length-1;i++){
if(i >= del){
m=i+1;
array1[i]=array1[m];
}
}
return array1;
}
public String[] DeleteStringItem(String[] array1, int del){
int m=0;
for(int i=0;i<array1.length-1;i++){
if(i >= del){
m=i+1;
array1[i]=array1[m];
}
}
return array1;
}
 
public void ShowHelp(){
System.out.println("laat helptext zien");
}
 
public String MakeText(){
String Text = "";//homebrew replace("","","") can't handle stringbuffer.toString()
for(int i=0;i<max_chars;i++){
if(CharArray[i] != null){
if(CharPosition[i] == 1){Text=Text+CharArray[i];}
else
if(CharPosition[i] == 2 ){Text=Text+"^" ;
while(CharPosition[i] == 2 && CharArray[i]!=null){
Text=Text+CharArray[i] ;
i++;
}
Text=Text+" ";
i=i-1;
}
else
if(CharPosition[i] == 0 ){
while(CharPosition[i] == 0 && CharArray[i]!=null){
Text=Text+CharArray[i] ;
i++;
}
Text=Text+" ";
i=i-1;
}
}
}
for(int p=1;p<10;p++){// Mn02 => MnO2
Text=replace(Text,"0"+p,"O"+p);
}
return Text;
}
public String MakeLaTeX(){
StringBuffer LaTeX = new StringBuffer();
for(int i=0;i<max_chars;i++){
if(CharArray[i] != null){
if(CharPosition[i] == 1){LaTeX.append(CharArray[i]);}
else
if(CharPosition[i] == 2 ){LaTeX.append("^{") ;
while(CharPosition[i] == 2 && CharArray[i]!=null){
LaTeX.append(CharArray[i]) ;
i++;
}
i=i-1;
LaTeX.append("}");
}
else
if(CharPosition[i] == 0 ){LaTeX.append("_{");
while(CharPosition[i] == 0 && CharArray[i]!=null){
LaTeX.append(CharArray[i]) ;
i++;
}
i=i-1;
LaTeX.append("}");
}
}
}
return LaTeX.toString();
}
 
public String MakeHtml(){
StringBuffer Html = new StringBuffer();
for(int i=0;i<max_chars;i++){
if(CharArray[i] != null){
if(CharPosition[i] == 1){Html.append(CharArray[i]);}
else
if(CharPosition[i] == 2 ){Html.append("<sup><font size=\"-1\">") ;
while(CharPosition[i] == 2 && CharArray[i]!=null){
Html.append(CharArray[i]) ;
i++;
}
i=i-1;
Html.append("</font></sup>");
}
else
if(CharPosition[i] == 0 ){Html.append("<sub><font size=\"-1\">");
while(CharPosition[i] == 0 && CharArray[i]!=null){
Html.append(CharArray[i]) ;
i++;
}
i=i-1;
Html.append("</font></sub>");
}
}
}
return Html.toString();
}
 
public int position=1;// 0,1,2 last edit
public int marked=-1;
public int y0;
public FontMetrics sfm;
public FontMetrics fm;
public Font f;
public Font sf;
public int fh; //font height
float R1,G1,B1,alpha;
public boolean once = false;
boolean editing = false;
public int fontsize = 18;
public String applettext="";
public Color bgcolor1;
public Color pencolor;
public Color bgcolor2;
public int max_chars = 200;
public String[] CharArray = new String[max_chars];
public int[] CharPosition = new int[max_chars];
public int[] CharWidth = new int[max_chars];
public int index=0;
}
 
///////////////////////////////////////////////////
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/ChemInput/build.xml
0,0 → 1,65
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for ChemInput.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="ChemInput" default="jar" basedir=".">
 
<description>ChemInput build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create ChemInput jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/ChemInput.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="ChemInput"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="ChemInput"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="ChemInput">
<attribute name="Specification-Title" value="ChemInput"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="ChemInput"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/rooster/build.xml
0,0 → 1,64
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for rooster.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="rooster" default="jar" basedir=".">
 
<description>rooster build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create rooster jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/rooster.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="rooster"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="rooster"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="rooster">
<attribute name="Specification-Title" value="rooster"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="rooster"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/rooster/src/rooster.java
0,0 → 1,364
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
This is all amateur scriblings...so No Copyrights
the applet presents a simple grid...E6/H1 pupils will be asked to
determine the perimetre and surface area (or ratio of these) of a "freestyle" figure
build from at least $x squares...
In the non-interactive mode, a random figure will be shown.
size_x and size_y may be different: the perimetre will be a float : calulated with x=1 y=size_y/size_x
 
example html page:
<html>
<body>
<script language="javascript" type="text/javascript">
function lees(){
var input=document.applets[0].ReadApplet();
alert(input);
<--- applet returns: String S=total+","+original+","+changed+","+cnt;
!! total squares,left original squares,changed squares,perimetre of changed squares
-->
}
</script>
<applet id="rooster" code="rooster.class" codebase="." archive="rooster.jar" width="640" height="480">
<param name="max_x" value="5">
<param name="max_y" value="5">
<param name="size_x" value="25">
<param name="size_y" value="50">
<param name="color1" value="25:100:76">
<param name="color2" value="orange">
<param name="interactive" value="0/1">
<param name="level" value="$level">
<param name="percentage" value="0/1">
</applet>
<p>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:lees();">
</body>
</html>
color1="background"
color2="clicked" in "interactive"=1
color2="questioncolor" in "interactive"=0
color may also be "red","green","blue","orange","yellow"
 
21/3/2008 added:
level: integer 0,1,2,3 only interesting when "interactive=0" (and not of importance for "percentage")
level=0 will produce somewhat easier random figures: level=3 will give maximum randomness.
 
percentage: only activated when "interactive=0" . Will give a random figure : but a non-random placement of the coloured squares.
thus an very easy reading of a "percentage coloured" surface. Use together with max_x and max_y to build easy exercises.
percentage=1 and level>0 will produce alternating coloures
percentage=1 and level=0 will produce a coloured block
 
22/3/2008 added
color names : lightgreen,lightblue,brown,pink,cyan,salmon
 
for both params level/percentage a full coloured figure is inhibited (so never 0% coloured or 100% coloured)
 
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.lang.Math;
 
public class rooster extends Applet implements Runnable{
private static final int serialVersionUID = 1;
int max_x=20;int max_y=20;
int rooster[][];
// = new int[max_y+2][max_x+2];
int dx;int dy;Thread thread = null;
Image plaatje;Graphics tekening;
int hokje_x=20;int hokje_y=20;
int xsize=hokje_x*max_x;
int ysize=hokje_y*max_y;
int R1=111;int G1=222;int B1=040;
int R2=040;int G2=222;int B2=111;
int interactive=1;int percentage=0;int level=3;
 
public void init(){
String c;
c=getParameter("color1");
if(c!=null && c.length()>0){
// don't know how to do this in 1 regexp
if(c.indexOf(',')== -1 && c.indexOf(':')== -1 && c.indexOf(';')== -1 ){
if(c.equalsIgnoreCase("red")){R1=255;G1=0;B1=0;}
else
if(c.equalsIgnoreCase("green")){R1=0;G1=255;B1=0;}
else
if(c.equalsIgnoreCase("blue")){R1=0;G1=0;B1=255;}
else
if(c.equalsIgnoreCase("orange")){R1=238;G1=154;B1=0;}
else
if(c.equalsIgnoreCase("yellow")){R1=255;G1=255;B1=0;}
else
if(c.equalsIgnoreCase("purple")){R1=160;G1=32;B1=240;}
else
if(c.equalsIgnoreCase("lightgreen")){R1=144;G1=238;B1=144;}
else
if(c.equalsIgnoreCase("lightblue")){R1=173;G1=216;B1=230;}
else
if(c.equalsIgnoreCase("cyan")){R1=0;G1=255;B1=255;}
else
if(c.equalsIgnoreCase("brown")){R1=165;G1=24;B1=24;}
else
if(c.equalsIgnoreCase("salmon")){R1=250;G1=128;B1=114;}
else
if(c.equalsIgnoreCase("pink")){R1=255;G1=192;B1=203;}
else{R1=255;G1=0;B1=0;}
}
else
{
c=c.replace(':',',');c=c.replace(';',',');
StringTokenizer q = new StringTokenizer(c, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a==0){R1=rgb;}
if(a==1){G1=rgb;}
if(a==2){B1=rgb;}
}
}
}
 
c=getParameter("color2");
if(c!=null && c.length()>0){
if(c.indexOf(',')== -1 && c.indexOf(':')== -1 && c.indexOf(';')== -1 ){
if(c.equalsIgnoreCase("red")){R2=255;G2=0;B2=0;}
else
if(c.equalsIgnoreCase("green")){R2=0;G2=255;B2=0;}
else
if(c.equalsIgnoreCase("blue")){R2=0;G2=0;B2=255;}
else
if(c.equalsIgnoreCase("orange")){R2=238;G2=154;B2=0;}
else
if(c.equalsIgnoreCase("yellow")){R2=255;G2=255;B2=0;}
else
if(c.equalsIgnoreCase("purple")){R2=160;G2=32;B2=240;}
else
if(c.equalsIgnoreCase("lightgreen")){R2=144;G2=238;B2=144;}
else
if(c.equalsIgnoreCase("lightblue")){R2=173;G2=216;B2=230;}
else
if(c.equalsIgnoreCase("cyan")){R2=0;G2=255;B2=255;}
else
if(c.equalsIgnoreCase("brown")){R2=165;G2=24;B2=24;}
else
if(c.equalsIgnoreCase("salmon")){R2=250;G2=128;B2=114;}
else
if(c.equalsIgnoreCase("pink")){R2=255;G2=192;B2=203;}
else{R2=0;G2=0;B1=255;}
}
else
{
c=c.replace(':',',');c=c.replace(';',',');
StringTokenizer q = new StringTokenizer(c, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a==0){R2=rgb;}
if(a==1){G2=rgb;}
if(a==2){B2=rgb;}
}
}
}
 
c=getParameter("max_x");
if(c!=null && c.length()>0){
max_x = Integer.parseInt(c, 10);
if(max_x>20){max_x=20;}
if(max_x<1){max_x=1;}
}
c=getParameter("max_y");
if(c!=null && c.length()>0){
max_y = Integer.parseInt(c, 10);
if(max_y>20){max_y=20;}
if(max_y<1){max_y=1;}
}
c=getParameter("size_x");
if(c!=null && c.length()>0){
hokje_x = Integer.parseInt(c, 10);
if(hokje_x>60){hokje_x=60;}
if(hokje_x<20){hokje_x=20;}
}
c=getParameter("size_y");
if(c!=null && c.length()>0){
hokje_y = Integer.parseInt(c, 10);
if(hokje_y>60){hokje_y=60;}
if(hokje_y<20){hokje_y=20;}
}
 
// 21-3-2008
c=getParameter("level");
if(c!=null && c.length()>0){
level = Integer.parseInt(c, 10);
if(level>3){level=3;}
if(level<0){level=0;}
}
c=getParameter("percentage");
if(c!=null && c.length()>0){
percentage = Integer.parseInt(c, 10);
if(percentage>0){percentage=1;}else{percentage=0;}
}
// eind
xsize=hokje_x*(max_x+2);
ysize=hokje_y*(max_y+2);
rooster=new int[max_y+2][max_x+2];
plaatje = createImage(xsize,ysize);
tekening = plaatje.getGraphics();
// hele veld met 0 == wit
for(int x=0;x<max_x+2;x++){;
for(int y=0;y<max_y+2;y++){
rooster[y][x]=0;
}
}
 
c=getParameter("interactive");
if(c.equals("0")){
interactive=0;
double p;
int hit1=0;int hit2=0;
if(percentage==0){
for(int x=1;x<max_x+1;x++){
for(int y=1;y<max_y+1;y++){
if(level==3){p=Math.random();if(p<0.5){rooster[y][x] = -1;hit1++;}else{rooster[y][x] = 1;hit2++;}}
else
if(level==2){p=Math.random();if(p<0.7){rooster[y][x] = -1;hit1++;}else{rooster[y][x] = 1;hit2++;}}
else
if(level==1){p=Math.random();if(p<0.8){rooster[y][x] = -1;hit1++;}else{rooster[y][x] = 1;hit2++;}}
else
if(level==0){p=Math.random();if(p<0.9){rooster[y][x] = -1;hit1++;}else{rooster[y][x] = 1;hit2++;}}
}
}
}
else
{
p=Math.random();
int chk=0;double perc=p*max_x*max_y;int alt=0;
for(int x=1;x<max_x+1;x++){
for(int y=1;y<max_y+1;y++){
if(level<2){chk++; if(chk<perc){rooster[y][x] = -1;hit1++;}else{rooster[y][x] = 1;hit2++;}}
else
{
chk++; if(chk<perc && alt==0){rooster[y][x] = -1;hit1++;alt=1;}else{rooster[y][x] = 1;hit2++;alt=0;}
}
}
}
}
if(hit1==0){rooster[1][1]=-1;}
if(hit2==0){rooster[1][1]=1;}
}
// plaatje tussen x=1 ...max_x+1 x=0/x=max_x+2===0
if(interactive==1){
for(int x=1;x<max_x+1;x++){;
for(int y=1;y<max_y+1;y++){
rooster[y][x]=1;
}
}
addMouseListener(
new MouseAdapter(){
public void mousePressed(MouseEvent e){
dx = e.getX() / hokje_x;
dy = e.getY() / hokje_y;
if(dx<max_x+1 && dy<max_y+1 && dx>0 && dy>0){
rooster[dy][dx] = -1 * rooster[dy][dx];
//System.out.println("rooster[dy][dx]="+rooster[dy][dx]+" dx="+dx+" dy="+dy);
repaint();
}
}
}
);
}
}
 
public void paint(Graphics g){
tekening.setColor(Color.white);
tekening.fillRect(0,0,xsize,ysize);
 
for(int t1 = 0;t1 < max_x+2;t1 ++){
for(int t2 = 0;t2 < max_y+2;t2 ++){
if(rooster[t2][t1]!=0){
if(rooster[t2][t1] == 1){tekening.setColor(new Color(R1,G1,B1));}else{tekening.setColor(new Color(R2,G2,B2));}
tekening.fill3DRect(hokje_x*t1,hokje_y*t2,hokje_x,hokje_y,true);
}
}
}
g.drawImage(plaatje,0,0,this);
}
 
public void start(){
if(thread == null){
thread = new Thread(this);
thread.start();
}
}
 
public void stop(){
thread = null;
}
 
public void run(){
while(thread != null){
try{
Thread.sleep(100);
}
catch (InterruptedException e){
}
}
}
 
public void update( Graphics g ){
paint( g ) ;
}
public String ReadApplet(){
// x==1
double hy=1.000*hokje_y;
double hx=1.000*hokje_x;
double factor=hy/hx;
//double hy=Double.valueOf(hokje_y);
//double hx=Double.valueOf(hokje_x);
//double factor=hy/hx;
int changed=0;int original=0;int total=0;
// rooster[y][x]=0 white border
// rooster[y][x]=-1 clicked
// rooster[y][x]=1 unchanged
for(int t1 = 0;t1 < max_x+2;t1 ++){
for(int t2 = 0;t2 < max_y+2;t2 ++){
if(rooster[t2][t1] == -1){ changed++; total++; }
if(rooster[t2][t1] == 1){ original++; total++; }
}
}
 
double border[][]=new double[max_y+4][2*max_x+4];
int c1;int c2;double t=0;
for( c1 = 1; c1 < max_x+1 ;c1++){
for( c2 =1; c2 < max_y+1 ;c2++){
if(rooster[c2][c1] == -1 ){t=0;
if((rooster[c2][c1-1] != -1) && (rooster[c2][c1+1] != -1) ){t=t+factor*2;}else{if( (rooster[c2][c1-1] != -1) || (rooster[c2][c1+1] != -1) ){t=t+factor;}}
if( (rooster[c2-1][c1] != -1) && (rooster[c2+1][c1] != -1) ){t=t+2;}else{if( (rooster[c2-1][c1] != -1) || (rooster[c2+1][c1] != -1) ){t=t+1;}}
border[c2][c1]=t;
}
}
}
double cnt=0;
for( c1=1 ; c1<max_x+1 ; c1++ ){
for( c2=1 ; c2<max_y+1 ; c2++ ){
cnt=cnt+border[c2][c1];
}
}
String S=total+","+original+","+changed+","+cnt;
return S;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/build.xml
0,0 → 1,63
<!--
 
Project buildfile for SharpTools.
 
-->
 
<project name="SharpTools" default="build" basedir=".">
 
<description>SharpTools: Spreadsheet</description>
 
<property name="ver" value="1.19"/>
 
<property name="src" location="."/>
<!--<property name="extern" location="extern"/>-->
<property name="build" location="build"/>
<property name="dist" location="dist"/>
 
<path id="project.class.path">
<!--<pathelement location="${classpath}/rt.jar"/>-->
<!--<pathelement location="/usr/local/javalib/xerces.jar"/>-->
</path>
 
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
<mkdir dir="${dist}"/>
</target>
 
<target name="compile" depends="init" description="compile the source">
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}" debug="on"
source="1.4" target="1.4" encoding="8859_1">
<classpath refid="project.class.path" />
</javac>
</target>
 
<target name="build" depends="compile" description="generate the distribution">
<!-- Create the distribution directory -->
<mkdir dir="${dist}"/>
 
<jar jarfile="${dist}/SharpTools.jar" basedir="${build}">
<manifest>
<attribute name="Main-Class" value="SharpTools.SharpTools"/>
</manifest>
<fileset dir="." includes="images/*.*" />
<fileset dir="." includes="lang/*.properties" />
<fileset dir="." includes="sharptools.ini" />
<!-- embed any other appropriate jar files...
<zipfileset src="extern/epsgraphics.jar"/>
-->
</jar>
</target>
 
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/lang/SharpToolsProperties_en.properties
0,0 → 1,223
############################################
###### AddressField.java
############################################
###### Cell.java
############################################
###### CellPoint.java
############################################
###### CellRange.java
############################################
###### Config.java
############################################
###### ConnectDialog.java
############################################
###### Database.java
############################################
###### Debug.java
############################################
###### EditOp.java
Cut=Cut
Copy=Copy
Paste=Paste
Clear=Clear
Fill=Fill
Find=Find
Find_Next=Find Next
Please_enter_a_value_to_fill_the_range=Please enter a value to fill the range
SharpTools_has_finished_the search=SharpTools has finished the search \n and could not find more hits.
Find_Completed=Search Competed
 
############################################
###### FileOp.java
Sharp_Tools_Spreadsheet=Sharp Tools Spreadsheet (*.tsv)
Untitled_-_Sharp_Tools_Spreadsheet=Untitled - Sharp Tools Spreadsheet=
Untitled=Untitled
Do_you_want_to_save_the_changes=Do you want to save the changes you made to
Save=Save
Open=Open
Print=Print
Exit=Exit
Unexpected_error=Unexpected Error !
File_already_exists=File already exists
Do_you_want_to_overwrite_it=Do you want to overwrite it?
File_cannot_be_created=File cannot be created
IO_error_in_saving=I/O error in saving
Sharp_Tools_Spreadsheet=Sharp Tools Spreadsheet
File_not_found=File not found
IO_error_in_opening=I/O error in opening
Printing_error=Printing error
Table_width_exceeds_printed_width=Table width exceeds printed width\nSome data will not be printed
 
############################################
###### FindDialog.java
Match_Case=Match Case
Match_Entire_Cell_Only=Match Entire Cell Only
OpenDb=OpenDB
OpenFile=Open File
############################################
###### Formula.java
sum_desc=Adds all the numbers in a set of values.
count_desc=Counts the number of cells that contain numbers and numbers within the list of arguments.
average_desc=Returns the average (arithmetric mean) of its arguments.
median_desc=Returns the median (value in the middle) of its arguments.
min_desc=Returns the smallest number in a set of values.
max_desc=Returns the largest number in a set of values.
diff_desc=Returns the difference between MAX and MIN in a set of values.
abs_desc=Returns the absolute value of a number.
sin_desc=Returns the sine of an angle.
cos_desc=Returns the cosine of an angle.
tan_desc=Returns the tangent of an angle.
asin_desc=Returns the arcsine of a number in radians, in the range -Pi/2 to Pi/2.
acos_desc=Returns the arccosine of a number in radians, in the range 0 to Pi.
atan_desc=Returns the arctangent of a number in radians, in the range -Pi/2 to Pi/2.
int_desc=Returns the integer part of a number.
round_desc=Returns the nearest integer of a number.
sqrt_desc=Returns a square root of a number.
log_desc=Returns the logarithm of a number to the base e.
meandev_desc=Returns the average absolute deviation in a set of values.
stddev_desc=Returns the standard deviation in a set of values.
pi_desc=Returns the value of PI.
e_desc= Returns value of e.
Help_Browser=Help Browser
Function=Function
helpmessage=<html><font size=2 color=black><b><font size=3>Functions</font></b><p><p>Functions are predefined formulas that perform calculations by<p>using specific values, called arguments, in a particular order,<p>or structure.<p><p><b>Arguments</b> Arguments can be numbers or cell references. A cell<p>reference can be a single cell or a range of cells. A single cell can<p>use relative addressing (A1) or absolute addressing ($B$5). A range<p>of cell is specified by a pair of diagonal cells (A1:C5, $A$1:$C$5).<p>Different functions may have different requirements on the number<p>or type of parameters.<p><p><b>Structure</b> The structure of a function begins with the function<p>name, followed by an opening parenthesis, the arguments for<p>the function separated by commas, and a closing parenthesis.<p>If the function starts a formula, type an equal sign (=) before<p>the function name. As you are editing a formula that contains<p>a function, you can click on a function in this list to insert the<p>function name into the cell.<p><p><b>Examples:</b><p><p>=SUM(A10,B5:B10,50,37)<p>=AVERAGE($B$5:$B$10)/10</font>
 
#####################################
###### HistoDialog.java
Histogram_Options=Histogram Options
Start_cell=Start cell
End_cell=End cell
Start_value=Start value
End_value=End value
Minumum_value_on_X_axis=Minimum value on X axis
Maximum_value_on_X_axis=Maximum value on X axis
Unit_on_X_axis=Unit on X axis
Minumum_value_on_Y_axis=Minimum value on Y axis
Maximum_value_on_Y_axis=Maximum value on Y axis
Unit_on_Y_axis=Unit on Y axis
Chart_Title=Chart Title
Cell_Range=Cell Range
Value_Range=Value Range
to=to
Bucket=Bucket
X_Scale=X Scale
Y_Scale=Y Scale
Unit=Unit
Display_Y_by=Display Y by
Count=Count
Bucket_Size=Bucket Size
Start_Value=Start Value
End_Value=End Value
X_Unit=X Unit
Y_Unit=Y Unit
X_Start=X Start
X_End=X End
Y_Start=Y Start
Y_End=Y End
percentage=percentage
sorry=Sorry, your command does not have a valid value. Please go back to check it.
 
############################################
###### Histogram.java
Histogram=Histogram
Show=Show
Add=Add
 
############################################
###### History.java
############################################
###### MainApplet.java
############################################
###### NewFileDialog.java
New=New
Rows=Rows
Columns=Columns
Save_as_default=Save as default
Error=Error
Invalid_row_value=Invalid row value
Invalid_column_value=Invalid column value
Row=Row
Column=Column
############################################
###### Node.java
############################################
###### NumberField.java
############################################
###### ParserException.java
############################################
###### PasswordDialog.java
Password=Password
Enter_password=Enter password
Confirm_Password=Confirm Password
Password_Incorrect=Password Incorrect
Passwords_do_not_match_Please_try_again=Passwords do not match!\n\n Please try again
 
############################################
###### SharpCellEditor.java
############################################
###### SharpCellRenderer.java
############################################
###### SharpClipboard.java
############################################
###### SharpDialog.java
############################################
###### SharpOptionPane.java
############################################
###### SharpTableModel.java
############################################
###### SharpTools.java
Sort_by_Column=Sort by Columnn
Table=Table
New=New
Database=Database...
Save_As=Save As...
Set_Password=Set Password...
Print=Print
Recent_Files=Recent Files
Save_Window_on_Exit=Save Window on Exit
Edit=Edit
Close=Close
Undo=Undo
Redo=Redo
Sort=Sort
Set_Column_Width=Set Column Width
Set_First_Column_Width=Set First Column Width
Chart=Chart
Show=Show
Help=Help
Help_Topics=Help Topics
Show_Functions=Show Functions
About_SharpTools=About Sharp Tools
Set_Password=Set Password
Insert_Row=Insert Row
Insert_Column=Insert Column
Delete_Row=Delete Row
Delete_Column=Delete Column
No_cells_selected=No cells selected
sorry2=Sorry, this function is not yet implemented
Functions=Functions
############################################
###### SharpToolsProperties.java
Descending=Descending
Ascending=Ascending
Sort_By=Sort By
Then_By=Then By
############################################
###### TabPanel.java
Options=Options
Update=Update
############################################
###### TableOp.java
Remove=Remove
Insert=Insert
Delete=Delete
Default_width=Default width
rem1=Please give the new column width in pixels
rem2=Please give the first column width in pixels
rem3=The deletion may cause irriversible data loss in other cells.
rem4=Do you really want to proceed?
rem5=You can not delete all the rows or columns!
WIMS=Send spreadsheet to the WIMS server
are_you_sure=Are You sure...should I send your spreadsheet to WIMS ?
yes=yes
no=no
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/lang/SharpToolsProperties_fr.properties
0,0 → 1,168
# generated by Google translate :)
 
Cut=Couper
Copy=Copie
Paste=Coller
Clear=Clair
Fill=Remplir
Find=Rechercher
Find_Next=Rechercher suivant
Please_enter_a_value_to_fill_the_range=S'il vous plaît entrer une valeur pour remplir la gamme
SharpTools_has_finished_the_search= SharpTools a terminé la recherche \n et ne peut pas trouver plus de visites.
Find_Competed=Recherche en concurrence
OpenDb=Open database
OpenFile=Open File
 
Sharp_Tools_Spreadsheet=Sharp Outils tableur (*. tsv)
Untitled_-_Sharp_Tools_Spreadsheet=Untitled - Sharp Tools Spreadsheet
Untitled=Untitled
Do_you_want_to_save_the_changes=Voulez-vous enregistrer les modifications apportées à
Save=Sauver
Open=Ouvert
Print=Imprimer
Exit=Exit
Unexpected_error=Erreur inattendue!
File_already_exists=Fichier existe déjà
Do_you_want_to_overwrite_it= Voulez-vous l'écraser?
File_cannot_be_created=Dossier ne peut pas être créé
IO_error_in_saving=I / O erreur dans la sauvegarde
Sharp_Tools_Spreadsheet=Sharp Tools Spreadsheet
File_not_found=Fichier non trouvé
IO_error_in_opening= I / O error dans l'ouverture
Printing_error= Erreur d'impression
Table_width_exceeds_printed_width=Tableau largeur est supérieure à la largeur imprimée \nSome données ne seront pas imprimées
 
 
 
Match_Case=Match Case
Match_Entire_Cell_Only=Match entier Cell seulement
 
 
 
sum_desc=Ajoute tous les numéros dans un ensemble de valeurs.
count_desc=Compte le nombre de cellules contenant des nombres et des chiffres dans la liste des arguments.
average_desc=Renvoie la moyenne (arithmetric moyenne) de ses arguments.
median_desc=Retourne la médiane (valeur dans le milieu) de ses arguments.
min_dec=Retourne le plus petit nombre dans un ensemble de valeurs.
max_descRetourne le plus grand nombre dans un ensemble de valeurs.
diff_desc=Renvoie la différence entre Max et Min dans une série de valeurs.
abs_desc=Retourne la valeur absolue d'un nombre.
sin_desc=Retourne le sinus d'un angle.
cos_desc=Retourne le cosinus d'un angle.
tan_desc=Renvoie la tangente d'un angle.
asin_desc=Retourne le arcsinus d'un certain nombre en radians, dans la gamme -Pi/2 à Pi/2.
acos_desc=Retourne le arccosinus d'un certain nombre en radians, dans la plage allant de 0 à Pi.
atan_desc=Retourne le arctangente d'un certain nombre en radians, dans la gamme-Pi / 2 à Pi / 2.
int_desc=Renvoie la partie entière d'un nombre.
round_desc=Retourne l'entier le plus proche d'un nombre.
sqrt_desc=Renvoie la racine carrée d'un nombre.
log_desc=Renvoie le logarithme d'un nombre à la base e.
meandev_desc=Retourne l'écart moyen absolu en un ensemble de valeurs.
stddev_descRetourne l'écart type dans un ensemble de valeurs.
pi_desc=Retourne la valeur de PI.
e_desc=Retourne la valeur de e.
Help_Browser=Aide du navigateur
Function=Fonction
helpmessage=<html><font size=2 color=black><b><font size=3>Functions</font></b><p><p>Functions are predefined formulas that perform calculations by<p>using specific values, called arguments, in a particular order,<p>or structure.<p><p><b>Arguments</b> Arguments can be numbers or cell references. A cell<p>reference can be a single cell or a range of cells. A single cell can<p>use relative addressing (A1) or absolute addressing ($B$5). A range<p>of cell is specified by a pair of diagonal cells (A1:C5, $A$1:$C$5).<p>Different functions may have different requirements on the number<p>or type of parameters.<p><p><b>Structure</b> The structure of a function begins with the function<p>name, followed by an opening parenthesis, the arguments for<p>the function separated by commas, and a closing parenthesis.<p>If the function starts a formula, type an equal sign (=) before<p>the function name. As you are editing a formula that contains<p>a function, you can click on a function in this list to insert the<p>function name into the cell.<p><p><b>Examples:</b><p><p>=SUM(A10,B5:B10,50,37)<p>=AVERAGE($B$5:$B$10)/10</font>
 
Histogram_Options=Histogramme Options
Start_cell=Début de cellules
End_cell=Fin de cellules
Start_value=Valeur de départ
End_value=Fin valeur
Minumum_value_on_X_axis=La valeur minimale sur l'axe X
Maximum_value_on_X_axis=La valeur maximale sur l'axe X
Unit_on_X_axis=Unité sur l'axe X
Minumum_value_on_Y_axis=La valeur minimale sur l'axe des Y
Maximum_value_on_Y_axis=La valeur maximale sur l'axe des Y
Unit_on_Y_axis=Unité sur l'axe des Y
Chart_Title=Titre du tableau
Cell_Range=Cell Range
Value_Range=Valeur Range
to=à
Bucket=Godet
X_Scale=X Scale
Y_Scale=Y Scale
Unit=Unité
Display_Y_by=Display Y par
Count=Count
Bucket_Size=Taille du godet
Start_Value=Valeur initiale
End_Value=Valeur finale
X_Unit=Unité X
Y_Unit=Unité Y
X_Start=Démarrer X
X_End=Fin X
Y_Start=Démarrer Y
Y_End=Y Fin
percentage=pourcentage
sorry=Désolé, votre commande n'a pas une valeur valide.\n S'il vous plaît revenir à vérifier.
Histogram=Histogramme
Show=Montrer
Add=Ajouter
New=Nouveau
Rows=Rangs
Columns=Colonnes
Save_as_default=Enregistrer par défaut
Error=Erreur
Invalid_row_value=La valeur de ligne non valide
Invalid_column_value=Valeur de colonne non valide
Row=Ligne
Column=Colonne
 
Password=Mot de passe
Enter_password=Entrez le mot de passe
Confirm_Password=Confirmer le mot de passe
Password_Incorrect=Mot de passe incorrect
Passwords_do_not_match_Please_try_again=Les mots de passe ne correspondent pas! \n \n S'il vous plaît essayez de nouveau
 
Sort_by_Columnn=Trier par Columnn
Table=Table
New=Nouveau
Database=Base de données ...
Save_As=Enregistrer sous ...
Set_Password=Définir le mot de passe ...
Recent_Files=Fichiers récents
Save_Window_on_Exit=Enregistrer la fenêtre à la sortie
Edit=Modifier
Close=Fermer
Undo=Annuler
Redo=Refaire
Sort=Trier
Set_Column_Width=Set Colonne Largeur
Set_First_Column_Width=Set premiere Colonne Largeur
Chart=Graphique
Show=Montrer
Help=Aider
Help_Topics=Sujets d'Aide
Show_Functions=Voir les fonctions
About_Sharp_Tools=A propos de Sharp Tools
Set_Password=Mot de passe
Insert_Row=Insérer une ligne
Insert_Column=Insérer une colonne
Delete_Row=Supprimer le rang
Delete_Column=Supprimer la colonne
No_cells_selected=Pas de cellules sélectionnées
sorry2=Désolé, cette fonction n'est pas encore mis en oeuvre
Functions=Fonctions
Descending=Descendant
Ascending=Ascendant
Sort_By=Trier par
Then_By=Ensuite, par
Options=Options
Update=Mettre à jour
Remove=Supprimer
Insert=Insérer
Delete=Supprimer
Default_width=Largeur par défaut
rem1=S'il vous plaît donner à la nouvelle largeur de colonne en pixels
rem2=S'il vous plaît donner la première colonne de la largeur en pixels
rem3=La suppression mai irriversible cause de perte de données dans d'autres cellules.
rem4=Voulez-vous vraiment continuer?
rem5=Vous ne pouvez pas supprimer toutes les lignes ou des colonnes!
 
 
WIMS=Send spreadsheet to the WIMS server
are_you_sure=Are You sure...should I send your spreadsheet to WIMS ?
yes=qui
no=non
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/lang/SharpToolsProperties_nl.properties
0,0 → 1,222
############################################
###### AddressField.java
############################################
###### Cell.java
############################################
###### CellPoint.java
############################################
###### CellRange.java
############################################
###### Config.java
############################################
###### ConnectDialog.java
############################################
###### Database.java
############################################
###### Debug.java
############################################
###### EditOp.java
Cut=Knippen
Copy=Kopieren
Paste=Plakken
Clear=Wissen
Fill=Vullen
Find=Zoeken
Find_Next=Zoek verder
Please_enter_a_value_to_fill_the_range=Geef de waarde voor de geselecteerde cellen.
SharpTools_has_finished_the search=Zoeken beeindigd: kan geen treffers meer vinden.
Find_Completed=Zoeken klaar
OpenDb=Open database
OpenFile=Open bestand
############################################
###### FileOp.java
Sharp_Tools_Spreadsheet=Sharp Tools Spreadsheet (*.tsv)
Untitled_-_Sharp_Tools_Spreadsheet=Zonder Naam - Sharp Tools Spreadsheet
Untitled=Zonder Naam
Do_you_want_to_save_the_changes=Wil je de veranderingen opslaan
Save=Bewaren
Open=Openen
Print=Afdrukken
Exit=Exit
Unexpected_error=Onverwachte fout !
File_already_exists=Het bestand bestaat al
Do_you_want_to_overwrite_it=Moet het worden overschreven ?
File_cannot_be_created=Bestand kan niet worden aangemaakt
IO_error_in_saving=I/O fout tijdens bewaren
Sharp_Tools_Spreadsheet=Sharp Tools Spreadsheet
File_not_found=Bestand kon niet worden gevonden
IO_error_in_opening=I/O fout tijdens openen
Printing_error=Fout bij het afdrukken
Table_width_exceeds_printed_width=De tabel is te breed\nEn niet in totaliteit worden afgedrukt
 
############################################
###### FindDialog.java
Match_Case=Hoofdletter gevoelig
Match_Entire_Cell_Only=Overeenstemming of cel niveau
 
############################################
###### Formula.java
sum_desc=telt alle getallen bij elkaar op.
count_desc=Telt het aantal cellen met daarin getallen en ook de getallen in de lijst met argumenten.
average_desc=Geeft het rekenkundige gemiddelde van de ingevoerde argumenten.
median_desc=Geeft de mediaan (het getal in het midden) van de ingevoerde argumenten.
min_desc=Geeft het kleinste getal in de set ingevoerde waarden.
max_desc=Geeft het grootste getal in de set ingevoerde waarden.
diff_desc=Geeft het verschil tussen MAX en MIN in de set ingevoerde waarden.
abs_desc=Geeft de absolute waarde van de ingevoerde waarde.
sin_desc=Geeft de sinus van een hoek.
cos_desc=Geeft de cosinus van een hoek.
tan_desc=Geeft de tangens van een hoek.
asin_desc=Geef de arcsinus van een getal in radialen, in het domein -Pi/2 tot Pi/2.
acos_desc=Geef de arccosinus van een getal in radialen, in het domein 0 tot Pi.
atan_desc=Geef de arctangens van een getal in radialen, in het domein -Pi/2 tot Pi/2.
int_desc=Geeft het integer gedeelte van een getal.
round_desc=Geeft het afgeronde (gehele) getal.
sqrt_desc=Geeft de tweedemachts worten van het getal.
log_desc=Geeft de e log van het getal.
meandev_desc=Geeft de absolute deviatie in een set getallen.
stddev_desc=Geeft de standaard deviatie van een set getallen.
pi_desc=Geeft een benadering voor het getal Pi
e_desc=Geeft een benadering voor het getal e
Help_Browser=Help Browser
Function=Functie
helpmessage=<html><b>Functies</b><p><p>Functies zijn voorgedefinieerde formules aan de hand<p>waarvan berekeningen worden uitgevoerd<p>op specifieke getallen, genaamd argumenten,in een<p>bepaalde volgorde of structuur.<p><p><b>Argumenten</b><p>Argumenten kunnen getallen zijn of celreferentie.<p><p><b>Een cel referentie</b><p>Kan zijn een enkele cel of een range cel adressen.<p>Een enkele cel mag ook worden aangesproken met een<p>relatief adres (zoals A1) of een absoluut adres (zoals $B$5)<p><p><b>De range</b><p>De range van een cel wordt bepaald door de diagonaal,<p>zoals: (A1:C5, $A$1:$C$5). <p>Sommige functie kunnen bepaalde eisen stellen aan een getal<p>of het soort parameters.<p><p><b>Structuur</b><p>De structuur van een functie begint met de functienaam<p>gevolgd door een open haakje, dan de argumenten voor <p>de functie ,gescheiden door kommas, en afgesloten door een rond haakje.<p> Als de functie een formule is moet deze <b>beginnen</b><p>met een <b>= teken</b> voor de functienaam<p>Bij het bewerken van een formule die ook een functie bevat,<p>kan deze ook worden ingevoegd door op de functie naam te klikken.<p><p><b>Voorbeelden:</b><p><p>=SUM(A10,B5:B10,50,37)<p>=AVERAGE($B$5:$B$10)/10
 
#####################################
###### HistoDialog.java
Histogram_Options=Histogram Opties
Start_cell=Begin cel
End_cell=Eind cel
Start_value=Begin waarde
End_value=Eind waarde
Minumum_value_on_X_axis=Minimum waarde X-as
Maximum_value_on_X_axis=Maximum waarde X-as
Unit_on_X_axis=Eenheid X-as
Minumum_value_on_Y_axis=Minimum waarde Y-as
Maximum_value_on_Y_axis=Maximum waarde Y-as
Unit_on_Y_axis=Eenheid Y-as
Chart_Title=Titel Histogram
Cell_Range=Cel range
Value_Range=Waarde range
to=naar
Bucket=Bucket
X_Scale=X schaal
Y_Scale=Y schaal
Unit=Eenheid
Display_Y_by=Toon Y dmv
Count=Tellen
Bucket_Size=Bucket Size
X_Unit=X eenheid
Y_Unit=Y eenheid
X_Start=X begin
X_End=X einde
Y_Start=Y begin
Y_End=Y einde
percentage=percentage
sorry=Helaas , je invoer geeft geen geldige waarde/betekenis.\n Verbeter je invoer.\nTip : begin niet met de eerste cel...\nDus als je sheet loopt van A1...F10\nselecteer dan A2...F10
 
############################################
###### Histogram.java
Histogram=Histogram
Show=Laat zien
Add=Toevoegen
 
############################################
###### History.java
############################################
###### MainApplet.java
############################################
###### NewFileDialog.java
New=Nieuw
Rows=Rijen
Columns=Kolommen
Save_as_default=Bewaar als default
Error=Fout
Invalid_row_value=Foutieve rij waarde
Invalid_column_value=Foutieve kolom waarde
Row=Rij
Column=Kolom
############################################
###### Node.java
############################################
###### NumberField.java
############################################
###### ParserException.java
############################################
###### PasswordDialog.java
Password=Wachtwoorde
Enter_password=Geef wachtwoord password
Confirm_Password=Herhaal wachtwoord
Password_Incorrect=Wachtwoord is incorrect
Passwords_do_not_match_Please_try_again=De wachtwoorden zijn verschillen!\n\nProbeer opnieuw
 
############################################
###### SharpCellEditor.java
############################################
###### SharpCellRenderer.java
############################################
###### SharpClipboard.java
############################################
###### SharpDialog.java
############################################
###### SharpOptionPane.java
############################################
###### SharpTableModel.java
############################################
###### SharpTools.java
Sort_by_Column=Sorteer op kolom
Table=Tabel
New=Nieuw
Database=Database...
Save_As=Bewaren als...
Set_Password=Zet een wachtwoord...
Print=Printen
Recent_Files=Recente bestanden
Save_Window_on_Exit=Bewaar bij sluiten venster
Edit=Bewerken
Close=Sluiten
Undo=Herstel
Redo=Opnieuw
Sort=Sorteren
Set_Column_Width=Instellen kolombreedte
Set_First_Column_Width=Instellen van de eerste kolom
Chart=Grafiek
Show=laat zien
Help=Help
Help_Topics=Help onderwerpen
Show_Functions=Laat functies zien
About_SharpTools=Over Sharp Tools
Set_Password=Geef wachtwoord
Insert_Row=Voeg een rij in
Insert_Column=Voeg een kolom in
Delete_Row=Verwijder rij
Delete_Column=Verwijder kolom
No_cells_selected=Geen cellen geselecteerd
sorry2=Helaas, deze functie is nog niet geimplementeerd
Functions=Functies
############################################
###### SharpToolsProperties.java
Descending=Aflopend
Ascending=Oplopend
Sort_By=Sorteren aan de hand van
Then_By=gevolgd door
############################################
###### TabPanel.java
Options=Opties
Update=Actualiseer
############################################
###### TableOp.java
Remove=Verwijderen
Insert=Invoegen
Delete=Verwijderen
Default_width=Default breedte
rem1=Geef de nieuwe kolom breedte in pixels
rem2=Geef de eerste kolom breedte in pixels
rem3=Deze verwijderen kan andere cellen corrumperen.
rem4=Wil je doorgaan?
rem5=Je kunt niet alle rijen en kolommen verwijderen...
 
WIMS=Stuur je spreadsheet naar de WIMS server
are_you_sure=Weet je zeker dat ik je sheet naar WIMS moet sturen?
yes=ja
no=nee
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/1.html
0,0 → 1,85
 
<html>
<head>
<title>Spreadsheet - Applet</title>
<style>a:link{color:blue;text-decoration:none;}a:hover{color:red;text-decoration:none;}</style>
</head>
<body bgcolor="#408040" text="#ffffff" link="#80ff80" vlink="#70d070" alink="#80ffff">
<h1>SpreadSheet Applet</h1>
<script language="javascript" type="text/javascript">
function readthisraw(){
var input=document.getElementById("SharpTools").ReadRawApplet();
alert("we will send to WIMS:\n\n"+input);
}
function readthis(){
var input=document.getElementById("SharpTools").ReadApplet();
alert("we will send to WIMS:\n\n"+input);
}
function showapplet(){
document.getElementById("SharpTools").ShowSpreadSheet(true);
}
function hideapplet(){
document.getElementById("SharpTools").ShowSpreadSheet(false);
}
</script>
<applet id="SharpTools" archive="dist/SharpTools.jar" code="SharpTools/MainApplet" width="120" height="30">
<param name="language" value="nl">
<param name="X_screen_location" value="100"><!-- default 0-->
<param name="Y_screen_location" value="100"><!-- default 0-->
<param name="window_width" value="700">
<param name="window_height" value="400">
<param name="replyurl" value="http://localhost/wims/wims.cgi?module=$module&session=$sssion&reply$n=">
<param name="reply_type" value="1">
<!-- 0 = matrix ["1","2","3";"a","b","c"] note: "" string protection for pari evaluation -->
<!-- 1 = csv 1,2,3 \n a,b,c note : no string protection -->
<!-- 2 = tsv 1 \t 2 \t 3 \n a \t b \t c note : no string protection -->
<param name="convert_initial_tsv_to_matrix" value="true"><!-- append (to the reply) a line with the given/initial tsv-flie as a matrix -->
<param name="file" value="http://localhost/test.tsv">
<param name="fontsize" value="16">
<param name="empty_cell" value="null">
<!-- fill the empty cells with a String : default null -->
<!-- sizes in pixels -->
<param name="COLUMNWIDTH" value="80">
<param name="FIRSTCOLUMNWIDTH" value="40">
<param name="HISTOGRAMWIDTH" value="400">
<param name="HISTOGRAMHEIGHT" value="400">
<!-- configuring the menu & toolbar -->
<!-- accepted value's like caseinsensitive : TRUE , 0 , NO , NEE , NON -->
<!-- all other value will result in FALSE -->
<param name="COLUMNS" value="5">
<param name="ROWS" value="5">
<param name="TOOLBAR_NEW" value="false">
<param name="TOOLBAR_PRINT" value="false">
<param name="TOOLBAR_UNDO" value="true">
<param name="TOOLBAR_REDO" value="true">
<param name="TOOLBAR_CUT" value="true">
<param name="TOOLBAR_COPY" value="true">
<param name="TOOLBAR_PASTE" value="true">
<param name="TOOLBAR_FIND" value="true">
<param name="TOOLBAR_INSERTROW" value="true">
<param name="TOOLBAR_INSERTCOLUMN" value="true">
<param name="TOOLBAR_DELETEROW" value="true">
<param name="TOOLBAR_DELETECOLUMN" value="true">
<param name="TOOLBAR_SORTCOLUMN" value="true">
<param name="TOOLBAR_HISTOGRAM" value="true">
<param name="TOOLBAR_HELP" value="true">
<param name="TOOLBAR_FUNCTIONS" value="true">
</applet>
<br>
Reading raw input:
<input type="button" name=".....RAW......" value="RAW" onclick="javascript:readthisraw();">
<br>
Reading calculated formula's:
<input type="button" name=".....TEST......" value="CALCULATED" onclick="javascript:readthis();">
<br>
Showing the applet with Javascript:
<input type="button" name=".....SHOW......" value=".....SHOW....." onclick="javascript:showapplet();">
<br>
Hiding the applet with Javascript:
<input type="button" name=".....HIDE......" value=".....HIDE....." onclick="javascript:hideapplet();">
</h1>
</body>
</html>
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/database/test.script
0,0 → 1,75
CREATE TABLE PRODUCT(ID BIGINT NOT NULL PRIMARY KEY,NAME VARCHAR,DESCRIPTION VARCHAR,PRICE FLOAT)
CREATE TABLE ACCOUNTS(ID INTEGER NOT NULL IDENTITY PRIMARY KEY,OWNERNAME VARCHAR,BALANCE DOUBLE)
CREATE TABLE USERS(USERID VARCHAR NOT NULL PRIMARY KEY,FIRSTNAME VARCHAR,LASTNAME VARCHAR,EMAIL VARCHAR)
GRANT ALL ON CLASS "org.hsqldb.Library" TO PUBLIC
GRANT ALL ON CLASS "java.lang.Math" TO PUBLIC
CREATE USER SA PASSWORD "" ADMIN
CREATE ALIAS DAYNAME FOR "org.hsqldb.Library.dayname"
CREATE ALIAS SPACE FOR "org.hsqldb.Library.space"
CREATE ALIAS SUBSTRING FOR "org.hsqldb.Library.substring"
CREATE ALIAS SQRT FOR "java.lang.Math.sqrt"
CREATE ALIAS ABS FOR "java.lang.Math.abs"
CREATE ALIAS POWER FOR "java.lang.Math.pow"
CREATE ALIAS CHAR FOR "org.hsqldb.Library.character"
CREATE ALIAS CONCAT FOR "org.hsqldb.Library.concat"
CREATE ALIAS PI FOR "org.hsqldb.Library.pi"
CREATE ALIAS SECOND FOR "org.hsqldb.Library.second"
CREATE ALIAS TRUNCATE FOR "org.hsqldb.Library.truncate"
CREATE ALIAS MONTH FOR "org.hsqldb.Library.month"
CREATE ALIAS LOWER FOR "org.hsqldb.Library.lcase"
CREATE ALIAS ATAN2 FOR "java.lang.Math.atan2"
CREATE ALIAS REPEAT FOR "org.hsqldb.Library.repeat"
CREATE ALIAS DAYOFMONTH FOR "org.hsqldb.Library.dayofmonth"
CREATE ALIAS TAN FOR "java.lang.Math.tan"
CREATE ALIAS RADIANS FOR "java.lang.Math.toRadians"
CREATE ALIAS FLOOR FOR "java.lang.Math.floor"
CREATE ALIAS NOW FOR "org.hsqldb.Library.now"
CREATE ALIAS ACOS FOR "java.lang.Math.acos"
CREATE ALIAS DAYOFWEEK FOR "org.hsqldb.Library.dayofweek"
CREATE ALIAS CEILING FOR "java.lang.Math.ceil"
CREATE ALIAS DAYOFYEAR FOR "org.hsqldb.Library.dayofyear"
CREATE ALIAS LCASE FOR "org.hsqldb.Library.lcase"
CREATE ALIAS WEEK FOR "org.hsqldb.Library.week"
CREATE ALIAS SOUNDEX FOR "org.hsqldb.Library.soundex"
CREATE ALIAS ASIN FOR "java.lang.Math.asin"
CREATE ALIAS LOCATE FOR "org.hsqldb.Library.locate"
CREATE ALIAS EXP FOR "java.lang.Math.exp"
CREATE ALIAS MONTHNAME FOR "org.hsqldb.Library.monthname"
CREATE ALIAS YEAR FOR "org.hsqldb.Library.year"
CREATE ALIAS LEFT FOR "org.hsqldb.Library.left"
CREATE ALIAS ROUNDMAGIC FOR "org.hsqldb.Library.roundMagic"
CREATE ALIAS BITOR FOR "org.hsqldb.Library.bitor"
CREATE ALIAS LTRIM FOR "org.hsqldb.Library.ltrim"
CREATE ALIAS COT FOR "org.hsqldb.Library.cot"
CREATE ALIAS COS FOR "java.lang.Math.cos"
CREATE ALIAS MOD FOR "org.hsqldb.Library.mod"
CREATE ALIAS SIGN FOR "org.hsqldb.Library.sign"
CREATE ALIAS DEGREES FOR "java.lang.Math.toDegrees"
CREATE ALIAS LOG FOR "java.lang.Math.log"
CREATE ALIAS SIN FOR "java.lang.Math.sin"
CREATE ALIAS CURTIME FOR "org.hsqldb.Library.curtime"
CREATE ALIAS DIFFERENCE FOR "org.hsqldb.Library.difference"
CREATE ALIAS INSERT FOR "org.hsqldb.Library.insert"
CREATE ALIAS DATABASE FOR "org.hsqldb.Library.database"
CREATE ALIAS MINUTE FOR "org.hsqldb.Library.minute"
CREATE ALIAS HOUR FOR "org.hsqldb.Library.hour"
CREATE ALIAS IDENTITY FOR "org.hsqldb.Library.identity"
CREATE ALIAS QUARTER FOR "org.hsqldb.Library.quarter"
CREATE ALIAS CURDATE FOR "org.hsqldb.Library.curdate"
CREATE ALIAS BITAND FOR "org.hsqldb.Library.bitand"
CREATE ALIAS USER FOR "org.hsqldb.Library.user"
CREATE ALIAS UCASE FOR "org.hsqldb.Library.ucase"
CREATE ALIAS RTRIM FOR "org.hsqldb.Library.rtrim"
CREATE ALIAS LOG10 FOR "org.hsqldb.Library.log10"
CREATE ALIAS RIGHT FOR "org.hsqldb.Library.right"
CREATE ALIAS ATAN FOR "java.lang.Math.atan"
CREATE ALIAS UPPER FOR "org.hsqldb.Library.ucase"
CREATE ALIAS ASCII FOR "org.hsqldb.Library.ascii"
CREATE ALIAS RAND FOR "java.lang.Math.random"
CREATE ALIAS LENGTH FOR "org.hsqldb.Library.length"
CREATE ALIAS ROUND FOR "org.hsqldb.Library.round"
CREATE ALIAS REPLACE FOR "org.hsqldb.Library.replace"
INSERT INTO PRODUCT VALUES(1,'Plier',NULL,3.5)
INSERT INTO PRODUCT VALUES(2,'Hammer',NULL,7.76)
INSERT INTO PRODUCT VALUES(3,'Saw',NULL,17.35)
INSERT INTO PRODUCT VALUES(4,'Clamp',NULL,4.37)
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/database/test.backup
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/database/browse.bat
0,0 → 1,0
java -classpath ..\hsqldb.jar org.hsqldb.util.DatabaseManager
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/database/create-hsql.sql
0,0 → 1,13
DROP TABLE PRODUCT;
CREATE TABLE PRODUCT(ID BIGINT NOT NULL PRIMARY KEY,NAME VARCHAR,DESCRIPTION VARCHAR,PRICE FLOAT);
 
INSERT INTO PRODUCT VALUES (1, 'Plier', NULL, 3.5);
INSERT INTO PRODUCT VALUES (2, 'Hammer', NULL, 7.76);
INSERT INTO PRODUCT VALUES (3, 'Saw', NULL, 17.35);
INSERT INTO PRODUCT VALUES (4, 'Clamp', NULL, 4.37);
 
DROP TABLE ACCOUNTS;
CREATE TABLE ACCOUNTS(ID INTEGER NOT NULL IDENTITY PRIMARY KEY,OWNERNAME VARCHAR,BALANCE DOUBLE);
 
DROP TABLE USERS;
CREATE TABLE USERS(USERID VARCHAR NOT NULL PRIMARY KEY,FIRSTNAME VARCHAR,LASTNAME VARCHAR,EMAIL VARCHAR);
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/database/test.data
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/database/test.properties
0,0 → 1,4
#HSQL database
#Thu May 24 15:47:48 PDT 2001
version=1.6
modified=no
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/AUTHORS
0,0 → 1,37
 
==================================
Author and Maintainer after v 1.1
==================================
Hua Zhong is the current Sharp Tools maintainer.
 
You can send email to sharp@cs.columbia.edu
The official website is http://www.cs.columbia.edu/sharptools/
==================================================
Original Authors of Sharp Tools Spreadsheet (v1.0)
==================================================
 
Hua Zhong (Team Leader) <huaz@cs.columbia.edu>
- Architecture and UI Design; Formulas; Undo/Redo; Histogram; Function help;
Data exchange with Excel
 
Ricky Chin
- Table Model; Clipboard; Table insertion/deletion/sorting
 
Daniel Goldberg
- Initial UI; File open/save; Printing
 
Daniel Medina
- Documentation; Help browser
 
Andrei Scudder
- Some of the dialogs
 
==================================
Contribution
==================================
 
Shariz Kanga <skanga@bigfoot.com>
- made Sharp Tools able to import tables from a database by JDBC
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/wims.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/deletecolumn.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/new.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/send.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/options.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/cut.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/insertrow.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/print.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/start.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/new32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/refresh.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/save.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/save32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/close.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/undo.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/database32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/copy.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/paste.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/no.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/colwidth.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/tool.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/find.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/insertcolumn.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/cancel.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/find32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/sort.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/help.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/redo.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/deleterow.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/fill32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/sort32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/help32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/locked.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/open.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/chart.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/unlocked.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/dberror32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/chart32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/password32.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/images/ok.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/CHANGELOG
0,0 → 1,75
3/2010
jm.evers
 
- Adapting applet to WIMS usage.
- Correcting a few flaws.(and introducing a few...)
- Sends spreadsheet data as matrix directly to WIMS
- Optional javascript methods for sending data...
 
 
<applet id="SharpTools" archive="dist/SharpTools.jar" code="SharpTools/MainApplet" width="120" height="30"><!-- open & close buttons -->
<param name="language" value="nl"><!-- nl,fr default en -->
<param name="X_screen_location" value="100"><!-- location on screen for applet window : default 0 -->
<param name="Y_screen_location" value="100"><!-- location on screen for applet window : default 0 -->
<param name="window_width" value="700"><!-- xsize of spreadsheet -->
<param name="window_height" value="400"><!-- ysize of spreadsheet -->
<param name="replyurl" value="http://localhost/wims/wims.cgi?module=$module&session=$sssion&reply$n=">
<param name="matrix_format" value="true"><!-- reply to wims in matrix [1a,2a,3a,4a;1b,2b,3b,4b;1c,2c,3c,4c;1d,2d,3d,4d;etc] -->
<param name="empty_cell" value="null"><!-- if matrix=true , fill the empty cells with this String : default null -->
<!-- if matrix=false the reply will be lines for rows and tab for columns -->
<param name="file" value="http://localhost/test.tsv"><!-- internal format TSV : wims getfile reading or direct downloading from module_dir -->
<param name="fontsize" value="16">
 
<!-- options. not really needed ... configuring the menu & toolbar -->
<param name="COLUMNWIDTH" value="80">
<param name="FIRSTCOLUMNWIDTH" value="40">
<param name="HISTOGRAMWIDTH" value="400">
<param name="HISTOGRAMHEIGHT" value="400">
<param name="COLUMNS" value="5">
<param name="ROWS" value="5">
<param name="TOOLBAR_NEW" value="false">
<param name="TOOLBAR_PRINT" value="false">
<param name="TOOLBAR_UNDO" value="true">
<param name="TOOLBAR_REDO" value="true">
<param name="TOOLBAR_CUT" value="true">
<param name="TOOLBAR_COPY" value="true">
<param name="TOOLBAR_PASTE" value="true">
<param name="TOOLBAR_FIND" value="true">
<param name="TOOLBAR_INSERTROW" value="true">
<param name="TOOLBAR_INSERTCOLUMN" value="true">
<param name="TOOLBAR_DELETEROW" value="true">
<param name="TOOLBAR_DELETECOLUMN" value="true">
<param name="TOOLBAR_SORTCOLUMN" value="true">
<param name="TOOLBAR_HISTOGRAM" value="true">
<param name="TOOLBAR_HELP" value="true">
<param name="TOOLBAR_FUNCTIONS" value="true">
NO JAVA
</applet>
 
 
Change logs
===================================
 
1.2
 
- Column headers enabled
- Column width can be dynamically adjusted
 
1.1
 
- Rewrote base dialog class (SharpDialog) and all other dialog subclasses;
this makes creating new dialogs much easier
- Shariz Kanga <skanga@bigfoot.com> made Sharp Tools able to import tables
from a database by JDBC. Tested with HSQL and Oracle (by Shariz) and
MySQL (by me).
- Use extention file name ".cvs" instead of ".sts".
- Put stuff in jar files.
 
If you want to use the new database function, you need to download the JDBC
driver(s) and put in CLASSPATH (edit SharpTools or SharpTools.bat).
 
Below are some such websites:
 
MySQL: http://www.worldserver.com/mm.mysql/
HSQL: http://sourceforge.net/projects/hsqldb/
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SharpCellRenderer.java
0,0 → 1,158
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
 
* SharpCellRenderer.java
*
* $Id: SharpCellRenderer.java,v 1.9 2001/06/03 22:21:28 huaz Exp $
*
* Created on October 26, 2000, 9:23 PM
*/
package SharpTools;
import javax.swing.*;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.border.*;
import java.awt.Component;
import java.awt.Color;
import java.awt.Rectangle;
 
/** The class for rendering (displaying) individual Cell objects in a
* <code>JTable</code>.
* <p>
* Because the DefaultTableCellRender is optimized for rendering objects
* in JTable, this renderer extends that class. Since the zeroth row and
* column of the table are used as labels, SharpCellRender renders them
* differently by have a gray background etc. SharpCellRenderer can
* be changed to toggle between displaying the text and value of a formula
* cell. This was done in a previous version but is not removed.
* @author Ricky Chin
* @version $Revision: 1.9 $
*/
public class SharpCellRenderer extends DefaultTableCellRenderer {
 
/**
* Creates a SharpCellRenderer.
*/
public SharpCellRenderer() {
super();
}
 
// implements javax.swing.table.TableCellRenderer
/**
* Returns the default table cell renderer.
* @param table the <code>JTable</code>
* @param value the value to assign to the cell at
* <code>[row, column]</code>
* @param isSelected true if cell is selected
* @param hasFocus true if cell has focus
* @param row the row of the cell to render
* @param column the column of the cell to render
* @return the default table cell renderer
*/
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
 
/* the following is the similar to DefaultTableCellRenderer */
if (isSelected && !(isHeaderCell(row, column))) {
super.setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
}else {
/* set header cells background to grey and rest to default */
if (isHeaderCell(row, column)) {
super.setBackground(Color.lightGray);
super.setForeground(table.getForeground());
}else {
super.setForeground(table.getForeground());
super.setBackground(table.getBackground());
}
}
if(SharpTools.inapplet){ setFont(MainApplet.defaultFont);}
else{ setFont(table.getFont());}
 
 
if (hasFocus) {
setBorder( UIManager.getBorder("Table.focusCellHighlightBorder") );
if (table.isCellEditable(row, column)) {
super.setForeground( UIManager.getColor(
"Table.focusCellForeground") );
super.setBackground( UIManager.getColor(
"Table.focusCellBackground") );
}
} else {
setBorder(noFocusBorder);
}
 
/* this method has been changed for formula feature */
setValue(value, isSelected, hasFocus, row, column);
 
//DefaulTableCellRenderer code
// begin optimization to avoid painting background
Color back = getBackground();
boolean colorMatch = (back != null) &&
( back.equals(table.getBackground()) ) && table.isOpaque();
setOpaque(!colorMatch);
// end optimization to aviod painting background
 
return this;
}
/**
* Sets the string for the cell being rendered to <code>value</code>.
* @param value the string value for this cell; if value is
* <code>null</code> it sets the text value to an empty string
* @param hasFocus whether cell has focus or not
* @param isSelected whether cell is selected
* @param row cell row
* @param column cell column
*/
protected void setValue(Object value, boolean hasFocus,
boolean isSelected, int row, int column) {
if (value instanceof Cell) {
//we only care about the value, not the formula string
Cell temp = (Cell)value;
Object data = temp.getValue();
if (isHeaderCell(row, column)) {
//label cells are center aligned
setHorizontalAlignment(JTextField.CENTER);
}else {
if (data instanceof Number) {
//numbers are right justified
setHorizontalAlignment(JTextField.RIGHT);
}else {
//everything else is left justified
setHorizontalAlignment(JTextField.LEFT);
}
}
//value to display in table
setText((data == null) ? "" : data.toString());
}
else {
//not cell object so render with toString of that object
setText((value == null) ? "" : value.toString());
}
}
 
/**
* Header cells are special.
*
* @param row the int value of the row
* @param column the int value of the column
* @return true if row = column = 0.
*/
protected boolean isHeaderCell(int row, int column) {
return (/*row == 0 || */column == SharpTools.baseCol-1);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SharpToolsProperties.java
0,0 → 1,15
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package SharpTools;
 
public abstract class SharpToolsProperties{}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/FileOp.java
0,0 → 1,934
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/*
* @(#)FileOp.java
*
* $Id: FileOp.java,v 1.84 2002/08/08 05:15:03 huaz Exp $
*
* Created on November 16, 2000, 12:00 AM
*
*/
package SharpTools;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.filechooser.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.awt.print.*;
import java.sql.*;
 
/**
* Handles the saving and opening of files, and the updating of the table model
* appropriately.
*
* @author Daniel Goldberg, Hua Zhong, Shiraz Kanga (openDb)
* @version $Revision: 1.84 $
*/
 
public class FileOp implements ActionListener, Printable {
 
final static private int UNNAMED = 0;
final static private int FILE = 1;
final static private int DATABASE = 2;
 
private int openType = UNNAMED;
private int maxNumPage = 1;
private boolean columnOverflow;
 
private StringTokenizer tokenizer;
private PrintStream out;
private BufferedReader in;
 
private SharpTools sharp;
private JTable table;
private SharpTableModel tableModel;
private File file;
private String password;
//Create a file chooser
private JFileChooser fileChooser;
private static SharpFileFilter filter;
final ImageIcon newIcon=new ImageIcon(getClass().getResource("/images/new32.gif"));
final ImageIcon openIcon=new ImageIcon(getClass().getResource("/images/open.gif"));
final ImageIcon saveIcon=new ImageIcon(getClass().getResource("/images/save32.gif"));
//final private static ImageIcon newIcon = SharpTools.getImageIcon("new32.gif");
//final private static ImageIcon openIcon = SharpTools.getImageIcon("open.gif");
//final private static ImageIcon saveIcon = SharpTools.getImageIcon("save32.gif");
final private static String extname = ".csv";
 
class SharpFileFilter extends javax.swing.filechooser.FileFilter {
public boolean accept(File file) {
if (file.isDirectory())
return true;
 
return file.getName().endsWith(extname);
}
 
public String getDescription() {
return SharpTools.translation.getProperty("Sharp_Tools_Spreadsheet");
}
}
/**
* This contructor creates a FileOperations object with reference
* SharpTableModel; the file of the TableModel is extracted.
*
* @param tableModel calling table model is referenced in
*/
public FileOp(SharpTools gui) {
sharp = gui;
table = gui.getTable();
tableModel = gui.getTableModel();
fileChooser = new JFileChooser(new File("."));
filter = new SharpFileFilter();
fileChooser.addChoosableFileFilter(filter);
sharp.setTitle(SharpTools.translation.getProperty("Untitled_-_Sharp_Tools_Spreadsheet"));
 
columnOverflow = false;
 
// below define key shortcuts
 
table.registerKeyboardAction
(this,SharpTools.translation.getProperty("New"),
KeyStroke.getKeyStroke
(KeyEvent.VK_N,ActionEvent.CTRL_MASK,false),
JComponent.WHEN_FOCUSED);
table.registerKeyboardAction
(this,SharpTools.translation.getProperty("OpenFile"),
KeyStroke.getKeyStroke
(KeyEvent.VK_O,ActionEvent.CTRL_MASK,false),
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction
(this,SharpTools.translation.getProperty("OpenDb"),
KeyStroke.getKeyStroke
(KeyEvent.VK_D,ActionEvent.CTRL_MASK,false),
JComponent.WHEN_FOCUSED);
table.registerKeyboardAction
(this,SharpTools.translation.getProperty("Save"),
KeyStroke.getKeyStroke
(KeyEvent.VK_S,ActionEvent.CTRL_MASK,false),
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction
(this,SharpTools.translation.getProperty("Print"),
KeyStroke.getKeyStroke
(KeyEvent.VK_P,ActionEvent.CTRL_MASK,false),
JComponent.WHEN_FOCUSED);
table.registerKeyboardAction
(this,SharpTools.translation.getProperty("Exit"),
KeyStroke.getKeyStroke
(KeyEvent.VK_E,ActionEvent.CTRL_MASK,false),
JComponent.WHEN_FOCUSED);
}
 
/**
* Confirm dialog box that queries whether user wishes to save
* current document or not.
*
* @return true to save, false otherwise
*/
public int queryForSave() {
// show confirm dialog box from static JOptionPane method
String filename = "Untitled";
if (file != null)
filename = file.getName();
int choice =
SharpOptionPane.showOptionDialog
(sharp,
"Do you want to save the changes you made to \""+filename+"\"?",
"Save",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
saveIcon);
// return user's choice
return choice;
}
 
/**
* Menu and button wrapper that handles interactive process of creating
* new document. queryForSave returns choice, which determines action
* action performed according to entry point in switch block.
*/
public void newFile() {
int choice;
 
// pop up querySave box (yes, no, cancel) and save choice
// if table modified state is modified, else set choice
// to JOptionPane.NO_OPTION which clears cells without
if(tableModel.isModified())
choice = queryForSave();
else
choice = JOptionPane.NO_OPTION;
switch(choice) {
case JOptionPane.YES_OPTION:
// if user chooses yes in dialog box, save document first
// before executing clear range
saveFile();
case JOptionPane.NO_OPTION:
 
Config config = sharp.getConfig();
 
NewFileDialog dialog = new NewFileDialog(sharp,
config.getInt("ROWS"),
config.getInt("COLUMNS"));
dialog.setLocationRelativeTo(sharp);
dialog.setVisible(true);
 
if (dialog.isCancelled())
return;
 
int row = dialog.getRows();
int col = dialog.getColumns();
 
// range of cells is cleared, the filename is set to untitled
// and the modified state is set to unmodified.
// file = new File("Untitled");
file = null;
sharp.setTitle(SharpTools.translation.getProperty("Untitled_-_Sharp_Tools_Spreadsheet"));
sharp.newTableModel(row, col);
tableModel = sharp.getTableModel();
 
// reset password
setPasswordValue(password);
 
default:
// break out of loop for all choices. action depends
// on entry point.
break;
}
}
 
/**
* Menu and button wrapper that handles interactive process of saving
* current file as itself.
*
*/
public void saveFile() {
if(tableModel.isModified()) {
// if(file.getName().equals("Untitled")) {
if (file == null) {
saveAsFile();
} else {
saveTableModel();
}
}
}
/**
* Menu and button wrapper that handles interactive process of saving
* current file.
*
*/
public void saveAsFile() {
// open save dialog and save user input
int choice = fileChooser.showSaveDialog(sharp);
// if user clicks ok, then procede with save, otherwise do nothing
if(choice == JFileChooser.APPROVE_OPTION) {
// get selected file to save to
File selectedfile = fileChooser.getSelectedFile();
 
fileChooser = new JFileChooser(selectedfile.getParentFile());
fileChooser.addChoosableFileFilter(filter);
 
// enforce the extension name
String path;
 
try {
path = selectedfile.getCanonicalPath();
}
catch (IOException e) {
fileOpError(SharpTools.translation.getProperty("Save"), SharpTools.translation.getProperty("Unexpected_error"));
return;
}
 
if (!path.endsWith(extname))
selectedfile = new File(path+extname);
 
// check the existence of the file
if (selectedfile.exists()) {
choice =
SharpOptionPane.showOptionDialog
(sharp,
SharpTools.translation.getProperty("File_already_exists")+" ("+selectedfile.getName()+")\n\n"+SharpTools.translation.getProperty("Do_you_want_to_overwrite_it"),
SharpTools.translation.getProperty("Save"),
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE,
saveIcon, 1);
if (choice != JOptionPane.YES_OPTION)
return;
}
saveTableModel(selectedfile);
}
}
 
/**
* Opens document. Queries user to save if modified state is modified.
* Uses switch statement on user's choice to choose path of execution.
*/
public void openFile() {
int choice;
 
// pop up querySave box (yes, no, cancel) and save choice
// if table modified state is modified, else set choice
// to JOptionPane.NO_OPTION which clears cells without
if(tableModel.isModified())
choice = queryForSave();
else
choice = JOptionPane.NO_OPTION;
switch(choice) {
case JOptionPane.YES_OPTION:
// if user chooses yes in dialog box, save document first
// before executing clear range
saveFile();
case JOptionPane.NO_OPTION:
// open dialog from filechooser and save user choice
int userChoice = fileChooser.showOpenDialog(sharp);
// if user chooses file, call openTableModel on new
// FileOperations object, else go to break in default
if(userChoice == JFileChooser.APPROVE_OPTION) {
File selectedfile = fileChooser.getSelectedFile();
fileChooser = new JFileChooser(selectedfile.getParentFile());
fileChooser.addChoosableFileFilter(filter);
 
openTableModel(selectedfile);
 
}
default:
// break out of loop for all choices. action depends
// on entry point.
break;
}
}
 
public void openFileString(String sp){
System.out.println("in FileOp :"+sp);
StringBuffer textBuf = new StringBuffer();
String line;
String password = null;
try {
in = new BufferedReader(new StringReader(sp));
line = in.readLine();
if (line.indexOf('\t') == -1 &&
line.startsWith("Password: ")) {
// password defined
password = line.substring(10);
if (!verifyPassword(password)) {
return;
}
}
else {
textBuf.append(line);
textBuf.append("\n");
}
while ((line = in.readLine()) != null) {
textBuf.append(line);
textBuf.append("\n");
}
 
// reset password
setPasswordValue(password);
 
String text = textBuf.toString();
// create new table model
CellPoint size = SharpTableModel.getSize(text);
// System.out.println(size);
sharp.newTableModel(size.getRow(), size.getCol());
tableModel = sharp.getTableModel();
tableModel.fromString(text, 0, 0,
new CellRange(SharpTools.baseRow,
size.getRow(),
SharpTools.baseCol,
size.getCol()));
} catch (Exception e) { e.printStackTrace();System.out.println("in FileOp.java string = "+sp);}
}
/**
* Closes program but checks to see if document is modified and prompts
* for save. Saves or not depending on user's choice. Then exits.
* Queries for save if modified, and uses switch to parse choice.
*
* @return whether the file is closed; user can cancel and return false
*/
public boolean closeFile() {
int choice;
if(tableModel.isModified())
choice = queryForSave();
else
choice = JOptionPane.NO_OPTION;
switch(choice) {
case JOptionPane.CANCEL_OPTION:
return false;
case JOptionPane.YES_OPTION:
// if user chooses yes in dialog box, save document first
// before exiting.
saveFile();
default:
// System.exit( 0 );
return true;
}
}
/**
* Saves table model to specified file cell by cell in tab-delimited
* format.
*
* @param aFile the file name to save to
*/
public void saveTableModel(File aFile) {
 
try {
// initialize output
 
out = new PrintStream(new FileOutputStream(aFile));
int rowCount = tableModel.getRowCount();
int colCount = tableModel.getColumnCount();
// print out number of columns and rows
// out.println(rowCount+"\t"+colCount);
if (password != null && password.length() > 0)
out.println("Password: "+password);
out.print(tableModel.toString());
out.flush();
file = aFile;
// set modified to false
tableModel.setPasswordModified(false);
tableModel.setModified(false);
 
// update recent files
addRecentFile(file);
String title = file.getName();
if (title.endsWith(extname))
title = title.substring(0, title.length()-4);
sharp.setTitle(title+" "+SharpTools.translation.getProperty("Sharp_Tools_Spreadsheet"));
} catch (FileNotFoundException e) {
fileOpError(SharpTools.translation.getProperty("Save"), SharpTools.translation.getProperty("File_cannot_be_created")+" : "+aFile.getName());
} catch (IOException e) {
fileOpError(SharpTools.translation.getProperty("Save"), SharpTools.translation.getProperty("IO_error_in_saving"+" : "+aFile.getName()+" !"));
}
}
/**
* Overloaded save function that takes the current filename as default.
*/
public void saveTableModel() {
saveTableModel(file);
}
 
/**
* Opens table model data from file.
*
* @param aFile file name from which to open
*/
public void openTableModel(File aFile) {
 
StringBuffer textBuf = new StringBuffer();
String line;
String password = null;
try {
in = new BufferedReader(new FileReader(aFile));
line = in.readLine();
if (line.indexOf('\t') == -1 &&
line.startsWith("Password: ")) {
// password defined
password = line.substring(10);
if (!verifyPassword(password)) {
return;
}
}
else {
textBuf.append(line);
textBuf.append("\n");
}
while ((line = in.readLine()) != null) {
textBuf.append(line);
textBuf.append("\n");
}
 
// reset password
setPasswordValue(password);
 
String text = textBuf.toString();
// create new table model
CellPoint size = SharpTableModel.getSize(text);
// System.out.println(size);
sharp.newTableModel(size.getRow(), size.getCol());
tableModel = sharp.getTableModel();
tableModel.fromString(text, 0, 0,
new CellRange(SharpTools.baseRow,
size.getRow(),
SharpTools.baseCol,
size.getCol()));
file = aFile;
// tableModel.setModified(false);
// set new title for spreadsheet
String title = file.getName();
if (title.endsWith(extname))
title = title.substring(0, title.length()-4);
 
sharp.setTitle(title+" - "+SharpTools.translation.getProperty("Sharp_Tools_Spreadsheet"));
 
// update recent files
addRecentFile(file);
} catch (FileNotFoundException e) {
fileOpError(SharpTools.translation.getProperty("Open"),SharpTools.translation.getProperty("File_not_found")+" : "+aFile.getName());
} catch (IOException e) {
fileOpError(SharpTools.translation.getProperty("Open"), SharpTools.translation.getProperty("IO_error_in_opening")+" : "+aFile.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
 
/**
* Get the file name from the recent list by index
*
* @param index the index in the list (also the menu)
* @return file name
*/
private String getRecentFile(int index) {
Config config = SharpTools.getConfig();
return config.get("RECENTFILE"+String.valueOf(index));
}
 
/**
* Set the file name in the recent list by index
*
* @param index the index in the list (also the menu)
* @param s file name
*/
private void setRecentFile(int index, String s) {
Config config = SharpTools.getConfig();
config.set("RECENTFILE"+String.valueOf(index), s);
}
 
/**
* Move an item from the specified index to the first one
*
* @param index the index in the list (also the menu)
*/
private void moveToFront(int index) {
if (index <= 0)
return;
String frontName = getRecentFile(index);
for (int i = index; i >0; i--)
setRecentFile(i, getRecentFile(i-1));
setRecentFile(0, frontName);
}
 
private void addRecentFile(File file) {
try {
String filename = file.getCanonicalPath();
int total = SharpTools.getConfig().getInt("RECENTFILELIST");
for (int i = 0; i < total; i++) {
if (filename.equals(getRecentFile(i))) {
moveToFront(i);
return;
}
}
// now we push it
setRecentFile(total-1, filename);
moveToFront(total-1);
}
catch (Exception e) {
}
}
 
/**
* construct the recent file list from Config
*
* @param menu the menu item to insert file list in
*/
public void createRecentFilesMenu(JMenu menu) {
Config config = SharpTools.getConfig();
menu.removeAll();
try {
for (int i = 0; i < config.getInt("RECENTFILELIST"); i++) {
String filename = getRecentFile(i);
if (filename.length() > 0) {
File file = new File(filename);
JMenuItem item = new JMenuItem(file.getName(), openIcon);
item.addActionListener(new RecentFileListener(file, this));
menu.add(item);
}
}
}
catch (Exception e) {}
 
}
/*
* Set password and do some extra stuff - always use this function
* to change password value!
*/
private void setPasswordValue(String newPassword) {
password = newPassword;
sharp.checkPasswordState();
}
/*
* Initiates print job by creating a <code>PrintJob</code> object,
* and assigning the current <code>FileOp</code> object to it.
* It then calls up the Print Dialog, and then if user clicks print
* on the dialog, print() is called on the PrintJob object. This call
* also calls the print method for the FileOp object, which takes
* care of the creation of a printable table
*/
public void printData() {
// create temporary object that contains this FileOp object
// and reset columnOverflow to false
FileOp fileOp = this;
columnOverflow = false;
 
try {
PrinterJob prnJob = PrinterJob.getPrinterJob();
 
prnJob.setPrintable(fileOp);
// opens print dialog, and if user doesn't cancel the dialog
// it calls print()
if (!prnJob.printDialog())
return;
maxNumPage = 1;
 
prnJob.print();
}
catch (PrinterException e) {
e.printStackTrace();
fileOpError(SharpTools.translation.getProperty("Print"), SharpTools.translation.getProperty("Printing_error")+" : "+e.toString());
}
}
/*
* Main print method of FileOp that performs calculations for
* dimensions of printed table, and writes the strings out to
* the <code>Graphics</code> object that is responsible for
* holding the printed data. All parameters are called by Java
* classes, specifically <code>PrintJob</code>, not explicitly in
* our code
*
* @param pg Graphics object that holds the printed information
* @param pageFormat PageFormat object that holds print dimensions
* @param pageIndex number of current Page
*
* @return status of current call of print method
*/
public int print(Graphics pg, PageFormat pageFormat,
int pageIndex) throws PrinterException {
// if pageIndex is beyond maximum page number, then
// don't return
if (pageIndex >= maxNumPage)
return NO_SUCH_PAGE;
 
// set Graphics object to printed cartesian origin
pg.translate((int)pageFormat.getImageableX(),
(int)pageFormat.getImageableY());
 
// get printable width and height of page
int wPage = 0;
int hPage = 0;
if (pageFormat.getOrientation() == pageFormat.PORTRAIT) {
wPage = (int)pageFormat.getImageableWidth();
hPage = (int)pageFormat.getImageableHeight();
 
wPage = 550;
hPage = 950;
}
else {
wPage = (int)pageFormat.getImageableWidth();
wPage += wPage/2;
hPage = (int)pageFormat.getImageableHeight();
wPage = 950;
hPage = 550;
 
pg.setClip(0,0,wPage,hPage);
}
 
// testcode
// Debug.println(wPage);
// Debug.println(hPage);
 
// create int to keep track of vertical distance
int y = 0;
 
// set particular font and color for printing title of file
pg.setColor(Color.black);
Font fn = pg.getFont().deriveFont(Font.BOLD);
FontMetrics fm = pg.getFontMetrics();
 
// increment height for title
y += fm.getAscent();
 
// if file has no name, then print hard coded string
if(getFile() == null)
pg.drawString("Untitled File", 0, y);
else
pg.drawString(getFile().getName(), 0, y);
 
y += 20; // space between title and table headers
 
// Font headerFont = table.getFont().deriveFont(Font.BOLD);
// pg.setFont(headerFont);
// fm = pg.getFontMetrics();
 
TableColumnModel colModel = table.getColumnModel();
int nColumns = colModel.getColumnCount();
int x[] = new int[nColumns];
x[0] = 0;
int h = fm.getAscent();
y += h; // add ascent of header font because of baseline
// positioning (see figure 2.10)
int nRow, nCol;
 
// define widths of each column
for (nCol=1; nCol<nColumns; nCol++) {
TableColumn tk = colModel.getColumn(nCol);
int width = tk.getWidth();
// check if table width is within print width
if (x[nCol] + width > wPage) {
nColumns = nCol;
// show error one time if table width exceeds print width
if(!columnOverflow) {
fileOpError(SharpTools.translation.getProperty("Print"), SharpTools.translation.getProperty("Table_width_exceeds_printed_width"));
columnOverflow = true;
}
 
break;
}
if (nCol+1<nColumns)
x[nCol+1] = x[nCol] + width;
String title = (String)tk.getIdentifier();
//pg.drawString(title, x[nCol], y);
}
pg.setFont(table.getFont());
fm = pg.getFontMetrics();
// find out number of rows that can be printed on current page
int header = y;
h = fm.getHeight();
int rowH = Math.max((int)(h*1.5), 10);
int rowPerPage = (hPage-header)/rowH;
maxNumPage = Math.max((int)Math.ceil(table.getRowCount()/
(double)rowPerPage), 1);
 
// calculate initial and final rows for current page
int iniRow = pageIndex*rowPerPage;
int endRow = Math.min(table.getRowCount(),
iniRow+rowPerPage);
// iterate through each rows for this page
for (nRow=iniRow+1; nRow<endRow; nRow++) {
 
y += h; // space between each row
 
// iterate through each column on the row, getting data of each
// cell and calling drawString with the data
for (nCol=1; nCol<nColumns; nCol++) {
int col = table.getColumnModel().getColumn(nCol).getModelIndex();
String str = tableModel.getCellAt(nRow, nCol).getValue().toString();
// testcode
// System.out.println(str);
pg.setColor(Color.black);
pg.drawString(str, x[nCol], y);
}
}
// explicit call on garbage collector to flush all temporary data
// used, such as graphics objects
System.gc();
return PAGE_EXISTS;
}
 
 
/**
* returns the file
*
* @return the file
*/
public File getFile() {
return file;
}
 
/**
* has password?
*
*
*/
public boolean hasPassword() {
return password != null && password.length() > 0;
}
/**
* Set Password Dialog
*/
public void setPassword() {
PasswordDialog passwordDialog = new PasswordDialog(sharp, null);
passwordDialog.setVisible(true);
String text = passwordDialog.getValidatedText();
if (text != null) {
setPasswordValue(text);
tableModel.setPasswordModified(true);
}
table.requestFocus();
}
 
/**
* Verify Password Dialog
*/
private boolean verifyPassword(String password) {
 
PasswordDialog passwordDialog = new PasswordDialog(sharp, password);
passwordDialog.pack();
passwordDialog.setLocationRelativeTo(sharp);
passwordDialog.setVisible(true);
String text = passwordDialog.getValidatedText();
table.requestFocus();
return text != null;
}
/**
* a function to display error messages
*
* @param op the operation that caused this error
* @param error the error message
*/
private void fileOpError(String op, String error) {
SharpOptionPane.showMessageDialog(sharp, error, op,
JOptionPane.ERROR_MESSAGE, null);
table.requestFocus();
}
 
/**
* This method is activated on the Keystrokes we are listening to
* in this implementation. Here it listens for keystroke
* ActionCommands.
*
* Without this listener, when we press certain keys the individual
* cell will be activated into editing mode in addition to the
* effect of the key accelerators we defined with menu items.
* With this key listener, we avoid this side effect.
*/
public void actionPerformed(ActionEvent e) {
 
if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("New"))==0) {
newFile();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("OpenFile"))==0) {
openFile();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("OpenDb"))==0) {
openDb();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Save"))==0) {
saveFile();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Print"))==0) {
printData();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Exit"))==0) {
sharp.exit();
}
}
 
/**
* Opens document. Queries user to save if modified state is modified.
* Uses switch statement on user's choice to choose path of execution.
*
* @author Shiraz Kanga
*/
public void openDb ()
{
int choice;
 
// pop up querySave box (yes, no, cancel) and save choice
// if table modified state is modified, else set choice
// to JOptionPane.NO_OPTION which clears cells without
if (tableModel.isModified ())
choice = queryForSave ();
else
choice = JOptionPane.NO_OPTION;
switch (choice) {
case JOptionPane.YES_OPTION:
// if user chooses yes in dialog box, save document first
// before executing clear range
saveFile ();
case JOptionPane.NO_OPTION:
Database db = new Database(sharp);
db.connectDb();
default:
// break out of loop for all choices. action depends
// on entry point.
break;
}
}
}
 
/**
* This is the listener for "Recent Files" menu
*
* @author Hua Zhong
*/
class RecentFileListener implements ActionListener {
File file;
FileOp fileOp;
RecentFileListener(File file, FileOp fileOp) {
this.file = file;
this.fileOp = fileOp;
}
 
public void actionPerformed(ActionEvent evt) {
fileOp.openTableModel(file);
}
}
 
 
 
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/PasswordDialog.java
0,0 → 1,141
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)PasswordDialog.java
*
* $Id: PasswordDialog.java,v 1.4 2001/05/27 22:28:58 huaz Exp $
*
* Created on November 16, 2000, 12:00 AM
*/
package SharpTools;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
* This class provides a password validating dialog.
* User is prompted to enter and confirm a password
* If passwords do not much an error message is displayed
* and user is prompted to re-enter the passwords
* <P>
*
* @author Andrei Scudder
* @author Hua Zhong (rewrote using SharpDialog)
* @version $Revision: 1.4 $
*/
public class PasswordDialog extends SharpDialog {
private JFrame frame;
private String typedText = null;
private String password;
final private JPasswordField textField;
final private JPasswordField confirmField;
final ImageIcon passwordIcon=new ImageIcon(getClass().getResource("/images/password32.gif"));
//final private static ImageIcon passwordIcon = SharpTools.getImageIcon("password32.gif");
// password is null if this is Set Password...
// it's a password if we need to verify
public PasswordDialog(JFrame aFrame, String pass) {
super(aFrame, "Password", true);
 
frame = aFrame;
password = pass;
//various properties of the dialog labels and text fields
final String msgString1 = SharpTools.translation.getProperty("Enter_password")+" : ";
final String msgString2 = SharpTools.translation.getProperty("Confirm_Password")+" : ";
textField = new JPasswordField(10);
confirmField = new JPasswordField(10);
Object[] input = {msgString1, textField, msgString2, confirmField};
Object[] verify = {msgString1, textField};
Object[] array = password == null ? input : verify;
 
setOptionPane(array,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
passwordIcon);
}
/*
* @return password string
*/
public String getValidatedText() {
return typedText;
}
//compares to arrays of characters
private static boolean fieldsAreTheSame(char[] input1, char[] input2) {
if (input1.length != input2.length)
return false;
for (int i = 0; i < input1.length; i ++)
if (input1[i] != input2[i])
return false;
return true;
}
 
protected boolean onOK() {
typedText = new String(textField.getPassword());
if (password != null) {
// verify password
if (!typedText.equals(password)) {
SharpOptionPane.showMessageDialog
(PasswordDialog.this,
SharpTools.translation.getProperty("Password_Incorrect")+" !" , SharpTools.translation.getProperty("Password"),
JOptionPane.ERROR_MESSAGE);
textField.setText(null);
textField.requestFocus();
return false;
}
else
return true;
}
//validate password
if (fieldsAreTheSame(textField.getPassword(),
confirmField.getPassword())) {
//compare the dialogs
return true;
} else {
// passwords dont match
textField.selectAll();
SharpOptionPane.showMessageDialog
(this,
SharpTools.translation.getProperty("Passwords_do_not_match_Please_try_again"),
SharpTools.translation.getProperty("Password"),
JOptionPane.ERROR_MESSAGE,
null);
typedText = null;
textField.setText(null);
confirmField.setText(null);
textField.requestFocus();
return false;
}
}
protected boolean onCancel() {
typedText = null;
return true;
}
protected void onOpen() {
// set the initial focus to textField
textField.requestFocus();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SharpCellEditor.java
0,0 → 1,86
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)SharpCellEditor.java
*
* $Id: SharpCellEditor.java,v 1.7 2000/12/02 21:44:52 rkc10 Exp $
*
* Created on October 27, 2000, 2:19 AM
*/
package SharpTools;
import javax.swing.*;
 
/** This is the only editor for the SharpTableModel because it is the only
* cell object editor. The only special feature is that it displays the
* formula string of a formula cell when cell is being edited. It inherits
* all methods of the DefaultCellEditor.
*
* @author Ricky Chin
* @version $Revision: 1.7 $
*/
public class SharpCellEditor extends DefaultCellEditor {
 
/** the JTextField object this editor uses
*/
private JTextField textField;
/**
* Creates new SharpCellEditor.
*
* @param textField a JtextField object
*/
public SharpCellEditor(final JTextField textField) {
super(textField);
this.textField = textField;
 
/* To account for formula feature only need
* to override the setValue method in EditorDelegate inner
* class.
*/
delegate = new EditorDelegate() {
public void setValue(Object value) {
if (value instanceof Cell) {
Cell temp = (Cell)value;
/* when editing formula cell
* a string representation is displayed
*/
if (temp.isFormula()) {
textField.setText("=" + temp.getFormula().toString());
}
else {
//otherwise it is just the normal string conversion
textField.setText(temp.getValue().toString());
}
}
else {
//empty cells display nothing
textField.setText((value == null) ? "" : value.toString());
}
 
}
 
public Object getCellEditorValue() {
return textField.getText();
}
};
textField.addActionListener(delegate);
}
 
/** get the component used by this editor
* @return the JTextField used by this editor
*/
public JTextField getTextField() { return textField; }
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/EditOp.java
0,0 → 1,451
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)EditOp.java
*
* $Id: EditOp.java,v 1.37 2001/06/03 22:20:47 huaz Exp $
*
* Created on November 19, 2000, 02:16:16 AM
*/
package SharpTools;
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
/**
* This contain certain higher level edit operations on the spreadsheet table
*
* @author Hua Zhong
* @version $Revision: 1.37 $
*/
 
 
 
public class EditOp implements ActionListener {
 
// these variables correspond to the variables in SharpTools
private SharpTools sharp;
private JTable table;
private SharpTableModel tableModel;
private History history;
private JToolBar toolBar;
private CellPoint copyPoint = new CellPoint(SharpTools.baseRow, SharpTools.baseCol);
// jm.evers
private Clipboard my_local_clipboard;
// used for Find and Find Next
// private String fillValue;
private String findValue;
private boolean matchCase = false;
private boolean matchCell = false;
final ImageIcon fillIcon=new ImageIcon(getClass().getResource("/images/fill32.gif"));
final ImageIcon findIcon=new ImageIcon(getClass().getResource("/images/find32.gif"));
//final private static ImageIcon fillIcon = SharpTools.getImageIcon("fill32.gif");
//final private static ImageIcon findIcon = SharpTools.getImageIcon("find32.gif");
/** constructor
*
* @param sharp the GUI object
*/
EditOp(SharpTools sharp) {
this.sharp = sharp;
table = sharp.getTable();
 
// Identifying the undo KeyStroke user can modify this
// to undo on some other Key combination.
KeyStroke undo = KeyStroke.getKeyStroke
(KeyEvent.VK_Z,ActionEvent.CTRL_MASK,false);
 
// Identifying the undo KeyStroke user can modify this
// to undo on some other Key combination.
KeyStroke redo = KeyStroke.getKeyStroke
(KeyEvent.VK_Y,ActionEvent.CTRL_MASK,false);
// Identifying the cut KeyStroke user can modify this
// to cut on some other Key combination.
KeyStroke cut = KeyStroke.getKeyStroke
(KeyEvent.VK_X,ActionEvent.CTRL_MASK,false);
// Identifying the copy KeyStroke user can modify this
// to copy on some other Key combination.
KeyStroke copy = KeyStroke.getKeyStroke
(KeyEvent.VK_C,ActionEvent.CTRL_MASK,false);
// Identifying the Paste KeyStroke user can modify this
// to copy on some other Key combination.
KeyStroke paste = KeyStroke.getKeyStroke
(KeyEvent.VK_V,ActionEvent.CTRL_MASK,false);
 
KeyStroke fill = KeyStroke.getKeyStroke
(KeyEvent.VK_L, ActionEvent.CTRL_MASK, false);
KeyStroke clear = KeyStroke.getKeyStroke
(KeyEvent.VK_DELETE, 0, false);
 
// Identifying the find/findnext KeyStroke user can modify this
// to find on some other Key combination.
KeyStroke find = KeyStroke.getKeyStroke
(KeyEvent.VK_F,ActionEvent.CTRL_MASK,false);
KeyStroke findnext = KeyStroke.getKeyStroke
(KeyEvent.VK_F3,0,false);
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Undo"), undo,
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Redo"), redo,
JComponent.WHEN_FOCUSED);
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Cut"), cut,
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Copy"), copy,
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Paste"),paste,
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Fill"),fill,
JComponent.WHEN_FOCUSED);
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Clear"),clear,
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Find"),find,
JComponent.WHEN_FOCUSED);
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Find_Next"),findnext,
JComponent.WHEN_FOCUSED);
 
 
init(sharp);
}
 
/**
* init method.
* The reason to have this is to reset the EditOp but keep
* the findValue and clipboard.
*
* @param sharp the GUI object
*/
public void init(SharpTools sharp) {
tableModel = sharp.getTableModel();
history = sharp.getHistory();
}
/**
* Perfroms a clipboard function of cutting COPY + CLEAR
*
* @param clipboard the SharpClipboard object
*/
public void cut(){
doCopy(true); //sets isCut to true
}
 
/**
* Perfroms a clipboard function of cutting COPY + CLEAR
*/
public void copy() {
doCopy(false); //sets isCut to false
}
/**
* Performs a clipboard function of cut/copy
*
* @param isCut true for cut, false for copy
*/
private void doCopy(boolean isCut) {
if (table.getSelectedRowCount() != 0) {
CellRange range = new CellRange(
table.getSelectedRows(), table.getSelectedColumns());
 
if (isCut) {
history.add(tableModel, range);
}
 
// toolBar.getComponent(8).setEnabled(true);
// now do the copy operation
StringBuffer sbf=new StringBuffer();
 
int startRow = table.getSelectedRow();
int startCol = table.getSelectedColumn();
int numrows=table.getSelectedRowCount();
int numcols=table.getSelectedColumnCount();
copyPoint = new CellPoint(table.getSelectedRow(),
table.getSelectedColumn());
 
String str = tableModel.toString(range, false);
StringSelection stsel = new StringSelection(str);
//jm.evers using a local clipboard to avoid jar-signing
//Clipboard clipboard = new Clipboard ("name").
my_local_clipboard = new Clipboard("my_local_clipboard");
my_local_clipboard.setContents(stsel,stsel);
 
if (isCut)
tableModel.clearRange(range);
} else {
if (isCut) {
sharp.noCellsSelected(SharpTools.translation.getProperty("Cut"));
}else {
sharp.noCellsSelected(SharpTools.translation.getProperty("Copy"));
}
}
}
 
/**
* Performs a clipboard function of pasting
*/
public void paste(){
//checks if anything is selected
if (table.getSelectedRowCount() != 0) {
int startRow=table.getSelectedRow();
int startCol=table.getSelectedColumn();
int rowOff = startRow-copyPoint.getRow();
int colOff = startCol-copyPoint.getCol();
try {
String trstring=
(String)(my_local_clipboard.getContents(this).
getTransferData(DataFlavor.stringFlavor));
 
CellPoint size = SharpTableModel.getSize(trstring);
int endRow = Math.min(table.getRowCount()-1,
startRow+size.getRow()-1);
int endCol = Math.min(table.getColumnCount()-1,
startCol+size.getCol()-1);
 
CellRange affectedRange = new CellRange(startRow, endRow,
startCol, endCol);
// add to history
history.add(tableModel, affectedRange);
// System.out.println(affectedRange);
tableModel.fromString(trstring, rowOff, colOff, affectedRange);
}
catch(Exception e){
System.out.println(e.toString());
}
} else {
sharp.noCellsSelected(SharpTools.translation.getProperty("Paste"));
}
}
/**
* Wrapper function to clear cell and range of cells....
*/
public void clear() {
//checks if anything is selected
if (table.getSelectedRowCount() != 0) {
CellRange range = new CellRange(
table.getSelectedRows(), table.getSelectedColumns());
history.add(tableModel, range);
Debug.println("Clear");
tableModel.clearRange(range);
} else {
sharp.noCellsSelected(SharpTools.translation.getProperty("Clear"));
}
}
 
 
/**
* Wrapper function to fill a range of cell with a user defined value
*/
public void fill() {
//checks if anything is selected
if (table.getSelectedRowCount() != 0) {
CellRange range = new CellRange(
table.getSelectedRows(), table.getSelectedColumns());
 
Cell first = tableModel.getCellAt(range.getStartRow(),
range.getStartCol());
String fillValue = null;
if (first.isFormula())
fillValue = "="+first.getFormula().toString();
else
fillValue = first.getValue().toString();
Object inputValue =
SharpOptionPane.showInputDialog
(sharp, SharpTools.translation.getProperty("Please_enter_a_value_to_fill_the_range"),
SharpTools.translation.getProperty("Fill"), JOptionPane.INFORMATION_MESSAGE,
fillIcon, null, fillValue);
 
//if input is cancelled or nothing is entered
//then don't change anything
if (inputValue != null){
if (((String)inputValue).length() != 0) {
history.add(tableModel, range);
tableModel.fillRange(range, (String)inputValue);
// fillValue = inputValue;
}
}
}else {
sharp.noCellsSelected(SharpTools.translation.getProperty("Fill"));
}
}
 
/**
* Wrapper function to fill a range of cell with a user defined value
*
* @param newValue is true if it should require a new value (Find...)
* is false if it already has a value (Find Next)
*/
public void find(boolean newValue) {
CellPoint start;
//checks if anything is selected
 
if (table.getSelectedRowCount() != 0) {
int x = table.getSelectedRow();
int y = table.getSelectedColumn();
// start from the next cell
if (!newValue)
if (y < table.getColumnCount()-1)
y++;
else {
y = 1;
x++;
}
start = new CellPoint(x, y);
}
else {
// or start from the beginning
start = new CellPoint(SharpTools.baseRow, SharpTools.baseCol);
}
 
if (newValue) {
// ask for new value
//String inputValue = SharpOptionPane.showInputDialog
//(sharp, "Find: ", "Find", findIcon, findValue, 10);
FindDialog findDialog = new FindDialog(sharp, findValue, matchCase, matchCell);
findDialog.pack();
findDialog.setLocationRelativeTo(sharp);
findDialog.setVisible(true);
 
String inputValue = findDialog.getString();
/*
matchCase = findDialog.isCaseSensitive();
matchCell = findDialog.isCellMatching();
 
Debug.println("case sens : " + findDialog.isCaseSensitive());
Debug.println("match cell : " + findDialog.isCellMatching());
*/
//if input is cancelled or nothing is entered
//then don't change anything
if (inputValue == null || inputValue.length() == 0)
return;
else {
setFindValue(inputValue);
matchCase = findDialog.isCaseSensitive();
matchCell = findDialog.isCellMatching();
 
Debug.println("case sens : " + findDialog.isCaseSensitive());
Debug.println("match cell : " + findDialog.isCellMatching());
}
}
else if (!hasFindValue())
return;
 
CellPoint found = tableModel.look(start, SharpTableModel.fieldParser(findValue), matchCase, matchCell);
if (found != null) {
//System.out.println(found);
table.setColumnSelectionInterval(found.getCol(),
found.getCol());
table.setRowSelectionInterval(found.getRow(),
found.getRow());
// set it visible
table.scrollRectToVisible
(new Rectangle
(table.getCellRect(found.getRow(), found.getCol(), true)));
}
else {
SharpOptionPane.showMessageDialog
(sharp,
SharpTools.translation.getProperty("SharpTools_has_finished_the_search") + " : "+ findValue ,
SharpTools.translation.getProperty("Find_Completed"),
JOptionPane.INFORMATION_MESSAGE, findIcon);
}
}
 
/**
* Whether a value has been searched by the user
*
* @return true if the findValue has been set
*/
public boolean hasFindValue() {
return findValue != null && findValue.length() != 0;
}
 
private void setFindValue(String s) {
findValue = s;
sharp.checkFindNextState();
}
/**
* Whether the clipboard has data
*
* @return true if clipboard has been set
*/
/*
public boolean hasClipboard() {
return
}
*/
/**
* This method is activated on the Keystrokes we are listening to
* in this implementation. Here it listens for keystroke
* ActionCommands.
*
* Without this listener, when we press certain keys the individual
* cell will be activated into editing mode in addition to the
* effect of the key accelerators we defined with menu items.
* With this key listener, we avoid this side effect.
*/
public void actionPerformed(ActionEvent e) {
 
if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Undo"))==0) {
history.undo(tableModel);
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Redo"))==0) {
history.redo(tableModel);
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Cut"))==0) {
cut();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Copy"))==0) {
copy();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Paste"))==0) {
paste();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Fill"))==0) {
fill();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Find"))==0) {
find(true);
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Find_Next"))==0) {
find(false);
}
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/Node.java
0,0 → 1,312
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)Node.java
*
* $Id: Node.java,v 1.28 2002/08/08 05:15:06 huaz Exp $
*
* Created on October 18, 2000, 3:27 PM
*/
package SharpTools;
import java.io.*;
import java.util.*;
 
/**
* Node is basic unit for Formula processing.
* <p>
* It can be one of the following:
* <ol>
* <li>Relative Address (LETTERS+numbers: A1)</li>
* <li>Absolute Address ($LETTERS$numbers: $A$1)</li>
* <li>Function (LETTERS)</li>
* <li>Left Parenthese</li>
* <li>Right Parenthese</li>
* <li>Number (a float number)</li>
* <li>Operator (+ - * / % ^)</li>
* <li>Comma (separating parameters)</li>
* <li>Colon (used in range addresses: A1:C6)</li>
* </ol>
*
* @see Formula
*
* @author Hua Zhong <huaz@cs.columbia.edu>
* @version $Revision: 1.28 $
*/
public class Node {
public static final int DEFAULT = 0; // reserved
public static final int REL_ADDR = 1; // LETTERS+numbers: A1
public static final int ABS_ADDR = 2; // $LETTERS$numbers: $A$1
public static final int FUNCTION = 3; // LETTERS: SUM
public static final int LPAREN = 4; // (
public static final int RPAREN = 5; // )
public static final int NUMBER = 6; // all numbers and has .: 0.5
public static final int OPERATOR = 7; // + - * / ^
public static final int COMMA = 8; // ,
public static final int COLON = 9; // :
public static final int EXP = 10; // an expression. the exp field counts.
// for each function param, its type is EXP
private static final String[] desc = {
"Default", "Rel_Addr", "Abs_Addr", "Function",
"LBracket", "RBracket", "Number", "Operator",
"Comma", "Colon", "Param" };
 
private int type; // which type the node is (see above 10 types)
private String data; // the raw data
private float number; // the numeric value
private int row;
private int col;
 
private LinkedList exp; // a LinkedList for a function's params
 
/*
* Used for Function address range parameter (ADDR1:ADDR2)
* An address range is ultimately represented as follows:
*
* node type: COLON
* node.nextRange points to the start address (a node of REL_ADDR or
* ABS_ADDR), the start address' nextRange points to the end address.
*/
private Node nextRange;
 
private boolean pending; // used for processing functions, see Formula
/**
* This is an empty node constructor
*/
Node() {
}
 
/**
* Node constructor
*
* @param node
*/
Node(Node node) {
type = node.type;
if (data != null)
data = new String(node.data);
number = node.number;
row = node.row;
col = node.col;
}
 
/** get/set functions */
public int getType() { return type; }
public boolean isType(int type) { return this.type == type; }
public float getNumber() { return number; }
public String getData() { return data; }
public LinkedList getParams() { return exp; }
public Node getNextRange() { return nextRange; }
public LinkedList getExp() { return exp; }
public int getRow() { return row; }
public int getCol() { return col; }
public void setType(int type) { this.type = type; }
public void setNumber(float number) { this.number = number; }
 
public void setData(String data) { this.data = data; }
public void appendData(char data) { this.data += data; }
public void appendData(String data) { this.data += data; }
public void setParams(LinkedList list) { exp = list; }
public void addParam(Node node) {
if (node.getExp().size()>0)
exp.add(node);
}
public void setNextRange(Node node) { nextRange = node; }
public void setExp(LinkedList exp) { this.exp = exp; }
 
public void setPending(boolean pending) { this.pending = pending; }
public boolean isPending() { return pending; }
 
public void setRow(int row) { this.row = row; }
public void setCol(int col) { this.col = col; }
 
public boolean hasValue() {
return (type == Node.NUMBER || type == Node.REL_ADDR ||
type == Node.ABS_ADDR || type == Node.FUNCTION ||
type == Node.RPAREN);
}
/**
* This string funciton is for debug purpose only.
* Node -> String
*/
public String toString() {
// return String.valueOf(type);
 
switch (type) {
case Node.NUMBER:
return Float.toString(number);
case Node.REL_ADDR:
StringBuffer buf1 = new StringBuffer();
buf1.append('(');
buf1.append(String.valueOf(col));
buf1.append(',');
buf1.append(row);
buf1.append(')');
return buf1.toString();
case Node.ABS_ADDR:
StringBuffer buf2 = new StringBuffer();
buf2.append('$');
buf2.append(translateColumn(col));
buf2.append('$');
buf2.append(translateRow(row));
return buf2.toString();
case Node.FUNCTION:
return data+exp.toString();
case Node.EXP:
return exp.toString();
case Node.LPAREN:
return "(";
case Node.RPAREN:
return ")";
case Node.COMMA:
return ",";
case Node.COLON:
return nextRange.toString()+":"+nextRange.nextRange.toString();
default:
return data;
}
 
}
 
/**
* This translates the string form of row into row number ('12' -> 12).
*
* @param row the string value of the row to be converted
* @return the int value of the row
*/
public static int translateRow(String row) {
int r = Integer.parseInt(row);
return r + SharpTools.baseRow - 1;
}
 
/**
* This translates the int value of row into a string (12 -> '12').
*
* @param row the int value of the row to be converted
* @return the string value of the row
*/
public static String translateRow(int row) {
if (row < 0)
return null;
else
return String.valueOf(row+1-SharpTools.baseRow);
}
 
/**
* This translates the string form of column into column number ('A' -> 1)
*
* @param column the string value of the column to be converted
* @return the int value of the column
*/
public static int translateColumn(String column) {
int col = 0;
 
for (int i = 0; i < column.length(); i++) {
col = col * 26 + (column.charAt(i) - 'A' + 1);
}
 
return col + SharpTools.baseCol -1;
}
 
/**
* This translates the int form of column into column string (1 -> 'A')
*
* @param column the int value of the column to be converted
* @return the string value of the column
*/
public static String translateColumn(int column) {
 
column = column - SharpTools.baseCol +1;
if (column < 1)
return null;
 
StringBuffer buf = new StringBuffer();
int div = 1;
 
while (div > 0) {
div = (column-1)/26;
buf.insert(0, (char)('A'+(column-1 - div*26)));
column = div;
}
return buf.toString();
}
 
/**
* Node -> CellPoint
*/
public CellPoint toCellPoint(int row, int col) {
if (isType(Node.REL_ADDR))
return new CellPoint(getRow()+row, getCol()+col);
else
return new CellPoint(getRow(), getCol());
}
 
private static int min(int m, int n) {
return m<n ? m:n;
}
 
private static int max(int m, int n) {
return m>n ? m:n;
}
/**
* Given one Node, this returns two CellPoints that identify the
* upleft and downright cells.
*
* row and col matter because relative addresses need them.
*
* @param row the int value fo the row
* @param col the int value of the column
* @return two CellPoint value for the range
*/
public CellPoint[] getAddressRange(int row, int col) {
 
CellPoint[] addr = new CellPoint[2];
if (isType(Node.COLON)) {
// if it's an address range
// get the start address
CellPoint addr1 = getNextRange().toCellPoint(row, col);
// get the end address
CellPoint addr2 = getNextRange().getNextRange().
toCellPoint(row, col);
 
addr[0] = new CellPoint(
min(addr1.getRow(), addr2.getRow()),
min(addr1.getCol(), addr2.getCol())
);
addr[1] = new CellPoint(
max(addr1.getRow(), addr2.getRow()),
max(addr1.getCol(), addr2.getCol())
);
}
else {
// otherwise it's a normal address
CellPoint cell = toCellPoint(row, col);
addr[0] = cell;
addr[1] = cell;
}
return addr;
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/TableOp.java
0,0 → 1,358
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)TableOp.java
*
* $Id: TableOp.java,v 1.40 2002/08/08 05:15:09 huaz Exp $
*
* Created on November 5, 2000, 11:21 PM
*/
package SharpTools;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
 
/**
* This contain certain higher level operations on the spreadsheet table
* such as sorting.
*
* @author Ricky Chin
* @version $Revision: 1.40 $
*/
public class TableOp implements ActionListener {
// these variables correspond to the variables in SharpTools
private SharpTools sharp;
public SharpOptionPane sharpoptionpane;
private JTable table;
private SharpTableModel tableModel;
private History history;
private JToolBar toolBar;
final ImageIcon colwidthIcon=new ImageIcon(getClass().getResource("/images/colwidth.gif"));
// constructor
TableOp(SharpTools sharp) {
init(sharp);
sharp.checkFindNextState();
// Identifying the Insert/Delete KeyStroke user can modify this
// to some other Key combination.
 
KeyStroke insertrow = KeyStroke.getKeyStroke
(KeyEvent.VK_INSERT,
ActionEvent.CTRL_MASK,
false);
 
KeyStroke insertcolumn = KeyStroke.getKeyStroke
(KeyEvent.VK_INSERT,
ActionEvent.CTRL_MASK|ActionEvent.SHIFT_MASK,
false);
 
KeyStroke deleterow = KeyStroke.getKeyStroke
(KeyEvent.VK_DELETE,
ActionEvent.CTRL_MASK,
false);
 
KeyStroke deletecolumn = KeyStroke.getKeyStroke
(KeyEvent.VK_DELETE,
ActionEvent.CTRL_MASK|ActionEvent.SHIFT_MASK,
false);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Insert_Row"),insertrow,
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Insert_Column"),insertcolumn,
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Delete_Row"),deleterow,
JComponent.WHEN_FOCUSED);
 
table.registerKeyboardAction(this,SharpTools.translation.getProperty("Delete_Column"),deletecolumn,
JComponent.WHEN_FOCUSED);
}
 
/**
* init method.
*
* @param sharp the GUI object
*/
private void init(SharpTools sharp) {
this.sharp = sharp;
table = sharp.getTable();
tableModel = sharp.getTableModel();
history = sharp.getHistory();
toolBar = sharp.getToolBar();
}
/* insert a row or column */
public void insert(boolean byRow) {
//checks if anything is selected
int insertNum = table.getSelectedRowCount();
if (insertNum != 0) {
if (byRow) {
int row = table.getSelectedRow();
CellRange range =
new CellRange(new CellPoint(row, SharpTools.baseCol),
new CellPoint(row+insertNum-1,
tableModel.getColumnCount()-1));
history.add(tableModel, range, History.INSERTROW);
tableModel.insertRow(range);
}
else {
insertNum = table.getSelectedColumnCount();
int column = table.getSelectedColumn();
CellRange range =
new CellRange(new CellPoint(SharpTools.baseRow, column),
new CellPoint(tableModel.getRowCount()-1,
column+insertNum-1));
 
history.add(tableModel, range, History.INSERTCOLUMN);
tableModel.insertColumn(range);
}
}else {
sharp.noCellsSelected("Insert");
}
}
 
public void remove(boolean byRow) {
int removeNum = table.getSelectedRowCount();
//checks if anything is selected
if (removeNum != 0) {
 
if (byRow) {
 
if (removeNum == table.getRowCount()-1) {
tooMuchDeletion();
return;
}
int row = table.getSelectedRow();
CellRange range =
new CellRange(new CellPoint(row, SharpTools.baseCol),
new CellPoint(row+removeNum-1,
tableModel.getColumnCount()-1));
 
if (tableModel.isDeletionSafe(range, true) || unsafeDeletion()) {
history.add(tableModel, range, History.REMOVEROW);
Debug.println(range);
tableModel.removeRow(range);
Debug.println("Delete row range "+range);
}
}
else {
int column = table.getSelectedColumn();
 
removeNum = table.getSelectedColumnCount();
 
if (removeNum == table.getColumnCount()-1) {
tooMuchDeletion();
return;
}
CellRange range =
new CellRange(new CellPoint(SharpTools.baseRow, column),
new CellPoint(tableModel.getRowCount()-1,
column+removeNum-1));
Debug.println("Delete column range "+range);
if (tableModel.isDeletionSafe(range, false) || unsafeDeletion()) {
history.add(tableModel, range, History.REMOVECOLUMN);
Debug.println(range);
tableModel.removeColumn(range);
}
}
}else {
sharp.noCellsSelected(SharpTools.translation.getProperty("Remove"));
}
}
public void sort(boolean byRow) {
//checks if anything is selected
if (table.getSelectedRowCount() != 0) {
CellRange range = new CellRange
(table.getSelectedRows(), table.getSelectedColumns());
 
//gets parameters for combo box in dialog
Vector primary = new Vector();
Vector secondary = new Vector();
secondary.add("None");
if (byRow) {
for(int i = range.getStartRow(); i <= range.getEndRow(); i++) {
primary.add(SharpTools.translation.getProperty("Row")+" "+ Node.translateRow(i));
secondary.add(SharpTools.translation.getProperty("Row")+" "+ Node.translateRow(i));
}
}else {
for(int i = range.getStartCol(); i <= range.getEndCol(); i++) {
primary.add(SharpTools.translation.getProperty("Column")+" "+ Node.translateColumn(i));
secondary.add(SharpTools.translation.getProperty("Column")+" "+ Node.translateColumn(i));
}
}
 
//create and show the sort dialog
SortDialog sortDialog = new SortDialog(sharp, primary, secondary);
sortDialog.pack();
sortDialog.setLocationRelativeTo(sharp);
sortDialog.setVisible(true);
Debug.println("Here we go " + sortDialog.getCriteriaA() + ": And : " + sortDialog.getCriteriaB());
Debug.println(sortDialog.firstAscending() + " : " + sortDialog.secondAscending());
int first = sortDialog.getCriteriaA();
//check to see if there is sorting criteria
if (first >= 0) {
history.add(tableModel, range);
//translate first to col/row number
if (byRow) {
first += range.getStartRow();
}else {
first += range.getStartCol();
}
 
int second = sortDialog.getCriteriaB();
//check to see if there is second sorting criteria
if (second > 0) {
//translate second to col/row number
if (byRow) {
//takes into account "none" choice
second += range.getStartRow() - 1;
}else {
second += range.getStartCol() - 1;
}
 
tableModel.sort(range, first, second, byRow,
sortDialog.firstAscending(),
sortDialog.secondAscending());
}else {
//sort according to first only
tableModel.sort(range, first, first, byRow,
sortDialog.firstAscending(),
sortDialog.secondAscending());
}
}
} else {
sharp.noCellsSelected(SharpTools.translation.getProperty("Sort"));
}
}
 
// set the column width
public void setColumnWidth() {
int width;
if(!SharpTools.inapplet){
width = SharpTools.getConfig().getInt("COLUMNWIDTH");
}
else
{
width = MainApplet.COLUMNWIDTH;
}
String inValue = JOptionPane.showInputDialog(SharpTools.translation.getProperty("Default_width")+"\n"+SharpTools.translation.getProperty("rem1")+":");
//System.out.println("ingetiept:"+inValue);
if (inValue != null) {
try {
int newwidth = Integer.parseInt(inValue,10);
if (newwidth != width && newwidth>=0) {
if(!SharpTools.inapplet){
SharpTools.getConfig().setInt("COLUMNWIDTH", newwidth);
}
sharp.setColumnWidth(newwidth);
}
}
catch (Exception e) {
}
}
}
 
public void setFirstColumnWidth() {
int width;
if(!SharpTools.inapplet){
width = SharpTools.getConfig().getInt("FIRSTCOLUMNWIDTH");
}
else
{
width = MainApplet.FIRSTCOLUMNWIDTH;
}
String inValue = JOptionPane.showInputDialog(SharpTools.translation.getProperty("Default_width")+"\n"+SharpTools.translation.getProperty("rem2")+":");
//System.out.println("ingetiept:"+inValue);
if (inValue != null) {
try {
int newwidth = Integer.parseInt(inValue,10);
if (newwidth != width && newwidth>=0) {
if(!SharpTools.inapplet){
SharpTools.getConfig().setInt("FIRSTCOLUMNWIDTH", newwidth);
}
sharp.setBaseColumnWidth(newwidth);
}
}
catch (Exception e) {
}
}
}
public int getColumnWidth(){
int width=0;
return width;
}
private boolean unsafeDeletion() {
int choice = sharpoptionpane.showOptionDialog(
sharp,
SharpTools.translation.getProperty("rem4") +"\n"+SharpTools.translation.getProperty("rem3")+"\n\n",
SharpTools.translation.getProperty("Delete"),
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
1
);
 
return choice == JOptionPane.YES_OPTION;
}
 
private void tooMuchDeletion() {
sharpoptionpane.showMessageDialog
(sharp, SharpTools.translation.getProperty("rem5"),SharpTools.translation.getProperty("Delete"),
JOptionPane.ERROR_MESSAGE);
}
 
/**
* This method is activated on the Keystrokes we are listening to
* in this implementation. Here it listens for keystroke
* ActionCommands.
*
* Without this listener, when we press certain keys the individual
* cell will be activated into editing mode in addition to the
* effect of the key accelerators we defined with menu items.
* With this key listener, we avoid this side effect.
*/
public void actionPerformed(ActionEvent e) {
 
if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Insert_Row"))==0) {
insert(true);
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Insert_Column"))==0) {
insert(false);
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Delete_Row"))==0) {
remove(true);
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Delete_Column"))==0) {
remove(false);
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/Debug.java
0,0 → 1,36
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* This is a class used for print out debug information and can be
* easily turned on/off.
*/
package SharpTools;
import java.io.*;
 
public class Debug {
 
static private boolean debug = false;
static void setDebug(boolean flag) {
debug = flag;
}
static boolean isDebug() {
return debug;
}
static void println(Object s) {
if (debug)
System.out.println(s.toString());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/CellPoint.java
0,0 → 1,144
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)CellPoint.java
*
* $Id: CellPoint.java,v 1.13 2000/12/02 21:44:53 rkc10 Exp $
*
* Created on October 22, 2000, 4:54 PM
*/
 
/** This is an object the represents the coordinates of a cell
* in the table. It is used as entries in the reference list
* of each cell. In addition, it is sometimes used as parameters
* of table manipulation methods. CellPoints are better parameters
* because there is no worry that someone will switch the order of
* parameters (ie. type column first and then row instead of the
* other way around).
* @author Ricky Chin
* @version $Revision: 1.13 $
*/
package SharpTools;
 
public class CellPoint implements Comparable {
/** This hold row coordinate of a cell */
private int row;
 
/** This holds column coordinate of a cell */
private int col;
 
/**
* Creates a new CellPoint.
*
* @param aRow row of a cell
* @param aCol column of a cell
*/
public CellPoint(int aRow, int aCol) {
row = aRow;
col = aCol;
}
/**
* Gets the row of cell referenced by this CellPoint.
*
* @return row value
*/
public int getRow() { return row; }
/** gets the column coordinate of cell reference stored.
* @return column value
*/
public int getCol() { return col; }
 
/**
* Sets the row coordinate of cell reference to be stored.
*
* @param row value to set row to
*/
public void setRow(int row) { this.row = row; }
/**
* Sets column coordinate.
*
* @param col value to set column coordinate to
*/
public void setCol(int col) { this.col = col; }
/** Increments row coordinate.
* @param x amount to increment row coordinate by
*/
public void incrRow(int x) { this.row += x; }
/** Increments column coordinate
* @param x amount to increment column coordinate
*/
public void incrCol(int x) { this.col += x; }
/**
* Compares CellPoints by row and then by column field. It is used by the
* reference list to maintain itself.
*
* @param x CellPoint to be compares
* @return 1 if greater, 0 if equal and -1 if > x
*/
public int compareTo(Object x) {
if (x instanceof CellPoint) {
CellPoint y = (CellPoint)x;
//by row
if (this.row > y.row) {
return 1;
}else {
if (this.row == y.row) {
//by column
if (this.col > y.col) {
return 1;
}else {
//equal
if (this.col == y.col) {
return 0;
}else return -1;
}
}else {
return -1;
}
}
}else return 2; /* can't compare non-CellPoint objects */
}
/**
* Two CellPoints are equal if all the fields are equal.
* Useful for updating the reference list.
*
* @param x CellPoint to compare this to
* @return true iff all fields equal
*/
public boolean equals(Object x) {
if (x instanceof CellPoint) {
CellPoint y = (CellPoint)x;
return ((this.row == y.row) && (this.col == y.col));
}else return false;
}
 
/**
* Converts the object to a string representation
*
* @return a string representation of CellPoint
*/
public String toString() {
return Node.translateColumn(col)+Node.translateRow(row);
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/MainApplet.java
0,0 → 1,268
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
trying to produce an applet from a opensource spreadsheet java application.
 
<applet id="SharpTools" archive="dist/SharpTools.jar" code="SharpTools/MainApplet" width="120" height="30">
<param name="language" value="nl">
<param name="X_screen_location" value="100"><!-- default 0-->
<param name="Y_screen_location" value="100"><!-- default 0-->
<param name="window_width" value="700">
<param name="window_height" value="400">
<param name="replyurl" value="http://localhost/wims/wims.cgi?module=$module&session=$sssion&reply$n=">
<param name="reply_type" value="1">
<!-- 0 = matrix ["1","2","3";"a","b","c"] note: "" string protection for pari evaluation -->
<!-- 1 = csv 1,2,3 \n a,b,c note : no string protection -->
<!-- 2 = tsv 1 \t 2 \t 3 \n a \t b \t c note : no string protection -->
<param name="convert_initial_tsv_to_matrix" value="true">
<!-- append (to the reply) a line with the given/initial tsv-flie as a set in parameter "reply_type" -->
<param name="file" value="test.csv">
<!-- if a template tsv is needed for the exercise-->
<param name="fontsize" value="16">
<param name="empty_cell" value="null">
<!-- fill the empty cells with a String : default null -->
<!-- sizes in pixels these are not really needed, defaults are fine -->
<param name="COLUMNWIDTH" value="80">
<param name="FIRSTCOLUMNWIDTH" value="40">
<param name="HISTOGRAMWIDTH" value="400">
<param name="HISTOGRAMHEIGHT" value="400">
<!-- configuring the menu & toolbar -->
<!-- accepted value's like caseinsensitive : TRUE , 0 , NO , NEE , NON -->
<!-- all other value will result in FALSE -->
<param name="COLUMNS" value="5">
<param name="ROWS" value="5">
<param name="TOOLBAR_NEW" value="false">
<param name="TOOLBAR_PRINT" value="false">
<param name="TOOLBAR_UNDO" value="true">
<param name="TOOLBAR_REDO" value="true">
<param name="TOOLBAR_CUT" value="true">
<param name="TOOLBAR_COPY" value="true">
<param name="TOOLBAR_PASTE" value="true">
<param name="TOOLBAR_FIND" value="true">
<param name="TOOLBAR_INSERTROW" value="true">
<param name="TOOLBAR_INSERTCOLUMN" value="true">
<param name="TOOLBAR_DELETEROW" value="true">
<param name="TOOLBAR_DELETECOLUMN" value="true">
<param name="TOOLBAR_SORTCOLUMN" value="true">
<param name="TOOLBAR_HISTOGRAM" value="true">
<param name="TOOLBAR_HELP" value="true">
<param name="TOOLBAR_FUNCTIONS" value="true">
</applet>
*/
 
package SharpTools;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.net.*;
import java.applet.AppletContext;
 
 
public class MainApplet extends JApplet {
SharpTools sharptools;
public static String spreadsheet_from_url;
public static String empty_cell;
public static String initial_tsv_matrix;
public static boolean found_spreadsheet_from_url=false;
public static boolean inapplet=true;
public static boolean convert_initial_tsv_to_matrix;
// instead of a configfile, a tunable paramlist;
public static int type,fontsize,RECENTFILELIST=8,NUMCONNECTIONS=5,ROWS,COLUMNS,FIRSTCOLUMNWIDTH,COLUMNWIDTH,Xlocation,Ylocation,window_width,window_height,HISTOGRAMWIDTH,HISTOGRAMHEIGHT;
public static boolean SAVEWINDOW,TOOLBAR_NEW,TOOLBAR_OPEN,TOOLBAR_SAVE,TOOLBAR_PASSWORD,TOOLBAR_PRINT,TOOLBAR_UNDO;
public static boolean TOOLBAR_REDO,TOOLBAR_CUT,TOOLBAR_COPY,TOOLBAR_PASTE,TOOLBAR_FIND,TOOLBAR_INSERTROW,TOOLBAR_INSERTCOLUMN;
public static boolean TOOLBAR_DELETEROW,TOOLBAR_DELETECOLUMN,TOOLBAR_SORTCOLUMN,TOOLBAR_HISTOGRAM,TOOLBAR_HELP,TOOLBAR_FUNCTIONS;
public static String CONNECTION1NAME="",CONNECTION1USERNAME="",CONNECTION1PASSWORD="",CONNECTION1URL="",CONNECTION1DRIVER="";
public static String RECENTFILE0="",RECENTFILE1="",RECENTFILE2="",RECENTFILE3="",RECENTFILE4="",RECENTFILE5="",RECENTFILE6="",RECENTFILE7="";
public static String language="en",nee="no",ja ="yes";
static Font defaultFont;
public static URL backurl;
public static String reply_url;
private Container container;
private JButton OpenButton;
private JButton CloseButton;
ImageIcon OpenIcon=new ImageIcon(getClass().getResource("/images/start.gif"));
ImageIcon CloseIcon=new ImageIcon(getClass().getResource("/images/close.gif"));
String Tooltip_open="Open spreadsheet";
String Tooltip_close="Close spreadsheet";
public static AppletContext applet_context;
public void init(){
applet_context = this.getAppletContext();
container = this.getContentPane();
container.setLayout(new BorderLayout());
OpenButton = new JButton(OpenIcon);
OpenButton.setToolTipText(Tooltip_open);
CloseButton = new JButton(CloseIcon);
CloseButton.setToolTipText(Tooltip_close);
String c;
c=getParameter("empty_cell");
if(c!=null && c.length()>0){empty_cell = c;}else{empty_cell = "null";}
c=getParameter("replyurl");
if(c!=null && c.length()>0){reply_url = c;}
 
c=getParameter("language");
if(c.equalsIgnoreCase("de") || c.equalsIgnoreCase("nl") || c.equalsIgnoreCase("fr") ){
language=c.toLowerCase();
if(language.equals("nl")){ nee = "nee"; ja = "ja";}
else
if(language.equals("fr")){ nee = "non"; ja = "oui";}
else
if(language.equals("de")){ nee = "nein"; ja = "ja";}
}else{language="en";}
type = getIntParameter ("reply_type",1);
convert_initial_tsv_to_matrix= getBoolParameter("convert_initial_tsv_to_matrix",false);
TOOLBAR_NEW = getBoolParameter("TOOLBAR_NEW",false);
TOOLBAR_PRINT = getBoolParameter("TOOLBAR_PRINT",true);
TOOLBAR_UNDO = getBoolParameter("TOOLBAR_UNDO",true);
TOOLBAR_REDO = getBoolParameter("TOOLBAR_REDO",true);
TOOLBAR_CUT = getBoolParameter("TOOLBAR_CUT",true);
TOOLBAR_COPY = getBoolParameter("TOOLBAR_COPY",true);
TOOLBAR_PASTE = getBoolParameter("TOOLBAR_PASTE",true);
TOOLBAR_FIND = getBoolParameter("TOOLBAR_FIND",true);
TOOLBAR_INSERTROW = getBoolParameter("TOOLBAR_INSERTROW",true);
TOOLBAR_INSERTCOLUMN = getBoolParameter("TOOLBAR_INSERTCOLUMN",true);
TOOLBAR_DELETEROW = getBoolParameter("TOOLBAR_DELETEROW",true);
TOOLBAR_DELETECOLUMN = getBoolParameter("TOOLBAR_DELETECOLUMN",true);
TOOLBAR_SORTCOLUMN = getBoolParameter("TOOLBAR_SORTCOLUMN",true);
TOOLBAR_HISTOGRAM = getBoolParameter("TOOLBAR_HISTOGRAM",true);
TOOLBAR_HELP = getBoolParameter("TOOLBAR_HELP",true);
TOOLBAR_FUNCTIONS = getBoolParameter("TOOLBAR_FUNCTIONS",true);
COLUMNS= getIntParameter ("COLUMNS",10);
ROWS = getIntParameter ("ROWS",10);
COLUMNWIDTH = getIntParameter ("COLUMNWIDTH",80);
FIRSTCOLUMNWIDTH = getIntParameter ("FIRSTCOLUMNWIDTH",25);
Xlocation = getIntParameter ("X_screen_location",0);
Ylocation = getIntParameter ("Y_screen_location",0);
window_width = getIntParameter ("window_width",800);
window_height = getIntParameter ("window_height",600);
fontsize = getIntParameter ("fontsize",14);
defaultFont = new Font( "Courier", Font.PLAIN, fontsize);
HISTOGRAMWIDTH = getIntParameter ("HISTOGRAMWIDTH",480);
HISTOGRAMHEIGHT = getIntParameter ("HISTOGRAMHEIGHT",360);
 
sharptools=new SharpTools(inapplet,language);
sharptools.setVisible(false);
try_to_open_wims_spreadsheet("file");
container.add(OpenButton,BorderLayout.EAST);
container.add(CloseButton,BorderLayout.WEST);
container.validate();
OpenButton.addActionListener (new ActionListener(){
public void actionPerformed (ActionEvent evt){
ShowSpreadSheet(true);
}
}
);
CloseButton.addActionListener (new ActionListener(){
public void actionPerformed (ActionEvent evt){
ShowSpreadSheet(false);
}
}
);
repaint(1000);
}
public boolean getBoolParameter(String S,boolean def){
String s = getParameter(S);
if( s != null && s.length()>0){
if(s.equals("0") || s.equalsIgnoreCase("false") || s.equalsIgnoreCase(nee) ){return false;}
if(s.equals("1") || s.equalsIgnoreCase("true") || s.equalsIgnoreCase(ja) ){return true;}
}
return def;
}
public int getIntParameter(String S,int def){
String s = getParameter(S);
if( s != null && s.length()>0){
try {
def = Integer.parseInt(s);
}catch(Exception e){
System.out.println("could not parse \"integer\" "+s+" from parameter "+S+"\nWill use default value "+def);
}
}
return def;
}
 
public void stop(){
sharptools.setVisible(false);
}
public void destroy(){
}
public void run(){}
public void start(){}
// javascript methods
public String ReadRawApplet(){//send data in tab-separated format to Javascript
String AppletReply=sharptools.ReadRawSpreadSheet();
return AppletReply;
}
public String ReadApplet(){//send data in tab-separated or matrix format to Javascript
// default [1,2,3;4,5,6]
String AppletReply=sharptools.ReadSpreadSheet(type);
return AppletReply;
}
public void ShowSpreadSheet(boolean v){
sharptools.setVisible(v);
}
public void try_to_open_wims_spreadsheet(String S){
String s = getParameter(S);
try{
spreadsheet_from_url = load(s);
if(spreadsheet_from_url != null){
found_spreadsheet_from_url=true;
sharptools.openFileString(spreadsheet_from_url);
if(convert_initial_tsv_to_matrix){
initial_tsv_matrix = sharptools.ReadSpreadSheet(type);
}
}
}
catch(Exception e){System.out.println(e);}
}
 
public static byte [] loadURL(URL url) throws IOException {
int bufSize = 1024 * 2;
byte [] buf = new byte[bufSize];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(url.openStream());
int n;
while ((n = in.read(buf)) > 0){
bout.write(buf, 0, n);
}
try { in.close(); } catch (Exception ignored) { }
return bout.toByteArray();
}
public static String loadFile(String fname) throws IOException {
// jm.evers :handy functions !!! not mine :(
byte[] bytes = loadURL(new URL("file:" + fname));
return new String(bytes);
}
 
public static String load(String fileOrURL) throws IOException {
// jm.evers :handy functions !!! not mine :(
try {
URL url = new URL(fileOrURL);
return new String(loadURL(url));
} catch (Exception e) { return loadFile(fileOrURL);}
}
public String getAppletInfo(){
return "Spreadsheet program for WIMS.";
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/Histogram.java
0,0 → 1,203
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)Histogram.java
*
* $Id: Histogram.java,v 1.35 2001/05/27 22:29:29 huaz Exp $
*
* Created Novenmber 21, 2000, 11:27 PM
*/
package SharpTools;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
 
/**
* This is a fully functional histogram class (including UI).
*
* A tabbed panel is used. Multiple histograms can be managed simultaneously.
*
* @author Hua Zhong
* @version $Revision: 1.35 $
*/
 
public class Histogram extends JFrame implements ActionListener {
private SharpTools sharp;
private JTable table;
private SharpTableModel model;
private JTabbedPane tab;
private int width;
private int height;
private String title;
private Point location;
private Dimension dim;
final ImageIcon histogramIcon=new ImageIcon(getClass().getResource("/images/chart.gif"));
//final private ImageIcon histogramIcon = SharpTools.getImageIcon("chart.gif");
// private int selected = -1;
/**
* Constructor:
*
* @param model the table model to read data from
* @param title the title for the histogram window
* @param width the initial widh
* @param height the initial height
*/
Histogram(SharpTools sharp, String title, int width, int height) {
super(title);
setSize(width, height);
// setIconImage(histogramIcon.getImage());
 
this.sharp = sharp;
this.table = sharp.getTable();
this.model = sharp.getTableModel();
this.title = title;
this.width = width;
this.height = height;
 
tab = new JTabbedPane();
 
// register toggle key
table.registerKeyboardAction
(this, SharpTools.translation.getProperty("Show"),
KeyStroke.getKeyStroke(KeyEvent.VK_F8,0, false),
JComponent.WHEN_FOCUSED);
 
// register add histogram key
table.registerKeyboardAction
(this, SharpTools.translation.getProperty("Add"),
KeyStroke.getKeyStroke(KeyEvent.VK_H, ActionEvent.CTRL_MASK, false),
JComponent.WHEN_FOCUSED);
Container container = getContentPane();
container.setLayout(new BorderLayout());
 
container.add(tab, BorderLayout.CENTER);
/*
if (selected >= 0) {
selected = Math.min(selected, tab.getTabCount()-1);
tab.setSelectedIndex(selected);
}
*/
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
 
// bring the dialog to the front; restore if minimized
private void bringToFront() {
if (getState() == Frame.ICONIFIED)
setState(Frame.NORMAL);
toFront();
}
/**
* Show histograms
*/
public void show() {
super.show();
sharp.checkShowHistogramState();
}
 
/**
* Hide histograms.
*/
public void hide() {
super.hide();
sharp.checkShowHistogramState();
}
 
/**
* Add a histogram to the tab panel
*
* @param title the title for the histogram
* @param range the selected cell range
*/
public void add(String title, CellRange range) {
 
bringToFront();
 
if (!isVisible())
show();
 
TabPanel newTab = new TabPanel(model, range, this, tab);
tab.addTab(title, null, newTab, range.toString());
tab.setSelectedIndex(tab.getTabCount()-1);
newTab.getOptions(true); // first time
}
 
/**
* toggle the show/hide state
*/
public void toggle() {
if (isVisible())
hide();
else if (hasChart()) {
// setSize(width, height);
bringToFront();
show();
}
}
 
/**
* Add Histogram
*/
public void addHistogram() {
//checks if anything is selected
if (table.getSelectedRowCount() != 0) {
CellRange range = new CellRange
(table.getSelectedRows(), table.getSelectedColumns());
 
String title = SharpTools.translation.getProperty("Chart")+" "+(tab.getTabCount()+1);
add(title, range);
sharp.checkShowHistogramState();
} else {
sharp.noCellsSelected(SharpTools.translation.getProperty("Histogram"));
}
}
/**
* Whether the histogram is currently having any defined charts
*
* @return true or false
*/
public boolean hasChart() {
return tab.getTabCount()>0;
}
 
/**
* This method is activated on the Keystrokes we are listening to
* in this implementation. Here it listens for "Show" ActionCommands.
* Without this listener, when we press certain keys the individual
* cell will be activated into editing mode in addition to the
* effect of the key accelerators we defined with menu items.
* With this key listener, we avoid this side effect.
*/
public void actionPerformed(ActionEvent e) {
 
if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Show"))==0) {
toggle();
}
else if (e.getActionCommand().compareTo(SharpTools.translation.getProperty("Add"))==0) {
addHistogram();
}
}
 
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SharpDialog.java
0,0 → 1,372
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This is a customized dialog which provides standard buttons.
*
* @author Hua Zhong
* @version $Revision: 1.3 $
*
*/
package SharpTools;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
 
/**
* @see PasswordDialog
* @see NewFileDialog
* @see FindDialog
* @see SortDialog
* @see HistoDialog
* @see ConnectDialog
*/
class SharpDialog extends JDialog {
static final public int CLOSED_OPTION = JOptionPane.CLOSED_OPTION;
static final public int YES_OPTION = JOptionPane.YES_OPTION;
static final public int NO_OPTION = JOptionPane.NO_OPTION;
static final public int OK_OPTION = JOptionPane.OK_OPTION;
static final public int CANCEL_OPTION = JOptionPane.CANCEL_OPTION;
final ImageIcon okIcon=new ImageIcon(getClass().getResource("/images/ok.gif"));
final ImageIcon cancelIcon=new ImageIcon(getClass().getResource("/images/cancel.gif"));
final ImageIcon noIcon=new ImageIcon(getClass().getResource("/images/no.gif"));
//static final private ImageIcon okIcon = SharpTools.getImageIcon("ok.gif");
//static final private ImageIcon cancelIcon = SharpTools.getImageIcon("cancel.gif");
//static final private ImageIcon noIcon = SharpTools.getImageIcon("no.gif");
 
// get string from the UIManager - support locale
final private JButton okButton = new JButton(UIManager.get("OptionPane.okButtonText").toString(), okIcon);
final private JButton cancelButton = new JButton(UIManager.get("OptionPane.cancelButtonText").toString(), cancelIcon);
// final private JButton yesButton = new JButton(UIManager.get("OptionPane.yesButtonText").toString(), okIcon);
// final private JButton noButton = new JButton(UIManager.get("OptionPane.noButtonText").toString(), noIcon);
final private JButton yesButton = new JButton((SharpTools.translation).getProperty("yes").toString(), okIcon);
final private JButton noButton = new JButton((SharpTools.translation).getProperty("no").toString(), noIcon);
 
final private Object[] ok = { okButton };
final private Object[] yesno = { yesButton, noButton };
final private Object[] yesnocancel = { yesButton, noButton, cancelButton };
final private Object[] okcancel = { okButton, cancelButton };
 
private int choice = CLOSED_OPTION;
 
 
// override all constructors
/**
* create a non-modal dialog
*
* @param c parent dialog
*/
SharpDialog(Dialog c) {
super(c);
}
 
/**
* @param c parent dialog
* @param model whether to create a modal dialog
*/
SharpDialog(Dialog c, boolean modal) {
super(c, modal);
}
 
/**
* create a non-modal dialog
*
* @param c parent dialog
* @param title title
*/
SharpDialog(Dialog c, String title) {
super(c, title);
}
 
/**
* @param c parent dialog
* @param title title
* @param model whether to create a modal dialog
*/
SharpDialog(Dialog c, String title, boolean modal) {
super(c, title, modal);
}
 
/**
* create a non-modal dialog
*
* @param c parent frame
*/
SharpDialog(Frame c) {
super(c);
}
 
/**
* @param c parent frame
* @param model whether to create a modal dialog
*/
SharpDialog(Frame c, boolean modal) {
super(c, modal);
}
 
/**
* create a non-modal dialog
*
* @param c parent frame
* @param title title
*/
SharpDialog(Frame c, String title) {
super(c, title);
}
 
/**
* @param c parent frame
* @param title title
* @param model whether to create a modal dialog
*/
SharpDialog(Frame c, String title, boolean modal) {
super(c, title, modal);
}
 
/**
* override this protected funciton to register ESCAPE with the root pane
*
* @return a customized JRootPane object
*/
protected JRootPane createRootPane() {
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
JRootPane rootPane = new JRootPane();
rootPane.registerKeyboardAction(
new ActionListener() {
public void actionPerformed
(ActionEvent ev) {
if (onClose()) {
choice = CLOSED_OPTION;
setVisible(false);
}
}
},
stroke,
JComponent.WHEN_IN_FOCUSED_WINDOW);
return rootPane;
}
 
/**
* I provide several hooks for the sublasses to override..
*/
 
/**
*
* This function is called when the dialog window is opened.
*
*/
protected void onOpen() {
}
/**
*
* This function is called when
* (1) the close button is clocked
* (2) Escape is pressed
*
* By default, we think it's the same as clicking Cancel button
*
* @return whether the dialog should be closed
*/
protected boolean onClose() {
return onCancel();
}
 
/**
*
* This function is called when the OK button is pressed
*
* @return whether the dialog should be closed
*/
protected boolean onOK() {
return true;
}
/**
*
* This function is called when the Cancel button is pressed
*
* @return whether the dialog should be closed
*/
protected boolean onCancel() {
return true;
}
 
/**
*
* This function is called when the Yes button is pressed
*
* @return whether the dialog should be closed
*/
protected boolean onYes() {
return true;
}
 
/**
*
* This function is called when the No button is pressed
*
* @return whether the dialog should be closed
*/
protected boolean onNo() {
return true;
}
 
/**
* This is used by subclasses to set the JOptionPane component
* in the dialog.
*
* @param message the message box
* @param messageType the message type
* @param optionType the option type
* @param icon the icon to display
*/
protected void setOptionPane(Object message,
int messageType,
int optionType,
Icon icon) {
setOptionPane(message, messageType, optionType, icon, 0);
}
/**
* This is used by subclasses to set the JOptionPane component
* in the dialog.
*
* @param message the message box
* @param messageType the message type
* @param optionType the option type
* @param icon the icon to display
* @param defaultIndex the default index
*/
protected void setOptionPane(Object message,
int messageType,
int optionType,
Icon icon,
int defaultIndex) {
addWindowListener(new WindowAdapter() {
 
public void windowOpened(WindowEvent we) {
// set the initial focus to rowField
onOpen();
}
public void windowClosing(WindowEvent we) {
if (onClose()) {
choice = CLOSED_OPTION;
setVisible(false);
}
}
});
// handle this by onClose()
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
 
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (onOK()) {
choice = OK_OPTION;
setVisible(false);
}
}
});
 
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (onCancel()) {
choice = CANCEL_OPTION;
setVisible(false);
}
}
});
yesButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (onYes()) {
choice = YES_OPTION;
setVisible(false);
}
}
});
noButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (onNo()) {
choice = NO_OPTION;
setVisible(false);
}
}
});
 
// setup Mnemonic
okButton.setMnemonic (KeyEvent.VK_O);
cancelButton.setMnemonic (KeyEvent.VK_C);
yesButton.setMnemonic (KeyEvent.VK_Y);
noButton.setMnemonic (KeyEvent.VK_N);
Object[] buttons = setButtons(optionType);
JOptionPane optionPane = new JOptionPane(message, messageType,
optionType, icon,
buttons,
buttons[defaultIndex]);
setContentPane(optionPane);
 
pack();
setLocationRelativeTo(getParent());
}
 
/**
* set button array
*/
private Object[] setButtons(int type) {
 
Object[] buttons;
switch (type) {
case JOptionPane.YES_NO_CANCEL_OPTION:
buttons = yesnocancel;
break;
case JOptionPane.YES_NO_OPTION:
buttons = yesno;
break;
case JOptionPane.OK_CANCEL_OPTION:
buttons = okcancel;
break;
default:
buttons = ok;
break;
}
 
return buttons;
}
 
/**
* @return user choice
*/
public int getChoice() {
return choice;
}
 
/**
* @return whether this operation was cancelled
*/
public boolean isCancelled() {
return choice == CANCEL_OPTION || choice == CLOSED_OPTION;
}
}
 
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SharpTools.java
0,0 → 1,1298
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)SharpTools.java
*
* $Id: SharpTools.java,v 1.178 2002/08/08 05:15:08 huaz Exp $
*
* Created on October 10, 2000, 1:15 AM
*/
package SharpTools;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;
 
/**
* This is the graphical user interface class for the spreadsheet.
* <p>
* The initial size of the window can be controlled by editing the
* sharptools.ini file. This class also contains button and menu
* initialization and editing methods.
*
* @author Daniel Goldberg (initial UI)
* @author Andrei Scudder, Daniel Medina (more work)
* @author Hua Zhong (complete for v1.0)
* @version $Revision: 1.178 $
*/
final public class SharpTools extends JFrame implements ListSelectionListener {
/* jm.evers */
public URL backurl;
public String reply_url;
SharpTools spreadsheet;
static boolean inapplet=false;
static String language="en";
public static Properties translation=new Properties();
protected int maxNumPage = 1;
 
// the rest of the components
private Container container;
private JTable table;
private JScrollPane scrollPane;
private JToolBar toolBar;
private JMenuBar menuBar;
private JPanel barPanel;
private History history;
private Histogram histogram;
public SharpOptionPane sharpoptionpane;
static private Config config;
private ListSelectionModel rowSelectionModel;
private ListSelectionModel columnSelectionModel;
private URL url;
// these are used to access our global objects
static public Config getConfig() { return config; }
public History getHistory() { return history; }
public JTable getTable() { return table; }
public SharpTableModel getTableModel() { return tableModel; }
public JToolBar getToolBar() { return toolBar; }
//public JMenuBar getMenuBar() { return menuBar; }
private FileOp fileOp;
private EditOp editOp;
private TableOp tableOp;
private SharpTableModel tableModel;
// private HelpOp helpOp;
 
// initialize JMenu fields
// menu headings
private JMenu fileMenu;
private JMenu openMenu;
private JMenu recentMenu;
private JMenu editMenu;
private JMenu tableMenu;
private JMenu chartMenu;
private JMenu helpMenu;
// submenu headings
private JMenu insertMenu;
private JMenu deleteMenu;
private JMenu sortMenu;
// private JMenuItem menuItem;
private JMenuItem saveMenuItem;
private JCheckBoxMenuItem saveOnExitMenuItem;
private JMenuItem undoMenuItem;
private JMenuItem redoMenuItem;
private JMenuItem findNextMenuItem;
private JCheckBoxMenuItem showHistogramMenuItem;
private JCheckBoxMenuItem showFunctionsMenuItem;
private JButton exitButton;
private JButton saveButton;
private JButton passwordButton;
private JButton undoButton;
private JButton redoButton;
private JComponent funcList;
// private JCheckBox showButton;
ImageIcon newIcon=new ImageIcon(getClass().getResource("/images/new.gif"));
ImageIcon openIcon=new ImageIcon(getClass().getResource("/images/open.gif"));
ImageIcon saveIcon=new ImageIcon(getClass().getResource("/images/save.gif"));
ImageIcon unlockedIcon=new ImageIcon(getClass().getResource("/images/unlocked.gif"));
ImageIcon lockedIcon=new ImageIcon(getClass().getResource("/images/locked.gif"));
ImageIcon printIcon=new ImageIcon(getClass().getResource("/images/print.gif"));
ImageIcon undoIcon=new ImageIcon(getClass().getResource("/images/undo.gif"));
ImageIcon redoIcon=new ImageIcon(getClass().getResource("/images/redo.gif"));
ImageIcon cutIcon=new ImageIcon(getClass().getResource("/images/cut.gif"));
ImageIcon copyIcon=new ImageIcon(getClass().getResource("/images/copy.gif"));
ImageIcon pasteIcon=new ImageIcon(getClass().getResource("/images/paste.gif"));
ImageIcon findIcon=new ImageIcon(getClass().getResource("/images/find.gif"));
ImageIcon insertRowIcon=new ImageIcon(getClass().getResource("/images/insertrow.gif"));
ImageIcon insertColumnIcon=new ImageIcon(getClass().getResource("/images/insertcolumn.gif"));
ImageIcon deleteRowIcon=new ImageIcon(getClass().getResource("/images/deleterow.gif"));
ImageIcon deleteColumnIcon=new ImageIcon(getClass().getResource("/images/deletecolumn.gif"));
ImageIcon sortIcon=new ImageIcon(getClass().getResource("/images/sort.gif"));
ImageIcon chartIcon=new ImageIcon(getClass().getResource("/images/chart.gif"));
ImageIcon helpIcon=new ImageIcon(getClass().getResource("/images/help.gif"));
ImageIcon exitIcon=new ImageIcon(getClass().getResource("/images/no.gif"));
ImageIcon WIMSIcon=new ImageIcon(getClass().getResource("/images/send.gif"));
public static int baseRow = 0;
public static int baseCol = 1;
public int firstColWidth;
private CellRange cellrange;
/** Creates new SharpTools */
public SharpTools(boolean is_this_the_applet,String lang) {
super("Sharp_Tools_Spreadsheet");
// setIconImage(Toolkit.getDefaultToolkit().getImage("tools.jpg"));
int x;
int y;
language=lang;
System.out.println("in Sharptools.java the language="+language);
if(is_this_the_applet){
inapplet = true;
x = MainApplet.Xlocation;
y = MainApplet.Ylocation;
backurl = MainApplet.backurl;
reply_url = MainApplet.reply_url;
}
else
{
inapplet = false;
x = config.getInt("X");
y = config.getInt("Y");
}
setLocation(x, y);
translation=loadProperties(language);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
// get content pane
container = this.getContentPane();
container.setLayout(new BorderLayout());
 
// create the table
table = new JTable();
 
// create the Functions combobox in the table
funcList = HelpOp.createFunctionListComponent(this, table);
// set up fileMenu
fileMenu = new JMenu("File", true);
fileMenu.setMnemonic(KeyEvent.VK_F); //used constructor instead
// add fileMenu actions
JMenuItem menuItem = new JMenuItem(translation.getProperty("New"));
menuItem.setMnemonic(KeyEvent.VK_N);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_N, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
if(!inapplet){fileOp.newFile();}else{ReStart();}
}
});
if(!inapplet){
// SJK Added
fileMenu.add(menuItem);
openMenu = new JMenu (translation.getProperty("Open"));
openMenu.setMnemonic (KeyEvent.VK_O);
menuItem = new JMenuItem (translation.getProperty("File"));
menuItem.setMnemonic (KeyEvent.VK_F);
menuItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_O, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.openFile ();
}
} );
openMenu.add (menuItem);
menuItem = new JMenuItem (translation.getProperty("Database"));
menuItem.setMnemonic (KeyEvent.VK_D);
menuItem.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_D, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.openDb ();
}
} );
openMenu.add (menuItem);
fileMenu.add (openMenu);
// use provate member for further reference
saveMenuItem = new JMenuItem(translation.getProperty("Save"));
saveMenuItem.setMnemonic(KeyEvent.VK_S);
saveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
saveMenuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.saveFile();
}
});
fileMenu.add(saveMenuItem);
menuItem = new JMenuItem(translation.getProperty("Save_As"));
menuItem.setMnemonic(KeyEvent.VK_A);
// menuItem.setAccelerator(KeyStroke.getKeyStroke(
// KeyEvent.VK_A, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.saveAsFile();
}
});
fileMenu.add(menuItem);
menuItem = new JMenuItem(translation.getProperty("Set_Password"));
menuItem.setMnemonic(KeyEvent.VK_E);
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.setPassword();
checkPasswordState();
}
});
fileMenu.add(menuItem);
fileMenu.addSeparator();
menuItem = new JMenuItem(translation.getProperty("Print"));
menuItem.setMnemonic(KeyEvent.VK_P); //used constructor instead
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
//notYetImplemented();
Thread runner = new Thread() {
public void run() {
fileOp.printData();
}
};
runner.start();
}
});
fileMenu.add(menuItem);
fileMenu.addSeparator();
 
recentMenu = new JMenu(translation.getProperty("Recent_Files"));
recentMenu.setMnemonic(KeyEvent.VK_R); //used constructor instead
recentMenu.addMenuListener(new MenuListener() {
public void menuCanceled(MenuEvent e) {}
public void menuDeselected(MenuEvent e) {}
public void menuSelected(MenuEvent e) {
fileOp.createRecentFilesMenu(recentMenu);
}
});
fileMenu.add(recentMenu);
fileMenu.addSeparator();
 
//set up Save Window on Exit
saveOnExitMenuItem = new JCheckBoxMenuItem(translation.getProperty("Save_Window_on_Exit"));
saveOnExitMenuItem.setMnemonic(KeyEvent.VK_W);
saveOnExitMenuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
config.setBoolean("SAVEWINDOW", saveOnExitMenuItem.isSelected());
}
});
// initialize
saveOnExitMenuItem.setSelected(config.getBoolean("SAVEWINDOW"));
fileMenu.add(saveOnExitMenuItem);
fileMenu.addSeparator();
menuItem = new JMenuItem(translation.getProperty("Exit"));
menuItem.setMnemonic(KeyEvent.VK_X);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
//exitMenuActionPerformed(evt);
exit();
}
});
fileMenu.add(menuItem);
} // einde if(!inapplet){}
//Set up Edit menu
editMenu = new JMenu(translation.getProperty("Edit"), true);
editMenu.setMnemonic(KeyEvent.VK_E);
 
// Undo
undoMenuItem = new JMenuItem(translation.getProperty("Undo"));
undoMenuItem.setMnemonic(KeyEvent.VK_U);
undoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
undoMenuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
// save current selection
history.undo(tableModel);
}
});
editMenu.add(undoMenuItem);
 
// Redo
redoMenuItem = new JMenuItem(translation.getProperty("Redo"));
redoMenuItem.setMnemonic(KeyEvent.VK_R);
redoMenuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_Y, ActionEvent.CTRL_MASK));
redoMenuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
history.redo(tableModel);
}
});
editMenu.add(redoMenuItem);
editMenu.addSeparator();
 
// cut
menuItem = new JMenuItem(translation.getProperty("Cut"));
menuItem.setMnemonic(KeyEvent.VK_T);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_X, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.cut();
}
});
editMenu.add(menuItem);
 
// copy
menuItem = new JMenuItem(translation.getProperty("Copy"));
menuItem.setMnemonic(KeyEvent.VK_C);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_C, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.copy();
}
});
editMenu.add(menuItem);
 
// paste
menuItem = new JMenuItem(translation.getProperty("Paste"));
menuItem.setMnemonic(KeyEvent.VK_P);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_V, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.paste();
}
});
editMenu.add(menuItem);
editMenu.addSeparator();
 
// Fill
menuItem = new JMenuItem(translation.getProperty("Fill"));
menuItem.setMnemonic(KeyEvent.VK_F);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_L, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.fill();
}
});
editMenu.add(menuItem);
 
// Clear
menuItem = new JMenuItem(translation.getProperty("Clear"));
menuItem.setMnemonic(KeyEvent.VK_L);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_DELETE, 0, true));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.clear();
}
});
editMenu.add(menuItem);
editMenu.addSeparator();
 
// Find
menuItem = new JMenuItem(translation.getProperty("Find"));
menuItem.setMnemonic(KeyEvent.VK_F);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_F, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.find(true);
}
});
editMenu.add(menuItem);
findNextMenuItem = new JMenuItem(translation.getProperty("Find_Next"));
findNextMenuItem.setMnemonic(KeyEvent.VK_N);
findNextMenuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_F3, 0));
findNextMenuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.find(false);
}
});
editMenu.add(findNextMenuItem);
//set up tablemenu
tableMenu = new JMenu(translation.getProperty("Table"), true);
tableMenu.setMnemonic(KeyEvent.VK_T);
//set up tableMenu actions
insertMenu = new JMenu(translation.getProperty("Insert"));
insertMenu.setMnemonic(KeyEvent.VK_I);
menuItem = new JMenuItem(translation.getProperty("Row"));
menuItem.setMnemonic(KeyEvent.VK_R);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_INSERT, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.insert(true);
}
});
insertMenu.add(menuItem);
menuItem = new JMenuItem(translation.getProperty("Column"));
menuItem.setMnemonic(KeyEvent.VK_C);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_INSERT,
ActionEvent.CTRL_MASK|
ActionEvent.SHIFT_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.insert(false);
}
});
insertMenu.add(menuItem);
tableMenu.add(insertMenu);
 
//set up Delete actions
deleteMenu = new JMenu(translation.getProperty("Delete"));
deleteMenu.setMnemonic(KeyEvent.VK_D);
menuItem = new JMenuItem(translation.getProperty("Row"));
menuItem.setMnemonic(KeyEvent.VK_R);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_DELETE, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
//notYetImplemented();
tableOp.remove(true);
}
});
deleteMenu.add(menuItem);
menuItem = new JMenuItem(translation.getProperty("Column"));
menuItem.setMnemonic(KeyEvent.VK_C);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_DELETE,
ActionEvent.CTRL_MASK|
ActionEvent.SHIFT_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
//notYetImplemented();
tableOp.remove(false);
}
});
deleteMenu.add(menuItem);
tableMenu.add(deleteMenu);
tableMenu.addSeparator();
//set up Sort actions
sortMenu = new JMenu(translation.getProperty("Sort"));
sortMenu.setMnemonic(KeyEvent.VK_S);
menuItem = new JMenuItem(translation.getProperty("Row"));
menuItem.setMnemonic(KeyEvent.VK_R);
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.sort(true);
}
});
sortMenu.add(menuItem);
menuItem = new JMenuItem(translation.getProperty("Column"));
menuItem.setMnemonic(KeyEvent.VK_C);
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.sort(false);
}
});
sortMenu.add(menuItem);
tableMenu.add(sortMenu);
tableMenu.addSeparator();
menuItem = new JMenuItem(translation.getProperty("Set_Column_Width"));
menuItem.setMnemonic(KeyEvent.VK_W);
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.setColumnWidth();
}
});
tableMenu.add(menuItem);
menuItem = new JMenuItem(translation.getProperty("Set_First_Column_Width"));
menuItem.setMnemonic(KeyEvent.VK_W);
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.setFirstColumnWidth();
}
});
tableMenu.add(menuItem);
//set up Histogram menu
chartMenu = new JMenu(translation.getProperty("Chart"), true);
chartMenu.setMnemonic(KeyEvent.VK_C);
 
chartMenu.addMenuListener (new MenuListener () {
public void menuSelected (MenuEvent e) {
checkShowHistogramState();
}
public void menuDeselected (MenuEvent e) { }
public void menuCanceled (MenuEvent e) { }
});
 
 
//set up Show Histogram actions
showHistogramMenuItem = new JCheckBoxMenuItem(translation.getProperty("Show"));
showHistogramMenuItem.setMnemonic(KeyEvent.VK_S);
showHistogramMenuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_F8, 0));
showHistogramMenuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
histogram.toggle();
}
});
chartMenu.add(showHistogramMenuItem);
 
//set up Add Histogram actions
menuItem = new JMenuItem(translation.getProperty("Histogram"));
menuItem.setMnemonic(KeyEvent.VK_H);
menuItem.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_H, ActionEvent.CTRL_MASK));
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
histogram.addHistogram();
}
});
 
chartMenu.add(menuItem);
tableMenu.add(chartMenu);
 
 
//set up Help menu
helpMenu = new JMenu(translation.getProperty("Help"), true);
helpMenu.setMnemonic(KeyEvent.VK_H);
 
//set up Help actions
menuItem = new JMenuItem(translation.getProperty("Help_Topics"));
menuItem.setMnemonic(KeyEvent.VK_H);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
 
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
// testcode
try {
URL url = new URL("http://localhost/sharptools/");
new HelpOp(url);
} catch(MalformedURLException e) {
e.printStackTrace();
return;
}
}
});
helpMenu.add(menuItem);
 
showFunctionsMenuItem = new JCheckBoxMenuItem(translation.getProperty("Show_Functions"));
showFunctionsMenuItem.setMnemonic(KeyEvent.VK_S);
if(inapplet){
showFunctionsMenuItem.setSelected(MainApplet.TOOLBAR_FUNCTIONS);
}
else
{
showFunctionsMenuItem.setSelected(config.getBoolean("TOOLBAR_FUNCTIONS"));
}
showFunctionsMenuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
boolean showFunc = showFunctionsMenuItem.isSelected();
if(!inapplet){
config.setBoolean("TOOLBAR_FUNCTIONS", showFunc);
}
funcList.setVisible(showFunc);
// repaint
}
});
helpMenu.add(showFunctionsMenuItem);
 
helpMenu.addSeparator();
menuItem = new JMenuItem(translation.getProperty("About_SharpTools"));
menuItem.setMnemonic(KeyEvent.VK_A);
menuItem.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
HelpOp.showAboutBox(SharpTools.this);
table.requestFocus();
}
});
helpMenu.add(menuItem);
// set up menu bar and menus
menuBar = new JMenuBar();
 
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(tableMenu);
menuBar.add(chartMenu);
menuBar.add(helpMenu);
// button initializations
JButton WIMSButton = new JButton(WIMSIcon);
JButton newButton = new JButton(newIcon);
JButton exitButton = new JButton(exitIcon);
JButton openButton = new JButton(openIcon);
JButton printButton = new JButton(printIcon);
passwordButton = new JButton(unlockedIcon);
saveButton = new JButton(saveIcon);
 
if(!inapplet){
newButton.setToolTipText(translation.getProperty("New"));
newButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.newFile();
table.requestFocus();
}
});
openButton.setToolTipText(translation.getProperty("Open"));
openButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.openFile();
table.requestFocus();
}
});
// we save this button as private member for further reference
saveButton.setToolTipText(translation.getProperty("Save"));
saveButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.saveFile();
table.requestFocus();
}
});
// we save this button as private member for further reference
passwordButton.setToolTipText(translation.getProperty("Set_Password"));
passwordButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
fileOp.setPassword();
table.requestFocus();
}
});
 
printButton.setToolTipText(translation.getProperty("Print"));
printButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
Thread runner = new Thread() {
public void run() {
fileOp.printData();
}
};
runner.start();
table.requestFocus();
}
});
}
 
WIMSButton.setToolTipText(translation.getProperty("WIMS"));
WIMSButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
if(HelpOp.are_you_sure(SharpTools.this) == 0 && inapplet){
send_to_wims();
}
}
});
 
undoButton = new JButton(undoIcon);
undoButton.setToolTipText(translation.getProperty("Undo"));
undoButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
history.undo(tableModel);
table.requestFocus();
}
});
 
redoButton = new JButton(redoIcon);
redoButton.setToolTipText(translation.getProperty("Redo"));
redoButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
history.redo(tableModel);
table.requestFocus();
}
});
JButton cutButton = new JButton(cutIcon);
cutButton.setToolTipText(translation.getProperty("Cut"));
cutButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.cut();
table.requestFocus();
}
});
JButton copyButton = new JButton(copyIcon);
copyButton.setToolTipText(translation.getProperty("Copy"));
copyButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.copy();
table.requestFocus();
}
});
JButton pasteButton = new JButton(pasteIcon);
pasteButton.setToolTipText(translation.getProperty("Paste"));
pasteButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.paste();
table.requestFocus();
}
});
 
JButton findButton = new JButton(findIcon);
findButton.setToolTipText(translation.getProperty("Find"));
findButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
editOp.find(true);
table.requestFocus();
}
});
 
JButton sortButton = new JButton(sortIcon);
sortButton.setToolTipText(translation.getProperty("Sort_by_Column"));
sortButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.sort(false);
table.requestFocus();
}
});
 
JButton insertRowButton = new JButton(insertRowIcon);
insertRowButton.setToolTipText(translation.getProperty("Insert_Row"));
insertRowButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.insert(true);
table.requestFocus();
}
});
 
JButton insertColumnButton = new JButton(insertColumnIcon);
insertColumnButton.setToolTipText(translation.getProperty("Insert_Column"));
insertColumnButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.insert(false);
table.requestFocus();
}
});
 
JButton deleteRowButton = new JButton(deleteRowIcon);
deleteRowButton.setToolTipText(translation.getProperty("Delete_Row"));
deleteRowButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.remove(true);
table.requestFocus();
}
});
 
JButton deleteColumnButton = new JButton(deleteColumnIcon);
deleteColumnButton.setToolTipText(translation.getProperty("Delete_Column"));
deleteColumnButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
tableOp.remove(false);
table.requestFocus();
}
});
 
JButton chartButton = new JButton(chartIcon);
chartButton.setToolTipText(translation.getProperty("Histogram"));
chartButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
histogram.addHistogram();
table.requestFocus();
}
});
JButton helpButton = new JButton(helpIcon);
helpButton.setToolTipText(translation.getProperty("Help"));
helpButton.addActionListener (new ActionListener () {
public void actionPerformed (ActionEvent evt) {
try {
if(!inapplet){
String basePath = System.getProperty("user.dir");
}
url = new URL("http://localhost/sharptools/");
new HelpOp(url);
 
} catch(MalformedURLException e) {
e.printStackTrace();
return;
}
table.requestFocus();
}
});
 
/*
* Set up toolbar
*
* Toolbar can be customized in the configuration file.
*/
toolBar = new JToolBar();
toolBar.setFloatable(false);
int w;int h;
if(!inapplet){
//if (config.getBoolean("TOOLBAR_NEW")){}
toolBar.add(newButton);
toolBar.add(openButton);
toolBar.add(saveButton);
toolBar.addSeparator();
toolBar.add(passwordButton);
toolBar.add(printButton);
toolBar.addSeparator();
toolBar.add(undoButton);
toolBar.add(redoButton);
toolBar.add(cutButton);
toolBar.add(copyButton);
toolBar.add(pasteButton);
toolBar.add(findButton);
toolBar.addSeparator();
toolBar.add(insertRowButton);
toolBar.add(insertColumnButton);
toolBar.add(deleteRowButton);
toolBar.add(deleteColumnButton);
toolBar.add(sortButton);
toolBar.addSeparator();
toolBar.add(chartButton);toolBar.addSeparator();
toolBar.add(helpButton);
toolBar.addSeparator();
toolBar.add(funcList);
funcList.setVisible(true);
newTableModel(config.getInt("ROWS"), config.getInt("COLUMNS"));
// set window pos and size
w = config.getInt("WIDTH");
h = config.getInt("HEIGHT");
}
else // inapplet ; we can't configure the sharptools.ini file...so we depend on params.
{
if (MainApplet.TOOLBAR_UNDO){toolBar.add(undoButton);}
if (MainApplet.TOOLBAR_REDO){toolBar.add(redoButton);}
if (MainApplet.TOOLBAR_CUT){toolBar.add(cutButton);}
if (MainApplet.TOOLBAR_COPY){toolBar.add(copyButton);}
if (MainApplet.TOOLBAR_PASTE){toolBar.add(pasteButton);}
if (MainApplet.TOOLBAR_FIND){toolBar.add(findButton);}
toolBar.addSeparator();
if (MainApplet.TOOLBAR_INSERTROW){toolBar.add(insertRowButton);}
if (MainApplet.TOOLBAR_INSERTCOLUMN){toolBar.add(insertColumnButton);}
if (MainApplet.TOOLBAR_DELETEROW){toolBar.add(deleteRowButton);}
if (MainApplet.TOOLBAR_DELETECOLUMN){toolBar.add(deleteColumnButton);}
if (MainApplet.TOOLBAR_SORTCOLUMN){toolBar.add(sortButton);}
toolBar.addSeparator();
if (MainApplet.TOOLBAR_HISTOGRAM) {toolBar.add(chartButton);toolBar.addSeparator();}
if (MainApplet.TOOLBAR_HELP){toolBar.add(helpButton);}
toolBar.addSeparator();
toolBar.add(funcList);
funcList.setVisible(MainApplet.TOOLBAR_FUNCTIONS);
// evers send button
toolBar.addSeparator();
toolBar.add(WIMSButton);
newTableModel(MainApplet.ROWS, MainApplet.COLUMNS);
// set window pos and size
w = MainApplet.window_width;
h = MainApplet.window_height;
}
if (w >= 0 && h >= 0)
table.setPreferredScrollableViewportSize(new Dimension(w, h));
 
// init fileOp objects
if(!inapplet){fileOp = new FileOp(this);}
 
// clobber resizing of all columns
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
// set table editor and renderer to custom ones
table.setDefaultRenderer(Cell.class, new SharpCellRenderer());
table.setDefaultEditor(Cell.class, new SharpCellEditor(
new JTextField()));
 
// set selection mode for contiguous intervals
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setCellSelectionEnabled(true);
 
// we don't allow reordering
table.getTableHeader().setReorderingAllowed(false);
table.getTableHeader().addMouseListener(new HeaderMouseAdapter());
// create selection models
rowSelectionModel = table.getSelectionModel();
columnSelectionModel = table.getColumnModel().getSelectionModel();
 
// add selection listeners to the selection models
rowSelectionModel.addListSelectionListener(this);
columnSelectionModel.addListSelectionListener(this);
// set menu bar
setJMenuBar(menuBar);
container.add(toolBar, BorderLayout.NORTH);
scrollPane = new JScrollPane(table,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
container.add(scrollPane, BorderLayout.CENTER);
// add window exit listener
addWindowListener (new WindowAdapter () {
public void windowOpened (WindowEvent evt) {
table.requestFocus();
}
public void windowClosing (WindowEvent evt) {
exit();
}
});
 
// initial selection
resetSelection();
table.setRequestFocusEnabled(true);
menuBar.setRequestFocusEnabled(false);
toolBar.setRequestFocusEnabled(false);
table.requestFocus();
pack();
show();
}
public void setColumnWidth(int colWidth) {
if (colWidth > 0){
for (int i = baseCol; i < tableModel.getColumnCount(); i ++) {
TableColumn column = table.getColumnModel().getColumn(i);
column.setMinWidth(colWidth);
column.setPreferredWidth(colWidth);
 
}
}
}
/**
* Creates new blank SharpTableModel object with specified number of
* rows and columns. table is set to this table model to update screen.
*
* @param rows number of rows in new table model
* @param cols number of columns in new table model
*/
public void newTableModel(int rows, int cols) {
tableModel = new SharpTableModel(this, rows, cols);
table.setModel(tableModel);
 
setBaseColumnWidth(0);
if(!inapplet){setColumnWidth(config.getInt("COLUMNWIDTH"));} else {setColumnWidth(MainApplet.COLUMNWIDTH);}
// update history with new one
history = new History(this);
tableModel.setHistory(history);
 
// inform tableModel that it's unmodified now
tableModel.setPasswordModified(false);
tableModel.setModified(false);
 
// init op objects
// we shouldn't init fileOp!
if (editOp == null)
editOp = new EditOp(this);
else
/* if we already have an object, we don't construct
a new EditOp to keep the clipboard and findValue
still valid. This makes us be able to exchange
data across files */
editOp.init(this);
 
tableOp = new TableOp(this);
if(!inapplet){
histogram = new Histogram(this, "Histograms",config.getInt("HISTOGRAMWIDTH"),config.getInt("HISTOGRAMHEIGHT"));
}
else
{
histogram = new Histogram(this, "Histograms",MainApplet.HISTOGRAMWIDTH,MainApplet.HISTOGRAMHEIGHT);
}
tableModel.setModified(false);
resetSelection();
// menubar/toolbar initial status
checkUndoRedoState();
table.requestFocus();
}
/**
* a function to display warning messages
*
* @param s the operation that caused this error
*/
public void noCellsSelected(String s) {
sharpoptionpane.showMessageDialog(this, s + ": No cells selected","Error", JOptionPane.ERROR_MESSAGE, null);
}
 
/**
* The error message for clicks on functions we haven't done yet.
*/
private void notYetImplemented(){
sharpoptionpane.showMessageDialog(this,
"Sorry, this function \n"+
"is not yet implemented!\n"+
"sharp@cs.columbia.edu",
"Sharp Tools Spreadsheet",
JOptionPane.WARNING_MESSAGE,
null);
}
 
/** Exit the Application */
public void exit() {
if(!inapplet){
if (fileOp.closeFile()) {
// save window position and size
if (config.getBoolean("SAVEWINDOW")) {
config.setInt("X", getX());
config.setInt("Y", getY());
Dimension dim = scrollPane.getViewport().getExtentSize();
config.setInt("WIDTH", (int)dim.getWidth());
config.setInt("HEIGHT", (int)dim.getHeight());
}
config.save();
System.exit(0);
}
}
else
{
setVisible(false);
}
}
/**
* Directly open a file with specified name - used only in main
*
* @param filename the String of filename
*/
private void openInitFile(String filename) {
if(!inapplet){
fileOp.openTableModel(new File(filename));
}
}
/**
* Check menu items and toolbar buttons
* Set to appropriate status (disable/enable)
*/
 
/**
* Check the save menu/button state
* Enable only when the file has been modified
*/
public void checkSaveState() {
boolean modified = tableModel.isModified();
if(!inapplet){
saveMenuItem.setEnabled(modified);
saveButton.setEnabled(modified);
}
}
 
/**
* Check the set password toolbar button icon
* Change the icon based on whether password is set
*/
public void checkPasswordState() {
if(!inapplet){
if (fileOp.hasPassword())
passwordButton.setIcon(lockedIcon);
else
passwordButton.setIcon(unlockedIcon);
}
}
 
/**
* Check the undo/redo menu/button state
* Enable only when it's undoable/redoable
*/
public void checkUndoRedoState() {
boolean enable = history.isUndoable();
undoMenuItem.setEnabled(enable);
undoButton.setEnabled(enable);
enable = history.isRedoable();
redoMenuItem.setEnabled(enable);
redoButton.setEnabled(enable);
}
 
/**
* Check the find next menu/button state
* Enable only when the user has searched once
*/
public void checkFindNextState() {
findNextMenuItem.setEnabled(editOp.hasFindValue());
}
 
/**
* Check the show histogram menu
* Enable only when there is at least one histogram defined
*/
public void checkShowHistogramState() {
showHistogramMenuItem.setState(histogram.isVisible());
showHistogramMenuItem.setEnabled(histogram.hasChart());
}
 
public void setBaseColumnWidth(int width) {
if(width == 0){
// resize first column
if (baseCol > 0) {
TableColumn firstColumn = table.getColumnModel().getColumn(baseCol-1);
int firstColWidth;
if(!inapplet){firstColWidth = config.getInt("FIRSTCOLUMNWIDTH");}else{firstColWidth=MainApplet.FIRSTCOLUMNWIDTH;}
if (firstColWidth>0) {
firstColumn.setMinWidth(firstColWidth);
firstColumn.setPreferredWidth(firstColWidth);
}
}
}
else
{
if(width>0){
TableColumn firstColumn = table.getColumnModel().getColumn(baseCol-1);
firstColumn.setMinWidth(width);
firstColumn.setPreferredWidth(width);
}
}
}
/** This is the main method that gets the ball rolling */
public static void main(String args[]){
if(!inapplet){
// read configuration file
config = new Config("sharptools.ini");
// set default value
config.setInt("ROWS", 20);
config.setInt("COLUMNS", 10);
// config.set("AUTORESIZE", "TRUE");
config.setInt("HISTOGRAMWIDTH", 600);
config.setInt("HISTOGRAMHEIGHT", 400);
// read file
config.load();
// only change it when DEBUG is uncommented in the config file
if (config.get("DEBUG") != null)
Debug.setDebug(config.getBoolean("DEBUG"));
}
// initialize the function handler table object
Formula.registerFunctions();
SharpTools spreadsheet = new SharpTools(inapplet,language);
spreadsheet.show();
if (args.length>0){spreadsheet.openInitFile(args[0]);}
}
 
// this is a static function to help loading images
public static ImageIcon getImageIcon(String name) {
//URL imgurl = SharpTools.class.getResource(name);
//URL imgurl = getClass().getResource(name);
//URL imgurl = ClassLoader.getResourceAsStream(name);
URL imgurl = ClassLoader.getSystemResource(name);
//URL imgurl = ClassLoader.getResource(name);
if (imgurl == null) {
System.out.println("image "+name+" not found");
return null;
}
return new ImageIcon(imgurl);
}
 
class HeaderMouseAdapter extends MouseAdapter {
 
public void mouseClicked(MouseEvent e) {
TableColumnModel colModel =
table.getColumnModel();
int col =
colModel.getColumn(colModel.getColumnIndexAtX(e.getX())).getModelIndex();
int rowCount = table.getRowCount();
table.setRowSelectionInterval(baseRow, rowCount - 1);
 
if (col < baseCol)
table.setColumnSelectionInterval(baseCol, table.getColumnCount()-1);
else
table.setColumnSelectionInterval(col, col);
}
}
 
// the ListSelectionListener interface
public void valueChanged(ListSelectionEvent e) {
table.requestFocus();
// Ignore extra messages
if (e.getValueIsAdjusting()) return;
// Get event source
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
if (lsm.isSelectionEmpty() && table.getColumnCount() > baseCol &&
table.getRowCount() > baseRow) {
// always set selection
table.setRowSelectionInterval(baseRow, baseRow);
table.setColumnSelectionInterval(baseCol, baseCol);
}/* else {
if (table.getSelectedColumn() < baseCol) {
int columnCount = table.getColumnCount();
if (columnCount > baseCol) {
Debug.println("setColumnSelectionInterval "
+ String.valueOf(baseCol)
+ " " + String.valueOf(columnCount - 1));
table.setColumnSelectionInterval(baseCol, columnCount - 1);
table.removeColumnSelectionInterval(baseRow,baseRow);
}
}
}*/
}
 
public void resetSelection() {
table.setRowSelectionInterval(baseRow, baseRow);
table.setColumnSelectionInterval(baseCol, baseCol);
}
 
/* jm.evers */
public void openFileString(String sp){
StringBuffer textBuf = new StringBuffer();
String line;
try {
BufferedReader in = new BufferedReader(new StringReader(sp));
line = in.readLine();
textBuf.append(line);
textBuf.append("\n");
while ((line = in.readLine()) != null) {
textBuf.append(line);
textBuf.append("\n");
}
 
String text = textBuf.toString();
// create new table model
CellPoint size = SharpTableModel.getSize(text);
newTableModel(size.getRow(), size.getCol());
//System.out.println(size.getRow()+","+size.getCol());
tableModel = getTableModel();
tableModel.fromString(text, 0,0,
new CellRange(baseRow,
size.getRow(),
baseCol,
size.getCol()));
} catch (Exception e) { e.printStackTrace();System.out.println("in FileOp.java string = "+sp);}
}
 
public void ReStart(){
setVisible(false);
SharpTools spreadsheet = new SharpTools(inapplet,language);
spreadsheet.show();
}
public String ReadRawSpreadSheet(){
// included raw functions like =SUM(1,2,3,4)
String reply=tableModel.toString();
return reply;
}
 
public String ReadSpreadSheet(int type){
String reply=tableModel.toWIMS(type);
return reply;
}
public void send_to_wims() {
String reply = ReadSpreadSheet(MainApplet.type);
if(MainApplet.convert_initial_tsv_to_matrix){reply = reply +"\n"+ MainApplet.initial_tsv_matrix;}
reply = URLEncoder.encode(reply);
try {backurl=new URL(reply_url+reply);
(MainApplet.applet_context).showDocument(backurl,"_self");
this.dispose();
}
catch (MalformedURLException e) {backurl=null;System.out.println("could not send spreadsheet to wims "+reply_url);}
}
 
public Properties loadProperties (String lang){
Properties P=new Properties();
// jm.evers : trying global properties file with translations
try{
InputStream in = getClass().getResourceAsStream("/lang/SharpToolsProperties_"+lang+".properties");
P.load(in);in.close();
return P;
}
catch (Exception e){ System.out.println("error reading lang/SharpToolsProperties_"+lang+".properties\n"+e);}
return null;
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/History.java
0,0 → 1,304
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)History.java
*
* $Id: History.java,v 1.26 2002/08/08 05:15:06 huaz Exp $
*
* Created on November 15, 2000, 10:38 PM
*/
package SharpTools;
import java.util.*;
import javax.swing.*;
 
/** This is the class to support nearly-arbitrary undo/redo operations.
* <p>
* It's based on clipboard. Each time a range of cells being changed,
* they are saved in a clipboard and the clibboard is added to a linked
* list. A <b>current</b> pointer is maintained.
* <ol>
* <li> When a new clipboard is added, the objects after <b>current</b> are deleted
* and the new clipboard is added to the list and <b>current</b> is updated to
* point to the this new clipboard.</li>
* <li> To undo, take out the object that <b>current</b> points to, and paste to the
* table. But before the paste the table data is saved to replace the
* <b>current</b> clipboard. Then move <b>current</b> one step backward</li>
* <li> To redo, move current a step forward, take out the object <b>current</b>
* points to, and paste to the table. But before the paste the table data
* is saved to replace the <b>current</b> clipboard.</li>
* <li> Row/Column insertion/deletion are specially treated.<li>
*</ol>
*
* @author Hua Zhong <huaz@cs.columbia.edu>
* @version $Revision: 1.26 $
*/
public class History {
 
/**
* This is the doubly linked list class that undo/redo is implemented with.
* It has a type, an object and two pointers (prev, next).
*/
class ListNode {
 
private ListNode prev; // points to previous node
private ListNode next; // points to next node
private int type; // one of the 5 History static values defined below
private Object obj; // could be a SharpClipboard or a CellRange
ListNode(Object obj) {
setObject(obj);
}
 
// simple get/set functions
Object getObject() { return obj; }
ListNode getPrev() { return prev; }
ListNode getNext() { return next; }
void setObject(Object obj) { this.obj = obj; }
void setPrev(ListNode prev) { this.prev = prev; }
void setNext(ListNode next) { this.next = next; }
int getType() { return type; }
void setType(int type) { this.type = type; }
}
 
private SharpTools sharp;
final public static int UNCHANGED = 0;
final public static int INSERTROW = 1;
final public static int INSERTCOLUMN = 2;
final public static int REMOVEROW = 3;
final public static int REMOVECOLUMN = 4;
 
/** Holds the objects that are cut or copied */
private ListNode current;
 
/**
* Constructor:
*
* @param sharp the SharpTools object
*/
History(SharpTools sharp) {
this.sharp = sharp;
current = new ListNode(null);
}
 
/**
* This adds the range of cells to the history.
*
* @param model the SharpTableModel we operate on
* @param range the cell range the operation will affect
*/
public void add(SharpTableModel model, CellRange range) {
// construct the clipboard to be saved
SharpClipboard clip = new SharpClipboard(model, range, false);
add(model, clip);
}
 
/**
* This adds a clipboard object to the history list.
*
* @param model the SharpTableModel we operate on
* @param range the cell range the operation will affect
*/
public void add(SharpTableModel model, SharpClipboard clip) {
ListNode node = new ListNode(clip);
if (Debug.isDebug())
Debug.println("Add history for range "+clip.getSource());
 
// add to the linked list
current.setNext(node);
node.setPrev(current);
 
// move current forward
current = node;
 
// modified!
// all operations should call add instead of setModified themselves
model.setModified(true);
sharp.checkUndoRedoState();
}
 
/*
* This method should only be called with type != UNCHANGED,
* i.e., for table insertion/deletion operations.
*
* @param model the SharpTableModel we operate on
* @param range the cell range the operation will affect
* @param type the operation type
*/
public void add(SharpTableModel model, CellRange range, int type) {
SharpClipboard clip;
ListNode node;
 
if (type == UNCHANGED) {
add(model, range);
return;
}
if (type == REMOVEROW || type == REMOVECOLUMN) {
// save the current range
clip = new SharpClipboard(model, range, false);
node = new ListNode(clip);
}
else {
// for insertion, no data need to be saved
// just save the range value
node = new ListNode(range);
}
node.setType(type);
 
// add to the end of history list
current.setNext(node);
node.setPrev(current);
 
// move current forward
current = node;
model.setModified(true);
sharp.checkUndoRedoState();
}
 
/**
* This is the undo method.
*
* @param model the SharpTableModel we operate on
*/
public void undo(SharpTableModel model) {
if (!isUndoable())
return;
 
int type = current.getType();
CellRange range;
if (type == UNCHANGED) {
// get the saved clipboard and its range
SharpClipboard oldClip = (SharpClipboard)current.getObject();
range = oldClip.getSource();
// replace the current object with the current table data
SharpClipboard newClip = new SharpClipboard(model, range, false);
current.setObject(newClip);
// recover the data (undo)
oldClip.paste(model, range.getminCorner());
}
else if (type == REMOVEROW ||
type == REMOVECOLUMN) {
// undo a removal is just do an insertion and paste
// saved data to it
SharpClipboard clip = (SharpClipboard)current.getObject();
range = clip.getSource();
// insert lines first
if (type == REMOVEROW)
model.insertRow(range);
else
model.insertColumn(range);
 
// then paste stuff
clip.paste(model, range.getminCorner());
}
else {
// undo an insertion is just a removal
range = (CellRange)current.getObject();
// System.out.println("Undo: remove "+range);
if (type == INSERTROW)
model.removeRow(range);
else
model.removeColumn(range);
}
 
current = current.getPrev();
 
// recover the selection
model.setSelection(range);
 
/*
if (!isUndoable()) { // has come back to the beginning
model.setModified(false);
}
*/
model.setModified(true);
sharp.checkUndoRedoState();
}
 
/**
* This is the redo method.
*
* @param model the SharpTableModel we operate on
*/
public void redo(SharpTableModel model) {
if (!isRedoable())
return;
current = current.getNext();
int type = current.getType();
CellRange range;
if (type == UNCHANGED) {
 
// get the saved clipboard
SharpClipboard oldClip = (SharpClipboard)current.getObject();
range = oldClip.getSource();
// replace the current object with the current model data
SharpClipboard newClip = new SharpClipboard(model, range, false);
current.setObject(newClip);
 
// restore data and selection
oldClip.paste(model, range.getminCorner());
model.setSelection(range);
}
else if (type == REMOVEROW ||
type == REMOVECOLUMN) {
// redo a removal
SharpClipboard clip = (SharpClipboard)current.getObject();
range = clip.getSource();
// insert lines first
if (type == REMOVEROW)
model.removeRow(range);
else
model.removeColumn(range);
}
else {
// redo an insertion
range = (CellRange)current.getObject();
if (type == INSERTROW)
model.insertRow(range);
else
model.insertColumn(range);
}
 
model.setModified(true);
sharp.checkUndoRedoState();
}
 
/**
* This method check if undo can be done.
*
* @return true if undo is possible
*/
public boolean isUndoable() {
return current.getPrev() != null;
}
 
/**
* This method check if redo can be done.
*
* @return true if redo is possible
*/
public boolean isRedoable() {
return current.getNext() != null;
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/Database.java
0,0 → 1,243
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @ (#)Database.java
*
* $Id: Database.java,v 1.7 2002/08/08 05:15:02 huaz Exp $
*
* Created on May 19, 2001, 09:10:28 PM
*
* Tested with Oracle and Hsql
*
* TODO
*
* 1) Add error handling - DONE
* 2) Add a Save function
* 3) Add to recent tables on menu
* 4) Save connection params in props - DONE (saving fails, Why? Gotta study Config.java)
* 5) Select from a list of tables - DONE
* 6) Save from file to db and from db to file.
* 7) Draw proper icons - DONE (could be better).
*
* This is not the most efficient implementation - just the easy way out.
*
* Currently the SharpTableModel knows how to create itself from a tab
* delimited string so we simply construct one of these from the database
* ResultSet and give it to the SharpTableModel. A better way would be to
* teach SharpTableModel how to create itself from a ResultSet too.
*
*/
package SharpTools;
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.sql.*;
import javax.swing.*;
 
/**
* This contains database operations on the spreadsheet table
*
* @author Shiraz Kanga
* @version $Revision: 1.7 $
*/
public class Database
{
// these variables correspond to the variables in SharpTools
private SharpTools sharp;
private JTable table;
private SharpTableModel tableModel;
final ImageIcon connectedIcon=new ImageIcon(getClass().getResource("/images/database32.gif"));
//final private static ImageIcon connectedIcon = SharpTools.getImageIcon ("database32.gif");
// final private static ImageIcon selectTableIcon = SharpTools.getImageIcon ("table32.gif");
 
final private static ImageIcon dbErrorIcon = null;
 
/**
* constructor
*
* @param sharp the GUI object
*/
Database (SharpTools sharp)
{
this.sharp = sharp;
table = sharp.getTable ();
tableModel = sharp.getTableModel ();
}
public void connectDb ()
{
String dbUsername = null;
String dbPassword = null;
String dbUrl = null;
String dbDriver = null;
String dbTable = null;
String connectName = null;
boolean lockTable;
boolean verifySave;
boolean newConnection = false;
StringBuffer textBuf = new StringBuffer ();
ConnectDialog connectDialog = new ConnectDialog (sharp);
connectDialog.setVisible (true);
if (connectDialog.isCancelled())
return;
Connection dbConnection = connectDialog.getConnection();
/*
connectName = connectDialog.getConnectName ();
dbUsername = connectDialog.getDbUsername ();
dbPassword = connectDialog.getDbPassword ();
dbUrl = connectDialog.getDbUrl ();
dbDriver = connectDialog.getDbDriver ();
*/
try {
DatabaseMetaData dma = dbConnection.getMetaData ();
SharpOptionPane.showMessageDialog (sharp, "Connected to database " + dma.getDatabaseProductName () + " v" + dma.getDatabaseProductVersion () + "\nusing driver " + dma.getDriverName () + " v" + dma.getDriverVersion (),
"Connected", JOptionPane.INFORMATION_MESSAGE, connectedIcon);
if ((dbTable == null) || dbTable.equals (""))
dbTable = selectDbTable (dma);
 
// need to check cancel - huaz
if (dbTable == null)
return;
Statement stmt = dbConnection.createStatement ();
ResultSet dbResults = stmt.executeQuery ("SELECT * FROM " + dbTable);
String warnings = checkForWarning (dbConnection.getWarnings ());
if ((warnings!=null) && !warnings.equals (""))
SharpOptionPane.showMessageDialog (sharp, warnings,
"Warning", JOptionPane.INFORMATION_MESSAGE, connectedIcon);
// metadata can supply information about the schema
ResultSetMetaData rsmd = dbResults.getMetaData ();
int numCols = rsmd.getColumnCount ();
// first print header labels from meta-data
for (int i=1; i<=numCols; i++) {
if (i != 1) textBuf.append ("\t");
textBuf.append (rsmd.getColumnLabel (i));
}
textBuf.append ("\n");
while (dbResults.next ()) {
// for one row
for (int j=1; j<=numCols; j++) {
if (j != 1) textBuf.append ("\t");
textBuf.append (dbResults.getString (j));
}
textBuf.append ("\n");
}
String text = textBuf.toString ();
// create new table model
CellPoint size = SharpTableModel.getSize (text);
// System.out.println (size);
sharp.newTableModel (size.getRow (), size.getCol ());
tableModel = sharp.getTableModel ();
tableModel.fromString (text, 0, 0, new CellRange (1, size.getRow (), 1, size.getCol ()));
// tableModel.setModified (false);
// set new title for spreadsheet
sharp.setTitle (dbTable + " - Sharp Tools Spreadsheet");
// update recent files
//addRecentFile (dbTable);
dbResults.close ();
stmt.close ();
}
catch (SQLException e) {
SharpOptionPane.showMessageDialog (sharp, "Unable to get data from the database.\n" + e.toString (),
"ERROR", JOptionPane.INFORMATION_MESSAGE, dbErrorIcon);
return;
}
}
 
/*
* check if the database server has anything to say
*/
private String checkForWarning (SQLWarning warn)
throws SQLException {
StringBuffer textBuf = new StringBuffer ();
if (warn != null) {
textBuf.append ("Warning:\n\n");
while (warn != null) {
textBuf.append ("Message: " + warn.getMessage () + "\n");
textBuf.append ("SQLState: " + warn.getSQLState () + "\n");
textBuf.append ("Vendor: " + warn.getErrorCode () + "\n");
warn = warn.getNextWarning ();
}
}
return textBuf.toString ();
}
private String selectDbTable (DatabaseMetaData dma)
throws SQLException {
// JDBC exposes must meta data as ResultSets
// Change the second parameter below to retrieve information
// about a particular schema in the database
ResultSet dbResults = dma.getTables (null, null, "%", null);
Vector vec = new Vector ();
/*
Each table description row has the following columns:
TABLE_CAT String => table catalog (may be null)
TABLE_SCHEM String => table schema (may be null)
TABLE_NAME String => table name
TABLE_TYPE String => table type
Common types are "TABLE", "VIEW", "SYSTEM TABLE"
REMARKS String => explanatory comment on the table
We are only want column 3 (table name)
*/
while (dbResults.next ())
vec.addElement (dbResults.getString (3));
 
if (vec.size() == 0) {
SharpOptionPane.showMessageDialog(sharp,
"This database has no tables defined.",
"Empty Database",
JOptionPane.WARNING_MESSAGE);
return null;
}
Object[] possibleValues = new Object[vec.size ()];
vec.copyInto (possibleValues);
Object selectedValue = SharpOptionPane.showInputDialog(sharp,
"Please select the table you wish to load: ", "Select Table",
0,
/*selectTableIcon*/
connectedIcon,
possibleValues,
possibleValues[0]);
if (selectedValue == null)
return null;
else
return selectedValue.toString ();
}
}
 
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/Formula.java
0,0 → 1,1174
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)Formula.java
*
* $Id: Formula.java,v 1.74 2002/08/08 05:15:04 huaz Exp $
*
* Created October 18, 2000, 3:27 PM
*/
package SharpTools;
import javax.swing.*;
import java.util.*;
import java.io.*;
 
/**
* This is the class for formula processing.
* <p>
* The major public interfaces are:
* <ol>
* <li>Constructors</li>
* <li>Number evaluate(TableModel table, int row, int col)</li>
* <li>String toString()</li>
* <li>TreeSet getDependency()</li>
* </ol>
*
* @see Node
* @see Function
* @see ParserException
*
* @author Hua Zhong <huaz@cs.columbia.edu>
* @version $Revision: 1.74 $
*/
 
public class Formula {
// a static hash table for function handlers
static private HashMap funcTable;
// tokens in order of postfix - used in calculation
private TreeSet dependency;
private LinkedList postfix;
// where the formula is - important to calculate rel_addr
private int row, col;
// the raw formula string
private String formulaString;
// error message
private ParserException error;
 
// whether this formula needs recalculation
private boolean needsRecalc;
/**
* Formula contructor.
*
* This is used to construct a Formula object without any
* parsing process.
*
* @param input the formula string
* @param row the current row where the formula is stored
* @param col the current column where the forluma is stored
* @param e a ParserException
*/
Formula(String input, int row, int col, ParserException e) {
formulaString = input.toUpperCase();
this.col = col;
this.row = row;
error = e;
}
/**
* Formula contructor.
*
* Parse the input string and translate into postfix form.
*
* @param input the formula string
* @param row the current row where the formula is stored
* @param col the current column where the forluma is stored
* @exception ParserException
* @see #toPostfix
*/
Formula(String input, int row, int col) throws ParserException {
 
this.col = col;
this.row = row;
formulaString = input.toUpperCase();
try {
// tokenize and convert the formula to postfix form
LinkedList tokens = tokenize(formulaString);
// Debug.println("Tokens: "+tokens);
dependency = createDependency(tokens);
// Debug.println("Dependency: "+dependency);
postfix = toPostfix(convertParams(tokens));
Debug.println("Postfix: "+postfix);
}catch (ParserException e) {
Debug.println("Formula constructor: "+e);
throwError(e);
}
}
 
/**
* Formula constructor.
*
* This is used for copy/paste. Take a formula and put it into a
* new position, and convert the formula string to make relative
* addresses correct.
*
* @param formula the original formula
* @param row the current(new) row
* @param col the current(old) column
* @exception ParserException
* @see #fixRelAddr
*/
Formula(Formula formula, int row, int col) throws ParserException {
 
this.col = col;
this.row = row;
try {
// do necessary conversion so the formula string
// is still right after changing the position
formulaString = fixRelAddr(formula.formulaString,
row-formula.row,
col-formula.col);
if (formulaString == null) {
formulaString = "$REFS$0";
error = new ParserException("REFS");
return;
}
// tokenize and convert the formula to postfix form
LinkedList tokens = tokenize(formulaString);
dependency = createDependency(tokens);
postfix = toPostfix(convertParams(tokens));
} catch (ParserException e) {
System.err.println("Shouldn't happen!");
throwError(e);
}
}
 
 
 
/**
* Check whether the paste of a formula to a new location is safe.
* A paste is not safe when at the new location relative addresses
* become invalid (e.g., can not use uppercase letters to represent
* the column number, or row number is non-positive).
*
* @param formula the original formula
* @param rowOff the row offset
* @param colOff the column offset
* @return true if it's safe
* @see #fixRelAddr
*/
public static boolean isSafe(Formula formula, int rowOff, int colOff) {
// do necessary conversion so the formula string
// is still right after changing the position
String newString = fixRelAddr(formula.formulaString,
rowOff, colOff);
return newString != null;
}
 
/**
* Check for bad formula.
*
* @return boolean true if postfix
*/
public boolean isBad() {
// postfix was set to null when there was any error
// in processing the formula string
return postfix == null;
}
 
/**
* Check whether needs a recalc
*
* @return boolean true if needs recalculation
*/
public boolean needsRecalc() {
return needsRecalc;
}
/**
* Mark it as needsRecalc
*
* @parem boolean true if needs recalculation
*/
public void setNeedsRecalc(boolean needs) {
needsRecalc = needs;
}
 
/**
* This takes the old formula string and the change of column/row return
* the fixed formula string.
* <p>
* For instance, a string 'A1*B2' should be changed to 'B2*C3' if it's
* moved from A3 to B4.
*
* @param oldFormula the original formula string
* @param col the current(old) column
* @param row the current(new) row
* @return the converted String; null if there is error
*/
public static String fixRelAddr(String oldFormula,
int rowOffset,
int colOffset) {
if (colOffset ==0 && rowOffset == 0)
return oldFormula;
 
StringBuffer newFormulaBuf = new StringBuffer();
int lastPos = 0;
 
for (int i = 0; i < oldFormula.length(); i++) {
char c = oldFormula.charAt(i);
int letterStart = i;
// search for uppercase letters
if (Character.isUpperCase(c)) {
boolean isAbsAddr = (i>0 && oldFormula.charAt(i-1)=='$');
StringBuffer colNameBuf = new StringBuffer();
// collect all the letters
while (i < oldFormula.length() &&
Character.isUpperCase(oldFormula.charAt(i))) {
colNameBuf.append(oldFormula.charAt(i++));
}
 
String colName = colNameBuf.toString();
if (i == oldFormula.length())
break;
// is it followed by digits?
if (!isAbsAddr &&
Character.isDigit(oldFormula.charAt(i))) {
// hey, we get a REL_ADDR here
StringBuffer rowNameBuf = new StringBuffer();
while (i < oldFormula.length() &&
Character.isDigit(oldFormula.charAt(i))) {
rowNameBuf.append(oldFormula.charAt(i++));
}
 
String rowName = rowNameBuf.toString();
// We've got colName and rowName
// add the string before the rel_addr first
newFormulaBuf.append(oldFormula.substring(lastPos,
letterStart));
// then add the new address (string -> number -> string)
if (colOffset == 0)
newFormulaBuf.append(colName);
else {
String col = translateColumn(translateColumn(colName)+
colOffset);
if (col == null)
return null;
newFormulaBuf.append(col);
}
 
if (rowOffset == 0)
newFormulaBuf.append(rowName);
else {
String row = translateRow(translateRow(rowName)+
rowOffset);
if (row == null)
return null;
newFormulaBuf.append(row);
}
lastPos = i;
}
}
}
 
newFormulaBuf.append(oldFormula.substring(lastPos));
return newFormulaBuf.toString();
}
/**
* Tokenize the formula string into a list of Nodes.
*
* @param input the input string to tokenize
* @exception ParserException
*
* @see Node
*/
private LinkedList tokenize(String input) throws ParserException {
LinkedList tokens = new LinkedList();
Stack stack = new Stack();
final Node zero = new Node();
zero.setType(Node.NUMBER);
zero.setNumber(0);
// input.toUpperCase();
 
int cur = 0;
int lastType = Node.DEFAULT;
Node lastToken = null;
// boolean hasRange = false; // has a pending address range
int nParen = 0; // balance of parens
while (cur < input.length()) {
Node node = new Node();
try {
char c = input.charAt(cur++);
node.setData(String.valueOf(c));
if (Character.isLetter(c)) {
// Function or Relative Address
node.setType(Node.FUNCTION);
node.setParams(new LinkedList());
 
// get all preceding letters
while (cur < input.length() &&
Character.isLetter(input.charAt(cur)))
node.appendData(input.charAt(cur++));
if (Character.isDigit(input.charAt(cur))) {
node.setType(Node.REL_ADDR);
// {letters}{numbers} is a relative address
node.setCol(translateColumn(node.getData()) - col);
node.setData("");
while (cur < input.length() &&
Character.isDigit(input.charAt(cur)))
node.appendData(input.charAt(cur++));
// relative row
node.setRow(translateRow(node.getData()) - row);
node.setData(null);
}
}else if (Character.isDigit(c) || c == '.')
/*||
(lastType == Node.DEFAULT ||
lastType == Node.LPAREN || lastType == Node.COMMA) &&
(c == '+' || c == '-')) */{
// Numbers
while (cur < input.length() &&
(Character.isDigit(input.charAt(cur)) ||
input.charAt(cur) == '.'))
// OK, we don't check for input like "3.56.4"
// this will be checked below by parseNumber
node.appendData(input.charAt(cur++));
 
try {
try {
node.setNumber(Integer.parseInt(node.getData()));
}
catch (NumberFormatException e) {
node.setNumber(Float.parseFloat(node.getData()));
}
node.setType(Node.NUMBER);
}catch (NumberFormatException e) {
// invalid number format
throwError("#NUM?");
}
}else if (c == '(') {
nParen++;
node.setType(Node.LPAREN);
}else if (c == ')') {
nParen--;
node.setType(Node.RPAREN);
}else if (c == ',') {
node.setType(Node.COMMA);
}else if (c == ':') {
 
node.setPending(true);
node.setType(Node.COLON);
Node prev = null;
 
try {
prev = (Node)tokens.removeLast();
}
catch (Exception e) {
throwError("#ADDR?");
};
 
if (prev.isType(Node.REL_ADDR) ||
prev.isType(Node.ABS_ADDR)) {
node.setNextRange(prev);
}
else
// invalid address format
throwError("#ADDR?");
}else if (c == '+' || c == '-' || c == '*' || c == '/' ||
c == '^' || c == '%') {
node.setType(Node.OPERATOR);
}else if (c == '$') {
// Absolute Address starts with $
node.setType(Node.ABS_ADDR);
node.setData("");
// a letter must follow the $
if (! Character.isLetter(input.charAt(cur))) {
// invalid address format
throwError("#ADDR?");
}
// look for column
while (Character.isLetter(input.charAt(cur)))
node.appendData(input.charAt(cur++));
 
// absolute address has to be the form of
// ${letters}${numbers}
if (input.charAt(cur++) != '$' ||
! Character.isDigit(input.charAt(cur))) {
// invalid address format
throwError("#ADDR?");
}
 
node.setCol(translateColumn(node.getData()));
node.setData("");
 
while (cur < input.length() &&
Character.isDigit(input.charAt(cur)))
node.appendData(input.charAt(cur++));
 
node.setRow(translateRow(node.getData()));
node.setData(null);
}else if (c == ' ')
continue;
else
// invalid char
throwError("#NAME?");
 
// after a ADDR or NUMBER token the following char
// should not be a letter or digit
if (cur < input.length() && (node.isType(Node.REL_ADDR) ||
node.isType(Node.ABS_ADDR) ||
node.isType(Node.NUMBER)) &&
Character.isLetterOrDigit(input.charAt(cur))) {
throwError
// invalid char
("#NAME?");
}
 
// process the second address of a cell range
if (lastToken != null &&
lastToken.isType(Node.COLON) &&
lastToken.isPending()) {
if (node.isType(Node.REL_ADDR) ||
node.isType(Node.ABS_ADDR)) {
 
Node range = (Node)tokens.removeLast();
 
try {
((Node)range.getNextRange()).setNextRange(node);
range.setPending(false);
}
catch (NullPointerException e) {
// invalid address format
throwError("#ADDR?");
}
 
node = range;
}
else
throwError("#ADDR?");
}
 
 
if (node.isType(Node.OPERATOR) &&
(node.getData().equals("+") ||
node.getData().equals("-")) &&
(lastToken == null || lastToken.isType(Node.LPAREN) ||
lastToken.isType(Node.COMMA))) {
tokens.add(zero);
}
tokens.add(node);
lastType = node.getType();
lastToken = node;
}catch (IndexOutOfBoundsException e) {
// error
throwError("#NAME?");
}catch (ParserException e) {
throwError(e);
}
catch (Exception e) {
Debug.println(e.toString());
}
}
 
if (nParen != 0) // imbalanced parenthesis
throwError("#PAREN?");
return tokens;
}
 
/**
* Convert function parameters. From a linear sequence of nodes,
* output a tree-like structure, with all the functions having a
* linked list of parameters, and each parameter having a linked
* list of nodes (that is, each parameter can be a formula).
*
* The basic rules are:
* <ol>
* <li>Pass values to the output (a linked list used as a stack) except
* the following.</li>
* <li>If a function name is encountered, it's set to "pending" (meaning
* it's expecting an enclosing parenthesis) and passed to the output, and
* its following '(' is discarded.</li>
* <li>If a left parenthesis is encountered, it's set to "pending"
* and passed to the output.</li>
* <li>If a comma is encountered, pop up all the previous nodes to a list
* until an unpending function node is found. Then set the list having
* all the popped nodes as the function's last parameter. The function
* node is pushed back.</li>
* <li>For a ')', pop all the previous nodes to a list until an unpending
* left parenthesis or an unpending function is found. For the former,
* the left parenthesis is set to "unpending", and push back all the
* popped nodes (including the right parenthesis). For the latter,
* it's the same as the comma case, except that the function node is
* set to "unpending".</li>
* </ol>
*
*/
private LinkedList convertParams(final LinkedList tokens)
throws ParserException {
if (tokens == null) {
throw error;
}
 
LinkedList stack = new LinkedList();
 
Iterator it = tokens.iterator();
 
try {
while (it.hasNext()) {
Node node = (Node)it.next();
 
if (node.isType(Node.FUNCTION)) {
node.setPending(true);
stack.add(node);
node = (Node)it.next();
// should be LParen
if (!node.isType(Node.LPAREN)) // ( expected
throwError("#NO(?");
}
else if (node.isType(Node.LPAREN)) {
node.setPending(true);
stack.add(node);
}
else if (node.isType(Node.COMMA)) {
Node exp = new Node();
LinkedList list = new LinkedList();
Node param = (Node)stack.removeLast();//pop();
// pop out until the unpending FUNCTION
while (!param.isType(Node.FUNCTION) ||
!param.isPending()) {
list.addFirst(param);
param = (Node)stack.removeLast();//pop();
}
 
exp.setType(Node.EXP);
exp.setExp(list);
 
param.addParam(exp);
 
// still pending
// stack.push(param);
stack.add(param);
}
else if (node.isType(Node.RPAREN)) {
// we don't know whether this is for a function.
Node exp = new Node();
LinkedList list = new LinkedList();
Node param = (Node)stack.removeLast(); //stack.pop();
 
// process the last parameter
while (!param.isPending() ||
!param.isType(Node.FUNCTION) &&
!param.isType(Node.LPAREN)) {
list.addFirst(param);
param = (Node)stack.removeLast();//pop();
}
 
// set to unpending
if (param.isType(Node.LPAREN)) {
// this is a normal left paren
param.setPending(false);
// push back
stack.add(param);
stack.addAll(list);
stack.add(node);
}
else {
// this is a function left paren
// Debug.println("exp is "+list);
// set the expression of that parameter
exp.setType(Node.EXP);
exp.setExp(list);
// add a parameter for the function
param.addParam(exp);
param.setPending(false);
stack.add(param);
}
}
else
stack.add(node); //push(node);
}
}
catch (ParserException e) {
throw e;
}
catch (Exception e) {
Debug.println(e);
// general param error
throwError("#PARAM?");
}
 
return stack;
}
/**
* This converts tokens to postfix format using stack.
* <p>
* The basic rules are:
* <ol>
* <li>Pass values to the output (a linked list)</li>
* <li>Push '(' to the stack</li>
* <li>For an operator, pop all the previous operators that have a lower
* priority to the output and push this one to the stack</li>
* <li>For ')', pop all the previous operators until a (</li>
* <li>If we reach the end, pop up everything</li>
* </ol>
*
* @param tokens a linked list to convert
* @exception ParserException
*
* @see Node
* @see #tokenize
* @see #convertParam
*/
private LinkedList toPostfix(LinkedList tokens) throws ParserException {
if (tokens == null) {
throw error;
}
 
// stack is used for the conversion
Stack stack = new Stack();
LinkedList postfix = new LinkedList();
Iterator it = tokens.iterator();
while (it.hasNext()) {
Node node = (Node)it.next();
switch (node.getType()) {
 
case Node.NUMBER:
case Node.REL_ADDR:
case Node.ABS_ADDR:
case Node.COLON:
// just add normal values to the list
postfix.add(node);
break;
case Node.LPAREN:
// push to stack; pop out when a RPAREN is encountered
stack.push(node);
break;
case Node.OPERATOR:
// get the precedence priority of the operator
int priority = getPriority(node);
 
// pop up operators with the same or higher priority from
// the stack
while (! stack.empty() &&
! ((Node)stack.peek()).isType(Node.LPAREN) &&
getPriority((Node)stack.peek()) >= priority) {
postfix.add((Node)stack.pop());
}
stack.push(node);
break;
case Node.RPAREN:
try {
Node op = (Node)stack.pop();
// pop out until the last LPAREN
while (! op.isType(Node.LPAREN)) {
postfix.add(op);
op = (Node)stack.pop();
}
}
catch (EmptyStackException e) {
// should not happen - imbalance in parenthesis
throwError("#PAREN?");
}
break;
case Node.FUNCTION:
 
// get the param list
LinkedList params = node.getParams();
 
Iterator paramIter = params.iterator();
 
while (paramIter.hasNext()) {
Node exp = (Node)paramIter.next();
exp.setExp(toPostfix(exp.getExp()));
}
 
postfix.add(node);
break;
default:
// unknown error - should not happen
throwError("#ERROR?");
}
}
 
// pop up the rest nodes
while (!stack.empty())
postfix.add((Node)stack.pop());
 
return postfix;
}
/**
* From a list of tokens generate a set of cells that this cell depends on.
*
* We do this before the postfix thing since the original token
* list has no nested stuff.
*
* @param tokens a list of tokens (nodes)
* @return a set of cells being referenced
*/
private TreeSet createDependency(LinkedList tokens) {
TreeSet dependency = new TreeSet();
Iterator it = tokens.iterator();
while (it.hasNext()) {
Node node = (Node)it.next();
if (node.isType(Node.REL_ADDR) || node.isType(Node.ABS_ADDR)) {
// for addresses, translate into CellPoint (absolute point)
CellPoint newCell = node.toCellPoint(row, col);
dependency.add(newCell);
} else if (node.isType(Node.COLON)) {
// all the cells in this range are referenced
CellPoint[] addr = node.getAddressRange(row, col);
for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
for (int j = addr[0].getCol(); j <= addr[1].getCol();
j++)
dependency.add(new CellPoint(i, j));
}
}
return dependency;
}
/**
* From the Node list; Creates the dependency set.
*
* @return a TreeSet of CellPoint that the current cell references
*/
 
public TreeSet getDependency() {
if (isBad()) {
// Debug.println("Bad formula: "+formulaString);
return new TreeSet();
}
 
return dependency;
}
 
/**
* This gets the priority of an operator.
*
* @param op the operator character
* @return 1='+' '-', 2='*' '/', 3='^'
*/
private static int getPriority(char op) {
switch (op) {
 
case '+':
case '-':
return 1;
case '*':
case '/':
case '%':
return 2;
case '^':
return 3;
default:
return 0;
}
}
 
/**
* This returns the highest-priority node.
*/
private static int getPriority(Node node) {
return getPriority(node.getData().charAt(0));
}
 
/**
* This returns the string value of the formula.
*
* @return the string value
*/
public String toString() {
return formulaString;
}
 
/**
* This takes an operator and two operands and returns the result.
*
* @param op the operator
* @param op1 operand 1
* @param op2 operand 2
* @return the float value of operand 1 operator operand 2
*/
private static Number calc(char op, Number op1, Number op2) {
float n1 = op1.floatValue();
float n2 = op2.floatValue();
float result;
switch (op) {
case '+': result = n1+n2; break;
case '-': result = n1-n2; break;
case '*': result = n1*n2; break;
case '/': result = n1/n2; break;
case '^': result = (float)Math.pow(n1, n2); break;
case '%': result = (float)((int)n1%(int)n2); break;
default: result = 0; break;
}
 
return new Float(result);
}
 
/**
* This evaluates the function.
*
* @param table the TableModel object
* @param node the head node of the function
* @return the value as a Float object
* @exception ParserException
*/
static private Number evalFunction(SharpTableModel table, Node node, int row, int col) throws ParserException {
String funcName = node.getData();
// get function handler from the funcTable
Function func=getFuncHandler(funcName);
 
if (func == null) {
// not registered function
throw new ParserException("#FUNC?");
}
else
{
return func.evaluate(table, node, row, col);
}
}
/**
* Evaluates the cell (row, col) of table.
*
* @param table the TableModel object
* @param row the row of the cell to be evaluated
* @param col the column of the cell to be evaluated
* @return the result as a Float object
* @exception ParserException
*/
public static Number evaluate(SharpTableModel table, int row, int col)
throws ParserException {
 
if (Debug.isDebug())
Debug.println("recalculating "+new CellPoint(row, col));
 
// get the formula object
Formula formula = table.getCellAt(row, col).getFormula();
formula.setNeedsRecalc(false);
if (formula == null)
return new Integer(0);
else
return formula.evaluate(table);
}
 
/**
* This is a private function only used internally.
* Evaluates the current formula of table.
*
* @param table the TableModel object
* @return the result as a Float object
* @exception ParserException
*/
private Number evaluate(SharpTableModel table) throws ParserException {
// if the formula is bad, directly returns the error
if (isBad()) {
throw error;
}
return evaluate(table, postfix, row, col);
}
/**
* It evaluates the postfix expression by a stack.
*
* @param table the TableModel object
* @param postfix the formula in postfix form
* @param row the row of the cell to be evaluated
* @param col the column of the cell to be evaluated
* @return the result as a Float object
* @exception ParserException
*/
static public Number evaluate(SharpTableModel table, LinkedList postfix,
int row, int col)
throws ParserException {
 
try {
Stack stack = new Stack();
Iterator it = postfix.iterator();
while (it.hasNext()) {
Node node = (Node)it.next();
//Number result;
Number result;
switch (node.getType()) {
case Node.OPERATOR:
// pop the 2 operands from stack top and save the result
// back to stack
Number n2 = (Number)stack.pop();
Number n1 = (Number)stack.pop();
result = calc(node.getData().charAt(0), n1, n2);
break;
case Node.FUNCTION:
// // evaluate the function
result = evalFunction(table, node, row, col);
break;
case Node.NUMBER:
// directly return the number
result = new Float(node.getNumber());
break;
case Node.ABS_ADDR:
// get the numeric value of that cell
result = //getNumericValueAt(table, node.getRow(),
// node.getCol());
table.getNumericValueAt(node.getRow(), node.getCol());
break;
case Node.REL_ADDR:
// get the numeric value of that cell
result = //getNumericValueAt(table, node.getRow()+row,
// node.getCol()+col);
table.getNumericValueAt(node.getRow()+row,
node.getCol()+col);
break;
default:
// evaluation error
throw new ParserException("#EVAL?");
}
 
// push to the stack
stack.push(result);
}
Number result = (Number)stack.pop();
return result;
}catch (EmptyStackException e) {
// imbalance between operands and operators
throw new ParserException("#OP?");
// ("Wrong format of formula: too many operators");
}catch (ParserException e) {
throw e;
}catch (Exception e) {
Debug.println(e);
 
}
 
return new Integer(0);
}
// The following are just simple functions
/**
* This translates the string form of row into row number ('12' -> 12),
* and vice versa.
*
* @param row the string representation of the row
* @return the int representation of the row
*/
final private static int translateRow(String row) {
return Node.translateRow(row);
}
 
/**
* This translates the int form of row into row string (12 -> '12').
*
* @param row the int representation of the row
* @return the string representation of the row
*/
final private static String translateRow(int row) {
return Node.translateRow(row);
}
 
/**
* This translates the int form of column into column string (1 -> 'A')
*
* @param column the int representation of the column
* @return the string represetnation of the column
*/
final private static int translateColumn(String column) {
return Node.translateColumn(column);
}
 
/**
* This translates the string form of column into column number ('A' -> 1)
*
* @param column the string representation of the column
* @return the int represetnation of the column
*/
final private static String translateColumn(int column) {
return Node.translateColumn(column);
}
 
/**
* Label the bad cells and throw ParserException.
* error is saved so next time it won't re-evaluate again:
* it directly throws the same exception.
*
* @param s the thing that's bad
* @exception ParserException
*/
private void throwError(Object s) throws ParserException {
// test code
// System.err.println("Marking formula "+formulaString+" as bad");
postfix = null;
if (error instanceof ParserException)
throw (ParserException)s;
else {
error = new ParserException(s);
throw error;
}
}
 
/**
* Gets the string form of the cell address ("A1", "B2", etc).
*
* @return the string value of the Cell
*/
private String getCellString() {
return getCellString(row, col);
}
/**
* Gets the string form of the cell address ("A1", "B2", etc).
*
* @param row the row coordinate
* @param col the column coordinate
* @return the string value of the Cell
*/
final static private String getCellString(int row, int col) {
return ""+translateColumn(col)+translateRow(row);
}
 
final static public CellPoint parseAddress(String s) {
 
try {
int row, col;
 
s = s.toUpperCase();
int len = 0;
int total = s.length();
StringBuffer buf = new StringBuffer();
char c;
while (len < total) {
c = s.charAt(len);
if (Character.isUpperCase(c)) {
buf.append(c);
len++;
}
else if (Character.isDigit(c))
break;
else
return null;
}
col = translateColumn(buf.toString());
if (col == 0)
return null;
buf = new StringBuffer();
while (len < total) {
c = s.charAt(len);
if (Character.isDigit(c)) {
buf.append(c);
len++;
}
else
return null;
}
row = translateRow(buf.toString());
if (row == 0)
return null;
return new CellPoint(row, col);
}
catch (Exception e) {
return null;
}
}
 
/**
* Adds a function to the function table.
*
* @param funcName the name of the function
* @param func the Function object
* @see Function
*/
static private void register(String funcName, Function func) {
funcTable.put(funcName, func);
}
/**
* Registers the functions on the funcTable.
* Should be called only once....well not for an applet
*/
static public void registerFunctions() {
funcTable = new HashMap();
register("SUM", new FunctionSum());
register("MEAN", new FunctionAverage());
register("AVERAGE", new FunctionAverage());
register("MEDIAN", new FunctionMedian());
register("ABS", new FunctionAbs());
register("INT", new FunctionInt());
register("ROUND", new FunctionRound());
register("SIN", new FunctionSin());
register("COS", new FunctionCos());
register("TAN", new FunctionTan());
register("ASIN", new FunctionAsin());
register("ACOS", new FunctionAcos());
register("ATAN", new FunctionAtan());
register("SQRT", new FunctionSqrt());
register("LOG", new FunctionLog());
register("MIN", new FunctionMin());
register("MAX", new FunctionMax());
register("RANGE", new FunctionRange());
register("STDDEV", new FunctionStddev());
register("MEANDEV", new FunctionMeandev());
register("COUNT", new FunctionCount());
register("PI", new FunctionPI());
register("E", new FunctionE());
}
 
/*
* provide a way to access these function handlers
*
* @param fname the function name
* @return the function object that can evaluate the specified function.
*
* @see Funciton
* @see SharpTools
*/
static public Function getFuncHandler(String fname) {
//jm.evers : needed by applet
registerFunctions();
return (Function)funcTable.get(fname);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/Config.java
0,0 → 1,242
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)SharpTools.java
*
* $Id: Config.java,v 1.11 2001/05/27 05:20:44 huaz Exp $
*
* Created on October 10, 2000, 1:15 AM
*/
package SharpTools;
import java.util.*;
import java.io.*;
 
/**
* This class reads configuration file and provides get functions for
* other classes to retrieve the information.
*
* This provides a central repository for global information.
*
* Note, Config only saves a pair when the key is already in the config file.
* This is very important!!!
*
* @author Hua Zhong <huaz@cs.columbia.edu>
* @version $Revision: 1.11 $
*/
 
final class Config {
 
private HashMap map;
private File file;
private boolean modified;
Config(String filename) {
modified = false;
map = new HashMap();
file = new File(filename);
}
 
// load from file
public void load() {
Debug.println("Loading configuration file...");
try {
// open the file
BufferedReader in = new BufferedReader
(new FileReader(file));
String line;
while ((line = in.readLine()) != null) {
 
// convert to <key,value> pair
String[] pair = getPair(line);
if (pair == null)
continue;
 
// key must not be empty
if (pair[0] == null || pair[0].length() == 0)
continue;
 
map.put(pair[0], pair[1]);
}
}
catch (IOException e) {
}
catch (Exception e) {
System.err.println("error parsing config file: "+e);
}
 
modified = false;
//Debug.println(map);
}
 
// save to file
public void save() {
if (!modified)
return;
Debug.println("Saving configuration file...");
String tmpfilename = file+".tmp";
File tmp = new File(tmpfilename);
try {
// open the file
BufferedReader in = new BufferedReader
(new FileReader(file));
PrintWriter out = new PrintWriter
(new BufferedWriter
(new FileWriter(tmp)));
String line;
while ((line = in.readLine()) != null) {
String[] pair = getPair(line.toUpperCase());
 
if (pair != null && pair[0] != null &&
map.get(pair[0]) != null)
out.println(pair[0]+'='+map.get(pair[0]));
else
out.println(line);
 
}
 
in.close();
out.close();
}
catch (IOException e) {
System.err.println("io error saving config file: "+e);
return;
}
catch (Exception e) {
System.err.println("error saving config file: "+e);
return;
}
 
// move tmp file bak
file.delete();
tmp.renameTo(file);
modified = false;
}
/**
* If a string is of form "Str1=Str2", return a pair
*
* @param line input string
* @return a pair of (key, value); null if it's not a pair
*/
private String[] getPair(String line) {
int index = line.indexOf('=');
if (index < 0)
return null;
 
// ignore comments
if (line.startsWith("#") || line.startsWith(";"))
return null;
String[] pair = new String[2];
pair[0] = line.substring(0, index).trim();
pair[1] = line.substring(index+1).trim();
return pair;
}
 
/**
* get value by string name
*
* @param key the variable name
* @return the value as a string
*/
public String get(String key) {
return (String)map.get(key);
}
 
/**
* get integer value by string name
*
* @param key the variable name
* @return the value as an integer; -1 if not available
*/
public int getInt(String key) {
String value = (String)map.get(key);
if (value == null)
return -1;
 
int intValue = -1;
try {
intValue = Integer.parseInt(value);
}
catch (NumberFormatException e) {
// Debug.println("Return -1 for "+key+";"+value);
return -1;
}
 
return intValue;
}
 
/**
* get boolean value by string name
*
* @param key the variable name
* @return the value as boolean; FALSE by default
*/
public boolean getBoolean(String key) {
String value = (String)map.get(key);
if (value == null)
return false;
 
return value.equals("TRUE");
}
 
/**
* set value by string name
*
* @param key the variable name
* @param the value as a string
*/
public void set(String key, String value) {
modified = true;
map.put(key, value);
}
 
/**
* set integer value by string name
*
* @param key the variable name
* @param the value as an integer
*/
public void setInt(String key, int value) {
set(key, String.valueOf(value));
}
 
/**
* set boolean value by string name
*
* @param key the variable name
* @param value the boolean value
*/
public void setBoolean(String key, boolean value) {
set(key, value?"TRUE":"FALSE");
}
}
 
 
 
 
 
 
 
 
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SharpTableModel.java
0,0 → 1,1742
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)SharpTable.java
*
* $Id: SharpTableModel.java,v 1.91 2002/08/08 05:15:07 huaz Exp $
*
* Created on October 14, 2000, 8:10 PM
*/
package SharpTools;
 
import java.util.*;
import java.io.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.TableModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableColumnModelEvent;
 
/** This is the table data structure of the spreadsheet (i.e. the heart of
* the backend). Although this class implements the methods needed for
* <code>TableModel</code>, it also has methods for maintaining dependencies
* and some data manipulation.
* <P>
* Note: This structure only holds Cell objects! It's methods take into account
* the Cell object. If you modified the cell class please check the methods
* in this class.
* @author Ricky Chin
* @version $Revision: 1.91 $
*/
public class SharpTableModel extends DefaultTableModel {
/** Stores modified state of document
*/
private boolean modified;
/** true if password has been changed
*/
private boolean passwordModified;
/** Stores file name of current document */
private SharpTools sharp;
/** holds the history information for the table
*/
private History history;
 
/** Constructs a default SharpTableModel which is a table
* of zero columns and zeros rows.
* @param sharp the gui component to tie it to
*/
public SharpTableModel(SharpTools sharp) {
super();
 
// initialize state to unmodified and file to untitled
modified = false;
this.sharp = sharp;
}
 
/** This constructor creates an empty table with numRow rows and numCol
* columns including the row and column label row and column.
* <P>
* The zeroth column are headers. The rows are numbered
* 1, 2, ... and columns are labeled A, B, ... . Thus, it really holds
* numRow X numCol-1 of data. The table is initialized with no cell
* objects. Each coordinate that will have data will have a cell object
* created for it later by the getCell method.
* @param sharp gui object to associated with this SharpTableModel
* @param numRows total number of rows including row header
* @param numColumns total number of columns including column header
*/
public SharpTableModel(SharpTools sharp, int numRows, int numColumns) {
super(numRows, numColumns+1);
//initialize row headers
for(int row = SharpTools.baseRow; row < numRows; row++) {
Cell temp = new Cell(new Integer(row+1));
super.setValueAt(temp, row, 0);
}
 
//initialize column headers
/*
for (int col = 1; col < numColumns; col++) {
Cell temp = new Cell(Node.translateColumn(col));
super.setValueAt(temp, 0, col);
}
*/
for(int row = SharpTools.baseRow; row < numRows; row++)
for (int col = SharpTools.baseCol; col < numColumns+1; col++)
// we initialize it here
super.setValueAt(new Cell(""), row, col);
 
// initialize state to unmodified and file to untitled
modified = false;
this.sharp = sharp;
}
 
/** This constructor is convenience for loading objects that are already in
* an array. It fills the SharpTableModel with the objects in the array
* making Object[0][0] be in cell A1, etc.
* <P>
* <B>Note:</B> This constructor does not assume that objects are of the
* desired form. It will parse a string to see if it is a number or
* formula.
* @param sharp gui object to associate with this SharpTableModel
* @param data the array of objects to place into the SharpTableModel
*/
public SharpTableModel(SharpTools sharp, Object[][] data) {
 
this(sharp, data.length + SharpTools.baseRow/*+ 1*/,
data[0].length + SharpTools.baseCol);
 
/* load the data */
for(int i = SharpTools.baseRow; i < data.length; i++) {
for(int j = SharpTools.baseCol; j < data[i].length; j++) {
doSetValueAt(data[i][j], i, j);
}
}
 
// initialize state to unmodified and file to untitled
modified = false;
// file = new File("Untitled");
this.sharp = sharp;
}
 
/**
* This is used to return the column name
*/
public String getColumnName(int col) {
Debug.println("name of column "+col);
if (col < SharpTools.baseCol)
return "";
else
return String.valueOf(Node.translateColumn(col));
}
/** This method associated the proper undo object to this SharpTableModel.
* It must be called right after the constructor.
* @param h the History object to associate with this SharpTableModel
*/
void setHistory(History h) {
history = h;
}
/**
* This method gets the whole Cell object located at the these
* coordinates. This method avoids the casting required when using
* getValueAt.
*
* Note: here we need to make row 1-based.
*
* <P>
* If the coordinates specify a cell that is out of bounds then it returns
* null. If a cell does not exist in the SharpTableModel at that valid
* coordinate, it creates an empty cell, places it at that spot and returns
* it.
*
* @param aRow the row of the cell
* @param aColumn the column of the cell
* @return the Cell object at this location
*/
public Cell getCellAt(int aRow, int aColumn) {
/* check for out of bounds */
if (aRow < 0 || aRow >= getRowCount() ||
aColumn < 0 || aColumn >= getColumnCount()) {
return null;
}
 
Cell temp = (Cell)super.getValueAt(aRow, aColumn);
return temp;
}
 
/** This class returns the cell object at those coordinates. It does
* exactly the same thing as getCellAt except that the return type is
* Object. It is implemented because TableModel requires this method
* return an Object.
*
* @param aRow the row coordinate
* @param aColumn the column coordinate
* @return the Cell
*/
public Object getValueAt(int aRow, int aColumn) {
return getCellAt(aRow, aColumn);
}
 
/**
* This is a warper method of the Formula class's evaluate method. This
* method recalculates the value of a formula at the given coordinates.
* If the coordinates do not specify a formula it does nothing.
*
* @param aRow the row coordinate
* @param aColumn the column coordinate
*/
 
public void recalculate(int aRow, int aColumn) {
if (isFormula(aRow, aColumn)) {
 
try {
Debug.println("recalculate");
Number eVal = Formula.evaluate(this, aRow, aColumn);
//we set the value here
getCellAt(aRow, aColumn).setValue(eVal);
}
catch (ParserException e) {
//set value as the appropriate error message
getCellAt(aRow, aColumn).setValue(e);
}
}
}
 
/**
* This is the version of recalculate that takes a CellPoint object as an
* argument.
*
* @param x the coordinates of the cell to be updated
*/
public void recalculate(CellPoint x) {
recalculate(x.getRow(), x.getCol());
}
 
/** This is a static method that parses string input passed to it from
* somewhere else. It parses the input and returns the appropriate object
* including formula object. It is used to create appropriate objects to
* pass to the other methods in table model.
* @param input the input string to parse
* @param c the point in table where this input to be placed
* @return the appropriate object after parsing
*/
private static Object fieldParser(String input, CellPoint c) {
if (input == null)
return new String("");
int row = c.getRow();
int col = c.getCol();
/* try making it a formula */
if (input.startsWith("=")) {
Formula form = null;
//create formula and its value and put in a cell
try {
return new Formula(input.substring(1), row, col);
}catch (ParserException e) {
// no parsing
return new Formula(input.substring(1), row, col, e);
}
}else {
/* try making it a number */
try {
// try {
// return new Integer(input);
// }
// catch (NumberFormatException e) {
return new Float(input);
// }
}catch (NumberFormatException e2) {
/* all else fails treat as string */
return input;
}
}
}
/** This method does not recognize formula strings. It is used for dialogue
* box input where there will be no formulas inputted or expected to be
* inputted.
* @param input input string to parse
* @return appropriate object after parsing
*/
public static Object fieldParser(String input) {
if (input == null)
return new String("");
/* try making it a number */
try {
return new Float(input);
}catch (NumberFormatException e) {
/* all else fails treat as string */
return input;
}
}
 
/** Sets the value of the cell. It takes care of formulas and data.
* If aValue is a string, it parses it to see if it is a formula (begins
* with an "=") or a number. It then sets the value of the cell
* accordingly.
* <P>
* This function is called by JTable automatically, which means
* user has manually input something. Thus, it records the previous value
* of the cell into the History object associated with this SharpTableModel.
* <p>
* We should never call it directly (use doSetValueAt instead).
* @param aValue the formula or data you want to set cell to
* @param aRow row coordinate
* @param aColumn column coordinate
*/
public void setValueAt(Object aValue, int aRow, int aColumn) {
CellPoint point = new CellPoint(aRow, aColumn);
history.add(this, new CellRange(point, point));
doSetValueAt(aValue, aRow, aColumn);
}
/** This method sets the value of the cell specified with these coordinates
* to aValue. It does the parsing of string objects to see if they are
* numbers or formulas. If you do not want any parsing at all, use
* setCellAt.
* @param aValue value to set cell to
* @param aRow row coordinate of cell
* @param aColumn column coordinate of cell
*/
public void doSetValueAt(Object aValue, int aRow, int aColumn) {
 
if (aValue == null)
aValue = new String("");
if (aValue instanceof String) {
 
String input = (String)aValue;
/* try making it a formula */
if (input.startsWith("=")) {
Formula form = null;
//create formula and its value and put in a cell
try {
form = new Formula(input.substring(1),
aRow, aColumn);
setCellAt(form, aRow, aColumn);
}
catch (ParserException e) {
// no parsing
form = new Formula(input.substring(1), aRow, aColumn, e);
setCellAt(form, aRow, aColumn);
getCellAt(aRow, aColumn).setValue(e);
}
}else {
 
// try {
// Integer idata = new Integer(input);
// setCellAt(idata, aRow, aColumn);
// }
/* if it begins with "=" but invalid just
* treat as a string
*/
// catch (NumberFormatException e) {
/* try making it a number */
try {
Float data = new Float(input);
setCellAt(data, aRow, aColumn);
}
/* if it begins with "=" but invalid just
* treat as a string
*/
catch (NumberFormatException e2) {
/* all else fails treat as string */
setCellAt(aValue, aRow, aColumn);
}
// }
}
}else {
/* it is an object, assume it is exactly
* what should the cell be set to
*/
if (aValue instanceof Formula) {
try {
Formula form = (Formula)aValue;
setCellAt(new Formula(form, aRow, aColumn), aRow, aColumn);
}catch (ParserException e) {
// errorMessage(e.toString());
Formula form2 = (Formula)aValue;
form2 = new Formula(form2.toString(), aRow, aColumn, e);
setCellAt(form2, aRow, aColumn);
getCellAt(aRow, aColumn).setValue(e);
}
}else {
setCellAt(aValue, aRow, aColumn);
}
}
}
/** This object assumes that the object passes to it is already the
* correct object to set the value of the cell as. For a formula, it
* also calculcates the value of the formula and records that in the cell.
* @param input object to set the Cell value as
* @param aRow row of cell to set
* @param aColumn column of cell to set
*/
public void setCellAt(Object input, int aRow, int aColumn) {
Cell temp = getCellAt(aRow, aColumn);
 
/* if for some reason value out of bounds ignore */
if (temp != null) {
 
//always remove references old formula referred to
removeRefs(aRow, aColumn);
//insert new formula
if (input instanceof Formula) {
temp.setFormula((Formula)input);
 
if (isLoop(new CellPoint(aRow, aColumn))) {
ParserException loop = new ParserException("#LOOP?");
Formula form2 = new Formula(input.toString(), aRow, aColumn, loop);
setCellAt(form2, aRow, aColumn);
getCellAt(aRow, aColumn).setValue(loop);
updateRefs(aRow, aColumn);
return;
}else {
addRefs(aRow, aColumn);
recalculate(aRow, aColumn);
updateRefs(aRow, aColumn);
 
}
}else {
//treat as normal data cell
temp.setData(input);
updateRefs(aRow, aColumn);
}
}
}
 
/** This method sets the cells given by the range to the cooresponding value
* in the Object array. In other words, this method pastes the object array
* onto the range. It is assumed that the range and Object array have the
* same dimensions. (a "placeAt" method for ranges)
* @param range the range of cells to paste to
* @param data the data to paste
*/
public void setRange(CellRange range, Object[][] data) {
/* Loop through the paste range */
for (int i = range.getStartRow(); i <= range.getEndRow(); i++) {
for (int j = range.getStartCol(); j <= range.getEndCol(); j++) {
//calculate the corresponding entry in data array
int x = i - range.getStartRow();
int y = j - range.getStartCol();
//place data entry at that place
doSetValueAt(data[x][y], i, j);
}
}
}
/**
* This is a method used to paste cells onto the table. This method
* is used by the SharpClipboard class. It's feature is that it can
* paste only the old evaluated values or it can be told to paste
* the data cells and formulas.
*
* @param range range to paste to
* @param data cells that need to be pasted
* @param byValue true if only paste values if there are formula
*/
public void setRange(CellRange range, Cell[][] data, boolean byValue) {
/* there may be formula so if byValue is true paste evaluated formula
* value into the range as a data cell
*/
if (byValue) {
for (int i = range.getStartRow(); i <= range.getEndRow(); i++) {
for (int j = range.getStartCol(); j <= range.getEndCol(); j++) {
int x = i - range.getStartRow();
int y = j - range.getStartCol();
//get only value of a formula cell not formula
doSetValueAt(data[x][y].getValue(), i, j);
}
}
}else {
for (int i = range.getStartRow(); i <= range.getEndRow(); i++) {
for (int j = range.getStartCol(); j <= range.getEndCol(); j++){
int x = i - range.getStartRow();
int y = j - range.getStartCol();
Cell info = data[x][y];
//paste new formula to recalculate
if (info.isFormula()) {
doSetValueAt(info.getFormula(), i, j);
}else {
doSetValueAt(info.getValue(), i, j);
}
}
}
}
}
/**
* This method clears all cells in the range but leaves the
* reference lists alone.
*
* @param range range to clear
*/
public void clearRange(CellRange range) {
fill(range, null);
}
protected void fillRange(CellRange range, String s) {
fill(range, SharpTableModel.fieldParser(s, range.getminCorner()));
}
/**
* This method is used to implement the fills of the spreadsheet.
* It takes a range and fills the range with the object. For formula,
* it is equivalent to pasting the formula on every cell in the range.
*
* @param range range to fill
* @param input object to fill range with
*/
protected void fill(CellRange range, Object input) {
//loop through range
for (int i = range.getStartRow(); i <= range.getEndRow(); i++) {
for (int j = range.getStartCol(); j <= range.getEndCol(); j++) {
doSetValueAt(input, i, j);
}
}
}
/** This searches of an object starting from a cell point.
* @param begin cellpoint to begin search
* @param goal the object to search for
* @param matchCase true if case sensitive (only active if goal is a string)
* @param matchCell true if goal must equal entire content of cell (only
* active if goal is a string)
* @return the CellPoint of next occurence of goal
*/
public CellPoint look(CellPoint begin, Object goal, boolean matchCase,
boolean matchCell) {
int startRow = begin.getRow();
int startCol = begin.getCol();
if ((goal instanceof String) && !matchCase && matchCell) {
String objective = (String)goal;
for(int i = startCol; i < getColumnCount(); i++) {
if (objective.equalsIgnoreCase(
getCellAt(startRow, i).getValue().toString())) {
return new CellPoint(startRow, i);
}
}
for(int i = startRow + 1; i < getRowCount(); i++) {
for(int j = 1; j < getColumnCount(); j++) {
if (objective.equalsIgnoreCase(
getCellAt(i, j).getValue().toString())) {
return new CellPoint(i, j);
}
}
}
return null;
}else {
if ((goal instanceof String) && !matchCell) {
String objective = (String)goal;
for(int i = startCol; i < getColumnCount(); i++) {
String test = getCellAt(startRow, i).getValue().toString();
if (!matchCase) {
objective = objective.toUpperCase();
test = test.toUpperCase();
}
for(int k = 0; k < test.length(); k++) {
if (test.startsWith(objective, k)) {
return new CellPoint(startRow, i);
}
}
}
for(int i = startRow + 1; i < getRowCount(); i++) {
for(int j = 1; j < getColumnCount(); j++) {
String test = getCellAt(i, j).getValue().toString();
if (!matchCase) {
objective = objective.toUpperCase();
test = test.toUpperCase();
}
for(int k = 0; k < test.length(); k++) {
if (test.startsWith(objective, k)) {
return new CellPoint(i, j);
}
}
}
}
return null;
}else {
for(int i = startCol; i < getColumnCount(); i++) {
if (goal.equals(getCellAt(startRow, i).getValue())) {
return new CellPoint(startRow, i);
}
}
for(int i = startRow + 1; i < getRowCount(); i++) {
for(int j = 1; j < getColumnCount(); j++) {
if (goal.equals(getCellAt(i, j).getValue())) {
return new CellPoint(i, j);
}
}
}
return null;
}
}
}
/**
* This method copies the cells in a range
* into a two-dimensional array of cells.
*
* @param range range of cells to copy
* @return copy of range
*/
public Cell[][] getRange(CellRange range) {
//get dimensions of range
Cell[][] board = new Cell[range.getHeight()][range.getWidth()];
//copy the cells
for (int i = range.getStartRow(); i <= range.getEndRow(); i++) {
for (int j = range.getStartCol(); j <= range.getEndCol(); j++) {
//translate to coordinates in copy array
int x = i - range.getStartRow();
int y = j - range.getStartCol();
Cell field = getCellAt(i, j);
/* if it is a formula copy both the value and the formula
* The value will be useful with a paste by value
*/
if (field.isFormula()) {
try {
Formula form = new Formula(field.getFormula(), i, j);
board[x][y] = new Cell(form, field.getValue(), null);
}catch (ParserException e) {
/* if there is a problem, always treat formula
* as a string.
*/
board[x][y] = new Cell(field.getFormula().toString());
}
}else {
//value cells have immutable objects
board[x][y] = new Cell(field.getValue());
}
}
}
return board;
}
 
/**
* This method should be called with a cell is set as a formula
* cell (although it does nothing if it is not a formula). When a formula
* is entered, it may reference other cells. These cells need to be
* notified that if they are changed, to notify this formula cell.
* This method adds the cell coordinates to the reference list of each
* cell that the formula references.
*
* @param aRow row of formula cell
* @param aColumn column of formula cell
*/
public void addRefs(int aRow, int aColumn) {
if (isFormula(aRow, aColumn)) {
Formula temp = getCellAt(aRow, aColumn).getFormula();
TreeSet list = temp.getDependency();
/* use formula's dependency to find cells
* that need to notify it if their values
* change
*/
Iterator it = list.iterator();
CellPoint thisRef = new CellPoint(aRow, aColumn);
while (it.hasNext()) {
CellPoint update = (CellPoint)it.next();
Cell field = getCellAt(update.getRow(), update.getCol());
//test of cell found was out of bounds
if (field != null)
field.addRef(thisRef);
}
}
}
/**
* This method removes this formula cell from the reference lists of all
* cells it references. If this is not a formula cell, it does nothing.
* This method should be called with a formula cell is being changed to a
* non-Formula cell.
*
* @param aRow row of cell to remove from reference list
* @param aColumn column of cell to remove from reference list
*/
public void removeRefs(int aRow, int aColumn) {
if (isFormula(aRow, aColumn)) {
Formula temp = getCellAt(aRow, aColumn).getFormula();
TreeSet list = temp.getDependency();
/* use formula dependcy list to go to cells that it references
* then remove its entry form their reference list
*/
Iterator it = list.iterator();
CellPoint thisRef = new CellPoint(aRow, aColumn);
while (it.hasNext()) {
CellPoint update = (CellPoint)it.next();
Cell field = getCellAt(update.getRow(), update.getCol());
if (field != null)
field.removeRef(thisRef);
}
}
}
 
/**
* This method updates the values of all cells that
* reference this one. It recursively updates all cells that depend on this
* one and cells that depend on those, etc.
*
* @param aRow row of cell to update
* @param aColumn column of cell to update
*/
public void updateRefs(int aRow, int aColumn) {
Cell temp = getCellAt(aRow, aColumn);
if (temp == null)
return;
 
TreeSet set = getRefs(aRow, aColumn);
 
// mark it as "needsRecalc";
Iterator it = set.iterator();
while (it.hasNext()) {
CellPoint point = (CellPoint)it.next();
Formula formula = getCellAt(point.getRow(), point.getCol()).getFormula();
formula.setNeedsRecalc(true);
// make sure JTable refreshes it
//fireTableCellUpdated(point.getRow(), point.getCol());
}
 
// recalculate
it = set.iterator();
while (it.hasNext()) {
CellPoint point = (CellPoint)it.next();
try {
getNumericValueAt(point.getRow(), point.getCol());
}
catch (ParserException e) {
}
// make sure JTable refreshes it
fireTableCellUpdated(point.getRow(), point.getCol());
}
//make sure to tell JTable things have changed
fireTableCellUpdated(aRow, aColumn);
}
 
/**
* This method gets the set of cells that will be affects
* by a value change for the cpecified cell.
*
* @param row the row
* @param col the column
*
*/
private TreeSet getRefs(int row, int col) {
TreeSet set = new TreeSet();
getRefs(row, col, set);
return set;
}
/**
* This method is a helper method for getReds(int, int).
* It recursively gets refs for each cell and merges it into
* the set.
*
* @param row the row
* @param col the column
* @param set the current of cells
*
*/
private void getRefs(int row, int col, TreeSet set) {
 
Cell cell = getCellAt(row, col);
if (cell == null || !cell.hasRefs())
return;
Iterator it = cell.getRefs().iterator();
while (it.hasNext()) {
CellPoint point = (CellPoint)it.next();
set.add(point);
getRefs(point.getRow(), point.getCol(), set);
}
}
/**
* This method recalculates all cells in the table
*
* @see #insertRow
* @see #insertColumn
* @see #removeRow
* @see #removeColumn
*
*/
public void recalculateAll() {
for (int i = 1; i < getRowCount(); i++)
for (int j = 1; j < getColumnCount(); j++) {
addRefs(i, j);
recalculate(i, j);
}
}
 
/** This method removes columns in the range.
* @param deletionRange the range that contains the columns to delete
*/
public void removeColumn(CellRange deletionRange) {
 
/* since the insertion point is given by a selected cell
* there will never be an out of bounds error
*/
/* first column to delete */
int col = deletionRange.getStartCol();
/* number of columns to delete including col */
int removeNum = deletionRange.getWidth();
//last entry of table
int lastRow = getRowCount() - 1;
int lastCol = getColumnCount() - 1;
/* everything to the right of the columns to remove
* need to be copied to be shifted right
*/
CellRange range = new CellRange(SharpTools.baseRow, lastRow,
col + removeNum, lastCol);
SharpClipboard scrap = new SharpClipboard(this, range, true);
JTable table = sharp.getTable();
for(int i = 0; i < removeNum; i++) {
// delete old column
removeColumn();
TableColumnModel tm = table.getColumnModel();
tm.removeColumn(tm.getColumn(tm.getColumnCount() - 1));
}
//shift clipboard elements right
scrap.paste(this, new CellPoint(SharpTools.baseRow, col));
 
// updateRefs(refs);
recalculateAll();
// set selection
if (table.getSelectedColumnCount() == 0) {
setSelection(new CellRange(SharpTools.baseRow, SharpTools.baseRow,
col, col));
}
 
// fireTableStructureChanged();
sharp.setBaseColumnWidth(0);
}
private void removeColumn() {
 
int lastRow = getRowCount() - 1;
int lastCol = getColumnCount() - 1;
//remove the data from cells to delete to maintain references
clearRange(new CellRange(SharpTools.baseRow, lastRow, lastCol, lastCol));
Iterator it = dataVector.iterator();
while (it.hasNext()) {
/* Since deleting B makes C the
* new B, the reference lists in cells of old "B"
* should not change. So, we only shift the data in cells right
* and deleted the last columns.
*/
Vector temp = (Vector)it.next();
temp.removeElementAt(getColumnCount() - 1);
}
//update inherited field from DefaultTableModel
columnIdentifiers.removeElementAt(columnIdentifiers.size() - 1);
// Notification is generated within the GUI
}
/** This method inserts columns to the left of the range with the number of
* new columns equal to the number of columns in the range.
* @param insertRange range of cells to add new columns to the left of
* creates the same number of new columns as range has
*/
 
public void insertColumn(CellRange insertRange) {
/* since the insertion point is given by a selected cell
* there will never be an out of bounds error
*/
Debug.println("insertRange: "+insertRange);
/* start inserting at this coordinate */
int col = insertRange.getStartCol();
/* number of columns to insert including col */
int insertNum = insertRange.getWidth();
//the coordinates of the last cell in table
int lastRow = getRowCount() - 1;
int lastCol = getColumnCount() - 1;
/* everything right to new columns must be shifted right
* so cut them to the clipboard. So if col is "C" then it
* is also copied. The max is a guard for inserting
* before the label column.
*/
CellRange range = new CellRange(SharpTools.baseRow, lastRow, Math.max(col, SharpTools.baseCol), lastCol);
SharpClipboard scrap = new SharpClipboard(this, range, true);
 
JTable table = sharp.getTable();
TableColumnModel tm = table.getColumnModel();
TableColumn column = tm.getColumn(col);
//add the new columns to the end
for(int i = 0; i < insertNum; i++) {
int curCol = lastCol+i+1;
addColumn();
TableColumn newcol = new TableColumn(curCol,
column.getPreferredWidth());
// TableColumn column = tm.getColumn(tm.getColumnCount() - 1);
// TableColumn newcol = new TableColumn(tm.getColumnCount(),
// column.getPreferredWidth());
newcol.setHeaderValue(Node.translateColumn(curCol));
tm.addColumn(newcol);
}
//shift relevant columns left
scrap.paste(this, new CellPoint(SharpTools.baseRow, col + insertNum));
 
recalculateAll();
// set selection
 
if (table.getSelectedColumnCount() == 0) {
setSelection(new CellRange(SharpTools.baseRow, SharpTools.baseRow,
col, col));
}
 
// sharp.setBaseColumnWidth();
//fireTableStructureChanged();
sharp.setBaseColumnWidth(0);
}
/** Helper method for insertColumn. This method will not
* send the appropriate notification to JTable. Please use insertColumn method
* instead.
*/
private void addColumn() {
columnIdentifiers.addElement(null);
 
/* Initialize the new column */
Iterator it = dataVector.iterator();
//Give column the appropriate label
if (it.hasNext()) {
Cell temp = new Cell(Node.translateColumn(getColumnCount() - 1));
((Vector)it.next()).addElement(temp);
}
//initialize cells
while (it.hasNext()) {
((Vector)it.next()).addElement(new Cell(""));
}
 
// Generate notification
/* newColumnsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
getColumnCount() - 1, TableModelEvent.INSERT));
*/
}
/** This method removes rows in the range.
* @param deletionRange CellRange that contains the rows to delete
*/
public void removeRow(CellRange deletionRange) {
/* since the insertion point is given by a selected cell
* there will never be an out of bounds error
*/
clearRange(deletionRange);
/* first row to delete */
int row = deletionRange.getStartRow();
/* number of rows to delete including the first */
int removeNum = deletionRange.getHeight();
//coordinates of last cell in spreadsheet
int lastRow = getRowCount() - 1;
int lastCol = getColumnCount() - 1;
//everything lower than rows to remove must be copied to be shifted
CellRange range = new CellRange(row + removeNum, lastRow,
SharpTools.baseCol, lastCol);
SharpClipboard scrap = new SharpClipboard(this, range, true);
for(int i = 0; i < removeNum; i++) {
super.removeRow(getRowCount() - 1);
}
//shift relevent rows up
scrap.paste(this, new CellPoint(row, SharpTools.baseCol));
 
recalculateAll();
JTable table = sharp.getTable();
// set selection
if (table.getSelectedColumnCount() == 0) {
setSelection(new CellRange(row, row, SharpTools.baseCol, SharpTools.baseCol));
}
}
 
/** This method inserts rows to the left of range. It adds as many rows as
* the range has.
* @param insertRange the range to the left of to add new rows
* also adds number of new rows equal to rows in range
*/
public void insertRow(CellRange insertRange) {
/* since the insertion point is given by a selected cell
* there will never be an out of bounds error
*/
/* insert starting at this coordinate */
int row = insertRange.getStartRow();
/* number of rows to insert including row */
int insertNum = insertRange.getHeight();
//coordinates of last cell of table
int lastRow = getRowCount() - 1;
int lastCol = getColumnCount() - 1;
 
/* copy things below these new rows
* The max is to prevent inserts above the column headers
*/
CellRange range = new CellRange(Math.max(row, SharpTools.baseRow), lastRow, SharpTools.baseCol, lastCol);
SharpClipboard scrap = new SharpClipboard(this, range, true);
//add the rows to the end
for(int i = 0; i < insertNum; i++) {
addRow();
}
//shift old rows down
scrap.paste(this, new CellPoint(row + insertNum, SharpTools.baseCol));
 
recalculateAll();
JTable table = sharp.getTable();
// set selection
if (table.getSelectedColumnCount() == 0) {
setSelection(new CellRange(row, row, SharpTools.baseCol, SharpTools.baseCol));
}
 
}
 
 
/**
* Adds row to end of table
*/
private void addRow() {
//create a new row with appropriate label
Vector rowData = new Vector();
rowData.add(0, new Cell(new Integer(getRowCount() + 1)));
//add it to the table
super.addRow(rowData);
for(int i = 1; i < getColumnCount(); i++) {
super.setValueAt(new Cell(""), getRowCount() - 1, i);
}
}
 
/**
* This implements a needed class to work with the Formula class.
* If it is a data cell, it returns the numerical value of the cell (for
* a String the value is 0). If it is a formula, then it recalculates the
* value and returns that as an answer.
*
* @param row row coordinate
* @param col column coordinate
* @throws ParserException if the value doesn't parse
* @return numerical value of the cell
*/
 
public Number getNumericValueAt(int row, int col) throws ParserException {
Cell cell = getCellAt(row, col);
if (cell != null) {
int type = cell.getType();
if (type == Cell.FORMULA) {
Object value = cell.getValue();
Formula form = cell.getFormula();
// if need recalc
if (form.needsRecalc()) {
try {
value = form.evaluate(this, row, col);
cell.setValue(value);
}
catch (ParserException e) {
cell.setValue(e);
value = e;
}
}
if (value instanceof ParserException)
throw (ParserException)value;
else
return (Number)cell.getValue();
}
else if (type == Cell.NUMBER)
return (Number)cell.getValue();
else
return new Float(0);
}
else
// a string or null
// return new Float(0);
throw new ParserException("#REFS?");
 
}
 
/**
* Determines if a cell at these coordinates is a formula cell
*
* @param aRow row coordinate
* @param aColumn column coordinate
* @return true only if the cell at those coordinates is a formula
*/
public boolean isFormula(int aRow, int aColumn) {
Cell temp = getCellAt(aRow, aColumn);
return ((temp != null) && (temp.getType() == Cell.FORMULA));
}
/**
* All Cells other than those in row 0 or column 0 are editable.
*
* @param row the row coordinate
* @param column the column coordinate
* @return true if cell is editable
*/
public boolean isCellEditable(int row, int column) {
// return !((row == 0) || (column == 0));
return column != 0;
}
 
/**
* JTable uses this method to determine the default renderer
* editor for each cell. This method tells JTable to use
* SharpCellRender and SharpCellEditor.
*
* @param c the column for which we need to determine the class
* @return Cell class
*/
public Class getColumnClass(int c) {
/* only cell objects in this TableModel */
return Cell.class;
}
 
/**
* Starting from cell, detect potential reference loops.
*
* @param cell specified CellPoint
*/
private boolean isLoop(CellPoint cell) {
return isLoop(cell, new TreeSet());
}
 
/**
* Starting from cell, detect potential reference loops.
*
* @param cell specified CellPoint
*/
private boolean isLoop(CellPoint cell, TreeSet set) {
if (set.contains(cell))
return true;
Cell objCell = getCellAt(cell.getRow(), cell.getCol());
if (objCell == null)
return false;
Formula formula = objCell.getFormula();
if (formula == null)
return false;
 
set.add(cell);
Iterator it = formula.getDependency().iterator();
while (it.hasNext()) {
CellPoint newCell = (CellPoint)it.next();
boolean ret = isLoop(newCell, set);
if (ret)
return true;
}
set.remove(cell);
return false;
}
 
/**
* Sets modified state of current document
*
* @param modified true sets state to modified
*/
public void setModified(boolean modified) {
this.modified = modified|passwordModified;
// enable/disable the "Save" button
sharp.checkSaveState();
}
/**
* Sets modified state of password; can't undo
*
* @param modified sets state to modified
* @see FileOp#setPassword
*/
public void setPasswordModified(boolean modified) {
passwordModified = modified;
setModified(this.modified);
// enable/disable the "Save" button
}
 
/**
* Returns modified state of document
*
* @return document's modified value - true or false
*/
public boolean isModified() {
return modified;
}
 
/**
* Returns JTable
*
* @return JTable
*/
public JTable getTable() {
return sharp.getTable();
}
 
/**
* set table selection to the range sel
*
* @param sel the range to be selected
*/
public void setSelection(CellRange sel) {
JTable table = sharp.getTable();
// validate sel
int maxRow = table.getRowCount()-1;
int maxCol = table.getColumnCount()-1;
 
int startRow = sel.getStartRow();
int startCol = sel.getStartCol();
int endRow = sel.getEndRow();
int endCol = sel.getEndCol();
 
table.setColumnSelectionInterval(Math.min(startCol, maxCol),
Math.min(endCol, maxCol));
table.setRowSelectionInterval(Math.min(startRow, maxRow),
Math.min(endRow, maxRow));
}
 
/**
* check whether the deletion is safe
*
* @param range the range to delete
* @param byRow whether it's deletion by row
* @return true if it's safe
*/
public boolean isDeletionSafe(CellRange range, boolean byRow) {
int rowOff, colOff;
CellRange needCheck;
if (byRow) {
rowOff = -range.getHeight();
colOff = 0;
if (range.getEndRow() == getRowCount()-1)
return true;
needCheck = new CellRange(range.getEndRow()+1, getRowCount()-1,
SharpTools.baseCol, getColumnCount()-1);
}
else {
rowOff = 0;
colOff = -range.getWidth();
if (range.getEndCol() == getColumnCount()-1)
return true;
needCheck = new CellRange(SharpTools.baseRow, getRowCount()-1,
range.getEndCol()+1, getColumnCount()-1);
}
 
for (int i = needCheck.getStartRow(); i <= needCheck.getEndRow(); i++)
for (int j = needCheck.getStartCol(); j <= needCheck.getEndCol();
j++) {
Cell cell = getCellAt(i, j);
if (cell.isFormula() &&
!Formula.isSafe(cell.getFormula(), rowOff, colOff)) {
Debug.println("relative addresses become invalid");
return false;
}
}
 
return true;
}
 
/** toString is used to convert a range of cells into a string.
* One row per line, and each column is tab-delimited.
* @param range the range in the table
* @param byValue get the value instead of a formula
* @return a string
* @see Formula#fixRelAddr
* @see FileOp#saveTableModel
* @see EditOp#cut
* @see EditOp#copy
* @see SharpClipboard
*/
public String toString(CellRange range, boolean byValue) {
StringBuffer sbf=new StringBuffer();
for (int i=range.getStartRow(); i<=range.getEndRow(); i++) {
for (int j=range.getStartCol(); j<=range.getEndCol(); j++) {
if (byValue) {
sbf.append(getValueAt(i, j));
}
else {
Cell cell = getCellAt(i, j);
if(cell != null)
sbf.append(cell.toString());
}
if (j<range.getEndCol())
sbf.append("\t");
}
sbf.append("\n");
}
 
String text = sbf.toString();
return text;
}
// jm.evers
public String to_WIMS(CellRange range, boolean byValue ,int type) {
StringBuffer sbf=new StringBuffer();
Number n=null;
String row_sep;
String col_sep;
String tmp="";
String empty_cell = MainApplet.empty_cell; // defined by params
if(type == 0 ){row_sep=",";col_sep=";";sbf.append("[");} // matrix
else
if(type == 1 ){row_sep=",";col_sep="\n";}// csv
else{ row_sep="\t";col_sep="\n"; } // tsv
for (int i=range.getStartRow(); i<=range.getEndRow(); i++) {
for (int j=range.getStartCol(); j<=range.getEndCol(); j++) {
n=null;
if(isFormula(i,j)){
try { n = getNumericValueAt(i,j);}
catch (ParserException e) {System.out.println("hmmm this should not happen"); }
}
if(n != null){
sbf.append(n);
}
else
{
if(byValue){
sbf.append(getValueAt(i, j));
}
else
{
Cell cell = getCellAt(i, j);
// if cell is not empty
if(cell != null){
tmp = cell.toString();
if(type == 0){//matrix
if( tmp.length()>0 ){ sbf.append("\""+tmp+"\"");}
else { sbf.append("\""+empty_cell+"\"");}//pari/gp gives trouble with [,,,;2,3,4]
}
else
{
if( tmp.length()>0 ){ sbf.append(tmp);}else{sbf.append(empty_cell);}
}
}
}
}
if (j<range.getEndCol()){sbf.append(row_sep);}
}
if( i<range.getEndRow()){sbf.append(col_sep);}
}
if(type == 0){sbf.append("]");}
String text = sbf.toString();
return text;
}
 
/** fromString is used to convert a string to valus in a range of cells.
* One row per line, and each column is tab-delimited.
* @param text the string
* @param rowOff the row offset
* @param colOff the column offset
* @param range the range to paste
* @see Formula#fixRelAddr
* @see FileOp#openTableModel
* @see EditOp#paste
* @see SharpClipboard
*/
// evers
void fromString(String text, int rowOff, int colOff, CellRange range) {
 
try {
BufferedReader in = new BufferedReader(new StringReader(text));
String line;
int row = range.getStartRow();
while (row <= range.getEndRow()) {
line = in.readLine();
int index;
int prev = 0;
// set col to startCol before each loop
int col = range.getStartCol();
String value;
while (col <= range.getEndCol()) {
index = line.indexOf('\t', prev);
if (index >= 0) {
value = line.substring(prev, index);
}
else {
value = line.substring(prev);
}
if (value.startsWith("=")) {
// need to fix relative address
value =
Formula.fixRelAddr(value.substring(1),
rowOff, colOff);
if (value == null)
value = new String("=$REFS$0");
else
value = "="+value;
}
doSetValueAt(value, row, col);
prev = index+1;
// increment column number
col++;
if (index == -1)
break;
}
row++;
}
}
catch (Exception e) {
}
}
/**
* convert the whole table to a string.
*
* @return a string
*
* @see FileOp
*/
public String toString() {
return toString(new CellRange(SharpTools.baseRow, getRowCount()-1,
SharpTools.baseCol, getColumnCount()-1), false);
}
public String toWIMS(int type) {
return to_WIMS(new CellRange(SharpTools.baseRow, getRowCount()-1,
SharpTools.baseCol, getColumnCount()-1), false, type);
}
/**
* From a string input determine how many rows/columns it requires
* for the table - it corresponds to the number of newlines and tabs.
*
* @param input the string to analyze
*/
static public CellPoint getSize(String input) {
BufferedReader in = new BufferedReader(new StringReader(input));
String line;
int rowcount = 0;
int colcount = 0;
 
try {
while ((line = in.readLine()) != null) {
rowcount++;
// initialize new tokenizer on line with tab delimiter.
// tokenizer = new StringTokenizer(line, "\t");
int index;
int prev = 0;
// set col to 1 before each loop
int col = 0;
while (true) {
index = line.indexOf('\t', prev);
prev = index+1;
// increment column number
col++;
if (index == -1)
break;
}
 
if (colcount < col)
colcount = col;
}
}
catch (Exception e) {
return null;
}
 
return new CellPoint(rowcount, colcount);
}
 
 
/** This method sorts an arbitrary range in the table.
* @param area range to sort
* @param primary primary row/column to sort by
* @param second second row/column to sort by (set equal to primary
* if there is no secondary criteria specified.
* @param isRow true if primary and secondary are row numbers
* @param ascend true if sorting in ascending order by primary criteria
* @param tiebreaker true if sorting in ascending order by secondary criteria
* data structure
*/
public void sort(CellRange area, int primary, int second, boolean isRow,
boolean ascend, boolean tiebreaker) {
 
/* original data order will be saved here
* and placed on clipboard for undo
*/
SharpClipboard[] data;
if (isRow) {
data = new SharpClipboard[area.getWidth()];
for(int i = 0; i < data.length; i++) {
CellRange temp = new CellRange(area.getStartRow(),
area.getEndRow(),
area.getStartCol() + i,
area.getStartCol() + i);
data[i] = new SharpClipboard(this, temp, false);
}
}else {
data = new SharpClipboard[area.getHeight()];
for(int i = 0; i < data.length; i++) {
CellRange temp = new CellRange(area.getStartRow() + i,
area.getStartRow() + i,
area.getStartCol(),
area.getEndCol());
data[i] = new SharpClipboard(this, temp, false);
}
}
/* We are going to do the sort within the world of the data array
* First, we do index sorting to create an index array.
* Then according to the index array, we paste the entries in data
* back in the sorted order.
*/
//do index sorting
int[] indices = internalSort(area, primary, second, isRow, ascend, tiebreaker);
//paste accordingly
if (isRow) {
for (int i = area.getStartCol(); i <= area.getEndCol(); i++){
//point to paste at
CellPoint point = new CellPoint(area.getStartRow(), i);
int y = i - area.getStartCol();
data[indices[y] - area.getStartCol()].paste(this, point);
}
}else {
for (int i = area.getStartRow(); i <= area.getEndRow(); i++) {
//point to paste at
CellPoint point = new CellPoint(i, area.getStartCol());
int y = i - area.getStartRow();
data[indices[y] - area.getStartRow()].paste(this, point);
}
}
}
/**
* This is a helper function that compares rows or columns
*
* @param data an array of cells
* @param primary first criteria to sort by
* @param secondary second criteria to sort by (set to -1 if not specified)
* @param isRow true if the criteria are rows
* @param i column or row you are comparing
* @param j column or row to compare i to
* @return -1 if i < j, 0 if i = j, 1 if i > j
*/
private int compareLines(int primary, boolean isRow, boolean ascending,
int i, int j) {
Cell x = getCriteria(primary, i, isRow);
Cell y = getCriteria(primary, j, isRow);
return x.compare(y, ascending);
}
 
/** used to make sorting method and helper methods for sort treat row
* sorting the same as column sorting.
* @param interest criteria coordinate for sort
* @param i other coordinate
* @param isRow true if coordinates are in form (row,col)
* @return cell at those coordinates
*/
private Cell getCriteria(int interest,
int i, boolean isRow) {
if (isRow) {
return getCellAt(interest, i);
}else {
return getCellAt(i, interest);
}
}
 
/** Determines if cells are in the wrong order
* Used only as helper method for sort.
*/
private boolean rightOrder(int primary, int second, boolean isRow, int i,
int j, boolean ascend, boolean order) {
//compare by first criteria
int result = compareLines(primary, isRow, ascend, i, j);
//if equal, use second as tiebreaker
if (result == 0) {
result = compareLines(second, isRow, order, i, j);
 
if (order) {
return (result < 0);
}else {
return (result > 0);
}
//otherwise just return results from primary criteria
}else {
if (ascend) {
return (result < 0);
}else {
return (result > 0);
}
}
}
/** Helper for sort that does the sorting. To implement different algorithms
* for sorting modify this method. Returns an index array after index sorting
* @param area area to sort in
* @param primary primary criteria to sort
* @param second secondary criteria (set equal to primary if
* not specified)
* @param isRow true if criteria are rows
* @param ascend true if sort ascending by primary
* @param tiebreaker true if sort ascending by secondary
* @return index array with row/col numbers of how cells
* should be arranged.
*/
private int[] internalSort(CellRange area, int primary, int second,
boolean isRow, boolean ascend,
boolean tiebreaker) {
//initialize index array
int[] index;
if (isRow) {
index = new int[area.getWidth()];
for(int i = 0; i < index.length; i++) {
index[i] = i + area.getStartCol();
}
}else {
index = new int[area.getHeight()];
for(int i = 0; i < index.length; i++) {
index[i] = i + area.getStartRow();
}
}
int j;
for (int p = 1; p < index.length ; p++) {
int tmp = index[p];
for (j = p; ((j > 0) && rightOrder(primary, second, isRow, tmp,
index[j - 1], ascend, tiebreaker));
j--) {
index[j] = index[j - 1];
}
index[j] = tmp;
}
return index;
}
 
/** Determines if a cell is empty
* @param row row coordinate of cell
* @param col column coordinate of cell
* @return true if cell is empty
*/
public boolean isEmptyCell(int row, int col) {
return getCellAt(row, col).getValue().equals("");
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/HistoDialog.java
0,0 → 1,484
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)HistoDialog.java
*
* $Id: HistoDialog.java,v 1.6 2001/05/27 22:28:57 huaz Exp $
*
* Created Novenmber 23, 2000, 2:55 PM
*/
package SharpTools;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
/**
* This is used to provide options configuration for a histogram
*
* @author Hua Zhong
* @version $Revision: 1.6 $
*/
 
public final class HistoDialog extends SharpDialog {
//static Properties translation=SharpTools.translation;
private JFrame owner;
private JTextField title;
private AddressField startCell;
private AddressField endCell;
private NumberField startValue;
private NumberField endValue;
private NumberField bucket;
private NumberField xMin;
private NumberField xMax;
private NumberField xUnit;
private NumberField yMin;
private NumberField yMax;
private NumberField yUnit;
private JRadioButton percentageButton; // radio button for "Percentage"
private JRadioButton countButton;
final ImageIcon histogramIcon32=new ImageIcon(getClass().getResource("/images/chart32.gif"));
//final private ImageIcon histogramIcon32 = SharpTools.getImageIcon ("chart32.gif");
 
/**
* construct a modal dialog
*
* @param aFrame the parent frame
*/
HistoDialog(JFrame aFrame) {
super(aFrame, "Histogram Options", true);
 
owner = aFrame;
 
// initialize all the components
title = new JTextField(10);
startCell = new AddressField(5);
endCell = new AddressField(5);
startValue = new NumberField(5);
endValue = new NumberField(5);
bucket = new NumberField(5, true);
xMin = new NumberField(5);
xMax = new NumberField(5);
xUnit = new NumberField(5, true);
yMin = new NumberField(5);
yMax = new NumberField(5);
yUnit = new NumberField(5, true);
 
// set tooltip text
startCell.setToolTipText(SharpTools.translation.getProperty("Start_cell"));
endCell.setToolTipText(SharpTools.translation.getProperty("End_cell"));
startValue.setToolTipText(SharpTools.translation.getProperty("Start_value"));
endValue.setToolTipText(SharpTools.translation.getProperty("End_value"));
xMin.setToolTipText(SharpTools.translation.getProperty("Minumum_value_on_X_axis"));
xMax.setToolTipText(SharpTools.translation.getProperty("Maximum_value_on_X_axis"));
xUnit.setToolTipText(SharpTools.translation.getProperty("Unit_on_X_axis"));
yMin.setToolTipText(SharpTools.translation.getProperty("Minumum_value_on_Y_axis"));
yMax.setToolTipText(SharpTools.translation.getProperty("Maximum_value_on_Y_axis"));
yUnit.setToolTipText(SharpTools.translation.getProperty("Unit_on_Y_axis"));
/*
* All the following crap is laying out the component.
* Nothing interesting.
*/
JPanel east = new JPanel();///new GridLayout(0, 1, 5, 5));
east.setLayout(new BoxLayout(east, BoxLayout.Y_AXIS));
east.setBorder(BorderFactory.createEmptyBorder(10,10,20,10));
 
// title
JPanel textPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel label = new JLabel(SharpTools.translation.getProperty("Chart_Title")+" : ");
label.setLabelFor(title);
label.setDisplayedMnemonic(KeyEvent.VK_T);
textPanel.add(label);
textPanel.add(title);
east.add(textPanel);
 
// separator
textPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
textPanel.add(new JSeparator());
// textPanel.setBorder(BorderFactory.createEtchedBorder());
east.add(textPanel);
// Cell Range
textPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
label = new JLabel(SharpTools.translation.getProperty("Cell_Range")+" : ");
label.setLabelFor(startCell);
label.setDisplayedMnemonic(KeyEvent.VK_C);
 
textPanel.add(label);
textPanel.add(startCell);
 
textPanel.add(new JLabel(":"));
textPanel.add(endCell);
 
east.add(textPanel);
 
// Value Range
textPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
 
label = new JLabel(SharpTools.translation.getProperty("Value_Range")+" : ");
label.setLabelFor(startValue);
label.setDisplayedMnemonic(KeyEvent.VK_V);
 
textPanel.add(label);
textPanel.add(startValue);
 
label = new JLabel(" "+SharpTools.translation.getProperty("to")+" ");
label.setLabelFor(endValue);
textPanel.add(label);
textPanel.add(endValue);
 
east.add(textPanel);
 
// Bucket Size
label = new JLabel(" "+SharpTools.translation.getProperty("Bucket")+" ");
label.setLabelFor(bucket);
label.setDisplayedMnemonic(KeyEvent.VK_B);
textPanel.add(label);
textPanel.add(bucket);
east.add(textPanel);
 
// separator
textPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
textPanel.add(new JSeparator());
// textPanel.setBorder(BorderFactory.createEtchedBorder());
east.add(textPanel);
// X Scale
textPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
 
label = new JLabel(SharpTools.translation.getProperty("X_Scale")+" : ");
label.setLabelFor(xMin);
label.setDisplayedMnemonic(KeyEvent.VK_X);
 
textPanel.add(label);
textPanel.add(xMin);
 
label = new JLabel(" "+SharpTools.translation.getProperty("to")+" ");
label.setLabelFor(xMax);
textPanel.add(label);
textPanel.add(xMax);
 
label = new JLabel(" "+SharpTools.translation.getProperty("Unit")+" ");
label.setLabelFor(xUnit);
label.setDisplayedMnemonic(KeyEvent.VK_U);
textPanel.add(label);
textPanel.add(xUnit);
 
east.add(textPanel);
 
// Y Scale
textPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
 
label = new JLabel(SharpTools.translation.getProperty("Y_Scale")+" : ");
label.setLabelFor(yMin);
label.setDisplayedMnemonic(KeyEvent.VK_Y);
 
textPanel.add(label);
textPanel.add(yMin);
 
label = new JLabel(" "+SharpTools.translation.getProperty("to")+" ");
label.setLabelFor(yMax);
textPanel.add(label);
textPanel.add(yMax);
 
label = new JLabel(" "+SharpTools.translation.getProperty("Unit")+" ");
label.setLabelFor(yUnit);
label.setDisplayedMnemonic(KeyEvent.VK_N);
textPanel.add(label);
textPanel.add(yUnit);
east.add(textPanel);
 
// separator
textPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
textPanel.add(new JSeparator());
east.add(textPanel);
 
// Radio buttons
textPanel = new JPanel();
textPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
 
// add radio buttons
ButtonGroup metric = new ButtonGroup();
percentageButton = new JRadioButton(SharpTools.translation.getProperty("percentage"));
percentageButton.setMnemonic(KeyEvent.VK_P);
// radio.setActionCommand("Count");
metric.add(percentageButton);
label = new JLabel(SharpTools.translation.getProperty("Display_Y_by")+" ");
textPanel.add(label);
textPanel.add(percentageButton);
// percentageButton.setSelected(true);
 
countButton = new JRadioButton(SharpTools.translation.getProperty("Count"));
countButton.setMnemonic(KeyEvent.VK_O);
metric.add(countButton);
textPanel.add(countButton);
east.add(textPanel);
 
setOptionPane(east,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
histogramIcon32);
 
// this is OK; onClose() will not be called
// but choice's default value is CLOSED_OPTION
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 
startCell.requestFocus();
}
 
// strings defined here
final static private String bucketstring = SharpTools.translation.getProperty("Bucket_Size");
final static private String startvaluestring = SharpTools.translation.getProperty("Start_Value");
final static private String endvaluestring = SharpTools.translation.getProperty("End_Value");
final static private String xunitstring = SharpTools.translation.getProperty("X_Unit");
final static private String yunitstring = SharpTools.translation.getProperty("Y_Unit");
final static private String xminstring = SharpTools.translation.getProperty("X_Start");
final static private String xmaxstring = SharpTools.translation.getProperty("X_End");
final static private String yminstring = SharpTools.translation.getProperty("Y_Start");
final static private String ymaxstring = SharpTools.translation.getProperty("Y_End");
 
/**
* Validates the input - called when the OK button is pressed
*
* @return whether the input is valid
*/
private boolean validateInput() {
/*
* get values from text fields and check the validity,
* give friendly error report
*/
if (!addressOK(startCell, SharpTools.translation.getProperty("Start_Cell")))
return false;
 
if (!addressOK(endCell, SharpTools.translation.getProperty("End_Cell")))
return false;
if (!orderOK(startValue, endValue, startvaluestring, endvaluestring))
return false;
if (!orderOK(xMin, xMax, xminstring, xmaxstring))
return false;
if (!orderOK(yMin, yMax, yminstring, ymaxstring))
return false;
if (isNegative(bucket, bucketstring))
return false;
 
if (isNegative(xUnit, xunitstring))
return false;
 
if (isNegative(yUnit, yunitstring))
return false;
 
return true;
}
 
/**
* Check the NumberField can't contain a negative number
*
* @param field the NumberField component
* @param name used for error reporting
* @return whether the input is a negative number
*/
private boolean isNegative(NumberField field, String name) {
Float f = field.getNumber();
if (f == null || f.floatValue() <= 0) {
invalidInput(name);
field.selectAll();
field.requestFocus();
return true;
}
return false;
}
/**
* Make sure first value is lower than the second's and both have valid input
*
* @param start the first number field
* @param end the second number field
* @param startname the name of the first field
* @param endname the name of the second field
* @return whether the order is correct
*/
private boolean orderOK(NumberField start, NumberField end,
String startname, String endname) {
// calculate
Float f1 = start.getNumber();
 
if (f1 == null) {
invalidInput(startname);
start.selectAll();
start.requestFocus();
return false;
}
Float f2 = end.getNumber();
 
if (f2 == null) {
invalidInput(endname);
end.selectAll();
end.requestFocus();
return false;
}
if (f1.floatValue() > f2.floatValue()) {
// exchange
start.setNumber(f2);
end.setNumber(f1);
}
 
return true;
}
 
/**
* Make sure AddressField valid input
*
* @param field the address text field
* @param name the name of this field
* @return whether the input is a valid address
*/
private boolean addressOK(AddressField field, String name) {
// calculate
CellPoint addr = field.getAddress();
if (addr == null) {
invalidInput(name);
field.selectAll();
field.requestFocus();
return false;
}
return true;
}
 
/*
* Set the Title textfield
* @param s the title
*/
public void setTitleField(String s) {
title.setText(s);
setTitle(SharpTools.translation.getProperty("Options")+"-"+s);
}
 
/**
* Get the Title textfield
*
* @return the new title
*/
public String getTitleField() {
return title.getText();
}
 
/**
* Set the cell range
*
* @param range the new cell range
*/
public void setCellRange(CellRange range) {
if (range != null) {
startCell.setAddress(range.getminCorner());
endCell.setAddress(range.getmaxCorner());
}
}
 
/**
* Get the cell range
*
* @return the range that user input
*/
public CellRange getCellRange() {
CellPoint point1 = startCell.getAddress();
CellPoint point2 = endCell.getAddress();
if (point1 == null || point2 == null)
return null;
else {
// correct problems like "A2:B1". Always convert to "A1:B2"
int minrow = Math.min(point1.getRow(), point2.getRow());
int maxrow = Math.max(point1.getRow(), point2.getRow());
int mincol = Math.min(point1.getCol(), point2.getCol());
int maxcol = Math.max(point1.getCol(), point2.getCol());
return new CellRange(minrow, maxrow, mincol, maxcol);
}
}
 
// many get/set functions
public CellPoint getStartCell() { return startCell.getAddress(); }
public void setStartCell(CellPoint addr) { startCell.setAddress(addr); }
public CellPoint getEndCell() { return endCell.getAddress(); }
public void setEndCell(CellPoint addr) { endCell.setAddress(addr); }
 
public Float getStartValue() { return startValue.getNumber(); }
public void setStartValue(Float f) { startValue.setNumber(f); }
public Float getEndValue() { return endValue.getNumber(); }
public void setEndValue(Float f) { endValue.setNumber(f); }
 
public Float getBucket() { return bucket.getNumber(); }
public void setBucket(Float f) { bucket.setNumber(f); }
 
public Float getXMin() { return xMin.getNumber(); }
public void setXMin(Float f) { xMin.setNumber(f); }
 
public Float getXMax() { return xMax.getNumber(); }
public void setXMax(Float f) { xMax.setNumber(f); }
 
public Float getXUnit() { return xUnit.getNumber(); }
public void setXUnit(Float f) { xUnit.setNumber(f); }
 
public Float getYMin() { return yMin.getNumber(); }
public void setYMin(Float f) { yMin.setNumber(f); }
 
public Float getYMax() { return yMax.getNumber(); }
public void setYMax(Float f) { yMax.setNumber(f); }
 
public Float getYUnit() { return yUnit.getNumber(); }
public void setYUnit(Float f) { yUnit.setNumber(f); }
 
public boolean getByPercentage() { return percentageButton.isSelected(); }
public void setByPercentage(boolean set) {
percentageButton.setSelected(set);
countButton.setSelected(!set);
}
 
/**
* Pop up an error message
*
* @param s the name of the field with invalod input
*/
private void invalidInput(String s){
SharpOptionPane.showMessageDialog(owner,
SharpTools.translation.getProperty("sorry")+"\n errormessage :"+s,
SharpTools.translation.getProperty("Histogram"),
JOptionPane.ERROR_MESSAGE, null);
}
 
protected boolean onOK() {
// validate the input here
return validateInput();
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SortDialog.java
0,0 → 1,211
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)SortDialog.java
*
* $Id: SortDialog.java,v 1.15 2001/05/27 22:28:58 huaz Exp $
*
* Created on November 16, 2000, 12:00 AM
*/
package SharpTools;
import java.util.*;
import java.util.Vector;
import javax.swing.*;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import java.awt.event.*;
 
/**
* This class provides a sort dialog.
* User is prompted to choose sort criteria.
*
* @author Andrei Scudder
* @author Hua Zhong (use SharpDialog)
* @version $Revision: 1.15 $
*/
public class SortDialog extends SharpDialog {
private JLabel label;
private JFrame frame;
private JComboBox primary;
private JComboBox tiebreaker;
private boolean ascending1 = true;
private boolean ascending2 = true;
private int criteriaA = -1;
private int criteriaB = -1;
final ImageIcon sortIcon=new ImageIcon(getClass().getResource("/images/sort32.gif"));
final private ButtonGroup group = new ButtonGroup();
final private ButtonGroup group2 = new ButtonGroup();
final private String ascending_1 = "ascending_1";
final private String descending_1 = "decending_1";
final private String ascending_2 = "ascending_2";
final private String descending_2 = "decending_2";
 
public SortDialog(JFrame aFrame, Vector first, Vector second) {
super(aFrame, "Sort", true);
primary = new JComboBox(first);
primary.setSelectedIndex(0);
tiebreaker = new JComboBox(second);
tiebreaker.setSelectedIndex(0);
JRadioButton[] radioButtons = new JRadioButton[4];
JButton enter = null;
JButton close = null;
JPanel box = new JPanel();
radioButtons[0] = new JRadioButton(SharpTools.translation.getProperty("Ascending"));
radioButtons[0].setActionCommand(ascending_1);
radioButtons[1] = new JRadioButton(SharpTools.translation.getProperty("Descending"));
radioButtons[1].setActionCommand(descending_1);
radioButtons[2] = new JRadioButton(SharpTools.translation.getProperty("Ascending"));
radioButtons[2].setActionCommand(ascending_2);
radioButtons[3] = new JRadioButton(SharpTools.translation.getProperty("Descending"));
radioButtons[3].setActionCommand(descending_2);
 
radioButtons[0].setSelected(true);
group.add(radioButtons[0]);
group.add(radioButtons[1]);
 
radioButtons[2].setSelected(true);
group2.add(radioButtons[2]);
group2.add(radioButtons[3]);
box.setLayout(new GridLayout(0, 3, 10, 5));
 
// define key shortcut
JLabel sortLabel = new JLabel(SharpTools.translation.getProperty("Sort_By:"));
sortLabel.setLabelFor(primary);
sortLabel.setDisplayedMnemonic(KeyEvent.VK_S);
radioButtons[0].setMnemonic(KeyEvent.VK_A);
radioButtons[1].setMnemonic(KeyEvent.VK_D);
box.add(sortLabel);
box.add(new JLabel(""));
box.add(new JLabel(""));
box.add(primary);
box.add(radioButtons[0]);
box.add(radioButtons[1]);
 
// define key shortcut
sortLabel = new JLabel(SharpTools.translation.getProperty("Then_By:"));
sortLabel.setLabelFor(tiebreaker);
sortLabel.setDisplayedMnemonic(KeyEvent.VK_T);
radioButtons[2].setMnemonic(KeyEvent.VK_C);
radioButtons[3].setMnemonic(KeyEvent.VK_E);
 
box.add(sortLabel);
box.add(new JLabel(""));
box.add(new JLabel(""));
box.add(tiebreaker);
box.add(radioButtons[2]);
box.add(radioButtons[3]);
Border padding = BorderFactory.createEmptyBorder(20,20,20,0);
box.setBorder(padding);
Object setting = box;
setOptionPane(box,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.YES_NO_OPTION,
sortIcon);
 
primary.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
criteriaA = cb.getSelectedIndex();
}
});
tiebreaker.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
criteriaB = cb.getSelectedIndex();
}
});
 
}
 
private JPanel setPanel(){
return null;
}
public boolean firstAscending(){
return ascending1;
}
public boolean secondAscending(){
return ascending2;
}
public int getCriteriaA(){
return criteriaA;
}
public int getCriteriaB(){
return criteriaB;
}
void setLabel(String newText) {
label.setText(newText);
}
 
protected boolean onOK() {
criteriaA = primary.getSelectedIndex();
criteriaB = tiebreaker.getSelectedIndex();
String command = group.getSelection().getActionCommand();
String command2 = group2.getSelection().getActionCommand();
//Set the sort order of the first column
if (command == ascending_1) {
ascending1 = true;
} else if (command == descending_1) {
ascending1 = false;
// Set the sort order of the scond column
}
if (command2 == ascending_2) {
ascending2 = true;
} else if (command2 == descending_2) {
ascending2 = false;
}
return true;
}
 
protected boolean onCancel() {
criteriaA = -1;
criteriaB = -1;
return true;
}
 
}
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/NewFileDialog.java
0,0 → 1,153
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)NewFileDialog.java
*
* $Id: NewFileDialog.java,v 1.6 2001/05/27 22:28:12 huaz Exp $
*
* Created on November 16, 2000, 12:00 AM
*/
package SharpTools;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
* This class provides a new-file dialog.
* User is prompted to choose rows/columns when they are creating a
* new document.
*
* @author Hua Zhong
* @version $Revision: 1.6 $
*/
 
public class NewFileDialog extends SharpDialog {
private int rows;
private int cols;
final ImageIcon newFileIcon=new ImageIcon(getClass().getResource("/images/new32.gif"));
//final private static ImageIcon newFileIcon = SharpTools.getImageIcon("new32.gif");
final NumberField rowField;
final NumberField colField;
final JCheckBox saveDefault;
public NewFileDialog(JFrame aFrame, int initrows, int initcols) {
super(aFrame, "New", true);
 
//various properties of the dialog labels and text fields
final JLabel msgString1 = new JLabel(SharpTools.translation.getProperty("Rows")+": ");
final JLabel msgString2 = new JLabel(SharpTools.translation.getProperty("Columns")+": ");
rowField = new NumberField(5, true, true);
colField = new NumberField(5, true, true);
msgString1.setLabelFor(rowField);
msgString2.setLabelFor(colField);
msgString1.setDisplayedMnemonic(KeyEvent.VK_R);
msgString2.setDisplayedMnemonic(KeyEvent.VK_C);
 
saveDefault = new JCheckBox(SharpTools.translation.getProperty("Save_as_default"), false);
saveDefault.setMnemonic(KeyEvent.VK_S);
 
rowField.setText(String.valueOf(initrows));
colField.setText(String.valueOf(initcols));
Object[] input = {msgString1, rowField, msgString2, colField,
saveDefault};
 
setOptionPane(input,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
newFileIcon);
// pack();
}
 
/**
* Get the input row number
*
* @return the row number
*/
public int getRows() { return rows; }
/**
* Get the input column number
*
* @return the column number
*/
public int getColumns() { return cols; }
 
/**
* a function to display error messages
*
* @param error the error message
* @param field the component causing this error
*/
private void newFileError(String error, JTextField com) {
SharpOptionPane.showMessageDialog(this, error, SharpTools.translation.getProperty("Error"),
JOptionPane.ERROR_MESSAGE);
com.selectAll();
com.requestFocus();
}
 
protected boolean onOK() {
try {
rows = rowField.getInteger().intValue();
}
catch (Exception e1) {
rows = 0;
}
if (rows <= 0) {
newFileError(SharpTools.translation.getProperty("Invalid_row_value"), rowField);
return false;
}
try {
cols = colField.getInteger().intValue();
}
catch (Exception e2) {
cols = 0;
}
if (cols <= 0) {
newFileError(SharpTools.translation.getProperty("Invalid_column_value"), colField);
return false;
}
if (saveDefault.isSelected()) {
// save stuff
Config config = SharpTools.getConfig();
config.setInt("ROWS", rows);
config.setInt("COLUMNS", cols);
}
return true;
}
 
protected boolean onCancel() {
rows = cols = 0;
return true;
}
protected void onOpen() {
// set the initial focus to rowField
rowField.selectAll();
rowField.requestFocus();
}
protected boolean onClose() {
// cancelled
rows = cols = 0;
return true;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/ConnectDialog.java
0,0 → 1,257
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @ (#)ConnectDialog.java
*
* $Id: ConnectDialog.java,v 1.11 2002/08/08 05:15:02 huaz Exp $
*
* Created on May 19, 2001, 09:10:28 PM
*
* Changelogs:
*
* first version - Shiraz Kanga
* various fixes and enhancements - Hua Zhong
*/
package SharpTools;
import javax.swing.*;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import java.awt.event.*;
import java.sql.*;
import java.util.Vector;
 
/**
* This class provides a database conection dialog.
* User is prompted to choose various database options.
*
* @author Shiraz Kanga (first version)
* @author Hua Zhong (ported to SharpDialog and various enhancements)
* @version $Revision: 1.11 $
*/
 
public class ConnectDialog extends SharpDialog {
private JFrame frame;
private JOptionPane optionPane;
private JCheckBox lockTableBox;
private JCheckBox verifySaveBox;
final ImageIcon removeIcon=new ImageIcon(getClass().getResource("/images/no.gif"));
//final private static ImageIcon removeIcon = SharpTools.getImageIcon ("no.gif");
final ImageIcon databaseIcon=new ImageIcon(getClass().getResource("/images/database32.gif"));
//final private static ImageIcon databaseIcon = SharpTools.getImageIcon ("database32.gif");
final private static ImageIcon dbErrorIcon = null;
private Connection dbConnection = null;
final private JTextField connectnameField = new JTextField ();
final private JTextField usernameField = new JTextField ();
final private JPasswordField passwordField = new JPasswordField ();
final private JTextField driverField = new JTextField ();
final private JTextField urlField = new JTextField ();
// final private JCheckBox save = new JCheckBox("Save connection", true);
final private JCheckBox saveConnection = new JCheckBox("Save Connection", true);
final private JCheckBox savePassword = new JCheckBox("Save Password", false);
 
private int maxConn = 0;
final private JButton removeButton = new JButton("Remove", removeIcon);
private JComboBox box;
public ConnectDialog (JFrame aFrame) {
super (aFrame, "Connect to Database", true);
frame = aFrame;
 
//various properties of the dialog labels and text fields
final String msgString0 = "Connection Name:";
final String msgString1 = "Username:";
final String msgString2 = "Password:";
final String msgString3 = "Driver:";
final String msgString4 = "URL:";
 
final Config config = SharpTools.getConfig();
maxConn = config.getInt ("NUMCONNECTIONS");
 
final Vector possibleValues = new Vector();
possibleValues.add("Previous connections");
// use Vector so that we won't enter null pointers in - huaz
for (int i=1; i<=maxConn; i++) {
String entry = config.get ("CONNECTION." + i + ".NAME");
if (entry != null && entry.length() > 0)
possibleValues.add(entry);
else
break;
}
 
box = new JComboBox(possibleValues);
box.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
// Config config = SharpTools.getConfig();
int index = box.getSelectedIndex();
if (index <= 0)
return;
String key = "CONNECTION."+index;
connectnameField.setText(config.get(key+".NAME"));
usernameField.setText(config.get(key+".USERNAME"));
passwordField.setText(config.get(key+".PASSWORD"));
urlField.setText(config.get(key+".URL"));
driverField.setText(config.get(key+".DRIVER"));
}
}
});
 
removeButton.setToolTipText("Remove the selected connection");
removeButton.setMnemonic(KeyEvent.VK_R);
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int index = box.getSelectedIndex();
if (index <= 0)
return;
// Config config = SharpTools.getConfig();
 
// we need to move the following connections upward
for (int i = index; i < maxConn; i++) {
config.set("CONNECTION."+i+".NAME",
config.get("CONNECTION."+(i+1)+".NAME"));
config.set("CONNECTION."+i+".USERNAME",
config.get("CONNECTION."+(i+1)+".USERNAME"));
config.set("CONNECTION."+i+".PASSWORD",
config.get("CONNECTION."+(i+1)+".PASSWORD"));
config.set("CONNECTION."+i+".URL",
config.get("CONNECTION."+(i+1)+".URL"));
config.set("CONNECTION."+i+".DRIVER",
config.get("CONNECTION."+(i+1)+".DRIVER"));
}
 
String maxkey = "CONNECTION."+maxConn;
config.set(maxkey+".NAME", "");
 
// remove from item
box.setSelectedIndex(0);
box.removeItemAt(index);
}
});
 
JPanel panel = new JPanel(new FlowLayout());
panel.add(box);
panel.add(removeButton);
 
JPanel cbPanel = new JPanel(new FlowLayout());
cbPanel.add(saveConnection);
cbPanel.add(savePassword);
Object[] input = {
panel,
msgString0, connectnameField, msgString1, usernameField,
msgString2, passwordField, msgString3, driverField,
msgString4, urlField, cbPanel
};
setOptionPane (input,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
databaseIcon);
}
 
public Connection getConnection() {
return dbConnection;
}
 
protected boolean onOK() {
String connectName = connectnameField.getText ().trim();
String dbUsername = usernameField.getText ().trim();
String dbPassword = String.copyValueOf(passwordField.getPassword ());
String dbDriver = driverField.getText ().trim();
String dbUrl = urlField.getText ().trim();
// validation moved from Database.java - huaz
 
if ((dbUsername == null || dbUsername.length () == 0) &&
(dbUrl == null || dbUrl.length () == 0) &&
(dbDriver == null || dbDriver.length () == 0)) {
SharpOptionPane.showMessageDialog(this,
"You must provide values for Username, Url and Driver.\n",
"Connect",
JOptionPane.INFORMATION_MESSAGE,
databaseIcon);
return false;
}
 
try {
Class.forName (dbDriver);
}
catch (ClassNotFoundException e) {
SharpOptionPane.showMessageDialog (this, "Unable to load class " + dbDriver + ". Please ensure that it is in your classpath.\n" + e.toString (),
"Class Not Found", JOptionPane.ERROR_MESSAGE, dbErrorIcon);
return false;
}
try {
dbConnection = DriverManager.getConnection (dbUrl, dbUsername, dbPassword);
}
catch (SQLException e) {
SharpOptionPane.showMessageDialog (this, "Unable to connect to the database at " + dbUrl + ".\nPlease ensure that the URL, Username and Password are correct.\n\n" + e.toString (),
"Connect", JOptionPane.ERROR_MESSAGE, dbErrorIcon);
return false;
}
// now we could try to save the connection - huaz
// if saveConnection is not checked we just return
if (! saveConnection.isSelected())
return true;
// if no name provided we don't save
if (connectName.length() == 0) {
SharpOptionPane.showMessageDialog(this, "You did not enter a connection name.\n\nThis connection succeeded but will not be saved.\n", "Save Connection", JOptionPane.WARNING_MESSAGE);
return true;
}
 
// first check whether the connectName is already saved
int index;
for (index = 1; index < box.getItemCount(); index++)
if (connectName.equals(box.getItemAt(index).toString()))
break;
 
if ((index != box.getItemCount() || box.getItemCount() <= maxConn)) {
String key = "CONNECTION."+index;
Debug.println("Saving "+key);
Config config = SharpTools.getConfig();
config.set(key+".NAME", connectName);
config.set(key+".USERNAME", dbUsername);
if (savePassword.isSelected())
config.set(key+".PASSWORD", dbPassword);
config.set(key+".URL", dbUrl);
config.set(key+".DRIVER", dbDriver);
}
else
SharpOptionPane.showMessageDialog(this, "You have defined "+maxConn+" connections.\nYour current connection setting cannot be saved.\n\nRefer to the manual for advanced configuration.\n", "Save Connection", JOptionPane.WARNING_MESSAGE);
return true;
}
 
protected void onOpen() {
// set the initial focus to textField
connectnameField.requestFocus ();
}
}
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SharpOptionPane.java
0,0 → 1,246
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This class provides dialogs that can display a message or receive input
* to the user. It has customized Buttons.
*
* The class is used to replace JOptionPane.
*
* @author Hua Zhong
* @version $Revision: 1.9 $
*
*/
package SharpTools;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
 
public class SharpOptionPane {
 
/**
* @param parentComponent the parent Component for the dialog
* @param message the Object to display
* @param title the String to display in the dialog title bar
* @param messageType the type of message to be displayed
* @param icon the Icon image to display
* @param selectionValues an array of Objects that gives the possible selections
* @param initialSelectionValue the value used to initialize the input field
* @return the input object
*/
public static Object showInputDialog(Component parentComponent,
Object message,
String title,
int messageType,
Icon icon,
Object[] selectionValues,
Object initialSelectionValue) {
return showInputDialog(parentComponent, message, title, messageType,
icon, selectionValues, initialSelectionValue,
false);
}
 
/**
* @param parentComponent the parent Component for the dialog
* @param message the Object to display
* @param title the String to display in the dialog title bar
* @param messageType the type of message to be displayed
* @param icon the Icon image to display
* @param initialSelectionValue the value used to initialize the input field
* @return the input string
*/
public static Integer showIntegerInputDialog(Component parentComponent,
Object message,
String title,
int messageType,
Icon icon,
Object initialSelectionValue) {
Object input = showInputDialog(parentComponent, message, title,messageType, icon, null,initialSelectionValue, true);
try {
if (input != null)
return Integer.getInteger(input.toString());
}
catch (Exception e) {
System.out.println("Error\n"+e);
}
return null;
}
/**
* This is used by showInputDialog and showIntegerInputDialog
*
* @param parentComponent the parent Component for the dialog
* @param message the Object to display
* @param title the String to display in the dialog title bar
* @param messageType the type of message to be displayed
* @param icon the Icon image to display
* @param selectionValues an array of Objects that gives the possible selections
* @param initialSelectionValue the value used to initialize the input field
* @param isInteger whether we only allow integer input
* @return the input object
*/
private static Object showInputDialog(Component parentComponent,
Object message,
String title,
int messageType,
Icon icon,
Object[] selectionValues,
Object initialSelectionValue,
boolean isInteger) {
JPanel panel = new JPanel(new BorderLayout());
JComponent com;
int choice;
 
if (selectionValues == null) {
// we use a JTextField
if (isInteger) {
com = new NumberField(true, true);
((JTextField)com).setText(initialSelectionValue.toString());
}
else
com = new JTextField(initialSelectionValue.toString());
 
((JTextField)com).selectAll();
}
else {
JComboBox box = new JComboBox(selectionValues);
if (initialSelectionValue != null)
box.setSelectedItem(initialSelectionValue);
else
box.setSelectedIndex(0);
 
com = box;
}
 
if (message instanceof Component)
panel.add((Component)message, BorderLayout.NORTH);
else
panel.add(new Label(message.toString()), BorderLayout.NORTH);
panel.add(com, BorderLayout.CENTER);
choice = showOptionDialog(parentComponent, panel, title,
JOptionPane.OK_CANCEL_OPTION,
messageType, icon);
 
if (choice == JOptionPane.OK_OPTION) {
if (com instanceof JTextField)
return ((JTextField)com).getText();
else
return ((JComboBox)com).getSelectedItem();
}
else
return null;
}
/**
* @param parentComponent the parent component
* @param message the message to be displayed
*/
public static void showMessageDialog(Component parentComponent,
Object message) {
showMessageDialog(parentComponent, message, null, 0, null);
}
/**
* @param parentComponent the parent component
* @param message the message to be displayed
* @param title dialog title
* @param messageType the message type
* @param icon the icon to display
*/
public static void showMessageDialog(Component parentComponent,
Object message,
String title,
int messageType) {
showMessageDialog(parentComponent, message, title, messageType, null);
}
/**
* @param parentComponent the parent component
* @param message the message to be displayed
* @param title dialog title
* @param messageType the message type
* @param icon the icon to display
*/
public static void showMessageDialog(Component parentComponent,
Object message,
String title,
int messageType,
Icon icon) {
showOptionDialog(parentComponent, message, title,
JOptionPane.DEFAULT_OPTION,
messageType, icon, 0);
}
 
/**
* @param parentComponent the parent component
* @param message the message to be displayed
* @param title dialog title
* @param optionType the option type
* @param messageType the message type
* @param icon the icon to display
* @return user choice
*/
public static int showOptionDialog(Component parentComponent,
Object message,
String title,
int optionType,
int messageType,
Icon icon) {
return showOptionDialog(parentComponent, message, title, optionType,
messageType, icon, 0);
}
/**
* Note the interface is different from JOptionPane.showOptionDialog()
*
* @param parentComponent the parent component
* @param message the message to be displayed
* @param title dialog title
* @param optionType the option type
* @param messageType the message type
* @param icon the icon to display
* @param defaultIndex defaultIndex
* @return user choice
*/
public static int showOptionDialog(Component parentComponent,
Object message,
String title,
int optionType,
int messageType,
Icon icon,
int defaultIndex) {
 
SharpDialog dialog;
 
if (parentComponent instanceof Frame)
dialog = new SharpDialog((Frame)parentComponent, title, true);
else
dialog = new SharpDialog((Dialog)parentComponent, title, true);
dialog.setOptionPane(message, messageType,
optionType, icon,
defaultIndex);
dialog.show();
return dialog.getChoice();
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/ParserException.java
0,0 → 1,74
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package SharpTools;
/*
* @(#)ParserException.java
*
* $Id: ParserException.java,v 1.6 2000/11/18 07:12:17 huaz Exp $
*
* Created on October 28, 2000, 6:26 PM
*/
 
/**
* This Exception is raised when Formula fails in tokenizing or parsing the
* formula.
*
* @author Hua Zhong <huaz@cs.columbia.edu>
* @version $Revision: 1.6 $
*/
public class ParserException extends Exception {
private boolean quiet;
private String msg;
 
/**
* Contructor for ParserException. By default, sets quiet to true.
*/
public ParserException() { quiet = true; };
 
/**
* @param msg the error message string
*/
public ParserException(String msg) { super(msg); this.msg = msg; };
 
/**
* @param msg the error object
*/
public ParserException(Object msg) {
super(msg.toString());
this.msg = msg.toString();
};
 
/**
* This returns the value of quiet.
*
* @return true if quiet is true, false otherwise
*/
public boolean isQuiet() { return quiet; }
 
/**
* toString method for ParserException.
*
* @return the error message string
*/
public String toString() { return msg; }
}
 
 
 
 
 
 
 
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/Cell.java
0,0 → 1,329
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)Cell.java
*
* $Id: Cell.java,v 1.27 2000/12/05 06:05:18 rkc10 Exp $
*
* Created on October 14, 2000, 6:23 PM
*/
package SharpTools;
import java.util.*;
 
/**
* This is a wrapper class for all objects in the table.
* <P>
* A cell has a value which is either text or a number.
* If it is a formula cell it also has an expression associated with it.
* In addition, a cell has a list of all cells that reference it.
*
* @author Ricky Chin
* @version $Revision: 1.27 $
*/
 
public class Cell {
 
/** The integer code that denotes the cell holds text. */
public static final int TEXT = 0;
 
/** The integer code that denotes the cell holds numbers. */
public static final int NUMBER = 1;
 
/** The integer code that denotes the cell holds a formula. */
public static final int FORMULA = 2;
 
/** Value of the cell. In a formula, value holds the evaluated value. */
private Object value;
/**
* This expression contains the string and internal representation
* of the formula if it exists.
*/
private Formula expression;
 
/**
* The list of cells that reference this cell. When a cell is changes,
* all cells on this list should notified.
*/
private TreeSet refs;
 
/** Creates an empty cell */
public Cell() {
value = null;
expression = null;
refs = null;
}
 
/**
* This constructor constructs a cell that will not have cells
* referencing it and are not formulas. Basically only used for creating
* the row and column labels.
* <P>
* <b>Warning:</b> Do not use this with Formulas
* @param datum the value of the "label" cell (not a Formula)
*/
public Cell(Object datum) {
value = datum;
expression = null;
refs = null;
}
/**
* The constructor creates a new data cell which is not a formula.
* <P>
* <b>Note:</b> A normal cell's data is stored in value field
* but expression (i.e. formula) field is null.
* @param datum the value of the cell (text or number)
* @param reference the list of cells that reference this one (can be null)
*/
public Cell(Object datum, TreeSet reference) {
value = datum;
expression = null;
refs = reference;
}
/**
* This version of the constructor constructs a formula cell.
*
* @param thing internal represenation of the formula
* @param eVal the evaluated value of the formula (thing)
* @param reference the list of cells that reference this one (can be null)
*/
public Cell(Formula thing, Object eVal, TreeSet reference) {
expression = thing;
value = eVal;
refs = reference;
}
 
/**
* This method returns the formula associated with the cell or null if it
* does not exist.
*
* @return the formula (string and internal object) or null if does not
* exist
*/
public Formula getFormula() {
return expression;
}
 
 
/**
* If it is a data cell, it returns the data of the cell. If it is a
* formula, it returns the previously evaluated value of the formula.
*
* @return the value (data or evaluated) of the cell
*/
public Object getValue() {
return value;
}
 
/**
* Sets the value field of the cell.
*
* @param datum the object to set the value of cell to
*/
public void setValue(Object datum) {
value = datum;
}
 
/**
* This method changes the cell to a data cell with value datum. This
* method useful because changing the value does not affect the value of
* the reference list.
*
* <b>Warning</b>: If the cell is going to be set to a formula, you must
* use setFormula() because this present method sets the associated formula
* field, expression, to null.
*
* @param datum the new value of cell
*/
public void setData(Object datum) {
value = datum;
expression = null;
}
 
/**
* This method sets the cell to be a formula cell. It puts the formula
* object into the expression field. The Table of Cells is responsible
* for recalculating and setting the appropriate value in the value
* field of this cell.
*
* @param form the internal representation of formula to set this cell to
*/
public void setFormula(Formula form) {
expression = form;
}
 
/** Returns true if cell at specified position is empty.
* @return true if empty, false is not
*/
public boolean isEmpty() {
if(value.equals("") && expression == null)
return true;
else
return false;
}
/**
* This method returns true if there are cells that reference this one.
*
* @return true only if there are cells that reference this one
*/
public boolean hasRefs() {
return (refs != null && !refs.isEmpty());
}
 
/**
* This method gets the list of cells that reference this one.
* This method should be used after the cell's value has been changed
* to find out which cells need to be updated.
*
* @return all cells that reference this cell
*/
public TreeSet getRefs() {
return refs;
}
 
/**
* This method removes a cell from reference list.
*
* @param reference the cell to be removed from the reference list
*/
public void removeRef(CellPoint reference) {
// System.out.println("remove ref "+reference+" from "+this);
if (refs != null) {
refs.remove(reference);
if (refs.isEmpty()) refs = null;
}
}
 
/**
* This method adds a cell to the dependency list.
*
* @param reference a new cell that references this one that needs to be
* added to the reference list
*/
public void addRef(CellPoint reference) {
// System.out.println("add ref "+reference+" to ("+this);
if (refs == null) {// check if refs is initiated
refs = new TreeSet();
}
refs.add(reference);
}
 
/**
* This method is useful for determining what information a cell holds. To
* check if a cell holds a certain type just see if
* getType() == Cell.CODE where CODE is any of the cell constants.
*
* @return the integer code of the type of data this cell holds
*/
public int getType() {
if (expression != null) return Cell.FORMULA;
if (value instanceof Number) return Cell.NUMBER;
return Cell.TEXT;
}
/**
* This method returns true IFF it is a formula cell
*
* @return true iff a formula cell
*/
public boolean isFormula() {
return (expression != null);
}
/**
* This method determines a cell is a formula cell that has a error.
*
* @return true if cell is an error cell
*/
public boolean isErrorCell() {
return ((isFormula()) && (value instanceof ParserException));
}
/**
* This is a method similar to compareTo except that it is not
* consistent with the equals method. It is used for sorting.
* Cells are rated in increasing order: blank, error, string,
* number (including formulas). If two cells are blank or errors
* then they are "equal" by this compare method. Numbers and
* strings are compared the usual way.
*
* @param x cell to compare this to
* @return -1 if this < x, 0 if this = x, 1 if this > x
*/
public int compare(Cell x, boolean ascending) {
//if this is blank which is lowest value
if (this.value.equals("")) {
//x is not blank so this is less than
if (!x.value.equals("")) {
if (ascending) {
return 1;
} else {
return -1;
}
} else { //otherwise equal
return 0;
}
} else {
if (x.value.equals("")) {
if (ascending) {
return -1;
}else {
return 1;
}
} else { //both have values
if (this.isErrorCell()) {
if (x.isErrorCell()) {
return 0;
} else {
return -1;
}
} else {
if (x.isErrorCell()) {
return 1;
} else {
if (this.getType() == Cell.TEXT) {
if (x.getType() == Cell.TEXT) {
String temp = (String)this.value;
return temp.compareToIgnoreCase((String)x.value);
} else {
return -1;
}
} else {
if (x.getType() == Cell.TEXT) {
return 1;
} else {
Float first = (Float)this.value;
Float second = (Float)x.value;
return first.compareTo(second);
}
}
}
}
}
}
}
public String toString() {
if (expression != null)
return "="+expression.toString();
else
return value.toString();
}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/Function.java
0,0 → 1,978
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)Function.java
*
* $Id: Function.java,v 1.24 2002/08/08 05:15:04 huaz Exp $
*
* Created on October 30, 2000, 10:29 AM
*/
package SharpTools;
import java.util.*;
import java.io.*;
 
/**
* Function classes used only by Formula to evaluate functions.
* Any function needs to have a function handler that implements
* the "evaluate" interface of the base class Function.
*
* A function can accept zero, one, or more parameters. Each parameter
* is a number, a relative/absolute address or an address range (e.g., A1:B3).
*
* @author Hua Zhong
* @version $Revision: 1.24 $
*/
 
public abstract class Function {
 
static private ParserException exception = new ParserException("#PARAM?");
// whether the specified parameter node is an address range
protected boolean isRange(Node param) {
LinkedList exp = param.getExp();
return exp.size() == 1 &&
((Node)exp.getFirst()).isType(Node.COLON);
//((Node)param.getExp().getFirst()).isType(Node.COLON);
}
 
// return the first node of a specified parameter
protected Node getFirst(Node param) {
return (Node)param.getExp().getFirst();
}
 
// whether this function has any parameter
protected void checkParamsExist(Node func) throws ParserException {
if (func.getParams().size()==0){
throw exception;
}
}
/**
* This gets the first float number of a parameter li
st, for functions
* only accepting a single parameter such as <code>ABS</code>, <code>COS
* </code>, etc.
*
* @param table the SharpTabelModel
* @param node the formula unit
* @param col the int column coordinate
* @param row the int row coordinate
* @return the float number
*/
static protected float getSingleParameter(SharpTableModel table, Node node,
int row, int col)
throws ParserException {
// Node param = node.getNextParam();
LinkedList params = node.getParams();
 
if (params.size() != 1)
throw new ParserException("#PARAM?");
 
LinkedList exp = ((Node)params.getFirst()).getExp();
return Formula.evaluate(table, exp, row, col).floatValue();
 
}
 
/*
* This gets two float numbers of a parameter list, for functions
* only accepting two parameters.
*
* @param table the SharpTabelModel
* @param node the formula unit
* @param col the int column coordinate
* @param row the int row coordinate
* @return two float nubmers
*/
/*
static protected float[] getDoubleParameter(SharpTableModel table,
Node node,
int row, int col)
throws ParserException {
// Node param = node.getNextParam();
LinkedList params = node.getParams();
 
if (params.size() != 2)
throw new ParserException("#PARAM?");
 
float[] values = new float[2];
LinkedList exp = ((Node)params.getFirst()).getExp();
values[0] = Formula.evaluate(table, exp, row, col).floatValue();
 
exp = ((Node)params.getLast()).getExp();
values[1] = Formula.evaluate(table, exp, row, col).floatValue();
 
return values;
}
*/
/**
* This should be implemented in each function.
*
* @param table the SharpTabelModel
* @param node the function node starting with the funciton name
* with a chain of parameters
* @param col the int column coordinate
* @param row the int row coordinate
* @exception ParserException
*/
public abstract Number evaluate(SharpTableModel table, Node node, int row, int col) throws ParserException;
 
/**
* Return the usage of the function
*/
public abstract String getUsage();
/**
* Return the description of the function
*/
public abstract String getDescription();
 
/**
* Whether this function requires parameters.
* By default yes.
* @see FunctionPI
* @see FunctionE
*/
public boolean requireParams() { return true; }
}
 
/**
* <code>SUM</code><br>
* usage: <code>=SUM(parameter list)</code><br>
* returns the arithmetic sum of the specified parameters<br>
* example: <code>=SUM(-1,2,57)</code> returns <code>58.0</code>
*/
 
class FunctionSum extends Function {
public Number evaluate(SharpTableModel table, Node node, int row, int col) throws ParserException {
// requires parameters
checkParamsExist(node);
float sum = 0;
 
LinkedList params = node.getParams();
if (params != null) {
 
// go over the parameters
Iterator it = params.iterator();
 
while (it.hasNext()) {
 
// get this parameter
Node exp = (Node)it.next();
 
// if it's a range of cells
if (isRange(exp)) {
CellPoint[] addr =
getFirst(exp).getAddressRange(row, col);
// for a range, go over the whole range
for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++)
// get the numeric value of that cell
sum += table.getNumericValueAt(i, j).floatValue();
}
else {
// evaluate this parameter's expression (sub-formula)
sum += Formula.evaluate(table, exp.getExp(), row, col).floatValue();
}
}
}
return (Number)(new Float(sum));
}
 
public String getUsage() {
return "SUM(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("sum_desc");
//return "Adds all the numbers in a set of values.";
}
}
 
 
/**
* <code>COUNT</code><br>
* usage: <code>=COUNT(parameter list)</code><br>
* returns the number of parameters specified<br>
* example: <code>=COUNT(A1:A7)</code> returns <code>7.0</code>
*/
class FunctionCount extends Function {
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
// requires parameters
checkParamsExist(node);
 
int count = 0;
 
LinkedList params = node.getParams();
if (params != null) {
 
Iterator it = params.iterator();
 
while (it.hasNext()) {
// the first parameter
Node exp = (Node)it.next();
if (isRange(exp)) {
// if it's a range then count the number of cells
CellPoint[] addr =
getFirst(exp).getAddressRange(row, col);
count += (addr[1].getRow()-addr[0].getRow()+1) *
(addr[1].getCol()-addr[0].getCol()+1);
}
else {
// otherwise count one
count++;
}
}
}
return new Integer(count);
}
 
public String getUsage() {
return "COUNT(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("count_desc");
//return "Counts the number of cells that contain numbers and numbers within the list of arguments.";
}
}
 
/**
* <code>AVERAGE</code><br>
* usage: <code>=AVERAGE(parameter list)</code><br>
* returns the arithmetic mean of the specified parameters<br>
* example: <code>=AVERAGE(1,2,3)</code> returns <code>2.0</code>
*/
class FunctionAverage extends Function {
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
float sum = (new FunctionSum()).evaluate(table, node, row, col).
floatValue();
float nCells = (new FunctionCount()).evaluate(table, node, row, col).
floatValue();
return new Float(sum/nCells);
}
 
public String getUsage() {
return "AVERAGE(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("average_desc");
//return "Returns the average (arithmetric mean) of its arguments.";
}
}
 
/**
* <code>MEDIAN</code><br>
* usage: <code>=MEDIAN(parameter list)</code><br>
* returns the median (the value in the middle) of the specified parameters<br>
* example: <code>=MEDIAN(1,2,5)</code> returns <code>2.0</code>
*/
class FunctionMedian extends Function {
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
// requires parameters
checkParamsExist(node);
 
// get number of values
int nCells = (int)(new FunctionCount()).
evaluate(table, node, row, col).floatValue();
 
float[] values = new float[nCells];
 
// get all the values
int index = 0;
LinkedList params = node.getParams();
if (params != null) {
 
Iterator it = params.iterator();
 
while (it.hasNext()) {
// the first parameter
Node exp = (Node)it.next();
if (isRange(exp)) {
// if it's a range get each cell's value
CellPoint[] addr =
getFirst(exp).getAddressRange(row, col);
for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
values[index++] =
table.getNumericValueAt(i, j).floatValue();
}
}
else {
// otherwise get this expression's value
values[index++] =
Formula.evaluate(table, exp.getExp(), row, col).floatValue();
}
}
}
 
// sort the values array
for (int m = 0; m < nCells-1; m++)
for (int n = m; n < nCells-1; n++)
if (values[m]>values[n]) {
float tmp = values[m];
values[m] = values[n];
values[n] = tmp;
}
 
// get the median
int half = nCells/2;
if (nCells != half*2)
return new Float(values[half]);
else
return new Float((values[half-1]+values[half])/2);
}
 
public String getUsage() {
return "MEDIAN(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("median_desc");
//return "Returns the median (value in the middle) of its arguments.";
}
}
 
/**
* <code>MIN</code><br>
* usage: <code>=MIN(parameter list)</code><br>
* returns the minimum value of the specified parameters<br>
* example: <code>=MIN(5,6,-1)</code> returns <code>-1.0</code>
*/
class FunctionMin extends Function {
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
// requires parameters
checkParamsExist(node);
float min = Float.MAX_VALUE;
LinkedList params = node.getParams();
if (params != null) {
 
Iterator it = params.iterator();
 
while (it.hasNext()) {
 
Node exp = (Node)it.next();
if (isRange(exp)) {
CellPoint[] addr =
getFirst(exp).getAddressRange(row, col);
for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
float value =
table.getNumericValueAt(i, j).floatValue();
if (value < min)
min = value;
}
}
else {
float value =
Formula.evaluate(table, exp.getExp(), row, col).floatValue();
if (value < min)
min = value;
}
}
}
return new Float(min);
}
 
public String getUsage() {
return "MIN(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("min_desc");
//return "Returns the smallest number in a set of values.";
}
}
 
/**
* <code>MAX</code><br>
* usage: <code>=MAX(parameter list)</code><br>
* returns the maximum value of the specified parameters<br>
* example: <code>=MAX(5,6,-1)</code> returns <code>6.0</code>
*/
class FunctionMax extends Function {
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
// requires parameters
checkParamsExist(node);
float max = Float.MIN_VALUE;
LinkedList params = node.getParams();
if (params != null) {
 
Iterator it = params.iterator();
 
while (it.hasNext()) {
 
Node exp = (Node)it.next();
if (isRange(exp)) {
CellPoint[] addr =
getFirst(exp).getAddressRange(row, col);
for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
float value =
table.getNumericValueAt(i, j).floatValue();
if (value > max)
max = value;
}
}
else {
float value =
Formula.evaluate(table, exp.getExp(), row, col).floatValue();
if (value > max)
max = value;
}
}
}
return new Float(max);
}
 
 
public String getUsage() {
return "MAX(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("max_desc");
//return "Returns the largest number in a set of values.";
}
}
 
/**
* <code>Range</code>
*/
class FunctionRange extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
float max = Formula.getFuncHandler("MAX").
evaluate(table, node, row, col).
floatValue();
float min = Formula.getFuncHandler("MIN").
evaluate(table, node, row, col).
floatValue();
return new Float(max - min);
}
 
 
public String getUsage() {
return "RANGE(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("diff_desc");
// return "Returns the difference between MAX and MIN in a set of values.";
}
}
 
/**
* <code>ABS</code><br>
* usage: <code>=ABS(parameter)</code><br>
* accepts only one literal or address<br>
* returns the absolute value of the specified parameter<br>
* example: <code>=ABS(-92)</code> returns <code>92.0</code>
*/
class FunctionAbs extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
return new Float(Math.abs
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "ABS(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("abs_desc");
//return "Returns the absolute value of a number.";
}
}
 
/**
* <code>SIN</code><br>
* usage: <code>=SIN(parameter)</code><br>
* accepts only one literal or address<br>
* returns the sine of the specified parameter (in radians)<br>
* example: <code>=SIN(45)</code> returns <code>0.8509035</code>
*/
class FunctionSin extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
return new Float(Math.sin
(getSingleParameter(table, node, row, col)));
}
 
 
public String getUsage() {
return "SIN(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("sin_desc");
//return "Returns the sine of an angle.";
}
}
 
/**
* <code>COS</code><br>
* usage: <code>=COS(parameter)</code><br>
* accepts only one literal or address<br>
* returns the cosine of the specified parameter (in radians)<br>
* example: <code>=COS(30)</code> returns <code>0.15425146</code>
*/
class FunctionCos extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
return new Float(Math.cos
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "COS(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("cos_desc");
//return "Returns the cosine of an angle.";
}
}
 
/**
* <code>TAN</code><br>
* usage: <code>=TAN(parameter)</code><br>
* accepts only one literal or address<br>
* returns the tangent of the specified parameter (in radians)<br>
* example: <code>=TAN(60)</code> returns <code>0.32004037</code>
*/
class FunctionTan extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
return new Float(Math.tan
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "TAN(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("tan_desc");
//return "Returns the tangent of an angle.";
}
}
 
/**
* <code>ASIN</code><br>
* usage: <code>=ASIN(parameter)</code><br>
* accepts only one literal or address<br>
* returns the arcsine of the specified parameter (in radians)<br>
* example: <code>=ASIN(60)</code> returns <code>0.5235988</code>
*/
class FunctionAsin extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
return new Float(Math.asin
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "ASIN(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("asin_desc");
//return "Returns the arcsine of a number in radians, in the range -Pi/2 to Pi/2.";
}
}
 
/**
* <code>ACOS</code><br>
* usage: <code>=ACOS(parameter)</code><br>
* accepts only one literal or address<br>
* returns the arccosine of the specified parameter (in radians)<br>
* example: <code>=ACOS(.5)</code> returns <code>1.0471976</code>
*/
class FunctionAcos extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
return new Float(Math.acos
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "ACOS(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("acos_desc");
//return "Returns the arccosine of a number in radians, in the range 0 to Pi.";
}
}
 
/**
* <code>ATAN</code><br>
* usage: <code>=ATAN(parameter)</code><br>
* accepts only one literal or address<br>
* returns the arctangent of the specified parameter (in radians)<br>
* example: <code>=ATAN(60)</code> returns <code>1.5541312</code>
*/
class FunctionAtan extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
return new Float(Math.atan
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "ATAN(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("atan_desc");
//return "Returns the arctangent of a number in radians, in the range -Pi/2 to Pi/2.";
}
}
 
/**
* <code>INT</code>
* returns the integer part of a number
*/
class FunctionInt extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
return new Float((int)getSingleParameter(table, node, row, col));
}
 
public String getUsage() {
return "INT(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("int_desc");
//return "Returns the integer part of a number.";
}
}
 
/**
* <code>ROUND</code><br>
* usage: <code>=ROUND(parameter, num_digits)</code><br>
* Rounds a number to a specified number of digits<br>
* example: <code>=ROUND(1.534, 2)</code> returns <code>1.53</code>
*/
class FunctionRound extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
return new Float(Math.round
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "ROUND(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("round_desc");
//return "Returns the nearest integer of a number.";
}
}
 
/**
* <code>SQRT</code><br>
* usage: <code>=STDDEV(parameter)</code><br>
* returns the standard deviation of the specified parameter<br>
* example: <code>=SQRT(19044)</code> returns <code>138.0</code>
*/
class FunctionSqrt extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
return new Float(Math.sqrt
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "SQRT(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("sqrt_desc");
//return "Returns a square root of a number.";
}
}
 
/**
* <code>LOG</code><br>
* usage: <code>=LOG(parameter)</code><br>
* returns the logarithm base E of the specified parameter<br>
* example: <code>=LOG(1)</code> returns <code>0.0</code>
*/
class FunctionLog extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
return new Float(Math.log
(getSingleParameter(table, node, row, col)));
}
 
public String getUsage() {
return "LOG(value)";
}
public String getDescription() {
return SharpTools.translation.getProperty("log_desc");
//return "Returns the logarithm of a number to the base e.";
}
}
 
/**
* <code>MEANDEV</code><br>
* usage: <code>=MEANDEV(parameter list)</code><br>
* returns the mean deviation of the specified parameters<br>
* example: <code>=STDDEV(100,60,60,80,80)</code> returns <code>12.8</code>
*/
class FunctionMeandev extends Function {
 
// mean deviation is the average of absolute deviations from the mean value
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
float dev = 0;
float nCells = (new FunctionCount()).
evaluate(table, node, row, col).floatValue();
float mean = (new FunctionAverage()).
evaluate(table, node, row, col).floatValue();
 
LinkedList params = node.getParams();
if (params != null) {
 
Iterator it = params.iterator();
 
while (it.hasNext()) {
 
Node exp = (Node)it.next();
if (isRange(exp)) {
CellPoint[] addr =
getFirst(exp).getAddressRange(row, col);
for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
dev += Math.abs(table.getNumericValueAt(i, j).
floatValue() - mean);
}
}
else {
dev +=
Math.abs(Formula.evaluate(table, exp.getExp(), row, col).floatValue());
}
}
}
 
return new Float(dev/nCells);
}
 
public String getUsage() {
return "MEANDEV(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("meandev_desc");
//return "Returns the average absolute deviation in a set of values.";
}
}
 
/**
* <code>STDDEV</code><br>
* usage: <code>=STDDEV(parameter list)</code><br>
* returns the standard deviation of the specified parameters<br>
* example:
* <code>=STDDEV(100,60,60,80,80)</code> returns <code>16.7332</code>
*/
class FunctionStddev extends Function {
 
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
float dev = 0;
float nCells = (new FunctionCount()).
evaluate(table, node, row, col).floatValue();
float mean = (new FunctionAverage()).
evaluate(table, node, row, col).floatValue();
 
LinkedList params = node.getParams();
if (params != null) {
 
Iterator it = params.iterator();
 
while (it.hasNext()) {
 
Node exp = (Node)it.next();
if (isRange(exp)) {
CellPoint[] addr =
getFirst(exp).getAddressRange(row, col);
for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
float temp = Math.abs(table.getNumericValueAt(i, j).
floatValue() - mean);
dev += temp*temp;
}
}
else {
float temp = Math.abs(Formula.evaluate(table, exp.getExp(), row, col).floatValue());
dev += temp*temp;
 
}
}
}
 
return new Float(Math.sqrt(dev/(nCells - 1)));
}
 
public String getUsage() {
return "STDDEV(value1,value2,...)";
}
public String getDescription() {
return SharpTools.translation.getProperty("stddev_desc");
//return "Returns the standard deviation in a set of values.";
}
}
 
/**
* This gives us contant PI.<br>
* <code>PI</code><br>
* usage: <code>=PI()</code><br>
* returns an approximation of the constant pi<br>
* example: <code>=PI()</code> returns <code>3.1415927</code>
*/
class FunctionPI extends Function {
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
// no parameters allowed
if (node.getParams().size() != 0)
throw new ParserException("#PARAM?");
return new Float(Math.PI);
}
 
public String getUsage() {
return "PI()";
}
public String getDescription() {
return SharpTools.translation.getProperty("pi_desc");
//return "Returns the value of PI.";
}
 
public boolean requireParams() { return false; }
}
 
/**
* This gives us contant E.<br>
* <code>E</code><br>
* usage: <code>=E()</code><br>
* returns an approximation of the golden mean<br>
* example: <code>=E()</code> returns <code>2.7182817</code>
*/
class FunctionE extends Function {
public Number evaluate(SharpTableModel table, Node node,
int row, int col) throws ParserException {
 
// no parameters allowed
if (node.getParams().size() != 0)
throw new ParserException("#PARAM?");
 
return new Float(Math.E);
}
 
public String getUsage() {
return "E()";
}
public String getDescription() {
return SharpTools.translation.getProperty("e_desc");
//return "Returns value of e.";
}
 
public boolean requireParams() { return false; }
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/TabPanel.java
0,0 → 1,513
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)TabPanel.java
*
* $Id: TabPanel.java,v 1.5 2001/05/27 22:29:49 huaz Exp $
*
* Created Novenmber 27, 2000, 11:27 PM
*/
package SharpTools;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
/**
* A class for one panel, which includes the image panel and
* all the control components. In short, this is everything
* for one chart.
*
* @author Hua Zhong
* @version $Revision: 1.5 $
*/
public class TabPanel extends JPanel {
 
private Histogram owner;
private SharpTableModel model;
private JTabbedPane tab;
private HistoPanel histo;
// values
private CellRange range;
private Float startvalue, endvalue, bucketvalue,
xmin, xmax, ymin, ymax, xunit, yunit;
private boolean bypercentage = true;
 
/**
* Constructor
*
* @param tableModel the SharpTableModel as backend data
* @param range the selected cell range
* @param frame the parent frame
* @param pane the JTabbedPane object that this panel belongs to
*/
TabPanel(SharpTableModel tableModel, CellRange range,
Histogram frame, JTabbedPane pane) {
super();
this.owner = frame;
this.model = tableModel;
this.tab = pane;
this.range = range;
// set layout - tedious..
setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
setLayout(new BorderLayout());
 
// add the HistoPanel - our canvas
histo = new HistoPanel();
histo.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
add(histo, BorderLayout.CENTER);
 
// buttons
JPanel south = new JPanel();
south.setBorder(BorderFactory.createEmptyBorder(10,0,0,0));
south.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 0));
 
// Remove button
final ImageIcon noIcon=new ImageIcon(getClass().getResource("/images/no.gif"));
JButton closeButton = new JButton(SharpTools.translation.getProperty("Remove"), noIcon);
closeButton.setMnemonic(KeyEvent.VK_R);
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// remove the current tab
tab.remove(tab.getSelectedComponent());
// if there is no tab left, close the window
if (tab.getTabCount() == 0) {
owner.hide();
}
}
});
 
// Options button
final ImageIcon optionsIcon=new ImageIcon(getClass().getResource("/images/options.gif"));
JButton optionButton = new JButton(SharpTools.translation.getProperty("Options"), optionsIcon);
optionButton.setMnemonic(KeyEvent.VK_O);
optionButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
getOptions(false);
}
});
 
// Update button
final ImageIcon refreshIcon=new ImageIcon(getClass().getResource("/images/refresh.gif"));
JButton updateButton = new JButton (SharpTools.translation.getProperty("Update"), refreshIcon);
updateButton.setMnemonic(KeyEvent.VK_U);
updateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
updateData();
histo.paintImmediately(0, 0, histo.getWidth(),
histo.getHeight());
}
});
south.add(updateButton);
south.add(optionButton);
south.add(closeButton);
add(south, BorderLayout.SOUTH);
}
 
/**
* Parameter configuration for this histogram
*
* @param firstTime whether this is the first time to call the dialog
*/
void getOptions(boolean firstTime) {
 
HistoDialog option = new HistoDialog(owner);
option.pack();
option.setLocationRelativeTo(owner);
 
// title textfield
option.setTitleField(tab.getTitleAt(tab.getSelectedIndex()));
if (firstTime) {
// set initial values
option.setCellRange(range);
 
float[] minmax = TabPanel.getValueMinMax(model, range);
int min = (int)minmax[0];
int max = (int)minmax[1];
 
startvalue = new Float(min);
endvalue = new Float(max);
 
// estimate a reasonable bucket size
int power = 0;
if (max>min)
power = (int)((Math.log(max-min)/Math.log(10)));
if (power<0)
power--;
bucketvalue = new Float(Math.pow(10, power));
xunit = bucketvalue;
 
xmin = new Float(min);
xmax = new Float(max);
ymin = new Float(0);
ymax = new Float(100);
yunit = new Float(10);
 
}
 
// initialize all the fields
option.setCellRange(range);
option.setStartValue(startvalue);
option.setEndValue(endvalue);
option.setBucket(bucketvalue);
option.setXMin(xmin);
option.setXMax(xmax);
option.setXUnit(xunit);
option.setYMin(ymin);
option.setYMax(ymax);
option.setYUnit(yunit);
option.setByPercentage(bypercentage);
 
// show the dialog
option.setVisible(true);
 
if (!option.isCancelled()) {
 
// save data
tab.setTitleAt(tab.getSelectedIndex(),
option.getTitleField());
range = option.getCellRange();
startvalue = option.getStartValue();
endvalue = option.getEndValue();
bucketvalue = option.getBucket();
xmin = option.getXMin();
xmax = option.getXMax();
ymin = option.getYMin();
ymax = option.getYMax();
xunit = option.getXUnit();
yunit = option.getYUnit();
bypercentage = option.getByPercentage();
 
// do an update to repaint the chart
update();
}
}
/**
* get the min and max values from the cell range
*
* @param model the backend table data source
* @param range the range of cells
* @return two float numbers, first is min and second is max
*/
static float[] getValueMinMax(SharpTableModel model, CellRange range) {
// value[0] is min, value[1] is max
float[] values = { Float.MAX_VALUE, Float.MIN_VALUE };
float v;
for (int i = range.getStartRow(); i <= range.getEndRow(); i++)
for (int j = range.getStartCol(); j <= range.getEndCol(); j++) {
try {
v = model.getNumericValueAt(i, j).floatValue();
}
catch (ParserException e) {
v= 0;
}
 
values[0] = Math.min(values[0], v);
values[1] = Math.max(values[1], v);
}
 
return values;
}
 
/**
* Update everything of the histogram.
*
* This is called after we change options by the Option dialog.
*/
public void update() {
 
float start = startvalue.floatValue();
float end = endvalue.floatValue();
float bucket = bucketvalue.floatValue();
float nb = (end-start)/bucket;
int nbars = (int)nb;
if (nbars > (int)nbars)
nbars++;
 
// values below and above
nbars += 2;
 
float[] data = new float[nbars];
histo.setData(data);
 
updateData();
histo.setStartEndPoints(start, end, bucket);
histo.setXYAxis(xmin.floatValue(),
xmax.floatValue(),
xunit.floatValue(),
ymin.floatValue(),
ymax.floatValue(),
yunit.floatValue());
 
histo.setByPercentage(bypercentage);
histo.paintImmediately(0, 0, histo.getWidth(), histo.getHeight());
}
 
/**
* Read values from textfields and update the histogram's data;
* Nothing else.
*
* This is called from the "Update" button.
*/
private void updateData() {
 
float start = startvalue.floatValue();
float end = endvalue.floatValue();
float bucket = bucketvalue.floatValue();
float[] data = histo.getData();
for (int k = 0; k < data.length; k++)
data[k] = 0;
// two more buckets below start or above end
// float scale = end-start+2;
 
for (int i = range.getStartRow(); i <= range.getEndRow(); i++) {
for (int j = range.getStartCol(); j <= range.getEndCol(); j++) {
float value = 0;
 
try {
value = model.getNumericValueAt(i, j).floatValue();
}
catch (Exception e) {
}
if (value < start)
data[0]++;
else if (value > end)
data[data.length-1]++;
else {
int index = (int)((value-start)/bucket)+1;
data[index]++;
}
}
}
 
if (bypercentage) {
int nums = range.getWidth()*range.getHeight();
for (int k = 0; k < data.length; k++)
data[k] = data[k]*100/nums;
}
// histo.setData(data); - dont need it since we've modified in-place
}
}
 
/**
*
* The is the panel to draw histogram on.
*
* One thing to pay attention to is the virtual coordinate we are using.
* Virtual coordinate is the coordinate used as in the histogram.
* The differences between a virtual coordinate and the Java coordinate system
* are:
* 1) Y axis direction is different
* 2) We take border into account for virtual coordinate (so it has a smaller
* scale).
*
* @author Hua Zhong
* @version $Revision: 1.5 $
*/
 
class HistoPanel extends JPanel /*implements ComponentListener*/ {
 
private float[] bars; // distribution
private float start, end, bucket;
private float xmin, xmax, xunit;
private float ymin, ymax, yunit;
private float xscale, yscale; // xmax-xmin and ymax-ymin
private int xsize, ysize;
private int xborder = 50;
private int yborder = 40;
private boolean bypercentage;
// private int maxdigits;
 
public void setStartEndPoints(float start, float end, float bucket) {
this.start = start;
this.end = end;
this.bucket = bucket;
}
 
public void setXYAxis(float xmin, float xmax, float xunit,
float ymin, float ymax, float yunit) {
this.xmin = xmin;
this.xmax = xmax;
this.xunit = xunit;
this.ymin = ymin;
this.ymax = ymax;
this.yunit = yunit;
 
xscale = xmax-xmin;
yscale = ymax-ymin;
 
// calculate optimized xborder
int len1 = String.valueOf(ymin).length();
int len2 = String.valueOf(ymax).length();
int len3 = String.valueOf(yunit).length();
 
int maxdigits = Math.max(Math.max(len1, len2), len3);
xborder = maxdigits*getGraphics().getFontMetrics().charWidth('0')+10;
}
 
public void setByPercentage(boolean bypercentage) {
this.bypercentage = bypercentage;
}
public void setData(float[] data) {
bars = data;
}
 
public float[] getData() {
return bars;
}
/**
* This is the overriden method of customized drawing
*
* @param g the Graphics object
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
 
if (bars == null)
return;
xsize = getXSize();
ysize = getYSize();
 
// draw x axise
if (xsize < 0 || ysize < 0)
return;
 
float xratio = xscale/xsize;
float yratio = yscale/ysize; // xscale/xsize; yscale/ysize
// x axis
drawLine(g, 0, 0, xsize+20, 0);
// y xais
drawLine(g, 0, 0, 0, ysize+20);
 
if (bypercentage)
cString(g, "(%)", 0, ysize+30);
 
// draw x ticks
for (float x = xmin; x <= xmax; x+=xunit) {
int xcoor = (int)((x-xmin)/xratio);
drawLine(g, xcoor, +3, xcoor, -3);
cString(g, String.valueOf(x), xcoor, -20);
}
 
// draw y ticks
for (float y = ymin; y <= ymax; y+=yunit) {
int ycoor = (int)((y-ymin)/yratio);
drawLine(g, -3, ycoor, +3, ycoor);
rString(g, String.valueOf(y), -5, ycoor);
}
// draw bars!
// int barwidth = (int)(bucket/xratio);
for (int i = 0; i < bars.length; i++) {
// for (float x = start-bucket; x < end+bucket; x+=bucket) {
float x = start+(i-1)*bucket;
int ycoor = (int)((bars[i]-ymin)/yratio);
int xcoor1 = (int)((x-xmin)/xratio);
int xcoor2 = (int)((x+bucket-xmin)/xratio);
 
// must be in range
xcoor1 = Math.max(xcoor1, 0);
xcoor2 = Math.min(xcoor2, xsize);
 
if (i == 0)
xcoor1 = 0;
 
if (i == bars.length-1)
xcoor2 = xsize;
if (xcoor1 >= xcoor2)
continue;
 
// draw the bar
drawLine(g, xcoor1, 0, xcoor1, ycoor);
drawLine(g, xcoor2, 0, xcoor2, ycoor);
drawLine(g, xcoor1, ycoor, xcoor2, ycoor);
 
}
}
 
private int getXSize() {
return getWidth()-2*xborder;
}
private int getYSize() {
return getHeight()-2*yborder;
}
 
// draw a line between virtual coordinates (x1, y1) and (x2, y2)
// borders are taken into account and Y axis is upwards.
private void drawLine(Graphics g, int x1, int y1, int x2, int y2) {
 
// draw axis
g.drawLine(x1+xborder, ysize-y1+yborder,
x2+xborder, ysize-y2+yborder);
}
 
// draw a string at virtual coordinate (x, y)
// borders are taken into account and Y axis are up.
private void drawString(Graphics g, String s, int x, int y) {
 
// draw axis
g.drawString(s, x+xborder, ysize-y+yborder);
}
// do some internal coordinate SharpTools.translation
// coordinate SharpTools.translation for X (to virtual coordinate)
private int getx(int x) {
return x+xborder;
}
// coordinate SharpTools.translation for Y (to virtual coordinate)
private int gety(int y) {
return ysize-y+yborder;
}
 
// display a string by center alignment
private void cString(Graphics g1, String s, int i, int j) {
int k = g1.getFontMetrics().stringWidth(s);
drawString(g1, s, i - k / 2, j);
}
 
// display a string by right alignment
private void rString(Graphics g1, String s, int i, int j) {
int k = g1.getFontMetrics().stringWidth(s);
drawString(g1, s, i - k, j);
}
 
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/HelpOp.java
0,0 → 1,273
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)HelpOp.java
*
* $Id: HelpOp.java,v 1.21 2002/08/08 05:15:05 huaz Exp $
*
* Created on October 22, 2000, 2:46 AM
*/
package SharpTools;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.util.*;
 
/**
* Code taken from
* http://www.inquiry.com/techtips/java_pro/answer.asp?pro=java_pro&docID=2282.
* Code for HTML Browser originally from DisplayHTML.java
* by Daniel Savarese on 9/15/98.
* This html browser allows for the browsing of local help files.
*
* @author Daniel Medina, Daniel Goldberg
* @version $Revision: 1.21 $
*/
class HelpOp {
public static Properties translation=SharpTools.translation;
private JEditorPane htmlPane;
private JScrollPane scrollPane;
private JFrame frame;
private Container container;
private WindowListener exitListener;
private HyperlinkListener linkListener;
private URL url;
 
public HelpOp(URL url) {
frame = new JFrame("Help Browser: " + url);
container = frame.getContentPane();
container.setLayout(new BorderLayout());
try {
htmlPane = new JEditorPane(url);
} catch(IOException e) {
e.printStackTrace();
return;
}
// We only want to display the file, not edit it.
htmlPane.setEditable(false);
linkListener = new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
URL newURL;
Document currentDocument;
if(e.getEventType() != HyperlinkEvent.EventType.ACTIVATED)
return;
if((newURL = e.getURL()) == null)
return;
currentDocument = htmlPane.getDocument();
try {
htmlPane.setPage(newURL);
} catch(IOException ex) {
htmlPane.setDocument(currentDocument);
}
}
};
htmlPane.addHyperlinkListener(linkListener);
 
scrollPane = new JScrollPane(htmlPane);
container.add(scrollPane);
scrollPane.setPreferredSize(new Dimension(500, 500));
exitListener = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
Window window = e.getWindow();
window.setVisible(false);
window.dispose();
}
};
frame.addWindowListener(exitListener);
frame.pack();
frame.show();
}
 
final static String message =
"<html><font size=3 color=black><p><font size=+1 color=blue><b>Sharp Tools Spreadsheet</b></font> Version 1.41</p>"+
"<p><p>a product of the Sharp Tools Software Engineering Team"+
"<p>Copyright (c) 2000-2002"+
"<p><p><font color=green><b>Credits:</b><font></p>"+
"<ul><li>Hua Zhong</li><li>Ricky Chin</li><li>Daniel Goldberg</li>"+
"<li>Daniel Medina</li><li>Andrei Scudder</li></ul></p>"+
"<font color=blue><u><p>http://www.cs.columbia.edu/sharptools/</p>"+
"<p>mailto:sharp@cs.columbia.edu</p></u></font></font>"+
"<p>5/2009 Converted into an Applet for WIMS usage"+
"<p>http://wims.math.leidenuniv.nl";
 
// display the About message box
static void showAboutBox(JFrame frame) {
SharpOptionPane.showMessageDialog
(frame,
message,
translation.getProperty("About_SharpTools"),
JOptionPane.INFORMATION_MESSAGE,
null
);
}
 
static int are_you_sure(JFrame frame) {
int choice = SharpOptionPane.showOptionDialog
(frame,
translation.getProperty("are_you_sure"),
translation.getProperty("are_you_sure"),
0,
1,
null,
0
);
return choice;
}
 
// return a component that can do function name insertion!
static public JComponent createFunctionListComponent(JFrame frame, JTable table) {
 
JPanel comboxPanel = new JPanel();
comboxPanel.setLayout(new BorderLayout());
String[] funcNames = {
translation.getProperty("Functions") , "ABS", "AVERAGE", "COUNT", "E", "INT",
"LOG", "MAX", "MEANDEV", "MEDIAN", "MIN", "PI", "RANGE", "ROUND",
"SQRT", "SUM", "STDDEV",
"SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN"
};
JComboBox funcList = new JComboBox(funcNames);
Dimension combodim = funcList.getSize();
funcList.setPreferredSize
(new Dimension(100, (int)combodim.getHeight()));
comboxPanel.add(funcList, BorderLayout.WEST);
 
// if a cell is being edited then insert the function name into the cell
funcList.addActionListener(new FunctionListListener(frame, table));
return comboxPanel;
}
}
 
/**
* Implements help on functions
*
* When the user selects a function and he is editing, insert the function
* name to the editing point; otherwise, pop up a help box to briefly
* explain the usage of this function.
*/
class FunctionListListener implements ActionListener {
 
public static Properties translation=SharpTools.translation;
JFrame frame;
JTable table;
final ImageIcon helpIcon=new ImageIcon(getClass().getResource("/images/help32.gif"));
//final private ImageIcon helpIcon = SharpTools.getImageIcon("help32.gif");
 
FunctionListListener(JFrame frame, JTable table) {
this.frame = frame;
this.table = table;
}
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
String funcName = (String)cb.getSelectedItem();
try {
if (table.isEditing()) {
int row = table.getEditingRow();
int col = table.getEditingRow();
// get the editor
JTextField text = ((SharpCellEditor)table.getCellEditor(row, col)).getTextField();
 
if (!funcName.equals(translation.getProperty("Functions"))) {
// insert our function name
text.replaceSelection(funcName+"()");
// set caret between parentheses if the user needs to input parameters
Function fh = Formula.getFuncHandler(funcName);
if (fh != null && fh.requireParams())
text.setCaretPosition(text.getCaretPosition()-1);
}
else
showGeneralFunctionHelp();
text.requestFocus();
}
else {
// pop up help message box!
Function fh = Formula.getFuncHandler(funcName);
if (fh != null) {
String message = "<html><font size=2 color=black><b>"+
fh.getUsage()+"</b><p><p>"+fh.getDescription()+"<p></font>";
 
SharpOptionPane.showMessageDialog(frame,
message,
translation.getProperty("Function"),
JOptionPane.INFORMATION_MESSAGE,
helpIcon);
}
else
showGeneralFunctionHelp();
table.requestFocus();
}
}
catch (Exception exception) {};
// reset the selection and focus
cb.setSelectedIndex(0);
}
 
private void showGeneralFunctionHelp() {
String message = translation.getProperty("helpmessage");
/* "<html><font size=2 color=black><b><font size=3>Functions</font></b><p>"+
"<p>Functions are predefined formulas that perform calculations by"+
"<p>using specific values, called arguments, in a particular order,"+"<p>or structure.<p>"+
"<p><b>Arguments</b> Arguments can be numbers or cell references. A cell"+
"<p>reference can be a single cell or a range of cells. A single cell can"+
"<p>use relative addressing (A1) or absolute addressing ($B$5). A range"+
"<p>of cell is specified by a pair of diagonal cells (A1:C5, $A$1:$C$5)."+
"<p>Different functions may have different requirements on the number"+
"<p>or type of parameters.<p>"+
"<p><b>Structure</b> The structure of a function begins with the function"+
"<p>name, followed by an opening parenthesis, the arguments for"+
"<p>the function separated by commas, and a closing parenthesis."+
"<p>If the function starts a formula, type an equal sign (=) before"+
"<p>the function name. As you are editing a formula that contains"+
"<p>a function, you can click on a function in this list to insert the"+
"<p>function name into the cell.<p>"+
"<p><b>Examples:</b><p>"+
"<p>=SUM(A10,B5:B10,50,37)"+
"<p>=AVERAGE($B$5:$B$10)/10</font>";
*/
SharpOptionPane.showMessageDialog(frame,
message,
"Function",
JOptionPane.INFORMATION_MESSAGE,
helpIcon);
 
}
}
 
 
 
 
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/AddressField.java
0,0 → 1,130
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
/*
* @(#)AddressField.java
*
* $Id: AddressField.java,v 1.5 2000/12/06 05:58:01 huaz Exp $
*
* Created Novenmber 25, 2000, 5:13 AM
*/
package SharpTools;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
 
/**
* This class is used to only allow address input (letters followed
* by numbers).
* It extends JTextField and provides its own Document Filter.
*
* @see NumberField
*
* @author Hua Zhong
* @version $Revision: 1.5 $
*/
public class AddressField extends JTextField {
 
/**
* get the input address
*
* @return a CellPoint object that converted from the user's input
*/
public CellPoint getAddress() {
return Formula.parseAddress(getText());
}
 
/**
* set the textfield to the specified address
*
* @param f a CellPoint object specifying the address
*/
public void setAddress(CellPoint point) {
if (point == null)
setText(null);
else
setText(point.toString());
}
 
// public Object getValue() { return getAddress(); }
 
// a class used to filter the user's input
class NumberFilterDocument extends PlainDocument {
private StringBuffer __scratchBuffer;
 
public NumberFilterDocument() {
__scratchBuffer = new StringBuffer();
}
 
// this is called when user inserts a string into the text field
public void insertString(int offset, String text, AttributeSet aset)
throws BadLocationException {
if (text == null || text.length() == 0)
return;
 
__scratchBuffer.setLength(0);
 
// Reject all strings that cause the contents of the field not
// to be a valid number (i.e., string representation of a double)
try {
__scratchBuffer.append(getText(0, getLength()));
__scratchBuffer.insert(offset, text);
// Kludge: Append a 0 so that leading decimal points
// and signs will be accepted
} catch(BadLocationException ble) {
ble.printStackTrace();
return;
} catch(StringIndexOutOfBoundsException sioobe) {
sioobe.printStackTrace();
return;
}
String buf = __scratchBuffer.toString();
boolean hasNumber = false;
// only allow {letters}{numbers}
for (int i=0; i<buf.length(); i++) {
char c = buf.charAt(i);
 
// is a letter?
if (!Character.isLetter(c)) {
// no, is a digit?
if (Character.isDigit(c) && i>0)
// the first c has to be letter
// yes, following should be all digits
hasNumber = true;
else
// no, invalid
return;
}
else if (hasNumber) // should not be letter anymore
return;
}
super.insertString(offset, text.toUpperCase(), aset);
}
}
 
/**
* Construct an address only text field.
*
* @param columns the length of the text field
*/
public AddressField(int columns) {
super(columns);
setDocument(new NumberFilterDocument());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/NumberField.java
0,0 → 1,246
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)NumberField.java
*
* $Id: NumberField.java,v 1.7 2001/05/27 06:13:27 huaz Exp $
*
* Created Novenmber 25, 2000, 5:13 AM
*/
package SharpTools;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
 
/**
* This class is used to only allow number input (int/float).
* It extends JTextField and provides its own Document Filter.
*
* For simplicity, now it uses InputVerifier - huaz
*
* @see HistoDialog
* @see NewFileDialog
* @see AddressField
*
* @author Hua Zhong
* @version $Revision: 1.7 $
*/
public class NumberField extends JTextField {
 
// private Float number;
// private String oldValue;
// private Float number;
private boolean positiveOnly;
private boolean integer;
 
/**
* Construct a float-number only text field (including integer)
*
* @param columns the length of the text field
*/
public NumberField(int columns) {
super(columns);
setDocument(new NumberFilterDocument());
// setInputVerifier(new NumberVerifier());
}
/**
* Construct a float-number only text field. If positive is true
* only positive float number is allowed.
*
* @param columns the length of the text field
* @param positive the value needs to be positive
*/
public NumberField(int columns, boolean positive) {
this(columns);
this.positiveOnly = positive;
setDocument(new NumberFilterDocument());
// setInputVerifier(new NumberVerifier());
}
 
/**
* Construct a number only text field and can add more restriction
* as positive number only or integer only
*
* @param columns the length of the text field
* @param positive the value needs to be positive
* @param integer the value needs to be an integer
*/
public NumberField(int columns, boolean positive, boolean integer) {
this(columns);
this.positiveOnly = positive;
this.integer = integer;
setDocument(new NumberFilterDocument());
// setInputVerifier(new NumberVerifier());
}
 
/**
* Construct a number only text field and can add more restriction
* as positive number only or integer only
*
* @param positive the value needs to be positive
* @param integer the value needs to be an integer
*/
public NumberField(boolean positive, boolean integer) {
super();
this.positiveOnly = positive;
this.integer = integer;
setDocument(new NumberFilterDocument());
//setInputVerifier(new NumberVerifier());
}
/**
* get the input float number
*
* @return a Float object that converted from the user's input
*/
public Float getNumber() {
try {
return new Float(Float.parseFloat(getText()));
}
catch (Exception e) {
return null;
}
}
 
/**
* set the textfield to the specified float number
*
* @param f a Float object
*/
public void setNumber(Float f) {
 
if (f == null)
setText(null);
else
setText(f.toString());
}
 
/**
* When it's used as integer field, get the input integer number.
*
* @return an Integer object that converted from the user's input
*/
public Integer getInteger() {
try {
return new Integer(Integer.parseInt(getText()));
}
catch (Exception e) {
return null;
}
}
 
/**
* When it's used as integer field, set the textfield to
* the specified integer number
*
* @param f a Float object
*/
public void setInteger(Integer i) {
 
if (i == null)
setText(null);
else
setText(i.toString());
}
 
// a class used to filter the user's input
class NumberFilterDocument extends PlainDocument {
private StringBuffer __scratchBuffer;
 
public NumberFilterDocument() {
super();
__scratchBuffer = new StringBuffer();
}
 
// this is called when user inserts a string into the text field
public void insertString(int offset, String text, AttributeSet aset)
throws BadLocationException {
if (text == null)
return;
__scratchBuffer.setLength(0);
 
// Reject all strings that cause the contents of the field not
// to be a valid number (i.e., string representation of a double)
try {
__scratchBuffer.append(getText(0, getLength()));
__scratchBuffer.insert(offset, text);
// Kludge: Append a 0 so that leading decimal points
// and signs will be accepted
__scratchBuffer.append('0');
} catch(BadLocationException ble) {
ble.printStackTrace();
return;
} catch(StringIndexOutOfBoundsException sioobe) {
sioobe.printStackTrace();
return;
}
 
float value;
try {
if (integer)
value = Integer.parseInt(__scratchBuffer.toString());
else
value = Float.parseFloat(__scratchBuffer.toString());
} catch(NumberFormatException nfe) {
// Resulting string will not be number, so reject it
return;
}
 
if (positiveOnly && value<0)
return;
super.insertString(offset, text, aset);
}
}
 
/*
class NumberVerifier extends InputVerifier {
 
NumberVerifier() {
super();
}
public boolean verify(JComponent input) {
JTextField tf = (JTextField)input;
String number = tf.getText();
float value = 0;
try {
if (integer)
value = Integer.parseInt(number);
else
value = Float.parseFloat(number);
} catch(NumberFormatException nfe) {
// Resulting string will not be number, so reject it
return false;
}
 
if (positiveOnly && value < 0)
return false;
return true;
}
}
*/
 
 
}
 
 
 
 
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/CellRange.java
0,0 → 1,159
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)CellRange.java
*
* $Id: CellRange.java,v 1.13 2000/12/02 21:44:51 rkc10 Exp $
*
* Created on November 5, 2000, 1:19 AM
*/
package SharpTools;
/**
* This class specifies how a range of cells are represented.
* <p>
* A range is a continuous rectangular area that can be specified by its
* upper left corner (minCorner) and lower right corner (maxCorner).
*
* @author Ricky Chin
* @version $Id: CellRange.java,v 1.13 2000/12/02 21:44:51 rkc10 Exp $
*/
public class CellRange {
/** Upper left corner of range */
CellPoint minCorner;
 
/** Lower right corner of range */
CellPoint maxCorner;
 
/** Creates new CellRange. In assumes that the array parameters have
* entries listed in ascending order. In other words, the row array
* has the row with the smallest number in index 0 and largest
* row in the last index. The same goes for the column array.
* @param rows the array range of rows
* @param cols the array range of columns
*/
public CellRange(int[] rows, int[] cols) {
//rows selected are in ascending order
int minRow = rows[0];
int maxRow = rows[rows.length - 1];
//columns selected are in ascending order
int minCol = cols[0];
int maxCol = cols[cols.length - 1];
minCorner = new CellPoint(minRow, minCol);
maxCorner = new CellPoint(maxRow, maxCol);
}
/**
* This contructor takes x1, x2, y1, y2 and constructs a range.
*
* @param minRow upper left corner row coordinate
* @param minCol upper left corner col coordinate
* @param maxRow lower right corner row coordinate
* @param maxCol lower right corner col coordinate
*/
public CellRange(int minRow, int maxRow, int minCol, int maxCol) {
minCorner = new CellPoint(minRow, minCol);
maxCorner = new CellPoint(maxRow, maxCol);
}
 
/**
* This constructor takes two CellPoints to construct a range.
*
* @param ULHCorner upper left corner
* @param LRHCorner lower right corner
*/
public CellRange(CellPoint ULHCorner, CellPoint LRHCorner) {
minCorner = ULHCorner;
maxCorner = LRHCorner;
}
/**
* This returns the first row in the range.
*
* @return first row of range
*/
public int getStartRow() {
return minCorner.getRow();
}
/**
* This returns the last row in the range.
*
* @return last row of range
*/
public int getEndRow() {
return maxCorner.getRow();
}
/**
* This returns the first column in the range.
*
* @return first column of range
*/
public int getStartCol() {
return minCorner.getCol();
}
/**
* This returns the last column in the range.
*
* @return last column of range
*/
public int getEndCol() {
return maxCorner.getCol();
}
/**
* This returns the number of columns in the range.
*
* @return number of columns in range
*/
public int getWidth() {
return getEndCol() - getStartCol() + 1;
}
/**
* This returns the number of rows in the range.
*
* @return number of rows in range
*/
public int getHeight() {
return getEndRow() - getStartRow() + 1;
}
 
/** This returns the upper left corner of the range
* @return the upper left corner of the range
*/
public CellPoint getminCorner() {
return minCorner;
}
/** This returns the lower right corner of the range
* @return the lower right corner of the range
*/
public CellPoint getmaxCorner() {
return maxCorner;
}
 
/**
* This returns a string represetation of the difference of the upper left
* and lower right corners
*
* @return string minCorner - maxCorner
*/
public String toString() {
return minCorner.toString()+':'+maxCorner.toString();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/SharpClipboard.java
0,0 → 1,135
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)SharpClipboard.java
*
* $Id: SharpClipboard.java,v 1.18 2002/08/08 05:15:07 huaz Exp $
*
* Created on October 27, 2000, 9:40 PM
*/
 
/** This clipboard class holds the objects that will be cut and pasted to
* a spreadsheet. Actually, it creates a string representation of the range
* of cell objects that is compatible with Microsoft Excel and the Windows
* clipboard. It also remembers the range of the cells in the table from
* which it was created. This class is used for many table manipulation
* methods.
* @author Ricky Chin
* @version $Revision: 1.18 $
*/
package SharpTools;
public class SharpClipboard {
 
/** holds the objects that are cut or copied
*/
private String text;
/** the range of Cells from which the clipboard was created
*/
private CellRange source;
/** Creates new SharpClipboard. If it is a cut, then it clears the range it
* was created from.
* @param model the SharpTableModel you are operating on
* @param range an array of CellPoint objects where the first is the
* upper left hand corner and the second entry is the
* lower right hand corner coordinates
* @param isCut true only if this is a cut
*/
public SharpClipboard(SharpTableModel model, CellRange range,
boolean isCut) {
text = model.toString(range, false);
 
source = range;
//if it is a cut, set the old cells to null
if (isCut) {
model.clearRange(range);
}
}
/** This gets the actual range of a paste from a corner point. This is
* actually a helper method for paste
* @param corner the upper left corner coordinate
* @return the actual cell range; null if it's beyond the table range
* @param model the SharpTableModel you are using
*/
public CellRange getRange(SharpTableModel model, CellPoint corner) {
//limit to paste region
int rowLimit = model.getRowCount() - 1;
int colLimit = model.getColumnCount() - 1;
//calculate dimensions of clipboard
int rowMax = corner.getRow() + source.getHeight() - 1;
int colMax = corner.getCol() + source.getWidth() - 1;
//cannot paste to nonexistent cells
if ((corner.getRow() < SharpTools.baseRow) ||
(corner.getCol() < SharpTools.baseCol)) {
return null;
}else {
//paste as much as you can
return new CellRange(corner,
new CellPoint(Math.min(rowMax, rowLimit),
Math.min(colMax, colLimit)));
}
}
/** This pastes the current contents of the spreadsheet object
* on to the region defined by the coordinates of the upper
* right hand corner. If the contents cannot be entirely pasted
* on this region, it pastes as much as it can
* @param table SharpTable model you are pasting to
* @param corner coordinate of upper left hand corner
*/
public void paste(SharpTableModel table, CellPoint corner) {
//if region to paste to is out of bounds
CellRange range = getRange(table, corner);
paste(table, range);
}
 
/** This is similar to the other paste, but take range as a parameter.
* This is used together with getRange.
* @param table SharpTableModel you are pasting to
* @param range range you are pasting to
*/
public void paste(SharpTableModel table, CellRange range) {
 
//if region to paste to is out of bounds
if (range != null) {
int rowOff = range.getStartRow()-source.getStartRow();
int colOff = range.getStartCol()-source.getStartCol();
table.fromString(text, rowOff, colOff, range);
}
}
/** This method returns the range the clipboard originally came from
* @return the range the clipboard originally can from
*/
public CellRange getSource() {
return source;
}
/** Set the source of the clipboard
* @param x CellRange to set as the source of the clipboard
*/
public void setSource(CellRange x) {
source = x;
}
 
/** Return the string representation of contents of the clipboard
* @return the string representation of contents of the clipboard
*/
public String toString() { return text; }
}
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/src/FindDialog.java
0,0 → 1,97
/*
License.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @(#)FindDialog.java
*
* $Id: FindDialog.java,v 1.3 2001/05/27 22:28:57 huaz Exp $
*
* Created on November 28, 2000, 02:12 AM
*/
package SharpTools;
import javax.swing.*;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import java.awt.event.*;
 
/**
* This class provides a find dialog.
* User is prompted to choose find options.
*
* @author Andrei Scudder
* @author Hua Zhong (use SharpDialog)
* @version $Revision: 1.3 $
*/
public class FindDialog extends SharpDialog {
private JLabel label;
private JFrame frame;
final private JTextField textField = new JTextField(10);
private JCheckBox caseSensitiveBox;
private JCheckBox matchCellBox;
private String typedText = null;
private boolean caseSensitive = false;
private boolean matchCell = false;
final ImageIcon findIcon=new ImageIcon(getClass().getResource("/images/find32.gif"));
//final private ImageIcon findIcon = SharpTools.getImageIcon("find32.gif");
 
public FindDialog(JFrame aFrame, String findValue, boolean mCase,
boolean mCell) {
super(aFrame, "Find", true);
textField.setText(findValue);
caseSensitiveBox = new JCheckBox(SharpTools.translation.getProperty("Match_Case"));
caseSensitiveBox.setMnemonic(KeyEvent.VK_M);
caseSensitiveBox.setSelected(mCase);
matchCellBox = new JCheckBox(SharpTools.translation.getProperty("Match_Entire_Cell_Only"));
matchCellBox.setMnemonic(KeyEvent.VK_E);
matchCellBox.setSelected(mCell);
 
JPanel box = new JPanel(new BorderLayout(0, 5));
 
box.add(textField, BorderLayout.NORTH);
box.add(caseSensitiveBox, BorderLayout.WEST);
box.add(matchCellBox, BorderLayout.EAST);
setOptionPane(box,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
findIcon);
}
public boolean isCaseSensitive(){
return caseSensitive;
}
public boolean isCellMatching(){
return matchCell;
}
public String getString(){
return typedText;
}
 
protected void onOpen() {
textField.selectAll();
textField.requestFocus();
}
 
protected boolean onOK() {
typedText = textField.getText();
caseSensitive = caseSensitiveBox.isSelected();
matchCell = matchCellBox.isSelected();
return true;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/COPYING
0,0 → 1,339
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
 
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
Preamble
 
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
 
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
 
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
 
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
 
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
 
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
 
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
 
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
 
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
 
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
 
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
 
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
 
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
 
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
 
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
 
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
 
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
 
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
 
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
 
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
 
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
 
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
 
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
 
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
 
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
 
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
 
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
 
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
 
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
 
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
 
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
 
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
 
NO WARRANTY
 
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
 
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
 
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
 
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
 
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
 
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
Also add information on how to contact you by electronic and paper mail.
 
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
 
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
 
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
 
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
 
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
 
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
 
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
/trunk/wims/src/Misc/authors/jm.evers/applets/SharpTools/README
0,0 → 1,53
 
Sharp Tools Spreadsheet version 1.2
===================================
 
Copyright (C) 2000-2001, Hua Zhong <huaz@cs.columbia.edu>
Copyright (C) 2000, Sharp Tools Team <sharp@cs.columbia.edu>
Sharp Tools spreadsheet was originally a Software Engineering course project
finished in the fall of 2000 by five CS students at Columbia University. It
is not a commecial product, nor is it meant to replace StarOffice, but it has
all the basic functionality as a spreadsheet. We also hope people can learn
from the code.
 
This is a development version. The documentation may be inaccurate.
 
===================================
Web sites
===================================
 
The official web site is http://www.cs.columbia.edu/sharptools/.
 
It's also available at:
 
SourceForge: http://sharptools.sourceforge.net/
Freshmeat: http://freshmeat.net/projects/sharptools/
 
===================================
Build and Run
===================================
 
If you want to build/run your own code, do the following (assuming Unix):
 
$ cd src
$ make
$ jar cvf SharpTools.jar *.class
$ mv SharpTools.jar ../bin
$ cd ../bin
$ ./SharpTools
 
You have to do so if you check out the code from CVS.
 
===================================
Database
===================================
 
If you want to use the new database function, you need to download the JDBC
driver(s) and put in CLASSPATH (edit SharpTools or SharpTools.bat).
 
Below are some such websites:
 
MySQL: http://www.worldserver.com/mm.mysql/
HSQL: http://sourceforge.net/projects/hsqldb/
 
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/CHANGELOG
0,0 → 1,94
CHANGELOG
21/02/2010
- improved plotting of 'discontinue' functions
- checks on NaN when computing plotpoints
- coordinate display will vanish when mouse exits the applet window
- plotjump redefined: now default is ysize ; if plotjump is defined in flyscript, the cutoff_y_value for plotting is "ysize+plotjump"
 
2/3/2010
- corrected numberformat error in farc/arc degrees
- changed text syntax log[6](123) can not be translated into unicode_math: use log6(123)
- changed text syntax sqrt[6](123) can not be translated into unicode_math: use sqrt6(123)
- 4cdot5 gives centerdot as *symbol
- pi: sin(4cdot pi ) : spaces around pi [to avoid conflicts with a word like "piano"]
- fixed empty word[0] bug when lines start with \t or multiple spaces
- added
- xscale x1,x1_name,x2,x2_name....,fontsize,fontname,color,xtic_linewidth
- yscale y1,y1_name,y2,y2_name....,fontsize,fontname,color,ytic_linewidth
syntax is mandatory !
example
xscale 0,London,1,Amsterdam,2,Berlin,3,Paris,22,Times,red,1
xscale -3*pi,-3cdot pi ,2*pi,-2cdot pi , -1*pi,- pi ,0,0,pi, pi ,2*pi,2cdot pi ,3*pi,3cdot pi,10,Helvetica,blue,1
 
4/3/2010
- added x/y log10 scale
-xlogscale color [alpha,linewidth]
-ylogscale color [alpha,linewidth]
 
15/3/2010
-added atp latex lib.
latex x,y,LatexString,color
example:
latex -1,6,\left{ \begin{array}{l} f(x) = \frac{1}{x} \\ g(x) = \frac{1}{x^{2}} \end{array} , blue
 
18/3/2010
- added unicode euro symbol : text 0,0,helvetica,42, euro , red
- added scaling background image:
image xmin,ymax,http://image_url
will scale image to applet size
image 1,1,http://image_url
will show the unscaled image with left uppercorner (1:1) on the given coordinate grid xmin/xmax:ymin/ymax
 
21/3/2010
-added textarea inputfields
-inputfield x,y,width,height,font,fontsize,editable-boolean,bgcolor,fgcolor
-x,y are coordinates of left upper corner of textarea
-width and height in same coordinatee system given by xrange/yrange
-hardcoded maximum of 20 textareas
-Textareas are read in sequence from flyapplet scriptfile,
-using document.getElementById("flyapplet").ReadText() javascript interface
example;
inputfield -5,5,4,1,helvetica,22,red,green,true,change this text
textarea left upper corner at (-5:5)
textarea right under corner at (-1:4)
textsize 22
is editable
preprint text is "change this text"
inputfield -5,5,4,1,helvetica,22,red,green
-corrected color mixup in grid
-corrected x/y-scale syntax bug
xscale x1,x1_name,x2,x2_name,x3,x3_name.....,fontsize,fontname,fontcolor,tickmark_linewidth
22/3/2010
-added scalelatex x,y,width,height,latexstring,[optional] bgcolor,fgcolor,bg_alpha,fg_alpha
scale the lateximage to width,height in coordinate system xrange/yrange
Attention: this may lead to very poor readability [the fontsizes are limited to the latex defaults [max 12]
 
-changed latex syntax : now the optional bgcolor and fgcolor may have alpha channel
latex x,y,latexstring,[optional] bgcolor,fgcolor,bg_alpha,fg_alpha
defaults are applet bgcolor and "draw color" [clickcolor]
 
14/5/2010
-added \euro to atp library :
latex x,y,\frac{100 ^{3 \times \euro }}{4 \cdot \euro },[optional] bgcolor,fgcolor,bg_alpha,fg_alpha
 
18/5/2010
-added "inputs/inputfields" for the amount of inputfields required [if not set: default=20]
inputs 24
inputfields 4
20/8/2010
-added xlabel/ylabel
xlabel "label_of_x-axis",fontsize [,fontname,color,alpha]
xlabel x axis,14,times,red,160
ylabel label_of_y-axis,fontsize [,fontname,color,alpha]
ylabel y axis,12
label of y_axis is always horizontal
21/8/2010
-changed xlabel position [closer to x-axis]
 
8/11/2010
- forgotten to implement userdraw filledpoly / fpoly
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/FlyApplet.java
0,0 → 1,2923
/*
*********************************************************************************
* J.M. Evers 19/11/2009*
* This is all amateur scriblings... So no copyrights.*
* This source code file, and compiled classes derived from it,*
* can be used and distributed without restriction, including for commercial use*
* No warrenty whatoever*
*********************************************************************************
 
I've used some code from X.Gang's input applet , to make it "compatibel"
with existing usage...although not thoroughly tested :(
And Gang's applet was an extended version of the original draw.java distributed with java applets as demo.
This work was GNU
 
And the Javia-libs however are excellent java and are GNU.
 
1) Syntax ; similar (...) to flydraw
[filled || dashed]
object coordinate_data,color [optional ,alpha,linewidth]
 
2) Compatibility with Input.java ex Gang
Use the normal applet params for Input.java [e.g without the script]
Or abandon the input_applet_params and let the script to produce the background image:
userdraw points | line | lines | (f)polygon | vector | (f)circle | (f)rect | semiline | points | curve
controls yes/no [use the direct reply buttons]
pointstyle cross | dot : only for userdrawing
 
new: right mousebutton removes parts of drawing
The result can be read through usual direct contact with wims.cgi
or via Javascript using ReadApplet() :
in this case the answers will be in the coordinate system of the drawing
[xrange/yrange] and always a list x1,y1,x2,y2,x3,y3.....
3) Using the applet as an drawable image [mouse drawinteraction] + coordinates display
mouse yes
userdraw points | line | lines | (f)polygon | (f)rect | vector | (f)circle | semiline | points | curve
coordinates yes/no or left out
pointstyle cross | dot
Drawing can be read via Javascript using ReadApplet() :
The answers will be in the coordinate system of the drawing
[xrange/yrange] and always a list x1,y1,x2,y2,x3,y3.....
4) Using the applet as an non_user_drawable image with coordinates display
mouse no
coordinates yes
 
5) Using the applet as a normal Fly image
mouse no
coordinates no
[this is default]
 
 
6) Script syntax [a sort of fly-script]
xrange int,int
yrange int,int
linewidth int
transparent color [,alpha]
 
dline || line x1,y1,x2,y2,color [,alpha,linewidth]
dhline || hline x1,x1,color [,alpha,linewidth]
dvline || vline x1,x1,color [,alpha,linewidth]
darrow || arrow x1,y1,x2,y2,head_factor(0.0001 - 0.99999),color [,alpha,linewidth
 
dpoly || poly || fpoly x1,y1...x_n,y_n,color [,alpha,linewidth]
drect || rect || frect x1,y1,x2,y2,color [,alpha,linewidth]
dtriangle || triangle || ftrianlge x1,y1,x2,y2,x3,y3,color [,alpha,linewidth]
 
points x1,y1,x2,y2...x_n,y_n,color [,alpha,linewidth]
point x,y,color [,alpha,linewidth]
pointstyle cross | dot : only for userdrawing
 
dcircle || circle || fcircle xc,yc,r,color [,alpha,linewidth]
dellipse || ellipse || fellipse xc,yc,r1,r2,color [,alpha,linewidth]
farc || arc xc,yc,radius,start_angle,end_angle,color [,alpha]
 
dgrid || grid xmajor,ymajor,xminor,yminor,color_mayor,color_minor,linewidth,linewidth [,alpha_major,alpha_minor]
example: grid 1,1,0.5,0.5,red,blue,2,1,190,120
parallel x1,y1,x2,y2,dx,dy,n,color [,alpha,linewidth]
 
plotsteps [int] default ysize
dcurve || curve || function in x,color [,alpha,linewidth]
image x1,y1,url // x & y are in coordinate system xrange/yrange
 
text x,y,fontname,fontsize,the_text_without_comma,color [,alpha] few latexstrings allowed rightarrow alpha beta Beta
textup x,y,angle,fontname,fontsize,some_the_text_without_comma,color [,alpha] : angle = clockwise rotation in degrees
 
precision 100 // 2 decimals for reading coords with "mouse yes"
 
debug yes //some info on loading script and other trouble
 
todo:
- Animating curves [very hard?]
- Animated gif as background
- xlogscale / ylogscale
wishlist:
- standalone application with menubars ; export drawing as flyscript ?
- using frame ?
<html>
<body>
<script type="text/javascript">
function ReadThis(){
reply = document.getElementById('FlyApplet').ReadApplet();
alert("answer is a list of coordinates \n"+reply);
}
</script>
<applet id="FlyApplet" name="FlyApplet" code="FlyApplet.class" archive="FlyApplet.jar" width="500" height="500">
<param name="file" value="serveradres_scriptfile">
</applet>
<br>
<input type="button" name="flyapplet1" value="Read Drawing" onclick="javascript:ReadThis();">
</body>
</html>
*/
 
 
import java.applet.*;
import java.lang.Math;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.StringTokenizer;
import javax.swing.*;
import java.net.*;
import java.awt.geom.AffineTransform;
import java.awt.font.TextLayout;
import java.awt.font.FontRenderContext;
import org.javia.arity.Symbols;
import org.javia.arity.SyntaxException;
 
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import atp.sHotEqn;
 
public class FlyApplet extends JApplet{
FlyApplet_panel panel;
FlyApplet_controls controls;
String flyscript;
double xmin=-10D,xmax=10D;
double ymin=-10D,ymax=10D;
int xsize,ysize;
URL url;
int object_count=0;
int image_count=0;
int user_object_count=0;
Vector objects = new Vector();
Vector user_objects = new Vector();
int linewidth = 1;
int alpha=255;
int fontsize = 18;
int plotjump;
int inputs = 20; // max inputfields
TextArea inputfield[];
int inputfieldindex=0;
String fontname = "TimesRoman";
Font font;
Font textfieldfont;
int plotsteps=500;
public Color clickcolor = new Color(0,0,0);
Color bgcolor = new Color(255,255,255);
String replystring;
public static String prompt="OK";
public static String retry="Erase";
URL backurl;
Graphics2D backg;
BufferedImage bg; // background image
double precision = 100D;
boolean mouse = false;
boolean debug = false;
boolean use_controls = false; // wims buttons
boolean use_coords = false; // show x/y
boolean dashed=false;
boolean cross = true;
Symbols symbols;
boolean use_xscale=false;
boolean use_yscale=false;
boolean use_ylog=false;
boolean use_xlog=false;
boolean use_inputarea=false;
public sHotEqn TeX;
public void init() {
/*
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames();
Font[] allFonts = ge.getAllFonts();
for(int i=0;i<allFonts.length;i++){
System.out.println("allFont["+i+"]="+allFonts[i].toString());
}
*/
URL url;
Dimension appletSize = this.getSize();
ysize = appletSize.height;
xsize = appletSize.width;
plotjump=ysize;
String parmstr;
// do we use a script ?
parmstr=getParameter("file");
symbols=new Symbols();
if ( parmstr!=null && parmstr.length()>0){
boolean go=true;
try{
flyscript = load(parmstr);
}catch(Exception e){System.out.println("could not set parameter \"file\" to "+parmstr+"\n"+e);go=false;}
if(go){
bg = new BufferedImage(xsize,ysize, BufferedImage.TYPE_INT_ARGB );
backg = (Graphics2D) bg.getGraphics();
ReadFlyScript(flyscript);
// nothing to draw just pointing}
if(!mouse){FlyApplet_panel.ctype=FlyApplet_panel.NULL;}
}
}
// see if Gang's params are set; if so use these settings for the drawing etc.
try{
parmstr=getParameter("type");
if( parmstr != null || parmstr.length() > 3 ){
use_controls = true;
parmstr.toLowerCase(); parmstr.trim();
FlyApplet_panel.ctype=FlyApplet_panel.NULL;
if(parmstr.compareTo("curve")==0) FlyApplet_panel.ctype=FlyApplet_panel.CURVE;
if(parmstr.compareTo("rectangle")==0) FlyApplet_panel.ctype=FlyApplet_panel.RECT;
if(parmstr.compareTo("rect")==0) FlyApplet_panel.ctype=FlyApplet_panel.RECT;
if(parmstr.compareTo("circle")==0) FlyApplet_panel.ctype=FlyApplet_panel.CIRCLE;
if(parmstr.compareTo("lines")==0) FlyApplet_panel.ctype=FlyApplet_panel.LINES;
if(parmstr.compareTo("segments")==0) FlyApplet_panel.ctype=FlyApplet_panel.LINES;
if(parmstr.compareTo("line")==0) FlyApplet_panel.ctype=FlyApplet_panel.LINE;
if(parmstr.compareTo("sline")==0) FlyApplet_panel.ctype=FlyApplet_panel.SLINE;
if(parmstr.compareTo("semiline")==0) FlyApplet_panel.ctype=FlyApplet_panel.SLINE;
if(parmstr.compareTo("seg")==0) FlyApplet_panel.ctype=FlyApplet_panel.SEG;
if(parmstr.compareTo("segment")==0) FlyApplet_panel.ctype=FlyApplet_panel.SEG;
if(parmstr.compareTo("poly")==0) FlyApplet_panel.ctype=FlyApplet_panel.POLY;
if(parmstr.compareTo("polygon")==0) FlyApplet_panel.ctype=FlyApplet_panel.POLY;
if(parmstr.compareTo("points")==0) FlyApplet_panel.ctype=FlyApplet_panel.POINTS;
if(parmstr.compareTo("vec")==0) FlyApplet_panel.ctype=FlyApplet_panel.VEC;
if(parmstr.compareTo("vector")==0) FlyApplet_panel.ctype=FlyApplet_panel.VEC;
}
parmstr=getParameter("replyurl");
if(parmstr!=null && parmstr.length()>0){ replystring = parmstr;}
else{ replystring="http://localhost/wims.cgi?";}
parmstr=getParameter("retry");
if(parmstr!=null && parmstr.length()>0){retry = parmstr;}
parmstr=getParameter("prompt");
if(parmstr!=null && parmstr.length()>0){prompt=parmstr;}
parmstr=getParameter("dashed");
if(parmstr!=null && parmstr.length()>0){ dashed = true;}
parmstr=getParameter("linewidth");
if(parmstr!=null && parmstr.length()>0){linewidth = Integer.parseInt(parmstr);}
parmstr=getParameter("alpha");
if(parmstr!=null && parmstr.length()>0){
alpha = Integer.parseInt(parmstr);
clickcolor = MakeTransparent(clickcolor,alpha);
}
 
parmstr=getParameter("pointstyle");
if(parmstr!=null && parmstr.length()>0){if(parmstr.equalsIgnoreCase("dot")){cross = false;}}
parmstr=getParameter("background");
if (parmstr!=null && parmstr.length()>0){
try {url=new URL(parmstr);}
catch (MalformedURLException e) {url=null;}
if(url != null){
try{
bg = (BufferedImage) ImageIO.read(url);
}catch(IOException e){DeBug("can not load image from "+url+"\n"+e); bg = null;}
}
}
parmstr=getParameter("bgcolor");
if(parmstr!=null && parmstr.length()>0) {
bgcolor=Color.decode(parmstr);
if(bgcolor==null) bgcolor=Color.white;
}
else bgcolor=Color.white;
}catch(Exception e){DeBug("Applet will not run in Gang's Input.java mode");}
if(use_coords){
textfieldfont = new Font("Helvetica", Font.BOLD, 16);
}
setLayout(new BorderLayout());
panel=new FlyApplet_panel(bgcolor,clickcolor,bg,linewidth,xsize,ysize,dashed,use_coords,precision,xmin,ymin,xmax,ymax,textfieldfont,cross);
controls=new FlyApplet_controls(panel,this);
add("Center", panel);
if(use_controls){add("South",controls);}
}//init end
 
public void destroy() {
remove(panel);
if(use_controls){remove(controls);}
}
 
public void replyback() {
try {backurl=new URL(panel.points2string(replystring));}
catch (MalformedURLException e) {backurl=null;}
getAppletContext().showDocument(backurl,"_self");
destroy();
}
public String ReadText(){
String reply = "";
if(use_inputarea){
boolean first = true;
for(int i = 0; i < inputfieldindex ;i++){
if(first){
reply = inputfield[i].getText();
first= false;
}
else
{
reply = reply + "," + inputfield[i].getText();
}
}
}
return reply;
}
 
public String ReadDrawing(){
String reply = "";
if((panel.Coords2String()).length() == 0){reply = "error";}else{reply=panel.Coords2String();}
return reply;
}
public String getAppletInfo() {
return "Interactive image & draw applet for WIMS.\nUsing Javia libs for curve plotting\nDerived from X.Gang's Input.java\nSun's Draw.java";
}
 
public void DeBug(String error){
if(debug){
System.out.println(error);
}
}
public void ReadFlyScript(String s){
StringTokenizer lines = new StringTokenizer(s, "\n");
int m=lines.countTokens();
String tmp;
for(int i=0 ; i<m ;i++){
tmp = lines.nextToken();
DeBug("reading script line "+i+": "+tmp);
if( tmp.indexOf("#") == 0 || tmp.indexOf("%") == 0 ){DeBug("ignoring line "+i); }
else{
if(!ExecuteCommand(tmp)){DeBug("line "+i+" : "+tmp);}
}
}
prepaint();// create the image in background.
}
 
public void prepaint(){
if(object_count >0){
int l=1;
for(int i=0;i<object_count;i++){
if(objects.elementAt(i) instanceof FlyArrow){
if(((FlyArrow)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyArrow)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke(
new BasicStroke(
((FlyArrow)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL
)
);
}
backg.setColor(((FlyArrow)objects.elementAt(i)).getColor());
int mx[] = ((FlyArrow)objects.elementAt(i)).getX();
int my[] = ((FlyArrow)objects.elementAt(i)).getY();
backg.drawLine( mx[0],my[0],mx[1],my[1]);
backg.drawLine( mx[2],my[2],mx[1],my[1]);
backg.drawLine( mx[3],my[3],mx[1],my[1]);
}
else
if(objects.elementAt(i) instanceof FlyInput){
int index = ((FlyInput)objects.elementAt(i)).getIndex();
inputfield[index] = new TextArea( ((FlyInput)objects.elementAt(i)).getValue() ,100,1,3);
add(inputfield[index]);
inputfield[index].setFont( ((FlyInput)objects.elementAt(i)).getFont() );
inputfield[index].setBackground( ((FlyInput)objects.elementAt(i)).getBgcolor() );
inputfield[index].setForeground( ((FlyInput)objects.elementAt(i)).getFgcolor() );
inputfield[index].setBounds(
((FlyInput)objects.elementAt(i)).getX(),
((FlyInput)objects.elementAt(i)).getY(),
((FlyInput)objects.elementAt(i)).getXsize(),
((FlyInput)objects.elementAt(i)).getYsize()
);
inputfield[index].setEditable(((FlyInput)objects.elementAt(i)).getEditable());
inputfield[index].setVisible(true);
}
else
if(objects.elementAt(i) instanceof FlyLatex){
backg.drawImage(((FlyLatex)objects.elementAt(i)).getLatex(),((FlyLatex)objects.elementAt(i)).getX(),((FlyLatex)objects.elementAt(i)).getY(),this);
}
else
if(objects.elementAt(i) instanceof FlyXscale){
if(((FlyXscale)objects.elementAt(i)).use_xscale()){
backg.setStroke( new BasicStroke(((FlyXscale)objects.elementAt(i)).getLineWidth()));
backg.setColor(((FlyXscale)objects.elementAt(i)).getColor());
backg.setFont(((FlyXscale)objects.elementAt(i)).getFont());
FontMetrics fm = backg.getFontMetrics(((FlyXscale)objects.elementAt(i)).getFont());
int h = fm.getHeight();
int w = 0;
int y0 =(int)( y2px(0));
int xtics[] = ((FlyXscale)objects.elementAt(i)).getX();
String[] xlabels = ((FlyXscale)objects.elementAt(i)).getXlabel();
for(int p=0;p<xtics.length;p++){
if(xlabels[p] != null){
w = (int) (fm.stringWidth(xlabels[p])/2);
backg.drawLine(xtics[p],y0 - h/4,xtics[p],y0 + h/4);
backg.drawString(xlabels[p],xtics[p] - w,y0 + h);
}
}
}
}
else
if(objects.elementAt(i) instanceof FlyYscale){
if(((FlyYscale)objects.elementAt(i)).use_yscale()){
backg.setStroke( new BasicStroke(((FlyYscale)objects.elementAt(i)).getLineWidth()));
backg.setColor(((FlyYscale)objects.elementAt(i)).getColor());
backg.setFont(((FlyYscale)objects.elementAt(i)).getFont());
FontMetrics fm = backg.getFontMetrics(((FlyYscale)objects.elementAt(i)).getFont());
int h = fm.getHeight();
int w = 0;
int x0 =(int)( x2px(0));
int ytics[] = ((FlyYscale)objects.elementAt(i)).getY();
String[] ylabels = ((FlyYscale)objects.elementAt(i)).getYlabel();
for(int p=0;p<ytics.length;p++){
if(ylabels[p] != null){
w = fm.stringWidth(ylabels[p]+" ");
backg.drawLine(x0 - h/4,ytics[p],x0 + h/4,ytics[p]);
backg.drawString(ylabels[p],x0 - w - h/3 , ytics[p]+h/4);
}
}
}
}
else
if(objects.elementAt(i) instanceof FlyArc){
if(((FlyArc)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyArc)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyArc)objects.elementAt(i)).getLineWidth()));
}
backg.setColor(((FlyArc)objects.elementAt(i)).getColor());
if( ((FlyArc)objects.elementAt(i)).getFilled() ){
backg.fillArc(
((FlyArc)objects.elementAt(i)).getXc(),
((FlyArc)objects.elementAt(i)).getYc(),
((FlyArc)objects.elementAt(i)).getW(),
((FlyArc)objects.elementAt(i)).getH(),
((FlyArc)objects.elementAt(i)).getAngle1(),
((FlyArc)objects.elementAt(i)).getAngle2());
}
else
{
backg.drawArc(
((FlyArc)objects.elementAt(i)).getXc(),
((FlyArc)objects.elementAt(i)).getYc(),
((FlyArc)objects.elementAt(i)).getW(),
((FlyArc)objects.elementAt(i)).getH(),
((FlyArc)objects.elementAt(i)).getAngle1(),
((FlyArc)objects.elementAt(i)).getAngle2());
}
}
else
if (objects.elementAt(i) instanceof FlyText){
backg.setColor(((FlyText)objects.elementAt(i)).getColor());
backg.setFont(((FlyText)objects.elementAt(i)).getFont());
AffineTransform at = new AffineTransform();
at.rotate(Math.PI*2*(((FlyText)objects.elementAt(i)).getRotation())/360,((FlyText)objects.elementAt(i)).getX(),((FlyText)objects.elementAt(i)).getY());
backg.setTransform(at);
backg.drawString(
((FlyText)objects.elementAt(i)).getTXT(),
((FlyText)objects.elementAt(i)).getX(),
((FlyText)objects.elementAt(i)).getY()
);
at = new AffineTransform(); // reset otherwise all will be rotated...
at.rotate(0);backg.setTransform(at);
}
else
if (objects.elementAt(i) instanceof FlyGrid){
// minor first
if(((FlyGrid)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyGrid)objects.elementAt(i)).getLineWidth_minor(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyGrid)objects.elementAt(i)).getLineWidth_minor()));
}
backg.setColor(((FlyGrid)objects.elementAt(i)).getColor_minor());
int mx[] = ((FlyGrid)objects.elementAt(i)).getX_minor();
int my[] = ((FlyGrid)objects.elementAt(i)).getY_minor();
for(int p=0;p<mx.length;p++){
backg.drawLine( mx[p],0,mx[p],ysize);
}
for(int p=0;p<my.length;p++){
backg.drawLine(0,my[p],xsize,my[p]);
}
if(((FlyGrid)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyGrid)objects.elementAt(i)).getLineWidth_major(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyGrid)objects.elementAt(i)).getLineWidth_major()));
}
int Mx[] = ((FlyGrid)objects.elementAt(i)).getX_major();
int My[] = ((FlyGrid)objects.elementAt(i)).getY_major();
backg.setColor(((FlyGrid)objects.elementAt(i)).getColor_major());
for(int p=0;p<Mx.length;p++){
backg.drawLine( Mx[p],0,Mx[p],ysize);
}
for(int p=0;p<My.length;p++){
backg.drawLine(0,My[p],xsize,My[p]);
}
}
else
if (objects.elementAt(i) instanceof FlyLine){
if(((FlyLine)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyLine)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyLine)objects.elementAt(i)).getLineWidth()));
}
backg.setColor(((FlyLine)objects.elementAt(i)).getColor());
backg.drawLine(
((FlyLine)objects.elementAt(i)).getX1(),
((FlyLine)objects.elementAt(i)).getY1(),
((FlyLine)objects.elementAt(i)).getX2(),
((FlyLine)objects.elementAt(i)).getY2()
);
}
else
if (objects.elementAt(i) instanceof FlyParallel){
if(((FlyParallel)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyParallel)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyParallel)objects.elementAt(i)).getLineWidth()));
}
backg.setColor(((FlyParallel)objects.elementAt(i)).getColor());
int x1[]=(((FlyParallel)objects.elementAt(i)).getX1());
int y1[]=(((FlyParallel)objects.elementAt(i)).getY1());
int x2[]=(((FlyParallel)objects.elementAt(i)).getX2());
int y2[]=(((FlyParallel)objects.elementAt(i)).getY2());
for( int p = 0 ; p<x1.length; p++){
backg.drawLine(x1[p],y1[p],x2[p],y2[p]);
}
}
else
if (objects.elementAt(i) instanceof FlyPoly){
if(((FlyPoly)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyPoly)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyPoly)objects.elementAt(i)).getLineWidth()));
}
backg.setColor(((FlyPoly)objects.elementAt(i)).getColor());
Polygon poly = new Polygon(
(((FlyPoly)objects.elementAt(i)).getX()),
(((FlyPoly)objects.elementAt(i)).getY()),
(((FlyPoly)objects.elementAt(i)).getX()).length
);
if( ((FlyPoly)objects.elementAt(i)).getFilled()){ backg.fillPolygon(poly);}
else{ backg.drawPolygon(poly);}
}
else
if (objects.elementAt(i) instanceof FlyPlot){
if(((FlyPlot)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyPlot)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyPlot)objects.elementAt(i)).getLineWidth()));
}
backg.setColor(((FlyPlot)objects.elementAt(i)).getColor());
int x[]=(((FlyPlot)objects.elementAt(i)).getX());
int y[]=(((FlyPlot)objects.elementAt(i)).getY());
for(int p=0;p<x.length - 1;p++){
if(y[p] < ysize && y[p+1] < ysize ){
backg.drawLine(x[p],y[p],x[p+1],y[p+1]);
}else{p++;}
}
}
else
if (objects.elementAt(i) instanceof FlyImage){
backg.drawImage(
(((FlyImage)objects.elementAt(i)).getImage()),
(((FlyImage)objects.elementAt(i)).getX()),
(((FlyImage)objects.elementAt(i)).getY()),
this
);
}
else
if (objects.elementAt(i) instanceof FlyPoints){
l = ((FlyPoints)objects.elementAt(i)).getLineWidth();
backg.setStroke( new BasicStroke(l));
backg.setColor(((FlyPoints)objects.elementAt(i)).getColor());
int x[]=(((FlyPoints)objects.elementAt(i)).getX());
int y[]=(((FlyPoints)objects.elementAt(i)).getY());
for(int p=0;p<x.length;p++){
backg.fillOval(x[p],y[p], l, l);
}
}
else
if (objects.elementAt(i) instanceof FlyPoint){
l = ((FlyPoints)objects.elementAt(i)).getLineWidth();
backg.setStroke( new BasicStroke(l));
backg.setColor(((FlyPoint)objects.elementAt(i)).getColor());
int x=(((FlyPoint)objects.elementAt(i)).getX());
int y=(((FlyPoint)objects.elementAt(i)).getY());
backg.fillOval(x,y, l, l);
}
else
if (objects.elementAt(i) instanceof FlyRect){
if(((FlyRect)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyRect)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyRect)objects.elementAt(i)).getLineWidth()));
}
backg.setColor(((FlyRect)objects.elementAt(i)).getColor());
if(((FlyRect)objects.elementAt(i)).getFilled()){
backg.fillRect(
((FlyRect)objects.elementAt(i)).getX(),
((FlyRect)objects.elementAt(i)).getY(),
((FlyRect)objects.elementAt(i)).getW(),
((FlyRect)objects.elementAt(i)).getH());
}
else
{
backg.drawRect(
((FlyRect)objects.elementAt(i)).getX(),
((FlyRect)objects.elementAt(i)).getY(),
((FlyRect)objects.elementAt(i)).getW(),
((FlyRect)objects.elementAt(i)).getH());
}
}
else
if (objects.elementAt(i) instanceof FlyXlabel){
backg.setColor(((FlyXlabel)objects.elementAt(i)).getColor());
backg.setFont(((FlyXlabel)objects.elementAt(i)).getFont());
FontMetrics fm = backg.getFontMetrics(((FlyXlabel)objects.elementAt(i)).getFont());
int h = fm.getHeight();
int w = fm.stringWidth(((FlyXlabel)objects.elementAt(i)).getXlabel()+" ");
int y =(int) (y2px(0) + 1.5*h);
int x = (int) (x2px(xmax) - w);
backg.drawString(((FlyXlabel)objects.elementAt(i)).getXlabel(),x,y);
}
else
if (objects.elementAt(i) instanceof FlyYlabel){
backg.setColor(((FlyYlabel)objects.elementAt(i)).getColor());
backg.setFont(((FlyYlabel)objects.elementAt(i)).getFont());
FontMetrics fm = backg.getFontMetrics(((FlyYlabel)objects.elementAt(i)).getFont());
int h = fm.getHeight();
int w = fm.stringWidth(((FlyYlabel)objects.elementAt(i)).getYlabel()+" ");
int x =(int) (x2px(0) - w);
int y = (int) (y2px(ymax) + h);
backg.drawString(((FlyYlabel)objects.elementAt(i)).getYlabel(),x,y);
}
if (objects.elementAt(i) instanceof FlyCircle){// nothing yet x;y;width px;height px
if(((FlyCircle)objects.elementAt(i)).getDashed() == true){
backg.setStroke(
new BasicStroke(
((FlyCircle)objects.elementAt(i)).getLineWidth(),
BasicStroke.JOIN_ROUND,
BasicStroke.JOIN_BEVEL,
1,
new float[] {9}, 0
)
);
}
else
{
backg.setStroke( new BasicStroke(((FlyCircle)objects.elementAt(i)).getLineWidth()));
}
backg.setColor(((FlyCircle)objects.elementAt(i)).getColor());
if(((FlyCircle)objects.elementAt(i)).getFilled()){
backg.fillOval(
((FlyCircle)objects.elementAt(i)).getXc(),
((FlyCircle)objects.elementAt(i)).getYc(),
((FlyCircle)objects.elementAt(i)).getW(),
((FlyCircle)objects.elementAt(i)).getH());
}
else
{
backg.drawOval(
((FlyCircle)objects.elementAt(i)).getXc(),
((FlyCircle)objects.elementAt(i)).getYc(),
((FlyCircle)objects.elementAt(i)).getW(),
((FlyCircle)objects.elementAt(i)).getH());
}
}
}
}
}
 
 
public boolean ExecuteCommand(String line){ // analyze script line by line
String[] words = String2Array(line); // command,x,y,z,blah blah,1,2,3
boolean filled = false;
boolean dashed = false;
String cmd = words[0].toLowerCase();
Color color = new Color(0,0,0,1); // use black as default
if(cmd.equals("debug")){// linewidth 5
debug = true;
try{
if(words[1] != null){
if(words[1].equalsIgnoreCase("no") || words[1].equalsIgnoreCase("off") || words[1].equals("0")){debug = false;}
}else{
debug = true;
}
}catch(Exception e){}
return debug;
}
else
// check on key_char "d" or "f" as first letter in command
if(cmd.indexOf("f") == 0 ){
filled = true;DeBug("setting filled");
}
else
if(cmd.indexOf("d") == 0){
dashed = true;DeBug("setting dashed"); // drect dline dpoly
}
else
if(cmd.equals("xrange")){
boolean ok=true;
try{ xmin = symbols.eval(words[1]);}catch(SyntaxException e){ok=false;DeBug("could not set xmin : error "+e);}
try{ xmax = symbols.eval(words[2]);}catch(SyntaxException e){ok=false;DeBug("could not set xmax : error "+e);}
if(ok){
if( xmax < xmin){
double t = xmin;
xmin = xmax;
xmax= t;
DeBug("xmin is larger than xmax...correcting :xmin ="+xmin+" xmax ="+xmax);
}
else
{
if( xmax == xmin){
xmin=-1*(Math.abs(xmin));xmax=Math.abs(xmax);
}
}
return true;
}
else
{
return false;
}
}
else
if(cmd.equals("scalelatex") || cmd.equals("scaletex")){// scalelatex 1,1,width,height,latexstring,bgcolor,fgcolor,bg_alpha,fg_alpha
TeX = new sHotEqn();int x;int y;int w;int h;
Color bgc = bgcolor;
Color fgc = clickcolor;
try{
x = (int) x2px(symbols.eval(words[1]));
y = (int) y2px(symbols.eval(words[2]));
w = (int) (symbols.eval(words[3]));
h = (int) (symbols.eval(words[4]));
w = (int) (w*xsize/(Math.abs(xmax - xmin)));
h = (int) (h*ysize/(Math.abs(ymax - ymin)));
}catch( SyntaxException e ){ DeBug("could not set x/y error :"+e); return false;}
try{
bgc = GetInternalColorCode(words[6]);
fgc = GetInternalColorCode(words[7]);
}catch(Exception e){DeBug("will use default colors for latex image");}
try{alpha = Integer.parseInt(words[8]);bgc = MakeTransparent(bgc,alpha);}catch(Exception e){}
try{alpha = Integer.parseInt(words[9]);fgc = MakeTransparent(fgc,alpha);}catch(Exception e){}
TeX.setEquation(words[5]);
BufferedImage img = TeX.mkImage(bgc,fgc,xsize,ysize);
BufferedImage scaled_image = new BufferedImage(w,h, BufferedImage.TYPE_INT_ARGB );
Graphics2D g2d = (Graphics2D) scaled_image.getGraphics();
AffineTransform affinetransform = AffineTransform.getScaleInstance((double) w / (double)img.getWidth(), (double) h / (double)img.getHeight());
g2d.drawRenderedImage(img, affinetransform);
img = scaled_image;
try{
objects.add(new FlyLatex(x,y,img));
object_count++;
DeBug("loaded tex string as image");
return true;
}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("latex") || cmd.equals("tex")){
TeX = new sHotEqn();int x;int y;
Color fgc = clickcolor;
Color bgc = bgcolor;
try{
x = (int) x2px(symbols.eval(words[1]));
y = (int) y2px(symbols.eval(words[2]));
}catch( SyntaxException e ){ DeBug("could not set x/y error :"+e); return false;}
try{
bgc = GetInternalColorCode(words[4]);
fgc = GetInternalColorCode(words[5]);
}catch(Exception e){DeBug("will use default colors for latex image");}
try{
alpha = Integer.parseInt(words[6]);bgc = MakeTransparent(bgc,alpha);
alpha = Integer.parseInt(words[7]);fgc = MakeTransparent(fgc,alpha);
}catch(Exception e){}
TeX.setEquation(words[3]);
BufferedImage img = TeX.mkImage(bgc,fgc,xsize,ysize);
try{
objects.add(new FlyLatex(x,y,img));
object_count++;
DeBug("loaded tex string as image");
return true;
}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("yrange")){
boolean ok=true;
try{ ymin = symbols.eval(words[1]);}catch(SyntaxException e){ok=false;DeBug("could not set ymin : error "+e);}
try{ ymax = symbols.eval(words[2]);}catch(SyntaxException e){ok=false;DeBug("could not set ymax : error "+e);}
if(ok){
if(ymax < ymin){
double t = ymin;
ymin = ymax;
ymax= t;
DeBug("ymin is larger than ymax...correcting :ymin ="+ymin+" ymax ="+ymax);
}
else
{
if( ymax == ymin ){
ymin=-1*(Math.abs(ymin));ymax=Math.abs(ymax);
}
}
return true;
}
else
{
return true;
}
}
else
if(cmd.equals("transparent")){
try{
bgcolor = GetInternalColorCode(words[1]);// transparent blue,100
alpha = Integer.parseInt(words[2]);
bgcolor = MakeTransparent(bgcolor,alpha);
this.setBackground(bgcolor);
}
catch(Exception e){
bgcolor = GetInternalColorCode(words[1]);// transparent blue
bgcolor = MakeTransparent(bgcolor,0);
this.setBackground(bgcolor);
}
DeBug("setting transparent color to :"+bgcolor);
return true;
}
else
if(cmd.equals("clickcolor")){
try{
clickcolor = GetInternalColorCode(words[1]);// transparent blue,100
alpha = Integer.parseInt(words[2]);
clickcolor = MakeTransparent(clickcolor,alpha);
}
catch(Exception e){
try{
clickcolor = GetInternalColorCode(words[1]);// transparent blue
clickcolor = MakeTransparent(clickcolor,255);
}catch(Exception ex){DeBug("unable to set color to "+words[1]+" will use default :"+clickcolor);}
}
DeBug("setting mouse clickcolor to :"+clickcolor);
return true;
}
else
if(cmd.equals("precision")){// 1000 -> 3 decimals
try{precision = new Double(words[1]).doubleValue(); DeBug("setting precision to :"+precision);}
catch(Exception e){ DeBug("could not set precision");return false;}
return true;
}
else
if(cmd.equals("coordinates")){
try{
if(words[1].equalsIgnoreCase("yes") || words[1].equals("1") ){use_coords = true;}else{use_coords = false;}// of no use without a mouse
}catch(Exception e){use_coords = false;DeBug("Setting "+words[0]+" to false");}
return true;
}
else
if(cmd.equals("controls")){ // wims control buttons
try{
if(words[1].equalsIgnoreCase("yes") || words[1].equals("1") ){use_controls=true;}else{use_controls=false;}
}catch(Exception e){DeBug("Setting "+words[0]+" to false");return false;}
}
else
if(cmd.equals("replyurl")){ // wims reply url
try{replystring = words[0];return true; }catch(Exception e){DeBug("Could not read "+words[0]);return false;}
}
else
if(cmd.equals("pointstyle")){ // draw dot or cross
try{
if(words[1].equalsIgnoreCase("cross")){cross = true;return true;}
else
if(words[1].equalsIgnoreCase("dot")){cross = false;return true;}
}catch(Exception e){cross = false;DeBug("Setting "+words[0]+" to false");}
return true;
}
else
if(cmd.equals("userdraw")){ // drawing primitives ex-wims
try{
if(words[1].equalsIgnoreCase("points")||words[1].equalsIgnoreCase("point")){FlyApplet_panel.ctype=8;}
else
if(words[1].equalsIgnoreCase("line")){FlyApplet_panel.ctype=4;}
else
if(words[1].equalsIgnoreCase("circle")){FlyApplet_panel.ctype=2;}
else
if(words[1].equalsIgnoreCase("fcircle")){FlyApplet_panel.ctype=2;FlyApplet_panel.filled=true;}
else
if(words[1].equalsIgnoreCase("segment") || words[1].equalsIgnoreCase("seg")){FlyApplet_panel.ctype=6;}
else
if(words[1].equalsIgnoreCase("rect") || words[1].equalsIgnoreCase("rectangle") ){FlyApplet_panel.ctype=1;}
else
if(words[1].equalsIgnoreCase("frect") || words[1].equalsIgnoreCase("frectangle") ){FlyApplet_panel.ctype=1;FlyApplet_panel.filled=true;}
else
if(words[1].equalsIgnoreCase("lines") || words[1].equalsIgnoreCase("segments") ){FlyApplet_panel.ctype=3;}
else
if(words[1].equalsIgnoreCase("vector") || words[1].equalsIgnoreCase("vec")){FlyApplet_panel.ctype=9;}
else
if(words[1].equalsIgnoreCase("fpolygon") || words[1].equalsIgnoreCase("fpoly")){FlyApplet_panel.ctype=7;FlyApplet_panel.filled=true;}
else
if(words[1].equalsIgnoreCase("polygon") || words[1].equalsIgnoreCase("poly")){FlyApplet_panel.ctype=7;}
else
if(words[1].equalsIgnoreCase("curve")){FlyApplet_panel.ctype=0;}
else
if(words[1].equalsIgnoreCase("sline") || words[1].equalsIgnoreCase("semiline")){FlyApplet_panel.ctype=5;}
else{DeBug("could not set "+words[0]+" : "+words[1]) ; return false;}
}catch(Exception e){DeBug("could not set "+words[0]+" : "+words[1]);return false;}
DeBug("setting drawing primitive to "+words[1]);
return true;
}
else
if(cmd.equals("inputfields") || cmd.equals("inputs")){ // number of inputfields
try{
inputs = (int) symbols.eval(words[1]);
}catch( SyntaxException e ){DeBug("could not parse number of inputs :"+e+"\n will use default = 20");}
return true;
}
else
// inputfield x,y,width,height,font,fontsize,bgcolor,fgcolor,editable,value
if(cmd.equals("inputfield") || cmd.equals("input")){
inputfield = new TextArea[inputs];
int x;
int y;
int w = 50;
int h = 25;
int fontsize = 12;
String fontname = "Times";
Color bgc = bgcolor;
Color fgc = clickcolor;
boolean editable = true;
String value = "";
try{
x = (int) x2px(symbols.eval(words[1]));
y = (int) y2px(symbols.eval(words[2]));
}catch( SyntaxException e ){ DeBug("could not parse inputfield x/y param ; error :"+e); return false;}
if( words[3].length() != 0 && words[3] != null){
try{
w = (int) ((symbols.eval(words[3]))*xsize/(Math.abs(xmax - xmin)));
}catch(SyntaxException e){}
}else{ DeBug("could not parse inputfield width param. will use default.");}
if( words[4].length() != 0 && words[4] != null){
try{
h = (int) ((symbols.eval(words[4]))*ysize/(Math.abs(ymax - ymin)));
}catch(SyntaxException e){}
}else{ DeBug("could not parse inputfield height param. will use default.");}
try{
fontname = words[5];
fontsize = Integer.parseInt(words[6]);
bgc = GetInternalColorCode(words[7]); // final word ?
fgc = GetInternalColorCode(words[8]); // final word ?
}catch( Exception e ){ DeBug("could not parse inputfield font and color params. will use defaults ; error :"+e);}
Font f = new Font(fontname,Font.PLAIN,fontsize);
try{
if( words[9].length() != 0 && words[9] != null){
if( words[9].equals("no") || words[9].equals("0") || words[9].equals("false")){
editable = false;
}
}else{ DeBug("could not parse inputfield editable param. will use true");}
if( words[10].length() != 0 && words[10] != null ){
value = words[10];
}else{ DeBug("could not parse inputfield value param. will use empty string.");}
}catch(Exception e){}
try{objects.add(new FlyInput(x,y,w,h,f,bgc,fgc,inputfieldindex,editable,value));inputfieldindex++;use_inputarea = true; object_count++;return true;}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("mouse")){// mouse : yes/no 1/0
try{
if(words[1].equalsIgnoreCase("yes") || words[1].equalsIgnoreCase("1")){ mouse=true;}else{mouse=false;}//check if "param mouse" is set
}catch(Exception e){DeBug("could not set "+words[0]);}
return true;
}
else
if(cmd.equals("linewidth") || cmd.equals("thickness")){// linewidth 5
try{linewidth = Integer.parseInt(words[1]);}catch(Exception e){ return false;}
return true;
}
else
if(cmd.equals("image") || cmd.equals("background")){// linewidth 5
try {url = new URL(words[words.length-1]);}catch (Exception e) {url = null;DeBug("could not load image "+words[words.length-1]);}
if(url != null){
int x=0;int y=0;
try{
x = (int) x2px(symbols.eval(words[1]));
y = (int) y2px(symbols.eval(words[2]));
 
}catch(SyntaxException e){ DeBug("Could not set leftcorner of image error :"+e); return false;}
BufferedImage img;
try{
img = ImageIO.read(url);
if( x == 0 && y == 0 ){ // scale the image
try{
BufferedImage scaled_image = new BufferedImage(xsize,ysize, BufferedImage.TYPE_INT_ARGB );
Graphics2D g2d = (Graphics2D) scaled_image.getGraphics();
AffineTransform affinetransform = AffineTransform.getScaleInstance((double)xsize / (double)img.getWidth(), (double)ysize / (double)img.getHeight());
g2d.drawRenderedImage(img, affinetransform);
img = scaled_image;
DeBug("scaling image to "+xsize+"x"+ysize);
}
catch(Exception e){DeBug("could not scale image ! ..."+e);}
}
else
{
DeBug("not scaling image.\nTip: if you want to scale the image to the applet_size \nuse the syntax :\nimage "+xmin+","+ymax+","+url);
}
}catch(IOException e){DeBug("can not load image from "+url+"\n"+e); return false;}
try{
objects.add(new FlyImage(x,y,img));
object_count++;
DeBug("loaded image from "+url);
return true;
}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
return false;
}
else
if(cmd.indexOf("arrow") !=-1){
int x[] = new int[4];
int y[] = new int[4];
try{
x[0] = (int) x2px(symbols.eval(words[1]));
y[0] = (int) y2px(symbols.eval(words[2]));
x[1] = (int) x2px(symbols.eval(words[3]));
y[1] = (int) y2px(symbols.eval(words[4]));
}catch( SyntaxException e ){ DeBug("could not set x/y error :"+e); return false;}
int deltaX = x[1] - x[0];
int deltaY = y[1] - y[0];
double frac = 1.0D;
try{ frac = symbols.eval(words[5]);}catch( SyntaxException e ){ DeBug("error "+e);}
x[2] = x[0] + (int)((1-frac)*deltaX + (0.5+linewidth/20)*frac*deltaY);
y[2] = y[0] + (int)((1-frac)*deltaY - (0.5+linewidth/20)*frac*deltaX);
x[3] = x[0] + (int)((1-frac)*deltaX - (0.5+linewidth/20)*frac*deltaY);
y[3] = y[0] + (int)((1-frac)*deltaY + (0.5+linewidth/20)*frac*deltaX);
color = GetInternalColorCode(words[6]);
try{alpha = Integer.parseInt(words[7]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[8]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){}
try{objects.add(new FlyArrow(x,y,color,linewidth,filled,dashed));object_count++;return true;}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.indexOf("ylogscale") != -1){//Math.pow(10, p)
double exp = 10.0D;
int y1=(int) ymin;int y2=(int) ymax;
int num = (int) (exp*(y2-y1));
int X1[] = new int[num];int X2[] = new int[num];
int Y1[] = new int[num];int Y2[] = new int[num];
int c=0;double m0;double m1;
for(int p=y1; p<y2;p++){
m0 = Math.pow(exp,p);m1=0;
for(int i=0;i<exp;i++){
X1[c]=0;
X2[c]=xsize;
m1 = m0 + m1;
Y1[c] = (int) (y2px(Math.log(m1)/(Math.log(exp))));
Y2[c] = Y1[c];
c++;
}
}
color = GetInternalColorCode(words[1]);
try{alpha = Integer.parseInt(words[2]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[3]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){}
try{objects.add(new FlyParallel(X1,Y1,X2,Y2,color,linewidth,dashed));object_count++;return true;}
catch(Exception e){DeBug("could not set ylogscale ");}
}
else
if(cmd.indexOf("xlogscale") != -1){//Math.pow(10, p)
double exp = 10.0D;
int x1=(int) xmin;int x2=(int) xmax;
int num = (int) (exp*(x2-x1));
int X1[] = new int[num];int X2[] = new int[num];
int Y1[] = new int[num];int Y2[] = new int[num];
int c=0;double m0;double m1;
for(int p=x1; p<x2;p++){
m0 = Math.pow(exp,p);m1=0;
for(int i=0;i<exp;i++){
Y1[c]=0;
Y2[c]=ysize;
m1 = m0 + m1;
X1[c] = (int) (x2px(Math.log(m1)/(Math.log(exp))));
X2[c] = X1[c];
c++;
}
}
color = GetInternalColorCode(words[1]);
try{alpha = Integer.parseInt(words[2]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[3]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){}
try{objects.add(new FlyParallel(X1,Y1,X2,Y2,color,linewidth,dashed));object_count++;return true;}
catch(Exception e){DeBug("could not set ylogscale ");}
}
else
if(cmd.indexOf("xlabel") != -1){
// xlabel x_axis-name,fontsize,fontname,[fontcolor,alpha]
int fontsize = 12;
String fontname = "Times";
String xl="x-axis";
color = Color.black;
try{
xl = words[1];
fontsize = Integer.parseInt(words[2]);
}catch(Exception e){DeBug("could not parse params for xlabel...use\n xlabel X-axis_name,fontsize,fontname,color,alpha ");return false;}
try{
fontname = words[3];
color = GetInternalColorCode(words[4]);
try{
alpha = Integer.parseInt(words[5]);
color = MakeTransparent(color,alpha);
}catch(Exception e){}
}catch(Exception e){DeBug("can not read alpha : will use defaults");}
font = new Font(fontname,Font.PLAIN,fontsize);
try{objects.add(new FlyXlabel(xl,font,color));object_count++;return true;}
catch(Exception e){DeBug("could not set xlabel ");}
}
else
if(cmd.indexOf("ylabel") != -1){
// xlabel x_axis-name,fontsize,fontname
int fontsize = 12;
String fontname = "Times";
String yl="y-axis";
color = Color.black;
try{
yl = words[1];
fontsize = Integer.parseInt(words[2]);
}catch(Exception e){DeBug("could not parse params for ylabel...use\n ylabel y-axis_name,fontsize,fontname,color,alpha ");return false;}
try{
color = GetInternalColorCode(words[4]);
fontname = words[3];
try{
alpha = Integer.parseInt(words[5]);
color = MakeTransparent(color,alpha);
}catch(Exception e){}
}catch(Exception e){DeBug("can not read alpha : will use defaults");}
font = new Font(fontname,Font.PLAIN,fontsize);
try{objects.add(new FlyYlabel(yl,font,color));object_count++;return true;}
catch(Exception e){DeBug("could not set xlabel ");}
}
else
if(cmd.indexOf("xscale") != -1){
use_xscale = true;
//xscale x1,x1_name,x2,x2_name,x3,x3_name,....,fontsize,fontname,color,linewidth
//xscale -1,pi,0,0,1,pi,2,pi,22,Times,green
int dl = words.length - 4;
int xscale[] = new int[(dl)/2];
String xname[] = new String[(dl)/2];
try{
int i=0;
for(int p = 1 ; p < dl;p = p+2){
xscale[i] = (int)(x2px(symbols.eval(words[p])));
xname[i] = LaTeX2Uni(words[p+1]);
i++;
}
}catch(SyntaxException e){DeBug("could not parse xscale param \n syntax is mandatory !\n xscale x1,x1_name,x2,x2_name,..., fontsize,fontname,color,linewidth \n : error "+ e);return false;}
try{
fontsize = Integer.parseInt(words[dl]);
fontname = words[dl+1];
color = GetInternalColorCode(words[dl+2]); // final word ?
linewidth = Integer.parseInt(words[dl+3]);
}catch(Exception e){DeBug("could not parse X fontparams : error "+ e);return false;}
font = new Font(fontname,Font.PLAIN,fontsize);
 
try{
objects.add(new FlyXscale(xscale,xname,use_xscale,font,color,linewidth));
object_count++;return true;
}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.indexOf("yscale") != -1){
use_yscale = true;
//yscale y1,y1_name,y2,y2_name,y3,y3_name,....,fontsize,fontname,color
int dl = words.length - 4;
int yscale[] = new int[(dl)/2];
String yname[] = new String[(dl)/2];
try{
int i=0;
for(int p = 1 ; p < dl;p = p+2){
yscale[i] =(int) (y2px(symbols.eval(words[p])));
yname[i] = LaTeX2Uni(words[p+1]);
i++;
}
}catch(SyntaxException e){DeBug("could not parse yscale param \n syntax is mandatory !\n yscale y1,y1_name,y2,y2_name,..., fontsize,fontname,color,linewidth \n : error "+ e);return false;}
try{
fontsize = Integer.parseInt(words[dl]);
fontname = words[dl+1];
color = GetInternalColorCode(words[dl+2]);
linewidth = Integer.parseInt(words[dl+3]);
}catch(Exception e){DeBug("could not parse Y fontparams : error "+ e);return false;}
font = new Font(fontname,Font.PLAIN,fontsize);
try{
objects.add(new FlyYscale(yscale,yname,use_yscale,font,color,linewidth));
object_count++;return true;
}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.indexOf("grid") !=-1){ //grid 1,1,0.5,0.5,red,blue,1,1
// step size in coords
double Mx=1.0D,My=1.0D,mx=0.5D,my=0.5D;
try{
Mx = symbols.eval(words[1]);
My = symbols.eval(words[2]);
mx = symbols.eval(words[3]);
my = symbols.eval(words[4]);
}catch(SyntaxException e ) {DeBug("could not set x/y-major x/y minor : error "+e);return false; }
// calculate number of lines == length of array
int M1= (int) Math.abs((xmax-xmin)/Mx);// number of major vertical lines
int M2= (int) Math.abs((ymax-ymin)/My);// number of major horizontal lines
int m1= (int) Math.abs((xmax-xmin)/mx);// number of minor vertical lines
int m2= (int) Math.abs((ymax-ymin)/my);// number of minor horizontal lines
int[] xminor= new int[m1];
int[] yminor= new int[m2];
int[] xmajor= new int[M1];
int[] ymajor= new int[M2];
int Ml=2;//defaults
int ml=1;
double s;
s=ymin;
for(int p=0;p<m2;p++){
s = s + my;
yminor[p] = (int) y2px(s);
}
s=ymin;
for(int p=0;p<M2;p++){
s = s + My;
ymajor[p] = (int) y2px(s);
}
s=xmin;
for(int p=0;p<m1;p++){
s = s + mx;
xminor[p] = (int) x2px(s);// convert to pixels
}
s=xmin;
for(int p=0;p<M1;p++){
s = s + Mx;
xmajor[p] = (int) x2px(s);
}
Color Mc = GetInternalColorCode(words[5]);
Color mc = GetInternalColorCode(words[6]);
try{
Ml=Integer.parseInt(words[7]);
ml=Integer.parseInt(words[8]);
alpha = Integer.parseInt(words[9]);Mc = MakeTransparent(Mc,alpha);
alpha = Integer.parseInt(words[10]);mc = MakeTransparent(mc,alpha);
}catch(Exception e){DeBug("no alpha colors in grid defined.");}
try{objects.add(new FlyGrid(xmajor,ymajor,xminor,yminor,Mc,mc,Ml,ml,dashed));
DeBug("setting grid ");
object_count++;return true;
}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("plotsteps")){// linewidth 5
try{plotsteps = Integer.parseInt(words[1]);}catch(Exception e){DeBug("failed setting plotsteps :"+e);}
return true;
}
if(cmd.equals("plotjump")){// linewidth 5
try{plotjump = Integer.parseInt(words[1]);}catch(Exception e){DeBug("failed setting plotjump :"+e);}
return true;
}
else
if(cmd.indexOf("parallel")!=-1 ){
int x1=1,y1=1,x2=1,y2=1,dx=1,dy=1;
try{
x1 = (int) x2px(symbols.eval(words[1]));
y1 = (int) y2px(symbols.eval(words[2]));
x2 = (int) x2px(symbols.eval(words[3]));
y2 = (int) y2px(symbols.eval(words[4]));
dx = (int) (xsize*(symbols.eval(words[6]))/(xmax - xmin));
dy = (int) (ysize*(symbols.eval(words[6]))/(ymax - ymin));
}catch( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
int num = Integer.parseInt(words[7]);
int X1[] = new int[num];
int X2[] = new int[num];
int Y1[] = new int[num];
int Y2[] = new int[num];
for(int i=0;i<num;i++){
X1[i] = x1 + i*dx;
Y1[i] = y1 - i*dy;
X2[i] = x2 + i*dx;
Y2[i] = y2 - i*dy;
}
color = GetInternalColorCode(words[8]);
try{alpha = Integer.parseInt(words[9]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[10]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){}
try{objects.add(new FlyParallel(X1,Y1,X2,Y2,color,linewidth,dashed));object_count++;return true;}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.indexOf("curve") !=-1 || cmd.indexOf("function") !=-1 || cmd.indexOf("plot") !=-1){
String fx = words[1];
double step = (xmax-xmin)/plotsteps;
int x[] = new int[plotsteps+1];
int y[] = new int[plotsteps+1];
int s=0;int dist;int xx;int yy;double py;
for (double px = xmin ; px < xmax; px=px+step){
x[s] = (int) x2px(px);
try {
py = symbols.eval( fx.replaceAll( "x","("+px+")" ));
if( (Double.toString(py)).equals("NaN")){DeBug("skipping x="+x[s]+" -> NaN"); s = s - 1;}
else { y[s] = (int) y2px( py ); if(y[s] > ysize+plotjump){ y[s] = ysize;}}
} catch (SyntaxException e ) {DeBug("error "+e);s=s-1;}
s++;
}
int tmpx[]=new int[s];// correcting array_size for skipped points
int tmpy[]=new int[s];
int i=0;
for(int p=0;p<s;p++){
tmpx[i] = x[p];
tmpy[i] = y[p];
i++;
}
x = tmpx;
y = tmpy;
color = GetInternalColorCode(words[2]);
try{alpha = Integer.parseInt(words[3]);color = MakeTransparent(color,alpha);}catch(Exception e){}
try{linewidth = Integer.parseInt(words[4]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
try{objects.add( new FlyPlot(x,y,color,linewidth,filled,dashed));object_count++;return true;}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("textup") || cmd.equals("rotatetext") ){
// text x,y,angle,fontname,fontsize,the_text_without_comma,color [,alpha]
int x=0,y=0;
try{
x = (int) x2px(symbols.eval(words[1]));
y = (int) y2px(symbols.eval(words[2]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
int angle = Integer.parseInt(words[3]);
if(words[4] != null){fontname = words[4];DeBug("setting fontname to :"+fontname);} // font
if(words[5] != null){fontsize = Integer.parseInt(words[5]);}
String txt = LaTeX2Uni(words[6]); // the text with spaces...
color = GetInternalColorCode(words[7]);
try{alpha = Integer.parseInt(words[8]);color = MakeTransparent(color,alpha);}catch(Exception e){}
try{ font = new Font(fontname,Font.PLAIN,fontsize);}catch(Exception e){DeBug("could nol load font"+fontname);}
try{objects.add(new FlyText(x,y,angle,font,txt,color));object_count++;return true;}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("text") ){
// text x,y,fontname,fontsize,the_text_without_comma,color [,alpha]
int x=0,y=0;
try{
x = (int) x2px(symbols.eval(words[1]));
y = (int) y2px(symbols.eval(words[2]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
if(words[3] != null){fontname = words[3];DeBug("setting fontname to :"+fontname);} // font
if(words[4] != null){fontsize = Integer.parseInt(words[4]);}
String txt = LaTeX2Uni(words[5]); // the text with spaces...
color = GetInternalColorCode(words[6]);
int angle = 0;
try{ alpha = Integer.parseInt(words[7]);color = MakeTransparent(color,alpha);}catch(Exception e){}
try{ font = new Font(fontname,Font.PLAIN,fontsize);DeBug("font = :"+font);}catch(Exception e){DeBug("could nol load font"+fontname);}
try{ objects.add(new FlyText(x,y,angle,font,txt,color));object_count++;return true;}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.indexOf("ellips")!=-1 || cmd.indexOf("oval") != -1){
int xc=0,yc=0,w=0,h=0;
try{
xc = (int) x2px(symbols.eval(words[1]));
yc = (int) y2px(symbols.eval(words[2]));
w = (int) c2px(symbols.eval(words[3]));
h = (int) c2px(symbols.eval(words[4]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
color = GetInternalColorCode(words[5]);
try{ alpha = Integer.parseInt(words[6]);color = MakeTransparent(color,alpha);
try{ linewidth = Integer.parseInt(words[7]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){} // syntax line 1,0,2,0,blue,123 [alpha =123
try{ objects.add(new FlyCircle(xc-w/2,yc-h/2,w,h,color,linewidth,filled,dashed));object_count++;return true;}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.indexOf("arc")!=-1 ){ // arc xc,yc,R,angle1,angle2,color [,alpha,line]
int xc=0,yc=0,r=0,a1=0,a2=0;
try{
xc = (int) x2px(symbols.eval(words[1]));
yc = (int) y2px(symbols.eval(words[2]));
r = (int) c2px(symbols.eval(words[3]));
a1 = (int) (symbols.eval(words[4]));
a2 = (int) (symbols.eval(words[5]));
} catch ( SyntaxException e ){ DeBug("Could not set xc,yc,radius or angles : "+e); return false; }
 
a2=Math.abs(a2-a1);//
color = GetInternalColorCode(words[6]);
try{alpha = Integer.parseInt(words[7]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[8]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){}
try{objects.add(new FlyArc(xc-r,yc-r,2*r,2*r,a1,a2,color,linewidth,filled,dashed));object_count++;return true;}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(words[0].indexOf("circle")!= -1){ // circle xc,yc,R,color [,alpha,line]
int xc=0,yc=0,r=0;
try{
xc = (int) x2px(symbols.eval(words[1]));
yc = (int) y2px(symbols.eval(words[2]));
r = (int) c2px(symbols.eval(words[3]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
color = GetInternalColorCode(words[4]);
try{alpha = Integer.parseInt(words[5]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[6]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){} // syntax line 1,0,2,0,blue,123 [alpha =123
// Oval x,y,w,h
try{objects.add(new FlyCircle(xc-r,yc-r,2*r,2*r,color,linewidth,filled,dashed));object_count++;return true;}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("vline") || cmd.equals("vlines") || cmd.equals("verticalline") ||
cmd.equals("dvline") || cmd.equals("dvlines") || cmd.equals("dverticalline")
){
int x1=0,x2=0;
try{
x1 = (int) x2px(symbols.eval(words[1]));
x2 = (int) x2px(symbols.eval(words[2]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
 
int y1 = (int) y2px(ymin-1);
int y2 = (int) y2px(ymax+1);
color = GetInternalColorCode(words[3]);
try{alpha = Integer.parseInt(words[4]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[5]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){} // syntax line 1,0,2,0,blue,123 [alpha =123
try{objects.add(new FlyLine(x1,y1,x1,y2,color,linewidth,dashed));object_count++;return true;}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("hline") || cmd.equals("hlines") || cmd.equals("horizontalline") ||
cmd.equals("dhline") || cmd.equals("dhlines") || cmd.equals("dhorizontalline")
){
int x1=0,y1=0;
try{
x1 = (int) x2px(symbols.eval(words[1]));
y1 = (int) y2px(symbols.eval(words[2]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
x1=(int) x2px(xmin-1);
int x2=(int) x2px(xmax+1);
color = GetInternalColorCode(words[3]);
try{alpha = Integer.parseInt(words[4]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[5]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){} // syntax line 1,0,2,0,blue,123 [alpha =123
try{objects.add(new FlyLine(x1,y1,x2,y1,color,linewidth,dashed));object_count++;return true;}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("line") || cmd.equals("lines") ||
cmd.equals("dline") || cmd.equals("dlines")
){
int x1=0,y1=0,x2=0,y2=0;
try{
x1 = (int) x2px(symbols.eval(words[1]));
y1 = (int) y2px(symbols.eval(words[2]));
x2 = (int) x2px(symbols.eval(words[3]));
y2 = (int) y2px(symbols.eval(words[4]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
color = GetInternalColorCode(words[5]);
try{alpha = Integer.parseInt(words[6]);color = MakeTransparent(color,alpha);
try{linewidth = Integer.parseInt(words[7]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){} // syntax line 1,0,2,0,blue,123 [alpha =123
try{objects.add(new FlyLine(x1,y1,x2,y2,color,linewidth,dashed));object_count++;return true;}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(words[0].indexOf("triangle")!=-1){
int x1=0,y1=0,x2=0,y2=0,x3=0,y3=0;
try{
x1 = (int) x2px(symbols.eval(words[1]));
y1 = (int) y2px(symbols.eval(words[2]));
x2 = (int) x2px(symbols.eval(words[3]));
y2 = (int) y2px(symbols.eval(words[4]));
x3 = (int) x2px(symbols.eval(words[5]));
y3 = (int) y2px(symbols.eval(words[6]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
 
int x[] = new int [4];
int y[] = new int [4];
x[0]=x1;y[0]=y1;
x[1]=x2;y[1]=y2;
x[2]=x3;y[2]=y3;
x[3]=x1;y[3]=y1;
color = GetInternalColorCode(words[7]);
try{alpha = Integer.parseInt(words[8]);color = MakeTransparent(color , alpha);
try{linewidth = Integer.parseInt(words[9]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){}
try{objects.add(new FlyPoly(x,y,color,linewidth,filled,dashed));object_count++;}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(words[0].indexOf("rect")!=-1 || cmd.indexOf("square")!=-1 ){
int x1=0,y1=0,x2=0,y2=0;
try{
x1 = (int) x2px(symbols.eval(words[1]));
y1 = (int) y2px(symbols.eval(words[2]));
x2 = (int) x2px(symbols.eval(words[3]));
y2 = (int) y2px(symbols.eval(words[4]));
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
 
int x[] = new int [5];
int y[] = new int [5];
x[0]=x1;y[0]=y1;
x[1]=x1;y[1]=y2;
x[2]=x2;y[2]=y2;
x[3]=x2;y[3]=y1;
x[4]=x1;y[4]=y1;
color = GetInternalColorCode(words[5]);
try{alpha = Integer.parseInt(words[6]);color = MakeTransparent(color , alpha);
try{linewidth = Integer.parseInt(words[7]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
}catch(Exception e){}
try{objects.add(new FlyPoly(x,y,color,linewidth,filled,dashed));object_count++;return true;}
catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.indexOf("poly") != -1){
int n=words.length;
int tmpx[] = new int[n] ;int tmpy[] = new int[n];
boolean found_color=false;
String x1="";String y1="";int c=0;
for(int i=1; i<n;i=i+2){
x1=words[i];
found_color=ColorOrNumber(x1);
if(!found_color){
y1=words[i+1];
try{
tmpx[c] = (int) x2px(symbols.eval(x1));
tmpy[c] = (int) y2px(symbols.eval(y1));
c++;
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
}
else
{
color = GetInternalColorCode(x1);
found_color=true;// now se if next word is alpha...
try{alpha = Integer.parseInt(words[i+1]);color = MakeTransparent(color , alpha);}catch(Exception e){DeBug("no alpha value given to polygon");}
try{linewidth = Integer.parseInt(words[i+2]);}catch(Exception e){DeBug("no linewidth given...using previous value "+linewidth );}
i=n+1;
}
}
try{
int x[] = new int[c-1];
int y[] = new int[c-1];
for(int p=0;p<c-1;p++){
x[p]=tmpx[p];
y[p]=tmpy[p];
}
objects.add(new FlyPoly(x,y,color,linewidth,filled,dashed));object_count++;return true;
}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
else
if(cmd.equals("point") || cmd.equals("points")){// points x1,y1,x2,y2,x3,y3,x4,y4.....blue,123 or point x1,y1,x2,y2,x3,y3,x4,y4.....blue
int n=words.length; int c=0;
double tmpx[] = new double[n] ;double tmpy[] = new double[n];
boolean found_color=false;
String x1="";String y1="";
for(int i=1;i<n;i=i+2){
x1=words[i];
found_color=ColorOrNumber(x1);
if(found_color){
color = GetInternalColorCode(x1);
try{alpha = Integer.parseInt(words[i+1]);color = MakeTransparent(color , alpha); found_color=true;}catch(Exception e){found_color=false;}
if(found_color){try{ linewidth = Integer.parseInt(words[i+2]);}catch(Exception e){}}
i=n;
}
else
{
y1=words[i+1];
try{
tmpx[c] = (int) x2px(symbols.eval(x1));
tmpy[c] = (int) y2px(symbols.eval(y1));
c++;
} catch ( SyntaxException e ){ DeBug("Could not set x/y , error : "+e); return false; }
 
}
}
int x[] = new int[c];
int y[] = new int[c];
for(int p=0;p<c;p++){
x[p]=(int)(tmpx[p] - linewidth/2);// a point is a filledOval
y[p]=(int)(tmpy[p] - linewidth/2);
}
try{ objects.add(new FlyPoints(x,y,color,linewidth));object_count++;}catch(Exception e){DeBug("failed adding "+words[0]+" exception = "+e); return false;}
}
return true;
}
public Color MakeTransparent(Color color, int alpha){
// adds/replaces alpha in a given color.
return new Color(color.getRed(),color.getGreen(),color.getBlue(),alpha);
}
 
public double c2px(double c){// coords to pixel
double C = c*xsize/(xmax - xmin);
return C;
}
 
public double x2px(double x){ // x-coords to pixel
double X = x*xsize/(xmax - xmin) - xsize*xmin/(xmax - xmin);
return X;
}
 
public double y2px(double y){ // y-coords to pixel
double Y = -1*y*ysize/(ymax-ymin) + ymax*ysize/(ymax-ymin);
return Y;
}
 
public boolean ColorOrNumber(String s){ // checks if netx item in cmd-string is a color or a number, to allow compact syntax: line x1,y1,x2,y2,color,alpha,linewidth
try{ symbols.eval(s); return false;} catch ( SyntaxException e ){ return true;}
}
 
public Color GetInternalColorCode(String color){// reads name and compares is caseinsnsitive with rgb.txt; returns matching color; alpha=255
boolean found=false;
Color k = new Color(0,0,0,255);
for(int i=0;i<colornames.length;i++){
if(colornames[i].equalsIgnoreCase(color)){//R,G,B,alpha
k = new Color(colors[i][0],colors[i][1],colors[i][2],colors[i][3]);
found=true;
break;
}
}
if(!found){DeBug("could not find color named "+color+"\nwill use black instead");}
return k;
}
// jm.evers; handy functions, not invented here :(
public byte [] loadURL(URL url) throws IOException {
int bufSize = 1024 * 2;
byte [] buf = new byte[bufSize];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(url.openStream());
int n;
while ((n = in.read(buf)) > 0){
bout.write(buf, 0, n);
}
try { in.close(); } catch (Exception ignored) { }
return bout.toByteArray();
}
 
public String loadFile(String fname) throws IOException {
byte[] bytes = loadURL(new URL("file:" + fname));
return new String(bytes);
}
 
public String load(String fileOrURL) throws IOException {
try { URL url = new URL(fileOrURL);
return new String(loadURL(url));
} catch(Exception e){ return loadFile(fileOrURL);}
}
// a listuniq on arrays ...uses System.arraycopy
public int[] ListUniq(int[] array){
Arrays.sort(array);
int k = 0;
for (int i = 0; i < array.length; i++){
if (i > 0 && array[i] == array[i -1] )
continue;
array[k++] = array[i];
}
int [] unique = new int[k];
System.arraycopy(array, 0, unique, 0, k);
return unique;
}
public String[] String2Array(String s){//syntax: command x,y,a,q,color,blah blah blah,4,5
s=s.replaceAll(",,",", ,");
s=s.replaceAll("\t","");
//s=s.replaceAll(" "," ");
StringTokenizer st = new StringTokenizer(s,",");
int m=st.countTokens();
String[] reply = new String[m+1];
String first = st.nextToken();//command x
StringTokenizer temp = new StringTokenizer(first," ");
reply[0]=temp.nextToken(); //command
reply[1]=temp.nextToken(); // x
for(int i=2;i<m+1;i++){
reply[i] = st.nextToken();// y,a,q,color,blah blah blah,4,5
}
return reply;
}
public String LaTeX2Uni(String S){
for(int i=0; i<LaTeX.length;i++){
if( S.indexOf(LaTeX[i]) != -1 ){
S = S.replaceAll(LaTeX[i],Unicode[i]);
}
}
return S;
}
public static int chars = 98;
 
public static String Unicode[] = {
"\u03B1", "\u0391", "\u03B2", "\u0392", "\u03B3", "\u0393", "\u03B4", "\u0394", "\u03B5", "\u0395",
"\u03D5", "\u03A6", "\u03C6", "\u03B3", "\u0393", "\u03B7", "\u0397", "\u03B9", "\u0399", "\u03BA",
"\u039A", "\u03BB", "\u039B", "\u03BC", "\u039C", "\u03BD", "\u039D", "\u03BF", "\u03A9", "\u03C0",
"\u03A0", "\u03C7", "\u03A7", "\u03C1", "\u03A1", "\u03C3", "\u03A3", "\u03C4", "\u03A4", "\u03C5",
"\u03A5", "\u03C8", "\u03A8", "\u03C9", "\u03A9", "\u03BE", "\u039E", "\u03C7", "\u03A7", "\u03B6",
"\u0396", "\u03B8", "\u0398", "\u0024", "%", "&", "\247", "\251", "\256", "\u2030",
"\275", "\u2153", "\274", "\276", "\u2154", "\261", "\u2202", "\u2206", "\u221E",
"\u22C1","\u22C0","\u22C0","\u2027","\u2027","\u00F7","\u2115","\u2124","\u211A","\u211D","\u2216",
"f\u00AF\u00B9(x)","\u2208","\u22C0","\u22C1","\u2209","rightarrow","\u21D4","\u221E","\u2192",
"\u00B2log","\u00B3log","\u2074log","\u2075log","\u2076log","\u2077log","\u2078log","\u2079log",
"\u221b","\u221c","\u2075sqrt","\u2076sqrt","\u2077sqrt","\u2078sqrt","\u2079sqrt","\u221a",
"\u20AC"
};
public static String LaTeX[] = {
" alpha "," Alpha ", " beta "," Beta "," gamma "," Gamma "," delta "," Delta "," epsilon "," Epsilon ",
" phi "," Phi "," varphi "," gamma "," Gamma "," eta "," Eta "," iota "," I "," kappa ",
" Kappa "," lambda "," Lambda "," mu "," Mu "," nu "," Nu "," omikron "," Omikron "," pi ",
" Pi "," chi "," Chi "," rho "," Rho "," sigma "," Sigma "," tau "," Tau "," uu ",
" Uu "," psi "," Psi "," omega "," Omega "," chi "," Chi "," ypsilon "," Ypsilon "," zeta ",
" Zeta "," theta "," Theta "," dollar "," percent "," ampersand "," paragraph "," copyright "," trademark "," promille ",
" half "," third "," quarter "," threequarters "," twothirds "," pm "," partial "," deltaop "," infty ",
" of "," et "," en ","cdot"," times "," div "," N "," Z "," Q "," R "," \\ ",
" f^-1(x) "," isin "," and "," or "," notin "," --> "," => "," inf "," -> ",
"log2","log3","log4","log5","log6","log7","log8","log9",
"sqrt3","sqrt4","sqrt5","sqrt6","sqrt7","sqrt8","sqrt8","sqrt",
" euro "
};
 
// /usr/X11R6/lib/X11/rgb.txt
 
int colors[][]={
{255,255,255,255},{255,0,0,255},{0,255,0,255},{0,0,255,255},{255,255,0,255},
{255,250,250,255},{248,248,255,255},{248,248,255,255},{245,245,245,255},{245,245,245,255},{220,220,220,255},{255,250,240,255},{255,250,240,255},
{253,245,230,255},{253,245,230,255},{250,240,230,255},{250,235,215,255},{250,235,215,255},{255,239,213,255},{255,239,213,255},{255,235,205,255},{255,235,205,255},
{255,228,196,255},{255,218,185,255},{255,218,185,255},{255,222,173,255},{255,222,173,255},{255,228,181,255},{255,248,220,255},{255,255,240,255},{255,250,205,255},
{255,250,205,255},{255,245,238,255},{240,255,240,255},{245,255,250,255},{245,255,250,255},{240,255,255,255},{240,248,255,255},{240,248,255,255},{230,230,250,255},
{255,240,245,255},{255,240,245,255},{255,228,225,255},{255,228,225,255},{255,255,255,255},{0,0,0,255},{47,79,79,255},{47,79,79,255},{47,79,79,255},{47,79,79,255},
{105,105,105,255},{105,105,105,255},{105,105,105,255},{105,105,105,255},{112,128,144,255},{112,128,144,255},{112,128,144,255},{112,128,144,255},{119,136,153,255},
{119,136,153,255},{119,136,153,255},{119,136,153,255},{190,190,190,255},{190,190,190,255},{211,211,211,255},{211,211,211,255},{211,211,211,255},{211,211,211,255},
{25,25,112,255},{25,25,112,255},{0,0,128,255},{0,0,128,255},{0,0,128,255},{100,149,237,255},{100,149,237,255},{72,61,139,255},{72,61,139,255},{106,90,205,255},{106,90,205,255},
{123,104,238,255},{123,104,238,255},{132,112,255,255},{132,112,255,255},{0,0,205,255},{0,0,205,255},{65,105,225,255},{65,105,225,255},{0,0,255,255},{30,144,255,255},
{30,144,255,255},{0,191,255,255},{0,191,255,255},{135,206,235,255},{135,206,235,255},{135,206,250,255},{135,206,250,255},{70,130,180,255},{70,130,180,255},{176,196,222,255},
{176,196,222,255},{173,216,230,255},{173,216,230,255},{176,224,230,255},{176,224,230,255},{175,238,238,255},{175,238,238,255},{0,206,209,255},{0,206,209,255},{72,209,204,255},
{72,209,204,255},{64,224,208,255},{0,255,255,255},{224,255,255,255},{224,255,255,255},{95,158,160,255},{95,158,160,255},{102,205,170,255},{102,205,170,255},{127,255,212,255},
{0,100,0,255},{0,100,0,255},{85,107,47,255},{85,107,47,255},{143,188,143,255},{143,188,143,255},{46,139,87,255},{46,139,87,255},{60,179,113,255},{60,179,113,255},{32,178,170,255},
{32,178,170,255},{152,251,152,255},{152,251,152,255},{0,255,127,255},{0,255,127,255},{124,252,0,255},{124,252,0,255},{0,255,0,255},{127,255,0,255},{0,250,154,255},{0,250,154,255},
{173,255,47,255},{173,255,47,255},{50,205,50,255},{50,205,50,255},{154,205,50,255},{154,205,50,255},{34,139,34,255},{34,139,34,255},{107,142,35,255},{107,142,35,255},
{189,183,107,255},{189,183,107,255},{240,230,140,255},{238,232,170,255},{238,232,170,255},{250,250,210,255},{250,250,210,255},{255,255,224,255},{255,255,224,255},
{255,255,0,255},{255,215,0,255},{238,221,130,255},{238,221,130,255},{218,165,32,255},{184,134,11,255},{184,134,11,255},{188,143,143,255},{188,143,143,255},{205,92,92,255},
{205,92,92,255},{139,69,19,255},{139,69,19,255},{160,82,45,255},{205,133,63,255},{222,184,135,255},{245,245,220,255},{245,222,179,255},{244,164,96,255},{244,164,96,255},
{210,180,140,255},{210,105,30,255},{178,34,34,255},{165,42,42,255},{233,150,122,255},{233,150,122,255},{250,128,114,255},{255,160,122,255},{255,160,122,255},{255,165,0,255},
{255,140,0,255},{255,140,0,255},{255,127,80,255},{240,128,128,255},{240,128,128,255},{255,99,71,255},{255,69,0,255},{255,69,0,255},{255,0,0,255},{255,105,180,255},
{255,105,180,255},{255,20,147,255},{255,20,147,255},{255,192,203,255},{255,182,193,255},{255,182,193,255},{219,112,147,255},{219,112,147,255},{176,48,96,255},
{199,21,133,255},{199,21,133,255},{208,32,144,255},{208,32,144,255},{255,0,255,255},{238,130,238,255},{221,160,221,255},{218,112,214,255},{186,85,211,255},{186,85,211,255},
{153,50,204,255},{153,50,204,255},{148,0,211,255},{148,0,211,255},{138,43,226,255},{138,43,226,255},{160,32,240,255},{147,112,219,255},{147,112,219,255},{216,191,216,255},
{255,250,250,255},{238,233,233,255},{205,201,201,255},{139,137,137,255},{255,245,238,255},{238,229,222,255},{205,197,191,255},{139,134,130,255},{255,239,219,255},
{238,223,204,255},{205,192,176,255},{139,131,120,255},{255,228,196,255},{238,213,183,255},{205,183,158,255},{139,125,107,255},{255,218,185,255},{238,203,173,255},
{205,175,149,255},{139,119,101,255},{255,222,173,255},{238,207,161,255},{205,179,139,255},{139,121,94,255},{255,250,205,255},{238,233,191,255},{205,201,165,255},
{139,137,112,255},{255,248,220,255},{238,232,205,255},{205,200,177,255},{139,136,120,255},{255,255,240,255},{238,238,224,255},{205,205,193,255},{139,139,131,255},
{240,255,240,255},{224,238,224,255},{193,205,193,255},{131,139,131,255},{255,240,245,255},{238,224,229,255},{205,193,197,255},{139,131,134,255},{255,228,225,255},
{238,213,210,255},{205,183,181,255},{139,125,123,255},{240,255,255,255},{224,238,238,255},{193,205,205,255},{131,139,139,255},{131,111,255,255},{122,103,238,255},
{105,89,205,255},{71,60,139,255},{72,118,255,255},{67,110,238,255},{58,95,205,255},{39,64,139,255},{0,0,255,255},{0,0,238,255},{0,0,205,255},{0,0,139,255},{30,144,255,255},
{28,134,238,255},{24,116,205,255},{16,78,139,255},{99,184,255,255},{92,172,238,255},{79,148,205,255},{54,100,139,255},{0,191,255,255},{0,178,238,255},{0,154,205,255},
{0,104,139,255},{135,206,255,255},{126,192,238,255},{108,166,205,255},{74,112,139,255},{176,226,255,255},{164,211,238,255},{141,182,205,255},{96,123,139,255},{198,226,255,255},
{185,211,238,255},{159,182,205,255},{108,123,139,255},{202,225,255,255},{188,210,238,255},{162,181,205,255},{110,123,139,255},{191,239,255,255},{178,223,238,255},
{154,192,205,255},{104,131,139,255},{224,255,255,255},{209,238,238,255},{180,205,205,255},{122,139,139,255},{187,255,255,255},{174,238,238,255},{150,205,205,255},
{102,139,139,255},{152,245,255,255},{142,229,238,255},{122,197,205,255},{83,134,139,255},{0,245,255,255},{0,229,238,255},{0,197,205,255},{0,134,139,255},{0,255,255,255},
{0,238,238,255},{0,205,205,255},{0,139,139,255},{151,255,255,255},{141,238,238,255},{121,205,205,255},{82,139,139,255},{127,255,212,255},{118,238,198,255},{102,205,170,255},
{69,139,116,255},{193,255,193,255},{180,238,180,255},{155,205,155,255},{105,139,105,255},{84,255,159,255},{78,238,148,255},{67,205,128,255},{46,139,87,255},{154,255,154,255},
{144,238,144,255},{124,205,124,255},{84,139,84,255},{0,255,127,255},{0,238,118,255},{0,205,102,255},{0,139,69,255},{0,255,0,255},{0,238,0,255},{0,205,0,255},{0,139,0,255},
{127,255,0,255},{118,238,0,255},{102,205,0,255},{69,139,0,255},{192,255,62,255},{179,238,58,255},{154,205,50,255},{105,139,34,255},{202,255,112,255},{188,238,104,255},
{162,205,90,255},{110,139,61,255},{255,246,143,255},{238,230,133,255},{205,198,115,255},{139,134,78,255},{255,236,139,255},{238,220,130,255},{205,190,112,255},
{139,129,76,255},{255,255,224,255},{238,238,209,255},{205,205,180,255},{139,139,122,255},{255,255,0,255},{238,238,0,255},{205,205,0,255},{139,139,0,255},{255,215,0,255},
{238,201,0,255},{205,173,0,255},{139,117,0,255},{255,193,37,255},{238,180,34,255},{205,155,29,255},{139,105,20,255},{255,185,15,255},{238,173,14,255},{205,149,12,255},
{139,101,8,255},{255,193,193,255},{238,180,180,255},{205,155,155,255},{139,105,105,255},{255,106,106,255},{238,99,99,255},{205,85,85,255},{139,58,58,255},{255,130,71,255},
{238,121,66,255},{205,104,57,255},{139,71,38,255},{255,211,155,255},{238,197,145,255},{205,170,125,255},{139,115,85,255},{255,231,186,255},{238,216,174,255},{205,186,150,255},
{139,126,102,255},{255,165,79,255},{238,154,73,255},{205,133,63,255},{139,90,43,255},{255,127,36,255},{238,118,33,255},{205,102,29,255},{139,69,19,255},{255,48,48,255},
{238,44,44,255},{205,38,38,255},{139,26,26,255},{255,64,64,255},{238,59,59,255},{205,51,51,255},{139,35,35,255},{255,140,105,255},{238,130,98,255},{205,112,84,255},
{139,76,57,255},{255,160,122,255},{238,149,114,255},{205,129,98,255},{139,87,66,255},{255,165,0,255},{238,154,0,255},{205,133,0,255},{139,90,0,255},{255,127,0,255},
{238,118,0,255},{205,102,0,255},{139,69,0,255},{255,114,86,255},{238,106,80,255},{205,91,69,255},{139,62,47,255},{255,99,71,255},{238,92,66,255},{205,79,57,255},{139,54,38,255},
{255,69,0,255},{238,64,0,255},{205,55,0,255},{139,37,0,255},{255,0,0,255},{238,0,0,255},{205,0,0,255},{139,0,0,255},{255,20,147,255},{238,18,137,255},{205,16,118,255},{139,10,80,255},
{255,110,180,255},{238,106,167,255},{205,96,144,255},{139,58,98,255},{255,181,197,255},{238,169,184,255},{205,145,158,255},{139,99,108,255},{255,174,185,255},{238,162,173,255},
{205,140,149,255},{139,95,101,255},{255,130,171,255},{238,121,159,255},{205,104,137,255},{139,71,93,255},{255,52,179,255},{238,48,167,255},{205,41,144,255},{139,28,98,255},
{255,62,150,255},{238,58,140,255},{205,50,120,255},{139,34,82,255},{255,0,255,255},{238,0,238,255},{205,0,205,255},{139,0,139,255},{255,131,250,255},{238,122,233,255},
{205,105,201,255},{139,71,137,255},{255,187,255,255},{238,174,238,255},{205,150,205,255},{139,102,139,255},{224,102,255,255},{209,95,238,255},{180,82,205,255},{122,55,139,255},
{191,62,255,255},{178,58,238,255},{154,50,205,255},{104,34,139,255},{155,48,255,255},{145,44,238,255},{125,38,205,255},{85,26,139,255},{171,130,255,255},{159,121,238,255},
{137,104,205,255},{93,71,139,255},{255,225,255,255},{238,210,238,255},{205,181,205,255},{139,123,139,255},{0,0,0,255},{0,0,0,255},{3,3,3,255},{3,3,3,255},{5,5,5,255},{5,5,5,255},
{8,8,8,255},{8,8,8,255},{10,10,10,255},{10,10,10,255},{13,13,13,255},{13,13,13,255},{15,15,15,255},{15,15,15,255},{18,18,18,255},{18,18,18,255},{20,20,20,255},{20,20,20,255},
{23,23,23,255},{23,23,23,255},{26,26,26,255},{26,26,26,255},{28,28,28,255},{28,28,28,255},{31,31,31,255},{31,31,31,255},{33,33,33,255},{33,33,33,255},{36,36,36,255},{36,36,36,255},
{38,38,38,255},{38,38,38,255},{41,41,41,255},{41,41,41,255},{43,43,43,255},{43,43,43,255},{46,46,46,255},{46,46,46,255},{48,48,48,255},{48,48,48,255},{51,51,51,255},{51,51,51,255},
{54,54,54,255},{54,54,54,255},{56,56,56,255},{56,56,56,255},{59,59,59,255},{59,59,59,255},{61,61,61,255},{61,61,61,255},{64,64,64,255},{64,64,64,255},{66,66,66,255},{66,66,66,255},
{69,69,69,255},{69,69,69,255},{71,71,71,255},{71,71,71,255},{74,74,74,255},{74,74,74,255},{77,77,77,255},{77,77,77,255},{79,79,79,255},{79,79,79,255},{82,82,82,255},{82,82,82,255},
{84,84,84,255},{84,84,84,255},{87,87,87,255},{87,87,87,255},{89,89,89,255},{89,89,89,255},{92,92,92,255},{92,92,92,255},{94,94,94,255},{94,94,94,255},{97,97,97,255},{97,97,97,255},
{99,99,99,255},{99,99,99,255},{102,102,102,255},{102,102,102,255},{105,105,105,255},{105,105,105,255},{107,107,107,255},{107,107,107,255},{110,110,110,255},{110,110,110,255},
{112,112,112,255},{112,112,112,255},{115,115,115,255},{115,115,115,255},{117,117,117,255},{117,117,117,255},{120,120,120,255},{120,120,120,255},{122,122,122,255},
{122,122,122,255},{125,125,125,255},{125,125,125,255},{127,127,127,255},{127,127,127,255},{130,130,130,255},{130,130,130,255},{133,133,133,255},{133,133,133,255},
{135,135,135,255},{135,135,135,255},{138,138,138,255},{138,138,138,255},{140,140,140,255},{140,140,140,255},{143,143,143,255},{143,143,143,255},{145,145,145,255},
{145,145,145,255},{148,148,148,255},{148,148,148,255},{150,150,150,255},{150,150,150,255},{153,153,153,255},{153,153,153,255},{156,156,156,255},{156,156,156,255},
{158,158,158,255},{158,158,158,255},{161,161,161,255},{161,161,161,255},{163,163,163,255},{163,163,163,255},{166,166,166,255},{166,166,166,255},{168,168,168,255},
{168,168,168,255},{171,171,171,255},{171,171,171,255},{173,173,173,255},{173,173,173,255},{176,176,176,255},{176,176,176,255},{179,179,179,255},{179,179,179,255},
{181,181,181,255},{181,181,181,255},{184,184,184,255},{184,184,184,255},{186,186,186,255},{186,186,186,255},{189,189,189,255},{189,189,189,255},{191,191,191,255},
{191,191,191,255},{194,194,194,255},{194,194,194,255},{196,196,196,255},{196,196,196,255},{199,199,199,255},{199,199,199,255},{201,201,201,255},{201,201,201,255},
{204,204,204,255},{204,204,204,255},{207,207,207,255},{207,207,207,255},{209,209,209,255},{209,209,209,255},{212,212,212,255},{212,212,212,255},{214,214,214,255},
{214,214,214,255},{217,217,217,255},{217,217,217,255},{219,219,219,255},{219,219,219,255},{222,222,222,255},{222,222,222,255},{224,224,224,255},{224,224,224,255},
{227,227,227,255},{227,227,227,255},{229,229,229,255},{229,229,229,255},{232,232,232,255},{232,232,232,255},{235,235,235,255},{235,235,235,255},{237,237,237,255},
{237,237,237,255},{240,240,240,255},{240,240,240,255},{242,242,242,255},{242,242,242,255},{245,245,245,255},{245,245,245,255},{247,247,247,255},{247,247,247,255},
{250,250,250,255},{250,250,250,255},{252,252,252,255},{252,252,252,255},{255,255,255,255},{255,255,255,255},{169,169,169,255},{169,169,169,255},{169,169,169,255},
{169,169,169,255},{0,0,139,255},{0,0,139,255},{0,139,139,255},{0,139,139,255},{139,0,139,255},{139,0,139,255},{139,0,0,255},{139,0,0,255},{144,238,144,255},{144,238,144,255}};
 
String[] colornames={ "white","red","green","blue","orange",
"snow","ghostwhite","GhostWhite","whitesmoke","WhiteSmoke","gainsboro","floralwhite","FloralWhite","oldlace","OldLace",
"linen","antiquewhite","AntiqueWhite","papayawhip","PapayaWhip","blanchedalmond","BlanchedAlmond","bisque","peachpuff","PeachPuff",
"navajowhite","NavajoWhite","moccasin","cornsilk","ivory","lemonchiffon","LemonChiffon","seashell","honeydew","mintcream","MintCream",
"azure","aliceblue","AliceBlue","lavender","lavenderblush","LavenderBlush","mistyrose","MistyRose","white","black","darkslategray",
"DarkSlateGray","darkslategrey","DarkSlateGrey","dimgray","DimGray","dimgrey","DimGrey","slategray","SlateGray","slategrey",
"SlateGrey","lightslategray","LightSlateGray","lightslategrey","LightSlateGrey","gray","grey","lightgrey","LightGrey","lightgray",
"LightGray","midnightblue","MidnightBlue","navy","navyblue","NavyBlue","cornflowerblue","CornflowerBlue","darkslateblue",
"DarkSlateBlue","slateblue","SlateBlue","mediumslateblue","MediumSlateBlue","lightslateblue","LightSlateBlue","mediumblue",
"MediumBlue","royalblue","RoyalBlue","blue","dodgerblue","DodgerBlue","deepskyblue","DeepSkyBlue","skyblue","SkyBlue",
"lightskyblue","LightSkyBlue","steelblue","SteelBlue","lightsteelblue","LightSteelBlue","lightblue","LightBlue","powderblue",
"PowderBlue","paleturquoise","PaleTurquoise","darkturquoise","DarkTurquoise","mediumturquoise","MediumTurquoise","turquoise",
"cyan","lightcyan","LightCyan","cadetblue","CadetBlue","mediumaquamarine","MediumAquamarine","aquamarine","darkgreen","DarkGreen",
"darkolivegreen","DarkOliveGreen","darkseagreen","DarkSeaGreen","seagreen","SeaGreen","mediumseagreen","MediumSeaGreen",
"lightseagreen","LightSeaGreen","palegreen","PaleGreen","springgreen","SpringGreen","lawngreen","LawnGreen","green","chartreuse",
"mediumspringgreen","MediumSpringGreen","greenyellow","GreenYellow","limegreen","LimeGreen","yellowgreen","YellowGreen",
"forestgreen","ForestGreen","olivedrab","OliveDrab","darkkhaki","DarkKhaki","khaki","palegoldenrod","PaleGoldenrod",
"lightgoldenrodyellow","LightGoldenrodYellow","lightyellow","LightYellow","yellow","gold","lightgoldenrod","LightGoldenrod",
"goldenrod","darkgoldenrod","DarkGoldenrod","rosybrown","RosyBrown","indianred","IndianRed","saddlebrown","SaddleBrown",
"sienna","peru","burlywood","beige","wheat","sandybrown","SandyBrown","tan","chocolate","firebrick","brown","darksalmon",
"DarkSalmon","salmon","lightsalmon","LightSalmon","orange","darkorange","DarkOrange","coral","lightcoral","LightCoral",
"tomato","orangered","OrangeRed","red","hotpink","HotPink","deeppink","DeepPink","pink","lightpink","LightPink","palevioletred",
"PaleVioletRed","maroon","mediumvioletred","MediumVioletRed","violetred","VioletRed","magenta","violet","plum","orchid",
"mediumorchid","MediumOrchid","darkorchid","DarkOrchid","darkviolet","DarkViolet","blueviolet","BlueViolet","purple",
"mediumpurple","MediumPurple","thistle","snow1","snow2","snow3","snow4","seashell1","seashell2","seashell3","seashell4",
"AntiqueWhite1","AntiqueWhite2","AntiqueWhite3","AntiqueWhite4","bisque1","bisque2","bisque3","bisque4","PeachPuff1","PeachPuff2",
"PeachPuff3","PeachPuff4","NavajoWhite1","NavajoWhite2","NavajoWhite3","NavajoWhite4","LemonChiffon1","LemonChiffon2",
"LemonChiffon3","LemonChiffon4","cornsilk1","cornsilk2","cornsilk3","cornsilk4","ivory1","ivory2","ivory3","ivory4","honeydew1",
"honeydew2","honeydew3","honeydew4","LavenderBlush1","LavenderBlush2","LavenderBlush3","LavenderBlush4","MistyRose1","MistyRose2",
"MistyRose3","MistyRose4","azure1","azure2","azure3","azure4","SlateBlue1","SlateBlue2","SlateBlue3","SlateBlue4","RoyalBlue1",
"RoyalBlue2","RoyalBlue3","RoyalBlue4","blue1","blue2","blue3","blue4","DodgerBlue1","DodgerBlue2","DodgerBlue3","DodgerBlue4",
"SteelBlue1","SteelBlue2","SteelBlue3","SteelBlue4","DeepSkyBlue1","DeepSkyBlue2","DeepSkyBlue3","DeepSkyBlue4","SkyBlue1","SkyBlue2",
"SkyBlue3","SkyBlue4","LightSkyBlue1","LightSkyBlue2","LightSkyBlue3","LightSkyBlue4","SlateGray1","SlateGray2","SlateGray3",
"SlateGray4","LightSteelBlue1","LightSteelBlue2","LightSteelBlue3","LightSteelBlue4","LightBlue1","LightBlue2","LightBlue3",
"LightBlue4","LightCyan1","LightCyan2","LightCyan3","LightCyan4","PaleTurquoise1","PaleTurquoise2","PaleTurquoise3","PaleTurquoise4",
"CadetBlue1","CadetBlue2","CadetBlue3","CadetBlue4","turquoise1","turquoise2","turquoise3","turquoise4","cyan1","cyan2","cyan3",
"cyan4","DarkSlateGray1","DarkSlateGray2","DarkSlateGray3","DarkSlateGray4","aquamarine1","aquamarine2","aquamarine3","aquamarine4",
"DarkSeaGreen1","DarkSeaGreen2","DarkSeaGreen3","DarkSeaGreen4","SeaGreen1","SeaGreen2","SeaGreen3","SeaGreen4","PaleGreen1",
"PaleGreen2","PaleGreen3","PaleGreen4","SpringGreen1","SpringGreen2","SpringGreen3","SpringGreen4","green1","green2","green3",
"green4","chartreuse1","chartreuse2","chartreuse3","chartreuse4","OliveDrab1","OliveDrab2","OliveDrab3","OliveDrab4","DarkOliveGreen1",
"DarkOliveGreen2","DarkOliveGreen3","DarkOliveGreen4","khaki1","khaki2","khaki3","khaki4","LightGoldenrod1","LightGoldenrod2",
"LightGoldenrod3","LightGoldenrod4","LightYellow1","LightYellow2","LightYellow3","LightYellow4","yellow1","yellow2","yellow3",
"yellow4","gold1","gold2","gold3","gold4","goldenrod1","goldenrod2","goldenrod3","goldenrod4","DarkGoldenrod1","DarkGoldenrod2",
"DarkGoldenrod3","DarkGoldenrod4","RosyBrown1","RosyBrown2","RosyBrown3","RosyBrown4","IndianRed1","IndianRed2","IndianRed3",
"IndianRed4","sienna1","sienna2","sienna3","sienna4","burlywood1","burlywood2","burlywood3","burlywood4","wheat1","wheat2","wheat3",
"wheat4","tan1","tan2","tan3","tan4","chocolate1","chocolate2","chocolate3","chocolate4","firebrick1","firebrick2","firebrick3",
"firebrick4","brown1","brown2","brown3","brown4","salmon1","salmon2","salmon3","salmon4","LightSalmon1","LightSalmon2","LightSalmon3",
"LightSalmon4","orange1","orange2","orange3","orange4","DarkOrange1","DarkOrange2","DarkOrange3","DarkOrange4","coral1","coral2",
"coral3","coral4","tomato1","tomato2","tomato3","tomato4","OrangeRed1","OrangeRed2","OrangeRed3","OrangeRed4","red1","red2","red3",
"red4","DeepPink1","DeepPink2","DeepPink3","DeepPink4","HotPink1","HotPink2","HotPink3","HotPink4","pink1","pink2","pink3","pink4",
"LightPink1","LightPink2","LightPink3","LightPink4","PaleVioletRed1","PaleVioletRed2","PaleVioletRed3","PaleVioletRed4","maroon1",
"maroon2","maroon3","maroon4","VioletRed1","VioletRed2","VioletRed3","VioletRed4","magenta1","magenta2","magenta3","magenta4","orchid1",
"orchid2","orchid3","orchid4","plum1","plum2","plum3","plum4","MediumOrchid1","MediumOrchid2","MediumOrchid3","MediumOrchid4",
"DarkOrchid1","DarkOrchid2","DarkOrchid3","DarkOrchid4","purple1","purple2","purple3","purple4","MediumPurple1","MediumPurple2",
"MediumPurple3","MediumPurple4","thistle1","thistle2","thistle3","thistle4","gray0","grey0","gray1","grey1","gray2","grey2","gray3",
"grey3","gray4","grey4","gray5","grey5","gray6","grey6","gray7","grey7","gray8","grey8","gray9","grey9","gray10","grey10","gray11",
"grey11","gray12","grey12","gray13","grey13","gray14","grey14","gray15","grey15","gray16","grey16","gray17","grey17","gray18","grey18",
"gray19","grey19","gray20","grey20","gray21","grey21","gray22","grey22","gray23","grey23","gray24","grey24","gray25","grey25","gray26",
"grey26","gray27","grey27","gray28","grey28","gray29","grey29","gray30","grey30","gray31","grey31","gray32","grey32","gray33","grey33",
"gray34","grey34","gray35","grey35","gray36","grey36","gray37","grey37","gray38","grey38","gray39","grey39","gray40","grey40","gray41",
"grey41","gray42","grey42","gray43","grey43","gray44","grey44","gray45","grey45","gray46","grey46","gray47","grey47","gray48","grey48",
"gray49","grey49","gray50","grey50","gray51","grey51","gray52","grey52","gray53","grey53","gray54","grey54","gray55","grey55","gray56",
"grey56","gray57","grey57","gray58","grey58","gray59","grey59","gray60","grey60","gray61","grey61","gray62","grey62","gray63","grey63",
"gray64","grey64","gray65","grey65","gray66","grey66","gray67","grey67","gray68","grey68","gray69","grey69","gray70","grey70","gray71",
"grey71","gray72","grey72","gray73","grey73","gray74","grey74","gray75","grey75","gray76","grey76","gray77","grey77","gray78","grey78",
"gray79","grey79","gray80","grey80","gray81","grey81","gray82","grey82","gray83","grey83","gray84","grey84","gray85","grey85","gray86",
"grey86","gray87","grey87","gray88","grey88","gray89","grey89","gray90","grey90","gray91","grey91","gray92","grey92","gray93","grey93",
"gray94","grey94","gray95","grey95","gray96","grey96","gray97","grey97","gray98","grey98","gray99","grey99","gray100","grey100",
"darkgrey","DarkGrey","darkgray","DarkGray","darkblue","DarkBlue","darkcyan","DarkCyan","darkmagenta","DarkMagenta","darkred",
"DarkRed","lightgreen","LightGreen"};
 
}
 
 
class FlyArc {
int xc,yc,w,h;
int linewidth;
int a1,a2;
Color color;
boolean filled,dashed;
public FlyArc( int xc , int yc, int w, int h , int a1, int a2,
Color color, int linewidth , boolean filled, boolean dashed )
{
this.xc = xc;
this.yc = yc;
this.h = h;
this.w = w;
this.a1 = a1;
this.a2 = a2;
this.color = color;
this.linewidth = linewidth;
this.filled = filled;
this.dashed = dashed;
}
public int getXc() { return xc; }
public int getYc() { return yc; }
public int getH() { return h; }
public int getW() { return w; }
public int getLineWidth() { return linewidth;}
public int getAngle1() { return a1;}
public int getAngle2() { return a2;}
public Color getColor() { return color;}
public boolean getFilled(){ return filled;}
public boolean getDashed(){ return dashed;}
 
}
 
class FlyCircle {
int xc,yc,w,h;
Color color;
int linewidth;
boolean filled;
boolean dashed;
public FlyCircle(int xc, int yc , int w, int h, Color color , int linewidth , boolean filled , boolean dashed ){
this.xc = xc;
this.yc = yc;
this.h = h;
this.w = w;
this.color = color;
this.linewidth = linewidth;
this.filled = filled;
}
public int getXc() { return xc; }
public int getYc() { return yc; }
public int getH() { return h; }
public int getW() { return w; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
public boolean getFilled(){ return filled;}
public boolean getDashed(){ return dashed;}
}
 
class FlyLine {
int x1,y1,x2,y2;
Color color;
int linewidth;
boolean dashed;
public FlyLine(int x1, int y1 , int x2 , int y2, Color color , int linewidth, boolean dashed ){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
this.linewidth = linewidth;
this.dashed = dashed;
}
public int getX1() { return x1; }
public int getY1() { return y1; }
public int getX2() { return x2; }
public int getY2() { return y2; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
public boolean getDashed(){ return dashed;}
}
 
class FlyRect{
int x,y,w,h;
Color color;
int linewidth;
boolean filled;
boolean dashed;
public FlyRect(int x,int y ,int w ,int h, Color color , int linewidth , boolean filled, boolean dashed ){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.linewidth = linewidth;
this.filled = filled;
this.dashed = dashed;
}
public int getX() { return x; }
public int getY() { return y; }
public int getW() { return w; }
public int getH() { return h; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
public boolean getFilled(){ return filled;}
public boolean getDashed(){ return dashed;}
}
 
 
class FlyParallel {
int x1[];
int y1[];
int x2[];
int y2[];
Color color;
int linewidth;
boolean dashed;
public FlyParallel(int x1[],int y1[] , int x2[],int y2[] , Color color , int linewidth , boolean dashed ){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
this.linewidth = linewidth;
this.dashed = dashed;
}
public int[] getX1() { return x1; }
public int[] getY1() { return y1; }
public int[] getX2() { return x2; }
public int[] getY2() { return y2; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
public boolean getDashed(){ return dashed;}
}
 
class FlyPoly {
int x[];
int y[];
Color color;
int linewidth;
boolean filled;
boolean dashed;
public FlyPoly(int x[],int y[] , Color color , int linewidth , boolean filled, boolean dashed ){
this.x = x;
this.y = y;
this.color = color;
this.linewidth = linewidth;
this.filled = filled;
this.dashed = dashed;
}
public int[] getX() { return x; }
public int[] getY() { return y; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
public boolean getFilled(){ return filled;}
public boolean getDashed(){ return dashed;}
}
 
class FlyLatex {
int x;
int y;
BufferedImage latex;
public FlyLatex(int x,int y ,BufferedImage latex ){
this.x = x;
this.y = y;
this.latex = latex;
}
public int getX() { return x; }
public int getY() { return y; }
public BufferedImage getLatex() { return latex;}
}
 
class FlyPlot{
int x[];
int y[];
Color color;
int linewidth;
boolean filled;
boolean dashed;
public FlyPlot(int x[],int y[] , Color color , int linewidth , boolean filled, boolean dashed ){
this.x = x;
this.y = y;
this.color = color;
this.linewidth = linewidth;
this.filled = filled;
this.dashed = dashed;
}
public int[] getX() { return x; }
public int[] getY() { return y; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
public boolean getFilled(){ return filled;}
public boolean getDashed(){ return dashed;}
}
 
 
class FlyArrow {
int x[];
int y[];
Color color;
int linewidth;
boolean filled;
boolean dashed;
public FlyArrow(int x[],int y[] , Color color , int linewidth , boolean filled , boolean dashed){
this.x = x;
this.y = y;
this.color = color;
this.linewidth = linewidth;
this.filled = filled;
this.dashed = dashed;
}
public int[] getX() { return x; }
public int[] getY() { return y; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
public boolean getFilled(){ return filled;}
public boolean getDashed(){ return dashed;}
}
 
class FlyPoints {
int x[];
int y[];
Color color;
int linewidth;
public FlyPoints(int x[],int y[] , Color color , int linewidth){
this.x = x;
this.y = y;
this.color = color;
this.linewidth = linewidth;
}
public int[] getX() { return x; }
public int[] getY() { return y; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
}
 
class FlyXlabel {
String Xlabel;
Font font;
Color color;
public FlyXlabel(String Xlabel, Font font , Color color ){
this.Xlabel = Xlabel;
this.font = font;
this.color = color;
}
public String getXlabel() { return Xlabel; }
public Font getFont() { return font; }
public Color getColor() { return color; }
}
 
class FlyYlabel {
String Ylabel;
Font font;
Color color;
public FlyYlabel(String Ylabel, Font font , Color color ){
this.Ylabel = Ylabel;
this.font = font;
this.color = color;
}
public String getYlabel() { return Ylabel; }
public Font getFont() { return font; }
public Color getColor() { return color; }
}
 
 
class FlyXscale {
int x[];
String Xlabel[];
boolean use_xscale;
Font font;
Color color;
int linewidth;
public FlyXscale(int x[], String Xlabel[], boolean use_xscale, Font font , Color color , int linewidth){
this.x = x;
this.Xlabel = Xlabel;
this.use_xscale = use_xscale;
this.font = font;
this.color = color;
this.linewidth = linewidth;
}
public int[] getX() { return x; }
public boolean use_xscale() { return use_xscale; }
public String[] getXlabel() { return Xlabel; }
public Font getFont() { return font; }
public Color getColor() { return color; }
public int getLineWidth() { return linewidth; }
}
 
class FlyYscale {
int y[];
String Ylabel[];
boolean use_yscale;
Font font;
Color color;
int linewidth;
 
public FlyYscale( int y[], String Ylabel[],boolean use_yscale,Font font , Color color , int linewidth){
this.y = y;
this.Ylabel = Ylabel;
this.use_yscale = use_yscale;
this.font = font;
this.color = color;
this.linewidth = linewidth;
}
public int[] getY() { return y; }
public boolean use_yscale() { return use_yscale; }
public String[] getYlabel() { return Ylabel; }
public Font getFont(){return font;}
public Color getColor(){return color;}
public int getLineWidth() { return linewidth; }
}
 
class FlyInput {
int x;
int y;
int xsize;
int ysize;
int index;
Font font;
Color bgcolor;
Color fgcolor;
String value;
boolean editable;
public FlyInput( int x, int y, int xsize, int ysize, Font font , Color bgcolor, Color fgcolor, int index,boolean editable,String value ){
this.x = x;
this.y = y;
this.xsize = xsize;
this.ysize = ysize;
this.font = font;
this.bgcolor = bgcolor;
this.fgcolor = fgcolor;
this.index = index;
this.editable = editable;
this.value = value;
}
public int getX() { return x; }
public int getY() { return y; }
public int getXsize() { return xsize; }
public int getYsize() { return ysize; }
public Font getFont(){return font;}
public Color getBgcolor(){return bgcolor;}
public Color getFgcolor(){return fgcolor;}
public int getIndex(){return index; }
public boolean getEditable(){return editable;}
public String getValue(){return value;}
}
 
class FlyPoint {
int x;
int y;
Color color;
int linewidth;
Font font;
public FlyPoint(int x,int y , Color color , int linewidth){
this.x = x;
this.y = y;
this.color = color;
this.linewidth = linewidth;
}
public int getX() { return x; }
public int getY() { return y; }
public int getLineWidth() { return linewidth; }
public Color getColor(){ return color;}
public Font getFont(){ return font;}
}
 
class FlyGrid {
int x_major[];
int x_minor[];
int y_major[];
int y_minor[];
Color color_major;
Color color_minor;
int linewidth_major;
int linewidth_minor;
boolean dashed;
public FlyGrid(int x_major[] , int y_major[] , int x_minor[] , int y_minor[] ,
Color color_major , Color color_minor , int linewidth_major , int linewidth_minor, boolean dashed ){
this.x_minor = x_minor;
this.y_minor = y_minor;
this.x_major = x_major;
this.y_major = y_major;
this.color_major = color_major;
this.color_minor = color_minor;
this.linewidth_major = linewidth_major;
this.linewidth_minor = linewidth_minor;
this.dashed = dashed;
}
public int[] getX_major() { return x_major; }
public int[] getY_major() { return y_major; }
public int[] getX_minor() { return x_minor; }
public int[] getY_minor() { return y_minor; }
public int getLineWidth_major() { return linewidth_major; }
public int getLineWidth_minor() { return linewidth_minor; }
public Color getColor_major(){ return color_major;}
public Color getColor_minor(){ return color_minor;}
public boolean getDashed(){ return dashed;}
}
 
class FlyImage {
int x;
int y;
BufferedImage image;
public FlyImage(int x,int y , BufferedImage image ){
this.x = x;
this.y = y;
this.image = image;
}
public int getX() { return x; }
public int getY() { return y; }
public BufferedImage getImage(){ return image;}
}
 
class FlyText {
int x;
int y;
int angle;
Font font;
String txt;
Color color;
public FlyText(int x,int y , int angle , Font font, String txt, Color color ){
this.x = x;
this.y = y;
this.angle = angle;
this.color = color;
this.font = font;
this.txt = txt;
}
public int getX() { return x; }
public int getY() { return y; }
public int getRotation() { return angle; }
public Font getFont() { return font; }
public Color getColor(){ return color;}
public String getTXT(){ return txt;}
}
 
class FlyReply{
String reply;
int x;
int y;
public FlyReply(String reply, int x, int y){
this.reply = reply;
this.x = x;
this.y = y;
}
public String getReply(){return reply;}
public int getX(){return x;}
public int getY(){return y;}
}
 
class FlyApplet_panel extends JPanel implements MouseListener, MouseMotionListener {
public static final int CURVE=0, RECT=1, CIRCLE=2, LINES=3, LINE=4,
SLINE=5,SEG=6,POLY=7,POINTS=8,VEC=9,NULL=-1;
public static int ctype;
static int ll=4;
Image bg;
Vector lines=new Vector(16384);
int x1,y1;
int x2,y2;
int radius;
double Radius;//in coords
int drag;
int st;
double xmin,ymin,xmax,ymax,precision;
int xsize,ysize,linewidth;
boolean dashed,use_coords,stopdrawing;
boolean display_coords = true;
boolean cross = true;
public static boolean filled = false;
public static String coordinates=" ";
Font font;
Color fgcolor;
Color bgcolor;
public static FontMetrics fm;
 
public FlyApplet_panel(Color Bgcolor,Color Fgcolor, Image gotbg , int LineWidth , int Xsize ,int Ysize, boolean Dashed,
boolean Use_Coords , double Precision , double Xmin,double Ymin,double Xmax,double Ymax,Font Font, boolean Cross ){
bgcolor=Bgcolor;
fgcolor =Fgcolor;
setBackground(bgcolor);
setForeground(fgcolor);
bg=gotbg;
dashed = Dashed;
linewidth = LineWidth;
st=0;
xmin=Xmin;
xmax=Xmax;
ymin=Ymin;
ymax=Ymax;
font = Font;
xsize=Xsize;
ysize=Ysize;
use_coords = Use_Coords;
cross = Cross;
precision = Precision;
addMouseMotionListener(this);
addMouseListener(this);
}
public String points2string(String rep) {
StringBuffer buf=new StringBuffer(16384);
buf.append(rep);
switch(ctype) {
case NULL:break;
case POLY:
case POINTS:
case LINES:
case CURVE: {
int i, np;
Point p=null;
np=lines.size();
for(i=0;i<np;i++) {
p=(Point)lines.elementAt(i);
buf.append(p.x).append(",").append(p.y).append(";");
}
break;
}
case SLINE:
case LINE:
case SEG:
case VEC:
case RECT: {
if(st>0) {
buf.append(x1).append(",").append(y1).append(",").append(x2).append(",").append(y2);
}
break;
}
case CIRCLE: {
if(st>0) {
buf.append(x1).append(",").append(y1).append(",").append(radius);
}
break;
}
}
return buf.toString();
}
 
public String Coords2String(){// returns values in the coordsystem xrang/yrange and rounded to "precision"
StringBuffer buf=new StringBuffer(16384);
// if(lines.size() == 0){return "error";}
// else{
if( (ctype == 1 || ctype == 4 || ctype == 5 || ctype == 6 || ctype == 9 ) && st>0){
buf.append(px2x(x1)).append(",").append(py2y(y1)).append(",").append(px2x(x2)).append(",").append(py2y(y2));
}
else
if( ctype == 2 && st>0 ){
buf.append(px2x(x1)).append(",").append(py2y(y1)).append(",").append((Math.round(precision*Radius))/precision);
}
else{
int i, np;
Point p=null;
np=lines.size();
for(i=0;i<np;i++){
p=(Point)lines.elementAt(i);
if(i != 0){
buf.append(",").append(px2x(p.x)).append(",").append(py2y(p.y));
}else{
buf.append(px2x(p.x)).append(",").append(py2y(p.y));// single point
}
}
}
// }
return buf.toString();
}
public void retry() {
lines.removeAllElements();
st=0; repaint();
}
 
public void mouseDragged(MouseEvent e) {
int t=lines.size();
int dr;
e.consume();
switch(ctype) {
case NULL:break;
case CURVE: {
if(t<2000) {
x1=e.getX(); y1=e.getY();
lines.addElement(new Point(x1, y1));
repaint();
}
st=2; return;
}
default: {
dr=drag; mouseMoved(e); drag=dr+1;
return;
}
}
}
 
public void mouseMoved(MouseEvent e) {
e.consume(); drag=0;
if(use_coords){
double mx = px2x(e.getX());
double my = py2y(e.getY());
if(ctype == 2){
coordinates = "(" + mx + ":" + my + ")" + " R="+Radius;
}else{coordinates = "(" + mx + ":" + my + ")";}
repaint();
}
switch(ctype) {
case NULL:break;
case POLY:{if(stopdrawing){mouseExited(e);return;}}
case POINTS:
case LINES:if(st==1){mouseClicked(e);}return;
case CURVE: {
if(st==0) return; else st=1;
x2=e.getX(); y2=e.getY(); break;
}
case CIRCLE:
case SLINE:
case LINE:
case SEG:
case VEC:
case RECT: {
if(st!=1) return;
x2=e.getX(); y2=e.getY();
radius=(int) Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
Radius=(double) (Math.round(precision*(Math.sqrt((px2x(x2)-px2x(x1))*(px2x(x2)-px2x(x1))+(py2y(y2)-py2y(y1))*(py2y(y2)-py2y(y1))))))/precision;
break;
}
default:return;
}
if(ctype!=POINTS) repaint();
}
 
public void mousePressed(MouseEvent e) {
mouseClicked(e);
e.consume();
switch(ctype) {
case NULL:break;
case CURVE: {
mouseClicked(e);
if(st>0) return;
x1=e.getX(); y1=e.getY(); x2=x1; y2=y1;
lines.removeAllElements();
lines.addElement(new Point(x1,y1));
repaint(); st=2;
return;
}
case POLY:{if(stopdrawing){mouseExited(e);return;}}
case POINTS:
case LINES: {
x2=e.getX(); y2=e.getY();
if(st==0) lines.removeAllElements();
lines.addElement(new Point(x2,y2));
st=1; x1=x2; y1=y2; repaint(); return;
}
case CIRCLE:
case SLINE:
case LINE:
case SEG:
case VEC:
case RECT: {
x2=e.getX(); y2=e.getY();
switch(st) {
case 2:
case 0: x1=x2; y1=y2; radius=0; st=1; repaint(); return;
case 1: {
radius=(int) Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
//Radius=(double) Math.sqrt((px2x(x2)-px2x(x1))*(px2x(x2)-px2x(x1))+(py2y(y2)-py2y(y1))*(py2y(y2)-py2y(y1)));
st=2; return;
}
}
break;
}
default: return;
}
}
 
public void mouseReleased(MouseEvent e) {
e.consume();
switch(ctype) {
case NULL:break;
case CURVE: {
if(st==2) return;
x2=e.getX(); y2=e.getY();
if(st==0) lines.removeAllElements();
lines.addElement(new Point(x2,y2));
st=1; x1=x2; y1=y2;
return;
}
case POINTS: return;
default: {
if(st>0 && drag>=8) mousePressed(e);
return;
}
}
}
 
public void mouseEntered(MouseEvent e) {
display_coords=true;
}
 
public void mouseExited(MouseEvent e) {
display_coords=false;if(use_coords){repaint();}
if(ctype!=CURVE && ctype!=LINES && ctype!=POLY) return;
e.consume();
x2=x1; y2=y1;
repaint();
}
 
public void mouseClicked(MouseEvent e){
if( e.getButton() == MouseEvent.BUTTON3){//right mouse click removes stuff
stopdrawing = false;
switch(ctype) {
case NULL:break;
case CURVE:
case POLY:if(lines.size()>0){RemoveRange(lines.size()-1,lines.size());x1=e.getX();y1=e.getY();repaint();}return;
case POINTS:RemoveElement(e.getX(),e.getY());repaint();return;
case LINES:if(lines.size()>0){RemoveRange(lines.size()-1,lines.size());x1=e.getX();y1=e.getY();repaint();}return;
case CIRCLE:RemoveElement(e.getX(),e.getY());repaint();return;
case SLINE:RemoveElement(e.getX(),e.getY());repaint();return;
case LINE:RemoveElement(e.getX(),e.getY());repaint();return;
case SEG:RemoveElement(e.getX(),e.getY());repaint();return;
case VEC:RemoveElement(e.getX(),e.getY());repaint();return;
case RECT:RemoveElement(e.getX(),e.getY());repaint();return;
default : return;
}
}
}
public void repaint(Graphics g){
update(g);
}
public void update(Graphics g){
paintComponent(g);
}
 
public void RemoveRange(int i,int ii){
if(i == 0){lines.removeAllElements();}
else{
for(int p=i;p<ii;p++){
lines.remove(p);
}
}
}
public void RemoveElement(int x,int y){
Point p=null;
int np=lines.size();
int marge=2*linewidth;
for(int i=0;i<np;i++){
p=(Point)lines.elementAt(i);
if(p.x-marge < x && p.x+marge > x && p.y-marge < y && p.y+marge > y){
lines.remove(i);
break;
}
}
}
public void paintComponent(Graphics g1){
g1.clearRect(0,0,xsize,ysize);
Graphics2D g = (Graphics2D) g1;
if(bg!=null) g.drawImage(bg,0,0,this);
if(dashed){
g.setStroke(new BasicStroke(linewidth,BasicStroke.JOIN_ROUND,BasicStroke.JOIN_BEVEL,1,new float[] {9},0));
}else{
g.setStroke( new BasicStroke(linewidth));
}
int np=lines.size();
Point pp;
if(use_coords && display_coords){
g.setFont(font);
g.setColor(Color.black);
g.drawString(coordinates,0,20);
g.setColor(fgcolor);
}
switch(ctype) {
case POINTS: {
if(np>0) for (int i=0; i < np; i++)
pointPaint(g,(Point)lines.elementAt(i),cross);
break;
}
case POLY:
case CURVE:
case LINES: {
if(np>0) {
pp=(Point)lines.elementAt(0);
for (int i=1; i < np; i++) {
Point p=(Point)lines.elementAt(i);
g.drawLine(pp.x, pp.y, p.x, p.y);
pp=p;
}
if (st==1) g.drawLine(x1, y1, x2, y2);
}
if(ctype==POLY && np>1) {
// filled
if(!filled){
Point p1=(Point)lines.elementAt(0);
Point p2=(Point)lines.elementAt(np-1);
if(st==0){ g.drawLine(p1.x,p1.y,p2.x,p2.y); } else { g.drawLine(p1.x,p1.y,x2,y2);}
}
else
{
int xpoly[] = new int[np];
int ypoly[] = new int[np];
for(int i=0;i<np;i++){
Point p=(Point)lines.elementAt(i);
xpoly[i] = p.x;
ypoly[i] = p.y;
}
g.fillPolygon(xpoly,ypoly,np);
}
}
break;
}
case SEG:
case VEC:
case SLINE:
case LINE:
case RECT: {
if(st>0) {
int xx1,yy1,xx2,yy2;
int X1,Y1,X2,Y2,max;
xx1=Math.min(x1,x2); yy1=Math.min(y1,y2);
xx2=Math.max(x1,x2); yy2=Math.max(y1,y2);
max=Math.max(Math.abs(x2-x1),Math.abs(y2-y1));
if(max<10) max=10;
max=500/max+1;
switch(ctype) {
case RECT:if(!filled){g.drawRect(xx1,yy1,xx2-xx1,yy2-yy1);}else{g.fillRect(xx1,yy1,xx2-xx1,yy2-yy1);} break;
case SLINE: {
g.fillOval(x1-2,y1-2,4,4);
g.drawLine(x1,y1,max*x2-(max-1)*x1,max*y2-(max-1)*y1); break;
}
case LINE: {
g.fillOval(x1-2,y1-2,4,4);
g.fillOval(x2-2,y2-2,4,4);
g.drawLine(max*x1-(max-1)*x2,max*y1-(max-1)*y2,
max*x2-(max-1)*x1,max*y2-(max-1)*y1); break;
}
case SEG: g.drawLine(x1,y1,x2,y2); break;
case VEC: {
g.drawLine(x1,y1,x2,y2);
if(radius > 5) { /* arrow head */
double dx,dy,dd[];
int xx[], yy[];
dd=new double[6];
xx=new int[3];
yy=new int[3];
//double l=12;
double l=linewidth;
double fat=linewidth*0.3;
xx[0]=x2;yy[0]=y2;
dx=x1-x2; dy=y1-y2;
dd[0]=l*dx/radius; dd[1]=l*dy/radius;
dd[2]=dd[0]+dd[1]*fat; dd[3]=dd[1]-dd[0]*fat;
dd[4]=dd[0]-dd[1]*fat; dd[5]=dd[1]+dd[0]*fat;
xx[1]=(int) (dd[2]+xx[0]);
yy[1]=(int) (dd[3]+yy[0]);
xx[2]=(int) (dd[4]+xx[0]);
yy[2]=(int) (dd[5]+yy[0]);
g.fillPolygon(xx,yy,3);
}
break;
}
}
}
break;
}
case CIRCLE: {
if(st>0) {
pointPaint(g,new Point(x1,y1),cross);
if(!filled){
g.drawOval(x1-radius,y1-radius,radius*2,radius*2);
}else{g.fillOval(x1-radius,y1-radius,radius*2,radius*2);}
}
break;
}
}
}
void pointPaint(Graphics g, Point p, boolean cross) {
if(cross){
g.drawLine(p.x-ll,p.y+ll,p.x+ll,p.y-ll);
g.drawLine(p.x+ll,p.y+ll,p.x-ll,p.y-ll);
}else{
g.fillOval(p.x - linewidth,p.y - linewidth , 2*linewidth, 2*linewidth);
}
}
 
public double px2x(int px){ //pixel to x-coords
double X = px*(xmax - xmin)/xsize + xmin;
X = (Math.round(precision*(X)))/precision;
return X;
}
public double py2y(int py){ // pixel to x-coords
double Y =ymax - py*(ymax - ymin)/ysize;
Y = (Math.round(precision*(Y)))/precision;
return Y;
}
}// end FlyApplet_panel
 
 
class FlyApplet_controls extends Panel implements ActionListener {
FlyApplet ci;
FlyApplet_panel targ;
Button retry, ok;
public FlyApplet_controls(FlyApplet_panel pan, FlyApplet cci) {
this.ci=cci;
targ=pan;
setLayout(new GridLayout());
setBackground(Color.white);
retry=new Button(FlyApplet.retry);
retry.addActionListener(this);
ok=new Button(FlyApplet.prompt);
ok.addActionListener(this);
add(retry); add(ok);
}
 
public void actionPerformed(ActionEvent e) {
Object src=e.getSource();
if(src == retry) targ.retry();
if(src == ok) ci.replyback();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/BoxC.java
0,0 → 1,24
package atp;
 
 
class BoxC
{
 
public BoxC(int i, int j, int k)
{
dx = i;
dy_pos = j;
dy_neg = k;
}
 
public BoxC()
{
dx = 0;
dy_pos = 0;
dy_neg = 0;
}
 
public int dx;
public int dy_pos;
public int dy_neg;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/SymbolLoader.java
0,0 → 1,154
package atp;
 
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.URL;
import java.util.Hashtable;
import java.util.StringTokenizer;
 
// Referenced classes of package atp:
// ColorMaskFilter
 
class SymbolLoader
{
 
public SymbolLoader()
{
fontdesH = new Hashtable(189);
}
 
public Image getImage(boolean flag, boolean flag1, String s, Graphics g, Applet applet)
{
StringTokenizer stringtokenizer = new StringTokenizer(s, "/");
String s1 = stringtokenizer.nextToken();
s1 = stringtokenizer.nextToken().substring(5);
String s2 = stringtokenizer.nextToken();
int i = -1;
boolean flag2 = true;
do
{
if(!flag2)
break;
if(fontsizes[++i].equals(s1))
flag2 = false;
if(i == 4)
flag2 = false;
} while(true);
if(imageSources[i] == null)
{
imageSources[i] = getBigImage(flag, flag1, (new StringBuilder()).append("Fonts").append(s1).append(".gif").toString(), applet);
String s3 = (new StringBuilder()).append("Des").append(s1).append(".gif").toString();
BufferedInputStream bufferedinputstream = null;
try
{
if(kLocalFonts)
{
InputStream inputstream = getClass().getResourceAsStream(s3);
bufferedinputstream = new BufferedInputStream(getClass().getResourceAsStream(s3));
} else
if((!flag) & (!flag1))
bufferedinputstream = new BufferedInputStream((new URL(s3)).openStream());
else
if(flag)
bufferedinputstream = new BufferedInputStream((new URL(applet.getCodeBase(), s3)).openStream());
else
try
{
bufferedinputstream = new BufferedInputStream(getClass().getResource(s3).openStream());
}
catch(Exception exception) { }
ObjectInputStream objectinputstream = new ObjectInputStream(bufferedinputstream);
int j = objectinputstream.readInt();
for(int k = 0; k < j; k++)
{
String s4 = (String)objectinputstream.readObject();
fontdesH.put((new StringBuilder()).append(s1).append(s4).toString(), new Rectangle((Rectangle)objectinputstream.readObject()));
}
 
bufferedinputstream.close();
}
catch(Exception exception1)
{
System.out.println(exception1.toString());
imageSources[i] = null;
}
}
Image image = null;
if(imageSources[i] != null)
{
Rectangle rectangle = (Rectangle)(Rectangle)fontdesH.get((new StringBuilder()).append(s1).append(s2).toString());
image = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(new FilteredImageSource(imageSources[i], new CropImageFilter(rectangle.x, rectangle.y, rectangle.width, rectangle.height)), new ColorMaskFilter(g.getColor())));
}
return image;
}
 
public ImageProducer getBigImage(boolean flag, boolean flag1, String s, Applet applet)
{
ImageProducer imageproducer = null;
if(kLocalFonts)
imageproducer = getLocalImageSource(s);
if(imageproducer == null)
{
kLocalFonts = false;
if((!flag) & (!flag1))
imageproducer = Toolkit.getDefaultToolkit().getImage(s).getSource();
else
if(flag)
imageproducer = applet.getImage(applet.getCodeBase(), s).getSource();
else
try
{
URL url = getClass().getResource(s);
imageproducer = (ImageProducer)url.getContent();
}
catch(Exception exception) { }
}
return imageproducer;
}
 
ImageProducer getLocalImageSource(String s)
{
ImageProducer imageproducer = null;
try
{
InputStream inputstream = getClass().getResourceAsStream(s);
int i = inputstream.available();
byte abyte0[] = new byte[i];
int j = 0;
int k = 0;
do
{
if(k == -1)
break;
k = inputstream.read(abyte0, j, i);
if(k != -1)
{
j += k;
i = inputstream.available();
int l = j + i;
if(l > abyte0.length)
{
byte abyte1[] = (byte[])(byte[])abyte0.clone();
abyte0 = new byte[l];
System.arraycopy(abyte1, 0, abyte0, 0, j);
}
}
} while(i != 0);
imageproducer = Toolkit.getDefaultToolkit().createImage(abyte0).getSource();
}
catch(Exception exception) { }
return imageproducer;
}
 
private ImageProducer imageSources[] = {
null, null, null, null, null
};
private String fontsizes[] = {
"8", "10", "12", "14", "18"
};
private Hashtable fontdesH;
private static boolean kLocalFonts = true;
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/ColorMaskFilter.java
0,0 → 1,38
package atp;
 
import java.awt.Color;
import java.awt.image.RGBImageFilter;
 
class ColorMaskFilter extends RGBImageFilter
{
 
ColorMaskFilter(Color color1)
{
maskORinvert = false;
color = color1;
maskORinvert = false;
canFilterIndexColorModel = true;
}
 
ColorMaskFilter(Color color1, boolean flag)
{
maskORinvert = false;
color = color1;
maskORinvert = flag;
canFilterIndexColorModel = true;
}
 
public int filterRGB(int i, int j, int k)
{
if(maskORinvert)
return 0x1fff0000;
int l = k & 0xffffff;
if(l == 0xffffff)
return l;
else
return 0xff000000 | color.getRGB();
}
 
Color color;
boolean maskORinvert;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Des10.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Des12.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Des14.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Fonts8.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/EqToken.java
0,0 → 1,69
package atp;
 
 
class EqToken
{
 
public EqToken(int i, String s)
{
typ = i;
stringS = s;
}
 
public EqToken(int i)
{
typ = i;
stringS = "";
}
 
public EqToken()
{
typ = 0;
stringS = "";
}
 
public int typ;
public String stringS;
public static final int EOF = 0;
public static final int Id = 1;
public static final int Num = 2;
public static final int BeginSym = 3;
public static final int EndSym = 4;
public static final int ANGLE = 5;
public static final int AndSym = 7;
public static final int DBackSlash = 8;
public static final int FUNC = 9;
public static final int SUP = 10;
public static final int SUB = 11;
public static final int FRAC = 12;
public static final int SQRT = 13;
public static final int VEC = 14;
public static final int ARRAY = 15;
public static final int LEFT = 16;
public static final int RIGHT = 17;
public static final int SYMBOP = 18;
public static final int SYMBOPD = 19;
public static final int SYMBOLBIG = 20;
public static final int ACCENT = 22;
public static final int LIM = 24;
public static final int SpaceChar = 25;
public static final int BEGIN = 50;
public static final int END = 51;
public static final int Null = 99;
public static final int Invalid = 100;
public static final int Op = 108;
public static final int Paren = 109;
public static final int NOT = 110;
public static final int SPACE = 113;
public static final int CHOOSE = 114;
public static final int ATOP = 115;
public static final int OverLINE = 116;
public static final int UnderLINE = 117;
public static final int OverBRACE = 118;
public static final int UnderBRACE = 119;
public static final int STACKREL = 120;
public static final int FGColor = 121;
public static final int BGColor = 122;
public static final int FBOX = 123;
public static final int MBOX = 124;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Des18.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Fonts10.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/EqScanner.java
0,0 → 1,840
package atp;
 
import java.io.PrintStream;
import java.util.Vector;
 
// Referenced classes of package atp:
// EqToken
 
class EqScanner
{
 
public EqScanner(String s)
{
EOF = false;
TokenV = new Vector(50, 50);
selectB = false;
collectB = false;
selectCount1 = 0;
selectCount2 = 0;
selectSB = new StringBuffer("");
token = new EqToken(99);
setEquation(s);
}
 
public String getSelectedArea(int i, int j)
{
selectCount1 = Math.min(i, j);
selectCount2 = Math.max(i, j);
selectB = true;
selectSB = new StringBuffer("");
setEquation(equation);
selectB = false;
return selectSB.toString();
}
 
public void setEquation(String s)
{
equation = s;
int i = 0;
boolean flag = false;
boolean flag1 = false;
EOF = false;
countT = -1;
count = -1;
TokenV.removeAllElements();
advance();
do
{
if(EOF)
break;
countT++;
if(selectB && countT == selectCount1)
collectB = true;
TokenV.addElement(ScanNextToken());
if(selectB && countT == selectCount2)
collectB = false;
} while(true);
countT = -1;
for(; i < TokenV.size(); i++)
{
if(((EqToken)TokenV.elementAt(i)).typ == 114)
{
int k = i - 1;
int j1 = 0;
do
{
if(k <= 0)
break;
if(((EqToken)TokenV.elementAt(k)).typ == 4)
j1--;
else
if(((EqToken)TokenV.elementAt(k)).typ == 3)
j1++;
if(j1 == 1)
break;
k--;
} while(true);
int i2 = i + 1;
j1 = 0;
do
{
if(i2 >= TokenV.size())
break;
if(((EqToken)TokenV.elementAt(i2)).typ == 4)
j1++;
else
if(((EqToken)TokenV.elementAt(i2)).typ == 3)
j1--;
if(j1 == 1)
break;
i2++;
} while(true);
if(j1 == 1 && k >= 0)
{
TokenV.insertElementAt(new EqToken(109, ")"), i2 + 1);
TokenV.insertElementAt(new EqToken(17), i2 + 1);
TokenV.setElementAt(new EqToken(4), i);
TokenV.insertElementAt(new EqToken(3), i + 1);
TokenV.insertElementAt(new EqToken(115), k);
TokenV.insertElementAt(new EqToken(109, "("), k);
TokenV.insertElementAt(new EqToken(16), k);
i += 4;
}
continue;
}
if(((EqToken)TokenV.elementAt(i)).typ != 115)
continue;
int l = i - 1;
int k1 = 0;
do
{
if(l <= 0)
break;
if(((EqToken)TokenV.elementAt(l)).typ == 4)
k1--;
else
if(((EqToken)TokenV.elementAt(l)).typ == 3)
k1++;
if(k1 == 1)
break;
l--;
} while(true);
if(l >= 0)
{
TokenV.setElementAt(new EqToken(4), i);
TokenV.insertElementAt(new EqToken(3), i + 1);
TokenV.insertElementAt(new EqToken(115), l);
i += 2;
}
}
 
for(int j = 0; j < TokenV.size() - 2; j++)
{
if(((EqToken)TokenV.elementAt(j)).typ != 13 || ((EqToken)TokenV.elementAt(j + 1)).typ != 109)
continue;
int i1 = j + 2;
int l1 = 0;
int j2 = 1;
for(; i1 < TokenV.size(); i1++)
{
if(((EqToken)TokenV.elementAt(i1)).typ == 4)
l1--;
else
if(((EqToken)TokenV.elementAt(i1)).typ == 3)
l1++;
if(l1 != 0)
continue;
if(((EqToken)TokenV.elementAt(i1)).stringS.equals("["))
j2++;
else
if(((EqToken)TokenV.elementAt(i1)).stringS.equals("]"))
j2--;
if(j2 != 0)
continue;
TokenV.setElementAt(new EqToken(4), i1);
break;
}
 
j++;
}
 
}
 
public void start()
{
countT = -1;
}
 
public int get_count()
{
return countT;
}
 
public void set_count(int i)
{
countT = i;
}
 
public EqToken nextToken()
{
countT++;
if(countT >= TokenV.size())
{
countT = TokenV.size() - 1;
return new EqToken(99);
} else
{
return (EqToken)TokenV.elementAt(countT);
}
}
 
public boolean EoT()
{
return countT == TokenV.size() - 1;
}
 
private char getChar()
{
return equation.charAt(count);
}
 
private void advance()
{
if(collectB)
selectSB.append(equation.charAt(count));
if(count < equation.length() - 1)
{
count++;
EOF = false;
} else
{
count = equation.length();
EOF = true;
}
}
 
private EqToken ScanNextToken()
{
StringBuffer stringbuffer = new StringBuffer("");
String s = new String("");
EqToken eqtoken = new EqToken();
boolean flag = false;
do
{
if(EOF)
break;
char c = getChar();
switch(c)
{
case 9: // '\t'
case 10: // '\n'
case 13: // '\r'
advance();
break;
 
case 32: // ' '
advance();
return new EqToken(25, new String(" "));
 
case 33: // '!'
case 35: // '#'
case 42: // '*'
case 43: // '+'
case 44: // ','
case 45: // '-'
case 47: // '/'
case 58: // ':'
case 59: // ';'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 126: // '~'
advance();
return new EqToken(108, String.valueOf(c));
 
case 123: // '{'
advance();
return new EqToken(3);
 
case 125: // '}'
advance();
return new EqToken(4);
 
case 40: // '('
case 41: // ')'
case 91: // '['
case 93: // ']'
case 124: // '|'
advance();
return new EqToken(109, String.valueOf(c));
 
case 38: // '&'
advance();
return new EqToken(7);
 
case 39: // '\''
case 64: // '@'
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 97: // 'a'
case 98: // 'b'
case 99: // 'c'
case 100: // 'd'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 108: // 'l'
case 109: // 'm'
case 110: // 'n'
case 111: // 'o'
case 112: // 'p'
case 113: // 'q'
case 114: // 'r'
case 115: // 's'
case 116: // 't'
case 117: // 'u'
case 118: // 'v'
case 119: // 'w'
case 120: // 'x'
case 121: // 'y'
case 122: // 'z'
stringbuffer.append(c);
advance();
boolean flag1 = false;
do
{
if(EOF || flag1)
break;
c = getChar();
switch(c)
{
case 39: // '\''
case 64: // '@'
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 97: // 'a'
case 98: // 'b'
case 99: // 'c'
case 100: // 'd'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 108: // 'l'
case 109: // 'm'
case 110: // 'n'
case 111: // 'o'
case 112: // 'p'
case 113: // 'q'
case 114: // 'r'
case 115: // 's'
case 116: // 't'
case 117: // 'u'
case 118: // 'v'
case 119: // 'w'
case 120: // 'x'
case 121: // 'y'
case 122: // 'z'
stringbuffer.append(c);
advance();
break;
 
case 40: // '('
case 41: // ')'
case 42: // '*'
case 43: // '+'
case 44: // ','
case 45: // '-'
case 46: // '.'
case 47: // '/'
case 48: // '0'
case 49: // '1'
case 50: // '2'
case 51: // '3'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
case 58: // ':'
case 59: // ';'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 63: // '?'
case 91: // '['
case 92: // '\\'
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
default:
flag1 = true;
break;
}
} while(true);
return new EqToken(1, stringbuffer.toString());
 
case 46: // '.'
case 48: // '0'
case 49: // '1'
case 50: // '2'
case 51: // '3'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
stringbuffer.append(c);
advance();
boolean flag2 = false;
do
{
if(EOF || flag2)
break;
c = getChar();
switch(c)
{
case 46: // '.'
case 48: // '0'
case 49: // '1'
case 50: // '2'
case 51: // '3'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
stringbuffer.append(c);
advance();
break;
 
case 47: // '/'
default:
flag2 = true;
break;
}
} while(true);
return new EqToken(2, stringbuffer.toString());
 
case 92: // '\\'
advance();
boolean flag3 = false;
if(!EOF)
{
c = getChar();
switch(c)
{
case 92: // '\\'
advance();
return new EqToken(8);
 
case 123: // '{'
advance();
return new EqToken(109, String.valueOf(c));
 
case 124: // '|'
advance();
return new EqToken(109, "||");
 
case 125: // '}'
advance();
return new EqToken(109, String.valueOf(c));
 
case 44: // ','
advance();
return new EqToken(113, "3");
 
case 58: // ':'
advance();
return new EqToken(113, "4");
 
case 59: // ';'
advance();
return new EqToken(113, "5");
 
case 33: // '!'
advance();
return new EqToken(113, "-3");
 
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 97: // 'a'
case 98: // 'b'
case 99: // 'c'
case 100: // 'd'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 108: // 'l'
case 109: // 'm'
case 110: // 'n'
case 111: // 'o'
case 112: // 'p'
case 113: // 'q'
case 114: // 'r'
case 115: // 's'
case 116: // 't'
case 117: // 'u'
case 118: // 'v'
case 119: // 'w'
case 120: // 'x'
case 121: // 'y'
case 122: // 'z'
stringbuffer.append(c);
advance();
boolean flag4 = false;
do
{
if(EOF || flag4)
break;
c = getChar();
switch(c)
{
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 97: // 'a'
case 98: // 'b'
case 99: // 'c'
case 100: // 'd'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 108: // 'l'
case 109: // 'm'
case 110: // 'n'
case 111: // 'o'
case 112: // 'p'
case 113: // 'q'
case 114: // 'r'
case 115: // 's'
case 116: // 't'
case 117: // 'u'
case 118: // 'v'
case 119: // 'w'
case 120: // 'x'
case 121: // 'y'
case 122: // 'z'
stringbuffer.append(c);
advance();
break;
 
case 91: // '['
case 92: // '\\'
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
default:
flag4 = true;
break;
}
} while(true);
String s1 = stringbuffer.toString();
if(s1.equals("euro"))
return new EqToken(2, "\u20AC");
if(s1.equals("acute"))
return new EqToken(22, "\uFFFD");
if(s1.equals("array"))
return new EqToken(15);
if(s1.equals("bar"))
return new EqToken(14, "bar");
if(s1.equals("ddot"))
return new EqToken(22, "..");
if(s1.equals("dot"))
return new EqToken(22, ".");
if(s1.equals("frac"))
return new EqToken(12);
if(s1.equals("grave"))
return new EqToken(22, "`");
if(s1.equals("hat"))
return new EqToken(22, "^");
if(s1.equals("int"))
return new EqToken(20, "int");
if(s1.equals("oint"))
return new EqToken(20, "oint");
if(s1.equals("left"))
return new EqToken(16);
if(s1.equals("limsup"))
return new EqToken(24, "lim sup");
if(s1.equals("liminf"))
return new EqToken(24, "lim inf");
if(s1.equals("prod"))
return new EqToken(20, "prod");
if(s1.equals("right"))
return new EqToken(17);
if(s1.equals("sqrt"))
return new EqToken(13);
if(s1.equals("sum"))
return new EqToken(20, "sum");
if(s1.equals("tilde"))
return new EqToken(22, "~");
if(s1.equals("vec"))
return new EqToken(14);
if(s1.equals("widehat"))
return new EqToken(14, "widehat");
if(s1.equals("widetilde"))
return new EqToken(14, "widetilde");
if(s1.equals("quad"))
return new EqToken(113, "18");
if(s1.equals("qquad"))
return new EqToken(113, "36");
if(s1.equals("backslash"))
return new EqToken(2, "\\");
if(s1.equals("langle"))
return new EqToken(5, "<");
if(s1.equals("rangle"))
return new EqToken(5, ">");
if(s1.equals("not"))
return new EqToken(110);
if(s1.equals("atop"))
return new EqToken(115);
if(s1.equals("choose"))
return new EqToken(114);
if(s1.equals("overline"))
return new EqToken(116);
if(s1.equals("underline"))
return new EqToken(117);
if(s1.equals("overbrace"))
return new EqToken(118);
if(s1.equals("underbrace"))
return new EqToken(119);
if(s1.equals("stackrel"))
return new EqToken(120);
if(s1.equals("begin"))
return new EqToken(50);
if(s1.equals("end"))
return new EqToken(51);
if(s1.equals("fgcolor"))
return new EqToken(121);
if(s1.equals("bgcolor"))
return new EqToken(122);
if(s1.equals("fbox"))
return new EqToken(123);
if(s1.equals("mbox"))
return new EqToken(124);
if(" arccos arcsin arctan arg cos cosh cot coth csc csch def deg dim exp hom ker lg ln log sec sech sin sinh tan tanh ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(9, s1);
if(" det gcd inf lim max min Pr sup ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(24, s1);
if(" alpha delta epsilon iota kappa lambda nu omega pi sigma theta tau upsilon varepsilon varpi vartheta pm mp times div cdot cdots ldots ast star amalg cap cup uplus sqcap sqcup vee wedge wr circ bullet diamond lhd rhd oslash odot Box bigtriangleup triangleleft triangleright oplus ominus otimes ll subset sqsubset in vdash models gg supset sqsupset ni dashv perp neq doteq approx cong equiv propto prec sim simeq asymp smile frown bowtie succ aleph forall hbar exists imath neg flat ell Re angle Im backslash mho Box prime emptyset triangle nabla partial top bot Join infty vdash dashv Fourier Laplace leftarrow gets hookrightarrow leftharpoondown rightarrow to rightharpoondown leadsto leftrightarrow mapsto hookleftarrow leftharpoonup rightharpoonup rightleftharpoons longleftarrow longrightarrow longleftrightarrow longmapsto ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(18, s1);
if(" beta chi eta gamma mu psi phi rho varrho varsigma varphi xi zeta le leq ge geq vdots ddots natural jmath bigtriangledown sharp uparrow downarrow updownarrow nearrow searrow swarrow nwarrow succeq mid preceq parallel subseteq sqsubseteq supseteq sqsupseteq clubsuit diamondsuit heartsuit spadesuit wp dagger ddagger setminus unlhd unrhd bigcirc ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(19, s1);
if(" Delta Gamma Lambda Omega Pi Phi Psi Sigma Theta Upsilon Xi Leftarrow Rightarrow Leftrightarrow Longleftarrow Longrightarrow Longleftrightarrow Diamond ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(18, (new StringBuilder()).append(s1).append("Big").toString());
if(" Uparrow Downarrow Updownarrow ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(19, (new StringBuilder()).append(s1).append("Big").toString());
// fall through
 
case 34: // '"'
case 35: // '#'
case 36: // '$'
case 37: // '%'
case 38: // '&'
case 39: // '\''
case 40: // '('
case 41: // ')'
case 42: // '*'
case 43: // '+'
case 45: // '-'
case 46: // '.'
case 47: // '/'
case 48: // '0'
case 49: // '1'
case 50: // '2'
case 51: // '3'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 63: // '?'
case 64: // '@'
case 91: // '['
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
default:
boolean flag5 = true;
advance();
System.out.println((new StringBuilder()).append("Scanner invalid tag: \\").append(stringbuffer.toString()).toString());
return new EqToken(100);
}
}
break;
 
case 94: // '^'
advance();
return new EqToken(10);
 
case 95: // '_'
advance();
return new EqToken(11);
 
case 11: // '\013'
case 12: // '\f'
case 14: // '\016'
case 15: // '\017'
case 16: // '\020'
case 17: // '\021'
case 18: // '\022'
case 19: // '\023'
case 20: // '\024'
case 21: // '\025'
case 22: // '\026'
case 23: // '\027'
case 24: // '\030'
case 25: // '\031'
case 26: // '\032'
case 27: // '\033'
case 28: // '\034'
case 29: // '\035'
case 30: // '\036'
case 31: // '\037'
case 34: // '"'
case 36: // '$'
case 37: // '%'
case 63: // '?'
case 96: // '`'
default:
advance();
System.out.println((new StringBuilder()).append("Scanner invalid character: ").append(c).toString());
return new EqToken(100);
}
} while(true);
return new EqToken(99);
}
 
private String equation;
private int count;
private int countT;
private EqToken token;
private boolean EOF;
private Vector TokenV;
private boolean selectB;
private boolean collectB;
private int selectCount1;
private int selectCount2;
private StringBuffer selectSB;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Fonts12.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/gpl.txt
0,0 → 1,674
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
 
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
Preamble
 
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
 
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
 
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
 
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
 
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
 
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
 
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
 
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
 
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
 
The precise terms and conditions for copying, distribution and
modification follow.
 
TERMS AND CONDITIONS
 
0. Definitions.
 
"This License" refers to version 3 of the GNU General Public License.
 
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
 
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
 
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
 
A "covered work" means either the unmodified Program or a work based
on the Program.
 
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
 
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
 
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
 
1. Source Code.
 
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
 
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
 
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
 
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
 
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
 
The Corresponding Source for a work in source code form is that
same work.
 
2. Basic Permissions.
 
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
 
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
 
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
 
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
 
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
 
4. Conveying Verbatim Copies.
 
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
 
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
 
5. Conveying Modified Source Versions.
 
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
 
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
 
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
 
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
 
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
 
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
 
6. Conveying Non-Source Forms.
 
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
 
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
 
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
 
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
 
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
 
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
 
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
 
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
 
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
 
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
 
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
 
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
 
7. Additional Terms.
 
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
 
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
 
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
 
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
 
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
 
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
 
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
 
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
 
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
 
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
 
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
 
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
 
8. Termination.
 
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
 
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
 
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
 
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
 
9. Acceptance Not Required for Having Copies.
 
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
 
10. Automatic Licensing of Downstream Recipients.
 
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
 
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
 
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
 
11. Patents.
 
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
 
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
 
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
 
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
 
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
 
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
 
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
 
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
 
12. No Surrender of Others' Freedom.
 
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
 
13. Use with the GNU Affero General Public License.
 
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
 
14. Revised Versions of this License.
 
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
 
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
 
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
 
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
 
15. Disclaimer of Warranty.
 
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 
16. Limitation of Liability.
 
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
 
17. Interpretation of Sections 15 and 16.
 
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
 
END OF TERMS AND CONDITIONS
 
How to Apply These Terms to Your New Programs
 
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
 
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
 
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
 
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
 
Also add information on how to contact you by electronic and paper mail.
 
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
 
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
 
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
 
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
 
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/sHotEqn.java
0,0 → 1,2549
package atp;
 
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.PrintStream;
import java.util.Hashtable;
import javax.swing.JApplet;
import javax.swing.JComponent;
 
// Referenced classes of package atp:
// sSymbolLoader, EqScanner, ColorMaskFilter, BoxC,
// EqToken
 
public class sHotEqn extends JComponent
implements MouseListener, MouseMotionListener
{
 
public sHotEqn()
{
this("sHotEqn", null, "sHotEqn");
}
 
public sHotEqn(String s)
{
this(s, null, "sHotEqn");
}
 
public sHotEqn(String s, JApplet japplet, String s1)
{
width = 0;
height = 0;
nameS = null;
equation = null;
Fontname = "Helvetica";
f1 = new Font(Fontname, 0, 16);
f2 = new Font(Fontname, 0, 14);
f3 = new Font(Fontname, 0, 11);
f4 = new Font(Fontname, 0, 10);
imageOK = false;
localWidth = 0;
localHeight = 0;
BGColor = Color.white;
EnvColor = Color.white;
FGColor = Color.black;
BorderColor = Color.red;
borderB = false;
roundRectBorderB = false;
border = 0;
halign = "left";
valign = "top";
xpos = 0;
ypos = 0;
drawn = false;
imageH = new Hashtable(13);
appletB = false;
beanB = false;
debug = true;
editMode = false;
editableB = true;
mouse1X = 0;
mouse1Y = 0;
mouse2X = 0;
mouse2Y = 0;
xOFF = 0;
yOFF = 0;
y0 = 0;
x0 = 0;
y1 = 0;
x1 = 0;
editModeRec = 5;
editModeFind = false;
editModeCount1 = 0;
editModeCount2 = 0;
app = japplet;
equation = s;
nameS = s1;
addMouseListener(this);
addMouseMotionListener(this);
if(japplet != null)
appletB = true;
symbolLoader = new SymbolLoader();
tracker = new MediaTracker(this);
eqScan = new EqScanner(s);
System.out.println((new StringBuilder()).append("sHotEqn V 4.00 ").append(s1).toString());
}
 
public void setEquation(String s)
{
equation = s;
eqScan.setEquation(s);
drawn = false;
imageOK = false;
repaint();
}
 
public String getEquation()
{
return equation;
}
 
public void printStatus(String s)
{
if(debug)
System.out.println((new StringBuilder()).append(nameS).append(" ").append(s).toString());
}
 
private void displayStatus(String s)
{
if(debug)
if(appletB)
app.showStatus((new StringBuilder()).append(nameS).append(" ").append(s).toString());
else
printStatus(s);
}
 
public Image getImage()
{
if(imageOK)
return bufferImage;
else
return null;
}
 
public BufferedImage GetMyImage()
{
return finalimage;
}
 
public void setDebug(boolean flag)
{
debug = flag;
}
 
public boolean isDebug()
{
return debug;
}
 
public void setFontname(String s)
{
Fontname = s;
}
 
public String getFontname()
{
return Fontname;
}
 
public void setFontsizes(int i, int j, int k, int l)
{
int i1 = 16;
int j1 = 14;
int k1 = 11;
int l1 = 9;
GreekSize[0] = 0;
GreekSize[1] = 0;
GreekSize[2] = 0;
GreekSize[3] = 0;
for(int i2 = 0; i2 < GreekFontSizes.length; i2++)
{
if(i == GreekFontSizes[i2])
{
GreekSize[0] = i;
GreekDescent[0] = GreekFontDescents[i2];
i1 = EmbedFontSizes[i2];
}
if(j == GreekFontSizes[i2])
{
GreekSize[1] = j;
GreekDescent[1] = GreekFontDescents[i2];
j1 = EmbedFontSizes[i2];
}
if(k == GreekFontSizes[i2])
{
GreekSize[2] = k;
GreekDescent[2] = GreekFontDescents[i2];
k1 = EmbedFontSizes[i2];
}
if(l == GreekFontSizes[i2])
{
GreekSize[3] = l;
GreekDescent[3] = GreekFontDescents[i2];
l1 = EmbedFontSizes[i2];
}
}
 
if(GreekSize[0] == 0)
{
GreekSize[0] = GreekFontSizes[GreekFontSizes.length - 1];
GreekDescent[0] = GreekFontDescents[GreekFontDescents.length - 1];
i1 = EmbedFontSizes[EmbedFontSizes.length - 1];
}
if(GreekSize[1] == 0)
{
GreekSize[1] = GreekSize[0];
GreekDescent[1] = GreekDescent[0];
j1 = i1;
}
if(GreekSize[2] == 0)
{
GreekSize[2] = GreekSize[1];
GreekDescent[2] = GreekDescent[1];
k1 = j1;
}
if(GreekSize[3] == 0)
{
GreekSize[3] = GreekSize[2];
GreekDescent[3] = GreekDescent[2];
l1 = k1;
}
f1 = new Font(Fontname, 0, i1);
f2 = new Font(Fontname, 0, j1);
f3 = new Font(Fontname, 0, k1);
f4 = new Font(Fontname, 0, l1);
}
 
public void setBackground(Color color)
{
BGColor = EnvColor = color;
drawn = false;
imageOK = false;
repaint();
}
 
public Color getBackground()
{
return BGColor;
}
 
public void setForeground(Color color)
{
FGColor = color;
drawn = false;
imageOK = false;
repaint();
}
 
public Color getForeground()
{
return FGColor;
}
 
public void setBorderColor(Color color)
{
BorderColor = color;
drawn = false;
imageOK = false;
repaint();
}
 
public Color getBorderColor()
{
return BorderColor;
}
 
public void setBorder(boolean flag)
{
borderB = flag;
drawn = false;
imageOK = false;
repaint();
}
 
public boolean isBorder()
{
return borderB;
}
 
public void setRoundRectBorder(boolean flag)
{
roundRectBorderB = flag;
drawn = false;
imageOK = false;
repaint();
}
 
public boolean isRoundRectBorder()
{
return roundRectBorderB;
}
 
public void setHAlign(String s)
{
halign = s;
drawn = false;
imageOK = false;
}
 
public void setEnvColor(Color color)
{
EnvColor = color;
drawn = false;
imageOK = false;
repaint();
}
 
public Color getEnvColor()
{
return EnvColor;
}
 
public String getHAlign()
{
return halign;
}
 
public void setVAlign(String s)
{
valign = s;
drawn = false;
imageOK = false;
}
 
public String getVAlign()
{
return valign;
}
 
public void setEditable(boolean flag)
{
editableB = flag;
}
 
public boolean isEditable()
{
return editableB;
}
 
public String getSelectedArea()
{
return eqScan.getSelectedArea(editModeCount1, editModeCount2);
}
 
public void mousePressed(MouseEvent mouseevent)
{
}
 
public void mouseReleased(MouseEvent mouseevent)
{
}
 
public void mouseEntered(MouseEvent mouseevent)
{
}
 
public void mouseExited(MouseEvent mouseevent)
{
}
 
public void mouseClicked(MouseEvent mouseevent)
{
}
 
public void mouseMoved(MouseEvent mouseevent)
{
}
 
public void mouseDragged(MouseEvent mouseevent)
{
}
 
public void processMouseEvent(MouseEvent mouseevent)
{
if(mouseevent.isControlDown())
{
if(mouseevent.getID() == 501 && !mouseevent.isMetaDown())
System.out.println((new StringBuilder()).append(nameS).append(" (width,height) given=(").append(getSize().width).append(",").append(getSize().height).append(") used=(").append(getPreferredSize().width).append(",").append(getPreferredSize().height).append(")").toString());
} else
if(editableB)
if(mouseevent.getID() == 501)
{
mouse1X = mouseevent.getX();
mouse1Y = mouseevent.getY();
mouse2X = 0;
mouse2Y = 0;
editModeRec = 5;
selectImage = null;
repaint();
} else
if(mouseevent.getID() == 502 && editMode)
{
Graphics g = getGraphics();
g.setFont(f1);
g.setColor(FGColor);
eqScan.start();
BoxC boxc = eqn(xOFF, yOFF, true, g, 1);
if(debug)
printStatus((new StringBuilder()).append("selectedArea = ").append(eqScan.getSelectedArea(editModeCount1, editModeCount2)).toString());
FilteredImageSource filteredimagesource = new FilteredImageSource(bufferImage.getSource(), new CropImageFilter(x0, y0, x1 - x0, y1 - y0));
FilteredImageSource filteredimagesource1 = new FilteredImageSource(filteredimagesource, new ColorMaskFilter(Color.red, true));
selectImage = Toolkit.getDefaultToolkit().createImage(filteredimagesource1);
g.drawImage(selectImage, x0, y0, this);
editMode = false;
}
super.processMouseEvent(mouseevent);
}
 
public void processMouseMotionEvent(MouseEvent mouseevent)
{
if(mouseevent.getID() == 506 && mouse1X != 0 && editableB)
{
editMode = true;
mouse2X = mouseevent.getX();
mouse2Y = mouseevent.getY();
}
}
 
public Dimension getPreferredSize()
{
if((width == 0) & (height == 0))
{
Graphics g = getGraphics();
if(g != null)
{
g.setFont(f1);
eqScan.start();
BoxC boxc = eqn(0, 150, false, g, 1);
if(borderB)
border = 5;
else
border = 0;
localWidth = 1 + boxc.dx + 2 * border;
localHeight = 1 + boxc.dy_pos + boxc.dy_neg + 2 * border;
}
}
width = localWidth;
height = localHeight;
if(localWidth <= 1)
return new Dimension(100, 100);
else
return new Dimension(localWidth, localHeight);
}
 
public Dimension getSizeof(String s)
{
Image image = createImage(200, 200);
Graphics g = image.getGraphics();
g.setFont(f1);
eqScan.setEquation(s);
BoxC boxc = eqn(0, 150, false, g, 1);
g.dispose();
byte byte0;
if(borderB)
byte0 = 5;
else
byte0 = 0;
return new Dimension(1 + boxc.dx + 2 * byte0, 1 + boxc.dy_pos + boxc.dy_neg + 2 * byte0);
}
 
public Dimension getMinimumSize()
{
return getPreferredSize();
}
 
public void addActionListener(ActionListener actionlistener)
{
actionListener = AWTEventMulticaster.add(actionListener, actionlistener);
enableEvents(16L);
}
 
public void removeActionListener(ActionListener actionlistener)
{
actionListener = AWTEventMulticaster.remove(actionListener, actionlistener);
}
 
private void draw_hourglass(Graphics g)
{
g.setColor(Color.red);
int i = height / 2 - 10;
int j = i + 20;
int k = width / 2 - 5;
int l = k + 10;
Polygon polygon = new Polygon();
polygon.addPoint(k, i);
polygon.addPoint(l, j);
polygon.addPoint(k, j);
polygon.addPoint(l, i);
g.fillPolygon(polygon);
}
 
public synchronized void paintComponent(Graphics g)
{
super.paintComponent(g);
if(width != getSize().width || height != getSize().height)
{
imageOK = false;
bufferImage = null;
width = getSize().width;
height = getSize().height;
}
if(!imageOK)
{
draw_hourglass(g);
selectImage = null;
if(bufferImage == null)
bufferImage = createImage(width, height);
Graphics g1 = bufferImage.getGraphics();
generateImage(g1);
g1.dispose();
}
g.drawImage(bufferImage, 0, 0, this);
if(selectImage != null)
g.drawImage(selectImage, x0, y0, this);
}
 
private synchronized void generateImage(Graphics g)
{
BoxC boxc = new BoxC();
Image image = createImage(width, height + height);
Graphics g1 = image.getGraphics();
g1.setFont(f1);
g.setColor(BGColor);
g.fillRect(0, 0, width, height);
g1.setColor(BGColor);
g1.fillRect(0, 0, width, height + height);
border = 0;
if(borderB && roundRectBorderB)
{
g.setColor(EnvColor);
g.fillRect(0, 0, width, height);
g.setColor(BGColor);
g.fillRoundRect(0, 0, width - 1, height - 1, 20, 20);
g.setColor(BorderColor);
g.drawRoundRect(0, 0, width - 1, height - 1, 20, 20);
border = 5;
} else
if(borderB && !roundRectBorderB)
{
g.setColor(BorderColor);
g.drawRect(0, 0, width - 1, height - 1);
border = 5;
}
g1.setColor(FGColor);
eqScan.start();
boxc = eqn(0, height, true, g1, 1);
displayStatus(" ");
xpos = 0;
if(halign.equals("center"))
xpos = 1;
else
if(halign.equals("right"))
xpos = 2;
ypos = 0;
if(valign.equals("middle"))
ypos = 1;
else
if(valign.equals("bottom"))
ypos = 2;
localWidth = 1 + boxc.dx + 2 * border;
localHeight = 1 + boxc.dy_pos + boxc.dy_neg + 2 * border;
boolean flag = false;
if(localWidth > width)
{
flag = true;
xpos = 0;
}
if(localHeight > height)
{
flag = true;
ypos = 1;
}
int i = border;
int j = border;
switch(xpos)
{
case 1: // '\001'
i = (width - boxc.dx) / 2;
break;
 
case 2: // '\002'
i = width - border - boxc.dx - 1;
break;
}
switch(ypos)
{
case 1: // '\001'
j = border - (localHeight - height) / 2;
break;
 
case 2: // '\002'
j = height - border - boxc.dy_neg - boxc.dy_pos;
break;
}
g.drawImage(image, i, j, i + boxc.dx, j + boxc.dy_pos + boxc.dy_neg + 1, 0, height - boxc.dy_pos, boxc.dx, height + boxc.dy_neg + 1, this);
g1.dispose();
if(flag)
printStatus((new StringBuilder()).append("(width,height) given=(").append(width).append(",").append(height).append(") used=(").append(localWidth).append(",").append(localHeight).append(")").toString());
imageOK = true;
drawn = true;
xOFF = i;
yOFF = j + boxc.dy_pos;
notify();
}
// jm.evers
public int[] getActualSize()
{
int ai[] = new int[2];
ai[0] = localWidth;
ai[1] = localHeight;
return ai;
}
// jm.evers
public synchronized BufferedImage mkImage(Color color, Color color1, int i, int j)
{
width = i;
height = j;
finalimage = new BufferedImage(width, height, 2);
Graphics g = finalimage.getGraphics();
BoxC boxc = new BoxC();
BoxC boxc1 = new BoxC();
g.setFont(f1);
g.setColor(color);
g.fillRect(0, 0, width, height);
border = 0;
if(borderB && roundRectBorderB)
{
g.setColor(EnvColor);
g.fillRect(0, 0, width, height);
g.setColor(color1);
g.fillRoundRect(0, 0, width - 1, height - 1, 20, 20);
g.setColor(BorderColor);
g.drawRoundRect(0, 0, width - 1, height - 1, 20, 20);
border = 5;
} else
if(borderB && !roundRectBorderB)
{
g.setColor(BorderColor);
g.drawRect(0, 0, width - 1, height - 1);
border = 5;
}
g.setColor(color1);
eqScan.start();
boxc1 = eqn(0, 150, false, g, 1);
displayStatus(" ");
xpos = 0;
if(halign.equals("center"))
xpos = 1;
else
if(halign.equals("right"))
xpos = 2;
ypos = 0;
if(valign.equals("middle"))
ypos = 1;
else
if(valign.equals("bottom"))
ypos = 2;
localWidth = 1 + boxc1.dx + 2 * border;
localHeight = 1 + boxc1.dy_pos + boxc1.dy_neg + 2 * border;
boolean flag = false;
if(localWidth > width)
{
flag = true;
xpos = 0;
}
if(localHeight > height)
{
flag = true;
ypos = 1;
}
int k = border;
int l = boxc1.dy_pos + border;
switch(xpos)
{
case 1: // '\001'
k = (width - boxc1.dx) / 2;
break;
 
case 2: // '\002'
k = width - border - boxc1.dx - 1;
break;
}
switch(ypos)
{
case 1: // '\001'
l = (border + boxc1.dy_pos) - (localHeight - height) / 2;
break;
 
case 2: // '\002'
l = height - border - boxc1.dy_neg - 1;
break;
}
eqScan.start();
boxc = eqn(k, l, true, g, 1);
xOFF = k;
yOFF = l;
g.dispose();
// ok now paint the image as big as it should be
finalimage = new BufferedImage(localWidth,localHeight, 2);
g = finalimage.getGraphics();
boxc = new BoxC();
boxc1 = new BoxC();
g.setFont(f1);
g.setColor(color);
g.fillRect(0, 0, localWidth, localHeight);
g.setColor(color1);
eqScan.start();
boxc = eqn(k, l, true, g, 1);
imageOK = true;
drawn = true;
xOFF = k;
yOFF = l;
notify();
g.dispose();
return finalimage;
}
 
private BoxC eqn(int i, int j, boolean flag, Graphics g, int k)
{
return eqn(i, j, flag, g, k, true);
}
 
private BoxC eqn(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
BoxC boxc = new BoxC();
BoxC boxc1 = new BoxC();
boolean flag2 = true;
boolean flag3 = false;
boolean flag5 = false;
int l = 0;
boolean flag6 = false;
do
{
if(eqScan.EoT() || !flag2)
break;
eqTok = eqScan.nextToken();
if(editMode && flag)
l = eqScan.get_count();
boolean flag4 = false;
int i1 = l;
int j1 = eqTok.typ;
switch(eqTok.typ)
{
case 4: // '\004'
case 7: // '\007'
case 8: // '\b'
case 17: // '\021'
case 51: // '3'
if(editModeFind && flag)
{
if(l > editModeCount2)
editModeCount2 = l;
if(l < editModeCount1)
editModeCount1 = l;
}
return boxc1;
 
case 22: // '\026'
boxc = ACCENT(i + boxc1.dx, j, flag, g, k);
break;
 
case 5: // '\005'
boxc = ANGLE(i + boxc1.dx, j, flag, g);
break;
 
case 15: // '\017'
if(editModeFind && flag)
flag5 = true;
boxc = ARRAY(i + boxc1.dx, j, flag, g, k);
break;
 
case 50: // '2'
if(editModeFind && flag)
flag5 = true;
boxc = BEGIN(i + boxc1.dx, j, flag, g, k);
break;
 
case 3: // '\003'
boxc = eqn(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 121: // 'y'
boxc = FG_BGColor(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 122: // 'z'
boxc = FG_BGColor(i + boxc1.dx, j, flag, g, k, false);
break;
 
case 123: // '{'
if(editModeFind && flag)
flag5 = true;
boxc = FBOX(i + boxc1.dx, j, flag, g, k);
break;
 
case 1: // '\001'
boxc = Id(i + boxc1.dx, j, flag, g);
break;
 
case 110: // 'n'
boxc = NOT(i + boxc1.dx, j, flag, g, k);
break;
 
case 108: // 'l'
boxc = Op(i + boxc1.dx, j, flag, g);
break;
 
case 12: // '\f'
boxc = FRAC(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 115: // 's'
boxc = FRAC(i + boxc1.dx, j, flag, g, k, false);
break;
 
case 2: // '\002'
case 9: // '\t'
boxc = Plain(i + boxc1.dx, j, flag, g);
break;
 
case 18: // '\022'
boxc = SYMBOP(i + boxc1.dx, j, flag, g, k, false);
break;
 
case 19: // '\023'
boxc = SYMBOP(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 16: // '\020'
if(editModeFind && flag)
flag5 = true;
boxc = LEFT(i + boxc1.dx, j, flag, g, k);
break;
 
case 24: // '\030'
boxc = LIM(i + boxc1.dx, j, flag, g, k);
break;
 
case 124: // '|'
boxc = MBOX(i + boxc1.dx, j, flag, g);
break;
 
case 118: // 'v'
boxc = OverBRACE(i + boxc1.dx, j, flag, g, k);
break;
 
case 119: // 'w'
boxc = UnderBRACE(i + boxc1.dx, j, flag, g, k);
break;
 
case 116: // 't'
boxc = OverUnderLINE(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 117: // 'u'
boxc = OverUnderLINE(i + boxc1.dx, j, flag, g, k, false);
break;
 
case 109: // 'm'
boxc = Paren(i + boxc1.dx, j, flag, g);
break;
 
case 113: // 'q'
boxc = SPACE(i + boxc1.dx, j, flag, g);
break;
 
case 13: // '\r'
if(editModeFind && flag)
flag5 = true;
boxc = SQRT(i + boxc1.dx, j, flag, g, k);
break;
 
case 120: // 'x'
boxc = STACKREL(i + boxc1.dx, j, flag, g, k);
break;
 
case 10: // '\n'
boxc = SUP(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 11: // '\013'
boxc = SUB(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 20: // '\024'
boxc = SYMBOLBIG(i + boxc1.dx, j, flag, g, k);
break;
 
case 14: // '\016'
boxc = VEC(i + boxc1.dx, j, flag, g, k);
break;
 
case 25: // '\031'
boxc = new BoxC(0, 0, 0);
flag4 = true;
break;
 
case 99: // 'c'
case 100: // 'd'
boxc = new BoxC(0, 0, 0);
break;
 
case 6: // '\006'
case 21: // '\025'
case 23: // '\027'
case 26: // '\032'
case 27: // '\033'
case 28: // '\034'
case 29: // '\035'
case 30: // '\036'
case 31: // '\037'
case 32: // ' '
case 33: // '!'
case 34: // '"'
case 35: // '#'
case 36: // '$'
case 37: // '%'
case 38: // '&'
case 39: // '\''
case 40: // '('
case 41: // ')'
case 42: // '*'
case 43: // '+'
case 44: // ','
case 45: // '-'
case 46: // '.'
case 47: // '/'
case 48: // '0'
case 49: // '1'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
case 58: // ':'
case 59: // ';'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 63: // '?'
case 64: // '@'
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 91: // '['
case 92: // '\\'
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
case 97: // 'a'
case 98: // 'b'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 111: // 'o'
case 112: // 'p'
case 114: // 'r'
default:
printStatus((new StringBuilder()).append("Parser: unknown token: ").append(eqTok.typ).append(" ").append(eqTok.stringS).toString());
break;
}
if(flag)
{
if(editMode)
{
if(!editModeFind && i + boxc1.dx <= mouse1X && mouse1X <= i + boxc1.dx + boxc.dx && j - boxc.dy_pos <= mouse1Y && mouse1Y <= j + boxc.dy_neg)
{
x0 = x1 = mouse1X;
y0 = y1 = mouse1Y;
editModeFind = true;
editModeCount1 = l;
editModeCount2 = l;
}
if(!editModeFind && i + boxc1.dx <= mouse2X && mouse2X <= i + boxc1.dx + boxc.dx && j - boxc.dy_pos <= mouse2Y && mouse2Y <= j + boxc.dy_neg)
{
x0 = x1 = mouse2X;
y0 = y1 = mouse2Y;
editModeFind = true;
editModeCount1 = l;
editModeCount2 = l;
int k1 = mouse2X;
int l1 = mouse2Y;
mouse2X = mouse1X;
mouse2Y = mouse1Y;
mouse1X = k1;
mouse1Y = l1;
}
if(editModeFind)
{
x0 = Math.min(x0, i + boxc1.dx);
x1 = Math.max(x1, i + boxc1.dx + boxc.dx);
y0 = Math.min(y0, j - boxc.dy_pos);
y1 = Math.max(y1, j + boxc.dy_neg);
if(editModeRec > k)
editModeRec = k;
switch(j1)
{
case 13: // '\r'
case 15: // '\017'
case 16: // '\020'
case 50: // '2'
case 123: // '{'
case 124: // '|'
flag5 = true;
if(i1 > editModeCount2)
editModeCount2 = i1;
if(i1 < editModeCount1)
editModeCount1 = i1;
l = eqScan.get_count();
break;
}
if(l > editModeCount2)
editModeCount2 = l;
if(l < editModeCount1)
editModeCount1 = l;
if(i + boxc1.dx <= mouse2X && mouse2X <= i + boxc1.dx + boxc.dx && j - boxc.dy_pos <= mouse2Y && mouse2Y <= j + boxc.dy_neg && editModeRec == k)
{
editMode = false;
editModeFind = false;
}
}
}
if(flag5)
{
x0 = Math.min(x0, i + boxc1.dx);
x1 = Math.max(x1, i + boxc1.dx + boxc.dx);
y0 = Math.min(y0, j - boxc.dy_pos);
y1 = Math.max(y1, j + boxc.dy_neg);
switch(j1)
{
case 13: // '\r'
case 15: // '\017'
case 16: // '\020'
case 50: // '2'
case 123: // '{'
case 124: // '|'
if(i1 > editModeCount2)
editModeCount2 = i1;
if(i1 < editModeCount1)
editModeCount1 = i1;
l = eqScan.get_count();
break;
}
if(l > editModeCount2)
editModeCount2 = l;
if(l < editModeCount1)
editModeCount1 = l;
flag5 = false;
}
}
boxc1.dx += boxc.dx;
boxc1.dy_pos = Math.max(boxc1.dy_pos, boxc.dy_pos);
boxc1.dy_neg = Math.max(boxc1.dy_neg, boxc.dy_neg);
if(!flag1 && !flag4)
flag2 = false;
} while(true);
return boxc1;
}
 
private BoxC ACCENT(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = 0;
FontMetrics fontmetrics = g.getFontMetrics();
String s = eqTok.stringS;
if(flag)
l = eqScan.get_count();
boxc = eqn(i, j, false, g, k, false);
int i1 = Math.max(boxc.dx, fontmetrics.stringWidth(s));
int j1 = boxc.dy_pos + fontmetrics.getAscent() / 2;
int k1 = boxc.dy_neg;
if(flag)
{
eqScan.set_count(l);
BoxC boxc1 = eqn(i, j, true, g, k, false);
int l1 = 3 * ((i1 - fontmetrics.stringWidth(s)) / 4);
if(s.equals(".") | s.equals(".."))
g.drawString(s, i + l1, j - fontmetrics.getAscent());
else
if(s.equals("\uFFFD") | s.equals("`"))
g.drawString(s, i + l1, j - fontmetrics.getAscent() / 3);
else
g.drawString(s, i + l1, j - (fontmetrics.getAscent() * 2) / 3);
}
return new BoxC(i1, j1, k1);
}
 
private BoxC ANGLE(int i, int j, boolean flag, Graphics g)
{
BoxC boxc = new BoxC();
FontMetrics fontmetrics = g.getFontMetrics();
int k = g.getFont().getSize() / 2;
int l = fontmetrics.getHeight() - fontmetrics.getDescent();
int i1 = fontmetrics.getDescent();
if(flag)
{
int j1 = (j - l) + 1;
int k1 = (j + i1) - 1;
int l1 = (j1 + k1) / 2;
if(eqTok.stringS.equals("<"))
{
g.drawLine(i + k, j1, i, l1);
g.drawLine(i, l1, i + k, k1);
} else
{
g.drawLine(i, j1, i + k, l1);
g.drawLine(i + k, l1, i, k1);
}
}
return new BoxC(k, l, i1);
}
 
private BoxC ARRAY(int i, int j, boolean flag, Graphics g, int k)
{
boolean flag1 = false;
boolean flag2 = false;
boolean flag3 = false;
int l1 = 0;
int ai[] = new int[100];
int ai1[] = new int[100];
int ai2[] = new int[100];
BoxC boxc = new BoxC();
int i2 = 0;
FontMetrics fontmetrics = g.getFontMetrics();
int j2 = g.getFont().getSize();
if(flag)
i2 = eqScan.get_count();
if(!expect(3, "ARRAY: BeginSym"))
return new BoxC(0, 0, 0);
int k2 = 0;
do
{
if(k2 >= 99)
break;
int i1 = 0;
int k1 = 0;
int l2 = 0;
do
{
if(l2 >= 99)
break;
BoxC boxc1 = eqn(i, j, false, g, k);
i1 = Math.max(i1, boxc1.dy_pos);
k1 = Math.max(k1, boxc1.dy_neg);
ai[l2] = Math.max(ai[l2], boxc1.dx + j2);
if(eqTok.typ == 8 || eqTok.typ == 4)
break;
l2++;
} while(true);
ai1[k2] = Math.max(ai1[k2], i1);
ai2[k2] = Math.max(ai2[k2], k1);
l1 += i1 + k1;
if(eqTok.typ == 4)
break;
k2++;
} while(true);
k2 = 0;
for(int i3 = 0; i3 < 99; i3++)
k2 += ai[i3];
 
if(flag)
{
eqScan.set_count(i2);
expect(3, "ARRAY: Begin");
int j1 = 0;
int j3 = 0;
do
{
if(j3 >= 99)
break;
int l = 0;
if(j3 == 0)
j1 = ai1[j3];
else
j1 += ai2[j3 - 1] + ai1[j3];
int k3 = 0;
do
{
if(k3 >= 99)
break;
BoxC boxc2 = eqn(i + l, (j - l1 / 2 - fontmetrics.getDescent()) + j1, true, g, k);
l += ai[k3];
if(eqTok.typ == 8 || eqTok.typ == 4)
break;
k3++;
} while(true);
if(eqTok.typ == 4)
break;
j3++;
} while(true);
}
return new BoxC(k2 - j2, l1 / 2 + fontmetrics.getDescent(), l1 / 2 - fontmetrics.getDescent());
}
 
private BoxC BEGIN(int i, int j, boolean flag, Graphics g, int k)
{
int i1 = 0;
int j2 = 0;
int ai[] = new int[100];
int ai1[] = new int[100];
int ai2[] = new int[100];
int ai3[] = new int[100];
int ai4[] = new int[100];
int k2 = 0;
int l2 = 0;
int i3 = 0;
BoxC boxc = new BoxC();
int j3 = 0;
FontMetrics fontmetrics = g.getFontMetrics();
int k4 = g.getFont().getSize();
int l4 = 0;
boolean flag1 = false;
boolean flag3 = false;
boolean flag4 = true;
boolean flag5 = true;
boolean flag6 = false;
boolean flag7 = false;
if(!expect(3))
return new BoxC(0, 0, 0);
if(eqScan.nextToken().stringS.equals("eqnarray"))
flag5 = false;
if(!expect(4, "BEGIN: EndSym"))
return new BoxC(0, 0, 0);
if(flag5)
{
j3 = eqScan.get_count();
if(!expect(3))
{
flag4 = false;
eqScan.set_count(j3);
}
}
if(flag5 && flag4)
{
EqToken eqtoken = new EqToken();
for(EqToken eqtoken1 = eqScan.nextToken(); eqtoken1.typ != 4; eqtoken1 = eqScan.nextToken())
{
StringBuffer stringbuffer = new StringBuffer(eqtoken1.stringS);
for(int l6 = 0; l6 < stringbuffer.length(); l6++)
label0:
switch(stringbuffer.charAt(l6))
{
case 108: // 'l'
ai3[l4] = 1;
if(l4 < 99)
l4++;
break;
 
case 99: // 'c'
ai3[l4] = 2;
if(l4 < 99)
l4++;
break;
 
case 114: // 'r'
ai3[l4] = 3;
if(l4 < 99)
l4++;
break;
 
case 64: // '@'
ai3[l4] = 4;
ai4[l4] = eqScan.get_count();
BoxC boxc1 = eqn(i, j, false, g, k, false);
k2 += boxc1.dx;
l2 = Math.max(l2, boxc1.dy_pos);
i3 = Math.max(i3, boxc1.dy_neg);
if(l4 < 99)
l4++;
break;
 
case 42: // '*'
expect(3, "Begin *{");
int j5;
try
{
j5 = Integer.parseInt(eqScan.nextToken().stringS);
}
catch(NumberFormatException numberformatexception)
{
j5 = 0;
}
expect(4, 3, "Begin }{");
int j7 = eqScan.get_count();
int k7 = 0;
do
{
if(k7 >= j5)
break label0;
eqScan.set_count(j7);
for(eqtoken1 = eqScan.nextToken(); eqtoken1.typ != 4; eqtoken1 = eqScan.nextToken())
{
StringBuffer stringbuffer1 = new StringBuffer(eqtoken1.stringS);
for(int l7 = 0; l7 < stringbuffer1.length(); l7++)
switch(stringbuffer1.charAt(l7))
{
case 108: // 'l'
ai3[l4] = 1;
if(l4 < 99)
l4++;
break;
 
case 99: // 'c'
ai3[l4] = 2;
if(l4 < 99)
l4++;
break;
 
case 114: // 'r'
ai3[l4] = 3;
if(l4 < 99)
l4++;
break;
 
case 64: // '@'
ai3[l4] = 4;
ai4[l4] = eqScan.get_count();
BoxC boxc2 = eqn(i, j, false, g, k, false);
k2 += boxc2.dx;
l2 = Math.max(l2, boxc2.dy_pos);
i3 = Math.max(i3, boxc2.dy_neg);
if(l4 < 99)
l4++;
break;
 
default:
printStatus("P: begin: illegal format 2");
break;
}
 
}
 
k7++;
} while(true);
 
default:
printStatus("P: begin: illegal format 1");
break;
}
 
}
 
}
if(!flag5)
{
ai3[0] = 3;
ai3[1] = 2;
ai3[2] = 1;
l4 = 3;
}
for(int k5 = 0; k5 < l4 - 1; k5++)
if(ai3[k5] != 4 && ai3[k5 + 1] != 4)
i1 += k4 / 2;
 
if(flag)
j3 = eqScan.get_count();
int l5 = 0;
do
{
if(l5 >= 99)
break;
int j1 = 0;
int l1 = 0;
int j6 = 0;
do
{
if(j6 >= 99)
break;
BoxC boxc3 = eqn(i, j, false, g, k);
j1 = Math.max(j1, boxc3.dy_pos);
l1 = Math.max(l1, boxc3.dy_neg);
ai[j6] = Math.max(ai[j6], boxc3.dx);
if(eqTok.typ == 8 || eqTok.typ == 51)
break;
j6++;
} while(true);
j1 = Math.max(j1, l2);
l1 = Math.max(l1, i3);
ai1[l5] = j1;
ai2[l5] = l1;
j2 += j1 + l1;
if(eqTok.typ == 51)
break;
l5++;
} while(true);
for(int i5 = 0; i5 < 99; i5++)
i1 += ai[i5];
 
i1 += (2 * k4) / 2;
if(flag)
{
eqScan.set_count(j3);
int k1 = 0;
int i2 = j2 / 2 + fontmetrics.getDescent();
int i6 = 0;
do
{
if(i6 >= 99)
break;
int l = k4 / 2;
if(i6 == 0)
k1 = ai1[i6];
else
k1 += ai2[i6 - 1] + ai1[i6];
int k6 = 0;
int i7 = 0;
do
{
if(i7 >= 99)
break;
for(; ai3[k6] == 4; k6++)
{
int k3 = eqScan.get_count();
eqScan.set_count(ai4[k6]);
BoxC boxc4 = eqn(i + l, (j - i2) + k1, true, g, k, false);
l += boxc4.dx;
eqScan.set_count(k3);
}
 
switch(ai3[k6])
{
case 0: // '\0'
case 1: // '\001'
BoxC boxc5 = eqn(i + l, (j - i2) + k1, true, g, k);
k6++;
break;
 
case 2: // '\002'
int l3 = eqScan.get_count();
BoxC boxc6 = eqn(i, j, false, g, k);
eqScan.set_count(l3);
boxc6 = eqn(i + l + (ai[i7] - boxc6.dx) / 2, (j - i2) + k1, true, g, k);
k6++;
break;
 
case 3: // '\003'
int i4 = eqScan.get_count();
BoxC boxc7 = eqn(i, j, false, g, k);
eqScan.set_count(i4);
boxc7 = eqn((i + l + ai[i7]) - boxc7.dx, (j - i2) + k1, true, g, k);
k6++;
break;
}
if(ai3[k6] != 4)
l += k4 / 2;
l += ai[i7];
boolean flag2 = false;
flag3 = false;
if(eqTok.typ == 8)
flag2 = true;
else
if(eqTok.typ == 51)
{
flag2 = true;
flag3 = true;
}
for(; ai3[k6] == 4; k6++)
{
int j4 = eqScan.get_count();
eqScan.set_count(ai4[k6]);
BoxC boxc8 = eqn(i + l, (j - i2) + k1, true, g, k, false);
l += boxc8.dx;
eqScan.set_count(j4);
}
 
if(flag2)
break;
i7++;
} while(true);
if(flag3)
break;
i6++;
} while(true);
}
if(!expect(3, "BEGIN 2: begin"))
return new BoxC(0, 0, 0);
eqScan.nextToken();
if(!expect(4, "BEGIN 2: end"))
return new BoxC(0, 0, 0);
else
return new BoxC(i1 + k2, j2 / 2 + fontmetrics.getDescent(), j2 / 2 - fontmetrics.getDescent());
}
 
private BoxC FBOX(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = g.getFont().getSize() / 2;
boxc = eqn(i + l, j, flag, g, k, false);
if(flag)
g.drawRect(i + l / 2, j - boxc.dy_pos - l / 2, boxc.dx + l, boxc.dy_pos + boxc.dy_neg + l);
return new BoxC(boxc.dx + l + l, boxc.dy_pos + l, boxc.dy_neg + l);
}
 
private BoxC FG_BGColor(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
BoxC boxc = new BoxC();
int l = 0;
Color color = Color.white;
if(!expect(3, "Color: BeginSym"))
return new BoxC(0, 0, 0);
StringBuffer stringbuffer = new StringBuffer("");
int i1 = 1;
do
{
if(i1 >= 7)
break;
stringbuffer.append(eqScan.nextToken().stringS);
if(stringbuffer.length() == 6)
break;
i1++;
} while(true);
try
{
color = new Color(Integer.parseInt(stringbuffer.toString(), 16));
}
catch(NumberFormatException numberformatexception)
{
BGColor = Color.white;
}
if(!expect(4, "Color: EndSym"))
return new BoxC(0, 0, 0);
if(flag)
l = eqScan.get_count();
Color color1 = g.getColor();
if(flag1)
g.setColor(color);
boxc = eqn(i, j, false, g, k, false);
g.setColor(color1);
if(flag)
{
eqScan.set_count(l);
g.setColor(color);
if(!flag1)
{
g.fillRect(i, j - boxc.dy_pos, boxc.dx, boxc.dy_pos + boxc.dy_neg);
g.setColor(color1);
}
boxc = eqn(i, j, true, g, k, false);
g.setColor(color1);
}
return boxc;
}
 
private BoxC FRAC(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
int l = 0;
BoxC boxc = new BoxC();
BoxC boxc2 = new BoxC();
BoxC boxc3 = new BoxC();
int i1 = 0;
Font font = g.getFont();
int j1 = font.getSize();
rec_Font(g, k + 1);
FontMetrics fontmetrics = g.getFontMetrics();
if(flag)
i1 = eqScan.get_count();
boxc2 = eqn(i, j, false, g, k + 1, false);
int k1 = boxc2.dy_pos + boxc2.dy_neg;
boxc3 = eqn(i, j, false, g, k + 1, false);
int l1 = Math.max(boxc2.dx, boxc3.dx);
int i2 = boxc3.dy_pos + boxc3.dy_neg;
Font font1 = g.getFont();
int j2 = (3 * font1.getSize()) / 18;
l1 += 2 * j2;
if(fontmetrics.getAscent() < i2)
l = fontmetrics.getAscent() / 2;
k1 += 2 + l;
i2 += 1 - l;
if(flag)
{
eqScan.set_count(i1);
if(flag1)
g.drawLine(i + j2, j - l, (i + l1) - j2, j - l);
BoxC boxc1 = eqn(i + (l1 - boxc2.dx) / 2, j - 2 - boxc2.dy_neg - l, true, g, k + 1, false);
if(editModeFind && k < editModeRec)
editModeRec = k;
boxc1 = eqn(i + (l1 - boxc3.dx) / 2, (j + 1 + boxc3.dy_pos) - l, true, g, k + 1, false);
}
rec_Font(g, k);
return new BoxC(l1, k1, i2);
}
 
private BoxC Id(int i, int j, boolean flag, Graphics g)
{
Font font = g.getFont();
g.setFont(new Font(Fontname, 2, font.getSize()));
FontMetrics fontmetrics = g.getFontMetrics();
if(flag)
g.drawString(eqTok.stringS, i, j);
int k = fontmetrics.stringWidth(eqTok.stringS);
int l = fontmetrics.getHeight() - fontmetrics.getDescent();
int i1 = fontmetrics.getDescent();
g.setFont(font);
return new BoxC(k, l, i1);
}
 
private void arc(Graphics g, int i, int j, int k, int l, int i1)
{
g.drawArc(i - k, j - k, 2 * k, 2 * k, l, i1);
}
 
private void drawBracket(Graphics g, String s, int i, int j, int k, int l, int i1,
int j1)
{
int k1 = j / 2;
int l1 = i + k1;
int i2 = i + j;
int j2 = i + k1 / 2;
int k2 = l1 + k1 / 2;
int l2 = (k + l) / 2;
int i3 = (int)((double)k1 * 0.86602540378444004D);
int j3 = k + i3;
int k3 = l - i3;
if(s.equals("["))
{
g.drawLine(j2, k, j2, l);
g.drawLine(j2, l, k2, l);
g.drawLine(j2, k, k2, k);
} else
if(s.equals("]"))
{
g.drawLine(k2, k, k2, l);
g.drawLine(j2, l, k2, l);
g.drawLine(j2, k, k2, k);
} else
if(s.equals("|"))
g.drawLine(l1, k, l1, l);
else
if(s.equals("||"))
{
int l3 = l1 + i1 / 4;
g.drawLine(l1, k, l1, l);
g.drawLine(l3, k, l3, l);
} else
if(s.equals("("))
{
for(int i4 = j1; i4 < 2 + j1; i4++)
{
int i5 = j2 + i4;
arc(g, k2 + i4, j3, k1, 180, -60);
g.drawLine(i5, j3, i5, k3);
arc(g, k2 + i4, k3, k1, 180, 60);
}
 
} else
if(s.equals(")"))
{
for(int j4 = j1; j4 < 2 + j1; j4++)
{
int j5 = k2 + j4;
arc(g, j2 + j4, j3, k1, 0, 60);
g.drawLine(j5, j3, j5, k3);
arc(g, j2 + j4, k3, k1, 0, -60);
}
 
} else
if(s.equals("<"))
{
g.drawLine(j2, l2, k2, k);
g.drawLine(j2, l2, k2, l);
} else
if(s.equals(">"))
{
g.drawLine(k2, l2, j2, k);
g.drawLine(k2, l2, j2, l);
} else
if(s.equals("{"))
{
for(int k4 = j1; k4 < 2 + j1; k4++)
{
int k5 = l1 + k4;
arc(g, i2 + k4, j3, k1, 180, -60);
g.drawLine(k5, j3, k5, l2 - k1);
arc(g, i + k4, l2 - k1, k1, 0, -90);
arc(g, i + k4, l2 + k1, k1, 0, 90);
g.drawLine(k5, l2 + k1, k5, k3);
arc(g, i2 + k4, k3, k1, 180, 60);
}
 
} else
if(s.equals("}"))
{
for(int l4 = j1; l4 < 2 + j1; l4++)
{
int l5 = l1 + l4;
arc(g, i + l4, j3, k1, 0, 60);
g.drawLine(l5, j3, l5, l2 - k1);
arc(g, i2 + l4, l2 - k1, k1, -180, 90);
arc(g, i2 + l4, l2 + k1, k1, 180, -90);
g.drawLine(l5, l2 + k1, l5, k3);
arc(g, i + l4, k3, k1, 0, -60);
}
 
}
}
 
private BoxC LEFT(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
int i1 = 0;
BoxC boxc = new BoxC();
int j1 = 0;
Font font = g.getFont();
int k1 = font.getSize();
int l1 = (int)(2.0F * (float)k1);
int i2 = k1 / 9;
if(flag)
j1 = eqScan.get_count();
String s = eqScan.nextToken().stringS;
boxc = eqn(i, j, false, g, k);
int j2 = boxc.dx;
int k2 = boxc.dy_pos;
int l2 = boxc.dy_neg;
int i3 = (j - k2) + 1;
int j3 = (j + l2) - 1;
String s2 = eqScan.nextToken().stringS;
int k3 = (k2 + l2) - 2;
Font font1 = new Font("Helvetica", 0, k3);
g.setFont(font1);
FontMetrics fontmetrics = g.getFontMetrics();
if(s.equals("<") || s.equals(">"))
l = k1;
else
if(k3 < l1)
{
l = fontmetrics.stringWidth(s);
if("([{)]}".indexOf(s) >= 0)
l += i2;
} else
{
l = k1;
}
if(s2.equals("<") || s2.equals(">"))
i1 = k1;
else
if(k3 < l1)
{
i1 = fontmetrics.stringWidth(s2);
if("([{)]}".indexOf(s2) >= 0)
i1 += i2;
} else
{
i1 = k1;
}
g.setFont(font);
int l3 = eqScan.get_count();
int j4 = 0;
int k4 = 0;
if(eqScan.nextToken().typ == 11)
{
BoxC boxc1 = SUB(i, j, false, g, k, false);
j4 = boxc1.dx;
k4 = (j3 + boxc1.dy_pos) - (boxc1.dy_pos + boxc1.dy_neg) / 2;
l2 += (boxc1.dy_pos + boxc1.dy_neg) / 2;
} else
{
eqScan.set_count(l3);
}
int l4 = eqScan.get_count();
int j5 = 0;
int k5 = 0;
if(eqScan.nextToken().typ == 10)
{
BoxC boxc2 = SUP(i, j, false, g, k, false);
j5 = boxc2.dx;
k5 = (i3 + boxc2.dy_pos) - (boxc2.dy_pos + boxc2.dy_neg) / 2;
k2 += (boxc2.dy_pos + boxc2.dy_neg) / 2;
} else
{
eqScan.set_count(l4);
}
j4 = Math.max(j4, j5);
if(flag)
{
eqScan.set_count(j1);
String s1 = eqScan.nextToken().stringS;
if(!s1.equals("."))
if(k3 < l1 && !s1.equals("<") && !s1.equals(">"))
{
g.setFont(font1);
g.drawString(s1, i, j3 - fontmetrics.getDescent() - fontmetrics.getLeading() / 2);
g.setFont(font);
} else
{
drawBracket(g, s1, i, l, i3, j3, k1, 0);
}
BoxC boxc3 = eqn(i + l, j, true, g, k);
String s3 = eqScan.nextToken().stringS;
if(!s3.equals("."))
if(k3 < l1 && !s3.equals("<") && !s3.equals(">"))
{
g.setFont(font1);
if("([{)]}".indexOf(s3) < 0)
i2 = 0;
g.drawString(s3, i + j2 + l + i2, j3 - fontmetrics.getDescent() - fontmetrics.getLeading() / 2);
g.setFont(font);
} else
{
drawBracket(g, s3, i + j2 + l, i1, i3, j3, -k1, -1);
}
int i4 = eqScan.get_count();
if(expect(11))
boxc3 = SUB(i + j2 + l + i1, k4, true, g, k, false);
else
eqScan.set_count(i4);
int i5 = eqScan.get_count();
if(expect(10))
boxc3 = SUP(i + j2 + l + i1, k5, true, g, k, false);
else
eqScan.set_count(i5);
}
return new BoxC(j2 + l + i1 + j4, k2 + 2, l2 + 2);
}
 
private BoxC LIM(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
BoxC boxc = new BoxC();
int i1 = 0;
int j1 = 0;
FontMetrics fontmetrics = g.getFontMetrics();
String s = eqTok.stringS;
int k1 = eqScan.get_count();
int l1 = l = fontmetrics.stringWidth(s);
int i2 = fontmetrics.getHeight() - fontmetrics.getDescent();
int j2 = fontmetrics.getDescent();
if(expect(11))
{
BoxC boxc1 = SUB(i, j, false, g, k, false);
i1 = boxc1.dx;
l = Math.max(l, boxc1.dx);
j1 = boxc1.dy_pos;
j2 = boxc1.dy_pos + boxc1.dy_neg;
} else
{
eqScan.set_count(k1);
}
if(flag)
{
eqScan.set_count(k1);
g.drawString(s, i + (l - l1) / 2, j);
BoxC boxc2;
if(expect(11))
boxc2 = SUB(i + (l - i1) / 2, j + j1, true, g, k, false);
else
eqScan.set_count(k1);
}
return new BoxC(l, i2, j2);
}
 
private BoxC MBOX(int i, int j, boolean flag, Graphics g)
{
int k = 0;
int l = 0;
int i1 = 0;
BoxC boxc = new BoxC();
if(!expect(3))
return new BoxC(0, 0, 0);
do
{
if(eqScan.EoT())
break;
eqTok = eqScan.nextToken();
if(eqTok.typ == 4)
break;
BoxC boxc1 = Plain(i + k, j, flag, g);
k += boxc1.dx;
l = Math.max(l, boxc1.dy_pos);
i1 = Math.max(i1, boxc1.dy_neg);
} while(true);
return new BoxC(k, l, i1);
}
 
private BoxC NOT(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
boxc = eqn(i, j, flag, g, k, false);
if(flag)
g.drawLine(i + boxc.dx / 4, j + boxc.dy_neg, i + (boxc.dx * 3) / 4, j - boxc.dy_pos);
return boxc;
}
 
private BoxC Op(int i, int j, boolean flag, Graphics g)
{
FontMetrics fontmetrics = g.getFontMetrics();
if(flag)
g.drawString(eqTok.stringS, i + 1, j);
return new BoxC(fontmetrics.stringWidth(eqTok.stringS) + 2, fontmetrics.getHeight() - fontmetrics.getDescent(), fontmetrics.getDescent());
}
 
private BoxC OverBRACE(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
BoxC boxc = new BoxC();
int i1 = g.getFont().getSize() / 4;
int j1 = i1 / 2;
int k1 = 0;
int l1 = 0;
int i2 = 0;
if(flag)
l = eqScan.get_count();
boxc = eqn(i, j, false, g, k, false);
int j2 = boxc.dx;
int k2 = j2 / 2;
int l2 = k2;
int i3 = boxc.dy_pos;
int j3 = boxc.dy_neg;
int k3 = eqScan.get_count();
if(expect(10))
{
BoxC boxc1 = SUP(i, j, false, g, k, false);
k1 = boxc1.dx;
l2 = Math.max(l2, k1 / 2);
l1 = i3 + boxc1.dy_neg;
i2 = boxc1.dy_pos + boxc1.dy_neg;
} else
{
eqScan.set_count(k3);
}
if(flag)
{
eqScan.set_count(l);
int i4 = (i + l2) - k2;
BoxC boxc2 = eqn(i4, j, true, g, k, false);
int j4 = (int)((double)i1 * 0.86602540378444004D);
for(int k4 = 0; k4 < 2; k4++)
{
int l4 = (j - i3 - j1) + k4;
arc(g, i4 + j4, l4 + i1, i1, 90, 60);
g.drawLine(i4 + j4, l4, (i4 + k2) - i1, l4);
arc(g, (i4 + k2) - i1, l4 - i1, i1, 0, -90);
arc(g, i4 + k2 + i1, l4 - i1, i1, -90, -90);
g.drawLine(i4 + k2 + i1, l4, (i4 + j2) - j4, l4);
arc(g, (i4 + j2) - j4, l4 + i1, i1, 90, -60);
}
 
int l3 = eqScan.get_count();
if(expect(10))
boxc2 = SUP((i + l2) - k1 / 2, j - l1 - i1 - j1, true, g, k, false);
else
eqScan.set_count(l3);
}
i3 += i2 + i1 + j1;
j2 = Math.max(j2, k1);
return new BoxC(j2, i3, j3);
}
 
private BoxC UnderBRACE(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
BoxC boxc = new BoxC();
int i1 = g.getFont().getSize() / 4;
int j1 = i1 / 2;
int k1 = 0;
int l1 = 0;
int i2 = 0;
if(flag)
l = eqScan.get_count();
boxc = eqn(i, j, false, g, k, false);
int j2 = boxc.dx;
int k2 = j2 / 2;
int l2 = k2;
int i3 = boxc.dy_pos;
int j3 = boxc.dy_neg;
int k3 = eqScan.get_count();
if(expect(11))
{
BoxC boxc1 = SUB(i, j, false, g, k, false);
k1 = boxc1.dx;
l2 = Math.max(l2, k1 / 2);
l1 = j3 + boxc1.dy_pos;
i2 = boxc1.dy_pos + boxc1.dy_neg;
} else
{
eqScan.set_count(k3);
}
if(flag)
{
eqScan.set_count(l);
int i4 = (i + l2) - k2;
BoxC boxc2 = eqn(i4, j, true, g, k, false);
int j4 = (int)((double)i1 * 0.86602540378444004D);
for(int k4 = 0; k4 < 2; k4++)
{
int l4 = (j + j3 + j1) - k4;
arc(g, i4 + j4, l4 - i1, i1, -90, -60);
g.drawLine(i4 + j4, l4, (i4 + k2) - i1, l4);
arc(g, (i4 + k2) - i1, l4 + i1, i1, 90, -90);
arc(g, i4 + k2 + i1, l4 + i1, i1, 90, 90);
g.drawLine(i4 + k2 + i1, l4, (i4 + j2) - j4, l4);
arc(g, (i4 + j2) - j4, l4 - i1, i1, -90, 60);
}
 
int l3 = eqScan.get_count();
if(eqScan.nextToken().typ == 11)
boxc2 = SUB((i + l2) - k1 / 2, j + l1 + i1 + j1, true, g, k, false);
else
eqScan.set_count(l3);
}
j3 += i2 + i1 + j1;
j2 = Math.max(j2, k1);
return new BoxC(j2, i3, j3);
}
 
private BoxC OverUnderLINE(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
int l = 0;
BoxC boxc = new BoxC();
if(flag)
l = eqScan.get_count();
boxc = eqn(i, j, false, g, k, false);
if(flag1)
boxc.dy_pos += 2;
else
boxc.dy_neg += 2;
int i1 = boxc.dy_pos;
int j1 = boxc.dy_neg;
if(flag)
{
eqScan.set_count(l);
if(flag1)
g.drawLine(i + 1, (j - i1) + 2, (i + boxc.dx) - 1, (j - i1) + 2);
else
g.drawLine(i, (j + j1) - 2, i + boxc.dx, (j + j1) - 2);
boxc = eqn(i, j, true, g, k, false);
}
return new BoxC(boxc.dx, i1, j1);
}
 
private BoxC Paren(int i, int j, boolean flag, Graphics g)
{
FontMetrics fontmetrics = g.getFontMetrics();
int k = g.getFont().getSize() / 9;
int l = fontmetrics.stringWidth(eqTok.stringS);
int i1 = "([{)]}".indexOf(eqTok.stringS);
if(i1 >= 0)
{
l += k;
if(i1 > 2)
i += k;
}
if(flag)
g.drawString(eqTok.stringS, i, j);
return new BoxC(l, fontmetrics.getHeight() - fontmetrics.getDescent(), fontmetrics.getDescent());
}
 
private BoxC Plain(int i, int j, boolean flag, Graphics g)
{
FontMetrics fontmetrics = g.getFontMetrics();
if(flag)
g.drawString(eqTok.stringS, i, j);
return new BoxC(fontmetrics.stringWidth(eqTok.stringS), fontmetrics.getHeight() - fontmetrics.getDescent(), fontmetrics.getDescent());
}
 
private BoxC SPACE(int i, int j, boolean flag, Graphics g)
{
int k = 0;
Font font = g.getFont();
try
{
k = Integer.parseInt(eqTok.stringS);
}
catch(NumberFormatException numberformatexception)
{
k = 0;
}
k = (k * font.getSize()) / 18;
return new BoxC(k, 0, 0);
}
 
private BoxC SQRT(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = 0;
FontMetrics fontmetrics = g.getFontMetrics();
int i1 = 0;
boolean flag1 = false;
int k1 = 0;
int l1 = 0;
boolean flag2 = false;
if(flag)
l = eqScan.get_count();
int i2 = fontmetrics.stringWidth("A");
int j2 = i2 / 2;
int k2 = eqScan.get_count();
EqToken eqtoken = new EqToken();
eqtoken = eqScan.nextToken();
if(eqtoken.stringS.equals("["))
{
rec_Font(g, k + 1);
boxc = eqn(i, j, false, g, k + 1, true);
rec_Font(g, k);
i1 = boxc.dx;
int j1 = boxc.dy_pos;
k1 = boxc.dy_neg;
l1 = k1 + j1;
flag2 = true;
} else
{
eqScan.set_count(k2);
}
boxc = eqn(i, j, false, g, k, false);
int l2 = boxc.dx + i2;
int i3 = boxc.dy_pos + 2;
int j3 = boxc.dy_neg;
if(flag2 & (i1 > j2))
l2 += i1 - j2;
if(flag)
{
eqScan.set_count(l);
int k3 = 0;
if(flag2 & (i1 > j2))
k3 = i1 - j2;
g.drawLine(i + k3 + 1, j - i3 / 2, i + k3 + j2, (j + j3) - 1);
g.drawLine(i + k3 + j2, (j + j3) - 1, (i + k3 + i2) - 2, (j - i3) + 2);
g.drawLine((i + k3 + i2) - 2, (j - i3) + 2, i + l2, (j - i3) + 2);
if(flag2)
{
EqToken eqtoken1 = eqScan.nextToken();
rec_Font(g, k + 1);
BoxC boxc2;
if(i1 >= j2)
{
g.drawLine(i + 1, j - i3 / 2, i + k3 + 1, j - i3 / 2);
BoxC boxc1 = eqn(i + 1, j - i3 / 2 - k1 - 1, true, g, k + 1, true);
} else
{
boxc2 = eqn(i + 1 + (j2 - i1), j - i3 / 2 - k1 - 1, true, g, k + 1, true);
}
rec_Font(g, k);
}
BoxC boxc3 = eqn(i + k3 + i2, j, true, g, k, false);
}
if(flag2 & (i3 / 2 < l1))
i3 = i3 / 2 + l1;
return new BoxC(l2, i3, j3);
}
 
private BoxC STACKREL(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = 0;
int i1 = g.getFontMetrics().getLeading();
if(flag)
l = eqScan.get_count();
boxc = SUP(i, j, false, g, k, true);
int j1 = boxc.dx;
int k1 = boxc.dx;
int l1 = (boxc.dy_pos + boxc.dy_neg) - i1;
int i2 = boxc.dy_neg - i1;
boxc = eqn(i, j, false, g, k, false);
j1 = Math.max(j1, boxc.dx);
int j2 = j1 / 2;
int k2 = boxc.dx;
l1 += boxc.dy_pos;
int l2 = boxc.dy_neg;
i2 += boxc.dy_pos;
if(flag)
{
eqScan.set_count(l);
BoxC boxc1 = SUP((i + j2) - k1 / 2, j - i2, true, g, k, false);
boxc1 = eqn((i + j2) - k2 / 2, j, true, g, k, false);
}
return new BoxC(j1, l1, l2);
}
 
private BoxC SUB(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
int l = 0;
int i1 = 0;
BoxC boxc = new BoxC();
int j1 = 0;
int l1 = g.getFontMetrics().getAscent() / 2;
if(flag)
j1 = eqScan.get_count();
rec_Font(g, k + 1);
boxc = eqn(i, j, false, g, k + 1, false);
int i2 = boxc.dx;
if(flag1)
{
l = l1 - 1;
i1 = (boxc.dy_pos + boxc.dy_neg) - l;
} else
{
i1 = boxc.dy_pos + boxc.dy_neg;
}
if(flag)
{
eqScan.set_count(j1);
if(flag1)
boxc = eqn(i, (j + boxc.dy_pos) - l, true, g, k + 1, false);
else
boxc = eqn(i, j + boxc.dy_pos, true, g, k + 1, false);
}
rec_Font(g, k);
if(flag1)
{
int k1 = eqScan.get_count();
if(expect(10))
{
BoxC boxc1 = SUP(i, j, flag, g, k, true);
i2 = Math.max(i2, boxc1.dx);
l = Math.max(l, boxc1.dy_pos);
} else
{
eqScan.set_count(k1);
}
}
return new BoxC(i2, l, i1);
}
 
private BoxC SUP(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
int l = 0;
int i1 = 0;
BoxC boxc = new BoxC();
int j1 = 0;
int l1 = g.getFontMetrics().getAscent() / 2;
if(flag)
j1 = eqScan.get_count();
rec_Font(g, k + 1);
boxc = eqn(i, j, false, g, k + 1, false);
int i2 = boxc.dx;
if(flag1)
{
i1 = -l1 - 1;
l = (boxc.dy_pos + boxc.dy_neg) - i1;
} else
{
l = boxc.dy_pos + boxc.dy_neg;
}
if(flag)
{
eqScan.set_count(j1);
if(flag1)
boxc = eqn(i, (j - boxc.dy_neg) + i1, true, g, k + 1, false);
else
boxc = eqn(i, j - boxc.dy_neg, true, g, k + 1, false);
}
rec_Font(g, k);
if(flag1)
{
int k1 = eqScan.get_count();
if(expect(11))
{
BoxC boxc1 = SUB(i, j, flag, g, k, true);
i2 = Math.max(i2, boxc1.dx);
i1 = Math.max(i1, boxc1.dy_neg);
} else
{
eqScan.set_count(k1);
}
}
return new BoxC(i2, l, i1);
}
 
private Image getSymbol(Graphics g, int i)
{
String s = (new StringBuilder()).append(eqTok.stringS).append(GreekSize[i - 1]).append(g.getColor().getRGB()).toString();
if(!imageH.containsKey(s))
{
String s1 = (new StringBuilder()).append("Fonts/Greek").append(GreekSize[i - 1]).append("/").append(eqTok.stringS).append(".gif").toString();
Image image = symbolLoader.getImage(appletB, beanB, s1, g, app);
int j = eqScan.get_count();
tracker.addImage(image, j);
displayStatus((new StringBuilder()).append("Loading ").append(eqTok.stringS).toString());
try
{
tracker.waitForID(j, 10000L);
}
catch(InterruptedException interruptedexception) { }
if(tracker.isErrorID(j))
displayStatus((new StringBuilder()).append("Error loading ").append(eqTok.stringS).toString());
else
imageH.put(s, image);
return image;
} else
{
return (Image)(Image)imageH.get(s);
}
}
 
private BoxC SYMBOP(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
FontMetrics fontmetrics = g.getFontMetrics();
k = Math.min(k, GreekSize.length);
Image image = getSymbol(g, k);
int l = image.getWidth(this);
if(l < 0)
l = fontmetrics.getMaxAdvance();
if(flag)
{
int i1 = 0;
if(flag1)
i1 = GreekDescent[k - 1];
g.drawImage(image, i, (j - image.getHeight(this)) + i1, this);
}
return new BoxC(l, fontmetrics.getHeight() - fontmetrics.getDescent(), fontmetrics.getDescent());
}
 
private BoxC SYMBOLBIG(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
BoxC boxc = new BoxC();
int i1 = 0;
int j1 = 0;
int k1 = 0;
int l1 = 0;
int i2 = 0;
int j2 = g.getFontMetrics().getAscent();
k = Math.min(k, GreekSize.length);
Image image = getSymbol(g, k);
int k2 = l = image.getWidth(this);
int l2 = image.getHeight(this);
if(l2 < 0)
{
l2 = 2 * j2;
k2 = l = j2;
}
int i3 = (int)((double)(l2 / 2) - 0.40000000000000002D * (double)j2);
int j3 = i2 = l2 - i3;
int k3 = eqScan.get_count();
if(expect(11))
{
BoxC boxc1 = SUB(i, j, false, g, k, false);
k1 = boxc1.dx;
l = Math.max(l, boxc1.dx);
i1 = i3 + boxc1.dy_pos;
i3 += boxc1.dy_pos + boxc1.dy_neg;
} else
{
eqScan.set_count(k3);
}
int l3 = eqScan.get_count();
if(expect(10))
{
BoxC boxc2 = SUP(i, j, false, g, k, false);
l1 = boxc2.dx;
l = Math.max(l, boxc2.dx);
j1 = j3 + boxc2.dy_neg;
j3 += boxc2.dy_pos + boxc2.dy_neg;
} else
{
eqScan.set_count(l3);
}
if(flag)
{
eqScan.set_count(k3);
g.drawImage(image, i + (l - k2) / 2, j - i2, this);
BoxC boxc3;
if(expect(11))
boxc3 = SUB(i + (l - k1) / 2, j + i1, true, g, k, false);
else
eqScan.set_count(k3);
int i4 = eqScan.get_count();
if(expect(10))
boxc3 = SUP(i + (l - l1) / 2, j - j1, true, g, k, false);
else
eqScan.set_count(i4);
}
return new BoxC(l, j3, i3);
}
 
private BoxC VEC(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = g.getFont().getSize();
String s = eqTok.stringS;
boxc = eqn(i, j, flag, g, k, false);
int i1 = boxc.dx;
int j1 = i1 / 2;
int k1 = l / 4;
int l1 = boxc.dy_pos + k1;
int i2 = boxc.dy_neg;
if(flag)
{
int j2 = (j - l1) + k1;
int k2 = l / 8;
int l2 = i + i1;
int i3 = i + j1;
if(s.equals(""))
{
g.drawLine(i, j2, l2, j2);
g.drawLine(i + (int)((double)i1 * 0.80000000000000004D), j2 - k2, l2, j2);
g.drawLine(i + (int)((double)i1 * 0.80000000000000004D), j2 + k2, l2, j2);
} else
if(s.equals("bar"))
g.drawLine(i, j2, l2, j2);
else
if(s.equals("widehat"))
{
g.drawLine(i, j2, i3, j2 - k1);
g.drawLine(i3, j2 - k1, l2, j2);
} else
if(s.equals("widetilde"))
{
boolean flag1 = false;
int k3 = 0;
for(int l3 = 1; l3 < j1; l3++)
{
int j3 = k3;
k3 = (int)((double)k2 * Math.sin((4.0840704496667311D * (double)l3) / (double)j1));
g.drawLine((i3 + l3) - 1, j2 + j3, i3 + l3, j2 + k3);
g.drawLine((i3 - l3) + 1, j2 - j3, i3 - l3, j2 - k3);
}
 
}
}
return new BoxC(i1, l1 + 2, i2);
}
 
private boolean expect(int i)
{
return expect(i, "");
}
 
private boolean expect(int i, String s)
{
int j;
while((j = eqScan.nextToken().typ) == 25) ;
if(j == i)
return true;
if(!s.equals(""))
printStatus((new StringBuilder()).append("Parser: ").append(s).append(" not found").toString());
return false;
}
 
private boolean expect(int i, int j)
{
return expect(i, j, "");
}
 
private boolean expect(int i, int j, String s)
{
int k;
while((k = eqScan.nextToken().typ) == 25) ;
boolean flag = k == i;
while((k = eqScan.nextToken().typ) == 25) ;
flag = k == j;
if(!flag && !s.equals(""))
printStatus((new StringBuilder()).append("Parser: ").append(s).append(" not found").toString());
return flag;
}
 
private void rec_Font(Graphics g, int i)
{
if(i <= 1)
g.setFont(f1);
else
if(i == 2)
g.setFont(f2);
else
if(i == 3)
g.setFont(f3);
else
g.setFont(f4);
}
 
private static final String VERSION = "sHotEqn V 4.00 ";
private int width;
private int height;
private String nameS;
private String equation;
private String Fontname;
ActionListener actionListener;
private EqScanner eqScan;
private EqToken eqTok;
private Font f1;
private Font f2;
private Font f3;
private Font f4;
private static final float mk = 2F;
private static final int GreekFontSizes[] = {
8, 10, 12, 14, 18
};
private static final int GreekFontDescents[] = {
2, 3, 4, 5, 6
};
private int GreekSize[] = {
14, 12, 10, 8
};
private int GreekDescent[] = {
3, 3, 3, 3
};
private static final int EmbedFontSizes[] = {
9, 11, 14, 16, 22
};
private Image bufferImage;
private boolean imageOK;
private int localWidth;
private int localHeight;
private Color BGColor;
private Color EnvColor;
private Color FGColor;
private Color BorderColor;
private boolean borderB;
private boolean roundRectBorderB;
private int border;
private String halign;
private String valign;
private int xpos;
private int ypos;
private boolean drawn;
private SymbolLoader symbolLoader;
private MediaTracker tracker;
private Hashtable imageH;
private JApplet app;
public boolean appletB;
public boolean beanB;
public boolean debug;
private boolean editMode;
private boolean editableB;
private int mouse1X;
private int mouse1Y;
private int mouse2X;
private int mouse2Y;
private int xOFF;
private int yOFF;
private int y0;
private int x0;
private int y1;
private int x1;
private int editModeRec;
private boolean editModeFind;
private int editModeCount1;
private int editModeCount2;
private Image selectImage;
public BufferedImage finalimage;
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Fonts14.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Fonts18.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/atp/Des8.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/ArityException.java
0,0 → 1,28
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Thrown when a {@link Function} is evaluated with a wrong number of arguments
(when the number of arguments is not equal to the function's arity).
*/
 
public class ArityException extends Exception {
public ArityException(String mes) {
super(mes);
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/FunctionAndName.java
0,0 → 1,32
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
This class is needed because we want to return both a function and its name.
(work-around for java not supporting multi-value return)
*/
 
public class FunctionAndName {
public Function function;
public String name;
 
public FunctionAndName(Function fun, String name) {
this.function = fun;
this.name = name;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Compiler.java
0,0 → 1,76
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Compiles a textual arithmetic expression to a {@link Function}.<p>
*/
class Compiler {
private final SyntaxException exception = new SyntaxException();
private final Lexer lexer = new Lexer(exception);
private final RPN rpn = new RPN(exception);
private final DeclarationParser declParser = new DeclarationParser(exception);
private final OptCodeGen codeGen = new OptCodeGen(exception);
private final SimpleCodeGen simpleCodeGen = new SimpleCodeGen(exception);
private final Declaration decl = new Declaration();
 
double eval(Symbols symbols, String expression) throws SyntaxException {
rpn.setConsumer(simpleCodeGen.setSymbols(symbols));
lexer.scan(expression, rpn);
return simpleCodeGen.getValue();
}
 
FunctionAndName compile(Symbols symbols, String source) throws SyntaxException {
Function fun = null;
decl.parse(source, lexer, declParser);
if (decl.arity == DeclarationParser.UNKNOWN_ARITY) {
try {
double value = eval(symbols, decl.expression);
fun = new Constant(value);
} catch (SyntaxException e) {
if (e != SimpleCodeGen.HAS_ARGUMENTS) {
throw e;
}
// fall-through (see below)
}
}
if (fun == null) { // either decl.arity was set, or an ArityException happened above
symbols.pushFrame();
symbols.addArguments(decl.args);
try {
rpn.setConsumer(codeGen.setSymbols(symbols));
lexer.scan(decl.expression, rpn);
} finally {
symbols.popFrame();
}
int arity = decl.arity;
if (arity == DeclarationParser.UNKNOWN_ARITY) {
arity = codeGen.intrinsicArity;
}
fun = codeGen.getFun(arity);
 
/*
if (decl.name != null && addDefinition) {
symbols.addDefinition(decl.name, fun, decl.arity==DeclarationParser.UNKNOWN_ARITY);
}
*/
}
 
return new FunctionAndName(fun, decl.name);
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/FunctionStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class FunctionStack {
private Function[] data = new Function[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(Function b) {
if (size >= data.length) {
Function[] newData = new Function[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
Function[] toArray() {
Function[] trimmed = new Function[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/MoreMath.java
0,0 → 1,183
/*
* Copyright (C) 2006-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
 
package org.javia.arity;
 
class MoreMath extends BaseMath {
private static final double LOG2E = 1.4426950408889634074;
 
public static final double asinh(double x) {
return (x < 0) ? -asinh(-x) : log(x + x + 1/(Math.sqrt(x*x + 1) + x));
}
public static final double acosh(double x) {
return log(x + x - 1/(Math.sqrt(x*x - 1) + x));
}
 
public static final double atanh(double x) {
return (x < 0) ? -atanh(-x) : 0.5 * log(1. + (x + x)/(1 - x));
}
 
public static final double trunc(double x) {
return x >= 0 ? Math.floor(x) : Math.ceil(x);
}
 
public static final double gcd(double x, double y) {
//double remainder = y;
if (Double.isNaN(x) || Double.isNaN(y) ||
Double.isInfinite(x) || Double.isInfinite(y)) {
return Double.NaN;
}
x = Math.abs(x);
y = Math.abs(y);
double save;
while (y > 1e-12) {
save = y;
y = x % y;
x = save;
//Log.log(y);
}
return x > 1e-10 ? x : 0;
}
public static final double lgamma(double x) {
double tmp = x + 5.2421875; //== 607/128. + .5;
return 0.9189385332046727418 //LN_SQRT2PI, ln(sqrt(2*pi))
+ log(
0.99999999999999709182 +
57.156235665862923517 / ++x +
-59.597960355475491248 / ++x +
14.136097974741747174 / ++x +
-0.49191381609762019978 / ++x +
.33994649984811888699e-4 / ++x +
.46523628927048575665e-4 / ++x +
-.98374475304879564677e-4 / ++x +
.15808870322491248884e-3 / ++x +
-.21026444172410488319e-3 / ++x +
.21743961811521264320e-3 / ++x +
-.16431810653676389022e-3 / ++x +
.84418223983852743293e-4 / ++x +
-.26190838401581408670e-4 / ++x +
.36899182659531622704e-5 / ++x
)
+ (tmp-4.7421875)*log(tmp) - tmp
;
}
 
static final double FACT[] = {
1.0,
40320.0,
2.0922789888E13,
6.204484017332394E23,
2.631308369336935E35,
8.159152832478977E47,
1.2413915592536073E61,
7.109985878048635E74,
1.2688693218588417E89,
6.1234458376886085E103,
7.156945704626381E118,
1.8548264225739844E134,
9.916779348709496E149,
1.0299016745145628E166,
1.974506857221074E182,
6.689502913449127E198,
3.856204823625804E215,
3.659042881952549E232,
5.5502938327393044E249,
1.3113358856834524E267,
4.7147236359920616E284,
2.5260757449731984E302,
};
 
public static final double factorial(double x) {
if (x < 0) { // x <= -1 ?
return Double.NaN;
}
if (x <= 170) {
if (Math.floor(x) == x) {
int n = (int)x;
double extra = x;
switch (n & 7) {
case 7: extra *= --x;
case 6: extra *= --x;
case 5: extra *= --x;
case 4: extra *= --x;
case 3: extra *= --x;
case 2: extra *= --x;
case 1: return FACT[n >> 3] * extra;
case 0: return FACT[n >> 3];
}
}
}
return exp(lgamma(x));
}
 
public static final double comb(double n, double k) {
if (n < 0 || k < 0) { return Double.NaN; }
if (n < k) { return 0; }
if (Math.floor(n) == n && Math.floor(k) == k) {
k = Math.min(k, n-k);
if (n <= 170 && 12 < k && k <= 170) {
return factorial(n)/factorial(k)/factorial(n-k);
} else {
double r = 1, diff = n-k;
for (double i = k; i > .5 && r < Double.POSITIVE_INFINITY; --i) {
r *= (diff+i)/i;
}
return r;
}
} else {
return exp(lgamma(n) - lgamma(k) - lgamma(n-k));
}
}
 
public static final double perm(double n, double k) {
if (n < 0 || k < 0) { return Double.NaN; }
if (n < k) { return 0; }
if (Math.floor(n) == n && Math.floor(k) == k) {
if (n <= 170 && 10 < k && k <= 170) {
return factorial(n)/factorial(n-k);
} else {
double r = 1, limit = n-k+.5;
for (double i = n; i > limit && r < Double.POSITIVE_INFINITY; --i) {
r *= i;
}
return r;
}
} else {
return exp(lgamma(n) - lgamma(n-k));
}
}
 
public static final double log2(double x) {
return log(x) * LOG2E;
}
 
private static final boolean isPiMultiple(double x) {
return x % Math.PI == 0;
}
 
public static final int intLog10(double x) {
//an alternative implem is using a for loop.
return (int)Math.floor(log10(x));
//return (int)log10(x);
}
 
public static final double intExp10(int exp) {
return Double.parseDouble("1E" + exp);
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Util.java
0,0 → 1,149
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Contains static helper methods for formatting double values.
*/
public class Util {
/*
private static String replace(String str, String what, String repl) {
int pos = str.indexOf(what);
while (pos != -1) {
str = str.substring(0, pos) + repl + str.substring(pos + what.length());
pos = str.indexOf(what);
}
//Log.log("replaced: '"+str+"'");
return str;
}
*/
 
/** Returns a number which is an approximation of v (within maxError)
and which has fewer digits in base-10).
@param value the value to be approximated
@param maxError the maximum deviation from value
@return an approximation with a more compact base-10 representation.
*/
public static double shortApprox(double value, double maxError) {
final double v = Math.abs(value);
final double tail = MoreMath.intExp10(MoreMath.intLog10(Math.abs(maxError)));
final double ret = Math.floor(v/tail +.5)*tail;
return (value < 0) ? -ret : ret;
}
 
/**
Returns an approximation with no more than maxLen chars.
@param str the value to truncate (e.g. "-2.898983455E20")
@param maxLen the maximum number of characters in the returned string
@return a truncation no longer then maxLen (e.g. "-2.8E20" for maxLen=7).
*/
public static String sizeTruncate(String str, int maxLen) {
int ePos = str.lastIndexOf('E');
String tail = (ePos != -1) ? str.substring(ePos) : "";
int tailLen = tail.length();
int maxHeadLen = maxLen - tailLen;
return str.substring(0, Math.min(str.length()-tailLen, maxHeadLen)) + tail;
}
 
/**
Rounds by dropping roundingDigits of double precision
(similar to 'hidden precision digits' on calculators),
and formats to String.
@param v the value to be converted to String
@param roundingDigits the number of 'hidden precision' digits (e.g. 2).
@return a String representation of v
*/
public static String doubleToString(double v, int roundingDigits) {
if (roundingDigits > 13) {
roundingDigits = 0;
}
int roundingStart = roundingDigits == 0 ? 17 : 15 - roundingDigits;
 
String str = Double.toString(Math.abs(v));
StringBuffer buf = new StringBuffer(str);
int ePos = str.lastIndexOf('E');
int exp = (ePos != -1) ? Integer.parseInt(str.substring(ePos + 1)) : 0;
if (ePos != -1) {
buf.setLength(ePos);
}
int len = buf.length();
 
//remove dot
int dotPos;
for (dotPos = 0; dotPos < len && buf.charAt(dotPos) != '.';) ++dotPos;
exp += dotPos;
if (dotPos < len) {
buf.deleteCharAt(dotPos);
--len;
}
 
//round
for (int p = 0; p < len && buf.charAt(p) == '0'; ++p) {
++roundingStart;
}
 
if (roundingStart < len) {
if (buf.charAt(roundingStart) >= '5') {
int p;
for (p = roundingStart-1; p >= 0 && buf.charAt(p)=='9'; --p) {
buf.setCharAt(p, '0');
}
if (p >= 0) {
buf.setCharAt(p, (char)(buf.charAt(p)+1));
} else {
buf.insert(0, '1');
++roundingStart;
++exp;
}
}
buf.setLength(roundingStart);
}
 
//re-insert dot
if ((exp < -5) || (exp > 10)) {
buf.insert(1, '.');
--exp;
} else {
for (int i = len; i < exp; ++i) {
buf.append('0');
}
buf.insert((exp<0)? 0 : exp, '.');
for (int i = exp; i <= 0; ++i) {
buf.insert(0, '0');
}
exp = 0;
}
len = buf.length();
//remove trailing dot and 0s.
int tail;
for (tail = len-1; tail >= 0 && buf.charAt(tail) == '0'; --tail) {
buf.deleteCharAt(tail);
}
if (tail >= 0 && buf.charAt(tail) == '.') {
buf.deleteCharAt(tail);
}
 
if (exp != 0) {
buf.append('E').append(exp);
}
if (v < 0) {
buf.insert(0, '-');
}
return buf.toString();
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/SimpleCodeGen.java
0,0 → 1,99
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/* Non-optimizing Code Generator
Reads tokens in RPN (Reverse Polish Notation) order,
and generates VM opcodes,
without any optimization.
*/
 
class SimpleCodeGen extends TokenConsumer {
private CompiledFunction compiledFunction = new CompiledFunction();
static final SyntaxException HAS_ARGUMENTS = new SyntaxException();
 
ByteStack code = new ByteStack();
DoubleStack consts = new DoubleStack();
FunctionStack funcs = new FunctionStack();
 
//String argNames[];
Symbols symbols;
 
SyntaxException exception;
 
SimpleCodeGen(SyntaxException exception) {
this.exception = exception;
}
 
SimpleCodeGen setSymbols(Symbols symbols) {
this.symbols = symbols;
return this;
}
 
//@Override
void start() {
code.clear();
consts.clear();
funcs.clear();
}
void push(Token token) throws SyntaxException {
byte op;
switch (token.id) {
case Lexer.NUMBER:
op = VM.CONST;
consts.push(token.value);
break;
case Lexer.CONST:
case Lexer.CALL:
Symbol symbol = symbols.lookup(token.name, token.arity);
if (symbol == null) {
throw exception.set("undefined '" + token.name + "' with arity " + token.arity, token.position);
}
if (symbol.op > 0) { // built-in
op = symbol.op;
if (op >= VM.LOAD0 && op <= VM.LOAD4) {
throw HAS_ARGUMENTS.set("eval() on implicit function", exception.position);
}
} else if (symbol.fun != null) { // function call
op = VM.CALL;
funcs.push(symbol.fun);
} else { // variable reference
op = VM.CONST;
consts.push(symbol.value);
}
break;
default:
op = token.vmop;
if (op <= 0) {
throw new Error("wrong vmop: " + op);
}
}
code.push(op);
}
double getValue() {
compiledFunction.init(0, code.toArray(), consts.toArray(), funcs.toArray());
try {
return compiledFunction.eval();
} catch (ArityException e) {
throw new Error("" + e); //never
}
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Lexer.java
0,0 → 1,176
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Lexer {
static final int
ADD = 1,
SUB = 2,
MUL = 3,
DIV = 4,
MOD = 5,
UMIN = 6,
POWER = 7,
FACT = 8,
NUMBER = 9,
CONST = 10,
CALL = 11,
COMMA = 12,
LPAREN = 13,
RPAREN = 14,
END = 15,
SQRT = 16;
static final Token
TOK_ADD = new Token(ADD, 3, Token.LEFT, VM.ADD),
TOK_SUB = new Token(SUB, 3, Token.LEFT, VM.SUB),
 
TOK_MUL = new Token(MUL, 4, Token.LEFT, VM.MUL),
TOK_DIV = new Token(DIV, 4, Token.LEFT, VM.DIV),
TOK_MOD = new Token(MOD, 4, Token.LEFT, VM.MOD),
 
TOK_UMIN = new Token(UMIN, 5, Token.PREFIX, VM.UMIN),
 
TOK_POWER = new Token(POWER, 6, Token.RIGHT, VM.POWER),
TOK_FACT = new Token(FACT, 7, Token.SUFIX, VM.FACT),
TOK_SQRT = new Token(SQRT, 8, Token.PREFIX, VM.SQRT),
 
TOK_LPAREN = new Token(LPAREN, 1, Token.PREFIX, 0),
TOK_RPAREN = new Token(RPAREN, 2, 0, 0),
TOK_COMMA = new Token(COMMA, 1, 0, 0),
TOK_END = new Token(END, 0, 0, 0),
 
TOK_NUMBER = new Token(NUMBER, 20, 0, 0),
TOK_CONST = new Token(CONST, 20, 0, 0);
 
private static final String WHITESPACE = " \n\r\t";
private static final char END_MARKER = '$';
private char[] input = new char[32];
private int pos;
private SyntaxException exception;
 
Lexer(SyntaxException exception) {
this.exception = exception;
init("");
}
 
void scan(String str, TokenConsumer consumer) throws SyntaxException {
init(str);
consumer.start();
Token token;
do {
int savePos = pos;
token = nextToken();
token.position = savePos;
consumer.push(token);
} while (token != TOK_END);
}
 
void init(String str) {
exception.expression = str;
int len = str.length();
if (input.length < len + 1) {
input = new char[len+1];
}
str.getChars(0, len, input, 0);
input[len] = END_MARKER;
pos = 0;
}
 
Token nextToken() throws SyntaxException {
while (WHITESPACE.indexOf(input[pos]) != -1) {
++pos;
}
 
char c = input[pos];
int begin = pos++;
 
switch (c) {
case '!': return TOK_FACT;
case END_MARKER: return TOK_END;
case '%': return TOK_MOD;
case '(': return TOK_LPAREN;
case ')': return TOK_RPAREN;
case '*': return TOK_MUL;
case '+': return TOK_ADD;
case ',': return TOK_COMMA;
case '-': return TOK_SUB;
case '/': return TOK_DIV;
}
if (c == '^') {
return TOK_POWER;
}
 
int p = pos;
if (('0' <= c && c <= '9') || c == '.') {
while (('0' <= c && c <= '9') || c == '.' || c == 'E' || c == 'e') {
if ((c == 'E' || c == 'e') && input[p] == '-') { //accept '-' only after E
++p;
}
c = input[p++];
}
pos = p-1;
String nbStr = String.valueOf(input, begin, p-1-begin);
try {
// parse single dot as 0
if (nbStr.equals(".")) {
return TOK_NUMBER.setValue(0);
} else {
double numberValue = Double.parseDouble(nbStr);
return TOK_NUMBER.setValue(numberValue);
}
} catch (NumberFormatException e) {
throw exception.set("invalid number '" + nbStr + "'", begin);
}
} else if (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z')) {
do {
c = input[p++];
} while (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
('0' <= c && c <= '9'));
String nameValue = String.valueOf(input, begin, p-1-begin);
while (WHITESPACE.indexOf(c) != -1) {
c = input[p++];
}
if (c == '(') {
pos = p;
return (new Token(CALL, 0, Token.PREFIX, 0)).setAlpha(nameValue);
} else {
pos = p-1;
return TOK_CONST.setAlpha(nameValue);
}
} else if ((c >= '\u0391' && c <= '\u03a9') || (c >= '\u03b1' && c <= '\u03c9')) {
return TOK_CONST.setAlpha(""+c);
} else {
switch (c) {
case '^':
return TOK_POWER;
case '\u00d7':
return TOK_MUL;
case '\u00f7':
return TOK_DIV;
case '\u2212':
return TOK_SUB;
case '\u221a':
return TOK_SQRT;
default:
throw exception.set("invalid character '" + c + "'", begin);
}
}
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/UnitTest.java
0,0 → 1,345
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class EvalCase {
String expr;
double result;
static final double ERR = -2, FUN = -3;
 
EvalCase(String expr, double result) {
this.expr = expr;
this.result = result;
}
}
 
class TestEval {
static EvalCase cases[] = {
new EvalCase(".", 0),
new EvalCase("1+.", 1),
new EvalCase("1", 1),
new EvalCase("\u03c0", Math.PI),
new EvalCase("2\u00d73", 6), //2*3
new EvalCase("1+\u221a9*2", 7), //1+sqrt(9)*2
new EvalCase("3\u221a 4", 6), //3*sqrt(4)
new EvalCase("\u221a16sin(2\u03c0/4)", 4), //sqrt(16)*sin(2pi/4)
new EvalCase("1+", EvalCase.ERR),
new EvalCase("1+1", 2),
new EvalCase("1+-1", 0),
new EvalCase("-0.5", -.5),
new EvalCase("+1e2", 100),
new EvalCase("-2^3!", -64),
new EvalCase("(-2)^3!", 64),
new EvalCase("-2^1^2", -2),
new EvalCase("--1", 1),
new EvalCase("-3^--2", -9),
new EvalCase("1+2)(2+3", 15),
new EvalCase("1+2)!^-2", 1./36),
new EvalCase("sin(0)", 0),
new EvalCase("cos(0)", 1),
new EvalCase("sin(-1--1)", 0),
new EvalCase("-(2+1)*-(4/2)", 6),
new EvalCase("-.5E-1", -.05),
new EvalCase("1E1.5", EvalCase.ERR),
new EvalCase("2 3 4", 24),
new EvalCase("pi", Math.PI),
new EvalCase("e", Math.E),
new EvalCase("sin(pi/2)", 1),
new EvalCase("f=sin(2x)", EvalCase.FUN),
new EvalCase("f(pi/2)", 0),
new EvalCase("a=3", 3),
new EvalCase("b=a+1", 4),
new EvalCase("f(x, y) = x*(y+1)", EvalCase.FUN),
new EvalCase("f(a, b-a)", 6),
new EvalCase(" f(a pi/4)", -1),
new EvalCase("f ( 1 + 1 , a+1)", 10),
new EvalCase("g(foo) = f (f(foo, 1)pi/2)", EvalCase.FUN),
new EvalCase("g(.5*2)", 0),
new EvalCase("NaN", Double.NaN),
new EvalCase("Inf", Double.POSITIVE_INFINITY),
new EvalCase("Infinity", Double.POSITIVE_INFINITY),
new EvalCase("-Inf", Double.NEGATIVE_INFINITY),
new EvalCase("0/0", Double.NaN)
};
 
private static boolean equal(double a, double b) {
return Math.abs(a-b) < 1E-15 ||
Double.doubleToLongBits(a) == Double.doubleToLongBits(b);
}
 
static boolean testEval() throws ArityException {
final String spaces = " ";
boolean allOk = true;
Symbols symbols = new Symbols();
for (int i = 0; i < cases.length; ++i) {
EvalCase c = cases[i];
String strResult;
boolean ok;
try {
double actual;
if (Symbols.isDefinition(c.expr)) {
FunctionAndName fan = symbols.compile(c.expr);
symbols.define(fan);
Function f = fan.function;
actual = f.arity()==0 ? f.eval() : EvalCase.FUN;
strResult = (f.arity()==0 ? Util.doubleToString(actual, 1) : f.toString());
} else {
actual = symbols.eval(c.expr);
strResult = Util.doubleToString(actual, 1);
}
ok = equal(c.result, actual);
} catch (SyntaxException e) {
strResult = e.toString();
ok = c.result == EvalCase.ERR;
}
System.out.println((ok ? "" : "failed (expected " + c.result + "): ")
+ c.expr
+ spaces.substring(0, Math.max(15-c.expr.length(), 0)) + " = "
+ strResult);
if (!ok) {
allOk = false;
}
}
return allOk;
}
}
 
 
class FormatCase {
public FormatCase(int rounding, double v, String s) {
this.rounding = rounding;
this.val = v;
this.res = s;
}
public int rounding;
public double val;
public String res;
}
 
class TestFormat {
static FormatCase cases[] = {
new FormatCase(0, 0.1, "0.1"),
new FormatCase(0, 0.12, "0.12"),
new FormatCase(0, 0.001, "0.001"),
new FormatCase(0, 0.0012, "0.0012"),
new FormatCase(0, 0.0000001, "1E-7"),
new FormatCase(0, 0.00000012, "1.2E-7"),
new FormatCase(0, 0.123456789012345, "0.123456789012345"),
 
new FormatCase(0, 0, "0"),
new FormatCase(0, 1, "1"),
new FormatCase(0, 12, "12"),
new FormatCase(0, 1234567890., "1234567890"),
new FormatCase(0, 1000000000., "1000000000"),
new FormatCase(0, 1.23456789012345, "1.23456789012345"),
new FormatCase(0, 12345.6789012345, "12345.6789012345"),
new FormatCase(0, 1234567890.12345, "1234567890.12345"),
new FormatCase(0, 123456789012345., "1.23456789012345E14"),
new FormatCase(0, 100000000000000., "1E14"),
new FormatCase(0, 120000000000000., "1.2E14"),
new FormatCase(0, 100000000000001., "1.00000000000001E14"),
 
new FormatCase(2, 0.1, "0.1"),
new FormatCase(2, 0.00000012, "1.2E-7"),
new FormatCase(1, 0.123456789012345, "0.12345678901235"),
 
new FormatCase(2, 0, "0"),
new FormatCase(1, 1.23456789012345, "1.2345678901235"),
new FormatCase(2, 1.23456789012345, "1.234567890123"),
new FormatCase(0, 12345.6789012345, "12345.6789012345"),
new FormatCase(1, 1234567890.12345, "1234567890.1235"),
new FormatCase(2, 123456789012345., "1.234567890123E14"),
new FormatCase(1, 100000000000001., "1E14"),
 
new FormatCase(0, 12345678901234567., "1.2345678901234568E16"),
new FormatCase(1, 12345678901234567., "1.2345678901235E16"),
 
new FormatCase(0, 99999999999999999., "1E17"),
new FormatCase(0, 9999999999999999., "1E16"),
new FormatCase(0, 999999999999999., "9.99999999999999E14"),
new FormatCase(1, 999999999999999., "1E15"),
new FormatCase(1, 999999999999994., "9.9999999999999E14"),
 
new FormatCase(1, MoreMath.log2(1+.00002), "00000.28853612282487")
};
 
static boolean testFormat() {
boolean ret = true;
for (int i = 0; i < cases.length; ++i) {
FormatCase c = cases[i];
double v = Double.parseDouble(c.res);
if (c.rounding == 0 && v != c.val) {
System.out.println("wrong test? " + c.res + " " + v + " " + c.val);
}
String res = Util.doubleToString(c.val, c.rounding);
if (!res.equals(c.res)) {
System.out.println("Expected '" + c.res + "', got '" + res + "'. " + Double.toString(c.val));
ret = false;
}
int nKeep = c.rounding == 0 ? 17 : 15 - c.rounding;
//System.out.println("" + Double.toString(c.val) + " " + Util.round(c.val, nKeep) + " " + c.res + ", got " + res);
}
return ret;
}
}
 
/**
Runs unit-tests.<p>
Usage: java -jar arity.jar
*/
public class UnitTest {
/**
Takes a single command-line argument, an expression; compiles and prints it.<p>
Without arguments, runs the unit tests.
@throws SyntaxException if there are errors compiling the expression.
*/
public static void main(String argv[]) throws SyntaxException, ArityException {
int size = argv.length;
if (size == 0) {
runUnitTests();
profile();
} else if (size == 1 && argv[0].equals("-profile")) {
profile();
} else {
Symbols symbols = new Symbols();
for (int i = 0; i < size; ++i) {
FunctionAndName fan = symbols.compile(argv[i]);
symbols.define(fan);
}
profile(symbols, argv[size-1]);
}
}
 
static void profile(Symbols symbols, String str) throws SyntaxException, ArityException {
Function f = symbols.compile(str).function;
System.out.println("\n" + str + ": " + f);
 
Runtime runtime = Runtime.getRuntime();
 
runtime.gc();
/*
long m1 = runtime.freeMemory();
for (int i = 0; i < 200; ++i) {
symbols.compile(str);
}
long m2 = runtime.freeMemory();
System.out.println("compilation memory: " + (m1 - m2)/200 + " bytes");
*/
runtime.gc();
long t1 = System.currentTimeMillis();
for (int i = 0; i < 1000; ++i) {
symbols.compile(str);
}
long t2 = System.currentTimeMillis();
System.out.println("compilation time: " + (t2 - t1) + " us");
double args[] = new double[f.arity()];
/*
runtime.gc();
m1 = runtime.freeMemory();
f.eval(args);
m2 = runtime.freeMemory();
if (m2 != m1) {
System.out.println("execution memory: " + (m1 - m2) + " bytes");
}
*/
runtime.gc();
t1 = System.currentTimeMillis();
for (int i = 0; i < 100000; ++i) {
f.eval(args);
}
t2 = System.currentTimeMillis();
long delta = t2 - t1;
System.out.println("execution time: " + (delta > 100 ? ""+delta/100.+" us" : ""+delta+" ns"));
}
 
private static final String profileCases[] = {
//"1+1",
"(100.5 + 20009.999)*(7+4+3)/(5/2)^3!)*2",
"fun1(x)=(x+2)*(x+3)",
"otherFun(x)=(fun1(x-1)*x+1)*(fun1(2-x)+10)",
"log(x+30.5, 3)^.7*sin(x+.5)"
};
 
private static void profile() {
String cases[] = profileCases;
Symbols symbols = new Symbols();
try {
for (int i = 0; i < cases.length; ++i) {
symbols.define(symbols.compile(cases[i]));
profile(symbols, cases[i]);
}
} catch (Exception e) {
throw new Error("" + e);
}
}
 
static void runUnitTests() {
checkCounter = 0;
 
cheq(MoreMath.log(-1), Double.NaN);
cheq(MoreMath.log(-0.03), Double.NaN);
cheq(MoreMath.intLog10(-0.03), 0);
cheq(MoreMath.intLog10(0.03), -2);
cheq(MoreMath.intExp10(3), 1000);
cheq(MoreMath.intExp10(-1), 0.1);
cheq(Util.shortApprox( 1.235, 0.02), 1.24);
cheq(Util.shortApprox( 1.235, 0.4), 1.2000000000000002);
cheq(Util.shortApprox(-1.235, 0.02), -1.24);
cheq(Util.shortApprox(-1.235, 0.4), -1.2000000000000002);
 
check(TestFormat.testFormat());
try {
check(TestEval.testEval());
} catch (ArityException e) {
System.out.println(""+e);
}
 
if (!allOk) {
System.out.println("\n*** Some tests FAILED ***\n");
System.exit(1);
} else {
System.out.println("\n*** All tests passed OK ***\n");
}
}
 
static void cheq(double v1, double v2) {
++checkCounter;
if (v1 != v2 && !(Double.isNaN(v1) && Double.isNaN(v2))) {
allOk = false;
//Log.log("check equal " + checkCounter + " failed: " + v1 + " " + v2);
}
}
static void check(boolean cond) {
++checkCounter;
if (!cond) {
allOk = false;
//Log.log("check " + checkCounter + " failed");
}
}
 
static boolean allOk = true;
static int checkCounter = 0;
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Token.java
0,0 → 1,71
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Token {
//kind
static final int
PREFIX = 1,
LEFT = 2,
RIGHT = 3,
SUFIX = 4;
 
final int priority;
final int assoc;
final int id;
final byte vmop;
 
double value = 0; //for NUMBER only
String name = null; //for CONST & CALL
int arity;
int position; //pos inside expression
 
Token(int id, int priority, int assoc, int vmop) {
this.id = id;
this.priority = priority;
this.assoc = assoc;
this.vmop = (byte)vmop;
arity = id == Lexer.CALL ? 1 : Symbol.CONST_ARITY;
}
Token setPos(int pos) {
this.position = pos;
return this;
}
 
Token setValue(double value) {
this.value = value;
return this;
}
 
Token setAlpha(String alpha) {
name = alpha;
return this;
}
 
public String toString() {
switch (id) {
case Lexer.NUMBER:
return "" + value;
case Lexer.CALL:
return name + '(' + arity + ')';
case Lexer.CONST:
return name;
}
return "" + id;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/VM.java
0,0 → 1,117
// This file is automatically generated by the build.py script. Do not edit!
 
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class VM {
 
public static final byte
RESERVED = 0,
CONST = 1,
CALL = 2,
ADD = 3,
SUB = 4,
MUL = 5,
DIV = 6,
MOD = 7,
RND = 8,
UMIN = 9,
POWER = 10,
FACT = 11,
SQRT = 12,
CBRT = 13,
EXP = 14,
LOG = 15,
SIN = 16,
COS = 17,
TAN = 18,
ASIN = 19,
ACOS = 20,
ATAN = 21,
SINH = 22,
COSH = 23,
TANH = 24,
ASINH = 25,
ACOSH = 26,
ATANH = 27,
ABS = 28,
FLOOR = 29,
CEIL = 30,
SIGN = 31,
MIN = 32,
MAX = 33,
GCD = 34,
COMB = 35,
PERM = 36,
LOAD0 = 37,
LOAD1 = 38,
LOAD2 = 39,
LOAD3 = 40,
LOAD4 = 41,
BYTECODE_END = 42;
 
public static final String[] opcodeName = {
"reserved",
"const",
"call",
"add",
"sub",
"mul",
"div",
"mod",
"rnd",
"umin",
"power",
"fact",
"sqrt",
"cbrt",
"exp",
"log",
"sin",
"cos",
"tan",
"asin",
"acos",
"atan",
"sinh",
"cosh",
"tanh",
"asinh",
"acosh",
"atanh",
"abs",
"floor",
"ceil",
"sign",
"min",
"max",
"gcd",
"comb",
"perm",
"load0",
"load1",
"load2",
"load3",
"load4",
"bytecode_end"
};
 
public static final byte[] builtinArity =
{-1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1};
 
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/BaseMath.java
0,0 → 1,65
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
 
package org.javia.arity;
 
// This class is a replacement for BaseMath.java to be used on Java 1.5 and later
class BaseMath {
public static final double atan(double x) {
return Math.atan(x);
}
public static final double asin(double x) {
return Math.asin(x);
}
 
public static final double acos(double x) {
return Math.acos(x);
}
 
public static final double exp(double x) {
return Math.exp(x);
}
 
public static final double log(double x) {
return Math.log(x);
}
 
public static final double sinh(double x) {
return Math.sinh(x);
}
 
public static final double cosh(double x) {
return Math.cosh(x);
}
 
public static final double tanh(double x) {
return Math.tanh(x);
}
 
public static final double cbrt(double x) {
return Math.cbrt(x);
}
public static final double pow(double x, double y) {
return Math.pow(x, y);
}
 
public static final double log10(double x) {
return Math.log10(x);
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Declaration.java
0,0 → 1,50
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Declaration {
private static final String NO_ARGS[] = {};
String name;
String args[];
int arity;
String expression;
 
void parse(String source, Lexer lexer, DeclarationParser declParser) throws SyntaxException {
int equalPos = source.indexOf('=');
String decl;
 
if (equalPos == -1) {
decl = null;
expression = source;
name = null;
args = NO_ARGS;
arity = DeclarationParser.UNKNOWN_ARITY;
} else {
decl = source.substring(0, equalPos);
expression = source.substring(equalPos + 1);
lexer.scan(decl, declParser);
name = declParser.name;
args = declParser.argNames();
arity = declParser.arity;
}
/*
if (arity == DeclarationParser.UNKNOWN_ARITY) {
args = IMPLICIT_ARGS;
}
*/
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Function.java
0,0 → 1,94
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Abstract base class for functions.<p>
A function has an arity (the number of arguments), and a way for evaluation
given the values of the arguments.<p>
Derive from this class to create user-defined functions.
 
<h3>Thread safety</h3>
Assuming the user didn't subclass Function to define user functions,
the compiled Functions are thread-safe
(the same Function instance can be evaluated from multiple threads without locking).<p>
 
Whatsmore, parallel evaluations of the same instance from multiple threads are not
serialized (good).<p>
 
If the user subclasses Function, he is responsible for the thread-safety of
his user-defined Functions.
*/
 
abstract public class Function {
private int cachedArity = -1;
 
/**
Gives the arity of this function.
@return the arity (the number of arguments). Arity >= 0.
*/
public int arity() {
if (cachedArity == -1) {
cachedArity = 0;
for (int i = 0; i < 5; ++i) {
double args[] = new double[i];
try {
eval(args);
cachedArity = i;
break;
} catch (ArityException e) {
//ignore, continue
}
}
}
return cachedArity;
}
 
/**
Evaluates an arity-0 function (a function with no arguments).
@return the value of the function
*/
public double eval() throws ArityException {
throw new ArityException("Didn't expect 0 args");
}
 
public double eval(double x) throws ArityException {
throw new ArityException("Didn't expect 1 args");
}
 
public double eval(double x, double y) throws ArityException {
throw new ArityException("Didn't expect 2 args");
}
 
/**
Evaluates the function given the argument values.
@param args array containing the arguments.
@return the value of the function
@throws ArityException if args.length != arity.
*/
public double eval(double args[]) throws ArityException {
switch (args.length) {
case 0:
return eval();
case 1:
return eval(args[0]);
case 2:
return eval(args[0], args[1]);
}
throw new ArityException("unexpected " + args.length + " args");
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/OptCodeGen.java
0,0 → 1,108
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/* Optimizing Code Generator
Reads tokens in RPN (Reverse Polish Notation) order,
and generates VM opcodes,
doing constant-folding optimization.
*/
 
class OptCodeGen extends SimpleCodeGen {
double stack[] = new double[CompiledFunction.MAX_STACK_SIZE];
int sp = -1;
 
double traceConsts[] = new double[1];
Function traceFuncs[] = new Function[1];
byte traceCode[] = new byte[1];
CompiledFunction tracer = new CompiledFunction(0, traceCode, traceConsts, traceFuncs);
 
int intrinsicArity;
OptCodeGen(SyntaxException e) {
super(e);
}
 
//@Override
void start() {
super.start();
sp = -1;
intrinsicArity = 0;
}
 
//@Override
void push(Token token) throws SyntaxException {
byte op;
switch (token.id) {
case Lexer.NUMBER:
op = VM.CONST;
traceConsts[0] = token.value;
break;
case Lexer.CONST:
case Lexer.CALL:
Symbol symbol = symbols.lookup(token.name, token.arity);
if (symbol == null) {
throw exception.set("undefined '" + token.name + "' with arity " + token.arity, token.position);
}
if (symbol.op > 0) { // built-in
op = symbol.op;
if (op >= VM.LOAD0 && op <= VM.LOAD4) {
int arg = op - VM.LOAD0;
if (arg + 1 > intrinsicArity) {
intrinsicArity = arg + 1;
}
}
} else if (symbol.fun != null) { // function call
op = VM.CALL;
traceFuncs[0] = symbol.fun;
} else { // variable reference
op = VM.CONST;
traceConsts[0] = symbol.value;
}
break;
default:
op = token.vmop;
if (op <= 0) {
throw new Error("wrong vmop: " + op);
}
}
int oldSP = sp;
traceCode[0] = op;
if (op != VM.RND) {
sp = tracer.execWithoutCheck(stack, sp);
} else {
stack[++sp] = Double.NaN;
}
 
//constant folding
if (!Double.isNaN(stack[sp]) || op == VM.CONST) {
code.pop(oldSP + 1 - sp);
consts.pop(oldSP + 1 - sp);
consts.push(stack[sp]);
op = VM.CONST;
} else if (op == VM.CALL) {
funcs.push(traceFuncs[0]);
}
code.push(op);
}
 
CompiledFunction getFun(int arity) {
return new CompiledFunction(arity, code.toArray(), consts.toArray(), funcs.toArray());
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Symbols.java
0,0 → 1,264
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
 
/**
The collection of names (<em>symbols</em>) used for parsing an expression
(the context in which the parsing takes place).<p>
 
Each symbol maps to either a {@link Function} or a constant.<p>
 
A symbol is identified by the pair (name, arity).
So a constant and a function with the same name,
or two function with the same name but with different arity
are distinct symbols.<p>
 
Symbols functions as a stack of <em>frames</em>:
when you pop the topmost frame, all the symbols added in that frame dissapear
(i.e. all the modifications done between the push and the pop are lost).<p>
 
Example:
<pre>
<code>
Symbols symbols = new Symbols();
symbols.eval("1+1"); //doesn't update symbols
symbols.define(symbols.compile("f(x)=x^2")); //updates symbols
</code>
</pre>
<p>
 
<h3>Thread safety</h3>
The Symbols class is thread-safe
(the same Symbols instance can be used by multiple threads without locking).<p>
 
The compile() methods are synchronized, so parallel compile() calls on the same Symbols
instance are serialized.
*/
 
public class Symbols {
/**
Constructs a Symbols containing the built-in symbols (such as sin, log).
*/
public Symbols() {
for (int i = 0; i < builtin.length; ++i) {
Symbol s = builtin[i];
symbols.put(s, s);
}
try {
for (int i = 0; i < defines.length; ++i) {
define(compile(defines[i]));
}
} catch (SyntaxException e) {
throw new Error(""+e); //never
}
}
 
/**
@param source the expression
@return true if the expression is a definition (i.e. contains a '=').<p>
These are definitions: "a=1+1"; "f(k)=2^k"<p>
These are not definitions: "1+1"; "x+1"
*/
public static boolean isDefinition(String source) {
return source.indexOf('=') != -1;
}
 
/**
Evaluates a simple expression (such as "1+1") and returns its value.
@throws SyntaxException in these cases:
<ul>
<li> the expression is not well-formed
<li> the expression is a definition (such as "a=1+1")
<li> the expression is an implicit function (such as "x+1")
</ul>
*/
public synchronized double eval(String expression) throws SyntaxException {
return getCompiler().eval(this, expression);
}
 
/**
Compiles an expression in the context of this Symbols.
Does not modify the symbols.
<p>
 
An expression is one of these cases (@see Symbols.isDefinition()):
<ul>
<li> constant value: 1+1
<li> implicit function: x+1
<li> constant definition: a=1+1
<li> function definition with explicit arguments: f(a)=a+1
<li> function definition with implicit arguments: f=x+1
</ul>
<p>
 
@param source the expression; may contain '=' to denote a definition (with a name).
@return the function together with its eventual name.<p>
 
If this is not a definition (e.g. "1+1", "x^2"), the name is null.<p>
If the expression is a constant (e.g. "1+1", "a=2"),
the returned Function is an instance of {@link Constant}.
 
@throws SyntaxException if there are errors compiling the expression.
*/
public synchronized FunctionAndName compile(String source) throws SyntaxException {
return getCompiler().compile(this, source);
}
 
/**
Adds a new function symbol to the top-most frame of this Symbols.
@param name the name of the function (e.g. "sin")
@param function the function to which the name maps
*/
synchronized public void define(String name, Function function) {
if (function instanceof Constant) {
addConstant(name, ((Constant) function).eval());
} else {
add(new Symbol(name, function));
}
}
 
/**
Adds a new function symbol to the top-most frame of this Symbols.
@param funAndName structure containing the function and its name
*/
synchronized public void define(FunctionAndName funAndName) {
if (funAndName.name != null) {
define(funAndName.name, funAndName.function);
}
}
 
/**
Adds a new constant symbol to the top-most frame of this Symbols.
@param name the name of the constant (e.g. "pi")
@param value the value of the constant
*/
synchronized public void addConstant(String name, double value) {
add(new Symbol(name, value));
}
 
/**
Pushes a new top frame.<p>
 
All modifications (defining new symbols) happen in the top-most frame.
When the frame is pop-ed the modifications that happened in it are reverted.
*/
synchronized public void pushFrame() {
frames.push(delta);
delta = null;
}
 
/**
Pops the top frame.<p>
 
All the modifications done since this frame was pushed are reverted.
@throws EmptyStackException if there were fewer <code>pushFrame</code> than <code>popFrame</code>.
*/
synchronized public void popFrame() {
if (delta != null) {
for (int i = delta.size() - 1; i >= 0; --i) {
Symbol previous = (Symbol) delta.elementAt(i);
if (previous.isEmpty()) {
symbols.remove(previous);
} else {
symbols.put(previous, previous);
}
}
}
delta = (Vector) frames.pop();
}
 
 
 
//--- non-public below
 
private final static Symbol builtin[];
private static Symbol shell = new Symbol(null, 0);
private static ThreadLocal compilers = new ThreadLocal();
private static Compiler getCompiler() {
Compiler compiler;
if ((compiler = (Compiler) compilers.get()) == null) {
compilers.set(compiler = new Compiler());
}
return compiler;
}
 
private Hashtable symbols = new Hashtable(); //Hashtable<Symbol, Symbol>
private Vector delta = null; //Vector<Symbol>
private Stack frames = new Stack(); //Stack<Vector>
 
static {
Vector vect = new Vector();
int arity;
for (byte i = 0; i < VM.BYTECODE_END; ++i) {
if ((arity = VM.builtinArity[i]) >= 0) {
vect.addElement(new Symbol(VM.opcodeName[i], arity, i));
}
}
 
final String IMPLICIT_ARGS[] = {"x", "y", "z"};
for (byte i = 0; i < IMPLICIT_ARGS.length; ++i) {
vect.addElement(new Symbol(IMPLICIT_ARGS[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
}
 
vect.addElement(new Symbol("pi", Math.PI));
vect.addElement(new Symbol("\u03c0", Math.PI));
vect.addElement(new Symbol("e", Math.E));
 
vect.addElement(new Symbol("Inf", Double.POSITIVE_INFINITY));
vect.addElement(new Symbol("Infinity", Double.POSITIVE_INFINITY));
vect.addElement(new Symbol("NaN", Double.NaN));
 
int size = vect.size();
builtin = new Symbol[size];
vect.copyInto(builtin);
}
 
private static final String defines[] = {
"ln(x) = log(x)",
"log2(x) = log(x) * 1.4426950408889634074", //*log2(e)
"log10(x) = log(x) * 0.43429448190325182765", //*log10(e)
"lg(x) = log10(x)",
"lb(x) = log2(x)",
"log(x, base) = log(x) / log(base)"
};
void addArguments(String args[]) {
for (int i = 0; i < args.length; ++i) {
add(new Symbol(args[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
}
}
 
void add(Symbol s) {
Object previous = symbols.put(s, s);
if (delta == null) {
delta = new Vector();
}
delta.addElement(previous != null ? previous : Symbol.newEmpty(s));
}
 
synchronized Symbol lookup(String name, int arity) {
return (Symbol) symbols.get(shell.setKey(name, arity));
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/ByteStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class ByteStack {
private byte[] data = new byte[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(byte b) {
if (size >= data.length) {
byte[] newData = new byte[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
byte[] toArray() {
byte[] trimmed = new byte[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Constant.java
0,0 → 1,30
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
public class Constant extends Function {
private double value;
 
public Constant(double value) {
this.value = value;
}
 
//@Override
public double eval() {
return value;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/TokenConsumer.java
0,0 → 1,24
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
abstract class TokenConsumer {
void start() {
}
 
abstract void push(Token token) throws SyntaxException;
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/RPN.java
0,0 → 1,161
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Stack;
import java.util.EmptyStackException;
 
/* Reverse Polish Notation
reads tokens in normal infix order (e.g.: 1 + 2)
and outputs them in Reverse Polish order (e.g.: 1 2 +).
See Dijkstra's Shunting Yard algorithm:
http://en.wikipedia.org/wiki/Shunting_yard_algorithm
*/
class RPN extends TokenConsumer {
Stack stack = new Stack();
int prevTokenId = 0;
TokenConsumer consumer;
SyntaxException exception;
 
RPN(SyntaxException exception) {
this.exception = exception;
}
 
void setConsumer(TokenConsumer consumer) {
this.consumer = consumer;
}
 
//@Override
void start() {
stack.removeAllElements();
prevTokenId = 0;
consumer.start();
}
 
private Token top() {
return stack.empty() ? null : (Token) stack.peek();
}
 
private void popHigher(int priority) throws SyntaxException {
Token t = top();
while (t != null && t.priority >= priority) {
consumer.push(t);
//code.push(t);
stack.pop();
t = top();
}
}
 
static final boolean isOperand(int id) {
return
id == Lexer.FACT ||
id == Lexer.RPAREN ||
id == Lexer.NUMBER ||
id == Lexer.CONST;
}
 
void push(Token token) throws SyntaxException {
int priority = token.priority;
int id = token.id;
switch (id) {
case Lexer.NUMBER:
case Lexer.CONST:
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
consumer.push(token);
break;
/*
case Lexer.CALL:
case Lexer.LPAREN:
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
stack.push(token);
break;
*/
case Lexer.RPAREN: {
if (prevTokenId == Lexer.CALL) {
top().arity--;
} else if (!isOperand(prevTokenId)) {
throw exception.set("unexpected ) or END", token.position);
}
 
popHigher(priority);
Token t = top();
if (t != null) {
if (t.id == Lexer.CALL) {
consumer.push(t);
} else if (t != Lexer.TOK_LPAREN) {
throw exception.set("expected LPAREN or CALL", token.position);
}
stack.pop();
}
break;
}
case Lexer.COMMA: {
if (!isOperand(prevTokenId)) {
throw exception.set("misplaced COMMA", token.position);
}
popHigher(priority);
Token t = top();
if (t==null || t.id != Lexer.CALL) {
throw exception.set("COMMA not inside CALL", token.position);
}
t.arity++;
//code.push(stack.pop());
break;
}
case Lexer.END: {
Token t = Lexer.TOK_RPAREN;
t.position = token.position;
do {
push(t);
} while (top() != null);
break;
}
default: //operators, CALL, LPAREN
if (token.assoc == Token.PREFIX) {
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
stack.push(token);
break;
}
if (!isOperand(prevTokenId)) {
if (id == Lexer.SUB) {
//change SUB to unary minus
token = Lexer.TOK_UMIN;
stack.push(token);
break;
} else if (id == Lexer.ADD) {
// ignore, keep prevTokenId unchanged
return;
}
throw exception.set("operator without operand", token.position);
}
popHigher(priority + (token.assoc == Token.RIGHT ? 1 : 0));
stack.push(token);
}
prevTokenId = token.id;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/DoubleStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class DoubleStack {
private double[] data = new double[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(double b) {
if (size >= data.length) {
double[] newData = new double[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
double[] toArray() {
double[] trimmed = new double[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/CompiledFunction.java
0,0 → 1,253
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Random;
 
class CompiledFunction extends Function {
//static final int INI_STACK_SIZE = 16;
static final int MAX_STACK_SIZE = 128; //if stack ever grows above this likely something is wrong
private static Random random = new Random();
 
private double consts[];
private Function funcs[];
private byte code[];
private int arity; // >= 0
 
private static final ThreadLocal stacks = new ThreadLocal();
 
CompiledFunction(int arity, byte[] code, double[] consts, Function funcs[]) {
init(arity, code, consts, funcs);
}
 
/* This empty constructor is used only by SimpleCodeGen,
which calls init() explicitly later.
*/
CompiledFunction() {
init(0, null, null, null);
}
 
void init(int arity, byte[] code, double[] consts, Function funcs[]) {
this.arity = arity;
this.code = code;
this.consts = consts;
this.funcs = funcs;
}
 
public int arity() {
return arity;
}
 
public String toString() {
StringBuffer buf = new StringBuffer();
int cpos = 0, fpos = 0;
if (arity != 0) {
buf.append("arity ").append(arity).append("; ");
}
for (int i = 0; i < code.length; ++i) {
byte op = code[i];
buf.append(VM.opcodeName[op]);
if (op == VM.CONST) {
buf.append(' ').append(consts[cpos++]);
} else if (op == VM.CALL) {
++fpos;
//buf.append(" {").append(funcs[fpos++].toString()).append('}');
}
buf.append("; ");
}
if (cpos != consts.length) {
buf.append("\nuses only ").append(cpos).append(" consts out of ").append(consts.length);
}
if (fpos != funcs.length) {
buf.append("\nuses only ").append(fpos).append(" funcs out of ").append(funcs.length);
}
return buf.toString();
}
 
private void checkArity(int nArgs) throws ArityException {
if (arity() != nArgs) {
throw new ArityException("Expected " + arity() + " arguments, got " + nArgs);
}
}
 
private double[] getStack() {
double stack[];
if ((stack = (double[]) stacks.get()) == null) {
stacks.set(stack = new double[MAX_STACK_SIZE]);
}
return stack;
}
static final double NO_ARGS[] = new double[0];
public double eval() throws ArityException {
return eval(NO_ARGS);
}
 
public double eval(double x) throws ArityException {
checkArity(1);
double stack[] = getStack();
stack[0] = x;
exec(stack, 0);
return stack[0];
}
 
public double eval(double x, double y) throws ArityException {
checkArity(2);
double stack[] = getStack();
stack[0] = x;
stack[1] = y;
exec(stack, 1);
return stack[0];
}
 
public double eval(double args[]) throws ArityException {
checkArity(args.length);
double stack[] = getStack();
if (args.length > 0) {
System.arraycopy(args, 0, stack, 0, args.length);
}
exec(stack, args.length - 1);
return stack[0];
}
 
void exec(double s[], int p) {
int finalP = execWithoutCheck(s, p);
int expected = p - arity + 1;
if (finalP != expected) {
throw new Error("stack pointer after exec: expected " +
expected + ", got " + finalP);
}
}
int execWithoutCheck(double s[], int p) {
byte[] code = this.code;
int initialSP = p;
int constp = 0;
int funp = 0;
final double angleFactor = 1; // 1/Calc.cfg.trigFactor;
// arguments, read from stack on exec entry
// we don't use an array in order to avoid the dynamic allocation (new)
// @see Compiler.MAX_ARITY
double a0, a1, a2, a3, a4;
a0 = a1 = a2 = a3 = a4 = Double.NaN;
switch (arity) {
case 5: a4 = s[p--];
case 4: a3 = s[p--];
case 3: a2 = s[p--];
case 2: a1 = s[p--];
case 1: a0 = s[p--];
}
 
//int expectedExitSP = p+1;
int codeLen = code.length;
for (int pc = 0; pc < codeLen; ++pc) {
switch (code[pc]) {
case VM.CONST: s[++p] = consts[constp++]; break;
case VM.CALL: {
Function f = funcs[funp++];
if (f instanceof CompiledFunction) {
p = ((CompiledFunction) f).execWithoutCheck(s, p);
} else {
int arity = f.arity();
p -= arity;
try {
double result;
switch (arity) {
case 0:
result = f.eval();
break;
case 1:
result = f.eval(s[p+1]);
break;
case 2:
result = f.eval(s[p+1], s[p+2]);
break;
default:
double args[] = new double[arity];
System.arraycopy(s, p+1, args, 0, arity);
result = f.eval(args);
}
s[++p] = result;
} catch (ArityException e) {
throw new Error(""+e); //never
}
}
break;
}
case VM.RND: s[++p] = random.nextDouble(); break;
case VM.ADD: s[--p] += s[p+1]; break;
case VM.SUB: s[--p] -= s[p+1]; break;
case VM.MUL: s[--p] *= s[p+1]; break;
case VM.DIV: s[--p] /= s[p+1]; break;
case VM.MOD: s[--p] %= s[p+1]; break;
case VM.POWER: s[--p] = MoreMath.pow(s[p], s[p+1]); break;
case VM.UMIN: s[p] = -s[p]; break;
case VM.FACT: s[p] = MoreMath.factorial(s[p]); break;
case VM.SIN: s[p] = Math.sin(s[p] * angleFactor); break;
case VM.COS: s[p] = Math.cos(s[p] * angleFactor); break;
case VM.TAN: s[p] = Math.tan(s[p] * angleFactor); break;
case VM.ASIN: s[p] = MoreMath.asin(s[p]) / angleFactor; break;
case VM.ACOS: s[p] = MoreMath.acos(s[p]) / angleFactor; break;
case VM.ATAN: s[p] = MoreMath.atan(s[p]) / angleFactor; break;
case VM.EXP: s[p] = MoreMath.exp(s[p]); break;
case VM.LOG: s[p] = MoreMath.log(s[p]); break;
case VM.SQRT: s[p] = Math.sqrt(s[p]); break;
case VM.CBRT: s[p] = MoreMath.cbrt(s[p]); break;
case VM.SINH: s[p] = MoreMath.sinh(s[p]); break;
case VM.COSH: s[p] = MoreMath.cosh(s[p]); break;
case VM.TANH: s[p] = MoreMath.tanh(s[p]); break;
case VM.ASINH: s[p] = MoreMath.asinh(s[p]); break;
case VM.ACOSH: s[p] = MoreMath.acosh(s[p]); break;
case VM.ATANH: s[p] = MoreMath.atanh(s[p]); break;
case VM.ABS: s[p] = Math.abs(s[p]); break;
case VM.FLOOR: s[p] = Math.floor(s[p]); break;
case VM.CEIL: s[p] = Math.ceil(s[p]); break;
case VM.SIGN: s[p] = s[p] > 0 ? 1 : s[p] < 0 ? -1 : 0; break;
case VM.MIN: s[--p] = Math.min(s[p], s[p+1]); break;
case VM.MAX: s[--p] = Math.min(s[p], s[p+1]); break;
case VM.GCD: s[--p] = MoreMath.gcd(s[p], s[p+1]); break;
case VM.COMB: s[--p] = MoreMath.comb(s[p], s[p+1]); break;
case VM.PERM: s[--p] = MoreMath.perm(s[p], s[p+1]); break;
case VM.LOAD0: s[++p] = a0; break;
case VM.LOAD1: s[++p] = a1; break;
case VM.LOAD2: s[++p] = a2; break;
case VM.LOAD3: s[++p] = a3; break;
case VM.LOAD4: s[++p] = a4; break;
default:
throw new Error("Unknown opcode " + code[pc]);
}
}
return p;
/*
if (p != expectedExitSP) {
throw new Error("stack pointer after exec: expected " + expectedExitSP +
" , got " + p);
}
*/
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/DeclarationParser.java
0,0 → 1,88
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Vector;
 
class DeclarationParser extends TokenConsumer {
static final String NO_ARGS[] = new String[0];
static final int UNKNOWN_ARITY = -2;
static final int MAX_ARITY = 5;
String name;
int arity = UNKNOWN_ARITY;
Vector args = new Vector();
 
private SyntaxException exception;
 
DeclarationParser(SyntaxException e) {
this.exception = e;
}
 
//@Override
void start() {
name = null;
args.setSize(0);
}
 
//@Override
void push(Token token) throws SyntaxException {
switch (token.id) {
case Lexer.CALL:
if (name == null) {
name = token.name;
arity = 0;
} else {
throw exception.set("repeated CALL in declaration", token.position);
}
break;
 
case Lexer.CONST:
if (name == null) {
name = token.name;
arity = UNKNOWN_ARITY;
} else if (arity >= 0) {
args.addElement(token.name);
++arity;
if (arity > MAX_ARITY) {
throw exception.set("Arity too large " + arity, token.position);
}
} else {
throw exception.set("Invalid declaration", token.position);
}
break;
 
case Lexer.RPAREN:
case Lexer.COMMA:
case Lexer.END:
break;
 
default:
throw exception.set("invalid token in declaration", token.position);
}
}
String[] argNames() {
if (arity > 0) {
String argNames[] = new String[arity];
args.copyInto(argNames);
return argNames;
} else {
return NO_ARGS;
}
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/SyntaxException.java
0,0 → 1,50
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Thrown when the expression can't be compiled, because it's either not
well-formed (e.g. "1+"), or because some simbols aren't defined (e.g. "foo+2").
*/
public class SyntaxException extends Exception {
/**
The expression which caused the error.
*/
public String expression;
 
/**
Explicative message (cause of error).
*/
public String message;
 
/**
The position inside expression where the error occured.
*/
public int position;
 
public String toString() {
return "SyntaxException: " + message
+ " in '" + expression
+ "' at position " + position;
}
 
SyntaxException set(String str, int pos) {
message = str;
position = pos;
return this;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/src/org/javia/arity/Symbol.java
0,0 → 1,66
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Symbol {
static final int CONST_ARITY = -3;
 
private String name;
private int arity;
 
byte op;
Function fun;
double value = 0;
 
Symbol(String name, int arity, byte op) {
setKey(name, arity);
this.op = op;
}
 
Symbol(String name, Function fun) {
setKey(name, fun.arity());
this.fun = fun;
}
 
Symbol(String name, double value) {
setKey(name, CONST_ARITY);
this.value = value;
}
 
static Symbol newEmpty(Symbol s) {
return new Symbol(s.name, s.arity, (byte)0);
}
 
boolean isEmpty() {
return op == 0 && fun == null && value == 0;
}
 
Symbol setKey(String name, int arity) {
this.name = name;
this.arity = arity;
return this;
}
 
public boolean equals(Object other) {
Symbol symbol = (Symbol) other;
return name.equals(symbol.name) && arity == symbol.arity;
}
 
public int hashCode() {
return name.hashCode() + arity;
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/FlyApplet/build.xml
0,0 → 1,68
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for FlyApplet.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="FlyApplet" default="jar" basedir=".">
 
<description>FlyApplet build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
<exec executable="/bin/sh">
<arg line="-c 'cp ${source-dir}/atp/*.gif ${build}/atp'"/>
</exec>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create FlyApplet jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/FlyApplet.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="FlyApplet"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="FlyApplet"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="FlyApplet">
<attribute name="Specification-Title" value="FlyApplet"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="FlyApplet"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/sinus.java
0,0 → 1,336
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
modified source of "j.-p. Quelen"
jdk1.2 - double-buffering
---------------------------------------------------------
<html>
<body>
<script language="javascript" type="text/javascript">
function sendanswer(){
var data=document.applets[0].ReadApplet();
var test=data.indexOf("error");
if(test!=-1){alert("Your answer will not be send...\nthe next objects could not be detected in your drawing...\n\n:"+data); return;}
else{
var answer=data.split(',');
alert("technical answer: \n"+answer[0]);
alert("unicode answer: \n"+answer[1]);
alert("unicode answer: \n"+answer[2]);
<!-- confirm("Send this ?\n"+data);
if(t==true){
data=encodeURIComponent(data);
var URL = '$wims_ref_name?session=$session&+moudule=$module&+cmd=reply&+reply$n='+data ;document.location.href = URL
-->
}
}
}
</script>
<p align=center>
<applet id="sinus" codebase="build" archive="sinus.jar" code="sinus.class" WIDTH="800" HEIGHT="400" ALIGN="CENTER" MAYSCRIPT>
<param name="language" value="nl">
<param name="applettext" value="a string">
<param name="degrees" value="rad">
<param name="functiontype" value="sin">
<param name="show_curve" value="yes">
<param name="start" value="180">
<param name="end" value="720">
<param name="Xaxis_units" value="yes">
No java
</applet>
<br>
<input type="button" onclick="javascript:sendanswer()" name="TEST" value="TEST TEST">
</p>
</body>
</html>
---------------------------------------------------------
reply string = degrees+","+radialen+"\u03C0"+","+degrees+"\u00B0";
item 1 = the answer in degrees
item 2 = the unicode view answer in radians
item 3 = the unicode view answer in degrees
---------------------------------------------------------
<param name="language" value="nl/fr/en"> default en
<param name="applettext" value="a string">
<param name="show_curve" value="yes/no">
<param name="type" value="sin/cos"> default sin
<param name="degrees" value="yes/rad/no"> default yes or radians or no
<param name="Xaxis_units" value="yes/no"> default yes using degrees or radians depending on "param degrees"
<param name="start" value="begin value of point P in degrees"> default 0
<param name="end" value="end value of point P in degrees"> default no value
 
attention: no "try / catch" is applied to the params !
 
*/
 
 
 
import java.awt.event.* ;
import java.awt.* ;
import java.applet.* ;
import geo.* ;
 
public class sinus extends java.applet.Applet implements MouseListener, MouseMotionListener{
Image img ;Graphics g ;Graphics g1 ;
Repere R, R1 ;
pt O,P,Px,Py,Pcosx,endpoint1,endpoint2,pp1,pp2;
PointSurDroite O1;
Cercle C, Cenr ;
ArcDeCercle IM ;
Droite xas, yas ,hline;
PointSurCercle M ;
Vecteur Endpoint;
Segment straal,OPx,OPy,value,proj ;
CourbeDeFonction functie ; sin sfunctie ;cos cfunctie;
int aNp, periodes = 0 ;double ap = 1.0, pi2 ;int X, Y, Xret, Yret ;int modepaint = -1 ;
double degrees;double absdegrees=0;int use_degrees=1;double start=0;double end=0;int type=0;
int xz;int yz;double scale=7.0;double minscale=7.0;int use_end=0;int units=1;int curve=1;
double yP;String rem1="Only point P [on the circle] can be rotated...";String rem2="zooming out...";String rem3="\u03C0 radians";
String rem4="the angle = ";String rem5=" The unit circle";
public void init(){
String param;
param=getParameter("language");if(param!=null && param.length()>0){
if(param.equalsIgnoreCase("nl")){
rem1="Alleen het punt P [op de cirkel] kan worden bewogen...";
rem2="uitzoomen...";
rem3="\u03C0 radialen";
rem4="de hoek = ";
rem5=" De eenheids cirkel";
}
if(param.equalsIgnoreCase("fr")){
rem1="Seulement point P [sur le cercle] peut être tourné ...";
rem2="zoomer en plan général...";
rem3="\u03C0 radians";
rem4="angle = ";
rem5=" Cercle unité";
}
}
param=getParameter("functiontype");if(param!=null && param.length()>0){if(param.equalsIgnoreCase("cos")){type=1;}}
param=getParameter("show_curve");if(param!=null && param.length()>0){if(param.equalsIgnoreCase("no")){curve=0;scale=4;minscale=4;}}
param=getParameter("Xaxis_units") ;if(param!=null && param.length()>0){if(param.equalsIgnoreCase("no" )){units=0;}}
param=getParameter("degrees");
if(param!=null && param.length()>0){
if(param.equalsIgnoreCase("no")){
use_degrees=0;
}
else
{
if(param.equalsIgnoreCase("radians") || param.equalsIgnoreCase("rad") ){use_degrees=2;}
}
}
param=getParameter("start");if(param!=null && param.length()>0){start=(double) Integer.parseInt(param, 10); }
param=getParameter("end");if(param!=null && param.length()>0){end=(double) Integer.parseInt(param, 10); use_end=1;}
setBackground(Color.white);modepaint = 1 ;
periodes = 0 ;
pi2 = Math.PI * 2.0;
img = createImage(getSize().width, getSize().height);g = img.getGraphics();
addMouseMotionListener(this);addMouseListener(this);
xz=getSize().width/2;yz=getSize().height/2;
R = new Repere(xz,yz, getSize().width, getSize().height,(double)(getSize().height / 2 - 20),(double)(getSize().height / 2 - 20));
R1 = new Repere(xz,yz, getSize().width, getSize().height,getSize().width/scale,getSize().width/scale);
xas = new Droite(0.0, 1.0, 0.0, "", R1);
yas = new Droite(1.0, 0.0, 0.0, "", R1);
O1 = new PointSurDroite(xz,yz, xas, "O", R1);
O = new PointSurDroite(xz,yz, xas, "O", R1);
C = new Cercle(O1, 1.0, "", R1);
Cenr= new Cercle(O1, 1.0, "", R1);
M = new PointSurCercle(start*pi2/360, C, "P", R1);
straal= new Segment(O1.x,O1.y,M.x,M.y,"",R1);
Px = new point(M.x,0, "P'", R1);
Py = new point(0,M.y, "P'", R1);
proj= new Segment(Px.x,Px.y,M.x,M.y,"",R1);
OPx= new Segment(O1.x,O1.y,M.x,0,"cos",R1);
OPy= new Segment(O1.x,O1.y,0,M.y,"sin",R1);
IM = new ArcDeCercle(0.0, 0.0, 1.0, 0.0, 1.0, "", R1);
if(type==0){
P = new pt(O1.x+1.0,M.y, "", R1);
sfunctie = new sin();
functie = new CourbeDeFonction(sfunctie, "", R1);;
}
else
{
P = new pt(O1.y + 1.0, M.y, "", R1);
cfunctie = new cos();
functie = new CourbeDeFonction(cfunctie, "", R1);
}
hline=new Droite(O1.x,O1.y,M.x,M.y,"",R1);
if(use_end==1){
endpoint2 = new point(end*pi2/360,0.0,"",R1);
endpoint1 = new point(end*pi2/360,getSize().height,"",R1);
Endpoint = new Vecteur(endpoint1,endpoint2, "end",R1);
}
Pcosx = new point(P.x,0, "P''", R1);
value= new Segment(P.x,P.y,P.x,0,"",R1);
}
 
public void paint(Graphics g1){
Font f = new Font("Arial", Font.PLAIN, 10);g.setFont(f);g.setColor(getBackground());g.fillRect(0, 0, R1.XMAX, R1.YMAX);
double Ma = M.a + pi2 *(double)(periodes);degrees=Ma*(360/(pi2));double Maa = M.a ;aNp = Math.abs(periodes);
if((M.a < 0.0) &&(periodes > 0)){ aNp -- ;Maa = Maa + pi2 ;} else { if((M.a > 0.0) &&(periodes < 0)){ aNp -- ;Maa = Maa - pi2 ;}}
g.setColor(Color.gray);
for(int i = 0 ; i < aNp ; i ++){ Cenr.Cercle(0.0, 0.0, 1.0 + R1.Abs(i + R1.X0));Cenr.trace(g); }
IM.trace(g); IM.ArcDeCercle(0.0, 0.0, 1.0 + R1.Abs(aNp + R1.X0), 0.0, Maa);
g.setColor(Color.gray); xas.trace(g);yas.trace(g);
g.setColor(Color.green);
straal.Segment(O1,M);straal.trace(g);
if(type==0){
g.setColor(Color.red);
Py.point(0,M.y);Py.trace(g);Py.traceNom(g);
OPy.Segment(O1,Py);OPy.trace(g);
proj.Segment(M,Py);proj.trace(g);
}
else
{
g.setColor(Color.red);
Px.point(M.x,0);Px.trace(g);Px.traceNom(g);
OPx.Segment(O1,Px);OPx.trace(g);
g.setColor(Color.green);
proj.Segment(M,Px);proj.trace(g);
}
if(curve==1){
if(units==1 && aNp<10){
g.setColor(Color.gray);
if(use_degrees==1){
for(int i=1; i<(aNp+4);i++){
pp1=new point(i*pi2,0.0,(i*360)+"\u00B0",R1);
pp2=new point(-1.0*i*pi2,0.0,"-"+(i*360)+"\u00B0",R1);
pp1.trace(g);pp2.trace(g);
}
}
else
{
for(int i=1; i<(aNp+4);i++){
pp1=new point(i*pi2,0.0,2*i+"\u03C0",R1);
pp2=new point(-1.0*i*pi2,0.0,"-"+2*i+"\u03C0",R1);
pp1.trace(g);pp2.trace(g);
}
}
}
g.setColor(Color.red);
if(type==1){
yP=(double) Math.cos(O1.x + Ma);
P.point(O1.x + Ma, yP);
}
else
{
yP=(double) Math.sin(O1.x + Ma);
P.point(O1.x + Ma, yP);
hline.Droite(P,M);hline.trace(g);
}
Pcosx.point(P.x,0);Pcosx.trace(g);
value.Segment(Pcosx,P);value.trace(g);
if(use_end==1){g.setColor(Color.green);Endpoint.trace(g);}
g.setColor(Color.orange);
functie.trace(g);
}
g.setColor(Color.black);
g.drawString(rem5,getSize().width/2,20);
if(use_degrees==1){g.drawString(rem4+(double)(Math.round(10*degrees))/10 +"\u00B0",getSize().width/2, getSize().height - 30);}
if(use_degrees==2){g.drawString(rem4+(double)(Math.round(1000*degrees/180))/1000 +rem3,getSize().width/2, getSize().height - 30);}
if(absdegrees>180){g.drawString(rem2,getSize().width/2, getSize().height - 50);}
C.trace(g);
R1.cadre(g);
P.trace(g);P.traceNom(g);
if(modepaint==2){
g.setColor(Color.red);
g.drawString(rem1,getSize().width/2, getSize().height - 40);
}
if(modepaint==0){g.setColor(Color.red);}
M.trace(g);
g1.drawImage(img, 0, 0, this);
}
 
public void mousePressed(MouseEvent e){
e.consume();
if( M.zone(e.getX(), e.getY()) ){
modepaint = 0 ;
X = -1 ;
repaint();
}
else
{
modepaint=2;
}
}
 
public void update(Graphics g1){paint(g1);}
 
public void mouseDragged(MouseEvent e)
{ e.consume();
M.bouge(e.getX(), e.getY());
if(M.a * ap < 0.0){
if(ap > 2.0){
periodes ++ ;
}
else
{
if(ap < -2.0){
periodes -- ;
}
}
}
ap = M.a ;
if(curve==1){
absdegrees=Math.abs(degrees);
if(absdegrees>180){scale=(absdegrees/180)*minscale;}
R1.Repere(xz,yz, getSize().width, getSize().height,getSize().width/scale,getSize().width/scale);
}
O1.bouge(e.getX(), e.getY());
repaint();
}
 
public void mouseReleased(MouseEvent e)
{ e.consume();
M.deplace = O1.deplace = false ; modepaint = 1 ;
repaint();
}
 
public void mouseMoved(MouseEvent e){
e.consume();
if(modepaint == 1){
if( M.zone(e.getX(), e.getY())){
this.X = e.getX() + 2 ; this.Y = e.getY() + 2 ;
M.deplace = false ;
}
Xret = e.getX(); Yret = e.getY();
repaint();
}
}
 
public void mouseClicked(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
 
public String getAppletInfo()
{ return "Written by J.P. Quelen\nModified for WIMS \n J.M. Evers 3/2008" ; }
 
protected class sin extends Fonction{
public boolean defini(double x){ return true ; }
public double Image(double x){ return Math.sin(x); }
}
 
protected class cos extends Fonction{
public boolean defini(double x){ return true ; }
public double Image(double x){ return Math.cos(x); }
}
// reading the degrees value of the applet by javascript
public String ReadApplet(){
double radialen=(Math.round(100.0*degrees/180.0))/100.0;
double deg=Math.round(degrees);
String reply=degrees+","+rem4+radialen+rem3+","+rem4+deg+"\u00B0";
return reply;
}
public void start(){}
public void stop(){}
public void destroy(){}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/pt.java
0,0 → 1,186
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
// pt.java - 09/12/98
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Point de coordonnées (x, y). X, Y sont les coordonnées sur l'écran.
* La variable Nom contient le Nom de ce point (souvent une lettre) ;
* R est le repère attaché à ce point ;
* defini précise si le point existe réellement (utile pour les problèmes d'intersection).
*/
 
public class pt extends ObjetRepere
{
 
/**
* Position du point sur l'écran.
*/
 
public int X, Y ;
 
/**
* Abscisse du point.
*/
 
public double x ;
 
/**
* Ordonnée du point.
*/
 
public double y ;
 
/**
* Construit un point abstrait.
*/
 
public pt (String Nom, Repere R)
{ super (Nom, R) ; }
 
/**
* Construit la copie du point A.
*/
 
public pt (pt A, String Nom, Repere R)
{ super (Nom, R) ; X = A.X ; Y = A.Y ;
x = A.x ; y = A.y ;
defini = A.defini ; }
 
/**
* Construit le point par sa position (X, Y) dans la fenêtre d'affichage.
*/
 
public pt (int X, int Y, String Nom, Repere R)
{ super (Nom, R) ; this.X = X ; this.Y = Y ;
x = R.Abs (X) ; y = R.Ord (Y) ;
defini = true ; }
 
 
/**
* Construit le point de coordonnées (x, y) relativement au repère R.
*/
 
public pt (double x, double y, String Nom, Repere R)
{ super (Nom, R) ;
this.x = x ; this.y = y ;
majXY () ; defini = true ; }
 
/**
* Met à jour la position (X, Y) du point à l'aide des coordonnées (x, y).
*/
 
public void majXY ()
{ X = R.Iabs (x) ; Y = R.Iord (y) ; }
 
 
/**
* Positionnement du point au milieu du bi-point AB.
*/
 
public void Milieu (pt A, pt B)
{ x = (A.x + B.x) / 2.0 ; y = (A.y + B.y) / 2.0 ;
majXY () ;
defini = A.defini && B.defini ; }
 
/**
* Point sur le symétrique de A par rapport au point C.
*/
 
public void Symetrique (pt A, pt C)
{ defini = A.defini && C.defini ;
if (defini) { x = 2.0 * C.x - A.x ; y = 2.0 * C.y - A.y ; majXY () ; }
}
 
/**
* Donne l'image du point A par la rotation de centre O et d'angle a.
*/
 
public void Rotation (pt A, pt O, double a)
{ defini = A.defini && O.defini ;
if (defini) { double OAx = A.x - O.x ;
double OAy = A.y - O.y ;
double cosa = Math.cos (a) ;
double sina = Math.sin (a) ;
x = O.x + cosa * OAx - sina * OAy ;
y = O.y + sina * OAx + cosa * OAy ;
majXY () ;
}
}
 
/**
* Donne l'image du point A par l'homothétie de centre O et de rapport k.
*/
 
public void Homothetique (pt A, pt O, double k)
{ defini = A.defini && O.defini ;
if (defini) { x = O.x + k * (A.x - O.x) ;
y = O.y + k * (A.y - O.y) ;
majXY () ;
}
}
 
/**
* Donne la distance du point A au point courant.
*/
 
public double Distance (pt A)
{ if (defini && A.defini)
{ double dx = x - A.x ; double dy = y - A.y ;
return Math.sqrt(dx * dx + dy * dy) ;
}
else return -1.0 ; }
 
/**
* teste si la souris est proche du point libre, retourne alors deplace = true
*/
 
public boolean zone (int X, int Y)
{ return ((X >= this.X - 2) && (X <= this.X + 2) && (Y >= this.Y - 2) && (Y <= this.Y + 2)) ; }
 
/**
* Trace ou efface le point.
*/
 
public void trace (Graphics g)
{ if (defini) { g.fillRect (X - 1, Y - 1, 3, 3);
if (Nom.length () != 0) g.drawString (Nom, X + 3, Y - 3); } }
 
/**
* Trace ou efface uniquement le Nom du point.
*/
 
public void traceNom (Graphics g)
{ if (defini && (Nom.length () != 0)) g.drawString (Nom, X + 3, Y - 3) ; }
 
/**
* Redéfinit le point par des coordonnées (x, y).
*/
 
public void point (double x, double y)
{ this.x = x ; this.y = y ; majXY () ; defini = true ; }
 
/**
* Redéfinit le point.
*/
 
public void point ()
{ majXY () ; }
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Scalaire.java
0,0 → 1,67
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Nombre lié à un repère.
*/
 
public class Scalaire extends ObjetRepere
{
 
/**
* Scalaire.
*/
 
public double d ;
 
/**
* Construit un nombre non défini.
*/
 
public Scalaire (String Nom, Repere R )
{ super (Nom, R ) ; }
 
/**
* Construit un nombre.
*/
 
public Scalaire (double d, String Nom, Repere R)
{ super (Nom, R ) ; this.d = d ; defini = true ; }
 
/**
* Donne l'angle de deux vecteurs.
*/
 
public void Angle (Vecteur u, Vecteur v)
{ defini = u.defini && v.defini &&
(u.x != 0.0 || u.y != 0.0) && (v.x != 0.0 || v.y != 0.0) ;
if (defini)
{ d = Math.acos ((u.x * v.x + u.y * v.y) / (u.Norme () * v.Norme ())) ;
if ((u.x * v.y - u.y * v.x) < 0.0) d = - d ;
}
}
 
/**
*Redéfinit le scalaire.
*/
 
public void Scalaire (double d)
{ this.d = d ; defini = true ; }
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/DemiDroite.java
0,0 → 1,147
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
import java.awt.Graphics ;
import geo.ObjetRepere ;
import geo.pt ;
import geo.Vecteur ;
 
/**
* Demi-droite [AB).
*/
 
public class DemiDroite extends ObjetRepere
{
 
/**
* Coordonnée de A.
*/
 
public double Ax, Ay ;
 
/**
* Coordonnée de B.
*/
 
public double Bx, By ;
 
/**
* Construit la demi-droite [AB).
*/
 
public DemiDroite (pt A, pt B, String Nom, Repere R)
{ super (Nom, R) ; DemiDroite (A, B) ; }
 
/**
* Construit une demi-droite non définie.
*/
 
public DemiDroite (String Nom, Repere R)
{ super (Nom, R) ; }
 
/**
* Construit la demi-droite [AB) à partir des coordonnées respectives (Ax, Ay) et (Bx, By) de A et B.
*/
 
public DemiDroite (double Ax, double Ay, double Bx, double By, String Nom, Repere R)
{ super (Nom, R) ; DemiDroite (Ax, Ay, Bx, By) ; }
 
/**
* Construit la demi-droite [Au où u est un vecteur.
*/
 
public DemiDroite (pt A, Vecteur u, String Nom, Repere R)
{ super (Nom, R) ; DemiDroite (A, u) ; }
 
/**
* Teste si la souris est proche de la demi-droite.
*/
 
public boolean zone (int X, int Y)
{ if (defini)
{ double x = R.Abs (X) ; double y = R.Ord (Y) ;
double a = By - Ay ; double b = Ax - Bx ;
double A = a / R.unitex ; double B = b / R.unitey ;
double d = Math.abs (a * x + b * y + Ay * Bx - Ax * By) / Math.sqrt (A * A + B * B) ;
double xax = x - Ax ; double xbx = x - Bx ; double yay = y - Ay ; double yby = y - By ;
if ((d <= 4.0) && ((xax * xbx <= 0) && (yay * yby <= 0) || (xax * xax + yay * yay >= xbx * xbx + yby * yby)))
return true ;
else return false ;
}
return false ;
}
 
/**
* Trace ou efface le DemiDroite.
*/
 
public void trace (Graphics g)
{ int N, X1, Y1, X2, Y2 ;
X1 = Y1 = X2 = Y2 = 0 ;
double a = By - Ay ; double b = Ax - Bx ; double c = Ay * Bx - Ax * By ;
if (defini) { if (Math.abs (b) >= Math.abs (a)) if (b < 0.0) { X1 = R.Iabs (Ax) ; Y1 = R.Iord (Ay) ;
X2 = R.XMAX ;
Y2 = R.Iord (-(a * R.Abs (X2) + c) / b) ;
}
else { X1 = 0 ;
Y1 = R.Iord (-(a * R.Abs (X1) + c) / b) ;
X2 = R.Iabs (Ax) ; Y2 = R.Iord (Ay) ;
}
else if (a > 0.0) { Y1 = 0 ;
X1 = R.Iabs (-(b * R.Ord (0) + c) / a);
X2 = R.Iabs (Ax) ; Y2 = R.Iord (Ay) ;
}
else { X1 = R.Iabs (Ax) ; Y1 = R.Iord (Ay) ;
Y2 = R.YMAX;
X2 = R.Iabs (-(b * R.Ord (Y2) + c) / a) ;
}
g.drawLine (X1, Y1, X2, Y2);
if (Nom.length () != 0) g.drawString (Nom, (X1 + X2) / 2 + 3, (Y1 + Y2) / 2 - 3) ;
}
}
 
 
 
 
/**
* Redéfinit la demi-droite [AB].
*/
 
public void DemiDroite (pt A, pt B)
{ defini = A.defini && B.defini && ((A.x != B.x) || (A.y != B.y)) ;
if (defini) { Ax = A.x ; Ay = A.y ; Bx = B.x ; By = B.y ; }
}
 
/**
* Redéfinit la demi-droite à partir des points de coordonnées (Ax, Ay) et (Bx, By).
*/
 
public void DemiDroite (double Ax, double Ay, double Bx, double By)
{ defini = ((Ax != Bx) || (Ay != By)) ;
if (defini) { this.Ax = Ax ; this.Ay = Ay ; this.Bx = Bx ; this.By = By ; }
}
 
/**
* Redéfinit la demi-droite [Au où u est un vecteur.
*/
 
public void DemiDroite (pt A, Vecteur u)
{ defini = ((u.x != 0.0) || (u.y != 0.0)) ;
if (defini) { Ax = A.x ; Ay = A.y ; Bx = A.x + u.x ; By = A.y + u.y ; }
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Droite.java
0,0 → 1,243
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Droite d'équation a x + b y + c = 0 (a et b non tous nuls).
*/
 
public class Droite extends ObjetRepere
{
 
/**
* Coefficient de l'équation de la droite.
*/
 
public double a, b, c;
 
/**
* Construit une droite non définie.
*/
 
public Droite (String Nom, Repere R)
{ super (Nom, R); }
 
/**
* Construit la copie de la droite d.
*/
 
public Droite (Droite d, String Nom, Repere R)
{ super (Nom, R); Droite (d) ; }
 
/**
* Construit la droite AB.
*/
 
public Droite (pt A, pt B, String Nom, Repere R)
{ super (Nom, R); Droite (A, B) ; }
 
/**
* Construit la droite passant par A et de vecteur directeur u.
*/
 
public Droite (pt A, Vecteur u, String Nom, Repere R)
{ super (Nom, R); Droite (A, u) ; }
 
/**
* Construit la droite passant par les points de coordonnées (xA, yA) et (xB, yB).
*/
 
public Droite (double xA, double yA, double xB, double yB, String Nom, Repere R)
{ super (Nom, R); Droite (xA, yA, xB, yB) ; }
 
/**
* Construit la droite d'équation a x + b y + c = 0.
*/
 
public Droite (double a, double b, double c, String Nom, Repere R)
{ super (Nom, R); Droite (a, b, c) ; }
 
/**
* Construit la droite à partir du segment s.
*/
 
public Droite (Segment s, String Nom, Repere R)
{ super (Nom, R); Droite (s) ; }
 
/**
* Définit la droite comme parallèle à la droite d et passant par A.
*/
 
public void Parallele (Droite d, pt A)
{ a = d.a; b = d.b; c = - (d.a * A.x + d.b * A.y);
defini = d.defini; }
 
/**
* retourne la parallèle au segment s passant par A
*
*/
 
public void Parallele (Segment s, pt A)
{ a = s.By - s.Ay; b = s.Ax - s.Bx;
c = - (a * A.x + b * A.y);
defini = ((a != 0.0) || (b != 0.0)) && (A.defini) ;
}
 
/**
* Définit la droite comme perpendiculaire à la droite d et passant par A.
*/
 
public void Perpendiculaire (Droite d, pt A)
{ a = - d.b; b = d.a; c = d.b * A.x - d.a * A.y;
defini = d.defini && A.defini ; }
 
/**
* retourne la perpendiculaire du segment s passant par A
*
*/
 
public void Perpendiculaire (Segment s, pt A)
{ b = s.By - s.Ay; a = s.Bx - s.Ax;
c = - (a * A.x + b * A.y);
defini = ((a != 0.0) || (b != 0.0)) && A.defini ;
}
 
/**
* Définit la droite comme médiatrice de [AB].
*/
 
public void Mediatrice (pt A, pt B)
{ defini = A.defini && B.defini && ((A.x != B.x) || (A.y != B.y)) ;
if (defini) { a = B.x - A.x ; b = B.y - A.y ;
c = (A.x * A.x - B.x * B.x + A.y * A.y - B.y * B.y) * 0.5 ;
}
}
 
/**
* Définit la droite comme bissectrice de l'angle ABC.
*/
 
public void Bissectrice (pt A, pt B, pt C)
{ defini = A.defini && B.defini && C.defini ;
if (defini) { double bcx = C.x - B.x ; double bcy = C.y - B.y ;
double bc = Math.sqrt (bcx * bcx + bcy * bcy) ;
double bax = A.x - B.x ; double bay = A.y - B.y ;
double ba = Math.sqrt (bax * bax + bay * bay) ;
bax = bc * bax ; bay = bc * bay ; bcx = ba * bcx ; bcy = ba * bcy ;
Droite (B.x, B.y, B.x + bax + bcx, B.y + bay + bcy) ;
}
}
 
/**
* Teste si la souris est proche de la droite.
*/
 
public boolean zone (int X, int Y)
{ if (defini)
{ double A = a / R.unitex ; double B = b / R.unitey ;
double d = Math.abs (a * R.Abs (X) + b * R.Ord (Y) + c) / Math.sqrt (A * A + B * B) ;
if (d <= 4.0) return true ; else return false ;
}
return false ;
}
 
/**
* Trace ou efface la droite.
*/
 
public void trace (Graphics g)
{ int N, X1, Y1, X2, Y2;
X1 = Y1 = X2 = Y2 = 0;
if (defini)
{ if (Math.abs (b) >= Math.abs (a))
{ X1 = 0;
Y1 = R.Iord (-(a * R.Abs (0) + c) / b);
X2 = R.XMAX;
Y2 = R.Iord (-(a * R.Abs (X2) + c) / b); }
else
{ Y1 = 0;
X1 = R.Iabs (-(b * R.Ord (0) + c) / a);
Y2 = R.YMAX;
X2 = R.Iabs (-(b * R.Ord (Y2) + c) / a); }
g.drawLine (X1, Y1, X2, Y2) ;
if (Nom.length () != 0)
{ int i ;
if (Math.abs (b) >= Math.abs (a))
{ i = R.XMAX / 2 ;
g.drawString (Nom, i + 3, R.Iord (- (a * R.Abs (i) + c) / b) - 3) ;
}
else
{ i = R.YMAX / 2 ;
g.drawString (Nom, R.Iabs (- (b * R.Ord (i) + c) / a) + 3, i - 3) ;
}
}
}
}
 
/**
* Redéfinit la droite passant par A et B.
*/
 
public void Droite (pt A, pt B)
{ a = B.y - A.y; b = A.x - B.x ;
c = A.y * B.x - A.x * B.y ;
defini = ((a != 0.0) || (b != 0.0)) && A.defini && B.defini ; }
 
/**
* Redéfinit la droite passant par A et de vecteur directeur u.
*/
 
public void Droite (pt A, Vecteur u)
{ defini = A.defini && u.defini && (u.x != 0.0 || u.y != 0.0) ;
a = u.y ; b = - u.x ;
c = A.y * u.x - A.x * u.y ; }
 
/**
* Redéfinit la droite passant par les points de coOrdonnées (xA, yA) et (xB, yB).
*/
 
public void Droite (double xA, double yA, double xB, double yB)
{ a = yB - yA ; b = xA - xB ;
c = yA * xB - xA * yB ; defini = (a != 0.0) || (b != 0.0) ;
}
 
/**
* Redéfinit la droite d'équation a x + b y + c = 0.
*/
 
public void Droite (double a, double b, double c)
{ this.a = a ; this.b = b ; this.c = c ; defini = (a != 0.0) | (b != 0.0) ; }
 
/**
* Redéfinit la droite à partir de d.
*/
 
public void Droite (Droite d)
{ a = d.a; b = d.b; c = d.c; defini = d.defini ; }
 
/**
* Redéfinit la droite à partir du segment s.
*/
 
public void Droite (Segment s)
{ defini = s.defini ;
if (defini) Droite (s.Ax, s.Ay, s.Bx, s.By) ;
}
 
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/CourbeDeFonction.java
0,0 → 1,73
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Courbe d'une fonction.
*/
 
public class CourbeDeFonction extends ObjetRepere
{
Fonction f ;
 
/**
* Définit la courbe à partir d'une fonction.
*/
 
public CourbeDeFonction (Fonction f, String Nom, Repere R)
{ super (Nom, R) ; this.f = f ; }
 
 
/**
* Trace ou efface la courbe.
*/
 
public void trace (Graphics g)
{ int X, Y ;
double x ;
for (X = 0 ; X <= R.XMAX ; X++)
{ x = R.Abs (X) ;
if (f.defini (x))
{ Y = R.Iord (f.Image (x)) ;
if ((Y >=0) && (Y <= R.YMAX)) g.drawLine (X, Y, X, Y) ;
}
}
if (Nom.length () != 0)
{ int U = R.XMAX / 2 ;
for (X = R.XMAX / 2 ; X >= 0 ; X --)
{ x = R.Abs (X) ;
if (f.defini (x))
{ Y = R.Iord (f.Image (x)) ;
if ((Y >=0) && (Y <= R.YMAX))
{ g.drawString (Nom, X + 3, Y - 3) ;
break ;
}
}
x = R.Abs (U) ;
if (f.defini (x))
{ Y = R.Iord (f.Image (x)) ;
if ((Y >=0) && (Y <= R.YMAX))
{ g.drawString (Nom, X + 3, Y - 3) ;
break ;
}
}
U ++ ;
}
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/point.java
0,0 → 1,270
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
// geo/point.java - 02/12/98
 
package geo ;
 
/**
* Super classe contenant tous les points calculés tels les points d'intersections de Droites et Cercles.
*/
 
public class point extends pt
{
 
/**
* Construit un point non défini.
*/
 
public point (String Nom, Repere R)
{ super (Nom, R) ; }
 
/**
* Construit une copie du point A.
*/
 
public point (pt A, String Nom, Repere R)
{ super (A, Nom, R) ; }
 
/**
* Construit le point placé en (X, Y) sur la fenêtre d'affichage.
*/
 
public point (int X, int Y, String Nom, Repere R)
{ super (X, Y, Nom, R) ; }
 
/**
* Construit le point de coordonnées (x, y).
*/
 
public point (double x, double y, String Nom, Repere R)
{ super (x, y, Nom, R) ; }
 
/**
* Donne le milieu du Segment s.
*/
 
public void Milieu (Segment s)
{ defini = s.defini ;
if (defini) { x = (s.Ax + s.Bx) / 2.0 ; y = (s.Ay + s.By) / 2.0 ; majXY () ; }
}
 
/**
* Donne l'intersection des droites d1 et d2.
*/
 
public void Intersection (Droite d1, Droite d2)
{ double det = d1.a * d2.b - d2.a * d1.b ;
defini = (d1.defini) && (d2.defini) && (det != 0.0) ;
if (defini) { x = (d2.c * d1.b - d1.c * d2.b) / det ;
y = (d2.a * d1.c - d1.a * d2.c) / det ;
majXY () ; }
}
/**
* Donne l'intersection des segments s1 et s2.
*/
 
public void Intersection (Segment s1, Segment s2)
{ double a1 = s1.By - s1.Ay ; double b1 = s1.Ax - s1.Bx ; double c1 = s1.Ay * s1.Bx - s1.Ax * s1.By ;
double a2 = s2.By - s2.Ay ; double b2 = s2.Ax - s2.Bx ; double c2 = s2.Ay * s2.Bx - s2.Ax * s2.By ;
double det = a1 * b2 - a2 * b1 ;
defini = (s1.defini) && (s2.defini) && (det != 0.0) ;
if (defini) { x = (c2 * b1 - c1 * b2) / det ;
y = (a2 * c1 - a1 * c2) / det ;
majXY () ; }
}
 
/**
* Donne le premier point d'intersection, s'il existe, de la droite d et du cercle c.
*/
 
public void Intersection1 (Droite d, Cercle c)
{ i12 (d, c, 1.0) ; }
 
 
/**
* Donne le second point d'intersection, s'il existe, de la Droite d et du Cercle c.
*/
 
public void Intersection2 (Droite d, Cercle c)
{ i12 (d, c, -1.0) ; }
 
private void i12 (Droite d, Cercle c, double signe)
{ defini = (d.defini) && (c.defini) ;
if (defini) { if (d.b != 0.0) { double u = d.a * (d.c + d.b * c.yo) - d.b * d.b * c.xo ;
double v = d.a * d.a + d.b * d.b ;
double w = d.c + d.b * c.yo ;
double deltap = u * u - v * (d.b * d.b * (c.xo * c.xo - c.r * c.r) + w * w) ;
if (deltap >= 0.0) { x = (- u + signe * Math.sqrt (deltap)) / v ;
y = - (d.a * x + d.c) / d.b ; }
else defini = false ;
}
else { x = - d.c / d.a ;
double u = x - c.xo ;
double v = c.r * c.r - u * u ;
if (v >= 0.0) y = c.yo + signe * Math.sqrt (v) ;
else defini = false ;
}
majXY () ;
}
}
 
/**
* Donne le premier point d'intersection de deux cercles quand celui-ci existe.
*/
 
public void Intersection1 (Cercle c1, Cercle c2)
{ icc (c1, c2, 1.0) ; }
 
 
/**
* Donne le second point d'intersection de 2 Cercles quand celui-ci existe.
*/
 
public void Intersection2 (Cercle c1, Cercle c2)
{ icc (c1, c2, -1.0) ; }
 
private void icc (Cercle c1, Cercle c2, double signe)
{ if (defini = c1.defini && c2.defini)
{ double a1 = -2.0 * c1.xo ; double b1 = -2.0 * c1.yo ;
double a2 = -2.0 * c2.xo ; double b2 = -2.0 * c2.yo ;
double a12 = a1 - a2 ; double b12 = b1 - b2 ;
double a = a12 * a12 + b12 * b12 ;
if (defini = (a != 0.0))
{ double C1 = c1.xo * c1.xo + c1.yo * c1.yo - c1.r * c1.r ;
double C2 = c2.xo * c2.xo + c2.yo * c2.yo - c2.r * c2.r ;
double C12 = C1 - C2 ;
double b, c;
boolean bpga = Math.abs(b12) >= Math.abs(a12) ;
if (bpga)
{ b = 2.0 * a12 * C12 + b12 * (b1 * a2 - a1 * b2) ;
c = C12 * C12 + b12 * (b1 * C2 - b2 * C1) ;
}
else
{ b = 2.0 * b12 * C12 + a12 * (a1 * b2 - b1 * a2) ;
c = C12 * C12 + a12 * (a1 * C2 - a2 * C1) ;
}
double delta = b * b - 4.0 * a * c ;
if (defini = (delta >= 0.0))
{ x = -0.5 * (b + signe * Math.sqrt (delta)) / a ;
if (bpga) y = - (a12 * x + C12) / b12 ;
else
{ y = x ; x = - (b12 * x + C12) / a12 ;
}
majXY () ;
}
}
}
}
 
/**
* Donne le centre d'un cercle.
*/
 
public void Centre (Cercle c)
{ defini = c.defini ;
if (defini) { x = c.xo ; y = c.yo ; majXY () ; }
}
 
/**
* Donne le projeté d'un point sur une Droite.
*/
 
public void Projection (pt A, Droite d)
{ defini = A.defini && d.defini ;
if (defini) { double u = (d.a * A.x + d.b * A.y + d.c) / (d.a * d.a + d.b * d.b) ;
x = A.x - u * d.a ; y = A.y - u * d.b ;
majXY () ;
}
}
 
/**
* Donne le projeté d'un point sur un segment (le point peut être à l'extérieur du segment).
*/
 
public void Projection (pt A, Segment s)
{ double a, b ;
a = s.Ay - s.By ; b = s.Bx - s.Ax ;
defini = A.defini && ((a != 0.0) || (b != 0.0)) ;
if (defini) { double c = - (a * s.Ax + b * s.Ay) ;
double u = (a * A.x + b * A.y + c) / (a * a + b * b) ;
x = A.x - u * a ; y = A.y - u * b ;
majXY () ;
}
}
 
/**
* Donne le symétrique de A par rapport à la droite d.
*/
 
public void Symetrique (pt A, Droite d)
// modifié le 27/09/99 pour autoriser C.Symetrique (C, d) ;
{ double Ax = A.x ; double Ay = A.y ; Projection (A, d) ;
if (defini) { x = 2.0 * x - Ax ; y = 2.0 * y - Ay ; majXY () ; }
}
 
/**
* Donne le symétrique de A par rapport au segment s.
*/
 
public void Symetrique (pt A, Segment s)
{ double Ax = A.x ; double Ay = A.y ; Projection (A, s) ;
if (defini) { x = 2.0 * x - Ax ; y = 2.0 * y - Ay ; majXY () ; }
}
 
/**
* Donne l'image de A par la rotation de centre O et d'angle correspondant à l'arc de cercle ARC.
*/
 
public void Rotation1 (pt A, pt O, ArcDeCercle ARC)
{ if (defini = ARC.defini) Rotation (A, O, ARC.b) ;
}
 
/**
* Retourne la distance du point à une droite.
*/
 
public double Distance (Droite d)
{ if (defini && d.defini) return Math.abs (d.a * x + d.b * y + d.c) / Math.sqrt (d.a * d.a + d.b * d.b) ;
else return -1.0 ;
}
 
 
/**
* Retourne la distance du point à un segment.
*/
 
public double Distance (Segment s)
{ double resultat = -1.0 ;
if (defini && s.defini) { double a = s.By - s.Ay ; double b = s.Ax - s.Bx ;
if ((a != 0.0) || (b != 0.0))
resultat = Math.abs (a * x + b * y + s.Ay * s.Bx - s.Ax * s.By) / Math.sqrt (a * a + b * b) ;
}
return resultat ;
}
 
/**
* Donne l'image du point A par la translation de vecteur v.
*/
 
public void Translation (pt A, Vecteur v)
{ defini = A.defini && v.defini ;
if (defini)
{ x = A.x + v.x ; y = A.y + v.y ;
majXY () ;
}
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Element.java
0,0 → 1,164
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
// geo/Element.java - 09/12/98
 
package geo ;
 
import java.awt.* ;
 
/**
* Définit un élement d'une figure géométrique.
*/
 
public class Element
{
 
/**
* Valeur de l'identificateur de l'élement de la figure.
*/
 
public final static int PT_X_Y = 1 ;
public final static int PT_MILIEU_PT_PT = 2 ;
public final static int PT_ROTATION_PT_A = 3 ;
public final static int PT_HOMOTHETIQUE_PT_PT_K = 4 ;
public final static int PT_SYMETRIQUE_PT_PT = 5 ;
public final static int POINTLIBRE = 6 ;
public final static int POINTSURDROITE_DT = 7 ;
public final static int POINTSURCERCLE_CRCL = 8 ;
public final static int POINT_CENTRE = 9 ;
public final static int POINT_INTER_DT_DT = 10 ;
public final static int POINT_INTER1_DT_CRCL = 11 ;
public final static int POINT_INTER2_DT_CRCL = 12 ;
public final static int POINT_INTER1_CRCL_CRCL = 13 ;
public final static int POINT_INTER2_CRCL_CRCL = 14 ;
public final static int POINT_PROJECTION_PT_DT = 15 ;
public final static int POINT_PROJECTION_PT_SEG = 16 ;
public final static int POINT_SYMETRIQUE_PT_DT = 17 ;
public final static int POINT_SYMETRIQUE_PT_SEG = 18 ;
public final static int POINT_ROTATION_PT_PT_ARCDECERCLE = 19 ;
public final static int POINT_TRANSLATION_PT_VECT = 20 ;
public final static int ARCDECERCLE_PT_PT_PT = 21 ;
public final static int CERCLE_PT_R = 22 ;
public final static int CERCLE_PT_PT = 23 ;
public final static int CERCLE_PT_PT_PT = 24 ;
public final static int SEGMENT_PT_PT = 25 ;
public final static int VECTEUR_PT_PT = 26 ;
public final static int VECTEUR_SOMME_V_W_PT = 27 ;
public final static int VECTEUR_PRODUIT_V_K_PT = 28 ;
public final static int VECTEUR_PT_PT_PT = 29 ;
public final static int DROITE_PT_PT = 30 ;
public final static int DROITE_PT_VECT = 31 ;
public final static int DROITE_A_B_C = 32 ;
public final static int DROITE_PARA_DT_PT = 33 ;
public final static int DROITE_PARA_SEG_PT = 34 ;
public final static int DROITE_PERP_DT_PT = 35 ;
public final static int DROITE_PERP_SEG_PT = 36 ;
public final static int DROITE_MEDI_PT_PT = 37 ;
public final static int DROITE_BISS_PT_PT_PT = 38 ;
public final static int DEMIDROITE_PT_PT = 39 ;
public final static int DEMIDROITE_PT_VECT = 40 ;
public final static int NOMBRE = 41 ;
public final static int NOMBRE_PT_ABS = 42 ;
public final static int NOMBRE_PT_ORD = 43 ;
public final static int NOMBRE_DISTANCE_PT_DR = 44 ;
public final static int NOMBRE_DISTANCE_PT_PT = 45 ;
public final static int NOMBRE_NORME_VECT = 46 ;
public final static int NOMBRE_LONGUEUR_SEG = 47 ;
public final static int NOMBRE_RAYON_CRCL = 48 ;
public final static int NOMBRE_SOMME = 49 ;
public final static int NOMBRE_DIFFERENCE = 50 ;
public final static int NOMBRE_PRODUIT = 51 ;
public final static int NOMBRE_QUOTIENT = 52 ;
public final static int NOMBRE_OPPOSE = 53 ;
public final static int NOMBRE_VABS = 54 ;
public final static int NOMBRE_RACINE = 55 ;
public final static int NOMBRE_COS = 56 ;
public final static int NOMBRE_SIN = 57 ;
public final static int NOMBRE_ARCCOS = 58 ;
public final static int NOMBRE_ARCSIN = 59 ;
public final static int NOMBRE_LN = 60 ;
public final static int NOMBRE_PUISSANCE = 61 ;
 
/**
* Identificateur de l'élement de la figure.
*/
 
public int id ;
 
/**
* Couleur de l'objet.
*/
 
public Color couleur ;
 
/**
* Objet géométrique.
*/
 
public ObjetRepere obj ;
 
/**
* Indique l'adresse des éléments servant à construire l'élément courant.
*/
 
public int args [] = {0, 0, 0} ;
 
/**
* Construction de l'élément.
*/
 
public Element (int id, Color couleur, ObjetRepere obj, int arg0, int arg1, int arg2)
{ this.id = id ; this.couleur = couleur ; this.obj = obj ;
args [0] = arg0 ; args [1] = arg1 ; args [2] = arg2 ; }
 
/**
* Construction d'un élément vide.
*/
 
public Element (int id)
{ this.id = id ; }
 
/**
* Effacement (graphique) de l'objet.
*/
 
public void efface (Graphics g)
{ if ((id >= PT_X_Y) && (id < NOMBRE))
switch (id)
{ case POINTLIBRE :
case POINTSURDROITE_DT :
case POINTSURCERCLE_CRCL :
if (((pointlibre) obj).deplace)
{ ((pointlibre) obj).efface (g) ;
break ;
}
default : obj.trace (g) ;
}
}
 
/**
* Tracé de l'objet.
*/
 
public void trace (Graphics g)
{ if ((id >= PT_X_Y) && (id < NOMBRE) && (couleur != Color.white))
{ g.setColor (couleur) ;
obj.trace (g) ;
}
}
 
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/PointSurDroite.java
0,0 → 1,65
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
/**
* Définit un point d'une droitedont on peut modifier l'emplacement.
*/
 
public class PointSurDroite extends pointlibre
{ public Droite d ;
 
/**
* Construit un point de position modifiable, projeté de M sur d.
*/
 
public PointSurDroite (int X, int Y, Droite d, String Nom, Repere R)
{ super (R.Abs (X), R.Ord (Y), Nom, R) ; this.d = d ; point () ; }
 
/**
* Construit un point de position modifiable, projeté de M (x, y) sur d.
*/
 
public PointSurDroite (double x, double y, Droite d, String Nom, Repere R)
{ super (x, y, Nom, R) ; this.d = d ; point () ; }
 
/**
* Pour un point en cours de déplacement, met à jour (X, Y) et met dans (Xp, Yp) les anciennes
* coordonnées "écran".
*/
 
public void bouge (int X, int Y)
{ if (deplace && defini && R.affiche (X, Y))
{ Xp = this.X ; Yp = this.Y ;
x = R.Abs (X) ; y = R.Ord (Y) ;
double k = (d.a * x + d.b * y + d.c) / (d.a * d.a + d.b * d.b) ;
x = x - k * d.a; y = y - k * d.b ;
this.X = R.Iabs (x); this.Y = R.Iord (y) ;
}
}
 
/**
* Redéfinit le point en cas de modification de la Droite d.
*/
 
public void point ()
{ if (d.defini) { double k = (d.a * x + d.b * y + d.c) / (d.a * d.a + d.b * d.b) ;
x = x - k * d.a ; y = y - k * d.b ;
Xp = X = R.Iabs (x) ; Yp = Y = R.Iord (y) ; }
defini = d.defini;
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/ArcDeCercle.java
0,0 → 1,191
// ArcDeCercle - 02/12/98 - 07/09/99 - 10/01/2001
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Définit un arc de cercle de centre de coordonnées (xo, yo) de rayon r relativement au repère R
* partant de A (xo + r cos a, yo + r sin a) allant vers B (xo + r cos (a+b), yo + r sin (a+b))
* dans le sens trigonométrique si b > 0 dans le sens contraire si b < 0.
*/
 
public class ArcDeCercle extends ObjetRepere
{
 
/**
* Coordonnée du centre de l'arc de cercle.
*/
 
public double xo, yo ;
 
/**
* Rayon de l'arc de cercle.
*/
 
public double r ;
 
/**
* Angle correspondant à une extrémité de l'arc de cercle.
*/
 
public double a, b ;
 
/**
* Construit un arc de cercle non défini.
*/
 
public ArcDeCercle (String Nom, Repere R)
{ super (Nom, R) ; }
 
/**
* Construit l'arc de cercle de centre O de rayon r relativement au repère R.
*/
 
public ArcDeCercle (pt O, double r, double a, double b, String Nom, Repere R)
{ super (Nom, R) ; ArcDeCercle (O, r, a, b) ; }
 
/**
* Construit l'arc de cercle de centre de coordonnées (xo, yo) de rayon r relativement au repère R.
*/
 
public ArcDeCercle (double xo, double yo, double r, double a, double b, String Nom, Repere R)
{ super (Nom, R) ; ArcDeCercle (xo, yo, r, a, b) ; }
 
/**
* Construit l'arc de cercle de centre O passant par A.
*/
 
public ArcDeCercle (pt O, pt A, double a, double b, String Nom, Repere R)
{ super (Nom, R) ; ArcDeCercle (O, A, a, b) ; }
 
/**
* Construit l'arc de cercle correspondant à l'angle AOB.
*/
 
public ArcDeCercle (pt A, pt O, pt B, String Nom, Repere R)
{ super (Nom, R) ; ArcDeCercle (A, O, B) ; }
 
/**
* Trace ou efface l'arc de cercle.
*/
 
public void trace (Graphics g)
{ if (defini) { int B = (int)(b * 180.0 / Math.PI) ;
int B1 = B % 360 ;
if (B1 != 0)
{ int Xo = R.Iabs (xo) ; int Yo = R.Iord (yo);
int RX = (int) (R.unitex * r) ; int RY = (int) (R.unitey * r) ;
g.drawArc (Xo - RX, Yo - RY, 2 * RX, 2 * RY,
(int)(a * 180.0 / Math.PI), B) ;
pt p = new pt (xo + r * Math.cos (a), yo + r * Math.sin (a), "", R) ;
p.Rotation (p, new pt (xo, yo, "", R), b) ;
double x = p.x - xo ; double y = p.y - yo ;
double l = Math.sqrt (x * x + y * y) ;
B = B % 360 ;
if (( B > 0) && (B <= 180) || (B < -180)) y = - y ; else x = - x ;
int X = (int) (y * 4.0 / l) ;
int Y = (int) (x * 4.0 / l) ;
g.drawLine (p.X, p.Y, p.X - X - Y, p.Y + Y - X) ;
g.drawLine (p.X, p.Y, p.X - X + Y, p.Y + Y + X) ;
 
}
if (Nom.length () != 0 )
{ int X = R.Iabs (xo + r * Math.cos (a + b / 2)) + 3 ;
int Y = R.Iord (yo + r * Math.sin (a + b / 2)) - 3 ;
g.drawString (Nom, X, Y) ;
}
}
}
 
/**
* Teste si la souris est proche de l'arc de cercle.
*/
 
public boolean zone (int X, int Y)
{ if (defini)
{ double dx = R.Abs (X) - xo ; double dy = R.Ord (Y) - yo ;
if (Math.abs (Math.sqrt (dx * dx + dy * dy) - r) * (R.unitex + R.unitey) > 3.0)
return false ;
else
{ Scalaire s = new Scalaire ("", R) ; s.Angle (new Vecteur (1.0, 0.0, "", R), new Vecteur (dx, dy, "", R)) ;
//10/01/2001
double angle = na (s.d - a) ;
double bt = na (b) ;
//
return (((bt >= 0.0) && (angle >= 0.0) && (angle <= bt)) || ((bt < 0.0) && (angle <= 0.0) && (angle >= bt))) ;
}
}
return false ;
}
 
//10/01/2001
private double na (double a)
{ double pi2 = 2.0 * Math.PI ;
while (a > Math.PI) a -= pi2 ;
while (a <= - Math.PI) a += pi2 ;
return a ;
}
//
 
/**
* Redéfinit l'arc de cercle de centre O de rayon r.
*/
 
public void ArcDeCercle (pt O, double r, double a, double b)
{ xo = O.x ; yo = O.y ; this.r = r ; this.a = a ; this.b = b ; defini = (r >= 0.0); }
 
/**
* Redéfinit l'arc de cercle de centre de coordonnées (xo, yo) de rayon r relativement au repère R.
*/
 
public void ArcDeCercle (double xo, double yo, double r, double a, double b)
{ this.xo = xo; this.yo = yo; this.r = r ; this.a = a ; this.b = b ; defini = (r >= 0.0); }
 
/**
* Redéfinit l'arc de cercle de centre O passant par A.
*/
 
public void ArcDeCercle (pt O, pt A, double a, double b)
{ defini = O.defini && A.defini ;
this.xo = O.x ; this.yo = O.y ;
r = A.x - O.x ; double d = A.y - O.y ; r = Math.sqrt (r * r + d * d) ;
this.a = a ; this.b = b ;
}
 
/**
* Redéfinit l'arc de cercle correspondant à l'angle AOB.
*/
 
public void ArcDeCercle (pt A, pt O, pt B)
{ defini = O.defini && A.defini && B.defini ;
if (defini)
{ xo = O.x ; yo = O.y ;
Vecteur u = new Vecteur (1.0, 0.0, "", R) ;
Vecteur v = new Vecteur (A.x - O.x, A.y - O.y, "", R) ;
r = v.Norme () ;
Scalaire S = new Scalaire ("", R) ;
S.Angle (u, v) ;
if (defini = S.defini)
{ a = S.d ;
u.Vecteur (B.x - O.x, B.y - O.y) ;
S.Angle (v, u) ;
if (defini = S.defini) b = S.d ;
}
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Polygone.java
0,0 → 1,145
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
// Polygone.java - 12/12/98
 
package geo ;
 
import java.awt.Graphics ;
import java.awt.Polygon ;
 
/**
* Polygone
*/
 
public class Polygone extends ObjetRepere
{
 
public double xi [] ;
public double yi [] ;
 
/**
* uitilisé pour le traçage : "true" pour un remplissage de la figure, "false" pour le dessin du bord uniquement
*/
 
public boolean plein ;
 
public Polygon p ;
 
/**
* Construit un polygone non défini.
*/
 
public Polygone (String Nom, Repere R)
{ super (Nom, R) ; plein = false ; }
 
/**
* Construit le polygone A1, A2, ..., An, A1.
*/
 
public Polygone (pt Ai [], int n, boolean type, String Nom, Repere R)
{ super (Nom, R) ; Polygone (Ai, n, type) ; }
 
/**
* Construit le polygone avec des coordonnees de points.
*/
 
public Polygone (double xi [], double yi [], int n, boolean type, String Nom, Repere R)
{ super (Nom, R) ; Polygone (xi, yi, n, type) ; }
 
/**
* Trace ou efface le polygone.
*/
 
public void trace (Graphics g)
{ if (defini) if (plein) g.fillPolygon (p) ; else g.drawPolygon (p) ;
if ((defini) && (Nom.length () != 0) && (p.npoints > 0))
g.drawString (Nom, p.xpoints [0] + 2 , p.ypoints [0] + 2) ;
}
 
/**
* Teste si le curseur de la souris est proche du polygone.
*/
 
public boolean zone (int X, int Y)
{ boolean resultat = false ;
if (defini) for (int i = 0 ; i < p.npoints ; i ++)
{ int AX = p.xpoints [i] ;
int AY = p.xpoints [i] ;
int BX = (i == p.npoints - 1) ? p.xpoints [0] : p.xpoints [i + 1] ;
int BY = (i == p.npoints - 1) ? p.ypoints [0] : p.ypoints [i + 1] ;
int A = BY - AY ; int B = AX - BX ;
double d = ((double) Math.abs (A * X + B * Y + AY * BX - AX * BY)) / Math.sqrt ((double) (A * A + B * B)) ;
if (resultat = ((d <= 4.0) && ((X - AX) * (X - BX) <= 0) && ((Y - AY) * (Y - BY) <= 0))) break ;
}
return resultat ;
}
 
/**
* Redéfinit le polygone.
*/
 
public void Polygone (pt Ai [], int n, boolean type)
{ defini = true ;
for (int i = 0 ; (i < n) && defini ; i ++) defini = defini && Ai [i].defini ;
if (defini)
{ if ((xi == null) || (n != xi.length))
{ xi = new double [n] ;
yi = new double [n] ;
}
for (int i = 0 ; i < n ; i ++)
{ xi [i] = Ai [i].x ;
yi [i] = Ai [i].y ;
}
maj (n) ;
plein = type ;
}
}
 
private void maj (int n)
{ if ((p == null) || (p.npoints != n + 1))
{ p = new Polygon () ;
for (int i = 0 ; i < n ; i ++) p.addPoint (R.Iabs (xi [i]), R.Iord (yi [i])) ;
p.addPoint (R.Iabs (xi [0]), R.Iord (yi [0])) ;
}
else
{ for (int i = 0 ; i < n ; i ++)
{ p.xpoints [i] = R.Iabs (xi [i]) ;
p.ypoints [i] = R.Iord (yi [i]) ;
}
p.xpoints [n] = R.Iabs (xi [0]) ;
p.ypoints [n] = R.Iord (yi [0]) ;
}
}
 
/**
* Redéfinit le polygone.
*/
 
public void Polygone (double xi [], double yi [], int n, boolean type)
{ defini = true ;
if ((this.xi == null) || (n != xi.length))
{ this.xi = new double [n] ;
this.yi = new double [n] ;
}
for (int i = 0 ; i < n ; i ++)
{ this.xi [i] = xi [i] ;
this.yi [i] = yi [i] ;
}
maj (n) ;
plein = type ;
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Cercle.java
0,0 → 1,159
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
// Cercle.java _ 26/11/98
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Cercle de centre de coordonnées (xo, yo) de rayon r relativement au repère R.
*/
 
public class Cercle extends ObjetRepere
{
 
/**
* Abscisse du centre.
*/
 
public double xo ;
 
/**
* Ordonnée du centre.
*/
 
public double yo ;
 
/**
* Rayon du cercle.
*/
 
public double r;
 
/**
* Construit le cercle de centre O de rayon r relativement au repère R.
*/
 
public Cercle (pt O, double r, String Nom, Repere R)
{ super (Nom, R) ; Cercle (O, r) ; }
 
/**
* Construit un cercle non défini.
*/
 
public Cercle (String Nom, Repere R)
{ super (Nom, R) ; }
 
/**
* Construit le cercle de centre de coordonnées (xo, yo) de rayon r relativement au repère R.
*/
 
public Cercle (double xo, double yo, double r, String Nom, Repere R)
{ super (Nom, R) ; Cercle (xo, yo, r) ; }
 
/**
* Construit le cercle de centre O passant par A.
*/
 
public Cercle (pt O, pt A, String Nom, Repere R)
{ super (Nom, R) ; Cercle (O, A) ; }
 
/**
* Construit le cercle passant par les points A, B et C.
*/
 
public Cercle (pt A, pt B, pt C, String Nom, Repere R)
{ super (Nom, R) ; Cercle (A, B, C) ; }
 
 
/**
* Teste si la souris est proche du cercle.
*/
 
public boolean zone (int X, int Y)
{ if (defini)
{ double d = R.Abs (X) - xo ; double d1 = R.Ord (Y) - yo ;
d = Math.abs (Math.sqrt (d * d + d1 * d1) - r) * (R.unitex + R.unitey) ;
if (d <= 2.0) return true ; else return false ;
}
return false ;
}
 
/**
* Trace ou efface le Cercle.
*/
 
public void trace (Graphics g)
{ if (defini) { int Xo, Yo, RAYONX, RAYONY ;
Xo = R.Iabs (xo); Yo = R.Iord (yo);
RAYONX = (int) (R.unitex * r) ;
RAYONY = (int) (R.unitey * r) ;
g.drawOval (Xo - RAYONX, Yo - RAYONY, 2 * RAYONX, 2 * RAYONY);
if (Nom.length () != 0 )
{ int X = R.Iabs (xo + r * 0.7) + 3 ;
int Y = R.Iord (yo + r * 0.7) - 3 ;
g.drawString (Nom, X, Y) ;
}
}
}
 
/**
* Redéfinit le Cercle de centre O de rayon r.
*/
 
public void Cercle (pt O, double r)
{ xo = O.x; yo = O.y; this.r = r; defini = (r >= 0.0); }
 
/**
* Redéfinit le Cercle de centre de coordonnées (xo, yo) de rayon r.
*/
 
public void Cercle (double xo, double yo, double r)
{ this.xo = xo; this.yo = yo; this.r = r; defini = (r >= 0.0); }
 
/**
* Redéfinit le Cercle de centre O passant par A.
*/
 
public void Cercle (pt O, pt A)
{ defini = O.defini && A.defini ;
this.xo = O.x ; this.yo = O.y ;
r = A.x - O.x ; double d = A.y - O.y ; r = Math.sqrt (r * r + d * d) ;
}
 
/**
* Redéfinit le Cercle passant par les points A, B et C.
*/
 
public void Cercle (pt A, pt B, pt C)
{ defini = A.defini && B.defini && C.defini ;
if (defini) { double det = A.x * (B.y - C.y) + B.x * (C.y - A.y) + C.x * (A.y - B.y) ;
defini = (det != 0.0) ;
if (defini) { double a = A.x * A.x + A.y * A.y ;
double b = B.x * B.x + B.y * B.y ;
double c = C.x * C.x + C.y * C.y ;
xo = (a * (B.y - C.y) + b * (C.y - A.y) + c * (A.y - B.y)) / (det + det) ;
yo = (a * (C.x - B.x) + b * (A.x - C.x) + c * (B.x - A.x)) / (det + det) ;
r = (a * (B.y * C.x - C.y * B.x) + b * (C.y * A.x - A.y * C.x) + c * (A.y * B.x - B.y * A.x)) / det ;
r = xo * xo + yo * yo - r ;
defini = (r >= 0.0) ;
if (defini) r = Math.sqrt (r) ;
}
}
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/PointSurCercle.java
0,0 → 1,83
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
/**
* définit un point dont on peut modifier l'emplacement mais qui appartient à un cercle
* c est le cercle contenant le point
* a est l'angle (en radians) correspondant à la position du point sur le cercle c
*/
 
public class PointSurCercle extends pointlibre
{ public double a;
public Cercle c;
 
/**
* Construit un point sur le cercle c.
*/
 
public PointSurCercle (double a, Cercle c, String Nom, Repere R)
{ super (c.xo + c.r * Math.cos (a), c.yo + c.r * Math.sin (a), Nom, R);
this.c = c ; defini = c.defini ;
this.a = a % (Math.PI * 2) ; if (this.a > Math.PI) this.a = this.a - 2.0 * Math.PI ;
}
 
/**
* Construit un point sur le cercle c.
*/
 
public PointSurCercle (int X, int Y, Cercle c, String Nom, Repere R)
{ super (R.Abs (X), R.Ord (Y), Nom, R) ;
defini = c.defini ; this.c = c ;
if (defini) a = calcule (X, Y, c) ; else a = 0.0 ;
}
 
 
private double calcule (int X, int Y, Cercle c)
{ double dx, dy ;
dx = X - R.Iabs (c.xo) ;
dy = R.Iord (c.yo) - Y ;
if (dx != 0.0) a = Math.atan (dy / dx) ;
else { a = Math.PI / 2 ; if (dy < 0) a = - a ; }
if (dx < 0) a = a + Math.PI ;
if (a > Math.PI) a = a - 2.0 * Math.PI ;
return a ;
}
 
/**
* Pour un point en cours de déplacement, met à jour (X, Y) et met dans (Xp, Yp) les anciennes
* coordonnées "écran".
*/
 
public void bouge (int X, int Y)
{ if (deplace && defini && R.affiche (X, Y)) { Xp = this.X ; Yp = this.Y ;
a = calcule (X, Y, c) ;
x = c.xo + c.r * Math.cos (a) ;
y = c.yo + c.r * Math.sin (a) ;
this.X = R.Iabs (x) ; this.Y = R.Iord (y) ;
}
}
 
/**
* Redéfinit le point en cas de modification du cercle c.
*/
 
public void point ()
{ x = c.xo + c.r * Math.cos (a) ; y = c.yo + c.r * Math.sin (a) ;
Xp = X = R.Iabs (x) ; Yp = Y = R.Iord (y) ;
defini = c.defini; }
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Segment.java
0,0 → 1,118
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Segment.
*/
 
public class Segment extends ObjetRepere
{
 
/**
* Position sur l'écran d'une extrémité du segment.
*/
 
public int AX, AY, BX, BY;
 
/**
* Coordonnée d'une extrémité du segment.
*/
 
public double Ax, Ay, Bx, By ;
 
/**
* Construit un segment non défini.
*/
 
public Segment (String Nom, Repere R)
{ super (Nom, R) ; }
 
/**
* Construit le segment [AB].
*/
 
public Segment (pt A, pt B, String Nom, Repere R)
{ super (Nom, R) ; Segment (A, B) ; }
 
/**
* Construit le segment d'extrémités les points de coordonnées (Ax, Ay) et (Bx, By).
*/
 
public Segment (double Ax, double Ay, double Bx, double By, String Nom, Repere R)
{ super (Nom, R) ; Segment (Ax, Ay, Bx, By) ; }
 
/**
* Retourne la longueur du segment.
*/
 
public double Longueur ()
{ if (defini) { double u = Bx - Ax ; double v = By - Ay ;
return Math.sqrt (u * u + v * v) ;
}
else return -1.0 ;
}
 
/**
* Trace ou efface le segment.
*/
 
public void trace (Graphics g)
{ if (defini)
{ g.drawLine (AX, AY, BX, BY) ;
if (Nom.length () != 0) g.drawString (Nom, (AX + BX) / 2 + 3, (AY + BY) / 2 - 3) ;
}
}
 
/**
* Teste si la souris est proche du segment.
*/
 
public boolean zone (int X, int Y)
{ if (defini)
{ int A = BY - AY ; int B = AX - BX ;
double d = ((double) Math.abs (A * X + B * Y + AY * BX - AX * BY)) / Math.sqrt ((double) (A * A + B * B)) ;
if ((d <= 4.0) && ((X - AX) * (X - BX) <= 0) && ((Y - AY) * (Y - BY) <= 0))
return true ;
else return false ;
}
return false ;
}
 
/**
* Redéfinit le Segment [AB].
*/
 
public void Segment (pt A, pt B)
{ defini = A.defini && B.defini ;
if (defini) { AX = A.X ; AY = A.Y ; BX = B.X ; BY = B.Y ;
Ax = A.x ; Ay = A.y ; Bx = B.x ; By = B.y ;
}
}
 
/**
* Redéfinit le Segment d'extrémités les points de coordonnées (Ax, Ay) et (Bx, By).
*/
 
public void Segment (double Ax, double Ay, double Bx, double By)
{ defini = true ;
if (defini) { this.Ax = Ax ; this.Ay = Ay ; this.Bx = Bx ; this.By = By ;
AX = R.Iabs (Ax) ; AY = R.Iord (Ay) ; BX = R.Iabs (Bx) ; BY = R.Iord (By) ;
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/ObjetRepere.java
0,0 → 1,66
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Objet géométrique lié à un repère.
*/
 
public class ObjetRepere
{
 
/**
* Repere associé.
*/
 
public Repere R ;
 
/**
* Existence de l'objet.
*/
 
public boolean defini ;
 
/**
* Nom de l'objet.
*/
 
public String Nom ;
 
/**
* Construit un objet non défini.
*/
 
public ObjetRepere (String Nom, Repere R )
{ this.Nom = Nom ; this.R = R ; defini = false ; }
 
/**
* Test la proximité de la souris.
*/
 
public boolean zone (int X, int Y)
{ return false ; }
 
/**
* Trace l'objet.
*/
 
public void trace (Graphics g)
{ }
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/pointlibre.java
0,0 → 1,90
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
// pointlibre.java - 28/11/98
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* définit un point dont l'emplacement peut être modifié à la souris
*
*/
 
public class pointlibre extends pt
{ public int Xp, Yp ;
public boolean deplace ;
 
/**
* construit un point libre à l'emplacement (X, Y)
*
*/
 
public pointlibre (int X, int Y, String Nom, Repere R)
{ super (X, Y, Nom, R) ; Xp = X ; Yp = Y ; deplace = false ; }
 
/**
* construit un point libre de coordonnées (x, y)
*
*/
 
public pointlibre (double x, double y, String Nom, Repere R)
{ super (x, y, Nom, R) ; Xp = X ; Yp = Y ; deplace = false; }
 
/**
* teste si la souris est proche du point libre, retourne alors deplace = true
*
*/
 
public boolean zone (int X, int Y)
{ if (deplace = (X >= this.X - 2) && (X <= this.X + 2) && (Y >= this.Y - 2) && (Y <= this.Y + 2))
Xp = this.X ; Yp = this.Y ;
return deplace ; }
 
/**
* pour un point en cours de déplacement, met à jour (X, Y) et met dans (Xp, Yp) les anciennes
* coordonnées "écran"
*
*/
 
public void bouge (int X, int Y)
{ if (deplace && R.affiche (X, Y)) { this.X = X ; x = R.Abs (X) ;
this.Y = Y ; y = R.Ord (Y) ;
}
}
 
/**
* efface le point (utilisé uniquement par les points libres)
*
*/
 
public void efface (Graphics g)
{ if (defini && deplace)
{ g.fillRect (Xp - 2, Yp - 2, 5, 5) ;
if (Nom.length () != 0) g.drawString (Nom, Xp + 3, Yp - 3) ;
Xp = X ; Yp = Y ;
}
}
 
/**
* Mise à jour d'un point libre.
*/
 
public void point ()
{ majXY () ; Xp = X ; Yp = Y ; }
 
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Vecteur.java
0,0 → 1,182
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
// vecteur.java - 09/12/98
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Vecteur.
*/
 
public class Vecteur extends ObjetRepere
{
 
/**
* Abscisse du vecteur.
*/
 
public double x ;
 
/**
* Ordonnée du vecteur.
*/
 
public double y ;
 
/**
* Abscisse de l'origine du représentant du vecteur.
*/
 
public double Ax ;
 
/**
* Ordonnée de l'origine du représentant du vecteur.
*/
 
public double Ay ;
 
/**
* Construit le vecteur de coordonnées (x, y).
*/
 
public Vecteur (double x, double y, String Nom, Repere R)
{ super (Nom, R) ; Vecteur (x, y) ; }
 
/**
* Construit un vecteur non défini.
*/
 
public Vecteur (String Nom, Repere R)
{ super (Nom, R) ; }
 
/**
* Construit le vecteur AB.
*/
 
public Vecteur (pt A, pt B, String Nom, Repere R)
{ super (Nom, R) ; Vecteur (A, B) ; }
 
/**
* Construit le vecteur AB et positionne l'origine du représentant en C.
*/
 
public Vecteur (pt A, pt B, pt C, String Nom, Repere R)
{ super (Nom, R) ; Vecteur (A, B, C) ; }
 
/**
* Retourne la somme des vecteurs v et w.
*/
 
public void Somme (Vecteur v, Vecteur w)
{ defini = v.defini && w.defini ;
x = v.x + w.x ;
y = v.y + w.y ;
}
 
/**
* Retourne le produit du vecteur v par le réel k.
*/
 
public void Produit (Vecteur v, double k)
{ defini = v.defini ;
x = k * v.x ;
y = k * v.y ;
}
 
/**
* Retourne la norme du vecteur ou -1 si le vecteur n'est pas défini.
*/
 
public double Norme ()
{ if (defini) return Math.sqrt (x * x + y * y) ; else return -1.0 ; }
 
/**
* Teste si la souris est proche du vecteur.
*/
 
public boolean zone (int X, int Y)
{ if (defini)
{ double xs = R.Abs (X) ; double ys = R.Ord (Y) ;
double d = Math.abs (y * xs - x * ys + Ay * x - Ax * y) / Math.sqrt (x * x + y * y) ;
if ((d <= 4.0) && ((xs - Ax) * (xs - Ax - x) <= 0) && ((ys - Ay) * (ys - Ay - y) <= 0))
return true ;
else return false ;
}
return false ;
}
 
/**
* Traçage d'un représentant d'un vecteur.
*/
 
public void trace (Graphics g)
{ if (defini)
{ int AX = R.Iabs (Ax) ; int AY = R.Iord (Ay) ;
double l = Math.sqrt (x * x + y * y) ;
if (l != 0.0)
{ int BX = AX + (int) (x * R.unitex) ;
int BY = AY - (int) (y * R.unitey) ;
g.drawLine (AX, AY, BX, BY) ;
int X = (int) (x * 4.0 / l) ;
int Y = (int) (y * 4.0 / l) ;
g.drawLine (BX, BY, BX - X - Y, BY + Y - X) ;
g.drawLine (BX, BY, BX - X + Y, BY + Y + X) ;
}
else g.fillRect (AX - 2, AY - 2, 5, 5) ;
if (Nom.length () != 0)
g.drawString (Nom, R.Iabs (x / 2.0 + Ax) + 3, R.Iord (y / 2.0 + Ay) - 3);
}
}
 
/**
* Fixe l'origine du vecteur en A.
*/
 
public void fixeVecteur (pt A)
{ defini = defini && A.defini ;
Ax = A.x ; Ay = A.y ;
}
 
/**
* Redéfinit le vecteur de coordonnées (x, y).
*/
 
public void Vecteur (double x, double y)
{ defini = true ; this.R = R ; this.x = x ; this.y = y ; Ax = Ay = 0.0 ; }
 
/**
* Redéfinit le vecteur AB.
*/
 
public void Vecteur (pt A, pt B)
{ defini = A.defini && B.defini ;
if (defini) { x = B.x - A.x ; y = B.y - A.y ; Ax = A.x ; Ay = A.y ; }
}
 
/**
* Redéfinit le vecteur AB et repositionne l'origine du représentant en C.
*/
 
public void Vecteur (pt A, pt B, pt C)
{ defini = A.defini && B.defini && C.defini ;
if (defini) { x = B.x - A.x ; y = B.y - A.y ; Ax = C.x ; Ay = C.y ; }
}
}
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Fonction.java
0,0 → 1,37
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
/**
* Fonction abstraite à étendre.
*/
 
public abstract class Fonction
{
 
/**
* Retourne "true" si l'image de x existe.
*/
 
public abstract boolean defini (double x) ;
 
/**
* Retourne l'image de x.
*/
 
public abstract double Image (double x) ;
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Figure.java
0,0 → 1,309
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
// geo/Figure.java - 31/01/99
 
package geo ;
 
import java.awt.* ;
import java.util.Vector ;
 
/**
* Figure géométrique formée d'une liste d'"Element"s. Cette liste contient en première position
* le repère.
*/
 
public class Figure extends Vector
{
 
/**
* Crée une figure vide.
*/
 
public Figure ()
{ super () ; }
 
// marque en remplaçant le "id" de tous les éléments construits à partir de index par - id
 
private void marquer (int index)
{ Element el ;
el = (Element) elementAt (index) ;
el.id = - el.id ;
for (int i = index + 1 ; i < size () ; i ++)
{ el = (Element) elementAt (i) ;
for (int j = 0 ; j < 3 ; j ++)
{ int k = el.args [j] ;
if ((k > 0) && (((Element) elementAt (k)).id < 0) && (el.id > 0))
el.id = - el.id ;
}
}
}
 
/**
* Effacement (graphique) de l'élément en position index et de tous les éléments chaînés
* à lui sauf l'élément en position index1.
*/
 
public void efface (int index, int index1, Graphics g)
{ if (index > 0)
{ marquer (index) ;
for (int i = 1 ; i < size () ; i ++)
{ Element el = (Element) elementAt (i) ;
if (el.id < 0)
{ el.id = - el.id ;
if (i != index1) el.efface (g) ;
 
// 31/01/99
else if ((el.id >= Element.PT_X_Y) && (el.id <= Element.POINT_TRANSLATION_PT_VECT))
((pt) el.obj).traceNom (g) ;
//
el.id = - el.id ;
}
}
}
else for (int i = 1 ; i < size () ; i ++)
if (i != index1) ((Element) elementAt (i)).efface (g) ;
}
 
/**
* Tracé de la figure. (Modifié le 18/05/99)
*/
 
public void trace (Graphics g)
{ for (int i = 1 ; i < size () ; i ++)
{ Element el = (Element) elementAt (i) ;
if (el.id > Element.POINT_TRANSLATION_PT_VECT) el.trace (g) ;
}
for (int i = 1 ; i < size () ; i ++)
{ Element el = (Element) elementAt (i) ;
if (el.id <= Element.POINT_TRANSLATION_PT_VECT) el.trace (g) ;
}
}
 
private Element tel [] = { null, null, null } ;
 
/**
* Ajoute un élément à la figure.
*/
 
public void ajout (Element el, String Nom, int X, int Y, double d)
{ Repere R = (Repere) firstElement () ;
for (int i = 0 ; i < 3 ; i ++)
{ tel [i] = null ;
if (el.args [i] > 0) tel [i] = ((Element) elementAt (el.args [i])) ;
}
ObjetRepere or ;
if ((el.id >= Element.PT_X_Y) && (el.id <= Element.PT_SYMETRIQUE_PT_PT))
or = new pt (Nom, R) ;
else if ((el.id >= Element.POINT_CENTRE) && (el.id <= Element.POINT_TRANSLATION_PT_VECT))
or = new point (Nom, R) ;
else if ((el.id >= Element.VECTEUR_PT_PT) && (el.id <= Element.VECTEUR_PT_PT_PT))
or = new Vecteur (Nom, R) ;
else if ((el.id >= Element.DROITE_PT_PT) && (el.id <= Element.DROITE_BISS_PT_PT_PT))
or = new Droite (Nom, R) ;
else if ((el.id >= Element.NOMBRE) && (el.id <= Element.NOMBRE_PUISSANCE))
or = new Scalaire (Nom, R) ;
else switch (el.id)
{ case Element.POINTLIBRE : or = new pointlibre (X, Y, Nom, R) ; break ;
case Element.POINTSURDROITE_DT : or = new PointSurDroite (X, Y, (Droite) tel [0].obj, Nom, R) ; break ;
case Element.POINTSURCERCLE_CRCL : or = new PointSurCercle (X, Y, (Cercle) tel [0].obj, Nom, R) ; break ;
case Element.ARCDECERCLE_PT_PT_PT : or = new ArcDeCercle (Nom, R) ; break ;
case Element.CERCLE_PT_R :
case Element.CERCLE_PT_PT :
case Element.CERCLE_PT_PT_PT : or = new Cercle (Nom, R) ; break ;
case Element.SEGMENT_PT_PT : or = new Segment (Nom, R) ; break ;
case Element.DEMIDROITE_PT_PT :
case Element.DEMIDROITE_PT_VECT : or = new DemiDroite (Nom, R) ; break ;
 
default : throw new IllegalArgumentException () ;
}
calcule (el, or, d) ;
el.obj = or ;
addElement (el) ;
}
 
 
/**
* Calcule l'objet géométrique (ObjetRepere) lié à l'élément.
*/
 
private void calcule (Element el, ObjetRepere or, double d)
{ switch (el.id)
{ case Element.PT_X_Y : ((pt) or).point (((Scalaire) tel [0].obj).d, ((Scalaire) tel [1].obj).d) ; break ;
case Element.PT_MILIEU_PT_PT : ((pt) or).Milieu ((pt) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.PT_ROTATION_PT_A : ((pt) or).Rotation ((pt) tel [0].obj, (pt) tel [1].obj, ((Scalaire) tel [2].obj).d) ; break ;
case Element.PT_HOMOTHETIQUE_PT_PT_K : ((pt) or).Homothetique ((pt) tel [0].obj, (pt) tel [1].obj, ((Scalaire) tel [2].obj).d) ; break ;
case Element.PT_SYMETRIQUE_PT_PT : ((pt) or).Symetrique ((pt) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.POINTLIBRE : ((pointlibre) or).point () ; break ;
case Element.POINTSURDROITE_DT : ((PointSurDroite) or).point () ; break ;
case Element.POINTSURCERCLE_CRCL : ((PointSurCercle) or).point () ; break ;
case Element.POINT_CENTRE : ((point) or).Centre ((Cercle) tel [0].obj) ; break ;
case Element.POINT_INTER_DT_DT : ((point) or).Intersection ((Droite) tel [0].obj, (Droite) tel [1].obj) ; break ;
case Element.POINT_INTER1_DT_CRCL : ((point) or).Intersection1 ((Droite) tel [0].obj, (Cercle) tel [1].obj) ; break ;
case Element.POINT_INTER2_DT_CRCL : ((point) or).Intersection2 ((Droite) tel [0].obj, (Cercle) tel [1].obj) ; break ;
case Element.POINT_INTER1_CRCL_CRCL : ((point) or).Intersection1 ((Cercle) tel [0].obj, (Cercle) tel [1].obj) ; break ;
case Element.POINT_INTER2_CRCL_CRCL : ((point) or).Intersection2 ((Cercle) tel [0].obj, (Cercle) tel [1].obj) ; break ;
case Element.POINT_PROJECTION_PT_DT : ((point) or).Projection ((pt) tel [0].obj, (Droite) tel [1].obj) ; break ;
case Element.POINT_PROJECTION_PT_SEG : ((point) or).Projection ((pt) tel [0].obj, (Segment) tel [1].obj) ; break ;
case Element.POINT_SYMETRIQUE_PT_DT : ((point) or).Symetrique ((pt) tel [0].obj, (Droite) tel [1].obj) ; break ;
case Element.POINT_ROTATION_PT_PT_ARCDECERCLE : ((point) or).Rotation1 ((pt) tel [0].obj, (pt) tel [1].obj, (ArcDeCercle) tel [2].obj) ; break ;
case Element.POINT_SYMETRIQUE_PT_SEG : ((point) or).Symetrique ((pt) tel [0].obj, (Segment) tel [1].obj) ; break ;
case Element.POINT_TRANSLATION_PT_VECT : ((point) or).Translation ((pt) tel [0].obj, (Vecteur) tel [1].obj) ; break ;
case Element.ARCDECERCLE_PT_PT_PT : ((ArcDeCercle) or).ArcDeCercle ((pt) tel [0].obj, (pt) tel [1].obj, (pt) tel [2].obj) ; break ;
case Element.CERCLE_PT_R : ((Cercle) or).Cercle ((pt) tel [0].obj, ((Scalaire) tel [1].obj).d) ; break ;
case Element.CERCLE_PT_PT : ((Cercle) or).Cercle ((pt) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.CERCLE_PT_PT_PT : ((Cercle) or).Cercle ((pt) tel [0].obj, (pt) tel [1].obj, (pt) tel [2].obj) ; break ;
case Element.SEGMENT_PT_PT : ((Segment) or).Segment ((pt) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.VECTEUR_PT_PT : ((Vecteur) or).Vecteur ((pt) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.VECTEUR_SOMME_V_W_PT : ((Vecteur) or).Somme ((Vecteur) tel [0].obj, (Vecteur) tel [1].obj) ;
((Vecteur) or).fixeVecteur ((pt) tel [2].obj) ; break ;
case Element.VECTEUR_PRODUIT_V_K_PT : ((Vecteur) or).Produit ((Vecteur) tel [0].obj, ((Scalaire) tel [2].obj).d) ;
((Vecteur) or).fixeVecteur ((pt) tel [1].obj) ; break ;
case Element.VECTEUR_PT_PT_PT : ((Vecteur) or).Vecteur ((pt) tel [0].obj, (pt) tel [1].obj, (pt) tel [2].obj) ; break ;
case Element.DROITE_PT_PT : ((Droite) or).Droite ((pt) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.DROITE_PT_VECT : ((Droite) or).Droite ((pt) tel [0].obj, (Vecteur) tel [1].obj) ; break ;
case Element.DROITE_A_B_C : ((Droite) or).Droite (((Scalaire) tel [0].obj).d, ((Scalaire) tel [1].obj).d, ((Scalaire) tel [2].obj).d) ; break ;
case Element.DROITE_PARA_DT_PT : ((Droite) or).Parallele ((Droite) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.DROITE_PARA_SEG_PT : ((Droite) or).Parallele ((Segment) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.DROITE_PERP_DT_PT : ((Droite) or).Perpendiculaire ((Droite) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.DROITE_PERP_SEG_PT : ((Droite) or).Perpendiculaire ((Segment) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.DROITE_MEDI_PT_PT : ((Droite) or).Mediatrice ((pt) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.DROITE_BISS_PT_PT_PT : ((Droite) or).Bissectrice ((pt) tel [0].obj, (pt) tel [1].obj, (pt) tel [2].obj) ; break ;
case Element.DEMIDROITE_PT_PT : ((DemiDroite) or).DemiDroite ((pt) tel [0].obj, (pt) tel [1].obj) ; break ;
case Element.DEMIDROITE_PT_VECT : ((DemiDroite) or).DemiDroite ((pt) tel [0].obj, (Vecteur) tel [1].obj) ; break ;
case Element.NOMBRE : ((Scalaire) or).Scalaire (d) ; break ;
case Element.NOMBRE_PT_ABS : ((Scalaire) or).Scalaire (((pt) tel [0].obj).x) ; break ;
case Element.NOMBRE_PT_ORD : ((Scalaire) or).Scalaire (((pt) tel [0].obj).y) ; break ;
case Element.NOMBRE_DISTANCE_PT_DR : ((Scalaire) or).Scalaire (((point) tel [0].obj).Distance ((Droite) tel [1].obj)) ; break ;
case Element.NOMBRE_DISTANCE_PT_PT : ((Scalaire) or).Scalaire (((pt) tel [0].obj).Distance ((pt) tel [1].obj)) ; break ;
case Element.NOMBRE_NORME_VECT : ((Scalaire) or).Scalaire (((Vecteur) tel [0].obj).Norme ()) ; break ;
case Element.NOMBRE_LONGUEUR_SEG : ((Scalaire) or).Scalaire (((Segment) tel [0].obj).Longueur ()) ; break ;
case Element.NOMBRE_RAYON_CRCL : ((Scalaire) or).Scalaire (((Cercle) tel [0].obj).r) ; break ;
case Element.NOMBRE_SOMME : ((Scalaire) or).Scalaire (((Scalaire) tel [0].obj).d + ((Scalaire) tel [1].obj).d) ; break ;
case Element.NOMBRE_DIFFERENCE : ((Scalaire) or).Scalaire (((Scalaire) tel [0].obj).d - ((Scalaire) tel [1].obj).d) ; break ;
case Element.NOMBRE_PRODUIT : ((Scalaire) or).Scalaire (((Scalaire) tel [0].obj).d * ((Scalaire) tel [1].obj).d) ; break ;
case Element.NOMBRE_QUOTIENT : ((Scalaire) or).Scalaire (((Scalaire) tel [0].obj).d / ((Scalaire) tel [1].obj).d) ; break ;
case Element.NOMBRE_OPPOSE : ((Scalaire) or).Scalaire (-((Scalaire) tel [0].obj).d) ; break ;
case Element.NOMBRE_VABS : ((Scalaire) or).Scalaire (Math.abs (((Scalaire) tel [0].obj).d)) ; break ;
case Element.NOMBRE_RACINE :
double d1 = ((Scalaire) tel [0].obj).d ;
if (d1 >= 0) ((Scalaire) or).Scalaire (Math.sqrt(d1)) ;
else ((Scalaire) or).defini = false ;
break ;
case Element.NOMBRE_COS : ((Scalaire) or).Scalaire (Math.cos (((Scalaire) tel [0].obj).d)) ; break ;
case Element.NOMBRE_SIN : ((Scalaire) or).Scalaire (Math.sin (((Scalaire) tel [0].obj).d)) ; break ;
case Element.NOMBRE_ARCCOS :
d1 = ((Scalaire) tel [0].obj).d ;
if (Math.abs(d1) <= 1.0) ((Scalaire) or).Scalaire (Math.acos (d1)) ;
else ((Scalaire) or).defini = false ;
break ;
case Element.NOMBRE_ARCSIN :
d1 = ((Scalaire) tel [0].obj).d ;
if (Math.abs(d1) <= 1.0) ((Scalaire) or).Scalaire (Math.asin (d1)) ;
else ((Scalaire) or).defini = false ;
break ;
case Element.NOMBRE_LN :
d1 = ((Scalaire) tel [0].obj).d ;
if (d1 > 0.0) ((Scalaire) or).Scalaire (Math.log (d1)) ;
else ((Scalaire) or).defini = false ;
break ;
case Element.NOMBRE_PUISSANCE :
d1 = ((Scalaire) tel [0].obj).d ;
double d2 = ((Scalaire) tel [1].obj).d ;
if ((d1 == 0.0) && (d2 < 0.0) || (d1 <= 0.0) && (d2 != Math.floor(d2))) ((Scalaire) or).defini = false ;
else ((Scalaire) or).Scalaire (Math.pow (d1, d2)) ;
break ;
 
default : throw new IllegalArgumentException () ;
}
}
 
 
/**
* Recalcule les éléments de la figure.
*/
 
public void recalcule (int index)
{ Repere R = (Repere) firstElement () ;
Element el ;
for (int i = 1 ; i < size () ; i ++)
{ el = ((Element) elementAt (i)) ;
if ((el.id < 0) || (index <= 0))
{ if (el.id < 0) el.id = - el.id ;
for (int j = 0 ; j < 3 ; j ++)
{ tel [j] = null ;
if (el.args [j] > 0) tel [j] = ((Element) elementAt (el.args [j])) ;
}
ObjetRepere or = el.obj ;
if (el.id != el.NOMBRE) calcule (el, or, 0.0) ;
}
}
}
 
/**
* Cherche le premier élément à l'emplacement (X, Y) parmi tous les élément dont l'identificateur est
* compris entre id1 et id2.
*/
 
public int zone (int id1, int id2, int X, int Y)
{ Element el ;
int i ;
for (i = size () - 1 ; i >= 1 ; i --)
{ el = ((Element) elementAt (i)) ;
if ((el.id >= id1) && (el.id <= id2) && (el.obj.zone (X, Y))) break ;
}
if (i == size ()) return 0 ; else return i ;
}
 
/**
* Supprime un élément et les éléments de figure fabriqués à partir de lui puis recalcule les chaînages.
*/
 
public void supprime (int i)
{ if ((i > 0) && (i < size ()))
{ setElementAt (null, i) ;
for (int k = i + 1 ; k < size () ; k ++)
{ Element el = (Element) elementAt (k) ;
for (int l = 0 ; l < 3 ; l ++)
{ int m = el.args [l] ;
if (m >0)
{ if (elementAt (m) == null)
{ setElementAt (null, k) ;
break ;
}
}
else break ;
}
}
int j = i ;
while (j < size ())
{ if (elementAt (j) == null)
{ removeElementAt (j) ;
for (int k = j + 1 ; k < size () ; k ++)
{ Element el = (Element) elementAt (k) ;
if (el != null)
for (int l = 0 ; l < 3 ; l ++)
{ int m = el.args [l] ;
if (m >0) { if (m > j) el.args [l] -- ; }
else break ;
}
}
}
else j ++ ;
}
}
}
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/sinus/geo/Repere.java
0,0 → 1,148
 
/*
Licence
Copyright J.P. Quelen
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
package geo ;
 
import java.awt.Graphics ;
 
/**
* Définit un repère orthogonal.
* Le point de coordonnées réelles (x, y) a pour position dans la fenêtre d'affichage (X, Y)
* où l'entier X varie de 0 à XMAX et Y de 0 à YMAX (vers le bas).
* (XO, YO) donne la position de l'origine sur l'écran et unitex, unitey fixent les unités sur les
* deux axes.
*/
 
public class Repere
{
 
/**
* Abscisse de l'origine du repère dans la fenêtre d'affichage.
*/
 
public int X0 ;
 
/**
* Ordonnée de l'origine du repère dans la fenêtre d'affichage.
*/
 
public int Y0 ;
 
/**
* Abscisse maximale.
*/
 
public int XMAX ;
 
/**
*
* Ordonnée maximale.
*/
 
public int YMAX ;
 
/**
* Valeur en points "écran" de l'unité suivant l'axe des x ; unitex = unitey pour un repère orthonormal.
*/
 
public double unitex ;
 
/**
* Valeur en points "écran" de l'unité suivant l'axe des y.
*/
 
public double unitey ;
 
/**
* Construit le repère orthogonal.
*/
 
public Repere (int X0,int Y0,int XMAX,int YMAX,double unitex,double unitey)
{ this.X0 = X0; this.Y0 = Y0;
this.XMAX = XMAX ; this.YMAX = YMAX ;
this.unitex = unitex ; this.unitey = unitey ;
}
 
/**
* Trace le repère.
*/
 
public void trace (Graphics g)
{ int UX = X0 + new Double (unitex) . intValue () ;
int UY = Y0 - new Double (unitey) . intValue () ;
if ((Y0 >= 0) && (Y0 <= YMAX)) { g.drawLine (0, Y0, XMAX, Y0) ;
if ((UX >= 0) && (UX <= XMAX))
g.drawLine (UX, Y0 - 2, UX, Y0 + 2) ;
}
if ((X0 >= 0) && (X0 <= XMAX)) { g.drawLine (X0, 0, X0, YMAX) ;
if ((UY >= 0) && (UY <= YMAX))
g.drawLine (X0 - 2, UY, X0 + 2, UY);
}
}
 
/**
* Trace un cadre.
*/
 
public void cadre (Graphics g)
{ g.drawRect (0, 0, XMAX - 1, YMAX - 1) ; }
 
/**
* Retourne la position X sur l'écran d'un point d'abscisse x.
*/
 
public int Iabs (double x)
{ return (int) (x * unitex + X0); }
 
/**
* Retourne la position Y sur l'écran d'un point d'abscisse y.
*/
 
public int Iord (double y)
{ return (int) (- y * unitey + Y0); }
 
/**
* Retourne l'abscisse x d'un point placé en position (X, Y) sur l'écran.
*/
 
public double Abs (int X)
{ return (X - X0) / unitex ; }
 
/**
* Retourne l'ordonnée y d'un point placé en position (X, Y) sur l'écran.
*/
 
public double Ord (int Y)
{ return (Y0 - Y) / unitey ; }
 
/**
* Retourne "true" si le point placé en position (X, Y) sur l'écran est affichable.
*/
 
public boolean affiche (int X, int Y)
{ return ((X >= 0) && (X <= XMAX) && (Y >= 0) && (Y <= YMAX)); }
 
/**
* Mise à jour du repère orthogonal.
*/
 
public void Repere (int X0,int Y0,int XMAX,int YMAX,double unitex,double unitey)
{ this.X0 = X0; this.Y0 = Y0;
this.XMAX = XMAX ; this.YMAX = YMAX ;
this.unitex = unitex ; this.unitey = unitey ;
}
 
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/sinus/build.xml
0,0 → 1,71
<?xml version="1.0" encoding="iso-8859-1"?>
 
<project name="sinus" default="build" basedir=".">
 
<description>
sinus project buildfile.
</description>
 
<property name="src.dir" value="./sinus"/>
<property name="build.dir" value="./build"/>
<property name="dist.dir" value="./dist"/>
<property name="sinus.jar" value="./dist/sinus.jar"/>
<property name="sinus.tar" value="./sinus.tar.gz"/>
 
 
<!-- Sets up classpath reference -->
<path id="sinus.classpath">
<pathelement path="${src.dir}"/>
</path>
 
 
<target name="-init" depends="-prepare">
<tstamp/>
</target>
 
 
<target name="-prepare" depends="-info">
<mkdir dir="${build.dir}"/>
<mkdir dir="${dist.dir}"/>
</target>
 
 
<target name="-info">
<property name="name" value="sinus"/>
<property name="acronym" value="sinus"/>
<property name="version" value="local"/>
<property name="year" value="2008-03"/>
<echo message="compiling sinus"/>
<echo message=""/>
</target>
 
 
<target name="compile" description="Compiles sinus sources" depends="-init">
<javac
target="1.4"
source="1.4"
verbose="verbose"
deprecation="true"
srcdir="${src.dir}"
classpathref="sinus.classpath"
excludes=""
destdir="${build.dir}"/>
</target>
 
 
<target name="build" description="Jar sinus" depends="compile" >
<jar destfile="${sinus.jar}" basedir="./build" excludes="" >
<manifest>
</manifest>
</jar>
</target>
 
<target name="clean" description="Cleans up" depends="-info">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
<delete>
<fileset dir="." includes="**/*~" />
</delete>
</target>
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/CHANGELOG
0,0 → 1,19
20/12/2010
- Ant build.
 
15/5/2010
 
- This is an "inline latex" viewer with input/reply option.
- Using the ATP library for fast latex_image generation for a "usable" amount of latex syntax.
- Added applet_auto_scaling.
- Added euro symbol \euro
- For applet autoscaling, the applet_tag "width" should be less than 10 : width="1"
- The autoscaling SetSize() javascript_function from the test.html adresses
the applets public function "getPrefferedSize();".
It could/should be called from the htmlpage "body onload".
Or in WIMS:
!set wims_html_onload=javascript:SetSize('TexApp');
If the applet has a width > 10 , no autoscaling is performed.
- The number of inputfields can be "user_controlled": see test.html
The fontsize is adapted to the inputfield height [more or less].
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/TexApp.java
0,0 → 1,376
/*
 
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
 
ATP library is GNU :see ./atp/gpl.txt
 
Example:
<html>
<body bgcolor=#0000ff onload="javascript:SetSize('TexApp');">
<script type="text/javascript">
function remove(t){
document.getElementById(t).width = 1;
document.getElementById(t).height = 1;
}
function SetSize(t){
var size = new Array(2);
size = document.getElementById(t).getPrefferedSize();
document.getElementById(t).width = size[0];
document.getElementById(t).height = size[1];
document.getElementById('showme').innerHTML='<hr><font color=red><b>preffered height = '+size[1]+'<br>preffered width = '+size[0]+'</b></font>';
}
function ReadApplet(t){
var reply = document.getElementById(t).ReadApplet();
document.getElementById('showme').innerHTML='<hr><font color=red><b>'+reply+'</b></font>';
}
function ExtraInput(t){
document.getElementById('TexApp').changeInputfields(t);
}
</script>
<div id="showme"></div>
<table ><tr valign=middle ><th>
<font color=red>
this is some text...
</font>
</th>
<th>
<applet id="TexApp" codebase="build" archive="DragStuff.jar" code="TexApp.class" width="1" height="1">
<param name="latex" value="\left\{ \begin{array}{l} 4 \times \euro = \\ 4 \times \euro = \\ 4 \times \euro = \end{array} "> <!-- values, plain latex no ":" or ";" allowed -->
 
<!-- optional -->
<param name="latex_bgcolor" value="0,0,255"><!-- rgb or #ffffff default white -->
<param name="latex_fgcolor" value="255,0,0"><!-- rgb or #ffffff default black -->
<param name="latex_fontsize" value="18"><!-- rgb or #ffffff default black -->
<!-- optional inputfield after the latex image -->
<param name="status" value="done"><!-- string : wims variable $status done/waiting -->
<param name="inputfields" value="3"><!-- int : optional : default 0 : number of inputfields on top of eachother-->
<param name="inputfield_width" value="120"><!-- int : default 10 : width in px of inputfield-->
<param name="inputfield_height" value="120"><!-- optional int : default fontsize in px : height in px of inputfield-->
<param name="inputfield_fontsize" value ="18"><!-- int : default 10 -->
<param name="inputfield_bgcolor" value="0,0,255"><!-- rgb or #ffffff default white -->
<param name="inputfield_fgcolor" value="255,0,0"><!-- rgb or #ffffff default black -->
<param name="inputfield_editable" value="1,1,1"><!-- field 1 is editable, field 2 is editable... default all editable -->
<param name="inputfield_values" value="12,44,"><!-- optional for correct answers: field 1 = "12", field 2 = "44" field3= "" field4 = "22" -->
NO JAVA
</applet>
</th>
<th>
<font color=red>
and this is the rest...</font>
</th></tr>
</table>
<p>
<font color=white>
For applet autoscaling, the applet_tag "width" should be less than 10 : width="1"<br>
The autoscaling SetSize() javascript_function could be called from the htmlpage "body onload".<br>
Or in WIMS:<br>
!set wims_html_onload=javascript:SetSize('TexApp');
<br>
If the applet has a width &gt; 10 , no autoscaling is performed.
</font>
<br>
<input type="button" name="ReadApplet()" value="ReadApplet()" onclick="javascript:ReadApplet('TexApp');">
<input type="button" name="SetSize()" value="SetSize()" onclick="javascript:SetSize('TexApp');">
<input type="button" name="remove()" value="remove()" onclick="javascript:remove('TexApp');">
<br>
<input type="button" name="extra inputfield" value="extra inputfield" onclick="javascript:ExtraInput('1');">
<input type="button" name="remove inputfield" value="remove inputfield" onclick="javascript:ExtraInput('-1');">
</body>
</html>
 
 
*/
 
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.StringTokenizer;
import atp.sHotEqn;
 
public class TexApp extends Applet {
 
public void init(){
setLayout(null);
Dimension appletSize = getSize();
if( appletSize.width < 10 ){ resize = true; xsize = 0; ysize = 0; }
else { resize = false; xsize = appletSize.width; ysize = appletSize.height; }
latex_bgcolor = colorParam("latex_bgcolor", Color.white);
latex_fgcolor = colorParam("latex_fgcolor", Color.black);
f1 = getInt("latex_fontsize",16);
f2 = f1-2;
f3 = f1-4;
f4 = f1-6;
inputs = getInt("inputfields",0);
if(inputs > 0 ){
inputwidth = getInt("inputfield_width",0);
}
Get_Latex();
if(inputs >0 ){ reinit();}
setBackground(latex_bgcolor);
}
public void reinit(){
fontsize = getInt("inputfield_fontsize", 12);
inputheight = getInt("inputfield_height",fontsize);
int ygap = (int) ( ysize - inputs*inputheight)/(inputs+1);
if(ygap < 0){
ygap = 0 ;
inputheight = (int) ysize / inputs;
}
if(fontsize > inputheight - 4){
fontsize = inputheight - 4; if(fontsize < 6 ){ fontsize = 6;}
}
myfont = new Font("Helvetica", 1, fontsize);
textfield_bgcolor = colorParam("inputfield_bgcolor", Color.white);
textfield_fgcolor = colorParam("inputfield_fgcolor", Color.black);
getEditable("inputfield_editable");
getValues("inputfield_values");
inputfield = new TextField[inputs];
int ystart = ygap;
for(int i = 0; i < inputs; i++){
inputfield[i] = new TextField(values[i],inputwidth);
this.add(inputfield[i]);
inputfield[i].setFont(myfont);
inputfield[i].setBackground(textfield_bgcolor);
inputfield[i].setForeground(textfield_fgcolor);
inputfield[i].setBounds(xsize - inputwidth,ystart,inputwidth,inputheight);
inputfield[i].setEditable(editable[i]);
inputfield[i].setVisible(true);
ystart = ystart + inputheight + ygap ;
}
repaint();
}
public void changeInputfields(int p){ // javascript
if(inputs == 0){ return; } // no inputfields defined...no need to generate them
for(int k = 0;k < inputs; k++){
this.remove(inputfield[k]);
}
inputs = inputs + p;
if(inputs < 1){inputs = 1;}
reinit();
}
public int[] getPrefferedSize(){
// auto resize applet !
// javascript reading preffered size of applet: use in wims_html_onload
// only called if width_applet_tag < 10
prefferedsize = new int[2];
prefferedsize[0] = xsize;
prefferedsize[1] = ysize;
return prefferedsize;
}
public Color MakeTransparent(Color color, int i){
return new Color(color.getRed(), color.getGreen(), color.getBlue(), i);
}
 
public Color colorParam(String s, Color color){
String s1 = getParameter(s);
if(s1 != null && s1.length() != 0){
s1 = s1.replaceAll(":", ",");
s1 = s1.replaceAll(";", ",");
if( s1.indexOf(',') > 0 ){
StringTokenizer stringtokenizer = new StringTokenizer(s1, ",");
int i = stringtokenizer.countTokens();
if(i < 3 || i > 4){ return color;}
int ai[] = new int[i + 1];
for(int j = 0; j < i; j++){
ai[j] = Integer.parseInt(stringtokenizer.nextToken());
if(ai[j] > 255 || ai[j] < 0){ ai[j] = 0;}
}
if(i == 3)
color = new Color(ai[0], ai[1], ai[2]);
else
color = new Color(ai[0], ai[1], ai[2], ai[3]);
}
else
{
try{ color = Color.decode( s1 );}catch(Exception e){System.out.println("could not parse "+s);}
return color;
}
}
return color;
}
 
public void getValues(String s){
String s1 = getParameter(s);
values = new String[inputs];
for(int i = 0; i < inputs; i++){ values[i] = " ";}
if( s1 != null && s1.length() != 0){
s1 = s1.replaceAll(":", ",");
s1 = s1.replaceAll(";", ",");
s1 = s1.replaceAll(",", " ,");
StringTokenizer stringtokenizer = new StringTokenizer(s1, ",");
int j = stringtokenizer.countTokens();
for(int k = 0; k < Math.min(j,inputs) ; k++){
values[k] = stringtokenizer.nextToken();
}
}
}
 
public boolean getStatus(){
String s1 = getParameter("status");
if( s1 != null && s1.length() != 0){
if( s1.equals("done")){
return true;
}
}
return false;
}
 
public void getEditable(String s){
editable = new boolean[inputs];
if( getStatus() ){ // status = done : no editing allowed
for(int i = 0; i < inputs; i++){ editable[i] = false ;}
}
else
{
String s1 = getParameter(s);
for(int i = 0; i < inputs; i++){ editable[i] = true;}
if(s1 != null){
s1 = s1.replaceAll(":", ",");
s1 = s1.replaceAll(";", ",");
StringTokenizer stringtokenizer = new StringTokenizer(s1, ",");
int j = stringtokenizer.countTokens();
for(int k = 0; k < Math.min(inputs,j); k++)
{
try{
String s2 = stringtokenizer.nextToken();
if(s2.equals("0") || s2.equalsIgnoreCase("no"))
editable[k] = false;
else
editable[k] = true;
}
catch(Exception e){}
}
}
}
}
 
public int getInt(String s, int i){
String s1 = getParameter(s);
if( s1 != null && s1.length()!=0){
try{
i = Integer.parseInt(s1);
}
catch(Exception exception){
System.out.println(" can not parse parameter "+s);
}
}
return i;
}
 
public boolean getBool(String s, boolean flag){
String s1 = getParameter(s);
if(s1 != null){
if(s1.equals("1") || s1.equalsIgnoreCase("yes") || s1.equalsIgnoreCase("true"))
return true;
if(s1.equals("0") || s1.equalsIgnoreCase("no") || s1.equalsIgnoreCase("false"))
return false;
}
return flag;
}
 
public void Get_Latex(){
String r1 = getParameter("latex");
if(r1 == null || r1.length() == 0){
System.out.println("can not read parameter \"latex\"");
r1="error_{parameter empty}";
}
StringTokenizer stringtokenizer_r = new StringTokenizer(r1, ",");
int j = stringtokenizer_r.countTokens();
Latex = new String[j];
icon = new BufferedImage[j];
Ylatex = new int[j];
for(int k = 0; k < j ;k++){
Latex[k] = stringtokenizer_r.nextToken();
}
if(resize){
int gap=0;
int actualsize[] = new int[2];
for(int k = 0; k < j; k++){
sHotEqn shoteqn = new sHotEqn();
shoteqn.setFontsizes(f1,f2,f3,f4);
shoteqn.setEquation(Latex[k]);
icon[k] = shoteqn.mkImage(latex_bgcolor, latex_fgcolor,400,400, false, 1, 1, false);
Ylatex[k] = ysize ;
actualsize = shoteqn.getActualSize();
if(actualsize[0] > xsize){ xsize = actualsize[0]; }
ysize = ysize + actualsize[1] + gap;
icon[k] = shoteqn.mkImage(latex_bgcolor, latex_fgcolor, actualsize[0], actualsize[1], false, 1, 1, false);
}
xsize = xsize + inputwidth;
}
else
{
for(int k = 0; k < j; k++){
sHotEqn shoteqn = new sHotEqn();
shoteqn.setFontsizes(f1,f2,f3,f4);
shoteqn.setEquation(Latex[k]);
icon[k] = shoteqn.mkImage(latex_bgcolor, latex_fgcolor, xsize - inputwidth, ysize/j, false, 1, 1, false);
Ylatex[k] = k*ysize/j ;
}
}
}
 
public void paint(Graphics g)
{
update(g);
}
 
public void update(Graphics g)
{
for(int p = 0 ; p < icon.length ; p++)
{
g.drawImage(icon[p],0,Ylatex[p],this);
}
}
 
public String ReadApplet(){
String reply="";
if(inputs > 0){
try{
reply = inputfield[0].getText();
for(int i = 1 ; i < inputs ; i++)
{
reply = reply + "," + inputfield[i].getText();
}
}catch(Exception e){System.out.println("ReadApplet error :"+e);}
}
else
{
reply = "error no inputfields defined via params...";
}
return reply;
}
 
public void run(){}
 
public void start(){}
 
public void stop(){}
 
public void destroy(){}
 
TextField inputfield[];
public int[] prefferedsize;
public int inputs,Ylatex[],inputwidth=0,inputheight=0,xsize,ysize,fontsize,f1,f2,f3,f4;
public Color textfield_bgcolor,textfield_fgcolor,latex_bgcolor,latex_fgcolor;
public String Latex[],values[];;
boolean editable[],resize;
public sHotEqn HSD;
BufferedImage icon[];
Font myfont;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/EqScanner.java
0,0 → 1,854
/*
Copyright 2006 Stefan Müller and Christian Schmid
This file is part of the HotEqn package.
 
HotEqn is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package atp;
 
import java.io.PrintStream;
import java.util.Vector;
 
// Referenced classes of package atp:
// EqToken
 
class EqScanner
{
 
public EqScanner(String s)
{
EOF = false;
TokenV = new Vector(50, 50);
selectB = false;
collectB = false;
selectCount1 = 0;
selectCount2 = 0;
selectSB = new StringBuffer("");
token = new EqToken(99);
setEquation(s);
}
 
public String getSelectedArea(int i, int j)
{
selectCount1 = Math.min(i, j);
selectCount2 = Math.max(i, j);
selectB = true;
selectSB = new StringBuffer("");
setEquation(equation);
selectB = false;
return selectSB.toString();
}
 
public void setEquation(String s)
{
equation = s;
int i = 0;
boolean flag = false;
boolean flag1 = false;
EOF = false;
countT = -1;
count = -1;
TokenV.removeAllElements();
advance();
do
{
if(EOF)
break;
countT++;
if(selectB && countT == selectCount1)
collectB = true;
TokenV.addElement(ScanNextToken());
if(selectB && countT == selectCount2)
collectB = false;
} while(true);
countT = -1;
for(; i < TokenV.size(); i++)
{
if(((EqToken)TokenV.elementAt(i)).typ == 114)
{
int k = i - 1;
int j1 = 0;
do
{
if(k <= 0)
break;
if(((EqToken)TokenV.elementAt(k)).typ == 4)
j1--;
else
if(((EqToken)TokenV.elementAt(k)).typ == 3)
j1++;
if(j1 == 1)
break;
k--;
} while(true);
int i2 = i + 1;
j1 = 0;
do
{
if(i2 >= TokenV.size())
break;
if(((EqToken)TokenV.elementAt(i2)).typ == 4)
j1++;
else
if(((EqToken)TokenV.elementAt(i2)).typ == 3)
j1--;
if(j1 == 1)
break;
i2++;
} while(true);
if(j1 == 1 && k >= 0)
{
TokenV.insertElementAt(new EqToken(109, ")"), i2 + 1);
TokenV.insertElementAt(new EqToken(17), i2 + 1);
TokenV.setElementAt(new EqToken(4), i);
TokenV.insertElementAt(new EqToken(3), i + 1);
TokenV.insertElementAt(new EqToken(115), k);
TokenV.insertElementAt(new EqToken(109, "("), k);
TokenV.insertElementAt(new EqToken(16), k);
i += 4;
}
continue;
}
if(((EqToken)TokenV.elementAt(i)).typ != 115)
continue;
int l = i - 1;
int k1 = 0;
do
{
if(l <= 0)
break;
if(((EqToken)TokenV.elementAt(l)).typ == 4)
k1--;
else
if(((EqToken)TokenV.elementAt(l)).typ == 3)
k1++;
if(k1 == 1)
break;
l--;
} while(true);
if(l >= 0)
{
TokenV.setElementAt(new EqToken(4), i);
TokenV.insertElementAt(new EqToken(3), i + 1);
TokenV.insertElementAt(new EqToken(115), l);
i += 2;
}
}
 
for(int j = 0; j < TokenV.size() - 2; j++)
{
if(((EqToken)TokenV.elementAt(j)).typ != 13 || ((EqToken)TokenV.elementAt(j + 1)).typ != 109)
continue;
int i1 = j + 2;
int l1 = 0;
int j2 = 1;
for(; i1 < TokenV.size(); i1++)
{
if(((EqToken)TokenV.elementAt(i1)).typ == 4)
l1--;
else
if(((EqToken)TokenV.elementAt(i1)).typ == 3)
l1++;
if(l1 != 0)
continue;
if(((EqToken)TokenV.elementAt(i1)).stringS.equals("["))
j2++;
else
if(((EqToken)TokenV.elementAt(i1)).stringS.equals("]"))
j2--;
if(j2 != 0)
continue;
TokenV.setElementAt(new EqToken(4), i1);
break;
}
 
j++;
}
 
}
 
public void start()
{
countT = -1;
}
 
public int get_count()
{
return countT;
}
 
public void set_count(int i)
{
countT = i;
}
 
public EqToken nextToken()
{
countT++;
if(countT >= TokenV.size())
{
countT = TokenV.size() - 1;
return new EqToken(99);
} else
{
return (EqToken)TokenV.elementAt(countT);
}
}
 
public boolean EoT()
{
return countT == TokenV.size() - 1;
}
 
private char getChar()
{
return equation.charAt(count);
}
 
private void advance()
{
if(collectB)
selectSB.append(equation.charAt(count));
if(count < equation.length() - 1)
{
count++;
EOF = false;
} else
{
count = equation.length();
EOF = true;
}
}
 
private EqToken ScanNextToken()
{
StringBuffer stringbuffer = new StringBuffer("");
String s = new String("");
EqToken eqtoken = new EqToken();
boolean flag = false;
do
{
if(EOF)
break;
char c = getChar();
switch(c)
{
case 9: // '\t'
case 10: // '\n'
case 13: // '\r'
advance();
break;
 
case 32: // ' '
advance();
return new EqToken(25, new String(" "));
 
case 33: // '!'
case 35: // '#'
case 42: // '*'
case 43: // '+'
case 44: // ','
case 45: // '-'
case 47: // '/'
case 58: // ':'
case 59: // ';'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 126: // '~'
advance();
return new EqToken(108, String.valueOf(c));
 
case 123: // '{'
advance();
return new EqToken(3);
 
case 125: // '}'
advance();
return new EqToken(4);
 
case 40: // '('
case 41: // ')'
case 91: // '['
case 93: // ']'
case 124: // '|'
advance();
return new EqToken(109, String.valueOf(c));
 
case 38: // '&'
advance();
return new EqToken(7);
 
case 39: // '\''
case 64: // '@'
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 97: // 'a'
case 98: // 'b'
case 99: // 'c'
case 100: // 'd'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 108: // 'l'
case 109: // 'm'
case 110: // 'n'
case 111: // 'o'
case 112: // 'p'
case 113: // 'q'
case 114: // 'r'
case 115: // 's'
case 116: // 't'
case 117: // 'u'
case 118: // 'v'
case 119: // 'w'
case 120: // 'x'
case 121: // 'y'
case 122: // 'z'
stringbuffer.append(c);
advance();
boolean flag1 = false;
do
{
if(EOF || flag1)
break;
c = getChar();
switch(c)
{
case 39: // '\''
case 64: // '@'
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 97: // 'a'
case 98: // 'b'
case 99: // 'c'
case 100: // 'd'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 108: // 'l'
case 109: // 'm'
case 110: // 'n'
case 111: // 'o'
case 112: // 'p'
case 113: // 'q'
case 114: // 'r'
case 115: // 's'
case 116: // 't'
case 117: // 'u'
case 118: // 'v'
case 119: // 'w'
case 120: // 'x'
case 121: // 'y'
case 122: // 'z'
stringbuffer.append(c);
advance();
break;
 
case 40: // '('
case 41: // ')'
case 42: // '*'
case 43: // '+'
case 44: // ','
case 45: // '-'
case 46: // '.'
case 47: // '/'
case 48: // '0'
case 49: // '1'
case 50: // '2'
case 51: // '3'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
case 58: // ':'
case 59: // ';'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 63: // '?'
case 91: // '['
case 92: // '\\'
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
default:
flag1 = true;
break;
}
} while(true);
return new EqToken(1, stringbuffer.toString());
 
case 46: // '.'
case 48: // '0'
case 49: // '1'
case 50: // '2'
case 51: // '3'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
stringbuffer.append(c);
advance();
boolean flag2 = false;
do
{
if(EOF || flag2)
break;
c = getChar();
switch(c)
{
case 46: // '.'
case 48: // '0'
case 49: // '1'
case 50: // '2'
case 51: // '3'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
stringbuffer.append(c);
advance();
break;
 
case 47: // '/'
default:
flag2 = true;
break;
}
} while(true);
return new EqToken(2, stringbuffer.toString());
 
case 92: // '\\'
advance();
boolean flag3 = false;
if(!EOF)
{
c = getChar();
switch(c)
{
case 92: // '\\'
advance();
return new EqToken(8);
 
case 123: // '{'
advance();
return new EqToken(109, String.valueOf(c));
 
case 124: // '|'
advance();
return new EqToken(109, "||");
 
case 125: // '}'
advance();
return new EqToken(109, String.valueOf(c));
 
case 44: // ','
advance();
return new EqToken(113, "3");
 
case 58: // ':'
advance();
return new EqToken(113, "4");
 
case 59: // ';'
advance();
return new EqToken(113, "5");
 
case 33: // '!'
advance();
return new EqToken(113, "-3");
 
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 97: // 'a'
case 98: // 'b'
case 99: // 'c'
case 100: // 'd'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 108: // 'l'
case 109: // 'm'
case 110: // 'n'
case 111: // 'o'
case 112: // 'p'
case 113: // 'q'
case 114: // 'r'
case 115: // 's'
case 116: // 't'
case 117: // 'u'
case 118: // 'v'
case 119: // 'w'
case 120: // 'x'
case 121: // 'y'
case 122: // 'z'
stringbuffer.append(c);
advance();
boolean flag4 = false;
do
{
if(EOF || flag4)
break;
c = getChar();
switch(c)
{
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 97: // 'a'
case 98: // 'b'
case 99: // 'c'
case 100: // 'd'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 108: // 'l'
case 109: // 'm'
case 110: // 'n'
case 111: // 'o'
case 112: // 'p'
case 113: // 'q'
case 114: // 'r'
case 115: // 's'
case 116: // 't'
case 117: // 'u'
case 118: // 'v'
case 119: // 'w'
case 120: // 'x'
case 121: // 'y'
case 122: // 'z'
stringbuffer.append(c);
advance();
break;
 
case 91: // '['
case 92: // '\\'
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
default:
flag4 = true;
break;
}
} while(true);
String s1 = stringbuffer.toString();
if(s1.equals("euro"))
return new EqToken(2, "\u20AC");
if(s1.equals("acute"))
return new EqToken(22, "\uFFFD");
if(s1.equals("array"))
return new EqToken(15);
if(s1.equals("bar"))
return new EqToken(14, "bar");
if(s1.equals("ddot"))
return new EqToken(22, "..");
if(s1.equals("dot"))
return new EqToken(22, ".");
if(s1.equals("frac"))
return new EqToken(12);
if(s1.equals("grave"))
return new EqToken(22, "`");
if(s1.equals("hat"))
return new EqToken(22, "^");
if(s1.equals("int"))
return new EqToken(20, "int");
if(s1.equals("oint"))
return new EqToken(20, "oint");
if(s1.equals("left"))
return new EqToken(16);
if(s1.equals("limsup"))
return new EqToken(24, "lim sup");
if(s1.equals("liminf"))
return new EqToken(24, "lim inf");
if(s1.equals("prod"))
return new EqToken(20, "prod");
if(s1.equals("right"))
return new EqToken(17);
if(s1.equals("sqrt"))
return new EqToken(13);
if(s1.equals("sum"))
return new EqToken(20, "sum");
if(s1.equals("tilde"))
return new EqToken(22, "~");
if(s1.equals("vec"))
return new EqToken(14);
if(s1.equals("widehat"))
return new EqToken(14, "widehat");
if(s1.equals("widetilde"))
return new EqToken(14, "widetilde");
if(s1.equals("quad"))
return new EqToken(113, "18");
if(s1.equals("qquad"))
return new EqToken(113, "36");
if(s1.equals("backslash"))
return new EqToken(2, "\\");
if(s1.equals("langle"))
return new EqToken(5, "<");
if(s1.equals("rangle"))
return new EqToken(5, ">");
if(s1.equals("not"))
return new EqToken(110);
if(s1.equals("atop"))
return new EqToken(115);
if(s1.equals("choose"))
return new EqToken(114);
if(s1.equals("overline"))
return new EqToken(116);
if(s1.equals("underline"))
return new EqToken(117);
if(s1.equals("overbrace"))
return new EqToken(118);
if(s1.equals("underbrace"))
return new EqToken(119);
if(s1.equals("stackrel"))
return new EqToken(120);
if(s1.equals("begin"))
return new EqToken(50);
if(s1.equals("end"))
return new EqToken(51);
if(s1.equals("fgcolor"))
return new EqToken(121);
if(s1.equals("bgcolor"))
return new EqToken(122);
if(s1.equals("fbox"))
return new EqToken(123);
if(s1.equals("mbox"))
return new EqToken(124);
if(" arccos arcsin arctan arg cos cosh cot coth csc csch def deg dim exp hom ker lg ln log sec sech sin sinh tan tanh ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(9, s1);
if(" det gcd inf lim max min Pr sup ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(24, s1);
if(" alpha delta epsilon iota kappa lambda nu omega pi sigma theta tau upsilon varepsilon varpi vartheta pm mp times div cdot cdots ldots ast star amalg cap cup uplus sqcap sqcup vee wedge wr circ bullet diamond lhd rhd oslash odot Box bigtriangleup triangleleft triangleright oplus ominus otimes ll subset sqsubset in vdash models gg supset sqsupset ni dashv perp neq doteq approx cong equiv propto prec sim simeq asymp smile frown bowtie succ aleph forall hbar exists imath neg flat ell Re angle Im backslash mho Box prime emptyset triangle nabla partial top bot Join infty vdash dashv Fourier Laplace leftarrow gets hookrightarrow leftharpoondown rightarrow to rightharpoondown leadsto leftrightarrow mapsto hookleftarrow leftharpoonup rightharpoonup rightleftharpoons longleftarrow longrightarrow longleftrightarrow longmapsto ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(18, s1);
if(" beta chi eta gamma mu psi phi rho varrho varsigma varphi xi zeta le leq ge geq vdots ddots natural jmath bigtriangledown sharp uparrow downarrow updownarrow nearrow searrow swarrow nwarrow succeq mid preceq parallel subseteq sqsubseteq supseteq sqsupseteq clubsuit diamondsuit heartsuit spadesuit wp dagger ddagger setminus unlhd unrhd bigcirc ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(19, s1);
if(" Delta Gamma Lambda Omega Pi Phi Psi Sigma Theta Upsilon Xi Leftarrow Rightarrow Leftrightarrow Longleftarrow Longrightarrow Longleftrightarrow Diamond ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(18, (new StringBuilder()).append(s1).append("Big").toString());
if(" Uparrow Downarrow Updownarrow ".indexOf((new StringBuilder()).append(" ").append(s1).append(" ").toString()) >= 0)
return new EqToken(19, (new StringBuilder()).append(s1).append("Big").toString());
// fall through
 
case 34: // '"'
case 35: // '#'
case 36: // '$'
case 37: // '%'
case 38: // '&'
case 39: // '\''
case 40: // '('
case 41: // ')'
case 42: // '*'
case 43: // '+'
case 45: // '-'
case 46: // '.'
case 47: // '/'
case 48: // '0'
case 49: // '1'
case 50: // '2'
case 51: // '3'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 63: // '?'
case 64: // '@'
case 91: // '['
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
default:
boolean flag5 = true;
advance();
System.out.println((new StringBuilder()).append("Scanner invalid tag: \\").append(stringbuffer.toString()).toString());
return new EqToken(100);
}
}
break;
 
case 94: // '^'
advance();
return new EqToken(10);
 
case 95: // '_'
advance();
return new EqToken(11);
 
case 11: // '\013'
case 12: // '\f'
case 14: // '\016'
case 15: // '\017'
case 16: // '\020'
case 17: // '\021'
case 18: // '\022'
case 19: // '\023'
case 20: // '\024'
case 21: // '\025'
case 22: // '\026'
case 23: // '\027'
case 24: // '\030'
case 25: // '\031'
case 26: // '\032'
case 27: // '\033'
case 28: // '\034'
case 29: // '\035'
case 30: // '\036'
case 31: // '\037'
case 34: // '"'
case 36: // '$'
case 37: // '%'
case 63: // '?'
case 96: // '`'
default:
advance();
System.out.println((new StringBuilder()).append("Scanner invalid character: ").append(c).toString());
return new EqToken(100);
}
} while(true);
return new EqToken(99);
}
 
private String equation;
private int count;
private int countT;
private EqToken token;
private boolean EOF;
private Vector TokenV;
private boolean selectB;
private boolean collectB;
private int selectCount1;
private int selectCount2;
private StringBuffer selectSB;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Fonts12.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/gpl.txt
0,0 → 1,674
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
 
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
Preamble
 
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
 
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
 
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
 
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
 
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
 
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
 
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
 
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
 
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
 
The precise terms and conditions for copying, distribution and
modification follow.
 
TERMS AND CONDITIONS
 
0. Definitions.
 
"This License" refers to version 3 of the GNU General Public License.
 
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
 
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
 
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
 
A "covered work" means either the unmodified Program or a work based
on the Program.
 
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
 
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
 
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
 
1. Source Code.
 
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
 
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
 
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
 
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
 
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
 
The Corresponding Source for a work in source code form is that
same work.
 
2. Basic Permissions.
 
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
 
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
 
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
 
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
 
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
 
4. Conveying Verbatim Copies.
 
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
 
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
 
5. Conveying Modified Source Versions.
 
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
 
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
 
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
 
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
 
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
 
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
 
6. Conveying Non-Source Forms.
 
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
 
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
 
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
 
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
 
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
 
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
 
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
 
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
 
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
 
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
 
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
 
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
 
7. Additional Terms.
 
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
 
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
 
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
 
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
 
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
 
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
 
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
 
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
 
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
 
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
 
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
 
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
 
8. Termination.
 
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
 
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
 
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
 
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
 
9. Acceptance Not Required for Having Copies.
 
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
 
10. Automatic Licensing of Downstream Recipients.
 
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
 
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
 
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
 
11. Patents.
 
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
 
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
 
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
 
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
 
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
 
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
 
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
 
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
 
12. No Surrender of Others' Freedom.
 
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
 
13. Use with the GNU Affero General Public License.
 
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
 
14. Revised Versions of this License.
 
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
 
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
 
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
 
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
 
15. Disclaimer of Warranty.
 
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 
16. Limitation of Liability.
 
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
 
17. Interpretation of Sections 15 and 16.
 
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
 
END OF TERMS AND CONDITIONS
 
How to Apply These Terms to Your New Programs
 
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
 
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
 
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
 
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
 
Also add information on how to contact you by electronic and paper mail.
 
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
 
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
 
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
 
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
 
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/sHotEqn.java
0,0 → 1,2563
/*
Copyright 2006 Stefan Müller and Christian Schmid
This file is part of the HotEqn package.
 
HotEqn is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package atp;
 
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.PrintStream;
import java.util.Hashtable;
import javax.swing.JApplet;
import javax.swing.JComponent;
 
// Referenced classes of package atp:
// sSymbolLoader, EqScanner, ColorMaskFilter, BoxC,
// EqToken
 
public class sHotEqn extends JComponent
implements MouseListener, MouseMotionListener
{
 
public sHotEqn()
{
this("sHotEqn", null, "sHotEqn");
}
 
public sHotEqn(String s)
{
this(s, null, "sHotEqn");
}
 
public sHotEqn(String s, JApplet japplet, String s1)
{
width = 0;
height = 0;
nameS = null;
equation = null;
Fontname = "Helvetica";
f1 = new Font(Fontname, 0, 18);
f2 = new Font(Fontname, 0, 14);
f3 = new Font(Fontname, 0, 12);
f4 = new Font(Fontname, 0, 10);
imageOK = false;
localWidth = 0;
localHeight = 0;
BGColor = Color.white;
EnvColor = Color.white;
FGColor = Color.black;
BorderColor = Color.red;
borderB = false;
roundRectBorderB = false;
border = 0;
halign = "left";
valign = "top";
xpos = 0;
ypos = 0;
drawn = false;
imageH = new Hashtable(13);
appletB = false;
beanB = false;
debug = false;
editMode = false;
editableB = true;
mouse1X = 0;
mouse1Y = 0;
mouse2X = 0;
mouse2Y = 0;
xOFF = 0;
yOFF = 0;
y0 = 0;
x0 = 0;
y1 = 0;
x1 = 0;
editModeRec = 5;
editModeFind = false;
editModeCount1 = 0;
editModeCount2 = 0;
app = japplet;
equation = s;
nameS = s1;
addMouseListener(this);
addMouseMotionListener(this);
if(japplet != null)
appletB = true;
symbolLoader = new SymbolLoader();
tracker = new MediaTracker(this);
eqScan = new EqScanner(s);
//System.out.println((new StringBuilder()).append("sHotEqn V 4.00 ").append(s1).toString());
}
 
public void setEquation(String s)
{
equation = s;
eqScan.setEquation(s);
drawn = false;
imageOK = false;
repaint();
}
 
public String getEquation()
{
return equation;
}
 
public void printStatus(String s)
{
if(debug)
System.out.println((new StringBuilder()).append(nameS).append(" ").append(s).toString());
}
 
private void displayStatus(String s)
{
if(debug)
if(appletB)
app.showStatus((new StringBuilder()).append(nameS).append(" ").append(s).toString());
else
printStatus(s);
}
 
public Image getImage()
{
if(imageOK)
return bufferImage;
else
return null;
}
 
public BufferedImage GetMyImage()
{
return finalimage;
}
 
public void setDebug(boolean flag)
{
debug = flag;
}
 
public boolean isDebug()
{
return debug;
}
 
public void setFontname(String s)
{
Fontname = s;
}
 
public String getFontname()
{
return Fontname;
}
 
public void setFontsizes(int i, int j, int k, int l)
{
int i1 = 18;
int j1 = 14;
int k1 = 12;
int l1 = 10;
GreekSize[0] = 0;
GreekSize[1] = 0;
GreekSize[2] = 0;
GreekSize[3] = 0;
for(int i2 = 0; i2 < GreekFontSizes.length; i2++)
{
if(i == GreekFontSizes[i2])
{
GreekSize[0] = i;
GreekDescent[0] = GreekFontDescents[i2];
i1 = EmbedFontSizes[i2];
}
if(j == GreekFontSizes[i2])
{
GreekSize[1] = j;
GreekDescent[1] = GreekFontDescents[i2];
j1 = EmbedFontSizes[i2];
}
if(k == GreekFontSizes[i2])
{
GreekSize[2] = k;
GreekDescent[2] = GreekFontDescents[i2];
k1 = EmbedFontSizes[i2];
}
if(l == GreekFontSizes[i2])
{
GreekSize[3] = l;
GreekDescent[3] = GreekFontDescents[i2];
l1 = EmbedFontSizes[i2];
}
}
 
if(GreekSize[0] == 0)
{
GreekSize[0] = GreekFontSizes[GreekFontSizes.length - 1];
GreekDescent[0] = GreekFontDescents[GreekFontDescents.length - 1];
i1 = EmbedFontSizes[EmbedFontSizes.length - 1];
}
if(GreekSize[1] == 0)
{
GreekSize[1] = GreekSize[0];
GreekDescent[1] = GreekDescent[0];
j1 = i1;
}
if(GreekSize[2] == 0)
{
GreekSize[2] = GreekSize[1];
GreekDescent[2] = GreekDescent[1];
k1 = j1;
}
if(GreekSize[3] == 0)
{
GreekSize[3] = GreekSize[2];
GreekDescent[3] = GreekDescent[2];
l1 = k1;
}
f1 = new Font(Fontname, 0, i1);
f2 = new Font(Fontname, 0, j1);
f3 = new Font(Fontname, 0, k1);
f4 = new Font(Fontname, 0, l1);
}
 
public void setBackground(Color color)
{
BGColor = EnvColor = color;
drawn = false;
imageOK = false;
repaint();
}
 
public Color getBackground()
{
return BGColor;
}
 
public void setForeground(Color color)
{
FGColor = color;
drawn = false;
imageOK = false;
repaint();
}
 
public Color getForeground()
{
return FGColor;
}
 
public void setBorderColor(Color color)
{
BorderColor = color;
drawn = false;
imageOK = false;
repaint();
}
 
public Color getBorderColor()
{
return BorderColor;
}
 
public void setBorder(boolean flag)
{
borderB = flag;
drawn = false;
imageOK = false;
repaint();
}
 
public boolean isBorder()
{
return borderB;
}
 
public void setRoundRectBorder(boolean flag)
{
roundRectBorderB = flag;
drawn = false;
imageOK = false;
repaint();
}
 
public boolean isRoundRectBorder()
{
return roundRectBorderB;
}
 
public void setHAlign(String s)
{
halign = s;
drawn = false;
imageOK = false;
}
 
public void setEnvColor(Color color)
{
EnvColor = color;
drawn = false;
imageOK = false;
repaint();
}
 
public Color getEnvColor()
{
return EnvColor;
}
 
public String getHAlign()
{
return halign;
}
 
public void setVAlign(String s)
{
valign = s;
drawn = false;
imageOK = false;
}
 
public String getVAlign()
{
return valign;
}
 
public void setEditable(boolean flag)
{
editableB = flag;
}
 
public boolean isEditable()
{
return editableB;
}
 
public String getSelectedArea()
{
return eqScan.getSelectedArea(editModeCount1, editModeCount2);
}
 
public void mousePressed(MouseEvent mouseevent)
{
}
 
public void mouseReleased(MouseEvent mouseevent)
{
}
 
public void mouseEntered(MouseEvent mouseevent)
{
}
 
public void mouseExited(MouseEvent mouseevent)
{
}
 
public void mouseClicked(MouseEvent mouseevent)
{
}
 
public void mouseMoved(MouseEvent mouseevent)
{
}
 
public void mouseDragged(MouseEvent mouseevent)
{
}
 
public void processMouseEvent(MouseEvent mouseevent)
{
if(mouseevent.isControlDown())
{
if(mouseevent.getID() == 501 && !mouseevent.isMetaDown())
System.out.println((new StringBuilder()).append(nameS).append(" (width,height) given=(").append(getSize().width).append(",").append(getSize().height).append(") used=(").append(getPreferredSize().width).append(",").append(getPreferredSize().height).append(")").toString());
} else
if(editableB)
if(mouseevent.getID() == 501)
{
mouse1X = mouseevent.getX();
mouse1Y = mouseevent.getY();
mouse2X = 0;
mouse2Y = 0;
editModeRec = 5;
selectImage = null;
repaint();
} else
if(mouseevent.getID() == 502 && editMode)
{
Graphics g = getGraphics();
g.setFont(f1);
g.setColor(FGColor);
eqScan.start();
BoxC boxc = eqn(xOFF, yOFF, true, g, 1);
if(debug)
printStatus((new StringBuilder()).append("selectedArea = ").append(eqScan.getSelectedArea(editModeCount1, editModeCount2)).toString());
FilteredImageSource filteredimagesource = new FilteredImageSource(bufferImage.getSource(), new CropImageFilter(x0, y0, x1 - x0, y1 - y0));
FilteredImageSource filteredimagesource1 = new FilteredImageSource(filteredimagesource, new ColorMaskFilter(Color.red, true));
selectImage = Toolkit.getDefaultToolkit().createImage(filteredimagesource1);
g.drawImage(selectImage, x0, y0, this);
editMode = false;
}
super.processMouseEvent(mouseevent);
}
 
public void processMouseMotionEvent(MouseEvent mouseevent)
{
if(mouseevent.getID() == 506 && mouse1X != 0 && editableB)
{
editMode = true;
mouse2X = mouseevent.getX();
mouse2Y = mouseevent.getY();
}
}
 
public Dimension getPreferredSize()
{
if((width == 0) & (height == 0))
{
Graphics g = getGraphics();
if(g != null)
{
g.setFont(f1);
eqScan.start();
BoxC boxc = eqn(0, 150, false, g, 1);
if(borderB)
border = 5;
else
border = 0;
localWidth = 1 + boxc.dx + 2 * border;
localHeight = 1 + boxc.dy_pos + boxc.dy_neg + 2 * border;
}
}
width = localWidth;
height = localHeight;
if(localWidth <= 1)
return new Dimension(100, 100);
else
return new Dimension(localWidth, localHeight);
}
 
public Dimension getSizeof(String s)
{
Image image = createImage(200, 200);
Graphics g = image.getGraphics();
g.setFont(f1);
eqScan.setEquation(s);
BoxC boxc = eqn(0, 150, false, g, 1);
g.dispose();
byte byte0;
if(borderB)
byte0 = 5;
else
byte0 = 0;
return new Dimension(1 + boxc.dx + 2 * byte0, 1 + boxc.dy_pos + boxc.dy_neg + 2 * byte0);
}
 
public Dimension getMinimumSize()
{
return getPreferredSize();
}
 
public void addActionListener(ActionListener actionlistener)
{
actionListener = AWTEventMulticaster.add(actionListener, actionlistener);
enableEvents(16L);
}
 
public void removeActionListener(ActionListener actionlistener)
{
actionListener = AWTEventMulticaster.remove(actionListener, actionlistener);
}
 
private void draw_hourglass(Graphics g)
{
g.setColor(Color.red);
int i = height / 2 - 10;
int j = i + 20;
int k = width / 2 - 5;
int l = k + 10;
Polygon polygon = new Polygon();
polygon.addPoint(k, i);
polygon.addPoint(l, j);
polygon.addPoint(k, j);
polygon.addPoint(l, i);
g.fillPolygon(polygon);
}
 
public synchronized void paintComponent(Graphics g)
{
super.paintComponent(g);
if(width != getSize().width || height != getSize().height)
{
imageOK = false;
bufferImage = null;
width = getSize().width;
height = getSize().height;
}
if(!imageOK)
{
draw_hourglass(g);
selectImage = null;
if(bufferImage == null)
bufferImage = createImage(width, height);
Graphics g1 = bufferImage.getGraphics();
generateImage(g1);
g1.dispose();
}
g.drawImage(bufferImage, 0, 0, this);
if(selectImage != null)
g.drawImage(selectImage, x0, y0, this);
}
 
private synchronized void generateImage(Graphics g)
{
BoxC boxc = new BoxC();
Image image = createImage(width, height + height);
Graphics g1 = image.getGraphics();
g1.setFont(f1);
g.setColor(BGColor);
g.fillRect(0, 0, width, height);
g1.setColor(BGColor);
g1.fillRect(0, 0, width, height + height);
border = 0;
if(borderB && roundRectBorderB)
{
g.setColor(EnvColor);
g.fillRect(0, 0, width, height);
g.setColor(BGColor);
g.fillRoundRect(0, 0, width - 1, height - 1, 20, 20);
g.setColor(BorderColor);
g.drawRoundRect(0, 0, width - 1, height - 1, 20, 20);
border = 5;
} else
if(borderB && !roundRectBorderB)
{
g.setColor(BorderColor);
g.drawRect(0, 0, width - 1, height - 1);
border = 5;
}
g1.setColor(FGColor);
eqScan.start();
boxc = eqn(0, height, true, g1, 1);
displayStatus(" ");
xpos = 0;
if(halign.equals("center"))
xpos = 1;
else
if(halign.equals("right"))
xpos = 2;
ypos = 0;
if(valign.equals("middle"))
ypos = 1;
else
if(valign.equals("bottom"))
ypos = 2;
localWidth = 1 + boxc.dx + 2 * border;
localHeight = 1 + boxc.dy_pos + boxc.dy_neg + 2 * border;
boolean flag = false;
if(localWidth > width)
{
flag = true;
xpos = 0;
}
if(localHeight > height)
{
flag = true;
ypos = 1;
}
int i = border;
int j = border;
switch(xpos)
{
case 1: // '\001'
i = (width - boxc.dx) / 2;
break;
 
case 2: // '\002'
i = width - border - boxc.dx - 1;
break;
}
switch(ypos)
{
case 1: // '\001'
j = border - (localHeight - height) / 2;
break;
 
case 2: // '\002'
j = height - border - boxc.dy_neg - boxc.dy_pos;
break;
}
g.drawImage(image, i, j, i + boxc.dx, j + boxc.dy_pos + boxc.dy_neg + 1, 0, height - boxc.dy_pos, boxc.dx, height + boxc.dy_neg + 1, this);
g1.dispose();
if(flag)
printStatus((new StringBuilder()).append("(width,height) given=(").append(width).append(",").append(height).append(") used=(").append(localWidth).append(",").append(localHeight).append(")").toString());
imageOK = true;
drawn = true;
xOFF = i;
yOFF = j + boxc.dy_pos;
notify();
}
// jm.evers
public int[] getActualSize()
{
int ai[] = new int[2];
ai[0] = localWidth;
ai[1] = localHeight;
return ai;
}
// jm.evers
public synchronized BufferedImage mkImage(Color color, Color color1, int i, int j ,boolean outline , int xp , int yp,boolean disk)
{
width = i;
height = j;
xpos = xp;
ypos = yp;
finalimage = new BufferedImage(width, height, 2);
Graphics g = finalimage.getGraphics();
BoxC boxc = new BoxC();
BoxC boxc1 = new BoxC();
g.setFont(f1);
g.setColor(color);
g.fillRect(0, 0, width, height);
border = 0;
if(borderB && roundRectBorderB)
{
g.setColor(EnvColor);
g.fillRect(0, 0, width, height);
g.setColor(color1);
g.fillRoundRect(0, 0, width - 1, height - 1, 20, 20);
g.setColor(BorderColor);
g.drawRoundRect(0, 0, width - 1, height - 1, 20, 20);
border = 5;
} else
if(borderB && !roundRectBorderB)
{
g.setColor(BorderColor);
g.drawRect(0, 0, width - 1, height - 1);
border = 5;
}
g.setColor(color1);
eqScan.start();
boxc1 = eqn(0, 150, false, g, 1);
displayStatus(" ");
localWidth = 1 + boxc1.dx + 2 * border;
localHeight = 1 + boxc1.dy_pos + boxc1.dy_neg + 2 * border;
boolean flag = false;
if(localWidth > width)
{
flag = true;
xpos = 0;
}
if(localHeight > height)
{
flag = true;
ypos = 1;
}
int k = border;
int l = boxc1.dy_pos + border;
switch(xpos)
{
case 1: // '\001'
k = (width - boxc1.dx) / 2;
break;
 
case 2: // '\002'
k = width - border - boxc1.dx - 1;
break;
}
switch(ypos)
{
case 1: // '\001'
l = (border + boxc1.dy_pos) - (localHeight - height) / 2;
break;
 
case 2: // '\002'
l = height - border - boxc1.dy_neg - 1;
break;
}
eqScan.start();
boxc = eqn(k, l, true, g, 1);
xOFF = k;
yOFF = l;
g.dispose();
if(localWidth > width ){ width = localWidth;}
if(localHeight > height ){height = localHeight;}
// ok now paint the image as big as it should be
finalimage = new BufferedImage(width,height, 2);
g = finalimage.getGraphics();
boxc = new BoxC();
boxc1 = new BoxC();
g.setFont(f1);
g.setColor(color);
if(disk){
g.fillOval(0, 0, width, height);
}
else
{
g.fillRect(0, 0, width, height);
}
g.setColor(color1);
if(outline){g.drawRect(border,border,width - border,height - border);}
eqScan.start();
boxc = eqn(k, l, true, g, 1);
imageOK = true;
drawn = true;
xOFF = k;
yOFF = l;
notify();
g.dispose();
return finalimage;
}
 
private BoxC eqn(int i, int j, boolean flag, Graphics g, int k)
{
return eqn(i, j, flag, g, k, true);
}
 
private BoxC eqn(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
BoxC boxc = new BoxC();
BoxC boxc1 = new BoxC();
boolean flag2 = true;
boolean flag3 = false;
boolean flag5 = false;
int l = 0;
boolean flag6 = false;
do
{
if(eqScan.EoT() || !flag2)
break;
eqTok = eqScan.nextToken();
if(editMode && flag)
l = eqScan.get_count();
boolean flag4 = false;
int i1 = l;
int j1 = eqTok.typ;
switch(eqTok.typ)
{
case 4: // '\004'
case 7: // '\007'
case 8: // '\b'
case 17: // '\021'
case 51: // '3'
if(editModeFind && flag)
{
if(l > editModeCount2)
editModeCount2 = l;
if(l < editModeCount1)
editModeCount1 = l;
}
return boxc1;
 
case 22: // '\026'
boxc = ACCENT(i + boxc1.dx, j, flag, g, k);
break;
 
case 5: // '\005'
boxc = ANGLE(i + boxc1.dx, j, flag, g);
break;
 
case 15: // '\017'
if(editModeFind && flag)
flag5 = true;
boxc = ARRAY(i + boxc1.dx, j, flag, g, k);
break;
 
case 50: // '2'
if(editModeFind && flag)
flag5 = true;
boxc = BEGIN(i + boxc1.dx, j, flag, g, k);
break;
 
case 3: // '\003'
boxc = eqn(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 121: // 'y'
boxc = FG_BGColor(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 122: // 'z'
boxc = FG_BGColor(i + boxc1.dx, j, flag, g, k, false);
break;
 
case 123: // '{'
if(editModeFind && flag)
flag5 = true;
boxc = FBOX(i + boxc1.dx, j, flag, g, k);
break;
 
case 1: // '\001'
boxc = Id(i + boxc1.dx, j, flag, g);
break;
 
case 110: // 'n'
boxc = NOT(i + boxc1.dx, j, flag, g, k);
break;
 
case 108: // 'l'
boxc = Op(i + boxc1.dx, j, flag, g);
break;
 
case 12: // '\f'
boxc = FRAC(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 115: // 's'
boxc = FRAC(i + boxc1.dx, j, flag, g, k, false);
break;
 
case 2: // '\002'
case 9: // '\t'
boxc = Plain(i + boxc1.dx, j, flag, g);
break;
 
case 18: // '\022'
boxc = SYMBOP(i + boxc1.dx, j, flag, g, k, false);
break;
 
case 19: // '\023'
boxc = SYMBOP(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 16: // '\020'
if(editModeFind && flag)
flag5 = true;
boxc = LEFT(i + boxc1.dx, j, flag, g, k);
break;
 
case 24: // '\030'
boxc = LIM(i + boxc1.dx, j, flag, g, k);
break;
 
case 124: // '|'
boxc = MBOX(i + boxc1.dx, j, flag, g);
break;
 
case 118: // 'v'
boxc = OverBRACE(i + boxc1.dx, j, flag, g, k);
break;
 
case 119: // 'w'
boxc = UnderBRACE(i + boxc1.dx, j, flag, g, k);
break;
 
case 116: // 't'
boxc = OverUnderLINE(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 117: // 'u'
boxc = OverUnderLINE(i + boxc1.dx, j, flag, g, k, false);
break;
 
case 109: // 'm'
boxc = Paren(i + boxc1.dx, j, flag, g);
break;
 
case 113: // 'q'
boxc = SPACE(i + boxc1.dx, j, flag, g);
break;
 
case 13: // '\r'
if(editModeFind && flag)
flag5 = true;
boxc = SQRT(i + boxc1.dx, j, flag, g, k);
break;
 
case 120: // 'x'
boxc = STACKREL(i + boxc1.dx, j, flag, g, k);
break;
 
case 10: // '\n'
boxc = SUP(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 11: // '\013'
boxc = SUB(i + boxc1.dx, j, flag, g, k, true);
break;
 
case 20: // '\024'
boxc = SYMBOLBIG(i + boxc1.dx, j, flag, g, k);
break;
 
case 14: // '\016'
boxc = VEC(i + boxc1.dx, j, flag, g, k);
break;
 
case 25: // '\031'
boxc = new BoxC(0, 0, 0);
flag4 = true;
break;
 
case 99: // 'c'
case 100: // 'd'
boxc = new BoxC(0, 0, 0);
break;
 
case 6: // '\006'
case 21: // '\025'
case 23: // '\027'
case 26: // '\032'
case 27: // '\033'
case 28: // '\034'
case 29: // '\035'
case 30: // '\036'
case 31: // '\037'
case 32: // ' '
case 33: // '!'
case 34: // '"'
case 35: // '#'
case 36: // '$'
case 37: // '%'
case 38: // '&'
case 39: // '\''
case 40: // '('
case 41: // ')'
case 42: // '*'
case 43: // '+'
case 44: // ','
case 45: // '-'
case 46: // '.'
case 47: // '/'
case 48: // '0'
case 49: // '1'
case 52: // '4'
case 53: // '5'
case 54: // '6'
case 55: // '7'
case 56: // '8'
case 57: // '9'
case 58: // ':'
case 59: // ';'
case 60: // '<'
case 61: // '='
case 62: // '>'
case 63: // '?'
case 64: // '@'
case 65: // 'A'
case 66: // 'B'
case 67: // 'C'
case 68: // 'D'
case 69: // 'E'
case 70: // 'F'
case 71: // 'G'
case 72: // 'H'
case 73: // 'I'
case 74: // 'J'
case 75: // 'K'
case 76: // 'L'
case 77: // 'M'
case 78: // 'N'
case 79: // 'O'
case 80: // 'P'
case 81: // 'Q'
case 82: // 'R'
case 83: // 'S'
case 84: // 'T'
case 85: // 'U'
case 86: // 'V'
case 87: // 'W'
case 88: // 'X'
case 89: // 'Y'
case 90: // 'Z'
case 91: // '['
case 92: // '\\'
case 93: // ']'
case 94: // '^'
case 95: // '_'
case 96: // '`'
case 97: // 'a'
case 98: // 'b'
case 101: // 'e'
case 102: // 'f'
case 103: // 'g'
case 104: // 'h'
case 105: // 'i'
case 106: // 'j'
case 107: // 'k'
case 111: // 'o'
case 112: // 'p'
case 114: // 'r'
default:
printStatus((new StringBuilder()).append("Parser: unknown token: ").append(eqTok.typ).append(" ").append(eqTok.stringS).toString());
break;
}
if(flag)
{
if(editMode)
{
if(!editModeFind && i + boxc1.dx <= mouse1X && mouse1X <= i + boxc1.dx + boxc.dx && j - boxc.dy_pos <= mouse1Y && mouse1Y <= j + boxc.dy_neg)
{
x0 = x1 = mouse1X;
y0 = y1 = mouse1Y;
editModeFind = true;
editModeCount1 = l;
editModeCount2 = l;
}
if(!editModeFind && i + boxc1.dx <= mouse2X && mouse2X <= i + boxc1.dx + boxc.dx && j - boxc.dy_pos <= mouse2Y && mouse2Y <= j + boxc.dy_neg)
{
x0 = x1 = mouse2X;
y0 = y1 = mouse2Y;
editModeFind = true;
editModeCount1 = l;
editModeCount2 = l;
int k1 = mouse2X;
int l1 = mouse2Y;
mouse2X = mouse1X;
mouse2Y = mouse1Y;
mouse1X = k1;
mouse1Y = l1;
}
if(editModeFind)
{
x0 = Math.min(x0, i + boxc1.dx);
x1 = Math.max(x1, i + boxc1.dx + boxc.dx);
y0 = Math.min(y0, j - boxc.dy_pos);
y1 = Math.max(y1, j + boxc.dy_neg);
if(editModeRec > k)
editModeRec = k;
switch(j1)
{
case 13: // '\r'
case 15: // '\017'
case 16: // '\020'
case 50: // '2'
case 123: // '{'
case 124: // '|'
flag5 = true;
if(i1 > editModeCount2)
editModeCount2 = i1;
if(i1 < editModeCount1)
editModeCount1 = i1;
l = eqScan.get_count();
break;
}
if(l > editModeCount2)
editModeCount2 = l;
if(l < editModeCount1)
editModeCount1 = l;
if(i + boxc1.dx <= mouse2X && mouse2X <= i + boxc1.dx + boxc.dx && j - boxc.dy_pos <= mouse2Y && mouse2Y <= j + boxc.dy_neg && editModeRec == k)
{
editMode = false;
editModeFind = false;
}
}
}
if(flag5)
{
x0 = Math.min(x0, i + boxc1.dx);
x1 = Math.max(x1, i + boxc1.dx + boxc.dx);
y0 = Math.min(y0, j - boxc.dy_pos);
y1 = Math.max(y1, j + boxc.dy_neg);
switch(j1)
{
case 13: // '\r'
case 15: // '\017'
case 16: // '\020'
case 50: // '2'
case 123: // '{'
case 124: // '|'
if(i1 > editModeCount2)
editModeCount2 = i1;
if(i1 < editModeCount1)
editModeCount1 = i1;
l = eqScan.get_count();
break;
}
if(l > editModeCount2)
editModeCount2 = l;
if(l < editModeCount1)
editModeCount1 = l;
flag5 = false;
}
}
boxc1.dx += boxc.dx;
boxc1.dy_pos = Math.max(boxc1.dy_pos, boxc.dy_pos);
boxc1.dy_neg = Math.max(boxc1.dy_neg, boxc.dy_neg);
if(!flag1 && !flag4)
flag2 = false;
} while(true);
return boxc1;
}
 
private BoxC ACCENT(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = 0;
FontMetrics fontmetrics = g.getFontMetrics();
String s = eqTok.stringS;
if(flag)
l = eqScan.get_count();
boxc = eqn(i, j, false, g, k, false);
int i1 = Math.max(boxc.dx, fontmetrics.stringWidth(s));
int j1 = boxc.dy_pos + fontmetrics.getAscent() / 2;
int k1 = boxc.dy_neg;
if(flag)
{
eqScan.set_count(l);
BoxC boxc1 = eqn(i, j, true, g, k, false);
int l1 = 3 * ((i1 - fontmetrics.stringWidth(s)) / 4);
if(s.equals(".") | s.equals(".."))
g.drawString(s, i + l1, j - fontmetrics.getAscent());
else
if(s.equals("\uFFFD") | s.equals("`"))
g.drawString(s, i + l1, j - fontmetrics.getAscent() / 3);
else
g.drawString(s, i + l1, j - (fontmetrics.getAscent() * 2) / 3);
}
return new BoxC(i1, j1, k1);
}
 
private BoxC ANGLE(int i, int j, boolean flag, Graphics g)
{
BoxC boxc = new BoxC();
FontMetrics fontmetrics = g.getFontMetrics();
int k = g.getFont().getSize() / 2;
int l = fontmetrics.getHeight() - fontmetrics.getDescent();
int i1 = fontmetrics.getDescent();
if(flag)
{
int j1 = (j - l) + 1;
int k1 = (j + i1) - 1;
int l1 = (j1 + k1) / 2;
if(eqTok.stringS.equals("<"))
{
g.drawLine(i + k, j1, i, l1);
g.drawLine(i, l1, i + k, k1);
} else
{
g.drawLine(i, j1, i + k, l1);
g.drawLine(i + k, l1, i, k1);
}
}
return new BoxC(k, l, i1);
}
 
private BoxC ARRAY(int i, int j, boolean flag, Graphics g, int k)
{
boolean flag1 = false;
boolean flag2 = false;
boolean flag3 = false;
int l1 = 0;
int ai[] = new int[100];
int ai1[] = new int[100];
int ai2[] = new int[100];
BoxC boxc = new BoxC();
int i2 = 0;
FontMetrics fontmetrics = g.getFontMetrics();
int j2 = g.getFont().getSize();
if(flag)
i2 = eqScan.get_count();
if(!expect(3, "ARRAY: BeginSym"))
return new BoxC(0, 0, 0);
int k2 = 0;
do
{
if(k2 >= 99)
break;
int i1 = 0;
int k1 = 0;
int l2 = 0;
do
{
if(l2 >= 99)
break;
BoxC boxc1 = eqn(i, j, false, g, k);
i1 = Math.max(i1, boxc1.dy_pos);
k1 = Math.max(k1, boxc1.dy_neg);
ai[l2] = Math.max(ai[l2], boxc1.dx + j2);
if(eqTok.typ == 8 || eqTok.typ == 4)
break;
l2++;
} while(true);
ai1[k2] = Math.max(ai1[k2], i1);
ai2[k2] = Math.max(ai2[k2], k1);
l1 += i1 + k1;
if(eqTok.typ == 4)
break;
k2++;
} while(true);
k2 = 0;
for(int i3 = 0; i3 < 99; i3++)
k2 += ai[i3];
 
if(flag)
{
eqScan.set_count(i2);
expect(3, "ARRAY: Begin");
int j1 = 0;
int j3 = 0;
do
{
if(j3 >= 99)
break;
int l = 0;
if(j3 == 0)
j1 = ai1[j3];
else
j1 += ai2[j3 - 1] + ai1[j3];
int k3 = 0;
do
{
if(k3 >= 99)
break;
BoxC boxc2 = eqn(i + l, (j - l1 / 2 - fontmetrics.getDescent()) + j1, true, g, k);
l += ai[k3];
if(eqTok.typ == 8 || eqTok.typ == 4)
break;
k3++;
} while(true);
if(eqTok.typ == 4)
break;
j3++;
} while(true);
}
return new BoxC(k2 - j2, l1 / 2 + fontmetrics.getDescent(), l1 / 2 - fontmetrics.getDescent());
}
 
private BoxC BEGIN(int i, int j, boolean flag, Graphics g, int k)
{
int i1 = 0;
int j2 = 0;
int ai[] = new int[100];
int ai1[] = new int[100];
int ai2[] = new int[100];
int ai3[] = new int[100];
int ai4[] = new int[100];
int k2 = 0;
int l2 = 0;
int i3 = 0;
BoxC boxc = new BoxC();
int j3 = 0;
FontMetrics fontmetrics = g.getFontMetrics();
int k4 = g.getFont().getSize();
int l4 = 0;
boolean flag1 = false;
boolean flag3 = false;
boolean flag4 = true;
boolean flag5 = true;
boolean flag6 = false;
boolean flag7 = false;
if(!expect(3))
return new BoxC(0, 0, 0);
if(eqScan.nextToken().stringS.equals("eqnarray"))
flag5 = false;
if(!expect(4, "BEGIN: EndSym"))
return new BoxC(0, 0, 0);
if(flag5)
{
j3 = eqScan.get_count();
if(!expect(3))
{
flag4 = false;
eqScan.set_count(j3);
}
}
if(flag5 && flag4)
{
EqToken eqtoken = new EqToken();
for(EqToken eqtoken1 = eqScan.nextToken(); eqtoken1.typ != 4; eqtoken1 = eqScan.nextToken())
{
StringBuffer stringbuffer = new StringBuffer(eqtoken1.stringS);
for(int l6 = 0; l6 < stringbuffer.length(); l6++)
label0:
switch(stringbuffer.charAt(l6))
{
case 108: // 'l'
ai3[l4] = 1;
if(l4 < 99)
l4++;
break;
 
case 99: // 'c'
ai3[l4] = 2;
if(l4 < 99)
l4++;
break;
 
case 114: // 'r'
ai3[l4] = 3;
if(l4 < 99)
l4++;
break;
 
case 64: // '@'
ai3[l4] = 4;
ai4[l4] = eqScan.get_count();
BoxC boxc1 = eqn(i, j, false, g, k, false);
k2 += boxc1.dx;
l2 = Math.max(l2, boxc1.dy_pos);
i3 = Math.max(i3, boxc1.dy_neg);
if(l4 < 99)
l4++;
break;
 
case 42: // '*'
expect(3, "Begin *{");
int j5;
try
{
j5 = Integer.parseInt(eqScan.nextToken().stringS);
}
catch(NumberFormatException numberformatexception)
{
j5 = 0;
}
expect(4, 3, "Begin }{");
int j7 = eqScan.get_count();
int k7 = 0;
do
{
if(k7 >= j5)
break label0;
eqScan.set_count(j7);
for(eqtoken1 = eqScan.nextToken(); eqtoken1.typ != 4; eqtoken1 = eqScan.nextToken())
{
StringBuffer stringbuffer1 = new StringBuffer(eqtoken1.stringS);
for(int l7 = 0; l7 < stringbuffer1.length(); l7++)
switch(stringbuffer1.charAt(l7))
{
case 108: // 'l'
ai3[l4] = 1;
if(l4 < 99)
l4++;
break;
 
case 99: // 'c'
ai3[l4] = 2;
if(l4 < 99)
l4++;
break;
 
case 114: // 'r'
ai3[l4] = 3;
if(l4 < 99)
l4++;
break;
 
case 64: // '@'
ai3[l4] = 4;
ai4[l4] = eqScan.get_count();
BoxC boxc2 = eqn(i, j, false, g, k, false);
k2 += boxc2.dx;
l2 = Math.max(l2, boxc2.dy_pos);
i3 = Math.max(i3, boxc2.dy_neg);
if(l4 < 99)
l4++;
break;
 
default:
printStatus("P: begin: illegal format 2");
break;
}
 
}
 
k7++;
} while(true);
 
default:
printStatus("P: begin: illegal format 1");
break;
}
 
}
 
}
if(!flag5)
{
ai3[0] = 3;
ai3[1] = 2;
ai3[2] = 1;
l4 = 3;
}
for(int k5 = 0; k5 < l4 - 1; k5++)
if(ai3[k5] != 4 && ai3[k5 + 1] != 4)
i1 += k4 / 2;
 
if(flag)
j3 = eqScan.get_count();
int l5 = 0;
do
{
if(l5 >= 99)
break;
int j1 = 0;
int l1 = 0;
int j6 = 0;
do
{
if(j6 >= 99)
break;
BoxC boxc3 = eqn(i, j, false, g, k);
j1 = Math.max(j1, boxc3.dy_pos);
l1 = Math.max(l1, boxc3.dy_neg);
ai[j6] = Math.max(ai[j6], boxc3.dx);
if(eqTok.typ == 8 || eqTok.typ == 51)
break;
j6++;
} while(true);
j1 = Math.max(j1, l2);
l1 = Math.max(l1, i3);
ai1[l5] = j1;
ai2[l5] = l1;
j2 += j1 + l1;
if(eqTok.typ == 51)
break;
l5++;
} while(true);
for(int i5 = 0; i5 < 99; i5++)
i1 += ai[i5];
 
i1 += (2 * k4) / 2;
if(flag)
{
eqScan.set_count(j3);
int k1 = 0;
int i2 = j2 / 2 + fontmetrics.getDescent();
int i6 = 0;
do
{
if(i6 >= 99)
break;
int l = k4 / 2;
if(i6 == 0)
k1 = ai1[i6];
else
k1 += ai2[i6 - 1] + ai1[i6];
int k6 = 0;
int i7 = 0;
do
{
if(i7 >= 99)
break;
for(; ai3[k6] == 4; k6++)
{
int k3 = eqScan.get_count();
eqScan.set_count(ai4[k6]);
BoxC boxc4 = eqn(i + l, (j - i2) + k1, true, g, k, false);
l += boxc4.dx;
eqScan.set_count(k3);
}
 
switch(ai3[k6])
{
case 0: // '\0'
case 1: // '\001'
BoxC boxc5 = eqn(i + l, (j - i2) + k1, true, g, k);
k6++;
break;
 
case 2: // '\002'
int l3 = eqScan.get_count();
BoxC boxc6 = eqn(i, j, false, g, k);
eqScan.set_count(l3);
boxc6 = eqn(i + l + (ai[i7] - boxc6.dx) / 2, (j - i2) + k1, true, g, k);
k6++;
break;
 
case 3: // '\003'
int i4 = eqScan.get_count();
BoxC boxc7 = eqn(i, j, false, g, k);
eqScan.set_count(i4);
boxc7 = eqn((i + l + ai[i7]) - boxc7.dx, (j - i2) + k1, true, g, k);
k6++;
break;
}
if(ai3[k6] != 4)
l += k4 / 2;
l += ai[i7];
boolean flag2 = false;
flag3 = false;
if(eqTok.typ == 8)
flag2 = true;
else
if(eqTok.typ == 51)
{
flag2 = true;
flag3 = true;
}
for(; ai3[k6] == 4; k6++)
{
int j4 = eqScan.get_count();
eqScan.set_count(ai4[k6]);
BoxC boxc8 = eqn(i + l, (j - i2) + k1, true, g, k, false);
l += boxc8.dx;
eqScan.set_count(j4);
}
 
if(flag2)
break;
i7++;
} while(true);
if(flag3)
break;
i6++;
} while(true);
}
if(!expect(3, "BEGIN 2: begin"))
return new BoxC(0, 0, 0);
eqScan.nextToken();
if(!expect(4, "BEGIN 2: end"))
return new BoxC(0, 0, 0);
else
return new BoxC(i1 + k2, j2 / 2 + fontmetrics.getDescent(), j2 / 2 - fontmetrics.getDescent());
}
 
private BoxC FBOX(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = g.getFont().getSize() / 2;
boxc = eqn(i + l, j, flag, g, k, false);
if(flag)
g.drawRect(i + l / 2, j - boxc.dy_pos - l / 2, boxc.dx + l, boxc.dy_pos + boxc.dy_neg + l);
return new BoxC(boxc.dx + l + l, boxc.dy_pos + l, boxc.dy_neg + l);
}
 
private BoxC FG_BGColor(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
BoxC boxc = new BoxC();
int l = 0;
Color color = Color.white;
if(!expect(3, "Color: BeginSym"))
return new BoxC(0, 0, 0);
StringBuffer stringbuffer = new StringBuffer("");
int i1 = 1;
do
{
if(i1 >= 7)
break;
stringbuffer.append(eqScan.nextToken().stringS);
if(stringbuffer.length() == 6)
break;
i1++;
} while(true);
try
{
color = new Color(Integer.parseInt(stringbuffer.toString(), 16));
}
catch(NumberFormatException numberformatexception)
{
BGColor = Color.white;
}
if(!expect(4, "Color: EndSym"))
return new BoxC(0, 0, 0);
if(flag)
l = eqScan.get_count();
Color color1 = g.getColor();
if(flag1)
g.setColor(color);
boxc = eqn(i, j, false, g, k, false);
g.setColor(color1);
if(flag)
{
eqScan.set_count(l);
g.setColor(color);
if(!flag1)
{
g.fillRect(i, j - boxc.dy_pos, boxc.dx, boxc.dy_pos + boxc.dy_neg);
g.setColor(color1);
}
boxc = eqn(i, j, true, g, k, false);
g.setColor(color1);
}
return boxc;
}
 
private BoxC FRAC(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
int l = 0;
BoxC boxc = new BoxC();
BoxC boxc2 = new BoxC();
BoxC boxc3 = new BoxC();
int i1 = 0;
Font font = g.getFont();
int j1 = font.getSize();
rec_Font(g, k + 1);
FontMetrics fontmetrics = g.getFontMetrics();
if(flag)
i1 = eqScan.get_count();
boxc2 = eqn(i, j, false, g, k + 1, false);
int k1 = boxc2.dy_pos + boxc2.dy_neg;
boxc3 = eqn(i, j, false, g, k + 1, false);
int l1 = Math.max(boxc2.dx, boxc3.dx);
int i2 = boxc3.dy_pos + boxc3.dy_neg;
Font font1 = g.getFont();
int j2 = (3 * font1.getSize()) / 18;
l1 += 2 * j2;
if(fontmetrics.getAscent() < i2)
l = fontmetrics.getAscent() / 2;
k1 += 2 + l;
i2 += 1 - l;
if(flag)
{
eqScan.set_count(i1);
if(flag1)
g.drawLine(i + j2, j - l, (i + l1) - j2, j - l);
BoxC boxc1 = eqn(i + (l1 - boxc2.dx) / 2, j - 2 - boxc2.dy_neg - l, true, g, k + 1, false);
if(editModeFind && k < editModeRec)
editModeRec = k;
boxc1 = eqn(i + (l1 - boxc3.dx) / 2, (j + 1 + boxc3.dy_pos) - l, true, g, k + 1, false);
}
rec_Font(g, k);
return new BoxC(l1, k1, i2);
}
 
private BoxC Id(int i, int j, boolean flag, Graphics g)
{
Font font = g.getFont();
g.setFont(new Font(Fontname, 2, font.getSize()));
FontMetrics fontmetrics = g.getFontMetrics();
if(flag)
g.drawString(eqTok.stringS, i, j);
int k = fontmetrics.stringWidth(eqTok.stringS);
int l = fontmetrics.getHeight() - fontmetrics.getDescent();
int i1 = fontmetrics.getDescent();
g.setFont(font);
return new BoxC(k, l, i1);
}
 
private void arc(Graphics g, int i, int j, int k, int l, int i1)
{
g.drawArc(i - k, j - k, 2 * k, 2 * k, l, i1);
}
 
private void drawBracket(Graphics g, String s, int i, int j, int k, int l, int i1,
int j1)
{
int k1 = j / 2;
int l1 = i + k1;
int i2 = i + j;
int j2 = i + k1 / 2;
int k2 = l1 + k1 / 2;
int l2 = (k + l) / 2;
int i3 = (int)((double)k1 * 0.86602540378444004D);
int j3 = k + i3;
int k3 = l - i3;
if(s.equals("["))
{
g.drawLine(j2, k, j2, l);
g.drawLine(j2, l, k2, l);
g.drawLine(j2, k, k2, k);
} else
if(s.equals("]"))
{
g.drawLine(k2, k, k2, l);
g.drawLine(j2, l, k2, l);
g.drawLine(j2, k, k2, k);
} else
if(s.equals("|"))
g.drawLine(l1, k, l1, l);
else
if(s.equals("||"))
{
int l3 = l1 + i1 / 4;
g.drawLine(l1, k, l1, l);
g.drawLine(l3, k, l3, l);
} else
if(s.equals("("))
{
for(int i4 = j1; i4 < 2 + j1; i4++)
{
int i5 = j2 + i4;
arc(g, k2 + i4, j3, k1, 180, -60);
g.drawLine(i5, j3, i5, k3);
arc(g, k2 + i4, k3, k1, 180, 60);
}
 
} else
if(s.equals(")"))
{
for(int j4 = j1; j4 < 2 + j1; j4++)
{
int j5 = k2 + j4;
arc(g, j2 + j4, j3, k1, 0, 60);
g.drawLine(j5, j3, j5, k3);
arc(g, j2 + j4, k3, k1, 0, -60);
}
 
} else
if(s.equals("<"))
{
g.drawLine(j2, l2, k2, k);
g.drawLine(j2, l2, k2, l);
} else
if(s.equals(">"))
{
g.drawLine(k2, l2, j2, k);
g.drawLine(k2, l2, j2, l);
} else
if(s.equals("{"))
{
for(int k4 = j1; k4 < 2 + j1; k4++)
{
int k5 = l1 + k4;
arc(g, i2 + k4, j3, k1, 180, -60);
g.drawLine(k5, j3, k5, l2 - k1);
arc(g, i + k4, l2 - k1, k1, 0, -90);
arc(g, i + k4, l2 + k1, k1, 0, 90);
g.drawLine(k5, l2 + k1, k5, k3);
arc(g, i2 + k4, k3, k1, 180, 60);
}
 
} else
if(s.equals("}"))
{
for(int l4 = j1; l4 < 2 + j1; l4++)
{
int l5 = l1 + l4;
arc(g, i + l4, j3, k1, 0, 60);
g.drawLine(l5, j3, l5, l2 - k1);
arc(g, i2 + l4, l2 - k1, k1, -180, 90);
arc(g, i2 + l4, l2 + k1, k1, 180, -90);
g.drawLine(l5, l2 + k1, l5, k3);
arc(g, i + l4, k3, k1, 0, -60);
}
 
}
}
 
private BoxC LEFT(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
int i1 = 0;
BoxC boxc = new BoxC();
int j1 = 0;
Font font = g.getFont();
int k1 = font.getSize();
int l1 = (int)(2.0F * (float)k1);
int i2 = k1 / 9;
if(flag)
j1 = eqScan.get_count();
String s = eqScan.nextToken().stringS;
boxc = eqn(i, j, false, g, k);
int j2 = boxc.dx;
int k2 = boxc.dy_pos;
int l2 = boxc.dy_neg;
int i3 = (j - k2) + 1;
int j3 = (j + l2) - 1;
String s2 = eqScan.nextToken().stringS;
int k3 = (k2 + l2) - 2;
Font font1 = new Font("Helvetica", 0, k3);
g.setFont(font1);
FontMetrics fontmetrics = g.getFontMetrics();
if(s.equals("<") || s.equals(">"))
l = k1;
else
if(k3 < l1)
{
l = fontmetrics.stringWidth(s);
if("([{)]}".indexOf(s) >= 0)
l += i2;
} else
{
l = k1;
}
if(s2.equals("<") || s2.equals(">"))
i1 = k1;
else
if(k3 < l1)
{
i1 = fontmetrics.stringWidth(s2);
if("([{)]}".indexOf(s2) >= 0)
i1 += i2;
} else
{
i1 = k1;
}
g.setFont(font);
int l3 = eqScan.get_count();
int j4 = 0;
int k4 = 0;
if(eqScan.nextToken().typ == 11)
{
BoxC boxc1 = SUB(i, j, false, g, k, false);
j4 = boxc1.dx;
k4 = (j3 + boxc1.dy_pos) - (boxc1.dy_pos + boxc1.dy_neg) / 2;
l2 += (boxc1.dy_pos + boxc1.dy_neg) / 2;
} else
{
eqScan.set_count(l3);
}
int l4 = eqScan.get_count();
int j5 = 0;
int k5 = 0;
if(eqScan.nextToken().typ == 10)
{
BoxC boxc2 = SUP(i, j, false, g, k, false);
j5 = boxc2.dx;
k5 = (i3 + boxc2.dy_pos) - (boxc2.dy_pos + boxc2.dy_neg) / 2;
k2 += (boxc2.dy_pos + boxc2.dy_neg) / 2;
} else
{
eqScan.set_count(l4);
}
j4 = Math.max(j4, j5);
if(flag)
{
eqScan.set_count(j1);
String s1 = eqScan.nextToken().stringS;
if(!s1.equals("."))
if(k3 < l1 && !s1.equals("<") && !s1.equals(">"))
{
g.setFont(font1);
g.drawString(s1, i, j3 - fontmetrics.getDescent() - fontmetrics.getLeading() / 2);
g.setFont(font);
} else
{
drawBracket(g, s1, i, l, i3, j3, k1, 0);
}
BoxC boxc3 = eqn(i + l, j, true, g, k);
String s3 = eqScan.nextToken().stringS;
if(!s3.equals("."))
if(k3 < l1 && !s3.equals("<") && !s3.equals(">"))
{
g.setFont(font1);
if("([{)]}".indexOf(s3) < 0)
i2 = 0;
g.drawString(s3, i + j2 + l + i2, j3 - fontmetrics.getDescent() - fontmetrics.getLeading() / 2);
g.setFont(font);
} else
{
drawBracket(g, s3, i + j2 + l, i1, i3, j3, -k1, -1);
}
int i4 = eqScan.get_count();
if(expect(11))
boxc3 = SUB(i + j2 + l + i1, k4, true, g, k, false);
else
eqScan.set_count(i4);
int i5 = eqScan.get_count();
if(expect(10))
boxc3 = SUP(i + j2 + l + i1, k5, true, g, k, false);
else
eqScan.set_count(i5);
}
return new BoxC(j2 + l + i1 + j4, k2 + 2, l2 + 2);
}
 
private BoxC LIM(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
BoxC boxc = new BoxC();
int i1 = 0;
int j1 = 0;
FontMetrics fontmetrics = g.getFontMetrics();
String s = eqTok.stringS;
int k1 = eqScan.get_count();
int l1 = l = fontmetrics.stringWidth(s);
int i2 = fontmetrics.getHeight() - fontmetrics.getDescent();
int j2 = fontmetrics.getDescent();
if(expect(11))
{
BoxC boxc1 = SUB(i, j, false, g, k, false);
i1 = boxc1.dx;
l = Math.max(l, boxc1.dx);
j1 = boxc1.dy_pos;
j2 = boxc1.dy_pos + boxc1.dy_neg;
} else
{
eqScan.set_count(k1);
}
if(flag)
{
eqScan.set_count(k1);
g.drawString(s, i + (l - l1) / 2, j);
BoxC boxc2;
if(expect(11))
boxc2 = SUB(i + (l - i1) / 2, j + j1, true, g, k, false);
else
eqScan.set_count(k1);
}
return new BoxC(l, i2, j2);
}
 
private BoxC MBOX(int i, int j, boolean flag, Graphics g)
{
int k = 0;
int l = 0;
int i1 = 0;
BoxC boxc = new BoxC();
if(!expect(3))
return new BoxC(0, 0, 0);
do
{
if(eqScan.EoT())
break;
eqTok = eqScan.nextToken();
if(eqTok.typ == 4)
break;
BoxC boxc1 = Plain(i + k, j, flag, g);
k += boxc1.dx;
l = Math.max(l, boxc1.dy_pos);
i1 = Math.max(i1, boxc1.dy_neg);
} while(true);
return new BoxC(k, l, i1);
}
 
private BoxC NOT(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
boxc = eqn(i, j, flag, g, k, false);
if(flag)
g.drawLine(i + boxc.dx / 4, j + boxc.dy_neg, i + (boxc.dx * 3) / 4, j - boxc.dy_pos);
return boxc;
}
 
private BoxC Op(int i, int j, boolean flag, Graphics g)
{
FontMetrics fontmetrics = g.getFontMetrics();
if(flag)
g.drawString(eqTok.stringS, i + 1, j);
return new BoxC(fontmetrics.stringWidth(eqTok.stringS) + 2, fontmetrics.getHeight() - fontmetrics.getDescent(), fontmetrics.getDescent());
}
 
private BoxC OverBRACE(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
BoxC boxc = new BoxC();
int i1 = g.getFont().getSize() / 4;
int j1 = i1 / 2;
int k1 = 0;
int l1 = 0;
int i2 = 0;
if(flag)
l = eqScan.get_count();
boxc = eqn(i, j, false, g, k, false);
int j2 = boxc.dx;
int k2 = j2 / 2;
int l2 = k2;
int i3 = boxc.dy_pos;
int j3 = boxc.dy_neg;
int k3 = eqScan.get_count();
if(expect(10))
{
BoxC boxc1 = SUP(i, j, false, g, k, false);
k1 = boxc1.dx;
l2 = Math.max(l2, k1 / 2);
l1 = i3 + boxc1.dy_neg;
i2 = boxc1.dy_pos + boxc1.dy_neg;
} else
{
eqScan.set_count(k3);
}
if(flag)
{
eqScan.set_count(l);
int i4 = (i + l2) - k2;
BoxC boxc2 = eqn(i4, j, true, g, k, false);
int j4 = (int)((double)i1 * 0.86602540378444004D);
for(int k4 = 0; k4 < 2; k4++)
{
int l4 = (j - i3 - j1) + k4;
arc(g, i4 + j4, l4 + i1, i1, 90, 60);
g.drawLine(i4 + j4, l4, (i4 + k2) - i1, l4);
arc(g, (i4 + k2) - i1, l4 - i1, i1, 0, -90);
arc(g, i4 + k2 + i1, l4 - i1, i1, -90, -90);
g.drawLine(i4 + k2 + i1, l4, (i4 + j2) - j4, l4);
arc(g, (i4 + j2) - j4, l4 + i1, i1, 90, -60);
}
 
int l3 = eqScan.get_count();
if(expect(10))
boxc2 = SUP((i + l2) - k1 / 2, j - l1 - i1 - j1, true, g, k, false);
else
eqScan.set_count(l3);
}
i3 += i2 + i1 + j1;
j2 = Math.max(j2, k1);
return new BoxC(j2, i3, j3);
}
 
private BoxC UnderBRACE(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
BoxC boxc = new BoxC();
int i1 = g.getFont().getSize() / 4;
int j1 = i1 / 2;
int k1 = 0;
int l1 = 0;
int i2 = 0;
if(flag)
l = eqScan.get_count();
boxc = eqn(i, j, false, g, k, false);
int j2 = boxc.dx;
int k2 = j2 / 2;
int l2 = k2;
int i3 = boxc.dy_pos;
int j3 = boxc.dy_neg;
int k3 = eqScan.get_count();
if(expect(11))
{
BoxC boxc1 = SUB(i, j, false, g, k, false);
k1 = boxc1.dx;
l2 = Math.max(l2, k1 / 2);
l1 = j3 + boxc1.dy_pos;
i2 = boxc1.dy_pos + boxc1.dy_neg;
} else
{
eqScan.set_count(k3);
}
if(flag)
{
eqScan.set_count(l);
int i4 = (i + l2) - k2;
BoxC boxc2 = eqn(i4, j, true, g, k, false);
int j4 = (int)((double)i1 * 0.86602540378444004D);
for(int k4 = 0; k4 < 2; k4++)
{
int l4 = (j + j3 + j1) - k4;
arc(g, i4 + j4, l4 - i1, i1, -90, -60);
g.drawLine(i4 + j4, l4, (i4 + k2) - i1, l4);
arc(g, (i4 + k2) - i1, l4 + i1, i1, 90, -90);
arc(g, i4 + k2 + i1, l4 + i1, i1, 90, 90);
g.drawLine(i4 + k2 + i1, l4, (i4 + j2) - j4, l4);
arc(g, (i4 + j2) - j4, l4 - i1, i1, -90, 60);
}
 
int l3 = eqScan.get_count();
if(eqScan.nextToken().typ == 11)
boxc2 = SUB((i + l2) - k1 / 2, j + l1 + i1 + j1, true, g, k, false);
else
eqScan.set_count(l3);
}
j3 += i2 + i1 + j1;
j2 = Math.max(j2, k1);
return new BoxC(j2, i3, j3);
}
 
private BoxC OverUnderLINE(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
int l = 0;
BoxC boxc = new BoxC();
if(flag)
l = eqScan.get_count();
boxc = eqn(i, j, false, g, k, false);
if(flag1)
boxc.dy_pos += 2;
else
boxc.dy_neg += 2;
int i1 = boxc.dy_pos;
int j1 = boxc.dy_neg;
if(flag)
{
eqScan.set_count(l);
if(flag1)
g.drawLine(i + 1, (j - i1) + 2, (i + boxc.dx) - 1, (j - i1) + 2);
else
g.drawLine(i, (j + j1) - 2, i + boxc.dx, (j + j1) - 2);
boxc = eqn(i, j, true, g, k, false);
}
return new BoxC(boxc.dx, i1, j1);
}
 
private BoxC Paren(int i, int j, boolean flag, Graphics g)
{
FontMetrics fontmetrics = g.getFontMetrics();
int k = g.getFont().getSize() / 9;
int l = fontmetrics.stringWidth(eqTok.stringS);
int i1 = "([{)]}".indexOf(eqTok.stringS);
if(i1 >= 0)
{
l += k;
if(i1 > 2)
i += k;
}
if(flag)
g.drawString(eqTok.stringS, i, j);
return new BoxC(l, fontmetrics.getHeight() - fontmetrics.getDescent(), fontmetrics.getDescent());
}
 
private BoxC Plain(int i, int j, boolean flag, Graphics g)
{
FontMetrics fontmetrics = g.getFontMetrics();
if(flag)
g.drawString(eqTok.stringS, i, j);
return new BoxC(fontmetrics.stringWidth(eqTok.stringS), fontmetrics.getHeight() - fontmetrics.getDescent(), fontmetrics.getDescent());
}
 
private BoxC SPACE(int i, int j, boolean flag, Graphics g)
{
int k = 0;
Font font = g.getFont();
try
{
k = Integer.parseInt(eqTok.stringS);
}
catch(NumberFormatException numberformatexception)
{
k = 0;
}
k = (k * font.getSize()) / 18;
return new BoxC(k, 0, 0);
}
 
private BoxC SQRT(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = 0;
FontMetrics fontmetrics = g.getFontMetrics();
int i1 = 0;
boolean flag1 = false;
int k1 = 0;
int l1 = 0;
boolean flag2 = false;
if(flag)
l = eqScan.get_count();
int i2 = fontmetrics.stringWidth("A");
int j2 = i2 / 2;
int k2 = eqScan.get_count();
EqToken eqtoken = new EqToken();
eqtoken = eqScan.nextToken();
if(eqtoken.stringS.equals("["))
{
rec_Font(g, k + 1);
boxc = eqn(i, j, false, g, k + 1, true);
rec_Font(g, k);
i1 = boxc.dx;
int j1 = boxc.dy_pos;
k1 = boxc.dy_neg;
l1 = k1 + j1;
flag2 = true;
} else
{
eqScan.set_count(k2);
}
boxc = eqn(i, j, false, g, k, false);
int l2 = boxc.dx + i2;
int i3 = boxc.dy_pos + 2;
int j3 = boxc.dy_neg;
if(flag2 & (i1 > j2))
l2 += i1 - j2;
if(flag)
{
eqScan.set_count(l);
int k3 = 0;
if(flag2 & (i1 > j2))
k3 = i1 - j2;
g.drawLine(i + k3 + 1, j - i3 / 2, i + k3 + j2, (j + j3) - 1);
g.drawLine(i + k3 + j2, (j + j3) - 1, (i + k3 + i2) - 2, (j - i3) + 2);
g.drawLine((i + k3 + i2) - 2, (j - i3) + 2, i + l2, (j - i3) + 2);
if(flag2)
{
EqToken eqtoken1 = eqScan.nextToken();
rec_Font(g, k + 1);
BoxC boxc2;
if(i1 >= j2)
{
g.drawLine(i + 1, j - i3 / 2, i + k3 + 1, j - i3 / 2);
BoxC boxc1 = eqn(i + 1, j - i3 / 2 - k1 - 1, true, g, k + 1, true);
} else
{
boxc2 = eqn(i + 1 + (j2 - i1), j - i3 / 2 - k1 - 1, true, g, k + 1, true);
}
rec_Font(g, k);
}
BoxC boxc3 = eqn(i + k3 + i2, j, true, g, k, false);
}
if(flag2 & (i3 / 2 < l1))
i3 = i3 / 2 + l1;
return new BoxC(l2, i3, j3);
}
 
private BoxC STACKREL(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = 0;
int i1 = g.getFontMetrics().getLeading();
if(flag)
l = eqScan.get_count();
boxc = SUP(i, j, false, g, k, true);
int j1 = boxc.dx;
int k1 = boxc.dx;
int l1 = (boxc.dy_pos + boxc.dy_neg) - i1;
int i2 = boxc.dy_neg - i1;
boxc = eqn(i, j, false, g, k, false);
j1 = Math.max(j1, boxc.dx);
int j2 = j1 / 2;
int k2 = boxc.dx;
l1 += boxc.dy_pos;
int l2 = boxc.dy_neg;
i2 += boxc.dy_pos;
if(flag)
{
eqScan.set_count(l);
BoxC boxc1 = SUP((i + j2) - k1 / 2, j - i2, true, g, k, false);
boxc1 = eqn((i + j2) - k2 / 2, j, true, g, k, false);
}
return new BoxC(j1, l1, l2);
}
 
private BoxC SUB(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
int l = 0;
int i1 = 0;
BoxC boxc = new BoxC();
int j1 = 0;
int l1 = g.getFontMetrics().getAscent() / 2;
if(flag)
j1 = eqScan.get_count();
rec_Font(g, k + 1);
boxc = eqn(i, j, false, g, k + 1, false);
int i2 = boxc.dx;
if(flag1)
{
l = l1 - 1;
i1 = (boxc.dy_pos + boxc.dy_neg) - l;
} else
{
i1 = boxc.dy_pos + boxc.dy_neg;
}
if(flag)
{
eqScan.set_count(j1);
if(flag1)
boxc = eqn(i, (j + boxc.dy_pos) - l, true, g, k + 1, false);
else
boxc = eqn(i, j + boxc.dy_pos, true, g, k + 1, false);
}
rec_Font(g, k);
if(flag1)
{
int k1 = eqScan.get_count();
if(expect(10))
{
BoxC boxc1 = SUP(i, j, flag, g, k, true);
i2 = Math.max(i2, boxc1.dx);
l = Math.max(l, boxc1.dy_pos);
} else
{
eqScan.set_count(k1);
}
}
return new BoxC(i2, l, i1);
}
 
private BoxC SUP(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
int l = 0;
int i1 = 0;
BoxC boxc = new BoxC();
int j1 = 0;
int l1 = g.getFontMetrics().getAscent() / 2;
if(flag)
j1 = eqScan.get_count();
rec_Font(g, k + 1);
boxc = eqn(i, j, false, g, k + 1, false);
int i2 = boxc.dx;
if(flag1)
{
i1 = -l1 - 1;
l = (boxc.dy_pos + boxc.dy_neg) - i1;
} else
{
l = boxc.dy_pos + boxc.dy_neg;
}
if(flag)
{
eqScan.set_count(j1);
if(flag1)
boxc = eqn(i, (j - boxc.dy_neg) + i1, true, g, k + 1, false);
else
boxc = eqn(i, j - boxc.dy_neg, true, g, k + 1, false);
}
rec_Font(g, k);
if(flag1)
{
int k1 = eqScan.get_count();
if(expect(11))
{
BoxC boxc1 = SUB(i, j, flag, g, k, true);
i2 = Math.max(i2, boxc1.dx);
i1 = Math.max(i1, boxc1.dy_neg);
} else
{
eqScan.set_count(k1);
}
}
return new BoxC(i2, l, i1);
}
 
private Image getSymbol(Graphics g, int i)
{
String s = (new StringBuilder()).append(eqTok.stringS).append(GreekSize[i - 1]).append(g.getColor().getRGB()).toString();
if(!imageH.containsKey(s))
{
String s1 = (new StringBuilder()).append("Fonts/Greek").append(GreekSize[i - 1]).append("/").append(eqTok.stringS).append(".gif").toString();
Image image = symbolLoader.getImage(appletB, beanB, s1, g, app);
int j = eqScan.get_count();
tracker.addImage(image, j);
displayStatus((new StringBuilder()).append("Loading ").append(eqTok.stringS).toString());
try
{
tracker.waitForID(j, 10000L);
}
catch(InterruptedException interruptedexception) { }
if(tracker.isErrorID(j))
displayStatus((new StringBuilder()).append("Error loading ").append(eqTok.stringS).toString());
else
imageH.put(s, image);
return image;
} else
{
return (Image)(Image)imageH.get(s);
}
}
 
private BoxC SYMBOP(int i, int j, boolean flag, Graphics g, int k, boolean flag1)
{
FontMetrics fontmetrics = g.getFontMetrics();
k = Math.min(k, GreekSize.length);
Image image = getSymbol(g, k);
int l = image.getWidth(this);
if(l < 0)
l = fontmetrics.getMaxAdvance();
if(flag)
{
int i1 = 0;
if(flag1)
i1 = GreekDescent[k - 1];
g.drawImage(image, i, (j - image.getHeight(this)) + i1, this);
}
return new BoxC(l, fontmetrics.getHeight() - fontmetrics.getDescent(), fontmetrics.getDescent());
}
 
private BoxC SYMBOLBIG(int i, int j, boolean flag, Graphics g, int k)
{
int l = 0;
BoxC boxc = new BoxC();
int i1 = 0;
int j1 = 0;
int k1 = 0;
int l1 = 0;
int i2 = 0;
int j2 = g.getFontMetrics().getAscent();
k = Math.min(k, GreekSize.length);
Image image = getSymbol(g, k);
int k2 = l = image.getWidth(this);
int l2 = image.getHeight(this);
if(l2 < 0)
{
l2 = 2 * j2;
k2 = l = j2;
}
int i3 = (int)((double)(l2 / 2) - 0.40000000000000002D * (double)j2);
int j3 = i2 = l2 - i3;
int k3 = eqScan.get_count();
if(expect(11))
{
BoxC boxc1 = SUB(i, j, false, g, k, false);
k1 = boxc1.dx;
l = Math.max(l, boxc1.dx);
i1 = i3 + boxc1.dy_pos;
i3 += boxc1.dy_pos + boxc1.dy_neg;
} else
{
eqScan.set_count(k3);
}
int l3 = eqScan.get_count();
if(expect(10))
{
BoxC boxc2 = SUP(i, j, false, g, k, false);
l1 = boxc2.dx;
l = Math.max(l, boxc2.dx);
j1 = j3 + boxc2.dy_neg;
j3 += boxc2.dy_pos + boxc2.dy_neg;
} else
{
eqScan.set_count(l3);
}
if(flag)
{
eqScan.set_count(k3);
g.drawImage(image, i + (l - k2) / 2, j - i2, this);
BoxC boxc3;
if(expect(11))
boxc3 = SUB(i + (l - k1) / 2, j + i1, true, g, k, false);
else
eqScan.set_count(k3);
int i4 = eqScan.get_count();
if(expect(10))
boxc3 = SUP(i + (l - l1) / 2, j - j1, true, g, k, false);
else
eqScan.set_count(i4);
}
return new BoxC(l, j3, i3);
}
 
private BoxC VEC(int i, int j, boolean flag, Graphics g, int k)
{
BoxC boxc = new BoxC();
int l = g.getFont().getSize();
String s = eqTok.stringS;
boxc = eqn(i, j, flag, g, k, false);
int i1 = boxc.dx;
int j1 = i1 / 2;
int k1 = l / 4;
int l1 = boxc.dy_pos + k1;
int i2 = boxc.dy_neg;
if(flag)
{
int j2 = (j - l1) + k1;
int k2 = l / 8;
int l2 = i + i1;
int i3 = i + j1;
if(s.equals(""))
{
g.drawLine(i, j2, l2, j2);
g.drawLine(i + (int)((double)i1 * 0.80000000000000004D), j2 - k2, l2, j2);
g.drawLine(i + (int)((double)i1 * 0.80000000000000004D), j2 + k2, l2, j2);
} else
if(s.equals("bar"))
g.drawLine(i, j2, l2, j2);
else
if(s.equals("widehat"))
{
g.drawLine(i, j2, i3, j2 - k1);
g.drawLine(i3, j2 - k1, l2, j2);
} else
if(s.equals("widetilde"))
{
boolean flag1 = false;
int k3 = 0;
for(int l3 = 1; l3 < j1; l3++)
{
int j3 = k3;
k3 = (int)((double)k2 * Math.sin((4.0840704496667311D * (double)l3) / (double)j1));
g.drawLine((i3 + l3) - 1, j2 + j3, i3 + l3, j2 + k3);
g.drawLine((i3 - l3) + 1, j2 - j3, i3 - l3, j2 - k3);
}
 
}
}
return new BoxC(i1, l1 + 2, i2);
}
 
private boolean expect(int i)
{
return expect(i, "");
}
 
private boolean expect(int i, String s)
{
int j;
while((j = eqScan.nextToken().typ) == 25) ;
if(j == i)
return true;
if(!s.equals(""))
printStatus((new StringBuilder()).append("Parser: ").append(s).append(" not found").toString());
return false;
}
 
private boolean expect(int i, int j)
{
return expect(i, j, "");
}
 
private boolean expect(int i, int j, String s)
{
int k;
while((k = eqScan.nextToken().typ) == 25) ;
boolean flag = k == i;
while((k = eqScan.nextToken().typ) == 25) ;
flag = k == j;
if(!flag && !s.equals(""))
printStatus((new StringBuilder()).append("Parser: ").append(s).append(" not found").toString());
return flag;
}
 
private void rec_Font(Graphics g, int i)
{
if(i <= 1)
g.setFont(f1);
else
if(i == 2)
g.setFont(f2);
else
if(i == 3)
g.setFont(f3);
else
g.setFont(f4);
}
 
private static final String VERSION = "sHotEqn V 4.00 ";
private int width;
private int height;
private String nameS;
private String equation;
private String Fontname;
ActionListener actionListener;
private EqScanner eqScan;
private EqToken eqTok;
private Font f1;
private Font f2;
private Font f3;
private Font f4;
private static final float mk = 2F;
private static final int GreekFontSizes[] = {
8, 10, 12, 14, 18
};
private static final int GreekFontDescents[] = {
2, 3, 4, 5, 6
};
private int GreekSize[] = {
14, 12, 10, 8
};
private int GreekDescent[] = {
3, 3, 3, 3
};
private static final int EmbedFontSizes[] = {
9, 11, 14, 16, 22
};
private Image bufferImage;
private boolean imageOK;
private int localWidth;
private int localHeight;
private Color BGColor;
private Color EnvColor;
private Color FGColor;
private Color BorderColor;
private boolean borderB;
private boolean roundRectBorderB;
private int border;
private String halign;
private String valign;
private int xpos;
private int ypos;
private boolean drawn;
private SymbolLoader symbolLoader;
private MediaTracker tracker;
private Hashtable imageH;
private JApplet app;
public boolean appletB;
public boolean beanB;
public boolean debug;
private boolean editMode;
private boolean editableB;
private int mouse1X;
private int mouse1Y;
private int mouse2X;
private int mouse2Y;
private int xOFF;
private int yOFF;
private int y0;
private int x0;
private int y1;
private int x1;
private int editModeRec;
private boolean editModeFind;
private int editModeCount1;
private int editModeCount2;
private Image selectImage;
public BufferedImage finalimage;
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Fonts14.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Fonts18.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Des8.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/BoxC.java
0,0 → 1,38
/*
Copyright 2006 Stefan Müller and Christian Schmid
This file is part of the HotEqn package.
 
HotEqn is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package atp;
 
 
class BoxC
{
 
public BoxC(int i, int j, int k)
{
dx = i;
dy_pos = j;
dy_neg = k;
}
 
public BoxC()
{
dx = 0;
dy_pos = 0;
dy_neg = 0;
}
 
public int dx;
public int dy_pos;
public int dy_neg;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/SymbolLoader.java
0,0 → 1,168
/*
Copyright 2006 Stefan Müller and Christian Schmid
This file is part of the HotEqn package.
 
HotEqn is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package atp;
 
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.URL;
import java.util.Hashtable;
import java.util.StringTokenizer;
 
// Referenced classes of package atp:
// ColorMaskFilter
 
class SymbolLoader
{
 
public SymbolLoader()
{
fontdesH = new Hashtable(189);
}
 
public Image getImage(boolean flag, boolean flag1, String s, Graphics g, Applet applet)
{
StringTokenizer stringtokenizer = new StringTokenizer(s, "/");
String s1 = stringtokenizer.nextToken();
s1 = stringtokenizer.nextToken().substring(5);
String s2 = stringtokenizer.nextToken();
int i = -1;
boolean flag2 = true;
do
{
if(!flag2)
break;
if(fontsizes[++i].equals(s1))
flag2 = false;
if(i == 4)
flag2 = false;
} while(true);
if(imageSources[i] == null)
{
imageSources[i] = getBigImage(flag, flag1, (new StringBuilder()).append("Fonts").append(s1).append(".gif").toString(), applet);
String s3 = (new StringBuilder()).append("Des").append(s1).append(".gif").toString();
BufferedInputStream bufferedinputstream = null;
try
{
if(kLocalFonts)
{
InputStream inputstream = getClass().getResourceAsStream(s3);
bufferedinputstream = new BufferedInputStream(getClass().getResourceAsStream(s3));
} else
if((!flag) & (!flag1))
bufferedinputstream = new BufferedInputStream((new URL(s3)).openStream());
else
if(flag)
bufferedinputstream = new BufferedInputStream((new URL(applet.getCodeBase(), s3)).openStream());
else
try
{
bufferedinputstream = new BufferedInputStream(getClass().getResource(s3).openStream());
}
catch(Exception exception) { }
ObjectInputStream objectinputstream = new ObjectInputStream(bufferedinputstream);
int j = objectinputstream.readInt();
for(int k = 0; k < j; k++)
{
String s4 = (String)objectinputstream.readObject();
fontdesH.put((new StringBuilder()).append(s1).append(s4).toString(), new Rectangle((Rectangle)objectinputstream.readObject()));
}
 
bufferedinputstream.close();
}
catch(Exception exception1)
{
System.out.println(exception1.toString());
imageSources[i] = null;
}
}
Image image = null;
if(imageSources[i] != null)
{
Rectangle rectangle = (Rectangle)(Rectangle)fontdesH.get((new StringBuilder()).append(s1).append(s2).toString());
image = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(new FilteredImageSource(imageSources[i], new CropImageFilter(rectangle.x, rectangle.y, rectangle.width, rectangle.height)), new ColorMaskFilter(g.getColor())));
}
return image;
}
 
public ImageProducer getBigImage(boolean flag, boolean flag1, String s, Applet applet)
{
ImageProducer imageproducer = null;
if(kLocalFonts)
imageproducer = getLocalImageSource(s);
if(imageproducer == null)
{
kLocalFonts = false;
if((!flag) & (!flag1))
imageproducer = Toolkit.getDefaultToolkit().getImage(s).getSource();
else
if(flag)
imageproducer = applet.getImage(applet.getCodeBase(), s).getSource();
else
try
{
URL url = getClass().getResource(s);
imageproducer = (ImageProducer)url.getContent();
}
catch(Exception exception) { }
}
return imageproducer;
}
 
ImageProducer getLocalImageSource(String s)
{
ImageProducer imageproducer = null;
try
{
InputStream inputstream = getClass().getResourceAsStream(s);
int i = inputstream.available();
byte abyte0[] = new byte[i];
int j = 0;
int k = 0;
do
{
if(k == -1)
break;
k = inputstream.read(abyte0, j, i);
if(k != -1)
{
j += k;
i = inputstream.available();
int l = j + i;
if(l > abyte0.length)
{
byte abyte1[] = (byte[])(byte[])abyte0.clone();
abyte0 = new byte[l];
System.arraycopy(abyte1, 0, abyte0, 0, j);
}
}
} while(i != 0);
imageproducer = Toolkit.getDefaultToolkit().createImage(abyte0).getSource();
}
catch(Exception exception) { }
return imageproducer;
}
 
private ImageProducer imageSources[] = {
null, null, null, null, null
};
private String fontsizes[] = {
"8", "10", "12", "14", "18"
};
private Hashtable fontdesH;
private static boolean kLocalFonts = true;
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/ColorMaskFilter.java
0,0 → 1,52
/*
Copyright 2006 Stefan Müller and Christian Schmid
This file is part of the HotEqn package.
 
HotEqn is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package atp;
 
import java.awt.Color;
import java.awt.image.RGBImageFilter;
 
class ColorMaskFilter extends RGBImageFilter
{
 
ColorMaskFilter(Color color1)
{
maskORinvert = false;
color = color1;
maskORinvert = false;
canFilterIndexColorModel = true;
}
 
ColorMaskFilter(Color color1, boolean flag)
{
maskORinvert = false;
color = color1;
maskORinvert = flag;
canFilterIndexColorModel = true;
}
 
public int filterRGB(int i, int j, int k)
{
if(maskORinvert)
return 0x1fff0000;
int l = k & 0xffffff;
if(l == 0xffffff)
return l;
else
return 0xff000000 | color.getRGB();
}
 
Color color;
boolean maskORinvert;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Des10.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Des12.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Des14.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Fonts8.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/EqToken.java
0,0 → 1,83
/*
Copyright 2006 Stefan Müller and Christian Schmid
This file is part of the HotEqn package.
 
HotEqn is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
HotEqn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package atp;
 
 
class EqToken
{
 
public EqToken(int i, String s)
{
typ = i;
stringS = s;
}
 
public EqToken(int i)
{
typ = i;
stringS = "";
}
 
public EqToken()
{
typ = 0;
stringS = "";
}
 
public int typ;
public String stringS;
public static final int EOF = 0;
public static final int Id = 1;
public static final int Num = 2;
public static final int BeginSym = 3;
public static final int EndSym = 4;
public static final int ANGLE = 5;
public static final int AndSym = 7;
public static final int DBackSlash = 8;
public static final int FUNC = 9;
public static final int SUP = 10;
public static final int SUB = 11;
public static final int FRAC = 12;
public static final int SQRT = 13;
public static final int VEC = 14;
public static final int ARRAY = 15;
public static final int LEFT = 16;
public static final int RIGHT = 17;
public static final int SYMBOP = 18;
public static final int SYMBOPD = 19;
public static final int SYMBOLBIG = 20;
public static final int ACCENT = 22;
public static final int LIM = 24;
public static final int SpaceChar = 25;
public static final int BEGIN = 50;
public static final int END = 51;
public static final int Null = 99;
public static final int Invalid = 100;
public static final int Op = 108;
public static final int Paren = 109;
public static final int NOT = 110;
public static final int SPACE = 113;
public static final int CHOOSE = 114;
public static final int ATOP = 115;
public static final int OverLINE = 116;
public static final int UnderLINE = 117;
public static final int OverBRACE = 118;
public static final int UnderBRACE = 119;
public static final int STACKREL = 120;
public static final int FGColor = 121;
public static final int BGColor = 122;
public static final int FBOX = 123;
public static final int MBOX = 124;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Des18.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/src/atp/Fonts10.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/build.xml
0,0 → 1,66
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for TexApp.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="TexApp" default="jar" basedir=".">
 
<description>TexApp build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
<exec executable="/bin/sh">
<arg line="-c 'cp ${source-dir}/atp/*.gif ${build}/atp/'"/>
</exec>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create TexApp jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/TexApp.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="TexApp"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="TexApp"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="TexApp">
<attribute name="Specification-Title" value="TexApp"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="TexApp"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/TexApp/test.html
0,0 → 1,78
<html>
<body bgcolor=#ffffff onload="javascript:SetSize('TexApp');">
<script type="text/javascript">
function remove(t){
document.getElementById(t).width = 1;
document.getElementById(t).height = 1;
}
function SetSize(t){
var size = new Array(2);
size = document.getElementById(t).getPrefferedSize();
document.getElementById(t).width = size[0];
document.getElementById(t).height = size[1];
document.getElementById('showme').innerHTML='<hr><font color=red><b>preffered height = '+size[1]+'<br>preffered width = '+size[0]+'</b></font>';
}
function ReadApplet(t){
var reply = document.getElementById(t).ReadApplet();
document.getElementById('showme').innerHTML='<hr><font color=red><b>'+reply+'</b></font>';
}
function ExtraInput(t){
document.getElementById('TexApp').changeInputfields(t);
}
</script>
<div id="showme"></div>
<table ><tr valign=middle ><th>
<font color=red>
this is some text...
</font>
</th>
<th>
<applet id="TexApp" codebase="dist" archive="TexApp.jar" code="TexApp.class" width="1" height="1">
<param name="latex_bgcolor" value="#ffffff"><!-- r,g,b default white -->
<param name="latex_fgcolor" value="#000000"><!-- r,g,b default black -->
<param name="latex" value="\left\{ \begin{array}{l} 4 \times \euro = \\ 4 \times \euro = \\ 4 \times \euro = \end{array} "> <!-- values, plain latex no ":" or ";" allowed -->
<param name="latex_fontsize" value="18"><!-- r,g,b default black -->
<!-- optional inputfield after the latex image -->
<param name="status" value="done"><!-- string : wims variable $status done/waiting -->
<param name="inputfields" value="3"><!-- int : optional : default 0 : number of inputfields on top of eachother-->
<param name="inputfield_width" value="120"><!-- int : default 10 : width in px of inputfield-->
<param name="inputfield_height" value="120"><!-- optional int : default fontsize in px : height in px of inputfield-->
<param name="inputfield_fontsize" value ="18"><!-- int : default 10 -->
<param name="inputfield_bgcolor" value="0,0,255"><!-- r,g,b default white -->
<param name="inputfield_fgcolor" value="255,0,0"><!-- r,g,b default black -->
<param name="inputfield_editable" value="1,1,1"><!-- field 1 is editable, field 2 is editable... default all editable -->
<param name="inputfield_values" value="12,44,"><!-- optional for correct answers: field 1 = "12", field 2 = "44" field3= "" field4 = "22" -->
NO JAVA
</applet>
</th>
<th>
<font color=red>
and this is the rest...</font>
</th></tr>
</table>
<p>
<font color=white>
For applet autoscaling, the applet_tag "width" should be less than 10 : width="1"<br>
The autoscaling SetSize() javascript_function could be called from the htmlpage "body onload".<br>
Or in WIMS:<br>
!set wims_html_onload=javascript:SetSize('TexApp');
<br>
If the applet has a width &gt; 10 , no autoscaling is performed.
</font>
<br>
<input type="button" name="ReadApplet()" value="ReadApplet()" onclick="javascript:ReadApplet('TexApp');">
<input type="button" name="SetSize()" value="SetSize()" onclick="javascript:SetSize('TexApp');">
<input type="button" name="remove()" value="remove()" onclick="javascript:remove('TexApp');">
<br>
<input type="button" name="extra inputfield" value="extra inputfield" onclick="javascript:ExtraInput('1');">
<input type="button" name="remove inputfield" value="remove inputfield" onclick="javascript:ExtraInput('-1');">
</body>
</html>
 
/trunk/wims/src/Misc/authors/jm.evers/applets/2D_pie/build.xml
0,0 → 1,65
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for PieChart.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="PieChart" default="jar" basedir=".">
 
<description>PieChart build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create PieChart jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/2D_pie.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="PieChart"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="PieChart"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="PieChart">
<attribute name="Specification-Title" value="PieChart"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="PieChart"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/2D_pie/src/PieChart.java
0,0 → 1,454
/*
* Configuration: config.html
* Status: Free
* Java Boutique:Upload Date October 11, 1999
* Author: Saket Kumar
* download from: http:*javaboutique.internet.com/PieChart/index.html
* PieChart.java for Drawing Bar Chart.
* slightly altered: J.M. Evers
* extra params: degree,radian,rounding etc etc
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
 
/*
* adapted for WIMS by jm.evers
* public JS functions: ReadApplet()
* public JS functions: SetApplet()
*
*
*
*/
import java.awt.*;
import java.io.*;
import java.lang.*;
import java.applet.Applet;
import java.util.*;
import java.io.PrintStream;
 
public class PieChart extends java.applet.Applet {
 
String title;
Font font;
FontMetrics fontMetrics;
int titleHeight = 15;
int columns;
public int round=1000;
public float values[];
Color colors[];
public String labels[];
public float percent[];
public float angle[];
public float degree[];
public float radian[];
public float rawinput[];
int maxLabelWidth = 0;
int maxValueWidth = 0;
int max = 0;
int strWidth=0;
public boolean showLabel=true; // Whether to display the label or not
public boolean showPercent=false; // Whether to display percentage or not
public boolean showRadians=false; // Whether to display radians or not
public boolean showDegrees=false; // Whether to display degrees or not
public boolean showInput=true; // Whether to display raw input numbers
String unit; // Whether to display a unit for rawinput values?
 
int lx=0,ly=0; //For Writing Label
int cx=0,cy=0; //Center of Circle
 
public synchronized void init() {
String temp;font = new java.awt.Font("Sanserif", Font.BOLD, 12);
fontMetrics = getFontMetrics(font);
String bgColor=getParameter("bgcolor"); // Background color of Chart
if (bgColor==null)
setBackground(Color.white);
else{
if (bgColor.equals("red")) {
setBackground(Color.red);
} else if (bgColor.equals("green")) {
setBackground(Color.green);
} else if (bgColor.equals("blue")) {
setBackground(Color.blue);
} else if (bgColor.equals("pink")) {
setBackground(Color.pink);
} else if (bgColor.equals("orange")) {
setBackground(Color.orange);
} else if (bgColor.equals("magenta")) {
setBackground(Color.magenta);
} else if (bgColor.equals("cyan")) {
setBackground(Color.cyan);
} else if (bgColor.equals("white")) {
setBackground(Color.white);
} else if (bgColor.equals("yellow")) {
setBackground(Color.yellow);
} else if (bgColor.equals("gray")) {
setBackground(Color.gray);
} else if (bgColor.equals("darkGray")) {
setBackground(Color.darkGray);
} else {
setBackground(Color.white);
}
}
title = getParameter("title"); // Title of the Pie Chart
if (title == null) {title = "WIMS Pie Chart";}
 
unit = getParameter("unit"); // Title of the Pie Chart
if (unit == null) {unit = "";}
temp = getParameter("columns");
if (temp == null) { columns = 5;} else {columns = Integer.parseInt(temp);}
 
temp = getParameter("rounding");
if (temp != null){round = Integer.parseInt(temp);if ( round < 1){ round=100;}}
 
temp = getParameter("showdegrees");
if (temp == null){showDegrees = false;}
else
{
if (temp.equalsIgnoreCase("YES")){showDegrees = true;}
if (temp.equalsIgnoreCase("NO")){showDegrees = false;}
}
temp = getParameter("showradians");
if (temp == null){showRadians = false;}
else
{
if (temp.equalsIgnoreCase("YES")){showRadians = true;}
if (temp.equalsIgnoreCase("NO")){showRadians = false;}
}
 
temp = getParameter("showinput");
if (temp == null){showInput = true;}
else
{
if (temp.equalsIgnoreCase("YES")){showInput = true;}
if (temp.equalsIgnoreCase("NO")){showInput = false;}
}
 
temp = getParameter("showlabel");
if (temp == null) {showLabel = false;}
else
{
if (temp.equalsIgnoreCase("YES")){showLabel = true;}
if (temp.equalsIgnoreCase("NO")){showLabel = false;}
}
 
temp = getParameter("showpercent");
if (temp == null) {showPercent = false;}
else
{
if (temp.equalsIgnoreCase("YES")){showPercent = true;}
if (temp.equalsIgnoreCase("NO")){showPercent = false;}
}
radian = new float[columns];
degree = new float[columns];
rawinput = new float[columns];
values = new float[columns];
colors = new Color[columns];
labels = new String[columns];
percent= new float[columns];
angle = new float[columns];
String tmp=null;
float totalValue=0;
for (int i=0; i < columns; i++) {
tmp=getParameter("Pvalue" + (i+1));
float f = Float.valueOf(tmp.trim()).floatValue();
values[i] =f;
float t = Float.valueOf(tmp).floatValue();
rawinput[i]=t;
totalValue += values[i];
// parse the label for this column
temp = getParameter("P" + "label"+ (i+1) );
labels[i] = (temp == null) ? "" : temp;
maxLabelWidth = Math.max(fontMetrics.stringWidth((String)(labels[i])),maxLabelWidth);
// parse the color attribute for this column
temp = getParameter("P" + "color"+ (i+1) );
if (temp != null) {
if (temp.equals("red")) {
colors[i] = Color.red;
} else if (temp.equals("green")) {
colors[i] = Color.green;
} else if (temp.equals("blue")) {
colors[i] = Color.blue;
} else if (temp.equals("pink")) {
colors[i] = Color.pink;
} else if (temp.equals("orange")) {
colors[i] = Color.orange;
} else if (temp.equals("magenta")) {
colors[i] = Color.magenta;
} else if (temp.equals("cyan")) {
colors[i] = Color.cyan;
} else if (temp.equals("white")) {
colors[i] = Color.white;
} else if (temp.equals("yellow")) {
colors[i] = Color.yellow;
} else if (temp.equals("gray")) {
colors[i] = Color.gray;
} else if (temp.equals("darkGray")) {
colors[i] = Color.darkGray;
} else {
colors[i] = Color.gray;
}
} else {
colors[i] = Color.gray;
}
}
float multiFactor = 100 / totalValue;
 
for (int i=0; i < columns; i++) {
percent[i]= (float) (Math.round(round*values[i] * multiFactor))/round;
angle[i] = (float) (Math.round(round*3.6*values[i] * multiFactor))/round; // Calculation of Angle (360/100)
degree[i] = (float) (Math.round(round*percent[i] * 3.6))/round ;
radian[i] = (float) (Math.round(round*angle[i]/180))/round; // * pi rad !!!
}
 
}
 
// paint method
 
public synchronized void paint(Graphics g) {
int x=0;
int y=0;
int width=0,height=0;
int ax=0,ay=0; //For Drawing Black line from center to Peripherial
int px=0,py=0; //For Writing Percentage
int radius=0;
width=height=Math.min((getSize().width - 100),(getSize().height - 100));
x=y=50;
 
if ( getSize().width > width ){
x = (getSize().width - width ) /2 ;
}
 
cx = x + width/2;
cy = y + height/2;
radius = width/2;
 
// Draw the Title of the Chart on Top of the Applet
 
strWidth=fontMetrics.stringWidth(title);
Font fnt = new java.awt.Font("Sanserif", Font.BOLD, 16);
g.setFont(fnt);
g.setColor(Color.red);
g.drawString(title,((getSize().width - strWidth )/2),15);
g.setFont(font);
int initAngle=90;
int sweepAngle=0;
int incSweepAngle=0;
int incLabelAngle= (int) (angle[0]/2);
 
for (int i=0; i < columns; i++) {
sweepAngle = (int) Math.round(angle[i]);
g.setColor((Color)colors[i]);
 
if (i==(columns-1)){
sweepAngle = 360 - incSweepAngle;
g.fillArc(x,y,width,height,initAngle,(-sweepAngle));
g.setColor(Color.black);
g.drawArc(x,y,width,height,initAngle,(-sweepAngle));
 
lx = (int) (cx + ( radius * Math.cos((incLabelAngle * 3.14f/180) - 3.14f/2)));
ly = (int) (cy + ( radius * Math.sin((incLabelAngle * 3.14f/180) - 3.14f/2)));
adjustLabel(i);
int ly2=ly+15;
 
if (showLabel)
{
g.drawString((String)labels[i] ,lx,ly);
if (showDegrees){g.drawString(String.valueOf(degree[i]) + "\u00b0" ,lx,ly2);}
else
{
if (showRadians){g.drawString( String.valueOf(radian[i]) +"\u03c0 rad" ,lx,ly2);}
else
{
if (showPercent){g.drawString( String.valueOf(percent[i]) +" %" ,lx,ly2);}
else
{
if (showInput){g.drawString( String.valueOf(rawinput[i])+" "+unit,lx,ly2);}
}
}
}
}
else
{
if (showDegrees){g.drawString(String.valueOf(degree[i]) + "\u00b0" ,lx,ly2);}
else
{
if (showRadians){g.drawString( String.valueOf(radian[i]) +"\u03c0 rad" ,lx,ly2);}
else
{
if (showPercent){g.drawString( String.valueOf((Math.round(round*percent[i]))/round) +" %" ,lx,ly2);}
else
{
if (showInput){g.drawString( String.valueOf(rawinput[i])+" "+ unit,lx,ly2);}
}
}
}
}
break;
}
 
g.fillArc(x,y,width,height,initAngle,(-sweepAngle));
g.setColor(Color.black);
g.drawArc(x,y,width,height,initAngle,(-sweepAngle));
incSweepAngle +=sweepAngle;
 
ax = (int) (cx + ( radius * Math.cos((incSweepAngle * 3.14f/180) - 3.14f/2)));
ay = (int) (cy + ( radius * Math.sin((incSweepAngle * 3.14f/180) - 3.14f/2)));
g.drawLine(cx,cy,ax,ay);
 
lx = (int) (cx + ( radius * Math.cos((incLabelAngle * 3.14f/180) - 3.14f/2)));
ly = (int) (cy + ( radius * Math.sin((incLabelAngle * 3.14f/180) - 3.14f/2)));
adjustLabel(i);
int ly2=ly+15;
if (showLabel){
g.drawString((String)labels[i],lx,ly);
if ( showDegrees){g.drawString(String.valueOf(degree[i]) + "\u00b0" ,lx,ly2);}
else
{
if ( showRadians){g.drawString(String.valueOf(radian[i])+"\u03c0 rad" ,lx,ly2);}
else
{
if (showPercent){g.drawString( String.valueOf(percent[i]) +" %" ,lx,ly2);}
else
{
if (showInput){g.drawString( String.valueOf(rawinput[i])+" "+unit,lx,ly2);}
}
}
}
}
else
{
if ( showDegrees){g.drawString(String.valueOf(degree[i]) + "\u00b0" ,lx,ly2);}
else
{
if ( showRadians){g.drawString(String.valueOf(radian[i])+"\u03c0 rad" ,lx,ly2);}
else
{
if (showPercent){g.drawString( String.valueOf((Math.round(round*percent[i]))/round) +" %" ,lx,ly2);}
else
{
if (showInput){g.drawString( String.valueOf(rawinput[i])+" "+unit,lx,ly2);}
}
}
}
}
incLabelAngle = incLabelAngle + (int) (angle[i]/2 + angle[i+1]/2);
initAngle += (-sweepAngle);
}
g.setColor(Color.black);
g.drawLine(cx,cy,cx,cy-radius);
}
 
private void adjustLabel(int i){
if ( (lx > cx) && (ly < cy) ){
lx +=5;
ly -=5;
}
 
if ( (lx > cx) && (ly > cy) ){
lx +=5;
ly +=10;
}
 
if ( (lx < cx) && (ly > cy) ){
strWidth=fontMetrics.stringWidth(labels[i]);
lx -= strWidth+5;
if (lx < 0)
lx=0;
}
 
if ( (lx < cx) && (ly < cy) ){
strWidth=fontMetrics.stringWidth(labels[i]);
lx -= strWidth+5;
if (lx < 0)
lx=0;
}
}
// jm.evers 3/2008 modification to avoid intervening of WIMS in the update of the applet
// that was a real waste of recources !!!
// public static String replace(String source, String pattern, String replace){
// if (source!=null){
// final int len = pattern.length();
// StringBuffer sb = new StringBuffer();
// int found = -1;
// int start = 0;
// while( (found = source.indexOf(pattern, start) ) != -1) {
// sb.append(source.substring(start, found));
// sb.append(replace);
// start = found + len;
// }
// sb.append(source.substring(start));
// return sb.toString();
// }
// else return "";
// }
public String ReadApplet(){
// ATTENTION MSIE-6 ? will not accept an array[]:it must be a string!!!
int len=values.length;String reply="";
if(len==0){
reply="error empty answer";
}
else
{
float p;String l="";
for(int i=0 ; i<len;i++){
l=labels[i];
p=rawinput[i];
reply=reply+"segment "+i+" [ "+l+" ] = "+p+"\n";
}
}
return reply;
}
// SetApplet() is called by javascript
// it reads the inputfield on the page...strips..."sends" them to the applet
// use a comma seperated list...
// we cannot handle "pi" or "+" or "-" or "*" or "/" etc
// JAVASCRIPT SHOULD DEAL WITH THIS !!!!!!
public void SetApplet( String i){
String tmp="";float input;
StringTokenizer R = new StringTokenizer(i,",");
int max=R.countTokens();
float value[]=new float[max];float sum=0;
for(int p=0;p<max;p++){
tmp=R.nextToken();
if(tmp.length()==0){tmp="0";}
input=Float.valueOf(tmp).floatValue();
System.out.println("input = " + input +"\n");
rawinput[p]=input;
value[p]=input;
sum=sum+input;
}
for(int p=0;p<max;p++){
input=value[p];
// we show the correct circlediagram...maybe the sum of the degrees were != 360 ...we don't care
angle[p] = 360*input/sum;
percent[p] = 100*input/sum;
radian[p] = (float) (input/sum);
degree[p] = 360*input/sum;
}
repaint();
}
/// end jm.evers 3/2008
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/InvulGrid/build.xml
0,0 → 1,63
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for InvulGrid.jar.
Just type:
ant -v
ant -v clean
-->
 
 
<project name="InvulGrid" default="make-jar" basedir=".">
 
<description>InvulGrid build file</description>
 
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="./src"/>
<property name="build" location="./build"/>
<property name="dist" location="./dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="make-jar" depends="compile" description="Create InvulGrid jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/InvulGrid.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="InvulGrid"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="InvulGrid"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="InvulGrid">
<attribute name="Specification-Title" value="InvulGrid"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="InvulGrid"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
</jar>
</target>
 
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/InvulGrid/src/InvulGrid.java
0,0 → 1,1350
/*
*********************************************************************************
* J.M. Evers 2010 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty. *
*********************************************************************************
version 0.4
10/12/2010
Added param pointsize to differ size of points from linewidth
Removed &minus;&times from html reply (problems with representation after sending to wims)
now just ascii + - : x
 
version 0.3
Added decimals [point object]
 
version 0.2
 
Added correct French button text [B. Perrin-Riou]
Added left hand +,-,x,: sign next to the lines [when language=fr ]
 
version 0.1
 
Applet for simple adding, subtracting,dividing and multiplying by pupils.
The result can be checked by WIMS.
 
Output:
document.getElementById('InvulGrid').ReadApplet("0") : itemlist [one item per horizontal line]
document.getElementById('InvulGrid').ReadApplet("1") : javascript confirmbox
document.getElementById('InvulGrid').ReadApplet("2") : html table
document.getElementById('InvulGrid').ReadApplet("3") : latex array/table
 
Example [same as test.html]
<html>
<body>
<script type="text/javascript">
function ReadThis(){
 
var wims_reply = document.getElementById('InvulGrid').ReadApplet("0");
alert("this can send to wims for correction:\n"+wims_reply);
var js_alert_show= document.getElementById('InvulGrid').ReadApplet("1");
alert("this can be the confirmbox for the pupil:\n"+js_alert_show);
var html_show= document.getElementById('InvulGrid').ReadApplet("2");
document.getElementById('html_reply').innerHTML="this is a html-table representation<br>"+html_show;
var latex_show= document.getElementById('InvulGrid').ReadApplet("3");
alert("this is an latex array of the answer:\n Usable via !insmath\n"+latex_show);
}
</script>.
<table>
<tr>
<th>
<applet id="InvulGrid" codebase="dist" archive="InvulGrid.jar" code="InvulGrid.class" width="400" height="400">
<param name="fontsize" value="50"><!-- optional: actual fontsize will be determined according xlines/ylines -- xsize/ysize -->
<param name="pencolor" value="0,0,255,150"><!-- optional: typing color -->
<param name="bgcolor" value="255,255,255"><!-- optional: canvas bgcolor;default white ; R,G,B,alpha -->
<param name="markcolor" value="10,255,10,60"><!-- optional: active field color -->
<param name="linecolor" value="200,10,60,150"><!-- optional: user drawn lines in applet -->
<param name="linewidth" value="6"><!-- linewidth of user drawn lines -->
<param name="pointsize" value="3"><!-- size of drawn decimal points -->
<param name="xlines" value="12"><!-- default 10 ; number of vertical lines : determines fontsize -->
<param name="ylines" value="12"><!-- default 10 ; number of horizontal lines -->
<param name="showgrid" value="1"><!-- show xlines and ylines as grid in gridcolor -->
<param name="gridcolor" value="0,0,255,40"><!-- color of grid -->
<param name="reverse" value="yes"><!-- default false ; editing from right to left -->
<param name="language" value="en"><!-- default en ; nl , fr -->
<!-- optional: is an itemlist, spaces matter .-->
<!-- Optional horizontal lines: ---|x|-|+|: -->
<!-- bug in java plugin's stringtokenizer: first token blancspace is stripped off... -->
<!-- in applet viewer this works fine -->
<!-- to produce an space before the first number, add a "," like-->
<!-- spaces matter !! -->
<param name="exercise" value=", 13456789, 567890, 12345, 45678, 2345678,---|-">
<!-- use first row of grid for user scribbling: this will not be send to wims -->
<param name="scribling_pencolor" value="255,200,0,170"><!-- optional -->
<!-- if param buttons is empty or not set : only a 'clear all; button will be shown -->
<param name="buttons" value="+"><!-- user draws lines with +,-,x,&divide; symbols ; do not use too many! -->
</applet>
<br>
<input type="button" name="InvulGrid" value="Read " onclick="javascript:ReadThis(0);">
</th>
<th>
<div id="html_reply"></div>
</th>
</tr>
<table>
</body>
</html>
*/
 
import java.applet.Applet;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.awt.Color;
import javax.swing.*;
//import java.io.*; not needed, we use javascript to communicate with WIMS
 
public class InvulGrid extends JApplet implements ActionListener,KeyListener,MouseListener, MouseMotionListener, MouseWheelListener {
Font font;
int fontsize,xsize,ysize,xlines,ylines,xstep,ystep,linewidth,pointsize;
Color scribling_pencolor,bgcolor,pencolor,linecolor,markcolor,gridcolor,deletecolor,marked_color,exercisecolor,scribling_rowcolor;
String[][] charArray;
boolean[][] Marked;
boolean[][] Editable;
boolean[] EditableObject;
int xindex = 0;
int yindex = 0;
int objcnt=0;
Graphics2D backg;
BufferedImage bg;
Vector objects = new Vector();
Vector decimalpoints = new Vector();
int pointcnt = 0;
boolean showgrid;
public String line_plus="line + ";
public String line_times="line x";
public String line_min="line -";
public String line_div="line :";
public String delete_line="delete line";
public String clear_all="clear all";
Container cp;
int editablecnt = 0;
int fontheight=10;
boolean check_segments = false;
boolean reverse = false;
boolean left_to_right = false;
int scribling = 2;
// true: --- + false: + ---
boolean right = true;
int fontwidth = 10;
// reverse :if no 'conclusion line' is drawn, we write form left to right
// if a line is drawn, we write from right to left...
 
// slow repainting can occur via update() : using bufferedimage of grid to avoid flickering.
public void init(){
scribling_pencolor = colorParam("scribling_pencolor", new Color(255,0,0));
if( (getBool("scribling_row",true)) == true){scribling = 2;}else{scribling = 1;}
getLanguage("language");
getButtons();
Dimension appletSize = getSize();
xsize = appletSize.width;
ysize = appletSize.height;
xlines = getInt("xlines",10);
ylines = getInt("ylines",10);
xstep = (int) xsize/xlines;
ystep = (int) ysize/(ylines+1);
bg = new BufferedImage(xsize,ysize, BufferedImage.TYPE_INT_ARGB);
backg = (Graphics2D) bg.getGraphics();
// fitfont kan ylines bepalen !! volgorde is belangrijk
fontsize = getInt("fontsize",28);
font = FitFont( backg ,"TimesRoman" , fontsize);
charArray = new String[xlines+1][ylines+1];
Marked = new boolean[xlines+1][ylines+1];
Editable = new boolean[xlines+1][ylines+1];
EditableObject = new boolean[xlines*ylines];
for(int x = 0; x < xlines+1; x++){
for(int y = 0; y < ylines+1 ; y++){
charArray[x][y]="";
Marked[x][y]=false;
Editable[x][y]=true;
}
}
for(int y = 0 ; y <xlines*ylines;y++){
EditableObject[y] = true;
}
showgrid = getBool("showgrid",true);
left_to_right = getBool("reverse",false);
scribling_rowcolor = colorParam("scribling_rowcolor",new Color(0,255,0,50));
bgcolor = colorParam("bgcolor",Color.white);
pencolor = colorParam("pencolor",Color.black);
linecolor = colorParam("linecolor",Color.red);
markcolor = colorParam("markcolor",Color.green);
gridcolor = colorParam("gridcolor",Color.blue);
exercisecolor = colorParam("exercisecolor",Color.black);
linewidth = getInt("linewidth",2);
pointsize = getInt("pointsize",5);
deletecolor = new Color(255,0,0,120);
marked_color = markcolor;
addKeyListener(this);
addMouseListener(this);
addMouseMotionListener(this);
addMouseWheelListener(this);
getSegments();
ReadStringParam();
prepaint();
requestFocus();
}
 
public String ReadApplet(String t){
String[] reply = new String[ylines+1];
String[] horline = new String[ylines+1];
StringBuffer tmp;
int cnt = 0;
int userline;
int maxlength=0;
String op;// operator +,-,/,*
boolean not_empty = false;
boolean found_line = false;
int pnt = -1;
for( int y = scribling ; y <= ylines ; y++ ){// y = 1 all including scribling row ; y=2 excluding scribling row
tmp = new StringBuffer();
found_line = false;
op = "";
pnt = -1;
for(int i = 0 ; i < objcnt ; i++){
if (objects.elementAt(i) instanceof GridLine){
if( ((GridLine)objects.elementAt(i)).isSegment() == true ){
userline = (int)(((GridLine)objects.elementAt(i)).getY1()/ystep) - 1;
if( y == userline ){
found_line = true;
op = ((GridLine)objects.elementAt(i)).getText();
i = objcnt; //exit
}
}
}
}
pnt = findPoint(y);
for( int x = 0 ; x <= xlines ; x++ ){
if(x == pnt){
tmp.append(".");
}
tmp.append(charArray[x][y]);
}
if(tmp.length() != 0){
if( tmp.length() > maxlength ){maxlength = tmp.length();}
not_empty = true;
reply[cnt] = replace(tmp.toString(), " " , "");
//System.out.println("added "+reply[cnt] + " by y = "+y);
if(found_line == true){horline[cnt] = op;}
cnt++;
}
}
if(not_empty == false){return "error:empty answer";}
 
if( t.equals("3") ){
return makeLatex(reply,horline);
}
else
{
if( t.equals("2") ){
return makeHtml(reply,horline);
}
else
{
if( t.equals("1") ){
return makeJs(reply,horline,maxlength);
}
else
{
if( t.equals("0") ){
return Array2String(reply,",");
}
else
{
return "error : usage is \n ReadApplet(0) ... wims itemlist\n ReadApplet(3) ... latex representation\n ReadApplet(2) ... html representation\n ReadApplet(1) ... javascript confirmbox";
}
}
}
}
}
public String Array2String(String[] s, String sep) {
StringBuilder result = new StringBuilder();
if (s.length > 0) {
result.append(s[0]);
for (int i=1; i < s.length; i++) {
if(s[i] != null){
result.append(sep);
result.append(s[i]);
}
}
}
return result.toString();
}
 
public String makeLatex(String[] reply , String[] horline){
String latex="";
String op="";
String space="";
boolean fraction = false;
int w = 0;int thisline=0;
while ( fraction == false && w <= ylines ){
if(reply[w] != null){
if(reply[w].indexOf("\\") != -1){
fraction = true;
thisline = w;
}
}
w++;
}
if(fraction == true ){
int start = (reply[thisline]).indexOf("/");
int end = (reply[thisline]).indexOf("\\");
w = end - start - 1;
if(w<0){w = reply[thisline].length();}
reply[thisline] = replace(reply[thisline],"\\"," & \\diagdown & ");
reply[thisline] = replace(reply[thisline],"/"," & \\diagup & ");
reply[thisline] = reply[thisline] + " \\\\ ";
latex="\\begin{array}{cclcc}"+reply[thisline];
thisline++;
}
else
{
latex="\\begin{array}{rr}";
thisline = 0;
}
for( int y = thisline ; y < reply.length ; y++ ){
if( reply[y] != null){
if(horline[y] != null){
if((horline[y]).equals("\u00D7")){
op =" \\times ";
}
else
{
if((horline[y]).equals("\u00F7")){
op =" \\div ";
}
else
{
op = horline[y];
}
}
if(fraction == false){
if(right){
latex = latex + " \\underline{" +reply[y]+ "} & "+horline[y] +" \\\\ ";
}
else // french
{
latex = latex + horline[y] +" & \\underline{" +reply[y]+ " } \\\\ ";
}
}
else
{
if( w > reply[y].length()){
for(int z=0; z < w - reply[y].length();z++){
space = space + " \\: ";
}
}
latex = latex + "& & \\underline{" +space+ reply[y]+"} & & \\\\ ";
}
}
else
{
if(fraction == false){
if(right){
latex = latex + " "+ reply[y] + " & "+ " \\\\ ";
}
else // french
{
latex = latex + " & "+ reply[y] + " \\\\ ";
}
}
else
{
if( w > reply[y].length()){
for(int z=0; z < w - reply[y].length();z++){
space = space + " \\: ";
}
}
latex = latex + "& & "+ space+ reply[y] +" & & \\\\ ";
}
}
}
}
latex = latex + " \\end{array}";
return latex;
}
 
public String makeHtml(String[] reply , String[] horline){
String table = "<table style=\"margin-bottom:1px;margin-top:1px;\"><tr><td align=\"right\"><table style=\"margin-bottom:1px;margin-top:1px;\" summary=\"\" width=\"100%\">";
String tmp="";
for( int y = 0 ; y < reply.length ; y++ ){
if(reply[y] != null){
if(right){
table=table+"<tr><td style=\"text-align:right\">"+reply[y]+"</td><td>&nbsp;&nbsp;&nbsp;&nbsp;</td></tr>";
}
else // french
{
table=table+"<tr><td>&nbsp;&nbsp;&nbsp;&nbsp;</td><td style=\"text-align:right\">"+reply[y]+"</td></tr>";
}
if(horline[y] != null){
if(horline[y].equals("\u00D7")) tmp = "x";
else
if(horline[y].equals("\u00F7")) tmp = ":";
else tmp = horline[y];
if(right){
table=table+"</table></td><tr><td><table style=\"margin-bottom:1px;margin-top:1px;\" summary=\"\" width=\"100%\"><tr><th width=\"90%\"><hr></th><th>"+tmp+"</th></tr></table></td></tr><td><table style=\"margin-bottom:1px;margin-top:1px;\" summary=\"\" width=\"100%\">";
}
else // french
{
table=table+"</table></td><tr><td><table style=\"margin-bottom:1px;margin-top:1px;\" summary=\"\" width=\"100%\"><tr><th>"+tmp+"</th><th width=\"90%\"><hr></th></tr></table></td></tr><td><table style=\"margin-bottom:1px;margin-top:1px;\" summary=\"\" width=\"100%\">";
}
}
}
}
table = table+"</table></td></tr></table>";
return table;
}
public String makeJs(String[] reply, String[] horline , int maxlength){
String js="";String space = "";String line = "";String op = "";
for(int i = 0 ; i < maxlength ; i++){
line = line + "-";
}
for( int y = 0 ; y < reply.length ; y++ ){
if(reply[y] != null){
if(horline[y] != null){
space = "";
for(int i = 0 ; i < (maxlength - reply[y].length()) ; i++){
space = space + " ";
}
if(right){
js = js + space+reply[y] + "\n" + line + " " + horline[y] + "\n";
}
else // french
{
js = js + space+reply[y] + "\n" + horline[y] +" "+ line + "\n";
}
}
else // trying to align at the rightside of the alertbox ... somehow this will not work properly
{
space = "";
for(int i = 0 ; i < (maxlength - reply[y].length()) ; i++){
space = space + " ";
}
js = js + space + reply[y] + "\n";
}
}
}
return js;
}
public void getSegments(){
String param = getParameter("segment1");
if(param != null && param.length() > 3){
int i = 1;
StringTokenizer s;
int m=0,x1=0,x2=0,y1=0,y2=0;
String colorparam;Color segmentcolor;
check_segments = true;
while( param != null && param.length() >3 ){
s = new StringTokenizer(param, ",");
m = s.countTokens();
if(m != 4){System.out.println("Expecting 2 points for a linesegment");return;}
for(int p = 0 ; p < 4 ; p++){
if( p == 0 ){ x1 = Integer.parseInt(s.nextToken());}
else
if( p == 1 ){ y1 = Integer.parseInt(s.nextToken());}
else
if( p == 2 ){ x2 = Integer.parseInt(s.nextToken());}
else
if( p == 3 ){ y2 = Integer.parseInt(s.nextToken());}
}
colorparam = "color"+i;
EditableObject[editablecnt] = false;editablecnt++;
segmentcolor = colorParam(colorparam,linecolor);
drawLine(x1*xstep,(y1+2)*ystep,x2*xstep,(y2+2)*ystep,segmentcolor,"",false,false);
i++;
param = getParameter("segment"+i);
}
}
}
 
 
public void ReadStringParam(){
String exo = getParameter("exercise");
if(exo != null && exo.length()>0){
StringTokenizer lines = new StringTokenizer(exo, ",");
int m=lines.countTokens();
boolean found_fraction = false;
boolean found_decimal_point = false;
if( m < ylines ){
String lastword="";
String word="";String tmp="";int xi=0;
for( int i = 0 ; i < m ; i++){
word = lines.nextToken();
if(word.indexOf("/") != -1){ found_fraction = true;}
if(word.indexOf("---|") != -1){// a special line and should be LAST !!
// the last word was: charArray[xindex - 1][yindex - 1]
char[] wordArray = lastword.toCharArray();
boolean found = false;int start = 0;int end = wordArray.length;
for(int s = 0; s < end;s++){
if(wordArray[s] != ' ' && !found){start = s;found = true;}
}
if(right && found_decimal_point){
end = end - 1;
}
else
{
if(!right && found_decimal_point && start >0 ){start = start - 1; end = end - 1;}
}
if(word.indexOf("---|+") != -1){ // ---- +
drawLine(start*xstep,(i+2)*ystep,end*xstep,(i+2)*ystep,linecolor,"+",false,true);
EditableObject[editablecnt] = false;editablecnt++;
}
else
{
if(word.indexOf("---|-") != -1){ // ---- -
drawLine(start*xstep,(i+2)*ystep,end*xstep,(i+2)*ystep,linecolor,"-",false,true);
EditableObject[editablecnt] = false;editablecnt++;
}
else
{
if(word.indexOf("---|x") != -1){ // ---- x
drawLine(start*xstep,(i+2)*ystep,end*xstep,(i+2)*ystep,linecolor,"\u00D7",false,true);
EditableObject[editablecnt] = false;editablecnt++;
}
else
{
if(word.indexOf("---|:") != -1){ // ---- division
drawLine(start*xstep,(i+2)*ystep,end*xstep,(i+2)*ystep,linecolor,"\u00F7",false,true);
EditableObject[editablecnt] = false;editablecnt++;
}
else
{
System.out.println("unknown command : "+word);
}
}
}
}
}
else
{
xi=0;
for( int p = 0 ; p < word.length(); p++){
if( p <= xlines ){
tmp = Character.toString(word.charAt(p));
if(tmp.equals(".")){
drawPoint(xi,i+2,pointsize,false);
found_decimal_point = true;
}
else
{
charArray[xi][i+2] = tmp;
//we do not use yindex=1 : space is used for controls...
lastword = word;
if(found_fraction == true){
Editable[xi][i+2] = false;
}
else
{
for(int c = 0 ; c<xlines;c++){ // disable editing of line y=i+2
Editable[c][i+2] = false;
}
}
xi++;
}
}
else
{
System.out.println("ERROR : word "+word+" too large for "+xlines+" gridlines...\nin param \"execise\"");
return;
}
}
}
}
for(int x = 0 ; x<xlines ; x++){
Editable[x][1] = true;
charArray[x][1]="";
}
}
else
{
System.out.println("ERROR : to many spaces in param \"exercise\"");
return;
}
}
}
 
 
public void getLanguage(String s){
s = getParameter("language");
if(s != null && s.length() == 2){
if( s.equalsIgnoreCase("nl")){
line_plus="lijn + ";
line_times="lijn x";
line_min="lijn -";
delete_line="verwijder lijn";
clear_all="alles wissen";
line_div="line :";
right=true;
return;
}
else
{
if( s.equalsIgnoreCase("fr")){
line_plus="+ à droite ";
line_times="droite x";
delete_line="effacer droite";
clear_all="effacer";
line_min="droite -";
line_div="droite :";
right=false;
return;
}
}
}
}
public Font FitFont(Graphics g , String fontname , int fontsize){
String maxstring="";
for(int p = 0 ; p<xlines+4;p++){
maxstring=maxstring+"5";
}
font = new Font(fontname,Font.BOLD,fontsize);
FontMetrics fm = g.getFontMetrics(font);
if(fm.stringWidth(maxstring) > xsize){
boolean does_not_fit = true;
while(fontsize > 4 && does_not_fit){
fontsize = fontsize - 1;
font = new Font(fontname,Font.BOLD,fontsize);
fm = g.getFontMetrics(font);
if(fm.stringWidth(maxstring) < xsize){
does_not_fit = false;
}
}
System.out.println("xsize ("+xsize+") of applet too small...I've adjusted fontsize to "+fontsize);
}
fontheight =(int) (0.6*fm.getHeight());
if( fontheight > ystep ){ // fonts will overlap !! decrease ygrid...
System.out.println("I will decrease number of horizontal lines: fonts will overlap...\nuse more xlines to overcome this.");
ystep = fontheight;
ylines = (int) (ysize / fontheight);
if(ylines < 2){ylines = 2;}
}
fontwidth = fm.stringWidth("+");
return font;
}
public int getInt(String s, int i){
String s1 = getParameter(s);
if( s1 != null && s1.length()!=0){
try{
i = Integer.parseInt(s1);
}
catch(Exception exception){System.out.println(" can not parse parameter "+s);}
}
return i;
}
 
public boolean getBool(String s, boolean flag){
String s1 = getParameter(s);
if(s1 != null){
if(s1.equals("1") || s1.equalsIgnoreCase("yes") || s1.equalsIgnoreCase("true"))
return true;
if(s1.equals("0") || s1.equalsIgnoreCase("no") || s1.equalsIgnoreCase("false"))
return false;
}
return flag;
}
 
public Color colorParam(String s, Color color){
String s1 = getParameter(s);
if(s1 != null && s1.length() != 0){
s1 = replace(s1,":", ",");
s1 = replace(s1,";", ",");
if( s1.indexOf(',') > 0 ){
StringTokenizer stringtokenizer = new StringTokenizer(s1, ",");
int i = stringtokenizer.countTokens();
if(i < 3 || i > 4){ return color;}
int ai[] = new int[i + 1];
for(int j = 0; j < i; j++){
ai[j] = Integer.parseInt(stringtokenizer.nextToken());
if(ai[j] > 255 || ai[j] < 0){ ai[j] = 0;}
}
if(i == 3){
color = new Color(ai[0], ai[1], ai[2]);
}
else
{
color = new Color(ai[0], ai[1], ai[2], ai[3]);
}
}
else
{
try{ color = Color.decode( s1 );}catch(Exception e){System.out.println("could not parse "+s);}
return color;
}
}
return color;
}
 
public void prepaint(){ // all "static" components are painted "once"
backg.setColor(bgcolor);
backg.fillRect(0,0,xsize,ysize);
if(showgrid){
backg.setColor(gridcolor);
backg.setStroke( new BasicStroke(1));
for(int x=0; x<xsize;x=x+xstep){
backg.drawLine(x,ystep,x,ysize);
}
for(int y=ystep;y<ysize;y=y+ystep){
backg.drawLine(0,y,xsize,y);
}
}
reverse=false;
backg.setFont(font);
for( int i = 0 ; i < objcnt; i++){
if (objects.elementAt(i) instanceof GridLine){
backg.setStroke( new BasicStroke(linewidth));
backg.setColor(((GridLine)objects.elementAt(i)).getColor());
backg.drawLine(
((GridLine)objects.elementAt(i)).getX1(),
((GridLine)objects.elementAt(i)).getY1(),
((GridLine)objects.elementAt(i)).getX2(),
((GridLine)objects.elementAt(i)).getY2()
);
if(right){
backg.drawString(
((GridLine)objects.elementAt(i)).getText(),
((GridLine)objects.elementAt(i)).getX2()+linewidth,
((GridLine)objects.elementAt(i)).getY2()+(fontheight-linewidth)/2
);
}
else
{
backg.drawString(
((GridLine)objects.elementAt(i)).getText(),
((GridLine)objects.elementAt(i)).getX1()-linewidth-fontwidth,
((GridLine)objects.elementAt(i)).getY2()+(fontheight-linewidth)/2
);
}
if(i == objcnt - 1){
reverse= ((GridLine)objects.elementAt(i)).isSegment();
}
}
}
for( int i = 0 ;i < pointcnt ; i++){
if (decimalpoints.elementAt(i) instanceof DecimalPoint){
int l = ((DecimalPoint)decimalpoints.elementAt(i)).getD();
backg.setStroke( new BasicStroke(l));
backg.setColor(pencolor);
backg.fillOval(
xstep*(((DecimalPoint)decimalpoints.elementAt(i)).getX()) - pointsize,
ystep*(1+((DecimalPoint)decimalpoints.elementAt(i)).getY()) - pointsize,
l,
l
);
}
}
backg.setColor(scribling_rowcolor);
for(int x = 0 ; x <= xlines ; x++){
backg.fillRect(x*xstep,ystep,xstep,ystep); //scribling row
}
 
backg.setColor(exercisecolor);
for(int x=0;x <= xlines ;x++){
for(int y=0;y <= ylines ;y++){
if(!Editable[x][y]){
backg.drawString(charArray[x][y],x*xstep,(y+1)*ystep);
}
}
}
}
public void update(Graphics g){
prepaint();
paintComponent(g);
}
public void paint(Graphics g){
update(g);
}
 
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(bg,0,0,this);
g2.setFont(font);
reverse=false;
for( int i = 0 ; i < objcnt; i++){
if (objects.elementAt(i) instanceof GridLine){
if( ((GridLine)objects.elementAt(i)).getEdit() ){
backg.setStroke( new BasicStroke(linewidth));
backg.setColor(((GridLine)objects.elementAt(i)).getColor());
backg.drawLine(
((GridLine)objects.elementAt(i)).getX1(),
((GridLine)objects.elementAt(i)).getY1(),
((GridLine)objects.elementAt(i)).getX2(),
((GridLine)objects.elementAt(i)).getY2()
);
if(right){
backg.drawString(
((GridLine)objects.elementAt(i)).getText(),
((GridLine)objects.elementAt(i)).getX2()+linewidth, // ---- +
((GridLine)objects.elementAt(i)).getY2()+(fontheight-linewidth)/2
);
}
else //french
{
backg.drawString(
((GridLine)objects.elementAt(i)).getText(),
((GridLine)objects.elementAt(i)).getX1()-linewidth-fontwidth, // + ----
((GridLine)objects.elementAt(i)).getY2()+(fontheight-linewidth)/2
);
}
}
if(i == objcnt - 1){
reverse= ((GridLine)objects.elementAt(i)).isSegment();
}
}
}
for( int i = 0 ; i < pointcnt; i++){
if (decimalpoints.elementAt(i) instanceof DecimalPoint){
int l = ((DecimalPoint)decimalpoints.elementAt(i)).getD();
backg.setStroke( new BasicStroke(l));
backg.setColor(pencolor);
backg.fillOval(
xstep*(((DecimalPoint)decimalpoints.elementAt(i)).getX()) - pointsize,
ystep*(1+((DecimalPoint)decimalpoints.elementAt(i)).getY()) - pointsize,
l,
l
);
}
}
for(int y=1;y <= ylines ;y++){ // start from scribling row
for(int x=0;x <= xlines ;x++){
if(Marked[x][y]){
g2.setColor(marked_color);
g2.fillRect(x*xstep,y*ystep,xstep,ystep);
Marked[x][y]=false;
}
if(Editable[x][y]){
if( y == 1){ // scribling row
g2.setColor(scribling_pencolor);
}
else
{
g2.setColor(pencolor);
}
g2.drawString(charArray[x][y],x*xstep,(y+1)*ystep);
}
}
}
}
public synchronized void mousePressed(MouseEvent evt){
int x = evt.getX();int y = evt.getY();
boolean xfound=false,yfound=false;
for(int p=0 ; p < xsize ; p = p + xstep){
if(x > p && x < p + xstep ){
xindex = (int) x/xstep;
xfound=true;
}
}
for(int p=ystep ; p < ysize ; p = p + ystep){
if(y > p && y < p + ystep ){
yindex = (int) y/ystep ;
yfound=true;
}
}
if(xfound && yfound){
Marked[xindex][yindex] = true;
repaint();
}
}
public void mouseWheelMoved(MouseWheelEvent evt){
int d = evt.getWheelRotation();
if(d < 0){
yindex--;
if(yindex < 1){yindex = 1;}
Marked[xindex][yindex] = true;
}
else
{
yindex++;
if(yindex > ylines ){yindex = ylines ;}
Marked[xindex][yindex] = true;
}
repaint();
}
 
public synchronized void mouseDragged(MouseEvent evt){
int x =(int) (evt.getX())/xstep;
int y =(int) (evt.getY())/ystep;
if(x>=0 && y>=1 && x<=xlines && y<=ylines){
if(Editable[x][y]){ // only delete if editable
Marked[x][y] = true;
charArray[x][y]="";
deleteDecimalPoint(x,y);
marked_color=deletecolor;
xindex = x;
yindex = y;
repaint();
}
}
}
public synchronized void mouseReleased(MouseEvent evt){}
public void mouseEntered(MouseEvent evt){requestFocus();}
public void mouseExited(MouseEvent evt){}
public void mouseMoved(MouseEvent evt){requestFocus();}
public void mouseClicked(MouseEvent evt){
int x =(int) (evt.getX())/xstep;
int y =(int) (evt.getY())/ystep;
if(x>=0 && y>=0 && x<=xlines && y<=ylines){
if(Editable[x][y]){
xindex = x;yindex = y;
Marked[xindex][yindex] = true;
repaint();
}
}
}
public int[] ForbiddenKeys={16,17,18,19,20,27,112,113,114,115,116,117,118,119,120,145,154,155};
 
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
//System.out.println("key="+key);
for(int i = 0 ; i < 18 ; i++){
if(key == ForbiddenKeys[i]){return;}
}
ProcessKey( key, Character.toString(e.getKeyChar()) );
repaint();
}
public void keyTyped(KeyEvent e ) {}
public void keyReleased(KeyEvent e){}
 
public void ProcessKey(int key,String c){
if(key == 46 || key == 44){if(Editable[xindex][yindex] == true){if(reverse){drawPoint(xindex+1,yindex,pointsize,true);}else{drawPoint(xindex,yindex,pointsize,true);}Marked[xindex][yindex] = true;}}
else
if(key == 32){ // space
xindex++;;
if( xindex > xlines - 1){
xindex = 0;
yindex++;
if(yindex > ylines ){yindex = ylines;}
}
Marked[xindex][yindex] = true;
}
else
if(key == 10){ // enter -> newline : starts under the first char of previous line
int[] word = findLastWordLength();
yindex++;
if(reverse && left_to_right == false ){xindex = word[2];}else{xindex = word[1];}
if(yindex > ylines ){yindex = ylines;}
Marked[xindex][yindex] = true;
}
else
if(key == 37){ // leftarrow
xindex--;
if(xindex < 0){xindex = xlines;
yindex--;
if(yindex < 1){yindex = 1;}// not smaller than 1 : control button space...
}
Marked[xindex][yindex] = true;
}
else
if(key == 39){ // rightarrow
xindex++;
if( xindex > xlines - 1){
xindex = 0;
yindex++;
if(yindex > ylines ){yindex = ylines;}
}
Marked[xindex][yindex] = true;
}
else
if( key == 36){// home;
yindex = 1;
xindex = 1;
Marked[xindex][yindex] = true;
}
else
if( key == 35){// end;
yindex = ylines ;
Marked[xindex][yindex] = true;
}
else
if( key == 38 || key == 33){// arrow up
yindex--;
if(yindex < 1){yindex = 1;}
Marked[xindex][yindex] = true;
}
else
if( key == 40 || key == 34 ){// arrow down
yindex++;
if(yindex > ylines ){yindex = ylines ;}
Marked[xindex][yindex] = true;
}
else
if( (key == 8 ) && Editable[xindex][yindex]){//backspace
charArray[xindex][yindex] = "";
deleteDecimalPoint(xindex,yindex);
xindex--;
if(xindex < 0){
xindex = xlines - 1;
yindex--;
if(yindex < 1){ yindex = 1;}
}
Marked[xindex][yindex] = true;
}
else
if( ( key == 127 ) && Editable[xindex][yindex]){// delete
charArray[xindex][yindex] = "";
Marked[xindex][yindex] = true;
deleteDecimalPoint(xindex,yindex);
}
else
{
if(Editable[xindex][yindex]){
charArray[xindex][yindex] = c;
if(reverse && left_to_right == false ){
if(xindex < xlines ){
xindex = xindex - 1;
if (xindex<0 ){
int[] pos = findLastWordLength();
xindex = pos[2];
yindex++;
if( yindex > ylines ){ yindex = ylines;}
}
}
}
else
{
if(xindex < xlines ){
xindex = xindex + 1;
if (xindex>=xlines ){
int[] pos = findLastWordLength();
xindex = pos[1];
yindex++;
if( yindex > ylines ){ yindex = ylines;}
}
}
}
Marked[xindex][yindex] = true;
}
}
marked_color = markcolor;
}
 
public void Clear(){
for(int x = 0; x < xlines+1; x++){
for(int y = 0; y < ylines+1 ; y++){
if(Editable[x][y]){ // only clear if editable
charArray[x][y]="";
Marked[x][y]=false;
}
}
}
repaint();
}
 
public int[] findLastWordLength(){
int[] word = new int[4];
int cnt;int thisline=0;int max=0;
for(int y = 0 ; y < ylines ; y++){
cnt=0;
for(int x=0 ; x < xlines ; x++){
if(charArray[x][y] != ""){cnt++;}
}
if(cnt>0){
thisline = y;
if( cnt > max ){ max = cnt;}
}
}
int begin=0;
int end=xlines;
for(int x = 0 ; x<xlines;x++){ // from left to word
if(charArray[x][thisline] != "" ){begin = x;x=xlines;}
}
for(int x = xlines - 1 ; x >= 0;x--){//from right to word
if(charArray[x][thisline] != "" ){ end = x; x=-1;}
}
word[0] = thisline;
word[1] = begin;
word[2] = end;
word[3] = max;
return word;
}
 
 
public String replace(String source, String pattern, String replace){
if ( source!=null && pattern.length()!=0 ){
final int len = pattern.length();
StringBuffer sb = new StringBuffer();
int found = -1;
int start = 0;
while( (found = source.indexOf(pattern, start) ) != -1) {
sb.append(source.substring(start, found));
sb.append(replace);
start = found + len;
}
sb.append(source.substring(start));
return sb.toString();
}
else return "";
}
 
public void deleteAllLines(){
int s = objcnt - 1;
for( int i = s ; i >=0; i--){
if(EditableObject[i]){
objects.removeElementAt(i);
objcnt--;
}
}
repaint();
}
 
public void deleteLine(){
if(objcnt <= 0){objcnt = 0; return;}
if( (EditableObject[objcnt - 1]) == true){
try{
objcnt--;
objects.removeElementAt(objcnt);
repaint();
}
catch(Exception e){System.out.println("can not remove line ... objcnt = "+objcnt+"\nerror : "+e);}
}
}
 
public void deleteAllPoints(){
int m = pointcnt - 1;
for( int i = m ; i >=0; i--){
if( (((DecimalPoint)decimalpoints.elementAt(i)).getEditable()) == true ){
decimalpoints.removeElementAt(i);
pointcnt--;
}
}
repaint();
}
public int findPoint(int y){ // find the x- location of a decimal point at line y : only 1 point allowed...
for(int i = 0 ; i<pointcnt;i++){
if( (DecimalPoint)decimalpoints.elementAt(i) != null ){
if( (((DecimalPoint)decimalpoints.elementAt(i)).getY()) == y ){
return (int) (((DecimalPoint)decimalpoints.elementAt(i)).getX());
}
}
}
return -1;
}
public void deleteDecimalPoint(int x,int y){
for( int i = 0 ; i < pointcnt; i++){
if(
(((DecimalPoint)decimalpoints.elementAt(i)).getX()) == x
&&
(((DecimalPoint)decimalpoints.elementAt(i)).getY()) == y
&&
(((DecimalPoint)decimalpoints.elementAt(i)).getEditable()) == true
){
try{
decimalpoints.removeElementAt(i);
pointcnt--;
repaint();
return;
}catch(Exception e){System.out.println("poincnt "+pointcnt+"\terror="+e);}
}
}
}
public void destroy() {}
public void start(){}
 
public void drawPoint(int x, int y, int pointsize,boolean can_be_edited){
try{
decimalpoints.add(new DecimalPoint(x,y,pointsize,can_be_edited));
pointcnt++;
}
catch(Exception e){System.out.println(e);}
}
public void drawLine(int x1,int y1,int x2,int y2,Color c,String s, boolean edit , boolean is_segment){
try{
objects.add(new GridLine(x1,y1,x2,y2,c,s,edit,is_segment));
objcnt++;
}
catch(Exception e){System.out.println(e);}
}
public void actionPerformed(ActionEvent e){
String command = e.getActionCommand();
if(command.equals(clear_all)){
Clear();
deleteAllLines();
deleteAllPoints();
}
else
{
if(command.equals(line_plus)){
int[] word = findLastWordLength();
if(word[0] > 1){
drawLine(word[1]*xstep,(word[0]+1)*ystep,(word[2]+1)*xstep,(word[0]+1)*ystep,linecolor,"+",true,true);//+
}
}
else
{
if(command.equals(line_min)){
int[] word = findLastWordLength();
if(word[0] > 1){
drawLine(word[1]*xstep,(word[0]+1)*ystep,(word[2]+1)*xstep,(word[0]+1)*ystep,linecolor,"-",true,true);//+
}
}
else
{
if(command.equals(line_div)){
int[] word = findLastWordLength();
if(word[0] > 1){
drawLine(word[1]*xstep,(word[0]+1)*ystep,(word[2]+1)*xstep,(word[0]+1)*ystep,linecolor,"\u00F7",true,true);//+
}
}
else
{
if(command.equals(line_times)){
int[] word = findLastWordLength();
if(word[0] > 1){
drawLine(word[1]*xstep,(word[0]+1)*ystep,(word[2]+1)*xstep,(word[0]+1)*ystep,linecolor,"\u00D7",true,true);
}
}
else
{
if(command.equals(delete_line)){
deleteLine();
}
}
}
}
}
}
repaint();
}
public void getButtons(){
String param = getParameter("buttons");
Panel panel;
if( param != null && param.length()>0){
panel = InvulGridPanel(param);
}
else
{
panel = InvulGridPanel("none");
}
cp = getContentPane();
cp.add(panel);
}
 
public Panel InvulGridPanel(String param){
Panel panel = new Panel();
setLayout(new FlowLayout());
Button s;
if(!param.equals("none")){
StringTokenizer label = new StringTokenizer(param, ",");
int m = label.countTokens();String operator="";
String txt="";
for(int i = 0; i < m ;i++){
operator = label.nextToken();
if(operator.equals("+")) txt = line_plus;
else
if(operator.equals("-")) txt = line_min;
else
if(operator.equals(":")) txt = line_div;
else
if(operator.equals("x")) txt = line_times;
s = new Button(txt);
s.addActionListener(this);
add(s);
}
s = new Button(delete_line);
s.addActionListener(this);
add(s);
}
s = new Button(clear_all);
s.addActionListener(this);
add(s);
return panel;
}
 
public static void main(String[] args) {
run(new InvulGrid(), 300, 300);
}
 
public static void run(JApplet applet, int width, int height) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(applet);
applet.init();
applet.start();
frame.setVisible(true);
}
 
 
}
 
 
class DecimalPoint {
int x,y;
int linewidth;
boolean editable;
public DecimalPoint(int x,int y, int linewidth,boolean editable){
this.x = x;
this.y = y;
this.linewidth = linewidth;
this.editable = editable;
}
public int getX(){return x;}
public int getY(){return y;}
public int getD(){return linewidth;}
public boolean getEditable(){return editable;}
}
 
class GridLine {
int x1,y1,x2,y2;
Color color;
String txt;
boolean edit;
boolean segment;
 
public GridLine(int x1, int y1 , int x2 , int y2, Color color, String txt,boolean edit, boolean segment){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
this.txt = txt;
this.edit = edit;
this.segment = segment;
}
public int getX1() { return x1; }
public int getY1() { return y1; }
public int getX2() { return x2; }
public int getY2() { return y2; }
public Color getColor(){ return color;}
public String getText() { return txt;}
public boolean getEdit() { return edit;}
public boolean isSegment() { return segment;}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/VrijeInvulVeld/build.xml
0,0 → 1,65
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for VrijeInvulVeld.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="VrijeInvulVeld" default="jar" basedir=".">
 
<description>VrijeInvulVeld build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create VrijeInvulVeld jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/VrijeInvulVeld.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="VrijeInvulVeld"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="VrijeInvulVeld"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="VrijeInvulVeld">
<attribute name="Specification-Title" value="VrijeInvulVeld"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="VrijeInvulVeld"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/VrijeInvulVeld/test.html
0,0 → 1,35
 
<html>
<head>test vrije invulveld</head>
<body>
<script language="javascript" type="text/javascript">
function READTHIS(){
var reply=document.applets[0].ReadApplet(1);
alert("the applet will send to wims:\n"+reply);
}
</script>
<center>
<applet codebase="dist" code="VrijeInvulVeld.class" archive="VrijeInvulVeld.jar" width="640" height="480">
<param name="xsize" value="300">
<param name="ysize" value="300">
<param name="bgcolor" value="255,255,255">
<param name="textcolor" value="250,0,0">
<param name="drawcolor" value="0,250,10">
<param name="penthickness" value="2">
<param name="penfontsize" value="18">
<param name="penfontfamily" value="Helvetica">
<param name="penfontstyle" value="bold">
<param name="language" value="nl">
<param name="text" value="yes"> <!-- if 0/no no text -->
<param name="line" value="yes"> <!-- if 0/no no lines -->
<param name="rect" value="0"> <!-- if 0/no no rec -->
<param name="ellipse" value="0"> <!-- if 0/no no ellipse -->
<param name="arrow" value="0"> <!-- if 0/no no arrows -->
<param name="grid" value="yes"> <!-- will produce a grid -->
<param name="textlines" value="10"> <!-- number of lines in the applet: strings are bound to these lines leave blank or remove parma-tag to revert to original behaviour of the drawing applet -->
<param name="textalign" value="vertical"> <!-- probability tree orientation -->
</applet>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:READTHIS();">
</body>
</html>
 
/trunk/wims/src/Misc/authors/jm.evers/applets/VrijeInvulVeld/src/VrijeInvulVeld.java
0,0 → 1,1134
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
 
<html>
<head>test vrije invulveld</head>
<body>
<script language="javascript" type="text/javascript">
function READTHIS(){
var reply=document.applets[0].ReadApplet(1);
alert("the applet will send to wims:\n"+reply);
}
</script>
<center>
<applet code="VrijeInvulVeld.class" archive="VrijeInvulVeld.jar" width="640" height="480">
<param name="xsize" value="300">
<param name="ysize" value="300">
<param name="bgcolor" value="255,255,255">
<param name="textcolor" value="250,0,0">
<param name="drawcolor" value="0,250,10">
<param name="penthickness" value="2">
<param name="penfontsize" value="18">
<param name="penfontfamily" value="Helvetica">
<param name="penfontstyle" value="bold">
<param name="language" value="nl">
<param name="text" value="yes"> <!-- if 0/no no text -->
<param name="line" value="yes"> <!-- if 0/no no lines -->
<param name="rect" value="0"> <!-- if 0/no no rec -->
<param name="ellipse" value="0"> <!-- if 0/no no ellipse -->
<param name="arrow" value="0"> <!-- if 0/no no arrows -->
<param name="grid" value="yes"> <!-- will produce a grid -->
<param name="textlines" value="10"> <!-- number of lines in the applet: strings are bound to these lines leave blank or remove parma-tag to revert to original behaviour of the drawing applet -->
<param name="textalign" value="vertical"> <!-- probability tree orientation -->
</applet>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:READTHIS();">
</center>
</body>
</html>
*/
 
import java.util.*;
import java.awt.*;
import java.applet.*;
 
 
 
/* The applet itself; contains a display, a control panel and a diagram */
 
public class VrijeInvulVeld extends Applet {
Diagram diagram;
DiagramControls controls;
DiagramDisplay display;
MessageArea message;
EventConsumer current_event_consumer;
 
// jm.evers a few defaults...i'm no good at this java :(
static int xsize=640;
static int ysize=480;
static int ygrid=50;// default disabled : less than 50 "lines" of text enables the "snap to line"
static Color bgcolor=new Color(250,250,250);
static Color textcolor=new Color(255,0,0);
static Color drawcolor=new Color(150,0,250);
static float thickness=2.0f;
static int penfontsize=16;
static String fontfamily="Helvetica";
static Font penfont= new Font(fontfamily, Font.BOLD, penfontsize);
static Font messagefont= new Font(fontfamily, Font.BOLD,16);
public String t_line="Line";
public String t_arrow="Arrow";
public String t_rectangle="Rectangle";
public String t_ellipse="Ellipse";
public String t_text="Text";
public String t_circle="Circle";
public String t_destroy="Delete";
public String t_move="Move";
static String t_press="Press return to finish the text";
static boolean textalign=false; // horizontal [snap to y: sort to y] . otherwise vertical [snap to x:sort to x]
static int textcounter=0;
static int linecounter=0;
static boolean original=false;
static boolean draw_line=true;
static boolean draw_text=true;
static boolean draw_arrow=true;
static boolean draw_ellipse=true;
static boolean draw_rect=true;
 
//
public void init() {
String param;
param = getParameter("language");
if(param != null) {
if(param.equalsIgnoreCase("nl")){
t_line="lijn";
t_arrow="pijl";
t_rectangle="rechthoek";
t_ellipse="ellips";
t_text="tekst";
t_circle="cirkel";
t_destroy="wissen";
t_move="verplaatsen";
t_press="Druk op enter als de tekst klaar is";
}
if(param.equalsIgnoreCase("de")){
t_line="Linie";
t_arrow="Pfeil";
t_rectangle="Rechteck";
t_ellipse="Ellipse";
t_text="Text";
t_circle="Kreis";
t_destroy="löschen";
t_move="verlagern";
t_press="Drücken Sie auf \"Eingabe\" am Ende des Textes";
}
if(param.equalsIgnoreCase("fr")){
t_line="droite";
t_arrow="flèche";
t_rectangle="rectangle";
t_ellipse="ellips";
t_text="texte";
t_circle="cercle ";
t_destroy="effacer";
t_move="déplacer";
t_press="Press return to finish the text";
}
}
param = getParameter("line");
if(param != null){if(param.equalsIgnoreCase("no") || param.equals("0")){draw_line=false;}}
param = getParameter("rect");
if(param != null){if(param.equalsIgnoreCase("no") || param.equals("0")){draw_rect=false;}}
param = getParameter("arrow");
if(param != null){if(param.equalsIgnoreCase("no") || param.equals("0")){draw_arrow=false;}}
param = getParameter("text");
if(param != null){if(param.equalsIgnoreCase("no") || param.equals("0")){draw_text=false;}}
param = getParameter("ellipse");
if(param != null){if(param.equalsIgnoreCase("no") || param.equals("0")){draw_ellipse=false;}}
param = getParameter("penfontsize");
if(param != null) {penfontsize=Integer.parseInt(param,10); penfont= new Font("Helvetica", Font.BOLD, penfontsize);}
param = getParameter("penfontfamily");
if(param != null) {penfont= new Font(param, Font.BOLD, penfontsize);}
param = getParameter("penfontstyle");
if(param != null) {
if(param.equalsIgnoreCase("bold")){penfont= new Font(param, Font.BOLD , penfontsize);}
else if(param.equalsIgnoreCase("italic")){penfont= new Font(param, Font.ITALIC , penfontsize);}
else if(param.equalsIgnoreCase("plain")){penfont= new Font(param, Font.PLAIN , penfontsize);}
}
param = getParameter("penthickness");
if(param != null) {thickness=Float.parseFloat(param);}
param = getParameter("xsize");
if(param != null) {xsize=Integer.parseInt(param,10);}
param = getParameter("ysize");
if(param != null) {ysize=Integer.parseInt(param,10);}
param = getParameter("textlines");
if(param != null) {ygrid=Integer.parseInt(param,10);
if(ygrid>100){ygrid=100;System.out.println("100 lines max !");}
if(ygrid<0){ygrid=10;System.out.println("positive number textlines !");}
}
param = getParameter("textalign");
if(param == null || param.length()==0){original=true;}else{original=false;if(param.equalsIgnoreCase("vertical")){textalign=true;}else{textalign=false;}}
resize(xsize,ysize);
param=getParameter("bgcolor"); // Background color of inputfield "input"
if (param != null && param.length()>0){bgcolor=ReturnColor(param);}
param=getParameter("textcolor"); // Background color of inputfield "input"
if (param != null && param.length()>0){textcolor=ReturnColor(param);}
param=getParameter("drawcolor"); // Background color of inputfield "input"
if (param != null && param.length()>0){drawcolor=ReturnColor(param);}
diagram = new Diagram();
diagram.editor = this;
// no idea how to tell this class that the names are passed on as params in init...
add(controls = new DiagramControls(this ,t_line,t_arrow,t_rectangle,t_ellipse,t_text,t_circle,t_destroy,t_move));
add(display = new DiagramDisplay(this ,thickness,textcolor,drawcolor,penfont));
current_event_consumer = controls;
}
 
// jm.evers
 
public Color ReturnColor(String RGB){
int R=0;int G=0;int B=0;
RGB=RGB.replace(':',',');RGB=RGB.replace(';',',');
StringTokenizer q = new StringTokenizer(RGB, ",");
String k;int rgb;Color kleur;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R = rgb;}
else if(a == 1){G = rgb;}
else if(a == 2){B = rgb;}
}
kleur=new Color(R,G,B);
return kleur;
}
public String ReadApplet(String arg){
String reply="";
if(arg.equals("1")){
String line_analysis="";
int[] text_x=new int[textcounter];
int[] text_y=new int[textcounter];
int[] line_x1=new int[linecounter];
int[] line_y1=new int[linecounter];
int[] line_x2=new int[linecounter];
int[] line_y2=new int[linecounter];
String[] tekst=new String[textcounter];
int real_text_length=0;String tmp="";
int real_line_length=0;int x1;int x2;int y1;int y2;
for(Enumeration e = diagram.elements(); e.hasMoreElements(); ){
DiagramItem item = (DiagramItem)e.nextElement();
if(item.specify_line_x1() != -1){
x1=item.specify_line_x1();
y1=item.specify_line_y1();
x2=item.specify_line_x2();
y2=item.specify_line_y2();
if(textalign){//alleen horizontale lijnen
if( x1 != x2 && y1 == y2){// avoid line-dots to be send as lines/branches
line_x1[real_line_length] = x1;
line_y1[real_line_length] = y1;
line_x2[real_line_length] = x2;
line_y2[real_line_length] = y2;
real_line_length++;
System.out.println("een horizontale lijn "+real_line_length);
}
}
else
{
if( y1 != y2 && x1 == x2 ){// avoid line-dots to be send as lines/branches
line_x1[real_line_length] = x1;
line_y1[real_line_length] = y1;
line_x2[real_line_length] = x2;
line_y2[real_line_length] = y2;
real_line_length++;
System.out.println("een vertikale lijn "+real_line_length);
}
}
}
if(item.specify_text() != null){
tmp = item.specify_text();
// remove the forgotten '_' and we can't use komma's in the reply...replace them by points ?
tmp =replace(tmp,"_"," ");
tekst[real_text_length] =replace(tmp,",",".");
text_x[real_text_length] = item.specify_text_x();
text_y[real_text_length] = item.specify_text_y();
real_text_length++;
}
}
boolean nog_meer = true;int i=0;int s=0;int temp_x;int temp_y;String temp_txt;
String[] sameline = new String[real_text_length];
FontMetrics fm =getFontMetrics(penfont);
int hoogte = fm.getMaxAscent();
if(textalign){//horizonal probability tree
while (nog_meer) {
nog_meer = false;
for ( i=0; i<real_text_length-1; i++ ){
if ( text_y[i] < text_y[i+1] ){ sameline[i]="\n";}
if ( text_y[i] > text_y[i+1] ){
temp_y = text_y[i]; text_y[i] = text_y[i+1]; text_y[i+1] = temp_y;
temp_x = text_x[i]; text_x[i] = text_x[i+1]; text_x[i+1] = temp_x;
temp_txt = tekst[i]; tekst[i] = tekst[i+1]; tekst[i+1] = temp_txt;
nog_meer = true;
sameline[i]="\n";
}
if ( text_y[i] == text_y[i+1] ){
sameline[i]=" ";
if( text_x[i] > text_x[i+1] ){
temp_y = text_y[i]; text_y[i] = text_y[i+1]; text_y[i+1] = temp_y;
temp_x = text_x[i]; text_x[i] = text_x[i+1]; text_x[i+1] = temp_x;
temp_txt = tekst[i]; tekst[i] = tekst[i+1]; tekst[i+1] = temp_txt;
nog_meer = true;
}
}
}
}
}
else
{//vertical probability tree
while (nog_meer) {
nog_meer = false;
for ( i=0; i<real_text_length-1; i++ ){
if ( text_x[i] < text_x[i+1] ){ sameline[i]="\n";}
if ( text_x[i] > text_x[i+1] ){
temp_y = text_y[i]; text_y[i] = text_y[i+1]; text_y[i+1] = temp_y;
temp_x = text_x[i]; text_x[i] = text_x[i+1]; text_x[i+1] = temp_x;
temp_txt = tekst[i]; tekst[i] = tekst[i+1]; tekst[i+1] = temp_txt;
nog_meer = true;
sameline[i]="\n";
}
if ( text_x[i] == text_x[i+1] ){
sameline[i]=" ";
if( text_y[i] > text_y[i+1] ){
temp_y = text_y[i]; text_y[i] = text_y[i+1]; text_y[i+1] = temp_y;
temp_x = text_x[i]; text_x[i] = text_x[i+1]; text_x[i+1] = temp_x;
temp_txt = tekst[i]; tekst[i] = tekst[i+1]; tekst[i+1] = temp_txt;
nog_meer = true;
}
}
}
}
}
int wacht=0;
if(textalign){
for(i=0;i<real_line_length;i++){
y1=line_y1[i];
for(s=0;s<real_text_length;s++){
if(text_y[s]==y1 ||( text_y[s]<y1 && text_y[s]>y1-hoogte)){
wacht=s;
}
}
if(wacht!=0){
sameline[wacht]="\n line \n";
wacht=0;
}
}
}
else
{
for(i=0;i<real_line_length;i++){
x1=line_x1[i];
x2=line_x2[i];
y1=line_y1[i];
y2=line_y2[1];
if(x1<x2+hoogte && x1>x2-hoogte){
// dus een "bijna vertikale lijn
for(s=0;s<real_text_length;s++){
if(text_y[s]==y1 ||( text_y[s]<y1 && text_y[s]>y1-hoogte)){
wacht=s;
}
}
if(wacht!=0){
sameline[wacht]="\n vertikale line \n";
wacht=0;
}
}
}
}
 
for(i=0;i<real_text_length;i++){
if(sameline[i] == null){sameline[i]="\n";}
reply=reply+tekst[i]+sameline[i];
}
}
else
{
//alldata...no special sorting of the text
for(Enumeration e = diagram.elements(); e.hasMoreElements(); ){
DiagramItem item = (DiagramItem)e.nextElement();
reply=reply+item.describe()+"\n";
}
}
 
return reply;
}
// replace compatible with java 1.4 [B. Perrin-Riou]
public static String replace(String source, String pattern, String replace){
if (source!=null){
final int len = pattern.length();
StringBuffer sb = new StringBuffer();
int found = -1;
int start = 0;
while( (found = source.indexOf(pattern, start) ) != -1){
sb.append(source.substring(start, found));
sb.append(replace);
start = found + len;
}
sb.append(source.substring(start));
return sb.toString();
}
else return "";
}
 
public void start() {
}
 
public void stop() {
}
 
public void destroy() {
}
 
public static void main(String argv[]) {
/* This more-or-less replicates what happens when we are run as an applet. */
Frame f = new Frame();
VrijeInvulVeld d = new VrijeInvulVeld();
d.init();
d.start();
f.add("Center", d);
f.show();
}
}
/* end applet */
 
 
 
/* The diagram */
 
class Diagram extends Vector {
VrijeInvulVeld editor;
DiagramItem nearby(int x, int y){
DiagramItem bestitem = null;
double bestdist = 6;
for(Enumeration e = elements(); e.hasMoreElements(); ) {
DiagramItem item = (DiagramItem)e.nextElement();
double dist = item.distance(x, y);
if(dist < bestdist) {
bestitem = item;
bestdist = dist;
}
}
return bestitem;
}
}
 
 
/* The drawing area */
 
class DiagramDisplay extends Canvas {
VrijeInvulVeld editor;
DiagramDisplay(VrijeInvulVeld ed , float thickness,Color textcolor,Color drawcolor, Font penfont){
editor = ed;
setBackground(VrijeInvulVeld.bgcolor);
resize(VrijeInvulVeld.xsize,VrijeInvulVeld.ysize);
}
 
 
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setFont(VrijeInvulVeld.penfont);
g2.setStroke( new BasicStroke(VrijeInvulVeld.thickness));
g2.setColor(VrijeInvulVeld.drawcolor);
for(Enumeration e = editor.diagram.elements(); e.hasMoreElements(); ) {
((DiagramItem)e.nextElement()).draw(g2);
}
}
 
public boolean mouseDown(Event e, int x, int y){
if(editor.current_event_consumer.down(x, y)){
repaint();
return true;
}
else
{
return false;
}
}
 
public boolean mouseUp(Event e, int x, int y){
if(editor.current_event_consumer.up(x, y)){
repaint();
return true;
}
else
{
return false;
}
}
 
public boolean mouseDrag(Event e, int x, int y){
if(editor.current_event_consumer.drag(x, y)){
repaint();
return true;
}
else
{
return false;
}
}
 
public boolean keyDown(Event e, int key){
if(editor.current_event_consumer.key(key)){
repaint();
return true;
}
else
{
return false;
}
}
}
 
/* The control panel and the diagram items do things in response to input */
 
interface EventConsumer {
public boolean down(int x, int y);
public boolean up(int x, int y);
public boolean drag(int x, int y);
public boolean key(int key);
public void yield();
}
 
/* The control panel */
 
class DiagramControls extends Panel implements EventConsumer {
VrijeInvulVeld editor;
CheckboxGroup buttons;
Checkbox line, arrow, rect, ellipse, text, destroy, move;
final int CREATE = 0, DESTROY = 1, MOVE = 2;
 
DiagramControls( VrijeInvulVeld ed ,String t_line,String t_arrow,String t_rectangle,String t_ellipse,String t_text,String t_circle,String t_destroy,String t_move) {
editor = ed;
setBackground(Color.white);
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
Component button;
setLayout(gridbag);
buttons = new CheckboxGroup();
c.gridy = 0;
c.gridx = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.anchor = GridBagConstraints.CENTER;
if(VrijeInvulVeld.draw_text){
button = new DiagramControl(this, CREATE, (new Text()).getClass(), t_text , true);
gridbag.setConstraints(button, c);add(button);c.gridx++;
}
if(VrijeInvulVeld.draw_line){
button = new DiagramControl(this, CREATE, (new Line()).getClass(), t_line , false);
gridbag.setConstraints(button, c);add(button);c.gridx++;
}
if(VrijeInvulVeld.draw_arrow){
button = new DiagramControl(this, CREATE, (new Arrow()).getClass(), t_arrow , false);
gridbag.setConstraints(button, c);add(button);c.gridx++;
}
if(VrijeInvulVeld.draw_rect){
button = new DiagramControl(this, CREATE, (new Rect()).getClass(), t_rectangle, false);
gridbag.setConstraints(button, c);add(button);c.gridx++;
}
if(VrijeInvulVeld.draw_ellipse){
button = new DiagramControl(this, CREATE, (new Ellipse()).getClass(), t_ellipse , false);
gridbag.setConstraints(button, c);add(button);c.gridx++;
}
button = new DiagramControl(this, MOVE, (new Object()).getClass(), t_move , false);
gridbag.setConstraints(button, c);
add(button);
c.gridx++;
button = new DiagramControl(this, DESTROY, (new Object()).getClass(), t_destroy , false);
gridbag.setConstraints(button, c);
add(button);
 
}
public boolean down(int x, int y) {
DiagramControl current_button = (DiagramControl)buttons.getCurrent();
DiagramItem target;
Diagram diagram = editor.diagram;
editor.showStatus("");
switch(current_button.mode) {
case CREATE:
try {
Class class_ = current_button.class_;
target = (DiagramItem)class_.newInstance();
target.diagram = diagram;
target.create();
editor.current_event_consumer = target;
diagram.addElement(target);
target.down(x, y);
}
catch (InstantiationException ex) {}
catch (IllegalAccessException ex) {}
return true;
case DESTROY:
target = diagram.nearby(x, y);
if(target != null) {diagram.removeElement(target);target.destroy();}
return true;
case MOVE:
target = diagram.nearby(x, y);
if(target != null) {target.move();editor.current_event_consumer = target;target.down(x, y);}
return false;
default:
return false;
}
}
 
public boolean up(int x, int y) {
return false;
}
 
public boolean drag(int x, int y) {
return false;
}
 
public boolean key(int key) {
return false;
}
 
public boolean keyDown(Event e, int key) {
/* For some reason we get the canvas key presses. Pass them on XXX */
return editor.display.keyDown(e, key);
}
 
public void yield() {}
}
 
/* The buttons in the control panel */
 
class DiagramControl extends Checkbox {
int mode;
Class class_;
DiagramControl(DiagramControls parent, int _mode, Class _class, String label, boolean state) {
super(label, parent.buttons, state);
mode = _mode;
class_ = _class;
}
}
 
 
/* The diagram items.
* The methods implemented here are suitable for shapes defined by two
* points (ends of a line, corners of an ellipse's bounding box). Other
* shapes should override. Maybe I should use a subclass for this, but
* some of the methods may be useful for other shapes (text could use
* these methods for moving but not creating; it would be nice to store the
* state just by switching the methods).
*/
 
abstract class DiagramItem implements EventConsumer {
Diagram diagram;
int state;
final int NONE=0, CREATE=1, MOVE=2;
int x, y, w, h;
int movex, movey;
DiagramItem() {
x = y = w = h = 0;
}
 
DiagramItem(StringTokenizer tok) throws Exception {
if(tok.countTokens() != 4)
throw new IllegalArgumentException();
x = (new Integer(tok.nextToken())).intValue();
y = (new Integer(tok.nextToken())).intValue();
w = (new Integer(tok.nextToken())).intValue();
h = (new Integer(tok.nextToken())).intValue();
}
 
abstract void draw(Graphics g);
abstract String describe();
abstract String specify_text();
abstract int specify_text_x();
abstract int specify_text_y();
abstract int specify_line_x1();
abstract int specify_line_y1();
abstract int specify_line_x2();
abstract int specify_line_y2();
 
void create() {
state = CREATE;
}
 
public void yield() {
diagram.editor.current_event_consumer = diagram.editor.controls;
state = NONE;
}
 
void destroy() {}
 
void move() {
state = MOVE;
}
 
public boolean down(int _x, int _y) {
switch(state){
case CREATE:
x = _x; y = _y;
return true;
case MOVE:
movex = _x; movey = _y;
return true;
}
return false;
}
 
public boolean up(int _x, int _y) {
switch(state){
case CREATE:
w = _x - x; h = _y - y;
yield();
return true;
case MOVE:
x += (_x - movex);
y += (_y - movey);
yield();
return true;
}
return false;
}
 
public boolean drag(int _x, int _y) {
switch(state){
case CREATE:
w = _x - x; h = _y - y;
return true;
case MOVE:
x += (_x - movex);
y += (_y - movey);
movex = _x;
movey = _y;
return true;
}
return false;
}
 
public boolean key(int key) {
return false;
}
 
abstract double distance(int x, int y);
}
 
class Ellipse extends DiagramItem {
Ellipse(){super();}
Ellipse(StringTokenizer tok) throws Exception {super(tok);}
String describe() {return "ellipse," + x + "," + y + "," + w + "," + h;}
String specify_text() {return null; }
int specify_text_x() {return -1; }
int specify_text_y() {return -1; }
int specify_line_x1(){return -1;}
int specify_line_y1(){return -1;}
int specify_line_x2(){return -1;}
int specify_line_y2(){return -1;}
void draw(Graphics g) {
g.drawOval(x, y, w, h);
}
double distance(int _x, int _y) {
/* Do this better! */
float ww = w < 1 ? 1 : w, hh = h < 1 ? 1 : h;
float yscale = ww/hh;
float xx = _x - (x + ww / 2);
float yy = (_y - (y + hh / 2)) * yscale;
double r = Math.sqrt(xx * xx + yy * yy);
return Math.abs(r - ww / 2);
}
}
 
/* The class name Rectangle is already taken :-( */
 
class Rect extends DiagramItem {
Rect(){super();}
Rect(StringTokenizer tok) throws Exception { super(tok);}
 
String describe() {return "rectangle," + x + "," + y + "," + (x+w) + "," + (y+h);}
String specify_text() {return null; }
int specify_text_x() {return -1; }
int specify_text_y() {return -1; }
int specify_line_x1(){return -1;}
int specify_line_y1(){return -1;}
int specify_line_x2(){return -1;}
int specify_line_y2(){return -1;}
 
void draw(Graphics g) {
g.drawLine(x , y , x+w, y );
g.drawLine(x+w, y , x+w, y+h);
g.drawLine(x+w, y+h, x , y+h);
g.drawLine(x , y+h, x , y );
}
 
double distance(int _x, int _y) {
double dtop, dbottom, dleft, dright, dist;
if(_x < x){
dtop = Misc.distance(_x, _y, x, y);
}
else
{
if(_x > x+w){
dtop = Misc.distance(_x, _y, x+w, y);
}
else
{
dtop = Math.abs(_y - y);
}
}
if(_x < x){
dbottom = Misc.distance(_x, _y, x, y+h);
}
else
{
if(_x > x+w){
dbottom = Misc.distance(_x, _y, x+w, y+h);
}
else
{
dbottom = Math.abs(_y - (y+h));
}
}
if(_y < y)
dleft = Misc.distance(_x, _y, x, y);
else if(_y > y+h)
dleft = Misc.distance(_x, _y, x, y+h);
else
dleft = Math.abs(_x - x);
if(_y < y)
dright = Misc.distance(_x, _y, x+w, y);
else if(_y > y+h)
dright = Misc.distance(_x, _y, x+w, y+h);
else
dright = Math.abs(_x - (x+w));
 
dist = dtop;
if(dbottom < dist){dist = dbottom;}
if(dleft < dist){dist = dleft;}
if(dright < dist){dist = dright;}
return dist;
}
}
 
class Line extends DiagramItem {
Line() {super();}
Line(StringTokenizer tok) throws Exception {super(tok);}
void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
if(!VrijeInvulVeld.original){
int dy=(int) VrijeInvulVeld.ysize / VrijeInvulVeld.ygrid;
int dx=(int) VrijeInvulVeld.xsize / VrijeInvulVeld.ygrid;
if(state != 2){
y=dy*((int) Math.round(y/dy));
h=dy*((int) Math.round(h/dy));
}
if(state == 1 || state == 2){
g2.setColor(VrijeInvulVeld.textcolor);
g2.setStroke( new BasicStroke(1.0f));
if(VrijeInvulVeld.textalign){
for(int p=0;p<VrijeInvulVeld.ysize;p=p+dy){
g2.drawLine(0,p,VrijeInvulVeld.xsize,p);
}
}
else
{
for(int p=0;p<VrijeInvulVeld.xsize;p=p+dx){
g2.drawLine(p,0,p,VrijeInvulVeld.ysize);
}
}
}
}
g2.setColor(VrijeInvulVeld.drawcolor);
g2.setStroke( new BasicStroke(VrijeInvulVeld.thickness));
g2.drawLine(x, y, x+w, y+h);
VrijeInvulVeld.linecounter++;
}
String describe() {return "line," + x + "," + y + "," + (x+w) + "," + (y+h);}
String specify_text() {return null; }
int specify_text_x(){return -1; }
int specify_text_y(){return -1; }
int specify_line_x1(){return x;}
int specify_line_y1(){return y;}
int specify_line_x2(){return (x+w);}
int specify_line_y2(){return (y+h);}
 
double distance(int _x, int _y) {
if(w == 0 && h == 0)
return Misc.distance(x, y, _x, _y);
/* Set origin to end of line */
_x -= x;
_y -= y;
/* Find line length and unit vector along line */
double len = Math.sqrt(w*w + h*h);
double u = w / len;
double v = h / len;
/* Find nearest point on line using dot product */
double r = _x * u + _y * v;
if(r < 0)
return Misc.distance(0, 0, _x, _y);
if(r > len)
return Misc.distance(w, h, _x, _y);
return Misc.distance(r * u, r * v, _x, _y);
}
}
 
class Arrow extends Line {
Arrow(){super();}
Arrow(StringTokenizer tok) throws Exception { super(tok);}
void draw(Graphics g) {
/* Draw a line */
Graphics2D g2 = (Graphics2D) g;
if(!VrijeInvulVeld.original){
int dy=(int) VrijeInvulVeld.ysize / VrijeInvulVeld.ygrid;
int dx=(int) VrijeInvulVeld.xsize / VrijeInvulVeld.ygrid;
if( state != 2){
y=dy*((int) Math.round(y/dy));
h=dy*((int) Math.round(h/dy));
}
if(state == 1 || state == 2){
g2.setColor(VrijeInvulVeld.textcolor);
g2.setStroke( new BasicStroke(1.0f));
if(VrijeInvulVeld.textalign){
for(int p=0;p<VrijeInvulVeld.ysize;p=p+dy){
g2.drawLine(0,p,VrijeInvulVeld.xsize,p);
}
}
else
{
for(int p=0;p<VrijeInvulVeld.xsize;p=p+dx){
g2.drawLine(p,0,p,VrijeInvulVeld.ysize);
}
}
}
}
VrijeInvulVeld.linecounter++;
g2.setColor(VrijeInvulVeld.drawcolor);
g2.setStroke( new BasicStroke(VrijeInvulVeld.thickness));
g2.drawLine(x, y, x+w, y+h);
if(w == 0 && h == 0){return;}
/* Find unit vector along line */
double len = Math.sqrt(w*w + h*h);
double u = w / len;
double v = h / len;
 
/* Draw arrow head */
double _x = x + w - 5 * u;
double _y = y + h - 5 * v;
g2.drawLine(x+w, y+h, (int)(_x - 5 * v + 0.5), (int)(_y + 5 * u + 0.5));
g2.drawLine(x+w, y+h, (int)(_x + 5 * v + 0.5), (int)(_y - 5 * u + 0.5));
}
String describe() {return "arrow," + x + "," + y + "," + (x+w) + "," +(y+h);}
String specify_text() {return null; }
int specify_text_x() {return -1; }
int specify_text_y() {return -1; }
int specify_line_x1(){return x;}
int specify_line_y1(){return y;}
int specify_line_x2(){return (x+w);}
int specify_line_y2(){return (y+h);}
 
}
 
class Text extends DiagramItem {
String text;
StringBuffer buffer;
Text() {
x = y = 0;
buffer = new StringBuffer();
text = buffer.toString().concat("_");
}
 
Text(StringTokenizer tok) throws Exception {
if(tok.countTokens() < 1){throw new IllegalArgumentException();}
x = (new Integer(tok.nextToken())).intValue();
y = (new Integer(tok.nextToken())).intValue();
text = tok.nextToken("\n\r").trim();
 
}
 
void create() {
super.create();
diagram.editor.controls.disable();
//diagram.editor.showStatus("Press return to finish string");
diagram.editor.showStatus(VrijeInvulVeld.t_press);
VrijeInvulVeld.textcounter++;
}
 
public void yield() {
super.yield();
diagram.editor.controls.enable();
text = buffer.toString();
}
 
String describe() {
return "text," + x + "," + y + "," + text;
}
String specify_text() {return text; }
int specify_text_x() {return x; }
int specify_text_y() {return y; }
int specify_line_x1(){return -1;}
int specify_line_y1(){return -1;}
int specify_line_x2(){return -1;}
int specify_line_y2(){return -1;}
 
void draw(Graphics g) {
//jm.evers
if(!VrijeInvulVeld.original){
Graphics2D g2 = (Graphics2D) g;
int dy=(int) VrijeInvulVeld.ysize / VrijeInvulVeld.ygrid;
int dx=(int) VrijeInvulVeld.xsize / VrijeInvulVeld.ygrid;
if(state == 1 || state == 2){//show a temp grid lines
g2.setColor(VrijeInvulVeld.drawcolor);
g2.setStroke( new BasicStroke(1.0f));
if(VrijeInvulVeld.textalign){for(int p=0;p<VrijeInvulVeld.ysize;p=p+dy){g2.drawLine(0,p,VrijeInvulVeld.xsize,p);}}
else{for(int p=0;p<VrijeInvulVeld.xsize;p=p+dx){g2.drawLine(p,0,p,VrijeInvulVeld.ysize);}}
g2.setFont(VrijeInvulVeld.penfont);
}
else
{
g2.setFont(VrijeInvulVeld.penfont);
}
if(state != 2){ // not while dragging
if(VrijeInvulVeld.ygrid<50 && VrijeInvulVeld.ygrid>1){
if(VrijeInvulVeld.textalign){// then snap to the nearest vertical line...
y=dy*((int) (Math.round(y/dy)));
if(y<dy){y=dy;}
if(y>VrijeInvulVeld.ysize-dy){y=VrijeInvulVeld.ysize-dy;}
}
else
{//snap to the nearest horizontal line...
x=dx*((int) (Math.round(x/dx)));
if(x<dx){x=dx;}
if(x>VrijeInvulVeld.xsize-dx){x=VrijeInvulVeld.xsize-dx;}
}
}
}
g2.setColor(VrijeInvulVeld.textcolor);
g2.setStroke( new BasicStroke(VrijeInvulVeld.thickness));
g2.drawString(text, x, y);
g2.setColor(VrijeInvulVeld.drawcolor);
}
else
{
g.drawString(text, x, y);
}
}
double distance(int _x, int _y) {
FontMetrics fm = diagram.editor.display.getGraphics().getFontMetrics();
int m = y - (fm.getAscent() / 2);
if(_x < x){return Misc.distance(x, m, _x, _y);}
int r = x + fm.stringWidth(text);
if(_x > r){return Misc.distance(r, m, _x, _y);}
return Math.abs(_y - m);
}
 
public boolean down(int _x, int _y) {
switch(state) {
case CREATE:
x = _x; y = _y;
return true;
case MOVE:
return super.down(_x, _y);
}
return false;
}
 
public boolean up(int _x, int _y) {
switch(state) {
case CREATE:
x = _x; y = _y;
return true;
case MOVE:
return super.up(_x, _y);
}
return false;
}
 
public boolean drag(int _x, int _y) {
switch(state) {
case CREATE:
x = _x; y = _y;
return true;
case MOVE:
return super.drag(_x, _y);
}
return false;
}
 
public boolean key(int key) {
char c[] = new char[1];
switch(state) {
case CREATE:
switch(key) {
case 10:/* LF */
 
case 13:/* CR */
yield();
if(text.equals("")){
diagram.removeElement(this);
destroy();
diagram.editor.showStatus("String was empty");
}
else
diagram.editor.showStatus("");
return true;
case 8:/* BS */
case 127:/* DEL */
int l = buffer.length();
if(l > 0)
buffer.setLength(l - 1);
break;
default:
buffer.append((char)key);
break;
}
text = buffer.toString().concat("_");
return true;
}
return false;
}
}
 
/* An area for displaying messages */
 
class MessageArea extends Canvas {
String text = "";
void setText(String s) {
text = s;
repaint();
}
 
public void paint(Graphics g) {
setBackground(VrijeInvulVeld.bgcolor);
//g.setFont(VrijeInvulVeld.messagefont);
g.drawString(text,5,20);
}
}
 
 
/* Handy functions */
 
class Misc {
static double distance(double x1, double y1, double x2, double y2) {
return Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/1.html
0,0 → 1,30
 
<html>
<head></head>
<body>
<script language="javascript" type="text/javascript">
function READTHIS(){
var input=document.applets[0].ReadApplet();
if(input.indexOf("error")!=-1){
alert(input);
}
else
{
alert("the applet will send:\n"+input);
}
}
</script>
<center>
<applet code="GetallenLijn.class" codebase="dist" archive="GetallenLijn.jar" width="600" height="240">
<param name="xmax" value="150">
<param name="fontsize" value="36">
<param name="join" value="yes"> <!-- append arrows? if "no" all arrows start in 0 -->
<param name="exercise" value=""><!-- could be something like: + 1 -3*-5 + -4= -->
<param name="language" value="nl">
<param name="pencolor" value="10,3,2"> <!-- input foreground color -->
<param name="bgcolor1" value="200,250,255"> <!-- input background color -->
<param name="bgcolor2" value="245,255,255"> <!-- canvas background color -->
</applet>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:READTHIS();">
</body>
</html>
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/DoubleStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class DoubleStack {
private double[] data = new double[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(double b) {
if (size >= data.length) {
double[] newData = new double[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
double[] toArray() {
double[] trimmed = new double[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/DeclarationParser.java
0,0 → 1,88
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Vector;
 
class DeclarationParser extends TokenConsumer {
static final String NO_ARGS[] = new String[0];
static final int UNKNOWN_ARITY = -2;
static final int MAX_ARITY = 5;
String name;
int arity = UNKNOWN_ARITY;
Vector args = new Vector();
 
private SyntaxException exception;
 
DeclarationParser(SyntaxException e) {
this.exception = e;
}
 
//@Override
void start() {
name = null;
args.setSize(0);
}
 
//@Override
void push(Token token) throws SyntaxException {
switch (token.id) {
case Lexer.CALL:
if (name == null) {
name = token.name;
arity = 0;
} else {
throw exception.set("repeated CALL in declaration", token.position);
}
break;
 
case Lexer.CONST:
if (name == null) {
name = token.name;
arity = UNKNOWN_ARITY;
} else if (arity >= 0) {
args.addElement(token.name);
++arity;
if (arity > MAX_ARITY) {
throw exception.set("Arity too large " + arity, token.position);
}
} else {
throw exception.set("Invalid declaration", token.position);
}
break;
 
case Lexer.RPAREN:
case Lexer.COMMA:
case Lexer.END:
break;
 
default:
throw exception.set("invalid token in declaration", token.position);
}
}
String[] argNames() {
if (arity > 0) {
String argNames[] = new String[arity];
args.copyInto(argNames);
return argNames;
} else {
return NO_ARGS;
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/CompiledFunction.java
0,0 → 1,253
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Random;
 
class CompiledFunction extends Function {
//static final int INI_STACK_SIZE = 16;
static final int MAX_STACK_SIZE = 128; //if stack ever grows above this likely something is wrong
private static Random random = new Random();
 
private double consts[];
private Function funcs[];
private byte code[];
private int arity; // >= 0
 
private static final ThreadLocal stacks = new ThreadLocal();
 
CompiledFunction(int arity, byte[] code, double[] consts, Function funcs[]) {
init(arity, code, consts, funcs);
}
 
/* This empty constructor is used only by SimpleCodeGen,
which calls init() explicitly later.
*/
CompiledFunction() {
init(0, null, null, null);
}
 
void init(int arity, byte[] code, double[] consts, Function funcs[]) {
this.arity = arity;
this.code = code;
this.consts = consts;
this.funcs = funcs;
}
 
public int arity() {
return arity;
}
 
public String toString() {
StringBuffer buf = new StringBuffer();
int cpos = 0, fpos = 0;
if (arity != 0) {
buf.append("arity ").append(arity).append("; ");
}
for (int i = 0; i < code.length; ++i) {
byte op = code[i];
buf.append(VM.opcodeName[op]);
if (op == VM.CONST) {
buf.append(' ').append(consts[cpos++]);
} else if (op == VM.CALL) {
++fpos;
//buf.append(" {").append(funcs[fpos++].toString()).append('}');
}
buf.append("; ");
}
if (cpos != consts.length) {
buf.append("\nuses only ").append(cpos).append(" consts out of ").append(consts.length);
}
if (fpos != funcs.length) {
buf.append("\nuses only ").append(fpos).append(" funcs out of ").append(funcs.length);
}
return buf.toString();
}
 
private void checkArity(int nArgs) throws ArityException {
if (arity() != nArgs) {
throw new ArityException("Expected " + arity() + " arguments, got " + nArgs);
}
}
 
private double[] getStack() {
double stack[];
if ((stack = (double[]) stacks.get()) == null) {
stacks.set(stack = new double[MAX_STACK_SIZE]);
}
return stack;
}
static final double NO_ARGS[] = new double[0];
public double eval() throws ArityException {
return eval(NO_ARGS);
}
 
public double eval(double x) throws ArityException {
checkArity(1);
double stack[] = getStack();
stack[0] = x;
exec(stack, 0);
return stack[0];
}
 
public double eval(double x, double y) throws ArityException {
checkArity(2);
double stack[] = getStack();
stack[0] = x;
stack[1] = y;
exec(stack, 1);
return stack[0];
}
 
public double eval(double args[]) throws ArityException {
checkArity(args.length);
double stack[] = getStack();
if (args.length > 0) {
System.arraycopy(args, 0, stack, 0, args.length);
}
exec(stack, args.length - 1);
return stack[0];
}
 
void exec(double s[], int p) {
int finalP = execWithoutCheck(s, p);
int expected = p - arity + 1;
if (finalP != expected) {
throw new Error("stack pointer after exec: expected " +
expected + ", got " + finalP);
}
}
int execWithoutCheck(double s[], int p) {
byte[] code = this.code;
int initialSP = p;
int constp = 0;
int funp = 0;
final double angleFactor = 1; // 1/Calc.cfg.trigFactor;
// arguments, read from stack on exec entry
// we don't use an array in order to avoid the dynamic allocation (new)
// @see Compiler.MAX_ARITY
double a0, a1, a2, a3, a4;
a0 = a1 = a2 = a3 = a4 = Double.NaN;
switch (arity) {
case 5: a4 = s[p--];
case 4: a3 = s[p--];
case 3: a2 = s[p--];
case 2: a1 = s[p--];
case 1: a0 = s[p--];
}
 
//int expectedExitSP = p+1;
int codeLen = code.length;
for (int pc = 0; pc < codeLen; ++pc) {
switch (code[pc]) {
case VM.CONST: s[++p] = consts[constp++]; break;
case VM.CALL: {
Function f = funcs[funp++];
if (f instanceof CompiledFunction) {
p = ((CompiledFunction) f).execWithoutCheck(s, p);
} else {
int arity = f.arity();
p -= arity;
try {
double result;
switch (arity) {
case 0:
result = f.eval();
break;
case 1:
result = f.eval(s[p+1]);
break;
case 2:
result = f.eval(s[p+1], s[p+2]);
break;
default:
double args[] = new double[arity];
System.arraycopy(s, p+1, args, 0, arity);
result = f.eval(args);
}
s[++p] = result;
} catch (ArityException e) {
throw new Error(""+e); //never
}
}
break;
}
case VM.RND: s[++p] = random.nextDouble(); break;
case VM.ADD: s[--p] += s[p+1]; break;
case VM.SUB: s[--p] -= s[p+1]; break;
case VM.MUL: s[--p] *= s[p+1]; break;
case VM.DIV: s[--p] /= s[p+1]; break;
case VM.MOD: s[--p] %= s[p+1]; break;
case VM.POWER: s[--p] = MoreMath.pow(s[p], s[p+1]); break;
case VM.UMIN: s[p] = -s[p]; break;
case VM.FACT: s[p] = MoreMath.factorial(s[p]); break;
case VM.SIN: s[p] = Math.sin(s[p] * angleFactor); break;
case VM.COS: s[p] = Math.cos(s[p] * angleFactor); break;
case VM.TAN: s[p] = Math.tan(s[p] * angleFactor); break;
case VM.ASIN: s[p] = MoreMath.asin(s[p]) / angleFactor; break;
case VM.ACOS: s[p] = MoreMath.acos(s[p]) / angleFactor; break;
case VM.ATAN: s[p] = MoreMath.atan(s[p]) / angleFactor; break;
case VM.EXP: s[p] = MoreMath.exp(s[p]); break;
case VM.LOG: s[p] = MoreMath.log(s[p]); break;
case VM.SQRT: s[p] = Math.sqrt(s[p]); break;
case VM.CBRT: s[p] = MoreMath.cbrt(s[p]); break;
case VM.SINH: s[p] = MoreMath.sinh(s[p]); break;
case VM.COSH: s[p] = MoreMath.cosh(s[p]); break;
case VM.TANH: s[p] = MoreMath.tanh(s[p]); break;
case VM.ASINH: s[p] = MoreMath.asinh(s[p]); break;
case VM.ACOSH: s[p] = MoreMath.acosh(s[p]); break;
case VM.ATANH: s[p] = MoreMath.atanh(s[p]); break;
case VM.ABS: s[p] = Math.abs(s[p]); break;
case VM.FLOOR: s[p] = Math.floor(s[p]); break;
case VM.CEIL: s[p] = Math.ceil(s[p]); break;
case VM.SIGN: s[p] = s[p] > 0 ? 1 : s[p] < 0 ? -1 : 0; break;
case VM.MIN: s[--p] = Math.min(s[p], s[p+1]); break;
case VM.MAX: s[--p] = Math.min(s[p], s[p+1]); break;
case VM.GCD: s[--p] = MoreMath.gcd(s[p], s[p+1]); break;
case VM.COMB: s[--p] = MoreMath.comb(s[p], s[p+1]); break;
case VM.PERM: s[--p] = MoreMath.perm(s[p], s[p+1]); break;
case VM.LOAD0: s[++p] = a0; break;
case VM.LOAD1: s[++p] = a1; break;
case VM.LOAD2: s[++p] = a2; break;
case VM.LOAD3: s[++p] = a3; break;
case VM.LOAD4: s[++p] = a4; break;
default:
throw new Error("Unknown opcode " + code[pc]);
}
}
return p;
/*
if (p != expectedExitSP) {
throw new Error("stack pointer after exec: expected " + expectedExitSP +
" , got " + p);
}
*/
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Symbol.java
0,0 → 1,66
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Symbol {
static final int CONST_ARITY = -3;
 
private String name;
private int arity;
 
byte op;
Function fun;
double value = 0;
 
Symbol(String name, int arity, byte op) {
setKey(name, arity);
this.op = op;
}
 
Symbol(String name, Function fun) {
setKey(name, fun.arity());
this.fun = fun;
}
 
Symbol(String name, double value) {
setKey(name, CONST_ARITY);
this.value = value;
}
 
static Symbol newEmpty(Symbol s) {
return new Symbol(s.name, s.arity, (byte)0);
}
 
boolean isEmpty() {
return op == 0 && fun == null && value == 0;
}
 
Symbol setKey(String name, int arity) {
this.name = name;
this.arity = arity;
return this;
}
 
public boolean equals(Object other) {
Symbol symbol = (Symbol) other;
return name.equals(symbol.name) && arity == symbol.arity;
}
 
public int hashCode() {
return name.hashCode() + arity;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/SyntaxException.java
0,0 → 1,50
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Thrown when the expression can't be compiled, because it's either not
well-formed (e.g. "1+"), or because some simbols aren't defined (e.g. "foo+2").
*/
public class SyntaxException extends Exception {
/**
The expression which caused the error.
*/
public String expression;
 
/**
Explicative message (cause of error).
*/
public String message;
 
/**
The position inside expression where the error occured.
*/
public int position;
 
public String toString() {
return "SyntaxException: " + message
+ " in '" + expression
+ "' at position " + position;
}
 
SyntaxException set(String str, int pos) {
message = str;
position = pos;
return this;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/ArityException.java
0,0 → 1,28
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Thrown when a {@link Function} is evaluated with a wrong number of arguments
(when the number of arguments is not equal to the function's arity).
*/
 
public class ArityException extends Exception {
public ArityException(String mes) {
super(mes);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/FunctionAndName.java
0,0 → 1,32
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
This class is needed because we want to return both a function and its name.
(work-around for java not supporting multi-value return)
*/
 
public class FunctionAndName {
public Function function;
public String name;
 
public FunctionAndName(Function fun, String name) {
this.function = fun;
this.name = name;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Compiler.java
0,0 → 1,76
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Compiles a textual arithmetic expression to a {@link Function}.<p>
*/
class Compiler {
private final SyntaxException exception = new SyntaxException();
private final Lexer lexer = new Lexer(exception);
private final RPN rpn = new RPN(exception);
private final DeclarationParser declParser = new DeclarationParser(exception);
private final OptCodeGen codeGen = new OptCodeGen(exception);
private final SimpleCodeGen simpleCodeGen = new SimpleCodeGen(exception);
private final Declaration decl = new Declaration();
 
double eval(Symbols symbols, String expression) throws SyntaxException {
rpn.setConsumer(simpleCodeGen.setSymbols(symbols));
lexer.scan(expression, rpn);
return simpleCodeGen.getValue();
}
 
FunctionAndName compile(Symbols symbols, String source) throws SyntaxException {
Function fun = null;
decl.parse(source, lexer, declParser);
if (decl.arity == DeclarationParser.UNKNOWN_ARITY) {
try {
double value = eval(symbols, decl.expression);
fun = new Constant(value);
} catch (SyntaxException e) {
if (e != SimpleCodeGen.HAS_ARGUMENTS) {
throw e;
}
// fall-through (see below)
}
}
if (fun == null) { // either decl.arity was set, or an ArityException happened above
symbols.pushFrame();
symbols.addArguments(decl.args);
try {
rpn.setConsumer(codeGen.setSymbols(symbols));
lexer.scan(decl.expression, rpn);
} finally {
symbols.popFrame();
}
int arity = decl.arity;
if (arity == DeclarationParser.UNKNOWN_ARITY) {
arity = codeGen.intrinsicArity;
}
fun = codeGen.getFun(arity);
 
/*
if (decl.name != null && addDefinition) {
symbols.addDefinition(decl.name, fun, decl.arity==DeclarationParser.UNKNOWN_ARITY);
}
*/
}
 
return new FunctionAndName(fun, decl.name);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/FunctionStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class FunctionStack {
private Function[] data = new Function[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(Function b) {
if (size >= data.length) {
Function[] newData = new Function[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
Function[] toArray() {
Function[] trimmed = new Function[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/MoreMath.java
0,0 → 1,183
/*
* Copyright (C) 2006-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
 
package org.javia.arity;
 
class MoreMath extends BaseMath {
private static final double LOG2E = 1.4426950408889634074;
 
public static final double asinh(double x) {
return (x < 0) ? -asinh(-x) : log(x + x + 1/(Math.sqrt(x*x + 1) + x));
}
public static final double acosh(double x) {
return log(x + x - 1/(Math.sqrt(x*x - 1) + x));
}
 
public static final double atanh(double x) {
return (x < 0) ? -atanh(-x) : 0.5 * log(1. + (x + x)/(1 - x));
}
 
public static final double trunc(double x) {
return x >= 0 ? Math.floor(x) : Math.ceil(x);
}
 
public static final double gcd(double x, double y) {
//double remainder = y;
if (Double.isNaN(x) || Double.isNaN(y) ||
Double.isInfinite(x) || Double.isInfinite(y)) {
return Double.NaN;
}
x = Math.abs(x);
y = Math.abs(y);
double save;
while (y > 1e-12) {
save = y;
y = x % y;
x = save;
//Log.log(y);
}
return x > 1e-10 ? x : 0;
}
public static final double lgamma(double x) {
double tmp = x + 5.2421875; //== 607/128. + .5;
return 0.9189385332046727418 //LN_SQRT2PI, ln(sqrt(2*pi))
+ log(
0.99999999999999709182 +
57.156235665862923517 / ++x +
-59.597960355475491248 / ++x +
14.136097974741747174 / ++x +
-0.49191381609762019978 / ++x +
.33994649984811888699e-4 / ++x +
.46523628927048575665e-4 / ++x +
-.98374475304879564677e-4 / ++x +
.15808870322491248884e-3 / ++x +
-.21026444172410488319e-3 / ++x +
.21743961811521264320e-3 / ++x +
-.16431810653676389022e-3 / ++x +
.84418223983852743293e-4 / ++x +
-.26190838401581408670e-4 / ++x +
.36899182659531622704e-5 / ++x
)
+ (tmp-4.7421875)*log(tmp) - tmp
;
}
 
static final double FACT[] = {
1.0,
40320.0,
2.0922789888E13,
6.204484017332394E23,
2.631308369336935E35,
8.159152832478977E47,
1.2413915592536073E61,
7.109985878048635E74,
1.2688693218588417E89,
6.1234458376886085E103,
7.156945704626381E118,
1.8548264225739844E134,
9.916779348709496E149,
1.0299016745145628E166,
1.974506857221074E182,
6.689502913449127E198,
3.856204823625804E215,
3.659042881952549E232,
5.5502938327393044E249,
1.3113358856834524E267,
4.7147236359920616E284,
2.5260757449731984E302,
};
 
public static final double factorial(double x) {
if (x < 0) { // x <= -1 ?
return Double.NaN;
}
if (x <= 170) {
if (Math.floor(x) == x) {
int n = (int)x;
double extra = x;
switch (n & 7) {
case 7: extra *= --x;
case 6: extra *= --x;
case 5: extra *= --x;
case 4: extra *= --x;
case 3: extra *= --x;
case 2: extra *= --x;
case 1: return FACT[n >> 3] * extra;
case 0: return FACT[n >> 3];
}
}
}
return exp(lgamma(x));
}
 
public static final double comb(double n, double k) {
if (n < 0 || k < 0) { return Double.NaN; }
if (n < k) { return 0; }
if (Math.floor(n) == n && Math.floor(k) == k) {
k = Math.min(k, n-k);
if (n <= 170 && 12 < k && k <= 170) {
return factorial(n)/factorial(k)/factorial(n-k);
} else {
double r = 1, diff = n-k;
for (double i = k; i > .5 && r < Double.POSITIVE_INFINITY; --i) {
r *= (diff+i)/i;
}
return r;
}
} else {
return exp(lgamma(n) - lgamma(k) - lgamma(n-k));
}
}
 
public static final double perm(double n, double k) {
if (n < 0 || k < 0) { return Double.NaN; }
if (n < k) { return 0; }
if (Math.floor(n) == n && Math.floor(k) == k) {
if (n <= 170 && 10 < k && k <= 170) {
return factorial(n)/factorial(n-k);
} else {
double r = 1, limit = n-k+.5;
for (double i = n; i > limit && r < Double.POSITIVE_INFINITY; --i) {
r *= i;
}
return r;
}
} else {
return exp(lgamma(n) - lgamma(n-k));
}
}
 
public static final double log2(double x) {
return log(x) * LOG2E;
}
 
private static final boolean isPiMultiple(double x) {
return x % Math.PI == 0;
}
 
public static final int intLog10(double x) {
//an alternative implem is using a for loop.
return (int)Math.floor(log10(x));
//return (int)log10(x);
}
 
public static final double intExp10(int exp) {
return Double.parseDouble("1E" + exp);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Util.java
0,0 → 1,149
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Contains static helper methods for formatting double values.
*/
public class Util {
/*
private static String replace(String str, String what, String repl) {
int pos = str.indexOf(what);
while (pos != -1) {
str = str.substring(0, pos) + repl + str.substring(pos + what.length());
pos = str.indexOf(what);
}
//Log.log("replaced: '"+str+"'");
return str;
}
*/
 
/** Returns a number which is an approximation of v (within maxError)
and which has fewer digits in base-10).
@param value the value to be approximated
@param maxError the maximum deviation from value
@return an approximation with a more compact base-10 representation.
*/
public static double shortApprox(double value, double maxError) {
final double v = Math.abs(value);
final double tail = MoreMath.intExp10(MoreMath.intLog10(Math.abs(maxError)));
final double ret = Math.floor(v/tail +.5)*tail;
return (value < 0) ? -ret : ret;
}
 
/**
Returns an approximation with no more than maxLen chars.
@param str the value to truncate (e.g. "-2.898983455E20")
@param maxLen the maximum number of characters in the returned string
@return a truncation no longer then maxLen (e.g. "-2.8E20" for maxLen=7).
*/
public static String sizeTruncate(String str, int maxLen) {
int ePos = str.lastIndexOf('E');
String tail = (ePos != -1) ? str.substring(ePos) : "";
int tailLen = tail.length();
int maxHeadLen = maxLen - tailLen;
return str.substring(0, Math.min(str.length()-tailLen, maxHeadLen)) + tail;
}
 
/**
Rounds by dropping roundingDigits of double precision
(similar to 'hidden precision digits' on calculators),
and formats to String.
@param v the value to be converted to String
@param roundingDigits the number of 'hidden precision' digits (e.g. 2).
@return a String representation of v
*/
public static String doubleToString(double v, int roundingDigits) {
if (roundingDigits > 13) {
roundingDigits = 0;
}
int roundingStart = roundingDigits == 0 ? 17 : 15 - roundingDigits;
 
String str = Double.toString(Math.abs(v));
StringBuffer buf = new StringBuffer(str);
int ePos = str.lastIndexOf('E');
int exp = (ePos != -1) ? Integer.parseInt(str.substring(ePos + 1)) : 0;
if (ePos != -1) {
buf.setLength(ePos);
}
int len = buf.length();
 
//remove dot
int dotPos;
for (dotPos = 0; dotPos < len && buf.charAt(dotPos) != '.';) ++dotPos;
exp += dotPos;
if (dotPos < len) {
buf.deleteCharAt(dotPos);
--len;
}
 
//round
for (int p = 0; p < len && buf.charAt(p) == '0'; ++p) {
++roundingStart;
}
 
if (roundingStart < len) {
if (buf.charAt(roundingStart) >= '5') {
int p;
for (p = roundingStart-1; p >= 0 && buf.charAt(p)=='9'; --p) {
buf.setCharAt(p, '0');
}
if (p >= 0) {
buf.setCharAt(p, (char)(buf.charAt(p)+1));
} else {
buf.insert(0, '1');
++roundingStart;
++exp;
}
}
buf.setLength(roundingStart);
}
 
//re-insert dot
if ((exp < -5) || (exp > 10)) {
buf.insert(1, '.');
--exp;
} else {
for (int i = len; i < exp; ++i) {
buf.append('0');
}
buf.insert((exp<0)? 0 : exp, '.');
for (int i = exp; i <= 0; ++i) {
buf.insert(0, '0');
}
exp = 0;
}
len = buf.length();
//remove trailing dot and 0s.
int tail;
for (tail = len-1; tail >= 0 && buf.charAt(tail) == '0'; --tail) {
buf.deleteCharAt(tail);
}
if (tail >= 0 && buf.charAt(tail) == '.') {
buf.deleteCharAt(tail);
}
 
if (exp != 0) {
buf.append('E').append(exp);
}
if (v < 0) {
buf.insert(0, '-');
}
return buf.toString();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/SimpleCodeGen.java
0,0 → 1,99
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/* Non-optimizing Code Generator
Reads tokens in RPN (Reverse Polish Notation) order,
and generates VM opcodes,
without any optimization.
*/
 
class SimpleCodeGen extends TokenConsumer {
private CompiledFunction compiledFunction = new CompiledFunction();
static final SyntaxException HAS_ARGUMENTS = new SyntaxException();
 
ByteStack code = new ByteStack();
DoubleStack consts = new DoubleStack();
FunctionStack funcs = new FunctionStack();
 
//String argNames[];
Symbols symbols;
 
SyntaxException exception;
 
SimpleCodeGen(SyntaxException exception) {
this.exception = exception;
}
 
SimpleCodeGen setSymbols(Symbols symbols) {
this.symbols = symbols;
return this;
}
 
//@Override
void start() {
code.clear();
consts.clear();
funcs.clear();
}
void push(Token token) throws SyntaxException {
byte op;
switch (token.id) {
case Lexer.NUMBER:
op = VM.CONST;
consts.push(token.value);
break;
case Lexer.CONST:
case Lexer.CALL:
Symbol symbol = symbols.lookup(token.name, token.arity);
if (symbol == null) {
throw exception.set("undefined '" + token.name + "' with arity " + token.arity, token.position);
}
if (symbol.op > 0) { // built-in
op = symbol.op;
if (op >= VM.LOAD0 && op <= VM.LOAD4) {
throw HAS_ARGUMENTS.set("eval() on implicit function", exception.position);
}
} else if (symbol.fun != null) { // function call
op = VM.CALL;
funcs.push(symbol.fun);
} else { // variable reference
op = VM.CONST;
consts.push(symbol.value);
}
break;
default:
op = token.vmop;
if (op <= 0) {
throw new Error("wrong vmop: " + op);
}
}
code.push(op);
}
double getValue() {
compiledFunction.init(0, code.toArray(), consts.toArray(), funcs.toArray());
try {
return compiledFunction.eval();
} catch (ArityException e) {
throw new Error("" + e); //never
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/UnitTest.java
0,0 → 1,345
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class EvalCase {
String expr;
double result;
static final double ERR = -2, FUN = -3;
 
EvalCase(String expr, double result) {
this.expr = expr;
this.result = result;
}
}
 
class TestEval {
static EvalCase cases[] = {
new EvalCase(".", 0),
new EvalCase("1+.", 1),
new EvalCase("1", 1),
new EvalCase("\u03c0", Math.PI),
new EvalCase("2\u00d73", 6), //2*3
new EvalCase("1+\u221a9*2", 7), //1+sqrt(9)*2
new EvalCase("3\u221a 4", 6), //3*sqrt(4)
new EvalCase("\u221a16sin(2\u03c0/4)", 4), //sqrt(16)*sin(2pi/4)
new EvalCase("1+", EvalCase.ERR),
new EvalCase("1+1", 2),
new EvalCase("1+-1", 0),
new EvalCase("-0.5", -.5),
new EvalCase("+1e2", 100),
new EvalCase("-2^3!", -64),
new EvalCase("(-2)^3!", 64),
new EvalCase("-2^1^2", -2),
new EvalCase("--1", 1),
new EvalCase("-3^--2", -9),
new EvalCase("1+2)(2+3", 15),
new EvalCase("1+2)!^-2", 1./36),
new EvalCase("sin(0)", 0),
new EvalCase("cos(0)", 1),
new EvalCase("sin(-1--1)", 0),
new EvalCase("-(2+1)*-(4/2)", 6),
new EvalCase("-.5E-1", -.05),
new EvalCase("1E1.5", EvalCase.ERR),
new EvalCase("2 3 4", 24),
new EvalCase("pi", Math.PI),
new EvalCase("e", Math.E),
new EvalCase("sin(pi/2)", 1),
new EvalCase("f=sin(2x)", EvalCase.FUN),
new EvalCase("f(pi/2)", 0),
new EvalCase("a=3", 3),
new EvalCase("b=a+1", 4),
new EvalCase("f(x, y) = x*(y+1)", EvalCase.FUN),
new EvalCase("f(a, b-a)", 6),
new EvalCase(" f(a pi/4)", -1),
new EvalCase("f ( 1 + 1 , a+1)", 10),
new EvalCase("g(foo) = f (f(foo, 1)pi/2)", EvalCase.FUN),
new EvalCase("g(.5*2)", 0),
new EvalCase("NaN", Double.NaN),
new EvalCase("Inf", Double.POSITIVE_INFINITY),
new EvalCase("Infinity", Double.POSITIVE_INFINITY),
new EvalCase("-Inf", Double.NEGATIVE_INFINITY),
new EvalCase("0/0", Double.NaN)
};
 
private static boolean equal(double a, double b) {
return Math.abs(a-b) < 1E-15 ||
Double.doubleToLongBits(a) == Double.doubleToLongBits(b);
}
 
static boolean testEval() throws ArityException {
final String spaces = " ";
boolean allOk = true;
Symbols symbols = new Symbols();
for (int i = 0; i < cases.length; ++i) {
EvalCase c = cases[i];
String strResult;
boolean ok;
try {
double actual;
if (Symbols.isDefinition(c.expr)) {
FunctionAndName fan = symbols.compile(c.expr);
symbols.define(fan);
Function f = fan.function;
actual = f.arity()==0 ? f.eval() : EvalCase.FUN;
strResult = (f.arity()==0 ? Util.doubleToString(actual, 1) : f.toString());
} else {
actual = symbols.eval(c.expr);
strResult = Util.doubleToString(actual, 1);
}
ok = equal(c.result, actual);
} catch (SyntaxException e) {
strResult = e.toString();
ok = c.result == EvalCase.ERR;
}
System.out.println((ok ? "" : "failed (expected " + c.result + "): ")
+ c.expr
+ spaces.substring(0, Math.max(15-c.expr.length(), 0)) + " = "
+ strResult);
if (!ok) {
allOk = false;
}
}
return allOk;
}
}
 
 
class FormatCase {
public FormatCase(int rounding, double v, String s) {
this.rounding = rounding;
this.val = v;
this.res = s;
}
public int rounding;
public double val;
public String res;
}
 
class TestFormat {
static FormatCase cases[] = {
new FormatCase(0, 0.1, "0.1"),
new FormatCase(0, 0.12, "0.12"),
new FormatCase(0, 0.001, "0.001"),
new FormatCase(0, 0.0012, "0.0012"),
new FormatCase(0, 0.0000001, "1E-7"),
new FormatCase(0, 0.00000012, "1.2E-7"),
new FormatCase(0, 0.123456789012345, "0.123456789012345"),
 
new FormatCase(0, 0, "0"),
new FormatCase(0, 1, "1"),
new FormatCase(0, 12, "12"),
new FormatCase(0, 1234567890., "1234567890"),
new FormatCase(0, 1000000000., "1000000000"),
new FormatCase(0, 1.23456789012345, "1.23456789012345"),
new FormatCase(0, 12345.6789012345, "12345.6789012345"),
new FormatCase(0, 1234567890.12345, "1234567890.12345"),
new FormatCase(0, 123456789012345., "1.23456789012345E14"),
new FormatCase(0, 100000000000000., "1E14"),
new FormatCase(0, 120000000000000., "1.2E14"),
new FormatCase(0, 100000000000001., "1.00000000000001E14"),
 
new FormatCase(2, 0.1, "0.1"),
new FormatCase(2, 0.00000012, "1.2E-7"),
new FormatCase(1, 0.123456789012345, "0.12345678901235"),
 
new FormatCase(2, 0, "0"),
new FormatCase(1, 1.23456789012345, "1.2345678901235"),
new FormatCase(2, 1.23456789012345, "1.234567890123"),
new FormatCase(0, 12345.6789012345, "12345.6789012345"),
new FormatCase(1, 1234567890.12345, "1234567890.1235"),
new FormatCase(2, 123456789012345., "1.234567890123E14"),
new FormatCase(1, 100000000000001., "1E14"),
 
new FormatCase(0, 12345678901234567., "1.2345678901234568E16"),
new FormatCase(1, 12345678901234567., "1.2345678901235E16"),
 
new FormatCase(0, 99999999999999999., "1E17"),
new FormatCase(0, 9999999999999999., "1E16"),
new FormatCase(0, 999999999999999., "9.99999999999999E14"),
new FormatCase(1, 999999999999999., "1E15"),
new FormatCase(1, 999999999999994., "9.9999999999999E14"),
 
new FormatCase(1, MoreMath.log2(1+.00002), "00000.28853612282487")
};
 
static boolean testFormat() {
boolean ret = true;
for (int i = 0; i < cases.length; ++i) {
FormatCase c = cases[i];
double v = Double.parseDouble(c.res);
if (c.rounding == 0 && v != c.val) {
System.out.println("wrong test? " + c.res + " " + v + " " + c.val);
}
String res = Util.doubleToString(c.val, c.rounding);
if (!res.equals(c.res)) {
System.out.println("Expected '" + c.res + "', got '" + res + "'. " + Double.toString(c.val));
ret = false;
}
int nKeep = c.rounding == 0 ? 17 : 15 - c.rounding;
//System.out.println("" + Double.toString(c.val) + " " + Util.round(c.val, nKeep) + " " + c.res + ", got " + res);
}
return ret;
}
}
 
/**
Runs unit-tests.<p>
Usage: java -jar arity.jar
*/
public class UnitTest {
/**
Takes a single command-line argument, an expression; compiles and prints it.<p>
Without arguments, runs the unit tests.
@throws SyntaxException if there are errors compiling the expression.
*/
public static void main(String argv[]) throws SyntaxException, ArityException {
int size = argv.length;
if (size == 0) {
runUnitTests();
profile();
} else if (size == 1 && argv[0].equals("-profile")) {
profile();
} else {
Symbols symbols = new Symbols();
for (int i = 0; i < size; ++i) {
FunctionAndName fan = symbols.compile(argv[i]);
symbols.define(fan);
}
profile(symbols, argv[size-1]);
}
}
 
static void profile(Symbols symbols, String str) throws SyntaxException, ArityException {
Function f = symbols.compile(str).function;
System.out.println("\n" + str + ": " + f);
 
Runtime runtime = Runtime.getRuntime();
 
runtime.gc();
/*
long m1 = runtime.freeMemory();
for (int i = 0; i < 200; ++i) {
symbols.compile(str);
}
long m2 = runtime.freeMemory();
System.out.println("compilation memory: " + (m1 - m2)/200 + " bytes");
*/
runtime.gc();
long t1 = System.currentTimeMillis();
for (int i = 0; i < 1000; ++i) {
symbols.compile(str);
}
long t2 = System.currentTimeMillis();
System.out.println("compilation time: " + (t2 - t1) + " us");
double args[] = new double[f.arity()];
/*
runtime.gc();
m1 = runtime.freeMemory();
f.eval(args);
m2 = runtime.freeMemory();
if (m2 != m1) {
System.out.println("execution memory: " + (m1 - m2) + " bytes");
}
*/
runtime.gc();
t1 = System.currentTimeMillis();
for (int i = 0; i < 100000; ++i) {
f.eval(args);
}
t2 = System.currentTimeMillis();
long delta = t2 - t1;
System.out.println("execution time: " + (delta > 100 ? ""+delta/100.+" us" : ""+delta+" ns"));
}
 
private static final String profileCases[] = {
//"1+1",
"(100.5 + 20009.999)*(7+4+3)/(5/2)^3!)*2",
"fun1(x)=(x+2)*(x+3)",
"otherFun(x)=(fun1(x-1)*x+1)*(fun1(2-x)+10)",
"log(x+30.5, 3)^.7*sin(x+.5)"
};
 
private static void profile() {
String cases[] = profileCases;
Symbols symbols = new Symbols();
try {
for (int i = 0; i < cases.length; ++i) {
symbols.define(symbols.compile(cases[i]));
profile(symbols, cases[i]);
}
} catch (Exception e) {
throw new Error("" + e);
}
}
 
static void runUnitTests() {
checkCounter = 0;
 
cheq(MoreMath.log(-1), Double.NaN);
cheq(MoreMath.log(-0.03), Double.NaN);
cheq(MoreMath.intLog10(-0.03), 0);
cheq(MoreMath.intLog10(0.03), -2);
cheq(MoreMath.intExp10(3), 1000);
cheq(MoreMath.intExp10(-1), 0.1);
cheq(Util.shortApprox( 1.235, 0.02), 1.24);
cheq(Util.shortApprox( 1.235, 0.4), 1.2000000000000002);
cheq(Util.shortApprox(-1.235, 0.02), -1.24);
cheq(Util.shortApprox(-1.235, 0.4), -1.2000000000000002);
 
check(TestFormat.testFormat());
try {
check(TestEval.testEval());
} catch (ArityException e) {
System.out.println(""+e);
}
 
if (!allOk) {
System.out.println("\n*** Some tests FAILED ***\n");
System.exit(1);
} else {
System.out.println("\n*** All tests passed OK ***\n");
}
}
 
static void cheq(double v1, double v2) {
++checkCounter;
if (v1 != v2 && !(Double.isNaN(v1) && Double.isNaN(v2))) {
allOk = false;
//Log.log("check equal " + checkCounter + " failed: " + v1 + " " + v2);
}
}
static void check(boolean cond) {
++checkCounter;
if (!cond) {
allOk = false;
//Log.log("check " + checkCounter + " failed");
}
}
 
static boolean allOk = true;
static int checkCounter = 0;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Lexer.java
0,0 → 1,176
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Lexer {
static final int
ADD = 1,
SUB = 2,
MUL = 3,
DIV = 4,
MOD = 5,
UMIN = 6,
POWER = 7,
FACT = 8,
NUMBER = 9,
CONST = 10,
CALL = 11,
COMMA = 12,
LPAREN = 13,
RPAREN = 14,
END = 15,
SQRT = 16;
static final Token
TOK_ADD = new Token(ADD, 3, Token.LEFT, VM.ADD),
TOK_SUB = new Token(SUB, 3, Token.LEFT, VM.SUB),
 
TOK_MUL = new Token(MUL, 4, Token.LEFT, VM.MUL),
TOK_DIV = new Token(DIV, 4, Token.LEFT, VM.DIV),
TOK_MOD = new Token(MOD, 4, Token.LEFT, VM.MOD),
 
TOK_UMIN = new Token(UMIN, 5, Token.PREFIX, VM.UMIN),
 
TOK_POWER = new Token(POWER, 6, Token.RIGHT, VM.POWER),
TOK_FACT = new Token(FACT, 7, Token.SUFIX, VM.FACT),
TOK_SQRT = new Token(SQRT, 8, Token.PREFIX, VM.SQRT),
 
TOK_LPAREN = new Token(LPAREN, 1, Token.PREFIX, 0),
TOK_RPAREN = new Token(RPAREN, 2, 0, 0),
TOK_COMMA = new Token(COMMA, 1, 0, 0),
TOK_END = new Token(END, 0, 0, 0),
 
TOK_NUMBER = new Token(NUMBER, 20, 0, 0),
TOK_CONST = new Token(CONST, 20, 0, 0);
 
private static final String WHITESPACE = " \n\r\t";
private static final char END_MARKER = '$';
private char[] input = new char[32];
private int pos;
private SyntaxException exception;
 
Lexer(SyntaxException exception) {
this.exception = exception;
init("");
}
 
void scan(String str, TokenConsumer consumer) throws SyntaxException {
init(str);
consumer.start();
Token token;
do {
int savePos = pos;
token = nextToken();
token.position = savePos;
consumer.push(token);
} while (token != TOK_END);
}
 
void init(String str) {
exception.expression = str;
int len = str.length();
if (input.length < len + 1) {
input = new char[len+1];
}
str.getChars(0, len, input, 0);
input[len] = END_MARKER;
pos = 0;
}
 
Token nextToken() throws SyntaxException {
while (WHITESPACE.indexOf(input[pos]) != -1) {
++pos;
}
 
char c = input[pos];
int begin = pos++;
 
switch (c) {
case '!': return TOK_FACT;
case END_MARKER: return TOK_END;
case '%': return TOK_MOD;
case '(': return TOK_LPAREN;
case ')': return TOK_RPAREN;
case '*': return TOK_MUL;
case '+': return TOK_ADD;
case ',': return TOK_COMMA;
case '-': return TOK_SUB;
case '/': return TOK_DIV;
}
if (c == '^') {
return TOK_POWER;
}
 
int p = pos;
if (('0' <= c && c <= '9') || c == '.') {
while (('0' <= c && c <= '9') || c == '.' || c == 'E' || c == 'e') {
if ((c == 'E' || c == 'e') && input[p] == '-') { //accept '-' only after E
++p;
}
c = input[p++];
}
pos = p-1;
String nbStr = String.valueOf(input, begin, p-1-begin);
try {
// parse single dot as 0
if (nbStr.equals(".")) {
return TOK_NUMBER.setValue(0);
} else {
double numberValue = Double.parseDouble(nbStr);
return TOK_NUMBER.setValue(numberValue);
}
} catch (NumberFormatException e) {
throw exception.set("invalid number '" + nbStr + "'", begin);
}
} else if (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z')) {
do {
c = input[p++];
} while (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
('0' <= c && c <= '9'));
String nameValue = String.valueOf(input, begin, p-1-begin);
while (WHITESPACE.indexOf(c) != -1) {
c = input[p++];
}
if (c == '(') {
pos = p;
return (new Token(CALL, 0, Token.PREFIX, 0)).setAlpha(nameValue);
} else {
pos = p-1;
return TOK_CONST.setAlpha(nameValue);
}
} else if ((c >= '\u0391' && c <= '\u03a9') || (c >= '\u03b1' && c <= '\u03c9')) {
return TOK_CONST.setAlpha(""+c);
} else {
switch (c) {
case '^':
return TOK_POWER;
case '\u00d7':
return TOK_MUL;
case '\u00f7':
return TOK_DIV;
case '\u2212':
return TOK_SUB;
case '\u221a':
return TOK_SQRT;
default:
throw exception.set("invalid character '" + c + "'", begin);
}
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Token.java
0,0 → 1,71
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Token {
//kind
static final int
PREFIX = 1,
LEFT = 2,
RIGHT = 3,
SUFIX = 4;
 
final int priority;
final int assoc;
final int id;
final byte vmop;
 
double value = 0; //for NUMBER only
String name = null; //for CONST & CALL
int arity;
int position; //pos inside expression
 
Token(int id, int priority, int assoc, int vmop) {
this.id = id;
this.priority = priority;
this.assoc = assoc;
this.vmop = (byte)vmop;
arity = id == Lexer.CALL ? 1 : Symbol.CONST_ARITY;
}
Token setPos(int pos) {
this.position = pos;
return this;
}
 
Token setValue(double value) {
this.value = value;
return this;
}
 
Token setAlpha(String alpha) {
name = alpha;
return this;
}
 
public String toString() {
switch (id) {
case Lexer.NUMBER:
return "" + value;
case Lexer.CALL:
return name + '(' + arity + ')';
case Lexer.CONST:
return name;
}
return "" + id;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/VM.java
0,0 → 1,117
// This file is automatically generated by the build.py script. Do not edit!
 
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class VM {
 
public static final byte
RESERVED = 0,
CONST = 1,
CALL = 2,
ADD = 3,
SUB = 4,
MUL = 5,
DIV = 6,
MOD = 7,
RND = 8,
UMIN = 9,
POWER = 10,
FACT = 11,
SQRT = 12,
CBRT = 13,
EXP = 14,
LOG = 15,
SIN = 16,
COS = 17,
TAN = 18,
ASIN = 19,
ACOS = 20,
ATAN = 21,
SINH = 22,
COSH = 23,
TANH = 24,
ASINH = 25,
ACOSH = 26,
ATANH = 27,
ABS = 28,
FLOOR = 29,
CEIL = 30,
SIGN = 31,
MIN = 32,
MAX = 33,
GCD = 34,
COMB = 35,
PERM = 36,
LOAD0 = 37,
LOAD1 = 38,
LOAD2 = 39,
LOAD3 = 40,
LOAD4 = 41,
BYTECODE_END = 42;
 
public static final String[] opcodeName = {
"reserved",
"const",
"call",
"add",
"sub",
"mul",
"div",
"mod",
"rnd",
"umin",
"power",
"fact",
"sqrt",
"cbrt",
"exp",
"log",
"sin",
"cos",
"tan",
"asin",
"acos",
"atan",
"sinh",
"cosh",
"tanh",
"asinh",
"acosh",
"atanh",
"abs",
"floor",
"ceil",
"sign",
"min",
"max",
"gcd",
"comb",
"perm",
"load0",
"load1",
"load2",
"load3",
"load4",
"bytecode_end"
};
 
public static final byte[] builtinArity =
{-1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1};
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/BaseMath.java
0,0 → 1,65
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
 
package org.javia.arity;
 
// This class is a replacement for BaseMath.java to be used on Java 1.5 and later
class BaseMath {
public static final double atan(double x) {
return Math.atan(x);
}
public static final double asin(double x) {
return Math.asin(x);
}
 
public static final double acos(double x) {
return Math.acos(x);
}
 
public static final double exp(double x) {
return Math.exp(x);
}
 
public static final double log(double x) {
return Math.log(x);
}
 
public static final double sinh(double x) {
return Math.sinh(x);
}
 
public static final double cosh(double x) {
return Math.cosh(x);
}
 
public static final double tanh(double x) {
return Math.tanh(x);
}
 
public static final double cbrt(double x) {
return Math.cbrt(x);
}
public static final double pow(double x, double y) {
return Math.pow(x, y);
}
 
public static final double log10(double x) {
return Math.log10(x);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Declaration.java
0,0 → 1,50
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Declaration {
private static final String NO_ARGS[] = {};
String name;
String args[];
int arity;
String expression;
 
void parse(String source, Lexer lexer, DeclarationParser declParser) throws SyntaxException {
int equalPos = source.indexOf('=');
String decl;
 
if (equalPos == -1) {
decl = null;
expression = source;
name = null;
args = NO_ARGS;
arity = DeclarationParser.UNKNOWN_ARITY;
} else {
decl = source.substring(0, equalPos);
expression = source.substring(equalPos + 1);
lexer.scan(decl, declParser);
name = declParser.name;
args = declParser.argNames();
arity = declParser.arity;
}
/*
if (arity == DeclarationParser.UNKNOWN_ARITY) {
args = IMPLICIT_ARGS;
}
*/
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Function.java
0,0 → 1,94
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Abstract base class for functions.<p>
A function has an arity (the number of arguments), and a way for evaluation
given the values of the arguments.<p>
Derive from this class to create user-defined functions.
 
<h3>Thread safety</h3>
Assuming the user didn't subclass Function to define user functions,
the compiled Functions are thread-safe
(the same Function instance can be evaluated from multiple threads without locking).<p>
 
Whatsmore, parallel evaluations of the same instance from multiple threads are not
serialized (good).<p>
 
If the user subclasses Function, he is responsible for the thread-safety of
his user-defined Functions.
*/
 
abstract public class Function {
private int cachedArity = -1;
 
/**
Gives the arity of this function.
@return the arity (the number of arguments). Arity >= 0.
*/
public int arity() {
if (cachedArity == -1) {
cachedArity = 0;
for (int i = 0; i < 5; ++i) {
double args[] = new double[i];
try {
eval(args);
cachedArity = i;
break;
} catch (ArityException e) {
//ignore, continue
}
}
}
return cachedArity;
}
 
/**
Evaluates an arity-0 function (a function with no arguments).
@return the value of the function
*/
public double eval() throws ArityException {
throw new ArityException("Didn't expect 0 args");
}
 
public double eval(double x) throws ArityException {
throw new ArityException("Didn't expect 1 args");
}
 
public double eval(double x, double y) throws ArityException {
throw new ArityException("Didn't expect 2 args");
}
 
/**
Evaluates the function given the argument values.
@param args array containing the arguments.
@return the value of the function
@throws ArityException if args.length != arity.
*/
public double eval(double args[]) throws ArityException {
switch (args.length) {
case 0:
return eval();
case 1:
return eval(args[0]);
case 2:
return eval(args[0], args[1]);
}
throw new ArityException("unexpected " + args.length + " args");
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/OptCodeGen.java
0,0 → 1,108
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/* Optimizing Code Generator
Reads tokens in RPN (Reverse Polish Notation) order,
and generates VM opcodes,
doing constant-folding optimization.
*/
 
class OptCodeGen extends SimpleCodeGen {
double stack[] = new double[CompiledFunction.MAX_STACK_SIZE];
int sp = -1;
 
double traceConsts[] = new double[1];
Function traceFuncs[] = new Function[1];
byte traceCode[] = new byte[1];
CompiledFunction tracer = new CompiledFunction(0, traceCode, traceConsts, traceFuncs);
 
int intrinsicArity;
OptCodeGen(SyntaxException e) {
super(e);
}
 
//@Override
void start() {
super.start();
sp = -1;
intrinsicArity = 0;
}
 
//@Override
void push(Token token) throws SyntaxException {
byte op;
switch (token.id) {
case Lexer.NUMBER:
op = VM.CONST;
traceConsts[0] = token.value;
break;
case Lexer.CONST:
case Lexer.CALL:
Symbol symbol = symbols.lookup(token.name, token.arity);
if (symbol == null) {
throw exception.set("undefined '" + token.name + "' with arity " + token.arity, token.position);
}
if (symbol.op > 0) { // built-in
op = symbol.op;
if (op >= VM.LOAD0 && op <= VM.LOAD4) {
int arg = op - VM.LOAD0;
if (arg + 1 > intrinsicArity) {
intrinsicArity = arg + 1;
}
}
} else if (symbol.fun != null) { // function call
op = VM.CALL;
traceFuncs[0] = symbol.fun;
} else { // variable reference
op = VM.CONST;
traceConsts[0] = symbol.value;
}
break;
default:
op = token.vmop;
if (op <= 0) {
throw new Error("wrong vmop: " + op);
}
}
int oldSP = sp;
traceCode[0] = op;
if (op != VM.RND) {
sp = tracer.execWithoutCheck(stack, sp);
} else {
stack[++sp] = Double.NaN;
}
 
//constant folding
if (!Double.isNaN(stack[sp]) || op == VM.CONST) {
code.pop(oldSP + 1 - sp);
consts.pop(oldSP + 1 - sp);
consts.push(stack[sp]);
op = VM.CONST;
} else if (op == VM.CALL) {
funcs.push(traceFuncs[0]);
}
code.push(op);
}
 
CompiledFunction getFun(int arity) {
return new CompiledFunction(arity, code.toArray(), consts.toArray(), funcs.toArray());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Symbols.java
0,0 → 1,264
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
 
/**
The collection of names (<em>symbols</em>) used for parsing an expression
(the context in which the parsing takes place).<p>
 
Each symbol maps to either a {@link Function} or a constant.<p>
 
A symbol is identified by the pair (name, arity).
So a constant and a function with the same name,
or two function with the same name but with different arity
are distinct symbols.<p>
 
Symbols functions as a stack of <em>frames</em>:
when you pop the topmost frame, all the symbols added in that frame dissapear
(i.e. all the modifications done between the push and the pop are lost).<p>
 
Example:
<pre>
<code>
Symbols symbols = new Symbols();
symbols.eval("1+1"); //doesn't update symbols
symbols.define(symbols.compile("f(x)=x^2")); //updates symbols
</code>
</pre>
<p>
 
<h3>Thread safety</h3>
The Symbols class is thread-safe
(the same Symbols instance can be used by multiple threads without locking).<p>
 
The compile() methods are synchronized, so parallel compile() calls on the same Symbols
instance are serialized.
*/
 
public class Symbols {
/**
Constructs a Symbols containing the built-in symbols (such as sin, log).
*/
public Symbols() {
for (int i = 0; i < builtin.length; ++i) {
Symbol s = builtin[i];
symbols.put(s, s);
}
try {
for (int i = 0; i < defines.length; ++i) {
define(compile(defines[i]));
}
} catch (SyntaxException e) {
throw new Error(""+e); //never
}
}
 
/**
@param source the expression
@return true if the expression is a definition (i.e. contains a '=').<p>
These are definitions: "a=1+1"; "f(k)=2^k"<p>
These are not definitions: "1+1"; "x+1"
*/
public static boolean isDefinition(String source) {
return source.indexOf('=') != -1;
}
 
/**
Evaluates a simple expression (such as "1+1") and returns its value.
@throws SyntaxException in these cases:
<ul>
<li> the expression is not well-formed
<li> the expression is a definition (such as "a=1+1")
<li> the expression is an implicit function (such as "x+1")
</ul>
*/
public synchronized double eval(String expression) throws SyntaxException {
return getCompiler().eval(this, expression);
}
 
/**
Compiles an expression in the context of this Symbols.
Does not modify the symbols.
<p>
 
An expression is one of these cases (@see Symbols.isDefinition()):
<ul>
<li> constant value: 1+1
<li> implicit function: x+1
<li> constant definition: a=1+1
<li> function definition with explicit arguments: f(a)=a+1
<li> function definition with implicit arguments: f=x+1
</ul>
<p>
 
@param source the expression; may contain '=' to denote a definition (with a name).
@return the function together with its eventual name.<p>
 
If this is not a definition (e.g. "1+1", "x^2"), the name is null.<p>
If the expression is a constant (e.g. "1+1", "a=2"),
the returned Function is an instance of {@link Constant}.
 
@throws SyntaxException if there are errors compiling the expression.
*/
public synchronized FunctionAndName compile(String source) throws SyntaxException {
return getCompiler().compile(this, source);
}
 
/**
Adds a new function symbol to the top-most frame of this Symbols.
@param name the name of the function (e.g. "sin")
@param function the function to which the name maps
*/
synchronized public void define(String name, Function function) {
if (function instanceof Constant) {
addConstant(name, ((Constant) function).eval());
} else {
add(new Symbol(name, function));
}
}
 
/**
Adds a new function symbol to the top-most frame of this Symbols.
@param funAndName structure containing the function and its name
*/
synchronized public void define(FunctionAndName funAndName) {
if (funAndName.name != null) {
define(funAndName.name, funAndName.function);
}
}
 
/**
Adds a new constant symbol to the top-most frame of this Symbols.
@param name the name of the constant (e.g. "pi")
@param value the value of the constant
*/
synchronized public void addConstant(String name, double value) {
add(new Symbol(name, value));
}
 
/**
Pushes a new top frame.<p>
 
All modifications (defining new symbols) happen in the top-most frame.
When the frame is pop-ed the modifications that happened in it are reverted.
*/
synchronized public void pushFrame() {
frames.push(delta);
delta = null;
}
 
/**
Pops the top frame.<p>
 
All the modifications done since this frame was pushed are reverted.
@throws EmptyStackException if there were fewer <code>pushFrame</code> than <code>popFrame</code>.
*/
synchronized public void popFrame() {
if (delta != null) {
for (int i = delta.size() - 1; i >= 0; --i) {
Symbol previous = (Symbol) delta.elementAt(i);
if (previous.isEmpty()) {
symbols.remove(previous);
} else {
symbols.put(previous, previous);
}
}
}
delta = (Vector) frames.pop();
}
 
 
 
//--- non-public below
 
private final static Symbol builtin[];
private static Symbol shell = new Symbol(null, 0);
private static ThreadLocal compilers = new ThreadLocal();
private static Compiler getCompiler() {
Compiler compiler;
if ((compiler = (Compiler) compilers.get()) == null) {
compilers.set(compiler = new Compiler());
}
return compiler;
}
 
private Hashtable symbols = new Hashtable(); //Hashtable<Symbol, Symbol>
private Vector delta = null; //Vector<Symbol>
private Stack frames = new Stack(); //Stack<Vector>
 
static {
Vector vect = new Vector();
int arity;
for (byte i = 0; i < VM.BYTECODE_END; ++i) {
if ((arity = VM.builtinArity[i]) >= 0) {
vect.addElement(new Symbol(VM.opcodeName[i], arity, i));
}
}
 
final String IMPLICIT_ARGS[] = {"x", "y", "z"};
for (byte i = 0; i < IMPLICIT_ARGS.length; ++i) {
vect.addElement(new Symbol(IMPLICIT_ARGS[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
}
 
vect.addElement(new Symbol("pi", Math.PI));
vect.addElement(new Symbol("\u03c0", Math.PI));
vect.addElement(new Symbol("e", Math.E));
 
vect.addElement(new Symbol("Inf", Double.POSITIVE_INFINITY));
vect.addElement(new Symbol("Infinity", Double.POSITIVE_INFINITY));
vect.addElement(new Symbol("NaN", Double.NaN));
 
int size = vect.size();
builtin = new Symbol[size];
vect.copyInto(builtin);
}
 
private static final String defines[] = {
"ln(x) = log(x)",
"log2(x) = log(x) * 1.4426950408889634074", //*log2(e)
"log10(x) = log(x) * 0.43429448190325182765", //*log10(e)
"lg(x) = log10(x)",
"lb(x) = log2(x)",
"log(x, base) = log(x) / log(base)"
};
void addArguments(String args[]) {
for (int i = 0; i < args.length; ++i) {
add(new Symbol(args[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
}
}
 
void add(Symbol s) {
Object previous = symbols.put(s, s);
if (delta == null) {
delta = new Vector();
}
delta.addElement(previous != null ? previous : Symbol.newEmpty(s));
}
 
synchronized Symbol lookup(String name, int arity) {
return (Symbol) symbols.get(shell.setKey(name, arity));
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/Constant.java
0,0 → 1,30
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
public class Constant extends Function {
private double value;
 
public Constant(double value) {
this.value = value;
}
 
//@Override
public double eval() {
return value;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/ByteStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class ByteStack {
private byte[] data = new byte[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(byte b) {
if (size >= data.length) {
byte[] newData = new byte[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
byte[] toArray() {
byte[] trimmed = new byte[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/TokenConsumer.java
0,0 → 1,24
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
abstract class TokenConsumer {
void start() {
}
 
abstract void push(Token token) throws SyntaxException;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/org/javia/arity/RPN.java
0,0 → 1,161
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Stack;
import java.util.EmptyStackException;
 
/* Reverse Polish Notation
reads tokens in normal infix order (e.g.: 1 + 2)
and outputs them in Reverse Polish order (e.g.: 1 2 +).
See Dijkstra's Shunting Yard algorithm:
http://en.wikipedia.org/wiki/Shunting_yard_algorithm
*/
class RPN extends TokenConsumer {
Stack stack = new Stack();
int prevTokenId = 0;
TokenConsumer consumer;
SyntaxException exception;
 
RPN(SyntaxException exception) {
this.exception = exception;
}
 
void setConsumer(TokenConsumer consumer) {
this.consumer = consumer;
}
 
//@Override
void start() {
stack.removeAllElements();
prevTokenId = 0;
consumer.start();
}
 
private Token top() {
return stack.empty() ? null : (Token) stack.peek();
}
 
private void popHigher(int priority) throws SyntaxException {
Token t = top();
while (t != null && t.priority >= priority) {
consumer.push(t);
//code.push(t);
stack.pop();
t = top();
}
}
 
static final boolean isOperand(int id) {
return
id == Lexer.FACT ||
id == Lexer.RPAREN ||
id == Lexer.NUMBER ||
id == Lexer.CONST;
}
 
void push(Token token) throws SyntaxException {
int priority = token.priority;
int id = token.id;
switch (id) {
case Lexer.NUMBER:
case Lexer.CONST:
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
consumer.push(token);
break;
/*
case Lexer.CALL:
case Lexer.LPAREN:
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
stack.push(token);
break;
*/
case Lexer.RPAREN: {
if (prevTokenId == Lexer.CALL) {
top().arity--;
} else if (!isOperand(prevTokenId)) {
throw exception.set("unexpected ) or END", token.position);
}
 
popHigher(priority);
Token t = top();
if (t != null) {
if (t.id == Lexer.CALL) {
consumer.push(t);
} else if (t != Lexer.TOK_LPAREN) {
throw exception.set("expected LPAREN or CALL", token.position);
}
stack.pop();
}
break;
}
case Lexer.COMMA: {
if (!isOperand(prevTokenId)) {
throw exception.set("misplaced COMMA", token.position);
}
popHigher(priority);
Token t = top();
if (t==null || t.id != Lexer.CALL) {
throw exception.set("COMMA not inside CALL", token.position);
}
t.arity++;
//code.push(stack.pop());
break;
}
case Lexer.END: {
Token t = Lexer.TOK_RPAREN;
t.position = token.position;
do {
push(t);
} while (top() != null);
break;
}
default: //operators, CALL, LPAREN
if (token.assoc == Token.PREFIX) {
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
stack.push(token);
break;
}
if (!isOperand(prevTokenId)) {
if (id == Lexer.SUB) {
//change SUB to unary minus
token = Lexer.TOK_UMIN;
stack.push(token);
break;
} else if (id == Lexer.ADD) {
// ignore, keep prevTokenId unchanged
return;
}
throw exception.set("operator without operand", token.position);
}
popHigher(priority + (token.assoc == Token.RIGHT ? 1 : 0));
stack.push(token);
}
prevTokenId = token.id;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/src/GetallenLijn.java
0,0 → 1,572
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
 
Example of usage:
 
<html>
<head></head>
<body>
<script language="javascript" type="text/javascript">
function readthis(){
var input=document.applets[0].ReadApplet();
if(input.indexOf(error)!=-1){
alert(input);
}
else
{
alert("we will send to WIMS:"+input);
}
}
</script>
<center>
<applet code="NumberLine.class" width=600 height=240>
<!--- no params needed ; defaults are fine --->
<param name="xmax" value="50">
<param name="fontsize" value="16">
<param name="join" value="no">
<param name="language" value="nl">
<param name="pencolor" value="0,0,255><!--- input field foreground color --->
<param name="bgcolor1" value="255,255,255><!--- input field background color --->
<param name="bgcolor2" value="255:255;255"><!--- canvas color : may conflict with arrow colors...--->
<param name="exercise" value="an exercise, if not given in a wims phml page">
</applet>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:readthis();">
</body>
</html>
 
the WIMS reply type format:
boolean,"verbatim reply"
true,123-23=100
false,123-23=99
false,error \n multiple = -signs [e.g. 123-23=100-0=100]
false,error \n mathematical error [Arity error exception]
 
todo: dynamic scaling of xmax/xmin/step [with mouse drag ?/]
 
Arity usage example:
fun="sin(2*pi/2)"
fun="(1.2345678-2.345678)/12345678"
try { y=symbols.eval(fun);} catch (SyntaxException e) {System.out.println("error "+e); }
*/
 
 
import java.awt.*;
import java.applet.*;
import java.util.*;
import org.javia.arity.*;
 
 
public class GetallenLijn extends Applet {
int xmax=100;int xmin=-100;
int xmax_org=xmax;int xmin_org=xmin;
double step=3.0D;int x_pix=600;int y_pix=240;int x_nul=300;int y_nul=60;
int font_size=36;int minmax=200;boolean start= false;
String op[]={"+","-"};
Graphics g;int vectors=0;
boolean join = false;
boolean conclusion_drawn=false;
int arrowdistance=10;// moet in verhouding met hoogte...
private TextField input;
double fragment[];
int now=0;
int kleuren[][]={ {255,0,0},{0,255,0},{0,0,255},{238,154,0},{255,255,0},{160,32,240},{144,238,144},{173,216,230},{0,255,255},{165,24,24},{250,128,114},{255,192,203} };
// 11 kleuren ... zie changecolor()
Color arrowcolor;
Color pencolor;
int R1=225;int G1=255;int B1=255;Color bgcolor1;
int R2=255;int G2=255;int B2=255;Color bgcolor2;
// java 1.4 can not use replaceAll();
String illegalchars[]={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","y","z","(",")","{","}","[","]","@","#","~","!","$","%","^","&","_",";",">","<","|"};
// 46 items : prepare();
String cijfers[]={"0","1","2","3","4","5","6","7","8","9"};
double multiplication[];
String param;String title;String exercise="";String inputtext;
String rem1="Error: wrong answer type (multiple = -signs)";
String rem2="Mathematical error";
String rem3="Error: = sign forgotten";
double tmpsum=1.0D;
 
public void init(){
Font myfont = new Font("Helvetica", Font.BOLD, font_size);
setLayout(new GridLayout(4, 1));
input=new TextField(40);
input.setFont(myfont);add(input);setVisible(true);
arrowcolor=new Color(kleuren[now][0],kleuren[now][1],kleuren[now][2]);
param=getParameter("language");
if(param!=null && param.length()>0){
if(param.equalsIgnoreCase("nl")){
rem1="Fout:verkeerd type antwoord (meerdere = -tekens)";
rem2="Wiskundige fout";
rem3="Fout:je hebt het = teken vergeten";
}
if(param.equalsIgnoreCase("de")){
rem1="Fehler";
rem2="Mathematik Fehler";
rem3="Fehler: = Zeichen vergessen";
}
if(param.equalsIgnoreCase("fr")){
rem1="Erreur";
rem2="Erreur mathematique";
rem3="Erreur: vous avez oublié d'utiliser un = signe";
}
}
param=getParameter("title");
if(param!=null){title=param;}else{title="";}
param=getParameter("xmax");
if(param!=null && param.length()>0 ){xmax = Integer.parseInt(param, 10);}
// param=getParameter("xmin");
// if(param!=null){xmin = Integer.parseInt(param, 10);}
param=getParameter("fontsize");
if(param!=null && param.length()>0){font_size = Integer.parseInt(param, 10);}
param=getParameter("join");
if(param!=null){if(param.equals("1") || param.equalsIgnoreCase("yes")){join = true;}}
param=getParameter("exercise");
if(param!=null && param.length()>0){exercise = param; input.setText(exercise);}
param=getParameter("pencolor"); // foreground color of inputfield "input"
if (param != null && param.length()>0){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R1 = rgb;}
else if(a == 1){G1 = rgb;}
else if(a == 2){B1 = rgb;}
}
pencolor=new Color(R1,G1,B1);
input.setForeground(pencolor);
}
 
param=getParameter("bgcolor1"); // Background color of inputfield "input"
if (param != null && param.length()>0){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R1 = rgb;}
else if(a == 1){G1 = rgb;}
else if(a == 2){B1 = rgb;}
}
bgcolor1=new Color(R1,G1,B1);
input.setBackground(bgcolor1);
}
 
param=getParameter("bgcolor2"); // Background color of canvas
if (param != null && param.length()>0){
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R2 = rgb;}
else if(a == 1){G2 = rgb;}
else if(a == 2){B2 = rgb;}
}
bgcolor2=new Color(R2,G2,B2);
}
// needs changing !
xmin=-1*xmax;
xmax_org=xmax;
xmin_org=xmin;
minmax=Math.abs(xmax-xmin);
if(minmax == 0){xmax=25;xmin=-25;minmax=50;}
x_pix = getSize().width;
y_pix = getSize().height;
y_nul=(int)y_pix/4;
// xnul is at center for now
x_nul =(int) ((xmax-xmin)/2)*x_pix/(minmax); // x_nul is positie op graphics in pixels
step=(double)x_pix/(minmax);
input.requestFocus();
}
 
public boolean keyUp(Event event, int key){
prepare();
return true;
}
 
public void prepare(){
inputtext=input.getText();
int len=inputtext.length();
if(len>0){
boolean found = false; String last;
inputtext=inputtext.toLowerCase();
for(int i=0;i<44;i++){
inputtext=replace(inputtext,illegalchars[i],"");
}
inputtext=replace(inputtext,",",".");
inputtext=replace(inputtext,":","/");
inputtext=replace(inputtext,"*","\u2217");
inputtext=replace(inputtext,"x","\u2217");
input.setText(inputtext);
len=inputtext.length();
last = inputtext.substring(inputtext.length()-1,inputtext.length());
for(int i=0;i<10;i++){
if(last.equals(cijfers[i])){ found = true;}
}
if( found ){convert();}else{repaint();}
}
input.setCaretPosition(len);
input.requestFocus();
}
public void changecolor(){
now++;// 11 kleuren, niet meer...
if( now > 11 ){ now = (int) (11*(Math.random())); }
arrowcolor=new Color(kleuren[now][0],kleuren[now][1],kleuren[now][2]);
}
public void convert(){
// arity lib throws errors +-5-+3------23 etc
Symbols symbols=new Symbols();
String S=input.getText();
for(int s=0;s<10;s++){
S=replace(S,"+-","-");
S=replace(S,"-+","-");
S=replace(S,"--","+");
S=replace(S,"++","+");
}
S=replace(S,"/","@1/");
S=replace(S,"+","#+");
S=replace(S,"-","#-");
S=replace(S,"==","=");
S=replace(S,"=","#=#");
S=replace(S,"\u2217#+","@");
S=replace(S,"\u2217#-","@-");
S=replace(S,"\u2217","@");
//System.out.println("S in nu:"+S);
int L=S.length();
if(S != null || L > 0){
String tmp1[]=S.split("#");int n=0;int sign=1;double t1=1D;double t2=1D;
fragment =new double[L];
multiplication = new double[L];
int idx;
tmpsum=0;
for(int i=0;i<tmp1.length;i++){
if(tmp1[i].length()!=0){
if(tmp1[i].indexOf("=")!= -1){
multiplication[n]=-1;
fragment[n]=1.23456789;n++;
}
else
{
if(tmp1[i].indexOf("@")!=-1){
String tmp2[]=tmp1[i].split("@");
t1=Double.parseDouble(replace(tmp2[0],"+",""));
tmp2[1]=replace(tmp2[1],"--","");
if(tmp2[1].indexOf("/")!=-1){
try {
t2=symbols.eval(replace(tmp2[1],"+",""));
} catch (SyntaxException e) {
input.setText("?");System.out.println("error "+e+"\n caused by "+fragment[n]);
return;
}
}
else
{
t2=Double.parseDouble(replace(tmp2[1],"+",""));
}
if(t1<0){sign=-1;}else{sign=1;} // -5*3 -> -1*3 -1*3 -1*3 -1*3 -1*3
t1=Math.abs(t1);
for(int p=0;p<t1;p++){
if(n >= L){
idx=(int)(t1)+n;
L=idx;
fragment = GrowArray(fragment,idx,n);
multiplication = GrowArray(multiplication,idx,n);
}
multiplication[n]=1;
fragment[n]=sign*t2;n++;
}
}
else
{
multiplication[n] = 0;
try { fragment[n]=symbols.eval(tmp1[i]);n++;} catch (SyntaxException e) {input.setText("?");System.out.println("error "+e+"\n caused by "+fragment[n]); }
}
}
if(join){
tmpsum=tmpsum+(fragment[n-1]);
}else{
// if((Math.abs(fragment[n-1]))>(Math.abs(tmpsum))){tmpsum=Math.abs(fragment[n-1]);}
if((Math.abs(fragment[n]))>(Math.abs(tmpsum))){tmpsum=Math.abs(fragment[n]);}
}
}
}
start=true;
tmpsum=Math.abs(tmpsum);
if(tmpsum>1000){tmpsum=1000;}
double tmp;
if(tmpsum<100){
tmp=Math.ceil(tmpsum/10);
xmax=10*((int)tmp);
}
else
{
tmp=Math.ceil(tmpsum/100);
xmax=100*(int)(tmp);
}
xmin=-1*xmax;// let op nog steeds x=0 symmetrisch op x_pix/2
repaint();
}
}
public boolean action(Event event, Object currentTarget){
// enter ...not used for now
return true;
}
 
public void paint(Graphics g){
step=(double)x_pix/(xmax - xmin);
if(step == 0){step=1;}
now=0;int y=y_nul+vectors+60;double x1=0.0D;double x2=0.0D;double previous=0.0D;
g.setColor(bgcolor2);g.fillRect(0,y_nul,x_pix,y_pix);
if(start){
for(int p=0;p<fragment.length;p++){
x2=fragment[p];
if(multiplication[p] < 1){changecolor();}else{arrowcolor=new Color(255,30,30);}
if(x2 != 0.0){
if(x2 == 1.23456789){
y=y+arrowdistance;
tekenconclusie( 0, y , x_pix , y, g);
y=y+2*arrowdistance;
previous=x_nul;
x2=fragment[p+1];p++;
conclusion_drawn=true;
}
if(join){
if( p == 0){
x1=(double) x_nul;
x2=x1+(x2*step);
previous=x2;
}
else
{
x1=previous;
if(x1 == 0.0){x1=x_nul;}
x2=x1+(x2*step);
previous=x2;
}
}
else
{
x1=x_nul;
x2=x1+(x2*step);
}
tekenVector( (int)x1, y , (int)x2 , y, conclusion_drawn, g);
//System.out.println("x1="+x1+" x2="+x2+" x_nul="+x_nul);
y=y+arrowdistance;
}
}
}
drawSchaal(g);
input.requestFocus();
}
public void drawSchaal(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.setStroke( new BasicStroke(1.1f) );
g2.setColor(Color.black);
int t=0;int sc;
int sc1=(int)(Math.abs(xmin));
int sc2=(int)(Math.abs(xmax));
if(sc1 > sc1){sc=sc1;}else{sc=sc2;}
int[] i=new int[3];
int[] s=new int[3];
s[0]=30;
s[1]=20;
s[2]=10;
if(sc>0 && sc<11){
i[0]=5;
i[1]=1;
i[2]=1;
}
else
{
if(sc>10 && sc<51){
i[0]=10;
i[1]=5;
i[2]=1;
}
else
{
if(sc>50 && sc<101){
i[0]=20;
i[1]=10;
i[2]=2;
}
else
{
if(sc>100 && sc<501){
i[0]=50;
i[1]=25;
i[2]=5;
}
else
{ // sc<1000
i[0]=100;
i[1]=50;
i[2]=25;
}
}
}
}
if(xmax>0){
for(int r=0;r<3;r++){
for(int p=0;p<xmax;p=p+i[r]){
t=(int) ((p*x_pix/(xmax - xmin)) - xmin*x_pix/(xmax - xmin));
g2.drawLine(t,y_nul,t,y_nul+s[r]);
if(r==0){
g2.drawString(""+p+"",t-(g.getFontMetrics().stringWidth(" "+p+" "))/2,y_nul+50);
}
}
}
}
if(xmin<0){
for(int r=0;r<3;r++){
for(int p=0;p>xmin;p=p-i[r]){
t=(int) ((p*x_pix/(xmax - xmin)) - xmin*x_pix/(xmax - xmin));
g2.drawLine(t,y_nul,t,y_nul+s[r]);
if(r==0){
g2.drawString(""+p+"",t-(g.getFontMetrics().stringWidth(" "+p+" "))/2,y_nul+50);
}
}
}
}
}
 
public void tekenVector(int x1, int y1, int x2, int y2, boolean con ,Graphics g ){
double d = Math.atan((float)((double)(y1 - y2) / (double)(x1 - x2)));
Graphics2D g2 = (Graphics2D) g;
g2.setColor(arrowcolor);
if(Math.abs(x2-x1) < step*10){g2.setStroke( new BasicStroke(2.0f) );}else{g2.setStroke( new BasicStroke(3.0f) );}
if(x1 - x2 < 0){d += 3.1415926535897931D;}
g2.drawLine(x1, y1, x2, y2);
g2.drawLine(x2, y2, x2 + (int)(Math.cos(d + 0.6D) * 10D), y2 + (int)(Math.sin(d + 0.6D) * 10D));
g2.drawLine(x2, y2, x2 + (int)(Math.cos(d - 0.6D) * 10D), y2 + (int)(Math.sin(d - 0.6D) * 10D));
if(con){//we have drawn a dashed conclusion line : no we mark the and of the final ? arrow with a vertical line
g2.setStroke( new BasicStroke(4f) );
g2.setColor(Color.red);
g2.drawLine(x2,0,x2,y2);
conclusion_drawn=false;
}
 
}
 
public void tekenconclusie(int x1, int y1, int x2, int y2, Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(dashed);
g2.setColor(Color.black);
g2.drawLine(x1, y1, x2, y2);
}
public static int[] Shuffle(int[] S){
int ll= S.length;
for (int i=0;i<ll;i++){
int r = (int) (Math.random() * (i+1));
int swap = S[r];
S[r] = S[i];
S[i] = swap;
}
return S;
}
public static String replace(String source, String pattern, String replace){
if (source!=null){
final int len = pattern.length();
StringBuffer sb = new StringBuffer();
int found = -1;
int start = 0;
while( (found = source.indexOf(pattern, start) ) != -1){
sb.append(source.substring(start, found));
sb.append(replace);
start = found + len;
}
sb.append(source.substring(start));
return sb.toString();
}
else return "";
}
final static float dash1[] = {10.0f};
final static BasicStroke dashed = new BasicStroke(1.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10.0f, dash1, 0.0f);
 
public String ReadApplet(){
Symbols symbols=new Symbols();
String reply=input.getText();
reply=replace(reply,"\u2217","*");
String con=reply;
for(int s=0;s<10;s++){
con=replace(con,"+-","-");
con=replace(con,"-+","-");
con=replace(con,"--","+");
con=replace(con,"++","+");
}
String tmp[]=con.split("=");
// answer must be: 123 - 23 = 100 ...so a single = sign is expected
double r1=0.0;double r2=1.0;boolean answer = false;
if(tmp.length < 2){
reply="error \n"+rem3;input.setText(rem3);
}
else
{
if(tmp.length > 2){
reply="error \n"+rem1;input.setText(rem1);
}
else
{
String tmp0=tmp[0];// trouble with +5-4=+1
String tmp1=tmp[1];
if(tmp0.charAt(0)=='+'){tmp0=tmp0.substring(1,tmp0.length());}
if(tmp1.charAt(0)=='+'){tmp1=tmp1.substring(1,tmp1.length());}
try { r1=symbols.eval(tmp0);} catch (SyntaxException e) {input.setText(rem2);reply="error \n"+rem2;}
try { r2=symbols.eval(tmp1);} catch (SyntaxException e) {input.setText(rem2);reply="error \n"+rem2;}
if(r1 == r2){ answer = true;}else{ answer = false;}
}
}
return answer+","+reply;
}
public double[] GrowArray(double array[], int newlength ,int oldlength){
double[] grow;
grow = new double[ newlength ];
for(int i=0; i < oldlength; i++){
grow[i] = array[i];
//System.out.println("grow[p]="+grow[i]);
}
return grow;
}
public void start(){}
public void stop(){}
 
public void run(){}
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/GetallenLijn/build.xml
0,0 → 1,65
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for GetallenLijn.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="GetallenLijn" default="jar" basedir=".">
 
<description>GetallenLijn build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create GetallenLijn jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/GetallenLijn.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="GetallenLijn"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="GetallenLijn"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="GetallenLijn">
<attribute name="Specification-Title" value="GetallenLijn"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="GetallenLijn"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/KansBoom/build.xml
0,0 → 1,65
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for KansBoom.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="KansBoom" default="jar" basedir=".">
 
<description>KansBoom build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create KansBoom jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/KansBoom.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="KansBoom"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="KansBoom"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="KansBoom">
<attribute name="Specification-Title" value="KansBoom"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="KansBoom"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/KansBoom/test.html
0,0 → 1,72
 
<html>
<head>testing probability tree applet</head>
<body>
<script language="javascript" type="text/javascript">
function READTHIS(){
var applet_data=document.applets[0].ReadApplet(1);
 
<!--- ReadApplet(0) : gives textdata for probability tree -->
<!-- ReadApplet(whatever) gives all objects and coordinates -->
<!-- catch some errors before sending the data to wims -->
<!-- error_1 = unused_line_error -->
<!-- error_2 = too_few_items_per_line -->
<!-- error_3 = too_many_items_per_line -->
<!-- error_4 = inbalance_too_few_lines -->
<!-- error_5 = inbalance_too_many_lines -->
<!-- error_6 = text_missing -->
<!-- error_7 = lines_missing -->
comments=new Array();
comments=["Your answer (drawing) is empty ???",
"there are lines with no labels or numbers in your probability tree...",
"there are lines with not enough labels or numbers in your sketch...",
"there are lines with more than the nessecary labels and/or numbers in your drawing...",
"there are not enough lines to match the amount of labels/numbers in your answer... ",
"there are too many lines to match the amount of labels/numbers in your answer... ",
"You have forgotten to write the numbers and names in the tree...",
"You have forgotten to draw lines in the probability tree..."];
var remark="";
<!-- find some errorcode -->
for(p=0;p<8;p++){
if(applet_data.indexOf("error_"+p) != -1){remark="--> "+comments[p]+"\n"+remark;}
}
if(remark.length!=0){alert("I have some comments on Your drawing:\n"+remark);return;}
applet_data=applet_data.split("@");
var line_analysis=applet_data[1];
var reply=applet_data[0];
if(line_analysis.length!=0){
alert("this is the information about the drawing\n"+line_analysis);
}
alert("the applet will send to wims:\n"+reply);
}
</script>
<center>
<applet codebase="dist" code="KansBoom.class" archive="KansBoom.jar" width="640" height="480">
<param name="xsize" value="480">
<param name="ysize" value="480">
<param name="bgcolor" value="200,215,235">
<param name="textcolor" value="250,115,50">
<param name="drawcolor" value="50,50,150">
<param name="penthickness" value="6">
<param name="penfontsize" value="22">
<param name="penfontfamily" value="Helvetica">
<param name="penfontstyle" value="bold">
<param name="language" value="fr">
<param name="grid" value="yes"> <!-- will produce a grid -->
<param name="xmax" value="10"> <!-- will produce a grid -->
<param name="xmin" value="0"> <!-- will produce a grid -->
<param name="ymax" value="10"> <!-- will produce a grid -->
<param name="ymin" value="0"> <!-- will produce a grid -->
<param name="textlines" value="8"> <!-- number of lines in the applet: strings are bound to these lines leave blank or remove parma-tag to revert to original behaviour of the drawing applet -->
<param name="textalign" value="vertical"> <!-- probability tree orientation -->
</applet>
<input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:READTHIS();">
</body>
</html>
 
/trunk/wims/src/Misc/authors/jm.evers/applets/KansBoom/src/KansBoom.java
0,0 → 1,1195
/*
*********************************************************************************
* J.M. Evers 19/11/2009 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled classes derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
* Test html page:
* <html>
* <head></head>
* <body>
* <script language="javascript" type="text/javascript">
* function READTHIS(){
* var input=document.applets[0].ReadApplet();
* alert("the applet will send:\n"+input);
* }
* </script>
* <center>
* <applet code="KansBoom.class" archive="KansBoom.jar" width="600" height="400" MAYSCRIPT>
* <param name="xsize" value="380">
* <param name="ysize" value="380">
* <param name="bgcolor" value="255,255,255">
* <param name="textcolor" value="25,5,5">
* <param name="drawcolor" value="25,5,150">
* <param name="penthickness" value="6">
* <param name="penfontsize" value="66">
* <param name="penfontfamily" value="Courier">
* <param name="penfontstyle" value="bold">
* <param name="language" value="nl">
* <param name="textlines" value="10">
* <param name="textalign" value="horizontal">
* </applet>
* <input type="button" name=".....TEST......" value=".....TEST....." onclick="javascript:READTHIS();">
* </body>
* </html>
*
*
*/
import java.util.*;
import java.awt.*;
import java.applet.*;
 
/* The applet itself; contains a display, a control panel and a diagram */
 
public class KansBoom extends Applet {
Diagram diagram;
DiagramControls controls;
DiagramDisplay display;
MessageArea message;
EventConsumer current_event_consumer;
 
// jm.evers a few defaults...i'm no good at this java :(
static int xsize=640;
static int ysize=480;
static int ygrid=50;// default disabled : less than 50 "lines" of text enables the "snap to line"
static Color bgcolor=new Color(250,250,250);
static Color textcolor=new Color(255,0,0);
static Color drawcolor=new Color(150,0,250);
static float thickness=2.0f;
static int penfontsize=16;
static String fontfamily="Helvetica";
static Font penfont= new Font(fontfamily, Font.BOLD, penfontsize);
static Font zoomfont= new Font(fontfamily, Font.BOLD,penfontsize+6);
static Font messagefont= new Font(fontfamily, Font.BOLD,16);
public String t_line="Line";
public String t_arrow="Arrow";
public String t_rectangle="Rectangle";
public String t_ellipse="Ellipse";
public String t_text="Text";
public String t_circle="Circle";
public String t_destroy="Delete";
public String t_move="Move";
static String t_press="Press return to finish the text";
static boolean textalign=false; // horizontal [snap to y: sort to y] . otherwise vertical [snap to x:sort to x]
static int textcounter=0;
static int linecounter=0;
static boolean original=false;
 
//
public void init() {
String param;
param = getParameter("language");
if(param != null) {
if(param.equalsIgnoreCase("nl")){
t_line="lijn";
t_arrow="pijl";
t_rectangle="rechthoek";
t_ellipse="ellips";
t_text="tekst";
t_circle="cirkel";
t_destroy="wissen";
t_move="verplaatsen";
t_press="Druk op enter als de tekst klaar is";
}
if(param.equalsIgnoreCase("de")){
t_line="Linie";
t_arrow="Pfeil";
t_rectangle="Rechteck";
t_ellipse="Ellipse";
t_text="Text";
t_circle="Kreis";
t_destroy="löschen";
t_move="verlagern";
t_press="Drücken Sie auf \"Eingabe\" am Ende des Textes";
}
if(param.equalsIgnoreCase("fr")){
t_line="droite";
t_arrow="flèche";
t_rectangle="rectangle";
t_ellipse="ellips";
t_text="texte";
t_circle="cercle ";
t_destroy="effacer";
t_move="déplacer";
t_press="Press return to finish the text";
}
}
param = getParameter("penfontsize");
if(param != null) {penfontsize=Integer.parseInt(param,10); penfont= new Font("Helvetica", Font.BOLD, penfontsize);}
param = getParameter("penfontfamily");
if(param != null) {penfont= new Font(param, Font.BOLD, penfontsize);}
param = getParameter("penfontstyle");
if(param != null) {
if(param.equalsIgnoreCase("bold")){penfont= new Font(param, Font.BOLD , penfontsize);}
else if(param.equalsIgnoreCase("italic")){penfont= new Font(param, Font.ITALIC , penfontsize);}
else if(param.equalsIgnoreCase("plain")){penfont= new Font(param, Font.PLAIN , penfontsize);}
}
param = getParameter("penthickness");
if(param != null) {thickness=Float.parseFloat(param);}
param = getParameter("xsize");
if(param != null) {xsize=Integer.parseInt(param,10);}
param = getParameter("ysize");
if(param != null) {ysize=Integer.parseInt(param,10);}
param = getParameter("textlines");
if(param != null) {ygrid=Integer.parseInt(param,10);}
param = getParameter("textalign");
if(param == null || param.length()==0){original=true;}else{original=false;if(param.equalsIgnoreCase("vertical")){textalign=true;}else{textalign=false;}}
resize(xsize,ysize);
param=getParameter("bgcolor"); // Background color of inputfield "input"
if (param != null && param.length()>0){
int R1=255;int G1=255;int B1=255;
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R1 = rgb;}
else if(a == 1){G1 = rgb;}
else if(a == 2){B1 = rgb;}
}
bgcolor=new Color(R1,G1,B1);
}
param=getParameter("textcolor"); // Background color of inputfield "input"
if (param != null && param.length()>0){
int R2=255;int G2=0;int B2=0;
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R2 = rgb;}
else if(a == 1){G2 = rgb;}
else if(a == 2){B2 = rgb;}
}
textcolor=new Color(R2,G2,B2);
}
 
param=getParameter("drawcolor"); // Background color of inputfield "input"
if (param != null && param.length()>0){
int R3=255;int G3=255;int B3=0;
param=param.replace(':',',');param=param.replace(';',',');
StringTokenizer q = new StringTokenizer(param, ",");
String k;int rgb;
for( int a=0; a<3 ; a++){
k=q.nextToken();
rgb=Integer.parseInt(k, 10);
if(rgb<0){rgb=0;}
if(rgb>255){rgb=255;}
if(a == 0){R3 = rgb;}
else if(a == 1){G3 = rgb;}
else if(a == 2){B3 = rgb;}
}
drawcolor=new Color(R3,G3,B3);
}
diagram = new Diagram();
diagram.editor = this;
// no idea how to tell this class that the names are passed on as params in init...
add(controls = new DiagramControls(this ,t_line,t_arrow,t_rectangle,t_ellipse,t_text,t_circle,t_destroy,t_move));
add(display = new DiagramDisplay(this ,penfont,thickness,textcolor,drawcolor,zoomfont));
current_event_consumer = controls;
}
 
// jm.evers
public String ReadApplet(String arg){
String reply="";
if(arg.equals("1")){
// we sort the text, that should depict a probability tree
// if textaling=true the orientation of the drawing is vertical [left to right ,top to bottom]
// a
// b c
// d e f g
// becomes: a \n b,c \n d,e,f,g
// else we expect a horizontal probability tree [top to bottom, left to right]
// d
// b
// e
// a
// f
// c
// g
// becomes: a \n b,c \n d,e,f,g
String line_analysis="";
int[] text_x=new int[textcounter];
int[] text_y=new int[textcounter];
int[] line_x1=new int[linecounter];
int[] line_y1=new int[linecounter];
int[] line_x2=new int[linecounter];
int[] line_y2=new int[linecounter];
String[] tekst=new String[textcounter];
int real_text_length=0;String tmp="";
int real_line_length=0;int x1;int x2;int y1;int y2;
for(Enumeration e = diagram.elements(); e.hasMoreElements(); ){
DiagramItem item = (DiagramItem)e.nextElement();
if(item.specify_line_x1() != -1){
x1=item.specify_line_x1();
y1=item.specify_line_y1();
x2=item.specify_line_x2();
y2=item.specify_line_y2();
if( x1 != x2 && y1 != y2 ){// avoid line-dots to be send as lines/branches
line_x1[real_line_length] = x1;
line_y1[real_line_length] = y1;
line_x2[real_line_length] = x2;
line_y2[real_line_length] = y2;
real_line_length++;
}
}
if(item.specify_text() != null){
tmp = item.specify_text();
// remove the forgotten '_' and we can't use komma's in the reply...replace them by points ?
tmp =replace(tmp,"_"," ");
tekst[real_text_length] =replace(tmp,",",".");
text_x[real_text_length] = item.specify_text_x();
text_y[real_text_length] = item.specify_text_y();
real_text_length++;
}
}
boolean online=false;
String[] isonline=new String[real_line_length];boolean found=false;
int items=0;
for(int s=0;s<real_line_length;s++){
found=false;items=0;
for(int r=0;r<real_text_length;r++){
online=point_near_line(line_x1[s],line_y1[s],line_x2[s],line_y2[s],text_x[r],text_y[r],tekst[r]);
//System.out.println("tekst "+tekst[r]+" ligt op lijn "+s+" ? : "+online);
if(online){
found=true;
items++;
if(isonline[s] == null){
isonline[s]=tekst[r];
}
else
{
isonline[s]=tekst[r]+","+isonline[s];
}
}
}
if(!found){
isonline[s]="error_1";//unused_line_error
}
// this gives too many user_errors jm.evers 18/1/2009
// else
// {
// if(items==1){
// isonline[s]=isonline[s]+",error_2";//too_few_items_per_line
// }
// else
// {
// if(items>3){
// isonline[s]=isonline[s]+",error_3";}//too_many_items_per_line
// }
// }
}
for(int s=0;s<real_line_length;s++){
//System.out.println("line"+s+" : "+isonline[s]);
line_analysis=isonline[s]+"\n"+line_analysis;
}
if(real_text_length != 2*real_line_length){
if(real_text_length> 2*real_line_length){
line_analysis=line_analysis+"\nerror_4";//inbalance_too_few_lines
}
else
{
line_analysis=line_analysis+"\nerror_5";//inbalance_too_many_lines
}
}
if(real_text_length == 0){line_analysis=line_analysis+"\nerror_6";}//text_missing
if(real_line_length == 0){line_analysis=line_analysis+"\nerror_7";}//lines_missing
boolean nog_meer = true;int i=0;int temp_x;int temp_y;String temp_txt;
nog_meer = true;
String[] sameline = new String[real_text_length];
if(textalign){//horizonal probability tree
while (nog_meer) {
nog_meer = false;
for ( i=0; i<real_text_length-1; i++ ){
if ( text_y[i] < text_y[i+1] ){ sameline[i]="\n";}
if ( text_y[i] > text_y[i+1] ){
temp_y = text_y[i]; text_y[i] = text_y[i+1]; text_y[i+1] = temp_y;
temp_x = text_x[i]; text_x[i] = text_x[i+1]; text_x[i+1] = temp_x;
temp_txt = tekst[i]; tekst[i] = tekst[i+1]; tekst[i+1] = temp_txt;
nog_meer = true;
sameline[i]="\n";
}
if ( text_y[i] == text_y[i+1] ){
sameline[i]=",";
if( text_x[i] > text_x[i+1] ){
temp_y = text_y[i]; text_y[i] = text_y[i+1]; text_y[i+1] = temp_y;
temp_x = text_x[i]; text_x[i] = text_x[i+1]; text_x[i+1] = temp_x;
temp_txt = tekst[i]; tekst[i] = tekst[i+1]; tekst[i+1] = temp_txt;
nog_meer = true;
}
}
}
}
}
else
{//vertical probability tree
while (nog_meer) {
nog_meer = false;
for ( i=0; i<real_text_length-1; i++ ){
if ( text_x[i] < text_x[i+1] ){ sameline[i]="\n";}
if ( text_x[i] > text_x[i+1] ){
temp_y = text_y[i]; text_y[i] = text_y[i+1]; text_y[i+1] = temp_y;
temp_x = text_x[i]; text_x[i] = text_x[i+1]; text_x[i+1] = temp_x;
temp_txt = tekst[i]; tekst[i] = tekst[i+1]; tekst[i+1] = temp_txt;
nog_meer = true;
sameline[i]="\n";
}
if ( text_x[i] == text_x[i+1] ){
sameline[i]=",";
if( text_y[i] > text_y[i+1] ){
temp_y = text_y[i]; text_y[i] = text_y[i+1]; text_y[i+1] = temp_y;
temp_x = text_x[i]; text_x[i] = text_x[i+1]; text_x[i+1] = temp_x;
temp_txt = tekst[i]; tekst[i] = tekst[i+1]; tekst[i+1] = temp_txt;
nog_meer = true;
}
}
}
}
}
 
for(i=0;i<real_text_length;i++){
if(sameline[i] == null){sameline[i]="\n";}
//reply=reply+tekst[i]+","+text_x[i]+","+text_y[i]+sameline[i];
reply=reply+tekst[i]+sameline[i];
}
reply=reply+"\n@\n"+line_analysis;
}
else
{
//alldata...no special sorting of the text
for(Enumeration e = diagram.elements(); e.hasMoreElements(); ){
DiagramItem item = (DiagramItem)e.nextElement();
reply=reply+item.describe()+"\n";
}
}
 
return reply;
}
// replace compatible with java 1.4 [B. Perrin-Riou]
public static String replace(String source, String pattern, String replace){
if (source!=null){
final int len = pattern.length();
StringBuffer sb = new StringBuffer();
int found = -1;
int start = 0;
while( (found = source.indexOf(pattern, start) ) != -1){
sb.append(source.substring(start, found));
sb.append(replace);
start = found + len;
}
sb.append(source.substring(start));
return sb.toString();
}
else return "";
}
// NOT READY: CHECK WHICH POINTS ARE "CONNECTED" WITH THE DRAWN LINES >>>> VERY TRICKY:
// /\
// / \
// A \ B
// / \
// / C D\
// /\ /\
// / \ / \
// E F\ G \H
// / \ / \
public boolean point_near_line(int lx1, int ly1 , int lx2, int ly2, int px , int py,String text){
// measure distance from point...eg text to a line ,describe by the two end-points
// close enough ? is 4 times the fontsize in pixels: so the margin would be 8xfm ??
// very likely to interfere with sloppy drawings, expected from pupils...
FontMetrics fm =getFontMetrics(penfont);
int w = fm.stringWidth(text);
w=(int)(Math.ceil(w/2));
//System.out.println("x-center begin = "+px);
px=px+w;// px is now the x-center of the string
//System.out.println("x-center = "+px);
int distance;double ys;double xs;
if( (py > (ly1 - w) && py < (ly2 + w)) || (py > (ly2 - w) && py < (ly1 + w)) ){
if( (px > (lx1 - 2*w) && px < (lx2 + 2*w)) || ( px > (lx2 - 2*w) && px < (lx1 + 2*w)) ){
// the point is in the rect x1y1,x2y2
if( (ly2 - ly1) == 0){
System.out.println("Horizontal line "); return false;
}
else
{
if( (lx2 - lx1) == 0 ){
System.out.println("Vertical line "); return false;
}
else
{
ys = (double)(((double)( (px-lx1)*(ly2-ly1)*(lx2-lx1)+(ly2-ly1)*(ly2-ly1)*py+(lx2-lx1)*(lx2-lx1)*ly1 ))/((double)((lx2-lx1)*(lx2-lx1)+(ly2-ly1)*(ly2-ly1))));
xs = (double)((double)(px))+ys*((double)( (double)(ly1-ly2))/((double)(lx2-lx1))) + ((double)py)*((double)( (double)(ly2-ly1))/((double)(lx2-lx1)));
distance=(int)(Math.sqrt( (ys - py)*(ys - py) + (xs - px)*(xs - px) ));
if(distance < 2*w ){return true;}else{return false;}
}
}
}
}
return false;
}
 
public void start() {
}
 
public void stop() {
}
 
public void destroy() {
}
 
public static void main(String argv[]) {
/* This more-or-less replicates what happens when we are run as an applet. */
Frame f = new Frame();
KansBoom d = new KansBoom();
d.init();
d.start();
f.add("Center", d);
f.show();
}
}
/* end applet */
 
 
 
/* The diagram */
 
class Diagram extends Vector {
KansBoom editor;
DiagramItem nearby(int x, int y){
DiagramItem bestitem = null;
double bestdist = 6;
for(Enumeration e = elements(); e.hasMoreElements(); ) {
DiagramItem item = (DiagramItem)e.nextElement();
double dist = item.distance(x, y);
if(dist < bestdist) {
bestitem = item;
bestdist = dist;
}
}
return bestitem;
}
 
}
 
 
/* The drawing area */
 
class DiagramDisplay extends Canvas {
KansBoom editor;
DiagramDisplay(KansBoom ed ,Font penfont, float thickness,Color textcolor,Color drawcolor, Font zoomfont){
editor = ed;
setBackground(KansBoom.bgcolor);
resize(KansBoom.xsize,KansBoom.ysize);
}
 
 
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setFont(KansBoom.penfont);
g2.setStroke( new BasicStroke(KansBoom.thickness));
g2.setColor(KansBoom.drawcolor);
for(Enumeration e = editor.diagram.elements(); e.hasMoreElements(); ) {
((DiagramItem)e.nextElement()).draw(g2);
}
}
 
public boolean mouseDown(Event e, int x, int y){
if(editor.current_event_consumer.down(x, y)){
repaint();
return true;
}
else
{
return false;
}
}
 
public boolean mouseUp(Event e, int x, int y){
if(editor.current_event_consumer.up(x, y)){
repaint();
return true;
}
else
{
return false;
}
}
 
public boolean mouseDrag(Event e, int x, int y){
if(editor.current_event_consumer.drag(x, y)){
repaint();
return true;
}
else
{
return false;
}
}
 
public boolean keyDown(Event e, int key){
if(editor.current_event_consumer.key(key)){
repaint();
return true;
}
else
{
return false;
}
}
}
 
/* The control panel and the diagram items do things in response to input */
 
interface EventConsumer {
public boolean down(int x, int y);
public boolean up(int x, int y);
public boolean drag(int x, int y);
public boolean key(int key);
public void yield();
}
 
/* The control panel */
 
class DiagramControls extends Panel implements EventConsumer {
KansBoom editor;
CheckboxGroup buttons;
Checkbox line, arrow, rect, ellipse, text, destroy, move;
final int CREATE = 0, DESTROY = 1, MOVE = 2;
 
DiagramControls(KansBoom ed ,String t_line,String t_arrow,String t_rectangle,String t_ellipse,String t_text,String t_circle,String t_destroy,String t_move) {
editor = ed;
setBackground(Color.white);
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
Component button;
setLayout(gridbag);
buttons = new CheckboxGroup();
c.gridy = 0;
c.gridx = GridBagConstraints.RELATIVE;
c.anchor = GridBagConstraints.WEST;
button = new DiagramControl(this, CREATE, (new Line()).getClass(), t_line , true);
gridbag.setConstraints(button, c);
add(button);
button = new DiagramControl(this, CREATE, (new Arrow()).getClass(), t_arrow , false);
gridbag.setConstraints(button, c);
add(button);
button = new DiagramControl(this, CREATE, (new Rect()).getClass(), t_rectangle, false);
gridbag.setConstraints(button, c);
add(button);
button = new DiagramControl(this, CREATE, (new Ellipse()).getClass(), t_ellipse , false);
gridbag.setConstraints(button, c);
add(button);
button = new DiagramControl(this, CREATE, (new Text()).getClass(), t_text , false);
gridbag.setConstraints(button, c);
add(button);
c.gridy = 1;
button = new DiagramControl(this, DESTROY, (new Object()).getClass(), t_destroy , false);
gridbag.setConstraints(button, c);
add(button);
button = new DiagramControl(this, MOVE, (new Object()).getClass(), t_move , false);
gridbag.setConstraints(button, c);
add(button);
 
}
public boolean down(int x, int y) {
DiagramControl current_button = (DiagramControl)buttons.getCurrent();
DiagramItem target;
Diagram diagram = editor.diagram;
editor.showStatus("");
switch(current_button.mode) {
case CREATE:
try {
Class class_ = current_button.class_;
target = (DiagramItem)class_.newInstance();
target.diagram = diagram;
target.create();
editor.current_event_consumer = target;
diagram.addElement(target);
target.down(x, y);
}
catch (InstantiationException ex) {}
catch (IllegalAccessException ex) {}
return true;
case DESTROY:
target = diagram.nearby(x, y);
if(target != null) {diagram.removeElement(target);target.destroy();}
return true;
case MOVE:
target = diagram.nearby(x, y);
if(target != null) {target.move();editor.current_event_consumer = target;target.down(x, y);}
return false;
default:
return false;
}
}
 
public boolean up(int x, int y) {
return false;
}
 
public boolean drag(int x, int y) {
return false;
}
 
public boolean key(int key) {
return false;
}
 
public boolean keyDown(Event e, int key) {
/* For some reason we get the canvas key presses. Pass them on XXX */
return editor.display.keyDown(e, key);
}
 
public void yield() {}
}
 
/* The buttons in the control panel */
 
class DiagramControl extends Checkbox {
int mode;
Class class_;
DiagramControl(DiagramControls parent, int _mode, Class _class, String label, boolean state) {
super(label, parent.buttons, state);
mode = _mode;
class_ = _class;
}
}
 
 
/* The diagram items.
* The methods implemented here are suitable for shapes defined by two
* points (ends of a line, corners of an ellipse's bounding box). Other
* shapes should override. Maybe I should use a subclass for this, but
* some of the methods may be useful for other shapes (text could use
* these methods for moving but not creating; it would be nice to store the
* state just by switching the methods).
*/
 
abstract class DiagramItem implements EventConsumer {
Diagram diagram;
int state;
final int NONE=0, CREATE=1, MOVE=2;
int x, y, w, h;
int movex, movey;
DiagramItem() {
x = y = w = h = 0;
}
 
DiagramItem(StringTokenizer tok) throws Exception {
if(tok.countTokens() != 4)
throw new IllegalArgumentException();
x = (new Integer(tok.nextToken())).intValue();
y = (new Integer(tok.nextToken())).intValue();
w = (new Integer(tok.nextToken())).intValue();
h = (new Integer(tok.nextToken())).intValue();
}
 
abstract void draw(Graphics g);
abstract String describe();
abstract String specify_text();
abstract int specify_text_x();
abstract int specify_text_y();
abstract int specify_line_x1();
abstract int specify_line_y1();
abstract int specify_line_x2();
abstract int specify_line_y2();
 
void create() {
state = CREATE;
}
 
public void yield() {
diagram.editor.current_event_consumer = diagram.editor.controls;
state = NONE;
}
 
void destroy() {}
 
void move() {
state = MOVE;
}
 
public boolean down(int _x, int _y) {
switch(state){
case CREATE:
x = _x; y = _y;
return true;
case MOVE:
movex = _x; movey = _y;
return true;
}
return false;
}
 
public boolean up(int _x, int _y) {
switch(state){
case CREATE:
w = _x - x; h = _y - y;
yield();
return true;
case MOVE:
x += (_x - movex);
y += (_y - movey);
yield();
return true;
}
return false;
}
 
public boolean drag(int _x, int _y) {
switch(state){
case CREATE:
w = _x - x; h = _y - y;
return true;
case MOVE:
x += (_x - movex);
y += (_y - movey);
movex = _x;
movey = _y;
return true;
}
return false;
}
 
public boolean key(int key) {
return false;
}
 
abstract double distance(int x, int y);
}
 
class Ellipse extends DiagramItem {
Ellipse(){super();}
Ellipse(StringTokenizer tok) throws Exception {super(tok);}
String describe() {return "ellipse," + x + "," + y + "," + w + "," + h;}
String specify_text() {return null; }
int specify_text_x() {return -1; }
int specify_text_y() {return -1; }
int specify_line_x1(){return -1;}
int specify_line_y1(){return -1;}
int specify_line_x2(){return -1;}
int specify_line_y2(){return -1;}
void draw(Graphics g) {
g.drawOval(x, y, w, h);
}
double distance(int _x, int _y) {
/* Do this better! */
float ww = w < 1 ? 1 : w, hh = h < 1 ? 1 : h;
float yscale = ww/hh;
float xx = _x - (x + ww / 2);
float yy = (_y - (y + hh / 2)) * yscale;
double r = Math.sqrt(xx * xx + yy * yy);
return Math.abs(r - ww / 2);
}
}
 
/* The class name Rectangle is already taken :-( */
 
class Rect extends DiagramItem {
Rect(){super();}
Rect(StringTokenizer tok) throws Exception { super(tok);}
 
String describe() {return "rectangle," + x + "," + y + "," + (x+w) + "," + (y+h);}
String specify_text() {return null; }
int specify_text_x() {return -1; }
int specify_text_y() {return -1; }
int specify_line_x1(){return -1;}
int specify_line_y1(){return -1;}
int specify_line_x2(){return -1;}
int specify_line_y2(){return -1;}
 
void draw(Graphics g) {
g.drawLine(x , y , x+w, y );
g.drawLine(x+w, y , x+w, y+h);
g.drawLine(x+w, y+h, x , y+h);
g.drawLine(x , y+h, x , y );
}
 
double distance(int _x, int _y) {
double dtop, dbottom, dleft, dright, dist;
if(_x < x){
dtop = Misc.distance(_x, _y, x, y);
}
else
{
if(_x > x+w){
dtop = Misc.distance(_x, _y, x+w, y);
}
else
{
dtop = Math.abs(_y - y);
}
}
if(_x < x){
dbottom = Misc.distance(_x, _y, x, y+h);
}
else
{
if(_x > x+w){
dbottom = Misc.distance(_x, _y, x+w, y+h);
}
else
{
dbottom = Math.abs(_y - (y+h));
}
}
if(_y < y)
dleft = Misc.distance(_x, _y, x, y);
else if(_y > y+h)
dleft = Misc.distance(_x, _y, x, y+h);
else
dleft = Math.abs(_x - x);
if(_y < y)
dright = Misc.distance(_x, _y, x+w, y);
else if(_y > y+h)
dright = Misc.distance(_x, _y, x+w, y+h);
else
dright = Math.abs(_x - (x+w));
 
dist = dtop;
if(dbottom < dist){dist = dbottom;}
if(dleft < dist){dist = dleft;}
if(dright < dist){dist = dright;}
return dist;
}
}
 
class Line extends DiagramItem {
Line() {super();}
Line(StringTokenizer tok) throws Exception {super(tok);}
void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
if(!KansBoom.original){
int dy=(int) KansBoom.ysize / KansBoom.ygrid;
int dx=(int) KansBoom.xsize / KansBoom.ygrid;
if(state != 2){
y=dy*((int) Math.round(y/dy));
h=dy*((int) Math.round(h/dy));
}
if(state == 1 || state == 2){
g2.setColor(KansBoom.textcolor);
g2.setStroke( new BasicStroke(1.0f));
if(KansBoom.textalign){
for(int p=0;p<KansBoom.ysize;p=p+dy){
g2.drawLine(0,p,KansBoom.xsize,p);
}
}
else
{
for(int p=0;p<KansBoom.xsize;p=p+dx){
g2.drawLine(p,0,p,KansBoom.ysize);
}
}
}
}
g2.setColor(KansBoom.drawcolor);
g2.setStroke( new BasicStroke(KansBoom.thickness));
g2.drawLine(x, y, x+w, y+h);
KansBoom.linecounter++;
}
String describe() {return "line," + x + "," + y + "," + (x+w) + "," + (y+h);}
String specify_text() {return null; }
int specify_text_x(){return -1; }
int specify_text_y(){return -1; }
int specify_line_x1(){return x;}
int specify_line_y1(){return y;}
int specify_line_x2(){return (x+w);}
int specify_line_y2(){return (y+h);}
 
double distance(int _x, int _y) {
if(w == 0 && h == 0)
return Misc.distance(x, y, _x, _y);
/* Set origin to end of line */
_x -= x;
_y -= y;
/* Find line length and unit vector along line */
double len = Math.sqrt(w*w + h*h);
double u = w / len;
double v = h / len;
/* Find nearest point on line using dot product */
double r = _x * u + _y * v;
if(r < 0)
return Misc.distance(0, 0, _x, _y);
if(r > len)
return Misc.distance(w, h, _x, _y);
return Misc.distance(r * u, r * v, _x, _y);
}
}
 
class Arrow extends Line {
Arrow(){super();}
Arrow(StringTokenizer tok) throws Exception { super(tok);}
void draw(Graphics g) {
/* Draw a line */
Graphics2D g2 = (Graphics2D) g;
if(!KansBoom.original){
int dy=(int) KansBoom.ysize / KansBoom.ygrid;
int dx=(int) KansBoom.xsize / KansBoom.ygrid;
if( state != 2){
y=dy*((int) Math.round(y/dy));
h=dy*((int) Math.round(h/dy));
}
if(state == 1 || state == 2){
g2.setColor(KansBoom.textcolor);
g2.setStroke( new BasicStroke(1.0f));
if(KansBoom.textalign){
for(int p=0;p<KansBoom.ysize;p=p+dy){
g2.drawLine(0,p,KansBoom.xsize,p);
}
}
else
{
for(int p=0;p<KansBoom.xsize;p=p+dx){
g2.drawLine(p,0,p,KansBoom.ysize);
}
}
}
}
KansBoom.linecounter++;
g2.setColor(KansBoom.drawcolor);
g2.setStroke( new BasicStroke(KansBoom.thickness));
g2.drawLine(x, y, x+w, y+h);
if(w == 0 && h == 0){return;}
/* Find unit vector along line */
double len = Math.sqrt(w*w + h*h);
double u = w / len;
double v = h / len;
 
/* Draw arrow head */
double _x = x + w - 5 * u;
double _y = y + h - 5 * v;
g2.drawLine(x+w, y+h, (int)(_x - 5 * v + 0.5), (int)(_y + 5 * u + 0.5));
g2.drawLine(x+w, y+h, (int)(_x + 5 * v + 0.5), (int)(_y - 5 * u + 0.5));
}
String describe() {return "arrow," + x + "," + y + "," + (x+w) + "," +(y+h);}
String specify_text() {return null; }
int specify_text_x() {return -1; }
int specify_text_y() {return -1; }
int specify_line_x1(){return x;}
int specify_line_y1(){return y;}
int specify_line_x2(){return (x+w);}
int specify_line_y2(){return (y+h);}
 
}
 
class Text extends DiagramItem {
String text;
StringBuffer buffer;
Text() {
x = y = 0;
buffer = new StringBuffer();
text = buffer.toString().concat("_");
}
 
Text(StringTokenizer tok) throws Exception {
if(tok.countTokens() < 1){throw new IllegalArgumentException();}
x = (new Integer(tok.nextToken())).intValue();
y = (new Integer(tok.nextToken())).intValue();
text = tok.nextToken("\n\r").trim();
 
}
 
void create() {
super.create();
diagram.editor.controls.disable();
//diagram.editor.showStatus("Press return to finish string");
diagram.editor.showStatus(KansBoom.t_press);
KansBoom.textcounter++;
}
 
public void yield() {
super.yield();
diagram.editor.controls.enable();
text = buffer.toString();
}
 
String describe() {
return "text," + x + "," + y + "," + text;
}
String specify_text() {return text; }
int specify_text_x() {return x; }
int specify_text_y() {return y; }
int specify_line_x1(){return -1;}
int specify_line_y1(){return -1;}
int specify_line_x2(){return -1;}
int specify_line_y2(){return -1;}
 
void draw(Graphics g) {
//jm.evers
if(!KansBoom.original){
Graphics2D g2 = (Graphics2D) g;
int dy=(int) KansBoom.ysize / KansBoom.ygrid;
int dx=(int) KansBoom.xsize / KansBoom.ygrid;
if(state == 1 || state == 2){//show a temp grid lines
g2.setColor(KansBoom.drawcolor);
g2.setStroke( new BasicStroke(1.0f));
if(KansBoom.textalign){for(int p=0;p<KansBoom.ysize;p=p+dy){g2.drawLine(0,p,KansBoom.xsize,p);}}
else{for(int p=0;p<KansBoom.xsize;p=p+dx){g2.drawLine(p,0,p,KansBoom.ysize);}}
g2.setFont(KansBoom.zoomfont);
}
else
{
g2.setFont(KansBoom.penfont);
}
if(state != 2){ // not while dragging
if(KansBoom.ygrid<50 && KansBoom.ygrid>1){
if(KansBoom.textalign){// then snap to the nearest vertical line...
y=dy*((int) (Math.round(y/dy)));
if(y<dy){y=dy;}
if(y>KansBoom.ysize-dy){y=KansBoom.ysize-dy;}
}
else
{//snap to the nearest horizontal line...
x=dx*((int) (Math.round(x/dx)));
if(x<dx){x=dx;}
if(x>KansBoom.xsize-dx){x=KansBoom.xsize-dx;}
}
}
}
g2.setColor(KansBoom.textcolor);
g2.setStroke( new BasicStroke(KansBoom.thickness));
g2.drawString(text, x, y);
g2.setColor(KansBoom.drawcolor);
}
else
{
g.drawString(text, x, y);
}
}
double distance(int _x, int _y) {
FontMetrics fm = diagram.editor.display.getGraphics().getFontMetrics();
int m = y - (fm.getAscent() / 2);
if(_x < x){return Misc.distance(x, m, _x, _y);}
int r = x + fm.stringWidth(text);
if(_x > r){return Misc.distance(r, m, _x, _y);}
return Math.abs(_y - m);
}
 
public boolean down(int _x, int _y) {
switch(state) {
case CREATE:
x = _x; y = _y;
return true;
case MOVE:
return super.down(_x, _y);
}
return false;
}
 
public boolean up(int _x, int _y) {
switch(state) {
case CREATE:
x = _x; y = _y;
return true;
case MOVE:
return super.up(_x, _y);
}
return false;
}
 
public boolean drag(int _x, int _y) {
switch(state) {
case CREATE:
x = _x; y = _y;
return true;
case MOVE:
return super.drag(_x, _y);
}
return false;
}
 
public boolean key(int key) {
char c[] = new char[1];
switch(state) {
case CREATE:
switch(key) {
case 10:/* LF */
 
case 13:/* CR */
yield();
if(text.equals("")){
diagram.removeElement(this);
destroy();
diagram.editor.showStatus("String was empty");
}
else
diagram.editor.showStatus("");
return true;
case 8:/* BS */
case 127:/* DEL */
int l = buffer.length();
if(l > 0)
buffer.setLength(l - 1);
break;
default:
buffer.append((char)key);
break;
}
text = buffer.toString().concat("_");
return true;
}
return false;
}
}
 
/* An area for displaying messages */
 
class MessageArea extends Canvas {
String text = "";
void setText(String s) {
text = s;
repaint();
}
 
public void paint(Graphics g) {
setBackground(KansBoom.bgcolor);
//g.setFont(KansBoom.messagefont);
g.drawString(text,5,20);
}
}
 
 
/* Handy functions */
 
class Misc {
static double distance(double x1, double y1, double x2, double y2) {
return Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/noninput/build.xml
0,0 → 1,64
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for noninput.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="noninput" default="jar" basedir=".">
 
<description>noninput build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create noninput jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/noninput.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="noninput"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="noninput"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="noninput">
<attribute name="Specification-Title" value="noninput"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="noninput"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/noninput/src/noninput.java
0,0 → 1,390
/* Copyright (C) 1998 XIAO, Gang of Universite de Nice - Sophia Antipolis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
slightly modified [crippled] by jm.evers
applet does not send any data to wims....
*/
 
import java.awt.event.*;
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.applet.*;
import java.util.Vector;
 
public class noninput extends Applet{
inp_panel panel;
inp_controls controls;
Image bg;
Color bgcolor;
/* String replystring;
public static String prompt="OK";
public static String retry="Erase";*/
URL backurl;
 
public void init() {
URL url;
String parmstr;
parmstr=getParameter("type");
if(parmstr!=null && parmstr.length()>0) {
parmstr.toLowerCase(); parmstr.trim();
if(parmstr.compareTo("curve")==0) inp_panel.ctype=inp_panel.CURVE;
if(parmstr.compareTo("rectangle")==0) inp_panel.ctype=inp_panel.RECT;
if(parmstr.compareTo("rect")==0) inp_panel.ctype=inp_panel.RECT;
if(parmstr.compareTo("circle")==0) inp_panel.ctype=inp_panel.CIRCLE;
if(parmstr.compareTo("lines")==0) inp_panel.ctype=inp_panel.LINES;
if(parmstr.compareTo("segments")==0) inp_panel.ctype=inp_panel.LINES;
if(parmstr.compareTo("line")==0) inp_panel.ctype=inp_panel.LINE;
if(parmstr.compareTo("sline")==0) inp_panel.ctype=inp_panel.SLINE;
if(parmstr.compareTo("semiline")==0) inp_panel.ctype=inp_panel.SLINE;
if(parmstr.compareTo("seg")==0) inp_panel.ctype=inp_panel.SEG;
if(parmstr.compareTo("segment")==0) inp_panel.ctype=inp_panel.SEG;
if(parmstr.compareTo("poly")==0) inp_panel.ctype=inp_panel.POLY;
if(parmstr.compareTo("polygon")==0) inp_panel.ctype=inp_panel.POLY;
if(parmstr.compareTo("points")==0) inp_panel.ctype=inp_panel.POINTS;
}
parmstr=getParameter("background");
if (parmstr!=null && parmstr.length()>0) {
try {url=new URL(parmstr);}
catch (MalformedURLException e) {url=null;}
if(url!=null) bg=getImage(url);
else bg=null;
}
else bg=null;
parmstr=getParameter("bgcolor");
if(parmstr!=null && parmstr.length()>0) {
bgcolor=Color.decode(parmstr);
if(bgcolor==null) bgcolor=Color.white;
}
else bgcolor=Color.white;
/* parmstr=getParameter("retry");
if(parmstr!=null && parmstr.length()>0) {
retry=parmstr;
}*/
/* parmstr=getParameter("prompt");
if(parmstr!=null && parmstr.length()>0) {
prompt=parmstr;
}*/
setLayout(new BorderLayout());
panel=new inp_panel(bgcolor,bg);
controls=new inp_controls(panel,this);
add("Center", panel);
/*add("South",controls);*/
}
 
public void destroy() {
remove(panel);
/*remove(controls);*/
}
 
public static void main(String args[]) {
Frame f=new Frame("input");
noninput noninput=new noninput();
noninput.init();
noninput.start();
 
f.add("Center", noninput);
f.setVisible(true);
}
 
public String getAppletInfo() {
return "Curve input program for WIMS.";
}
}
 
class inp_panel extends Panel implements MouseListener, MouseMotionListener {
public static final int CURVE=0, RECT=1, CIRCLE=2, LINES=3, LINE=4,
SLINE=5,SEG=6,POLY=7,POINTS=8;
public static int ctype;
static int ll=4;
Image bg;
Vector lines=new Vector(16384);
int x1,y1;
int x2,y2;
int radius;
int drag;
int st;
 
public inp_panel(Color bgcolor,Image gotbg) {
setBackground(bgcolor);
setForeground(Color.black);
bg=gotbg;
addMouseMotionListener(this);
addMouseListener(this);
st=0;
}
/* public String points2string(String rep) {
StringBuffer buf=new StringBuffer(16384);
buf.append(rep);
switch(ctype) {
case POLY:
case POINTS:
case LINES:
case CURVE: {
int i, np;
Point p=null;
np=lines.size();
for(i=0;i<np;i++) {
p=(Point)lines.elementAt(i);
buf.append(p.x).append(",").append(p.y).append(";");
}
break;
}
case SLINE:
case LINE:
case SEG:
case RECT: {
if(st>0) {
buf.append(x1).append(",").append(y1).append(",").append(x2).append(",").append(y2);
}
break;
}
case CIRCLE: {
if(st>0) {
buf.append(x1).append(",").append(y1).append(",").append(radius);
}
break;
}
}
return buf.toString();
}
*/
public void retry() {
lines.removeAllElements();
st=0; repaint();
}
 
public void mouseDragged(MouseEvent e) {
int t=lines.size();
int dr;
e.consume();
switch(ctype) {
case CURVE: {
if(t<2000) {
x1=e.getX(); y1=e.getY();
lines.addElement(new Point(x1, y1));
repaint();
}
st=2; return;
}
default: {
dr=drag; mouseMoved(e); drag=dr+1;
return;
}
}
}
 
public void mouseMoved(MouseEvent e) {
e.consume(); drag=0;
switch(ctype) {
case POLY:
case POINTS:
case LINES:
case CURVE: {
if(st==0) return; else st=1;
x2=e.getX(); y2=e.getY(); break;
}
case CIRCLE:
case SLINE:
case LINE:
case SEG:
case RECT: {
if(st!=1) return;
x2=e.getX(); y2=e.getY();
radius=(int) Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
break;
}
default: return;
}
if(ctype!=POINTS) repaint();
}
 
public void mousePressed(MouseEvent e) {
e.consume();
switch(ctype) {
case CURVE: {
if(st>0) return;
x1=e.getX(); y1=e.getY(); x2=x1; y2=y1;
lines.removeAllElements();
lines.addElement(new Point(x1,y1));
repaint(); st=2;
return;
}
case POLY:
case POINTS:
case LINES: {
x2=e.getX(); y2=e.getY();
if(st==0) lines.removeAllElements();
lines.addElement(new Point(x2,y2));
st=1; x1=x2; y1=y2; repaint(); return;
}
case CIRCLE:
case SLINE:
case LINE:
case SEG:
case RECT: {
x2=e.getX(); y2=e.getY();
switch(st) {
case 2:
case 0: x1=x2; y1=y2; radius=0; st=1; repaint(); return;
case 1: {
radius=(int) Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
st=2; return;
}
}
break;
}
default: return;
}
}
 
public void mouseReleased(MouseEvent e) {
e.consume();
switch(ctype) {
case CURVE: {
if(st==2) return;
x2=e.getX(); y2=e.getY();
if(st==0) lines.removeAllElements();
lines.addElement(new Point(x2,y2));
st=1; x1=x2; y1=y2;
return;
}
case POINTS: return;
default: {
if(st>0 && drag>=8) mousePressed(e);
return;
}
}
}
 
public void mouseEntered(MouseEvent e) {
}
 
public void mouseExited(MouseEvent e) {
if(ctype!=CURVE && ctype!=LINES && ctype!=POLY) return;
e.consume();
x2=x1; y2=y1; if(st>0) repaint();
}
 
public void mouseClicked(MouseEvent e) {
}
 
public void paint(Graphics g) {
int np=lines.size();
Point pp;
 
if(bg!=null) g.drawImage(bg,0,0,this);
switch(ctype) {
case POINTS: {
if(np>0) for (int i=0; i < np; i++)
pointPaint(g,(Point)lines.elementAt(i));
break;
}
case POLY:
case CURVE:
case LINES: {
if(np>0) {
pp=(Point)lines.elementAt(0);
for (int i=1; i < np; i++) {
Point p=(Point)lines.elementAt(i);
g.drawLine(pp.x, pp.y, p.x, p.y);
pp=p;
}
if (st==1) g.drawLine(x1, y1, x2, y2);
}
if(ctype==POLY && np>1) {
Point p1=(Point)lines.elementAt(0);
Point p2=(Point)lines.elementAt(np-1);
if(st==0) g.drawLine(p1.x,p1.y,p2.x,p2.y);
else g.drawLine(p1.x,p1.y,x2,y2);
}
break;
}
case SEG:
case SLINE:
case LINE:
case RECT: {
if(st>0) {
int xx1,yy1,xx2,yy2;
int X1,Y1,X2,Y2,max;
xx1=Math.min(x1,x2); yy1=Math.min(y1,y2);
xx2=Math.max(x1,x2); yy2=Math.max(y1,y2);
max=Math.max(Math.abs(x2-x1),Math.abs(y2-y1));
if(max<10) max=10;
max=500/max+1;
switch(ctype) {
case RECT: g.drawRect(xx1,yy1,xx2-xx1,yy2-yy1); break;
case SLINE: {
g.fillOval(x1-2,y1-2,4,4);
g.drawLine(x1,y1,max*x2-(max-1)*x1,max*y2-(max-1)*y1); break;
}
case LINE: {
g.fillOval(x1-2,y1-2,4,4);
g.fillOval(x2-2,y2-2,4,4);
g.drawLine(max*x1-(max-1)*x2,max*y1-(max-1)*y2,
max*x2-(max-1)*x1,max*y2-(max-1)*y1); break;
}
case SEG: g.drawLine(x1,y1,x2,y2); break;
}
}
break;
}
case CIRCLE: {
if(st>0) {
pointPaint(g,new Point(x1,y1));
g.drawOval(x1-radius,y1-radius,radius*2,radius*2);
}
break;
}
}
}
void pointPaint(Graphics g, Point p) {
g.drawLine(p.x-ll,p.y+ll,p.x+ll,p.y-ll);
g.drawLine(p.x+ll,p.y+ll,p.x-ll,p.y-ll);
}
}
 
 
class inp_controls extends Panel implements ActionListener {
noninput ci;
inp_panel targ;
Button retry, ok;
public inp_controls(inp_panel pan, noninput cci) {
this.ci=cci;
targ=pan;
setLayout(new GridLayout());
setBackground(Color.white);
/* retry=new Button(noninput.retry);*/
/* retry.addActionListener(this);*/
/*ok=new Button(noninput.prompt);
ok.addActionListener(this);
add(retry); add(ok);*/
}
public void actionPerformed(ActionEvent e) {
Object src=e.getSource();
if(src == retry) targ.retry();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/ThreeD/src/Matrix3D.java
0,0 → 1,200
/*
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
 
/** A fairly conventional 3D matrix object that can transform sets of
3D points and perform a variety of manipulations on the transform */
class Matrix3D {
float xx, xy, xz, xo;
float yx, yy, yz, yo;
float zx, zy, zz, zo;
static final double pi = 3.14159265;
/** Create a new unit matrix */
Matrix3D () {
xx = 1.0f;
yy = 1.0f;
zz = 1.0f;
}
/** Scale by f in all dimensions */
void scale(float f) {
xx *= f;
xy *= f;
xz *= f;
xo *= f;
yx *= f;
yy *= f;
yz *= f;
yo *= f;
zx *= f;
zy *= f;
zz *= f;
zo *= f;
}
/** Scale along each axis independently */
void scale(float xf, float yf, float zf) {
xx *= xf;
xy *= xf;
xz *= xf;
xo *= xf;
yx *= yf;
yy *= yf;
yz *= yf;
yo *= yf;
zx *= zf;
zy *= zf;
zz *= zf;
zo *= zf;
}
/** Translate the origin */
void translate(float x, float y, float z) {
xo += x;
yo += y;
zo += z;
}
/** rotate theta degrees about the y axis */
void yrot(double theta) {
theta *= (pi / 180);
double ct = Math.cos(theta);
double st = Math.sin(theta);
 
float Nxx = (float) (xx * ct + zx * st);
float Nxy = (float) (xy * ct + zy * st);
float Nxz = (float) (xz * ct + zz * st);
float Nxo = (float) (xo * ct + zo * st);
 
float Nzx = (float) (zx * ct - xx * st);
float Nzy = (float) (zy * ct - xy * st);
float Nzz = (float) (zz * ct - xz * st);
float Nzo = (float) (zo * ct - xo * st);
 
xo = Nxo;
xx = Nxx;
xy = Nxy;
xz = Nxz;
zo = Nzo;
zx = Nzx;
zy = Nzy;
zz = Nzz;
}
/** rotate theta degrees about the x axis */
void xrot(double theta) {
theta *= (pi / 180);
double ct = Math.cos(theta);
double st = Math.sin(theta);
 
float Nyx = (float) (yx * ct + zx * st);
float Nyy = (float) (yy * ct + zy * st);
float Nyz = (float) (yz * ct + zz * st);
float Nyo = (float) (yo * ct + zo * st);
 
float Nzx = (float) (zx * ct - yx * st);
float Nzy = (float) (zy * ct - yy * st);
float Nzz = (float) (zz * ct - yz * st);
float Nzo = (float) (zo * ct - yo * st);
 
yo = Nyo;
yx = Nyx;
yy = Nyy;
yz = Nyz;
zo = Nzo;
zx = Nzx;
zy = Nzy;
zz = Nzz;
}
/** rotate theta degrees about the z axis */
void zrot(double theta) {
theta *= (pi / 180);
double ct = Math.cos(theta);
double st = Math.sin(theta);
 
float Nyx = (float) (yx * ct + xx * st);
float Nyy = (float) (yy * ct + xy * st);
float Nyz = (float) (yz * ct + xz * st);
float Nyo = (float) (yo * ct + xo * st);
 
float Nxx = (float) (xx * ct - yx * st);
float Nxy = (float) (xy * ct - yy * st);
float Nxz = (float) (xz * ct - yz * st);
float Nxo = (float) (xo * ct - yo * st);
 
yo = Nyo;
yx = Nyx;
yy = Nyy;
yz = Nyz;
xo = Nxo;
xx = Nxx;
xy = Nxy;
xz = Nxz;
}
/** Multiply this matrix by a second: M = M*R */
void mult(Matrix3D rhs) {
float lxx = xx * rhs.xx + yx * rhs.xy + zx * rhs.xz;
float lxy = xy * rhs.xx + yy * rhs.xy + zy * rhs.xz;
float lxz = xz * rhs.xx + yz * rhs.xy + zz * rhs.xz;
float lxo = xo * rhs.xx + yo * rhs.xy + zo * rhs.xz + rhs.xo;
 
float lyx = xx * rhs.yx + yx * rhs.yy + zx * rhs.yz;
float lyy = xy * rhs.yx + yy * rhs.yy + zy * rhs.yz;
float lyz = xz * rhs.yx + yz * rhs.yy + zz * rhs.yz;
float lyo = xo * rhs.yx + yo * rhs.yy + zo * rhs.yz + rhs.yo;
 
float lzx = xx * rhs.zx + yx * rhs.zy + zx * rhs.zz;
float lzy = xy * rhs.zx + yy * rhs.zy + zy * rhs.zz;
float lzz = xz * rhs.zx + yz * rhs.zy + zz * rhs.zz;
float lzo = xo * rhs.zx + yo * rhs.zy + zo * rhs.zz + rhs.zo;
 
xx = lxx;
xy = lxy;
xz = lxz;
xo = lxo;
 
yx = lyx;
yy = lyy;
yz = lyz;
yo = lyo;
 
zx = lzx;
zy = lzy;
zz = lzz;
zo = lzo;
}
 
/** Reinitialize to the unit matrix */
void unit() {
xo = 0;
xx = 1;
xy = 0;
xz = 0;
yo = 0;
yx = 0;
yy = 1;
yz = 0;
zo = 0;
zx = 0;
zy = 0;
zz = 1;
}
/** Transform nvert points from v into tv. v contains the input
coordinates in floating point. Three successive entries in
the array constitute a point. tv ends up holding the transformed
points as integers; three successive entries per point */
void transform(float v[], int tv[], int nvert) {
float lxx = xx, lxy = xy, lxz = xz, lxo = xo;
float lyx = yx, lyy = yy, lyz = yz, lyo = yo;
float lzx = zx, lzy = zy, lzz = zz, lzo = zo;
for (int i = nvert * 3; (i -= 3) >= 0;) {
float x = v[i];
float y = v[i + 1];
float z = v[i + 2];
tv[i ] = (int) (x * lxx + y * lxy + z * lxz + lxo);
tv[i + 1] = (int) (x * lyx + y * lyy + z * lyz + lyo);
tv[i + 2] = (int) (x * lzx + y * lzy + z * lzz + lzo);
}
}
public String toString() {
return ("[" + xo + "," + xx + "," + xy + "," + xz + ";"
+ yo + "," + yx + "," + yy + "," + yz + ";"
+ zo + "," + zx + "," + zy + "," + zz + "]");
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/ThreeD/src/ThreeD.java
0,0 → 1,441
/*
* @(#)TreeD.java
*
* Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
/* A set of classes to parse, represent and display 3D wireframe models
represented in Wavefront .obj format. */
 
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Event;
import java.io.StreamTokenizer;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
 
class FileFormatException extends Exception {
public FileFormatException(String s) {
super(s);
}
}
 
/** The representation of a 3D model */
class Model3D {
float vert[];
int tvert[];
int nvert, maxvert;
int con[];
int ncon, maxcon;
boolean transformed;
Matrix3D mat;
 
float xmin, xmax, ymin, ymax, zmin, zmax;
 
Model3D () {
mat = new Matrix3D ();
mat.xrot(20);
mat.yrot(30);
}
/** Create a 3D model by parsing an input stream */
Model3D (InputStream is) throws IOException, FileFormatException {
this();
StreamTokenizer st = new StreamTokenizer(is);
st.eolIsSignificant(true);
st.commentChar('#');
scan:
while (true) {
switch (st.nextToken()) {
default:
break scan;
case StreamTokenizer.TT_EOL:
break;
case StreamTokenizer.TT_WORD:
if ("v".equals(st.sval)) {
double x = 0, y = 0, z = 0;
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
x = st.nval;
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
y = st.nval;
if (st.nextToken() == StreamTokenizer.TT_NUMBER)
z = st.nval;
}
}
addVert((float) x, (float) y, (float) z);
while (st.ttype != StreamTokenizer.TT_EOL &&
st.ttype != StreamTokenizer.TT_EOF)
st.nextToken();
} else if ("f".equals(st.sval) || "fo".equals(st.sval) || "l".equals(st.sval)) {
int start = -1;
int prev = -1;
int n = -1;
while (true)
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
n = (int) st.nval;
if (prev >= 0)
add(prev - 1, n - 1);
if (start < 0)
start = n;
prev = n;
} else if (st.ttype == '/')
st.nextToken();
else
break;
if (start >= 0)
add(start - 1, prev - 1);
if (st.ttype != StreamTokenizer.TT_EOL)
break scan;
} else {
while (st.nextToken() != StreamTokenizer.TT_EOL
&& st.ttype != StreamTokenizer.TT_EOF);
}
}
}
is.close();
if (st.ttype != StreamTokenizer.TT_EOF)
throw new FileFormatException(st.toString());
}
 
/** Add a vertex to this model */
int addVert(float x, float y, float z) {
int i = nvert;
if (i >= maxvert)
if (vert == null) {
maxvert = 100;
vert = new float[maxvert * 3];
} else {
maxvert *= 2;
float nv[] = new float[maxvert * 3];
System.arraycopy(vert, 0, nv, 0, vert.length);
vert = nv;
}
i *= 3;
vert[i] = x;
vert[i + 1] = y;
vert[i + 2] = z;
return nvert++;
}
/** Add a line from vertex p1 to vertex p2 */
void add(int p1, int p2) {
int i = ncon;
if (p1 >= nvert || p2 >= nvert)
return;
if (i >= maxcon)
if (con == null) {
maxcon = 100;
con = new int[maxcon];
} else {
maxcon *= 2;
int nv[] = new int[maxcon];
System.arraycopy(con, 0, nv, 0, con.length);
con = nv;
}
if (p1 > p2) {
int t = p1;
p1 = p2;
p2 = t;
}
con[i] = (p1 << 16) | p2;
ncon = i + 1;
}
/** Transform all the points in this model */
void transform() {
if (transformed || nvert <= 0)
return;
if (tvert == null || tvert.length < nvert * 3)
tvert = new int[nvert*3];
mat.transform(vert, tvert, nvert);
transformed = true;
}
 
/* Quick Sort implementation
*/
private void quickSort(int a[], int left, int right)
{
int leftIndex = left;
int rightIndex = right;
int partionElement;
if ( right > left)
{
 
/* Arbitrarily establishing partition element as the midpoint of
* the array.
*/
partionElement = a[ ( left + right ) / 2 ];
 
// loop through the array until indices cross
while( leftIndex <= rightIndex )
{
/* find the first element that is greater than or equal to
* the partionElement starting from the leftIndex.
*/
while( ( leftIndex < right ) && ( a[leftIndex] < partionElement ) )
++leftIndex;
 
/* find an element that is smaller than or equal to
* the partionElement starting from the rightIndex.
*/
while( ( rightIndex > left ) &&
( a[rightIndex] > partionElement ) )
--rightIndex;
 
// if the indexes have not crossed, swap
if( leftIndex <= rightIndex )
{
swap(a, leftIndex, rightIndex);
++leftIndex;
--rightIndex;
}
}
 
/* If the right index has not reached the left side of array
* must now sort the left partition.
*/
if( left < rightIndex )
quickSort( a, left, rightIndex );
 
/* If the left index has not reached the right side of array
* must now sort the right partition.
*/
if( leftIndex < right )
quickSort( a, leftIndex, right );
 
}
}
 
private void swap(int a[], int i, int j)
{
int T;
T = a[i];
a[i] = a[j];
a[j] = T;
}
 
 
/** eliminate duplicate lines */
void compress() {
int limit = ncon;
int c[] = con;
quickSort(con, 0, ncon - 1);
int d = 0;
int pp1 = -1;
for (int i = 0; i < limit; i++) {
int p1 = c[i];
if (pp1 != p1) {
c[d] = p1;
d++;
}
pp1 = p1;
}
ncon = d;
}
 
static Color gr[];
 
/** Paint this model to a graphics context. It uses the matrix associated
with this model to map from model space to screen space.
The next version of the browser should have double buffering,
which will make this *much* nicer */
void paint(Graphics g) {
if (vert == null || nvert <= 0)
return;
transform();
if (gr == null) {
gr = new Color[16];
for (int i = 0; i < 16; i++) {
int grey = (int) (170*(1-Math.pow(i/15.0, 2.3)));
gr[i] = new Color(grey, grey, grey);
}
}
int lg = 0;
int lim = ncon;
int c[] = con;
int v[] = tvert;
if (lim <= 0 || nvert <= 0)
return;
for (int i = 0; i < lim; i++) {
int T = c[i];
int p1 = ((T >> 16) & 0xFFFF) * 3;
int p2 = (T & 0xFFFF) * 3;
int grey = v[p1 + 2] + v[p2 + 2];
if (grey < 0)
grey = 0;
if (grey > 15)
grey = 15;
if (grey != lg) {
lg = grey;
g.setColor(gr[grey]);
}
g.drawLine(v[p1], v[p1 + 1],
v[p2], v[p2 + 1]);
}
}
 
/** Find the bounding box of this model */
void findBB() {
if (nvert <= 0)
return;
float v[] = vert;
float xmin = v[0], xmax = xmin;
float ymin = v[1], ymax = ymin;
float zmin = v[2], zmax = zmin;
for (int i = nvert * 3; (i -= 3) > 0;) {
float x = v[i];
if (x < xmin)
xmin = x;
if (x > xmax)
xmax = x;
float y = v[i + 1];
if (y < ymin)
ymin = y;
if (y > ymax)
ymax = y;
float z = v[i + 2];
if (z < zmin)
zmin = z;
if (z > zmax)
zmax = z;
}
this.xmax = xmax;
this.xmin = xmin;
this.ymax = ymax;
this.ymin = ymin;
this.zmax = zmax;
this.zmin = zmin;
}
}
 
/** An applet to put a 3D model into a page */
public class ThreeD extends Applet implements Runnable {
Model3D md;
boolean painted = true;
float xfac;
int prevx, prevy;
float xtheta, ytheta;
float scalefudge = 1;
Matrix3D amat = new Matrix3D(), tmat = new Matrix3D();
String mdname = null;
String message = null;
 
public void init() {
mdname = getParameter("model");
try {
scalefudge = Float.valueOf(getParameter("scale")).floatValue();
}catch(Exception e){};
amat.yrot(20);
amat.xrot(20);
if (mdname == null)
mdname = "model.obj";
resize(size().width <= 20 ? 400 : size().width,
size().height <= 20 ? 400 : size().height);
}
public void run() {
InputStream is = null;
try {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
is = new URL(getDocumentBase(), mdname).openStream();
Model3D m = new Model3D (is);
md = m;
m.findBB();
m.compress();
float xw = m.xmax - m.xmin;
float yw = m.ymax - m.ymin;
float zw = m.zmax - m.zmin;
if (yw > xw)
xw = yw;
if (zw > xw)
xw = zw;
float f1 = size().width / xw;
float f2 = size().height / xw;
xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge;
} catch(Exception e) {
md = null;
message = e.toString();
}
try {
if (is != null)
is.close();
} catch(Exception e) {
}
repaint();
}
public void start() {
if (md == null && message == null)
new Thread(this).start();
}
public void stop() {
}
public boolean mouseDown(Event e, int x, int y) {
prevx = x;
prevy = y;
return true;
}
public boolean mouseDrag(Event e, int x, int y) {
tmat.unit();
float xtheta = (prevy - y) * 360.0f / size().width;
float ytheta = (x - prevx) * 360.0f / size().height;
tmat.xrot(xtheta);
tmat.yrot(ytheta);
amat.mult(tmat);
if (painted) {
painted = false;
repaint();
}
prevx = x;
prevy = y;
return true;
}
public void paint(Graphics g) {
if (md != null) {
md.mat.unit();
md.mat.translate(-(md.xmin + md.xmax) / 2,
-(md.ymin + md.ymax) / 2,
-(md.zmin + md.zmax) / 2);
md.mat.mult(amat);
// md.mat.scale(xfac, -xfac, 8 * xfac / size().width);
md.mat.scale(xfac, -xfac, 16 * xfac / size().width);
md.mat.translate(size().width / 2, size().height / 2, 8);
md.transformed = false;
md.paint(g);
setPainted();
} else if (message != null) {
g.drawString("Error in model:", 3, 20);
g.drawString(message, 10, 40);
}
}
private synchronized void setPainted() {
painted = true;
notifyAll();
}
// private synchronized void waitPainted() {
// while (!painted)
// wait();
// painted = false;
// }
}
/trunk/wims/src/Misc/authors/jm.evers/applets/ThreeD/src/XYZApp.java
0,0 → 1,447
/*
* @(#)XYZApp.java
*
* Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted.
* Please refer to the file http://java.sun.com/copy_trademarks.html
* for further important copyright and trademark information and to
* http://java.sun.com/licensing.html for further important licensing
* information for the Java (tm) Technology.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SUN
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
 
import java.applet.Applet;
import java.awt.Image;
import java.awt.Event;
import java.awt.Graphics;
import java.io.StreamTokenizer;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.net.URL;
import java.util.Hashtable;
import java.awt.image.IndexColorModel;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
 
 
/** The representation of a Chemical .xyz model */
class XYZChemModel {
float vert[];
Atom atoms[];
int tvert[];
int ZsortMap[];
int nvert, maxvert;
 
static Hashtable atomTable = new Hashtable();
static Atom defaultAtom;
static {
atomTable.put("c", new Atom(0, 0, 0));
atomTable.put("x", new Atom(176, 160, 240));
atomTable.put("h", new Atom(210, 210, 210));
atomTable.put("n", new Atom(0, 0, 255));
atomTable.put("o", new Atom(255, 0, 0));
atomTable.put("p", new Atom(255, 0, 255));
atomTable.put("s", new Atom(255, 255, 0));
atomTable.put("hn", new Atom(150, 255, 150)); /* !!*/
defaultAtom = new Atom(255, 100, 200);
}
 
boolean transformed;
Matrix3D mat;
 
float xmin, xmax, ymin, ymax, zmin, zmax;
 
 
XYZChemModel () {
mat = new Matrix3D();
mat.xrot(20);
mat.yrot(30);
}
 
 
/** Create a Cehmical model by parsing an input stream */
XYZChemModel (InputStream is) throws Exception {
this();
StreamTokenizer st = new StreamTokenizer(new BufferedInputStream(is, 4000));
st.eolIsSignificant(true);
st.commentChar('#');
int slot = 0;
scan:
while (true)
switch (st.nextToken()) {
case StreamTokenizer.TT_EOF:
break scan;
default:
break;
case StreamTokenizer.TT_WORD:
String name = st.sval;
double x = 0, y = 0, z = 0;
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
x = st.nval;
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
y = st.nval;
if (st.nextToken() == StreamTokenizer.TT_NUMBER)
z = st.nval;
}
}
addVert(name, (float) x, (float) y, (float) z);
while (st.ttype != StreamTokenizer.TT_EOL &&
st.ttype != StreamTokenizer.TT_EOF)
st.nextToken();
}
is.close();
if (st.ttype != StreamTokenizer.TT_EOF)
throw new Exception(st.toString());
}
 
/** Add a vertex to this model */
int addVert(String name, float x, float y, float z) {
int i = nvert;
if (i >= maxvert)
if (vert == null) {
maxvert = 100;
vert = new float[maxvert * 3];
atoms = new Atom[maxvert];
} else {
maxvert *= 2;
float nv[] = new float[maxvert * 3];
System.arraycopy(vert, 0, nv, 0, vert.length);
vert = nv;
Atom na[] = new Atom[maxvert];
System.arraycopy(atoms, 0, na, 0, atoms.length);
atoms = na;
}
Atom a = (Atom) atomTable.get(name.toLowerCase());
if (a == null) a = defaultAtom;
atoms[i] = a;
i *= 3;
vert[i] = x;
vert[i + 1] = y;
vert[i + 2] = z;
return nvert++;
}
 
/** Transform all the points in this model */
void transform() {
if (transformed || nvert <= 0)
return;
if (tvert == null || tvert.length < nvert * 3)
tvert = new int[nvert * 3];
mat.transform(vert, tvert, nvert);
transformed = true;
}
 
 
/** Paint this model to a graphics context. It uses the matrix associated
with this model to map from model space to screen space.
The next version of the browser should have double buffering,
which will make this *much* nicer */
void paint(Graphics g) {
if (vert == null || nvert <= 0)
return;
transform();
int v[] = tvert;
int zs[] = ZsortMap;
if (zs == null) {
ZsortMap = zs = new int[nvert];
for (int i = nvert; --i >= 0;)
zs[i] = i * 3;
}
 
/*
* I use a bubble sort since from one iteration to the next, the sort
* order is pretty stable, so I just use what I had last time as a
* "guess" of the sorted order. With luck, this reduces O(N log N)
* to O(N)
*/
 
for (int i = nvert - 1; --i >= 0;) {
boolean flipped = false;
for (int j = 0; j <= i; j++) {
int a = zs[j];
int b = zs[j + 1];
if (v[a + 2] > v[b + 2]) {
zs[j + 1] = a;
zs[j] = b;
flipped = true;
}
}
if (!flipped)
break;
}
 
int lg = 0;
int lim = nvert;
Atom ls[] = atoms;
if (lim <= 0 || nvert <= 0)
return;
for (int i = 0; i < lim; i++) {
int j = zs[i];
int grey = v[j + 2];
if (grey < 0)
grey = 0;
if (grey > 15)
grey = 15;
// g.drawString(names[i], v[j], v[j+1]);
atoms[j/3].paint(g, v[j], v[j + 1], grey);
// g.drawImage(iBall, v[j] - (iBall.width >> 1), v[j + 1] -
// (iBall.height >> 1));
}
}
 
/** Find the bounding box of this model */
void findBB() {
if (nvert <= 0)
return;
float v[] = vert;
float xmin = v[0], xmax = xmin;
float ymin = v[1], ymax = ymin;
float zmin = v[2], zmax = zmin;
for (int i = nvert * 3; (i -= 3) > 0;) {
float x = v[i];
if (x < xmin)
xmin = x;
if (x > xmax)
xmax = x;
float y = v[i + 1];
if (y < ymin)
ymin = y;
if (y > ymax)
ymax = y;
float z = v[i + 2];
if (z < zmin)
zmin = z;
if (z > zmax)
zmax = z;
}
this.xmax = xmax;
this.xmin = xmin;
this.ymax = ymax;
this.ymin = ymin;
this.zmax = zmax;
this.zmin = zmin;
}
}
 
/** An applet to put a Cehmical model into a page */
public class XYZApp extends Applet implements Runnable {
XYZChemModel md;
boolean painted = true;
float xfac;
int prevx, prevy;
float xtheta, ytheta;
float scalefudge = 1;
Matrix3D amat = new Matrix3D(), tmat = new Matrix3D();
String mdname = null;
String message = null;
Image backBuffer;
Graphics backGC;
 
 
public void init() {
mdname = getParameter("model");
try {
scalefudge = Float.valueOf(getParameter("scale")).floatValue();
} catch(Exception e) {
};
amat.yrot(20);
amat.xrot(20);
if (mdname == null)
mdname = "model.obj";
resize(size().width <= 20 ? 400 : size().width,
size().height <= 20 ? 400 : size().height);
}
public void run() {
InputStream is = null;
try {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
is = new URL(getDocumentBase(), mdname).openStream();
XYZChemModel m = new XYZChemModel (is);
Atom.setApplet(this);
md = m;
m.findBB();
float xw = m.xmax - m.xmin;
float yw = m.ymax - m.ymin;
float zw = m.zmax - m.zmin;
if (yw > xw)
xw = yw;
if (zw > xw)
xw = zw;
float f1 = size().width / xw;
float f2 = size().height / xw;
xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge;
backBuffer = createImage(size().width, size().height);
backGC = backBuffer.getGraphics();
} catch(Exception e) {
e.printStackTrace();
md = null;
message = e.toString();
}
try {
if (is != null)
is.close();
} catch(Exception e) {
}
repaint();
}
public void start() {
if (md == null && message == null)
new Thread(this).start();
}
public void stop() {
}
public boolean mouseDown(Event e, int x, int y) {
prevx = x;
prevy = y;
return true;
}
public boolean mouseDrag(Event e, int x, int y) {
tmat.unit();
float xtheta = (prevy - y) * (360.0f / size().width);
float ytheta = (x - prevx) * (360.0f / size().height);
tmat.xrot(xtheta);
tmat.yrot(ytheta);
amat.mult(tmat);
if (painted) {
painted = false;
repaint();
}
prevx = x;
prevy = y;
return true;
}
public void update(Graphics g) {
if (backBuffer == null)
g.clearRect(0, 0, size().width, size().height);
paint(g);
}
public void paint(Graphics g) {
if (md != null) {
md.mat.unit();
md.mat.translate(-(md.xmin + md.xmax) / 2,
-(md.ymin + md.ymax) / 2,
-(md.zmin + md.zmax) / 2);
md.mat.mult(amat);
// md.mat.scale(xfac, -xfac, 8 * xfac / size().width);
md.mat.scale(xfac, -xfac, 16 * xfac / size().width);
md.mat.translate(size().width / 2, size().height / 2, 8);
md.transformed = false;
if (backBuffer != null) {
backGC.setColor(getBackground());
backGC.fillRect(0,0,size().width,size().height);
md.paint(backGC);
g.drawImage(backBuffer, 0, 0, this);
} else
md.paint(g);
setPainted();
} else if (message != null) {
g.drawString("Error in model:", 3, 20);
g.drawString(message, 10, 40);
}
}
private synchronized void setPainted() {
painted = true;
notifyAll();
}
private synchronized void waitPainted() {
while (!painted)
try { wait(); } catch (Exception e) {}
painted = false;
}
}
 
class Atom {
private static Applet applet;
private static byte[] data;
private final static int R = 40;
private final static int hx = 15;
private final static int hy = 15;
private final static int bgGrey = 192;
private final static int nBalls = 16;
private static int maxr;
 
private int Rl;
private int Gl;
private int Bl;
private Image balls[];
 
static {
data = new byte[R * 2 * R * 2];
int mr = 0;
for (int Y = 2 * R; --Y >= 0;) {
int x0 = (int) (Math.sqrt(R * R - (Y - R) * (Y - R)) + 0.5);
int p = Y * (R * 2) + R - x0;
for (int X = -x0; X < x0; X++) {
int x = X + hx;
int y = Y - R + hy;
int r = (int) (Math.sqrt(x * x + y * y) + 0.5);
if (r > mr)
mr = r;
data[p++] = r <= 0 ? 1 : (byte) r;
}
}
maxr = mr;
}
static void setApplet(Applet app) {
applet = app;
}
Atom(int Rl, int Gl, int Bl) {
this.Rl = Rl;
this.Gl = Gl;
this.Bl = Bl;
}
private final int blend(int fg, int bg, float fgfactor) {
return (int) (bg + (fg - bg) * fgfactor);
}
private void Setup() {
balls = new Image[nBalls];
byte red[] = new byte[256];
red[0] = (byte) bgGrey;
byte green[] = new byte[256];
green[0] = (byte) bgGrey;
byte blue[] = new byte[256];
blue[0] = (byte) bgGrey;
for (int r = 0; r < nBalls; r++) {
float b = (float) (r+1) / nBalls;
for (int i = maxr; i >= 1; --i) {
float d = (float) i / maxr;
red[i] = (byte) blend(blend(Rl, 255, d), bgGrey, b);
green[i] = (byte) blend(blend(Gl, 255, d), bgGrey, b);
blue[i] = (byte) blend(blend(Bl, 255, d), bgGrey, b);
}
IndexColorModel model = new IndexColorModel(8, maxr + 1,
red, green, blue, 0);
balls[r] = applet.createImage(
new MemoryImageSource(R*2, R*2, model, data, 0, R*2));
}
}
void paint(Graphics gc, int x, int y, int r) {
Image ba[] = balls;
if (ba == null) {
Setup();
ba = balls;
}
Image i = ba[r];
int size = 10 + r;
gc.drawImage(i, x - (size >> 1), y - (size >> 1), size, size, applet);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/ThreeD/build.xml
0,0 → 1,64
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for ThreeD.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="ThreeD" default="jar" basedir=".">
 
<description>ThreeD build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create ThreeD jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/ThreeD.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="ThreeD"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="ThreeD"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="ThreeD">
<attribute name="Specification-Title" value="ThreeD"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="ThreeD"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/Makefile
0,0 → 1,35
PACKAGES = $(shell ls -Fd *| grep /| tr -d /)
HOME_WIMS = ../../../../..
APPLET_DIR = public_html/scripts/authors/jm.evers/applets
INSTALL_DIR = $(HOME_WIMS)/$(APPLET_DIR)
LOGFILE = $(shell pwd)/log.txt
 
all:
@echo "Build date: $$(date)" > $(LOGFILE)
@echo "+--------------------------------+"
@echo "| Compiling applets. See log.txt |"
@echo "+--------------------------------+"
@for d in $(PACKAGES) ; do ( \
echo "============== $$d ==============" >> $(LOGFILE); \
cd $$d; \
ant -v ; \
j=`find dist -iname "*.jar" 2>/dev/null`; \
if [ $$j ] ; then \
echo "OK: compiled $$d/$$j" >> $(LOGFILE); \
else \
echo "NOK for package $$d" >> $(LOGFILE); \
fi; ); \
done
 
clean:
rm -rf */dist */build log.txt *~
 
install:
for d in $(PACKAGES) ; do \
j=`find $$d/dist -iname "*.jar" 2>/dev/null`; \
if [ $$j ] ; then \
install -m 644 $$j $(INSTALL_DIR); \
fi; \
done
 
.PHONY: all clean install
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/build.xml
0,0 → 1,82
<?xml version="1.0" encoding="iso-8859-1"?>
 
<project name="Plot" default="jar" basedir=".">
 
 
<description>
Plot (Plot) project buildfile.
</description>
 
<property name="src.dir" value="./ptolemy"/>
<property name="build.dir" value="./build"/>
<property name="dist.dir" value="./dist"/>
<property name="dest.dir" value="${build.dir}"/>
<property name="Plot.jar" value="${build.dir}/../dist/Plot.jar"/>
<property name="Plot.tar" value="${build.dir}/../Plot.tgz"/>
 
 
<!-- Sets up classpath reference -->
<path id="Plot.classpath">
<pathelement path="${src.dir}"/>
<pathelement path="${dest.dir}"/>
</path>
 
 
<target name="-init" depends="-prepare">
<tstamp/>
</target>
 
 
<target name="-prepare" depends="-info">
<mkdir dir="${build.dir}"/>
<mkdir dir="${dest.dir}"/>
<mkdir dir="${dist.dir}"/>
</target>
 
 
<target name="-info">
<property name="name" value="Plot"/>
<property name="acronym" value="Plot"/>
<property name="version" value="local"/>
<property name="year" value="2008-03"/>
<echo message="compiling Plot"/>
<echo message=""/>
</target>
 
 
<target name="compile" description="Compiles Plot sources" depends="-init">
<javac
target="1.4"
source="1.4"
verbose="verbose"
deprecation="true"
srcdir="${src.dir}"
classpathref="Plot.classpath"
excludes=""
destdir="${dest.dir}"/>
</target>
 
 
<target name="jar" description="Jar Plot" depends="compile" >
<jar destfile="${Plot.jar}" basedir="${dest.dir}" excludes="" >
<manifest>
</manifest>
</jar>
</target>
 
<target name="tar" description="Tars source distribution files" depends="clean, jar">
<tar longfile="gnu" destfile="${Plot.tar}" compression="gzip" >
<tarfileset dir="${basedir}" excludes=" build/*Plot*.tgz" prefix="Plot"/>
</tar>
</target>
 
 
<target name="clean" description="Cleans up" depends="-info">
<delete dir="${dist.dir}"/>
<delete dir="${build.dir}"/>
<delete>
<fileset dir="." includes="**/*~" />
</delete>
</target>
 
</project>
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/bargraph_via_file.html
0,0 → 1,89
<html>
<head></head>
<body>
Data processed via param "dataurl" (datafile)<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.PlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "dataurl" value="bargraph.txt">
</applet>
TitleText: Software Downloads<br>
XRange: 0,10<br>
YRange: 0,10000<br>
# Manually specify X ticks<br>
# Note that the 0 and 10 point result in clipping of the rectangles.<br>
XTicks: 1993 0, 1994 1, 1995 2, 1996 3, 1997 4, 1998 5, 1999 6, 2000 7, 2001 8, 2002 9, 2003 10<br>
XLabel: Year<br>
YLabel: Downloads<br>
Marks: none<br>
Lines: off<br>
# Width and offset of bars<br>
Bars: 0.5, 0.2<br>
NumSets: 3<br>
<br>
DataSet: program a<br>
0, 100<br>
1, 300<br>
2, 600<br>
3, 1000<br>
4, 4000<br>
5, 6000<br>
6, 3000<br>
7, 1000<br>
8, 400<br>
9, 0<br>
10, 0<br>
<br>
DataSet: program b<br>
0, 0<br>
1, 0<br>
2, 50<br>
3, 100<br>
4, 800<br>
5, 400<br>
6, 1000<br>
7, 5000<br>
8, 2000<br>
9, 300<br>
10, 0<br>
<br>
DataSet: program c<br>
0, 0<br>
1, 0<br>
2, 0<br>
3, 10<br>
4, 100<br>
5, 400<br>
6, 2000<br>
7, 5000<br>
8, 9000<br>
9, 7000<br>
10, 1000<br>
 
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/graph_via_string.html
0,0 → 1,44
<html>
<head></head>
<body>
Data processed via a single data parm string (eg:wims variable)<p>
Syntax of the string:
<font size=-1>
titletext: text of title ;xrange :50,300 ;yrange : 0,4000 ;grid : on ;xlabel :x-axis ;ylabel :y-axis ;xlog :off ;ylog :off ;color :on;Marks :dots ;numsets :10 ;dataset firstset ;x1 y1 ;x2 y2; ... ; x_n y_n ;dataset: the second ;x1 y1;x2 y2... dataset:last [numsets]; x1 y1 ;...
</font>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.PlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "data" value="TitleText:Vermogens Regeling [theoretisch];XRange: 50,250 ;YRange: 0,4000 ;Grid: on ;XLabel: Generator Voltage ;YLabel: Vermogen ;Marks: various ;NumSets: 1 ;Color: on ;Dataset A;0 0;50 15;100 190;150 700;200 2000;250 3900">
</applet>
</body>
</html>
 
<!--
<param name = "data" value="TitleText: 1031 datapoints processed via a single param string;XRange: 0,4 ;YRange: -4,4 ;Grid: on ;XLabel: X Axis ;YLabel: Y Axis ;Marks: various ;NumSets: 10 ;Color: on ;Dataset: 1;0.0 5.0;1.0 4.938441702975688;2.0 4.755282581475768;3.0 4.455032620941839;4.0 4.045084971874737;5.0 3.5355339059327378;6.0 2.938926261462366;7.0 2.269952498697734;8.0 1.5450849718747373;9.0 0.7821723252011547;10.0 3.061515884555943E-16;11.0 -0.7821723252011529;12.0 -1.5450849718747368;13.0 -2.2699524986977337;14.0 -2.9389262614623655;15.0 -3.5355339059327373;16.0 -4.045084971874737;17.0 -4.455032620941839;18.0 -4.755282581475767;19.0 -4.938441702975688;20.0 -5.0;21.0 -4.938441702975688;22.0 -4.755282581475769;23.0 -4.455032620941839;24.0 -4.045084971874737;25.0 -3.535533905932738;26.0 -2.9389262614623664;27.0 -2.2699524986977346;28.0 -1.545084971874738;29.0 -0.7821723252011552;30.0 -9.18454765366783E-16;31.0 0.7821723252011534;32.0 1.5450849718747361;33.0 2.269952498697733;34.0 2.938926261462365;35.0 3.535533905932737;36.0 4.045084971874736;37.0 4.4550326209418385;38.0 4.755282581475767;39.0 4.938441702975688;40.0 5.0;41.0 4.938441702975689;42.0 4.755282581475768;43.0 4.45503262094184;44.0 4.045084971874741;45.0 3.5355339059327386;46.0 2.938926261462367;47.0 2.269952498697731;48.0 1.5450849718747386;49.0 0.7821723252011602;50.0 1.5307579422779716E-15;51.0 -0.7821723252011484;52.0 -1.5450849718747357;53.0 -2.2699524986977364;54.0 -2.938926261462364;55.0 -3.5355339059327395;56.0 -4.045084971874736;57.0 -4.455032620941837;58.0 -4.755282581475767;59.0 -4.9384417029756875;60.0 -5.0;61.0 -4.938441702975688;62.0 -4.755282581475768;63.0 -4.4550326209418385;64.0 -4.045084971874738;65.0 -3.535533905932742;66.0 -2.9389262614623672;67.0 -2.26995249869774;68.0 -1.545084971874739;69.0 -0.7821723252011521;70.0 -2.1430611191891602E-15;71.0 0.7821723252011565;72.0 1.545084971874735;73.0 2.269952498697728;74.0 2.9389262614623637;75.0 3.535533905932733;76.0 4.0450849718747355;77.0 4.45503262094184;78.0 4.755282581475767;79.0 4.938441702975689;80.0 5.0;81.0 4.938441702975689;82.0 4.755282581475772;83.0 4.4550326209418385;84.0 4.045084971874739;85.0 3.5355339059327364;86.0 2.9389262614623677;87.0 2.2699524986977404;88.0 1.5450849718747481;89.0 0.7821723252011527;90.0 2.755364296100349E-15;91.0 -0.7821723252011472;92.0 -1.5450849718747344;93.0 -2.2699524986977275;94.0 -2.9389262614623703;95.0 -3.5355339059327386;96.0 -4.0450849718747355;97.0 -4.455032620941836;98.0 -4.755282581475764;99.0 -4.938441702975688;100.0 -5.0;;Dataset:2;0.0 4.5;1.0 4.46451615591515;2.0 4.35862422507884;3.0 4.183994186497132;4.0 3.943380060197386;5.0 3.6405764746872635;6.0 3.280358823396352;7.0 2.8684079538691036;8.0 2.4112205774054845;9.0 1.9160068120428269;10.0 1.3905764746872635;11.0 0.8432159156357613;12.0 0.28255733788191084;13.0 -0.2825573378819103;14.0 -0.8432159156357607;15.0 -1.3905764746872622;16.0 -1.9160068120428273;17.0 -2.411220577405486;18.0 -2.8684079538691036;19.0 -3.280358823396351;20.0 -3.640576474687263;21.0 -3.9433800601973865;22.0 -4.183994186497131;23.0 -4.35862422507884;24.0 -4.46451615591515;25.0 -4.5;26.0 -4.46451615591515;27.0 -4.35862422507884;28.0 -4.183994186497132;29.0 -3.943380060197386;30.0 -3.640576474687265;31.0 -3.280358823396353;32.0 -2.868407953869103;33.0 -2.4112205774054836;34.0 -1.9160068120428246;35.0 -1.3905764746872642;36.0 -0.8432159156357608;37.0 -0.2825573378819094;38.0 0.28255733788190773;39.0 0.8432159156357593;40.0 1.3905764746872626;41.0 1.9160068120428233;42.0 2.4112205774054853;43.0 2.868407953869102;44.0 3.2803588233963508;45.0 3.6405764746872626;46.0 3.9433800601973843;47.0 4.183994186497132;48.0 4.358624225078839;49.0 4.46451615591515;50.0 4.5;51.0 4.464516155915151;52.0 4.35862422507884;53.0 4.183994186497131;54.0 3.943380060197387;55.0 3.640576474687264;56.0 3.280358823396352;57.0 2.8684079538691063;58.0 2.411220577405484;59.0 1.9160068120428289;60.0 1.3905764746872684;61.0 0.8432159156357614;62.0 0.28255733788191395;63.0 -0.2825573378819112;64.0 -0.8432159156357626;65.0 -1.390576474687262;66.0 -1.91600681204283;67.0 -2.411220577405485;68.0 -2.8684079538691076;69.0 -3.280358823396353;70.0 -3.6405764746872626;71.0 -3.943380060197388;72.0 -4.183994186497132;73.0 -4.358624225078839;74.0 -4.464516155915151;75.0 -4.5;76.0 -4.464516155915151;77.0 -4.35862422507884;78.0 -4.183994186497133;79.0 -3.9433800601973856;80.0 -3.6405764746872644;81.0 -3.280358823396355;82.0 -2.86840795386911;83.0 -2.411220577405481;84.0 -1.9160068120428257;85.0 -1.390576474687265;86.0 -0.8432159156357658;87.0 -0.2825573378819185;88.0 0.2825573378819067;89.0 0.843215915635762;90.0 1.3905764746872615;91.0 1.9160068120428222;92.0 2.411220577405478;93.0 2.868407953869101;94.0 3.2803588233963525;95.0 3.640576474687262;96.0 3.9433800601973834;97.0 4.183994186497131;98.0 4.358624225078839;99.0 4.464516155915151;100.0 4.5;;;;Dataset:3;0.0 4.0;1.0 3.978087581473093;2.0 3.9125904029352228;3.0 3.804226065180614;4.0 3.6541818305704035;5.0 3.464101615137755;6.0 3.23606797749979;7.0 2.972579301909577;8.0 2.676522425435433;9.0 2.3511410091698925;10.0 2.0000000000000004;11.0 1.6269465723032015;12.0 1.2360679774997898;13.0 0.8316467632710369;14.0 0.41811385307061383;15.0 1.1330996904646007E-15;16.0 -0.41811385307061333;17.0 -0.8316467632710374;18.0 -1.2360679774997894;19.0 -1.6269465723032002;20.0 -1.9999999999999991;21.0 -2.351141009169892;22.0 -2.6765224254354316;23.0 -2.972579301909576;24.0 -3.2360679774997894;25.0 -3.464101615137755;26.0 -3.654181830570404;27.0 -3.804226065180614;28.0 -3.9125904029352228;29.0 -3.9780875814730936;30.0 -4.0;31.0 -3.9780875814730936;32.0 -3.9125904029352228;33.0 -3.8042260651806146;34.0 -3.6541818305704035;35.0 -3.4641016151377553;36.0 -3.2360679774997902;37.0 -2.972579301909577;38.0 -2.676522425435434;39.0 -2.351141009169893;40.0 -2.0000000000000018;41.0 -1.6269465723032035;42.0 -1.2360679774997902;43.0 -0.8316467632710391;44.0 -0.41811385307061694;45.0 -7.347638122934264E-16;46.0 0.41811385307061194;47.0 0.8316467632710377;48.0 1.236067977499789;49.0 1.626946572303199;50.0 2.0000000000000004;51.0 2.3511410091698917;52.0 2.676522425435434;53.0 2.972579301909577;54.0 3.2360679774997894;55.0 3.4641016151377553;56.0 3.654181830570404;57.0 3.804226065180614;58.0 3.9125904029352228;59.0 3.978087581473093;60.0 4.0;61.0 3.9780875814730936;62.0 3.912590402935223;63.0 3.8042260651806146;64.0 3.6541818305704044;65.0 3.464101615137756;66.0 3.2360679774997902;67.0 2.9725793019095783;68.0 2.676522425435433;69.0 2.3511410091698934;70.0 2.000000000000002;71.0 1.6269465723032008;72.0 1.236067977499791;73.0 0.8316467632710397;74.0 0.4181138530706139;75.0 1.2246063538223773E-15;76.0 -0.4181138530706115;77.0 -0.8316467632710338;78.0 -1.2360679774997885;79.0 -1.6269465723032017;80.0 -1.999999999999997;81.0 -2.3511410091698917;82.0 -2.6765224254354285;83.0 -2.972579301909579;84.0 -3.236067977499789;85.0 -3.4641016151377553;86.0 -3.654181830570402;87.0 -3.8042260651806137;88.0 -3.9125904029352214;89.0 -3.9780875814730936;90.0 -4.0;91.0 -3.978087581473093;92.0 -3.912590402935223;93.0 -3.8042260651806146;94.0 -3.654181830570403;95.0 -3.464101615137753;96.0 -3.2360679774997907;97.0 -2.972579301909581;98.0 -2.6765224254354356;99.0 -2.351141009169894;100.0 -1.9999999999999993;;;Dataset:4;0.0 3.5;1.0 3.4859100289833367;2.0 3.4437535600952036;3.0 3.3738700124354866;4.0 3.2768220472390803;5.0 3.153391037658467;6.0 3.0045707776065314;7.0 2.831559480312316;8.0 2.6357501310126383;9.0 2.4187192714540267;10.0 2.1822143065055672;11.0 1.9281394350823593;12.0 1.6585403186554954;13.0 1.3755876107887328;14.0 1.081559480312316;15.0 0.7788232688471006;16.0 0.4698164303617944;17.0 0.15702690622680246;18.0 -0.15702690622680202;19.0 -0.46981643036179394;20.0 -0.7788232688471002;21.0 -1.0815594803123156;22.0 -1.3755876107887317;23.0 -1.658540318655495;24.0 -1.9281394350823586;25.0 -2.1822143065055672;26.0 -2.418719271454026;27.0 -2.635750131012638;28.0 -2.8315594803123156;29.0 -3.0045707776065314;30.0 -3.1533910376584666;31.0 -3.27682204723908;32.0 -3.3738700124354866;33.0 -3.4437535600952036;34.0 -3.4859100289833367;35.0 -3.5;36.0 -3.4859100289833367;37.0 -3.443753560095204;38.0 -3.3738700124354866;39.0 -3.2768220472390803;40.0 -3.153391037658467;41.0 -3.0045707776065327;42.0 -2.831559480312316;43.0 -2.6357501310126388;44.0 -2.418719271454028;45.0 -2.1822143065055677;46.0 -1.9281394350823593;47.0 -1.658540318655496;48.0 -1.3755876107887333;49.0 -1.0815594803123165;50.0 -0.778823268847101;51.0 -0.46981643036179477;52.0 -0.15702690622680288;53.0 0.1570269062268016;54.0 0.4698164303617935;55.0 0.7788232688470997;56.0 1.0815594803123154;57.0 1.375587610788732;58.0 1.6585403186554948;59.0 1.9281394350823582;60.0 2.182214306505567;61.0 2.4187192714540258;62.0 2.635750131012638;63.0 2.8315594803123156;64.0 3.004570777606531;65.0 3.1533910376584666;66.0 3.27682204723908;67.0 3.373870012435486;68.0 3.4437535600952036;69.0 3.4859100289833367;70.0 3.5;71.0 3.4859100289833367;72.0 3.443753560095204;73.0 3.3738700124354866;74.0 3.2768220472390808;75.0 3.1533910376584675;76.0 3.004570777606532;77.0 2.8315594803123165;78.0 2.6357501310126388;79.0 2.418719271454027;80.0 2.182214306505568;81.0 1.9281394350823597;82.0 1.658540318655499;83.0 1.3755876107887308;84.0 1.081559480312317;85.0 0.7788232688471014;86.0 0.4698164303617952;87.0 0.1570269062268064;88.0 -0.15702690622679805;89.0 -0.46981643036179616;90.0 -0.7788232688470993;91.0 -1.081559480312315;92.0 -1.3755876107887317;93.0 -1.6585403186554943;94.0 -1.928139435082358;95.0 -2.1822143065055664;96.0 -2.4187192714540253;97.0 -2.6357501310126374;98.0 -2.831559480312315;99.0 -3.004570777606531;100.0 -3.1533910376584666;;Dataset:5;0.0 3.0;1.0 2.990752001199384;2.0 2.9630650217854133;3.0 2.91710976119303;4.0 2.853169548885461;5.0 2.7716385975338604;6.0 2.673019572565104;7.0 2.5579204930622765;8.0 2.4270509831248424;9.0 2.2812178968000927;10.0 2.121320343559643;11.0 1.9483441449905512;12.0 1.7633557568774194;13.0 1.5674956941478466;14.0 1.3619714992186405;15.0 1.1480502970952695;16.0 0.9270509831248425;17.0 0.7003360915677164;18.0 0.46930339512069275;19.0 0.235377287183535;20.0 1.836909530733566E-16;21.0 -0.23537728718353465;22.0 -0.46930339512069175;23.0 -0.700336091567716;24.0 -0.927050983124842;25.0 -1.148050297095269;26.0 -1.3619714992186402;27.0 -1.5674956941478464;28.0 -1.7633557568774192;29.0 -1.9483441449905508;30.0 -2.1213203435596424;31.0 -2.2812178968000927;32.0 -2.427050983124842;33.0 -2.5579204930622765;34.0 -2.6730195725651034;35.0 -2.77163859753386;36.0 -2.8531695488854605;37.0 -2.91710976119303;38.0 -2.9630650217854133;39.0 -2.990752001199384;40.0 -3.0;41.0 -2.9907520011993842;42.0 -2.9630650217854133;43.0 -2.91710976119303;44.0 -2.8531695488854614;45.0 -2.7716385975338604;46.0 -2.673019572565104;47.0 -2.557920493062276;48.0 -2.4270509831248424;49.0 -2.281217896800094;50.0 -2.121320343559643;51.0 -1.9483441449905523;52.0 -1.7633557568774199;53.0 -1.567495694147846;54.0 -1.361971499218641;55.0 -1.1480502970952686;56.0 -0.9270509831248428;57.0 -0.700336091567718;58.0 -0.46930339512069313;59.0 -0.2353772871835367;60.0 -5.510728592200698E-16;61.0 0.2353772871835356;62.0 0.469303395120692;63.0 0.7003360915677169;64.0 0.9270509831248417;65.0 1.1480502970952675;66.0 1.3619714992186398;67.0 1.5674956941478448;68.0 1.763355756877419;69.0 1.9483441449905514;70.0 2.121320343559642;71.0 2.281217896800093;72.0 2.427050983124842;73.0 2.5579204930622756;74.0 2.6730195725651034;75.0 2.7716385975338595;76.0 2.8531695488854605;77.0 2.91710976119303;78.0 2.963065021785413;79.0 2.990752001199384;80.0 3.0;81.0 2.9907520011993842;82.0 2.9630650217854138;83.0 2.91710976119303;84.0 2.853169548885461;85.0 2.77163859753386;86.0 2.673019572565104;87.0 2.557920493062278;88.0 2.427050983124844;89.0 2.2812178968000927;90.0 2.1213203435596433;91.0 1.9483441449905525;92.0 1.76335575687742;93.0 1.5674956941478484;94.0 1.3619714992186387;95.0 1.1480502970952688;96.0 0.9270509831248431;97.0 0.7003360915677184;98.0 0.46930339512069613;99.0 0.2353772871835344;100.0 9.18454765366783E-16;;Dataset:6;1.0 2.4939101256495606;2.0 2.475670171853926;3.0 2.4453690018345142;4.0 2.4031542398457972;5.0 2.349231551964771;6.0 2.283863644106502;7.0 2.2073689821473175;8.0 2.120120240391065;9.0 2.0225424859373686;10.0 1.9151111077974452;11.0 1.798349500846628;12.0 1.6728265158971456;13.0 1.5391536883141457;14.0 1.397982258676867;15.0 1.2500000000000002;16.0 1.0959278669726935;17.0 0.9365164835397799;18.0 0.7725424859373686;19.0 0.6048047389991698;20.0 0.4341204441673261;21.0 0.26132115816913365;22.0 0.0872487417562527;23.0 -0.08724874175625184;24.0 -0.2613211581691333;25.0 -0.43412044416732576;26.0 -0.6048047389991694;27.0 -0.7725424859373684;28.0 -0.9365164835397801;29.0 -1.0959278669726937;30.0 -1.2499999999999996;31.0 -1.3979822586768669;32.0 -1.5391536883141457;33.0 -1.6728265158971456;34.0 -1.7983495008466281;35.0 -1.9151111077974448;36.0 -2.0225424859373686;37.0 -2.120120240391065;38.0 -2.207368982147317;39.0 -2.283863644106502;40.0 -2.349231551964771;41.0 -2.403154239845797;42.0 -2.4453690018345142;43.0 -2.475670171853926;44.0 -2.4939101256495606;45.0 -2.5;46.0 -2.4939101256495606;47.0 -2.475670171853926;48.0 -2.4453690018345142;49.0 -2.4031542398457972;50.0 -2.349231551964771;51.0 -2.2838636441065026;52.0 -2.207368982147317;53.0 -2.1201202403910653;54.0 -2.0225424859373686;55.0 -1.9151111077974452;56.0 -1.7983495008466277;57.0 -1.672826515897146;58.0 -1.5391536883141452;59.0 -1.3979822586768682;60.0 -1.2500000000000009;61.0 -1.0959278669726944;62.0 -0.9365164835397807;63.0 -0.772542485937369;64.0 -0.6048047389991695;65.0 -0.4341204441673258;66.0 -0.26132115816913337;67.0 -0.08724874175625412;68.0 0.0872487417562532;69.0 0.2613211581691325;70.0 0.4341204441673249;71.0 0.6048047389991686;72.0 0.7725424859373681;73.0 0.9365164835397799;74.0 1.0959278669726935;75.0 1.2500000000000002;76.0 1.3979822586768655;77.0 1.5391536883141463;78.0 1.6728265158971445;79.0 1.798349500846627;80.0 1.9151111077974445;81.0 2.022542485937368;82.0 2.1201202403910635;83.0 2.2073689821473175;84.0 2.283863644106502;85.0 2.3492315519647713;86.0 2.403154239845797;87.0 2.445369001834514;88.0 2.475670171853926;89.0 2.4939101256495606;90.0 2.5;91.0 2.4939101256495606;92.0 2.4756701718539262;93.0 2.4453690018345147;94.0 2.4031542398457972;95.0 2.349231551964771;96.0 2.283863644106503;97.0 2.207368982147318;98.0 2.1201202403910653;99.0 2.0225424859373677;100.0 1.9151111077974454;;Dataset:7;0.0 2.0;1.0 1.9960534568565431;2.0 1.9842294026289558;3.0 1.9645745014573774;4.0 1.9371663222572622;5.0 1.902113032590307;6.0 1.859552971776503;7.0 1.8096541049320392;8.0 1.7526133600877272;9.0 1.6886558510040302;10.0 1.618033988749895;11.0 1.5410264855515785;12.0 1.457937254842823;13.0 1.3690942118573772;14.0 1.2748479794973795;15.0 1.1755705045849465;16.0 1.071653589957993;17.0 0.9635073482034303;18.0 0.8515585831301453;19.0 0.7362491053693562;20.0 0.6180339887498949;21.0 0.4973797743297095;22.0 0.3747626291714495;23.0 0.25066646712860896;24.0 0.12558103905862705;25.0 1.2246063538223773E-16;26.0 -0.1255810390586268;27.0 -0.2506664671286083;28.0 -0.3747626291714492;29.0 -0.4973797743297097;30.0 -0.6180339887498942;31.0 -0.7362491053693555;32.0 -0.8515585831301454;33.0 -0.9635073482034309;34.0 -1.0716535899579938;35.0 -1.175570504584946;36.0 -1.2748479794973795;37.0 -1.3690942118573775;38.0 -1.4579372548428227;39.0 -1.5410264855515783;40.0 -1.6180339887498947;41.0 -1.6886558510040297;42.0 -1.7526133600877272;43.0 -1.8096541049320387;44.0 -1.8595529717765027;45.0 -1.902113032590307;46.0 -1.937166322257262;47.0 -1.9645745014573774;48.0 -1.9842294026289555;49.0 -1.9960534568565431;50.0 -2.0;51.0 -1.9960534568565431;52.0 -1.9842294026289558;53.0 -1.9645745014573772;54.0 -1.9371663222572624;55.0 -1.9021130325903073;56.0 -1.859552971776503;57.0 -1.8096541049320394;58.0 -1.752613360087727;59.0 -1.6886558510040304;60.0 -1.6180339887498956;61.0 -1.5410264855515785;62.0 -1.4579372548428235;63.0 -1.3690942118573772;64.0 -1.274847979497379;65.0 -1.1755705045849465;66.0 -1.0716535899579926;67.0 -0.9635073482034305;68.0 -0.8515585831301443;69.0 -0.7362491053693556;70.0 -0.6180339887498951;71.0 -0.49737977432970887;72.0 -0.37476262917144926;73.0 -0.2506664671286092;74.0 -0.12558103905862641;75.0 -3.673819061467132E-16;76.0 0.12558103905862567;77.0 0.25066646712860846;78.0 0.37476262917144854;79.0 0.49737977432970987;80.0 0.6180339887498945;81.0 0.7362491053693548;82.0 0.8515585831301437;83.0 0.9635073482034314;84.0 1.0716535899579935;85.0 1.1755705045849458;86.0 1.2748479794973786;87.0 1.369094211857376;88.0 1.4579372548428224;89.0 1.5410264855515787;90.0 1.6180339887498947;91.0 1.6886558510040295;92.0 1.7526133600877263;93.0 1.8096541049320387;94.0 1.859552971776503;95.0 1.902113032590307;96.0 1.937166322257262;97.0 1.9645745014573774;98.0 1.9842294026289555;99.0 1.9960534568565431;100.0 2.0;;;Dataset:8;0.0 1.5;1.0 1.4975536558892035;2.0 1.4902226030228254;3.0 1.4780307537715396;4.0 1.4610178754135004;5.0 1.439239460421746;6.0 1.412766545459287;7.0 1.3816854796722753;8.0 1.3460976430370377;9.0 1.3061191156796659;10.0 1.2618802992467717;11.0 1.2135254915624212;12.0 1.1612124159586237;13.0 1.1051117068146072;14.0 1.0454063529829403;15.0 0.9822911009179277;16.0 0.9159718194531573;17.0 0.8466648283001538;18.0 0.7745961924584429;19.0 0.7000009848385107;20.0 0.6231225195028297;21.0 0.5442115580259614;22.0 0.4635254915624215;23.0 0.38132750129023063;24.0 0.2978856999686183;25.0 0.21347225740992767;26.0 0.12836251271825944;27.0 0.04283407619054471;28.0 -0.0428340761905442;29.0 -0.12836251271825957;30.0 -0.21347225740992748;31.0 -0.29788569996861813;32.0 -0.38132750129023013;33.0 -0.463525491562421;34.0 -0.5442115580259616;35.0 -0.6231225195028295;36.0 -0.7000009848385106;37.0 -0.7745961924584427;38.0 -0.8466648283001534;39.0 -0.9159718194531568;40.0 -0.9822911009179276;41.0 -1.04540635298294;42.0 -1.1051117068146075;43.0 -1.1612124159586237;44.0 -1.2135254915624207;45.0 -1.2618802992467715;46.0 -1.3061191156796654;47.0 -1.3460976430370375;48.0 -1.381685479672275;49.0 -1.4127665454592868;50.0 -1.439239460421746;51.0 -1.4610178754135001;52.0 -1.4780307537715396;53.0 -1.4902226030228254;54.0 -1.4975536558892035;55.0 -1.5;56.0 -1.4975536558892035;57.0 -1.4902226030228254;58.0 -1.4780307537715396;59.0 -1.4610178754135004;60.0 -1.4392394604217462;61.0 -1.412766545459287;62.0 -1.3816854796722753;63.0 -1.3460976430370375;64.0 -1.306119115679666;65.0 -1.2618802992467721;66.0 -1.2135254915624212;67.0 -1.161212415958624;68.0 -1.1051117068146072;69.0 -1.0454063529829403;70.0 -0.9822911009179278;71.0 -0.9159718194531575;72.0 -0.8466648283001538;73.0 -0.7745961924584436;74.0 -0.7000009848385109;75.0 -0.6231225195028295;76.0 -0.5442115580259622;77.0 -0.4635254915624214;78.0 -0.38132750129023146;79.0 -0.2978856999686188;80.0 -0.21347225740992787;81.0 -0.1283625127182606;82.0 -0.0428340761905449;83.0 0.04283407619054434;84.0 0.12836251271826005;85.0 0.2134722574099273;86.0 0.29788569996861824;87.0 0.38132750129022963;88.0 0.46352549156241957;89.0 0.5442115580259617;90.0 0.623122519502829;91.0 0.7000009848385104;92.0 0.774596192458442;93.0 0.8466648283001533;94.0 0.9159718194531571;95.0 0.9822911009179279;96.0 1.0454063529829398;97.0 1.1051117068146075;98.0 1.1612124159586232;99.0 1.2135254915624216;100.0 1.261880299246772;;;Dataset:9;0.0 1.0;1.0 0.9986295347545738;2.0 0.9945218953682733;3.0 0.9876883405951378;4.0 0.9781476007338057;5.0 0.9659258262890683;6.0 0.9510565162951535;7.0 0.9335804264972017;8.0 0.9135454576426009;9.0 0.8910065241883679;10.0 0.8660254037844387;11.0 0.838670567945424;12.0 0.8090169943749475;13.0 0.7771459614569709;14.0 0.7431448254773942;15.0 0.7071067811865476;16.0 0.6691306063588582;17.0 0.6293203910498375;18.0 0.5877852522924731;19.0 0.5446390350150272;20.0 0.5000000000000001;21.0 0.4539904997395468;22.0 0.4067366430758004;23.0 0.3583679495453004;24.0 0.30901699437494745;25.0 0.25881904510252074;26.0 0.20791169081775923;27.0 0.15643446504023092;28.0 0.10452846326765346;29.0 0.052335956242943744;30.0 2.8327492261615017E-16;31.0 -0.05233595624294362;32.0 -0.10452846326765333;33.0 -0.1564344650402308;34.0 -0.20791169081775934;35.0 -0.25881904510252063;36.0 -0.30901699437494734;37.0 -0.35836794954530027;38.0 -0.40673664307580004;39.0 -0.4539904997395467;40.0 -0.4999999999999998;41.0 -0.5446390350150268;42.0 -0.587785252292473;43.0 -0.6293203910498373;44.0 -0.6691306063588579;45.0 -0.7071067811865475;46.0 -0.743144825477394;47.0 -0.7771459614569709;48.0 -0.8090169943749473;49.0 -0.8386705679454239;50.0 -0.8660254037844387;51.0 -0.8910065241883678;52.0 -0.913545457642601;53.0 -0.9335804264972017;54.0 -0.9510565162951535;55.0 -0.9659258262890683;56.0 -0.9781476007338057;57.0 -0.9876883405951377;58.0 -0.9945218953682734;59.0 -0.9986295347545738;60.0 -1.0;61.0 -0.9986295347545738;62.0 -0.9945218953682734;63.0 -0.9876883405951378;64.0 -0.9781476007338057;65.0 -0.9659258262890684;66.0 -0.9510565162951536;67.0 -0.9335804264972019;68.0 -0.9135454576426009;69.0 -0.8910065241883679;70.0 -0.8660254037844388;71.0 -0.838670567945424;72.0 -0.8090169943749476;73.0 -0.777145961456971;74.0 -0.7431448254773942;75.0 -0.7071067811865477;76.0 -0.6691306063588585;77.0 -0.6293203910498378;78.0 -0.5877852522924732;79.0 -0.544639035015027;80.0 -0.5000000000000004;81.0 -0.4539904997395469;82.0 -0.4067366430758009;83.0 -0.3583679495452999;84.0 -0.30901699437494756;85.0 -0.25881904510252063;86.0 -0.2079116908177598;87.0 -0.15643446504023104;88.0 -0.10452846326765423;89.0 -0.052335956242943425;90.0 -1.836909530733566E-16;91.0 0.052335956242943946;92.0 0.10452846326765299;93.0 0.15643446504023067;94.0 0.20791169081775943;95.0 0.25881904510252113;96.0 0.30901699437494723;97.0 0.35836794954529955;98.0 0.40673664307579976;99.0 0.45399049973954664;;Dataset:last but not least;0.0 0.5;1.0 0.4994161134161633;2.0 0.4976658173588243;3.0 0.49475319972552556;4.0 0.4906850630697067;5.0 0.485470908713026;6.0 0.4791229145545831;7.0 0.4716559066288715;8.0 0.4630873244788883;9.0 0.4534371804252727;10.0 0.44272801282660496;11.0 0.43098483344002464;12.0 0.41823506900511337;13.0 0.4045084971874737;14.0 0.3898371770316112;15.0 0.3742553740855506;16.0 0.35779948037206055;17.0 0.3405079293933985;18.0 0.3224211063680853;19.0 0.30358125390935564;20.0 0.28403237336557796;21.0 0.2638201220530664;22.0 0.2429917066213031;23.0 0.22159577279962067;24.0 0.19968229178284783;25.0 0.17730244352126778;26.0 0.15450849718747373;27.0 0.13135368909929354;28.0 0.10789209838390307;29.0 0.08417852067351932;30.0 0.060268340127661614;31.0 0.0362174000808812;32.0 0.012081872618066208;33.0 -0.012081872618066147;34.0 -0.03621740008088125;35.0 -0.06026834012766144;36.0 -0.08417852067351926;37.0 -0.10789209838390301;38.0 -0.13135368909929337;39.0 -0.15450849718747367;40.0 -0.17730244352126773;41.0 -0.19968229178284766;42.0 -0.22159577279962062;43.0 -0.24299170662130304;44.0 -0.26382012205306626;45.0 -0.28403237336557785;46.0 -0.3035812539093556;47.0 -0.32242110636808535;48.0 -0.3405079293933985;49.0 -0.3577994803720605;50.0 -0.3742553740855506;51.0 -0.38983717703161114;52.0 -0.40450849718747367;53.0 -0.41823506900511337;54.0 -0.43098483344002453;55.0 -0.4427280128266049;56.0 -0.4534371804252727;57.0 -0.4630873244788882;58.0 -0.4716559066288715;59.0 -0.4791229145545831;60.0 -0.48547090871302595;61.0 -0.4906850630697067;62.0 -0.49475319972552556;63.0 -0.4976658173588243;64.0 -0.49941611341616327;65.0 -0.5;66.0 -0.4994161134161633;67.0 -0.4976658173588243;68.0 -0.4947531997255255;69.0 -0.4906850630697067;70.0 -0.48547090871302606;71.0 -0.47912291455458306;72.0 -0.4716559066288716;73.0 -0.46308732447888834;74.0 -0.45343718042527276;75.0 -0.44272801282660496;76.0 -0.4309848334400247;77.0 -0.4182350690051134;78.0 -0.4045084971874738;79.0 -0.3898371770316112;80.0 -0.37425537408555065;81.0 -0.3577994803720606;82.0 -0.34050792939339874;83.0 -0.32242110636808513;84.0 -0.3035812539093557;85.0 -0.28403237336557796;86.0 -0.2638201220530664;87.0 -0.24299170662130334;88.0 -0.22159577279962092;89.0 -0.19968229178284758;90.0 -0.17730244352126795;91.0 -0.15450849718747378;92.0 -0.13135368909929349;93.0 -0.10789209838390346;94.0 -0.08417852067351916;95.0 -0.06026834012766134;96.0 -0.036217400080881375;97.0 -0.01208187261806627;98.0 0.012081872618066087;99.0 0.03621740008088119;100.0 0.0602683401276616; ">
 
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
 
<param name="data" value="TitleText: My Plot 1031 datapoints processed ;XRange: 0,4 ;YRange: -4,4 ;# Manually specify X ticks ;XTicks: zero 0, one 1, two 2, pi 3.1428, four 4, five 5 ;Grid: on ;XLabel: X Axis ;YLabel: Y Axis ;Marks: various ;NumSets: 10 ;Color: on ;;Dataset: 1;0.0 5.0;1.0 4.938441702975688;2.0 4.755282581475768;3.0 4.455032620941839;4.0 4.045084971874737;5.0 3.5355339059327378;6.0 2.938926261462366;7.0 2.269952498697734;8.0 1.5450849718747373;9.0 0.7821723252011547;10.0 3.061515884555943E-16;11.0 -0.7821723252011529;12.0 -1.5450849718747368;13.0 -2.2699524986977337;14.0 -2.9389262614623655;15.0 -3.5355339059327373;16.0 -4.045084971874737;17.0 -4.455032620941839;18.0 -4.755282581475767;19.0 -4.938441702975688;20.0 -5.0;21.0 -4.938441702975688;22.0 -4.755282581475769;23.0 -4.455032620941839;24.0 -4.045084971874737;25.0 -3.535533905932738;26.0 -2.9389262614623664;27.0 -2.2699524986977346;28.0 -1.545084971874738;29.0 -0.7821723252011552;30.0 -9.18454765366783E-16;31.0 0.7821723252011534;32.0 1.5450849718747361;33.0 2.269952498697733;34.0 2.938926261462365;35.0 3.535533905932737;36.0 4.045084971874736;37.0 4.4550326209418385;38.0 4.755282581475767;39.0 4.938441702975688;40.0 5.0;41.0 4.938441702975689;42.0 4.755282581475768;43.0 4.45503262094184;44.0 4.045084971874741;45.0 3.5355339059327386;46.0 2.938926261462367;47.0 2.269952498697731;48.0 1.5450849718747386;49.0 0.7821723252011602;50.0 1.5307579422779716E-15;51.0 -0.7821723252011484;52.0 -1.5450849718747357;53.0 -2.2699524986977364;54.0 -2.938926261462364;55.0 -3.5355339059327395;56.0 -4.045084971874736;57.0 -4.455032620941837;58.0 -4.755282581475767;59.0 -4.9384417029756875;60.0 -5.0;61.0 -4.938441702975688;62.0 -4.755282581475768;63.0 -4.4550326209418385;64.0 -4.045084971874738;65.0 -3.535533905932742;66.0 -2.9389262614623672;67.0 -2.26995249869774;68.0 -1.545084971874739;69.0 -0.7821723252011521;70.0 -2.1430611191891602E-15;71.0 0.7821723252011565;72.0 1.545084971874735;73.0 2.269952498697728;74.0 2.9389262614623637;75.0 3.535533905932733;76.0 4.0450849718747355;77.0 4.45503262094184;78.0 4.755282581475767;79.0 4.938441702975689;80.0 5.0;81.0 4.938441702975689;82.0 4.755282581475772;83.0 4.4550326209418385;84.0 4.045084971874739;85.0 3.5355339059327364;86.0 2.9389262614623677;87.0 2.2699524986977404;88.0 1.5450849718747481;89.0 0.7821723252011527;90.0 2.755364296100349E-15;91.0 -0.7821723252011472;92.0 -1.5450849718747344;93.0 -2.2699524986977275;94.0 -2.9389262614623703;95.0 -3.5355339059327386;96.0 -4.0450849718747355;97.0 -4.455032620941836;98.0 -4.755282581475764;99.0 -4.938441702975688;100.0 -5.0;;Dataset:2;0.0 4.5;1.0 4.46451615591515;2.0 4.35862422507884;3.0 4.183994186497132;4.0 3.943380060197386;5.0 3.6405764746872635;6.0 3.280358823396352;7.0 2.8684079538691036;8.0 2.4112205774054845;9.0 1.9160068120428269;10.0 1.3905764746872635;11.0 0.8432159156357613;12.0 0.28255733788191084;13.0 -0.2825573378819103;14.0 -0.8432159156357607;15.0 -1.3905764746872622;16.0 -1.9160068120428273;17.0 -2.411220577405486;18.0 -2.8684079538691036;19.0 -3.280358823396351;20.0 -3.640576474687263;21.0 -3.9433800601973865;22.0 -4.183994186497131;23.0 -4.35862422507884;24.0 -4.46451615591515;25.0 -4.5;26.0 -4.46451615591515;27.0 -4.35862422507884;28.0 -4.183994186497132;29.0 -3.943380060197386;30.0 -3.640576474687265;31.0 -3.280358823396353;32.0 -2.868407953869103;33.0 -2.4112205774054836;34.0 -1.9160068120428246;35.0 -1.3905764746872642;36.0 -0.8432159156357608;37.0 -0.2825573378819094;38.0 0.28255733788190773;39.0 0.8432159156357593;40.0 1.3905764746872626;41.0 1.9160068120428233;42.0 2.4112205774054853;43.0 2.868407953869102;44.0 3.2803588233963508;45.0 3.6405764746872626;46.0 3.9433800601973843;47.0 4.183994186497132;48.0 4.358624225078839;49.0 4.46451615591515;50.0 4.5;51.0 4.464516155915151;52.0 4.35862422507884;53.0 4.183994186497131;54.0 3.943380060197387;55.0 3.640576474687264;56.0 3.280358823396352;57.0 2.8684079538691063;58.0 2.411220577405484;59.0 1.9160068120428289;60.0 1.3905764746872684;61.0 0.8432159156357614;62.0 0.28255733788191395;63.0 -0.2825573378819112;64.0 -0.8432159156357626;65.0 -1.390576474687262;66.0 -1.91600681204283;67.0 -2.411220577405485;68.0 -2.8684079538691076;69.0 -3.280358823396353;70.0 -3.6405764746872626;71.0 -3.943380060197388;72.0 -4.183994186497132;73.0 -4.358624225078839;74.0 -4.464516155915151;75.0 -4.5;76.0 -4.464516155915151;77.0 -4.35862422507884;78.0 -4.183994186497133;79.0 -3.9433800601973856;80.0 -3.6405764746872644;81.0 -3.280358823396355;82.0 -2.86840795386911;83.0 -2.411220577405481;84.0 -1.9160068120428257;85.0 -1.390576474687265;86.0 -0.8432159156357658;87.0 -0.2825573378819185;88.0 0.2825573378819067;89.0 0.843215915635762;90.0 1.3905764746872615;91.0 1.9160068120428222;92.0 2.411220577405478;93.0 2.868407953869101;94.0 3.2803588233963525;95.0 3.640576474687262;96.0 3.9433800601973834;97.0 4.183994186497131;98.0 4.358624225078839;99.0 4.464516155915151;100.0 4.5;;;;Dataset:3;0.0 4.0;1.0 3.978087581473093;2.0 3.9125904029352228;3.0 3.804226065180614;4.0 3.6541818305704035;5.0 3.464101615137755;6.0 3.23606797749979;7.0 2.972579301909577;8.0 2.676522425435433;9.0 2.3511410091698925;10.0 2.0000000000000004;11.0 1.6269465723032015;12.0 1.2360679774997898;13.0 0.8316467632710369;14.0 0.41811385307061383;15.0 1.1330996904646007E-15;16.0 -0.41811385307061333;17.0 -0.8316467632710374;18.0 -1.2360679774997894;19.0 -1.6269465723032002;20.0 -1.9999999999999991;21.0 -2.351141009169892;22.0 -2.6765224254354316;23.0 -2.972579301909576;24.0 -3.2360679774997894;25.0 -3.464101615137755;26.0 -3.654181830570404;27.0 -3.804226065180614;28.0 -3.9125904029352228;29.0 -3.9780875814730936;30.0 -4.0;31.0 -3.9780875814730936;32.0 -3.9125904029352228;33.0 -3.8042260651806146;34.0 -3.6541818305704035;35.0 -3.4641016151377553;36.0 -3.2360679774997902;37.0 -2.972579301909577;38.0 -2.676522425435434;39.0 -2.351141009169893;40.0 -2.0000000000000018;41.0 -1.6269465723032035;42.0 -1.2360679774997902;43.0 -0.8316467632710391;44.0 -0.41811385307061694;45.0 -7.347638122934264E-16;46.0 0.41811385307061194;47.0 0.8316467632710377;48.0 1.236067977499789;49.0 1.626946572303199;50.0 2.0000000000000004;51.0 2.3511410091698917;52.0 2.676522425435434;53.0 2.972579301909577;54.0 3.2360679774997894;55.0 3.4641016151377553;56.0 3.654181830570404;57.0 3.804226065180614;58.0 3.9125904029352228;59.0 3.978087581473093;60.0 4.0;61.0 3.9780875814730936;62.0 3.912590402935223;63.0 3.8042260651806146;64.0 3.6541818305704044;65.0 3.464101615137756;66.0 3.2360679774997902;67.0 2.9725793019095783;68.0 2.676522425435433;69.0 2.3511410091698934;70.0 2.000000000000002;71.0 1.6269465723032008;72.0 1.236067977499791;73.0 0.8316467632710397;74.0 0.4181138530706139;75.0 1.2246063538223773E-15;76.0 -0.4181138530706115;77.0 -0.8316467632710338;78.0 -1.2360679774997885;79.0 -1.6269465723032017;80.0 -1.999999999999997;81.0 -2.3511410091698917;82.0 -2.6765224254354285;83.0 -2.972579301909579;84.0 -3.236067977499789;85.0 -3.4641016151377553;86.0 -3.654181830570402;87.0 -3.8042260651806137;88.0 -3.9125904029352214;89.0 -3.9780875814730936;90.0 -4.0;91.0 -3.978087581473093;92.0 -3.912590402935223;93.0 -3.8042260651806146;94.0 -3.654181830570403;95.0 -3.464101615137753;96.0 -3.2360679774997907;97.0 -2.972579301909581;98.0 -2.6765224254354356;99.0 -2.351141009169894;100.0 -1.9999999999999993;;;Dataset:4;0.0 3.5;1.0 3.4859100289833367;2.0 3.4437535600952036;3.0 3.3738700124354866;4.0 3.2768220472390803;5.0 3.153391037658467;6.0 3.0045707776065314;7.0 2.831559480312316;8.0 2.6357501310126383;9.0 2.4187192714540267;10.0 2.1822143065055672;11.0 1.9281394350823593;12.0 1.6585403186554954;13.0 1.3755876107887328;14.0 1.081559480312316;15.0 0.7788232688471006;16.0 0.4698164303617944;17.0 0.15702690622680246;18.0 -0.15702690622680202;19.0 -0.46981643036179394;20.0 -0.7788232688471002;21.0 -1.0815594803123156;22.0 -1.3755876107887317;23.0 -1.658540318655495;24.0 -1.9281394350823586;25.0 -2.1822143065055672;26.0 -2.418719271454026;27.0 -2.635750131012638;28.0 -2.8315594803123156;29.0 -3.0045707776065314;30.0 -3.1533910376584666;31.0 -3.27682204723908;32.0 -3.3738700124354866;33.0 -3.4437535600952036;34.0 -3.4859100289833367;35.0 -3.5;36.0 -3.4859100289833367;37.0 -3.443753560095204;38.0 -3.3738700124354866;39.0 -3.2768220472390803;40.0 -3.153391037658467;41.0 -3.0045707776065327;42.0 -2.831559480312316;43.0 -2.6357501310126388;44.0 -2.418719271454028;45.0 -2.1822143065055677;46.0 -1.9281394350823593;47.0 -1.658540318655496;48.0 -1.3755876107887333;49.0 -1.0815594803123165;50.0 -0.778823268847101;51.0 -0.46981643036179477;52.0 -0.15702690622680288;53.0 0.1570269062268016;54.0 0.4698164303617935;55.0 0.7788232688470997;56.0 1.0815594803123154;57.0 1.375587610788732;58.0 1.6585403186554948;59.0 1.9281394350823582;60.0 2.182214306505567;61.0 2.4187192714540258;62.0 2.635750131012638;63.0 2.8315594803123156;64.0 3.004570777606531;65.0 3.1533910376584666;66.0 3.27682204723908;67.0 3.373870012435486;68.0 3.4437535600952036;69.0 3.4859100289833367;70.0 3.5;71.0 3.4859100289833367;72.0 3.443753560095204;73.0 3.3738700124354866;74.0 3.2768220472390808;75.0 3.1533910376584675;76.0 3.004570777606532;77.0 2.8315594803123165;78.0 2.6357501310126388;79.0 2.418719271454027;80.0 2.182214306505568;81.0 1.9281394350823597;82.0 1.658540318655499;83.0 1.3755876107887308;84.0 1.081559480312317;85.0 0.7788232688471014;86.0 0.4698164303617952;87.0 0.1570269062268064;88.0 -0.15702690622679805;89.0 -0.46981643036179616;90.0 -0.7788232688470993;91.0 -1.081559480312315;92.0 -1.3755876107887317;93.0 -1.6585403186554943;94.0 -1.928139435082358;95.0 -2.1822143065055664;96.0 -2.4187192714540253;97.0 -2.6357501310126374;98.0 -2.831559480312315;99.0 -3.004570777606531;100.0 -3.1533910376584666;;Dataset:5;0.0 3.0;1.0 2.990752001199384;2.0 2.9630650217854133;3.0 2.91710976119303;4.0 2.853169548885461;5.0 2.7716385975338604;6.0 2.673019572565104;7.0 2.5579204930622765;8.0 2.4270509831248424;9.0 2.2812178968000927;10.0 2.121320343559643;11.0 1.9483441449905512;12.0 1.7633557568774194;13.0 1.5674956941478466;14.0 1.3619714992186405;15.0 1.1480502970952695;16.0 0.9270509831248425;17.0 0.7003360915677164;18.0 0.46930339512069275;19.0 0.235377287183535;20.0 1.836909530733566E-16;21.0 -0.23537728718353465;22.0 -0.46930339512069175;23.0 -0.700336091567716;24.0 -0.927050983124842;25.0 -1.148050297095269;26.0 -1.3619714992186402;27.0 -1.5674956941478464;28.0 -1.7633557568774192;29.0 -1.9483441449905508;30.0 -2.1213203435596424;31.0 -2.2812178968000927;32.0 -2.427050983124842;33.0 -2.5579204930622765;34.0 -2.6730195725651034;35.0 -2.77163859753386;36.0 -2.8531695488854605;37.0 -2.91710976119303;38.0 -2.9630650217854133;39.0 -2.990752001199384;40.0 -3.0;41.0 -2.9907520011993842;42.0 -2.9630650217854133;43.0 -2.91710976119303;44.0 -2.8531695488854614;45.0 -2.7716385975338604;46.0 -2.673019572565104;47.0 -2.557920493062276;48.0 -2.4270509831248424;49.0 -2.281217896800094;50.0 -2.121320343559643;51.0 -1.9483441449905523;52.0 -1.7633557568774199;53.0 -1.567495694147846;54.0 -1.361971499218641;55.0 -1.1480502970952686;56.0 -0.9270509831248428;57.0 -0.700336091567718;58.0 -0.46930339512069313;59.0 -0.2353772871835367;60.0 -5.510728592200698E-16;61.0 0.2353772871835356;62.0 0.469303395120692;63.0 0.7003360915677169;64.0 0.9270509831248417;65.0 1.1480502970952675;66.0 1.3619714992186398;67.0 1.5674956941478448;68.0 1.763355756877419;69.0 1.9483441449905514;70.0 2.121320343559642;71.0 2.281217896800093;72.0 2.427050983124842;73.0 2.5579204930622756;74.0 2.6730195725651034;75.0 2.7716385975338595;76.0 2.8531695488854605;77.0 2.91710976119303;78.0 2.963065021785413;79.0 2.990752001199384;80.0 3.0;81.0 2.9907520011993842;82.0 2.9630650217854138;83.0 2.91710976119303;84.0 2.853169548885461;85.0 2.77163859753386;86.0 2.673019572565104;87.0 2.557920493062278;88.0 2.427050983124844;89.0 2.2812178968000927;90.0 2.1213203435596433;91.0 1.9483441449905525;92.0 1.76335575687742;93.0 1.5674956941478484;94.0 1.3619714992186387;95.0 1.1480502970952688;96.0 0.9270509831248431;97.0 0.7003360915677184;98.0 0.46930339512069613;99.0 0.2353772871835344;100.0 9.18454765366783E-16;;Dataset:6;1.0 2.4939101256495606;2.0 2.475670171853926;3.0 2.4453690018345142;4.0 2.4031542398457972;5.0 2.349231551964771;6.0 2.283863644106502;7.0 2.2073689821473175;8.0 2.120120240391065;9.0 2.0225424859373686;10.0 1.9151111077974452;11.0 1.798349500846628;12.0 1.6728265158971456;13.0 1.5391536883141457;14.0 1.397982258676867;15.0 1.2500000000000002;16.0 1.0959278669726935;17.0 0.9365164835397799;18.0 0.7725424859373686;19.0 0.6048047389991698;20.0 0.4341204441673261;21.0 0.26132115816913365;22.0 0.0872487417562527;23.0 -0.08724874175625184;24.0 -0.2613211581691333;25.0 -0.43412044416732576;26.0 -0.6048047389991694;27.0 -0.7725424859373684;28.0 -0.9365164835397801;29.0 -1.0959278669726937;30.0 -1.2499999999999996;31.0 -1.3979822586768669;32.0 -1.5391536883141457;33.0 -1.6728265158971456;34.0 -1.7983495008466281;35.0 -1.9151111077974448;36.0 -2.0225424859373686;37.0 -2.120120240391065;38.0 -2.207368982147317;39.0 -2.283863644106502;40.0 -2.349231551964771;41.0 -2.403154239845797;42.0 -2.4453690018345142;43.0 -2.475670171853926;44.0 -2.4939101256495606;45.0 -2.5;46.0 -2.4939101256495606;47.0 -2.475670171853926;48.0 -2.4453690018345142;49.0 -2.4031542398457972;50.0 -2.349231551964771;51.0 -2.2838636441065026;52.0 -2.207368982147317;53.0 -2.1201202403910653;54.0 -2.0225424859373686;55.0 -1.9151111077974452;56.0 -1.7983495008466277;57.0 -1.672826515897146;58.0 -1.5391536883141452;59.0 -1.3979822586768682;60.0 -1.2500000000000009;61.0 -1.0959278669726944;62.0 -0.9365164835397807;63.0 -0.772542485937369;64.0 -0.6048047389991695;65.0 -0.4341204441673258;66.0 -0.26132115816913337;67.0 -0.08724874175625412;68.0 0.0872487417562532;69.0 0.2613211581691325;70.0 0.4341204441673249;71.0 0.6048047389991686;72.0 0.7725424859373681;73.0 0.9365164835397799;74.0 1.0959278669726935;75.0 1.2500000000000002;76.0 1.3979822586768655;77.0 1.5391536883141463;78.0 1.6728265158971445;79.0 1.798349500846627;80.0 1.9151111077974445;81.0 2.022542485937368;82.0 2.1201202403910635;83.0 2.2073689821473175;84.0 2.283863644106502;85.0 2.3492315519647713;86.0 2.403154239845797;87.0 2.445369001834514;88.0 2.475670171853926;89.0 2.4939101256495606;90.0 2.5;91.0 2.4939101256495606;92.0 2.4756701718539262;93.0 2.4453690018345147;94.0 2.4031542398457972;95.0 2.349231551964771;96.0 2.283863644106503;97.0 2.207368982147318;98.0 2.1201202403910653;99.0 2.0225424859373677;100.0 1.9151111077974454;;Dataset:7;0.0 2.0;1.0 1.9960534568565431;2.0 1.9842294026289558;3.0 1.9645745014573774;4.0 1.9371663222572622;5.0 1.902113032590307;6.0 1.859552971776503;7.0 1.8096541049320392;8.0 1.7526133600877272;9.0 1.6886558510040302;10.0 1.618033988749895;11.0 1.5410264855515785;12.0 1.457937254842823;13.0 1.3690942118573772;14.0 1.2748479794973795;15.0 1.1755705045849465;16.0 1.071653589957993;17.0 0.9635073482034303;18.0 0.8515585831301453;19.0 0.7362491053693562;20.0 0.6180339887498949;21.0 0.4973797743297095;22.0 0.3747626291714495;23.0 0.25066646712860896;24.0 0.12558103905862705;25.0 1.2246063538223773E-16;26.0 -0.1255810390586268;27.0 -0.2506664671286083;28.0 -0.3747626291714492;29.0 -0.4973797743297097;30.0 -0.6180339887498942;31.0 -0.7362491053693555;32.0 -0.8515585831301454;33.0 -0.9635073482034309;34.0 -1.0716535899579938;35.0 -1.175570504584946;36.0 -1.2748479794973795;37.0 -1.3690942118573775;38.0 -1.4579372548428227;39.0 -1.5410264855515783;40.0 -1.6180339887498947;41.0 -1.6886558510040297;42.0 -1.7526133600877272;43.0 -1.8096541049320387;44.0 -1.8595529717765027;45.0 -1.902113032590307;46.0 -1.937166322257262;47.0 -1.9645745014573774;48.0 -1.9842294026289555;49.0 -1.9960534568565431;50.0 -2.0;51.0 -1.9960534568565431;52.0 -1.9842294026289558;53.0 -1.9645745014573772;54.0 -1.9371663222572624;55.0 -1.9021130325903073;56.0 -1.859552971776503;57.0 -1.8096541049320394;58.0 -1.752613360087727;59.0 -1.6886558510040304;60.0 -1.6180339887498956;61.0 -1.5410264855515785;62.0 -1.4579372548428235;63.0 -1.3690942118573772;64.0 -1.274847979497379;65.0 -1.1755705045849465;66.0 -1.0716535899579926;67.0 -0.9635073482034305;68.0 -0.8515585831301443;69.0 -0.7362491053693556;70.0 -0.6180339887498951;71.0 -0.49737977432970887;72.0 -0.37476262917144926;73.0 -0.2506664671286092;74.0 -0.12558103905862641;75.0 -3.673819061467132E-16;76.0 0.12558103905862567;77.0 0.25066646712860846;78.0 0.37476262917144854;79.0 0.49737977432970987;80.0 0.6180339887498945;81.0 0.7362491053693548;82.0 0.8515585831301437;83.0 0.9635073482034314;84.0 1.0716535899579935;85.0 1.1755705045849458;86.0 1.2748479794973786;87.0 1.369094211857376;88.0 1.4579372548428224;89.0 1.5410264855515787;90.0 1.6180339887498947;91.0 1.6886558510040295;92.0 1.7526133600877263;93.0 1.8096541049320387;94.0 1.859552971776503;95.0 1.902113032590307;96.0 1.937166322257262;97.0 1.9645745014573774;98.0 1.9842294026289555;99.0 1.9960534568565431;100.0 2.0;;;Dataset:8;0.0 1.5;1.0 1.4975536558892035;2.0 1.4902226030228254;3.0 1.4780307537715396;4.0 1.4610178754135004;5.0 1.439239460421746;6.0 1.412766545459287;7.0 1.3816854796722753;8.0 1.3460976430370377;9.0 1.3061191156796659;10.0 1.2618802992467717;11.0 1.2135254915624212;12.0 1.1612124159586237;13.0 1.1051117068146072;14.0 1.0454063529829403;15.0 0.9822911009179277;16.0 0.9159718194531573;17.0 0.8466648283001538;18.0 0.7745961924584429;19.0 0.7000009848385107;20.0 0.6231225195028297;21.0 0.5442115580259614;22.0 0.4635254915624215;23.0 0.38132750129023063;24.0 0.2978856999686183;25.0 0.21347225740992767;26.0 0.12836251271825944;27.0 0.04283407619054471;28.0 -0.0428340761905442;29.0 -0.12836251271825957;30.0 -0.21347225740992748;31.0 -0.29788569996861813;32.0 -0.38132750129023013;33.0 -0.463525491562421;34.0 -0.5442115580259616;35.0 -0.6231225195028295;36.0 -0.7000009848385106;37.0 -0.7745961924584427;38.0 -0.8466648283001534;39.0 -0.9159718194531568;40.0 -0.9822911009179276;41.0 -1.04540635298294;42.0 -1.1051117068146075;43.0 -1.1612124159586237;44.0 -1.2135254915624207;45.0 -1.2618802992467715;46.0 -1.3061191156796654;47.0 -1.3460976430370375;48.0 -1.381685479672275;49.0 -1.4127665454592868;50.0 -1.439239460421746;51.0 -1.4610178754135001;52.0 -1.4780307537715396;53.0 -1.4902226030228254;54.0 -1.4975536558892035;55.0 -1.5;56.0 -1.4975536558892035;57.0 -1.4902226030228254;58.0 -1.4780307537715396;59.0 -1.4610178754135004;60.0 -1.4392394604217462;61.0 -1.412766545459287;62.0 -1.3816854796722753;63.0 -1.3460976430370375;64.0 -1.306119115679666;65.0 -1.2618802992467721;66.0 -1.2135254915624212;67.0 -1.161212415958624;68.0 -1.1051117068146072;69.0 -1.0454063529829403;70.0 -0.9822911009179278;71.0 -0.9159718194531575;72.0 -0.8466648283001538;73.0 -0.7745961924584436;74.0 -0.7000009848385109;75.0 -0.6231225195028295;76.0 -0.5442115580259622;77.0 -0.4635254915624214;78.0 -0.38132750129023146;79.0 -0.2978856999686188;80.0 -0.21347225740992787;81.0 -0.1283625127182606;82.0 -0.0428340761905449;83.0 0.04283407619054434;84.0 0.12836251271826005;85.0 0.2134722574099273;86.0 0.29788569996861824;87.0 0.38132750129022963;88.0 0.46352549156241957;89.0 0.5442115580259617;90.0 0.623122519502829;91.0 0.7000009848385104;92.0 0.774596192458442;93.0 0.8466648283001533;94.0 0.9159718194531571;95.0 0.9822911009179279;96.0 1.0454063529829398;97.0 1.1051117068146075;98.0 1.1612124159586232;99.0 1.2135254915624216;100.0 1.261880299246772;;;Dataset:9;0.0 1.0;1.0 0.9986295347545738;2.0 0.9945218953682733;3.0 0.9876883405951378;4.0 0.9781476007338057;5.0 0.9659258262890683;6.0 0.9510565162951535;7.0 0.9335804264972017;8.0 0.9135454576426009;9.0 0.8910065241883679;10.0 0.8660254037844387;11.0 0.838670567945424;12.0 0.8090169943749475;13.0 0.7771459614569709;14.0 0.7431448254773942;15.0 0.7071067811865476;16.0 0.6691306063588582;17.0 0.6293203910498375;18.0 0.5877852522924731;19.0 0.5446390350150272;20.0 0.5000000000000001;21.0 0.4539904997395468;22.0 0.4067366430758004;23.0 0.3583679495453004;24.0 0.30901699437494745;25.0 0.25881904510252074;26.0 0.20791169081775923;27.0 0.15643446504023092;28.0 0.10452846326765346;29.0 0.052335956242943744;30.0 2.8327492261615017E-16;31.0 -0.05233595624294362;32.0 -0.10452846326765333;33.0 -0.1564344650402308;34.0 -0.20791169081775934;35.0 -0.25881904510252063;36.0 -0.30901699437494734;37.0 -0.35836794954530027;38.0 -0.40673664307580004;39.0 -0.4539904997395467;40.0 -0.4999999999999998;41.0 -0.5446390350150268;42.0 -0.587785252292473;43.0 -0.6293203910498373;44.0 -0.6691306063588579;45.0 -0.7071067811865475;46.0 -0.743144825477394;47.0 -0.7771459614569709;48.0 -0.8090169943749473;49.0 -0.8386705679454239;50.0 -0.8660254037844387;51.0 -0.8910065241883678;52.0 -0.913545457642601;53.0 -0.9335804264972017;54.0 -0.9510565162951535;55.0 -0.9659258262890683;56.0 -0.9781476007338057;57.0 -0.9876883405951377;58.0 -0.9945218953682734;59.0 -0.9986295347545738;60.0 -1.0;61.0 -0.9986295347545738;62.0 -0.9945218953682734;63.0 -0.9876883405951378;64.0 -0.9781476007338057;65.0 -0.9659258262890684;66.0 -0.9510565162951536;67.0 -0.9335804264972019;68.0 -0.9135454576426009;69.0 -0.8910065241883679;70.0 -0.8660254037844388;71.0 -0.838670567945424;72.0 -0.8090169943749476;73.0 -0.777145961456971;74.0 -0.7431448254773942;75.0 -0.7071067811865477;76.0 -0.6691306063588585;77.0 -0.6293203910498378;78.0 -0.5877852522924732;79.0 -0.544639035015027;80.0 -0.5000000000000004;81.0 -0.4539904997395469;82.0 -0.4067366430758009;83.0 -0.3583679495452999;84.0 -0.30901699437494756;85.0 -0.25881904510252063;86.0 -0.2079116908177598;87.0 -0.15643446504023104;88.0 -0.10452846326765423;89.0 -0.052335956242943425;90.0 -1.836909530733566E-16;91.0 0.052335956242943946;92.0 0.10452846326765299;93.0 0.15643446504023067;94.0 0.20791169081775943;95.0 0.25881904510252113;96.0 0.30901699437494723;97.0 0.35836794954529955;98.0 0.40673664307579976;99.0 0.45399049973954664;;Dataset:last but not least;0.0 0.5;1.0 0.4994161134161633;2.0 0.4976658173588243;3.0 0.49475319972552556;4.0 0.4906850630697067;5.0 0.485470908713026;6.0 0.4791229145545831;7.0 0.4716559066288715;8.0 0.4630873244788883;9.0 0.4534371804252727;10.0 0.44272801282660496;11.0 0.43098483344002464;12.0 0.41823506900511337;13.0 0.4045084971874737;14.0 0.3898371770316112;15.0 0.3742553740855506;16.0 0.35779948037206055;17.0 0.3405079293933985;18.0 0.3224211063680853;19.0 0.30358125390935564;20.0 0.28403237336557796;21.0 0.2638201220530664;22.0 0.2429917066213031;23.0 0.22159577279962067;24.0 0.19968229178284783;25.0 0.17730244352126778;26.0 0.15450849718747373;27.0 0.13135368909929354;28.0 0.10789209838390307;29.0 0.08417852067351932;30.0 0.060268340127661614;31.0 0.0362174000808812;32.0 0.012081872618066208;33.0 -0.012081872618066147;34.0 -0.03621740008088125;35.0 -0.06026834012766144;36.0 -0.08417852067351926;37.0 -0.10789209838390301;38.0 -0.13135368909929337;39.0 -0.15450849718747367;40.0 -0.17730244352126773;41.0 -0.19968229178284766;42.0 -0.22159577279962062;43.0 -0.24299170662130304;44.0 -0.26382012205306626;45.0 -0.28403237336557785;46.0 -0.3035812539093556;47.0 -0.32242110636808535;48.0 -0.3405079293933985;49.0 -0.3577994803720605;50.0 -0.3742553740855506;51.0 -0.38983717703161114;52.0 -0.40450849718747367;53.0 -0.41823506900511337;54.0 -0.43098483344002453;55.0 -0.4427280128266049;56.0 -0.4534371804252727;57.0 -0.4630873244788882;58.0 -0.4716559066288715;59.0 -0.4791229145545831;60.0 -0.48547090871302595;61.0 -0.4906850630697067;62.0 -0.49475319972552556;63.0 -0.4976658173588243;64.0 -0.49941611341616327;65.0 -0.5;66.0 -0.4994161134161633;67.0 -0.4976658173588243;68.0 -0.4947531997255255;69.0 -0.4906850630697067;70.0 -0.48547090871302606;71.0 -0.47912291455458306;72.0 -0.4716559066288716;73.0 -0.46308732447888834;74.0 -0.45343718042527276;75.0 -0.44272801282660496;76.0 -0.4309848334400247;77.0 -0.4182350690051134;78.0 -0.4045084971874738;79.0 -0.3898371770316112;80.0 -0.37425537408555065;81.0 -0.3577994803720606;82.0 -0.34050792939339874;83.0 -0.32242110636808513;84.0 -0.3035812539093557;85.0 -0.28403237336557796;86.0 -0.2638201220530664;87.0 -0.24299170662130334;88.0 -0.22159577279962092;89.0 -0.19968229178284758;90.0 -0.17730244352126795;91.0 -0.15450849718747378;92.0 -0.13135368909929349;93.0 -0.10789209838390346;94.0 -0.08417852067351916;95.0 -0.06026834012766134;96.0 -0.036217400080881375;97.0 -0.01208187261806627;98.0 0.012081872618066087;99.0 0.03621740008088119;100.0 0.0602683401276616;">
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/graph_via_functions.html
0,0 → 1,76
<html>
<head></head>
<body>
Data are processed via normal (rawmath) funtions.<br>
This can become really slow if too many datapoints/functions are asked.<br>
The available params are:<p>
&lt;param name="background" value="hexcolor value"&gt;<br>
&lt;param name="foreground" value="hexcolor value"&gt;<br>
&lt;param name="dataurl" value="url"&gt;<br>
&lt;param name="height" value="integer"&gt;<br>
&lt;param name="width" value="integer"&gt;<br>
&lt;param name="function" value="String1,String2,String3..."&gt;<br>
&lt;param name="smooth" value="0/1""&gt;<br>
&lt;param name="names" value="names function1,name function2 ... or left blank "&gt;<br>
&lt;param name="xmin" value="minimum x-value or left blank for auto detection"&gt;<br>
&lt;param name="xmax" value="maximum x-value or left blank for auto detection"&gt;<br>
&lt;param name="ymin" value="minimum y-value or left blank for auto detection"&gt;<br>
&lt;param name="ymax" value="maximum y-value or left blank for auto detection"&gt;<br>
&lt;param name="xlog" value="x-axis is log-scale: 0 or 1: default 0"&gt;<br>
&lt;param name="ylog" value="y-axis is log-scale: 0 or 1: default 0"&gt;<br>
&lt;param name="color" value="0 or 1 :default 1"&gt;<br>
&lt;param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank "&gt;<br>
&lt;param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank "&gt;<br>
&lt;param name="xlabel" value="label of the x-axis: default x-axis"&gt;<br>
&lt;param name="ylabel" value="label of the y-axis: default y-axis" &gt;<br>
&lt;param name="title" value="title of the plot" &gt;<br>
<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.PlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name="title" value="titel htmlsyntax: &amp; pi ... &pi;">
<param name="xlabel" value="x-as label">
<param name="ylabel" value="y-as label">
<param name="grid" value="on">
<param name="color" value="on">
<param name="xmin" value="0">
<param name="xmax" value="6">
<param name="ymax" value="5">
<param name="ymin" value="-5">
<param name="color" value="on">
<param name="smooth" value="0">
<param name="ylog" value="1">
<param name="xlog" value="1">
<param name="function" value="log(x),tan(x),sin(x),cos(x),2*cos(x),cos(2*x),1/cos(x)">
<param name="names" value="curve0:log(x),curve 1:tan(x),curve 2: sin(x),curve 3:cos(x),2*cos(x),cos(2*x),1/cos(x)">
<param name="plotsteps" value="100">
</applet>
</body>
</html>
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/editablegraph_via_file.html
0,0 → 1,37
<html>
<head></head>
<body>
Data processed via param "dataurl" (datafile)<p>
This applet "ptolemy.plot.EditablePlotApplet" can be "edited"
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.EditablePlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "true">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "dataurl" value="sinus.txt">
</applet>
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/histogram_via_file.html
0,0 → 1,114
<html>
<head></head>
<body>
Data processed via param "dataurl" (datafile)<p>
Using the "ptolemy.plot.HistogramApplet" from the Plot.jar
<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.HistogramApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "dataurl" value="histogram.data.txt">
</applet>
<p>
 
A histogram plotter<br> The plot can be configured and data can
be provided either through a file with commands or through direct
invocation of the public methods of the class<br> To read a file or a
URL, use the read() method<br>
<p>
When calling the public methods, in most cases the changes will not
be visible until paint() has been called<br> To request that this
be done, call repaint()<br> One exception is addPoint(), which
makes the affect of the new point visible immediately (or nearly
immediately) if the plot is visible on the screen<br>
<p>
The ASCII format for the file file contains any number commands,
one per line<br> Unrecognized commands and commands with syntax
errors are ignored<br> Comments are denoted by a line starting with a
pound sign "#"<br> The recognized commands include those supported by
the base class, plus a few more<br> The commands are case
insensitive, but are usually capitalized<br> The number of data sets
to be plotted does not need to be specified<br> Data sets are added as needed<br>
Each dataset is identified with a color (see the base class)<br>
<P>
The appearance of the histogram can be altered by the following commands:
<pre>
Bars: <i>width</i>
Bars: <i>width, offset</i>
</pre>
The <i>width</i> is a real number specifying the width of the bars
as a fraction of the bin width<br> It usually has a value less than
or equal to one,
and defaults to 0<br>5<br> The <i>offset</i> is a real number
specifying how much the bar of the <i>i </i><sup>th</sup> data set
is offset from the previous one<br> This allows bars to "peek out"
from behind the ones in front<br> It defaults to 0<br>15<br>
Note that the frontmost data set will be the first one<br>
<p>
The width of each bin of the histogram can be specified using:
<pre>
BinWidth: <i>width</i>
</pre>
This is given in whatever units the data has<br>
By default, each bin is centered at <i>x</i> = <i>nw</i>,
where <i>w</i> is the width of the bin and <i>n</i> is an integer<br>
That bin represents values in the range (<i>x - w/2, x + w/2</i>)<br>
The alignment of the bins can be changed with the following command:
<pre>
BinOffset: <i>offset</i>
</pre>
If this method is used with argument <i>o</i>, then each bin is
centered at <i>x = nw + o</i>, and represents values in the range
(<i>x - w/2 + o, x + w/2 + o</i>)<br> So for example, if <i>o = w/2</i>,
then each bin represents values from <i>nw</i> to
(<i>n</i> + 1)<i>w</i> for some integer <i>n</i><br>
The default offset is 0<br>5, half the default bin width<br>
<p>
To specify data to be plotted, start a data set with the following command:
<pre>
DataSet: <i>string</i>
</pre>
Here, <i>string</i> is a label that will appear in the legend<br>
It is not necessary to enclose the string in quotation marks<br>
To start a new dataset without giving it a name, use:
<pre>
DataSet:
</pre>
In this case, no item will appear in the legend<br>
New datasets are plotted <i>behind</i> the previous ones<br>
The data itself is given by a sequence of numbers, one per line<br>
The numbers are specified as
strings that can be parsed by the Double parser in Java<br>
It is also possible to specify the numbers using all the formats
accepted by the Plot class, so that the same data may be plotted by
both classes<br> The <i>x</i> data is ignored, and only the <i>y</i>
data is used to calculate the histogram<br>
 
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/graph_via_file.html
0,0 → 1,1082
<html>
<head></head>
<body>
Data processed via param "dataurl" (datafile)<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.PlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "dataurl" value="sinus.txt">
</applet>
<br>
<small>see page source for data</small>
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
TitleText: My Plot 1031 datapoints processed
XRange: 0,4
YRange: -4,4
# Manually specify X ticks
XTicks: zero 0, one 1, two 2, pi 3.1428, four 4, five 5
Grid: on
XLabel: X Axis
YLabel: Y Axis
Marks: various
NumSets: 10
Color: on
 
Dataset: 1
0.0 5.0
1.0 4.938441702975688
2.0 4.755282581475768
3.0 4.455032620941839
4.0 4.045084971874737
5.0 3.5355339059327378
6.0 2.938926261462366
7.0 2.269952498697734
8.0 1.5450849718747373
9.0 0.7821723252011547
10.0 3.061515884555943E-16
11.0 -0.7821723252011529
12.0 -1.5450849718747368
13.0 -2.2699524986977337
14.0 -2.9389262614623655
15.0 -3.5355339059327373
16.0 -4.045084971874737
17.0 -4.455032620941839
18.0 -4.755282581475767
19.0 -4.938441702975688
20.0 -5.0
21.0 -4.938441702975688
22.0 -4.755282581475769
23.0 -4.455032620941839
24.0 -4.045084971874737
25.0 -3.535533905932738
26.0 -2.9389262614623664
27.0 -2.2699524986977346
28.0 -1.545084971874738
29.0 -0.7821723252011552
30.0 -9.18454765366783E-16
31.0 0.7821723252011534
32.0 1.5450849718747361
33.0 2.269952498697733
34.0 2.938926261462365
35.0 3.535533905932737
36.0 4.045084971874736
37.0 4.4550326209418385
38.0 4.755282581475767
39.0 4.938441702975688
40.0 5.0
41.0 4.938441702975689
42.0 4.755282581475768
43.0 4.45503262094184
44.0 4.045084971874741
45.0 3.5355339059327386
46.0 2.938926261462367
47.0 2.269952498697731
48.0 1.5450849718747386
49.0 0.7821723252011602
50.0 1.5307579422779716E-15
51.0 -0.7821723252011484
52.0 -1.5450849718747357
53.0 -2.2699524986977364
54.0 -2.938926261462364
55.0 -3.5355339059327395
56.0 -4.045084971874736
57.0 -4.455032620941837
58.0 -4.755282581475767
59.0 -4.9384417029756875
60.0 -5.0
61.0 -4.938441702975688
62.0 -4.755282581475768
63.0 -4.4550326209418385
64.0 -4.045084971874738
65.0 -3.535533905932742
66.0 -2.9389262614623672
67.0 -2.26995249869774
68.0 -1.545084971874739
69.0 -0.7821723252011521
70.0 -2.1430611191891602E-15
71.0 0.7821723252011565
72.0 1.545084971874735
73.0 2.269952498697728
74.0 2.9389262614623637
75.0 3.535533905932733
76.0 4.0450849718747355
77.0 4.45503262094184
78.0 4.755282581475767
79.0 4.938441702975689
80.0 5.0
81.0 4.938441702975689
82.0 4.755282581475772
83.0 4.4550326209418385
84.0 4.045084971874739
85.0 3.5355339059327364
86.0 2.9389262614623677
87.0 2.2699524986977404
88.0 1.5450849718747481
89.0 0.7821723252011527
90.0 2.755364296100349E-15
91.0 -0.7821723252011472
92.0 -1.5450849718747344
93.0 -2.2699524986977275
94.0 -2.9389262614623703
95.0 -3.5355339059327386
96.0 -4.0450849718747355
97.0 -4.455032620941836
98.0 -4.755282581475764
99.0 -4.938441702975688
100.0 -5.0
 
Dataset:2
0.0 4.5
1.0 4.46451615591515
2.0 4.35862422507884
3.0 4.183994186497132
4.0 3.943380060197386
5.0 3.6405764746872635
6.0 3.280358823396352
7.0 2.8684079538691036
8.0 2.4112205774054845
9.0 1.9160068120428269
10.0 1.3905764746872635
11.0 0.8432159156357613
12.0 0.28255733788191084
13.0 -0.2825573378819103
14.0 -0.8432159156357607
15.0 -1.3905764746872622
16.0 -1.9160068120428273
17.0 -2.411220577405486
18.0 -2.8684079538691036
19.0 -3.280358823396351
20.0 -3.640576474687263
21.0 -3.9433800601973865
22.0 -4.183994186497131
23.0 -4.35862422507884
24.0 -4.46451615591515
25.0 -4.5
26.0 -4.46451615591515
27.0 -4.35862422507884
28.0 -4.183994186497132
29.0 -3.943380060197386
30.0 -3.640576474687265
31.0 -3.280358823396353
32.0 -2.868407953869103
33.0 -2.4112205774054836
34.0 -1.9160068120428246
35.0 -1.3905764746872642
36.0 -0.8432159156357608
37.0 -0.2825573378819094
38.0 0.28255733788190773
39.0 0.8432159156357593
40.0 1.3905764746872626
41.0 1.9160068120428233
42.0 2.4112205774054853
43.0 2.868407953869102
44.0 3.2803588233963508
45.0 3.6405764746872626
46.0 3.9433800601973843
47.0 4.183994186497132
48.0 4.358624225078839
49.0 4.46451615591515
50.0 4.5
51.0 4.464516155915151
52.0 4.35862422507884
53.0 4.183994186497131
54.0 3.943380060197387
55.0 3.640576474687264
56.0 3.280358823396352
57.0 2.8684079538691063
58.0 2.411220577405484
59.0 1.9160068120428289
60.0 1.3905764746872684
61.0 0.8432159156357614
62.0 0.28255733788191395
63.0 -0.2825573378819112
64.0 -0.8432159156357626
65.0 -1.390576474687262
66.0 -1.91600681204283
67.0 -2.411220577405485
68.0 -2.8684079538691076
69.0 -3.280358823396353
70.0 -3.6405764746872626
71.0 -3.943380060197388
72.0 -4.183994186497132
73.0 -4.358624225078839
74.0 -4.464516155915151
75.0 -4.5
76.0 -4.464516155915151
77.0 -4.35862422507884
78.0 -4.183994186497133
79.0 -3.9433800601973856
80.0 -3.6405764746872644
81.0 -3.280358823396355
82.0 -2.86840795386911
83.0 -2.411220577405481
84.0 -1.9160068120428257
85.0 -1.390576474687265
86.0 -0.8432159156357658
87.0 -0.2825573378819185
88.0 0.2825573378819067
89.0 0.843215915635762
90.0 1.3905764746872615
91.0 1.9160068120428222
92.0 2.411220577405478
93.0 2.868407953869101
94.0 3.2803588233963525
95.0 3.640576474687262
96.0 3.9433800601973834
97.0 4.183994186497131
98.0 4.358624225078839
99.0 4.464516155915151
100.0 4.5
 
 
 
Dataset:3
0.0 4.0
1.0 3.978087581473093
2.0 3.9125904029352228
3.0 3.804226065180614
4.0 3.6541818305704035
5.0 3.464101615137755
6.0 3.23606797749979
7.0 2.972579301909577
8.0 2.676522425435433
9.0 2.3511410091698925
10.0 2.0000000000000004
11.0 1.6269465723032015
12.0 1.2360679774997898
13.0 0.8316467632710369
14.0 0.41811385307061383
15.0 1.1330996904646007E-15
16.0 -0.41811385307061333
17.0 -0.8316467632710374
18.0 -1.2360679774997894
19.0 -1.6269465723032002
20.0 -1.9999999999999991
21.0 -2.351141009169892
22.0 -2.6765224254354316
23.0 -2.972579301909576
24.0 -3.2360679774997894
25.0 -3.464101615137755
26.0 -3.654181830570404
27.0 -3.804226065180614
28.0 -3.9125904029352228
29.0 -3.9780875814730936
30.0 -4.0
31.0 -3.9780875814730936
32.0 -3.9125904029352228
33.0 -3.8042260651806146
34.0 -3.6541818305704035
35.0 -3.4641016151377553
36.0 -3.2360679774997902
37.0 -2.972579301909577
38.0 -2.676522425435434
39.0 -2.351141009169893
40.0 -2.0000000000000018
41.0 -1.6269465723032035
42.0 -1.2360679774997902
43.0 -0.8316467632710391
44.0 -0.41811385307061694
45.0 -7.347638122934264E-16
46.0 0.41811385307061194
47.0 0.8316467632710377
48.0 1.236067977499789
49.0 1.626946572303199
50.0 2.0000000000000004
51.0 2.3511410091698917
52.0 2.676522425435434
53.0 2.972579301909577
54.0 3.2360679774997894
55.0 3.4641016151377553
56.0 3.654181830570404
57.0 3.804226065180614
58.0 3.9125904029352228
59.0 3.978087581473093
60.0 4.0
61.0 3.9780875814730936
62.0 3.912590402935223
63.0 3.8042260651806146
64.0 3.6541818305704044
65.0 3.464101615137756
66.0 3.2360679774997902
67.0 2.9725793019095783
68.0 2.676522425435433
69.0 2.3511410091698934
70.0 2.000000000000002
71.0 1.6269465723032008
72.0 1.236067977499791
73.0 0.8316467632710397
74.0 0.4181138530706139
75.0 1.2246063538223773E-15
76.0 -0.4181138530706115
77.0 -0.8316467632710338
78.0 -1.2360679774997885
79.0 -1.6269465723032017
80.0 -1.999999999999997
81.0 -2.3511410091698917
82.0 -2.6765224254354285
83.0 -2.972579301909579
84.0 -3.236067977499789
85.0 -3.4641016151377553
86.0 -3.654181830570402
87.0 -3.8042260651806137
88.0 -3.9125904029352214
89.0 -3.9780875814730936
90.0 -4.0
91.0 -3.978087581473093
92.0 -3.912590402935223
93.0 -3.8042260651806146
94.0 -3.654181830570403
95.0 -3.464101615137753
96.0 -3.2360679774997907
97.0 -2.972579301909581
98.0 -2.6765224254354356
99.0 -2.351141009169894
100.0 -1.9999999999999993
 
 
Dataset:4
0.0 3.5
1.0 3.4859100289833367
2.0 3.4437535600952036
3.0 3.3738700124354866
4.0 3.2768220472390803
5.0 3.153391037658467
6.0 3.0045707776065314
7.0 2.831559480312316
8.0 2.6357501310126383
9.0 2.4187192714540267
10.0 2.1822143065055672
11.0 1.9281394350823593
12.0 1.6585403186554954
13.0 1.3755876107887328
14.0 1.081559480312316
15.0 0.7788232688471006
16.0 0.4698164303617944
17.0 0.15702690622680246
18.0 -0.15702690622680202
19.0 -0.46981643036179394
20.0 -0.7788232688471002
21.0 -1.0815594803123156
22.0 -1.3755876107887317
23.0 -1.658540318655495
24.0 -1.9281394350823586
25.0 -2.1822143065055672
26.0 -2.418719271454026
27.0 -2.635750131012638
28.0 -2.8315594803123156
29.0 -3.0045707776065314
30.0 -3.1533910376584666
31.0 -3.27682204723908
32.0 -3.3738700124354866
33.0 -3.4437535600952036
34.0 -3.4859100289833367
35.0 -3.5
36.0 -3.4859100289833367
37.0 -3.443753560095204
38.0 -3.3738700124354866
39.0 -3.2768220472390803
40.0 -3.153391037658467
41.0 -3.0045707776065327
42.0 -2.831559480312316
43.0 -2.6357501310126388
44.0 -2.418719271454028
45.0 -2.1822143065055677
46.0 -1.9281394350823593
47.0 -1.658540318655496
48.0 -1.3755876107887333
49.0 -1.0815594803123165
50.0 -0.778823268847101
51.0 -0.46981643036179477
52.0 -0.15702690622680288
53.0 0.1570269062268016
54.0 0.4698164303617935
55.0 0.7788232688470997
56.0 1.0815594803123154
57.0 1.375587610788732
58.0 1.6585403186554948
59.0 1.9281394350823582
60.0 2.182214306505567
61.0 2.4187192714540258
62.0 2.635750131012638
63.0 2.8315594803123156
64.0 3.004570777606531
65.0 3.1533910376584666
66.0 3.27682204723908
67.0 3.373870012435486
68.0 3.4437535600952036
69.0 3.4859100289833367
70.0 3.5
71.0 3.4859100289833367
72.0 3.443753560095204
73.0 3.3738700124354866
74.0 3.2768220472390808
75.0 3.1533910376584675
76.0 3.004570777606532
77.0 2.8315594803123165
78.0 2.6357501310126388
79.0 2.418719271454027
80.0 2.182214306505568
81.0 1.9281394350823597
82.0 1.658540318655499
83.0 1.3755876107887308
84.0 1.081559480312317
85.0 0.7788232688471014
86.0 0.4698164303617952
87.0 0.1570269062268064
88.0 -0.15702690622679805
89.0 -0.46981643036179616
90.0 -0.7788232688470993
91.0 -1.081559480312315
92.0 -1.3755876107887317
93.0 -1.6585403186554943
94.0 -1.928139435082358
95.0 -2.1822143065055664
96.0 -2.4187192714540253
97.0 -2.6357501310126374
98.0 -2.831559480312315
99.0 -3.004570777606531
100.0 -3.1533910376584666
 
Dataset:5
0.0 3.0
1.0 2.990752001199384
2.0 2.9630650217854133
3.0 2.91710976119303
4.0 2.853169548885461
5.0 2.7716385975338604
6.0 2.673019572565104
7.0 2.5579204930622765
8.0 2.4270509831248424
9.0 2.2812178968000927
10.0 2.121320343559643
11.0 1.9483441449905512
12.0 1.7633557568774194
13.0 1.5674956941478466
14.0 1.3619714992186405
15.0 1.1480502970952695
16.0 0.9270509831248425
17.0 0.7003360915677164
18.0 0.46930339512069275
19.0 0.235377287183535
20.0 1.836909530733566E-16
21.0 -0.23537728718353465
22.0 -0.46930339512069175
23.0 -0.700336091567716
24.0 -0.927050983124842
25.0 -1.148050297095269
26.0 -1.3619714992186402
27.0 -1.5674956941478464
28.0 -1.7633557568774192
29.0 -1.9483441449905508
30.0 -2.1213203435596424
31.0 -2.2812178968000927
32.0 -2.427050983124842
33.0 -2.5579204930622765
34.0 -2.6730195725651034
35.0 -2.77163859753386
36.0 -2.8531695488854605
37.0 -2.91710976119303
38.0 -2.9630650217854133
39.0 -2.990752001199384
40.0 -3.0
41.0 -2.9907520011993842
42.0 -2.9630650217854133
43.0 -2.91710976119303
44.0 -2.8531695488854614
45.0 -2.7716385975338604
46.0 -2.673019572565104
47.0 -2.557920493062276
48.0 -2.4270509831248424
49.0 -2.281217896800094
50.0 -2.121320343559643
51.0 -1.9483441449905523
52.0 -1.7633557568774199
53.0 -1.567495694147846
54.0 -1.361971499218641
55.0 -1.1480502970952686
56.0 -0.9270509831248428
57.0 -0.700336091567718
58.0 -0.46930339512069313
59.0 -0.2353772871835367
60.0 -5.510728592200698E-16
61.0 0.2353772871835356
62.0 0.469303395120692
63.0 0.7003360915677169
64.0 0.9270509831248417
65.0 1.1480502970952675
66.0 1.3619714992186398
67.0 1.5674956941478448
68.0 1.763355756877419
69.0 1.9483441449905514
70.0 2.121320343559642
71.0 2.281217896800093
72.0 2.427050983124842
73.0 2.5579204930622756
74.0 2.6730195725651034
75.0 2.7716385975338595
76.0 2.8531695488854605
77.0 2.91710976119303
78.0 2.963065021785413
79.0 2.990752001199384
80.0 3.0
81.0 2.9907520011993842
82.0 2.9630650217854138
83.0 2.91710976119303
84.0 2.853169548885461
85.0 2.77163859753386
86.0 2.673019572565104
87.0 2.557920493062278
88.0 2.427050983124844
89.0 2.2812178968000927
90.0 2.1213203435596433
91.0 1.9483441449905525
92.0 1.76335575687742
93.0 1.5674956941478484
94.0 1.3619714992186387
95.0 1.1480502970952688
96.0 0.9270509831248431
97.0 0.7003360915677184
98.0 0.46930339512069613
99.0 0.2353772871835344
100.0 9.18454765366783E-16
 
Dataset:6
1.0 2.4939101256495606
2.0 2.475670171853926
3.0 2.4453690018345142
4.0 2.4031542398457972
5.0 2.349231551964771
6.0 2.283863644106502
7.0 2.2073689821473175
8.0 2.120120240391065
9.0 2.0225424859373686
10.0 1.9151111077974452
11.0 1.798349500846628
12.0 1.6728265158971456
13.0 1.5391536883141457
14.0 1.397982258676867
15.0 1.2500000000000002
16.0 1.0959278669726935
17.0 0.9365164835397799
18.0 0.7725424859373686
19.0 0.6048047389991698
20.0 0.4341204441673261
21.0 0.26132115816913365
22.0 0.0872487417562527
23.0 -0.08724874175625184
24.0 -0.2613211581691333
25.0 -0.43412044416732576
26.0 -0.6048047389991694
27.0 -0.7725424859373684
28.0 -0.9365164835397801
29.0 -1.0959278669726937
30.0 -1.2499999999999996
31.0 -1.3979822586768669
32.0 -1.5391536883141457
33.0 -1.6728265158971456
34.0 -1.7983495008466281
35.0 -1.9151111077974448
36.0 -2.0225424859373686
37.0 -2.120120240391065
38.0 -2.207368982147317
39.0 -2.283863644106502
40.0 -2.349231551964771
41.0 -2.403154239845797
42.0 -2.4453690018345142
43.0 -2.475670171853926
44.0 -2.4939101256495606
45.0 -2.5
46.0 -2.4939101256495606
47.0 -2.475670171853926
48.0 -2.4453690018345142
49.0 -2.4031542398457972
50.0 -2.349231551964771
51.0 -2.2838636441065026
52.0 -2.207368982147317
53.0 -2.1201202403910653
54.0 -2.0225424859373686
55.0 -1.9151111077974452
56.0 -1.7983495008466277
57.0 -1.672826515897146
58.0 -1.5391536883141452
59.0 -1.3979822586768682
60.0 -1.2500000000000009
61.0 -1.0959278669726944
62.0 -0.9365164835397807
63.0 -0.772542485937369
64.0 -0.6048047389991695
65.0 -0.4341204441673258
66.0 -0.26132115816913337
67.0 -0.08724874175625412
68.0 0.0872487417562532
69.0 0.2613211581691325
70.0 0.4341204441673249
71.0 0.6048047389991686
72.0 0.7725424859373681
73.0 0.9365164835397799
74.0 1.0959278669726935
75.0 1.2500000000000002
76.0 1.3979822586768655
77.0 1.5391536883141463
78.0 1.6728265158971445
79.0 1.798349500846627
80.0 1.9151111077974445
81.0 2.022542485937368
82.0 2.1201202403910635
83.0 2.2073689821473175
84.0 2.283863644106502
85.0 2.3492315519647713
86.0 2.403154239845797
87.0 2.445369001834514
88.0 2.475670171853926
89.0 2.4939101256495606
90.0 2.5
91.0 2.4939101256495606
92.0 2.4756701718539262
93.0 2.4453690018345147
94.0 2.4031542398457972
95.0 2.349231551964771
96.0 2.283863644106503
97.0 2.207368982147318
98.0 2.1201202403910653
99.0 2.0225424859373677
100.0 1.9151111077974454
 
Dataset:7
0.0 2.0
1.0 1.9960534568565431
2.0 1.9842294026289558
3.0 1.9645745014573774
4.0 1.9371663222572622
5.0 1.902113032590307
6.0 1.859552971776503
7.0 1.8096541049320392
8.0 1.7526133600877272
9.0 1.6886558510040302
10.0 1.618033988749895
11.0 1.5410264855515785
12.0 1.457937254842823
13.0 1.3690942118573772
14.0 1.2748479794973795
15.0 1.1755705045849465
16.0 1.071653589957993
17.0 0.9635073482034303
18.0 0.8515585831301453
19.0 0.7362491053693562
20.0 0.6180339887498949
21.0 0.4973797743297095
22.0 0.3747626291714495
23.0 0.25066646712860896
24.0 0.12558103905862705
25.0 1.2246063538223773E-16
26.0 -0.1255810390586268
27.0 -0.2506664671286083
28.0 -0.3747626291714492
29.0 -0.4973797743297097
30.0 -0.6180339887498942
31.0 -0.7362491053693555
32.0 -0.8515585831301454
33.0 -0.9635073482034309
34.0 -1.0716535899579938
35.0 -1.175570504584946
36.0 -1.2748479794973795
37.0 -1.3690942118573775
38.0 -1.4579372548428227
39.0 -1.5410264855515783
40.0 -1.6180339887498947
41.0 -1.6886558510040297
42.0 -1.7526133600877272
43.0 -1.8096541049320387
44.0 -1.8595529717765027
45.0 -1.902113032590307
46.0 -1.937166322257262
47.0 -1.9645745014573774
48.0 -1.9842294026289555
49.0 -1.9960534568565431
50.0 -2.0
51.0 -1.9960534568565431
52.0 -1.9842294026289558
53.0 -1.9645745014573772
54.0 -1.9371663222572624
55.0 -1.9021130325903073
56.0 -1.859552971776503
57.0 -1.8096541049320394
58.0 -1.752613360087727
59.0 -1.6886558510040304
60.0 -1.6180339887498956
61.0 -1.5410264855515785
62.0 -1.4579372548428235
63.0 -1.3690942118573772
64.0 -1.274847979497379
65.0 -1.1755705045849465
66.0 -1.0716535899579926
67.0 -0.9635073482034305
68.0 -0.8515585831301443
69.0 -0.7362491053693556
70.0 -0.6180339887498951
71.0 -0.49737977432970887
72.0 -0.37476262917144926
73.0 -0.2506664671286092
74.0 -0.12558103905862641
75.0 -3.673819061467132E-16
76.0 0.12558103905862567
77.0 0.25066646712860846
78.0 0.37476262917144854
79.0 0.49737977432970987
80.0 0.6180339887498945
81.0 0.7362491053693548
82.0 0.8515585831301437
83.0 0.9635073482034314
84.0 1.0716535899579935
85.0 1.1755705045849458
86.0 1.2748479794973786
87.0 1.369094211857376
88.0 1.4579372548428224
89.0 1.5410264855515787
90.0 1.6180339887498947
91.0 1.6886558510040295
92.0 1.7526133600877263
93.0 1.8096541049320387
94.0 1.859552971776503
95.0 1.902113032590307
96.0 1.937166322257262
97.0 1.9645745014573774
98.0 1.9842294026289555
99.0 1.9960534568565431
100.0 2.0
 
 
Dataset:8
0.0 1.5
1.0 1.4975536558892035
2.0 1.4902226030228254
3.0 1.4780307537715396
4.0 1.4610178754135004
5.0 1.439239460421746
6.0 1.412766545459287
7.0 1.3816854796722753
8.0 1.3460976430370377
9.0 1.3061191156796659
10.0 1.2618802992467717
11.0 1.2135254915624212
12.0 1.1612124159586237
13.0 1.1051117068146072
14.0 1.0454063529829403
15.0 0.9822911009179277
16.0 0.9159718194531573
17.0 0.8466648283001538
18.0 0.7745961924584429
19.0 0.7000009848385107
20.0 0.6231225195028297
21.0 0.5442115580259614
22.0 0.4635254915624215
23.0 0.38132750129023063
24.0 0.2978856999686183
25.0 0.21347225740992767
26.0 0.12836251271825944
27.0 0.04283407619054471
28.0 -0.0428340761905442
29.0 -0.12836251271825957
30.0 -0.21347225740992748
31.0 -0.29788569996861813
32.0 -0.38132750129023013
33.0 -0.463525491562421
34.0 -0.5442115580259616
35.0 -0.6231225195028295
36.0 -0.7000009848385106
37.0 -0.7745961924584427
38.0 -0.8466648283001534
39.0 -0.9159718194531568
40.0 -0.9822911009179276
41.0 -1.04540635298294
42.0 -1.1051117068146075
43.0 -1.1612124159586237
44.0 -1.2135254915624207
45.0 -1.2618802992467715
46.0 -1.3061191156796654
47.0 -1.3460976430370375
48.0 -1.381685479672275
49.0 -1.4127665454592868
50.0 -1.439239460421746
51.0 -1.4610178754135001
52.0 -1.4780307537715396
53.0 -1.4902226030228254
54.0 -1.4975536558892035
55.0 -1.5
56.0 -1.4975536558892035
57.0 -1.4902226030228254
58.0 -1.4780307537715396
59.0 -1.4610178754135004
60.0 -1.4392394604217462
61.0 -1.412766545459287
62.0 -1.3816854796722753
63.0 -1.3460976430370375
64.0 -1.306119115679666
65.0 -1.2618802992467721
66.0 -1.2135254915624212
67.0 -1.161212415958624
68.0 -1.1051117068146072
69.0 -1.0454063529829403
70.0 -0.9822911009179278
71.0 -0.9159718194531575
72.0 -0.8466648283001538
73.0 -0.7745961924584436
74.0 -0.7000009848385109
75.0 -0.6231225195028295
76.0 -0.5442115580259622
77.0 -0.4635254915624214
78.0 -0.38132750129023146
79.0 -0.2978856999686188
80.0 -0.21347225740992787
81.0 -0.1283625127182606
82.0 -0.0428340761905449
83.0 0.04283407619054434
84.0 0.12836251271826005
85.0 0.2134722574099273
86.0 0.29788569996861824
87.0 0.38132750129022963
88.0 0.46352549156241957
89.0 0.5442115580259617
90.0 0.623122519502829
91.0 0.7000009848385104
92.0 0.774596192458442
93.0 0.8466648283001533
94.0 0.9159718194531571
95.0 0.9822911009179279
96.0 1.0454063529829398
97.0 1.1051117068146075
98.0 1.1612124159586232
99.0 1.2135254915624216
100.0 1.261880299246772
 
 
Dataset:9
0.0 1.0
1.0 0.9986295347545738
2.0 0.9945218953682733
3.0 0.9876883405951378
4.0 0.9781476007338057
5.0 0.9659258262890683
6.0 0.9510565162951535
7.0 0.9335804264972017
8.0 0.9135454576426009
9.0 0.8910065241883679
10.0 0.8660254037844387
11.0 0.838670567945424
12.0 0.8090169943749475
13.0 0.7771459614569709
14.0 0.7431448254773942
15.0 0.7071067811865476
16.0 0.6691306063588582
17.0 0.6293203910498375
18.0 0.5877852522924731
19.0 0.5446390350150272
20.0 0.5000000000000001
21.0 0.4539904997395468
22.0 0.4067366430758004
23.0 0.3583679495453004
24.0 0.30901699437494745
25.0 0.25881904510252074
26.0 0.20791169081775923
27.0 0.15643446504023092
28.0 0.10452846326765346
29.0 0.052335956242943744
30.0 2.8327492261615017E-16
31.0 -0.05233595624294362
32.0 -0.10452846326765333
33.0 -0.1564344650402308
34.0 -0.20791169081775934
35.0 -0.25881904510252063
36.0 -0.30901699437494734
37.0 -0.35836794954530027
38.0 -0.40673664307580004
39.0 -0.4539904997395467
40.0 -0.4999999999999998
41.0 -0.5446390350150268
42.0 -0.587785252292473
43.0 -0.6293203910498373
44.0 -0.6691306063588579
45.0 -0.7071067811865475
46.0 -0.743144825477394
47.0 -0.7771459614569709
48.0 -0.8090169943749473
49.0 -0.8386705679454239
50.0 -0.8660254037844387
51.0 -0.8910065241883678
52.0 -0.913545457642601
53.0 -0.9335804264972017
54.0 -0.9510565162951535
55.0 -0.9659258262890683
56.0 -0.9781476007338057
57.0 -0.9876883405951377
58.0 -0.9945218953682734
59.0 -0.9986295347545738
60.0 -1.0
61.0 -0.9986295347545738
62.0 -0.9945218953682734
63.0 -0.9876883405951378
64.0 -0.9781476007338057
65.0 -0.9659258262890684
66.0 -0.9510565162951536
67.0 -0.9335804264972019
68.0 -0.9135454576426009
69.0 -0.8910065241883679
70.0 -0.8660254037844388
71.0 -0.838670567945424
72.0 -0.8090169943749476
73.0 -0.777145961456971
74.0 -0.7431448254773942
75.0 -0.7071067811865477
76.0 -0.6691306063588585
77.0 -0.6293203910498378
78.0 -0.5877852522924732
79.0 -0.544639035015027
80.0 -0.5000000000000004
81.0 -0.4539904997395469
82.0 -0.4067366430758009
83.0 -0.3583679495452999
84.0 -0.30901699437494756
85.0 -0.25881904510252063
86.0 -0.2079116908177598
87.0 -0.15643446504023104
88.0 -0.10452846326765423
89.0 -0.052335956242943425
90.0 -1.836909530733566E-16
91.0 0.052335956242943946
92.0 0.10452846326765299
93.0 0.15643446504023067
94.0 0.20791169081775943
95.0 0.25881904510252113
96.0 0.30901699437494723
97.0 0.35836794954529955
98.0 0.40673664307579976
99.0 0.45399049973954664
 
Dataset:last but not least
0.0 0.5
1.0 0.4994161134161633
2.0 0.4976658173588243
3.0 0.49475319972552556
4.0 0.4906850630697067
5.0 0.485470908713026
6.0 0.4791229145545831
7.0 0.4716559066288715
8.0 0.4630873244788883
9.0 0.4534371804252727
10.0 0.44272801282660496
11.0 0.43098483344002464
12.0 0.41823506900511337
13.0 0.4045084971874737
14.0 0.3898371770316112
15.0 0.3742553740855506
16.0 0.35779948037206055
17.0 0.3405079293933985
18.0 0.3224211063680853
19.0 0.30358125390935564
20.0 0.28403237336557796
21.0 0.2638201220530664
22.0 0.2429917066213031
23.0 0.22159577279962067
24.0 0.19968229178284783
25.0 0.17730244352126778
26.0 0.15450849718747373
27.0 0.13135368909929354
28.0 0.10789209838390307
29.0 0.08417852067351932
30.0 0.060268340127661614
31.0 0.0362174000808812
32.0 0.012081872618066208
33.0 -0.012081872618066147
34.0 -0.03621740008088125
35.0 -0.06026834012766144
36.0 -0.08417852067351926
37.0 -0.10789209838390301
38.0 -0.13135368909929337
39.0 -0.15450849718747367
40.0 -0.17730244352126773
41.0 -0.19968229178284766
42.0 -0.22159577279962062
43.0 -0.24299170662130304
44.0 -0.26382012205306626
45.0 -0.28403237336557785
46.0 -0.3035812539093556
47.0 -0.32242110636808535
48.0 -0.3405079293933985
49.0 -0.3577994803720605
50.0 -0.3742553740855506
51.0 -0.38983717703161114
52.0 -0.40450849718747367
53.0 -0.41823506900511337
54.0 -0.43098483344002453
55.0 -0.4427280128266049
56.0 -0.4534371804252727
57.0 -0.4630873244788882
58.0 -0.4716559066288715
59.0 -0.4791229145545831
60.0 -0.48547090871302595
61.0 -0.4906850630697067
62.0 -0.49475319972552556
63.0 -0.4976658173588243
64.0 -0.49941611341616327
65.0 -0.5
66.0 -0.4994161134161633
67.0 -0.4976658173588243
68.0 -0.4947531997255255
69.0 -0.4906850630697067
70.0 -0.48547090871302606
71.0 -0.47912291455458306
72.0 -0.4716559066288716
73.0 -0.46308732447888834
74.0 -0.45343718042527276
75.0 -0.44272801282660496
76.0 -0.4309848334400247
77.0 -0.4182350690051134
78.0 -0.4045084971874738
79.0 -0.3898371770316112
80.0 -0.37425537408555065
81.0 -0.3577994803720606
82.0 -0.34050792939339874
83.0 -0.32242110636808513
84.0 -0.3035812539093557
85.0 -0.28403237336557796
86.0 -0.2638201220530664
87.0 -0.24299170662130334
88.0 -0.22159577279962092
89.0 -0.19968229178284758
90.0 -0.17730244352126795
91.0 -0.15450849718747378
92.0 -0.13135368909929349
93.0 -0.10789209838390346
94.0 -0.08417852067351916
95.0 -0.06026834012766134
96.0 -0.036217400080881375
97.0 -0.01208187261806627
98.0 0.012081872618066087
99.0 0.03621740008088119
100.0 0.0602683401276616
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/bargraph.txt
0,0 → 1,52
TitleText: Software Downloads
XRange: 0,10
YRange: 0,10000
# Manually specify X ticks
# Note that the 0 and 10 point result in clipping of the rectangles.
XTicks: 1993 0, 1994 1, 1995 2, 1996 3, 1997 4, 1998 5, 1999 6, 2000 7, 2001 8, 2002 9, 2003 10
XLabel: Year
YLabel: Downloads
Marks: none
Lines: off
# Width and offset of bars
Bars: 0.5, 0.2
NumSets: 3
 
DataSet: program a
0, 100
1, 300
2, 600
3, 1000
4, 4000
5, 6000
6, 3000
7, 1000
8, 400
9, 0
10, 0
 
DataSet: program b
0, 0
1, 0
2, 50
3, 100
4, 800
5, 400
6, 1000
7, 5000
8, 2000
9, 300
10, 0
 
DataSet: program c
0, 0
1, 0
2, 0
3, 10
4, 100
5, 400
6, 2000
7, 5000
8, 9000
9, 7000
10, 1000
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/histogram_via_function.html
0,0 → 1,130
<html>
<head></head>
<body>
Data processed via a function)<p>
Using the "ptolemy.plot.HistogramApplet" from the Plot.jar
<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.HistogramApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "function" value="cos(x)">
<param name="xlabel" value="x-as label">
<param name="ylabel" value="y-as label">
<param name="grid" value="on">
<param name="color" value="on">
<param name="xmin" value="-10">
<param name="xmax" value="10">
<param name="ymax" value="">
<param name="ymin" value="">
<param name="color" value="on">
<param name="smooth" value="0">
<param name="bargraph" value="0.7,0.15">
<param name="binwidth" value="0.1">
<param name="binoffset" value="0.1">
<param name="function" value="3*sin(4*x),cos(2*x)">
<param name="names" value="curve 1,curve 2,curve 3">
<param name="plotsteps" value="100">
</applet>
<p>
 
A histogram plotter<br> The plot can be configured and data can
be provided either through a file with commands or through direct
invocation of the public methods of the class<br> To read a file or a
URL, use the read() method<br>
<p>
When calling the public methods, in most cases the changes will not
be visible until paint() has been called<br> To request that this
be done, call repaint()<br> One exception is addPoint(), which
makes the affect of the new point visible immediately (or nearly
immediately) if the plot is visible on the screen<br>
<p>
The ASCII format for the file file contains any number commands,
one per line<br> Unrecognized commands and commands with syntax
errors are ignored<br> Comments are denoted by a line starting with a
pound sign "#"<br> The recognized commands include those supported by
the base class, plus a few more<br> The commands are case
insensitive, but are usually capitalized<br> The number of data sets
to be plotted does not need to be specified<br> Data sets are added as needed<br>
Each dataset is identified with a color (see the base class)<br>
<P>
The appearance of the histogram can be altered by the following commands:
<pre>
Bars: <i>width</i>
Bars: <i>width, offset</i>
</pre>
The <i>width</i> is a real number specifying the width of the bars
as a fraction of the bin width<br> It usually has a value less than
or equal to one,
and defaults to 0<br>5<br> The <i>offset</i> is a real number
specifying how much the bar of the <i>i </i><sup>th</sup> data set
is offset from the previous one<br> This allows bars to "peek out"
from behind the ones in front<br> It defaults to 0<br>15<br>
Note that the frontmost data set will be the first one<br>
<p>
The width of each bin of the histogram can be specified using:
<pre>
BinWidth: <i>width</i>
</pre>
This is given in whatever units the data has<br>
By default, each bin is centered at <i>x</i> = <i>nw</i>,
where <i>w</i> is the width of the bin and <i>n</i> is an integer<br>
That bin represents values in the range (<i>x - w/2, x + w/2</i>)<br>
The alignment of the bins can be changed with the following command:
<pre>
BinOffset: <i>offset</i>
</pre>
If this method is used with argument <i>o</i>, then each bin is
centered at <i>x = nw + o</i>, and represents values in the range
(<i>x - w/2 + o, x + w/2 + o</i>)<br> So for example, if <i>o = w/2</i>,
then each bin represents values from <i>nw</i> to
(<i>n</i> + 1)<i>w</i> for some integer <i>n</i><br>
The default offset is 0<br>5, half the default bin width<br>
<p>
To specify data to be plotted, start a data set with the following command:
<pre>
DataSet: <i>string</i>
</pre>
Here, <i>string</i> is a label that will appear in the legend<br>
It is not necessary to enclose the string in quotation marks<br>
To start a new dataset without giving it a name, use:
<pre>
DataSet:
</pre>
In this case, no item will appear in the legend<br>
New datasets are plotted <i>behind</i> the previous ones<br>
The data itself is given by a sequence of numbers, one per line<br>
The numbers are specified as
strings that can be parsed by the Double parser in Java<br>
It is also possible to specify the numbers using all the formats
accepted by the Plot class, so that the same data may be plotted by
both classes<br> The <i>x</i> data is ignored, and only the <i>y</i>
data is used to calculate the histogram<br>
 
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/bargraph_via_http_url.html
0,0 → 1,40
<html>
<head></head>
<body>
Data processed via param "file" : value=http://localhost/data.txt<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.PlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "file" value="http://localhost/data.txt">
</applet>
<br>
data.txt:<br>
"TitleText: Software Downloads;XRange: 0,10;YRange: 0,10000;# Manually specify X ticks;# Note that the 0 and 10 point result in clipping of the rectangles.;XTicks: 1993 0, 1994 1, 1995 2, 1996 3, 1997 4, 1998 5, 1999 6, 2000 7, 2001 8, 2002 9, 2003 10;XLabel: Year;YLabel: Downloads;Marks: none;Lines: off;# Width and offset of bars;Bars: 0.5, 0.2;NumSets: 3;;DataSet: program a;0, 100;1, 300;2, 600;3, 1000;4, 4000;5, 6000;6, 3000;7, 1000;8, 400;9, 0;10, 0;;DataSet: program b;0, 0;1, 0;2, 50;3, 100;4, 800;5, 400;6, 1000;7, 5000;8, 2000;9, 300;10, 0;;DataSet: program c;0, 0;1, 0;2, 0;3, 10;4, 100;5, 400;6, 2000;7, 5000;8, 9000;9, 7000;10, 1000"
 
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/sinus.histogram.txt
0,0 → 1,1042
TitleText: Sample histogram
XLabel: values
YLabel: count
YRange: 0.0,100.0
BarGraph: 0.5,0.15
BinWidth: 1.0
BinOffset: 0.5
Color: on
NumSets: 10
 
Dataset: 1
0.0 5.0
1.0 4.938441702975688
2.0 4.755282581475768
3.0 4.455032620941839
4.0 4.045084971874737
5.0 3.5355339059327378
6.0 2.938926261462366
7.0 2.269952498697734
8.0 1.5450849718747373
9.0 0.7821723252011547
10.0 3.061515884555943E-16
11.0 -0.7821723252011529
12.0 -1.5450849718747368
13.0 -2.2699524986977337
14.0 -2.9389262614623655
15.0 -3.5355339059327373
16.0 -4.045084971874737
17.0 -4.455032620941839
18.0 -4.755282581475767
19.0 -4.938441702975688
20.0 -5.0
21.0 -4.938441702975688
22.0 -4.755282581475769
23.0 -4.455032620941839
24.0 -4.045084971874737
25.0 -3.535533905932738
26.0 -2.9389262614623664
27.0 -2.2699524986977346
28.0 -1.545084971874738
29.0 -0.7821723252011552
30.0 -9.18454765366783E-16
31.0 0.7821723252011534
32.0 1.5450849718747361
33.0 2.269952498697733
34.0 2.938926261462365
35.0 3.535533905932737
36.0 4.045084971874736
37.0 4.4550326209418385
38.0 4.755282581475767
39.0 4.938441702975688
40.0 5.0
41.0 4.938441702975689
42.0 4.755282581475768
43.0 4.45503262094184
44.0 4.045084971874741
45.0 3.5355339059327386
46.0 2.938926261462367
47.0 2.269952498697731
48.0 1.5450849718747386
49.0 0.7821723252011602
50.0 1.5307579422779716E-15
51.0 -0.7821723252011484
52.0 -1.5450849718747357
53.0 -2.2699524986977364
54.0 -2.938926261462364
55.0 -3.5355339059327395
56.0 -4.045084971874736
57.0 -4.455032620941837
58.0 -4.755282581475767
59.0 -4.9384417029756875
60.0 -5.0
61.0 -4.938441702975688
62.0 -4.755282581475768
63.0 -4.4550326209418385
64.0 -4.045084971874738
65.0 -3.535533905932742
66.0 -2.9389262614623672
67.0 -2.26995249869774
68.0 -1.545084971874739
69.0 -0.7821723252011521
70.0 -2.1430611191891602E-15
71.0 0.7821723252011565
72.0 1.545084971874735
73.0 2.269952498697728
74.0 2.9389262614623637
75.0 3.535533905932733
76.0 4.0450849718747355
77.0 4.45503262094184
78.0 4.755282581475767
79.0 4.938441702975689
80.0 5.0
81.0 4.938441702975689
82.0 4.755282581475772
83.0 4.4550326209418385
84.0 4.045084971874739
85.0 3.5355339059327364
86.0 2.9389262614623677
87.0 2.2699524986977404
88.0 1.5450849718747481
89.0 0.7821723252011527
90.0 2.755364296100349E-15
91.0 -0.7821723252011472
92.0 -1.5450849718747344
93.0 -2.2699524986977275
94.0 -2.9389262614623703
95.0 -3.5355339059327386
96.0 -4.0450849718747355
97.0 -4.455032620941836
98.0 -4.755282581475764
99.0 -4.938441702975688
100.0 -5.0
 
Dataset:2
0.0 4.5
1.0 4.46451615591515
2.0 4.35862422507884
3.0 4.183994186497132
4.0 3.943380060197386
5.0 3.6405764746872635
6.0 3.280358823396352
7.0 2.8684079538691036
8.0 2.4112205774054845
9.0 1.9160068120428269
10.0 1.3905764746872635
11.0 0.8432159156357613
12.0 0.28255733788191084
13.0 -0.2825573378819103
14.0 -0.8432159156357607
15.0 -1.3905764746872622
16.0 -1.9160068120428273
17.0 -2.411220577405486
18.0 -2.8684079538691036
19.0 -3.280358823396351
20.0 -3.640576474687263
21.0 -3.9433800601973865
22.0 -4.183994186497131
23.0 -4.35862422507884
24.0 -4.46451615591515
25.0 -4.5
26.0 -4.46451615591515
27.0 -4.35862422507884
28.0 -4.183994186497132
29.0 -3.943380060197386
30.0 -3.640576474687265
31.0 -3.280358823396353
32.0 -2.868407953869103
33.0 -2.4112205774054836
34.0 -1.9160068120428246
35.0 -1.3905764746872642
36.0 -0.8432159156357608
37.0 -0.2825573378819094
38.0 0.28255733788190773
39.0 0.8432159156357593
40.0 1.3905764746872626
41.0 1.9160068120428233
42.0 2.4112205774054853
43.0 2.868407953869102
44.0 3.2803588233963508
45.0 3.6405764746872626
46.0 3.9433800601973843
47.0 4.183994186497132
48.0 4.358624225078839
49.0 4.46451615591515
50.0 4.5
51.0 4.464516155915151
52.0 4.35862422507884
53.0 4.183994186497131
54.0 3.943380060197387
55.0 3.640576474687264
56.0 3.280358823396352
57.0 2.8684079538691063
58.0 2.411220577405484
59.0 1.9160068120428289
60.0 1.3905764746872684
61.0 0.8432159156357614
62.0 0.28255733788191395
63.0 -0.2825573378819112
64.0 -0.8432159156357626
65.0 -1.390576474687262
66.0 -1.91600681204283
67.0 -2.411220577405485
68.0 -2.8684079538691076
69.0 -3.280358823396353
70.0 -3.6405764746872626
71.0 -3.943380060197388
72.0 -4.183994186497132
73.0 -4.358624225078839
74.0 -4.464516155915151
75.0 -4.5
76.0 -4.464516155915151
77.0 -4.35862422507884
78.0 -4.183994186497133
79.0 -3.9433800601973856
80.0 -3.6405764746872644
81.0 -3.280358823396355
82.0 -2.86840795386911
83.0 -2.411220577405481
84.0 -1.9160068120428257
85.0 -1.390576474687265
86.0 -0.8432159156357658
87.0 -0.2825573378819185
88.0 0.2825573378819067
89.0 0.843215915635762
90.0 1.3905764746872615
91.0 1.9160068120428222
92.0 2.411220577405478
93.0 2.868407953869101
94.0 3.2803588233963525
95.0 3.640576474687262
96.0 3.9433800601973834
97.0 4.183994186497131
98.0 4.358624225078839
99.0 4.464516155915151
100.0 4.5
 
 
 
Dataset:3
0.0 4.0
1.0 3.978087581473093
2.0 3.9125904029352228
3.0 3.804226065180614
4.0 3.6541818305704035
5.0 3.464101615137755
6.0 3.23606797749979
7.0 2.972579301909577
8.0 2.676522425435433
9.0 2.3511410091698925
10.0 2.0000000000000004
11.0 1.6269465723032015
12.0 1.2360679774997898
13.0 0.8316467632710369
14.0 0.41811385307061383
15.0 1.1330996904646007E-15
16.0 -0.41811385307061333
17.0 -0.8316467632710374
18.0 -1.2360679774997894
19.0 -1.6269465723032002
20.0 -1.9999999999999991
21.0 -2.351141009169892
22.0 -2.6765224254354316
23.0 -2.972579301909576
24.0 -3.2360679774997894
25.0 -3.464101615137755
26.0 -3.654181830570404
27.0 -3.804226065180614
28.0 -3.9125904029352228
29.0 -3.9780875814730936
30.0 -4.0
31.0 -3.9780875814730936
32.0 -3.9125904029352228
33.0 -3.8042260651806146
34.0 -3.6541818305704035
35.0 -3.4641016151377553
36.0 -3.2360679774997902
37.0 -2.972579301909577
38.0 -2.676522425435434
39.0 -2.351141009169893
40.0 -2.0000000000000018
41.0 -1.6269465723032035
42.0 -1.2360679774997902
43.0 -0.8316467632710391
44.0 -0.41811385307061694
45.0 -7.347638122934264E-16
46.0 0.41811385307061194
47.0 0.8316467632710377
48.0 1.236067977499789
49.0 1.626946572303199
50.0 2.0000000000000004
51.0 2.3511410091698917
52.0 2.676522425435434
53.0 2.972579301909577
54.0 3.2360679774997894
55.0 3.4641016151377553
56.0 3.654181830570404
57.0 3.804226065180614
58.0 3.9125904029352228
59.0 3.978087581473093
60.0 4.0
61.0 3.9780875814730936
62.0 3.912590402935223
63.0 3.8042260651806146
64.0 3.6541818305704044
65.0 3.464101615137756
66.0 3.2360679774997902
67.0 2.9725793019095783
68.0 2.676522425435433
69.0 2.3511410091698934
70.0 2.000000000000002
71.0 1.6269465723032008
72.0 1.236067977499791
73.0 0.8316467632710397
74.0 0.4181138530706139
75.0 1.2246063538223773E-15
76.0 -0.4181138530706115
77.0 -0.8316467632710338
78.0 -1.2360679774997885
79.0 -1.6269465723032017
80.0 -1.999999999999997
81.0 -2.3511410091698917
82.0 -2.6765224254354285
83.0 -2.972579301909579
84.0 -3.236067977499789
85.0 -3.4641016151377553
86.0 -3.654181830570402
87.0 -3.8042260651806137
88.0 -3.9125904029352214
89.0 -3.9780875814730936
90.0 -4.0
91.0 -3.978087581473093
92.0 -3.912590402935223
93.0 -3.8042260651806146
94.0 -3.654181830570403
95.0 -3.464101615137753
96.0 -3.2360679774997907
97.0 -2.972579301909581
98.0 -2.6765224254354356
99.0 -2.351141009169894
100.0 -1.9999999999999993
 
 
Dataset:4
0.0 3.5
1.0 3.4859100289833367
2.0 3.4437535600952036
3.0 3.3738700124354866
4.0 3.2768220472390803
5.0 3.153391037658467
6.0 3.0045707776065314
7.0 2.831559480312316
8.0 2.6357501310126383
9.0 2.4187192714540267
10.0 2.1822143065055672
11.0 1.9281394350823593
12.0 1.6585403186554954
13.0 1.3755876107887328
14.0 1.081559480312316
15.0 0.7788232688471006
16.0 0.4698164303617944
17.0 0.15702690622680246
18.0 -0.15702690622680202
19.0 -0.46981643036179394
20.0 -0.7788232688471002
21.0 -1.0815594803123156
22.0 -1.3755876107887317
23.0 -1.658540318655495
24.0 -1.9281394350823586
25.0 -2.1822143065055672
26.0 -2.418719271454026
27.0 -2.635750131012638
28.0 -2.8315594803123156
29.0 -3.0045707776065314
30.0 -3.1533910376584666
31.0 -3.27682204723908
32.0 -3.3738700124354866
33.0 -3.4437535600952036
34.0 -3.4859100289833367
35.0 -3.5
36.0 -3.4859100289833367
37.0 -3.443753560095204
38.0 -3.3738700124354866
39.0 -3.2768220472390803
40.0 -3.153391037658467
41.0 -3.0045707776065327
42.0 -2.831559480312316
43.0 -2.6357501310126388
44.0 -2.418719271454028
45.0 -2.1822143065055677
46.0 -1.9281394350823593
47.0 -1.658540318655496
48.0 -1.3755876107887333
49.0 -1.0815594803123165
50.0 -0.778823268847101
51.0 -0.46981643036179477
52.0 -0.15702690622680288
53.0 0.1570269062268016
54.0 0.4698164303617935
55.0 0.7788232688470997
56.0 1.0815594803123154
57.0 1.375587610788732
58.0 1.6585403186554948
59.0 1.9281394350823582
60.0 2.182214306505567
61.0 2.4187192714540258
62.0 2.635750131012638
63.0 2.8315594803123156
64.0 3.004570777606531
65.0 3.1533910376584666
66.0 3.27682204723908
67.0 3.373870012435486
68.0 3.4437535600952036
69.0 3.4859100289833367
70.0 3.5
71.0 3.4859100289833367
72.0 3.443753560095204
73.0 3.3738700124354866
74.0 3.2768220472390808
75.0 3.1533910376584675
76.0 3.004570777606532
77.0 2.8315594803123165
78.0 2.6357501310126388
79.0 2.418719271454027
80.0 2.182214306505568
81.0 1.9281394350823597
82.0 1.658540318655499
83.0 1.3755876107887308
84.0 1.081559480312317
85.0 0.7788232688471014
86.0 0.4698164303617952
87.0 0.1570269062268064
88.0 -0.15702690622679805
89.0 -0.46981643036179616
90.0 -0.7788232688470993
91.0 -1.081559480312315
92.0 -1.3755876107887317
93.0 -1.6585403186554943
94.0 -1.928139435082358
95.0 -2.1822143065055664
96.0 -2.4187192714540253
97.0 -2.6357501310126374
98.0 -2.831559480312315
99.0 -3.004570777606531
100.0 -3.1533910376584666
 
Dataset:5
0.0 3.0
1.0 2.990752001199384
2.0 2.9630650217854133
3.0 2.91710976119303
4.0 2.853169548885461
5.0 2.7716385975338604
6.0 2.673019572565104
7.0 2.5579204930622765
8.0 2.4270509831248424
9.0 2.2812178968000927
10.0 2.121320343559643
11.0 1.9483441449905512
12.0 1.7633557568774194
13.0 1.5674956941478466
14.0 1.3619714992186405
15.0 1.1480502970952695
16.0 0.9270509831248425
17.0 0.7003360915677164
18.0 0.46930339512069275
19.0 0.235377287183535
20.0 1.836909530733566E-16
21.0 -0.23537728718353465
22.0 -0.46930339512069175
23.0 -0.700336091567716
24.0 -0.927050983124842
25.0 -1.148050297095269
26.0 -1.3619714992186402
27.0 -1.5674956941478464
28.0 -1.7633557568774192
29.0 -1.9483441449905508
30.0 -2.1213203435596424
31.0 -2.2812178968000927
32.0 -2.427050983124842
33.0 -2.5579204930622765
34.0 -2.6730195725651034
35.0 -2.77163859753386
36.0 -2.8531695488854605
37.0 -2.91710976119303
38.0 -2.9630650217854133
39.0 -2.990752001199384
40.0 -3.0
41.0 -2.9907520011993842
42.0 -2.9630650217854133
43.0 -2.91710976119303
44.0 -2.8531695488854614
45.0 -2.7716385975338604
46.0 -2.673019572565104
47.0 -2.557920493062276
48.0 -2.4270509831248424
49.0 -2.281217896800094
50.0 -2.121320343559643
51.0 -1.9483441449905523
52.0 -1.7633557568774199
53.0 -1.567495694147846
54.0 -1.361971499218641
55.0 -1.1480502970952686
56.0 -0.9270509831248428
57.0 -0.700336091567718
58.0 -0.46930339512069313
59.0 -0.2353772871835367
60.0 -5.510728592200698E-16
61.0 0.2353772871835356
62.0 0.469303395120692
63.0 0.7003360915677169
64.0 0.9270509831248417
65.0 1.1480502970952675
66.0 1.3619714992186398
67.0 1.5674956941478448
68.0 1.763355756877419
69.0 1.9483441449905514
70.0 2.121320343559642
71.0 2.281217896800093
72.0 2.427050983124842
73.0 2.5579204930622756
74.0 2.6730195725651034
75.0 2.7716385975338595
76.0 2.8531695488854605
77.0 2.91710976119303
78.0 2.963065021785413
79.0 2.990752001199384
80.0 3.0
81.0 2.9907520011993842
82.0 2.9630650217854138
83.0 2.91710976119303
84.0 2.853169548885461
85.0 2.77163859753386
86.0 2.673019572565104
87.0 2.557920493062278
88.0 2.427050983124844
89.0 2.2812178968000927
90.0 2.1213203435596433
91.0 1.9483441449905525
92.0 1.76335575687742
93.0 1.5674956941478484
94.0 1.3619714992186387
95.0 1.1480502970952688
96.0 0.9270509831248431
97.0 0.7003360915677184
98.0 0.46930339512069613
99.0 0.2353772871835344
100.0 9.18454765366783E-16
 
Dataset:6
1.0 2.4939101256495606
2.0 2.475670171853926
3.0 2.4453690018345142
4.0 2.4031542398457972
5.0 2.349231551964771
6.0 2.283863644106502
7.0 2.2073689821473175
8.0 2.120120240391065
9.0 2.0225424859373686
10.0 1.9151111077974452
11.0 1.798349500846628
12.0 1.6728265158971456
13.0 1.5391536883141457
14.0 1.397982258676867
15.0 1.2500000000000002
16.0 1.0959278669726935
17.0 0.9365164835397799
18.0 0.7725424859373686
19.0 0.6048047389991698
20.0 0.4341204441673261
21.0 0.26132115816913365
22.0 0.0872487417562527
23.0 -0.08724874175625184
24.0 -0.2613211581691333
25.0 -0.43412044416732576
26.0 -0.6048047389991694
27.0 -0.7725424859373684
28.0 -0.9365164835397801
29.0 -1.0959278669726937
30.0 -1.2499999999999996
31.0 -1.3979822586768669
32.0 -1.5391536883141457
33.0 -1.6728265158971456
34.0 -1.7983495008466281
35.0 -1.9151111077974448
36.0 -2.0225424859373686
37.0 -2.120120240391065
38.0 -2.207368982147317
39.0 -2.283863644106502
40.0 -2.349231551964771
41.0 -2.403154239845797
42.0 -2.4453690018345142
43.0 -2.475670171853926
44.0 -2.4939101256495606
45.0 -2.5
46.0 -2.4939101256495606
47.0 -2.475670171853926
48.0 -2.4453690018345142
49.0 -2.4031542398457972
50.0 -2.349231551964771
51.0 -2.2838636441065026
52.0 -2.207368982147317
53.0 -2.1201202403910653
54.0 -2.0225424859373686
55.0 -1.9151111077974452
56.0 -1.7983495008466277
57.0 -1.672826515897146
58.0 -1.5391536883141452
59.0 -1.3979822586768682
60.0 -1.2500000000000009
61.0 -1.0959278669726944
62.0 -0.9365164835397807
63.0 -0.772542485937369
64.0 -0.6048047389991695
65.0 -0.4341204441673258
66.0 -0.26132115816913337
67.0 -0.08724874175625412
68.0 0.0872487417562532
69.0 0.2613211581691325
70.0 0.4341204441673249
71.0 0.6048047389991686
72.0 0.7725424859373681
73.0 0.9365164835397799
74.0 1.0959278669726935
75.0 1.2500000000000002
76.0 1.3979822586768655
77.0 1.5391536883141463
78.0 1.6728265158971445
79.0 1.798349500846627
80.0 1.9151111077974445
81.0 2.022542485937368
82.0 2.1201202403910635
83.0 2.2073689821473175
84.0 2.283863644106502
85.0 2.3492315519647713
86.0 2.403154239845797
87.0 2.445369001834514
88.0 2.475670171853926
89.0 2.4939101256495606
90.0 2.5
91.0 2.4939101256495606
92.0 2.4756701718539262
93.0 2.4453690018345147
94.0 2.4031542398457972
95.0 2.349231551964771
96.0 2.283863644106503
97.0 2.207368982147318
98.0 2.1201202403910653
99.0 2.0225424859373677
100.0 1.9151111077974454
 
Dataset:7
0.0 2.0
1.0 1.9960534568565431
2.0 1.9842294026289558
3.0 1.9645745014573774
4.0 1.9371663222572622
5.0 1.902113032590307
6.0 1.859552971776503
7.0 1.8096541049320392
8.0 1.7526133600877272
9.0 1.6886558510040302
10.0 1.618033988749895
11.0 1.5410264855515785
12.0 1.457937254842823
13.0 1.3690942118573772
14.0 1.2748479794973795
15.0 1.1755705045849465
16.0 1.071653589957993
17.0 0.9635073482034303
18.0 0.8515585831301453
19.0 0.7362491053693562
20.0 0.6180339887498949
21.0 0.4973797743297095
22.0 0.3747626291714495
23.0 0.25066646712860896
24.0 0.12558103905862705
25.0 1.2246063538223773E-16
26.0 -0.1255810390586268
27.0 -0.2506664671286083
28.0 -0.3747626291714492
29.0 -0.4973797743297097
30.0 -0.6180339887498942
31.0 -0.7362491053693555
32.0 -0.8515585831301454
33.0 -0.9635073482034309
34.0 -1.0716535899579938
35.0 -1.175570504584946
36.0 -1.2748479794973795
37.0 -1.3690942118573775
38.0 -1.4579372548428227
39.0 -1.5410264855515783
40.0 -1.6180339887498947
41.0 -1.6886558510040297
42.0 -1.7526133600877272
43.0 -1.8096541049320387
44.0 -1.8595529717765027
45.0 -1.902113032590307
46.0 -1.937166322257262
47.0 -1.9645745014573774
48.0 -1.9842294026289555
49.0 -1.9960534568565431
50.0 -2.0
51.0 -1.9960534568565431
52.0 -1.9842294026289558
53.0 -1.9645745014573772
54.0 -1.9371663222572624
55.0 -1.9021130325903073
56.0 -1.859552971776503
57.0 -1.8096541049320394
58.0 -1.752613360087727
59.0 -1.6886558510040304
60.0 -1.6180339887498956
61.0 -1.5410264855515785
62.0 -1.4579372548428235
63.0 -1.3690942118573772
64.0 -1.274847979497379
65.0 -1.1755705045849465
66.0 -1.0716535899579926
67.0 -0.9635073482034305
68.0 -0.8515585831301443
69.0 -0.7362491053693556
70.0 -0.6180339887498951
71.0 -0.49737977432970887
72.0 -0.37476262917144926
73.0 -0.2506664671286092
74.0 -0.12558103905862641
75.0 -3.673819061467132E-16
76.0 0.12558103905862567
77.0 0.25066646712860846
78.0 0.37476262917144854
79.0 0.49737977432970987
80.0 0.6180339887498945
81.0 0.7362491053693548
82.0 0.8515585831301437
83.0 0.9635073482034314
84.0 1.0716535899579935
85.0 1.1755705045849458
86.0 1.2748479794973786
87.0 1.369094211857376
88.0 1.4579372548428224
89.0 1.5410264855515787
90.0 1.6180339887498947
91.0 1.6886558510040295
92.0 1.7526133600877263
93.0 1.8096541049320387
94.0 1.859552971776503
95.0 1.902113032590307
96.0 1.937166322257262
97.0 1.9645745014573774
98.0 1.9842294026289555
99.0 1.9960534568565431
100.0 2.0
 
 
Dataset:8
0.0 1.5
1.0 1.4975536558892035
2.0 1.4902226030228254
3.0 1.4780307537715396
4.0 1.4610178754135004
5.0 1.439239460421746
6.0 1.412766545459287
7.0 1.3816854796722753
8.0 1.3460976430370377
9.0 1.3061191156796659
10.0 1.2618802992467717
11.0 1.2135254915624212
12.0 1.1612124159586237
13.0 1.1051117068146072
14.0 1.0454063529829403
15.0 0.9822911009179277
16.0 0.9159718194531573
17.0 0.8466648283001538
18.0 0.7745961924584429
19.0 0.7000009848385107
20.0 0.6231225195028297
21.0 0.5442115580259614
22.0 0.4635254915624215
23.0 0.38132750129023063
24.0 0.2978856999686183
25.0 0.21347225740992767
26.0 0.12836251271825944
27.0 0.04283407619054471
28.0 -0.0428340761905442
29.0 -0.12836251271825957
30.0 -0.21347225740992748
31.0 -0.29788569996861813
32.0 -0.38132750129023013
33.0 -0.463525491562421
34.0 -0.5442115580259616
35.0 -0.6231225195028295
36.0 -0.7000009848385106
37.0 -0.7745961924584427
38.0 -0.8466648283001534
39.0 -0.9159718194531568
40.0 -0.9822911009179276
41.0 -1.04540635298294
42.0 -1.1051117068146075
43.0 -1.1612124159586237
44.0 -1.2135254915624207
45.0 -1.2618802992467715
46.0 -1.3061191156796654
47.0 -1.3460976430370375
48.0 -1.381685479672275
49.0 -1.4127665454592868
50.0 -1.439239460421746
51.0 -1.4610178754135001
52.0 -1.4780307537715396
53.0 -1.4902226030228254
54.0 -1.4975536558892035
55.0 -1.5
56.0 -1.4975536558892035
57.0 -1.4902226030228254
58.0 -1.4780307537715396
59.0 -1.4610178754135004
60.0 -1.4392394604217462
61.0 -1.412766545459287
62.0 -1.3816854796722753
63.0 -1.3460976430370375
64.0 -1.306119115679666
65.0 -1.2618802992467721
66.0 -1.2135254915624212
67.0 -1.161212415958624
68.0 -1.1051117068146072
69.0 -1.0454063529829403
70.0 -0.9822911009179278
71.0 -0.9159718194531575
72.0 -0.8466648283001538
73.0 -0.7745961924584436
74.0 -0.7000009848385109
75.0 -0.6231225195028295
76.0 -0.5442115580259622
77.0 -0.4635254915624214
78.0 -0.38132750129023146
79.0 -0.2978856999686188
80.0 -0.21347225740992787
81.0 -0.1283625127182606
82.0 -0.0428340761905449
83.0 0.04283407619054434
84.0 0.12836251271826005
85.0 0.2134722574099273
86.0 0.29788569996861824
87.0 0.38132750129022963
88.0 0.46352549156241957
89.0 0.5442115580259617
90.0 0.623122519502829
91.0 0.7000009848385104
92.0 0.774596192458442
93.0 0.8466648283001533
94.0 0.9159718194531571
95.0 0.9822911009179279
96.0 1.0454063529829398
97.0 1.1051117068146075
98.0 1.1612124159586232
99.0 1.2135254915624216
100.0 1.261880299246772
 
 
Dataset:9
0.0 1.0
1.0 0.9986295347545738
2.0 0.9945218953682733
3.0 0.9876883405951378
4.0 0.9781476007338057
5.0 0.9659258262890683
6.0 0.9510565162951535
7.0 0.9335804264972017
8.0 0.9135454576426009
9.0 0.8910065241883679
10.0 0.8660254037844387
11.0 0.838670567945424
12.0 0.8090169943749475
13.0 0.7771459614569709
14.0 0.7431448254773942
15.0 0.7071067811865476
16.0 0.6691306063588582
17.0 0.6293203910498375
18.0 0.5877852522924731
19.0 0.5446390350150272
20.0 0.5000000000000001
21.0 0.4539904997395468
22.0 0.4067366430758004
23.0 0.3583679495453004
24.0 0.30901699437494745
25.0 0.25881904510252074
26.0 0.20791169081775923
27.0 0.15643446504023092
28.0 0.10452846326765346
29.0 0.052335956242943744
30.0 2.8327492261615017E-16
31.0 -0.05233595624294362
32.0 -0.10452846326765333
33.0 -0.1564344650402308
34.0 -0.20791169081775934
35.0 -0.25881904510252063
36.0 -0.30901699437494734
37.0 -0.35836794954530027
38.0 -0.40673664307580004
39.0 -0.4539904997395467
40.0 -0.4999999999999998
41.0 -0.5446390350150268
42.0 -0.587785252292473
43.0 -0.6293203910498373
44.0 -0.6691306063588579
45.0 -0.7071067811865475
46.0 -0.743144825477394
47.0 -0.7771459614569709
48.0 -0.8090169943749473
49.0 -0.8386705679454239
50.0 -0.8660254037844387
51.0 -0.8910065241883678
52.0 -0.913545457642601
53.0 -0.9335804264972017
54.0 -0.9510565162951535
55.0 -0.9659258262890683
56.0 -0.9781476007338057
57.0 -0.9876883405951377
58.0 -0.9945218953682734
59.0 -0.9986295347545738
60.0 -1.0
61.0 -0.9986295347545738
62.0 -0.9945218953682734
63.0 -0.9876883405951378
64.0 -0.9781476007338057
65.0 -0.9659258262890684
66.0 -0.9510565162951536
67.0 -0.9335804264972019
68.0 -0.9135454576426009
69.0 -0.8910065241883679
70.0 -0.8660254037844388
71.0 -0.838670567945424
72.0 -0.8090169943749476
73.0 -0.777145961456971
74.0 -0.7431448254773942
75.0 -0.7071067811865477
76.0 -0.6691306063588585
77.0 -0.6293203910498378
78.0 -0.5877852522924732
79.0 -0.544639035015027
80.0 -0.5000000000000004
81.0 -0.4539904997395469
82.0 -0.4067366430758009
83.0 -0.3583679495452999
84.0 -0.30901699437494756
85.0 -0.25881904510252063
86.0 -0.2079116908177598
87.0 -0.15643446504023104
88.0 -0.10452846326765423
89.0 -0.052335956242943425
90.0 -1.836909530733566E-16
91.0 0.052335956242943946
92.0 0.10452846326765299
93.0 0.15643446504023067
94.0 0.20791169081775943
95.0 0.25881904510252113
96.0 0.30901699437494723
97.0 0.35836794954529955
98.0 0.40673664307579976
99.0 0.45399049973954664
 
Dataset:last but not least
0.0 0.5
1.0 0.4994161134161633
2.0 0.4976658173588243
3.0 0.49475319972552556
4.0 0.4906850630697067
5.0 0.485470908713026
6.0 0.4791229145545831
7.0 0.4716559066288715
8.0 0.4630873244788883
9.0 0.4534371804252727
10.0 0.44272801282660496
11.0 0.43098483344002464
12.0 0.41823506900511337
13.0 0.4045084971874737
14.0 0.3898371770316112
15.0 0.3742553740855506
16.0 0.35779948037206055
17.0 0.3405079293933985
18.0 0.3224211063680853
19.0 0.30358125390935564
20.0 0.28403237336557796
21.0 0.2638201220530664
22.0 0.2429917066213031
23.0 0.22159577279962067
24.0 0.19968229178284783
25.0 0.17730244352126778
26.0 0.15450849718747373
27.0 0.13135368909929354
28.0 0.10789209838390307
29.0 0.08417852067351932
30.0 0.060268340127661614
31.0 0.0362174000808812
32.0 0.012081872618066208
33.0 -0.012081872618066147
34.0 -0.03621740008088125
35.0 -0.06026834012766144
36.0 -0.08417852067351926
37.0 -0.10789209838390301
38.0 -0.13135368909929337
39.0 -0.15450849718747367
40.0 -0.17730244352126773
41.0 -0.19968229178284766
42.0 -0.22159577279962062
43.0 -0.24299170662130304
44.0 -0.26382012205306626
45.0 -0.28403237336557785
46.0 -0.3035812539093556
47.0 -0.32242110636808535
48.0 -0.3405079293933985
49.0 -0.3577994803720605
50.0 -0.3742553740855506
51.0 -0.38983717703161114
52.0 -0.40450849718747367
53.0 -0.41823506900511337
54.0 -0.43098483344002453
55.0 -0.4427280128266049
56.0 -0.4534371804252727
57.0 -0.4630873244788882
58.0 -0.4716559066288715
59.0 -0.4791229145545831
60.0 -0.48547090871302595
61.0 -0.4906850630697067
62.0 -0.49475319972552556
63.0 -0.4976658173588243
64.0 -0.49941611341616327
65.0 -0.5
66.0 -0.4994161134161633
67.0 -0.4976658173588243
68.0 -0.4947531997255255
69.0 -0.4906850630697067
70.0 -0.48547090871302606
71.0 -0.47912291455458306
72.0 -0.4716559066288716
73.0 -0.46308732447888834
74.0 -0.45343718042527276
75.0 -0.44272801282660496
76.0 -0.4309848334400247
77.0 -0.4182350690051134
78.0 -0.4045084971874738
79.0 -0.3898371770316112
80.0 -0.37425537408555065
81.0 -0.3577994803720606
82.0 -0.34050792939339874
83.0 -0.32242110636808513
84.0 -0.3035812539093557
85.0 -0.28403237336557796
86.0 -0.2638201220530664
87.0 -0.24299170662130334
88.0 -0.22159577279962092
89.0 -0.19968229178284758
90.0 -0.17730244352126795
91.0 -0.15450849718747378
92.0 -0.13135368909929349
93.0 -0.10789209838390346
94.0 -0.08417852067351916
95.0 -0.06026834012766134
96.0 -0.036217400080881375
97.0 -0.01208187261806627
98.0 0.012081872618066087
99.0 0.03621740008088119
100.0 0.0602683401276616
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/bargraph_via_string.html
0,0 → 1,42
<html>
<head></head>
<body>
Data processed via a String (eg a wims variable)<p>
value="TitleText: Software Downloads;XRange: 0,10;YRange: 0,10000;# Manually specify X ticks;# Note that the 0 and 10 point result in clipping of the rectangles.;XTicks: 1993 0, 1994 1, 1995 2, 1996 3, 1997 4, 1998 5, 1999 6, 2000 7, 2001 8, 2002 9, 2003 10;XLabel: Year;YLabel: Downloads;Marks: none;Lines: off;# Width and offset of bars;Bars: 0.5, 0.2;NumSets: 3;;DataSet: program a;0, 100;1, 300;2, 600;3, 1000;4, 4000;5, 6000;6, 3000;7, 1000;8, 400;9, 0;10, 0;;DataSet: program b;0, 0;1, 0;2, 50;3, 100;4, 800;5, 400;6, 1000;7, 5000;8, 2000;9, 300;10, 0;;DataSet: program c;0, 0;1, 0;2, 0;3, 10;4, 100;5, 400;6, 2000;7, 5000;8, 9000;9, 7000;10, 1000"
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.PlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "name" value = "PlotApplet">
<param name = "data" value= "TitleText:Oefenen met grafiek lezen.;numsets:4;color:on;lines:off;bars:0.5,0.2;xticks:1957 1,1958 2,1959 3,1960 4,1961 5,1962 6,1963 7,1964 8;xlabel: jaar ;ylabel:aantal ;grid :off;dataset:lege vaten;1,8;2,2;3,4;4,3;5,6;6,7;7,1;8,5;dataset:schoenen;1,8; 2,32; 3,24; 4,56; 5,16; 6,40; 7,48; 8,64;dataset:legejerrycans;1,3; 2,18; 3,312; 4,24; 5,15; 6,6; 7,21; 8,9;dataset:containers;1,48; 2,8; 3,64; 4,40; 5,32; 6,24; 7,56; 8,16;">
</applet>
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
 
 
 
 
<param name = "data" value="TitleText:an Software Downloads;XRange: 0,10;YRange: 0,10000;# Manually specify X ticks;# Note that the 0 and 10 point result in clipping of the rectangles.;XTicks: 1993 0, 1994 1, 1995 2, 1996 3, 1997 4, 1998 5, 1999 6, 2000 7, 2001 8, 2002 9, 2003 10;XLabel: Year;YLabel: Downloads;Marks: none;Lines: off;# Width and offset of bars;Bars: 0.5, 0.2;NumSets: 3;;DataSet: program a;0, 100;1, 300;2, 600;3, 1000;4, 4000;5, 6000;6, 3000;7, 1000;8, 400;9, 0;10, 0;;DataSet: program b;0, 0;1, 0;2, 50;3, 100;4, 800;5, 400;6, 1000;7, 5000;8, 2000;9, 300;10, 0;;DataSet: program c;0, 0;1, 0;2, 0;3, 10;4, 100;5, 400;6, 2000;7, 5000;8, 9000;9, 7000;10, 1000">
 
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/sinus.txt
0,0 → 1,1044
TitleText: My Plot 1031 datapoints processed
XRange: 0,4
YRange: -4,4
# Manually specify X ticks
XTicks: zero 0, one 1, two 2, pi 3.1428, four 4, five 5
Grid: on
XLabel: X Axis
YLabel: Y Axis
Marks: various
NumSets: 10
Color: on
 
Dataset: 1
0.0 5.0
1.0 4.938441702975688
2.0 4.755282581475768
3.0 4.455032620941839
4.0 4.045084971874737
5.0 3.5355339059327378
6.0 2.938926261462366
7.0 2.269952498697734
8.0 1.5450849718747373
9.0 0.7821723252011547
10.0 3.061515884555943E-16
11.0 -0.7821723252011529
12.0 -1.5450849718747368
13.0 -2.2699524986977337
14.0 -2.9389262614623655
15.0 -3.5355339059327373
16.0 -4.045084971874737
17.0 -4.455032620941839
18.0 -4.755282581475767
19.0 -4.938441702975688
20.0 -5.0
21.0 -4.938441702975688
22.0 -4.755282581475769
23.0 -4.455032620941839
24.0 -4.045084971874737
25.0 -3.535533905932738
26.0 -2.9389262614623664
27.0 -2.2699524986977346
28.0 -1.545084971874738
29.0 -0.7821723252011552
30.0 -9.18454765366783E-16
31.0 0.7821723252011534
32.0 1.5450849718747361
33.0 2.269952498697733
34.0 2.938926261462365
35.0 3.535533905932737
36.0 4.045084971874736
37.0 4.4550326209418385
38.0 4.755282581475767
39.0 4.938441702975688
40.0 5.0
41.0 4.938441702975689
42.0 4.755282581475768
43.0 4.45503262094184
44.0 4.045084971874741
45.0 3.5355339059327386
46.0 2.938926261462367
47.0 2.269952498697731
48.0 1.5450849718747386
49.0 0.7821723252011602
50.0 1.5307579422779716E-15
51.0 -0.7821723252011484
52.0 -1.5450849718747357
53.0 -2.2699524986977364
54.0 -2.938926261462364
55.0 -3.5355339059327395
56.0 -4.045084971874736
57.0 -4.455032620941837
58.0 -4.755282581475767
59.0 -4.9384417029756875
60.0 -5.0
61.0 -4.938441702975688
62.0 -4.755282581475768
63.0 -4.4550326209418385
64.0 -4.045084971874738
65.0 -3.535533905932742
66.0 -2.9389262614623672
67.0 -2.26995249869774
68.0 -1.545084971874739
69.0 -0.7821723252011521
70.0 -2.1430611191891602E-15
71.0 0.7821723252011565
72.0 1.545084971874735
73.0 2.269952498697728
74.0 2.9389262614623637
75.0 3.535533905932733
76.0 4.0450849718747355
77.0 4.45503262094184
78.0 4.755282581475767
79.0 4.938441702975689
80.0 5.0
81.0 4.938441702975689
82.0 4.755282581475772
83.0 4.4550326209418385
84.0 4.045084971874739
85.0 3.5355339059327364
86.0 2.9389262614623677
87.0 2.2699524986977404
88.0 1.5450849718747481
89.0 0.7821723252011527
90.0 2.755364296100349E-15
91.0 -0.7821723252011472
92.0 -1.5450849718747344
93.0 -2.2699524986977275
94.0 -2.9389262614623703
95.0 -3.5355339059327386
96.0 -4.0450849718747355
97.0 -4.455032620941836
98.0 -4.755282581475764
99.0 -4.938441702975688
100.0 -5.0
 
Dataset:2
0.0 4.5
1.0 4.46451615591515
2.0 4.35862422507884
3.0 4.183994186497132
4.0 3.943380060197386
5.0 3.6405764746872635
6.0 3.280358823396352
7.0 2.8684079538691036
8.0 2.4112205774054845
9.0 1.9160068120428269
10.0 1.3905764746872635
11.0 0.8432159156357613
12.0 0.28255733788191084
13.0 -0.2825573378819103
14.0 -0.8432159156357607
15.0 -1.3905764746872622
16.0 -1.9160068120428273
17.0 -2.411220577405486
18.0 -2.8684079538691036
19.0 -3.280358823396351
20.0 -3.640576474687263
21.0 -3.9433800601973865
22.0 -4.183994186497131
23.0 -4.35862422507884
24.0 -4.46451615591515
25.0 -4.5
26.0 -4.46451615591515
27.0 -4.35862422507884
28.0 -4.183994186497132
29.0 -3.943380060197386
30.0 -3.640576474687265
31.0 -3.280358823396353
32.0 -2.868407953869103
33.0 -2.4112205774054836
34.0 -1.9160068120428246
35.0 -1.3905764746872642
36.0 -0.8432159156357608
37.0 -0.2825573378819094
38.0 0.28255733788190773
39.0 0.8432159156357593
40.0 1.3905764746872626
41.0 1.9160068120428233
42.0 2.4112205774054853
43.0 2.868407953869102
44.0 3.2803588233963508
45.0 3.6405764746872626
46.0 3.9433800601973843
47.0 4.183994186497132
48.0 4.358624225078839
49.0 4.46451615591515
50.0 4.5
51.0 4.464516155915151
52.0 4.35862422507884
53.0 4.183994186497131
54.0 3.943380060197387
55.0 3.640576474687264
56.0 3.280358823396352
57.0 2.8684079538691063
58.0 2.411220577405484
59.0 1.9160068120428289
60.0 1.3905764746872684
61.0 0.8432159156357614
62.0 0.28255733788191395
63.0 -0.2825573378819112
64.0 -0.8432159156357626
65.0 -1.390576474687262
66.0 -1.91600681204283
67.0 -2.411220577405485
68.0 -2.8684079538691076
69.0 -3.280358823396353
70.0 -3.6405764746872626
71.0 -3.943380060197388
72.0 -4.183994186497132
73.0 -4.358624225078839
74.0 -4.464516155915151
75.0 -4.5
76.0 -4.464516155915151
77.0 -4.35862422507884
78.0 -4.183994186497133
79.0 -3.9433800601973856
80.0 -3.6405764746872644
81.0 -3.280358823396355
82.0 -2.86840795386911
83.0 -2.411220577405481
84.0 -1.9160068120428257
85.0 -1.390576474687265
86.0 -0.8432159156357658
87.0 -0.2825573378819185
88.0 0.2825573378819067
89.0 0.843215915635762
90.0 1.3905764746872615
91.0 1.9160068120428222
92.0 2.411220577405478
93.0 2.868407953869101
94.0 3.2803588233963525
95.0 3.640576474687262
96.0 3.9433800601973834
97.0 4.183994186497131
98.0 4.358624225078839
99.0 4.464516155915151
100.0 4.5
 
 
 
Dataset:3
0.0 4.0
1.0 3.978087581473093
2.0 3.9125904029352228
3.0 3.804226065180614
4.0 3.6541818305704035
5.0 3.464101615137755
6.0 3.23606797749979
7.0 2.972579301909577
8.0 2.676522425435433
9.0 2.3511410091698925
10.0 2.0000000000000004
11.0 1.6269465723032015
12.0 1.2360679774997898
13.0 0.8316467632710369
14.0 0.41811385307061383
15.0 1.1330996904646007E-15
16.0 -0.41811385307061333
17.0 -0.8316467632710374
18.0 -1.2360679774997894
19.0 -1.6269465723032002
20.0 -1.9999999999999991
21.0 -2.351141009169892
22.0 -2.6765224254354316
23.0 -2.972579301909576
24.0 -3.2360679774997894
25.0 -3.464101615137755
26.0 -3.654181830570404
27.0 -3.804226065180614
28.0 -3.9125904029352228
29.0 -3.9780875814730936
30.0 -4.0
31.0 -3.9780875814730936
32.0 -3.9125904029352228
33.0 -3.8042260651806146
34.0 -3.6541818305704035
35.0 -3.4641016151377553
36.0 -3.2360679774997902
37.0 -2.972579301909577
38.0 -2.676522425435434
39.0 -2.351141009169893
40.0 -2.0000000000000018
41.0 -1.6269465723032035
42.0 -1.2360679774997902
43.0 -0.8316467632710391
44.0 -0.41811385307061694
45.0 -7.347638122934264E-16
46.0 0.41811385307061194
47.0 0.8316467632710377
48.0 1.236067977499789
49.0 1.626946572303199
50.0 2.0000000000000004
51.0 2.3511410091698917
52.0 2.676522425435434
53.0 2.972579301909577
54.0 3.2360679774997894
55.0 3.4641016151377553
56.0 3.654181830570404
57.0 3.804226065180614
58.0 3.9125904029352228
59.0 3.978087581473093
60.0 4.0
61.0 3.9780875814730936
62.0 3.912590402935223
63.0 3.8042260651806146
64.0 3.6541818305704044
65.0 3.464101615137756
66.0 3.2360679774997902
67.0 2.9725793019095783
68.0 2.676522425435433
69.0 2.3511410091698934
70.0 2.000000000000002
71.0 1.6269465723032008
72.0 1.236067977499791
73.0 0.8316467632710397
74.0 0.4181138530706139
75.0 1.2246063538223773E-15
76.0 -0.4181138530706115
77.0 -0.8316467632710338
78.0 -1.2360679774997885
79.0 -1.6269465723032017
80.0 -1.999999999999997
81.0 -2.3511410091698917
82.0 -2.6765224254354285
83.0 -2.972579301909579
84.0 -3.236067977499789
85.0 -3.4641016151377553
86.0 -3.654181830570402
87.0 -3.8042260651806137
88.0 -3.9125904029352214
89.0 -3.9780875814730936
90.0 -4.0
91.0 -3.978087581473093
92.0 -3.912590402935223
93.0 -3.8042260651806146
94.0 -3.654181830570403
95.0 -3.464101615137753
96.0 -3.2360679774997907
97.0 -2.972579301909581
98.0 -2.6765224254354356
99.0 -2.351141009169894
100.0 -1.9999999999999993
 
 
Dataset:4
0.0 3.5
1.0 3.4859100289833367
2.0 3.4437535600952036
3.0 3.3738700124354866
4.0 3.2768220472390803
5.0 3.153391037658467
6.0 3.0045707776065314
7.0 2.831559480312316
8.0 2.6357501310126383
9.0 2.4187192714540267
10.0 2.1822143065055672
11.0 1.9281394350823593
12.0 1.6585403186554954
13.0 1.3755876107887328
14.0 1.081559480312316
15.0 0.7788232688471006
16.0 0.4698164303617944
17.0 0.15702690622680246
18.0 -0.15702690622680202
19.0 -0.46981643036179394
20.0 -0.7788232688471002
21.0 -1.0815594803123156
22.0 -1.3755876107887317
23.0 -1.658540318655495
24.0 -1.9281394350823586
25.0 -2.1822143065055672
26.0 -2.418719271454026
27.0 -2.635750131012638
28.0 -2.8315594803123156
29.0 -3.0045707776065314
30.0 -3.1533910376584666
31.0 -3.27682204723908
32.0 -3.3738700124354866
33.0 -3.4437535600952036
34.0 -3.4859100289833367
35.0 -3.5
36.0 -3.4859100289833367
37.0 -3.443753560095204
38.0 -3.3738700124354866
39.0 -3.2768220472390803
40.0 -3.153391037658467
41.0 -3.0045707776065327
42.0 -2.831559480312316
43.0 -2.6357501310126388
44.0 -2.418719271454028
45.0 -2.1822143065055677
46.0 -1.9281394350823593
47.0 -1.658540318655496
48.0 -1.3755876107887333
49.0 -1.0815594803123165
50.0 -0.778823268847101
51.0 -0.46981643036179477
52.0 -0.15702690622680288
53.0 0.1570269062268016
54.0 0.4698164303617935
55.0 0.7788232688470997
56.0 1.0815594803123154
57.0 1.375587610788732
58.0 1.6585403186554948
59.0 1.9281394350823582
60.0 2.182214306505567
61.0 2.4187192714540258
62.0 2.635750131012638
63.0 2.8315594803123156
64.0 3.004570777606531
65.0 3.1533910376584666
66.0 3.27682204723908
67.0 3.373870012435486
68.0 3.4437535600952036
69.0 3.4859100289833367
70.0 3.5
71.0 3.4859100289833367
72.0 3.443753560095204
73.0 3.3738700124354866
74.0 3.2768220472390808
75.0 3.1533910376584675
76.0 3.004570777606532
77.0 2.8315594803123165
78.0 2.6357501310126388
79.0 2.418719271454027
80.0 2.182214306505568
81.0 1.9281394350823597
82.0 1.658540318655499
83.0 1.3755876107887308
84.0 1.081559480312317
85.0 0.7788232688471014
86.0 0.4698164303617952
87.0 0.1570269062268064
88.0 -0.15702690622679805
89.0 -0.46981643036179616
90.0 -0.7788232688470993
91.0 -1.081559480312315
92.0 -1.3755876107887317
93.0 -1.6585403186554943
94.0 -1.928139435082358
95.0 -2.1822143065055664
96.0 -2.4187192714540253
97.0 -2.6357501310126374
98.0 -2.831559480312315
99.0 -3.004570777606531
100.0 -3.1533910376584666
 
Dataset:5
0.0 3.0
1.0 2.990752001199384
2.0 2.9630650217854133
3.0 2.91710976119303
4.0 2.853169548885461
5.0 2.7716385975338604
6.0 2.673019572565104
7.0 2.5579204930622765
8.0 2.4270509831248424
9.0 2.2812178968000927
10.0 2.121320343559643
11.0 1.9483441449905512
12.0 1.7633557568774194
13.0 1.5674956941478466
14.0 1.3619714992186405
15.0 1.1480502970952695
16.0 0.9270509831248425
17.0 0.7003360915677164
18.0 0.46930339512069275
19.0 0.235377287183535
20.0 1.836909530733566E-16
21.0 -0.23537728718353465
22.0 -0.46930339512069175
23.0 -0.700336091567716
24.0 -0.927050983124842
25.0 -1.148050297095269
26.0 -1.3619714992186402
27.0 -1.5674956941478464
28.0 -1.7633557568774192
29.0 -1.9483441449905508
30.0 -2.1213203435596424
31.0 -2.2812178968000927
32.0 -2.427050983124842
33.0 -2.5579204930622765
34.0 -2.6730195725651034
35.0 -2.77163859753386
36.0 -2.8531695488854605
37.0 -2.91710976119303
38.0 -2.9630650217854133
39.0 -2.990752001199384
40.0 -3.0
41.0 -2.9907520011993842
42.0 -2.9630650217854133
43.0 -2.91710976119303
44.0 -2.8531695488854614
45.0 -2.7716385975338604
46.0 -2.673019572565104
47.0 -2.557920493062276
48.0 -2.4270509831248424
49.0 -2.281217896800094
50.0 -2.121320343559643
51.0 -1.9483441449905523
52.0 -1.7633557568774199
53.0 -1.567495694147846
54.0 -1.361971499218641
55.0 -1.1480502970952686
56.0 -0.9270509831248428
57.0 -0.700336091567718
58.0 -0.46930339512069313
59.0 -0.2353772871835367
60.0 -5.510728592200698E-16
61.0 0.2353772871835356
62.0 0.469303395120692
63.0 0.7003360915677169
64.0 0.9270509831248417
65.0 1.1480502970952675
66.0 1.3619714992186398
67.0 1.5674956941478448
68.0 1.763355756877419
69.0 1.9483441449905514
70.0 2.121320343559642
71.0 2.281217896800093
72.0 2.427050983124842
73.0 2.5579204930622756
74.0 2.6730195725651034
75.0 2.7716385975338595
76.0 2.8531695488854605
77.0 2.91710976119303
78.0 2.963065021785413
79.0 2.990752001199384
80.0 3.0
81.0 2.9907520011993842
82.0 2.9630650217854138
83.0 2.91710976119303
84.0 2.853169548885461
85.0 2.77163859753386
86.0 2.673019572565104
87.0 2.557920493062278
88.0 2.427050983124844
89.0 2.2812178968000927
90.0 2.1213203435596433
91.0 1.9483441449905525
92.0 1.76335575687742
93.0 1.5674956941478484
94.0 1.3619714992186387
95.0 1.1480502970952688
96.0 0.9270509831248431
97.0 0.7003360915677184
98.0 0.46930339512069613
99.0 0.2353772871835344
100.0 9.18454765366783E-16
 
Dataset:6
1.0 2.4939101256495606
2.0 2.475670171853926
3.0 2.4453690018345142
4.0 2.4031542398457972
5.0 2.349231551964771
6.0 2.283863644106502
7.0 2.2073689821473175
8.0 2.120120240391065
9.0 2.0225424859373686
10.0 1.9151111077974452
11.0 1.798349500846628
12.0 1.6728265158971456
13.0 1.5391536883141457
14.0 1.397982258676867
15.0 1.2500000000000002
16.0 1.0959278669726935
17.0 0.9365164835397799
18.0 0.7725424859373686
19.0 0.6048047389991698
20.0 0.4341204441673261
21.0 0.26132115816913365
22.0 0.0872487417562527
23.0 -0.08724874175625184
24.0 -0.2613211581691333
25.0 -0.43412044416732576
26.0 -0.6048047389991694
27.0 -0.7725424859373684
28.0 -0.9365164835397801
29.0 -1.0959278669726937
30.0 -1.2499999999999996
31.0 -1.3979822586768669
32.0 -1.5391536883141457
33.0 -1.6728265158971456
34.0 -1.7983495008466281
35.0 -1.9151111077974448
36.0 -2.0225424859373686
37.0 -2.120120240391065
38.0 -2.207368982147317
39.0 -2.283863644106502
40.0 -2.349231551964771
41.0 -2.403154239845797
42.0 -2.4453690018345142
43.0 -2.475670171853926
44.0 -2.4939101256495606
45.0 -2.5
46.0 -2.4939101256495606
47.0 -2.475670171853926
48.0 -2.4453690018345142
49.0 -2.4031542398457972
50.0 -2.349231551964771
51.0 -2.2838636441065026
52.0 -2.207368982147317
53.0 -2.1201202403910653
54.0 -2.0225424859373686
55.0 -1.9151111077974452
56.0 -1.7983495008466277
57.0 -1.672826515897146
58.0 -1.5391536883141452
59.0 -1.3979822586768682
60.0 -1.2500000000000009
61.0 -1.0959278669726944
62.0 -0.9365164835397807
63.0 -0.772542485937369
64.0 -0.6048047389991695
65.0 -0.4341204441673258
66.0 -0.26132115816913337
67.0 -0.08724874175625412
68.0 0.0872487417562532
69.0 0.2613211581691325
70.0 0.4341204441673249
71.0 0.6048047389991686
72.0 0.7725424859373681
73.0 0.9365164835397799
74.0 1.0959278669726935
75.0 1.2500000000000002
76.0 1.3979822586768655
77.0 1.5391536883141463
78.0 1.6728265158971445
79.0 1.798349500846627
80.0 1.9151111077974445
81.0 2.022542485937368
82.0 2.1201202403910635
83.0 2.2073689821473175
84.0 2.283863644106502
85.0 2.3492315519647713
86.0 2.403154239845797
87.0 2.445369001834514
88.0 2.475670171853926
89.0 2.4939101256495606
90.0 2.5
91.0 2.4939101256495606
92.0 2.4756701718539262
93.0 2.4453690018345147
94.0 2.4031542398457972
95.0 2.349231551964771
96.0 2.283863644106503
97.0 2.207368982147318
98.0 2.1201202403910653
99.0 2.0225424859373677
100.0 1.9151111077974454
 
Dataset:7
0.0 2.0
1.0 1.9960534568565431
2.0 1.9842294026289558
3.0 1.9645745014573774
4.0 1.9371663222572622
5.0 1.902113032590307
6.0 1.859552971776503
7.0 1.8096541049320392
8.0 1.7526133600877272
9.0 1.6886558510040302
10.0 1.618033988749895
11.0 1.5410264855515785
12.0 1.457937254842823
13.0 1.3690942118573772
14.0 1.2748479794973795
15.0 1.1755705045849465
16.0 1.071653589957993
17.0 0.9635073482034303
18.0 0.8515585831301453
19.0 0.7362491053693562
20.0 0.6180339887498949
21.0 0.4973797743297095
22.0 0.3747626291714495
23.0 0.25066646712860896
24.0 0.12558103905862705
25.0 1.2246063538223773E-16
26.0 -0.1255810390586268
27.0 -0.2506664671286083
28.0 -0.3747626291714492
29.0 -0.4973797743297097
30.0 -0.6180339887498942
31.0 -0.7362491053693555
32.0 -0.8515585831301454
33.0 -0.9635073482034309
34.0 -1.0716535899579938
35.0 -1.175570504584946
36.0 -1.2748479794973795
37.0 -1.3690942118573775
38.0 -1.4579372548428227
39.0 -1.5410264855515783
40.0 -1.6180339887498947
41.0 -1.6886558510040297
42.0 -1.7526133600877272
43.0 -1.8096541049320387
44.0 -1.8595529717765027
45.0 -1.902113032590307
46.0 -1.937166322257262
47.0 -1.9645745014573774
48.0 -1.9842294026289555
49.0 -1.9960534568565431
50.0 -2.0
51.0 -1.9960534568565431
52.0 -1.9842294026289558
53.0 -1.9645745014573772
54.0 -1.9371663222572624
55.0 -1.9021130325903073
56.0 -1.859552971776503
57.0 -1.8096541049320394
58.0 -1.752613360087727
59.0 -1.6886558510040304
60.0 -1.6180339887498956
61.0 -1.5410264855515785
62.0 -1.4579372548428235
63.0 -1.3690942118573772
64.0 -1.274847979497379
65.0 -1.1755705045849465
66.0 -1.0716535899579926
67.0 -0.9635073482034305
68.0 -0.8515585831301443
69.0 -0.7362491053693556
70.0 -0.6180339887498951
71.0 -0.49737977432970887
72.0 -0.37476262917144926
73.0 -0.2506664671286092
74.0 -0.12558103905862641
75.0 -3.673819061467132E-16
76.0 0.12558103905862567
77.0 0.25066646712860846
78.0 0.37476262917144854
79.0 0.49737977432970987
80.0 0.6180339887498945
81.0 0.7362491053693548
82.0 0.8515585831301437
83.0 0.9635073482034314
84.0 1.0716535899579935
85.0 1.1755705045849458
86.0 1.2748479794973786
87.0 1.369094211857376
88.0 1.4579372548428224
89.0 1.5410264855515787
90.0 1.6180339887498947
91.0 1.6886558510040295
92.0 1.7526133600877263
93.0 1.8096541049320387
94.0 1.859552971776503
95.0 1.902113032590307
96.0 1.937166322257262
97.0 1.9645745014573774
98.0 1.9842294026289555
99.0 1.9960534568565431
100.0 2.0
 
 
Dataset:8
0.0 1.5
1.0 1.4975536558892035
2.0 1.4902226030228254
3.0 1.4780307537715396
4.0 1.4610178754135004
5.0 1.439239460421746
6.0 1.412766545459287
7.0 1.3816854796722753
8.0 1.3460976430370377
9.0 1.3061191156796659
10.0 1.2618802992467717
11.0 1.2135254915624212
12.0 1.1612124159586237
13.0 1.1051117068146072
14.0 1.0454063529829403
15.0 0.9822911009179277
16.0 0.9159718194531573
17.0 0.8466648283001538
18.0 0.7745961924584429
19.0 0.7000009848385107
20.0 0.6231225195028297
21.0 0.5442115580259614
22.0 0.4635254915624215
23.0 0.38132750129023063
24.0 0.2978856999686183
25.0 0.21347225740992767
26.0 0.12836251271825944
27.0 0.04283407619054471
28.0 -0.0428340761905442
29.0 -0.12836251271825957
30.0 -0.21347225740992748
31.0 -0.29788569996861813
32.0 -0.38132750129023013
33.0 -0.463525491562421
34.0 -0.5442115580259616
35.0 -0.6231225195028295
36.0 -0.7000009848385106
37.0 -0.7745961924584427
38.0 -0.8466648283001534
39.0 -0.9159718194531568
40.0 -0.9822911009179276
41.0 -1.04540635298294
42.0 -1.1051117068146075
43.0 -1.1612124159586237
44.0 -1.2135254915624207
45.0 -1.2618802992467715
46.0 -1.3061191156796654
47.0 -1.3460976430370375
48.0 -1.381685479672275
49.0 -1.4127665454592868
50.0 -1.439239460421746
51.0 -1.4610178754135001
52.0 -1.4780307537715396
53.0 -1.4902226030228254
54.0 -1.4975536558892035
55.0 -1.5
56.0 -1.4975536558892035
57.0 -1.4902226030228254
58.0 -1.4780307537715396
59.0 -1.4610178754135004
60.0 -1.4392394604217462
61.0 -1.412766545459287
62.0 -1.3816854796722753
63.0 -1.3460976430370375
64.0 -1.306119115679666
65.0 -1.2618802992467721
66.0 -1.2135254915624212
67.0 -1.161212415958624
68.0 -1.1051117068146072
69.0 -1.0454063529829403
70.0 -0.9822911009179278
71.0 -0.9159718194531575
72.0 -0.8466648283001538
73.0 -0.7745961924584436
74.0 -0.7000009848385109
75.0 -0.6231225195028295
76.0 -0.5442115580259622
77.0 -0.4635254915624214
78.0 -0.38132750129023146
79.0 -0.2978856999686188
80.0 -0.21347225740992787
81.0 -0.1283625127182606
82.0 -0.0428340761905449
83.0 0.04283407619054434
84.0 0.12836251271826005
85.0 0.2134722574099273
86.0 0.29788569996861824
87.0 0.38132750129022963
88.0 0.46352549156241957
89.0 0.5442115580259617
90.0 0.623122519502829
91.0 0.7000009848385104
92.0 0.774596192458442
93.0 0.8466648283001533
94.0 0.9159718194531571
95.0 0.9822911009179279
96.0 1.0454063529829398
97.0 1.1051117068146075
98.0 1.1612124159586232
99.0 1.2135254915624216
100.0 1.261880299246772
 
 
Dataset:9
0.0 1.0
1.0 0.9986295347545738
2.0 0.9945218953682733
3.0 0.9876883405951378
4.0 0.9781476007338057
5.0 0.9659258262890683
6.0 0.9510565162951535
7.0 0.9335804264972017
8.0 0.9135454576426009
9.0 0.8910065241883679
10.0 0.8660254037844387
11.0 0.838670567945424
12.0 0.8090169943749475
13.0 0.7771459614569709
14.0 0.7431448254773942
15.0 0.7071067811865476
16.0 0.6691306063588582
17.0 0.6293203910498375
18.0 0.5877852522924731
19.0 0.5446390350150272
20.0 0.5000000000000001
21.0 0.4539904997395468
22.0 0.4067366430758004
23.0 0.3583679495453004
24.0 0.30901699437494745
25.0 0.25881904510252074
26.0 0.20791169081775923
27.0 0.15643446504023092
28.0 0.10452846326765346
29.0 0.052335956242943744
30.0 2.8327492261615017E-16
31.0 -0.05233595624294362
32.0 -0.10452846326765333
33.0 -0.1564344650402308
34.0 -0.20791169081775934
35.0 -0.25881904510252063
36.0 -0.30901699437494734
37.0 -0.35836794954530027
38.0 -0.40673664307580004
39.0 -0.4539904997395467
40.0 -0.4999999999999998
41.0 -0.5446390350150268
42.0 -0.587785252292473
43.0 -0.6293203910498373
44.0 -0.6691306063588579
45.0 -0.7071067811865475
46.0 -0.743144825477394
47.0 -0.7771459614569709
48.0 -0.8090169943749473
49.0 -0.8386705679454239
50.0 -0.8660254037844387
51.0 -0.8910065241883678
52.0 -0.913545457642601
53.0 -0.9335804264972017
54.0 -0.9510565162951535
55.0 -0.9659258262890683
56.0 -0.9781476007338057
57.0 -0.9876883405951377
58.0 -0.9945218953682734
59.0 -0.9986295347545738
60.0 -1.0
61.0 -0.9986295347545738
62.0 -0.9945218953682734
63.0 -0.9876883405951378
64.0 -0.9781476007338057
65.0 -0.9659258262890684
66.0 -0.9510565162951536
67.0 -0.9335804264972019
68.0 -0.9135454576426009
69.0 -0.8910065241883679
70.0 -0.8660254037844388
71.0 -0.838670567945424
72.0 -0.8090169943749476
73.0 -0.777145961456971
74.0 -0.7431448254773942
75.0 -0.7071067811865477
76.0 -0.6691306063588585
77.0 -0.6293203910498378
78.0 -0.5877852522924732
79.0 -0.544639035015027
80.0 -0.5000000000000004
81.0 -0.4539904997395469
82.0 -0.4067366430758009
83.0 -0.3583679495452999
84.0 -0.30901699437494756
85.0 -0.25881904510252063
86.0 -0.2079116908177598
87.0 -0.15643446504023104
88.0 -0.10452846326765423
89.0 -0.052335956242943425
90.0 -1.836909530733566E-16
91.0 0.052335956242943946
92.0 0.10452846326765299
93.0 0.15643446504023067
94.0 0.20791169081775943
95.0 0.25881904510252113
96.0 0.30901699437494723
97.0 0.35836794954529955
98.0 0.40673664307579976
99.0 0.45399049973954664
 
Dataset:last but not least
0.0 0.5
1.0 0.4994161134161633
2.0 0.4976658173588243
3.0 0.49475319972552556
4.0 0.4906850630697067
5.0 0.485470908713026
6.0 0.4791229145545831
7.0 0.4716559066288715
8.0 0.4630873244788883
9.0 0.4534371804252727
10.0 0.44272801282660496
11.0 0.43098483344002464
12.0 0.41823506900511337
13.0 0.4045084971874737
14.0 0.3898371770316112
15.0 0.3742553740855506
16.0 0.35779948037206055
17.0 0.3405079293933985
18.0 0.3224211063680853
19.0 0.30358125390935564
20.0 0.28403237336557796
21.0 0.2638201220530664
22.0 0.2429917066213031
23.0 0.22159577279962067
24.0 0.19968229178284783
25.0 0.17730244352126778
26.0 0.15450849718747373
27.0 0.13135368909929354
28.0 0.10789209838390307
29.0 0.08417852067351932
30.0 0.060268340127661614
31.0 0.0362174000808812
32.0 0.012081872618066208
33.0 -0.012081872618066147
34.0 -0.03621740008088125
35.0 -0.06026834012766144
36.0 -0.08417852067351926
37.0 -0.10789209838390301
38.0 -0.13135368909929337
39.0 -0.15450849718747367
40.0 -0.17730244352126773
41.0 -0.19968229178284766
42.0 -0.22159577279962062
43.0 -0.24299170662130304
44.0 -0.26382012205306626
45.0 -0.28403237336557785
46.0 -0.3035812539093556
47.0 -0.32242110636808535
48.0 -0.3405079293933985
49.0 -0.3577994803720605
50.0 -0.3742553740855506
51.0 -0.38983717703161114
52.0 -0.40450849718747367
53.0 -0.41823506900511337
54.0 -0.43098483344002453
55.0 -0.4427280128266049
56.0 -0.4534371804252727
57.0 -0.4630873244788882
58.0 -0.4716559066288715
59.0 -0.4791229145545831
60.0 -0.48547090871302595
61.0 -0.4906850630697067
62.0 -0.49475319972552556
63.0 -0.4976658173588243
64.0 -0.49941611341616327
65.0 -0.5
66.0 -0.4994161134161633
67.0 -0.4976658173588243
68.0 -0.4947531997255255
69.0 -0.4906850630697067
70.0 -0.48547090871302606
71.0 -0.47912291455458306
72.0 -0.4716559066288716
73.0 -0.46308732447888834
74.0 -0.45343718042527276
75.0 -0.44272801282660496
76.0 -0.4309848334400247
77.0 -0.4182350690051134
78.0 -0.4045084971874738
79.0 -0.3898371770316112
80.0 -0.37425537408555065
81.0 -0.3577994803720606
82.0 -0.34050792939339874
83.0 -0.32242110636808513
84.0 -0.3035812539093557
85.0 -0.28403237336557796
86.0 -0.2638201220530664
87.0 -0.24299170662130334
88.0 -0.22159577279962092
89.0 -0.19968229178284758
90.0 -0.17730244352126795
91.0 -0.15450849718747378
92.0 -0.13135368909929349
93.0 -0.10789209838390346
94.0 -0.08417852067351916
95.0 -0.06026834012766134
96.0 -0.036217400080881375
97.0 -0.01208187261806627
98.0 0.012081872618066087
99.0 0.03621740008088119
100.0 0.0602683401276616
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/sinus.graph.txt
0,0 → 1,1044
TitleText: My Plot 1031 datapoints processed
XRange: 0,4
YRange: -4,4
# Manually specify X ticks
XTicks: zero 0, one 1, two 2, pi 3.1428, four 4, five 5
Grid: on
XLabel: X Axis
YLabel: Y Axis
Marks: various
NumSets: 10
Color: on
 
Dataset: 1
0.0 5.0
1.0 4.938441702975688
2.0 4.755282581475768
3.0 4.455032620941839
4.0 4.045084971874737
5.0 3.5355339059327378
6.0 2.938926261462366
7.0 2.269952498697734
8.0 1.5450849718747373
9.0 0.7821723252011547
10.0 3.061515884555943E-16
11.0 -0.7821723252011529
12.0 -1.5450849718747368
13.0 -2.2699524986977337
14.0 -2.9389262614623655
15.0 -3.5355339059327373
16.0 -4.045084971874737
17.0 -4.455032620941839
18.0 -4.755282581475767
19.0 -4.938441702975688
20.0 -5.0
21.0 -4.938441702975688
22.0 -4.755282581475769
23.0 -4.455032620941839
24.0 -4.045084971874737
25.0 -3.535533905932738
26.0 -2.9389262614623664
27.0 -2.2699524986977346
28.0 -1.545084971874738
29.0 -0.7821723252011552
30.0 -9.18454765366783E-16
31.0 0.7821723252011534
32.0 1.5450849718747361
33.0 2.269952498697733
34.0 2.938926261462365
35.0 3.535533905932737
36.0 4.045084971874736
37.0 4.4550326209418385
38.0 4.755282581475767
39.0 4.938441702975688
40.0 5.0
41.0 4.938441702975689
42.0 4.755282581475768
43.0 4.45503262094184
44.0 4.045084971874741
45.0 3.5355339059327386
46.0 2.938926261462367
47.0 2.269952498697731
48.0 1.5450849718747386
49.0 0.7821723252011602
50.0 1.5307579422779716E-15
51.0 -0.7821723252011484
52.0 -1.5450849718747357
53.0 -2.2699524986977364
54.0 -2.938926261462364
55.0 -3.5355339059327395
56.0 -4.045084971874736
57.0 -4.455032620941837
58.0 -4.755282581475767
59.0 -4.9384417029756875
60.0 -5.0
61.0 -4.938441702975688
62.0 -4.755282581475768
63.0 -4.4550326209418385
64.0 -4.045084971874738
65.0 -3.535533905932742
66.0 -2.9389262614623672
67.0 -2.26995249869774
68.0 -1.545084971874739
69.0 -0.7821723252011521
70.0 -2.1430611191891602E-15
71.0 0.7821723252011565
72.0 1.545084971874735
73.0 2.269952498697728
74.0 2.9389262614623637
75.0 3.535533905932733
76.0 4.0450849718747355
77.0 4.45503262094184
78.0 4.755282581475767
79.0 4.938441702975689
80.0 5.0
81.0 4.938441702975689
82.0 4.755282581475772
83.0 4.4550326209418385
84.0 4.045084971874739
85.0 3.5355339059327364
86.0 2.9389262614623677
87.0 2.2699524986977404
88.0 1.5450849718747481
89.0 0.7821723252011527
90.0 2.755364296100349E-15
91.0 -0.7821723252011472
92.0 -1.5450849718747344
93.0 -2.2699524986977275
94.0 -2.9389262614623703
95.0 -3.5355339059327386
96.0 -4.0450849718747355
97.0 -4.455032620941836
98.0 -4.755282581475764
99.0 -4.938441702975688
100.0 -5.0
 
Dataset:2
0.0 4.5
1.0 4.46451615591515
2.0 4.35862422507884
3.0 4.183994186497132
4.0 3.943380060197386
5.0 3.6405764746872635
6.0 3.280358823396352
7.0 2.8684079538691036
8.0 2.4112205774054845
9.0 1.9160068120428269
10.0 1.3905764746872635
11.0 0.8432159156357613
12.0 0.28255733788191084
13.0 -0.2825573378819103
14.0 -0.8432159156357607
15.0 -1.3905764746872622
16.0 -1.9160068120428273
17.0 -2.411220577405486
18.0 -2.8684079538691036
19.0 -3.280358823396351
20.0 -3.640576474687263
21.0 -3.9433800601973865
22.0 -4.183994186497131
23.0 -4.35862422507884
24.0 -4.46451615591515
25.0 -4.5
26.0 -4.46451615591515
27.0 -4.35862422507884
28.0 -4.183994186497132
29.0 -3.943380060197386
30.0 -3.640576474687265
31.0 -3.280358823396353
32.0 -2.868407953869103
33.0 -2.4112205774054836
34.0 -1.9160068120428246
35.0 -1.3905764746872642
36.0 -0.8432159156357608
37.0 -0.2825573378819094
38.0 0.28255733788190773
39.0 0.8432159156357593
40.0 1.3905764746872626
41.0 1.9160068120428233
42.0 2.4112205774054853
43.0 2.868407953869102
44.0 3.2803588233963508
45.0 3.6405764746872626
46.0 3.9433800601973843
47.0 4.183994186497132
48.0 4.358624225078839
49.0 4.46451615591515
50.0 4.5
51.0 4.464516155915151
52.0 4.35862422507884
53.0 4.183994186497131
54.0 3.943380060197387
55.0 3.640576474687264
56.0 3.280358823396352
57.0 2.8684079538691063
58.0 2.411220577405484
59.0 1.9160068120428289
60.0 1.3905764746872684
61.0 0.8432159156357614
62.0 0.28255733788191395
63.0 -0.2825573378819112
64.0 -0.8432159156357626
65.0 -1.390576474687262
66.0 -1.91600681204283
67.0 -2.411220577405485
68.0 -2.8684079538691076
69.0 -3.280358823396353
70.0 -3.6405764746872626
71.0 -3.943380060197388
72.0 -4.183994186497132
73.0 -4.358624225078839
74.0 -4.464516155915151
75.0 -4.5
76.0 -4.464516155915151
77.0 -4.35862422507884
78.0 -4.183994186497133
79.0 -3.9433800601973856
80.0 -3.6405764746872644
81.0 -3.280358823396355
82.0 -2.86840795386911
83.0 -2.411220577405481
84.0 -1.9160068120428257
85.0 -1.390576474687265
86.0 -0.8432159156357658
87.0 -0.2825573378819185
88.0 0.2825573378819067
89.0 0.843215915635762
90.0 1.3905764746872615
91.0 1.9160068120428222
92.0 2.411220577405478
93.0 2.868407953869101
94.0 3.2803588233963525
95.0 3.640576474687262
96.0 3.9433800601973834
97.0 4.183994186497131
98.0 4.358624225078839
99.0 4.464516155915151
100.0 4.5
 
 
 
Dataset:3
0.0 4.0
1.0 3.978087581473093
2.0 3.9125904029352228
3.0 3.804226065180614
4.0 3.6541818305704035
5.0 3.464101615137755
6.0 3.23606797749979
7.0 2.972579301909577
8.0 2.676522425435433
9.0 2.3511410091698925
10.0 2.0000000000000004
11.0 1.6269465723032015
12.0 1.2360679774997898
13.0 0.8316467632710369
14.0 0.41811385307061383
15.0 1.1330996904646007E-15
16.0 -0.41811385307061333
17.0 -0.8316467632710374
18.0 -1.2360679774997894
19.0 -1.6269465723032002
20.0 -1.9999999999999991
21.0 -2.351141009169892
22.0 -2.6765224254354316
23.0 -2.972579301909576
24.0 -3.2360679774997894
25.0 -3.464101615137755
26.0 -3.654181830570404
27.0 -3.804226065180614
28.0 -3.9125904029352228
29.0 -3.9780875814730936
30.0 -4.0
31.0 -3.9780875814730936
32.0 -3.9125904029352228
33.0 -3.8042260651806146
34.0 -3.6541818305704035
35.0 -3.4641016151377553
36.0 -3.2360679774997902
37.0 -2.972579301909577
38.0 -2.676522425435434
39.0 -2.351141009169893
40.0 -2.0000000000000018
41.0 -1.6269465723032035
42.0 -1.2360679774997902
43.0 -0.8316467632710391
44.0 -0.41811385307061694
45.0 -7.347638122934264E-16
46.0 0.41811385307061194
47.0 0.8316467632710377
48.0 1.236067977499789
49.0 1.626946572303199
50.0 2.0000000000000004
51.0 2.3511410091698917
52.0 2.676522425435434
53.0 2.972579301909577
54.0 3.2360679774997894
55.0 3.4641016151377553
56.0 3.654181830570404
57.0 3.804226065180614
58.0 3.9125904029352228
59.0 3.978087581473093
60.0 4.0
61.0 3.9780875814730936
62.0 3.912590402935223
63.0 3.8042260651806146
64.0 3.6541818305704044
65.0 3.464101615137756
66.0 3.2360679774997902
67.0 2.9725793019095783
68.0 2.676522425435433
69.0 2.3511410091698934
70.0 2.000000000000002
71.0 1.6269465723032008
72.0 1.236067977499791
73.0 0.8316467632710397
74.0 0.4181138530706139
75.0 1.2246063538223773E-15
76.0 -0.4181138530706115
77.0 -0.8316467632710338
78.0 -1.2360679774997885
79.0 -1.6269465723032017
80.0 -1.999999999999997
81.0 -2.3511410091698917
82.0 -2.6765224254354285
83.0 -2.972579301909579
84.0 -3.236067977499789
85.0 -3.4641016151377553
86.0 -3.654181830570402
87.0 -3.8042260651806137
88.0 -3.9125904029352214
89.0 -3.9780875814730936
90.0 -4.0
91.0 -3.978087581473093
92.0 -3.912590402935223
93.0 -3.8042260651806146
94.0 -3.654181830570403
95.0 -3.464101615137753
96.0 -3.2360679774997907
97.0 -2.972579301909581
98.0 -2.6765224254354356
99.0 -2.351141009169894
100.0 -1.9999999999999993
 
 
Dataset:4
0.0 3.5
1.0 3.4859100289833367
2.0 3.4437535600952036
3.0 3.3738700124354866
4.0 3.2768220472390803
5.0 3.153391037658467
6.0 3.0045707776065314
7.0 2.831559480312316
8.0 2.6357501310126383
9.0 2.4187192714540267
10.0 2.1822143065055672
11.0 1.9281394350823593
12.0 1.6585403186554954
13.0 1.3755876107887328
14.0 1.081559480312316
15.0 0.7788232688471006
16.0 0.4698164303617944
17.0 0.15702690622680246
18.0 -0.15702690622680202
19.0 -0.46981643036179394
20.0 -0.7788232688471002
21.0 -1.0815594803123156
22.0 -1.3755876107887317
23.0 -1.658540318655495
24.0 -1.9281394350823586
25.0 -2.1822143065055672
26.0 -2.418719271454026
27.0 -2.635750131012638
28.0 -2.8315594803123156
29.0 -3.0045707776065314
30.0 -3.1533910376584666
31.0 -3.27682204723908
32.0 -3.3738700124354866
33.0 -3.4437535600952036
34.0 -3.4859100289833367
35.0 -3.5
36.0 -3.4859100289833367
37.0 -3.443753560095204
38.0 -3.3738700124354866
39.0 -3.2768220472390803
40.0 -3.153391037658467
41.0 -3.0045707776065327
42.0 -2.831559480312316
43.0 -2.6357501310126388
44.0 -2.418719271454028
45.0 -2.1822143065055677
46.0 -1.9281394350823593
47.0 -1.658540318655496
48.0 -1.3755876107887333
49.0 -1.0815594803123165
50.0 -0.778823268847101
51.0 -0.46981643036179477
52.0 -0.15702690622680288
53.0 0.1570269062268016
54.0 0.4698164303617935
55.0 0.7788232688470997
56.0 1.0815594803123154
57.0 1.375587610788732
58.0 1.6585403186554948
59.0 1.9281394350823582
60.0 2.182214306505567
61.0 2.4187192714540258
62.0 2.635750131012638
63.0 2.8315594803123156
64.0 3.004570777606531
65.0 3.1533910376584666
66.0 3.27682204723908
67.0 3.373870012435486
68.0 3.4437535600952036
69.0 3.4859100289833367
70.0 3.5
71.0 3.4859100289833367
72.0 3.443753560095204
73.0 3.3738700124354866
74.0 3.2768220472390808
75.0 3.1533910376584675
76.0 3.004570777606532
77.0 2.8315594803123165
78.0 2.6357501310126388
79.0 2.418719271454027
80.0 2.182214306505568
81.0 1.9281394350823597
82.0 1.658540318655499
83.0 1.3755876107887308
84.0 1.081559480312317
85.0 0.7788232688471014
86.0 0.4698164303617952
87.0 0.1570269062268064
88.0 -0.15702690622679805
89.0 -0.46981643036179616
90.0 -0.7788232688470993
91.0 -1.081559480312315
92.0 -1.3755876107887317
93.0 -1.6585403186554943
94.0 -1.928139435082358
95.0 -2.1822143065055664
96.0 -2.4187192714540253
97.0 -2.6357501310126374
98.0 -2.831559480312315
99.0 -3.004570777606531
100.0 -3.1533910376584666
 
Dataset:5
0.0 3.0
1.0 2.990752001199384
2.0 2.9630650217854133
3.0 2.91710976119303
4.0 2.853169548885461
5.0 2.7716385975338604
6.0 2.673019572565104
7.0 2.5579204930622765
8.0 2.4270509831248424
9.0 2.2812178968000927
10.0 2.121320343559643
11.0 1.9483441449905512
12.0 1.7633557568774194
13.0 1.5674956941478466
14.0 1.3619714992186405
15.0 1.1480502970952695
16.0 0.9270509831248425
17.0 0.7003360915677164
18.0 0.46930339512069275
19.0 0.235377287183535
20.0 1.836909530733566E-16
21.0 -0.23537728718353465
22.0 -0.46930339512069175
23.0 -0.700336091567716
24.0 -0.927050983124842
25.0 -1.148050297095269
26.0 -1.3619714992186402
27.0 -1.5674956941478464
28.0 -1.7633557568774192
29.0 -1.9483441449905508
30.0 -2.1213203435596424
31.0 -2.2812178968000927
32.0 -2.427050983124842
33.0 -2.5579204930622765
34.0 -2.6730195725651034
35.0 -2.77163859753386
36.0 -2.8531695488854605
37.0 -2.91710976119303
38.0 -2.9630650217854133
39.0 -2.990752001199384
40.0 -3.0
41.0 -2.9907520011993842
42.0 -2.9630650217854133
43.0 -2.91710976119303
44.0 -2.8531695488854614
45.0 -2.7716385975338604
46.0 -2.673019572565104
47.0 -2.557920493062276
48.0 -2.4270509831248424
49.0 -2.281217896800094
50.0 -2.121320343559643
51.0 -1.9483441449905523
52.0 -1.7633557568774199
53.0 -1.567495694147846
54.0 -1.361971499218641
55.0 -1.1480502970952686
56.0 -0.9270509831248428
57.0 -0.700336091567718
58.0 -0.46930339512069313
59.0 -0.2353772871835367
60.0 -5.510728592200698E-16
61.0 0.2353772871835356
62.0 0.469303395120692
63.0 0.7003360915677169
64.0 0.9270509831248417
65.0 1.1480502970952675
66.0 1.3619714992186398
67.0 1.5674956941478448
68.0 1.763355756877419
69.0 1.9483441449905514
70.0 2.121320343559642
71.0 2.281217896800093
72.0 2.427050983124842
73.0 2.5579204930622756
74.0 2.6730195725651034
75.0 2.7716385975338595
76.0 2.8531695488854605
77.0 2.91710976119303
78.0 2.963065021785413
79.0 2.990752001199384
80.0 3.0
81.0 2.9907520011993842
82.0 2.9630650217854138
83.0 2.91710976119303
84.0 2.853169548885461
85.0 2.77163859753386
86.0 2.673019572565104
87.0 2.557920493062278
88.0 2.427050983124844
89.0 2.2812178968000927
90.0 2.1213203435596433
91.0 1.9483441449905525
92.0 1.76335575687742
93.0 1.5674956941478484
94.0 1.3619714992186387
95.0 1.1480502970952688
96.0 0.9270509831248431
97.0 0.7003360915677184
98.0 0.46930339512069613
99.0 0.2353772871835344
100.0 9.18454765366783E-16
 
Dataset:6
1.0 2.4939101256495606
2.0 2.475670171853926
3.0 2.4453690018345142
4.0 2.4031542398457972
5.0 2.349231551964771
6.0 2.283863644106502
7.0 2.2073689821473175
8.0 2.120120240391065
9.0 2.0225424859373686
10.0 1.9151111077974452
11.0 1.798349500846628
12.0 1.6728265158971456
13.0 1.5391536883141457
14.0 1.397982258676867
15.0 1.2500000000000002
16.0 1.0959278669726935
17.0 0.9365164835397799
18.0 0.7725424859373686
19.0 0.6048047389991698
20.0 0.4341204441673261
21.0 0.26132115816913365
22.0 0.0872487417562527
23.0 -0.08724874175625184
24.0 -0.2613211581691333
25.0 -0.43412044416732576
26.0 -0.6048047389991694
27.0 -0.7725424859373684
28.0 -0.9365164835397801
29.0 -1.0959278669726937
30.0 -1.2499999999999996
31.0 -1.3979822586768669
32.0 -1.5391536883141457
33.0 -1.6728265158971456
34.0 -1.7983495008466281
35.0 -1.9151111077974448
36.0 -2.0225424859373686
37.0 -2.120120240391065
38.0 -2.207368982147317
39.0 -2.283863644106502
40.0 -2.349231551964771
41.0 -2.403154239845797
42.0 -2.4453690018345142
43.0 -2.475670171853926
44.0 -2.4939101256495606
45.0 -2.5
46.0 -2.4939101256495606
47.0 -2.475670171853926
48.0 -2.4453690018345142
49.0 -2.4031542398457972
50.0 -2.349231551964771
51.0 -2.2838636441065026
52.0 -2.207368982147317
53.0 -2.1201202403910653
54.0 -2.0225424859373686
55.0 -1.9151111077974452
56.0 -1.7983495008466277
57.0 -1.672826515897146
58.0 -1.5391536883141452
59.0 -1.3979822586768682
60.0 -1.2500000000000009
61.0 -1.0959278669726944
62.0 -0.9365164835397807
63.0 -0.772542485937369
64.0 -0.6048047389991695
65.0 -0.4341204441673258
66.0 -0.26132115816913337
67.0 -0.08724874175625412
68.0 0.0872487417562532
69.0 0.2613211581691325
70.0 0.4341204441673249
71.0 0.6048047389991686
72.0 0.7725424859373681
73.0 0.9365164835397799
74.0 1.0959278669726935
75.0 1.2500000000000002
76.0 1.3979822586768655
77.0 1.5391536883141463
78.0 1.6728265158971445
79.0 1.798349500846627
80.0 1.9151111077974445
81.0 2.022542485937368
82.0 2.1201202403910635
83.0 2.2073689821473175
84.0 2.283863644106502
85.0 2.3492315519647713
86.0 2.403154239845797
87.0 2.445369001834514
88.0 2.475670171853926
89.0 2.4939101256495606
90.0 2.5
91.0 2.4939101256495606
92.0 2.4756701718539262
93.0 2.4453690018345147
94.0 2.4031542398457972
95.0 2.349231551964771
96.0 2.283863644106503
97.0 2.207368982147318
98.0 2.1201202403910653
99.0 2.0225424859373677
100.0 1.9151111077974454
 
Dataset:7
0.0 2.0
1.0 1.9960534568565431
2.0 1.9842294026289558
3.0 1.9645745014573774
4.0 1.9371663222572622
5.0 1.902113032590307
6.0 1.859552971776503
7.0 1.8096541049320392
8.0 1.7526133600877272
9.0 1.6886558510040302
10.0 1.618033988749895
11.0 1.5410264855515785
12.0 1.457937254842823
13.0 1.3690942118573772
14.0 1.2748479794973795
15.0 1.1755705045849465
16.0 1.071653589957993
17.0 0.9635073482034303
18.0 0.8515585831301453
19.0 0.7362491053693562
20.0 0.6180339887498949
21.0 0.4973797743297095
22.0 0.3747626291714495
23.0 0.25066646712860896
24.0 0.12558103905862705
25.0 1.2246063538223773E-16
26.0 -0.1255810390586268
27.0 -0.2506664671286083
28.0 -0.3747626291714492
29.0 -0.4973797743297097
30.0 -0.6180339887498942
31.0 -0.7362491053693555
32.0 -0.8515585831301454
33.0 -0.9635073482034309
34.0 -1.0716535899579938
35.0 -1.175570504584946
36.0 -1.2748479794973795
37.0 -1.3690942118573775
38.0 -1.4579372548428227
39.0 -1.5410264855515783
40.0 -1.6180339887498947
41.0 -1.6886558510040297
42.0 -1.7526133600877272
43.0 -1.8096541049320387
44.0 -1.8595529717765027
45.0 -1.902113032590307
46.0 -1.937166322257262
47.0 -1.9645745014573774
48.0 -1.9842294026289555
49.0 -1.9960534568565431
50.0 -2.0
51.0 -1.9960534568565431
52.0 -1.9842294026289558
53.0 -1.9645745014573772
54.0 -1.9371663222572624
55.0 -1.9021130325903073
56.0 -1.859552971776503
57.0 -1.8096541049320394
58.0 -1.752613360087727
59.0 -1.6886558510040304
60.0 -1.6180339887498956
61.0 -1.5410264855515785
62.0 -1.4579372548428235
63.0 -1.3690942118573772
64.0 -1.274847979497379
65.0 -1.1755705045849465
66.0 -1.0716535899579926
67.0 -0.9635073482034305
68.0 -0.8515585831301443
69.0 -0.7362491053693556
70.0 -0.6180339887498951
71.0 -0.49737977432970887
72.0 -0.37476262917144926
73.0 -0.2506664671286092
74.0 -0.12558103905862641
75.0 -3.673819061467132E-16
76.0 0.12558103905862567
77.0 0.25066646712860846
78.0 0.37476262917144854
79.0 0.49737977432970987
80.0 0.6180339887498945
81.0 0.7362491053693548
82.0 0.8515585831301437
83.0 0.9635073482034314
84.0 1.0716535899579935
85.0 1.1755705045849458
86.0 1.2748479794973786
87.0 1.369094211857376
88.0 1.4579372548428224
89.0 1.5410264855515787
90.0 1.6180339887498947
91.0 1.6886558510040295
92.0 1.7526133600877263
93.0 1.8096541049320387
94.0 1.859552971776503
95.0 1.902113032590307
96.0 1.937166322257262
97.0 1.9645745014573774
98.0 1.9842294026289555
99.0 1.9960534568565431
100.0 2.0
 
 
Dataset:8
0.0 1.5
1.0 1.4975536558892035
2.0 1.4902226030228254
3.0 1.4780307537715396
4.0 1.4610178754135004
5.0 1.439239460421746
6.0 1.412766545459287
7.0 1.3816854796722753
8.0 1.3460976430370377
9.0 1.3061191156796659
10.0 1.2618802992467717
11.0 1.2135254915624212
12.0 1.1612124159586237
13.0 1.1051117068146072
14.0 1.0454063529829403
15.0 0.9822911009179277
16.0 0.9159718194531573
17.0 0.8466648283001538
18.0 0.7745961924584429
19.0 0.7000009848385107
20.0 0.6231225195028297
21.0 0.5442115580259614
22.0 0.4635254915624215
23.0 0.38132750129023063
24.0 0.2978856999686183
25.0 0.21347225740992767
26.0 0.12836251271825944
27.0 0.04283407619054471
28.0 -0.0428340761905442
29.0 -0.12836251271825957
30.0 -0.21347225740992748
31.0 -0.29788569996861813
32.0 -0.38132750129023013
33.0 -0.463525491562421
34.0 -0.5442115580259616
35.0 -0.6231225195028295
36.0 -0.7000009848385106
37.0 -0.7745961924584427
38.0 -0.8466648283001534
39.0 -0.9159718194531568
40.0 -0.9822911009179276
41.0 -1.04540635298294
42.0 -1.1051117068146075
43.0 -1.1612124159586237
44.0 -1.2135254915624207
45.0 -1.2618802992467715
46.0 -1.3061191156796654
47.0 -1.3460976430370375
48.0 -1.381685479672275
49.0 -1.4127665454592868
50.0 -1.439239460421746
51.0 -1.4610178754135001
52.0 -1.4780307537715396
53.0 -1.4902226030228254
54.0 -1.4975536558892035
55.0 -1.5
56.0 -1.4975536558892035
57.0 -1.4902226030228254
58.0 -1.4780307537715396
59.0 -1.4610178754135004
60.0 -1.4392394604217462
61.0 -1.412766545459287
62.0 -1.3816854796722753
63.0 -1.3460976430370375
64.0 -1.306119115679666
65.0 -1.2618802992467721
66.0 -1.2135254915624212
67.0 -1.161212415958624
68.0 -1.1051117068146072
69.0 -1.0454063529829403
70.0 -0.9822911009179278
71.0 -0.9159718194531575
72.0 -0.8466648283001538
73.0 -0.7745961924584436
74.0 -0.7000009848385109
75.0 -0.6231225195028295
76.0 -0.5442115580259622
77.0 -0.4635254915624214
78.0 -0.38132750129023146
79.0 -0.2978856999686188
80.0 -0.21347225740992787
81.0 -0.1283625127182606
82.0 -0.0428340761905449
83.0 0.04283407619054434
84.0 0.12836251271826005
85.0 0.2134722574099273
86.0 0.29788569996861824
87.0 0.38132750129022963
88.0 0.46352549156241957
89.0 0.5442115580259617
90.0 0.623122519502829
91.0 0.7000009848385104
92.0 0.774596192458442
93.0 0.8466648283001533
94.0 0.9159718194531571
95.0 0.9822911009179279
96.0 1.0454063529829398
97.0 1.1051117068146075
98.0 1.1612124159586232
99.0 1.2135254915624216
100.0 1.261880299246772
 
 
Dataset:9
0.0 1.0
1.0 0.9986295347545738
2.0 0.9945218953682733
3.0 0.9876883405951378
4.0 0.9781476007338057
5.0 0.9659258262890683
6.0 0.9510565162951535
7.0 0.9335804264972017
8.0 0.9135454576426009
9.0 0.8910065241883679
10.0 0.8660254037844387
11.0 0.838670567945424
12.0 0.8090169943749475
13.0 0.7771459614569709
14.0 0.7431448254773942
15.0 0.7071067811865476
16.0 0.6691306063588582
17.0 0.6293203910498375
18.0 0.5877852522924731
19.0 0.5446390350150272
20.0 0.5000000000000001
21.0 0.4539904997395468
22.0 0.4067366430758004
23.0 0.3583679495453004
24.0 0.30901699437494745
25.0 0.25881904510252074
26.0 0.20791169081775923
27.0 0.15643446504023092
28.0 0.10452846326765346
29.0 0.052335956242943744
30.0 2.8327492261615017E-16
31.0 -0.05233595624294362
32.0 -0.10452846326765333
33.0 -0.1564344650402308
34.0 -0.20791169081775934
35.0 -0.25881904510252063
36.0 -0.30901699437494734
37.0 -0.35836794954530027
38.0 -0.40673664307580004
39.0 -0.4539904997395467
40.0 -0.4999999999999998
41.0 -0.5446390350150268
42.0 -0.587785252292473
43.0 -0.6293203910498373
44.0 -0.6691306063588579
45.0 -0.7071067811865475
46.0 -0.743144825477394
47.0 -0.7771459614569709
48.0 -0.8090169943749473
49.0 -0.8386705679454239
50.0 -0.8660254037844387
51.0 -0.8910065241883678
52.0 -0.913545457642601
53.0 -0.9335804264972017
54.0 -0.9510565162951535
55.0 -0.9659258262890683
56.0 -0.9781476007338057
57.0 -0.9876883405951377
58.0 -0.9945218953682734
59.0 -0.9986295347545738
60.0 -1.0
61.0 -0.9986295347545738
62.0 -0.9945218953682734
63.0 -0.9876883405951378
64.0 -0.9781476007338057
65.0 -0.9659258262890684
66.0 -0.9510565162951536
67.0 -0.9335804264972019
68.0 -0.9135454576426009
69.0 -0.8910065241883679
70.0 -0.8660254037844388
71.0 -0.838670567945424
72.0 -0.8090169943749476
73.0 -0.777145961456971
74.0 -0.7431448254773942
75.0 -0.7071067811865477
76.0 -0.6691306063588585
77.0 -0.6293203910498378
78.0 -0.5877852522924732
79.0 -0.544639035015027
80.0 -0.5000000000000004
81.0 -0.4539904997395469
82.0 -0.4067366430758009
83.0 -0.3583679495452999
84.0 -0.30901699437494756
85.0 -0.25881904510252063
86.0 -0.2079116908177598
87.0 -0.15643446504023104
88.0 -0.10452846326765423
89.0 -0.052335956242943425
90.0 -1.836909530733566E-16
91.0 0.052335956242943946
92.0 0.10452846326765299
93.0 0.15643446504023067
94.0 0.20791169081775943
95.0 0.25881904510252113
96.0 0.30901699437494723
97.0 0.35836794954529955
98.0 0.40673664307579976
99.0 0.45399049973954664
 
Dataset:last but not least
0.0 0.5
1.0 0.4994161134161633
2.0 0.4976658173588243
3.0 0.49475319972552556
4.0 0.4906850630697067
5.0 0.485470908713026
6.0 0.4791229145545831
7.0 0.4716559066288715
8.0 0.4630873244788883
9.0 0.4534371804252727
10.0 0.44272801282660496
11.0 0.43098483344002464
12.0 0.41823506900511337
13.0 0.4045084971874737
14.0 0.3898371770316112
15.0 0.3742553740855506
16.0 0.35779948037206055
17.0 0.3405079293933985
18.0 0.3224211063680853
19.0 0.30358125390935564
20.0 0.28403237336557796
21.0 0.2638201220530664
22.0 0.2429917066213031
23.0 0.22159577279962067
24.0 0.19968229178284783
25.0 0.17730244352126778
26.0 0.15450849718747373
27.0 0.13135368909929354
28.0 0.10789209838390307
29.0 0.08417852067351932
30.0 0.060268340127661614
31.0 0.0362174000808812
32.0 0.012081872618066208
33.0 -0.012081872618066147
34.0 -0.03621740008088125
35.0 -0.06026834012766144
36.0 -0.08417852067351926
37.0 -0.10789209838390301
38.0 -0.13135368909929337
39.0 -0.15450849718747367
40.0 -0.17730244352126773
41.0 -0.19968229178284766
42.0 -0.22159577279962062
43.0 -0.24299170662130304
44.0 -0.26382012205306626
45.0 -0.28403237336557785
46.0 -0.3035812539093556
47.0 -0.32242110636808535
48.0 -0.3405079293933985
49.0 -0.3577994803720605
50.0 -0.3742553740855506
51.0 -0.38983717703161114
52.0 -0.40450849718747367
53.0 -0.41823506900511337
54.0 -0.43098483344002453
55.0 -0.4427280128266049
56.0 -0.4534371804252727
57.0 -0.4630873244788882
58.0 -0.4716559066288715
59.0 -0.4791229145545831
60.0 -0.48547090871302595
61.0 -0.4906850630697067
62.0 -0.49475319972552556
63.0 -0.4976658173588243
64.0 -0.49941611341616327
65.0 -0.5
66.0 -0.4994161134161633
67.0 -0.4976658173588243
68.0 -0.4947531997255255
69.0 -0.4906850630697067
70.0 -0.48547090871302606
71.0 -0.47912291455458306
72.0 -0.4716559066288716
73.0 -0.46308732447888834
74.0 -0.45343718042527276
75.0 -0.44272801282660496
76.0 -0.4309848334400247
77.0 -0.4182350690051134
78.0 -0.4045084971874738
79.0 -0.3898371770316112
80.0 -0.37425537408555065
81.0 -0.3577994803720606
82.0 -0.34050792939339874
83.0 -0.32242110636808513
84.0 -0.3035812539093557
85.0 -0.28403237336557796
86.0 -0.2638201220530664
87.0 -0.24299170662130334
88.0 -0.22159577279962092
89.0 -0.19968229178284758
90.0 -0.17730244352126795
91.0 -0.15450849718747378
92.0 -0.13135368909929349
93.0 -0.10789209838390346
94.0 -0.08417852067351916
95.0 -0.06026834012766134
96.0 -0.036217400080881375
97.0 -0.01208187261806627
98.0 0.012081872618066087
99.0 0.03621740008088119
100.0 0.0602683401276616
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/graph_via_function_and_string.html
0,0 → 1,84
<html>
<head></head>
<body>
Data are processed via normal (rawmath) funtions.<br>
This can become really slow if too many datapoints/functions are asked.<br>
The available params are:<p>
&lt;param name="background" value="hexcolor value"&gt;<br>
&lt;param name="foreground" value="hexcolor value"&gt;<br>
&lt;param name="dataurl" value="url"&gt;<br>
&lt;param name="height" value="integer"&gt;<br>
&lt;param name="width" value="integer"&gt;<br>
&lt;param name="function" value="String1,String2,String3..."&gt;<br>
&lt;param name="smooth" value="0/1""&gt;<br>
&lt;param name="names" value="names function1,name function2 ... or left blank "&gt;<br>
&lt;param name="xmin" value="minimum x-value or left blank for auto detection"&gt;<br>
&lt;param name="xmax" value="maximum x-value or left blank for auto detection"&gt;<br>
&lt;param name="ymin" value="minimum y-value or left blank for auto detection"&gt;<br>
&lt;param name="ymax" value="maximum y-value or left blank for auto detection"&gt;<br>
&lt;param name="xlog" value="x-axis is log-scale: 0 or 1: default 0"&gt;<br>
&lt;param name="ylog" value="y-axis is log-scale: 0 or 1: default 0"&gt;<br>
&lt;param name="color" value="0 or 1 :default 1"&gt;<br>
&lt;param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank "&gt;<br>
&lt;param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank "&gt;<br>
&lt;param name="xlabel" value="label of the x-axis: default x-axis"&gt;<br>
&lt;param name="ylabel" value="label of the y-axis: default y-axis" &gt;<br>
&lt;param name="title" value="title of the plot" &gt;<br>
&lt;param name="normalexponent" value="yes"&gt;<br>&lt;!-- if set 1.0&times;10<sup>3</sup> in stead of 1.0E3 --&gt;
 
A data string -in this case 10 curves- can be added to a set of -in this case 2- functions.
 
<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.PlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name="title" value="titel">
<param name="xlabel" value="x-as label">
<param name="ylabel" value="y-as label">
<param name="grid" value="on">
<param name="color" value="on">
<param name="xmin" value="-5">
<param name="xmax" value="5">
<param name="ymax" value="">
<param name="ylog" value="1">
<param name="xlog" value="1">
<param name="ymin" value="">
<param name="color" value="on">
<param name="smooth" value="0">
<param name="plotsteps" value="100">
<param name ="data" value="dataset:extra data through a string ; -5,25 ; -4,16 ; -3,9 ; -2,4 ; -1,1 ; 0,0 ; 1,1 ; 2,4 ; 3,9 ; 4,16 ; 5,25">
<param name="function" value="5*sin(x),5*cos(x)">
<param name="names" value="curve 1:sin(x),cos(x)">
<param name="normalexponent" value="yes">
</applet>
</body>
</html>
<!-- <dataset:pi;3.1428 0;3.1428 1">
<param name="function" value="tan(x),sin(x),cos(x),2*cos(x),cos(2*x),1/cos(x)">
<param name="names" value="curve 1:tan(x),curve 2: sin(x),curve 3:cos(x),2*cos(x),cos(2*x),1/cos(x)">
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0,one 1,two 2,pi 3.1428,four "jan 2008",five 5.... or left blank ">
<param name="ytics" value="thing1 0,thing2 1,thing3 2,three 3,four 4,five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/histogram_via_http_url.html
0,0 → 1,1155
<html>
<head></head>
<body>
Data processed via param "dataurl" (datafile)<p>
Using the "ptolemy.plot.HistogramApplet" from the Plot.jar
<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.HistogramApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "file" value="http://localhost/data.txt">
</applet>
<p>
 
A histogram plotter<br> The plot can be configured and data can
be provided either through a file with commands or through direct
invocation of the public methods of the class<br> To read a file or a
URL, use the read() method<br>
<p>
When calling the public methods, in most cases the changes will not
be visible until paint() has been called<br> To request that this
be done, call repaint()<br> One exception is addPoint(), which
makes the affect of the new point visible immediately (or nearly
immediately) if the plot is visible on the screen<br>
<p>
The ASCII format for the file file contains any number commands,
one per line<br> Unrecognized commands and commands with syntax
errors are ignored<br> Comments are denoted by a line starting with a
pound sign "#"<br> The recognized commands include those supported by
the base class, plus a few more<br> The commands are case
insensitive, but are usually capitalized<br> The number of data sets
to be plotted does not need to be specified<br> Data sets are added as needed<br>
Each dataset is identified with a color (see the base class)<br>
<P>
The appearance of the histogram can be altered by the following commands:
<pre>
Bars: <i>width</i>
Bars: <i>width, offset</i>
</pre>
The <i>width</i> is a real number specifying the width of the bars
as a fraction of the bin width<br> It usually has a value less than
or equal to one,
and defaults to 0<br>5<br> The <i>offset</i> is a real number
specifying how much the bar of the <i>i </i><sup>th</sup> data set
is offset from the previous one<br> This allows bars to "peek out"
from behind the ones in front<br> It defaults to 0<br>15<br>
Note that the frontmost data set will be the first one<br>
<p>
The width of each bin of the histogram can be specified using:
<pre>
BinWidth: <i>width</i>
</pre>
This is given in whatever units the data has<br>
By default, each bin is centered at <i>x</i> = <i>nw</i>,
where <i>w</i> is the width of the bin and <i>n</i> is an integer<br>
That bin represents values in the range (<i>x - w/2, x + w/2</i>)<br>
The alignment of the bins can be changed with the following command:
<pre>
BinOffset: <i>offset</i>
</pre>
If this method is used with argument <i>o</i>, then each bin is
centered at <i>x = nw + o</i>, and represents values in the range
(<i>x - w/2 + o, x + w/2 + o</i>)<br> So for example, if <i>o = w/2</i>,
then each bin represents values from <i>nw</i> to
(<i>n</i> + 1)<i>w</i> for some integer <i>n</i><br>
The default offset is 0<br>5, half the default bin width<br>
<p>
To specify data to be plotted, start a data set with the following command:
<pre>
DataSet: <i>string</i>
</pre>
Here, <i>string</i> is a label that will appear in the legend<br>
It is not necessary to enclose the string in quotation marks<br>
To start a new dataset without giving it a name, use:
<pre>
DataSet:
</pre>
In this case, no item will appear in the legend<br>
New datasets are plotted <i>behind</i> the previous ones<br>
The data itself is given by a sequence of numbers, one per line<br>
The numbers are specified as
strings that can be parsed by the Double parser in Java<br>
It is also possible to specify the numbers using all the formats
accepted by the Plot class, so that the same data may be plotted by
both classes<br> The <i>x</i> data is ignored, and only the <i>y</i>
data is used to calculate the histogram<br>
 
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->TitleText: Sample histogram
XLabel: values
YLabel: count
YRange: 0.0,100.0
BarGraph: 0.5,0.15
BinWidth: 1.0
BinOffset: 0.5
Color: on
NumSets: 10
 
Dataset: 1
0.0 5.0
1.0 4.938441702975688
2.0 4.755282581475768
3.0 4.455032620941839
4.0 4.045084971874737
5.0 3.5355339059327378
6.0 2.938926261462366
7.0 2.269952498697734
8.0 1.5450849718747373
9.0 0.7821723252011547
10.0 3.061515884555943E-16
11.0 -0.7821723252011529
12.0 -1.5450849718747368
13.0 -2.2699524986977337
14.0 -2.9389262614623655
15.0 -3.5355339059327373
16.0 -4.045084971874737
17.0 -4.455032620941839
18.0 -4.755282581475767
19.0 -4.938441702975688
20.0 -5.0
21.0 -4.938441702975688
22.0 -4.755282581475769
23.0 -4.455032620941839
24.0 -4.045084971874737
25.0 -3.535533905932738
26.0 -2.9389262614623664
27.0 -2.2699524986977346
28.0 -1.545084971874738
29.0 -0.7821723252011552
30.0 -9.18454765366783E-16
31.0 0.7821723252011534
32.0 1.5450849718747361
33.0 2.269952498697733
34.0 2.938926261462365
35.0 3.535533905932737
36.0 4.045084971874736
37.0 4.4550326209418385
38.0 4.755282581475767
39.0 4.938441702975688
40.0 5.0
41.0 4.938441702975689
42.0 4.755282581475768
43.0 4.45503262094184
44.0 4.045084971874741
45.0 3.5355339059327386
46.0 2.938926261462367
47.0 2.269952498697731
48.0 1.5450849718747386
49.0 0.7821723252011602
50.0 1.5307579422779716E-15
51.0 -0.7821723252011484
52.0 -1.5450849718747357
53.0 -2.2699524986977364
54.0 -2.938926261462364
55.0 -3.5355339059327395
56.0 -4.045084971874736
57.0 -4.455032620941837
58.0 -4.755282581475767
59.0 -4.9384417029756875
60.0 -5.0
61.0 -4.938441702975688
62.0 -4.755282581475768
63.0 -4.4550326209418385
64.0 -4.045084971874738
65.0 -3.535533905932742
66.0 -2.9389262614623672
67.0 -2.26995249869774
68.0 -1.545084971874739
69.0 -0.7821723252011521
70.0 -2.1430611191891602E-15
71.0 0.7821723252011565
72.0 1.545084971874735
73.0 2.269952498697728
74.0 2.9389262614623637
75.0 3.535533905932733
76.0 4.0450849718747355
77.0 4.45503262094184
78.0 4.755282581475767
79.0 4.938441702975689
80.0 5.0
81.0 4.938441702975689
82.0 4.755282581475772
83.0 4.4550326209418385
84.0 4.045084971874739
85.0 3.5355339059327364
86.0 2.9389262614623677
87.0 2.2699524986977404
88.0 1.5450849718747481
89.0 0.7821723252011527
90.0 2.755364296100349E-15
91.0 -0.7821723252011472
92.0 -1.5450849718747344
93.0 -2.2699524986977275
94.0 -2.9389262614623703
95.0 -3.5355339059327386
96.0 -4.0450849718747355
97.0 -4.455032620941836
98.0 -4.755282581475764
99.0 -4.938441702975688
100.0 -5.0
 
Dataset:2
0.0 4.5
1.0 4.46451615591515
2.0 4.35862422507884
3.0 4.183994186497132
4.0 3.943380060197386
5.0 3.6405764746872635
6.0 3.280358823396352
7.0 2.8684079538691036
8.0 2.4112205774054845
9.0 1.9160068120428269
10.0 1.3905764746872635
11.0 0.8432159156357613
12.0 0.28255733788191084
13.0 -0.2825573378819103
14.0 -0.8432159156357607
15.0 -1.3905764746872622
16.0 -1.9160068120428273
17.0 -2.411220577405486
18.0 -2.8684079538691036
19.0 -3.280358823396351
20.0 -3.640576474687263
21.0 -3.9433800601973865
22.0 -4.183994186497131
23.0 -4.35862422507884
24.0 -4.46451615591515
25.0 -4.5
26.0 -4.46451615591515
27.0 -4.35862422507884
28.0 -4.183994186497132
29.0 -3.943380060197386
30.0 -3.640576474687265
31.0 -3.280358823396353
32.0 -2.868407953869103
33.0 -2.4112205774054836
34.0 -1.9160068120428246
35.0 -1.3905764746872642
36.0 -0.8432159156357608
37.0 -0.2825573378819094
38.0 0.28255733788190773
39.0 0.8432159156357593
40.0 1.3905764746872626
41.0 1.9160068120428233
42.0 2.4112205774054853
43.0 2.868407953869102
44.0 3.2803588233963508
45.0 3.6405764746872626
46.0 3.9433800601973843
47.0 4.183994186497132
48.0 4.358624225078839
49.0 4.46451615591515
50.0 4.5
51.0 4.464516155915151
52.0 4.35862422507884
53.0 4.183994186497131
54.0 3.943380060197387
55.0 3.640576474687264
56.0 3.280358823396352
57.0 2.8684079538691063
58.0 2.411220577405484
59.0 1.9160068120428289
60.0 1.3905764746872684
61.0 0.8432159156357614
62.0 0.28255733788191395
63.0 -0.2825573378819112
64.0 -0.8432159156357626
65.0 -1.390576474687262
66.0 -1.91600681204283
67.0 -2.411220577405485
68.0 -2.8684079538691076
69.0 -3.280358823396353
70.0 -3.6405764746872626
71.0 -3.943380060197388
72.0 -4.183994186497132
73.0 -4.358624225078839
74.0 -4.464516155915151
75.0 -4.5
76.0 -4.464516155915151
77.0 -4.35862422507884
78.0 -4.183994186497133
79.0 -3.9433800601973856
80.0 -3.6405764746872644
81.0 -3.280358823396355
82.0 -2.86840795386911
83.0 -2.411220577405481
84.0 -1.9160068120428257
85.0 -1.390576474687265
86.0 -0.8432159156357658
87.0 -0.2825573378819185
88.0 0.2825573378819067
89.0 0.843215915635762
90.0 1.3905764746872615
91.0 1.9160068120428222
92.0 2.411220577405478
93.0 2.868407953869101
94.0 3.2803588233963525
95.0 3.640576474687262
96.0 3.9433800601973834
97.0 4.183994186497131
98.0 4.358624225078839
99.0 4.464516155915151
100.0 4.5
 
 
 
Dataset:3
0.0 4.0
1.0 3.978087581473093
2.0 3.9125904029352228
3.0 3.804226065180614
4.0 3.6541818305704035
5.0 3.464101615137755
6.0 3.23606797749979
7.0 2.972579301909577
8.0 2.676522425435433
9.0 2.3511410091698925
10.0 2.0000000000000004
11.0 1.6269465723032015
12.0 1.2360679774997898
13.0 0.8316467632710369
14.0 0.41811385307061383
15.0 1.1330996904646007E-15
16.0 -0.41811385307061333
17.0 -0.8316467632710374
18.0 -1.2360679774997894
19.0 -1.6269465723032002
20.0 -1.9999999999999991
21.0 -2.351141009169892
22.0 -2.6765224254354316
23.0 -2.972579301909576
24.0 -3.2360679774997894
25.0 -3.464101615137755
26.0 -3.654181830570404
27.0 -3.804226065180614
28.0 -3.9125904029352228
29.0 -3.9780875814730936
30.0 -4.0
31.0 -3.9780875814730936
32.0 -3.9125904029352228
33.0 -3.8042260651806146
34.0 -3.6541818305704035
35.0 -3.4641016151377553
36.0 -3.2360679774997902
37.0 -2.972579301909577
38.0 -2.676522425435434
39.0 -2.351141009169893
40.0 -2.0000000000000018
41.0 -1.6269465723032035
42.0 -1.2360679774997902
43.0 -0.8316467632710391
44.0 -0.41811385307061694
45.0 -7.347638122934264E-16
46.0 0.41811385307061194
47.0 0.8316467632710377
48.0 1.236067977499789
49.0 1.626946572303199
50.0 2.0000000000000004
51.0 2.3511410091698917
52.0 2.676522425435434
53.0 2.972579301909577
54.0 3.2360679774997894
55.0 3.4641016151377553
56.0 3.654181830570404
57.0 3.804226065180614
58.0 3.9125904029352228
59.0 3.978087581473093
60.0 4.0
61.0 3.9780875814730936
62.0 3.912590402935223
63.0 3.8042260651806146
64.0 3.6541818305704044
65.0 3.464101615137756
66.0 3.2360679774997902
67.0 2.9725793019095783
68.0 2.676522425435433
69.0 2.3511410091698934
70.0 2.000000000000002
71.0 1.6269465723032008
72.0 1.236067977499791
73.0 0.8316467632710397
74.0 0.4181138530706139
75.0 1.2246063538223773E-15
76.0 -0.4181138530706115
77.0 -0.8316467632710338
78.0 -1.2360679774997885
79.0 -1.6269465723032017
80.0 -1.999999999999997
81.0 -2.3511410091698917
82.0 -2.6765224254354285
83.0 -2.972579301909579
84.0 -3.236067977499789
85.0 -3.4641016151377553
86.0 -3.654181830570402
87.0 -3.8042260651806137
88.0 -3.9125904029352214
89.0 -3.9780875814730936
90.0 -4.0
91.0 -3.978087581473093
92.0 -3.912590402935223
93.0 -3.8042260651806146
94.0 -3.654181830570403
95.0 -3.464101615137753
96.0 -3.2360679774997907
97.0 -2.972579301909581
98.0 -2.6765224254354356
99.0 -2.351141009169894
100.0 -1.9999999999999993
 
 
Dataset:4
0.0 3.5
1.0 3.4859100289833367
2.0 3.4437535600952036
3.0 3.3738700124354866
4.0 3.2768220472390803
5.0 3.153391037658467
6.0 3.0045707776065314
7.0 2.831559480312316
8.0 2.6357501310126383
9.0 2.4187192714540267
10.0 2.1822143065055672
11.0 1.9281394350823593
12.0 1.6585403186554954
13.0 1.3755876107887328
14.0 1.081559480312316
15.0 0.7788232688471006
16.0 0.4698164303617944
17.0 0.15702690622680246
18.0 -0.15702690622680202
19.0 -0.46981643036179394
20.0 -0.7788232688471002
21.0 -1.0815594803123156
22.0 -1.3755876107887317
23.0 -1.658540318655495
24.0 -1.9281394350823586
25.0 -2.1822143065055672
26.0 -2.418719271454026
27.0 -2.635750131012638
28.0 -2.8315594803123156
29.0 -3.0045707776065314
30.0 -3.1533910376584666
31.0 -3.27682204723908
32.0 -3.3738700124354866
33.0 -3.4437535600952036
34.0 -3.4859100289833367
35.0 -3.5
36.0 -3.4859100289833367
37.0 -3.443753560095204
38.0 -3.3738700124354866
39.0 -3.2768220472390803
40.0 -3.153391037658467
41.0 -3.0045707776065327
42.0 -2.831559480312316
43.0 -2.6357501310126388
44.0 -2.418719271454028
45.0 -2.1822143065055677
46.0 -1.9281394350823593
47.0 -1.658540318655496
48.0 -1.3755876107887333
49.0 -1.0815594803123165
50.0 -0.778823268847101
51.0 -0.46981643036179477
52.0 -0.15702690622680288
53.0 0.1570269062268016
54.0 0.4698164303617935
55.0 0.7788232688470997
56.0 1.0815594803123154
57.0 1.375587610788732
58.0 1.6585403186554948
59.0 1.9281394350823582
60.0 2.182214306505567
61.0 2.4187192714540258
62.0 2.635750131012638
63.0 2.8315594803123156
64.0 3.004570777606531
65.0 3.1533910376584666
66.0 3.27682204723908
67.0 3.373870012435486
68.0 3.4437535600952036
69.0 3.4859100289833367
70.0 3.5
71.0 3.4859100289833367
72.0 3.443753560095204
73.0 3.3738700124354866
74.0 3.2768220472390808
75.0 3.1533910376584675
76.0 3.004570777606532
77.0 2.8315594803123165
78.0 2.6357501310126388
79.0 2.418719271454027
80.0 2.182214306505568
81.0 1.9281394350823597
82.0 1.658540318655499
83.0 1.3755876107887308
84.0 1.081559480312317
85.0 0.7788232688471014
86.0 0.4698164303617952
87.0 0.1570269062268064
88.0 -0.15702690622679805
89.0 -0.46981643036179616
90.0 -0.7788232688470993
91.0 -1.081559480312315
92.0 -1.3755876107887317
93.0 -1.6585403186554943
94.0 -1.928139435082358
95.0 -2.1822143065055664
96.0 -2.4187192714540253
97.0 -2.6357501310126374
98.0 -2.831559480312315
99.0 -3.004570777606531
100.0 -3.1533910376584666
 
Dataset:5
0.0 3.0
1.0 2.990752001199384
2.0 2.9630650217854133
3.0 2.91710976119303
4.0 2.853169548885461
5.0 2.7716385975338604
6.0 2.673019572565104
7.0 2.5579204930622765
8.0 2.4270509831248424
9.0 2.2812178968000927
10.0 2.121320343559643
11.0 1.9483441449905512
12.0 1.7633557568774194
13.0 1.5674956941478466
14.0 1.3619714992186405
15.0 1.1480502970952695
16.0 0.9270509831248425
17.0 0.7003360915677164
18.0 0.46930339512069275
19.0 0.235377287183535
20.0 1.836909530733566E-16
21.0 -0.23537728718353465
22.0 -0.46930339512069175
23.0 -0.700336091567716
24.0 -0.927050983124842
25.0 -1.148050297095269
26.0 -1.3619714992186402
27.0 -1.5674956941478464
28.0 -1.7633557568774192
29.0 -1.9483441449905508
30.0 -2.1213203435596424
31.0 -2.2812178968000927
32.0 -2.427050983124842
33.0 -2.5579204930622765
34.0 -2.6730195725651034
35.0 -2.77163859753386
36.0 -2.8531695488854605
37.0 -2.91710976119303
38.0 -2.9630650217854133
39.0 -2.990752001199384
40.0 -3.0
41.0 -2.9907520011993842
42.0 -2.9630650217854133
43.0 -2.91710976119303
44.0 -2.8531695488854614
45.0 -2.7716385975338604
46.0 -2.673019572565104
47.0 -2.557920493062276
48.0 -2.4270509831248424
49.0 -2.281217896800094
50.0 -2.121320343559643
51.0 -1.9483441449905523
52.0 -1.7633557568774199
53.0 -1.567495694147846
54.0 -1.361971499218641
55.0 -1.1480502970952686
56.0 -0.9270509831248428
57.0 -0.700336091567718
58.0 -0.46930339512069313
59.0 -0.2353772871835367
60.0 -5.510728592200698E-16
61.0 0.2353772871835356
62.0 0.469303395120692
63.0 0.7003360915677169
64.0 0.9270509831248417
65.0 1.1480502970952675
66.0 1.3619714992186398
67.0 1.5674956941478448
68.0 1.763355756877419
69.0 1.9483441449905514
70.0 2.121320343559642
71.0 2.281217896800093
72.0 2.427050983124842
73.0 2.5579204930622756
74.0 2.6730195725651034
75.0 2.7716385975338595
76.0 2.8531695488854605
77.0 2.91710976119303
78.0 2.963065021785413
79.0 2.990752001199384
80.0 3.0
81.0 2.9907520011993842
82.0 2.9630650217854138
83.0 2.91710976119303
84.0 2.853169548885461
85.0 2.77163859753386
86.0 2.673019572565104
87.0 2.557920493062278
88.0 2.427050983124844
89.0 2.2812178968000927
90.0 2.1213203435596433
91.0 1.9483441449905525
92.0 1.76335575687742
93.0 1.5674956941478484
94.0 1.3619714992186387
95.0 1.1480502970952688
96.0 0.9270509831248431
97.0 0.7003360915677184
98.0 0.46930339512069613
99.0 0.2353772871835344
100.0 9.18454765366783E-16
 
Dataset:6
1.0 2.4939101256495606
2.0 2.475670171853926
3.0 2.4453690018345142
4.0 2.4031542398457972
5.0 2.349231551964771
6.0 2.283863644106502
7.0 2.2073689821473175
8.0 2.120120240391065
9.0 2.0225424859373686
10.0 1.9151111077974452
11.0 1.798349500846628
12.0 1.6728265158971456
13.0 1.5391536883141457
14.0 1.397982258676867
15.0 1.2500000000000002
16.0 1.0959278669726935
17.0 0.9365164835397799
18.0 0.7725424859373686
19.0 0.6048047389991698
20.0 0.4341204441673261
21.0 0.26132115816913365
22.0 0.0872487417562527
23.0 -0.08724874175625184
24.0 -0.2613211581691333
25.0 -0.43412044416732576
26.0 -0.6048047389991694
27.0 -0.7725424859373684
28.0 -0.9365164835397801
29.0 -1.0959278669726937
30.0 -1.2499999999999996
31.0 -1.3979822586768669
32.0 -1.5391536883141457
33.0 -1.6728265158971456
34.0 -1.7983495008466281
35.0 -1.9151111077974448
36.0 -2.0225424859373686
37.0 -2.120120240391065
38.0 -2.207368982147317
39.0 -2.283863644106502
40.0 -2.349231551964771
41.0 -2.403154239845797
42.0 -2.4453690018345142
43.0 -2.475670171853926
44.0 -2.4939101256495606
45.0 -2.5
46.0 -2.4939101256495606
47.0 -2.475670171853926
48.0 -2.4453690018345142
49.0 -2.4031542398457972
50.0 -2.349231551964771
51.0 -2.2838636441065026
52.0 -2.207368982147317
53.0 -2.1201202403910653
54.0 -2.0225424859373686
55.0 -1.9151111077974452
56.0 -1.7983495008466277
57.0 -1.672826515897146
58.0 -1.5391536883141452
59.0 -1.3979822586768682
60.0 -1.2500000000000009
61.0 -1.0959278669726944
62.0 -0.9365164835397807
63.0 -0.772542485937369
64.0 -0.6048047389991695
65.0 -0.4341204441673258
66.0 -0.26132115816913337
67.0 -0.08724874175625412
68.0 0.0872487417562532
69.0 0.2613211581691325
70.0 0.4341204441673249
71.0 0.6048047389991686
72.0 0.7725424859373681
73.0 0.9365164835397799
74.0 1.0959278669726935
75.0 1.2500000000000002
76.0 1.3979822586768655
77.0 1.5391536883141463
78.0 1.6728265158971445
79.0 1.798349500846627
80.0 1.9151111077974445
81.0 2.022542485937368
82.0 2.1201202403910635
83.0 2.2073689821473175
84.0 2.283863644106502
85.0 2.3492315519647713
86.0 2.403154239845797
87.0 2.445369001834514
88.0 2.475670171853926
89.0 2.4939101256495606
90.0 2.5
91.0 2.4939101256495606
92.0 2.4756701718539262
93.0 2.4453690018345147
94.0 2.4031542398457972
95.0 2.349231551964771
96.0 2.283863644106503
97.0 2.207368982147318
98.0 2.1201202403910653
99.0 2.0225424859373677
100.0 1.9151111077974454
 
Dataset:7
0.0 2.0
1.0 1.9960534568565431
2.0 1.9842294026289558
3.0 1.9645745014573774
4.0 1.9371663222572622
5.0 1.902113032590307
6.0 1.859552971776503
7.0 1.8096541049320392
8.0 1.7526133600877272
9.0 1.6886558510040302
10.0 1.618033988749895
11.0 1.5410264855515785
12.0 1.457937254842823
13.0 1.3690942118573772
14.0 1.2748479794973795
15.0 1.1755705045849465
16.0 1.071653589957993
17.0 0.9635073482034303
18.0 0.8515585831301453
19.0 0.7362491053693562
20.0 0.6180339887498949
21.0 0.4973797743297095
22.0 0.3747626291714495
23.0 0.25066646712860896
24.0 0.12558103905862705
25.0 1.2246063538223773E-16
26.0 -0.1255810390586268
27.0 -0.2506664671286083
28.0 -0.3747626291714492
29.0 -0.4973797743297097
30.0 -0.6180339887498942
31.0 -0.7362491053693555
32.0 -0.8515585831301454
33.0 -0.9635073482034309
34.0 -1.0716535899579938
35.0 -1.175570504584946
36.0 -1.2748479794973795
37.0 -1.3690942118573775
38.0 -1.4579372548428227
39.0 -1.5410264855515783
40.0 -1.6180339887498947
41.0 -1.6886558510040297
42.0 -1.7526133600877272
43.0 -1.8096541049320387
44.0 -1.8595529717765027
45.0 -1.902113032590307
46.0 -1.937166322257262
47.0 -1.9645745014573774
48.0 -1.9842294026289555
49.0 -1.9960534568565431
50.0 -2.0
51.0 -1.9960534568565431
52.0 -1.9842294026289558
53.0 -1.9645745014573772
54.0 -1.9371663222572624
55.0 -1.9021130325903073
56.0 -1.859552971776503
57.0 -1.8096541049320394
58.0 -1.752613360087727
59.0 -1.6886558510040304
60.0 -1.6180339887498956
61.0 -1.5410264855515785
62.0 -1.4579372548428235
63.0 -1.3690942118573772
64.0 -1.274847979497379
65.0 -1.1755705045849465
66.0 -1.0716535899579926
67.0 -0.9635073482034305
68.0 -0.8515585831301443
69.0 -0.7362491053693556
70.0 -0.6180339887498951
71.0 -0.49737977432970887
72.0 -0.37476262917144926
73.0 -0.2506664671286092
74.0 -0.12558103905862641
75.0 -3.673819061467132E-16
76.0 0.12558103905862567
77.0 0.25066646712860846
78.0 0.37476262917144854
79.0 0.49737977432970987
80.0 0.6180339887498945
81.0 0.7362491053693548
82.0 0.8515585831301437
83.0 0.9635073482034314
84.0 1.0716535899579935
85.0 1.1755705045849458
86.0 1.2748479794973786
87.0 1.369094211857376
88.0 1.4579372548428224
89.0 1.5410264855515787
90.0 1.6180339887498947
91.0 1.6886558510040295
92.0 1.7526133600877263
93.0 1.8096541049320387
94.0 1.859552971776503
95.0 1.902113032590307
96.0 1.937166322257262
97.0 1.9645745014573774
98.0 1.9842294026289555
99.0 1.9960534568565431
100.0 2.0
 
 
Dataset:8
0.0 1.5
1.0 1.4975536558892035
2.0 1.4902226030228254
3.0 1.4780307537715396
4.0 1.4610178754135004
5.0 1.439239460421746
6.0 1.412766545459287
7.0 1.3816854796722753
8.0 1.3460976430370377
9.0 1.3061191156796659
10.0 1.2618802992467717
11.0 1.2135254915624212
12.0 1.1612124159586237
13.0 1.1051117068146072
14.0 1.0454063529829403
15.0 0.9822911009179277
16.0 0.9159718194531573
17.0 0.8466648283001538
18.0 0.7745961924584429
19.0 0.7000009848385107
20.0 0.6231225195028297
21.0 0.5442115580259614
22.0 0.4635254915624215
23.0 0.38132750129023063
24.0 0.2978856999686183
25.0 0.21347225740992767
26.0 0.12836251271825944
27.0 0.04283407619054471
28.0 -0.0428340761905442
29.0 -0.12836251271825957
30.0 -0.21347225740992748
31.0 -0.29788569996861813
32.0 -0.38132750129023013
33.0 -0.463525491562421
34.0 -0.5442115580259616
35.0 -0.6231225195028295
36.0 -0.7000009848385106
37.0 -0.7745961924584427
38.0 -0.8466648283001534
39.0 -0.9159718194531568
40.0 -0.9822911009179276
41.0 -1.04540635298294
42.0 -1.1051117068146075
43.0 -1.1612124159586237
44.0 -1.2135254915624207
45.0 -1.2618802992467715
46.0 -1.3061191156796654
47.0 -1.3460976430370375
48.0 -1.381685479672275
49.0 -1.4127665454592868
50.0 -1.439239460421746
51.0 -1.4610178754135001
52.0 -1.4780307537715396
53.0 -1.4902226030228254
54.0 -1.4975536558892035
55.0 -1.5
56.0 -1.4975536558892035
57.0 -1.4902226030228254
58.0 -1.4780307537715396
59.0 -1.4610178754135004
60.0 -1.4392394604217462
61.0 -1.412766545459287
62.0 -1.3816854796722753
63.0 -1.3460976430370375
64.0 -1.306119115679666
65.0 -1.2618802992467721
66.0 -1.2135254915624212
67.0 -1.161212415958624
68.0 -1.1051117068146072
69.0 -1.0454063529829403
70.0 -0.9822911009179278
71.0 -0.9159718194531575
72.0 -0.8466648283001538
73.0 -0.7745961924584436
74.0 -0.7000009848385109
75.0 -0.6231225195028295
76.0 -0.5442115580259622
77.0 -0.4635254915624214
78.0 -0.38132750129023146
79.0 -0.2978856999686188
80.0 -0.21347225740992787
81.0 -0.1283625127182606
82.0 -0.0428340761905449
83.0 0.04283407619054434
84.0 0.12836251271826005
85.0 0.2134722574099273
86.0 0.29788569996861824
87.0 0.38132750129022963
88.0 0.46352549156241957
89.0 0.5442115580259617
90.0 0.623122519502829
91.0 0.7000009848385104
92.0 0.774596192458442
93.0 0.8466648283001533
94.0 0.9159718194531571
95.0 0.9822911009179279
96.0 1.0454063529829398
97.0 1.1051117068146075
98.0 1.1612124159586232
99.0 1.2135254915624216
100.0 1.261880299246772
 
 
Dataset:9
0.0 1.0
1.0 0.9986295347545738
2.0 0.9945218953682733
3.0 0.9876883405951378
4.0 0.9781476007338057
5.0 0.9659258262890683
6.0 0.9510565162951535
7.0 0.9335804264972017
8.0 0.9135454576426009
9.0 0.8910065241883679
10.0 0.8660254037844387
11.0 0.838670567945424
12.0 0.8090169943749475
13.0 0.7771459614569709
14.0 0.7431448254773942
15.0 0.7071067811865476
16.0 0.6691306063588582
17.0 0.6293203910498375
18.0 0.5877852522924731
19.0 0.5446390350150272
20.0 0.5000000000000001
21.0 0.4539904997395468
22.0 0.4067366430758004
23.0 0.3583679495453004
24.0 0.30901699437494745
25.0 0.25881904510252074
26.0 0.20791169081775923
27.0 0.15643446504023092
28.0 0.10452846326765346
29.0 0.052335956242943744
30.0 2.8327492261615017E-16
31.0 -0.05233595624294362
32.0 -0.10452846326765333
33.0 -0.1564344650402308
34.0 -0.20791169081775934
35.0 -0.25881904510252063
36.0 -0.30901699437494734
37.0 -0.35836794954530027
38.0 -0.40673664307580004
39.0 -0.4539904997395467
40.0 -0.4999999999999998
41.0 -0.5446390350150268
42.0 -0.587785252292473
43.0 -0.6293203910498373
44.0 -0.6691306063588579
45.0 -0.7071067811865475
46.0 -0.743144825477394
47.0 -0.7771459614569709
48.0 -0.8090169943749473
49.0 -0.8386705679454239
50.0 -0.8660254037844387
51.0 -0.8910065241883678
52.0 -0.913545457642601
53.0 -0.9335804264972017
54.0 -0.9510565162951535
55.0 -0.9659258262890683
56.0 -0.9781476007338057
57.0 -0.9876883405951377
58.0 -0.9945218953682734
59.0 -0.9986295347545738
60.0 -1.0
61.0 -0.9986295347545738
62.0 -0.9945218953682734
63.0 -0.9876883405951378
64.0 -0.9781476007338057
65.0 -0.9659258262890684
66.0 -0.9510565162951536
67.0 -0.9335804264972019
68.0 -0.9135454576426009
69.0 -0.8910065241883679
70.0 -0.8660254037844388
71.0 -0.838670567945424
72.0 -0.8090169943749476
73.0 -0.777145961456971
74.0 -0.7431448254773942
75.0 -0.7071067811865477
76.0 -0.6691306063588585
77.0 -0.6293203910498378
78.0 -0.5877852522924732
79.0 -0.544639035015027
80.0 -0.5000000000000004
81.0 -0.4539904997395469
82.0 -0.4067366430758009
83.0 -0.3583679495452999
84.0 -0.30901699437494756
85.0 -0.25881904510252063
86.0 -0.2079116908177598
87.0 -0.15643446504023104
88.0 -0.10452846326765423
89.0 -0.052335956242943425
90.0 -1.836909530733566E-16
91.0 0.052335956242943946
92.0 0.10452846326765299
93.0 0.15643446504023067
94.0 0.20791169081775943
95.0 0.25881904510252113
96.0 0.30901699437494723
97.0 0.35836794954529955
98.0 0.40673664307579976
99.0 0.45399049973954664
 
Dataset:last but not least
0.0 0.5
1.0 0.4994161134161633
2.0 0.4976658173588243
3.0 0.49475319972552556
4.0 0.4906850630697067
5.0 0.485470908713026
6.0 0.4791229145545831
7.0 0.4716559066288715
8.0 0.4630873244788883
9.0 0.4534371804252727
10.0 0.44272801282660496
11.0 0.43098483344002464
12.0 0.41823506900511337
13.0 0.4045084971874737
14.0 0.3898371770316112
15.0 0.3742553740855506
16.0 0.35779948037206055
17.0 0.3405079293933985
18.0 0.3224211063680853
19.0 0.30358125390935564
20.0 0.28403237336557796
21.0 0.2638201220530664
22.0 0.2429917066213031
23.0 0.22159577279962067
24.0 0.19968229178284783
25.0 0.17730244352126778
26.0 0.15450849718747373
27.0 0.13135368909929354
28.0 0.10789209838390307
29.0 0.08417852067351932
30.0 0.060268340127661614
31.0 0.0362174000808812
32.0 0.012081872618066208
33.0 -0.012081872618066147
34.0 -0.03621740008088125
35.0 -0.06026834012766144
36.0 -0.08417852067351926
37.0 -0.10789209838390301
38.0 -0.13135368909929337
39.0 -0.15450849718747367
40.0 -0.17730244352126773
41.0 -0.19968229178284766
42.0 -0.22159577279962062
43.0 -0.24299170662130304
44.0 -0.26382012205306626
45.0 -0.28403237336557785
46.0 -0.3035812539093556
47.0 -0.32242110636808535
48.0 -0.3405079293933985
49.0 -0.3577994803720605
50.0 -0.3742553740855506
51.0 -0.38983717703161114
52.0 -0.40450849718747367
53.0 -0.41823506900511337
54.0 -0.43098483344002453
55.0 -0.4427280128266049
56.0 -0.4534371804252727
57.0 -0.4630873244788882
58.0 -0.4716559066288715
59.0 -0.4791229145545831
60.0 -0.48547090871302595
61.0 -0.4906850630697067
62.0 -0.49475319972552556
63.0 -0.4976658173588243
64.0 -0.49941611341616327
65.0 -0.5
66.0 -0.4994161134161633
67.0 -0.4976658173588243
68.0 -0.4947531997255255
69.0 -0.4906850630697067
70.0 -0.48547090871302606
71.0 -0.47912291455458306
72.0 -0.4716559066288716
73.0 -0.46308732447888834
74.0 -0.45343718042527276
75.0 -0.44272801282660496
76.0 -0.4309848334400247
77.0 -0.4182350690051134
78.0 -0.4045084971874738
79.0 -0.3898371770316112
80.0 -0.37425537408555065
81.0 -0.3577994803720606
82.0 -0.34050792939339874
83.0 -0.32242110636808513
84.0 -0.3035812539093557
85.0 -0.28403237336557796
86.0 -0.2638201220530664
87.0 -0.24299170662130334
88.0 -0.22159577279962092
89.0 -0.19968229178284758
90.0 -0.17730244352126795
91.0 -0.15450849718747378
92.0 -0.13135368909929349
93.0 -0.10789209838390346
94.0 -0.08417852067351916
95.0 -0.06026834012766134
96.0 -0.036217400080881375
97.0 -0.01208187261806627
98.0 0.012081872618066087
99.0 0.03621740008088119
100.0 0.0602683401276616
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/histogram.data.txt
0,0 → 1,630
TitleText: Histogram from datafile
XLabel: values
YLabel: count
YRange: 0.0,100.0
BarGraph: 0.5,0.15
BinWidth: 1.0
BinOffset: 0.5
dataset: first
1
5.0
4.938441702975688
4.755282581475768
4.455032620941839
4.045084971874737
3.5355339059327378
2.938926261462366
2.269952498697734
1.5450849718747373
0.7821723252011547
3.061515884555943E-16
-0.7821723252011529
-1.5450849718747368
-2.2699524986977337
-2.9389262614623655
-3.5355339059327373
-4.045084971874737
-4.455032620941839
-4.755282581475767
-4.938441702975688
-5.0
-4.938441702975688
-4.755282581475769
-4.455032620941839
-4.045084971874737
-3.535533905932738
-2.9389262614623664
-2.2699524986977346
-1.545084971874738
-0.7821723252011552
-9.18454765366783E-16
0.7821723252011534
1.5450849718747361
2.269952498697733
2.938926261462365
3.535533905932737
4.045084971874736
4.4550326209418385
4.755282581475767
4.938441702975688
5.0
4.938441702975689
4.755282581475768
4.45503262094184
4.045084971874741
3.5355339059327386
2.938926261462367
2.269952498697731
1.5450849718747386
0.7821723252011602
1.5307579422779716E-15
-0.7821723252011484
-1.5450849718747357
-2.2699524986977364
-2.938926261462364
-3.5355339059327395
-4.045084971874736
-4.455032620941837
-4.755282581475767
-4.9384417029756875
-5.0
-4.938441702975688
-4.755282581475768
-4.4550326209418385
-4.045084971874738
-3.535533905932742
-2.9389262614623672
-2.26995249869774
-1.545084971874739
-0.7821723252011521
-2.1430611191891602E-15
0.7821723252011565
1.545084971874735
2.269952498697728
2.9389262614623637
3.535533905932733
4.0450849718747355
4.45503262094184
4.755282581475767
4.938441702975689
5.0
4.938441702975689
4.755282581475772
4.4550326209418385
4.045084971874739
3.5355339059327364
2.9389262614623677
2.2699524986977404
1.5450849718747481
0.7821723252011527
2.755364296100349E-15
-0.7821723252011472
-1.5450849718747344
-2.2699524986977275
-2.9389262614623703
-3.5355339059327386
-4.0450849718747355
-4.455032620941836
-4.755282581475764
-4.938441702975688
-5.0
 
dataset: second
4.5
4.46451615591515
4.35862422507884
4.183994186497132
3.943380060197386
3.6405764746872635
3.280358823396352
2.8684079538691036
2.4112205774054845
1.9160068120428269
1.3905764746872635
0.8432159156357613
0.28255733788191084
-0.2825573378819103
-0.8432159156357607
-1.3905764746872622
-1.9160068120428273
-2.411220577405486
-2.8684079538691036
-3.280358823396351
-3.640576474687263
-3.9433800601973865
-4.183994186497131
-4.35862422507884
-4.46451615591515
-4.5
-4.46451615591515
-4.35862422507884
-4.183994186497132
-3.943380060197386
-3.640576474687265
-3.280358823396353
-2.868407953869103
-2.4112205774054836
-1.9160068120428246
-1.3905764746872642
-0.8432159156357608
-0.2825573378819094
0.28255733788190773
0.8432159156357593
1.3905764746872626
1.9160068120428233
2.4112205774054853
2.868407953869102
3.2803588233963508
3.6405764746872626
3.9433800601973843
4.183994186497132
4.358624225078839
4.46451615591515
4.5
4.464516155915151
4.35862422507884
4.183994186497131
3.943380060197387
3.640576474687264
3.280358823396352
2.8684079538691063
2.411220577405484
1.9160068120428289
1.3905764746872684
0.8432159156357614
0.28255733788191395
-0.2825573378819112
-0.8432159156357626
-1.390576474687262
-1.91600681204283
-2.411220577405485
-2.8684079538691076
-3.280358823396353
-3.6405764746872626
-3.943380060197388
-4.183994186497132
-4.358624225078839
-4.464516155915151
-4.5
-4.464516155915151
-4.35862422507884
-4.183994186497133
-3.9433800601973856
-3.6405764746872644
-3.280358823396355
-2.86840795386911
-2.411220577405481
-1.9160068120428257
-1.390576474687265
-0.8432159156357658
-0.2825573378819185
0.2825573378819067
0.843215915635762
1.3905764746872615
1.9160068120428222
2.411220577405478
2.868407953869101
3.2803588233963525
3.640576474687262
3.9433800601973834
4.183994186497131
4.358624225078839
4.464516155915151
4.5
 
 
 
dataset: third
 
4.0
3.978087581473093
3.9125904029352228
3.804226065180614
3.6541818305704035
3.464101615137755
3.23606797749979
2.972579301909577
2.676522425435433
2.3511410091698925
2.0000000000000004
1.6269465723032015
1.2360679774997898
0.8316467632710369
0.41811385307061383
1.1330996904646007E-15
-0.41811385307061333
-0.8316467632710374
-1.2360679774997894
-1.6269465723032002
-1.9999999999999991
-2.351141009169892
-2.6765224254354316
-2.972579301909576
-3.2360679774997894
-3.464101615137755
-3.654181830570404
-3.804226065180614
-3.9125904029352228
-3.9780875814730936
-4.0
-3.9780875814730936
-3.9125904029352228
-3.8042260651806146
-3.6541818305704035
-3.4641016151377553
-3.2360679774997902
-2.972579301909577
-2.676522425435434
-2.351141009169893
-2.0000000000000018
-1.6269465723032035
-1.2360679774997902
-0.8316467632710391
-0.41811385307061694
-7.347638122934264E-16
0.41811385307061194
0.8316467632710377
1.236067977499789
1.626946572303199
2.0000000000000004
2.3511410091698917
2.676522425435434
2.972579301909577
3.2360679774997894
3.4641016151377553
3.654181830570404
3.804226065180614
3.9125904029352228
3.978087581473093
4.0
3.9780875814730936
3.912590402935223
3.8042260651806146
3.6541818305704044
3.464101615137756
3.2360679774997902
2.9725793019095783
2.676522425435433
2.3511410091698934
2.000000000000002
1.6269465723032008
1.236067977499791
0.8316467632710397
0.4181138530706139
1.2246063538223773E-15
-0.4181138530706115
-0.8316467632710338
-1.2360679774997885
-1.6269465723032017
-1.999999999999997
-2.3511410091698917
-2.6765224254354285
-2.972579301909579
-3.236067977499789
-3.4641016151377553
-3.654181830570402
-3.8042260651806137
-3.9125904029352214
-3.9780875814730936
-4.0
-3.978087581473093
-3.912590402935223
-3.8042260651806146
-3.654181830570403
-3.464101615137753
-3.2360679774997907
-2.972579301909581
-2.6765224254354356
-2.351141009169894
-1.9999999999999993
 
 
 
dataset: forth
3.5
3.4859100289833367
3.4437535600952036
3.3738700124354866
3.2768220472390803
3.153391037658467
3.0045707776065314
2.831559480312316
2.6357501310126383
2.4187192714540267
2.1822143065055672
1.9281394350823593
1.6585403186554954
1.3755876107887328
1.081559480312316
0.7788232688471006
0.4698164303617944
0.15702690622680246
-0.15702690622680202
-0.46981643036179394
-0.7788232688471002
-1.0815594803123156
-1.3755876107887317
-1.658540318655495
-1.9281394350823586
-2.1822143065055672
-2.418719271454026
-2.635750131012638
-2.8315594803123156
-3.0045707776065314
-3.1533910376584666
-3.27682204723908
-3.3738700124354866
-3.4437535600952036
-3.4859100289833367
-3.5
-3.4859100289833367
-3.443753560095204
-3.3738700124354866
-3.2768220472390803
-3.153391037658467
-3.0045707776065327
-2.831559480312316
-2.6357501310126388
-2.418719271454028
-2.1822143065055677
-1.9281394350823593
-1.658540318655496
-1.3755876107887333
-1.0815594803123165
-0.778823268847101
-0.46981643036179477
-0.15702690622680288
0.1570269062268016
0.4698164303617935
0.7788232688470997
1.0815594803123154
1.375587610788732
1.6585403186554948
1.9281394350823582
2.182214306505567
2.4187192714540258
2.635750131012638
2.8315594803123156
3.004570777606531
3.1533910376584666
3.27682204723908
3.373870012435486
3.4437535600952036
3.4859100289833367
3.5
3.4859100289833367
3.443753560095204
3.3738700124354866
3.2768220472390808
3.1533910376584675
3.004570777606532
2.8315594803123165
2.6357501310126388
2.418719271454027
2.182214306505568
1.9281394350823597
1.658540318655499
1.3755876107887308
1.081559480312317
0.7788232688471014
0.4698164303617952
0.1570269062268064
-0.15702690622679805
-0.46981643036179616
-0.7788232688470993
-1.081559480312315
-1.3755876107887317
-1.6585403186554943
-1.928139435082358
-2.1822143065055664
-2.4187192714540253
-2.6357501310126374
-2.831559480312315
-3.004570777606531
-3.1533910376584666
 
dataset: fifth
 
3.0
2.990752001199384
2.9630650217854133
2.91710976119303
2.853169548885461
2.7716385975338604
2.673019572565104
2.5579204930622765
2.4270509831248424
2.2812178968000927
2.121320343559643
1.9483441449905512
1.7633557568774194
1.5674956941478466
1.3619714992186405
1.1480502970952695
0.9270509831248425
0.7003360915677164
0.46930339512069275
0.235377287183535
1.836909530733566E-16
-0.23537728718353465
-0.46930339512069175
-0.700336091567716
-0.927050983124842
-1.148050297095269
-1.3619714992186402
-1.5674956941478464
-1.7633557568774192
-1.9483441449905508
-2.1213203435596424
-2.2812178968000927
-2.427050983124842
-2.5579204930622765
-2.6730195725651034
-2.77163859753386
-2.8531695488854605
-2.91710976119303
-2.9630650217854133
-2.990752001199384
-3.0
-2.9907520011993842
-2.9630650217854133
-2.91710976119303
-2.8531695488854614
-2.7716385975338604
-2.673019572565104
-2.557920493062276
-2.4270509831248424
-2.281217896800094
-2.121320343559643
-1.9483441449905523
-1.7633557568774199
-1.567495694147846
-1.361971499218641
-1.1480502970952686
-0.9270509831248428
-0.700336091567718
-0.46930339512069313
-0.2353772871835367
-5.510728592200698E-16
0.2353772871835356
0.469303395120692
0.7003360915677169
0.9270509831248417
1.1480502970952675
1.3619714992186398
1.5674956941478448
1.763355756877419
1.9483441449905514
2.121320343559642
2.281217896800093
2.427050983124842
2.5579204930622756
2.6730195725651034
2.7716385975338595
2.8531695488854605
2.91710976119303
2.963065021785413
2.990752001199384
3.0
2.9907520011993842
2.9630650217854138
2.91710976119303
2.853169548885461
2.77163859753386
2.673019572565104
2.557920493062278
2.427050983124844
2.2812178968000927
2.1213203435596433
1.9483441449905525
1.76335575687742
1.5674956941478484
1.3619714992186387
1.1480502970952688
0.9270509831248431
0.7003360915677184
0.46930339512069613
0.2353772871835344
9.18454765366783E-16
 
dataset:ninth
2.4939101256495606
2.475670171853926
2.4453690018345142
2.4031542398457972
2.349231551964771
2.283863644106502
2.2073689821473175
2.120120240391065
2.0225424859373686
1.9151111077974452
1.798349500846628
1.6728265158971456
1.5391536883141457
1.397982258676867
1.2500000000000002
1.0959278669726935
0.9365164835397799
0.7725424859373686
0.6048047389991698
0.4341204441673261
0.26132115816913365
0.0872487417562527
-0.08724874175625184
-0.2613211581691333
-0.43412044416732576
-0.6048047389991694
-0.7725424859373684
-0.9365164835397801
-1.0959278669726937
-1.2499999999999996
-1.3979822586768669
-1.5391536883141457
-1.6728265158971456
-1.7983495008466281
-1.9151111077974448
-2.0225424859373686
-2.120120240391065
-2.207368982147317
-2.283863644106502
-2.349231551964771
-2.403154239845797
-2.4453690018345142
-2.475670171853926
-2.4939101256495606
-2.5
-2.4939101256495606
-2.475670171853926
-2.4453690018345142
-2.4031542398457972
-2.349231551964771
-2.2838636441065026
-2.207368982147317
-2.1201202403910653
-2.0225424859373686
-1.9151111077974452
-1.7983495008466277
-1.672826515897146
-1.5391536883141452
-1.3979822586768682
-1.2500000000000009
-1.0959278669726944
-0.9365164835397807
-0.772542485937369
-0.6048047389991695
-0.4341204441673258
-0.26132115816913337
-0.08724874175625412
0.0872487417562532
0.2613211581691325
0.4341204441673249
0.6048047389991686
0.7725424859373681
0.9365164835397799
1.0959278669726935
1.2500000000000002
1.3979822586768655
1.5391536883141463
1.6728265158971445
1.798349500846627
1.9151111077974445
2.022542485937368
2.1201202403910635
2.2073689821473175
2.283863644106502
2.3492315519647713
2.403154239845797
2.445369001834514
2.475670171853926
2.4939101256495606
2.5
2.4939101256495606
2.4756701718539262
2.4453690018345147
2.4031542398457972
2.349231551964771
2.283863644106503
2.207368982147318
2.1201202403910653
2.0225424859373677
1.9151111077974454
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/editablegraph_via_functions.html
0,0 → 1,74
<html>
<head></head>
<body>
Data are processed via normal (rawmath) funtions.<br>
This can become really slow if too many datapoints/functions are asked.<br>
The available params are:<p>
&lt;param name="background" value="hexcolor value"&gt;<br>
&lt;param name="foreground" value="hexcolor value"&gt;<br>
&lt;param name="dataurl" value="url"&gt;<br>
&lt;param name="height" value="integer"&gt;<br>
&lt;param name="width" value="integer"&gt;<br>
&lt;param name="function" value="String1,String2,String3..."&gt;<br>
&lt;param name="smooth" value="0/1""&gt;<br>
&lt;param name="names" value="names function1,name function2 ... or left blank "&gt;<br>
&lt;param name="xmin" value="minimum x-value or left blank for auto detection"&gt;<br>
&lt;param name="xmax" value="maximum x-value or left blank for auto detection"&gt;<br>
&lt;param name="ymin" value="minimum y-value or left blank for auto detection"&gt;<br>
&lt;param name="ymax" value="maximum y-value or left blank for auto detection"&gt;<br>
&lt;param name="xlog" value="x-axis is log-scale: 0 or 1: default 0"&gt;<br>
&lt;param name="ylog" value="y-axis is log-scale: 0 or 1: default 0"&gt;<br>
&lt;param name="color" value="0 or 1 :default 1"&gt;<br>
&lt;param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank "&gt;<br>
&lt;param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank "&gt;<br>
&lt;param name="xlabel" value="label of the x-axis: default x-axis"&gt;<br>
&lt;param name="ylabel" value="label of the y-axis: default y-axis" &gt;<br>
&lt;param name="title" value="title of the plot" &gt;<br>
<p>
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.EditablePlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name="title" value="titel htmlsyntax: &amp; pi ... &pi;">
<param name="xlabel" value="x-as label">
<param name="ylabel" value="y-as label">
<param name="grid" value="on">
<param name="color" value="on">
<param name="xmin" value="0">
<param name="xmax" value="6">
<param name="ymax" value="5">
<param name="ymin" value="-5">
<param name="color" value="on">
<param name="smooth" value="0">
<param name="function" value="tan(x),sin(x),cos(x),2*cos(x),cos(2*x),1/cos(x)">
<param name="names" value="curve 1:tan(x),curve 2: sin(x),curve 3:cos(x),2*cos(x),cos(2*x),1/cos(x)">
<param name="plotsteps" value="100">
</applet>
</body>
</html>
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="color" value="0 or 1 :default 1">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/examples/histogram_via_string.html
0,0 → 1,116
<html>
<head></head>
<body>
Data processed via param "data". In this case the histogram is calulated from 9 datasets.<p>
Using the "ptolemy.plot.HistogramApplet" from the Plot.jar
<p>
&lt;param name = "data" value="TitleText: Histogram from datastring [WIMS variable];XLabel: values ;YLabel: count;YRange: 0.0,100.0;BarGraph: 0.5,0.15 ;BinWidth: 1.0;BinOffset: 0.5 ;dataset: first;1;5.0;4.938441702975688;4.755282581475768;4.455032620941839;4.045084971874737;3.5355339059327378;2.938926261462366;2.269952498697734;1.5450849718747373;0.7821723252011547;3.061515884555943E-16;-0.7821723252011529;-1.5450849718747368;-2.2699524986977337;-2.9389262614623655;-3.5355339059327373;-4.045084971874737;-4.455032620941839;-4.755282581475767;-4.938441702975688;-5.0;-4.938441702975688;-4.755282581475769;-4.455032620941839;-4.045084971874737;-3.535533905932738;-2.9389262614623664;-2.2699524986977346;-1.545084971874738;-0.7821723252011552;-9.18454765366783E-16;0.7821723252011534;1.5450849718747361;2.269952498697733;2.938926261462365;3.535533905932737;4.045084971874736;4.4550326209418385;4.755282581475767;4.938441702975688;5.0;4.938441702975689;4.755282581475768;4.45503262094184;4.045084971874741;3.5355339059327386;2.938926261462367;2.269952498697731;1.5450849718747386;0.7821723252011602;1.5307579422779716E-15;-0.7821723252011484;-1.5450849718747357;-2.2699524986977364;-2.938926261462364;-3.5355339059327395;-4.045084971874736;-4.455032620941837;-4.755282581475767;-4.9384417029756875;-5.0;-4.938441702975688;-4.755282581475768;-4.4550326209418385;-4.045084971874738;-3.535533905932742;-2.9389262614623672;-2.26995249869774;-1.545084971874739;-0.7821723252011521;-2.1430611191891602E-15;0.7821723252011565;1.545084971874735;2.269952498697728;2.9389262614623637;3.535533905932733;4.0450849718747355;4.45503262094184;4.755282581475767;4.938441702975689;5.0;4.938441702975689;4.755282581475772;4.4550326209418385;4.045084971874739;3.5355339059327364;2.9389262614623677;2.2699524986977404;1.5450849718747481;0.7821723252011527;2.755364296100349E-15;-0.7821723252011472;-1.5450849718747344;-2.2699524986977275;-2.9389262614623703;-3.5355339059327386;-4.0450849718747355;-4.455032620941836;-4.755282581475764;-4.938441702975688;-5.0;dataset: second;4.5;4.46451615591515;4.35862422507884;4.183994186497132;3.943380060197386;3.6405764746872635;3.280358823396352;2.8684079538691036;2.4112205774054845;1.9160068120428269;1.3905764746872635;0.8432159156357613;0.28255733788191084;-0.2825573378819103;-0.8432159156357607;-1.3905764746872622;-1.9160068120428273;-2.411220577405486;-2.8684079538691036;-3.280358823396351;-3.640576474687263;-3.9433800601973865;-4.183994186497131;-4.35862422507884;-4.46451615591515;-4.5;-4.46451615591515;-4.35862422507884;-4.183994186497132;-3.943380060197386;-3.640576474687265;-3.280358823396353;-2.868407953869103;-2.4112205774054836;-1.9160068120428246;-1.3905764746872642;-0.8432159156357608;-0.2825573378819094;0.28255733788190773;0.8432159156357593;1.3905764746872626;1.9160068120428233;2.4112205774054853;2.868407953869102;3.2803588233963508;3.6405764746872626;3.9433800601973843;4.183994186497132;4.358624225078839;4.46451615591515;4.5;4.464516155915151;4.35862422507884;4.183994186497131;3.943380060197387;3.640576474687264;3.280358823396352;2.8684079538691063;2.411220577405484;1.9160068120428289;1.3905764746872684;0.8432159156357614;0.28255733788191395;-0.2825573378819112;-0.8432159156357626;-1.390576474687262;-1.91600681204283;-2.411220577405485;-2.8684079538691076;-3.280358823396353;-3.6405764746872626;-3.943380060197388;-4.183994186497132;-4.358624225078839;-4.464516155915151;-4.5;-4.464516155915151;-4.35862422507884;-4.183994186497133;-3.9433800601973856;-3.6405764746872644;-3.280358823396355;-2.86840795386911;-2.411220577405481;-1.9160068120428257;-1.390576474687265;-0.8432159156357658;-0.2825573378819185;0.2825573378819067;0.843215915635762;1.3905764746872615;1.9160068120428222;2.411220577405478;2.868407953869101;3.2803588233963525;3.640576474687262;3.9433800601973834;4.183994186497131;4.358624225078839;4.464516155915151;4.5;dataset: third;4.0;3.978087581473093;3.9125904029352228;3.804226065180614;3.6541818305704035;3.464101615137755;3.23606797749979;2.972579301909577;2.676522425435433;2.3511410091698925;2.0000000000000004;1.6269465723032015;1.2360679774997898;0.8316467632710369;0.41811385307061383;1.1330996904646007E-15;-0.41811385307061333;-0.8316467632710374;-1.2360679774997894;-1.6269465723032002;-1.9999999999999991;-2.351141009169892;-2.6765224254354316;-2.972579301909576;-3.2360679774997894;-3.464101615137755;-3.654181830570404;-3.804226065180614;-3.9125904029352228;-3.9780875814730936;-4.0;-3.9780875814730936;-3.9125904029352228;-3.8042260651806146;-3.6541818305704035;-3.4641016151377553;-3.2360679774997902;-2.972579301909577;-2.676522425435434;-2.351141009169893;-2.0000000000000018;-1.6269465723032035;-1.2360679774997902;-0.8316467632710391;-0.41811385307061694;-7.347638122934264E-16;0.41811385307061194;0.8316467632710377;1.236067977499789;1.626946572303199;2.0000000000000004;2.3511410091698917;2.676522425435434;2.972579301909577;3.2360679774997894;3.4641016151377553;3.654181830570404;3.804226065180614;3.9125904029352228;3.978087581473093;4.0;3.9780875814730936;3.912590402935223;3.8042260651806146;3.6541818305704044;3.464101615137756;3.2360679774997902;2.9725793019095783;2.676522425435433;2.3511410091698934;2.000000000000002;1.6269465723032008;1.236067977499791;0.8316467632710397;0.4181138530706139;1.2246063538223773E-15;-0.4181138530706115;-0.8316467632710338;-1.2360679774997885;-1.6269465723032017;-1.999999999999997;-2.3511410091698917;-2.6765224254354285;-2.972579301909579;-3.236067977499789;-3.4641016151377553;-3.654181830570402;-3.8042260651806137;-3.9125904029352214;-3.9780875814730936;-4.0;-3.978087581473093;-3.912590402935223;-3.8042260651806146;-3.654181830570403;-3.464101615137753;-3.2360679774997907;-2.972579301909581;-2.6765224254354356;-2.351141009169894;-1.9999999999999993;dataset: forth;3.5;3.4859100289833367;3.4437535600952036;3.3738700124354866;3.2768220472390803;3.153391037658467;3.0045707776065314;2.831559480312316;2.6357501310126383;2.4187192714540267;2.1822143065055672;1.9281394350823593;1.6585403186554954;1.3755876107887328;1.081559480312316;0.7788232688471006;0.4698164303617944;0.15702690622680246;-0.15702690622680202;-0.46981643036179394;-0.7788232688471002;-1.0815594803123156;-1.3755876107887317;-1.658540318655495;-1.9281394350823586;-2.1822143065055672;-2.418719271454026;-2.635750131012638;-2.8315594803123156;-3.0045707776065314;-3.1533910376584666;-3.27682204723908;-3.3738700124354866;-3.4437535600952036;-3.4859100289833367;-3.5;-3.4859100289833367;-3.443753560095204;-3.3738700124354866;-3.2768220472390803;-3.153391037658467;-3.0045707776065327;-2.831559480312316;-2.6357501310126388;-2.418719271454028;-2.1822143065055677;-1.9281394350823593;-1.658540318655496;-1.3755876107887333;-1.0815594803123165;-0.778823268847101;-0.46981643036179477;-0.15702690622680288;0.1570269062268016;0.4698164303617935;0.7788232688470997;1.0815594803123154;1.375587610788732;1.6585403186554948;1.9281394350823582;2.182214306505567;2.4187192714540258;2.635750131012638;2.8315594803123156;3.004570777606531;3.1533910376584666;3.27682204723908;3.373870012435486;3.4437535600952036;3.4859100289833367;3.5;3.4859100289833367;3.443753560095204;3.3738700124354866;3.2768220472390808;3.1533910376584675;3.004570777606532;2.8315594803123165;2.6357501310126388;2.418719271454027;2.182214306505568;1.9281394350823597;1.658540318655499;1.3755876107887308;1.081559480312317;0.7788232688471014;0.4698164303617952;0.1570269062268064;-0.15702690622679805;-0.46981643036179616;-0.7788232688470993;-1.081559480312315;-1.3755876107887317;-1.6585403186554943;-1.928139435082358;-2.1822143065055664;-2.4187192714540253;-2.6357501310126374;-2.831559480312315;-3.004570777606531;-3.1533910376584666;dataset: fifth;3.0;2.990752001199384;2.9630650217854133;2.91710976119303;2.853169548885461;2.7716385975338604;2.673019572565104;2.5579204930622765;2.4270509831248424;2.2812178968000927;2.121320343559643;1.9483441449905512;1.7633557568774194;1.5674956941478466;1.3619714992186405;1.1480502970952695;0.9270509831248425;0.7003360915677164;0.46930339512069275;0.235377287183535;1.836909530733566E-16;-0.23537728718353465;-0.46930339512069175;-0.700336091567716;-0.927050983124842;-1.148050297095269;-1.3619714992186402;-1.5674956941478464;-1.7633557568774192;-1.9483441449905508;-2.1213203435596424;-2.2812178968000927;-2.427050983124842;-2.5579204930622765;-2.6730195725651034;-2.77163859753386;-2.8531695488854605;-2.91710976119303;-2.9630650217854133;-2.990752001199384;-3.0;-2.9907520011993842;-2.9630650217854133;-2.91710976119303;-2.8531695488854614;-2.7716385975338604;-2.673019572565104;-2.557920493062276;-2.4270509831248424;-2.281217896800094;-2.121320343559643;-1.9483441449905523;-1.7633557568774199;-1.567495694147846;-1.361971499218641;-1.1480502970952686;-0.9270509831248428;-0.700336091567718;-0.46930339512069313;-0.2353772871835367;-5.510728592200698E-16;0.2353772871835356;0.469303395120692;0.7003360915677169;0.9270509831248417;1.1480502970952675;1.3619714992186398;1.5674956941478448;1.763355756877419;1.9483441449905514;2.121320343559642;2.281217896800093;2.427050983124842;2.5579204930622756;2.6730195725651034;2.7716385975338595;2.8531695488854605;2.91710976119303;2.963065021785413;2.990752001199384;3.0;2.9907520011993842;2.9630650217854138;2.91710976119303;2.853169548885461;2.77163859753386;2.673019572565104;2.557920493062278;2.427050983124844;2.2812178968000927;2.1213203435596433;1.9483441449905525;1.76335575687742;1.5674956941478484;1.3619714992186387;1.1480502970952688;0.9270509831248431;0.7003360915677184;0.46930339512069613;0.2353772871835344;9.18454765366783E-16;dataset:ninth;2.4939101256495606;2.475670171853926;2.4453690018345142;2.4031542398457972;2.349231551964771;2.283863644106502;2.2073689821473175;2.120120240391065;2.0225424859373686;1.9151111077974452;1.798349500846628;1.6728265158971456;1.5391536883141457;1.397982258676867;1.2500000000000002;1.0959278669726935;0.9365164835397799;0.7725424859373686;0.6048047389991698;0.4341204441673261;0.26132115816913365;0.0872487417562527;-0.08724874175625184;-0.2613211581691333;-0.43412044416732576;-0.6048047389991694;-0.7725424859373684;-0.9365164835397801;-1.0959278669726937;-1.2499999999999996;-1.3979822586768669;-1.5391536883141457;-1.6728265158971456;-1.7983495008466281;-1.9151111077974448;-2.0225424859373686;-2.120120240391065;-2.207368982147317;-2.283863644106502;-2.349231551964771;-2.403154239845797;-2.4453690018345142;-2.475670171853926;-2.4939101256495606;-2.5;-2.4939101256495606;-2.475670171853926;-2.4453690018345142;-2.4031542398457972;-2.349231551964771;-2.2838636441065026;-2.207368982147317;-2.1201202403910653;-2.0225424859373686;-1.9151111077974452;-1.7983495008466277;-1.672826515897146;-1.5391536883141452;-1.3979822586768682;-1.2500000000000009;-1.0959278669726944;-0.9365164835397807;-0.772542485937369;-0.6048047389991695;-0.4341204441673258;-0.26132115816913337;-0.08724874175625412;0.0872487417562532;0.2613211581691325;0.4341204441673249;0.6048047389991686;0.7725424859373681;0.9365164835397799;1.0959278669726935;1.2500000000000002;1.3979822586768655;1.5391536883141463;1.6728265158971445;1.798349500846627;1.9151111077974445;2.022542485937368;2.1201202403910635;2.2073689821473175;2.283863644106502;2.3492315519647713;2.403154239845797;2.445369001834514;2.475670171853926;2.4939101256495606;2.5;2.4939101256495606;2.4756701718539262;2.4453690018345147;2.4031542398457972;2.349231551964771;2.283863644106503;2.207368982147318;2.1201202403910653;2.0225424859373677;1.9151111077974454 "&gt;
 
<applet width = "640" height = "480" codebase=".." archive="Plot.jar" code="ptolemy.plot.HistogramApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name = "data" value="TitleText: Histogram from datastring [WIMS variable];bargraph: 0.5,0.15 ;binwidth: 1.0;binoffset: 0.5;XLabel: values ;YLabel: count;YRange: 0.0,100.0;BarGraph: 0.5,0.15 ;BinWidth: 1.0;BinOffset: 0.5 ;dataset: 1a;1;5.0;4.938441702975688;4.755282581475768;4.455032620941839;4.045084971874737;3.5355339059327378;2.938926261462366;2.269952498697734;1.5450849718747373;0.7821723252011547;3.061515884555943E-16;-0.7821723252011529;-1.5450849718747368;-2.2699524986977337;-2.9389262614623655;-3.5355339059327373;-4.045084971874737;-4.455032620941839;-4.755282581475767;-4.938441702975688;-5.0;-4.938441702975688;-4.755282581475769;-4.455032620941839;-4.045084971874737;-3.535533905932738;-2.9389262614623664;-2.2699524986977346;-1.545084971874738;-0.7821723252011552;-9.18454765366783E-16;0.7821723252011534;1.5450849718747361;2.269952498697733;2.938926261462365;3.535533905932737;4.045084971874736;4.4550326209418385;4.755282581475767;4.938441702975688;5.0;4.938441702975689;4.755282581475768;4.45503262094184;4.045084971874741;3.5355339059327386;2.938926261462367;2.269952498697731;1.5450849718747386;0.7821723252011602;1.5307579422779716E-15;-0.7821723252011484;-1.5450849718747357;-2.2699524986977364;-2.938926261462364;-3.5355339059327395;-4.045084971874736;-4.455032620941837;-4.755282581475767;-4.9384417029756875;-5.0;-4.938441702975688;-4.755282581475768;-4.4550326209418385;-4.045084971874738;-3.535533905932742;-2.9389262614623672;-2.26995249869774;-1.545084971874739;-0.7821723252011521;-2.1430611191891602E-15;0.7821723252011565;1.545084971874735;2.269952498697728;2.9389262614623637;3.535533905932733;4.0450849718747355;4.45503262094184;4.755282581475767;4.938441702975689;5.0;4.938441702975689;4.755282581475772;4.4550326209418385;4.045084971874739;3.5355339059327364;2.9389262614623677;2.2699524986977404;1.5450849718747481;0.7821723252011527;2.755364296100349E-15;-0.7821723252011472;-1.5450849718747344;-2.2699524986977275;-2.9389262614623703;-3.5355339059327386;-4.0450849718747355;-4.455032620941836;-4.755282581475764;-4.938441702975688;-5.0;dataset: second;4.5;4.46451615591515;4.35862422507884;4.183994186497132;3.943380060197386;3.6405764746872635;3.280358823396352;2.8684079538691036;2.4112205774054845;1.9160068120428269;1.3905764746872635;0.8432159156357613;0.28255733788191084;-0.2825573378819103;-0.8432159156357607;-1.3905764746872622;-1.9160068120428273;-2.411220577405486;-2.8684079538691036;-3.280358823396351;-3.640576474687263;-3.9433800601973865;-4.183994186497131;-4.35862422507884;-4.46451615591515;-4.5;-4.46451615591515;-4.35862422507884;-4.183994186497132;-3.943380060197386;-3.640576474687265;-3.280358823396353;-2.868407953869103;-2.4112205774054836;-1.9160068120428246;-1.3905764746872642;-0.8432159156357608;-0.2825573378819094;0.28255733788190773;0.8432159156357593;1.3905764746872626;1.9160068120428233;2.4112205774054853;2.868407953869102;3.2803588233963508;3.6405764746872626;3.9433800601973843;4.183994186497132;4.358624225078839;4.46451615591515;4.5;4.464516155915151;4.35862422507884;4.183994186497131;3.943380060197387;3.640576474687264;3.280358823396352;2.8684079538691063;2.411220577405484;1.9160068120428289;1.3905764746872684;0.8432159156357614;0.28255733788191395;-0.2825573378819112;-0.8432159156357626;-1.390576474687262;-1.91600681204283;-2.411220577405485;-2.8684079538691076;-3.280358823396353;-3.6405764746872626;-3.943380060197388;-4.183994186497132;-4.358624225078839;-4.464516155915151;-4.5;-4.464516155915151;-4.35862422507884;-4.183994186497133;-3.9433800601973856;-3.6405764746872644;-3.280358823396355;-2.86840795386911;-2.411220577405481;-1.9160068120428257;-1.390576474687265;-0.8432159156357658;-0.2825573378819185;0.2825573378819067;0.843215915635762;1.3905764746872615;1.9160068120428222;2.411220577405478;2.868407953869101;3.2803588233963525;3.640576474687262;3.9433800601973834;4.183994186497131;4.358624225078839;4.464516155915151;4.5;dataset: third;4.0;3.978087581473093;3.9125904029352228;3.804226065180614;3.6541818305704035;3.464101615137755;3.23606797749979;2.972579301909577;2.676522425435433;2.3511410091698925;2.0000000000000004;1.6269465723032015;1.2360679774997898;0.8316467632710369;0.41811385307061383;1.1330996904646007E-15;-0.41811385307061333;-0.8316467632710374;-1.2360679774997894;-1.6269465723032002;-1.9999999999999991;-2.351141009169892;-2.6765224254354316;-2.972579301909576;-3.2360679774997894;-3.464101615137755;-3.654181830570404;-3.804226065180614;-3.9125904029352228;-3.9780875814730936;-4.0;-3.9780875814730936;-3.9125904029352228;-3.8042260651806146;-3.6541818305704035;-3.4641016151377553;-3.2360679774997902;-2.972579301909577;-2.676522425435434;-2.351141009169893;-2.0000000000000018;-1.6269465723032035;-1.2360679774997902;-0.8316467632710391;-0.41811385307061694;-7.347638122934264E-16;0.41811385307061194;0.8316467632710377;1.236067977499789;1.626946572303199;2.0000000000000004;2.3511410091698917;2.676522425435434;2.972579301909577;3.2360679774997894;3.4641016151377553;3.654181830570404;3.804226065180614;3.9125904029352228;3.978087581473093;4.0;3.9780875814730936;3.912590402935223;3.8042260651806146;3.6541818305704044;3.464101615137756;3.2360679774997902;2.9725793019095783;2.676522425435433;2.3511410091698934;2.000000000000002;1.6269465723032008;1.236067977499791;0.8316467632710397;0.4181138530706139;1.2246063538223773E-15;-0.4181138530706115;-0.8316467632710338;-1.2360679774997885;-1.6269465723032017;-1.999999999999997;-2.3511410091698917;-2.6765224254354285;-2.972579301909579;-3.236067977499789;-3.4641016151377553;-3.654181830570402;-3.8042260651806137;-3.9125904029352214;-3.9780875814730936;-4.0;-3.978087581473093;-3.912590402935223;-3.8042260651806146;-3.654181830570403;-3.464101615137753;-3.2360679774997907;-2.972579301909581;-2.6765224254354356;-2.351141009169894;-1.9999999999999993;dataset: forth;3.5;3.4859100289833367;3.4437535600952036;3.3738700124354866;3.2768220472390803;3.153391037658467;3.0045707776065314;2.831559480312316;2.6357501310126383;2.4187192714540267;2.1822143065055672;1.9281394350823593;1.6585403186554954;1.3755876107887328;1.081559480312316;0.7788232688471006;0.4698164303617944;0.15702690622680246;-0.15702690622680202;-0.46981643036179394;-0.7788232688471002;-1.0815594803123156;-1.3755876107887317;-1.658540318655495;-1.9281394350823586;-2.1822143065055672;-2.418719271454026;-2.635750131012638;-2.8315594803123156;-3.0045707776065314;-3.1533910376584666;-3.27682204723908;-3.3738700124354866;-3.4437535600952036;-3.4859100289833367;-3.5;-3.4859100289833367;-3.443753560095204;-3.3738700124354866;-3.2768220472390803;-3.153391037658467;-3.0045707776065327;-2.831559480312316;-2.6357501310126388;-2.418719271454028;-2.1822143065055677;-1.9281394350823593;-1.658540318655496;-1.3755876107887333;-1.0815594803123165;-0.778823268847101;-0.46981643036179477;-0.15702690622680288;0.1570269062268016;0.4698164303617935;0.7788232688470997;1.0815594803123154;1.375587610788732;1.6585403186554948;1.9281394350823582;2.182214306505567;2.4187192714540258;2.635750131012638;2.8315594803123156;3.004570777606531;3.1533910376584666;3.27682204723908;3.373870012435486;3.4437535600952036;3.4859100289833367;3.5;3.4859100289833367;3.443753560095204;3.3738700124354866;3.2768220472390808;3.1533910376584675;3.004570777606532;2.8315594803123165;2.6357501310126388;2.418719271454027;2.182214306505568;1.9281394350823597;1.658540318655499;1.3755876107887308;1.081559480312317;0.7788232688471014;0.4698164303617952;0.1570269062268064;-0.15702690622679805;-0.46981643036179616;-0.7788232688470993;-1.081559480312315;-1.3755876107887317;-1.6585403186554943;-1.928139435082358;-2.1822143065055664;-2.4187192714540253;-2.6357501310126374;-2.831559480312315;-3.004570777606531;-3.1533910376584666;dataset: fifth;3.0;2.990752001199384;2.9630650217854133;2.91710976119303;2.853169548885461;2.7716385975338604;2.673019572565104;2.5579204930622765;2.4270509831248424;2.2812178968000927;2.121320343559643;1.9483441449905512;1.7633557568774194;1.5674956941478466;1.3619714992186405;1.1480502970952695;0.9270509831248425;0.7003360915677164;0.46930339512069275;0.235377287183535;1.836909530733566E-16;-0.23537728718353465;-0.46930339512069175;-0.700336091567716;-0.927050983124842;-1.148050297095269;-1.3619714992186402;-1.5674956941478464;-1.7633557568774192;-1.9483441449905508;-2.1213203435596424;-2.2812178968000927;-2.427050983124842;-2.5579204930622765;-2.6730195725651034;-2.77163859753386;-2.8531695488854605;-2.91710976119303;-2.9630650217854133;-2.990752001199384;-3.0;-2.9907520011993842;-2.9630650217854133;-2.91710976119303;-2.8531695488854614;-2.7716385975338604;-2.673019572565104;-2.557920493062276;-2.4270509831248424;-2.281217896800094;-2.121320343559643;-1.9483441449905523;-1.7633557568774199;-1.567495694147846;-1.361971499218641;-1.1480502970952686;-0.9270509831248428;-0.700336091567718;-0.46930339512069313;-0.2353772871835367;-5.510728592200698E-16;0.2353772871835356;0.469303395120692;0.7003360915677169;0.9270509831248417;1.1480502970952675;1.3619714992186398;1.5674956941478448;1.763355756877419;1.9483441449905514;2.121320343559642;2.281217896800093;2.427050983124842;2.5579204930622756;2.6730195725651034;2.7716385975338595;2.8531695488854605;2.91710976119303;2.963065021785413;2.990752001199384;3.0;2.9907520011993842;2.9630650217854138;2.91710976119303;2.853169548885461;2.77163859753386;2.673019572565104;2.557920493062278;2.427050983124844;2.2812178968000927;2.1213203435596433;1.9483441449905525;1.76335575687742;1.5674956941478484;1.3619714992186387;1.1480502970952688;0.9270509831248431;0.7003360915677184;0.46930339512069613;0.2353772871835344;9.18454765366783E-16;dataset:ninth;2.4939101256495606;2.475670171853926;2.4453690018345142;2.4031542398457972;2.349231551964771;2.283863644106502;2.2073689821473175;2.120120240391065;2.0225424859373686;1.9151111077974452;1.798349500846628;1.6728265158971456;1.5391536883141457;1.397982258676867;1.2500000000000002;1.0959278669726935;0.9365164835397799;0.7725424859373686;0.6048047389991698;0.4341204441673261;0.26132115816913365;0.0872487417562527;-0.08724874175625184;-0.2613211581691333;-0.43412044416732576;-0.6048047389991694;-0.7725424859373684;-0.9365164835397801;-1.0959278669726937;-1.2499999999999996;-1.3979822586768669;-1.5391536883141457;-1.6728265158971456;-1.7983495008466281;-1.9151111077974448;-2.0225424859373686;-2.120120240391065;-2.207368982147317;-2.283863644106502;-2.349231551964771;-2.403154239845797;-2.4453690018345142;-2.475670171853926;-2.4939101256495606;-2.5;-2.4939101256495606;-2.475670171853926;-2.4453690018345142;-2.4031542398457972;-2.349231551964771;-2.2838636441065026;-2.207368982147317;-2.1201202403910653;-2.0225424859373686;-1.9151111077974452;-1.7983495008466277;-1.672826515897146;-1.5391536883141452;-1.3979822586768682;-1.2500000000000009;-1.0959278669726944;-0.9365164835397807;-0.772542485937369;-0.6048047389991695;-0.4341204441673258;-0.26132115816913337;-0.08724874175625412;0.0872487417562532;0.2613211581691325;0.4341204441673249;0.6048047389991686;0.7725424859373681;0.9365164835397799;1.0959278669726935;1.2500000000000002;1.3979822586768655;1.5391536883141463;1.6728265158971445;1.798349500846627;1.9151111077974445;2.022542485937368;2.1201202403910635;2.2073689821473175;2.283863644106502;2.3492315519647713;2.403154239845797;2.445369001834514;2.475670171853926;2.4939101256495606;2.5;2.4939101256495606;2.4756701718539262;2.4453690018345147;2.4031542398457972;2.349231551964771;2.283863644106503;2.207368982147318;2.1201202403910653;2.0225424859373677;1.9151111077974454 ">
</applet>
<p>
A histogram plotter<br> The plot can be configured and data can
be provided either through a file with commands or through direct
invocation of the public methods of the class<br> To read a file or a
URL, use the read() method<br>
<p>
When calling the public methods, in most cases the changes will not
be visible until paint() has been called<br> To request that this
be done, call repaint()<br> One exception is addPoint(), which
makes the affect of the new point visible immediately (or nearly
immediately) if the plot is visible on the screen<br>
<p>
The ASCII format for the file file contains any number commands,
one per line<br> Unrecognized commands and commands with syntax
errors are ignored<br> Comments are denoted by a line starting with a
pound sign "#"<br> The recognized commands include those supported by
the base class, plus a few more<br> The commands are case
insensitive, but are usually capitalized<br> The number of data sets
to be plotted does not need to be specified<br> Data sets are added as needed<br>
Each dataset is identified with a color (see the base class)<br>
<P>
The appearance of the histogram can be altered by the following commands:
<pre>
Bars: <i>width</i>
Bars: <i>width, offset</i>
</pre>
The <i>width</i> is a real number specifying the width of the bars
as a fraction of the bin width<br> It usually has a value less than
or equal to one,
and defaults to 0<br>5<br> The <i>offset</i> is a real number
specifying how much the bar of the <i>i </i><sup>th</sup> data set
is offset from the previous one<br> This allows bars to "peek out"
from behind the ones in front<br> It defaults to 0<br>15<br>
Note that the frontmost data set will be the first one<br>
<p>
The width of each bin of the histogram can be specified using:
<pre>
BinWidth: <i>width</i>
</pre>
This is given in whatever units the data has<br>
By default, each bin is centered at <i>x</i> = <i>nw</i>,
where <i>w</i> is the width of the bin and <i>n</i> is an integer<br>
That bin represents values in the range (<i>x - w/2, x + w/2</i>)<br>
The alignment of the bins can be changed with the following command:
<pre>
BinOffset: <i>offset</i>
</pre>
If this method is used with argument <i>o</i>, then each bin is
centered at <i>x = nw + o</i>, and represents values in the range
(<i>x - w/2 + o, x + w/2 + o</i>)<br> So for example, if <i>o = w/2</i>,
then each bin represents values from <i>nw</i> to
(<i>n</i> + 1)<i>w</i> for some integer <i>n</i><br>
The default offset is 0<br>5, half the default bin width<br>
<p>
To specify data to be plotted, start a data set with the following command:
<pre>
DataSet: <i>string</i>
</pre>
Here, <i>string</i> is a label that will appear in the legend<br>
It is not necessary to enclose the string in quotation marks<br>
To start a new dataset without giving it a name, use:
<pre>
DataSet:
</pre>
In this case, no item will appear in the legend<br>
New datasets are plotted <i>behind</i> the previous ones<br>
The data itself is given by a sequence of numbers, one per line<br>
The numbers are specified as
strings that can be parsed by the Double parser in Java<br>
It is also possible to specify the numbers using all the formats
accepted by the Plot class, so that the same data may be plotted by
both classes<br> The <i>x</i> data is ignored, and only the <i>y</i>
data is used to calculate the histogram<br>
 
</body>
</html>
 
<!--
<param name="background" value="hexcolor value">
<param name="foreground" value="hexcolor value">
<param name="dataurl" value="url">
<param name="height" value="integer">
<param name="width" value="integer">
<param name="function" value="String1,String2,String3...">
<param name="smooth" value="0/1"">
<param name="names" value="names function1,name function2 ... or left blank ">
<param name="xmin" value="minimum x-value or left blank for auto detection">
<param name="xmax" value="maximum x-value or left blank for auto detection">
<param name="ymin" value="minimum y-value or left blank for auto detection">
<param name="ymax" value="maximum y-value or left blank for auto detection">
<param name="xlog" value="x-axis is log-scale: 0 or 1: default 0">
<param name="ylog" value="y-axis is log-scale: 0 or 1: default 0">
<param name="xtics" value=" zero 0, one 1, two 2, pi 3.1428, four "jan 2008", five 5.... or left blank ">
<param name="ytics" value="thing1 0, thing2 1, thing3 2, three 3, four 4, five 5...or left blank ">
<param name="xlabel" value="label of the x-axis: default x-axis">
<param name="ylabel" value="label of the y-axis: default y-axis" >
<param name="title" value="title of the plot" >
-->
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/1.html
0,0 → 1,116
<html>
<head></head>
<body>
<applet width = "640" height = "480" codebase="dist" archive="Plot.jar" code="ptolemy.plot.PlotApplet">
<param name = "progressbar" value = "true">
<param name = "scriptable" value = "false">
<param name = "background" value = "#ffffff">
<param name = "name" value = "PlotApplet">
<param name="title" value="in the titel, htmlsyntax like &quot; &amp; &auml; &rarr; &pi; &quot; , is allowed">
<param name="xlabel" value="x-as label">
<param name="ylabel" value="y-as label">
<param name="grid" value="on">
<param name="color" value="on">
<param name="xmin" value="0">
<param name="xmax" value="6">
<param name="ymax" value="5">
<param name="ymin" value="-5">
<param name="color" value="on">
<param name="smooth" value="0">
<param name="function" value="tan(x),sin(x),cos(x),2*cos(x),cos(2*x),1/cos(x)">
<param name="names" value="curve 1:tan(x),curve 2: sin(x),curve 3:cos(x),2*cos(x),cos(2*x),1/cos(x)">
<param name="plotsteps" value="100">
<param name="normalexponent" value="yes">
</applet>
<br>
data loaded by function param:
&lt;param name="function" value="tan(x),sin(x),cos(x),2*cos(x),cos(2*x),1/cos(x)"&gt;
<p>Applet htmlcode:<br>
<tt>
&lt;applet width = "640" height = "480" codebase="." archive="Plot.jar" code="ptolemy.plot.PlotApplet"&gt;<br>
&lt;param name = "progressbar" value = "true"&gt;<br>
&lt;param name = "scriptable" value = "false"&gt;<br>
&lt;param name = "background" value = "#ffffff"&gt;<br>
&lt;param name = "name" value = "PlotApplet"&gt;<br>
&lt;param name="title" value="titel htmlsyntax: &amp; pi ... &pi;"&gt;<br>
&lt;param name="xlabel" value="x-as label"&gt;<br>
&lt;param name="ylabel" value="y-as label"&gt;<br>
&lt;param name="grid" value="on"&gt;<br>
&lt;param name="color" value="on"&gt;<br>
&lt;param name="xmin" value="0"&gt;<br>
&lt;param name="xmax" value="6"&gt;<br>
&lt;param name="ymax" value="5"&gt;<br>
&lt;param name="ymin" value="-5"&gt;<br>
&lt;param name="color" value="on"&gt;<br>
&lt;param name="smooth" value="0"&gt;<br>
&lt;param name="function" value="tan(x),sin(x),cos(x),2*cos(x),cos(2*x),1/cos(x)"&gt;<br>
&lt;param name="names" value="curve 1:tan(x),curve 2: sin(x),curve 3:cos(x),2*cos(x),cos(2*x),1/cos(x)"&gt;<br>
&lt;param name="plotsteps" value="100"&gt;<br>
&lt;param name="normalexponent" value="yes"&gt;&lt;!-- used for logscales: if set 1.0&times;10<sup>3</sup> in stead of 1.0E3 --&gt;<br>
&lt;/applet&gt;<br>
</tt>
Other means of loading data:<br>
&lt;param name="file" value="http://localhost/wims/wims.cgi?session=&cmd=getfile&special_parm=mydata"&gt;<br><br>
example of a single line datafile:<br>
"TitleText: Software Downloads;XRange: 0,10;YRange: 0,10000;# Manually specify X ticks;# Note that the 0 and 10 point result in clipping of the rectangles.;XTicks: 1993 0, 1994 1, 1995 2, 1996 3, 1997 4, 1998 5, 1999 6, 2000 7, 2001 8, 2002 9, 2003 10;XLabel: Year;YLabel: Downloads;Marks: none;Lines: off;# Width and offset of bars;Bars: 0.5, 0.2;NumSets: 3;;DataSet: program a;0, 100;1, 300;2, 600;3, 1000;4, 4000;5, 6000;6, 3000;7, 1000;8, 400;9, 0;10, 0;;DataSet: program b;0, 0;1, 0;2, 50;3, 100;4, 800;5, 400;6, 1000;7, 5000;8, 2000;9, 300;10, 0;;DataSet: program c;0, 0;1, 0;2, 0;3, 10;4, 100;5, 400;6, 2000;7, 5000;8, 9000;9, 7000;10, 1000"
<p>
Or by direct file in a directory
<tt>?&lt;param name="dataurl" value="../data/thisdata.txt"&gt;</tt><br>
An example of a multiline datafile:<br>
<tt>
TitleText: Software Downloads<br>
XRange: 0,10<br>
YRange: 0,10000<br>
# Manually specify X ticks<br>
# Note that the 0 and 10 point result in clipping of the rectangles.<br>
XTicks: 1993 0, 1994 1, 1995 2, 1996 3, 1997 4, 1998 5, 1999 6, 2000 7, 2001 8, 2002 9, 2003 10<br>
XLabel: Year<br>
YLabel: Downloads<br>
Marks: none<br>
Lines: off<br>
# Width and offset of bars<br>
Bars: 0.5, 0.2<br>
NumSets: 3<br>
<br>
DataSet: program a<br>
0, 100<br>
1, 300<br>
2, 600<br>
3, 1000<br>
4, 4000<br>
5, 6000<br>
6, 3000<br>
7, 1000<br>
8, 400<br>
9, 0<br>
10, 0<br>
<br>
DataSet: program b<br>
0, 0<br>
1, 0<br>
2, 50<br>
3, 100<br>
4, 800<br>
5, 400<br>
6, 1000<br>
7, 5000<br>
8, 2000<br>
9, 300<br>
10, 0<br>
<br>
DataSet: program c<br>
0, 0<br>
1, 0<br>
2, 0<br>
3, 10<br>
4, 100<br>
5, 400<br>
6, 2000<br>
7, 5000<br>
8, 9000<br>
9, 7000<br>
10, 1000<br>
</tt>
</body>
</html>
 
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/util/FileUtilities.java
0,0 → 1,633
/* Utilities used to manipulate files
 
Copyright (c) 2004-2008 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
 
*/
package ptolemy.util;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
 
// Avoid importing any packages from ptolemy.* here so that we
// can ship Ptplot.
//////////////////////////////////////////////////////////////////////////
//// FileUtilities
 
/**
A collection of utilities for manipulating files
These utilities do not depend on any other ptolemy.* packages.
 
@author Christopher Brooks
@version $Id: FileUtilities.java,v 1.54.4.3 2008/03/25 22:32:41 cxh Exp $
@since Ptolemy II 4.0
@Pt.ProposedRating Green (cxh)
@Pt.AcceptedRating Green (cxh)
*/
public class FileUtilities {
/** Instances of this class cannot be created.
*/
private FileUtilities() {
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Copy sourceURL to destinationFile without doing any byte conversion.
* @param sourceURL The source URL
* @param destinationFile The destination File.
* @return true if the file was copied, false if the file was not
* copied because the sourceURL and the destinationFile refer to the
* same file.
* @exception IOException If the source file does not exist.
*/
public static boolean binaryCopyURLToFile(URL sourceURL,
File destinationFile) throws IOException {
URL destinationURL = destinationFile.getCanonicalFile().toURI().toURL();
 
if (sourceURL.sameFile(destinationURL)) {
return false;
}
 
// If sourceURL is of the form file:./foo, then we need to try again.
File sourceFile = new File(sourceURL.getFile());
 
// If the sourceURL is not a jar URL, then check to see if we
// have the same file.
// FIXME: should we check for !/ and !\ everywhere?
if ((sourceFile.getPath().indexOf("!/") == -1)
&& (sourceFile.getPath().indexOf("!\\") == -1)) {
try {
if (sourceFile.getCanonicalFile().toURI().toURL().sameFile(
destinationURL)) {
return false;
}
} catch (IOException ex) {
// JNLP Jar urls sometimes throw an exception here.
// IOException constructor does not take a cause
IOException ioException = new IOException(
"Cannot find canonical file name of '" + sourceFile
+ "'");
ioException.initCause(ex);
throw ioException;
}
}
 
_binaryCopyStream(sourceURL.openStream(), destinationFile);
 
return true;
}
 
/** Extract a jar file into a directory. This is a trivial
* implementation of the <code>jar -xf</code> command.
* @param jarFileName The name of the jar file to extract
* @param directoryName The name of the directory. If this argument
* is null, then the files are extracted in the current directory.
* @exception IOException If the jar file cannot be opened, or
* if there are problems extracting the contents of the jar file
*/
public static void extractJarFile(String jarFileName, String directoryName)
throws IOException {
JarFile jarFile = new JarFile(jarFileName);
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) entries.nextElement();
File destinationFile = new File(directoryName, jarEntry.getName());
if (jarEntry.isDirectory()) {
if (!destinationFile.isDirectory() && !destinationFile.mkdirs()) {
throw new IOException("Warning, failed to create "
+ "directory for \"" + destinationFile + "\".");
}
} else {
_binaryCopyStream(jarFile.getInputStream(jarEntry),
destinationFile);
}
}
}
 
/** Extract the contents of a jar file.
* @param args An array of arguments. The first argument
* names the jar file to be extracted. The first argument
* is required. The second argument names the directory in
* which to extract the files from the jar file. The second
* argument is optional.
*/
public static void main(String[] args) {
if (args.length < 1 || args.length > 2) {
System.err.println("Usage: java -classpath $PTII "
+ "ptolemy.util.FileUtilities jarFile [directory]\n"
+ "where jarFile is the name of the jar file\n"
+ "and directory is the optional directory in which to "
+ "extract.");
StringUtilities.exit(2);
}
String jarFileName = args[0];
String directoryName = null;
if (args.length >= 2) {
directoryName = args[1];
}
try {
extractJarFile(jarFileName, directoryName);
} catch (Throwable throwable) {
System.err.println("Failed to extract \"" + jarFileName + "\"");
throwable.printStackTrace();
StringUtilities.exit(3);
}
}
 
/** Given a file name or URL, construct a java.io.File object that
* refers to the file name or URL. This method
* first attempts to directly use the file name to construct the
* File. If the resulting File is a relative pathname, then
* it is resolved relative to the specified base URI, if
* there is one. If there is no such base URI, then it simply
* returns the relative File object. See the java.io.File
* documentation for a details about relative and absolute pathnames.
*
* <p>
* The file need not exist for this method to succeed. Thus,
* this method can be used to determine whether a file with a given
* name exists, prior to calling openForWriting(), for example.
*
* <p>This method is similar to
* {@link #nameToURL(String, URI, ClassLoader)}
* except that in this method, the file or URL must be readable.
* Usually, this method is use for write a file and
* {@link #nameToURL(String, URI, ClassLoader)} is used for reading.
*
* @param name The file name or URL.
* @param base The base for relative URLs.
* @return A File, or null if the filename argument is null or
* an empty string.
* @see #nameToURL(String, URI, ClassLoader)
*/
public static File nameToFile(String name, URI base) {
if ((name == null) || name.trim().equals("")) {
return null;
}
 
File file = new File(name);
 
if (!file.isAbsolute()) {
// Try to resolve the base directory.
if (base != null) {
URI newURI = base.resolve(name);
 
//file = new File(newURI);
String urlString = newURI.getPath();
file = new File(StringUtilities.substitute(urlString, "%20",
" "));
}
}
return file;
}
 
/** Given a file or URL name, return as a URL. If the file name
* is relative, then it is interpreted as being relative to the
* specified base directory. If the name begins with
* "xxxxxxCLASSPATHxxxxxx" or "$CLASSPATH" then search for the
* file relative to the classpath.
*
* <p>Note that "xxxxxxCLASSPATHxxxxxx" is the value of the
* globally defined constant $CLASSPATH available in the Ptolemy
* II expression language.
*
* <p>If no file is found, then throw an exception.
*
* <p>This method is similar to {@link #nameToFile(String, URI)}
* except that in this method, the file or URL must be readable.
* Usually, this method is use for reading a file and
* is used for writing {@link #nameToFile(String, URI)}.
*
* @param name The name of a file or URL.
* @param baseDirectory The base directory for relative file names,
* or null to specify none.
* @param classLoader The class loader to use to locate system
* resources, or null to use the system class loader that was used
* to load this class.
* @return A URL, or null if the name is null or the empty string.
* @exception IOException If the file cannot be read, or
* if the file cannot be represented as a URL (e.g. System.in), or
* the name specification cannot be parsed.
* @see #nameToFile(String, URI)
*/
public static URL nameToURL(String name, URI baseDirectory,
ClassLoader classLoader) throws IOException {
if ((name == null) || name.trim().equals("")) {
return null;
}
 
// If the name begins with "$CLASSPATH", or
// "xxxxxxCLASSPATHxxxxxx",then attempt to open the file
// relative to the classpath.
// NOTE: Use the dummy variable constant set up in the constructor.
if (name.startsWith(_CLASSPATH_VALUE) || name.startsWith("$CLASSPATH")) {
// Try relative to classpath.
String classpathKey;
 
if (name.startsWith(_CLASSPATH_VALUE)) {
classpathKey = _CLASSPATH_VALUE;
} else {
classpathKey = "$CLASSPATH";
}
 
String trimmedName = name.substring(classpathKey.length() + 1);
 
if (classLoader == null) {
String referenceClassName = "ptolemy.util.FileUtilities";
 
try {
// WebStart: We might be in the Swing Event thread, so
// Thread.currentThread().getContextClassLoader()
// .getResource(entry) probably will not work so we
// use a marker class.
Class referenceClass = Class.forName(referenceClassName);
classLoader = referenceClass.getClassLoader();
} catch (Exception ex) {
// IOException constructor does not take a cause
IOException ioException = new IOException(
"Cannot look up class \"" + referenceClassName
+ "\" or get its ClassLoader.");
ioException.initCause(ex);
throw ioException;
}
}
 
// Use Thread.currentThread()... for Web Start.
URL result = classLoader.getResource(trimmedName);
 
if (result == null) {
throw new IOException("Cannot find file '" + trimmedName
+ "' in classpath");
}
 
return result;
}
 
File file = new File(name);
 
if (file.isAbsolute()) {
if (!file.canRead()) {
// FIXME: This is a hack.
// Expanding the configuration with Ptolemy II installed
// in a directory with spaces in the name fails on
// JAIImageReader because PtolemyII.jpg is passed in
// to this method as C:\Program%20Files\Ptolemy\...
file = new File(StringUtilities.substitute(name, "%20", " "));
 
URL possibleJarURL = null;
 
if (!file.canRead()) {
// ModelReference and FilePortParameters sometimes
// have paths that have !/ in them.
possibleJarURL = ClassUtilities.jarURLEntryResource(name);
 
if (possibleJarURL != null) {
file = new File(possibleJarURL.getFile());
}
}
 
if (!file.canRead()) {
throw new IOException("Cannot read file '"
+ name
+ "' or '"
+ StringUtilities.substitute(name, "%20", " ")
+ "'"
+ ((possibleJarURL == null) ? "" : (" or '"
+ possibleJarURL.getFile() + "")));
}
}
 
return file.toURI().toURL();
} else {
// Try relative to the base directory.
if (baseDirectory != null) {
// Try to resolve the URI.
URI newURI;
 
try {
newURI = baseDirectory.resolve(name);
} catch (Exception ex) {
// FIXME: Another hack
// This time, if we try to open some of the JAI
// demos that have actors that have defaults FileParameters
// like "$PTII/doc/img/PtolemyII.jpg", then resolve()
// bombs.
String name2 = StringUtilities.substitute(name, "%20", " ");
try {
newURI = baseDirectory.resolve(name2);
name = name2;
} catch (Exception ex2) {
IOException io = new IOException(
"Problem with URI format in '"
+ name
+ "'. "
+ "and '"
+ name2
+ "' "
+ "This can happen if the file name "
+ "is not absolute"
+ "and is not present relative to the "
+ "directory in which the specified model "
+ "was read (which was '"
+ baseDirectory + "')");
io.initCause(ex2);
throw io;
}
}
 
String urlString = newURI.toString();
 
try {
// Adding another '/' for remote execution.
if ((newURI.getScheme() != null)
&& (newURI.getAuthority() == null)) {
urlString = urlString.substring(0, 6) + "//"
+ urlString.substring(6);
 
//} else {
// urlString = urlString.substring(0, 6) + "/"
// + urlString.substring(6);
}
return new URL(urlString);
} catch (Exception ex3) {
try {
// Under Webstart, opening
// hoc/demo/ModelReference/ModelReference.xml
// requires this because the URL is relative.
return new URL(baseDirectory.toURL(), urlString);
} catch (Exception ex4) {
 
try {
// Under Webstart, ptalon, EightChannelFFT
// requires this.
return new URL(baseDirectory.toURL(), newURI.toString());
} catch (Exception ex5) {
// Ignore
}
 
IOException io = new IOException(
"Problem with URI format in '"
+ urlString
+ "'. "
+ "This can happen if the '"
+ urlString
+ "' is not absolute"
+ " and is not present relative to the directory"
+ " in which the specified model was read"
+ " (which was '" + baseDirectory + "')");
io.initCause(ex3);
throw io;
}
}
}
 
// As a last resort, try an absolute URL.
 
URL url = new URL(name);
 
// If we call new URL("http", null, /foo);
// then we get "http:/foo", which should be "http://foo"
// This change suggested by Dan Higgins and Kevin Kruland
// See kepler/src/util/URLToLocalFile.java
try {
String fixedURLAsString = url.toString().replaceFirst(
"(https?:)//?", "$1//");
url = new URL(fixedURLAsString);
} catch (Exception e) {
// Ignore
}
return url;
}
}
 
/** Open the specified file for reading. If the specified name is
* "System.in", then a reader from standard in is returned. If
* the name begins with "$CLASSPATH" or "xxxxxxCLASSPATHxxxxxx",
* then the name is passed to {@link #nameToURL(String, URI, ClassLoader)}
* If the file name is not absolute, the it is assumed to be relative to
* the specified base URI.
* @see #nameToURL(String, URI, ClassLoader)
* @param name File name.
* @param base The base URI for relative references.
* @param classLoader The class loader to use to locate system
* resources, or null to use the system class loader that was used
* to load this class.
* @return If the name is null or the empty string,
* then null is returned, otherwise a buffered reader is returned.
 
* @exception IOException If the file cannot be opened.
*/
public static BufferedReader openForReading(String name, URI base,
ClassLoader classLoader) throws IOException {
if ((name == null) || name.trim().equals("")) {
return null;
}
 
if (name.trim().equals("System.in")) {
if (STD_IN == null) {
STD_IN = new BufferedReader(new InputStreamReader(System.in));
}
 
return STD_IN;
}
 
 
 
// Not standard input. Try URL mechanism.
URL url = nameToURL(name, base, classLoader);
 
if (url == null) {
throw new IOException("Could not convert \"" + name
+ "\" with base \"" + base + "\" to a URL.");
}
 
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(url.openStream());
} catch (IOException ex) {
// Try it as a jar url.
// WebStart ptalon MapReduce needs this.
try {
URL possibleJarURL = ClassUtilities.jarURLEntryResource(url.toString());
if (possibleJarURL != null) {
inputStreamReader = new InputStreamReader(possibleJarURL.openStream());
}
// If possibleJarURL is null, this throws an exception,
// which we ignore and report the first exception (ex)
return new BufferedReader(inputStreamReader);
} catch (Exception ex2) {
try {
if (inputStreamReader != null) {
inputStreamReader.close();
}
} catch (IOException ex3) {
// Ignore
}
IOException ioException = new IOException("Failed to open \""
+ url + "\".");
ioException.initCause(ex);
throw ioException;
}
}
 
return new BufferedReader(inputStreamReader);
}
 
/** Open the specified file for writing or appending. If the
* specified name is "System.out", then a writer to standard out
* is returned; otherwise, pass the name and base to {@link
* #nameToFile(String, URI)} and create a file writer. If the
* file does not exist, then create it. If the file name is not
* absolute, the it is assumed to be relative to the specified
* base directory. If permitted, this method will return a
* Writer that will simply overwrite the contents of the file. It
* is up to the user of this method to check whether this is OK
* (by first calling {@link #nameToFile(String, URI)} and calling
* exists() on the returned value).
*
* @param name File name.
* @param base The base URI for relative references.
* @param append If true, then append to the file rather than
* overwriting.
* @return If the name is null or the empty string,
* then null is returned, otherwise a writer is returned.
* @exception IOException If the file cannot be opened
* or created.
*/
public static Writer openForWriting(String name, URI base, boolean append)
throws IOException {
if ((name == null) || name.trim().equals("")) {
return null;
}
 
if (name.trim().equals("System.out")) {
if (STD_OUT == null) {
STD_OUT = new PrintWriter(System.out);
}
 
return STD_OUT;
}
 
File file = nameToFile(name, base);
return new FileWriter(file, append);
}
 
///////////////////////////////////////////////////////////////////
//// public members ////
 
/** Standard in as a reader, which will be non-null
* only after a call to openForReading("System.in").
*/
public static BufferedReader STD_IN = null;
 
/** Standard out as a writer, which will be non-null
* only after a call to openForWriting("System.out").
*/
public static PrintWriter STD_OUT = null;
 
///////////////////////////////////////////////////////////////////
//// private methods ////
 
/** Copy files safely. If there are problems, the streams are
* close appropriately.
* @param inputStream The input stream.
* @param destinationFile The destination File.
* @exception IOException If the input stream cannot be created
* or read, or * if there is a problem writing to the destination
* file.
*/
private static void _binaryCopyStream(InputStream inputStream,
File destinationFile) throws IOException {
// Copy the source file.
BufferedInputStream input = null;
 
try {
input = new BufferedInputStream(inputStream);
 
BufferedOutputStream output = null;
 
try {
File parent = destinationFile.getParentFile();
if (parent != null && !parent.exists()) {
if (!parent.mkdirs()) {
throw new IOException("Failed to create directories "
+ "for \"" + parent + "\".");
}
}
 
output = new BufferedOutputStream(new FileOutputStream(
destinationFile));
 
int c;
 
while ((c = input.read()) != -1) {
output.write(c);
}
} finally {
if (output != null) {
try {
output.close();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
}
} finally {
if (input != null) {
try {
input.close();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
}
}
 
///////////////////////////////////////////////////////////////////
//// private members ////
 
/** Tag value used by this class and registered as a parser
* constant for the identifier "CLASSPATH" to indicate searching
* in the classpath. This is a hack, but it deals with the fact
* that Java is not symmetric in how it deals with getting files
* from the classpath (using getResource) and getting files from
* the file system.
*/
private static String _CLASSPATH_VALUE = "xxxxxxCLASSPATHxxxxxx";
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/util/ClassUtilities.java
0,0 → 1,180
/* Utilities used to manipulate classes
 
Copyright (c) 2003-2005 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
 
*/
package ptolemy.util;
 
import java.io.File;
import java.io.IOException;
import java.net.URL;
 
//////////////////////////////////////////////////////////////////////////
//// ClassUtilities
 
/**
A collection of utilities for manipulating classes.
These utilities do not depend on any other ptolemy.* packages.
 
 
@author Christopher Hylands
@version $Id: ClassUtilities.java,v 1.24 2005/10/24 19:09:12 cxh Exp $
@since Ptolemy II 4.0
@Pt.ProposedRating Green (cxh)
@Pt.AcceptedRating Green (cxh)
*/
public class ClassUtilities {
/** Instances of this class cannot be created.
*/
private ClassUtilities() {
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Lookup a jar URL and return the resource.
 
* A resource is a file such as a class file or image file that
* is found in the classpath. A jar URL is a URL that refers to
* a resource in a jar file. For example,
* <code>file://./foo.jar!/a/b/c.class</code> is a jar URL that
* refers to the <code>a/b/c.class</code> resource in
* <code>foo.jar</code>. If this method is called with
* <code>file://./foo.jar!/a/b/c.class</code> then it will return
* <code>a/b/c.class</code> if <code>a/b/c.class</code> can be
* found as a resource in the class loader that loaded this class
* (ptolemy.util.ClassUtilities). If the resource cannot be found,
* then an IOException is thrown. If the jarURLString parameter
* does not contain <code>!/</code>, then return null.
* Note that everything before the <code>!/</code> is removed before
* searching the classpath.
*
* <p>This method is necessary because Web Start uses jar URL, and
* there are some cases where if we have a jar URL, then we may
* need to strip off the jar:<i>url</i>!/ part so that we can
* search for the {entry} as a resource.
*
* @param jarURLString The string containing the jar URL.
* @return The resource, if any.If the spec string does not
* contain <code>!/</code>, then return null.
* @exception IOException If this method cannot convert the specification
* to a URL.
* @see java.net.JarURLConnection
*/
public static URL jarURLEntryResource(String jarURLString)
throws IOException {
// At first glance, it would appear that this method could appear
// in specToURL(), but the problem is that specToURL() creates
// a new URL with the spec, so it only does further checks if
// the URL is malformed. Unfortunately, in Web Start applications
// the URL will often refer to a resource in another jar file,
// which means that the jar url is not malformed, but there is
// no resource by that name. Probably specToURL() should return
// the resource after calling new URL().
int jarEntry = jarURLString.indexOf("!/");
 
if (jarEntry == -1) {
jarEntry = jarURLString.indexOf("!\\");
 
if (jarEntry == -1) {
return null;
}
}
 
try {
// !/ means that this could be in a jar file.
String entry = jarURLString.substring(jarEntry + 2);
 
// We might be in the Swing Event thread, so
// Thread.currentThread().getContextClassLoader()
// .getResource(entry) probably will not work.
Class refClass = Class.forName("ptolemy.util.ClassUtilities");
URL entryURL = refClass.getClassLoader().getResource(entry);
return entryURL;
} catch (Exception ex) {
// IOException constructor does not take a cause, so we add it.
IOException ioException = new IOException("Cannot find \""
+ jarURLString + "\".");
ioException.initCause(ex);
throw ioException;
}
}
 
/** Given a dot separated classname, return the jar file or directory
* where the class can be found.
* @param necessaryClass The dot separated class name, for example
* "ptolemy.util.ClassUtilities"
* @return If the class can be found as a resource, return the
* directory or jar file where the necessary class can be found.
* otherwise, return null. If the resource is found in a directory,
* then the return value will always have forward slashes, it will
* never use backslashes.
*/
public static String lookupClassAsResource(String necessaryClass) {
// This method is called from copernicus.kernel.GeneratorAttribute
// and actor.lib.python.PythonScript. We moved it here
// to avoid dependencies.
String necessaryResource = StringUtilities.substitute(necessaryClass,
".", "/")
+ ".class";
 
URL necessaryURL = Thread.currentThread().getContextClassLoader()
.getResource(necessaryResource);
 
if (necessaryURL != null) {
String resourceResults = necessaryURL.getFile();
 
// Strip off the file:/ and the necessaryResource.
if (resourceResults.startsWith("file:/")) {
resourceResults = resourceResults.substring(6);
}
 
// Strip off the name of the resource we were looking for
// so that we are left with the directory or jar file
// it is in
resourceResults = resourceResults.substring(0, resourceResults
.length()
- necessaryResource.length());
 
// Strip off the trailing !/
if (resourceResults.endsWith("!/")) {
resourceResults = resourceResults.substring(0, resourceResults
.length() - 2);
}
 
// Unfortunately, under Windows, URL.getFile() may
// return things like /c:/ptII, so we create a new
// File and get its path, which will return c:\ptII
File resourceFile = new File(resourceResults);
 
// Convert backslashes
String sanitizedResourceName = StringUtilities.substitute(
resourceFile.getPath(), "\\", "/");
return sanitizedResourceName;
}
 
return null;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/util/StringUtilities.java
0,0 → 1,1050
/* Utilities used to manipulate strings.
 
Copyright (c) 2002-2008 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
 
*/
package ptolemy.util;
 
// Note that classes in ptolemy.util do not depend on any
// other ptolemy packages.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
 
//////////////////////////////////////////////////////////////////////////
//// StringUtilities
 
/**
A collection of utilities for manipulating strings.
These utilities do not depend on any other ptolemy packages.
 
@author Christopher Brooks, Contributors: Teale Fristoe
@version $Id: StringUtilities.java,v 1.111 2008/01/24 02:07:35 cxh Exp $
@since Ptolemy II 2.1
@Pt.ProposedRating Green (eal)
@Pt.AcceptedRating Green (cxh)
*/
public class StringUtilities {
/** Instances of this class cannot be created.
*/
private StringUtilities() {
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Abbreviate a string.
* If the string is longer than 80 characters, truncate it by
* displaying the first 37 chars, then ". . .", then the last 38
* characters.
* If the <i>longName</i> argument is null, then the string
* "&gt;Unnamed&lt;" is returned.
* @param longName The string to be abbreviated.
* @return The possibly abbreviated name.
* @see #split(String)
*/
public static String abbreviate(String longName) {
// This method is used to abbreviate window titles so that long
// file names may appear in the window title bar. It is not
// parameterized so that we can force a unified look and feel.
// FIXME: it would be nice to split on a nearby space.
if (longName == null) {
return "<Unnamed>";
}
 
if (longName.length() <= 80) {
return longName;
}
 
return longName.substring(0, 37) + ". . ."
+ longName.substring(longName.length() - 38);
}
 
/** Return a string with a maximum line length of <i>length</i>
* characters, limited to the given number of characters.
* If there are more than 10 newlines, then the string is truncated
* after 10 lines.
* If the string is truncated, an ellipsis (three periods in a
* row: "...") will be appended to the end of the string.
* Lines that are longer than 160 characters are split into lines
* that are shorter than 160 characters.
* @param string The string to truncate.
* @param length The number of characters to which to truncate the string.
* @return The possibly truncated string with ellipsis possibly added.
*/
public static String ellipsis(String string, int length) {
// If necessary, insert newlines into long strings.
// If we don't do split long lines and we throw an exception
// with a very long line, then the window close button and
// possible the dismiss button will be off the right side of
// the screen.
// The number 160 was generated by trying different sizes and
// seeing what fits on a 1024 wide screen.
string = StringUtilities.split(string, 160);
 
// Third argument being true means return the delimiters as tokens.
StringTokenizer tokenizer = new StringTokenizer(string, LINE_SEPARATOR,
true);
 
// If there are more than 42 lines and 42 newlines, return
// truncate after the first 42 lines and newlines.
// This is necessary so that we can deal with very long lines
// of text without spaces.
if (tokenizer.countTokens() > 42) {
StringBuffer results = new StringBuffer();
 
for (int i = 0; (i < 42) && tokenizer.hasMoreTokens(); i++) {
results.append(tokenizer.nextToken());
}
 
results.append("...");
string = results.toString();
}
 
if (string.length() > length) {
return string.substring(0, length - 3) + "...";
}
 
return string;
}
 
/** Given a string, replace all the instances of XML special characters
* with their corresponding XML entities. This is necessary to
* allow arbitrary strings to be encoded within XML.
*
* <p>In this method, we make the following translations:
* <pre>
* &amp; becomes &amp;amp;
* " becomes &amp;quot;
* < becomes &amp;lt;
* > becomes &amp;gt;
* newline becomes &amp;#10;
* carriage return becomes $amp;#13;
* </pre>
* @see #unescapeForXML(String)
*
* @param string The string to escape.
* @return A new string with special characters replaced.
*/
public static String escapeForXML(String string) {
string = substitute(string, "&", "&amp;");
string = substitute(string, "\"", "&quot;");
string = substitute(string, "<", "&lt;");
string = substitute(string, ">", "&gt;");
string = substitute(string, "\n", "&#10;");
string = substitute(string, "\r", "&#13;"); // Carriage return
return string;
}
 
/** Given a string, return a string that when fed to the
* Ptolemy expression parser, will turn into the argument
* string. That is, replace all the instances of backslashes
* with double backslashes, all quotation marks with \",
* etc.
* For example
* <pre>
* x"y becomes x\"y;
* x\"y becomes x\\\"y;
* x\y"z becomes x\\y\"z;
* x\\y\"z becomes x\\\\y\\\"
* </pre>
* Similarly, this method replaces the following charaters
* exactly as defined in Java strings: \n, \t, \b, \r, and \f.
* @param string The string to escape.
* @return A new string with that can be put between quotation marks.
*/
public static String escapeString(String string) {
// Since the first string is a regular expression, it needs extra escaping.
// I have no idea why the extra escaping is needed on the second argument.
string = string.replaceAll("\\\\", "\\\\\\\\");
string = string.replaceAll("\"", "\\\\\"");
string = string.replaceAll("\n", "\\\\n");
string = string.replaceAll("\t", "\\\\t");
string = string.replaceAll("\b", "\\\\b");
string = string.replaceAll("\r", "\\\\r");
// Not needed.
// string = string.replaceAll("\'", "\\\\'");
return string;
}
 
/** If the ptolemy.ptII.exitAfterWrapup property is not set, then
* call System.exit().
* Ptolemy code should call this method instead of directly calling
* System.exit() so that we can test code that would usually exit.
* @param returnValue The return value of this process, where
* non-zero values indicate an error.
*/
public static void exit(int returnValue) {
if (StringUtilities.getProperty("ptolemy.ptII.exitAfterWrapup")
.length() > 0) {
throw new RuntimeException("Normally, we would "
+ "exit here because Manager.exitAfterWrapup() "
+ "was called. However, because the "
+ "ptolemy.ptII.exitAfterWrapup property "
+ "is set, we throw this exception instead.");
} else {
// Non-zero indicates a problem.
System.exit(returnValue);
}
}
 
/** Return a number of spaces that is proportional to the argument.
* If the argument is negative or zero, return an empty string.
* @param level The level of indenting represented by the spaces.
* @return A string with zero or more spaces.
*/
public static String getIndentPrefix(int level) {
if (level <= 0) {
return "";
}
 
StringBuffer result = new StringBuffer(level * 4);
 
for (int i = 0; i < level; i++) {
result.append(" ");
}
 
return result.toString();
}
 
/** Get the specified property from the environment. An empty
* string is returned if the property named by the "propertyName"
* argument environment variable does not exist, though if
* certain properties are not defined, then we make various
* attempts to determine them and then set them. See the javadoc
* page for java.util.System.getProperties() for a list of system
* properties.
 
* <p>The following properties are handled specially
* <dl>
* <dt> "ptolemy.ptII.dir"
* <dd> vergil usually sets the ptolemy.ptII.dir property to the
* value of $PTII. However, if we are running under Web Start,
* then this property might not be set, in which case we look
* for "ptolemy/util/StringUtilities.class" and set the
* property accordingly.
* <dt> "ptolemy.ptII.dirAsURL"
* <dd> Return $PTII as a URL. For example, if $PTII was c:\ptII,
* then return file:/c:/ptII/.
* <dt> "user.dir"
* <dd> Return the canonical path name to the current working
* directory. This is necessary because under Windows with
* JDK1.4.1, the System.getProperty() call returns
* <code><b>c</b>:/<i>foo</i></code> whereas most of the other
* methods that operate on path names return
* <code><b>C</b>:/<i>foo</i></code>.
* </dl>
* @param propertyName The name of property.
* @return A String containing the string value of the property.
* If the property is not found, then we return the empty string.
*/
public static String getProperty(String propertyName) {
// NOTE: getProperty() will probably fail in applets, which
// is why this is in a try block.
String property = null;
 
try {
property = System.getProperty(propertyName);
} catch (SecurityException ex) {
if (!propertyName.equals("ptolemy.ptII.dir")) {
// Constants.java depends on this when running with
// -sandbox.
SecurityException security = new SecurityException(
"Could not find '" + propertyName + "' System property");
security.initCause(ex);
throw security;
}
}
 
if (propertyName.equals("user.dir")) {
try {
File userDirFile = new File(property);
return userDirFile.getCanonicalPath();
} catch (IOException ex) {
return property;
}
}
 
// Check for cases where the ptII property starts with
// the string "/cygdrive". This can happen if the property
// was set by doing "PTII=`pwd`" under Cygwin bash.
if (property != null) {
if (propertyName.equals("ptolemy.ptII.dir")
&& property.startsWith("/cygdrive")
&& !_printedCygwinWarning) {
// This error only occurs when users build their own,
// so it is safe to print to stderr
_printedCygwinWarning = true;
System.err.println("ptolemy.ptII.dir property = \"" + property
+ "\", which contains \"cygdrive\". "
+ "This is almost always an error under Cygwin that "
+ "is occurs when one does PTII=`pwd`. Instead, do "
+ "PTII=c:/foo/ptII");
}
 
return property;
}
 
if (propertyName.equals("ptolemy.ptII.dirAsURL")) {
// Return $PTII as a URL. For example, if $PTII was c:\ptII,
// then return file:/c:/ptII/
File ptIIAsFile = new File(getProperty("ptolemy.ptII.dir"));
 
try {
// Convert first to a URI, then to a URL so that we
// properly handle cases where $PTII has spaces in it.
URI ptIIAsURI = ptIIAsFile.toURI();
URL ptIIAsURL = ptIIAsURI.toURL();
return ptIIAsURL.toString();
} catch (java.net.MalformedURLException malformed) {
throw new RuntimeException("While trying to find '"
+ propertyName + "', could not convert '" + ptIIAsFile
+ "' to a URL", malformed);
}
}
 
if (propertyName.equals("ptolemy.ptII.dir")) {
if (_ptolemyPtIIDir != null) {
// Return the previously calculated value
return _ptolemyPtIIDir;
} else {
String stringUtilitiesPath = "ptolemy/util/StringUtilities.class";
 
// PTII variable was not set
URL namedObjURL = Thread.currentThread()
.getContextClassLoader().getResource(
stringUtilitiesPath);
 
if (namedObjURL != null) {
// Get the file portion of URL
String namedObjFileName = namedObjURL.getFile();
 
// FIXME: How do we get from a URL to a pathname?
if (namedObjFileName.startsWith("file:")) {
if (namedObjFileName.startsWith("file:/")
|| namedObjFileName.startsWith("file:\\")) {
// We get rid of either file:/ or file:\
namedObjFileName = namedObjFileName.substring(6);
} else {
// Get rid of file:
namedObjFileName = namedObjFileName.substring(5);
}
}
 
String abnormalHome = namedObjFileName.substring(0,
namedObjFileName.length()
- stringUtilitiesPath.length());
 
// abnormalHome will have values like: "/C:/ptII/"
// which cause no end of trouble, so we construct a File
// and call toString().
_ptolemyPtIIDir = (new File(abnormalHome)).toString();
 
// If we are running under Web Start, then strip off
// the trailing "!"
if (_ptolemyPtIIDir.endsWith("/!")
|| _ptolemyPtIIDir.endsWith("\\!")) {
_ptolemyPtIIDir = _ptolemyPtIIDir.substring(0,
_ptolemyPtIIDir.length() - 1);
}
 
// Web Start, we might have
// RMptsupport.jar or
// XMptsupport.jar1088483703686
String ptsupportJarName = File.separator + "DMptolemy"
+ File.separator + "RMptsupport.jar";
 
if (_ptolemyPtIIDir.endsWith(ptsupportJarName)) {
_ptolemyPtIIDir = _ptolemyPtIIDir.substring(0,
_ptolemyPtIIDir.length()
- ptsupportJarName.length());
} else {
ptsupportJarName = "/DMptolemy/XMptsupport.jar";
 
if (_ptolemyPtIIDir.lastIndexOf(ptsupportJarName) != -1) {
_ptolemyPtIIDir = _ptolemyPtIIDir.substring(0,
_ptolemyPtIIDir
.lastIndexOf(ptsupportJarName));
} else {
// Ptolemy II 6.0.1 under Windows: remove
// "\ptolemy\ptsupport.jar!"
// If we don't do this, then ptolemy.ptII.dir
// is set incorrectly and then links to the javadoc
// files will not be found if the javadoc only
// exists in codeDoc.jar and lib/ptII.properties
// is not present.
ptsupportJarName = File.separator + "ptolemy"
+ File.separator + "ptsupport.jar";
 
if (_ptolemyPtIIDir.lastIndexOf(ptsupportJarName) != -1) {
_ptolemyPtIIDir = _ptolemyPtIIDir.substring(0,
_ptolemyPtIIDir
.lastIndexOf(ptsupportJarName));
}
}
}
}
 
// Convert %20 to spaces because if a URL has %20 in it,
// then we know we have a space, but file names do not
// recognize %20 as being a single space, instead file names
// see %20 as three characters: '%', '2', '0'.
if (_ptolemyPtIIDir != null) {
_ptolemyPtIIDir = StringUtilities.substitute(
_ptolemyPtIIDir, "%20", " ");
}
 
if (_ptolemyPtIIDir == null) {
throw new RuntimeException("Could not find "
+ "'ptolemy.ptII.dir'" + " property. "
+ "Also tried loading '" + stringUtilitiesPath
+ "' as a resource and working from that. "
+ "Vergil should be "
+ "invoked with -Dptolemy.ptII.dir" + "=\"$PTII\"");
}
 
try {
// Here, we set the property so that future updates
// will get the correct value.
System.setProperty("ptolemy.ptII.dir", _ptolemyPtIIDir);
} catch (SecurityException security) {
// Ignore, we are probably running as an applet or -sandbox
}
 
return _ptolemyPtIIDir;
}
}
 
// If the property is not set then we return the empty string.
if (property == null) {
return "";
}
 
return property;
}
 
/** Merge the properties in lib/ptII.properties with the current
* properties. lib/ptII.properties is searched for in the
* classpath. The value of properties listed in
* lib/ptII.properties do not override properties with the same
* name in the current properties.
* @exception IOException If thrown while looking for the
* $CLASSPATH/lib/ptII.properties file.
*/
public static void mergePropertiesFile() throws IOException {
Properties systemProperties = System.getProperties();
Properties newProperties = new Properties();
String propertyFileName = "$CLASSPATH/lib/ptII.properties";
 
// FIXME: xxxxxxCLASSPATHxxxxxx is an ugly hack
URL propertyFileURL = FileUtilities.nameToURL(
"xxxxxxCLASSPATHxxxxxx/lib/ptII.properties", null, null);
 
if (propertyFileURL == null) {
throw new IOException("Could not find " + propertyFileName);
}
 
newProperties.load(propertyFileURL.openStream());
 
// systemProperties is a HashSet, so we merge in the new properties.
newProperties.putAll(systemProperties);
System.setProperties(newProperties);
// FIXME: This should be logged, not printed.
//System.out.println("Loaded " + propertyFileURL);
}
 
/** Return a string representing the name of the file expected to
* contain the source code for the specified object. This method
* simply replaces "." with "/" and appends ".java" to the class
* name.
* @param object The object.
* @return The expected source file name.
*/
public static String objectToSourceFileName(Object object) {
String sourceFileNameBase = object.getClass().getName().replace('.',
'/');
 
// Inner classes: Get rid of everything past the first $
if (sourceFileNameBase.indexOf("$") != -1) {
sourceFileNameBase = sourceFileNameBase.substring(0,
sourceFileNameBase.indexOf("$"));
}
 
return sourceFileNameBase + ".java";
}
 
/** Return the preferences directory, creating it if necessary.
* @return A string naming the preferences directory. The last
* character of the string will have the file.separator character
* appended.
* @exception IOException If the directory could not be created.
* @see #PREFERENCES_DIRECTORY
*/
public static String preferencesDirectory() throws IOException {
String preferencesDirectoryName = StringUtilities
.getProperty("user.home")
+ File.separator
+ StringUtilities.PREFERENCES_DIRECTORY
+ File.separator;
File preferencesDirectory = new File(preferencesDirectoryName);
 
if (!preferencesDirectory.isDirectory()) {
if (preferencesDirectory.mkdirs() == false) {
throw new IOException("Could not create user preferences "
+ "directory '" + preferencesDirectoryName + "'");
}
}
 
return preferencesDirectoryName;
}
 
/** Return the name of the properties file.
* The properties file is a file of a format suitable for
* java.util.properties.load(InputStream).
* The file is named "ptII.properties" and is found in the
* {@link #PREFERENCES_DIRECTORY} directory that is returned
* by {@link #preferencesDirectory()}. Typically, this value
* is "$HOME/.ptolemyII/ptII.properties".
* @see #preferencesDirectory()
* @see #PREFERENCES_DIRECTORY
* @return The name of the properties file.
* @exception IOException If {@link #preferencesDirectory()} throws it.
*/
public static String propertiesFileName() throws IOException {
return preferencesDirectory() + "ptII.properties";
}
 
/** Return a LinkedList of the lines in a string that aren't comments.
* @param lines A String containing the lines to be separated.
* @return A LinkedList of the lines that aren't comments.
* @exception IOException If thrown when reading from the input String.
*/
public static LinkedList readLines(String lines) throws IOException {
BufferedReader bufferedReader = null;
LinkedList returnList = new LinkedList();
String line;
bufferedReader = new BufferedReader(new StringReader(lines));
try {
// Read line by line, skipping comments.
while ((line = bufferedReader.readLine()) != null) {
line = line.trim();
if (!(line.length() == 0 || line.startsWith("/*") || line
.startsWith("//"))) {
returnList.add(line);
}
}
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
// Ignore
ex.printStackTrace();
}
}
}
return returnList;
}
 
/** Sanitize a String so that it can be used as a Java identifier.
* Section 3.8 of the Java language spec says:
* <blockquote>
* "An identifier is an unlimited-length sequence of Java letters
* and Java digits, the first of which must be a Java letter. An
* identifier cannot have the same spelling (Unicode character
* sequence) as a keyword (3.9), boolean literal (3.10.3), or
* the null literal (3.10.7)."
* </blockquote>
* Java characters are A-Z, a-z, $ and _.
* <p> Characters that are not permitted in a Java identifier are changed
* to underscores.
* This method does not check that the returned string is a
* keyword or literal.
* Note that two different strings can sanitize to the same
* string.
* This method is commonly used during code generation to map the
* name of a ptolemy object to a valid identifier name.
* @param name A string with spaces and other characters that
* cannot be in a Java name.
* @return A String that follows the Java identifier rules.
*/
public static String sanitizeName(String name) {
char[] nameArray = name.toCharArray();
 
for (int i = 0; i < nameArray.length; i++) {
if (!Character.isJavaIdentifierPart(nameArray[i])) {
nameArray[i] = '_';
}
}
 
if (nameArray.length == 0) {
return "";
} else {
if (!Character.isJavaIdentifierStart(nameArray[0])) {
return "_" + new String(nameArray);
} else {
return new String(nameArray);
}
}
}
 
/** If the string is longer than 79 characters, split it up by
* adding newlines in all newline delimited substrings
* that are longer than 79 characters.
* If the <i>longName</i> argument is null, then the string
* "&gt;Unnamed&lt;" is returned.
* @see #abbreviate(String)
* @see #split(String, int)
* @param longName The string to optionally split up
* @return Either the original string, or the string with newlines
* inserted.
*/
public static String split(String longName) {
return split(longName, 79);
}
 
/** If the string is longer than <i>length</i> characters,
* split the string up by adding newlines in all
* newline delimited substrings that are longer than <i>length</i>
* characters.
* If the <i>longName</i> argument is null, then the string
* "&gt;Unnamed&lt;" is returned.
* @see #abbreviate(String)
* @see #split(String)
* @param longName The string to optionally split.
* @param length The maximum length of the sequence of characters
* before a newline is inserted.
* @return Either the original string, or the string with newlines
* inserted.
*/
public static String split(String longName, int length) {
if (longName == null) {
return "<Unnamed>";
}
 
if (longName.length() <= length) {
return longName;
}
 
StringBuffer results = new StringBuffer();
 
// The third argument is true, which means return the delimiters
// as part of the tokens.
StringTokenizer tokenizer = new StringTokenizer(longName,
LINE_SEPARATOR, true);
 
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
int mark = 0;
 
while (mark < (token.length() - length)) {
// We look for the space from the end of the first length
// characters. If we find one, then we use that
// as the place to insert a newline.
int lastSpaceIndex = token.substring(mark, mark + length)
.lastIndexOf(" ");
 
if (lastSpaceIndex < 0) {
// No space found, just insert a new line after length
results.append(token.substring(mark, mark + length)
+ LINE_SEPARATOR);
mark += length;
} else {
results.append(token.substring(mark, mark + lastSpaceIndex)
+ LINE_SEPARATOR);
mark += (lastSpaceIndex + 1);
}
}
 
results.append(token.substring(mark));
}
 
return results.toString();
}
 
/** Given a file or URL name, return as a URL. If the file name
* is relative, then it is interpreted as being relative to the
* specified base directory. If the name begins with
* "xxxxxxCLASSPATHxxxxxx" or "$CLASSPATH"
* then search for the file relative to the classpath.
* Note that this is the value of the globally defined constant
* $CLASSPATH available in the expression language.
* If no file is found, then throw an exception.
* @param name The name of a file or URL.
* @param baseDirectory The base directory for relative file names,
* or null to specify none.
* @param classLoader The class loader to use to locate system
* resources, or null to use the system class loader.
* @return A URL, or null if no file name or URL has been specified.
* @exception IOException If the file cannot be read, or
* if the file cannot be represented as a URL (e.g. System.in), or
* the name specification cannot be parsed.
* @exception MalformedURLException If the URL is malformed.
* @deprecated Use FileUtilities.nameToURL instead.
*/
public static URL stringToURL(String name, URI baseDirectory,
ClassLoader classLoader) throws IOException {
return FileUtilities.nameToURL(name, baseDirectory, classLoader);
}
 
/** Replace all occurrences of <i>pattern</i> in the specified
* string with <i>replacement</i>. Note that the pattern is NOT
* a regular expression, and that relative to the
* String.replaceAll() method in jdk1.4, this method is extremely
* slow. This method does not work well with back slashes.
* @param string The string to edit.
* @param pattern The string to replace.
* @param replacement The string to replace it with.
* @return A new string with the specified replacements.
*/
public static String substitute(String string, String pattern,
String replacement) {
int start = string.indexOf(pattern);
 
while (start != -1) {
StringBuffer buffer = new StringBuffer(string);
buffer.delete(start, start + pattern.length());
buffer.insert(start, replacement);
string = new String(buffer);
start = string.indexOf(pattern, start + replacement.length());
}
 
return string;
}
 
/** Perform file prefix substitution.
* If <i>string</i> starts with <i>prefix</i>, then we return a
* new string that consists of the value or <i>replacement</i>
* followed by the value of <i>string</i> with the value of
* <i>prefix</i> removed. For example,
* substituteFilePrefix("c:/ptII", "c:/ptII/ptolemy, "$PTII")
* will return "$PTII/ptolemy"
*
* <p>If <i>prefix</i> is not a simple prefix of <i>string</i>, then
* we use the file system to find the canonical names of the files.
* For this to work, <i>prefix</i> and <i>string</i> should name
* files that exist, see java.io.File.getCanonicalFile() for details.
*
* <p>If <i>prefix</i> is not a prefix of <i>string</i>, then
* we return <i>string</i>
*
* @param prefix The prefix string, for example, "c:/ptII".
* @param string The string to be substituted, for example,
* "c:/ptII/ptolemy".
* @param replacement The replacement to be substituted in, for example,
* "$PTII"
* @return The possibly substituted string.
*/
public static String substituteFilePrefix(String prefix, String string,
String replacement) {
// This method is currently used by $PTII/util/testsuite/auto.tcl
if (string.startsWith(prefix)) {
// Hmm, what about file separators?
return replacement + string.substring(prefix.length());
} else {
try {
String prefixCanonicalPath = (new File(prefix))
.getCanonicalPath();
 
String stringCanonicalPath = (new File(string))
.getCanonicalPath();
 
if (stringCanonicalPath.startsWith(prefixCanonicalPath)) {
return replacement
+ stringCanonicalPath.substring(prefixCanonicalPath
.length());
}
} catch (Throwable throwable) {
// ignore.
}
}
 
return string;
}
 
/** Tokenize a String to an array of Strings for use with
* Runtime.exec(String []).
*
* <p>Lines that begin with an octothorpe '#' are ignored.
* Substrings that start and end with a double quote are considered
* to be a single token and are returned as a single array element.
*
* @param inputString The String to tokenize
* @return An array of substrings.
* @exception IOException If StreamTokenizer.nextToken() throws it.
*/
public static String[] tokenizeForExec(String inputString)
throws IOException {
// The java.lang.Runtime.exec(String command) call uses
// java.util.StringTokenizer() to parse the command string.
// Unfortunately, this means that double quotes are not handled
// in the same way that the shell handles them in that 'ls "foo
// 'bar"' will interpreted as three tokens 'ls', '"foo' and
// 'bar"'. In the shell, the string would be two tokens 'ls' and
// '"foo bar"'. What is worse is that the exec() behaviour is
// slightly different under Windows and Unix. To solve this
// problem, we preprocess the command argument using
// java.io.StreamTokenizer, which converts quoted substrings into
// single tokens. We then call java.lang.Runtime.exec(String []
// commands);
// Parse the command into tokens
List commandList = new LinkedList();
 
StreamTokenizer streamTokenizer = new StreamTokenizer(new StringReader(
inputString));
 
// We reset the syntax so that we don't convert to numbers,
// otherwise, if PTII is "d:\\tmp\\ptII\ 2.0", then
// we have no end of problems.
streamTokenizer.resetSyntax();
streamTokenizer.whitespaceChars(0, 32);
streamTokenizer.wordChars(33, 127);
 
// We can't use quoteChar here because it does backslash
// substitution, so "c:\ptII" ends up as "c:ptII"
// Substituting forward slashes for backward slashes seems like
// overkill.
// streamTokenizer.quoteChar('"');
streamTokenizer.ordinaryChar('"');
 
streamTokenizer.eolIsSignificant(true);
 
streamTokenizer.commentChar('#');
 
// Current token
String token = "";
 
// Single character token, usually a -
String singleToken = "";
 
// Set to true if we are inside a double quoted String.
boolean inDoubleQuotedString = false;
 
while (streamTokenizer.nextToken() != StreamTokenizer.TT_EOF) {
switch (streamTokenizer.ttype) {
case StreamTokenizer.TT_WORD:
 
if (inDoubleQuotedString) {
if (token.length() > 0) {
// FIXME: multiple spaces will get compacted here
token += " ";
}
 
token += (singleToken + streamTokenizer.sval);
} else {
token = singleToken + streamTokenizer.sval;
commandList.add(token);
}
 
singleToken = "";
break;
 
case StreamTokenizer.TT_NUMBER:
throw new RuntimeException("Internal error: Found TT_NUMBER: '"
+ streamTokenizer.nval + "'. We should not be "
+ "tokenizing numbers");
 
//break;
case StreamTokenizer.TT_EOL:
case StreamTokenizer.TT_EOF:
break;
 
default:
singleToken = Character.toString((char) streamTokenizer.ttype);
 
if (singleToken.equals("\"")) {
if (inDoubleQuotedString) {
commandList.add(token);
}
 
inDoubleQuotedString = !inDoubleQuotedString;
singleToken = "";
token = "";
}
 
break;
}
}
 
return (String[]) commandList.toArray(new String[commandList.size()]);
}
 
/** Return a string with a maximum line length of <i>lineLength</i>
* and a maximum number of lines <i>numberOfLines</i>.
* Each line that exceeds the line length is replaced with a line that
* ends with "...". If the number of lines exceeds <i>numberOfLines</i>,
* then the returned string will have exactly <i>numberOfLines</i> lines
* where the last line is "...".
* @param string The string to truncate.
* @param lineLength The number of characters to which to truncate each line.
* @param numberOfLines The maximum number of lines.
* @return The possibly truncated string with ellipsis possibly added.
*/
public static String truncateString(String string, int lineLength,
int numberOfLines) {
 
// Third argument being true means the delimiters (LINE_SEPARATOR) are
// included in as tokens in the parsed results.
StringTokenizer tokenizer = new StringTokenizer(string, LINE_SEPARATOR,
true);
 
StringBuffer results = new StringBuffer();
// Count the lines + newlines.
int lineCount = 0;
while (tokenizer.hasMoreTokens()) {
if (lineCount >= numberOfLines * 2) {
// Presumably, the last line is a line separator.
// We append an additional line to indicate that there
// are more lines.
results.append("...");
break;
}
lineCount++;
String line = tokenizer.nextToken();
if (line.length() > lineLength) {
line = line.substring(0, lineLength - 3) + "...";
}
results.append(line);
}
return results.toString();
}
 
/** Given a string, replace all the instances of XML entities
* with their corresponding XML special characters. This is necessary to
* allow arbitrary strings to be encoded within XML.
*
* <p>In this method, we make the following translations:
* <pre>
* &amp;amp; becomes &amp
* &amp;quot; becomes "
* &amp;lt; becomes <
* &amp;gt; becomes >
* &amp;#10; becomes newline
* &amp;#13; becomes carriage return
* </pre>
* @see #escapeForXML(String)
*
* @param string The string to escape.
* @return A new string with special characters replaced.
*/
public static String unescapeForXML(String string) {
string = substitute(string, "&amp;", "&");
string = substitute(string, "&quot;", "\"");
string = substitute(string, "&lt;", "<");
string = substitute(string, "&gt;", ">");
string = substitute(string, "&#10;", "\n");
string = substitute(string, "&#13;", "\r");
return string;
}
 
/** Return a string that contains a description of how to use a
* class that calls this method. For example, this method is
* called by "$PTII/bin/vergil -help".
* @param commandTemplate A string naming the command and the
* format of the arguments, for example
* "moml [options] [file . . .]"
* @param commandOptions A 2xN array of Strings that list command-line
* options that take arguments where the first
* element is a String naming the command line option, and the
* second element is the argument, for example
* <code>{"-class", "<classname>")</code>
* @param commandFlags An array of Strings that list command-line
* options that are either present or not.
* @return A string that describes the command.
*/
public static String usageString(String commandTemplate,
String[][] commandOptions, String[] commandFlags) {
// This method is static so that we can reuse it in places
// like copernicus/kernel/Copernicus and actor/gui/MoMLApplication
StringBuffer result = new StringBuffer("Usage: " + commandTemplate
+ "\n\n" + "Options that take values:\n");
 
int i;
 
for (i = 0; i < commandOptions.length; i++) {
result.append(" " + commandOptions[i][0] + " "
+ commandOptions[i][1] + "\n");
}
 
result.append("\nBoolean flags:\n");
 
for (i = 0; i < commandFlags.length; i++) {
result.append(" " + commandFlags[i]);
}
 
return result.toString();
}
 
///////////////////////////////////////////////////////////////////
//// public variables ////
// If you change these, be sure to try running vergil on
// a HSIF moml file
// vergil ../hsif/demo/SwimmingPool/SwimmingPool.xml
 
/** Maximum length in characters of a long string before
* {@link #ellipsis(String, int)} truncates and add a
* trailing ". . .". This variable is used by callers
* of ellipsis(String, int).
*/
public static final int ELLIPSIS_LENGTH_LONG = 2000;
 
/** Maximum length in characters of a short string before
* {@link #ellipsis(String, int)} truncates and add a
* trailing ". . .". This variable is used by callers
* of ellipsis(String, int).
*/
public static final int ELLIPSIS_LENGTH_SHORT = 400;
 
/** The line separator string. Under Windows, this would
* be "\r\n"; under Unix, "\n"; Under Macintosh, "\r".
*/
public static final String LINE_SEPARATOR = System
.getProperty("line.separator");
 
/** Location of Application preferences such as the user library.
* This field is not final in case other applications want to
* set it to a different directory.
* @see #preferencesDirectory()
*/
public static String PREFERENCES_DIRECTORY = ".ptolemyII";
 
///////////////////////////////////////////////////////////////////
//// private variables ////
 
/** Set to true if we print the cygwin warning in getProperty(). */
private static boolean _printedCygwinWarning = false;
 
/** Cached value of ptolemy.ptII.dir property. */
private static String _ptolemyPtIIDir = null;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/EditListener.java
0,0 → 1,56
/* Interface for listeners that are informed of plot edit events.
 
Copyright (c) 1998-2005 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
 
*/
package ptolemy.plot;
 
//////////////////////////////////////////////////////////////////////////
//// EditListener
 
/**
Interface for listeners that are informed of plot edit events.
These events are generated when a user modifies the plot data using
interactive facilities of an editable subclass of Plot.
 
@author Edward A. Lee
@version $Id: EditListener.java,v 1.13 2005/07/08 19:59:33 cxh Exp $
@since Ptolemy II 0.4
@Pt.ProposedRating Red (eal)
@Pt.AcceptedRating Red (cxh)
@see EditablePlot
 
*/
public interface EditListener {
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Notify that data in the specified plot has been modified
* by a user edit action.
* @param source The plot containing the modified data.
* @param dataset The data set that has been modified.
*/
public void editDataModified(EditablePlot source, int dataset);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/img/reset.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/img/fill.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/img/format.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/img/print.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/Histogram.java
0,0 → 1,871
/* A histogram plotter.
 
@Copyright (c) 1997-2007 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.awt.Graphics;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Random;
import java.util.Vector;
 
//////////////////////////////////////////////////////////////////////////
//// Histogram
 
/**
A histogram plotter. The plot can be configured and data can
be provided either through a file with commands or through direct
invocation of the public methods of the class. To read a file or a
URL, use the read() method.
<p>
When calling the public methods, in most cases the changes will not
be visible until paint() has been called. To request that this
be done, call repaint(). One exception is addPoint(), which
makes the affect of the new point visible immediately (or nearly
immediately) if the plot is visible on the screen.
<p>
The ASCII format for the file file contains any number commands,
one per line. Unrecognized commands and commands with syntax
errors are ignored. Comments are denoted by a line starting with a
pound sign "#". The recognized commands include those supported by
the base class, plus a few more. The commands are case
insensitive, but are usually capitalized. The number of data sets
to be plotted does not need to be specified. Data sets are added as needed.
Each dataset is identified with a color (see the base class).
<P>
The appearance of the histogram can be altered by the following commands:
<pre>
Bars: <i>width</i>
Bars: <i>width, offset</i>
</pre>
The <i>width</i> is a real number specifying the width of the bars
as a fraction of the bin width. It usually has a value less than
or equal to one,
and defaults to 0.5. The <i>offset</i> is a real number
specifying how much the bar of the <i>i </i><sup>th</sup> data set
is offset from the previous one. This allows bars to "peek out"
from behind the ones in front. It defaults to 0.15.
Note that the frontmost data set will be the first one.
<p>
The width of each bin of the histogram can be specified using:
<pre>
BinWidth: <i>width</i>
</pre>
This is given in whatever units the data has.
By default, each bin is centered at <i>x</i> = <i>nw</i>,
where <i>w</i> is the width of the bin and <i>n</i> is an integer.
That bin represents values in the range (<i>x - w/2, x + w/2</i>).
The alignment of the bins can be changed with the following command:
<pre>
BinOffset: <i>offset</i>
</pre>
If this method is used with argument <i>o</i>, then each bin is
centered at <i>x = nw + o</i>, and represents values in the range
(<i>x - w/2 + o, x + w/2 + o</i>). So for example, if <i>o = w/2</i>,
then each bin represents values from <i>nw</i> to
(<i>n</i> + 1)<i>w</i> for some integer <i>n</i>.
The default offset is 0.5, half the default bin width.
<p>
To specify data to be plotted, start a data set with the following command:
<pre>
DataSet: <i>string</i>
</pre>
Here, <i>string</i> is a label that will appear in the legend.
It is not necessary to enclose the string in quotation marks.
To start a new dataset without giving it a name, use:
<pre>
DataSet:
</pre>
In this case, no item will appear in the legend.
New datasets are plotted <i>behind</i> the previous ones.
The data itself is given by a sequence of numbers, one per line.
The numbers are specified as
strings that can be parsed by the Double parser in Java.
It is also possible to specify the numbers using all the formats
accepted by the Plot class, so that the same data may be plotted by
both classes. The <i>x</i> data is ignored, and only the <i>y</i>
data is used to calculate the histogram.
 
@author Edward A. Lee
@version $Id: Histogram.java,v 1.50 2007/12/06 18:23:52 cxh Exp $
@since Ptolemy II 0.3
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class Histogram extends PlotBox {
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Add a legend (displayed at the upper right) for the specified
* data set with the specified string. Short strings generally
* fit better than long strings.
* @param dataset The dataset index.
* @param legend The label for the dataset.
*/
public void addLegend(int dataset, String legend) {
_checkDatasetIndex(dataset);
super.addLegend(dataset, legend);
}
 
/** In the specified data set, add the specified value to the
* histogram. Data set indices begin with zero. If the data set
* does not exist, create it.
* The new point will visibly alter the histogram if the plot is visible
* on the screen. Otherwise, it will be drawn the next time the histogram
* is drawn on the screen.
* <p>
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the point will
* not be added immediately (unless you call this method from within
* the event dispatch thread). All the methods that do this deferring
* coordinate so that they are executed in the order that you
* called them.
*
* @param dataset The data set index.
* @param value The new value.
*/
public synchronized void addPoint(final int dataset, final double value) {
Runnable doAddPoint = new Runnable() {
public void run() {
_addPoint(dataset, value);
}
};
 
deferIfNecessary(doAddPoint);
}
 
/** In the specified data set, add the specified y value to the
* histogram. The x value and the <i>connected</i> arguments are
* ignored. Data set indices begin with zero. If the data set
* does not exist, create it.
* @param dataset The data set index.
* @param x Ignored.
* @param y The Y position of the new point.
* @param connected Ignored
*/
public synchronized void addPoint(int dataset, double x, double y,
boolean connected) {
addPoint(dataset, y);
}
 
/** Clear the plot of all data points. If the argument is true, then
* reset all parameters to their initial conditions, including
* the persistence, plotting format, and axes formats.
* For the change to take effect, you must call repaint().
* <p>
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the clear will
* not be executed immediately (unless you call this method from within
* the event dispatch thread). All the methods that do this deferring
* coordinate so that they are executed in the order that you
* called them.
*
* @param format If true, clear the format controls as well.
*/
public synchronized void clear(final boolean format) {
Runnable doClear = new Runnable() {
public void run() {
_clear(format);
}
};
 
deferIfNecessary(doClear);
}
 
/** Write plot data information to the specified output stream in PlotML,
* but in such a way that the Plot class can read it and reproduce the
* histogram. The ordinary mechanism for saving the histogram
* records the raw data and the configuration to be used by this class.
* @param output A buffered print writer.
* @param dtd The DTD, or null to reference the default.
*/
public synchronized void exportToPlot(PrintWriter output, String dtd) {
if (dtd == null) {
output.println("<?xml version=\"1.0\" standalone=\"yes\"?>");
output
.println("<!DOCTYPE plot PUBLIC \"-//UC Berkeley//DTD PlotML 1//EN\"");
output
.println(" \"http://ptolemy.eecs.berkeley.edu/xml/dtd/PlotML_1.dtd\">");
} else {
output.println("<?xml version=\"1.0\" standalone=\"no\"?>");
output.println("<!DOCTYPE plot SYSTEM \"" + dtd + "\">");
}
 
output.println("<plot>");
output.println("<!-- Ptolemy plot, version " + PTPLOT_RELEASE
+ " , PlotML format. Exported from Histogram. -->");
 
super.writeFormat(output);
output.println("<barGraph width=\"" + (_barwidth * _binWidth)
+ "\" offset=\"" + (_baroffset * _binWidth) + "\"/>");
 
for (int dataset = 0; dataset < _points.size(); dataset++) {
// Write the dataset directive
String legend = getLegend(dataset);
 
if (legend != null) {
output.println("<dataset name=\"" + legend
+ "\" connected=\"no\">");
} else {
output.println("<dataset connected=\"no\">");
}
 
Hashtable data = (Hashtable) _histogram.elementAt(dataset);
Enumeration keys = data.keys();
 
while (keys.hasMoreElements()) {
Integer bin = (Integer) keys.nextElement();
Integer count = (Integer) data.get(bin);
 
// The X axis value is a bit complex to get.
int xValue = (int) ((bin.intValue() * _binWidth) + _binOffset);
output.println("<p x=\"" + xValue + "\" y=\""
+ count.intValue() + "\"/>");
}
 
output.println("</dataset>");
}
 
output.println("</plot>");
output.flush();
}
 
/** Rescale so that the data that is currently plotted just fits.
* This overrides the base class method to ensure that the
* fill is actually performed in the event dispatch thread.
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the fill will
* not occur immediately (unless you call this method from within
* the event dispatch thread). All the methods that do this deferring
* coordinate so that they are executed in the order that you
* called them.
*/
public synchronized void fillPlot() {
Runnable doFill = new Runnable() {
public void run() {
_fillPlot();
}
};
 
deferIfNecessary(doFill);
}
 
/** Create a sample plot.
*/
public synchronized void samplePlot() {
// Create a sample plot.
clear(true);
 
setTitle("Sample histogram");
setXLabel("values");
setYLabel("count");
 
Random random = new Random();
 
for (int i = 0; i <= 1000; i++) {
this.addPoint(0, 5.0 * Math.cos((Math.PI * i) / 500.0));
this.addPoint(1, (10.0 * random.nextDouble()) - 5.0);
this.addPoint(2, 2.0 * random.nextGaussian());
}
 
this.repaint();
}
 
/** Set the width and offset of the bars. Both are specified
* as a fraction of a bin width. The offset is the amount by which the
* i < sup>th</sup> data set is shifted to the right, so that it
* peeks out from behind the earlier data sets.
* @param width The width of the bars.
* @param offset The offset per data set.
*/
public synchronized void setBars(double width, double offset) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_barwidth = width;
_baroffset = offset;
}
 
/** Set the offset of the bins, in whatever units the data are given.
* Without calling this, each bin is centered at <i>x</i> = <i>nw</i>,
* where <i>w</i> is the width of the bin and <i>n</i> is an integer.
* That bin represents values in the range (<i>x - w/2, x + w/2</i>).
* If this method is called with argument <i>o</i>, then each bin is
* centered at <i>x = nw + o</i>, and represents values in the range
* (<i>x - w/2 + o, x + w/2 + o</i>). So for example, if <i>o = w/2</i>,
* then each bin represents values from <i>nw</i> to
* (<i>n</i> + 1)<i>w</i>) for some integer <i>n</i>.
* @param offset The bin offset.
*/
public synchronized void setBinOffset(double offset) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_binOffset = offset;
}
 
/** Set the width of the bins, in whatever units the data are given.
* @param width The width of the bins.
*/
public void setBinWidth(double width) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_binWidth = width;
}
 
/** Write the current data and plot configuration to the
* specified stream in PlotML syntax. This writes the histogram,
* not the raw data, in such a way that the Plot class (not the
* Histogram class) will correctly render it.
* The URL (relative or absolute) for the DTD is
* given as the second argument. If that argument is null,
* then the PlotML PUBLIC DTD is referenced, resulting in a file
* that can be read by a PlotML parser without any external file
* references, as long as that parser has local access to the DTD.
* The output is buffered, and is flushed before exiting.
* @param out An output writer.
* @param dtd The reference (URL) for the DTD, or null to use the
* PUBLIC DTD.
*/
public synchronized void write(Writer out, String dtd) {
// Auto-flush is disabled.
PrintWriter output = new PrintWriter(new BufferedWriter(out), false);
exportToPlot(output, dtd);
}
 
/** Write plot data information to the specified output stream in PlotML.
* @param output A buffered print writer.
*/
public synchronized void writeData(PrintWriter output) {
super.writeData(output);
 
for (int dataset = 0; dataset < _points.size(); dataset++) {
// Write the dataset directive
String legend = getLegend(dataset);
 
if (legend != null) {
output.println("<dataset name=\"" + legend + "\">");
} else {
output.println("<dataset>");
}
 
// Write the data
Vector pts = (Vector) _points.elementAt(dataset);
 
for (int pointnum = 0; pointnum < pts.size(); pointnum++) {
Double pt = (Double) pts.elementAt(pointnum);
output.println("<p y=\"" + pt.doubleValue() + "\"/>");
}
 
output.println("</dataset>");
}
}
 
/** Write plot format information to the specified output stream.
* @param output A buffered print writer.
*/
public synchronized void writeFormat(PrintWriter output) {
super.writeFormat(output);
 
// NOTE: Regrettably, the meaning of the barGraph data is
// different for a histogram than for a normal plot.
// In a histogram, it is proportional to the bin width.
// Thus, this is not the same as the corresponding line
// in exportToPlot().
output.println("<barGraph width=\"" + _barwidth + "\" offset=\""
+ _baroffset + "\"/>");
 
output.println("<bin width=\"" + _binWidth + "\" offset=\""
+ _binOffset + "\"/>");
}
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
 
/** Check the argument to ensure that it is a valid data set index.
* If it is less than zero, throw an IllegalArgumentException (which
* is a runtime exception). If it does not refer to an existing
* data set, then fill out the _points and _histogram
* Vectors so that they refer
* to all existing data sets.
* @param dataset The data set index.
*/
protected void _checkDatasetIndex(int dataset) {
if (dataset < 0) {
throw new IllegalArgumentException(
"Plot._checkDatasetIndex: Cannot"
+ " give a negative number for the data set index.");
}
 
while (dataset >= _points.size()) {
_points.addElement(new Vector());
_histogram.addElement(new Hashtable());
}
}
 
/** Draw bar from the specified point to the y axis.
* If the specified point is below the y axis or outside the
* x range, do nothing. If the <i>clip</i> argument is true,
* then do not draw above the y range.
* Note that paint() should be called before
* calling this method so that _xscale and _yscale are properly set.
* @param graphics The graphics context.
* @param dataset The index of the dataset.
* @param xpos The x position.
* @param ypos The y position.
* @param clip If true, then do not draw outside the range.
*/
protected void _drawBar(Graphics graphics, int dataset, long xpos,
long ypos, boolean clip) {
if (clip) {
if (ypos < _uly) {
ypos = _uly;
}
 
if (ypos > _lry) {
ypos = _lry;
}
}
 
if ((ypos <= _lry) && (xpos <= _lrx) && (xpos >= _ulx)) {
// left x position of bar.
int barlx = (int) (xpos - ((_barwidth * _binWidth * _xscale) / 2) + (dataset
* _baroffset * _binWidth * _xscale));
 
// right x position of bar
int barrx = (int) (barlx + (_barwidth * _binWidth * _xscale));
 
if (barlx < _ulx) {
barlx = _ulx;
}
 
if (barrx > _lrx) {
barrx = _lrx;
}
 
// Make sure that a bar is always at least one pixel wide.
if (barlx >= barrx) {
barrx = barlx + 1;
}
 
// The y position of the zero line.
long zeroypos = _lry - (long) ((0 - _yMin) * _yscale);
 
if (_lry < zeroypos) {
zeroypos = _lry;
}
 
if (_uly > zeroypos) {
zeroypos = _uly;
}
 
if ((_yMin >= 0) || (ypos <= zeroypos)) {
graphics.fillRect(barlx, (int) ypos, barrx - barlx,
(int) (zeroypos - ypos));
} else {
graphics.fillRect(barlx, (int) zeroypos, barrx - barlx,
(int) (ypos - zeroypos));
}
}
}
 
/** Draw the axes and then plot the histogram. If the second
* argument is true, clear the display first.
* This method is called by paint(). To cause it to be called you
* would normally call repaint(), which eventually causes paint() to
* be called.
* <p>
* Note that this is synchronized so that points are not added
* by other threads while the drawing is occurring. This method
* should be called only from the event dispatch thread, consistent
* with swing policy.
* @param graphics The graphics context.
* @param clearfirst If true, clear the plot before proceeding.
*/
protected synchronized void _drawPlot(Graphics graphics, boolean clearfirst) {
// We must call PlotBox._drawPlot() before calling _drawPlotPoint
// so that _xscale and _yscale are set.
super._drawPlot(graphics, clearfirst);
 
_showing = true;
 
// Plot the histograms in reverse order so that the first colors
// appear on top.
for (int dataset = _points.size() - 1; dataset >= 0; dataset--) {
Hashtable data = (Hashtable) _histogram.elementAt(dataset);
Enumeration keys = data.keys();
 
while (keys.hasMoreElements()) {
Integer bin = (Integer) keys.nextElement();
Integer count = (Integer) data.get(bin);
_drawPlotPoint(graphics, dataset, bin.intValue(), count
.intValue());
}
}
}
 
/** Parse a line that gives plotting information. Return true if
* the line is recognized. Lines with syntax errors are ignored.
* @param line A command line.
* It is not synchronized, so its caller should be.
* @return True if the line is recognized.
*/
protected boolean _parseLine(String line) {
// parse only if the super class does not recognize the line.
if (super._parseLine(line)) {
return true;
} else {
// We convert the line to lower case so that the command
// names are case insensitive
String lcLine = line.toLowerCase();
 
if (lcLine.startsWith("dataset:")) {
// new data set
_currentdataset++;
 
if (lcLine.length() > 0) {
String legend = (line.substring(8)).trim();
 
if ((legend != null) && (legend.length() > 0)) {
addLegend(_currentdataset, legend);
}
}
 
return true;
} else if (lcLine.startsWith("bars:")
|| lcLine.startsWith("bargraph:")) {
// The PlotML code uses barGraph, but the older style
// uses bars
int comma = line.indexOf(",", 5);
String barwidth;
String baroffset = null;
 
if (comma > 0) {
barwidth = (line.substring(5, comma)).trim();
baroffset = (line.substring(comma + 1)).trim();
} else {
barwidth = (line.substring(5)).trim();
}
 
try {
Double bwidth = Double.valueOf(barwidth);
double boffset = _baroffset;
 
if (baroffset != null) {
boffset = (Double.valueOf(baroffset)).doubleValue();
}
 
setBars(bwidth.doubleValue(), boffset);
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
 
return true;
} else if (lcLine.startsWith("binwidth:")) {
String binwidth = (line.substring(9)).trim();
 
try {
Double bwidth = Double.valueOf(binwidth);
setBinWidth(bwidth.doubleValue());
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
 
return true;
} else if (lcLine.startsWith("binoffset:")) {
String binoffset = (line.substring(10)).trim();
 
try {
Double boffset = Double.valueOf(binoffset);
setBinOffset(boffset.doubleValue());
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
 
return true;
} else if (lcLine.startsWith("numsets:")) {
// Obsolete field... ignore.
return true;
} else if (line.startsWith("move:")) {
// deal with 'move: 1 2' and 'move:2 2'
line = line.substring(5, line.length()).trim();
} else if (line.startsWith("move")) {
// deal with 'move 1 2' and 'move2 2'
line = line.substring(4, line.length()).trim();
} else if (line.startsWith("draw:")) {
// a connected point, if connect is enabled.
line = line.substring(5, line.length()).trim();
} else if (line.startsWith("draw")) {
// a connected point, if connect is enabled.
line = line.substring(4, line.length()).trim();
}
 
line = line.trim();
 
// Handle Plot formats
int fieldsplit = line.indexOf(",");
 
if (fieldsplit == -1) {
fieldsplit = line.indexOf(" ");
}
 
if (fieldsplit == -1) {
fieldsplit = line.indexOf("\t"); // a tab
}
 
if (fieldsplit == -1) {
// Have just one number per line
try {
Double xpt = Double.valueOf(line);
addPoint(_currentdataset, xpt.doubleValue());
return true;
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
} else {
String y = (line.substring(fieldsplit + 1)).trim();
 
try {
Double ypt = Double.valueOf(y);
addPoint(_currentdataset, ypt.doubleValue());
return true;
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
}
}
 
return false;
}
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
 
/** @serial The current dataset. */
protected int _currentdataset = -1;
 
/** @serial A vector of datasets. */
protected Vector _points = new Vector();
 
/** @serial A vector of histogram data. */
protected Vector _histogram = new Vector();
 
///////////////////////////////////////////////////////////////////
//// private methods ////
 
/* In the specified data set, add the specified value to the
* histogram. Data set indices begin with zero. If the data set
* does not exist, create it.
* The new point will visibly alter the histogram if the plot is visible
* on the screen. Otherwise, it will be drawn the next time the histogram
* is drawn on the screen.
*
* This is not synchronized, so the caller should be. Moreover, this
* should only be called in the event dispatch thread. It should only
* be called by _executeDeferredActions().
*
* @param dataset The data set index.
* @param value The new value.
*/
private void _addPoint(int dataset, double value) {
// Ensure replot of offscreen buffer.
_plotImage = null;
 
_checkDatasetIndex(dataset);
 
// Calculate the bin number.
int bin = (int) (Math.round((value - _binOffset) / _binWidth));
Integer binobj = Integer.valueOf(bin);
 
// Add to the appropriate bin
Hashtable bins = (Hashtable) _histogram.elementAt(dataset);
int count;
 
if (bins.containsKey(binobj)) {
// increase the count
count = 1 + ((Integer) bins.get(binobj)).intValue();
bins.put(binobj, Integer.valueOf(count));
} else {
// start a new entry.
count = 1;
bins.put(binobj, Integer.valueOf(count));
}
 
// For auto-ranging, keep track of min and max.
double x = (bin * _binWidth) + _binOffset;
 
if (x < _xBottom) {
_xBottom = x;
}
 
double xtop = x + (_binWidth / 2.0);
 
if (xtop > _xTop) {
_xTop = xtop;
}
 
if (count > _yTop) {
_yTop = count;
}
 
_yBottom = 0.0;
 
Vector pts = (Vector) _points.elementAt(dataset);
pts.addElement(Double.valueOf(value));
 
// Draw the point on the screen only if the plot is showing.
// Need to check that graphics is not null because plot may have
// been dismissed.
Graphics graphics = getGraphics();
 
if (_showing && (graphics != null)) {
// In swing, updates to showing graphics must be done in the
// event thread, not here. Thus, we have to queue the request.
final int pendingDataset = dataset;
final int pendingBin = bin;
final int pendingCount = count;
 
// We are in the event thread, so this is safe...
_drawPlotPoint(graphics, pendingDataset, pendingBin, pendingCount);
}
}
 
/* Clear the plot of all data points. If the argument is true, then
* reset all parameters to their initial conditions, including
* the persistence, plotting format, and axes formats.
* For the change to take effect, you must call repaint().
*
* @param format If true, clear the format controls as well.
*/
private void _clear(boolean format) {
// Ensure replot of offscreen buffer.
_plotImage = null;
 
super.clear(format);
_currentdataset = -1;
_points = new Vector();
_histogram = new Vector();
_showing = false;
 
if (format) {
// Reset format controls
_barwidth = 0.5;
_baroffset = 0.15;
_binWidth = 1.0;
_binOffset = 0.5;
}
}
 
/* Draw the specified histogram bar.
* Note that paint() should be called before
* calling this method so that it calls _drawPlot(), which sets
* _xscale and _yscale. Note that this does not check the dataset
* index. It is up to the caller to do that.
*
* Note that this method is not synchronized, so the caller should be.
* Moreover this method should always be called from the event thread
* when being used to write to the screen.
*/
private void _drawPlotPoint(Graphics graphics, int dataset, int bin,
int count) {
// Set the color
if (_usecolor) {
int color = dataset % _colors.length;
graphics.setColor(_colors[color]);
} else {
graphics.setColor(_foreground);
}
 
double y = count;
double x = (_binWidth * bin) + _binOffset;
 
if (_xlog) {
if (x <= 0.0) {
System.err.println("Can't plot non-positive X values "
+ "when the logarithmic X axis value is specified: "
+ x);
return;
}
 
x = Math.log(x) * _LOG10SCALE;
}
 
if (_ylog) {
if (y <= 0.0) {
System.err.println("Can't plot non-positive Y values "
+ "when the logarithmic Y axis value is specified: "
+ y);
return;
}
 
y = Math.log(y) * _LOG10SCALE;
}
 
// Use long here because these numbers can be quite large
// (when we are zoomed out a lot).
long ypos = _lry - (long) ((y - _yMin) * _yscale);
long xpos = _ulx + (long) ((x - _xMin) * _xscale);
 
_drawBar(graphics, dataset, xpos, ypos, true);
 
// Restore the color, in case the box gets redrawn.
graphics.setColor(_foreground);
}
 
/* Rescale so that the data that is currently plotted just fits.
* This simply calls the base class.
*
* This is not synchronized, so the caller should be. Moreover, this
* should only be called in the event dispatch thread. It should only
* be called by _executeDeferredActions().
*/
private void _fillPlot() {
super.fillPlot();
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
 
/** @serial The width of a bar. */
private double _barwidth = 0.5;
 
/** @serial The offset between bars. */
private double _baroffset = 0.15;
 
/** @serial The width of a bin. */
private double _binWidth = 1.0;
 
/** @serial The offset between bins. */
private double _binOffset = 0.5;
 
/** @serial Set by _drawPlot(), and reset by clear(). */
private boolean _showing = false;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotLive.java
0,0 → 1,240
/* A live signal plotter.
 
@Copyright (c) 1997-2005 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JButton;
 
//////////////////////////////////////////////////////////////////////////
//// PlotLive
 
/**
Plot signals dynamically, where points can be added at any time
and the display will be updated. This should be normally used
with some finite persistence so that old points are erased as new
points are added. Unfortunately, the most efficient way to erase
old points is to draw graphics using the "exclusive or" mode, which
introduces quite a number of artifacts. When lines are drawn
between points, where they overlap the points the line becomes
white. Moreover, if two lines or points overlap completely, they
disappear.
<p>
This class is abstract, so it must be used by creating a derived
class. To use it, create a derived class with an
addPoints() method. Your class may also set graph parameters like
titles and axis labels in the constructor by calling
methods in the Plot or PlotBox classes (both of which are base classes).
The addPoints() method should call addPoint() of the Plot base
class to dynamically add points to the plot. This method is called
within a thread separate from the applet thread, so the zooming
mechanism and buttons remain live.
 
@author Edward A. Lee, Christopher Brooks, Contributor: Jeff Lane
@version $Id: PlotLive.java,v 1.67 2005/07/28 18:49:32 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public abstract class PlotLive extends Plot implements Runnable {
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Redefine in derived classes to add points to the plot.
* Adding many points at once will make the plot somewhat faster
* because the thread yields between calls to this method.
* However, the plot will also be somewhat less responsive to user
* inputs such as zooming, filling, or stopping. In the derived-class
* implementation, this method should probably be synchronized.
*
* <p>Jeff Lane points out that if the derived class version of
* addPoints() does not return quickly, and it seems like then you
* may want to experiment with addPoints() to not being synchronized.
*/
public abstract void addPoints();
 
/** Make start and stop buttons.
* This method is deprecated. Use setButtons() instead.
* @deprecated
*/
public void makeButtons() {
if (_startButton == null) {
_startButton = new JButton("start");
_startButton.addActionListener(new StartButtonListener());
add(_startButton);
}
 
_startButton.setVisible(true);
 
if (_stopButton == null) {
_stopButton = new JButton("stop");
_stopButton.addActionListener(new StopButtonListener());
add(_stopButton);
}
 
_stopButton.setVisible(true);
_stopButton.setEnabled(false);
_startButton.setEnabled(true);
}
 
/** Pause the plot. To resume, call start().
*/
public void pause() {
_paused = true;
_plotting = false;
_stopButton.setEnabled(false);
_startButton.setEnabled(true);
}
 
/** This is the body of a thread that repeatedly calls addPoints()
* if the plot is active. To make the plot active, call start().
* To pause the plot, call pause(). To stop the plot and destroy
* the thread, call stop(). The next time start() is called, a new
* thread will be started. Between calls to addPoints(), this method calls
* Thread.yield() so that the thread does not hog all
* the resources. This somewhat slows down execution, so derived
* classes may wish to plot quite a few points in their
* addPoints() method, if possible. However,
* plotting more points at once may also decrease the
* responsiveness of the user interface.
*/
public void run() {
while (_plotting || _paused) {
if (_plotting) {
addPoints();
 
// Give the event thread a chance.
Thread.yield();
} else if (_paused) {
// NOTE: Cannot synchronize this entire method because then
// the Thread.yield() call above does not yield to any
// synchronized methods (like _drawPlot()).
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
}
}
 
/** If the argument is true, make a start, stop, and fill button
* visible at the upper right. Otherwise, make the buttons invisible.
* NOTE: The buttons may infringe on the title space,
* if the title is long. In an application, it is preferable to provide
* a menu with the commands. This way, when printing the plot,
* the printed plot will not have spurious buttons. Thus, this method
* should be used only by applets, which normally do not have menus.
*/
public void setButtons(boolean visible) {
super.setButtons(visible);
 
if (_startButton == null) {
_startButton = new JButton("start");
_startButton.addActionListener(new StartButtonListener());
add(_startButton);
}
 
_startButton.setVisible(visible);
 
if (_stopButton == null) {
_stopButton = new JButton("stop");
_stopButton.addActionListener(new StopButtonListener());
add(_stopButton);
}
 
_stopButton.setVisible(visible);
 
if (visible) {
_stopButton.setEnabled(false);
_startButton.setEnabled(true);
}
}
 
/** Make the plot active. Start a new thread if necessary.
*/
public synchronized void start() {
_plotting = true;
_paused = false;
_stopButton.setEnabled(true);
_startButton.setEnabled(false);
 
if (_plotLiveThread == null) {
_plotLiveThread = new Thread(this, "PlotLive Thread");
_plotLiveThread.start();
} else {
synchronized (this) {
notifyAll();
}
}
}
 
/** Stop the plot. The plot thread exits. This should be called by
* an applet's stop() method.
*/
public void stop() {
_plotting = false;
_paused = false;
_plotLiveThread = null;
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
 
/** @serial Thread of this plotter */
private Thread _plotLiveThread = null;
 
/** @serial True if we are actually plotting. */
private boolean _plotting = false;
 
/** @serial True if we are paused. */
private boolean _paused = false;
 
/** @serial Start and Stop Buttons. */
private JButton _startButton;
 
/** @serial Start and Stop Buttons. */
private JButton _stopButton;
 
///////////////////////////////////////////////////////////////////
//// inner classes ////
class StartButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
start();
}
}
 
// Despite the name, the stop button calls pause.
class StopButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
pause();
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotApplication.java
0,0 → 1,390
/* A standalone plot application.
 
Copyright (c) 1998-2008 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
 
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
 
import ptolemy.util.StringUtilities;
 
//////////////////////////////////////////////////////////////////////////
//// PlotApplication
 
/**
PlotApplication is a versatile two-dimensional data plotter application.
It can read files compatible with the Ptolemy plot
file format (currently only ASCII). For a description of the file
format, see the Plot and PlotBox classes.
Command-line options include:
<dl>
 
<dt><code>-help</code></a>
<dt>Print the usage, including all command-line options
that exist for backward compatibility and then exit.
The help menu choice will display the same information.
<dt><code>-test</code></a>
<dt>Display the plot, then exit after 2 seconds.
 
<dt><code>-version</code></a>
<dt>Print the program version and then exit.
While ptplot is running,
the version menu choice will display the same information.
<dt><code>-</code></a>
<dt>Read the plot data from standard in.
</dl>
 
<p>
For compatibility with historical applications, this application has
a limited ability to read pxgraph files. The command line arguments
must be used, and the options that are understood are exactly those
of the pxgraph application, plus some more to allow for cross-platform
reading. It is not possible to read pxgraph files
using the "Open" menu command (because of the cross-platform problems).
The additional command-line arguments are:
<dl>
 
<dt><code>-bigendian</code></a>
<dt>Data files are in big-endian, or network binary format.
If you are on a little-endian machine, such as a machine
with an Intel x86 chip, and you would like to read a binary
format file created on a big-endian machine, such as a Sun SPARC,
use the <code>-bigendian</code> flag.
 
<dt><code>-littleendian</code></a>
<dt>Data files are in little-endian, or x86 binary format.
If you are on a big-endian machine, such as a Sun Sparc,
and you would like to read a binary
format file created on a little-endian machine, such as Intel x86
machine, then use the <code>-littleendian</code> flag.
</dl>
<p>
To compile and run this application, do the following:
<pre>
javac -classpath ../.. PlotApplication.java
java -classpath ../.. ptolemy.plot.PlotApplication
</pre>
<p>
This assumes a particular directory structure. If this is not what you
have, then alter the above accordingly.
 
@see Plot
@see PlotBox
@author Christopher Brooks and Edward A. Lee
@version $Id: PlotApplication.java,v 1.69.4.1 2008/04/04 20:01:01 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class PlotApplication extends PlotFrame {
/** Construct a plot with no command-line arguments.
* It initially displays a sample plot.
* @exception Exception Not thrown in this base class.
*/
public PlotApplication() throws Exception {
this(new String[0]);
}
 
/** Construct a plot with the specified command-line arguments.
* @param args The command-line arguments.
* @exception Exception If command line arguments have problems.
*/
public PlotApplication(String[] args) throws Exception {
this(new Plot(), args);
}
 
/** Construct a plot with the specified command-line arguments
* and instance of plot. If there are no command-line arguments,
* then display a sample plot.
* @param plot The instance of Plot to use.
* @param args The command-line arguments.
* @exception Exception If command line arguments have problems.
*/
public PlotApplication(PlotBox plot, String[] args) throws Exception {
// invoke the base class constructor and pass in the argument a Plot
// object. This makes sure that the plot field is an instance of
// Plot class.
super("PlotApplication", plot);
 
// Handle window closing by exiting the application.
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// Strangely, calling _close() here sends javac into
// an infinite loop (in jdk 1.1.4).
// _close();
System.exit(0);
}
});
 
_parseArgs(args);
 
if ((args == null) || (args.length == 0)) {
samplePlot();
}
 
setVisible(true);
}
 
/** Display the given plot. Unlike the two argument constructor,
* this does not take command-line arguments, and does not fill
* the plot with a sample plot.
* @param plot The instance of Plot to display.
*/
public PlotApplication(PlotBox plot) {
// Invoke the base class constructor and pass in the argument a Plot
// object. This makes sure that the plot field is an instance of
// Plot class.
super("PlotApplication", plot);
 
// Handle window closing by exiting the application.
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// Strangely, calling _close() here sends javac into
// an infinite loop (in jdk 1.1.4).
// _close();
System.exit(0);
}
});
 
setVisible(true);
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Create a new plot window and map it to the screen.
*/
public static void main(final String[] args) {
try {
// Run this in the Swing Event Thread.
Runnable doActions = new Runnable() {
public void run() {
try {
new PlotApplication(new Plot(), args);
} catch (Exception ex) {
System.err.println(ex.toString());
ex.printStackTrace();
}
}
};
 
SwingUtilities.invokeAndWait(doActions);
} catch (Exception ex) {
System.err.println(ex.toString());
ex.printStackTrace();
}
 
// If the -test arg was set, then exit after 2 seconds.
if (_test) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
 
System.exit(0);
}
}
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
protected void _about() {
JOptionPane
.showMessageDialog(
this,
"PlotApplication class\n"
+ "By: Edward A. Lee "
+ "and Christopher Brooks\n"
+ "Version "
+ PlotBox.PTPLOT_RELEASE
+ ", Build: $Id: PlotApplication.java,v 1.69.4.1 2008/04/04 20:01:01 cxh Exp $\n\n"
+ "For more information, see\n"
+ "http://ptolemy.eecs.berkeley.edu/java/ptplot\n\n"
+ "Copyright (c) 1997-2008, "
+ "The Regents of the University of California.",
"About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
}
 
/** Exit the application.
*/
protected void _close() {
StringUtilities.exit(0);
}
 
/** Display more detailed information than given by _about().
*/
protected void _help() {
JOptionPane.showMessageDialog(this,
"PlotApplication is a standalone plot " + " application.\n"
+ " File formats understood: Ptplot ASCII.\n"
+ " Left mouse button: Zooming.\n\n" + _usage(),
"About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
}
 
/** Parse the command-line
* arguments and make calls to the Plot class accordingly.
* @return The number of arguments read.
* @exception CmdLineArgException If a command line argument cannot
* be parsed.
* @exception FileNotFoundException If an input file cannot be found.
* @exception IOException If there is a problem reading an input.
*/
protected int _parseArgs(String[] args) throws CmdLineArgException,
FileNotFoundException, IOException {
int i = 0;
int argumentsRead;
String arg;
String title = "Ptolemy plot";
 
int width = 500; // Default width of the graph
int height = 300; // Default height of the graph
 
while ((args != null) && (i < args.length)) {
arg = args[i++];
 
if (arg.equals("-height")) {
if (i > (args.length - 1)) {
throw new CmdLineArgException(_usage());
}
 
height = Integer.valueOf(args[i++]).intValue();
continue;
} else if (arg.equals("-help")) {
System.out.println(_usage());
StringUtilities.exit(0);
continue;
} else if (arg.equals("-test")) {
_test = true;
continue;
} else if (arg.equals("-version")) {
System.out
.println("Version "
+ PlotBox.PTPLOT_RELEASE
+ ", Build $Id: PlotApplication.java,v 1.69.4.1 2008/04/04 20:01:01 cxh Exp $");
StringUtilities.exit(0);
continue;
} else if (arg.equals("-width")) {
if (i > (args.length - 1)) {
throw new CmdLineArgException(
"-width requires an integer argument");
}
 
width = Integer.valueOf(args[i++]).intValue();
continue;
} else if (arg.equals("")) {
// Ignore blank argument.
} else if (arg.equals("-")) {
// read from standard input
URL base = new URL("file", null, "standard input");
_read(base, System.in);
} else if (!arg.startsWith("-")) {
// Have a filename. First attempt to open it as a URL.
InputStream instream;
URL base;
 
try {
// First argument is null because we are only
// processing absolute URLs this way. Relative
// URLs are opened as ordinary files.
URL inurl = new URL(null, arg);
base = inurl;
instream = inurl.openStream();
} catch (MalformedURLException ex) {
File file = new File(arg);
instream = new FileInputStream(file);
_file = new File(file.getAbsolutePath());
title = _file.getName();
_directory = _file.getParentFile();
base = new URL("file", null, _directory.getAbsolutePath());
}
 
_read(base, instream);
} else {
// Unrecognized option.
throw new CmdLineArgException("Unrecognized option: " + arg);
}
}
 
setSize(width, height);
setTitle(title);
 
argumentsRead = i;
 
return argumentsRead;
}
 
/** Return a string summarizing the command-line arguments.
* @return A usage string.
*/
protected String _usage() {
// We use a table here to keep things neat.
// If we have:
// {"-bd", "<color>", "Border", "White", "(Unsupported)"},
// -bd - The argument
// <color> - The description of the value of the argument
// Border - The Xgraph file directive (not supported at this time).
// White - The default (not supported at this time)
// "(Unsupported)" - The string that is printed to indicate if
// a option is unsupported.
String[][] commandOptions = { { "-height", "<pixels>" },
{ "-width", "<pixels>" }, };
 
String[] commandFlags = { "-help", "-test", "-version", "-", };
StringBuffer result = new StringBuffer(
"Usage: ptplot [ options ] [file ...]\n\n"
+ "Options that take values:\n");
 
int i;
 
for (i = 0; i < commandOptions.length; i++) {
result.append(" " + commandOptions[i][0] + " "
+ commandOptions[i][1] + "\n");
}
 
result.append("\nBoolean flags:\n");
 
for (i = 0; i < commandFlags.length; i++) {
result.append(" " + commandFlags[i]);
}
 
return result.toString();
}
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
 
/** If true, then auto exit after a few seconds. */
protected static boolean _test = false;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotFormatter.java
0,0 → 1,475
/* A panel for controlling the format of a plotter.
 
Copyright (c) 1998-2005 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Frame;
import java.util.Vector;
 
import javax.swing.JPanel;
 
import ptolemy.gui.ComponentDialog;
import ptolemy.gui.Query;
import ptolemy.gui.QueryListener;
 
//////////////////////////////////////////////////////////////////////////
//// PlotFormatter
 
/**
 
PlotFormatter is a panel that controls the format of a plotter object
passed to the constructor.
 
@see Plot
@see PlotBox
@author Edward A. Lee
@version $Id: PlotFormatter.java,v 1.26 2005/07/08 19:59:35 cxh Exp $
@since Ptolemy II 1.0
@Pt.ProposedRating Yellow (eal)
@Pt.AcceptedRating Red (cxh)
*/
public class PlotFormatter extends JPanel {
/** Construct a plot formatter for the specified plot object.
*/
public PlotFormatter(PlotBox plot) {
super();
_plot = plot;
 
setLayout(new BorderLayout());
_wideQuery = new Query();
add(_wideQuery, BorderLayout.WEST);
_narrowQuery = new Query();
add(_narrowQuery, BorderLayout.EAST);
 
// Populate the wide query.
_wideQuery.setTextWidth(20);
_originalTitle = plot.getTitle();
_wideQuery.addLine("title", "Title", _originalTitle);
_originalXLabel = plot.getXLabel();
_wideQuery.addLine("xlabel", "X Label", _originalXLabel);
_originalYLabel = plot.getYLabel();
_wideQuery.addLine("ylabel", "Y Label", _originalYLabel);
_originalXRange = plot.getXRange();
_wideQuery.addLine("xrange", "X Range", "" + _originalXRange[0] + ", "
+ _originalXRange[1]);
_originalYRange = plot.getYRange();
_wideQuery.addLine("yrange", "Y Range", "" + _originalYRange[0] + ", "
+ _originalYRange[1]);
 
String[] marks = { "none", "points", "dots", "various", "pixels" };
_originalMarks = "none";
 
if (plot instanceof Plot) {
_originalMarks = ((Plot) plot).getMarksStyle();
_wideQuery.addRadioButtons("marks", "Marks", marks, _originalMarks);
}
 
_originalXTicks = plot.getXTicks();
_originalXTicksSpec = "";
 
if (_originalXTicks != null) {
StringBuffer buffer = new StringBuffer();
Vector positions = _originalXTicks[0];
Vector labels = _originalXTicks[1];
 
for (int i = 0; i < labels.size(); i++) {
if (buffer.length() > 0) {
buffer.append(", ");
}
 
buffer.append(labels.elementAt(i).toString());
buffer.append(" ");
buffer.append(positions.elementAt(i).toString());
}
 
_originalXTicksSpec = buffer.toString();
}
 
_wideQuery.addLine("xticks", "X Ticks", _originalXTicksSpec);
 
_originalYTicks = plot.getYTicks();
_originalYTicksSpec = "";
 
if (_originalYTicks != null) {
StringBuffer buffer = new StringBuffer();
Vector positions = _originalYTicks[0];
Vector labels = _originalYTicks[1];
 
for (int i = 0; i < labels.size(); i++) {
if (buffer.length() > 0) {
buffer.append(", ");
}
 
buffer.append(labels.elementAt(i).toString());
buffer.append(" ");
buffer.append(positions.elementAt(i).toString());
}
 
_originalYTicksSpec = buffer.toString();
}
 
_wideQuery.addLine("yticks", "Y Ticks", _originalYTicksSpec);
 
_originalGrid = plot.getGrid();
_narrowQuery.addCheckBox("grid", "Grid", _originalGrid);
_originalStems = false;
_originalConnected = null;
 
if (plot instanceof Plot) {
_originalStems = ((Plot) plot).getImpulses();
_narrowQuery.addCheckBox("stems", "Stems", _originalStems);
_saveConnected();
_narrowQuery.addCheckBox("connected", "Connect", ((Plot) plot)
.getConnected());
}
 
_originalColor = plot.getColor();
_narrowQuery.addCheckBox("color", "Use Color", _originalColor);
 
// FIXME: setXLog() and setYLog() cause problems with
// dropped data if they are toggled after data is read in.
// This is because the log axis facility modifies the datasets
// in addPlotPoint() in Plot.java. When this is fixed
// we can add the XLog and YLog facility to the Format menu
//
// _originalXLog = plot.getXLog();
//_narrowQuery.addCheckBox("xlog", "X Log", _originalXLog);
//if (_originalXTicks != null) {
// _narrowQuery.setBoolean("xlog", false);
// _narrowQuery.setEnabled("xlog", false);
//}
// _originalYLog = plot.getYLog();
//_narrowQuery.addCheckBox("ylog", "Y Log", _originalYLog);
//if (_originalYTicks != null) {
// _narrowQuery.setBoolean("ylog", false);
// _narrowQuery.setEnabled("ylog", false);
//}
// Attach listeners.
_wideQuery.addQueryListener(new QueryListener() {
public void changed(String name) {
if (name.equals("title")) {
_plot.setTitle(_wideQuery.getStringValue("title"));
} else if (name.equals("xlabel")) {
_plot.setXLabel(_wideQuery.getStringValue("xlabel"));
} else if (name.equals("ylabel")) {
_plot.setYLabel(_wideQuery.getStringValue("ylabel"));
} else if (name.equals("xrange")) {
_plot
.read("XRange: "
+ _wideQuery.getStringValue("xrange"));
} else if (name.equals("xticks")) {
String spec = _wideQuery.getStringValue("xticks").trim();
_plot.read("XTicks: " + spec);
 
// FIXME: log axis format temporarily
// disabled, see above.
// if (spec.equals("")) {
// _narrowQuery.setEnabled("xlog", true);
// } else {
// _narrowQuery.setBoolean("xlog", false);
// _narrowQuery.setEnabled("xlog", false);
// }
} else if (name.equals("yticks")) {
String spec = _wideQuery.getStringValue("yticks").trim();
_plot.read("YTicks: " + spec);
 
// FIXME: log axis format temporarily
// disabled, see above.
// if (spec.equals("")) {
// _narrowQuery.setEnabled("ylog", true);
// } else {
// _narrowQuery.setBoolean("ylog", false);
// _narrowQuery.setEnabled("ylog", false);
// }
} else if (name.equals("yrange")) {
_plot
.read("YRange: "
+ _wideQuery.getStringValue("yrange"));
} else if (name.equals("marks")) {
((Plot) _plot).setMarksStyle(_wideQuery
.getStringValue("marks"));
}
 
_plot.repaint();
}
});
 
_narrowQuery.addQueryListener(new QueryListener() {
public void changed(String name) {
if (name.equals("grid")) {
_plot.setGrid(_narrowQuery.getBooleanValue("grid"));
} else if (name.equals("stems")) {
((Plot) _plot).setImpulses(_narrowQuery
.getBooleanValue("stems"));
_plot.repaint();
} else if (name.equals("color")) {
_plot.setColor(_narrowQuery.getBooleanValue("color"));
 
// FIXME: log axis format temporarily
// disabled, see above.
// } else if (name.equals("xlog")) {
// _plot.setXLog(_narrowQuery.getBooleanValue("xlog"));
// } else if (name.equals("ylog")) {
// _plot.setYLog(_narrowQuery.getBooleanValue("ylog"));
} else if (name.equals("connected")) {
_setConnected(_narrowQuery.getBooleanValue("connected"));
}
 
_plot.repaint();
}
});
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Apply currently specified values to the associated plot.
* This requests a repaint of the plot.
*/
public void apply() {
// Apply current values.
_plot.setTitle(_wideQuery.getStringValue("title"));
_plot.setXLabel(_wideQuery.getStringValue("xlabel"));
_plot.setYLabel(_wideQuery.getStringValue("ylabel"));
_plot.read("XRange: " + _wideQuery.getStringValue("xrange"));
_plot.read("YRange: " + _wideQuery.getStringValue("yrange"));
_plot.setGrid(_narrowQuery.getBooleanValue("grid"));
_plot.setColor(_narrowQuery.getBooleanValue("color"));
 
// FIXME: log axis format temporarily disable, see above.
// _plot.setXLog(_narrowQuery.getBooleanValue("xlog"));
// _plot.setYLog(_narrowQuery.getBooleanValue("ylog"));
if (_plot instanceof Plot) {
Plot cplot = (Plot) _plot;
cplot.setMarksStyle(_wideQuery.getStringValue("marks"));
cplot.setImpulses(_narrowQuery.getBooleanValue("stems"));
_setConnected(_narrowQuery.getBooleanValue("connected"));
}
 
// FIXME: log axis format temporarily disable, see above.
// String spec = _wideQuery.getStringValue("xticks").trim();
// _plot.read("XTicks: " + spec);
// if (spec.equals("")) {
// _narrowQuery.setEnabled("xlog", true);
// } else {
// _narrowQuery.setBoolean("xlog", false);
// _narrowQuery.setEnabled("xlog", false);
// }
// spec = _wideQuery.getStringValue("yticks").trim();
// _plot.read("YTicks: " + spec);
// if (spec.equals("")) {
// _narrowQuery.setEnabled("ylog", true);
// } else {
// _narrowQuery.setBoolean("ylog", false);
// _narrowQuery.setEnabled("ylog", false);
// }
_plot.repaint();
}
 
/** Open a format control window as a top-level, modal dialog.
*/
public void openModal() {
String[] buttons = { "Apply", "Cancel" };
 
// NOTE: If the plot is in a top-level container that is a Frame
// (as opposed to an applet), then tell the dialog that the Frame
// owns the dialog.
Container toplevel = _plot.getTopLevelAncestor();
Frame frame = null;
 
if (toplevel instanceof Frame) {
frame = (Frame) toplevel;
}
 
ComponentDialog dialog = new ComponentDialog(frame, "Set plot format",
this, buttons);
 
if (dialog.buttonPressed().equals("Apply")) {
apply();
} else {
restore();
}
}
 
/** Restore the original configuration of the plot, and request a
* a redraw.
*/
public void restore() {
// Restore _original values.
_plot.setTitle(_originalTitle);
_plot.setXLabel(_originalXLabel);
_plot.setYLabel(_originalYLabel);
_plot.setXRange(_originalXRange[0], _originalXRange[1]);
_plot.setYRange(_originalYRange[0], _originalYRange[1]);
_plot.setGrid(_originalGrid);
_plot.setColor(_originalColor);
 
// FIXME: log axis format temporarily disable, see above.
// _plot.setXLog(_originalXLog);
// _plot.setYLog(_originalYLog);
if (_plot instanceof Plot) {
Plot cplot = (Plot) _plot;
cplot.setMarksStyle(_originalMarks);
cplot.setImpulses(_originalStems);
_restoreConnected();
}
 
// FIXME: log axis format temporarily disabled, see above.
// _plot.read("XTicks: " + _originalXTicksSpec);
// if (_originalXTicksSpec.equals("")) {
// _narrowQuery.setEnabled("xlog", true);
// } else {
// _narrowQuery.setBoolean("xlog", false);
// _narrowQuery.setEnabled("xlog", false);
// }
// _plot.read("YTicks: " + _originalYTicksSpec);
// if (_originalYTicksSpec.equals("")) {
// _narrowQuery.setEnabled("ylog", true);
// } else {
// _narrowQuery.setBoolean("ylog", false);
// _narrowQuery.setEnabled("ylog", false);
// }
_plot.repaint();
}
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
 
/** @serial The plot object controlled by this formatter. */
protected final PlotBox _plot;
 
///////////////////////////////////////////////////////////////////
//// private methods ////
// Save the current connected state of all the point currently in the
// plot. NOTE: This method reaches into the protected members of
// the Plot class, taking advantage of the fact that this class is
// in the same package.
private void _saveConnected() {
Vector points = ((Plot) _plot)._points;
_originalConnected = new boolean[points.size()][];
_originalPoints = new PlotPoint[points.size()][];
 
for (int dataset = 0; dataset < points.size(); dataset++) {
Vector pts = (Vector) points.elementAt(dataset);
_originalConnected[dataset] = new boolean[pts.size()];
_originalPoints[dataset] = new PlotPoint[pts.size()];
 
for (int i = 0; i < pts.size(); i++) {
PlotPoint pt = (PlotPoint) pts.elementAt(i);
_originalConnected[dataset][i] = pt.connected;
_originalPoints[dataset][i] = pt;
}
}
}
 
// Set the current connected state of all the point in the
// plot. NOTE: This method reaches into the protected members of
// the Plot class, taking advantage of the fact that this class is
// in the same package.
private void _setConnected(boolean value) {
Vector points = ((Plot) _plot)._points;
 
// Make sure the default matches.
((Plot) _plot).setConnected(value);
 
boolean[][] result = new boolean[points.size()][];
 
for (int dataset = 0; dataset < points.size(); dataset++) {
Vector pts = (Vector) points.elementAt(dataset);
result[dataset] = new boolean[pts.size()];
 
boolean first = true;
 
for (int i = 0; i < pts.size(); i++) {
PlotPoint pt = (PlotPoint) pts.elementAt(i);
pt.connected = value && !first;
first = false;
}
}
}
 
// Restore the connected state of all the point that were in the
// plot when their connected state was saved.
// NOTE: This method reaches into the protected members of
// the plot class, taking advantage of the fact that this class is
// in the same package.
private void _restoreConnected() {
for (int dataset = 0; dataset < _originalPoints.length; dataset++) {
for (int i = 0; i < _originalPoints[dataset].length; i++) {
PlotPoint pt = _originalPoints[dataset][i];
pt.connected = _originalConnected[dataset][i];
}
}
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
// Query widgets.
private Query _wideQuery;
 
///////////////////////////////////////////////////////////////////
//// private variables ////
// Query widgets.
private Query _narrowQuery;
 
// Original configuration of the plot.
private String _originalTitle;
 
// Original configuration of the plot.
private String _originalXLabel;
 
// Original configuration of the plot.
private String _originalYLabel;
 
// Original configuration of the plot.
private String _originalMarks;
 
// Original configuration of the plot.
private String _originalXTicksSpec;
 
// Original configuration of the plot.
private String _originalYTicksSpec;
 
private double[] _originalXRange;
 
private double[] _originalYRange;
 
private Vector[] _originalXTicks;
 
private Vector[] _originalYTicks;
 
private boolean _originalGrid;
 
private boolean _originalStems;
 
private boolean _originalColor;
 
private boolean[][] _originalConnected;
 
private PlotPoint[][] _originalPoints;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/HistogramApplet.java
0,0 → 1,63
/* HistogramApplet
 
@Copyright (c) 1997-2005 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
 
*/
package ptolemy.plot;
 
//////////////////////////////////////////////////////////////////////////
//// HistogramApplet
 
/**
A Histogram. Data can be given in ASCII format at a URL.
If none is given, then a sample histogram is generated.
 
@author Edward A. Lee
@version $Id: HistogramApplet.java,v 1.25 2005/07/08 19:59:34 cxh Exp $
@since Ptolemy II 0.3
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class HistogramApplet extends PlotApplet {
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Return a string describing this applet.
* @return A string describing the applet.
*/
public String getAppletInfo() {
return "Histogram 1.0: Demo of PlotApplet.\n"
+ "By: Edward A. Lee\n "
+ "($Id: HistogramApplet.java,v 1.25 2005/07/08 19:59:34 cxh Exp $)";
}
 
/** Create a new Histogram object for the applet.
* @return A new instance of Histogram.
*/
public PlotBox newPlot() {
return new Histogram();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotLiveApplet.java
0,0 → 1,69
/* A live signal plotter applet
 
@Author: Edward A. Lee and Christopher Brooks
 
@Copyright (c) 1997-2005 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
//////////////////////////////////////////////////////////////////////////
//// PlotLiveApplet
 
/**
An Applet for the PlotLive class. Derived classes should redefine
newPlot() to return a concrete instance of PlotLive.
 
@author Edward A. Lee, Christopher Brooks
@version $Id: PlotLiveApplet.java,v 1.31 2005/07/28 18:49:33 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class PlotLiveApplet extends PlotApplet {
/** Return a string describing this applet.
* @return A description of the applet.
*/
public String getAppletInfo() {
return "PlotLiveApplet "
+ PlotBox.PTPLOT_RELEASE
+ " : Demo of PlotLive.\n"
+ "By: Edward A. Lee\n"
+ " Christopher Brooks\n"
+ "($Id: PlotLiveApplet.java,v 1.31 2005/07/28 18:49:33 cxh Exp $)";
}
 
/** Start the plot thread.
*/
public void start() {
((PlotLive) plot()).start();
}
 
/** Stop the plot thread.
*/
public void stop() {
((PlotLive) plot()).stop();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/EPSGraphics.java
0,0 → 1,497
/* Graphics class supporting EPS export from plots.
 
Copyright (c) 1998-2006 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.image.ImageObserver;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Hashtable;
 
import ptolemy.util.StringUtilities;
 
//////////////////////////////////////////////////////////////////////////
//// EPSGraphics
 
/**
Graphics class supporting EPS export from plots.
If this is used from within an applet, then the output goes to the standard
output. Unfortunately, with standard browsers, this is not useful.
With MS Internet Explorer, standard output is not available.
With Netscape Navigator, standard output is available in the Java console,
but is limited to fewer lines than what is usually generated.
Thus, we recommend using this within Sun's appletviewer, and redirecting
its standard output to a file.
 
@author Edward A. Lee
@version $Id: EPSGraphics.java,v 1.41 2006/03/30 16:36:39 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class EPSGraphics extends Graphics {
/** Constructor for a graphics object that writes encapsulated
* PostScript to the specified output stream. If the out argument is
* null, then it writes to standard output (it would write it to
* the clipboard, but as of this writing, writing to the clipboard
* does not work in Java).
* @param out The stream to write to, or null to write to standard out.
* @param width The width of the plot graphic, in units of 1/72 inch.
* @param height The height of the plot graphic, in units of 1/72 inch.
*/
public EPSGraphics(OutputStream out, int width, int height) {
_width = width;
_height = height;
_out = out;
_buffer.append("%!PS-Adobe-3.0 EPSF-3.0\n");
_buffer.append("%%Creator: UC Berkeley Plot Package\n");
_buffer.append("%%BoundingBox: 50 50 " + (50 + width) + " "
+ (50 + height) + "\n");
_buffer.append("%%Pages: 1\n");
_buffer.append("%%Page: 1 1\n");
_buffer.append("%%LanguageLevel: 2\n");
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
public void clearRect(int x, int y, int width, int height) {
}
 
public void clipRect(int x, int y, int width, int height) {
}
 
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
}
 
public Graphics create() {
return new EPSGraphics(_out, _width, _height);
}
 
public void dispose() {
}
 
public void drawArc(int x, int y, int width, int height, int startAngle,
int arcAngle) {
}
 
public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
return true;
}
 
public boolean drawImage(Image img, int x, int y, int width, int height,
ImageObserver observer) {
return true;
}
 
public boolean drawImage(Image img, int x, int y, Color bgcolor,
ImageObserver observer) {
return true;
}
 
public boolean drawImage(Image img, int x, int y, int width, int height,
Color bgcolor, ImageObserver observer) {
return true;
}
 
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
return true;
}
 
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2, Color bgcolor,
ImageObserver observer) {
return true;
}
 
/** Draw a line, using the current color, between the points (x1, y1)
* and (x2, y2) in this graphics context's coordinate system.
* @param x1 the x coordinate of the first point.
* @param y1 the y coordinate of the first point.
* @param x2 the x coordinate of the second point.
* @param y2 the y coordinate of the second point.
*/
public void drawLine(int x1, int y1, int x2, int y2) {
Point start = _convert(x1, y1);
Point end = _convert(x2, y2);
_buffer.append("newpath " + start.x + " " + start.y + " moveto\n");
_buffer.append("" + end.x + " " + end.y + " lineto\n");
_buffer.append("stroke\n");
}
 
public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
}
 
/** Draw a closed polygon defined by arrays of x and y coordinates.
* Each pair of (x, y) coordinates defines a vertex. The third argument
* gives the number of vertices. If the arrays are not long enough to
* define this many vertices, or if the third argument is less than three,
* then nothing is drawn.
* @param xPoints An array of x coordinates.
* @param yPoints An array of y coordinates.
* @param nPoints The total number of vertices.
*/
public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
if (!_polygon(xPoints, yPoints, nPoints)) {
return;
} else {
_buffer.append("closepath stroke\n");
}
}
 
/** Draw an oval bounded by the specified rectangle with the current color.
* @param x The x coordinate of the upper left corner
* @param y The y coordinate of the upper left corner
* @param width The width of the oval to be filled.
* @param height The height of the oval to be filled.
*/
 
// FIXME: Currently, this ignores the fourth argument and draws a circle
// with diameter given by the third argument.
public void drawOval(int x, int y, int width, int height) {
int radius = width / 2;
Point center = _convert(x + radius, y + radius);
_buffer.append("newpath " + center.x + " " + center.y + " " + radius
+ " 0 360 arc closepath stroke\n");
}
 
public void drawRect(int x, int y, int width, int height) {
Point start = _convert(x, y);
_buffer.append("newpath " + start.x + " " + start.y + " moveto\n");
_buffer.append("0 " + (-height) + " rlineto\n");
_buffer.append("" + width + " 0 rlineto\n");
_buffer.append("0 " + height + " rlineto\n");
_buffer.append("" + (-width) + " 0 rlineto\n");
_buffer.append("closepath stroke\n");
}
 
public void drawRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight) {
}
 
public void drawString(java.text.AttributedCharacterIterator iterator,
int x, int y) {
// FIXME: This method is present in the graphics class in JDK1.2,
// but not in JDK1.1.
throw new RuntimeException(
"Sorry, drawString(java.text.AttributedCharacterIterator, "
+ "int , int) is not implemented in EPSGraphics");
}
 
/** Draw a string. "(" is converted to "\(" and
* ")" is converted to "\) so as to avoid EPS Syntax errors.
* @param str The string to draw.
* @param x The x location of the string.
* @param y The y location of the string.
*/
public void drawString(String str, int x, int y) {
Point start = _convert(x, y);
_buffer.append("" + start.x + " " + start.y + " moveto\n");
 
if ((str.indexOf("(") > -1) && (str.indexOf("\\(") == -1)) {
str = StringUtilities.substitute(str, "(", "\\(");
}
 
if ((str.indexOf(")") > -1) && (str.indexOf("\\)") == -1)) {
str = StringUtilities.substitute(str, ")", "\\)");
}
 
_buffer.append("(" + str + ") show\n");
}
 
public void fillArc(int x, int y, int width, int height, int startAngle,
int arcAngle) {
}
 
/** Draw a filled polygon defined by arrays of x and y coordinates.
* Each pair of (x, y) coordinates defines a vertex. The third argument
* gives the number of vertices. If the arrays are not long enough to
* define this many vertices, or if the third argument is less than three,
* then nothing is drawn.
* @param xPoints An array of x coordinates.
* @param yPoints An array of y coordinates.
* @param nPoints The total number of vertices.
*/
public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
if (!_polygon(xPoints, yPoints, nPoints)) {
return;
} else {
_buffer.append("closepath fill\n");
}
}
 
/** Fill an oval bounded by the specified rectangle with the current color.
* @param x The x coordinate of the upper left corner
* @param y The y coordinate of the upper left corner
* @param width The width of the oval to be filled.
* @param height The height of the oval to be filled.
*/
 
// FIXME: Currently, this ignores the fourth argument and draws a circle
// with diameter given by the third argument.
public void fillOval(int x, int y, int width, int height) {
int radius = width / 2;
Point center = _convert(x + radius, y + radius);
_buffer.append("newpath " + center.x + " " + center.y + " " + radius
+ " 0 360 arc closepath fill\n");
}
 
/** Fill the specified rectangle and draw a thin outline around it.
* The left and right edges of the rectangle are at x and x + width - 1.
* The top and bottom edges are at y and y + height - 1.
* The resulting rectangle covers an area width pixels wide by
* height pixels tall. The rectangle is filled using the
* brightness of the current color to set the level of gray.
* @param x The x coordinate of the top left corner.
* @param y The y coordinate of the top left corner.
* @param width The width of the rectangle.
* @param height The height of the rectangle.
*/
public void fillRect(int x, int y, int width, int height) {
Point start = _convert(x, y);
_fillPattern();
_buffer.append("newpath " + start.x + " " + start.y + " moveto\n");
_buffer.append("0 " + (-height) + " rlineto\n");
_buffer.append("" + width + " 0 rlineto\n");
_buffer.append("0 " + height + " rlineto\n");
_buffer.append("" + (-width) + " 0 rlineto\n");
_buffer.append("closepath gsave fill grestore\n");
_buffer.append("0.5 setlinewidth 0 setgray [] 0 setdash stroke\n");
 
// reset the gray scale to black
_buffer.append("1 setlinewidth\n");
}
 
public void fillRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight) {
}
 
public Shape getClip() {
return null;
}
 
public Rectangle getClipBounds() {
return null;
}
 
public Color getColor() {
return _currentColor;
}
 
public Font getFont() {
return _currentFont;
}
 
public FontMetrics getFontMetrics(Font f) {
return null;
}
 
public void setFont(Font font) {
if (font == null) {
return;
}
 
int size = font.getSize();
boolean bold = font.isBold();
 
if (bold) {
_buffer.append("/Helvetica-Bold findfont\n");
} else {
_buffer.append("/Helvetica findfont\n");
}
 
_buffer.append("" + size + " scalefont setfont\n");
_currentFont = font;
}
 
public void setClip(Shape clip) {
}
 
public void setClip(int x, int y, int width, int height) {
}
 
/** Set the current color. Since we are generating gray scale
* postscript, set a line style. Set the gray level to zero (black).
* @param c The desired current color.
*/
public void setColor(Color c) {
if (c == Color.black) {
_buffer.append("0 setgray\n");
_buffer.append("[] 0 setdash\n");
_buffer.append("1 setlinewidth\n");
} else if (c == Color.white) {
_buffer.append("1 setgray\n");
_buffer.append("[] 0 setdash\n");
_buffer.append("1 setlinewidth\n");
} else if (c == Color.lightGray) {
_buffer.append("0.9 setgray\n");
_buffer.append("[] 0 setdash\n");
_buffer.append("0.5 setlinewidth\n");
} else {
if (_linepattern.containsKey(c)) {
_buffer.append((String) _linepattern.get(c) + " 0 setdash\n");
_buffer.append("1 setlinewidth\n");
} else {
_buffer.append("0 setgray\n");
 
// construct a new line pattern.
if (_patternIndex >= _patterns.length) {
_patternIndex = 0;
}
 
_buffer.append(_patterns[_patternIndex] + " 0 setdash\n");
_buffer.append("1 setlinewidth\n");
_linepattern.put(c, _patterns[_patternIndex]);
_patternIndex++;
}
}
 
_currentColor = c;
}
 
public void setPaintMode() {
}
 
public void setXORMode(Color c1) {
}
 
/** Issue the PostScript showpage command, then write and flush the output.
* If the output argument of the constructor was null, then write
* to the clipboard.
*/
public void showpage() {
_buffer.append("showpage\n");
 
if (_out != null) {
PrintWriter output = new PrintWriter(new BufferedOutputStream(_out));
 
output.println(_buffer.toString());
output.flush();
} else {
// Write to clipboard instead
// NOTE: This doesn't work at least with jdk 1.3beta
if (_clipboard == null) {
_clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
}
 
StringSelection sel = new StringSelection(_buffer.toString());
_clipboard.setContents(sel, sel);
}
}
 
public void translate(int x, int y) {
}
 
///////////////////////////////////////////////////////////////////
//// private methods ////
// Convert the screen coordinate system to that of postscript.
private Point _convert(int x, int y) {
return new Point(x + 50, (_height + 50) - y);
}
 
// Draw a closed polygon defined by arrays of x and y coordinates.
// Return false if arguments are misformed.
private boolean _polygon(int[] xPoints, int[] yPoints, int nPoints) {
if ((nPoints < 3) || (xPoints.length < nPoints)
|| (yPoints.length < nPoints)) {
return false;
}
 
Point start = _convert(xPoints[0], yPoints[0]);
_buffer.append("newpath " + start.x + " " + start.y + " moveto\n");
 
for (int i = 1; i < nPoints; i++) {
Point vertex = _convert(xPoints[i], yPoints[i]);
_buffer.append("" + vertex.x + " " + vertex.y + " lineto\n");
}
 
return true;
}
 
// Issue a command to set the fill pattern.
// Currently, this is a gray level that is a function of the color.
private void _fillPattern() {
// FIXME: We probably want a fill pattern rather than
// just a gray scale.
int red = _currentColor.getRed();
int green = _currentColor.getGreen();
int blue = _currentColor.getBlue();
 
// Scaling constants so that fully saturated R, G, or B appear
// different.
double bluescale = 0.6; // darkest
double redscale = 0.8;
double greenscale = 1.0; // lightest
double fullscale = Math.sqrt(255.0 * 255.0 * ((bluescale * bluescale)
+ (redscale * redscale) + (greenscale * greenscale)));
double graylevel = Math.sqrt(((red * red * redscale * redscale)
+ (blue * blue * bluescale * bluescale) + (green * green
* greenscale * greenscale)))
/ fullscale;
_buffer.append("" + graylevel + " setgray\n");
 
// NOTE -- for debugging, output color spec in comments
_buffer.append("%---- rgb: " + red + " " + green + " " + blue + "\n");
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
private Color _currentColor = Color.black;
 
private Font _currentFont;
 
private int _width;
 
private int _height;
 
private Hashtable _linepattern = new Hashtable();
 
private OutputStream _out;
 
private StringBuffer _buffer = new StringBuffer();
 
private Clipboard _clipboard;
 
// Default line patterns.
// FIXME: Need at least 11 of these.
static private String[] _patterns = { "[]", "[1 1]", "[4 4]", "[4 4 1 4]",
"[2 2]", "[4 2 1 2 1 2]", "[5 3 2 3]", "[3 3]", "[4 2 1 2 2 2]",
"[1 2 5 2 1 2 1 2]", "[4 1 2 1]", };
 
private int _patternIndex = 0;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/EditablePlot.java
0,0 → 1,540
/* Extension of plot that allows interactive modification of plot data.
 
Copyright (c) 1998-2007 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
 
*/
package ptolemy.plot;
 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Enumeration;
import java.util.Stack;
import java.util.Vector;
 
//////////////////////////////////////////////////////////////////////////
//// EditablePlot
 
/**
This extension of Plot permits interactive modification of plotted
data, one dataset at a time. By default, you can modify dataset
number zero (the first one given). To change this default, call
setEditable(). To edit a plot, use the right mouse button.
Click and drag to the left to trace out new values for the data.
To read back the modified data, use getData(). To undo a change to
the data, type Control-Z. To redo the change, type Control-Y.
The undo history is infinite.
<p>
The style of editing is very particular. This class assumes the data
specify a function of <i>x</i>. I.e., there there is exactly one
<i>y</i> value for every <i>x</i> value. Thus, with the right mouse
button, you are allowed to trace out new <i>y</i> values
starting with some leftmost <i>x</i> value. You can only trace
values to the right. This feature makes it easy to trace values
with discontinuities. Just start at the left, and drag to the right
to the point of the discontinuity, then drag to the left,
then right again. You will have to try it...
Notice that this style of editing probably does not make sense with
error bars, since there is no mechanism for editing the error bars.
<p>
To be able to modify the data in a dataset, of course, there must
be data in the dataset. Thus, you should create a dataset (for
example by calling addPoint()) before editing it. Only the visible
part of the dataset can be edited (that is, the portion of the dataset
along the visible part of the horizontal axis). If you zoom in, then,
you can edit particular points more precisely.
<p>
To be notified when the user sketches a new signal, create an
object that implements the EditListener interface and add that
listener using addEditListener().
 
@author Edward A. Lee
@version $Id: EditablePlot.java,v 1.39 2007/12/06 18:23:51 cxh Exp $
@since Ptolemy II 0.4
@Pt.ProposedRating Red (cxh)
@Pt.AcceptedRating Red (cxh)
*/
public class EditablePlot extends Plot {
/** Constructor.
*/
public EditablePlot() {
super();
addMouseListener(new EditMouseListener());
addMouseMotionListener(new ModifyListener());
addKeyListener(new UndoListener());
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Add a listener to be informed when the user modifies a data set.
* @param listener The listener.
* @see EditListener
*/
public void addEditListener(EditListener listener) {
if (_editListeners == null) {
_editListeners = new Vector();
} else {
if (_editListeners.contains(listener)) {
return;
}
}
 
_editListeners.addElement(listener);
}
 
/** Get the data in the specified dataset. This is returned as
* a two-dimensional array, where the first index specifies
* X or Y data (index 0 or 1 respectively), and the second
* index specifies the point.
* @return The data in the specified dataset.
*/
public double[][] getData(int dataset) {
_checkDatasetIndex(dataset);
 
Vector pts = (Vector) _points.elementAt(dataset);
int size = pts.size();
double[][] result = new double[2][size];
 
for (int i = 0; i < size; i++) {
PlotPoint pt = (PlotPoint) pts.elementAt(i);
result[0][i] = pt.x;
result[1][i] = pt.y;
}
 
return result;
}
 
/** Redo the latest signal editing operation that was undone by
* calling undo(), if there was one. Otherwise, do nothing.
*/
public void redo() {
if (_redoStack.empty()) {
return;
}
 
Object[] save = new Object[2];
save[0] = Integer.valueOf(_dataset);
save[1] = getData(_dataset);
_undoStack.push(save);
 
Object[] saved = (Object[]) _redoStack.pop();
_setData(((Integer) saved[0]).intValue(), (double[][]) saved[1]);
 
// Ensure replot of offscreen buffer.
_plotImage = null;
repaint();
_notifyListeners(_dataset);
}
 
/** Unregister a edit listener. If the specified listener has not
* been previously registered, then do nothing.
* @param listener The listener to remove from the list of listeners
* to which edit events are sent.
*/
public void removeEditListener(EditListener listener) {
if (_editListeners == null) {
return;
}
 
_editListeners.removeElement(listener);
}
 
/** Specify which dataset is editable. By default, if this method is
* not called, dataset number zero is editable. If you call this
* method with a negative number, then no dataset will be editable.
* @param dataset The editable dataset.
*/
public void setEditable(int dataset) {
if (dataset >= 0) {
_checkDatasetIndex(dataset);
}
 
_dataset = dataset;
}
 
/** Undo the latest signal editing operation, if there was one.
* Otherwise, do nothing.
*/
public void undo() {
if (_undoStack.empty()) {
return;
}
 
Object[] save = new Object[2];
save[0] = Integer.valueOf(_dataset);
save[1] = getData(_dataset);
_redoStack.push(save);
 
Object[] saved = (Object[]) _undoStack.pop();
_setData(((Integer) saved[0]).intValue(), (double[][]) saved[1]);
 
// Ensure replot of offscreen buffer.
_plotImage = null;
repaint();
_notifyListeners(_dataset);
}
 
///////////////////////////////////////////////////////////////////
//// private methods ////
// Clear the editing spec and modify the dataset.
private synchronized void _edit(int x, int y) {
if (_dataset < 0) {
return;
}
 
// Save for undo.
Object[] save = new Object[2];
save[0] = Integer.valueOf(_dataset);
save[1] = getData(_dataset);
 
// FIXME: Need a way to notify menus to enable items...
_undoStack.push(save);
 
// NOTE: the clear() method was added in jdk 1.2, so we don't
// use it here for maximal compatibility...
// _redoStack.clear();
while (!_redoStack.empty()) {
_redoStack.pop();
}
 
// constrain to be in range
if (y > _lry) {
y = _lry;
}
 
if (y < _uly) {
y = _uly;
}
 
if (x > _lrx) {
x = _lrx;
}
 
if (x < _ulx) {
x = _ulx;
}
 
_editPoint(x, y);
 
// Edit the points in the signal.
Vector pts = (Vector) _points.elementAt(_dataset);
 
for (int i = 0; i < pts.size(); i++) {
PlotPoint pt = (PlotPoint) pts.elementAt(i);
 
// Only bother with points in visual range
if ((pt.x >= _xMin) && (pt.x <= _xMax)) {
int index = (int) ((pt.x - _xMin) * _xscale)
- (_lrx - _ulx - _editSpecX.length);
 
if ((index >= 0) && (index < _editSpecX.length)) {
if (_editSpecSet[index]) {
pt.y = _yMax - ((_editSpecY[index] - _uly) / _yscale);
 
// For auto-ranging, keep track of min and max.
if (pt.y < _yBottom) {
_yBottom = pt.y;
}
 
if (pt.y > _yTop) {
_yTop = pt.y;
}
}
}
}
}
 
// Ensure replot of offscreen buffer.
_plotImage = null;
repaint();
 
// Erase the guide
// I don't think we need to do this, since we call repaint().
// graphics.setXORMode(_editColor);
// for (int i = 0; i < _editSpecX.length; i++) {
// if (_editSpecSet[i]) {
// graphics.drawLine(_editSpecX[i], _editSpecY[i]-1,
// _editSpecX[i], _editSpecY[i]+1);
// }
// }
// graphics.setPaintMode();
_notifyListeners(_dataset);
}
 
// Make a record of a new edit point.
private synchronized void _editPoint(int x, int y) {
if (_dataset < 0) {
return;
}
 
Graphics graphics = getGraphics();
 
// constrain to be in range
if (y > _lry) {
y = _lry;
}
 
if (y < _uly) {
y = _uly;
}
 
if (x > _lrx) {
x = _lrx;
}
 
if (x < _ulx) {
x = _ulx;
}
 
if ((x <= _currentEditX) || (x >= _lrx)) {
// ignore
return;
}
 
int step = _currentEditX;
 
while (step <= x) {
int index = step - (_lrx - _editSpecX.length);
double proportion = (step - _currentEditX)
/ (double) (x - _currentEditX);
int newY = (int) (_currentEditY + (proportion * (y - _currentEditY)));
 
if (!_editSpecSet[index]) {
_editSpecX[index] = step;
_editSpecY[index] = newY;
_editSpecSet[index] = true;
 
// Draw point, linearly interpolated from previous point
graphics.setXORMode(_editColor);
graphics.drawLine(step, newY - 1, step, newY + 1);
graphics.setPaintMode();
}
 
step++;
}
 
_currentEditX = x;
_currentEditY = y;
}
 
// Make a record of the starting x and y position of an edit.
private synchronized void _editStart(int x, int y) {
if (_dataset < 0) {
return;
}
 
// constrain to be in range
if (y > _lry) {
y = _lry;
}
 
if (y < _uly) {
y = _uly;
}
 
if (x > _lrx) {
x = _lrx;
}
 
if (x < _ulx) {
x = _ulx;
}
 
// Allocate a vector to store the points.
int size = _lrx - x + 1;
_editSpecX = new int[size];
_editSpecY = new int[size];
_editSpecSet = new boolean[size];
 
_editSpecX[0] = x;
_editSpecY[0] = y;
_editSpecSet[0] = true;
 
_currentEditX = x;
_currentEditY = y;
 
Graphics graphics = getGraphics();
 
// Draw point (as a 3 pixel vertical line, for thickness)
graphics.setXORMode(_editColor);
graphics.drawLine(x, y - 1, x, y + 1);
graphics.setPaintMode();
}
 
// Notify all edit listeners that have registered.
private void _notifyListeners(int dataset) {
if (_editListeners == null) {
return;
} else {
Enumeration listeners = _editListeners.elements();
 
while (listeners.hasMoreElements()) {
((EditListener) listeners.nextElement()).editDataModified(this,
dataset);
}
}
}
 
// Set the data in the specified dataset. The argument is of the
// form returned by getData.
private void _setData(int dataset, double[][] data) {
_checkDatasetIndex(dataset);
 
Vector pts = (Vector) _points.elementAt(dataset);
int size = pts.size();
 
if (data[0].length < size) {
size = data[0].length;
}
 
for (int i = 0; i < size; i++) {
PlotPoint pt = (PlotPoint) pts.elementAt(i);
pt.x = data[0][i];
pt.y = data[1][i];
}
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
private int[] _editSpecX;
 
///////////////////////////////////////////////////////////////////
//// private variables ////
private int[] _editSpecY;
 
private boolean[] _editSpecSet;
 
private int _currentEditX;
 
private int _currentEditY;
 
private int _dataset = 0;
 
// Call setXORMode with a hardwired color because
// _background does not work in an application,
// and _foreground does not work in an applet
private static final Color _editColor = Color.white;
 
// Stack for undo.
private Stack _undoStack = new Stack();
 
private Stack _redoStack = new Stack();
 
// Edit listeners.
private Vector _editListeners = null;
 
///////////////////////////////////////////////////////////////////
//// inner classes ////
public class EditMouseListener implements MouseListener {
public void mouseClicked(MouseEvent event) {
}
 
public void mouseEntered(MouseEvent event) {
}
 
public void mouseExited(MouseEvent event) {
}
 
public void mousePressed(MouseEvent event) {
if ((event.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
EditablePlot.this._editStart(event.getX(), event.getY());
}
}
 
public void mouseReleased(MouseEvent event) {
if ((event.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
EditablePlot.this._edit(event.getX(), event.getY());
}
}
}
 
public class ModifyListener implements MouseMotionListener {
public void mouseDragged(MouseEvent event) {
if ((event.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
EditablePlot.this._editPoint(event.getX(), event.getY());
}
}
 
public void mouseMoved(MouseEvent event) {
}
}
 
public class UndoListener implements KeyListener {
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
 
switch (keycode) {
case KeyEvent.VK_CONTROL:
_control = true;
break;
 
case KeyEvent.VK_Z:
 
if (_control) {
undo();
}
 
break;
 
case KeyEvent.VK_Y:
 
if (_control) {
redo();
}
 
break;
 
default:
// None
}
}
 
public void keyReleased(KeyEvent e) {
int keycode = e.getKeyCode();
 
switch (keycode) {
case KeyEvent.VK_CONTROL:
_control = false;
break;
 
default:
// None
}
}
 
// The keyTyped method is broken in jdk 1.1.4.
// It always gets "unknown key code".
public void keyTyped(KeyEvent e) {
}
 
private boolean _control = false;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/EditablePlotApplet.java
0,0 → 1,129
/* Applet containing the EditablePlot class.
 
@Copyright (c) 1997-2005 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
 
import ptolemy.plot.EditablePlot;
import ptolemy.plot.Plot;
import ptolemy.plot.PlotBox;
 
//////////////////////////////////////////////////////////////////////////
//// EditablePlotApplet
 
/**
This applet reads a URL giving a Plot file for a plot and places
the data into an editable plot.
 
@see EditablePlot
@author Edward A. Lee
@version $Id: EditablePlotApplet.java,v 1.31 2005/07/08 19:59:37 cxh Exp $
@since Ptolemy II 0.4
@Pt.ProposedRating red (eal)
@Pt.AcceptedRating red (cxh)
*/
public class EditablePlotApplet extends PlotApplet {
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Initialize the applet. Place an instance of EditablePlot
* and a widget for selecting the data set to edit.
*/
public void init() {
super.init();
 
JPanel controlPanel = new JPanel();
 
// Make the panel transparent so that the background shows through.
controlPanel.setOpaque(false);
getContentPane().add(controlPanel, BorderLayout.SOUTH);
 
controlPanel.add(new JLabel("Data set to edit:"));
 
_choice = new JComboBox();
controlPanel.add(_choice);
 
for (int i = 0; i < ((Plot) plot()).getNumDataSets(); i++) {
_choice.addItem(plot().getLegend(i));
}
 
_choice.addActionListener(new ChoiceListener());
}
 
/**
* Return a string describing this applet.
*/
public String getAppletInfo() {
return "EditablePlotDemo "
+ ": Demo of EditablePlot.\n"
+ "By: Edward A. Lee\n "
+ "($Id: EditablePlotApplet.java,v 1.31 2005/07/08 19:59:37 cxh Exp $)";
}
 
/** Create a new Plot object for the applet. Derived classes can
* redefine this method to return a different type of plot object.
*/
public PlotBox newPlot() {
return new EditablePlot();
}
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
 
/** Given the size of the applet, set the size of the plot.
* Derived classes may override this to allow room for other
* widgets below the plot.
* @param appletWidth The width of the applet.
* @param appletHeight The height of the applet.
*/
protected void _setPlotSize(int appletWidth, int appletHeight) {
if (appletHeight > 50) {
plot().setSize(appletWidth, appletHeight - 50);
} else {
plot().setSize(appletWidth, appletHeight);
}
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
// Choice widget for selecting the editable data set.
private JComboBox _choice;
 
///////////////////////////////////////////////////////////////////
//// inner classes ////
private class ChoiceListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
((EditablePlot) plot()).setEditable(_choice.getSelectedIndex());
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/Plot.java
0,0 → 1,2622
/* A signal plotter.
 
@Copyright (c) 1997-2007 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
// TO DO:
// - steps between points rather than connected lines.
// - cubic spline interpolation
//
// NOTE: The XOR drawing mode is needed in order to be able to erase
// plotted points and restore the grid line, tick marks, and boundary
// rectangle. This introduces a number of artifacts, particularly
// where lines cross. A better alternative in the long run would be
// use Java 2-D, which treats each notation on the screen as an object,
// and supports redrawing only damaged regions of the screen.
// NOTE: There are quite a few subjective spacing parameters, all
// given, unfortunately, in pixels. This means that as resolutions
// get better, this program may need to be adjusted.
import java.awt.BasicStroke;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.URL;
import java.util.Enumeration;
import java.util.Vector;
 
import javax.swing.JComponent;
 
//////////////////////////////////////////////////////////////////////////
//// Plot
 
/**
A flexible signal plotter. The plot can be configured and data can
be provided either through a file with commands or through direct
invocation of the public methods of the class.
<p>
When calling the public methods, in most cases the changes will not
be visible until paintComponent() is called. To request that this
be done, call repaint(). One exception is addPoint(), which
makes the new point visible immediately if the plot is visible on
the screen and addPoint() is called from the event dispatching thread.
<p>
This base class supports a simple file syntax that has largely been
replaced by the XML-based PlotML syntax. To read a file or a
URL in this older syntax, use the read() method.
This older syntax contains any number commands,
one per line. Unrecognized commands and commands with syntax
errors are ignored. Comments are denoted by a line starting with a
pound sign "#". The recognized commands include those supported by
the base class, plus a few more. The commands are case
insensitive, but are usually capitalized. The number of data sets
to be plotted does not need to be specified. Data sets are added as needed.
Each dataset can be optionally identified with
color (see the base class) or with unique marks. The style of
marks used to denote a data point is defined by one of the following
commands:
<pre>
Marks: none
Marks: points
Marks: dots
Marks: various
Marks: pixels
</pre>
Here, "points" are small dots, while "dots" are larger. If "various"
is specified, then unique marks are used for the first ten data sets,
and then recycled. If "pixels" are specified, then each point is
drawn as one pixel.
Using no marks is useful when lines connect the points in a plot,
which is done by default. However, if persistence is set, then you
may want to choose "pixels" because the lines may overlap, resulting
in annoying gaps in the drawn line.
If the above directive appears before any DataSet directive, then it
specifies the default for all data sets. If it appears after a DataSet
directive, then it applies only to that data set.
<p>
To disable connecting lines, use:
<pre>
Lines: off
</pre>
To reenable them, use
<pre>
Lines: on
</pre>
You can also specify "impulses", which are lines drawn from a plotted point
down to the x axis. Plots with impulses are often called "stem plots."
These are off by default, but can be turned on with the
command:
<pre>
Impulses: on
</pre>
or back off with the command
<pre>
Impulses: off
</pre>
If that command appears before any DataSet directive, then the command
applies to all data sets. Otherwise, it applies only to the current data
set.
To create a bar graph, turn off lines and use any of the following commands:
<pre>
Bars: on
Bars: <i>width</i>
Bars: <i>width, offset</i>
</pre>
The <i>width</i> is a real number specifying the width of the bars
in the units of the x axis. The <i>offset</i> is a real number
specifying how much the bar of the <i>i</i><sup>th</sup> data set
is offset from the previous one. This allows bars to "peek out"
from behind the ones in front. Note that the frontmost data set
will be the first one. To turn off bars, use
<pre>
Bars: off
</pre>
To specify data to be plotted, start a data set with the following command:
<pre>
DataSet: <i>string</i>
</pre>
Here, <i>string</i> is a label that will appear in the legend.
It is not necessary to enclose the string in quotation marks.
To start a new dataset without giving it a name, use:
<pre>
DataSet:
</pre>
In this case, no item will appear in the legend.
New datasets are plotted <i>behind</i> the previous ones.
If the following directive occurs:
<pre>
ReuseDataSets: on
</pre>
Then datasets with the same name will be merged. This makes it
easier to combine multiple datafiles that contain the same datasets
into one file. By default, this capability is turned off, so
datasets with the same name are not merged.
The data itself is given by a sequence of commands with one of the
following forms:
<pre>
<i>x</i>, <i>y</i>
draw: <i>x</i>, <i>y</i>
move: <i>x</i>, <i>y</i>
<i>x</i>, <i>y</i>, <i>yLowErrorBar</i>, <i>yHighErrorBar</i>
draw: <i>x</i>, <i>y</i>, <i>yLowErrorBar</i>, <i>yHighErrorBar</i>
move: <i>x</i>, <i>y</i>, <i>yLowErrorBar</i>, <i>yHighErrorBar</i>
</pre>
The "draw" command is optional, so the first two forms are equivalent.
The "move" command causes a break in connected points, if lines are
being drawn between points. The numbers <i>x</i> and <i>y</i> are
arbitrary numbers as supported by the Double parser in Java.
If there are four numbers, then the last two numbers are assumed to
be the lower and upper values for error bars.
The numbers can be separated by commas, spaces or tabs.
<p>Some of the methods, such as those that add points a plot, are
executed in the event thread, possibly some time after they are called.
If they are called from a thread different from the event thread,
then the order in which changes to the plot take effect may be
surprising. We recommend that any code you write that changes
the plot in visible ways be executed in the event thread. You
can accomplish this using the following template:
<pre>
Runnable doAction = new Runnable() {
public void run() {
... make changes here (e.g. setMarksStyle()) ...
}
};
plot.deferIfNecessary(doAction);
</pre>
<p>
This plotter has some <A NAME="ptplot limitations">limitations</a>:
<ul>
<li> If you zoom in far enough, the plot becomes unreliable.
In particular, if the total extent of the plot is more than
2<sup>32</sup> times extent of the visible area, quantization
errors can result in displaying points or lines.
Note that 2<sup>32</sup> is over 4 billion.
<li> The limitations of the log axis facility are listed in
the <code>_gridInit()</code> method in the PlotBox class.
</ul>
 
@author Edward A. Lee, Christopher Brooks
@version $Id: Plot.java,v 1.248 2007/12/16 07:29:47 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class Plot extends PlotBox {
///////////////////////////////////////////////////////////////////
//// public methods ////
/** Add a legend (displayed at the upper right) for the specified
* data set with the specified string. Short strings generally
* fit better than long strings.
* @param dataset The dataset index.
* @param legend The label for the dataset.
*/
public synchronized void addLegend(int dataset, String legend) {
_checkDatasetIndex(dataset);
 
if (!_reuseDatasets) {
super.addLegend(dataset, legend);
} else {
// If _reuseDataSets is true, then look to see if we
// already have a dataset with the same legend.
String possibleLegend = getLegend(dataset);
 
if ((possibleLegend == null)
|| ((possibleLegend != null) && !possibleLegend
.equals(legend))) {
super.addLegend(dataset, legend);
}
}
}
 
/** In the specified data set, add the specified x, y point to the
* plot. Data set indices begin with zero. If the data set
* does not exist, create it. The fourth argument indicates
* whether the point should be connected by a line to the previous
* point. Regardless of the value of this argument, a line will not
* drawn if either there has been no previous point for this dataset
* or setConnected() has been called with a false argument.
* <p>
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the point will
* not be added immediately (unless you call this method from within
* the event dispatch thread). All the methods that do this deferring
* coordinate so that they are executed in the order that you
* called them.
*
* @param dataset The data set index.
* @param x The X position of the new point.
* @param y The Y position of the new point.
* @param connected If true, a line is drawn to connect to the previous
* point.
*/
public synchronized void addPoint(final int dataset, final double x,
final double y, final boolean connected) {
Runnable doAddPoint = new Runnable() {
public void run() {
_addPoint(dataset, x, y, 0, 0, connected, false);
}
};
 
deferIfNecessary(doAddPoint);
}
 
/** In the specified data set, add the specified x, y point to the
* plot with error bars. Data set indices begin with zero. If
* the dataset does not exist, create it. yLowEB and
* yHighEB are the lower and upper error bars. The sixth argument
* indicates whether the point should be connected by a line to
* the previous point.
* The new point will be made visible if the plot is visible
* on the screen. Otherwise, it will be drawn the next time the plot
* is drawn on the screen.
* This method is based on a suggestion by
* Michael Altmann <michael@email.labmed.umn.edu>.
* <p>
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the point will
* not be added immediately (unless you call this method from within
* the event dispatch thread). All the methods that do this deferring
* coordinate so that they are executed in the order that you
* called them.
*
* @param dataset The data set index.
* @param x The X position of the new point.
* @param y The Y position of the new point.
* @param yLowEB The low point of the error bar.
* @param yHighEB The high point of the error bar.
* @param connected If true, a line is drawn to connect to the previous
* point.
*/
public synchronized void addPointWithErrorBars(final int dataset,
final double x, final double y, final double yLowEB,
final double yHighEB, final boolean connected) {
Runnable doAddPoint = new Runnable() {
public void run() {
_addPoint(dataset, x, y, yLowEB, yHighEB, connected, true);
}
};
 
deferIfNecessary(doAddPoint);
}
 
/** Clear the plot of all data points. If the argument is true, then
* reset all parameters to their initial conditions, including
* the persistence, plotting format, and axes formats.
* For the change to take effect, you must call repaint().
* @param format If true, clear the format controls as well.
* <p>
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the clear will
* not be executed immediately (unless you call this method from within
* the event dispatch thread). All the methods that do this deferring
* coordinate so that they are executed in the order that you
* called them.
*/
public synchronized void clear(final boolean format) {
Runnable doClear = new Runnable() {
public void run() {
_clear(format);
}
};
 
deferIfNecessary(doClear);
}
 
/** Clear the plot of data points in the specified dataset.
* This calls repaint() to request an update of the display.
* <p>
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the point will
* not be added immediately (unless you call this method from within
* the event dispatch thread). If you call this method, the addPoint()
* method, and the erasePoint() method in any order, they are assured
* of being processed in the order that you called them.
*
* @param dataset The dataset to clear.
*/
public synchronized void clear(final int dataset) {
Runnable doClear = new Runnable() {
public void run() {
_clear(dataset);
}
};
 
deferIfNecessary(doClear);
}
 
/** Erase the point at the given index in the given dataset. If
* lines are being drawn, also erase the line to the next points
* (note: not to the previous point). The point is not checked to
* see whether it is in range, so care must be taken by the caller
* to ensure that it is.
* <p>
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the point will
* not be erased immediately (unless you call this method from within
* the event dispatch thread). All the methods that do this deferring
* coordinate so that they are executed in the order that you
* called them.
*
* @param dataset The data set index.
* @param index The index of the point to erase.
*/
public synchronized void erasePoint(final int dataset, final int index) {
Runnable doErasePoint = new Runnable() {
public void run() {
_erasePoint(dataset, index);
}
};
 
deferIfNecessary(doErasePoint);
}
 
/** Rescale so that the data that is currently plotted just fits.
* This overrides the base class method to ensure that the protected
* variables _xBottom, _xTop, _yBottom, and _yTop are valid.
* This method calls repaint(), which eventually causes the display
* to be updated.
* <p>
* In order to work well with swing and be thread safe, this method
* actually defers execution to the event dispatch thread, where
* all user interface actions are performed. Thus, the fill will
* not occur immediately (unless you call this method from within
* the event dispatch thread). All the methods that do this deferring
* coordinate so that they are executed in the order that you
* called them.
*/
public synchronized void fillPlot() {
Runnable doFill = new Runnable() {
public void run() {
_fillPlot();
}
};
 
deferIfNecessary(doFill);
}
 
/** Return whether the default is to connect
* subsequent points with a line. If the result is false, then
* points are not connected. When points are by default
* connected, individual points can be not connected by giving the
* appropriate argument to addPoint(). Also, a different default
* can be set for each dataset, overriding this global default.
*/
public boolean getConnected() {
return _connected;
}
 
/** Return whether a line will be drawn from any
* plotted point down to the x axis.
* A plot with such lines is also known as a stem plot.
*/
public boolean getImpulses() {
return _impulses;
}
 
/** Get the marks style, which is one of
* "none", "points", "dots", or "various".
* @return A string specifying the style for points.
*/
public synchronized String getMarksStyle() {
// NOTE: If the number of marks increases, we will need to do
// something better here...
if (_marks == 0) {
return "none";
} else if (_marks == 1) {
return "points";
} else if (_marks == 2) {
return "dots";
} else if (_marks == 3) {
return "various";
} else {
return "pixels";
}
}
 
/** Return the maximum number of data sets.
* This method is deprecated, since there is no longer an upper bound.
* @deprecated
*/
public int getMaxDataSets() {
return Integer.MAX_VALUE;
}
 
/** Return the actual number of data sets.
* @return The number of data sets that have been created.
*/
public synchronized int getNumDataSets() {
return _points.size();
}
 
/** Return false if setReuseDatasets() has not yet been called
* or if setReuseDatasets(false) has been called.
* @return false if setReuseDatasets() has not yet been called
* or if setReuseDatasets(false) has been called.
* @since Ptplot 5.3
* @see #setReuseDatasets(boolean)
*/
public boolean getReuseDatasets() {
return _reuseDatasets;
}
 
/** Override the base class to indicate that a new data set is being read.
* This method is deprecated. Use read() instead (to read the old
* file format) or one of the classes in the plotml package to read
* the new (XML) file format.
* @deprecated
*/
public void parseFile(String filespec, URL documentBase) {
_firstInSet = true;
_sawFirstDataSet = false;
super.parseFile(filespec, documentBase);
}
 
/** Read a file with the old syntax (non-XML).
* Override the base class to register that we are reading a new
* data set.
* @param inputStream The input stream.
* @exception IOException If the stream cannot be read.
*/
public synchronized void read(InputStream inputStream) throws IOException {
super.read(inputStream);
_firstInSet = true;
_sawFirstDataSet = false;
}
 
/** Create a sample plot. This is not actually done immediately
* unless the calling thread is the event dispatch thread.
* Instead, it is deferred to the event dispatch thread.
* It is important that the calling thread not hold a synchronize
* lock on the Plot object, or deadlock will result (unless the
* calling thread is the event dispatch thread).
*/
public synchronized void samplePlot() {
// This needs to be done in the event thread.
Runnable sample = new Runnable() {
public void run() {
synchronized (Plot.this) {
// Create a sample plot.
clear(true);
 
setTitle("Sample plot");
setYRange(-4, 4);
setXRange(0, 100);
setXLabel("time");
setYLabel("value");
addYTick("-PI", -Math.PI);
addYTick("-PI/2", -Math.PI / 2);
addYTick("0", 0);
addYTick("PI/2", Math.PI / 2);
addYTick("PI", Math.PI);
setMarksStyle("none");
setImpulses(true);
 
boolean first = true;
 
for (int i = 0; i <= 100; i++) {
double xvalue = i;
 
// NOTE: jdk 1.3beta has a bug exhibited here.
// The value of the second argument in the calls
// to addPoint() below is corrupted the second
// time that this method is called. The print
// statement below shows that the value is
// correct before the call.
// System.out.println("x value: " + xvalue);
// For some bizarre reason, this problem goes
// away when this code is executed in the event
// dispatch thread.
addPoint(0, xvalue, 5 * Math.cos((Math.PI * i) / 20),
!first);
addPoint(1, xvalue, 4.5 * Math.cos((Math.PI * i) / 25),
!first);
addPoint(2, xvalue, 4 * Math.cos((Math.PI * i) / 30),
!first);
addPoint(3, xvalue, 3.5 * Math.cos((Math.PI * i) / 35),
!first);
addPoint(4, xvalue, 3 * Math.cos((Math.PI * i) / 40),
!first);
addPoint(5, xvalue, 2.5 * Math.cos((Math.PI * i) / 45),
!first);
addPoint(6, xvalue, 2 * Math.cos((Math.PI * i) / 50),
!first);
addPoint(7, xvalue, 1.5 * Math.cos((Math.PI * i) / 55),
!first);
addPoint(8, xvalue, 1 * Math.cos((Math.PI * i) / 60),
!first);
addPoint(9, xvalue, 0.5 * Math.cos((Math.PI * i) / 65),
!first);
first = false;
} // for
} // synchronized
 
repaint();
} // run method
}; // Runnable class
 
deferIfNecessary(sample);
}
 
/** Turn bars on or off (for bar charts). Note that this is a global
* property, not per dataset.
* @param on If true, turn bars on.
*/
public void setBars(boolean on) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_bars = on;
}
 
/** Turn bars on and set the width and offset. Both are specified
* in units of the x axis. The offset is the amount by which the
* i < sup>th</sup> data set is shifted to the right, so that it
* peeks out from behind the earlier data sets.
* @param width The width of the bars.
* @param offset The offset per data set.
*/
public synchronized void setBars(double width, double offset) {
// Ensure replot of offscreen buffer.
_plotImage = null;
barWidth = width;
_barOffset = offset;
_bars = true;
}
 
/** If the argument is true, then the default is to connect
* subsequent points with a line. If the argument is false, then
* points are not connected. When points are by default
* connected, individual points can be not connected by giving the
* appropriate argument to addPoint(). Also, a different default
* can be set for each dataset, overriding this global default.
* @param on If true, draw lines between points.
* @see #setConnected(boolean, int)
*/
public void setConnected(boolean on) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_connected = on;
}
 
/** If the first argument is true, then by default for the specified
* dataset, points will be connected by a line. Otherwise, the
* points will not be connected. When points are by default
* connected, individual points can be not connected by giving the
* appropriate argument to addPoint().
* Note that this method should be called before adding any points.
* Note further that this method should probably be called from
* the event thread.
* @param on If true, draw lines between points.
* @param dataset The dataset to which this should apply.
* @see #setConnected(boolean)
*/
public synchronized void setConnected(boolean on, int dataset) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_checkDatasetIndex(dataset);
 
Format fmt = (Format) _formats.elementAt(dataset);
fmt.connected = on;
fmt.connectedUseDefault = false;
}
 
/** If the argument is true, then a line will be drawn from any
* plotted point down to the x axis. Otherwise, this feature is
* disabled. A plot with such lines is also known as a stem plot.
* @param on If true, draw a stem plot.
*/
public synchronized void setImpulses(boolean on) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_impulses = on;
}
 
/** If the first argument is true, then a line will be drawn from any
* plotted point in the specified dataset down to the x axis.
* Otherwise, this feature is
* disabled. A plot with such lines is also known as a stem plot.
* @param on If true, draw a stem plot.
* @param dataset The dataset to which this should apply.
*/
public synchronized void setImpulses(boolean on, int dataset) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_checkDatasetIndex(dataset);
 
Format fmt = (Format) _formats.elementAt(dataset);
fmt.impulses = on;
fmt.impulsesUseDefault = false;
}
 
/** Set the marks style to "none", "points", "dots", or "various".
* In the last case, unique marks are used for the first ten data
* sets, then recycled.
* This method should be called only from the event dispatch thread.
* @param style A string specifying the style for points.
*/
public synchronized void setMarksStyle(String style) {
// Ensure replot of offscreen buffer.
_plotImage = null;
 
if (style.equalsIgnoreCase("none")) {
_marks = 0;
} else if (style.equalsIgnoreCase("points")) {
_marks = 1;
} else if (style.equalsIgnoreCase("dots")) {
_marks = 2;
} else if (style.equalsIgnoreCase("various")) {
_marks = 3;
} else if (style.equalsIgnoreCase("pixels")) {
_marks = 4;
}
}
 
/** Set the marks style to "none", "points", "dots", "various",
* or "pixels" for the specified dataset.
* In the last case, unique marks are used for the first ten data
* sets, then recycled.
* @param style A string specifying the style for points.
* @param dataset The dataset to which this should apply.
*/
public synchronized void setMarksStyle(String style, int dataset) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_checkDatasetIndex(dataset);
 
Format fmt = (Format) _formats.elementAt(dataset);
 
if (style.equalsIgnoreCase("none")) {
fmt.marks = 0;
} else if (style.equalsIgnoreCase("points")) {
fmt.marks = 1;
} else if (style.equalsIgnoreCase("dots")) {
fmt.marks = 2;
} else if (style.equalsIgnoreCase("various")) {
fmt.marks = 3;
} else if (style.equalsIgnoreCase("pixels")) {
fmt.marks = 4;
}
 
fmt.marksUseDefault = false;
}
 
/** Specify the number of data sets to be plotted together.
* This method is deprecated, since it is no longer necessary to
* specify the number of data sets ahead of time.
* @param numSets The number of data sets.
* @deprecated
*/
public void setNumSets(int numSets) {
// Ensure replot of offscreen buffer.
_plotImage = null;
 
if (numSets < 1) {
throw new IllegalArgumentException("Number of data sets ("
+ numSets + ") must be greater than 0.");
}
 
_currentdataset = -1;
_points.removeAllElements();
_formats.removeAllElements();
_prevx.removeAllElements();
_prevy.removeAllElements();
 
for (int i = 0; i < numSets; i++) {
_points.addElement(new Vector());
_formats.addElement(new Format());
_prevx.addElement(_initialPreviousValue);
_prevy.addElement(_initialPreviousValue);
}
}
 
/** Calling this method with a positive argument sets the
* persistence of the plot to the given number of points. Calling
* with a zero argument turns off this feature, reverting to
* infinite memory (unless sweeps persistence is set). If both
* sweeps and points persistence are set then sweeps take
* precedence.
* <p>
* Setting the persistence greater than zero forces the plot to
* be drawn in XOR mode, which allows points to be quickly and
* efficiently erased. However, there is a bug in Java (as of
* version 1.3), where XOR mode does not work correctly with
* double buffering. Thus, if you call this with an argument
* greater than zero, then we turn off double buffering for this
* panel <i>and all of its parents</i>. This actually happens
* on the next call to addPoint().
*/
public void setPointsPersistence(int persistence) {
// Ensure replot of offscreen buffer.
_plotImage = null;
 
// NOTE: No file format. It's not clear it makes sense to have one.
_pointsPersistence = persistence;
}
 
/** If the argument is true, then datasets with the same name
* are merged into a single dataset.
* @param on If true, then merge datasets.
* @see #getReuseDatasets()
*/
public void setReuseDatasets(boolean on) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_reuseDatasets = on;
}
 
/** Calling this method with a positive argument sets the
* persistence of the plot to the given width in units of the
* horizontal axis. Calling
* with a zero argument turns off this feature, reverting to
* infinite memory (unless points persistence is set). If both
* X and points persistence are set then both are applied,
* meaning that points that are old by either criterion will
* be erased.
* <p>
* Setting the X persistence greater than zero forces the plot to
* be drawn in XOR mode, which allows points to be quickly and
* efficiently erased. However, there is a bug in Java (as of
* version 1.3), where XOR mode does not work correctly with
* double buffering. Thus, if you call this with an argument
* greater than zero, then we turn off double buffering for this
* panel <i>and all of its parents</i>. This actually happens
* on the next call to addPoint().
*/
public void setXPersistence(double persistence) {
// Ensure replot of offscreen buffer.
_plotImage = null;
 
// NOTE: No file format. It's not clear it makes sense to have one.
_xPersistence = persistence;
}
 
/** Write plot data information to the specified output stream in PlotML.
* @param output A buffered print writer.
*/
public synchronized void writeData(PrintWriter output) {
super.writeData(output);
 
for (int dataset = 0; dataset < _points.size(); dataset++) {
StringBuffer options = new StringBuffer();
 
Format fmt = (Format) _formats.elementAt(dataset);
 
if (!fmt.connectedUseDefault) {
if (_isConnected(dataset)) {
options.append(" connected=\"yes\"");
} else {
options.append(" connected=\"no\"");
}
}
 
if (!fmt.impulsesUseDefault) {
if (fmt.impulses) {
options.append(" stems=\"yes\"");
} else {
output.println(" stems=\"no\"");
}
}
 
if (!fmt.marksUseDefault) {
switch (fmt.marks) {
case 0:
options.append(" marks=\"none\"");
break;
 
case 1:
options.append(" marks=\"points\"");
break;
 
case 2:
options.append(" marks=\"dots\"");
break;
 
case 3:
options.append(" marks=\"various\"");
break;
 
case 4:
options.append(" marks=\"pixels\"");
break;
}
}
 
String legend = getLegend(dataset);
 
if (legend != null) {
options.append(" name=\"" + getLegend(dataset) + "\"");
}
 
output.println("<dataset" + options.toString() + ">");
 
// Write the data
Vector pts = (Vector) _points.elementAt(dataset);
 
for (int pointnum = 0; pointnum < pts.size(); pointnum++) {
PlotPoint pt = (PlotPoint) pts.elementAt(pointnum);
 
if (!pt.connected) {
output.print("<m ");
} else {
output.print("<p ");
}
 
output.print("x=\"" + pt.x + "\" y=\"" + pt.y + "\"");
 
if (pt.errorBar) {
output.print(" lowErrorBar=\"" + pt.yLowEB
+ "\" highErrorBar=\"" + pt.yHighEB + "\"");
}
 
output.println("/>");
}
 
output.println("</dataset>");
}
}
 
/** Write plot format information to the specified output stream in
* PlotML, an XML scheme.
* @param output A buffered print writer.
*/
public synchronized void writeFormat(PrintWriter output) {
super.writeFormat(output);
 
if (_reuseDatasets) {
output.println("<reuseDatasets/>");
}
 
StringBuffer defaults = new StringBuffer();
 
if (!_connected) {
defaults.append(" connected=\"no\"");
}
 
switch (_marks) {
case 1:
defaults.append(" marks=\"points\"");
break;
 
case 2:
defaults.append(" marks=\"dots\"");
break;
 
case 3:
defaults.append(" marks=\"various\"");
break;
 
case 4:
defaults.append(" marks=\"pixels\"");
break;
}
 
// Write the defaults for formats that can be controlled by dataset
if (_impulses) {
defaults.append(" stems=\"yes\"");
}
 
if (defaults.length() > 0) {
output.println("<default" + defaults.toString() + "/>");
}
 
if (_bars) {
output.println("<barGraph width=\"" + barWidth + "\" offset=\""
+ _barOffset + "\"/>");
}
}
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
 
/** Check the argument to ensure that it is a valid data set index.
* If it is less than zero, throw an IllegalArgumentException (which
* is a runtime exception). If it does not refer to an existing
* data set, then fill out the _points Vector so that it does refer
* to an existing data set. All other dataset-related vectors are
* similarly filled out.
* @param dataset The data set index.
*/
protected synchronized void _checkDatasetIndex(int dataset) {
if (dataset < 0) {
throw new IllegalArgumentException(
"Plot._checkDatasetIndex: Cannot"
+ " give a negative number for the data set index.");
}
 
while (dataset >= _points.size()) {
_points.addElement(new Vector());
_formats.addElement(new Format());
_prevx.addElement(_initialPreviousValue);
_prevy.addElement(_initialPreviousValue);
}
}
 
/** Draw bar from the specified point to the y axis.
* If the specified point is below the y axis or outside the
* x range, do nothing. If the <i>clip</i> argument is true,
* then do not draw above the y range.
* Note that paintComponent() should be called before
* calling this method so that _xscale and _yscale are properly set.
* This method should be called only from the event dispatch thread.
* It is not synchronized, so its caller should be.
* @param graphics The graphics context.
* @param dataset The index of the dataset.
* @param xpos The x position.
* @param ypos The y position.
* @param clip If true, then do not draw outside the range.
*/
protected void _drawBar(Graphics graphics, int dataset, long xpos,
long ypos, boolean clip) {
if (clip) {
if (ypos < _uly) {
ypos = _uly;
}
 
if (ypos > _lry) {
ypos = _lry;
}
}
 
if ((ypos <= _lry) && (xpos <= _lrx) && (xpos >= _ulx)) {
// left x position of bar.
int barlx = (int) (xpos - ((barWidth * _xscale) / 2) + (dataset
* _barOffset * _xscale));
 
// right x position of bar
int barrx = (int) (barlx + (barWidth * _xscale));
 
if (barlx < _ulx) {
barlx = _ulx;
}
 
if (barrx > _lrx) {
barrx = _lrx;
}
 
// Make sure that a bar is always at least one pixel wide.
if (barlx >= barrx) {
barrx = barlx + 1;
}
 
// The y position of the zero line.
long zeroypos = _lry - (long) ((0 - _yMin) * _yscale);
 
if (_lry < zeroypos) {
zeroypos = _lry;
}
 
if (_uly > zeroypos) {
zeroypos = _uly;
}
 
if ((_yMin >= 0) || (ypos <= zeroypos)) {
graphics.fillRect(barlx, (int) ypos, barrx - barlx,
(int) (zeroypos - ypos));
} else {
graphics.fillRect(barlx, (int) zeroypos, barrx - barlx,
(int) (ypos - zeroypos));
}
}
}
 
/** Draw an error bar for the specified yLowEB and yHighEB values.
* If the specified point is below the y axis or outside the
* x range, do nothing. If the <i>clip</i> argument is true,
* then do not draw above the y range.
* This method should be called only from the event dispatch thread.
* It is not synchronized, so its caller should be.
* @param graphics The graphics context.
* @param dataset The index of the dataset.
* @param xpos The x position.
* @param yLowEBPos The lower y position of the error bar.
* @param yHighEBPos The upper y position of the error bar.
* @param clip If true, then do not draw above the range.
*/
protected void _drawErrorBar(Graphics graphics, int dataset, long xpos,
long yLowEBPos, long yHighEBPos, boolean clip) {
_drawLine(graphics, dataset, xpos - _ERRORBAR_LEG_LENGTH, yHighEBPos,
xpos + _ERRORBAR_LEG_LENGTH, yHighEBPos, clip);
_drawLine(graphics, dataset, xpos, yLowEBPos, xpos, yHighEBPos, clip);
_drawLine(graphics, dataset, xpos - _ERRORBAR_LEG_LENGTH, yLowEBPos,
xpos + _ERRORBAR_LEG_LENGTH, yLowEBPos, clip);
}
 
/** Draw a line from the specified point to the y axis.
* If the specified point is below the y axis or outside the
* x range, do nothing. If the <i>clip</i> argument is true,
* then do not draw above the y range.
* This method should be called only from the event dispatch thread.
* It is not synchronized, so its caller should be.
* @param graphics The graphics context.
* @param xpos The x position.
* @param ypos The y position.
* @param clip If true, then do not draw outside the range.
*/
protected void _drawImpulse(Graphics graphics, long xpos, long ypos,
boolean clip) {
if (clip) {
if (ypos < _uly) {
ypos = _uly;
}
 
if (ypos > _lry) {
ypos = _lry;
}
}
 
if ((ypos <= _lry) && (xpos <= _lrx) && (xpos >= _ulx)) {
// The y position of the zero line.
double zeroypos = _lry - (long) ((0 - _yMin) * _yscale);
 
if (_lry < zeroypos) {
zeroypos = _lry;
}
 
if (_uly > zeroypos) {
zeroypos = _uly;
}
 
_setWidth(graphics, 1f);
graphics.drawLine((int) xpos, (int) ypos, (int) xpos,
(int) zeroypos);
}
}
 
/** Draw a line from the specified starting point to the specified
* ending point. The current color is used. If the <i>clip</i> argument
* is true, then draw only that portion of the line that lies within the
* plotting rectangle. This method draws a line one pixel wide.
* This method should be called only from the event dispatch thread.
* It is not synchronized, so its caller should be.
* @param graphics The graphics context.
* @param dataset The index of the dataset.
* @param startx The starting x position.
* @param starty The starting y position.
* @param endx The ending x position.
* @param endy The ending y position.
* @param clip If true, then do not draw outside the range.
*/
protected void _drawLine(Graphics graphics, int dataset, long startx,
long starty, long endx, long endy, boolean clip) {
_drawLine(graphics, dataset, startx, starty, endx, endy, clip, 1f);
}
 
/** Draw a line from the specified starting point to the specified
* ending point. The current color is used. If the <i>clip</i> argument
* is true, then draw only that portion of the line that lies within the
* plotting rectangle. The width argument is ignored if the graphics
* argument is not an instance of Graphics2D.
* This method should be called only from the event dispatch thread.
* It is not synchronized, so its caller should be.
* @param graphics The graphics context.
* @param dataset The index of the dataset.
* @param startx The starting x position.
* @param starty The starting y position.
* @param endx The ending x position.
* @param endy The ending y position.
* @param clip If true, then do not draw outside the range.
* @param width The thickness of the line.
*/
protected void _drawLine(Graphics graphics, int dataset, long startx,
long starty, long endx, long endy, boolean clip, float width) {
_setWidth(graphics, width);
 
if (clip) {
// Rule out impossible cases.
if (!(((endx <= _ulx) && (startx <= _ulx))
|| ((endx >= _lrx) && (startx >= _lrx))
|| ((endy <= _uly) && (starty <= _uly)) || ((endy >= _lry) && (starty >= _lry)))) {
// If the end point is out of x range, adjust
// end point to boundary.
// The integer arithmetic has to be done with longs so as
// to not loose precision on extremely close zooms.
if (startx != endx) {
if (endx < _ulx) {
endy = (int) (endy + (((starty - endy) * (_ulx - endx)) / (startx - endx)));
endx = _ulx;
} else if (endx > _lrx) {
endy = (int) (endy + (((starty - endy) * (_lrx - endx)) / (startx - endx)));
endx = _lrx;
}
}
 
// If end point is out of y range, adjust to boundary.
// Note that y increases downward
if (starty != endy) {
if (endy < _uly) {
endx = (int) (endx + (((startx - endx) * (_uly - endy)) / (starty - endy)));
endy = _uly;
} else if (endy > _lry) {
endx = (int) (endx + (((startx - endx) * (_lry - endy)) / (starty - endy)));
endy = _lry;
}
}
 
// Adjust current point to lie on the boundary.
if (startx != endx) {
if (startx < _ulx) {
starty = (int) (starty + (((endy - starty) * (_ulx - startx)) / (endx - startx)));
startx = _ulx;
} else if (startx > _lrx) {
starty = (int) (starty + (((endy - starty) * (_lrx - startx)) / (endx - startx)));
startx = _lrx;
}
}
 
if (starty != endy) {
if (starty < _uly) {
startx = (int) (startx + (((endx - startx) * (_uly - starty)) / (endy - starty)));
starty = _uly;
} else if (starty > _lry) {
startx = (int) (startx + (((endx - startx) * (_lry - starty)) / (endy - starty)));
starty = _lry;
}
}
}
 
// Are the new points in range?
if ((endx >= _ulx) && (endx <= _lrx) && (endy >= _uly)
&& (endy <= _lry) && (startx >= _ulx) && (startx <= _lrx)
&& (starty >= _uly) && (starty <= _lry)) {
graphics.drawLine((int) startx, (int) starty, (int) endx,
(int) endy);
}
} else {
// draw unconditionally.
graphics.drawLine((int) startx, (int) starty, (int) endx,
(int) endy);
}
}
 
/** Draw the axes and then plot all points. If the second
* argument is true, clear the display first.
* This method is called by paintComponent().
* To cause it to be called you would normally call repaint(),
* which eventually causes paintComponent() to be called.
* <p>
* Note that this is synchronized so that points are not added
* by other threads while the drawing is occurring. This method
* should be called only from the event dispatch thread, consistent
* with swing policy.
* @param graphics The graphics context.
* @param clearfirst If true, clear the plot before proceeding.
* @param drawRectangle The Rectangle to draw in.
*/
protected synchronized void _drawPlot(Graphics graphics,
boolean clearfirst, Rectangle drawRectangle) {
if (_graphics == null) {
_graphics = graphics;
} else if (graphics != _graphics) {
// If the graphics has changed, then we don't care about
// the previous values. Exporting to EPS uses a different
// graphics, see test/onePointStem.plt for an example that
// requires this change.
_graphics = graphics;
_prevx = new Vector();
_prevy = new Vector();
for (int dataset = 0; dataset < _points.size(); dataset++) {
_prevx.addElement(_initialPreviousValue);
_prevy.addElement(_initialPreviousValue);
}
}
 
// We must call PlotBox._drawPlot() before calling _drawPlotPoint
// so that _xscale and _yscale are set.
super._drawPlot(graphics, clearfirst, drawRectangle);
 
// Plot the points in reverse order so that the first colors
// appear on top.
for (int dataset = _points.size() - 1; dataset >= 0; dataset--) {
Vector data = (Vector) _points.elementAt(dataset);
 
for (int pointnum = 0; pointnum < data.size(); pointnum++) {
_drawPlotPoint(graphics, dataset, pointnum);
}
}
 
_showing = true;
}
 
/** Put a mark corresponding to the specified dataset at the
* specified x and y position. The mark is drawn in the current
* color. What kind of mark is drawn depends on the _marks
* variable and the dataset argument. If the fourth argument is
* true, then check the range and plot only points that
* are in range.
* This method should be called only from the event dispatch thread.
* It is not synchronized, so its caller should be.
* @param graphics The graphics context.
* @param dataset The index of the dataset.
* @param xpos The x position.
* @param ypos The y position.
* @param clip If true, then do not draw outside the range.
*/
protected void _drawPoint(Graphics graphics, int dataset, long xpos,
long ypos, boolean clip) {
// If the point is not out of range, draw it.
boolean pointinside = (ypos <= _lry) && (ypos >= _uly)
&& (xpos <= _lrx) && (xpos >= _ulx);
 
if (!clip || pointinside) {
int xposi = (int) xpos;
int yposi = (int) ypos;
 
// Check to see whether the dataset has a marks directive
Format fmt = (Format) _formats.elementAt(dataset);
int marks = _marks;
 
if (!fmt.marksUseDefault) {
marks = fmt.marks;
}
 
// If the point is out of range, and being drawn, then it is
// probably a legend point. When printing in black and white,
// we want to use a line rather than a point for the legend.
// (So that line patterns are visible). The only exception is
// when the marks style uses distinct marks, or if there is
// no line being drawn.
// NOTE: It is unfortunate to have to test the class of graphics,
// but there is no easy way around this that I can think of.
if (!pointinside && (marks != 3) && _isConnected(dataset)
&& (graphics instanceof EPSGraphics)) {
graphics.drawLine(xposi - 6, yposi, xposi + 6, yposi);
} else {
// Color display. Use normal legend.
switch (marks) {
case 0:
 
// If no mark style is given, draw a filled rectangle.
// This is used, for example, to draw the legend.
graphics.fillRect(xposi - 6, yposi - 6, 6, 6);
break;
 
case 1:
 
// points -- use 3-pixel ovals.
graphics.fillOval(xposi - 1, yposi - 1, 3, 3);
break;
 
case 2:
 
// dots
graphics.fillOval(xposi - _radius, yposi - _radius,
_diameter, _diameter);
break;
 
case 3:
 
// various
int[] xpoints;
 
// various
int[] ypoints;
 
// Points are only distinguished up to _MAX_MARKS data sets.
int mark = dataset % _MAX_MARKS;
 
switch (mark) {
case 0:
 
// filled circle
graphics.fillOval(xposi - _radius, yposi - _radius,
_diameter, _diameter);
break;
 
case 1:
 
// cross
graphics.drawLine(xposi - _radius, yposi - _radius,
xposi + _radius, yposi + _radius);
graphics.drawLine(xposi + _radius, yposi - _radius,
xposi - _radius, yposi + _radius);
break;
 
case 2:
 
// square
graphics.drawRect(xposi - _radius, yposi - _radius,
_diameter, _diameter);
break;
 
case 3:
 
// filled triangle
xpoints = new int[4];
ypoints = new int[4];
xpoints[0] = xposi;
ypoints[0] = yposi - _radius;
xpoints[1] = xposi + _radius;
ypoints[1] = yposi + _radius;
xpoints[2] = xposi - _radius;
ypoints[2] = yposi + _radius;
xpoints[3] = xposi;
ypoints[3] = yposi - _radius;
graphics.fillPolygon(xpoints, ypoints, 4);
break;
 
case 4:
 
// diamond
xpoints = new int[5];
ypoints = new int[5];
xpoints[0] = xposi;
ypoints[0] = yposi - _radius;
xpoints[1] = xposi + _radius;
ypoints[1] = yposi;
xpoints[2] = xposi;
ypoints[2] = yposi + _radius;
xpoints[3] = xposi - _radius;
ypoints[3] = yposi;
xpoints[4] = xposi;
ypoints[4] = yposi - _radius;
graphics.drawPolygon(xpoints, ypoints, 5);
break;
 
case 5:
 
// circle
graphics.drawOval(xposi - _radius, yposi - _radius,
_diameter, _diameter);
break;
 
case 6:
 
// plus sign
graphics.drawLine(xposi, yposi - _radius, xposi, yposi
+ _radius);
graphics.drawLine(xposi - _radius, yposi, xposi
+ _radius, yposi);
break;
 
case 7:
 
// filled square
graphics.fillRect(xposi - _radius, yposi - _radius,
_diameter, _diameter);
break;
 
case 8:
 
// triangle
xpoints = new int[4];
ypoints = new int[4];
xpoints[0] = xposi;
ypoints[0] = yposi - _radius;
xpoints[1] = xposi + _radius;
ypoints[1] = yposi + _radius;
xpoints[2] = xposi - _radius;
ypoints[2] = yposi + _radius;
xpoints[3] = xposi;
ypoints[3] = yposi - _radius;
graphics.drawPolygon(xpoints, ypoints, 4);
break;
 
case 9:
 
// filled diamond
xpoints = new int[5];
ypoints = new int[5];
xpoints[0] = xposi;
ypoints[0] = yposi - _radius;
xpoints[1] = xposi + _radius;
ypoints[1] = yposi;
xpoints[2] = xposi;
ypoints[2] = yposi + _radius;
xpoints[3] = xposi - _radius;
ypoints[3] = yposi;
xpoints[4] = xposi;
ypoints[4] = yposi - _radius;
graphics.fillPolygon(xpoints, ypoints, 5);
break;
}
 
break;
 
case 4:
 
// If the mark style is pixels, draw a filled rectangle.
graphics.fillRect(xposi, yposi, 1, 1);
break;
 
default:
// none
}
}
}
}
 
/** Parse a line that gives plotting information. Return true if
* the line is recognized. Lines with syntax errors are ignored.
* It is not synchronized, so its caller should be.
* @param line A command line.
* @return True if the line is recognized.
*/
protected boolean _parseLine(String line) {
boolean connected = false;
 
if (_isConnected(_currentdataset)) {
connected = true;
}
 
// parse only if the super class does not recognize the line.
if (super._parseLine(line)) {
return true;
} else {
// We convert the line to lower case so that the command
// names are case insensitive
String lcLine = line.toLowerCase();
 
if (lcLine.startsWith("marks:")) {
// If we have seen a dataset directive, then apply the
// request to the current dataset only.
String style = (line.substring(6)).trim();
 
if (_sawFirstDataSet) {
setMarksStyle(style, _currentdataset);
} else {
setMarksStyle(style);
}
 
return true;
} else if (lcLine.startsWith("numsets:")) {
// Ignore. No longer relevant.
return true;
} else if (lcLine.startsWith("reusedatasets:")) {
if (lcLine.indexOf("off", 16) >= 0) {
setReuseDatasets(false);
} else {
setReuseDatasets(true);
}
 
return true;
} else if (lcLine.startsWith("dataset:")) {
if (_reuseDatasets && (lcLine.length() > 0)) {
String tlegend = (line.substring(8)).trim();
_currentdataset = -1;
 
int i;
 
for (i = 0; i <= _maxDataset; i++) {
if (getLegend(i).compareTo(tlegend) == 0) {
_currentdataset = i;
}
}
 
if (_currentdataset != -1) {
return true;
} else {
_currentdataset = _maxDataset;
}
}
 
// new data set
_firstInSet = true;
_sawFirstDataSet = true;
_currentdataset++;
 
if (lcLine.length() > 0) {
String legend = (line.substring(8)).trim();
 
if ((legend != null) && (legend.length() > 0)) {
addLegend(_currentdataset, legend);
}
}
 
_maxDataset = _currentdataset;
return true;
} else if (lcLine.startsWith("lines:")) {
if (_sawFirstDataSet) {
// Backward compatbility with xgraph here.
// If we see some data sets, then they are drawn
// with lines, if we then see a Lines: off
// the current dataset and succeeding datasets
// will be drawn without lines.
// For each of the existing datasets, if
// it fmt.connectedUseDefault is true, then
// set fmt.connectedUseDefault to false and set
// the value of fmt.connected
Enumeration formats = _formats.elements();
 
while (formats.hasMoreElements()) {
Format format = (Format) formats.nextElement();
 
if (format.connectedUseDefault) {
format.connectedUseDefault = false;
format.connected = _connected;
}
}
}
 
if (lcLine.indexOf("off", 6) >= 0) {
setConnected(false);
} else {
setConnected(true);
}
 
return true;
} else if (lcLine.startsWith("impulses:")) {
// If we have not yet seen a dataset, then this is interpreted
// as the global default. Otherwise, it is assumed to apply
// only to the current dataset.
if (_sawFirstDataSet) {
if (lcLine.indexOf("off", 9) >= 0) {
setImpulses(false, _currentdataset);
} else {
setImpulses(true, _currentdataset);
}
} else {
if (lcLine.indexOf("off", 9) >= 0) {
setImpulses(false);
} else {
setImpulses(true);
}
}
 
return true;
} else if (lcLine.startsWith("bars:")) {
if (lcLine.indexOf("off", 5) >= 0) {
setBars(false);
} else {
setBars(true);
 
int comma = line.indexOf(",", 5);
String barwidth;
String baroffset = null;
 
if (comma > 0) {
barwidth = (line.substring(5, comma)).trim();
baroffset = (line.substring(comma + 1)).trim();
} else {
barwidth = (line.substring(5)).trim();
}
 
try {
// Use Double.parseDouble() and avoid creating a Double
double bwidth = Double.parseDouble(barwidth);
double boffset = _barOffset;
 
if (baroffset != null) {
boffset = Double.parseDouble(baroffset);
}
 
setBars(bwidth, boffset);
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
}
 
return true;
} else if (line.startsWith("move:")) {
// a disconnected point
connected = false;
 
// deal with 'move: 1 2' and 'move:2 2'
line = line.substring(5, line.length()).trim();
} else if (line.startsWith("move")) {
// a disconnected point
connected = false;
 
// deal with 'move 1 2' and 'move2 2'
line = line.substring(4, line.length()).trim();
} else if (line.startsWith("draw:")) {
// a connected point, if connect is enabled.
line = line.substring(5, line.length()).trim();
} else if (line.startsWith("draw")) {
// a connected point, if connect is enabled.
line = line.substring(4, line.length()).trim();
}
 
line = line.trim();
 
// We can't use StreamTokenizer here because it can't
// process numbers like 1E-01.
// This code is somewhat optimized for speed, since
// most data consists of two data points, we want
// to handle that case as efficiently as possible.
int fieldsplit = line.indexOf(",");
 
if (fieldsplit == -1) {
fieldsplit = line.indexOf(" ");
}
 
if (fieldsplit == -1) {
fieldsplit = line.indexOf("\t"); // a tab
}
 
if (fieldsplit > 0) {
String x = (line.substring(0, fieldsplit)).trim();
String y = (line.substring(fieldsplit + 1)).trim();
 
// Any more separators?
int fieldsplit2 = y.indexOf(",");
 
if (fieldsplit2 == -1) {
fieldsplit2 = y.indexOf(" ");
}
 
if (fieldsplit2 == -1) {
fieldsplit2 = y.indexOf("\t"); // a tab
}
 
if (fieldsplit2 > 0) {
line = (y.substring(fieldsplit2 + 1)).trim();
y = (y.substring(0, fieldsplit2)).trim();
}
 
try {
// Use Double.parseDouble() and avoid creating a Double.
double xpt = Double.parseDouble(x);
double ypt = Double.parseDouble(y);
 
if (fieldsplit2 > 0) {
// There was one separator after the y value, now
// look for another separator.
int fieldsplit3 = line.indexOf(",");
 
if (fieldsplit3 == -1) {
fieldsplit3 = line.indexOf(" ");
}
 
//if (fieldsplit3 == -1) {
// fieldsplit2 = line.indexOf("\t"); // a tab
//}
if (fieldsplit3 > 0) {
// We have more numbers, assume that this is
// an error bar
String yl = (line.substring(0, fieldsplit3)).trim();
String yh = (line.substring(fieldsplit3 + 1))
.trim();
double yLowEB = Double.parseDouble(yl);
double yHighEB = Double.parseDouble(yh);
connected = _addLegendIfNecessary(connected);
addPointWithErrorBars(_currentdataset, xpt, ypt,
yLowEB, yHighEB, connected);
return true;
} else {
// It is unlikely that we have a fieldsplit2 >0
// but not fieldsplit3 >0, but just in case:
connected = _addLegendIfNecessary(connected);
addPoint(_currentdataset, xpt, ypt, connected);
return true;
}
} else {
// There were no more fields, so this is
// a regular pt.
connected = _addLegendIfNecessary(connected);
addPoint(_currentdataset, xpt, ypt, connected);
return true;
}
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
}
}
 
return false;
}
 
/** If the graphics argument is an instance of Graphics2D, then set
* the current stroke to the specified width. Otherwise, do nothing.
* @param graphics The graphics object.
* @param width The width.
*/
protected void _setWidth(Graphics graphics, float width) {
// For historical reasons, the API here only assumes Graphics
// objects, not Graphics2D.
if (graphics instanceof Graphics2D) {
// We cache the two most common cases.
if (width == 1f) {
((Graphics2D) graphics).setStroke(_lineStroke1);
} else if (width == 2f) {
((Graphics2D) graphics).setStroke(_lineStroke2);
} else {
((Graphics2D) graphics).setStroke(new BasicStroke(width,
BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
}
}
}
 
/** Write plot information to the specified output stream in
* the "old syntax," which predates PlotML.
* Derived classes should override this method to first call
* the parent class method, then add whatever additional information
* they wish to add to the stream.
* It is not synchronized, so its caller should be.
* @param output A buffered print writer.
* @deprecated
*/
protected void _writeOldSyntax(PrintWriter output) {
super._writeOldSyntax(output);
 
// NOTE: NumSets is obsolete, so we don't write it.
if (_reuseDatasets) {
output.println("ReuseDatasets: on");
}
 
if (!_connected) {
output.println("Lines: off");
}
 
if (_bars) {
output.println("Bars: " + barWidth + ", " + _barOffset);
}
 
// Write the defaults for formats that can be controlled by dataset
if (_impulses) {
output.println("Impulses: on");
}
 
switch (_marks) {
case 1:
output.println("Marks: points");
break;
 
case 2:
output.println("Marks: dots");
break;
 
case 3:
output.println("Marks: various");
break;
 
case 4:
output.println("Marks: pixels");
break;
}
 
for (int dataset = 0; dataset < _points.size(); dataset++) {
// Write the dataset directive
String legend = getLegend(dataset);
 
if (legend != null) {
output.println("DataSet: " + getLegend(dataset));
} else {
output.println("DataSet:");
}
 
// Write dataset-specific format information
Format fmt = (Format) _formats.elementAt(dataset);
 
if (!fmt.impulsesUseDefault) {
if (fmt.impulses) {
output.println("Impulses: on");
} else {
output.println("Impulses: off");
}
}
 
if (!fmt.marksUseDefault) {
switch (fmt.marks) {
case 0:
output.println("Marks: none");
break;
 
case 1:
output.println("Marks: points");
break;
 
case 2:
output.println("Marks: dots");
break;
 
case 3:
output.println("Marks: various");
break;
 
case 4:
output.println("Marks: pixels");
break;
}
}
 
// Write the data
Vector pts = (Vector) _points.elementAt(dataset);
 
for (int pointnum = 0; pointnum < pts.size(); pointnum++) {
PlotPoint pt = (PlotPoint) pts.elementAt(pointnum);
 
if (!pt.connected) {
output.print("move: ");
}
 
if (pt.errorBar) {
output.println(pt.x + ", " + pt.y + ", " + pt.yLowEB + ", "
+ pt.yHighEB);
} else {
output.println(pt.x + ", " + pt.y);
}
}
}
}
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
 
/** @serial The current dataset. */
protected int _currentdataset = -1;
 
/** @serial A vector of datasets. */
protected Vector _points = new Vector();
 
/** @serial An indicator of the marks style. See _parseLine method for
* interpretation.
*/
protected int _marks;
 
///////////////////////////////////////////////////////////////////
//// private methods ////
 
/* Add a legend if necessary, return the value of the connected flag.
*/
private boolean _addLegendIfNecessary(boolean connected) {
if ((!_sawFirstDataSet || (_currentdataset < 0)) && !_reuseDatasets) {
// We did not set a DataSet line, but
// we did get called with -<digit> args and
// we did not see reusedatasets: yes
_sawFirstDataSet = true;
_currentdataset++;
}
 
if (!_sawFirstDataSet && (getLegend(_currentdataset) == null)) {
// We did not see a "DataSet" string yet,
// nor did we call addLegend().
_firstInSet = true;
_sawFirstDataSet = true;
addLegend(_currentdataset, "Set " + _currentdataset);
}
 
if (_firstInSet && !_reuseDatasets) {
connected = false;
_firstInSet = false;
}
 
return connected;
}
 
/* In the specified data set, add the specified x, y point to the
* plot. Data set indices begin with zero. If the dataset
* argument is less than zero, throw an IllegalArgumentException
* (a runtime exception). If it refers to a data set that does
* not exist, create the data set. The fourth argument indicates
* whether the point should be connected by a line to the previous
* point. However, this argument is ignored if setConnected() has
* been called with a false argument. In that case, a point is never
* connected to the previous point. That argument is also ignored
* if the point is the first in the specified dataset.
* The point is drawn on the screen only if is visible.
* Otherwise, it is drawn the next time paintComponent() is called.
*
* This is not synchronized, so the caller should be. Moreover, this
* should only be called in the event dispatch thread. It should only
* be called via deferIfNecessary().
*/
private void _addPoint(int dataset, double x, double y, double yLowEB,
double yHighEB, boolean connected, boolean errorBar) {
// Ensure replot of offscreen buffer.
_plotImage = null;
 
_checkDatasetIndex(dataset);
 
if (_xlog) {
if (x <= 0.0) {
System.err.println("Can't plot non-positive X values "
+ "when the logarithmic X axis value is specified: "
+ x);
return;
}
 
x = Math.log(x) * _LOG10SCALE;
}
 
if (_ylog) {
if (y <= 0.0) {
System.err.println("Can't plot non-positive Y values "
+ "when the logarithmic Y axis value is specified: "
+ y);
return;
}
 
y = Math.log(y) * _LOG10SCALE;
 
if (errorBar) {
if ((yLowEB <= 0.0) || (yHighEB <= 0.0)) {
System.err
.println("Can't plot non-positive Y values "
+ "when the logarithmic Y axis value is specified: "
+ y);
return;
}
 
yLowEB = Math.log(yLowEB) * _LOG10SCALE;
yHighEB = Math.log(yHighEB) * _LOG10SCALE;
}
}
 
Vector pts = (Vector) _points.elementAt(dataset);
 
// If X persistence has been set, then delete any old points.
if (_xPersistence > 0.0) {
int numToDelete = 0;
 
while (numToDelete < pts.size()) {
PlotPoint old = (PlotPoint) (pts.elementAt(numToDelete));
 
if ((x - old.originalx) <= _xPersistence) {
break;
}
 
numToDelete++;
}
 
for (int i = 0; i < numToDelete; i++) {
erasePoint(dataset, 0);
}
}
 
// Get the new size after deletions.
int size = pts.size();
 
PlotPoint pt = new PlotPoint();
 
// Original value of x before wrapping.
pt.originalx = x;
 
// Modify x if wrapping.
if (_wrap) {
double width = _wrapHigh - _wrapLow;
 
if (x < _wrapLow) {
x += (width * Math.floor(1.0 + ((_wrapLow - x) / width)));
} else if (x > _wrapHigh) {
x -= (width * Math.floor(1.0 + ((x - _wrapHigh) / width)));
 
// NOTE: Could quantization errors be a problem here?
if (Math.abs(x - _wrapLow) < 0.00001) {
x = _wrapHigh;
}
}
}
 
// For auto-ranging, keep track of min and max.
if (x < _xBottom) {
_xBottom = x;
}
 
if (x > _xTop) {
_xTop = x;
}
 
if (y < _yBottom) {
_yBottom = y;
}
 
if (y > _yTop) {
_yTop = y;
}
 
pt.x = x;
pt.y = y;
pt.connected = connected && _isConnected(dataset);
 
if (errorBar) {
if (yLowEB < _yBottom) {
_yBottom = yLowEB;
}
 
if (yLowEB > _yTop) {
_yTop = yLowEB;
}
 
if (yHighEB < _yBottom) {
_yBottom = yHighEB;
}
 
if (yHighEB > _yTop) {
_yTop = yHighEB;
}
 
pt.yLowEB = yLowEB;
pt.yHighEB = yHighEB;
pt.errorBar = true;
}
 
// If this is the first point in the dataset, clear the connected bit.
if (size == 0) {
pt.connected = false;
} else if (_wrap) {
// Do not connect points if wrapping...
PlotPoint old = (PlotPoint) (pts.elementAt(size - 1));
 
if (old.x > x) {
pt.connected = false;
}
}
 
pts.addElement(pt);
 
// If points persistence has been set, then delete one old point.
if (_pointsPersistence > 0) {
if (size > _pointsPersistence) {
erasePoint(dataset, 0);
}
}
 
// Draw the point on the screen only if the plot is showing.
Graphics graphics = getGraphics();
 
// Need to check that graphics is not null because plot may have
// been dismissed.
if (_showing && (graphics != null)) {
if (((_pointsPersistence > 0) || (_xPersistence > 0.0))
&& isDoubleBuffered()) {
// NOTE: Double buffering has a bug in Java (in at least
// version 1.3) where there is a one pixel alignment problem
// that prevents XOR drawing from working correctly.
// XOR drawing is used for live plots, and if double buffering
// is turned on, then cruft is left on the screen whenever the
// fill or zoom functions are used.
// Here, if it hasn't been done already, we turn off double
// buffering on this panel and all its parents for which this
// is possible. Note that we could do this globally using
//
// RepaintManager repaintManager
// = RepaintManager.currentManager(this);
// repaintManager.setDoubleBufferingEnabled(false);
//
// However, that turns off double buffering in all windows
// of the application, which means that other windows that only
// work properly with double buffering (such as vergil windows)
// will not work.
//
// NOTE: This fix creates another problem...
// If there are other widgets besides the plotter in the
// same top-level window, and they implement double
// buffering (which they will by default), then they
// need to be opaque or drawing artifacts will appear
// upon exposure events. The workaround is simple:
// Make these other objects opaque, and set their
// background color appropriately.
//
// See:
// <pre>
// http://developer.java.sun.com/developer/bugParade/bugs/
// 4188795.html
// 4204551.html
// 4295712.htm
// </pre>
//
// Since we are assured of being in the event dispatch thread,
// we can simply execute this.
setDoubleBuffered(false);
 
Component parent = getParent();
 
while (parent != null) {
if (parent instanceof JComponent) {
((JComponent) parent).setDoubleBuffered(false);
}
 
parent = parent.getParent();
}
}
 
// Again, we are in the event thread, so this is safe...
_drawPlotPoint(graphics, dataset, pts.size() - 1);
}
 
if (_wrap && (Math.abs(x - _wrapHigh)) < 0.00001) {
// Plot a second point at the low end of the range.
_addPoint(dataset, _wrapLow, y, yLowEB, yHighEB, false, errorBar);
}
}
 
/* Clear the plot of all data points. If the argument is true, then
* reset all parameters to their initial conditions, including
* the persistence, plotting format, and axes formats.
* For the change to take effect, you must call repaint().
*
* This is not synchronized, so the caller should be. Moreover, this
* should only be called in the event dispatch thread. It should only
* be called via deferIfNecessary().
*/
private void _clear(boolean format) {
// Ensure replot of offscreen buffer.
_plotImage = null;
super.clear(format);
_currentdataset = -1;
_points = new Vector();
_prevx = new Vector();
_prevy = new Vector();
_maxDataset = -1;
_firstInSet = true;
_sawFirstDataSet = false;
_xyInvalid = true;
 
if (format) {
_showing = false;
 
// Reset format controls
_formats = new Vector();
_marks = 0;
_pointsPersistence = 0;
_xPersistence = 0;
_bars = false;
barWidth = 0.5;
_barOffset = 0.05;
_connected = true;
_impulses = false;
_reuseDatasets = false;
}
}
 
/** Clear the plot of data points in the specified dataset.
* This calls repaint() to request an update of the display.
*
* This is not synchronized, so the caller should be. Moreover, this
* should only be called in the event dispatch thread. It should only
* be called via deferIfNecessary().
*/
private void _clear(int dataset) {
// Ensure replot of offscreen buffer.
_plotImage = null;
_checkDatasetIndex(dataset);
_xyInvalid = true;
 
Vector points = (Vector) _points.elementAt(dataset);
 
// Vector.clear() is new in JDK1.2, so we use just
// create a new Vector here so that we can compile
// this with JDK1.1 for use in JDK1.1 browsers
points.clear();
 
//_points.setElementAt(new Vector(), dataset);
_points.setElementAt(points, dataset);
repaint();
}
 
/* Draw the specified point and associated lines, if any.
* Note that paintComponent() should be called before
* calling this method so that it calls _drawPlot(), which sets
* _xscale and _yscale. Note that this does not check the dataset
* index. It is up to the caller to do that.
*
* Note that this method is not synchronized, so the caller should be.
* Moreover this method should always be called from the event thread
* when being used to write to the screen.
*/
private void _drawPlotPoint(Graphics graphics, int dataset, int index) {
if ((_pointsPersistence > 0) || (_xPersistence > 0.0)) {
// To allow erasing to work by just redrawing the points.
if (_background == null) {
// java.awt.Component.setBackground(color) says that
// if the color "parameter is null then this component
// will inherit the background color of its parent."
graphics.setXORMode(getBackground());
} else {
graphics.setXORMode(_background);
}
}
 
// Set the color
if (_usecolor) {
int color = dataset % _colors.length;
graphics.setColor(_colors[color]);
} else {
graphics.setColor(_foreground);
}
 
Vector pts = (Vector) _points.elementAt(dataset);
PlotPoint pt = (PlotPoint) pts.elementAt(index);
 
// Use long here because these numbers can be quite large
// (when we are zoomed out a lot).
long ypos = _lry - (long) ((pt.y - _yMin) * _yscale);
long xpos = _ulx + (long) ((pt.x - _xMin) * _xscale);
 
// Draw the line to the previous point.
long prevx = ((Long) _prevx.elementAt(dataset)).longValue();
long prevy = ((Long) _prevy.elementAt(dataset)).longValue();
 
// Avoid drawing points and lines that are invisible.
// Note that if the size of the dataset is 1, then we have only
// one point, so we should be sure to draw it.
if ((xpos != prevx) || (ypos != prevy) || (pts.size() == 1)) {
// MIN_VALUE is a flag that there has been no previous x or y.
if (pt.connected) {
_drawLine(graphics, dataset, xpos, ypos, prevx, prevy, true, 2f);
}
 
// Save the current point as the "previous" point for future
// line drawing.
_prevx.setElementAt(Long.valueOf(xpos), dataset);
_prevy.setElementAt(Long.valueOf(ypos), dataset);
 
// Draw decorations that may be specified on a per-dataset basis
Format fmt = (Format) _formats.elementAt(dataset);
 
if (fmt.impulsesUseDefault) {
if (_impulses) {
_drawImpulse(graphics, xpos, ypos, true);
}
} else {
if (fmt.impulses) {
_drawImpulse(graphics, xpos, ypos, true);
}
}
 
// Check to see whether the dataset has a marks directive
int marks = _marks;
 
if (!fmt.marksUseDefault) {
marks = fmt.marks;
}
 
if (marks != 0) {
_drawPoint(graphics, dataset, xpos, ypos, true);
}
 
if (_bars) {
_drawBar(graphics, dataset, xpos, ypos, true);
}
}
 
if (pt.errorBar) {
_drawErrorBar(graphics, dataset, xpos, _lry
- (long) ((pt.yLowEB - _yMin) * _yscale), _lry
- (long) ((pt.yHighEB - _yMin) * _yscale), true);
}
 
// Restore the color, in case the box gets redrawn.
graphics.setColor(_foreground);
 
if ((_pointsPersistence > 0) || (_xPersistence > 0.0)) {
// Restore paint mode in case axes get redrawn.
graphics.setPaintMode();
}
}
 
/* Erase the point at the given index in the given dataset. If
* lines are being drawn, also erase the line to the next points
* (note: not to the previous point).
*
* This is not synchronized, so the caller should be. Moreover, this
* should only be called in the event dispatch thread. It should only
* be called via deferIfNecessary().
*/
private void _erasePoint(int dataset, int index) {
// Ensure replot of offscreen buffer.
_plotImage = null;
 
_checkDatasetIndex(dataset);
 
// Plot has probably been dismissed. Return.
Graphics graphics = getGraphics();
 
// Need to check that graphics is not null because plot may have
// been dismissed.
if (_showing && (graphics != null)) {
// Set the color
if ((_pointsPersistence > 0) || (_xPersistence > 0.0)) {
// To allow erasing to work by just redrawing the points.
if (_background == null) {
graphics.setXORMode(getBackground());
} else {
graphics.setXORMode(_background);
}
}
 
if (_usecolor) {
int color = dataset % _colors.length;
graphics.setColor(_colors[color]);
} else {
graphics.setColor(_foreground);
}
 
Vector pts = (Vector) _points.elementAt(dataset);
PlotPoint pt = (PlotPoint) pts.elementAt(index);
long ypos = _lry - (long) ((pt.y - _yMin) * _yscale);
long xpos = _ulx + (long) ((pt.x - _xMin) * _xscale);
 
// Erase line to the next point, if appropriate.
if (index < (pts.size() - 1)) {
PlotPoint nextp = (PlotPoint) pts.elementAt(index + 1);
int nextx = _ulx + (int) ((nextp.x - _xMin) * _xscale);
int nexty = _lry - (int) ((nextp.y - _yMin) * _yscale);
 
// NOTE: I have no idea why I have to give this point backwards.
if (nextp.connected) {
_drawLine(graphics, dataset, nextx, nexty, xpos, ypos,
true, 2f);
}
 
nextp.connected = false;
}
 
// Draw decorations that may be specified on a per-dataset basis
Format fmt = (Format) _formats.elementAt(dataset);
 
if (fmt.impulsesUseDefault) {
if (_impulses) {
_drawImpulse(graphics, xpos, ypos, true);
}
} else {
if (fmt.impulses) {
_drawImpulse(graphics, xpos, ypos, true);
}
}
 
// Check to see whether the dataset has a marks directive
int marks = _marks;
 
if (!fmt.marksUseDefault) {
marks = fmt.marks;
}
 
if (marks != 0) {
_drawPoint(graphics, dataset, xpos, ypos, true);
}
 
if (_bars) {
_drawBar(graphics, dataset, xpos, ypos, true);
}
 
if (pt.errorBar) {
_drawErrorBar(graphics, dataset, xpos, _lry
- (long) ((pt.yLowEB - _yMin) * _yscale), _lry
- (long) ((pt.yHighEB - _yMin) * _yscale), true);
}
 
// Restore the color, in case the box gets redrawn.
graphics.setColor(_foreground);
 
if ((_pointsPersistence > 0) || (_xPersistence > 0.0)) {
// Restore paint mode in case axes get redrawn.
graphics.setPaintMode();
}
}
 
// The following is executed whether the plot is showing or not.
// Remove the point from the model.
Vector points = (Vector) _points.elementAt(dataset);
 
if (points != null) {
// If this point is at the maximum or minimum x or y boundary,
// then flag that boundary needs to be recalculated next time
// fillPlot() is called.
PlotPoint pt = (PlotPoint) points.elementAt(index);
 
if (pt != null) {
if ((pt.x == _xBottom) || (pt.x == _xTop) || (pt.y == _yBottom)
|| (pt.y == _yTop)) {
_xyInvalid = true;
}
 
points.removeElementAt(index);
}
}
}
 
/* Rescale so that the data that is currently plotted just fits.
* This overrides the base class method to ensure that the protected
* variables _xBottom, _xTop, _yBottom, and _yTop are valid.
* This method calls repaint(), which causes the display
* to be updated.
*
* This is not synchronized, so the caller should be. Moreover, this
* should only be called in the event dispatch thread. It should only
* be called via deferIfNecessary().
*/
private void _fillPlot() {
if (_xyInvalid) {
// Recalculate the boundaries based on currently visible data
_xBottom = Double.MAX_VALUE;
_xTop = -Double.MAX_VALUE;
_yBottom = Double.MAX_VALUE;
_yTop = -Double.MAX_VALUE;
 
for (int dataset = 0; dataset < _points.size(); dataset++) {
Vector points = (Vector) _points.elementAt(dataset);
 
for (int index = 0; index < points.size(); index++) {
PlotPoint pt = (PlotPoint) points.elementAt(index);
 
if (pt.x < _xBottom) {
_xBottom = pt.x;
}
 
if (pt.x > _xTop) {
_xTop = pt.x;
}
 
if (pt.y < _yBottom) {
_yBottom = pt.y;
}
 
if (pt.y > _yTop) {
_yTop = pt.y;
}
}
}
}
 
_xyInvalid = false;
 
// If this is a bar graph, then make sure the Y range includes 0
if (_bars) {
if (_yBottom > 0.0) {
_yBottom = 0.0;
}
 
if (_yTop < 0.0) {
_yTop = 0.0;
}
}
 
super.fillPlot();
}
 
// Return true if the specified dataset is connected by default.
private boolean _isConnected(int dataset) {
if (dataset < 0) {
return _connected;
}
 
_checkDatasetIndex(dataset);
 
Format fmt = (Format) _formats.elementAt(dataset);
 
if (fmt.connectedUseDefault) {
return _connected;
} else {
return fmt.connected;
}
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
 
/** @serial Number of points to persist for. */
private int _pointsPersistence = 0;
 
/** @serial Persistence in units of the horizontal axis. */
private double _xPersistence = 0.0;
 
/** @serial True if this is a bar plot. */
private boolean _bars = false;
 
/** @serial Width of a bar in x axis units. */
private double barWidth = 0.5;
 
/** @serial Offset per dataset in x axis units. */
private double _barOffset = 0.05;
 
/** @serial True if the points are connected. */
private boolean _connected = true;
 
/** @serial True if this is an impulse plot. */
private boolean _impulses = false;
 
/** @serial The highest data set used. */
private int _maxDataset = -1;
 
/** @serial True if we saw 'reusedatasets: on' in the file. */
private boolean _reuseDatasets = false;
 
/** @serial Is this the first datapoint in a set? */
private boolean _firstInSet = true;
 
/** @serial Have we seen a DataSet line in the current data file? */
private boolean _sawFirstDataSet = false;
 
/** @serial Give the radius of a point for efficiency. */
private int _radius = 3;
 
/** @serial Give the diameter of a point for efficiency. */
private int _diameter = 6;
 
/** @serial Information about the previously plotted point. */
private Vector _prevx = new Vector();
 
/** @serial Information about the previously plotted point. */
private Vector _prevy = new Vector();
 
// Half of the length of the error bar horizontal leg length;
private static final int _ERRORBAR_LEG_LENGTH = 5;
 
// Maximum number of different marks
// NOTE: There are 11 colors in the base class. Combined with 10
// marks, that makes 110 unique signal identities.
private static final int _MAX_MARKS = 10;
 
// A stroke of width 1.
private static final BasicStroke _lineStroke1 = new BasicStroke(1f,
BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
 
// A stroke of width 2.
private static final BasicStroke _lineStroke2 = new BasicStroke(2f,
BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
 
// The stroke to use for thin lines in the plot.
//private static final BasicStroke _thinStroke = new BasicStroke(
// 1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
 
/** @serial Flag indicating validity of _xBottom, _xTop,
* _yBottom, and _yTop.
*/
private boolean _xyInvalid = true;
 
/** @serial Set by _drawPlot(), and reset by clear(). */
private boolean _showing = false;
 
/** @serial Format information on a per data set basis. */
private Vector _formats = new Vector();
 
/** Initial value for elements in _prevx and _prevy that indicate
* we have not yet seen data.
*/
private static final Long _initialPreviousValue = Long.valueOf(0x0L);
 
/** Cached copy of graphics, needed to reset when we are exporting
* to EPS.
*/
private Graphics _graphics = null;
 
///////////////////////////////////////////////////////////////////
//// inner classes ////
private static class Format implements Serializable {
// FindBugs suggests making this class static so as to decrease
// the size of instances and avoid dangling references.
 
// Indicate whether the current dataset is connected.
public boolean connected;
 
// Indicate whether the above variable should be ignored.
public boolean connectedUseDefault = true;
 
// Indicate whether a stem plot should be drawn for this data set.
// This is ignored unless the following variable is set to false.
public boolean impulses;
 
// Indicate whether the above variable should be ignored.
public boolean impulsesUseDefault = true;
 
// Indicate what type of mark to use.
// This is ignored unless the following variable is set to false.
public int marks;
 
// Indicate whether the above variable should be ignored.
public boolean marksUseDefault = true;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/CmdLineArgException.java
0,0 → 1,51
/* Thrown when an incorrect argument is passed to the plotter.
 
@Copyright (c) 1997-2005 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
//////////////////////////////////////////////////////////////////////////
//// CmdLineArgException
 
/**
Exception thrown by plot classes if there are format
problems with the data to be plotted.
 
@author Christopher Brooks
@version $Id: CmdLineArgException.java,v 1.34 2005/07/28 18:49:20 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class CmdLineArgException extends Exception {
public CmdLineArgException() {
super();
}
 
public CmdLineArgException(String s) {
super(s);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotApplet.java
0,0 → 1,481
/* Appletable Plotter
 
@Author: Edward A. Lee and Christopher Hylands
 
@Version: $Id: PlotApplet.java,v 1.76 2005/07/30 05:30:56 cxh Exp $
 
@Copyright (c) 1997-2005 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.net.*;
 
//import java.awt.BorderLayout;
//import java.awt.Color;
//import java.io.FileNotFoundException;
//import java.io.IOException;
//import java.io.InputStream;
//import java.net.MalformedURLException;
//import java.net.URL;
import javax.swing.JApplet;
import javax.swing.SwingUtilities;
 
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import java.lang.Math;
 
 
import org.javia.arity.*;
 
//////////////////////////////////////////////////////////////////////////
//// PlotApplet
 
/**
An Applet that can plot data from a URL.
The URL should be specified using the dataurl applet parameter.
The formatting commands are included in the file with the
the data.
If no URL is given, then a sample plot is generated.
 
@author Edward A. Lee, Christopher Hylands, Contributor: Roger Robins
@version $Id: PlotApplet.java,v 1.76 2005/07/30 05:30:56 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
@see PlotBox
@see Plot
*/
public class PlotApplet extends JApplet {
// /** Construct a Plot applet */
// public PlotApplet() {
// FIXME: having the mutex causes applets to hang.
// The mutex was introduced to Work around problem in Java
// 1.3.1_08 where if we create 6 instances of a Plot applet then
// navigate forward then back - IE and Navigator hang.
// However, since we are now operating inside the Swing Event
// thread, I think this code is unnecessary.
// if (_mutex == null) {
// _mutex = new Object();
// }
// }
public static boolean normalexponent=false;
public String ReadApplet(){
String reply="";
reply=plot().ReadPlotApplet();
return reply;
}
 
/** Return a string describing this applet.
* @return A string describing the applet.
*/
public String getAppletInfo() {
return "PlotApplet " + PlotBox.PTPLOT_RELEASE + ": A data plotter.\n"
+ "By: Edward A. Lee and\n " + "Christopher Hylands\n"
+ "($Id: PlotApplet.java,v 1.76 2005/07/30 05:30:56 cxh Exp $)";
}
 
/** Return information about parameters.
* @return A array of arrays giving parameter names, the type,
* and the default value or description.
*/
public String[][] getParameterInfo() {
String[][] pinfo = {
{ "data", "String", "My_Data_String as String" },
{ "function", "String", "function1,function2,function3,function4 ..." },
{ "file", "String", "http://localhost/wims/wims.cgi?session=$session&cmd=getfile&special_parm=My_Data_String_File" },
{ "dataurl", "url", "the URL of the data to plot" },
{ "plotsteps", "integer", "only for data input via function param" },
{ "background", "hexcolor value", "background color" },
{ "foreground", "hexcolor value", "foreground color" },
{ "height", "integer", "100" },
{ "width", "integer", "100" },
{ "smooth", "integer", "0 or 1 : use with care. default=0" },
{ "names", "String", "names function1,name function2 ... or left blank " },
{ "xmin", "integer", "minimum x-value or left blank for auto detection" },
{ "xmax", "integer", "maximum x-value or left blank for auto detection" },
{ "ymin", "integer", "minimum y-value or left blank for auto detection" },
{ "ymax", "integer", "maximum y-value or left blank for auto detection" },
{ "xlog", "integer", "x-axis is log-scale: 0 or 1: default 0" },
{ "ylog", "integer", "y-axis is log-scale: 0 or 1: default 0" },
{ "color", "integer", " 0 or 1 :default 1" },
{ "xtics", "String", " zero 0, one 1, two 2, pi 3.1428, four 4, five 5 " },
{ "ytics", "String", " thing1 0, thing2 1, thing3 2, three 3, four 4, five 5 " },
{ "xlabel", "String", "label of the x-axis: default x-axis" },
{ "ylabel", "String", "label of the y-axis: default y-axis" },
{ "title", "String", "title of the plot" },
};
return pinfo;
}
 
/** Initialize the applet. Read the applet parameters.
 
* Subclasses that extend this method and call Swing UI methods
* should do so in the Swing Event thread by calling
* SwingUtilities.invokeAndWait().
* Note that some Plot methods will automatically run in the
* Swing Event thread, some will not.
* For details about SwingUtilities.invokeAndWait(), see
* <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/applet.html#thread">The Sun Applet Tutorial</a>
*/
 
// jm.evers
public static byte [] loadURL(URL url) throws IOException {
// jm.evers :handy functions !!! not mine :(
int bufSize = 1024 * 2;
byte [] buf = new byte[bufSize];
ByteArrayOutputStream bout = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(url.openStream());
int n;
while ((n = in.read(buf)) > 0) {
bout.write(buf, 0, n);
}
try
{ in.close(); } catch (Exception ignored) { }
return bout.toByteArray();
}
 
public static String loadFile(String fname) throws IOException {
// jm.evers :handy functions !!! not mine :(
byte[] bytes = loadURL(new URL("file:" + fname));
return new String(bytes);
}
public static String load(String fileOrURL) throws IOException {
// jm.evers :handy functions !!! not mine :(
try {
URL url = new URL(fileOrURL);
return new String(loadURL(url));
}
catch (Exception e) {return loadFile(fileOrURL);}
}
 
public synchronized void read_from_param(String data){
StringTokenizer f = new StringTokenizer(data, ";");
int max=f.countTokens();String line="";
for(int s=0;s<max;s++){
line=f.nextToken();
plot().read(line);
}
showStatus("Done");
repaint();
}
public synchronized void read_data_from_url(String data_url){
try{
String data=(load(data_url)).toString();
StringTokenizer f = new StringTokenizer(data, ";");
int max=f.countTokens();String line="";
for(int s=0;s<max;s++){
line=f.nextToken();
plot().read(line);
}
showStatus("Done");
repaint();
}
catch (Exception e){System.out.println("Could not load data from URL or file : "+data_url);}
}
 
public synchronized void read_function_from_param(String function,String names,String totaal,int xmin,int xmax,int plotsteps,int smooth){
String fun;String line="";String fff;
Symbols symbols=new Symbols();
double stap=(double) (xmax-xmin)/plotsteps;double org=stap;double y=0.0;double x=0.0;double dy=0.0;
float diff;
int s;int max;int tot=0;int n;String legenda="";
if(names.length()!=0){ n=1; } else { n=0; }
StringTokenizer ff = new StringTokenizer(function, ",");max=ff.countTokens();
StringTokenizer nn = new StringTokenizer(names, ",");
for(s=0;s<max;s++){
if(n==0){ totaal=totaal+";dataset:"+s; } else {legenda=nn.nextToken(); totaal=totaal+";dataset:"+legenda; }
fff=ff.nextToken();
System.out.println("functie "+s + "="+fff);
for(x=xmin; x<xmax; x=x+stap){
if(smooth==1){
diff=(float) Math.abs(y-dy);
if(diff>10*stap && stap>0.001){stap=0.5*stap;}else{stap=org;}
}
fun=fff.replaceAll("x","("+Double.toString(x)+")");
try { y=symbols.eval(fun);} catch (SyntaxException e) {System.out.println("error "+e); }
totaal=totaal+";"+x+","+y;
tot++;
}
}
System.out.println("totaal aantal punten is "+tot);
StringTokenizer f = new StringTokenizer(totaal, ";");max=f.countTokens();
for(s=0;s<max;s++){
plot().read(f.nextToken());
}
showStatus("Done");
repaint();
}
 
 
public void init() {
super.init();
 
// FIXME: having the mutex causes applets to hang.
//synchronized (_mutex) {
Runnable doActions = new Runnable() {
public void run() {
if (_plot == null) {
_plot = newPlot();
}
 
getContentPane().add(plot(), BorderLayout.NORTH);
 
// Process the width and height applet parameters
int width;
 
// Process the width and height applet parameters
int height;
String widthspec = getParameter("width");
 
if (widthspec != null) {
width = Integer.parseInt(widthspec);
} else {
width = 400;
}
 
String heightspec = getParameter("height");
 
if (heightspec != null) {
height = Integer.parseInt(heightspec);
} else {
height = 400;
}
 
_setPlotSize(width, height);
plot().setButtons(true);
 
// Process the background parameter.
Color background = Color.white;
String colorspec = getParameter("background");
 
if (colorspec != null) {
background = PlotBox.getColorByName(colorspec);
}
 
setBackground(background);
plot().setBackground(background);
getContentPane().setBackground(background);
 
// Process the foreground parameter.
Color foreground = Color.black;
colorspec = getParameter("foreground");
 
if (colorspec != null) {
foreground = PlotBox.getColorByName(colorspec);
}
 
setForeground(foreground);
plot().setForeground(foreground);
plot().setVisible(true);
//jm.evers
String normalExponent=getParameter("normalexponent");
if(normalExponent != null && normalExponent.length()!=0){
if(normalExponent.equalsIgnoreCase("yes") || normalExponent.equals("1")){
normalexponent=true;
}
}
int finput=0;String data;
// reading the function param and all other params needed for plotting.
data=getParameter("function");
if(data!=null && data.length()!=0){
finput=1;int xmin;int xmax;int plotsteps=500;double ymin;double ymax;
String param;String xlabel;String ylabel;String grid;String title;String kleur="on";String xtics="";String ytics="";
String names="";int smooth=0;String xlog="off";String ylog="off";
String bargraph="";String binwidth="";String binoffset="";
param=getParameter("bargraph");
if(param!=null && param.length()!=0){ bargraph=param; }
param=getParameter("binwidth");
if(param!=null && param.length()!=0){ binwidth=param; }
param=getParameter("binoffset");
if(param!=null && param.length()!=0){ binoffset=param; }
param=getParameter("xmax");
if(param!=null && param.length()!=0){ xmax=(int) Integer.parseInt(param, 10); } else { xmax=10; }
param=getParameter("xmin");
if(param!=null && param.length()!=0){ xmin=(int) Integer.parseInt(param, 10); } else { xmin=-1*xmax; }
 
param=getParameter("ymax");
if(param!=null && param.length()!=0){
ymax=(double) Integer.parseInt(param, 10);
param=getParameter("ymin");
ymin=(double) Integer.parseInt(param, 10);
plot().setYRange(ymin,ymax);
}
param=getParameter("ylog");
if(param!=null && param.length()!=0){ if(param.equals("1")){ylog="on";}}
param=getParameter("xlog");
if(param!=null && param.length()!=0){ if(param.equals("1")){xlog="on";}}
param=getParameter("smooth");
if(param!=null && param.length()!=0){ if(param.equals("1")){smooth=1;}}
param=getParameter("names");
if(param!=null && param.length()!=0){ names=param; } else { names=""; }
param=getParameter("xlabel");
if(param!=null && param.length()!=0){ xlabel=param; } else { xlabel="x-axis"; }
param=getParameter("ylabel");
if(param!=null && param.length()!=0){ ylabel=param; } else { ylabel="y-axis"; }
param=getParameter("grid");
if(param.equalsIgnoreCase("off")){ grid="off"; } else { grid="on"; }
param=getParameter("title");
if(param!=null && param.length()!=0){ title=param; } else { title="WIMS data plotter"; }
param=getParameter("color");
if(param.equalsIgnoreCase("off")){ kleur="off"; }
param=getParameter("xtics");
if(param!=null && param.length()!=0){ xtics=param; }
param=getParameter("ytics");
if(param!=null && param.length()!=0){ ytics=param; }
param=getParameter("plotsteps");
if(param!=null && param.length()!=0){ plotsteps=(int) Integer.parseInt(param, 10); }
 
String totaal="TitleText: "+title+";xlabel: "+xlabel+";ylabel: "+ylabel+";xlog: "+xlog+";ylog: "+ylog+";grid: "+grid+";color: "+kleur+";xticks:"+xtics+";yticks:"+ytics+";bargraph: "+bargraph+";binwidth: "+binwidth+";binoffset: "+binoffset;
read_function_from_param(data , names , totaal, xmin , xmax , plotsteps , smooth);
}
// reading a string of data in the "plt" format. typical: the string is provided by a wims variable
data=getParameter("data");
if(data!=null){
finput=1;
read_from_param(data);
}
data=getParameter("file");
if(data!=null && finput==0){
finput=1;
read_data_from_url(data);
}
// Process the dataurl parameter.
// the file is written by wims and stored in the session-dir/getfile/
String dataurlspec = getParameter("dataurl");
 
if (dataurlspec != null && finput==0) {
try {
showStatus("Reading data");
System.out.println("Trying to read data from"+dataurlspec);
URL dataurl = new URL(getDocumentBase(), dataurlspec);
InputStream in = dataurl.openStream();
_read(in);
showStatus("Done");
} catch (MalformedURLException e) {
System.out.println(e.toString());
} catch (FileNotFoundException e) {
System.out.println("PlotApplet: file not found: " + e);
} catch (IOException e) {
System.out.println("PlotApplet: error reading input file: " + e);
}
}
}
};
 
try {
// NOTE: Using invokeAndWait() here risks causing
// deadlock. However, the Sun Tutorial recommends calling
// invokeAndWait so that the work finishes before returning.
// if we call invokeLater() then demo/PlotFourierSeries.java
// has problems.
SwingUtilities.invokeAndWait(doActions);
} catch (Exception ex) {
// Ignore InterruptedException.
// Other exceptions should not occur.
}
 
//}
}
 
/** Create a new Plot object for the applet. Derived classes can
* redefine this method to return a different type of plot object.
* @return A new instance of PlotBox.
*/
public PlotBox newPlot() {
return new Plot();
}
 
/** Return the plot object to operate on.
* @return The plot object associated with this applet.
*/
public PlotBox plot() {
return _plot;
}
 
/** Set the plot object to operate on.
* @param plot The plot object to associate with this applet.
*/
public void setPlot(PlotBox plot) {
// FIXME: this method is necessary for PxgraphApplet to work
// properly. We could modify newPlot() to set _plot, but
// that would change the newPlot() contract, so we add another method.
_plot = plot;
}
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
 
/** Read the specified stream. Derived classes may override this
* to support other file formats.
* @param in The input stream.
* @exception IOException If the stream cannot be read.
*/
protected void _read(InputStream in) throws IOException {
plot().read(in);
}
 
/** Given the size of the applet, set the size of the plot.
* Derived classes may override this to allow room for other
* widgets below the plot.
* @param appletWidth The width of the applet.
* @param appletHeight The height of the applet.
*/
protected void _setPlotSize(int appletWidth, int appletHeight) {
plot().setSize(appletWidth, appletHeight);
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
// Work around problem in Java 1.3.1_08 where if we create
// 6 instances of a Plot applet then navigate forward then
// back - IE and Navigator hang. (Roger Robins)
// FIXME: having the mutex causes applets to hang.
//private static Object _mutex = null;
// The Plot component we are running.
private transient PlotBox _plot;
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotBox.java
0,0 → 1,4354
/* A labeled box for signal plots.
 
@Copyright (c) 1997-2008 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.*;
 
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
 
import ptolemy.util.FileUtilities;
import ptolemy.util.StringUtilities;
 
// TO DO:
// - Augment getColorByName to support a full complement of colors
// (get the color list from Tycho).
//////////////////////////////////////////////////////////////////////////
//// PlotBox
 
/**
This class provides a labeled box within which to place a data plot.
A title, X and Y axis labels, tick marks, and a legend are all supported.
Zooming in and out is supported. To zoom in, drag the mouse
downwards to draw a box. To zoom out, drag the mouse upward.
<p>
The box can be configured either through a file with commands or
through direct invocation of the public methods of the class.
<p>
When calling the methods, in most cases the changes will not
be visible until paintComponent() has been called. To request that this
be done, call repaint().
<p>
A small set of key bindings are provided for convenience.
They are:
<ul>
<li> Cntrl-c: Export the plot to the clipboard (in PlotML).
<li> D: Dump the plot to standard output (in PlotML).
<li> E: Export the plot to standard output in EPS format.
<li> F: Fill the plot.
<li> H or ?: Display a simple help message.
<li> Cntrl-D or Q: quit
</ul>
These commands are provided in a menu by the PlotFrame class.
Note that exporting to the clipboard is not allowed in applets
(it used to be), so this will result in an error message.
<p>
At this time, the two export commands produce encapsulated postscript
tuned for black-and-white printers. In the future, more formats may
supported.
Exporting to the clipboard and to standard output, in theory,
is allowed for applets, unlike writing to a file. Thus, these
key bindings provide a simple mechanism to obtain a high-resolution
image of the plot from an applet, suitable for incorporation in
a document. However, in some browsers, exporting to standard out
triggers a security violation. You can use the JDK appletviewer instead.
<p>
To read commands from a file or URL, the preferred technique is
to use one of the classes in the plotml package. That package
supports both PlotML, an XML extension for plots, and a historical
file format specific to ptplot. The historical file format is
understood by the read() method in this class.
The syntax of the historical format, documented below, is rudimentary,
and will probably not be extended as ptplot evolves. Nonetheless,
we document it here since it is directly supported by this class.
<p>
The historical format for the file allows any number
commands, one per line. Unrecognized commands and commands with
syntax errors are ignored. Comments are denoted by a line starting
with a pound sign "#". The recognized commands include:
<pre>
TitleText: <i>string</i>
XLabel: <i>string</i>
YLabel: <i>string</i>
</pre>
These commands provide a title and labels for the X (horizontal) and Y
(vertical) axes.
A <i>string</i> is simply a sequence of characters, possibly
including spaces. There is no need here to surround them with
quotation marks, and in fact, if you do, the quotation marks will
be included in the labels.
<p>
The ranges of the X and Y axes can be optionally given by commands like:
<pre>
XRange: <i>min</i>, <i>max</i>
YRange: <i>min</i>, <i>max</i>
</pre>
The arguments <i>min</i> and <i>max</i> are numbers, possibly
including a sign and a decimal point. If they are not specified,
then the ranges are computed automatically from the data and padded
slightly so that datapoints are not plotted on the axes.
<p>
The tick marks for the axes are usually computed automatically from
the ranges. Every attempt is made to choose reasonable positions
for the tick marks regardless of the data ranges (powers of
ten multiplied by 1, 2, or 5 are used). However, they can also be
specified explicitly using commands like:
<pre>
XTicks: <i>label position, label position, ...</i>
YTicks: <i>label position, label position, ...</i>
</pre>
A <i>label</i> is a string that must be surrounded by quotation
marks if it contains any spaces. A <i>position</i> is a number
giving the location of the tick mark along the axis. For example,
a horizontal axis for a frequency domain plot might have tick marks
as follows:
<pre>
XTicks: -PI -3.14159, -PI/2 -1.570795, 0 0, PI/2 1.570795, PI 3.14159
</pre>
Tick marks could also denote years, months, days of the week, etc.
<p>
The X and Y axes can use a logarithmic scale with the following commands:
<pre>
XLog: on
YLog: on
</pre>
The grid labels represent powers of 10. Note that if a logarithmic
scale is used, then the values must be positive. Non-positive values
will be silently dropped. Note further that when using logarithmic
axes that the log of input data is taken as the data is added to the plot.
This means that <pre>XLog: on</pre> or <pre>YLog: on</pre> should
appear before any data. Also, the value of the XTicks, YTicks,
XRange or YRange directives should be in log units.
So, <pre>XTicks: 1K 3</pre> will display the string <pre>1K</pre>
at the 1000 mark.
<p>
By default, tick marks are connected by a light grey background grid.
This grid can be turned off with the following command:
<pre>
Grid: off
</pre>
It can be turned back on with
<pre>
Grid: on
</pre>
Also, by default, the first ten data sets are shown each in a unique color.
The use of color can be turned off with the command:
<pre>
Color: off
</pre>
It can be turned back on with
<pre>
Color: on
</pre>
Finally, the rather specialized command
<pre>
Wrap: on
</pre>
enables wrapping of the X (horizontal) axis, which means that if
a point is added with X out of range, its X value will be modified
modulo the range so that it lies in range. This command only has an
effect if the X range has been set explicitly. It is designed specifically
to support oscilloscope-like behavior, where the X value of points is
increasing, but the display wraps it around to left. A point that lands
on the right edge of the X range is repeated on the left edge to give
a better sense of continuity. The feature works best when points do land
precisely on the edge, and are plotted from left to right, increasing
in X.
<p>
All of the above commands can also be invoked directly by calling the
the corresponding public methods from some Java procedure.
<p>
This class uses features of JDK 1.2, and hence if used in an applet,
it can only be viewed by a browser that supports JDK 1.2, or a plugin.
 
@author Edward A. Lee, Christopher Brooks, Contributors: Jun Wu (jwu@inin.com.au), William Wu, Robert Kroeger
 
@version $Id: PlotBox.java,v 1.283.4.3 2008/04/01 01:19:02 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class PlotBox extends JPanel implements Printable {
// jm.evers //
public String ReadPlotApplet(){
String reply="error\nReadApplet() not implemented\nNO SENSIBLE USER INTERACTION PRESENT";
return reply;
}
// jm.evers //
///////////////////////////////////////////////////////////////////
//// constructor ////
 
/** Construct a plot box with a default configuration. */
public PlotBox() {
// If we make this transparent, the background shows through.
// However, we assume that the user will set the background.
// NOTE: A component is transparent by default (?).
// setOpaque(false);
setOpaque(true);
 
// Create a right-justified layout with spacing of 2 pixels.
setLayout(new FlowLayout(FlowLayout.RIGHT, 2, 2));
addMouseListener(new ZoomListener());
addKeyListener(new CommandListener());
addMouseMotionListener(new DragListener());
 
// This is something we want to do only once...
_measureFonts();
 
// Request the focus so that key events are heard.
// NOTE: no longer needed?
// requestFocus();
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Add a legend (displayed at the upper right) for the specified
* data set with the specified string. Short strings generally
* fit better than long strings. If the string is empty, or the
* argument is null, then no legend is added.
* @param dataset The dataset index.
* @param legend The label for the dataset.
* @see #renameLegend(int, String)
*/
public synchronized void addLegend(int dataset, String legend) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
if ((legend == null) || legend.equals("")) {
return;
}
 
_legendStrings.addElement(legend);
_legendDatasets.addElement(Integer.valueOf(dataset));
}
 
/** Specify a tick mark for the X axis. The label given is placed
* on the axis at the position given by <i>position</i>. If this
* is called once or more, automatic generation of tick marks is
* disabled. The tick mark will appear only if it is within the X
* range.
* @param label The label for the tick mark.
* @param position The position on the X axis.
*/
public synchronized void addXTick(String label, double position) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
if (_xticks == null) {
_xticks = new Vector();
_xticklabels = new Vector();
}
 
_xticks.addElement(Double.valueOf(position));
_xticklabels.addElement(label);
}
 
/** Specify a tick mark for the Y axis. The label given is placed
* on the axis at the position given by <i>position</i>. If this
* is called once or more, automatic generation of tick marks is
* disabled. The tick mark will appear only if it is within the Y
* range.
* @param label The label for the tick mark.
* @param position The position on the Y axis.
*/
public synchronized void addYTick(String label, double position) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
if (_yticks == null) {
_yticks = new Vector();
_yticklabels = new Vector();
}
 
_yticks.addElement(Double.valueOf(position));
_yticklabels.addElement(label);
}
 
/** If the argument is true, clear the axes. I.e., set all parameters
* controlling the axes to their initial conditions.
* For the change to take effect, call repaint(). If the argument
* is false, do nothing.
* @param axes If true, clear the axes parameters.
*/
public synchronized void clear(boolean axes) {
// We need to repaint the offscreen buffer.
_plotImage = null;
 
_xBottom = Double.MAX_VALUE;
_xTop = -Double.MAX_VALUE;
_yBottom = Double.MAX_VALUE;
_yTop = -Double.MAX_VALUE;
 
if (axes) {
// Protected members first.
_yMax = 0;
_yMin = 0;
_xMax = 0;
_xMin = 0;
_xRangeGiven = false;
_yRangeGiven = false;
_originalXRangeGiven = false;
_originalYRangeGiven = false;
_rangesGivenByZooming = false;
_xlog = false;
_ylog = false;
_grid = true;
_wrap = false;
_usecolor = true;
 
// Private members next...
_filespec = null;
_xlabel = null;
_ylabel = null;
_title = null;
_legendStrings = new Vector();
_legendDatasets = new Vector();
_xticks = null;
_xticklabels = null;
_yticks = null;
_yticklabels = null;
}
}
 
/** Clear all legends. This will show up on the next redraw.
*/
public synchronized void clearLegends() {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_legendStrings = new Vector();
_legendDatasets = new Vector();
}
 
/** If this method is called in the event thread, then simply
* execute the specified action. Otherwise,
* if there are already deferred actions, then add the specified
* one to the list. Otherwise, create a list of deferred actions,
* if necessary, and request that the list be processed in the
* event dispatch thread.
*
* Note that it does not work nearly as well to simply schedule
* the action yourself on the event thread because if there are a
* large number of actions, then the event thread will not be able
* to keep up. By grouping these actions, we avoid this problem.
*
* This method is not synchronized, so the caller should be.
* @param action The Runnable object to execute.
*/
public void deferIfNecessary(Runnable action) {
// In swing, updates to showing graphics must be done in the
// event thread. If we are in the event thread, then proceed.
// Otherwise, queue a request or add to a pending request.
if (EventQueue.isDispatchThread()) {
action.run();
} else {
if (_deferredActions == null) {
_deferredActions = new LinkedList();
}
 
// Add the specified action to the list of actions to perform.
_deferredActions.add(action);
 
// If it hasn't already been requested, request that actions
// be performed in the event dispatch thread.
if (!_actionsDeferred) {
Runnable doActions = new Runnable() {
public void run() {
_executeDeferredActions();
}
};
 
try {
// NOTE: Using invokeAndWait() here risks causing
// deadlock. Don't do it!
SwingUtilities.invokeLater(doActions);
} catch (Exception ex) {
// Ignore InterruptedException.
// Other exceptions should not occur.
}
 
_actionsDeferred = true;
}
}
}
 
/** Export a description of the plot.
* Currently, only EPS is supported. But in the future, this
* may cause a dialog box to open to allow the user to select
* a format. If the argument is null, then the description goes
* to the clipboard. Otherwise, it goes to the specified file.
* To send it to standard output, use
* <code>System.out</code> as an argument.
* @param out An output stream to which to send the description.
*/
public synchronized void export(OutputStream out) {
try {
EPSGraphics g = new EPSGraphics(out, _width, _height);
_drawPlot(g, false);
g.showpage();
} catch (RuntimeException ex) {
String message = "Export failed: " + ex.getMessage();
JOptionPane.showMessageDialog(this, message,
"Ptolemy Plot Message", JOptionPane.ERROR_MESSAGE);
 
// Rethrow the exception so that we don't report success,
// and so the stack trace is displayed on standard out.
throw (RuntimeException) ex.fillInStackTrace();
}
}
 
// CONTRIBUTED CODE.
// I wanted the ability to use the Plot object in a servlet and to
// write out the resultant images. The following routines,
// particularly exportImage(), permit this. I also had to make some
// minor changes elsewhere. Rob Kroeger, May 2001.
// NOTE: This code has been modified by EAL to conform with Ptolemy II
// coding style.
 
/** Create a BufferedImage and draw this plot to it.
* The size of the returned image matches the current size of the plot.
* This method can be used, for
* example, by a servlet to produce an image, rather than
* requiring an applet to instantiate a PlotBox.
* @return An image filled by the plot.
*/
public synchronized BufferedImage exportImage() {
Rectangle rectangle = new Rectangle(_preferredWidth, _preferredHeight);
return exportImage(new BufferedImage(rectangle.width, rectangle.height,
BufferedImage.TYPE_INT_ARGB), rectangle,
_defaultImageRenderingHints(), false);
}
 
/** Create a BufferedImage the size of the given rectangle and draw
* this plot to it at the position specified by the rectangle.
* The plot is rendered using anti-aliasing.
* @param rectangle The size of the plot. This method can be used, for
* example, by a servlet to produce an image, rather than
* requiring an applet to instantiate a PlotBox.
* @return An image containing the plot.
*/
public synchronized BufferedImage exportImage(Rectangle rectangle) {
return exportImage(new BufferedImage(rectangle.width, rectangle.height,
BufferedImage.TYPE_INT_ARGB), rectangle,
_defaultImageRenderingHints(), false);
}
 
/** Draw this plot onto the specified image at the position of the
* specified rectangle with the size of the specified rectangle.
* The plot is rendered using anti-aliasing.
* This can be used to paint a number of different
* plots onto a single buffered image. This method can be used, for
* example, by a servlet to produce an image, rather than
* requiring an applet to instantiate a PlotBox.
* @param bufferedImage Image onto which the plot is drawn.
* @param rectangle The size and position of the plot in the image.
* @param hints Rendering hints for this plot.
* @param transparent Indicator that the background of the plot
* should not be painted.
* @return The modified bufferedImage.
*/
public synchronized BufferedImage exportImage(BufferedImage bufferedImage,
Rectangle rectangle, RenderingHints hints, boolean transparent) {
Graphics2D graphics = bufferedImage.createGraphics();
graphics.addRenderingHints(_defaultImageRenderingHints());
 
if (!transparent) {
graphics.setColor(Color.white); // set the background color
graphics.fill(rectangle);
}
 
_drawPlot(graphics, false, rectangle);
return bufferedImage;
}
 
/** Draw this plot onto the provided image.
* This method does not paint the background, so the plot is
* transparent. The plot fills the image, and is rendered
* using anti-aliasing. This method can be used to overlay
* multiple plots on the same image, although you must use care
* to ensure that the axes and other labels are identical.
* Hence, it is usually better to simply combine data sets into
* a single plot.
* @param bufferedImage The image onto which to render the plot.
* @return The modified bufferedImage.
*/
public synchronized BufferedImage exportImage(BufferedImage bufferedImage) {
return exportImage(bufferedImage, new Rectangle(bufferedImage
.getWidth(), bufferedImage.getHeight()),
_defaultImageRenderingHints(), true);
}
 
/** Rescale so that the data that is currently plotted just fits.
* This is done based on the protected variables _xBottom, _xTop,
* _yBottom, and _yTop. It is up to derived classes to ensure that
* variables are valid.
* This method calls repaint(), which eventually causes the display
* to be updated.
*/
public synchronized void fillPlot() {
// NOTE: These used to be _setXRange() and _setYRange() to avoid
// confusing this with user-specified ranges. But we want to treat
// a fill command as a user specified range.
// EAL, 6/12/00.
setXRange(_xBottom, _xTop);
setYRange(_yBottom, _yTop);
repaint();
 
// Reacquire the focus so that key bindings work.
// NOTE: no longer needed?
// requestFocus();
}
 
/** Return whether the plot uses color.
* @return True if the plot uses color.
*/
public boolean getColor() {
return _usecolor;
}
 
/** Get the point colors.
* @return Array of colors
* @see #setColors(Color[])
*/
public Color[] getColors() {
return _colors;
}
 
/** Convert a color name into a Color. Currently, only a very limited
* set of color names is supported: black, white, red, green, and blue.
* @param name A color name, or null if not found.
* @return An instance of Color.
*/
public static Color getColorByName(String name) {
try {
// Check to see if it is a hexadecimal
if (name.startsWith("#")) {
name = name.substring(1);
}
 
Color col = new Color(Integer.parseInt(name, 16));
return col;
} catch (NumberFormatException e) {
}
 
// FIXME: This is a poor excuse for a list of colors and values.
// We should use a hash table here.
// Note that Color decode() wants the values to start with 0x.
String[][] names = { { "black", "00000" }, { "white", "ffffff" },
{ "red", "ff0000" }, { "green", "00ff00" },
{ "blue", "0000ff" } ,{"yellow", "ffff00"} };
 
for (int i = 0; i < names.length; i++) {
if (name.equals(names[i][0])) {
try {
Color col = new Color(Integer.parseInt(names[i][1], 16));
return col;
} catch (NumberFormatException e) {
}
}
}
 
return null;
}
 
/** Get the file specification that was given by setDataurl.
* This method is deprecated. Use read() instead.
* @deprecated
*/
public String getDataurl() {
return _filespec;
}
 
/** Get the document base that was set by setDocumentBase.
* This method is deprecated. Use read() instead.
* @deprecated
*/
public URL getDocumentBase() {
return _documentBase;
}
 
/** Return whether the grid is drawn.
* @return True if a grid is drawn.
*/
public boolean getGrid() {
return _grid;
}
 
/** Get the legend for a dataset, or null if there is none.
* The legend would have been set by addLegend().
* @param dataset The dataset index.
* @return The legend label, or null if there is none.
*/
public synchronized String getLegend(int dataset) {
int idx = _legendDatasets.indexOf(Integer.valueOf(dataset), 0);
 
if (idx != -1) {
return (String) _legendStrings.elementAt(idx);
} else {
return null;
}
}
 
/** Given a legend string, return the corresponding dataset or -1 if no
* legend was added with that legend string
* The legend would have been set by addLegend().
* @param legend The String naming the legend
* @return The legend dataset, or -1 if not found.
* @since Ptplot 5.2p1
*/
public synchronized int getLegendDataset(String legend) {
int index = _legendStrings.indexOf(legend);
 
if (index == -1) {
return -1;
}
 
return ((Integer) _legendDatasets.get(index)).intValue();
}
 
/** If the size of the plot has been set by setSize(),
* then return that size. Otherwise, return what the superclass
* returns (which is undocumented, but apparently imposes no maximum size).
* Currently (JDK 1.3), only BoxLayout pays any attention to this.
* @return The maximum desired size.
*/
 
// public synchronized Dimension getMaximumSize() {
// if (_sizeHasBeenSet) {
// return new Dimension(_preferredWidth, _preferredHeight);
// } else {
// return super.getMaximumSize();
// }
// }
/** Get the minimum size of this component.
* This is simply the dimensions specified by setSize(),
* if this has been called. Otherwise, return whatever the base
* class returns, which is undocumented.
* @return The minimum size.
*/
 
// public synchronized Dimension getMinimumSize() {
// if (_sizeHasBeenSet) {
// return new Dimension(_preferredWidth, _preferredHeight);
// } else {
// return super.getMinimumSize();
// }
// }
/** Get the current plot rectangle.
* Note that Rectangle returned by this method is calculated
* from the values of {@link #_ulx}, {@link #_uly},
* {@link #_lrx} and {@link #_lry}. The value passed in by
* setPlotRectangle() is not directly used, thus calling
* getPlotRectangle() may not return the same rectangle that
* was passed in with setPlotRectangle().
* @return Rectangle
* @see #setPlotRectangle(Rectangle)
*/
public Rectangle getPlotRectangle() {
return new Rectangle(_ulx, _uly, _lrx - _ulx, _lry - _uly);
}
 
/** Get the preferred size of this component.
* This is simply the dimensions specified by setSize(),
* if this has been called, or the default width and height
* otherwise (500 by 300).
* @return The preferred size.
*/
public synchronized Dimension getPreferredSize() {
return new Dimension(_preferredWidth, _preferredHeight);
}
 
/** Get the title of the graph, or an empty string if there is none.
* @return The title.
*/
public synchronized String getTitle() {
if (_title == null) {
return "";
}
 
return _title;
}
 
/** Get the range for X values of the data points registered so far.
* Usually, derived classes handle managing the range by checking
* each new point against the current range.
* @return An array of two doubles where the first element is the
* minimum and the second element is the maximum.
* @see #getXRange()
*/
public synchronized double[] getXAutoRange() {
double[] result = new double[2];
result[0] = _xBottom;
result[1] = _xTop;
return result;
}
 
/** Get the label for the X (horizontal) axis, or null if none has
* been set.
* @return The X label.
*/
public synchronized String getXLabel() {
return _xlabel;
}
 
/** Return whether the X axis is drawn with a logarithmic scale.
* @return True if the X axis is logarithmic.
*/
public boolean getXLog() {
return _xlog;
}
 
/** Get the X range. If {@link #setXRange(double, double)} has been
* called, then this method returns the values passed in as
* arguments to setXRange(double, double). If setXRange(double,
* double) has not been called, then this method returns the
* range of the data to be plotted, which might not be all of the
* data due to zooming.
* @return An array of two doubles where the first element is the
* minimum and the second element is the maximum.
* @see #getXAutoRange()
*/
public synchronized double[] getXRange() {
double[] result = new double[2];
 
if (_xRangeGiven) {
result[0] = _xlowgiven;
result[1] = _xhighgiven;
} else {
// Have to first correct for the padding.
result[0] = _xMin + ((_xMax - _xMin) * _padding);
result[1] = _xMax - ((_xMax - _xMin) * _padding);
;
}
 
return result;
}
 
/** Get the X ticks that have been specified, or null if none.
* The return value is an array with two vectors, the first of
* which specifies the X tick locations (as instances of Double),
* and the second of which specifies the corresponding labels.
* @return The X ticks.
*/
public synchronized Vector[] getXTicks() {
if (_xticks == null) {
return null;
}
 
Vector[] result = new Vector[2];
result[0] = _xticks;
result[1] = _xticklabels;
return result;
}
 
/** Get the range for Y values of the data points registered so far.
* Usually, derived classes handle managing the range by checking
* each new point against the range.
* @return An array of two doubles where the first element is the
* minimum and the second element is the maximum.
* @see #getYRange()
*/
public synchronized double[] getYAutoRange() {
double[] result = new double[2];
result[0] = _yBottom;
result[1] = _yTop;
return result;
}
 
/** Get the label for the Y (vertical) axis, or null if none has
* been set.
* @return The Y label.
*/
public String getYLabel() {
return _ylabel;
}
 
/** Return whether the Y axis is drawn with a logarithmic scale.
* @return True if the Y axis is logarithmic.
*/
public boolean getYLog() {
return _ylog;
}
 
/** Get the Y range. If {@link #setYRange(double, double)} has been
* called, then this method returns the values passed in as
* arguments to setYRange(double, double). If setYRange(double,
* double) has not been called, then this method returns the
* range of the data to be plotted, which might not be all of the
* data due to zooming.
* @return An array of two doubles where the first element is the
* minimum and the second element is the maximum.
* @see #getYAutoRange()
*/
public synchronized double[] getYRange() {
double[] result = new double[2];
 
if (_yRangeGiven) {
result[0] = _ylowgiven;
result[1] = _yhighgiven;
} else {
// Have to first correct for the padding.
result[0] = _yMin + ((_yMax - _yMin) * _padding);
result[1] = _yMax - ((_yMax - _yMin) * _padding);
;
}
 
return result;
}
 
/** Get the Y ticks that have been specified, or null if none.
* The return value is an array with two vectors, the first of
* which specifies the Y tick locations (as instances of Double),
* and the second of which specifies the corresponding labels.
* @return The Y ticks.
*/
public synchronized Vector[] getYTicks() {
if (_yticks == null) {
return null;
}
 
Vector[] result = new Vector[2];
result[0] = _yticks;
result[1] = _yticklabels;
return result;
}
 
/** Initialize the component, creating the fill button and parsing
* an input file, if one has been specified. This is deprecated.
* Call setButtons() and read() instead.
* @deprecated
*/
public void init() {
setButtons(true);
 
if (_filespec != null) {
parseFile(_filespec, _documentBase);
}
}
 
/** Paint the component contents, which in this base class is
* only the axes.
* @param graphics The graphics context.
*/
public synchronized void paintComponent(Graphics graphics) {
// super.paintComponent(graphics);
// _drawPlot(graphics, true);
BufferedImage newPlotImage = _plotImage;
 
if (newPlotImage == null) {
Rectangle bounds = getBounds();
newPlotImage = new BufferedImage(bounds.width, bounds.height,
BufferedImage.TYPE_3BYTE_BGR);
_plotImage = newPlotImage;
 
Graphics2D offScreenGraphics = newPlotImage.createGraphics();
super.paintComponent(offScreenGraphics);
_drawPlot(offScreenGraphics, true);
}
 
// Blit the offscreen image onto the screen.
graphics.drawImage(newPlotImage, 0, 0, null);
 
// Acquire the focus so that key bindings work.
// NOTE: no longer needed?
// requestFocus();
}
 
/** Syntactic sugar for parseFile(filespec, documentBase).
* This method is deprecated. Use read() to read the old file
* format, or use one of the classes in the plotml package to
* read the XML-based file format.
* @deprecated
*/
public void parseFile(String filespec) {
parseFile(filespec, (URL) null);
}
 
/** Open up the input file, which could be stdin, a URL, or a file.
* @deprecated This method is deprecated. Use read() instead.
*/
public synchronized void parseFile(String filespec, URL documentBase) {
DataInputStream in = null;
 
if ((filespec == null) || (filespec.length() == 0)) {
// Open up stdin
in = new DataInputStream(System.in);
} else {
try {
URL url = null;
 
if ((documentBase == null) && (_documentBase != null)) {
documentBase = _documentBase;
}
 
if (documentBase == null) {
url = new URL(filespec);
} else {
try {
url = new URL(documentBase, filespec);
} catch (NullPointerException e) {
// If we got a NullPointerException, then perhaps we
// are calling this as an application, not as an applet
url = new URL(filespec);
}
}
 
in = new DataInputStream(url.openStream());
} catch (MalformedURLException e) {
try {
// Just try to open it as a file.
in = new DataInputStream(new FileInputStream(filespec));
} catch (FileNotFoundException me) {
_errorMsg = new String[2];
_errorMsg[0] = "File not found: " + filespec;
_errorMsg[1] = me.getMessage();
return;
} catch (SecurityException me) {
_errorMsg = new String[2];
_errorMsg[0] = "Security Exception: " + filespec;
_errorMsg[1] = me.getMessage();
return;
}
} catch (IOException ioe) {
_errorMsg = new String[3];
_errorMsg[0] = "Failure opening URL: ";
_errorMsg[1] = " " + filespec;
_errorMsg[2] = ioe.getMessage();
return;
}
}
 
// At this point, we've opened the data source, now read it in
try {
BufferedReader din = new BufferedReader(new InputStreamReader(in));
String line = din.readLine();
 
while (line != null) {
_parseLine(line);
line = din.readLine();
}
} catch (MalformedURLException e) {
_errorMsg = new String[2];
_errorMsg[0] = "Malformed URL: " + filespec;
_errorMsg[1] = e.getMessage();
return;
} catch (IOException e) {
_errorMsg = new String[2];
_errorMsg[0] = "Failure reading data: " + filespec;
_errorMsg[1] = e.getMessage();
_errorMsg[1] = e.getMessage();
} finally {
try {
in.close();
} catch (IOException me) {
}
}
}
 
/** Print the plot to a printer, represented by the specified graphics
* object.
* @param graphics The context into which the page is drawn.
* @param format The size and orientation of the page being drawn.
* @param index The zero based index of the page to be drawn.
* @return PAGE_EXISTS if the page is rendered successfully, or
* NO_SUCH_PAGE if pageIndex specifies a non-existent page.
* @exception PrinterException If the print job is terminated.
*/
public synchronized int print(Graphics graphics, PageFormat format,
int index) throws PrinterException {
 
if (graphics == null) {
return Printable.NO_SUCH_PAGE;
}
 
// We only print on one page.
if (index >= 1) {
return Printable.NO_SUCH_PAGE;
}
 
Graphics2D graphics2D = (Graphics2D) graphics;
 
// Scale the printout to fit the pages.
// Contributed by Laurent ETUR, Schlumberger Riboud Product Center
double scalex = format.getImageableWidth() / getWidth();
double scaley = format.getImageableHeight() / getHeight();
double scale = Math.min(scalex, scaley);
graphics2D.translate((int) format.getImageableX(), (int) format
.getImageableY());
graphics2D.scale(scale, scale);
_drawPlot(graphics, true);
return Printable.PAGE_EXISTS;
}
 
/** Read commands and/or plot data from an input stream in the old
* (non-XML) file syntax.
* To update the display, call repaint(), or make the plot visible with
* setVisible(true).
* <p>
* To read from standard input, use:
* <pre>
* read(System.in);
* </pre>
* To read from a url, use:
* <pre>
* read(url.openStream());
* </pre>
* To read a URL from within an applet, use:
* <pre>
* URL url = new URL(getDocumentBase(), urlSpec);
* read(url.openStream());
* </pre>
* Within an application, if you have an absolute URL, use:
* <pre>
* URL url = new URL(urlSpec);
* read(url.openStream());
* </pre>
* To read from a file, use:
* <pre>
* read(new FileInputStream(filename));
* </pre>
* @param in The input stream.
* @exception IOException If the stream cannot be read.
*/
public synchronized void read(InputStream in) throws IOException {
try {
// NOTE: I tried to use exclusively the jdk 1.1 Reader classes,
// but they provide no support like DataInputStream, nor
// support for URL accesses. So I use the older classes
// here in a strange mixture.
BufferedReader din = new BufferedReader(new InputStreamReader(in));
 
try {
String line = din.readLine();
 
while (line != null) {
_parseLine(line);
line = din.readLine();
}
} finally {
din.close();
}
} catch (IOException e) {
_errorMsg = new String[2];
_errorMsg[0] = "Failure reading input data.";
_errorMsg[1] = e.getMessage();
throw e;
}
}
 
/** Read a single line command provided as a string.
* The commands can be any of those in the ASCII file format.
* @param command A command.
*/
public synchronized void read(String command) {
_parseLine(command);
}
 
/** Remove the legend (displayed at the upper right) for the specified
* data set. If the dataset is not found, nothing will occur.
* The PlotBox must be repainted in order for this to take effect.
* @param dataset The dataset index.
*/
public synchronized void removeLegend(int dataset) {
final int len = _legendDatasets.size();
int foundIndex = -1;
boolean found = false;
 
for (int i = 0; (i < len) && !found; ++i) {
if (((Integer) _legendDatasets.get(i)).intValue() == dataset) {
foundIndex = i;
found = true;
}
}
 
if (found) {
_legendDatasets.remove(foundIndex);
_legendStrings.remove(foundIndex);
}
}
 
/** Rename a legend.
* @param dataset The dataset of the legend to be renamed.
* If there is no dataset with this value, then nothing happens.
* @param newName The new name of legend.
* @see #addLegend(int, String)
*/
public synchronized void renameLegend(int dataset, String newName) {
int index = _legendDatasets.indexOf(Integer.valueOf(dataset), 0);
 
if (index != -1) {
_legendStrings.setElementAt(newName, index);
 
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
}
}
 
/** Reset the X and Y axes to the ranges that were first specified
* using setXRange() and setYRange(). If these methods have not been
* called, then reset to the default ranges.
* This method calls repaint(), which eventually causes the display
* to be updated.
*/
public synchronized void resetAxes() {
setXRange(_originalXlow, _originalXhigh);
setYRange(_originalYlow, _originalYhigh);
repaint();
}
 
/** Do nothing in this base class. Derived classes might want to override
* this class to give an example of their use.
*/
public void samplePlot() {
// Empty default implementation.
}
 
/** Set the background color.
* @param background The background color.
*/
public synchronized void setBackground(Color background) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_background = background;
super.setBackground(_background);
}
 
/** Move and resize this component. The new location of the top-left
* corner is specified by x and y, and the new size is specified by
* width and height. This overrides the base class method to make
* a record of the new size.
* @param x The new x-coordinate of this component.
* @param y The new y-coordinate of this component.
* @param width The new width of this component.
* @param height The new height of this component.
*/
public synchronized void setBounds(int x, int y, int width, int height) {
_width = width;
_height = height;
 
// Resizing the component means we need to redraw the buffer.
_plotImage = null;
 
super.setBounds(x, y, _width, _height);
}
 
/** If the argument is true, make a fill button visible at the upper
* right. This button auto-scales the plot.
* NOTE: The button may infringe on the title space,
* if the title is long. In an application, it is preferable to provide
* a menu with the fill command. This way, when printing the plot,
* the printed plot will not have a spurious button. Thus, this method
* should be used only by applets, which normally do not have menus.
* This method should only be called from within the event dispatch
* thread, since it interacts with swing.
*/
public synchronized void setButtons(boolean visible) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
if (_printButton == null) {
// Load the image by using the absolute path to the gif.
URL img = null;
try {
// FindBugs: Usage of GetResource may be unsafe if
// class is extended
img = FileUtilities.nameToURL(
"$CLASSPATH/ptolemy/plot/img/print.gif", null, null);
} catch (IOException ex) {
ex.printStackTrace();
}
 
if (img != null) {
ImageIcon printIcon = new ImageIcon(img);
_printButton = new JButton(printIcon);
_printButton.setBorderPainted(false);
} else {
// Backup in case something goes wrong with the
// class loader.
_printButton = new JButton("P");
}
 
// FIXME: If we failed to get an image, then the letter "P"
// Is not likely to fit into a 20x20 button.
_printButton.setPreferredSize(new Dimension(20, 20));
_printButton.setToolTipText("Print the plot.");
_printButton.addActionListener(new ButtonListener());
add(_printButton);
}
 
_printButton.setVisible(visible);
 
if (_resetButton == null) {
// Load the image by using the absolute path to the gif.
URL img = null;
try {
// FindBugs: Usage of GetResource may be unsafe if
// class is extended
img = FileUtilities.nameToURL(
"$CLASSPATH/ptolemy/plot/img/reset.gif", null, null);
} catch (IOException ex) {
ex.printStackTrace();
}
if (img != null) {
ImageIcon resetIcon = new ImageIcon(img);
_resetButton = new JButton(resetIcon);
_resetButton.setBorderPainted(false);
} else {
// Backup in case something goes wrong with the
// class loader.
_resetButton = new JButton("R");
}
 
// FIXME: If we failed to get an image, then the letter "R"
// Is not likely to fit into a 20x20 button.
_resetButton.setPreferredSize(new Dimension(20, 20));
_resetButton
.setToolTipText("Reset X and Y ranges to their original values");
_resetButton.addActionListener(new ButtonListener());
add(_resetButton);
}
 
_resetButton.setVisible(visible);
 
if (_formatButton == null) {
// Load the image by using the absolute path to the gif.
URL img = null;
try {
// FindBugs: Usage of GetResource may be unsafe if
// class is extended
img = FileUtilities.nameToURL(
"$CLASSPATH/ptolemy/plot/img/format.gif", null, null);
} catch (IOException ex) {
ex.printStackTrace();
}
if (img != null) {
ImageIcon formatIcon = new ImageIcon(img);
_formatButton = new JButton(formatIcon);
_formatButton.setBorderPainted(false);
} else {
// Backup in case something goes wrong with the
// class loader.
_formatButton = new JButton("S");
}
 
// FIXME: If we failed to get an image, then the letter "S"
// Is not likely to fit into a 20x20 button.
_formatButton.setPreferredSize(new Dimension(20, 20));
_formatButton.setToolTipText("Set the plot format");
_formatButton.addActionListener(new ButtonListener());
add(_formatButton);
}
 
_formatButton.setVisible(visible);
 
if (_fillButton == null) {
// Load the image by using the absolute path to the gif.
URL img = null;
try {
// FindBugs: Usage of GetResource may be unsafe if
// class is extended
img = FileUtilities.nameToURL(
"$CLASSPATH/ptolemy/plot/img/fill.gif", null, null);
} catch (IOException ex) {
ex.printStackTrace();
}
if (img != null) {
ImageIcon fillIcon = new ImageIcon(img);
_fillButton = new JButton(fillIcon);
_fillButton.setBorderPainted(false);
} else {
// Backup in case something goes wrong with the
// class loader.
_fillButton = new JButton("F");
}
 
// FIXME: If we failed to get an image, then the letter "F"
// Is not likely to fit into a 20x20 button.
_fillButton.setPreferredSize(new Dimension(20, 20));
_fillButton.setToolTipText("Rescale the plot to fit the data");
_fillButton.addActionListener(new ButtonListener());
add(_fillButton);
}
 
_fillButton.setVisible(visible);
 
// Request the focus so that key events are heard.
// NOTE: no longer needed?
// requestFocus();
}
 
/** If the argument is false, draw the plot without using color
* (in black and white). Otherwise, draw it in color (the default).
* @param useColor False to draw in back and white.
*/
public synchronized void setColor(boolean useColor) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_usecolor = useColor;
}
 
/** Set the point colors. Note that the default colors have been
* carefully selected to maximize readability and that it is easy
* to use colors that result in a very ugly plot.
* @param colors Array of colors to use in succession for data sets.
* @see #getColors()
*/
public synchronized void setColors(Color[] colors) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_colors = colors;
}
 
/** Set the file to read when init() is called.
* This method is deprecated. Use read() instead.
* @deprecated
*/
public void setDataurl(String filespec) {
_filespec = filespec;
}
 
/** Set the document base to used when init() is called to read a URL.
* This method is deprecated. Use read() instead.
* @deprecated
*/
public void setDocumentBase(URL documentBase) {
_documentBase = documentBase;
}
 
/** Set the foreground color.
* @param foreground The foreground color.
*/
public synchronized void setForeground(Color foreground) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_foreground = foreground;
super.setForeground(_foreground);
}
 
/** Control whether the grid is drawn.
* @param grid If true, a grid is drawn.
*/
public synchronized void setGrid(boolean grid) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_grid = grid;
}
 
/** Set the label font, which is used for axis labels and legend labels.
* The font names understood are those understood by
* java.awt.Font.decode().
* @param name A font name.
*/
public synchronized void setLabelFont(String name) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_labelFont = Font.decode(name);
_labelFontMetrics = getFontMetrics(_labelFont);
}
 
/** Set the plot rectangle inside the axes. This method
* can be used to create two plots that share the same axes.
* @param rectangle Rectangle space inside axes.
* @see #getPlotRectangle()
*/
public synchronized void setPlotRectangle(Rectangle rectangle) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_specifiedPlotRectangle = rectangle;
}
 
/** Set the size of the plot. This overrides the base class to make
* it work. In particular, it records the specified size so that
* getMinimumSize() and getPreferredSize() return the specified value.
* However, it only works if the plot is placed in its own JPanel.
* This is because the JPanel asks the contained component for
* its preferred size before determining the size of the panel.
* If the plot is placed directly in the content pane of a JApplet,
* then, mysteriously, this method has no effect.
* @param width The width, in pixels.
* @param height The height, in pixels.
*/
public synchronized void setSize(int width, int height) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_width = width;
_height = height;
_preferredWidth = width;
_preferredHeight = height;
 
//_sizeHasBeenSet = true;
super.setSize(width, height);
}
 
/** Set the title of the graph.
* @param title The title.
*/
public synchronized void setTitle(String title) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_title = title;
}
 
/** Set the title font.
* The font names understood are those understood by
* java.awt.Font.decode().
* @param name A font name.
*/
public synchronized void setTitleFont(String name) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_titleFont = Font.decode(name);
_titleFontMetrics = getFontMetrics(_titleFont);
}
 
/** Specify whether the X axis is wrapped.
* If it is, then X values that are out of range are remapped
* to be in range using modulo arithmetic. The X range is determined
* by the most recent call to setXRange() (or the most recent zoom).
* If the X range has not been set, then use the default X range,
* or if data has been plotted, then the current fill range.
* @param wrap If true, wrapping of the X axis is enabled.
*/
public synchronized void setWrap(boolean wrap) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_wrap = wrap;
 
if (!_xRangeGiven) {
if (_xBottom > _xTop) {
// have nothing to go on.
setXRange(0, 0);
} else {
setXRange(_xBottom, _xTop);
}
}
 
_wrapLow = _xlowgiven;
_wrapHigh = _xhighgiven;
}
 
/** Set the label for the X (horizontal) axis.
* @param label The label.
*/
public synchronized void setXLabel(String label) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_xlabel = label;
}
 
/** Specify whether the X axis is drawn with a logarithmic scale.
* If you would like to have the X axis drawn with a
* logarithmic axis, then setXLog(true) should be called before
* adding any data points.
* @param xlog If true, logarithmic axis is used.
*/
public synchronized void setXLog(boolean xlog) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_xlog = xlog;
}
 
/** Set the X (horizontal) range of the plot. If this is not done
* explicitly, then the range is computed automatically from data
* available when the plot is drawn. If min and max
* are identical, then the range is arbitrarily spread by 1.
* @param min The left extent of the range.
* @param max The right extent of the range.
*/
public synchronized void setXRange(double min, double max) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_xRangeGiven = true;
_xlowgiven = min;
_xhighgiven = max;
_setXRange(min, max);
}
 
/** Set the label for the Y (vertical) axis.
* @param label The label.
*/
public synchronized void setYLabel(String label) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_ylabel = label;
}
 
/** Specify whether the Y axis is drawn with a logarithmic scale.
* If you would like to have the Y axis drawn with a
* logarithmic axis, then setYLog(true) should be called before
* adding any data points.
* @param ylog If true, logarithmic axis is used.
*/
public synchronized void setYLog(boolean ylog) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_ylog = ylog;
}
 
/** Set the Y (vertical) range of the plot. If this is not done
* explicitly, then the range is computed automatically from data
* available when the plot is drawn. If min and max are identical,
* then the range is arbitrarily spread by 0.1.
* @param min The bottom extent of the range.
* @param max The top extent of the range.
*/
public synchronized void setYRange(double min, double max) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_yRangeGiven = true;
_ylowgiven = min;
_yhighgiven = max;
_setYRange(min, max);
}
 
/** Write the current data and plot configuration to the
* specified stream in PlotML syntax. PlotML is an XML
* extension for plot data. The written information is
* standalone, in that it includes the DTD (document type
* definition). This makes is somewhat verbose. To get
* smaller files, use the two argument version of write().
* The output is buffered, and is flushed and
* closed before exiting. Derived classes should override
* writeFormat and writeData rather than this method.
* @param out An output stream.
*/
public void write(OutputStream out) {
write(out, null);
}
 
/** Write the current data and plot configuration to the
* specified stream in PlotML syntax. PlotML is an XML
* scheme for plot data. The URL (relative or absolute) for the DTD is
* given as the second argument. If that argument is null,
* then the PlotML PUBLIC DTD is referenced, resulting in a file
* that can be read by a PlotML parser without any external file
* references, as long as that parser has local access to the DTD.
* The output is buffered, and is flushed and
* closed before exiting. Derived classes should override
* writeFormat and writeData rather than this method.
* @param out An output stream.
* @param dtd The reference (URL) for the DTD, or null to use the
* PUBLIC DTD.
*/
public synchronized void write(OutputStream out, String dtd) {
write(new OutputStreamWriter(out), dtd);
}
 
/** Write the current data and plot configuration to the
* specified stream in PlotML syntax. PlotML is an XML
* scheme for plot data. The URL (relative or absolute) for the DTD is
* given as the second argument. If that argument is null,
* then the PlotML PUBLIC DTD is referenced, resulting in a file
* that can be read by a PlotML parser without any external file
* references, as long as that parser has local access to the DTD.
* The output is buffered, and is flushed before exiting.
* @param out An output writer.
* @param dtd The reference (URL) for the DTD, or null to use the
* PUBLIC DTD.
*/
public synchronized void write(Writer out, String dtd) {
// Auto-flush is disabled.
PrintWriter output = new PrintWriter(new BufferedWriter(out), false);
 
if (dtd == null) {
output.println("<?xml version=\"1.0\" standalone=\"yes\"?>");
output
.println("<!DOCTYPE plot PUBLIC \"-//UC Berkeley//DTD PlotML 1//EN\"");
output
.println(" \"http://ptolemy.eecs.berkeley.edu/xml/dtd/PlotML_1.dtd\">");
} else {
output.println("<?xml version=\"1.0\" standalone=\"no\"?>");
output.println("<!DOCTYPE plot SYSTEM \"" + dtd + "\">");
}
 
output.println("<plot>");
output.println("<!-- Ptolemy plot, version " + PTPLOT_RELEASE
+ " , PlotML format. -->");
writeFormat(output);
writeData(output);
output.println("</plot>");
output.flush();
 
// NOTE: We used to close the stream, but if this is part
// of an exportMoML operation, that is the wrong thing to do.
// if (out != System.out) {
// output.close();
// }
}
 
/** Write plot data information to the specified output stream in PlotML.
* In this base class, there is no data to write, so this method
* returns without doing anything.
* @param output A buffered print writer.
*/
public synchronized void writeData(PrintWriter output) {
}
 
/** Write plot format information to the specified output stream in PlotML.
* Derived classes should override this method to first call
* the parent class method, then add whatever additional format
* information they wish to add to the stream.
* @param output A buffered print writer.
*/
public synchronized void writeFormat(PrintWriter output) {
// NOTE: If you modify this, you should change the _DTD variable
// accordingly.
if (_title != null) {
output.println("<title>" + _title + "</title>");
}
 
if (_xlabel != null) {
output.println("<xLabel>" + _xlabel + "</xLabel>");
}
 
if (_ylabel != null) {
output.println("<yLabel>" + _ylabel + "</yLabel>");
}
 
if (_xRangeGiven) {
output.println("<xRange min=\"" + _xlowgiven + "\" max=\""
+ _xhighgiven + "\"/>");
}
 
if (_yRangeGiven) {
output.println("<yRange min=\"" + _ylowgiven + "\" max=\""
+ _yhighgiven + "\"/>");
}
 
if ((_xticks != null) && (_xticks.size() > 0)) {
output.println("<xTicks>");
 
int last = _xticks.size() - 1;
 
for (int i = 0; i <= last; i++) {
output.println(" <tick label=\""
+ (String) _xticklabels.elementAt(i) + "\" position=\""
+ _xticks.elementAt(i) + "\"/>");
}
 
output.println("</xTicks>");
}
 
if ((_yticks != null) && (_yticks.size() > 0)) {
output.println("<yTicks>");
 
int last = _yticks.size() - 1;
 
for (int i = 0; i <= last; i++) {
output.println(" <tick label=\""
+ (String) _yticklabels.elementAt(i) + "\" position=\""
+ _yticks.elementAt(i) + "\"/>");
}
 
output.println("</yTicks>");
}
 
if (_xlog) {
output.println("<xLog/>");
}
 
if (_ylog) {
output.println("<yLog/>");
}
 
if (!_grid) {
output.println("<noGrid/>");
}
 
if (_wrap) {
output.println("<wrap/>");
}
 
if (!_usecolor) {
output.println("<noColor/>");
}
}
 
/** Write the current data and plot configuration to the
* specified stream in the old PtPlot syntax.
* The output is buffered, and is flushed and
* closed before exiting. Derived classes should override
* _writeOldSyntax() rather than this method.
* @param out An output stream.
* @deprecated
*/
public synchronized void writeOldSyntax(OutputStream out) {
// Auto-flush is disabled.
PrintWriter output = new PrintWriter(new BufferedOutputStream(out),
false);
_writeOldSyntax(output);
output.flush();
 
// Avoid closing standard out.
if (out != System.out) {
output.close();
}
}
 
/** Zoom in or out to the specified rectangle.
* This method calls repaint().
* @param lowx The low end of the new X range.
* @param lowy The low end of the new Y range.
* @param highx The high end of the new X range.
* @param highy The high end of the new Y range.
*/
public synchronized void zoom(double lowx, double lowy, double highx,
double highy) {
setXRange(lowx, highx);
setYRange(lowy, highy);
repaint();
}
 
///////////////////////////////////////////////////////////////////
//// public variables ////
public static final String PTPLOT_RELEASE = "5.7";
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
 
/** Draw the axes using the current range, label, and title information.
* If the second argument is true, clear the display before redrawing.
* This method is called by paintComponent(). To cause it to be called
* you would normally call repaint(), which eventually causes
* paintComponent() to be called.
* <p>
* Note that this is synchronized so that points are not added
* by other threads while the drawing is occurring. This method
* should be called only from the event dispatch thread, consistent
* with swing policy.
* @param graphics The graphics context.
* @param clearfirst If true, clear the plot before proceeding.
*/
protected synchronized void _drawPlot(Graphics graphics, boolean clearfirst) {
Rectangle bounds = getBounds();
_drawPlot(graphics, clearfirst, bounds);
}
 
/** Draw the axes using the current range, label, and title information,
* at the size of the specified rectangle.
* If the second argument is true, clear the display before redrawing.
* This method is called by paintComponent(). To cause it to be called
* you would normally call repaint(), which eventually causes
* paintComponent() to be called.
* <p>
* Note that this is synchronized so that points are not added
* by other threads while the drawing is occurring. This method
* should be called only from the event dispatch thread, consistent
* with swing policy.
* @param graphics The graphics context.
* @param clearfirst If true, clear the plot before proceeding.
* @param drawRect A specification of the size.
*/
protected synchronized void _drawPlot(Graphics graphics,
boolean clearfirst, Rectangle drawRect) {
// Ignore if there is no graphics object to draw on.
if (graphics == null) {
return;
}
 
graphics.setPaintMode();
 
/* NOTE: The following seems to be unnecessary with Swing...
if (clearfirst) {
// NOTE: calling clearRect() here permits the background
// color to show through, but it messes up printing.
// Printing results in black-on-black title and axis labels.
graphics.setColor(_background);
graphics.drawRect(0, 0, drawRect.width, drawRect.height);
graphics.setColor(Color.black);
}
*/
 
// If an error message has been set, display it and return.
if (_errorMsg != null) {
int fheight = _labelFontMetrics.getHeight() + 2;
int msgy = fheight;
graphics.setColor(Color.black);
 
for (int i = 0; i < _errorMsg.length; i++) {
graphics.drawString(_errorMsg[i], 10, msgy);
msgy += fheight;
System.err.println(_errorMsg[i]);
}
 
return;
}
 
// Make sure we have an x and y range
if (!_xRangeGiven) {
if (_xBottom > _xTop) {
// have nothing to go on.
_setXRange(0, 0);
} else {
_setXRange(_xBottom, _xTop);
}
}
 
if (!_yRangeGiven) {
if (_yBottom > _yTop) {
// have nothing to go on.
_setYRange(0, 0);
} else {
_setYRange(_yBottom, _yTop);
}
}
 
// If user specified a plot rectangle, compute
// a working plot rectangle which lies inside the
// drawRect at the user specified coordinates
Rectangle workingPlotRectangle = null;
 
if (_specifiedPlotRectangle != null) {
workingPlotRectangle = new Rectangle(Math.max(0,
_specifiedPlotRectangle.x), Math.max(0,
_specifiedPlotRectangle.y), Math.min(drawRect.width,
_specifiedPlotRectangle.width), Math.min(drawRect.height,
_specifiedPlotRectangle.height));
}
 
// Vertical space for title, if appropriate.
// NOTE: We assume a one-line title.
int titley = 0;
int titlefontheight = _titleFontMetrics.getHeight();
 
if (_title == null) {
// NOTE: If the _title is null, then set it to the empty
// string to solve the problem where the fill button overlaps
// the legend if there is no title. The fix here would
// be to modify the legend printing text so that it takes
// into account the case where there is no title by offsetting
// just enough for the button.
_title = "";
}
 
if ((_title != null) || (_yExp != 0)) {
titley = titlefontheight + _topPadding;
}
 
// Number of vertical tick marks depends on the height of the font
// for labeling ticks and the height of the window.
Font previousFont = graphics.getFont();
graphics.setFont(_labelFont);
graphics.setColor(_foreground); // foreground color not set here --Rob.
 
int labelheight = _labelFontMetrics.getHeight();
int halflabelheight = labelheight / 2;
 
// Draw scaling annotation for x axis.
// NOTE: 5 pixel padding on bottom.
int ySPos = drawRect.height - 5;
int xSPos = drawRect.width - _rightPadding;
 
if (_xlog) {
_xExp = (int) Math.floor(_xtickMin);
}
 
if ((_xExp != 0) && (_xticks == null)) {
String superscript = Integer.toString(_xExp);
xSPos -= _superscriptFontMetrics.stringWidth(superscript);
graphics.setFont(_superscriptFont);
 
if (!_xlog) {
graphics
.drawString(superscript, xSPos, ySPos - halflabelheight);
xSPos -= _labelFontMetrics.stringWidth("x10");
graphics.setFont(_labelFont);
graphics.drawString("x10", xSPos, ySPos);
}
 
// NOTE: 5 pixel padding on bottom
_bottomPadding = ((3 * labelheight) / 2) + 5;
}
 
// NOTE: 5 pixel padding on the bottom.
if ((_xlabel != null) && (_bottomPadding < (labelheight + 5))) {
_bottomPadding = labelheight + 5;
}
 
// Compute the space needed around the plot, starting with vertical.
// NOTE: padding of 5 pixels below title.
if (workingPlotRectangle != null) {
_uly = workingPlotRectangle.y;
} else {
_uly = titley + 5;
}
 
// NOTE: 3 pixels above bottom labels.
if (workingPlotRectangle != null) {
_lry = workingPlotRectangle.y + workingPlotRectangle.height;
} else {
_lry = drawRect.height - labelheight - _bottomPadding - 3;
}
 
int height = _lry - _uly;
_yscale = height / (_yMax - _yMin);
_ytickscale = height / (_ytickMax - _ytickMin);
 
////////////////// vertical axis
// Number of y tick marks.
// NOTE: subjective spacing factor.
int ny = 2 + (height / (labelheight + 10));
 
// Compute y increment.
double yStep = _roundUp((_ytickMax - _ytickMin) / ny);
 
// Compute y starting point so it is a multiple of yStep.
double yStart = yStep * Math.ceil(_ytickMin / yStep);
 
// NOTE: Following disables first tick. Not a good idea?
// if (yStart == _ytickMin) yStart += yStep;
// Define the strings that will label the y axis.
// Meanwhile, find the width of the widest label.
// The labels are quantized so that they don't have excess resolution.
int widesty = 0;
 
// These do not get used unless ticks are automatic, but the
// compiler is not smart enough to allow us to reference them
// in two distinct conditional clauses unless they are
// allocated outside the clauses.
String[] ylabels = new String[ny];
int[] ylabwidth = new int[ny];
 
int ind = 0;
 
if (_yticks == null) {
Vector ygrid = null;
 
if (_ylog) {
ygrid = _gridInit(yStart, yStep, true, null);
}
 
// automatic ticks
// First, figure out how many digits after the decimal point
// will be used.
int numfracdigits = _numFracDigits(yStep);
 
// NOTE: Test cases kept in case they are needed again.
// System.out.println("0.1 with 3 digits: " + _formatNum(0.1, 3));
// System.out.println("0.0995 with 3 digits: " +
// _formatNum(0.0995, 3));
// System.out.println("0.9995 with 3 digits: " +
// _formatNum(0.9995, 3));
// System.out.println("1.9995 with 0 digits: " +
// _formatNum(1.9995, 0));
// System.out.println("1 with 3 digits: " + _formatNum(1, 3));
// System.out.println("10 with 0 digits: " + _formatNum(10, 0));
// System.out.println("997 with 3 digits: " + _formatNum(997, 3));
// System.out.println("0.005 needs: " + _numFracDigits(0.005));
// System.out.println("1 needs: " + _numFracDigits(1));
// System.out.println("999 needs: " + _numFracDigits(999));
// System.out.println("999.0001 needs: "+_numFracDigits(999.0001));
// System.out.println("0.005 integer digits: " +
// _numIntDigits(0.005));
// System.out.println("1 integer digits: " + _numIntDigits(1));
// System.out.println("999 integer digits: " + _numIntDigits(999));
// System.out.println("-999.0001 integer digits: " +
// _numIntDigits(999.0001));
double yTmpStart = yStart;
 
if (_ylog) {
yTmpStart = _gridStep(ygrid, yStart, yStep, _ylog);
}
 
for (double ypos = yTmpStart; ypos <= _ytickMax; ypos = _gridStep(
ygrid, ypos, yStep, _ylog)) {
// Prevent out of bounds exceptions
if (ind >= ny) {
break;
}
 
String yticklabel;
 
if (_ylog) {
yticklabel = _formatLogNum(ypos, numfracdigits);
} else {
yticklabel = _formatNum(ypos, numfracdigits);
}
 
ylabels[ind] = yticklabel;
 
int lw = _labelFontMetrics.stringWidth(yticklabel);
ylabwidth[ind++] = lw;
 
if (lw > widesty) {
widesty = lw;
}
}
} else {
// explicitly specified ticks
Enumeration nl = _yticklabels.elements();
 
while (nl.hasMoreElements()) {
String label = (String) nl.nextElement();
int lw = _labelFontMetrics.stringWidth(label);
 
if (lw > widesty) {
widesty = lw;
}
}
}
 
// Next we do the horizontal spacing.
if (workingPlotRectangle != null) {
_ulx = workingPlotRectangle.x;
} else {
if (_ylabel != null) {
_ulx = widesty + _labelFontMetrics.stringWidth("W")
+ _leftPadding;
} else {
_ulx = widesty + _leftPadding;
}
}
 
int legendwidth = _drawLegend(graphics, drawRect.width - _rightPadding,
_uly);
 
if (workingPlotRectangle != null) {
_lrx = workingPlotRectangle.x + workingPlotRectangle.width;
} else {
_lrx = drawRect.width - legendwidth - _rightPadding;
}
 
int width = _lrx - _ulx;
_xscale = width / (_xMax - _xMin);
 
_xtickscale = width / (_xtickMax - _xtickMin);
 
// Background for the plotting rectangle.
// Always use a white background because the dataset colors
// were designed for a white background.
graphics.setColor(Color.white);
graphics.fillRect(_ulx, _uly, width, height);
 
graphics.setColor(_foreground);
graphics.drawRect(_ulx, _uly, width, height);
 
// NOTE: subjective tick length.
int tickLength = 5;
int xCoord1 = _ulx + tickLength;
int xCoord2 = _lrx - tickLength;
 
if (_yticks == null) {
// auto-ticks
Vector ygrid = null;
double yTmpStart = yStart;
 
if (_ylog) {
ygrid = _gridInit(yStart, yStep, true, null);
yTmpStart = _gridStep(ygrid, yStart, yStep, _ylog);
ny = ind;
}
 
ind = 0;
 
// Set to false if we don't need the exponent
boolean needExponent = _ylog;
 
for (double ypos = yTmpStart; ypos <= _ytickMax; ypos = _gridStep(
ygrid, ypos, yStep, _ylog)) {
// Prevent out of bounds exceptions
if (ind >= ny) {
break;
}
 
int yCoord1 = _lry - (int) ((ypos - _ytickMin) * _ytickscale);
 
// The lowest label is shifted up slightly to avoid
// colliding with x labels.
int offset = 0;
 
if ((ind > 0) && !_ylog) {
offset = halflabelheight;
}
 
graphics.drawLine(_ulx, yCoord1, xCoord1, yCoord1);
graphics.drawLine(_lrx, yCoord1, xCoord2, yCoord1);
 
if (_grid && (yCoord1 != _uly) && (yCoord1 != _lry)) {
graphics.setColor(Color.lightGray);
graphics.drawLine(xCoord1, yCoord1, xCoord2, yCoord1);
graphics.setColor(_foreground);
}
 
// Check to see if any of the labels printed contain
// the exponent. If we don't see an exponent, then print it.
if (_ylog && (ylabels[ind].indexOf('e') != -1)) {
needExponent = false;
}
 
// NOTE: 4 pixel spacing between axis and labels.
graphics.drawString(ylabels[ind], _ulx - ylabwidth[ind++] - 4,
yCoord1 + offset);
}
 
if (_ylog) {
// Draw in grid lines that don't have labels.
Vector unlabeledgrid = _gridInit(yStart, yStep, false, ygrid);
 
if (unlabeledgrid.size() > 0) {
// If the step is greater than 1, clamp it to 1 so that
// we draw the unlabeled grid lines for each
//integer interval.
double tmpStep = (yStep > 1.0) ? 1.0 : yStep;
 
for (double ypos = _gridStep(unlabeledgrid, yStart,
tmpStep, _ylog); ypos <= _ytickMax; ypos = _gridStep(
unlabeledgrid, ypos, tmpStep, _ylog)) {
int yCoord1 = _lry
- (int) ((ypos - _ytickMin) * _ytickscale);
 
if (_grid && (yCoord1 != _uly) && (yCoord1 != _lry)) {
graphics.setColor(Color.lightGray);
graphics.drawLine(_ulx + 1, yCoord1, _lrx - 1,
yCoord1);
graphics.setColor(_foreground);
}
}
}
 
if (needExponent) {
// We zoomed in, so we need the exponent
_yExp = (int) Math.floor(yTmpStart);
} else {
_yExp = 0;
}
}
 
// Draw scaling annotation for y axis.
if (_yExp != 0) {
graphics.drawString("x10", 2, titley);
graphics.setFont(_superscriptFont);
graphics.drawString(Integer.toString(_yExp), _labelFontMetrics
.stringWidth("x10") + 2, titley - halflabelheight);
graphics.setFont(_labelFont);
}
} else {
// ticks have been explicitly specified
Enumeration nt = _yticks.elements();
Enumeration nl = _yticklabels.elements();
 
while (nl.hasMoreElements()) {
String label = (String) nl.nextElement();
double ypos = ((Double) (nt.nextElement())).doubleValue();
 
if ((ypos > _yMax) || (ypos < _yMin)) {
continue;
}
 
int yCoord1 = _lry - (int) ((ypos - _yMin) * _yscale);
int offset = 0;
 
if (ypos < (_lry - labelheight)) {
offset = halflabelheight;
}
 
graphics.drawLine(_ulx, yCoord1, xCoord1, yCoord1);
graphics.drawLine(_lrx, yCoord1, xCoord2, yCoord1);
 
if (_grid && (yCoord1 != _uly) && (yCoord1 != _lry)) {
graphics.setColor(Color.lightGray);
graphics.drawLine(xCoord1, yCoord1, xCoord2, yCoord1);
graphics.setColor(_foreground);
}
 
// NOTE: 3 pixel spacing between axis and labels.
graphics.drawString(label, _ulx
- _labelFontMetrics.stringWidth(label) - 3, yCoord1
+ offset);
}
}
 
//////////////////// horizontal axis
int yCoord1 = _uly + tickLength;
int yCoord2 = _lry - tickLength;
int charwidth = _labelFontMetrics.stringWidth("8");
 
if (_xticks == null) {
// auto-ticks
// Number of x tick marks.
// Need to start with a guess and converge on a solution here.
int nx = 10;
double xStep = 0.0;
int numfracdigits = 0;
 
if (_xlog) {
// X axes log labels will be at most 6 chars: -1E-02
nx = 2 + (width / ((charwidth * 6) + 10));
} else {
// Limit to 10 iterations
int count = 0;
 
while (count++ <= 10) {
xStep = _roundUp((_xtickMax - _xtickMin) / nx);
 
// Compute the width of a label for this xStep
numfracdigits = _numFracDigits(xStep);
 
// Number of integer digits is the maximum of two endpoints
int intdigits = _numIntDigits(_xtickMax);
int inttemp = _numIntDigits(_xtickMin);
 
if (intdigits < inttemp) {
intdigits = inttemp;
}
 
// Allow two extra digits (decimal point and sign).
int maxlabelwidth = charwidth
* (numfracdigits + 2 + intdigits);
 
// Compute new estimate of number of ticks.
int savenx = nx;
 
// NOTE: 10 additional pixels between labels.
// NOTE: Try to ensure at least two tick marks.
nx = 2 + (width / (maxlabelwidth + 10));
 
if (((nx - savenx) <= 1) || ((savenx - nx) <= 1)) {
break;
}
}
}
 
xStep = _roundUp((_xtickMax - _xtickMin) / nx);
numfracdigits = _numFracDigits(xStep);
 
// Compute x starting point so it is a multiple of xStep.
double xStart = xStep * Math.ceil(_xtickMin / xStep);
 
// NOTE: Following disables first tick. Not a good idea?
// if (xStart == _xMin) xStart += xStep;
Vector xgrid = null;
double xTmpStart = xStart;
 
if (_xlog) {
xgrid = _gridInit(xStart, xStep, true, null);
 
//xgrid = _gridInit(xStart, xStep);
xTmpStart = _gridRoundUp(xgrid, xStart);
}
 
// Set to false if we don't need the exponent
boolean needExponent = _xlog;
 
// Label the x axis. The labels are quantized so that
// they don't have excess resolution.
for (double xpos = xTmpStart; xpos <= _xtickMax; xpos = _gridStep(
xgrid, xpos, xStep, _xlog)) {
String xticklabel;
 
if (_xlog) {
xticklabel = _formatLogNum(xpos, numfracdigits);
 
if (xticklabel.indexOf('e') != -1) {
needExponent = false;
}
} else {
xticklabel = _formatNum(xpos, numfracdigits);
}
 
xCoord1 = _ulx + (int) ((xpos - _xtickMin) * _xtickscale);
graphics.drawLine(xCoord1, _uly, xCoord1, yCoord1);
graphics.drawLine(xCoord1, _lry, xCoord1, yCoord2);
 
if (_grid && (xCoord1 != _ulx) && (xCoord1 != _lrx)) {
graphics.setColor(Color.lightGray);
graphics.drawLine(xCoord1, yCoord1, xCoord1, yCoord2);
graphics.setColor(_foreground);
}
 
int labxpos = xCoord1
- (_labelFontMetrics.stringWidth(xticklabel) / 2);
 
// NOTE: 3 pixel spacing between axis and labels.
graphics
.drawString(xticklabel, labxpos, _lry + 3 + labelheight);
}
 
if (_xlog) {
// Draw in grid lines that don't have labels.
// If the step is greater than 1, clamp it to 1 so that
// we draw the unlabeled grid lines for each
// integer interval.
double tmpStep = (xStep > 1.0) ? 1.0 : xStep;
 
// Recalculate the start using the new step.
xTmpStart = tmpStep * Math.ceil(_xtickMin / tmpStep);
 
Vector unlabeledgrid = _gridInit(xTmpStart, tmpStep, false,
xgrid);
 
if (unlabeledgrid.size() > 0) {
for (double xpos = _gridStep(unlabeledgrid, xTmpStart,
tmpStep, _xlog); xpos <= _xtickMax; xpos = _gridStep(
unlabeledgrid, xpos, tmpStep, _xlog)) {
xCoord1 = _ulx
+ (int) ((xpos - _xtickMin) * _xtickscale);
 
if (_grid && (xCoord1 != _ulx) && (xCoord1 != _lrx)) {
graphics.setColor(Color.lightGray);
graphics.drawLine(xCoord1, _uly + 1, xCoord1,
_lry - 1);
graphics.setColor(_foreground);
}
}
}
 
if (needExponent) {
_xExp = (int) Math.floor(xTmpStart);
graphics.setFont(_superscriptFont);
graphics.drawString(Integer.toString(_xExp), xSPos, ySPos
- halflabelheight);
xSPos -= _labelFontMetrics.stringWidth("x10");
graphics.setFont(_labelFont);
graphics.drawString("x10", xSPos, ySPos);
} else {
_xExp = 0;
}
}
} else {
// ticks have been explicitly specified
Enumeration nt = _xticks.elements();
Enumeration nl = _xticklabels.elements();
 
// Code contributed by Jun Wu (jwu@inin.com.au)
double preLength = 0.0;
 
while (nl.hasMoreElements()) {
String label = (String) nl.nextElement();
double xpos = ((Double) (nt.nextElement())).doubleValue();
 
// If xpos is out of range, ignore.
if ((xpos > _xMax) || (xpos < _xMin)) {
continue;
}
 
// Find the center position of the label.
xCoord1 = _ulx + (int) ((xpos - _xMin) * _xscale);
 
// Find the start position of x label.
int labxpos = xCoord1
- (_labelFontMetrics.stringWidth(label) / 2);
 
// If the labels are not overlapped, proceed.
if (labxpos > preLength) {
// calculate the length of the label
preLength = xCoord1
+ (_labelFontMetrics.stringWidth(label) / 2) + 10;
 
// Draw the label.
// NOTE: 3 pixel spacing between axis and labels.
graphics.drawString(label, labxpos, _lry + 3 + labelheight);
 
// Draw the label mark on the axis
graphics.drawLine(xCoord1, _uly, xCoord1, yCoord1);
graphics.drawLine(xCoord1, _lry, xCoord1, yCoord2);
 
// Draw the grid line
if (_grid && (xCoord1 != _ulx) && (xCoord1 != _lrx)) {
graphics.setColor(Color.lightGray);
graphics.drawLine(xCoord1, yCoord1, xCoord1, yCoord2);
graphics.setColor(_foreground);
}
}
}
}
 
//////////////////// Draw title and axis labels now.
// Center the title and X label over the plotting region, not
// the window.
graphics.setColor(_foreground);
 
if (_title != null) {
graphics.setFont(_titleFont);
 
int titlex = _ulx
+ ((width - _titleFontMetrics.stringWidth(_title)) / 2);
graphics.drawString(_title, titlex, titley);
}
 
graphics.setFont(_labelFont);
 
if (_xlabel != null) {
int labelx = _ulx
+ ((width - _labelFontMetrics.stringWidth(_xlabel)) / 2);
graphics.drawString(_xlabel, labelx, ySPos);
}
 
int charcenter = 2 + (_labelFontMetrics.stringWidth("W") / 2);
 
if (_ylabel != null) {
int yl = _ylabel.length();
 
if (graphics instanceof Graphics2D) {
int starty = (_uly + ((_lry - _uly) / 2) + (_labelFontMetrics
.stringWidth(_ylabel) / 2))
- charwidth;
Graphics2D g2d = (Graphics2D) graphics;
 
// NOTE: Fudge factor so label doesn't touch axis labels.
int startx = (charcenter + halflabelheight) - 2;
g2d.rotate(Math.toRadians(-90), startx, starty);
g2d.drawString(_ylabel, startx, starty);
g2d.rotate(Math.toRadians(90), startx, starty);
} else {
// Not graphics 2D, no support for rotation.
// Vertical label is fairly complex to draw.
int starty = (_uly + ((_lry - _uly) / 2))
- (yl * halflabelheight) + labelheight;
 
for (int i = 0; i < yl; i++) {
String nchar = _ylabel.substring(i, i + 1);
int cwidth = _labelFontMetrics.stringWidth(nchar);
graphics.drawString(nchar, charcenter - (cwidth / 2),
starty);
starty += labelheight;
}
}
}
 
graphics.setFont(previousFont);
}
 
/** Put a mark corresponding to the specified dataset at the
* specified x and y position. The mark is drawn in the
* current color. In this base class, a point is a
* filled rectangle 6 pixels across. Note that marks greater than
* about 6 pixels in size will not look very good since they will
* overlap axis labels and may not fit well in the legend. The
* <i>clip</i> argument, if <code>true</code>, states
* that the point should not be drawn if
* it is out of range.
*
* Note that this method is not synchronized, so the caller should be.
* Moreover this method should always be called from the event thread
* when being used to write to the screen.
*
* @param graphics The graphics context.
* @param dataset The index of the data set.
* @param xpos The X position.
* @param ypos The Y position.
* @param clip If true, do not draw if out of range.
*/
protected void _drawPoint(Graphics graphics, int dataset, long xpos,
long ypos, boolean clip) {
// Ignore if there is no graphics object to draw on.
if (graphics == null) {
return;
}
 
boolean pointinside = (ypos <= _lry) && (ypos >= _uly)
&& (xpos <= _lrx) && (xpos >= _ulx);
 
if (!pointinside && clip) {
return;
}
 
graphics.fillRect((int) xpos - 6, (int) ypos - 6, 6, 6);
}
 
/** Display basic information in its own window.
*/
protected void _help() {
String message = "Ptolemy plot package\n"
+ "By: Edward A. Lee\n"
+ "and Christopher Brooks\n"
+ "Version "
+ PTPLOT_RELEASE
+ ", Build: $Id: PlotBox.java,v 1.283.4.3 2008/04/01 01:19:02 cxh Exp $\n\n"
+ "Key bindings:\n"
+ " Cntrl-c: copy plot to clipboard (EPS format), if permitted\n"
+ " D: dump plot data to standard out\n"
+ " E: export plot to standard out (EPS format)\n"
+ " F: fill plot\n"
+ " H or ?: print help message (this message)\n"
+ " Cntrl-D or Q: quit\n" + "For more information, see\n"
+ "http://ptolemy.eecs.berkeley.edu/java/ptplot\n";
JOptionPane.showMessageDialog(this, message,
"Ptolemy Plot Help Window", JOptionPane.INFORMATION_MESSAGE);
}
 
/** Parse a line that gives plotting information. In this base
* class, only lines pertaining to the title and labels are processed.
* Everything else is ignored. Return true if the line is recognized.
* It is not synchronized, so its caller should be.
* @param line A line of text.
*/
protected boolean _parseLine(String line) {
// If you modify this method, you should also modify write()
// We convert the line to lower case so that the command
// names are case insensitive.
String lcLine = line.toLowerCase();
 
if (lcLine.startsWith("#")) {
// comment character
return true;
} else if (lcLine.startsWith("titletext:")) {
setTitle((line.substring(10)).trim());
return true;
} else if (lcLine.startsWith("title:")) {
// Tolerate alternative tag.
setTitle((line.substring(6)).trim());
return true;
} else if (lcLine.startsWith("xlabel:")) {
setXLabel((line.substring(7)).trim());
return true;
} else if (lcLine.startsWith("ylabel:")) {
setYLabel((line.substring(7)).trim());
return true;
} else if (lcLine.startsWith("xrange:")) {
int comma = line.indexOf(",", 7);
 
if (comma > 0) {
String min = (line.substring(7, comma)).trim();
String max = (line.substring(comma + 1)).trim();
 
try {
Double dmin = Double.valueOf(min);
Double dmax = Double.valueOf(max);
setXRange(dmin.doubleValue(), dmax.doubleValue());
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
}
 
return true;
} else if (lcLine.startsWith("yrange:")) {
int comma = line.indexOf(",", 7);
 
if (comma > 0) {
String min = (line.substring(7, comma)).trim();
String max = (line.substring(comma + 1)).trim();
 
try {
Double dmin = Double.valueOf(min);
Double dmax = Double.valueOf(max);
setYRange(dmin.doubleValue(), dmax.doubleValue());
} catch (NumberFormatException e) {
// ignore if format is bogus.
}
}
 
return true;
} else if (lcLine.startsWith("xticks:")) {
// example:
// XTicks "label" 0, "label" 1, "label" 3
_parsePairs(line.substring(7), true);
return true;
} else if (lcLine.startsWith("yticks:")) {
// example:
// YTicks "label" 0, "label" 1, "label" 3
_parsePairs(line.substring(7), false);
return true;
} else if (lcLine.startsWith("xlog:")) {
if (lcLine.indexOf("off", 5) >= 0) {
_xlog = false;
} else {
_xlog = true;
}
 
return true;
} else if (lcLine.startsWith("ylog:")) {
if (lcLine.indexOf("off", 5) >= 0) {
_ylog = false;
} else {
_ylog = true;
}
 
return true;
} else if (lcLine.startsWith("grid:")) {
if (lcLine.indexOf("off", 5) >= 0) {
_grid = false;
} else {
_grid = true;
}
 
return true;
} else if (lcLine.startsWith("wrap:")) {
if (lcLine.indexOf("off", 5) >= 0) {
_wrap = false;
} else {
_wrap = true;
}
 
return true;
} else if (lcLine.startsWith("color:")) {
if (lcLine.indexOf("off", 6) >= 0) {
_usecolor = false;
} else {
_usecolor = true;
}
 
return true;
}
 
return false;
}
 
/** Set the visibility of the Fill button.
* This is deprecated. Use setButtons().
* @deprecated
*/
protected void _setButtonsVisibility(boolean vis) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_printButton.setVisible(vis);
_fillButton.setVisible(vis);
_formatButton.setVisible(vis);
_resetButton.setVisible(vis);
}
 
/** Set the padding multiple.
* The plot rectangle can be "padded" in each direction -x, +x, -y, and
* +y. If the padding is set to 0.05 (and the padding is used), then
* there is 10% more length on each axis than set by the setXRange() and
* setYRange() methods, 5% in each direction.
* @param padding The padding multiple.
*/
protected void _setPadding(double padding) {
// Changing legend means we need to repaint the offscreen buffer.
_plotImage = null;
 
_padding = padding;
}
 
/** Write plot information to the specified output stream in the
* old PtPlot syntax.
* Derived classes should override this method to first call
* the parent class method, then add whatever additional information
* they wish to add to the stream.
* It is not synchronized, so its caller should be.
* @param output A buffered print writer.
* @deprecated
*/
protected void _writeOldSyntax(PrintWriter output) {
output.println("# Ptolemy plot, version 2.0");
 
if (_title != null) {
output.println("TitleText: " + _title);
}
 
if (_xlabel != null) {
output.println("XLabel: " + _xlabel);
}
 
if (_ylabel != null) {
output.println("YLabel: " + _ylabel);
}
 
if (_xRangeGiven) {
output.println("XRange: " + _xlowgiven + ", " + _xhighgiven);
}
 
if (_yRangeGiven) {
output.println("YRange: " + _ylowgiven + ", " + _yhighgiven);
}
 
if ((_xticks != null) && (_xticks.size() > 0)) {
output.print("XTicks: ");
 
int last = _xticks.size() - 1;
 
for (int i = 0; i < last; i++) {
output.print("\"" + (String) _xticklabels.elementAt(i) + "\" "
+ _xticks.elementAt(i) + ", ");
}
 
output.println("\"" + (String) _xticklabels.elementAt(last) + "\" "
+ _xticks.elementAt(last));
}
 
if ((_yticks != null) && (_yticks.size() > 0)) {
output.print("YTicks: ");
 
int last = _yticks.size() - 1;
 
for (int i = 0; i < last; i++) {
output.print("\"" + (String) _yticklabels.elementAt(i) + "\" "
+ _yticks.elementAt(i) + ", ");
}
 
output.println("\"" + (String) _yticklabels.elementAt(last) + "\" "
+ _yticks.elementAt(last));
}
 
if (_xlog) {
output.println("XLog: on");
}
 
if (_ylog) {
output.println("YLog: on");
}
 
if (!_grid) {
output.println("Grid: off");
}
 
if (_wrap) {
output.println("Wrap: on");
}
 
if (!_usecolor) {
output.println("Color: off");
}
}
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
// The range of the data to be plotted.
protected transient double _yMax = 0;
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
// The range of the data to be plotted.
protected transient double _yMin = 0;
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
// The range of the data to be plotted.
protected transient double _xMax = 0;
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
// The range of the data to be plotted.
protected transient double _xMin = 0;
 
/** The factor we pad by so that we don't plot points on the axes.
*/
protected double _padding = 0.05;
 
// Whether the ranges have been given.
protected transient boolean _xRangeGiven = false;
 
protected transient boolean _yRangeGiven = false;
 
protected transient boolean _rangesGivenByZooming = false;
 
/** @serial The given X and Y ranges.
* If they have been given the top and bottom of the x and y ranges.
* This is different from _xMin and _xMax, which actually represent
* the range of data that is plotted. This represents the range
* specified (which may be different due to zooming).
*/
protected double _xlowgiven;
 
/** @serial The given X and Y ranges.
* If they have been given the top and bottom of the x and y ranges.
* This is different from _xMin and _xMax, which actually represent
* the range of data that is plotted. This represents the range
* specified (which may be different due to zooming).
*/
protected double _xhighgiven;
 
/** @serial The given X and Y ranges.
* If they have been given the top and bottom of the x and y ranges.
* This is different from _xMin and _xMax, which actually represent
* the range of data that is plotted. This represents the range
* specified (which may be different due to zooming).
*/
protected double _ylowgiven;
 
/** @serial The given X and Y ranges.
* If they have been given the top and bottom of the x and y ranges.
* This is different from _xMin and _xMax, which actually represent
* the range of data that is plotted. This represents the range
* specified (which may be different due to zooming).
*/
protected double _yhighgiven;
 
/** @serial The minimum X value registered so for, for auto ranging. */
protected double _xBottom = Double.MAX_VALUE;
 
/** @serial The maximum X value registered so for, for auto ranging. */
protected double _xTop = -Double.MAX_VALUE;
 
/** @serial The minimum Y value registered so for, for auto ranging. */
protected double _yBottom = Double.MAX_VALUE;
 
/** @serial The maximum Y value registered so for, for auto ranging. */
protected double _yTop = -Double.MAX_VALUE;
 
/** @serial Whether to draw the axes using a logarithmic scale. */
protected boolean _xlog = false;
 
/** @serial Whether to draw the axes using a logarithmic scale. */
protected boolean _ylog = false;
 
// For use in calculating log base 10. A log times this is a log base 10.
protected static final double _LOG10SCALE = 1 / Math.log(10);
 
/** @serial Whether to draw a background grid. */
protected boolean _grid = true;
 
/** @serial Whether to wrap the X axis. */
protected boolean _wrap = false;
 
/** @serial The high range of the X axis for wrapping. */
protected double _wrapHigh;
 
/** @serial The low range of the X axis for wrapping. */
protected double _wrapLow;
 
/** @serial Color of the background, settable from HTML. */
protected Color _background = Color.white;
 
/** @serial Color of the foreground, settable from HTML. */
protected Color _foreground = Color.black;
 
/** @serial Top padding.
* Derived classes can increment these to make space around the plot.
*/
protected int _topPadding = 10;
 
/** @serial Bottom padding.
* Derived classes can increment these to make space around the plot.
*/
protected int _bottomPadding = 5;
 
/** @serial Right padding.
* Derived classes can increment these to make space around the plot.
*/
protected int _rightPadding = 10;
 
/** @serial Left padding.
* Derived classes can increment these to make space around the plot.
*/
protected int _leftPadding = 10;
 
// The naming convention is: "_ulx" = "upper left x", where "x" is
// the horizontal dimension.
 
/** The x value of the upper left corner of the plot rectangle in pixels. */
protected int _ulx = 1;
 
/** The y value of the upper left corner of the plot rectangle in pixels. */
protected int _uly = 1;
 
/** The x value of the lower right corner of
* the plot rectangle in pixels. */
protected int _lrx = 100;
 
/** The y value of the lower right corner of
* the plot rectangle in pixels. */
protected int _lry = 100;
 
/** User specified plot rectangle, null if none specified.
* @see #setPlotRectangle(Rectangle)
*/
protected Rectangle _specifiedPlotRectangle = null;
 
/** Scaling used for the vertical axis in plotting points.
* The units are pixels/unit, where unit is the units of the Y axis.
*/
protected double _yscale = 1.0;
 
/** Scaling used for the horizontal axis in plotting points.
* The units are pixels/unit, where unit is the units of the X axis.
*/
protected double _xscale = 1.0;
 
/** @serial Indicator whether to use _colors. */
protected boolean _usecolor = true;
 
// Default _colors, by data set.
// There are 11 colors so that combined with the
// 10 marks of the Plot class, we can distinguish 110
// distinct data sets.
static protected Color[] _colors = { new Color(0xff0000), // red
new Color(0x0000ff), // blue
new Color(0x00aaaa), // cyan-ish
new Color(0x000000), // black
new Color(0xffa500), // orange
new Color(0x53868b), // cadetblue4
new Color(0xff7f50), // coral
new Color(0x45ab1f), // dark green-ish
new Color(0x90422d), // sienna-ish
new Color(0xa0a0a0), // grey-ish
new Color(0x14ff14), // green-ish
new Color(0xffff00), // yellow
};
 
/** @serial Width and height of component in pixels. */
protected int _width = 500;
 
/** @serial Width and height of component in pixels. */
protected int _height = 300;
 
/** @serial Width and height of component in pixels. */
protected int _preferredWidth = 500;
 
/** @serial Width and height of component in pixels. */
protected int _preferredHeight = 300;
 
/** @serial Indicator that size has been set. */
 
//protected boolean _sizeHasBeenSet = false;
/** @serial The document base we use to find the _filespec.
* NOTE: Use of this variable is deprecated. But it is made available
* to derived classes for backward compatibility.
* FIXME: Sun's appletviewer gives an exception if this is protected.
* Why?? So we make it temporarily public.
*/
public URL _documentBase = null;
 
///////////////////////////////////////////////////////////////////
//// private methods ////
 
/*
* Draw the legend in the upper right corner and return the width
* (in pixels) used up. The arguments give the upper right corner
* of the region where the legend should be placed.
*/
private int _drawLegend(Graphics graphics, int urx, int ury) {
// Ignore if there is no graphics object to draw on.
if (graphics == null) {
return 0;
}
 
// FIXME: consolidate all these for efficiency
Font previousFont = graphics.getFont();
graphics.setFont(_labelFont);
 
int spacing = _labelFontMetrics.getHeight();
 
Enumeration v = _legendStrings.elements();
Enumeration i = _legendDatasets.elements();
int ypos = ury + spacing;
int maxwidth = 0;
 
while (v.hasMoreElements()) {
String legend = (String) v.nextElement();
 
// NOTE: relies on _legendDatasets having the same num. of entries.
int dataset = ((Integer) i.nextElement()).intValue();
 
if (dataset >= 0) {
if (_usecolor) {
// Points are only distinguished up to the number of colors
int color = dataset % _colors.length;
graphics.setColor(_colors[color]);
}
 
_drawPoint(graphics, dataset, urx - 3, ypos - 3, false);
 
graphics.setColor(_foreground);
 
int width = _labelFontMetrics.stringWidth(legend);
 
if (width > maxwidth) {
maxwidth = width;
}
 
graphics.drawString(legend, urx - 15 - width, ypos);
ypos += spacing;
}
}
 
graphics.setFont(previousFont);
return 22 + maxwidth; // NOTE: subjective spacing parameter.
}
 
// Execute all actions pending on the deferred action list.
// The list is cleared and the _actionsDeferred variable is set
// to false, even if one of the deferred actions fails.
// This method should only be invoked in the event dispatch thread.
// It is synchronized, so the integrity of the deferred actions list
// is ensured, since modifications to that list occur only in other
// synchronized methods.
private synchronized void _executeDeferredActions() {
try {
Iterator actions = _deferredActions.iterator();
 
while (actions.hasNext()) {
Runnable action = (Runnable) actions.next();
action.run();
}
} finally {
_actionsDeferred = false;
_deferredActions.clear();
}
}
 
/*
* Return the number as a String for use as a label on a
* logarithmic axis.
* Since this is a log plot, number passed in will not have too many
* digits to cause problems.
* If the number is an integer, then we print 1e<num>.
* If the number is not an integer, then print only the fractional
* components.
*/
private String _formatLogNum(double num, int numfracdigits) {
String results;
int exponent = (int) num;
 
// Determine the exponent, prepending 0 or -0 if necessary.
if ((exponent >= 0) && (exponent < 10)) {
//results = "0" + exponent;
results = "" + exponent;
} else {
if ((exponent < 0) && (exponent > -10)) {
//results = "-0" + (-exponent);
results = "-" + (-exponent);
} else {
results = Integer.toString(exponent);
}
}
// Handle the mantissa.
if (num >= 0.0) {
if ((num - (int) (num)) < 0.001) {
results = "1e" + results;
} else {
results = _formatNum(Math.pow(10.0, (num - (int) num)),
numfracdigits);
}
} else {
if ((-num - (int) (-num)) < 0.001) {
results = "1e" + results;
} else {
results = _formatNum(Math.pow(10.0, (num - (int) num)) * 10,
numfracdigits);
}
}
// jm.evers
return toExponential(results);
//return results;
}
 
/*
* Return a string for displaying the specified number
* using the specified number of digits after the decimal point.
* NOTE: java.text.NumberFormat in Netscape 4.61 has a bug
* where it fails to round numbers instead it truncates them.
* As a result, we don't use java.text.NumberFormat, instead
* We use the method from Ptplot1.3
*/
private String _formatNum(double num, int numfracdigits) {
// When java.text.NumberFormat works under Netscape,
// uncomment the next block of code and remove
// the code after it.
// Ptplot developers at UCB can access a test case at:
// http://ptolemy.eecs.berkeley.edu/~ptII/ptIItree/ptolemy/plot/adm/trunc/trunc-jdk11.html
// The plot will show two 0.7 values on the x axis if the bug
// continues to exist.
//if (_numberFormat == null) {
// // Cache the number format so that we don't have to get
// // info about local language etc. from the OS each time.
// _numberFormat = NumberFormat.getInstance();
//}
//_numberFormat.setMinimumFractionDigits(numfracdigits);
//_numberFormat.setMaximumFractionDigits(numfracdigits);
//return _numberFormat.format(num);
// The section below is from Ptplot1.3
// First, round the number.
double fudge = 0.5;
 
if (num < 0.0) {
fudge = -0.5;
}
 
String numString = Double.toString(num
+ (fudge * Math.pow(10.0, -numfracdigits)));
 
// Next, find the decimal point.
int dpt = numString.lastIndexOf(".");
StringBuffer result = new StringBuffer();
 
if (dpt < 0) {
// The number we are given is an integer.
if (numfracdigits <= 0) {
// The desired result is an integer.
result.append(numString);
//return result.toString();
return toExponential(result);
}
 
// Append a decimal point and some zeros.
result.append(".");
 
for (int i = 0; i < numfracdigits; i++) {
result.append("0");
}
//return result.toString();
return toExponential(result);
} else {
// There are two cases. First, there may be enough digits.
int shortby = numfracdigits - (numString.length() - dpt - 1);
 
if (shortby <= 0) {
int numtocopy = dpt + numfracdigits + 1;
 
if (numfracdigits == 0) {
// Avoid copying over a trailing decimal point.
numtocopy -= 1;
}
 
result.append(numString.substring(0, numtocopy));
//return result.toString();
return toExponential(result);
} else {
result.append(numString);
 
for (int i = 0; i < shortby; i++) {
result.append("0");
}
//return result.toString();
return toExponential(result);
}
}
}
//jm.evers logscale exponents
public String toExponential(StringBuffer S){
String result=S.toString();
if(PlotApplet.normalexponent){
result=result.replaceAll("e-","x10^-");
result=result.replaceAll("e+","x10^");
result=result.replaceAll("e","x10^");
}
return result;
}
public String toExponential(String S){
String result=S.toString();
if(PlotApplet.normalexponent){
result=result.replaceAll("e-","x10^-");
result=result.replaceAll("e+","x10^");
result=result.replaceAll("e","x10^");
}
return result;
}
 
 
/*
* Determine what values to use for log axes.
* Based on initGrid() from xgraph.c by David Harrison.
*/
private Vector _gridInit(double low, double step, boolean labeled,
Vector oldgrid) {
// How log axes work:
// _gridInit() creates a vector with the values to use for the
// log axes. For example, the vector might contain
// {0.0 0.301 0.698}, which could correspond to
// axis labels {1 1.2 1.5 10 12 15 100 120 150}
//
// _gridStep() gets the proper value. _gridInit is cycled through
// for each integer log value.
//
// Bugs in log axes:
// * Sometimes not enough grid lines are displayed because the
// region is small. This bug is present in the oriignal xgraph
// binary, which is the basis of this code. The problem is that
// as ratio gets closer to 1.0, we need to add more and more
// grid marks.
Vector grid = new Vector(10);
 
//grid.addElement(Double.valueOf(0.0));
double ratio = Math.pow(10.0, step);
int ngrid = 1;
 
if (labeled) {
// Set up the number of grid lines that will be labeled
if (ratio <= 3.5) {
if (ratio > 2.0) {
ngrid = 2;
} else if (ratio > 1.26) {
ngrid = 5;
} else if (ratio > 1.125) {
ngrid = 10;
} else {
ngrid = (int) Math.rint(1.0 / step);
}
}
} else {
// Set up the number of grid lines that will not be labeled
if (ratio > 10.0) {
ngrid = 1;
} else if (ratio > 3.0) {
ngrid = 2;
} else if (ratio > 2.0) {
ngrid = 5;
} else if (ratio > 1.125) {
ngrid = 10;
} else {
ngrid = 100;
}
 
// Note: we should keep going here, but this increases the
// size of the grid array and slows everything down.
}
 
int oldgridi = 0;
 
for (int i = 0; i < ngrid; i++) {
double gridval = (i * 1.0) / ngrid * 10;
double logval = _LOG10SCALE * Math.log(gridval);
 
if (logval == Double.NEGATIVE_INFINITY) {
logval = 0.0;
}
 
// If oldgrid is not null, then do not draw lines that
// were already drawn in oldgrid. This is necessary
// so we avoid obliterating the tick marks on the plot borders.
if ((oldgrid != null) && (oldgridi < oldgrid.size())) {
// Cycle through the oldgrid until we find an element
// that is equal to or greater than the element we are
// trying to add.
while ((oldgridi < oldgrid.size())
&& (((Double) oldgrid.elementAt(oldgridi))
.doubleValue() < logval)) {
oldgridi++;
}
 
if (oldgridi < oldgrid.size()) {
// Using == on doubles is bad if the numbers are close,
// but not exactly equal.
if (Math.abs(((Double) oldgrid.elementAt(oldgridi))
.doubleValue()
- logval) > 0.00001) {
grid.addElement(Double.valueOf(logval));
}
} else {
grid.addElement(Double.valueOf(logval));
}
} else {
grid.addElement(Double.valueOf(logval));
}
}
 
// _gridCurJuke and _gridBase are used in _gridStep();
_gridCurJuke = 0;
 
if (low == -0.0) {
low = 0.0;
}
 
_gridBase = Math.floor(low);
 
double x = low - _gridBase;
 
// Set gridCurJuke so that the value in grid is greater than
// or equal to x. This sets us up to process the first point.
for (_gridCurJuke = -1; ((_gridCurJuke + 1) < grid.size())
&& (x >= ((Double) grid.elementAt(_gridCurJuke + 1))
.doubleValue()); _gridCurJuke++) {
}
 
return grid;
}
 
/*
* Round pos up to the nearest value in the grid.
*/
private double _gridRoundUp(Vector grid, double pos) {
double x = pos - Math.floor(pos);
int i;
 
for (i = 0; (i < grid.size())
&& (x >= ((Double) grid.elementAt(i)).doubleValue()); i++) {
}
 
if (i >= grid.size()) {
return pos;
} else {
return Math.floor(pos) + ((Double) grid.elementAt(i)).doubleValue();
}
}
 
/*
* Used to find the next value for the axis label.
* For non-log axes, we just return pos + step.
* For log axes, we read the appropriate value in the grid Vector,
* add it to _gridBase and return the sum. We also take care
* to reset _gridCurJuke if necessary.
* Note that for log axes, _gridInit() must be called before
* calling _gridStep().
* Based on stepGrid() from xgraph.c by David Harrison.
*/
private double _gridStep(Vector grid, double pos, double step,
boolean logflag) {
if (logflag) {
if (++_gridCurJuke >= grid.size()) {
_gridCurJuke = 0;
_gridBase += Math.ceil(step);
}
 
if (_gridCurJuke >= grid.size()) {
return pos + step;
}
 
return _gridBase
+ ((Double) grid.elementAt(_gridCurJuke)).doubleValue();
} else {
return pos + step;
}
}
 
/*
* Measure the various fonts. You only want to call this once.
*/
private void _measureFonts() {
// We only measure the fonts once, and we do it from addNotify().
if (_labelFont == null) {
_labelFont = new Font("Helvetica", Font.PLAIN, 12);
}
 
if (_superscriptFont == null) {
_superscriptFont = new Font("Helvetica", Font.PLAIN, 9);
}
 
if (_titleFont == null) {
_titleFont = new Font("Helvetica", Font.BOLD, 14);
}
 
_labelFontMetrics = getFontMetrics(_labelFont);
_superscriptFontMetrics = getFontMetrics(_superscriptFont);
_titleFontMetrics = getFontMetrics(_titleFont);
}
 
/*
* Return the number of fractional digits required to display the
* given number. No number larger than 15 is returned (if
* more than 15 digits are required, 15 is returned).
*/
private int _numFracDigits(double num) {
int numdigits = 0;
 
while ((numdigits <= 15) && (num != Math.floor(num))) {
num *= 10.0;
numdigits += 1;
}
 
return numdigits;
}
 
/*
* Return the number of integer digits required to display the
* given number. No number larger than 15 is returned (if
* more than 15 digits are required, 15 is returned).
*/
private int _numIntDigits(double num) {
int numdigits = 0;
 
while ((numdigits <= 15) && ((int) num != 0.0)) {
num /= 10.0;
numdigits += 1;
}
 
return numdigits;
}
 
/*
* Parse a string of the form: "word num, word num, word num, ..."
* where the word must be enclosed in quotes if it contains spaces,
* and the number is interpreted as a floating point number. Ignore
* any incorrectly formatted fields. I <i>xtick</i> is true, then
* interpret the parsed string to specify the tick labels on the x axis.
* Otherwise, do the y axis.
*/
private void _parsePairs(String line, boolean xtick) {
// Clear current ticks first.
if (xtick) {
_xticks = null;
_xticklabels = null;
} else {
_yticks = null;
_yticklabels = null;
}
 
int start = 0;
boolean cont = true;
 
while (cont) {
int comma = line.indexOf(",", start);
String pair = null;
 
if (comma > start) {
pair = (line.substring(start, comma)).trim();
} else {
pair = (line.substring(start)).trim();
cont = false;
}
 
int close = -1;
int open = 0;
 
if (pair.startsWith("\"")) {
close = pair.indexOf("\"", 1);
open = 1;
} else {
close = pair.indexOf(" ");
}
 
if (close > 0) {
String label = pair.substring(open, close);
String index = (pair.substring(close + 1)).trim();
 
try {
double idx = (Double.valueOf(index)).doubleValue();
 
if (xtick) {
addXTick(label, idx);
} else {
addYTick(label, idx);
}
} catch (NumberFormatException e) {
System.err.println("Warning from PlotBox: "
+ "Unable to parse ticks: " + e.getMessage());
 
// ignore if format is bogus.
}
}
 
start = comma + 1;
comma = line.indexOf(",", start);
}
}
 
/** Return a default set of rendering hints for image export, which
* specifies the use of anti-aliasing.
*/
private RenderingHints _defaultImageRenderingHints() {
RenderingHints hints = new RenderingHints(null);
hints.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
return hints;
}
 
/*
* Given a number, round up to the nearest power of ten
* times 1, 2, or 5.
*
* Note: The argument must be strictly positive.
*/
private double _roundUp(double val) {
int exponent = (int) Math.floor(Math.log(val) * _LOG10SCALE);
val *= Math.pow(10, -exponent);
 
if (val > 5.0) {
val = 10.0;
} else if (val > 2.0) {
val = 5.0;
} else if (val > 1.0) {
val = 2.0;
}
 
val *= Math.pow(10, exponent);
return val;
}
 
/*
* Internal implementation of setXRange, so that it can be called when
* autoranging.
*/
private void _setXRange(double min, double max) {
// We check to see if the original range has been given here
// because if we check in setXRange(), then we will not catch
// the case where we have a simple plot file that consists of just
// data points
//
// 1. Create a file that consists of two data points
// 1 1
// 2 3
// 2. Start up plot on it
// $PTII/bin/ptplot foo.plt
// 3. Zoom in
// 4. Hit reset axes
// 5. The bug is that the axes do not reset to the initial settings
// Changing the range means we have to replot.
_plotImage = null;
 
if (!_originalXRangeGiven) {
_originalXlow = min;
_originalXhigh = max;
_originalXRangeGiven = true;
}
 
// If values are invalid, try for something reasonable.
if (min > max) {
min = -1.0;
max = 1.0;
} else if (min == max) {
min -= 1.0;
max += 1.0;
}
 
//if (_xRangeGiven) {
// The user specified the range, so don't pad.
// _xMin = min;
// _xMax = max;
//} else {
// Pad slightly so that we don't plot points on the axes.
_xMin = min - ((max - min) * _padding);
_xMax = max + ((max - min) * _padding);
 
//}
// Find the exponent.
double largest = Math.max(Math.abs(_xMin), Math.abs(_xMax));
_xExp = (int) Math.floor(Math.log(largest) * _LOG10SCALE);
 
// Use the exponent only if it's larger than 2 in magnitude.
if ((_xExp > 2) || (_xExp < -2)) {
double xs = 1.0 / Math.pow(10.0, _xExp);
_xtickMin = _xMin * xs;
_xtickMax = _xMax * xs;
} else {
_xtickMin = _xMin;
_xtickMax = _xMax;
_xExp = 0;
}
}
 
/*
* Internal implementation of setYRange, so that it can be called when
* autoranging.
*/
private void _setYRange(double min, double max) {
// See comment in _setXRange() about why this is necessary.
// Changing the range means we have to replot.
_plotImage = null;
 
if (!_originalYRangeGiven) {
_originalYlow = min;
_originalYhigh = max;
_originalYRangeGiven = true;
}
 
// If values are invalid, try for something reasonable.
if (min > max) {
min = -1.0;
max = 1.0;
} else if (min == max) {
min -= 0.1;
max += 0.1;
}
 
//if (_yRangeGiven) {
// The user specified the range, so don't pad.
// _yMin = min;
// _yMax = max;
//} else {
// Pad slightly so that we don't plot points on the axes.
_yMin = min - ((max - min) * _padding);
_yMax = max + ((max - min) * _padding);
 
//}
// Find the exponent.
double largest = Math.max(Math.abs(_yMin), Math.abs(_yMax));
_yExp = (int) Math.floor(Math.log(largest) * _LOG10SCALE);
 
// Use the exponent only if it's larger than 2 in magnitude.
if ((_yExp > 2) || (_yExp < -2)) {
double ys = 1.0 / Math.pow(10.0, _yExp);
_ytickMin = _yMin * ys;
_ytickMax = _yMax * ys;
} else {
_ytickMin = _yMin;
_ytickMax = _yMax;
_yExp = 0;
}
}
 
/*
* Zoom in or out based on the box that has been drawn.
* The argument gives the lower right corner of the box.
* This method is not synchronized because it is called within
* the UI thread, and making it synchronized causes a deadlock.
* @param x The final x position.
* @param y The final y position.
*/
void _zoom(int x, int y) {
// FIXME: This is friendly because Netscape 4.0.3 cannot access it if
// it is private!
// NOTE: Due to a bug in JDK 1.1.7B, the BUTTON1_MASK does
// not work on mouse drags, thus we have to use this variable
// to determine whether we are actually zooming. It is used only
// in _zoomBox, since calling this method is properly masked.
_zooming = false;
 
Graphics graphics = getGraphics();
 
// Ignore if there is no graphics object to draw on.
if (graphics == null) {
return;
}
 
if ((_zoomin == true) && (_drawn == true)) {
if ((_zoomxn != -1) || (_zoomyn != -1)) {
// erase previous rectangle.
int minx = Math.min(_zoomx, _zoomxn);
int maxx = Math.max(_zoomx, _zoomxn);
int miny = Math.min(_zoomy, _zoomyn);
int maxy = Math.max(_zoomy, _zoomyn);
graphics.setXORMode(_boxColor);
graphics.drawRect(minx, miny, maxx - minx, maxy - miny);
graphics.setPaintMode();
 
// constrain to be in range
if (y > _lry) {
y = _lry;
}
 
if (y < _uly) {
y = _uly;
}
 
if (x > _lrx) {
x = _lrx;
}
 
if (x < _ulx) {
x = _ulx;
}
 
// NOTE: ignore if total drag less than 5 pixels.
if ((Math.abs(_zoomx - x) > 5) && (Math.abs(_zoomy - y) > 5)) {
double a = _xMin + ((_zoomx - _ulx) / _xscale);
double b = _xMin + ((x - _ulx) / _xscale);
 
// NOTE: It used to be that it was problematic to set
// the X range here because it conflicted with the wrap
// mechanism. But now the wrap mechanism saves the state
// of the X range when the setWrap() method is called,
// so this is safe.
// EAL 6/12/00.
if (a < b) {
setXRange(a, b);
} else {
setXRange(b, a);
}
 
a = _yMax - ((_zoomy - _uly) / _yscale);
b = _yMax - ((y - _uly) / _yscale);
 
if (a < b) {
setYRange(a, b);
} else {
setYRange(b, a);
}
}
 
repaint();
}
} else if ((_zoomout == true) && (_drawn == true)) {
// Erase previous rectangle.
graphics.setXORMode(_boxColor);
 
int x_diff = Math.abs(_zoomx - _zoomxn);
int y_diff = Math.abs(_zoomy - _zoomyn);
graphics.drawRect(_zoomx - 15 - x_diff, _zoomy - 15 - y_diff,
30 + (x_diff * 2), 30 + (y_diff * 2));
graphics.setPaintMode();
 
// Calculate zoom factor.
double a = (Math.abs(_zoomx - x)) / 30.0;
double b = (Math.abs(_zoomy - y)) / 30.0;
double newx1 = _xMax + ((_xMax - _xMin) * a);
double newx2 = _xMin - ((_xMax - _xMin) * a);
 
// NOTE: To limit zooming out to the fill area, uncomment this...
// if (newx1 > _xTop) newx1 = _xTop;
// if (newx2 < _xBottom) newx2 = _xBottom;
double newy1 = _yMax + ((_yMax - _yMin) * b);
double newy2 = _yMin - ((_yMax - _yMin) * b);
 
// NOTE: To limit zooming out to the fill area, uncomment this...
// if (newy1 > _yTop) newy1 = _yTop;
// if (newy2 < _yBottom) newy2 = _yBottom;
zoom(newx2, newy2, newx1, newy1);
repaint();
} else if (_drawn == false) {
repaint();
}
 
_drawn = false;
_zoomin = _zoomout = false;
_zoomxn = _zoomyn = _zoomx = _zoomy = -1;
}
 
/*
* Draw a box for an interactive zoom box. The starting point (the
* upper left corner of the box) is taken
* to be that specified by the startZoom() method. The argument gives
* the lower right corner of the box. If a previous box
* has been drawn, erase it first.
* This method is not synchronized because it is called within
* the UI thread, and making it synchronized causes a deadlock.
* @param x The x position.
* @param y The y position.
*/
void _zoomBox(int x, int y) {
// FIXME: This is friendly because Netscape 4.0.3 cannot access it if
// it is private!
// NOTE: Due to a bug in JDK 1.1.7B, the BUTTON1_MASK does
// not work on mouse drags, thus we have to use this variable
// to determine whether we are actually zooming.
if (!_zooming) {
return;
}
 
Graphics graphics = getGraphics();
 
// Ignore if there is no graphics object to draw on.
if (graphics == null) {
return;
}
 
// Bound the rectangle so it doesn't go outside the box.
if (y > _lry) {
y = _lry;
}
 
if (y < _uly) {
y = _uly;
}
 
if (x > _lrx) {
x = _lrx;
}
 
if (x < _ulx) {
x = _ulx;
}
 
// erase previous rectangle, if there was one.
if (((_zoomx != -1) || (_zoomy != -1))) {
// Ability to zoom out added by William Wu.
// If we are not already zooming, figure out whether we
// are zooming in or out.
if ((_zoomin == false) && (_zoomout == false)) {
if (y < _zoomy) {
_zoomout = true;
 
// Draw reference box.
graphics.setXORMode(_boxColor);
graphics.drawRect(_zoomx - 15, _zoomy - 15, 30, 30);
} else if (y > _zoomy) {
_zoomin = true;
}
}
 
if (_zoomin == true) {
// Erase the previous box if necessary.
if (((_zoomxn != -1) || (_zoomyn != -1)) && (_drawn == true)) {
int minx = Math.min(_zoomx, _zoomxn);
int maxx = Math.max(_zoomx, _zoomxn);
int miny = Math.min(_zoomy, _zoomyn);
int maxy = Math.max(_zoomy, _zoomyn);
graphics.setXORMode(_boxColor);
graphics.drawRect(minx, miny, maxx - minx, maxy - miny);
}
 
// Draw a new box if necessary.
if (y > _zoomy) {
_zoomxn = x;
_zoomyn = y;
 
int minx = Math.min(_zoomx, _zoomxn);
int maxx = Math.max(_zoomx, _zoomxn);
int miny = Math.min(_zoomy, _zoomyn);
int maxy = Math.max(_zoomy, _zoomyn);
graphics.setXORMode(_boxColor);
graphics.drawRect(minx, miny, maxx - minx, maxy - miny);
_drawn = true;
return;
} else {
_drawn = false;
}
} else if (_zoomout == true) {
// Erase previous box if necessary.
if (((_zoomxn != -1) || (_zoomyn != -1)) && (_drawn == true)) {
int x_diff = Math.abs(_zoomx - _zoomxn);
int y_diff = Math.abs(_zoomy - _zoomyn);
graphics.setXORMode(_boxColor);
graphics.drawRect(_zoomx - 15 - x_diff, _zoomy - 15
- y_diff, 30 + (x_diff * 2), 30 + (y_diff * 2));
}
 
if (y < _zoomy) {
_zoomxn = x;
_zoomyn = y;
 
int x_diff = Math.abs(_zoomx - _zoomxn);
int y_diff = Math.abs(_zoomy - _zoomyn);
graphics.setXORMode(_boxColor);
graphics.drawRect(_zoomx - 15 - x_diff, _zoomy - 15
- y_diff, 30 + (x_diff * 2), 30 + (y_diff * 2));
_drawn = true;
return;
} else {
_drawn = false;
}
}
}
 
graphics.setPaintMode();
}
 
/*
* Set the starting point for an interactive zoom box (the upper left
* corner).
* This method is not synchronized because it is called within
* the UI thread, and making it synchronized causes a deadlock.
* @param x The x position.
* @param y The y position.
*/
void _zoomStart(int x, int y) {
// FIXME: This is friendly because Netscape 4.0.3 cannot access it if
// it is private!
// constrain to be in range
if (y > _lry) {
y = _lry;
}
 
if (y < _uly) {
y = _uly;
}
 
if (x > _lrx) {
x = _lrx;
}
 
if (x < _ulx) {
x = _ulx;
}
 
_zoomx = x;
_zoomy = y;
_zooming = true;
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
 
/** @serial Indicator of whether actions are deferred. */
private boolean _actionsDeferred = false;
 
/** @serial List of deferred actions. */
private List _deferredActions;
 
/** @serial The file to be opened. */
private String _filespec = null;
 
// Call setXORMode with a hardwired color because
// _background does not work in an application,
// and _foreground does not work in an applet.
// NOTE: For some reason, this comes out blue, which is fine...
private static final Color _boxColor = Color.orange;
 
/** @serial The range of the plot as labeled
* (multiply by 10^exp for actual range.
*/
private double _ytickMax = 0.0;
 
/** @serial The range of the plot as labeled
* (multiply by 10^exp for actual range.
*/
private double _ytickMin = 0.0;
 
/** @serial The range of the plot as labeled
* (multiply by 10^exp for actual range.
*/
private double _xtickMax = 0.0;
 
/** @serial The range of the plot as labeled
* (multiply by 10^exp for actual range.
*/
private double _xtickMin = 0.0;
 
/** @serial The power of ten by which the range numbers should
* be multiplied.
*/
private int _yExp = 0;
 
/** @serial The power of ten by which the range numbers should
* be multiplied.
*/
private int _xExp = 0;
 
/** @serial Scaling used in making tick marks. */
private double _ytickscale = 0.0;
 
/** @serial Scaling used in making tick marks. */
private double _xtickscale = 0.0;
 
/** @serial Font information. */
private Font _labelFont = null;
 
/** @serial Font information. */
private Font _superscriptFont = null;
 
/** @serial Font information. */
private Font _titleFont = null;
 
/** @serial FontMetric information. */
private FontMetrics _labelFontMetrics = null;
 
/** @serial FontMetric information. */
private FontMetrics _superscriptFontMetrics = null;
 
/** @serial FontMetric information. */
private FontMetrics _titleFontMetrics = null;
 
// Number format cache used by _formatNum.
// See the comment in _formatNum for more information.
// private transient NumberFormat _numberFormat = null;
// Used for log axes. Index into vector of axis labels.
private transient int _gridCurJuke = 0;
 
// Used for log axes. Base of the grid.
private transient double _gridBase = 0.0;
 
// An array of strings for reporting errors.
private transient String[] _errorMsg;
 
/** @serial The title and label strings. */
private String _xlabel;
 
/** @serial The title and label strings. */
private String _ylabel;
 
/** @serial The title and label strings. */
private String _title;
 
/** @serial Legend information. */
private Vector _legendStrings = new Vector();
 
/** @serial Legend information. */
private Vector _legendDatasets = new Vector();
 
/** @serial If XTicks or YTicks are given/ */
private Vector _xticks = null;
 
/** @serial If XTicks or YTicks are given/ */
private Vector _xticklabels = null;
 
/** @serial If XTicks or YTicks are given/ */
private Vector _yticks = null;
 
/** @serial If XTicks or YTicks are given/ */
private Vector _yticklabels = null;
 
// A button for filling the plot
private transient JButton _fillButton = null;
 
// A button for formatting the plot
private transient JButton _formatButton = null;
 
// Indicator of whether X and Y range has been first specified.
boolean _originalXRangeGiven = false;
 
// Indicator of whether X and Y range has been first specified.
boolean _originalYRangeGiven = false;
 
// First values specified to setXRange() and setYRange().
double _originalXlow = 0.0;
 
// First values specified to setXRange() and setYRange().
double _originalXhigh = 0.0;
 
// First values specified to setXRange() and setYRange().
double _originalYlow = 0.0;
 
// First values specified to setXRange() and setYRange().
double _originalYhigh = 0.0;
 
// An offscreen buffer for improving plot performance.
protected transient BufferedImage _plotImage = null;
 
// A button for printing the plot
private transient JButton _printButton = null;
 
// A button for filling the plot
private transient JButton _resetButton = null;
 
// Variables keeping track of the interactive zoom box.
// Initialize to impossible values.
private transient int _zoomx = -1;
 
private transient int _zoomy = -1;
 
private transient int _zoomxn = -1;
 
private transient int _zoomyn = -1;
 
// Control whether we are zooming in or out.
private transient boolean _zoomin = false;
 
private transient boolean _zoomout = false;
 
private transient boolean _drawn = false;
 
private transient boolean _zooming = false;
 
// NOTE: It is unfortunate to have to include the DTD here, but there
// seems to be no other way to ensure that the generated data exactly
// matches the DTD.
// private static final String _DTD =
// "<!-- PlotML DTD, created by Edward A. Lee.\n"
// + " See http://ptolemy.eecs.berkeley.edu/java/ptplot -->\n"
// + "<!ELEMENT plot (barGraph | bin | dataset | default | noColor | \n"
// + " noGrid | title | wrap | xLabel | xLog | xRange | xTicks | yLabel | \n"
// + " yLog | yRange | yTicks)*>\n"
// + " <!ELEMENT barGraph EMPTY>\n"
// + " <!ATTLIST barGraph width CDATA #IMPLIED>\n"
// + " <!ATTLIST barGraph offset CDATA #IMPLIED>\n"
// + " <!ELEMENT bin EMPTY>\n"
// + " <!ATTLIST bin width CDATA #IMPLIED>\n"
// + " <!ATTLIST bin offset CDATA #IMPLIED>\n"
// + " <!ELEMENT dataset (m | move | p | point)*>\n"
// + " <!ATTLIST dataset connected (yes | no) #IMPLIED>\n"
// + " <!ATTLIST dataset marks (none | dots | points | various) #IMPLIED>\n"
// + " <!ATTLIST dataset name CDATA #IMPLIED>\n"
// + " <!ATTLIST dataset stems (yes | no) #IMPLIED>\n"
// + " <!ELEMENT default EMPTY>\n"
// + " <!ATTLIST default connected (yes | no) \"yes\">\n"
// + " <!ATTLIST default marks (none | dots | points | various) \"none\">\n"
// + " <!ATTLIST default stems (yes | no) \"no\">\n"
// + " <!ELEMENT noColor EMPTY>\n"
// + " <!ELEMENT noGrid EMPTY>\n"
// + " <!ELEMENT title (#PCDATA)>\n"
// + " <!ELEMENT wrap EMPTY>\n"
// + " <!ELEMENT xLabel (#PCDATA)>\n"
// + " <!ELEMENT xLog EMPTY>\n"
// + " <!ELEMENT xRange EMPTY>\n"
// + " <!ATTLIST xRange min CDATA #REQUIRED>\n"
// + " <!ATTLIST xRange max CDATA #REQUIRED>\n"
// + " <!ELEMENT xTicks (tick)+>\n"
// + " <!ELEMENT yLabel (#PCDATA)>\n"
// + " <!ELEMENT yLog EMPTY>\n"
// + " <!ELEMENT yRange EMPTY>\n"
// + " <!ATTLIST yRange min CDATA #REQUIRED>\n"
// + " <!ATTLIST yRange max CDATA #REQUIRED>\n"
// + " <!ELEMENT yTicks (tick)+>\n"
// + " <!ELEMENT tick EMPTY>\n"
// + " <!ATTLIST tick label CDATA #REQUIRED>\n"
// + " <!ATTLIST tick position CDATA #REQUIRED>\n"
// + " <!ELEMENT m EMPTY>\n"
// + " <!ATTLIST m x CDATA #IMPLIED>\n"
// + " <!ATTLIST m x CDATA #REQUIRED>\n"
// + " <!ATTLIST m lowErrorBar CDATA #IMPLIED>\n"
// + " <!ATTLIST m highErrorBar CDATA #IMPLIED>\n"
// + " <!ELEMENT move EMPTY>\n"
// + " <!ATTLIST move x CDATA #IMPLIED>\n"
// + " <!ATTLIST move x CDATA #REQUIRED>\n"
// + " <!ATTLIST move lowErrorBar CDATA #IMPLIED>\n"
// + " <!ATTLIST move highErrorBar CDATA #IMPLIED>\n"
// + " <!ELEMENT p EMPTY>\n"
// + " <!ATTLIST p x CDATA #IMPLIED>\n"
// + " <!ATTLIST p x CDATA #REQUIRED>\n"
// + " <!ATTLIST p lowErrorBar CDATA #IMPLIED>\n"
// + " <!ATTLIST p highErrorBar CDATA #IMPLIED>\n"
// + " <!ELEMENT point EMPTY>\n"
// + " <!ATTLIST point x CDATA #IMPLIED>\n"
// + " <!ATTLIST point x CDATA #REQUIRED>\n"
// + " <!ATTLIST point lowErrorBar CDATA #IMPLIED>\n"
// + " <!ATTLIST point highErrorBar CDATA #IMPLIED>";
///////////////////////////////////////////////////////////////////
//// inner classes ////
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
if (event.getSource() == _fillButton) {
fillPlot();
} else if (event.getSource() == _printButton) {
// FIXME: Code duplication with PlotFrame._printCrossPlatform
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
PrinterJob job = PrinterJob.getPrinterJob();
 
// rbeyer@LPL.Arizona.EDU: Get the Page Format and use it.
//PageFormat format = job.pageDialog(job.defaultPage());
//job.setPrintable(PlotBox.this, format);
job.setPrintable(PlotBox.this);
 
if (job.printDialog(aset)) {
try {
job.print(aset);
} catch (Exception ex) {
Component ancestor = getTopLevelAncestor();
JOptionPane.showMessageDialog(ancestor,
"Printing failed:\n" + ex.toString(),
"Print Error", JOptionPane.WARNING_MESSAGE);
}
}
} else if (event.getSource() == _resetButton) {
resetAxes();
} else if (event.getSource() == _formatButton) {
PlotFormatter fmt = new PlotFormatter(PlotBox.this);
fmt.openModal();
}
}
}
 
public class ZoomListener implements MouseListener {
public void mouseClicked(MouseEvent event) {
requestFocus();
}
 
public void mouseEntered(MouseEvent event) {
}
 
public void mouseExited(MouseEvent event) {
}
 
public void mousePressed(MouseEvent event) {
// http://developer.java.sun.com/developer/bugParade/bugs/4072703.html
// BUTTON1_MASK still not set for MOUSE_PRESSED events
// suggests:
// Workaround
// Assume that a press event with no modifiers must be button 1.
// This has the serious drawback that it is impossible to be sure
// that button 1 hasn't been pressed along with one of the other
// buttons.
// This problem affects Netscape 4.61 under Digital Unix and
// 4.51 under Solaris
if (((event.getModifiers() & InputEvent.BUTTON1_MASK) != 0)
|| (event.getModifiers() == 0)) {
PlotBox.this._zoomStart(event.getX(), event.getY());
}
}
 
public void mouseReleased(MouseEvent event) {
if (((event.getModifiers() & InputEvent.BUTTON1_MASK) != 0)
|| (event.getModifiers() == 0)) {
PlotBox.this._zoom(event.getX(), event.getY());
}
}
}
 
public class DragListener implements MouseMotionListener {
public void mouseDragged(MouseEvent event) {
// NOTE: Due to a bug in JDK 1.1.7B, the BUTTON1_MASK does
// not work on mouse drags. It does work on MouseListener
// methods, so those methods set a variable _zooming that
// is used by _zoomBox to determine whether to draw a box.
// if ((event.getModifiers() & event.BUTTON1_MASK)!= 0) {
PlotBox.this._zoomBox(event.getX(), event.getY());
 
// }
}
 
public void mouseMoved(MouseEvent event) {
}
}
 
class CommandListener implements KeyListener {
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
 
switch (keycode) {
case KeyEvent.VK_CONTROL:
_control = true;
break;
 
case KeyEvent.VK_SHIFT:
_shift = true;
break;
 
case KeyEvent.VK_C:
 
if (_control) {
// The "null" sends the output to the clipboard.
export(null);
 
String message = "Encapsulated PostScript (EPS) "
+ "exported to clipboard.";
JOptionPane.showMessageDialog(PlotBox.this, message,
"Ptolemy Plot Message",
JOptionPane.INFORMATION_MESSAGE);
}
 
break;
 
case KeyEvent.VK_D:
 
if (!_control && _shift) {
write(System.out);
 
String message = "Plot data sent to standard out.";
JOptionPane.showMessageDialog(PlotBox.this, message,
"Ptolemy Plot Message",
JOptionPane.INFORMATION_MESSAGE);
}
 
if (_control) {
// xgraph and many other Unix apps use Control-D to exit
StringUtilities.exit(1);
}
 
break;
 
case KeyEvent.VK_E:
 
if (!_control && _shift) {
export(System.out);
 
String message = "Encapsulated PostScript (EPS) "
+ "exported to standard out.";
JOptionPane.showMessageDialog(PlotBox.this, message,
"Ptolemy Plot Message",
JOptionPane.INFORMATION_MESSAGE);
}
 
break;
 
case KeyEvent.VK_F:
 
if (!_control && _shift) {
fillPlot();
}
 
break;
 
case KeyEvent.VK_H:
 
if (!_control && _shift) {
_help();
}
 
break;
 
case KeyEvent.VK_Q:
 
if (!_control) {
// xv uses q to quit.
StringUtilities.exit(1);
}
 
break;
 
case KeyEvent.VK_SLASH:
 
if (_shift) {
// Question mark is SHIFT-SLASH
_help();
}
 
break;
 
default:
// None
}
}
 
public void keyReleased(KeyEvent e) {
int keycode = e.getKeyCode();
 
switch (keycode) {
case KeyEvent.VK_CONTROL:
_control = false;
break;
 
case KeyEvent.VK_SHIFT:
_shift = false;
break;
 
default:
// None
}
}
 
// The keyTyped method is broken in jdk 1.1.4.
// It always gets "unknown key code".
public void keyTyped(KeyEvent e) {
}
 
private boolean _control = false;
 
private boolean _shift = false;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotDataException.java
0,0 → 1,51
/* A labeled box for signal plots.
 
@Copyright (c) 1997-2005 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
//////////////////////////////////////////////////////////////////////////
//// PlotDataException
 
/**
Exception thrown by plot classes if there are format
problems with the data to be plotted.
 
@author Christopher Brooks
@version $Id: PlotDataException.java,v 1.30 2005/07/28 18:49:29 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
class PlotDataException extends Throwable {
public PlotDataException() {
super();
}
 
public PlotDataException(String s) {
super(s);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotPoint.java
0,0 → 1,70
/* A point in a plot.
 
@Author: Edward A. Lee
@Version: $Id: PlotPoint.java,v 1.37 2005/07/08 19:59:36 cxh Exp $
 
@Copyright (c) 1997-2005 The Regents of the University of California.
All rights reserved.
 
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in all
copies of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.io.Serializable;
 
//////////////////////////////////////////////////////////////////////////
//// PlotPoint
 
/**
A simple structure for storing a plot point.
@author Edward A. Lee
@version $Id: PlotPoint.java,v 1.37 2005/07/08 19:59:36 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class PlotPoint implements Serializable {
///////////////////////////////////////////////////////////////////
//// public variables ////
 
/** True if this point is connected to the previous point by a line. */
public boolean connected = false;
 
/** True if the yLowEB and yHighEB fields are valid. */
public boolean errorBar = false;
 
/** Original value of x before wrapping. */
public double originalx;
 
/** X value after wrapping (if any). */
public double x;
 
/** Y value. */
public double y;
 
/** Error bar Y low value. */
public double yLowEB;
 
/** Error bar Y low value. */
public double yHighEB;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/plot/PlotFrame.java
0,0 → 1,700
/* Top-level window containing a plotter.
 
Copyright (c) 1998-2005 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.plot;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
 
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;
 
import ptolemy.util.StringUtilities;
 
// TO DO:
// - Add a mechanism for combining two plots into one
//////////////////////////////////////////////////////////////////////////
//// PlotFrame
 
/**
 
PlotFrame is a versatile two-dimensional data plotter that runs as
part of an application, but in its own window. It can read files
compatible with the old Ptolemy plot file format (currently only ASCII).
It is extended with the capability to read PlotML files in PlotMLFrame.
An application can also interact directly with the contained Plot
object, which is visible as a public member, by invoking its methods.
<p>
An application that uses this class should set up the handling of
window-closing events. Presumably, the application will exit when
all windows have been closed. This is done with code something like:
<pre>
plotFrameInstance.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// Handle the event
}
});
</pre>
<p>
PlotFrame contains an instance of PlotBox. PlotBox is the base class for
classes with drawing capability, e.g. Plot, LogicAnalyzer. If not
specified in the constructor, the default is to contain a Plot object. This
field is set once in the constructor and immutable afterwards.
 
@see Plot
@see PlotBox
@author Christopher Brooks and Edward A. Lee
@version $Id: PlotFrame.java,v 1.84 2007/12/16 07:29:48 cxh Exp $
@since Ptolemy II 0.2
@Pt.ProposedRating Yellow (cxh)
@Pt.AcceptedRating Yellow (cxh)
*/
public class PlotFrame extends JFrame {
/** Construct a plot frame with a default title and by default contains
* an instance of Plot. After constructing this, it is necessary
* to call setVisible(true) to make the plot appear.
*/
public PlotFrame() {
this("Ptolemy Plot Frame");
}
 
/** Construct a plot frame with the specified title and by default
* contains an instance of Plot. After constructing this, it is necessary
* to call setVisible(true) to make the plot appear.
* @param title The title to put on the window.
*/
public PlotFrame(String title) {
this(title, null);
}
 
/** Construct a plot frame with the specified title and the specified
* instance of PlotBox. After constructing this, it is necessary
* to call setVisible(true) to make the plot appear.
* @param title The title to put on the window.
* @param plotArg the plot object to put in the frame, or null to create
* an instance of Plot.
*/
public PlotFrame(String title, PlotBox plotArg) {
super(title);
 
// The Java look & feel is pretty lame, so we use the native
// look and feel of the platform we are running on.
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
// Ignore exceptions, which only result in the wrong look and feel.
}
 
if (plotArg == null) {
plot = new Plot();
} else {
plot = plotArg;
}
 
// Background color is a light grey.
plot.setBackground(new Color(0xe5e5e5));
 
_fileMenu.setMnemonic(KeyEvent.VK_F);
_editMenu.setMnemonic(KeyEvent.VK_E);
_specialMenu.setMnemonic(KeyEvent.VK_S);
 
// File menu
JMenuItem[] fileMenuItems = { new JMenuItem("Open", KeyEvent.VK_O),
new JMenuItem("Save", KeyEvent.VK_S),
new JMenuItem("SaveAs", KeyEvent.VK_A),
new JMenuItem("Export", KeyEvent.VK_E),
new JMenuItem("Print", KeyEvent.VK_P),
new JMenuItem("Close", KeyEvent.VK_C), };
 
// Open button = ctrl-o.
fileMenuItems[0].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
Event.CTRL_MASK));
 
// Save button = ctrl-s.
fileMenuItems[1].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
Event.CTRL_MASK));
 
// Print button = ctrl-p.
fileMenuItems[4].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,
Event.CTRL_MASK));
 
// Close button = ctrl-w.
fileMenuItems[5].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
Event.CTRL_MASK));
 
FileMenuListener fml = new FileMenuListener();
 
// Set the action command and listener for each menu item.
for (int i = 0; i < fileMenuItems.length; i++) {
fileMenuItems[i].setActionCommand(fileMenuItems[i].getText());
fileMenuItems[i].addActionListener(fml);
_fileMenu.add(fileMenuItems[i]);
}
 
_menubar.add(_fileMenu);
 
// Edit menu
JMenuItem format = new JMenuItem("Format", KeyEvent.VK_F);
FormatListener formatListener = new FormatListener();
format.addActionListener(formatListener);
_editMenu.add(format);
_menubar.add(_editMenu);
 
// Special menu
JMenuItem[] specialMenuItems = { new JMenuItem("About", KeyEvent.VK_A),
new JMenuItem("Help", KeyEvent.VK_H),
new JMenuItem("Clear", KeyEvent.VK_C),
new JMenuItem("Fill", KeyEvent.VK_F),
new JMenuItem("Reset axes", KeyEvent.VK_R),
new JMenuItem("Sample plot", KeyEvent.VK_S), };
SpecialMenuListener sml = new SpecialMenuListener();
 
// Set the action command and listener for each menu item.
for (int i = 0; i < specialMenuItems.length; i++) {
specialMenuItems[i].setActionCommand(specialMenuItems[i].getText());
specialMenuItems[i].addActionListener(sml);
_specialMenu.add(specialMenuItems[i]);
}
 
_menubar.add(_specialMenu);
 
setJMenuBar(_menubar);
 
getContentPane().add(plot, BorderLayout.CENTER);
 
// FIXME: This should not be hardwired in here.
setSize(500, 300);
 
// Center.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = getSize();
int x = (screenSize.width - frameSize.width) / 2;
int y = (screenSize.height - frameSize.height) / 2;
setLocation(x, y);
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Create a sample plot.
*/
public void samplePlot() {
_file = null;
_directory = null;
plot.samplePlot();
}
 
/** Set the visibility. As a side effect, this method
* sets the background of the menus.
* @param visible True if the Frame is to be visible, false
* if it is not visible.
*/
public void setVisible(boolean visible) {
super.setVisible(visible);
_editMenu.setBackground(_menubar.getBackground());
_fileMenu.setBackground(_menubar.getBackground());
_specialMenu.setBackground(_menubar.getBackground());
}
 
///////////////////////////////////////////////////////////////////
//// public variables ////
 
/** @serial The plot object held by this frame. */
 
// FIXME: uncomment final when we upgrade to jdk1.2
public/*final*/PlotBox plot;
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
 
/** @serial Menubar for this frame. */
protected JMenuBar _menubar = new JMenuBar();
 
/** @serial Edit menu for this frame. */
protected JMenu _editMenu = new JMenu("Edit");
 
/** @serial File menu for this frame. */
protected JMenu _fileMenu = new JMenu("File");
 
/** @serial Special menu for this frame. */
protected JMenu _specialMenu = new JMenu("Special");
 
/** @serial Directory that contains the input file. */
protected File _directory = null;
 
/** @serial The input file. */
protected File _file = null;
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
protected void _about() {
JOptionPane
.showMessageDialog(
this,
"PlotFrame class\n"
+ "By: Edward A. Lee "
+ "and Christopher Brooks\n"
+ "Version "
+ PlotBox.PTPLOT_RELEASE
+ ", Build: $Id: PlotFrame.java,v 1.84 2007/12/16 07:29:48 cxh Exp $\n\n"
+ "For more information, see\n"
+ "http://ptolemy.eecs.berkeley.edu/java/ptplot\n\n"
+ "Copyright (c) 1997-2005, "
+ "The Regents of the University of California.",
"About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
}
 
/** Close the window.
*/
protected void _close() {
dispose();
}
 
/** Interactively edit the file format in a modal dialog.
*/
protected void _editFormat() {
PlotFormatter fmt = new PlotFormatter(plot);
fmt.openModal();
}
 
/** Query the user for a filename and export the plot to that file.
* Currently, the only supported format is EPS.
*/
protected void _export() {
JFileChooser fileDialog = new JFileChooser();
fileDialog.addChoosableFileFilter(new EPSFileFilter());
fileDialog.setDialogTitle("Export EPS to...");
 
if (_directory != null) {
fileDialog.setCurrentDirectory(_directory);
} else {
// The default on Windows is to open at user.home, which is
// typically an absurd directory inside the O/S installation.
// So we use the current directory instead.
String cwd = StringUtilities.getProperty("user.dir");
 
if (cwd != null) {
fileDialog.setCurrentDirectory(new File(cwd));
}
}
 
fileDialog.setSelectedFile(new File(fileDialog.getCurrentDirectory(),
"plot.eps"));
 
int returnVal = fileDialog.showDialog(this, "Export");
 
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fileDialog.getSelectedFile();
 
try {
FileOutputStream fout = null;
 
try {
fout = new FileOutputStream(file);
plot.export(fout);
} finally {
try {
fout.close();
} catch (Throwable throwable) {
System.out.println("Ignoring failure to close stream "
+ "on " + file);
throwable.printStackTrace();
}
}
} catch (IOException ex) {
JOptionPane.showMessageDialog(this, "Error exporting plot: "
+ ex, "Ptolemy II Error", JOptionPane.WARNING_MESSAGE);
}
}
}
 
/** Display more detailed information than given by _about().
*/
protected void _help() {
JOptionPane.showMessageDialog(this,
"PlotFrame is a plot in a top-level window.\n"
+ " File formats understood: Ptplot ASCII.\n"
+ " Left mouse button: Zooming.",
"About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
}
 
/** Open a new file and plot its data.
*/
protected void _open() {
JFileChooser fileDialog = new JFileChooser();
fileDialog.setDialogTitle("Select a plot file");
 
// Filter file names.
fileDialog.addChoosableFileFilter(new PLTOrXMLFileFilter());
 
if (_directory != null) {
fileDialog.setCurrentDirectory(_directory);
} else {
// The default on Windows is to open at user.home, which is
// typically an absurd directory inside the O/S installation.
// So we use the current directory instead.
String cwd = StringUtilities.getProperty("user.dir");
 
if (cwd != null) {
fileDialog.setCurrentDirectory(new File(cwd));
}
}
 
int returnVal = fileDialog.showOpenDialog(this);
 
if (returnVal == JFileChooser.APPROVE_OPTION) {
_file = fileDialog.getSelectedFile();
setTitle(_file.getName());
_directory = fileDialog.getCurrentDirectory();
 
try {
plot.clear(true);
_read(new URL("file", null, _directory.getAbsolutePath()),
new FileInputStream(_file));
plot.repaint();
} catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog(this, "File not found:\n"
+ ex.toString(), "Ptolemy Plot Error",
JOptionPane.WARNING_MESSAGE);
} catch (IOException ex) {
JOptionPane.showMessageDialog(this, "Error reading input:\n"
+ ex.toString(), "Ptolemy Plot Error",
JOptionPane.WARNING_MESSAGE);
}
}
}
 
/** Print the plot.
*/
protected void _print() {
_printCrossPlatform();
 
//_printNative();
}
 
/** Print using the cross platform dialog.
* FIXME: this dialog is slow and is often hidden
* behind other windows. However, it does honor
* the user's choice of portrait vs. landscape
*/
protected void _printCrossPlatform() {
// Build a set of attributes
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(plot);
 
if (job.printDialog(aset)) {
try {
job.print(aset);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "Printing failed:\n"
+ ex.toString(), "Print Error",
JOptionPane.WARNING_MESSAGE);
}
}
}
 
/** Print using the native dialog.
* FIXME: This method does not seem to honor the user's
* choice of portrait vs. landscape.
*/
protected void _printNative() {
PrinterJob job = PrinterJob.getPrinterJob();
 
//PageFormat pageFormat = job.defaultPage();
//job.setPrintable(plot, pageFormat);
job.setPrintable(plot);
 
if (job.printDialog()) {
try {
// job.print() eventually
// calls PlotBox.print(Graphics, PageFormat)
job.print();
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "Printing failed:\n"
+ ex.toString(), "Print Error",
JOptionPane.WARNING_MESSAGE);
}
}
}
 
/** Read the specified stream. Derived classes may override this
* to support other file formats.
* @param base The base for relative file references, or null if
* there are not relative file references.
* @param in The input stream.
* @exception IOException If the stream cannot be read.
*/
protected void _read(URL base, InputStream in) throws IOException {
plot.read(in);
}
 
/** Save the plot to the current file, determined by the
* and _file protected variable.
*/
protected void _save() {
if (_file != null) {
try {
FileOutputStream fout = new FileOutputStream(_file);
plot.write(fout);
} catch (IOException ex) {
JOptionPane.showMessageDialog(this, "Error writing file:\n"
+ ex.toString(), "Ptolemy Plot Error",
JOptionPane.WARNING_MESSAGE);
}
} else {
_saveAs();
}
}
 
/** Query the user for a filename and save the plot to that file.
*/
protected void _saveAs() {
JFileChooser fileDialog = new JFileChooser();
fileDialog.addChoosableFileFilter(new PLTOrXMLFileFilter());
fileDialog.setDialogTitle("Save plot as...");
 
if (_directory != null) {
fileDialog.setCurrentDirectory(_directory);
} else {
// The default on Windows is to open at user.home, which is
// typically an absurd directory inside the O/S installation.
// So we use the current directory instead.
String cwd = StringUtilities.getProperty("user.dir");
 
if (cwd != null) {
fileDialog.setCurrentDirectory(new File(cwd));
}
}
 
fileDialog.setSelectedFile(new File(fileDialog.getCurrentDirectory(),
"plot.xml"));
 
int returnVal = fileDialog.showSaveDialog(this);
 
if (returnVal == JFileChooser.APPROVE_OPTION) {
_file = fileDialog.getSelectedFile();
setTitle(_file.getName());
_directory = fileDialog.getCurrentDirectory();
_save();
}
}
 
///////////////////////////////////////////////////////////////////
//// inner classes ////
class FileMenuListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JMenuItem target = (JMenuItem) e.getSource();
String actionCommand = target.getActionCommand();
 
try {
if (actionCommand.equals("Open")) {
_open();
} else if (actionCommand.equals("Save")) {
_save();
} else if (actionCommand.equals("SaveAs")) {
_saveAs();
} else if (actionCommand.equals("Export")) {
_export();
} else if (actionCommand.equals("Print")) {
_print();
} else if (actionCommand.equals("Close")) {
_close();
}
} catch (Exception exception) {
// If we do not catch exceptions here, then they
// disappear to stdout, which is bad if we launched
// where there is no stdout visible.
JOptionPane.showMessageDialog(null, "File Menu Exception:\n"
+ exception.toString(), "Ptolemy Plot Error",
JOptionPane.WARNING_MESSAGE);
}
 
// NOTE: The following should not be needed, but there jdk1.3beta
// appears to have a bug in swing where repainting doesn't
// properly occur.
repaint();
}
}
 
class FormatListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
_editFormat();
} catch (Exception exception) {
// If we do not catch exceptions here, then they
// disappear to stdout, which is bad if we launched
// where there is no stdout visible.
JOptionPane.showMessageDialog(null, "Format Exception:\n"
+ exception.toString(), "Ptolemy Plot Error",
JOptionPane.WARNING_MESSAGE);
}
 
// NOTE: The following should not be needed, but there jdk1.3beta
// appears to have a bug in swing where repainting doesn't
// properly occur.
repaint();
}
}
 
class SpecialMenuListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JMenuItem target = (JMenuItem) e.getSource();
String actionCommand = target.getActionCommand();
 
try {
if (actionCommand.equals("About")) {
_about();
} else if (actionCommand.equals("Help")) {
_help();
} else if (actionCommand.equals("Fill")) {
plot.fillPlot();
} else if (actionCommand.equals("Reset axes")) {
plot.resetAxes();
} else if (actionCommand.equals("Clear")) {
plot.clear(false);
plot.repaint();
} else if (actionCommand.equals("Sample plot")) {
plot.clear(true);
samplePlot();
}
} catch (Exception exception) {
// If we do not catch exceptions here, then they
// disappear to stdout, which is bad if we launched
// where there is no stdout visible.
JOptionPane.showMessageDialog(null, "Special Menu Exception:\n"
+ exception.toString(), "Ptolemy Plot Error",
JOptionPane.WARNING_MESSAGE);
}
 
// NOTE: The following should not be needed, but there jdk1.3beta
// appears to have a bug in swing where repainting doesn't
// properly occur.
repaint();
}
}
 
///////////////////////////////////////////////////////////////////
//// inner classes ////
 
/** Display only .eps files */
static class EPSFileFilter extends FileFilter {
/** Accept only .eps files.
* @param file The file to be checked.
* @return true if the file is a directory, a .eps file
*/
public boolean accept(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()) {
return true;
}
 
String fileOrDirectoryName = fileOrDirectory.getName();
int dotIndex = fileOrDirectoryName.lastIndexOf('.');
 
if (dotIndex == -1) {
return false;
}
 
String extension = fileOrDirectoryName.substring(dotIndex);
 
if (extension != null) {
if (extension.equalsIgnoreCase(".eps")) {
return true;
} else {
return false;
}
}
 
return false;
}
 
/** The description of this filter */
public String getDescription() {
return "Encapsulated PostScript (.eps) files";
}
}
 
/** Display only .plt and .xml files */
static class PLTOrXMLFileFilter extends FileFilter {
/** Accept only .plt or .xml files.
* @param file The file to be checked.
* @return true if the file is a directory, a .plot or a .xml file.
*/
public boolean accept(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()) {
return true;
}
 
String fileOrDirectoryName = fileOrDirectory.getName();
int dotIndex = fileOrDirectoryName.lastIndexOf('.');
 
if (dotIndex == -1) {
return false;
}
 
String extension = fileOrDirectoryName.substring(dotIndex);
 
if (extension != null) {
if (extension.equalsIgnoreCase(".plt")
|| extension.equalsIgnoreCase(".xml")) {
return true;
} else {
return false;
}
}
 
return false;
}
 
/** The description of this filter */
public String getDescription() {
return ".plt and .xml files";
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/gui/Query.java
0,0 → 1,1953
/* Query dialog.
 
Copyright (c) 1998-2007 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
 
*/
package ptolemy.gui;
 
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
 
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicComboBoxEditor;
 
// Avoid importing any packages from ptolemy.* here so that we
// can ship Ptplot.
//////////////////////////////////////////////////////////////////////////
//// Query
 
/**
Create a query with various types of entry boxes and controls. Each type
of entry box has a colon and space appended to the end of its label, to
ensure uniformity.
Here is one example of creating a query with a radio button:
<pre>
query = new Query();
getContentPane().add(query);
String[] options = {"water", "soda", "juice", "none"};
query.addRadioButtons("radio", "Radio buttons", options, "water");
</pre>
 
@author Edward A. Lee, Manda Sutijono, Elaine Cheong
@version $Id: Query.java,v 1.127 2007/12/16 07:29:47 cxh Exp $
@since Ptolemy II 0.3
@Pt.ProposedRating Yellow (eal)
@Pt.AcceptedRating Red (eal)
*/
public class Query extends JPanel {
/** Construct a panel with no entries in it.
*/
public Query() {
_grid = new GridBagLayout();
_constraints = new GridBagConstraints();
_constraints.fill = GridBagConstraints.HORIZONTAL;
 
// If the next line is commented out, then the PtolemyApplet
// model parameters will have an entry that is less than one
// character wide unless the window is made to be fairly large.
_constraints.weightx = 1.0;
_constraints.anchor = GridBagConstraints.NORTHWEST;
_entryPanel.setLayout(_grid);
 
// It's not clear whether the following has any real significance...
// _entryPanel.setOpaque(true);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
 
_entryPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
 
// Add a message panel into which a message can be placed using
// setMessage().
_messageArea = new JTextArea("");
_messageArea.setFont(new Font("SansSerif", Font.PLAIN, 12));
_messageArea.setEditable(false);
_messageArea.setLineWrap(true);
_messageArea.setWrapStyleWord(true);
 
// It seems like setLineWrap is somewhat broken. Really,
// setLineWrap works best with scrollbars. We have
// a couple of choices: use scrollbars or hack in something
// that guesses the number of lines. Note that to
// use scrollbars, the tutorial at
// http://java.sun.com/docs/books/tutorial/uiswing/components/simpletext.html#textarea
// suggests: "If you put a text area in a scroll pane, be
// sure to set the scroll pane's preferred size or use a
// text area constructor that sets the number of rows and
// columns for the text area."
_messageArea.setBackground(null);
 
_messageArea.setAlignmentX(Component.LEFT_ALIGNMENT);
 
_messageScrollPane = new JScrollPane(_messageArea);
_messageScrollPane
.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
 
// Get rid of the border.
_messageScrollPane.setBorder(BorderFactory.createEmptyBorder());
_messageScrollPane.getViewport().setBackground(null);
 
// Useful for debugging:
//_messageScrollPane.setBorder(
// BorderFactory.createLineBorder(Color.pink));
// We add the _messageScrollPane when we first use it.
_entryScrollPane = new JScrollPane(_entryPanel);
 
// Get rid of the border.
_entryScrollPane.setBorder(BorderFactory.createEmptyBorder());
_entryScrollPane.getViewport().setBackground(null);
_entryScrollPane.setBackground(null);
add(_entryScrollPane);
 
// Setting the background to null allegedly means it inherits the
// background color from the container.
_entryPanel.setBackground(null);
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Create an on-off check box.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param defaultValue The default value (true for on).
*/
public void addCheckBox(String name, String label, boolean defaultValue) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
JCheckBox checkbox = new JCheckBox();
checkbox.setBackground(_background);
checkbox.setOpaque(false);
checkbox.setSelected(defaultValue);
_addPair(name, lbl, checkbox, checkbox);
 
// Add the listener last so that there is no notification
// of the first value.
checkbox.addItemListener(new QueryItemListener(name));
}
 
/** Create an uneditable choice menu.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param values The list of possible choices.
* @param defaultChoice Default choice.
*/
public void addChoice(String name, String label, String[] values,
String defaultChoice) {
addChoice(name, label, values, defaultChoice, false);
}
 
/** Create a choice menu.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param values The list of possible choices.
* @param defaultChoice Default choice.
* @param editable True if an arbitrary choice can be entered, in addition
* to the choices in values.
*/
public void addChoice(String name, String label, String[] values,
String defaultChoice, boolean editable) {
addChoice(name, label, values, defaultChoice, editable, Color.white,
Color.black);
}
 
/** Create a choice menu.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param values The list of possible choices.
* @param defaultChoice Default choice.
* @param editable True if an arbitrary choice can be entered, in addition
* to the choices in values.
* @param background The background color for the editable part.
* @param foreground The foreground color for the editable part.
*/
public void addChoice(String name, String label, String[] values,
String defaultChoice, boolean editable, final Color background,
final Color foreground) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
JComboBox combobox = new JComboBox(values);
combobox.setEditable(editable);
 
// NOTE: Typical of Swing, the following does not set
// the background color. So we have to specify a
// custom editor. #$(#&$#(@#!!
// combobox.setBackground(background);
combobox.setEditor(new BasicComboBoxEditor() {
public Component getEditorComponent() {
Component result = super.getEditorComponent();
result.setBackground(background);
result.setForeground(foreground);
return result;
}
});
combobox.setSelectedItem(defaultChoice);
_addPair(name, lbl, combobox, combobox);
 
// Add the listener last so that there is no notification
// of the first value.
combobox.addItemListener(new QueryItemListener(name));
}
 
/** Create a ColorChooser.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param defaultColor The default color to use.
*/
public void addColorChooser(String name, String label, String defaultColor) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
QueryColorChooser colorChooser = new QueryColorChooser(name,
defaultColor);
_addPair(name, lbl, colorChooser, colorChooser);
}
 
/** Create a simple one-line text display, a non-editable value that
* is set externally using the setDisplay() method.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param theValue Default string to display.
*/
public void addDisplay(String name, String label, String theValue) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
// NOTE: JLabel would be a reasonable choice here, but at
// least in the current version of swing, JLabel.setText() does
// not work.
JTextArea displayField = new JTextArea(theValue, 1, 10);
displayField.setEditable(false);
displayField.setBackground(_background);
_addPair(name, lbl, displayField, displayField);
}
 
/** Create a FileChooser that selects files only, not directories, and
* has the default colors (white in the background, black in the
* foreground).
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param defaultName The default file name to use.
* @param base The URI with respect to which to give
* relative file names, or null to give absolute file name.
* @param startingDirectory The directory to open the file chooser in.
*/
public void addFileChooser(String name, String label, String defaultName,
URI base, File startingDirectory) {
addFileChooser(name, label, defaultName, base, startingDirectory, true,
false, Color.white, Color.black);
}
 
/** Create a FileChooser with default colors (white in the foreground,
* black in the background).
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param defaultName The default file name to use.
* @param base The URI with respect to which to give
* relative file names, or null to give absolute file name.
* @param startingDirectory The directory to open the file chooser in.
* @param allowFiles True if regular files may be chosen.
* @param allowDirectories True if directories may be chosen.
*/
public void addFileChooser(String name, String label, String defaultName,
URI base, File startingDirectory, boolean allowFiles,
boolean allowDirectories) {
addFileChooser(name, label, defaultName, base, startingDirectory,
allowFiles, allowDirectories, Color.white, Color.black);
}
 
/** Create a FileChooser that selects files only, not directories.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param defaultName The default file name to use.
* @param base The URI with respect to which to give
* relative file names, or null to give absolute file name.
* @param startingDirectory The directory to open the file chooser in.
* @param background The background color for the text entry box.
* @param foreground The foreground color for the text entry box.
*/
public void addFileChooser(String name, String label, String defaultName,
URI base, File startingDirectory, Color background, Color foreground) {
addFileChooser(name, label, defaultName, base, startingDirectory, true,
false, background, foreground);
}
 
/** Create a FileChooser.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param defaultName The default file name to use.
* @param base The URI with respect to which to give
* relative file names, or null to give absolute file name.
* @param startingDirectory The directory to open the file chooser in.
* @param allowFiles True if regular files may be chosen.
* @param allowDirectories True if directories may be chosen.
* @param background The background color for the text entry box.
* @param foreground The foreground color for the text entry box.
*/
public void addFileChooser(String name, String label, String defaultName,
URI base, File startingDirectory, boolean allowFiles,
boolean allowDirectories, Color background, Color foreground) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
QueryFileChooser fileChooser = new QueryFileChooser(name, defaultName,
base, startingDirectory, allowFiles, allowDirectories,
background, foreground);
_addPair(name, lbl, fileChooser, fileChooser);
}
 
/** Create a single-line entry box with the specified name, label, and
* default value. To control the width of the box, call setTextWidth()
* first.
* @param name The name used to identify the entry (when accessing
* the entry).
* @param label The label to attach to the entry.
* @param defaultValue Default value to appear in the entry box.
*/
public void addLine(String name, String label, String defaultValue) {
addLine(name, label, defaultValue, Color.white, Color.black);
}
 
/** Create a single-line entry box with the specified name, label,
* default value, and background color. To control the width of
* the box, call setTextWidth() first.
* @param name The name used to identify the entry (when accessing
* the entry).
* @param label The label to attach to the entry.
* @param defaultValue Default value to appear in the entry box.
* @param background The background color.
* @param foreground The foreground color.
*/
public void addLine(String name, String label, String defaultValue,
Color background, Color foreground) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
JTextField entryBox = new JTextField(defaultValue, _width);
entryBox.setBackground(background);
entryBox.setForeground(foreground);
_addPair(name, lbl, entryBox, entryBox);
 
// Add the listener last so that there is no notification
// of the first value.
entryBox.addActionListener(new QueryActionListener(name));
 
// Add a listener for loss of focus. When the entry gains
// and then loses focus, listeners are notified of an update,
// but only if the value has changed since the last notification.
// FIXME: Unfortunately, Java calls this listener some random
// time after the window has been closed. It is not even a
// a queued event when the window is closed. Thus, we have
// a subtle bug where if you enter a value in a line, do not
// hit return, and then click on the X to close the window,
// the value is restored to the original, and then sometime
// later, the focus is lost and the entered value becomes
// the value of the parameter. I don't know of any workaround.
entryBox.addFocusListener(new QueryFocusListener(name));
}
 
/** Create a single-line password box with the specified name, label, and
* default value. To control the width of the box, call setTextWidth()
* first. A value that is entered in the password box should be
* accessed using getCharArrayValue(). The value returned by
* stringValue() is whatever you specify as a defaultValue.
* @param name The name used to identify the entry (when accessing
* the entry).
* @param label The label to attach to the entry.
* @param defaultValue Default value to appear in the entry box.
* @since Ptolemy II 3.1
*/
public void addPassword(String name, String label, String defaultValue) {
addPassword(name, label, defaultValue, Color.white, Color.black);
}
 
/** Create a single-line password box with the specified name,
* label, and default value. To control the width of the box,
* call setTextWidth() first.
* To get the value, call getCharArrayValue().
* Calling getStringValue() on a password entry will result in an
* error because it is less secure to pass around passwords as
* Strings than as arrays of characters.
* <p>The underlying class that is used to implement the password
* facility is javax.swing.JPasswordField. For details about how to
* use JPasswordField, see the
* <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/passwordfield.html" target="_top">Java Tutorial</a>
*
* @param name The name used to identify the entry (when accessing
* the entry).
* @param label The label to attach to the entry.
* @param defaultValue Default value to appear in the entry box.
* @param background The background color.
* @param foreground The foreground color.
* @since Ptolemy II 3.1
*/
public void addPassword(String name, String label, String defaultValue,
Color background, Color foreground) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
JPasswordField entryBox = new JPasswordField(defaultValue, _width);
entryBox.setBackground(background);
entryBox.setForeground(foreground);
_addPair(name, lbl, entryBox, entryBox);
 
// Add the listener last so that there is no notification
// of the first value.
entryBox.addActionListener(new QueryActionListener(name));
 
// Add a listener for loss of focus. When the entry gains
// and then loses focus, listeners are notified of an update,
// but only if the value has changed since the last notification.
// FIXME: Unfortunately, Java calls this listener some random
// time after the window has been closed. It is not even a
// a queued event when the window is closed. Thus, we have
// a subtle bug where if you enter a value in a line, do not
// hit return, and then click on the X to close the window,
// the value is restored to the original, and then sometime
// later, the focus is lost and the entered value becomes
// the value of the parameter. I don't know of any workaround.
entryBox.addFocusListener(new QueryFocusListener(name));
}
 
/** Add a listener. The changed() method of the listener will be
* called when any of the entries is changed. Note that "line"
* entries only trigger this call when Return or Enter is pressed, or
* when the entry gains and then loses the keyboard focus.
* Notice that the currently selected line loses focus when the
* panel is destroyed, so notification of any changes that
* have been made will be done at that time. That notification
* will occur in the UI thread, and may be later than expected.
* Notification due to loss of focus only occurs if the value
* of the entry has changed since the last notification.
* If the listener has already been added, then do nothing.
* @param listener The listener to add.
* @see #removeQueryListener(QueryListener)
*/
public void addQueryListener(QueryListener listener) {
if (_listeners == null) {
_listeners = new Vector();
}
 
if (_listeners.contains(listener)) {
return;
}
 
_listeners.add(listener);
}
 
/** Create a bank of radio buttons. A radio button provides a list of
* choices, only one of which may be chosen at a time.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param values The list of possible choices.
* @param defaultValue Default value.
*/
public void addRadioButtons(String name, String label, String[] values,
String defaultValue) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
FlowLayout flow = new FlowLayout();
flow.setAlignment(FlowLayout.LEFT);
 
// This must be a JPanel, not a Panel, or the scroll bars won't work.
JPanel buttonPanel = new JPanel(flow);
 
ButtonGroup group = new ButtonGroup();
QueryActionListener listener = new QueryActionListener(name);
 
// Regrettably, ButtonGroup provides no method to find out
// which button is selected, so we have to go through a
// song and dance here...
JRadioButton[] buttons = new JRadioButton[values.length];
 
for (int i = 0; i < values.length; i++) {
JRadioButton checkbox = new JRadioButton(values[i]);
buttons[i] = checkbox;
checkbox.setBackground(_background);
 
// The following (essentially) undocumented method does nothing...
// checkbox.setContentAreaFilled(true);
checkbox.setOpaque(false);
 
if (values[i].equals(defaultValue)) {
checkbox.setSelected(true);
}
 
group.add(checkbox);
buttonPanel.add(checkbox);
 
// Add the listener last so that there is no notification
// of the first value.
checkbox.addActionListener(listener);
}
 
_addPair(name, lbl, buttonPanel, buttons);
}
 
/** Create a bank of buttons that provides a list of
* choices, any subset of which may be chosen at a time.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param values The list of possible choices.
* @param initiallySelected The initially selected choices, or null
* to indicate that none are selected.
*/
public void addSelectButtons(String name, String label, String[] values,
Set initiallySelected) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
FlowLayout flow = new FlowLayout();
flow.setAlignment(FlowLayout.LEFT);
 
// This must be a JPanel, not a Panel, or the scroll bars won't work.
JPanel buttonPanel = new JPanel(flow);
 
QueryActionListener listener = new QueryActionListener(name);
 
if (initiallySelected == null) {
initiallySelected = new HashSet();
}
 
JRadioButton[] buttons = new JRadioButton[values.length];
 
for (int i = 0; i < values.length; i++) {
JRadioButton checkbox = new JRadioButton(values[i]);
buttons[i] = checkbox;
checkbox.setBackground(_background);
 
// The following (essentially) undocumented method does nothing...
// checkbox.setContentAreaFilled(true);
checkbox.setOpaque(false);
 
if (initiallySelected.contains(values[i])) {
checkbox.setSelected(true);
}
 
buttonPanel.add(checkbox);
 
// Add the listener last so that there is no notification
// of the first value.
checkbox.addActionListener(listener);
}
 
_addPair(name, lbl, buttonPanel, buttons);
}
 
/** Create a slider with the specified name, label, default
* value, maximum, and minimum.
* @param name The name used to identify the slider.
* @param label The label to attach to the slider.
* @param defaultValue Initial position of slider.
* @param maximum Maximum value of slider.
* @param minimum Minimum value of slider.
* @exception IllegalArgumentException If the desired default value
* is not between the minimum and maximum.
*/
public void addSlider(String name, String label, int defaultValue,
int minimum, int maximum) throws IllegalArgumentException {
JLabel lbl = new JLabel(label + ": ");
 
if (minimum > maximum) {
int temp = minimum;
minimum = maximum;
maximum = temp;
}
 
if ((defaultValue > maximum) || (defaultValue < minimum)) {
throw new IllegalArgumentException("Desired default " + "value \""
+ defaultValue + "\" does not fall "
+ "between the minimum and maximum.");
}
 
JSlider slider = new JSlider(minimum, maximum, defaultValue);
_addPair(name, lbl, slider, slider);
slider.addChangeListener(new SliderListener(name));
}
 
/** Create a text area.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param theValue The value of this text area
*/
public void addTextArea(String name, String label, String theValue) {
addTextArea(name, label, theValue, Color.white, Color.black, _height,
_width);
}
 
/** Create a text area.
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param theValue The value of this text area.
* @param background The background color.
* @param foreground The foreground color.
*/
public void addTextArea(String name, String label, String theValue,
Color background, Color foreground) {
addTextArea(name, label, theValue, background, foreground, _height,
_width);
}
 
/** Create a text area with the specified height and width (in
* characters).
* @param name The name used to identify the entry (when calling get).
* @param label The label to attach to the entry.
* @param theValue The value of this text area.
* @param background The background color.
* @param foreground The foreground color.
* @param height The height.
* @param width The width.
*/
public void addTextArea(String name, String label, String theValue,
Color background, Color foreground, int height, int width) {
JLabel lbl = new JLabel(label + ": ");
lbl.setBackground(_background);
 
JTextArea textArea = new JTextArea(theValue, height, width);
textArea.setEditable(true);
textArea.setBackground(background);
textArea.setForeground(foreground);
 
QueryScrollPane textPane = new QueryScrollPane(textArea);
_addPair(name, lbl, textPane, textPane);
textArea.addFocusListener(new QueryFocusListener(name));
}
 
/** Get the current value in the entry with the given name
* and return as a boolean. If the entry is not a checkbox,
* then throw an exception.
* @param name The name of the entry.
* @deprecated Use getBooleanValue(String name) instead.
* @return The state of the checkbox.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* checkbox. This is a runtime exception, so it
* need not be declared explicitly.
*/
public boolean booleanValue(String name) throws NoSuchElementException,
IllegalArgumentException {
return getBooleanValue(name);
}
 
/** Get the current value in the entry with the given name
* and return as a double value. If the entry is not a line,
* then throw an exception. If the value of the entry is not
* a double, then throw an exception.
* @param name The name of the entry.
* @deprecated Use getDoubleValue(String name) instead.
* @return The value currently in the entry as a double.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception NumberFormatException If the value of the entry cannot
* be converted to a double. This is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* line. This is a runtime exception, so it
* need not be declared explicitly.
*/
public double doubleValue(String name) throws IllegalArgumentException,
NoSuchElementException, NumberFormatException {
return getDoubleValue(name);
}
 
/** Get the current value in the entry with the given name
* and return as a boolean. If the entry is not a checkbox,
* then throw an exception.
* @param name The name of the entry.
* @return The state of the checkbox.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* checkbox. This is a runtime exception, so it
* need not be declared explicitly.
*/
public boolean getBooleanValue(String name) throws NoSuchElementException,
IllegalArgumentException {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ "\" in the query box.");
}
 
if (result instanceof JToggleButton) {
return ((JToggleButton) result).isSelected();
} else {
throw new IllegalArgumentException("Item named \"" + name
+ "\" is not a radio button, and hence does not have "
+ "a boolean value.");
}
}
 
/** Get the current value in the entry with the given name
* and return as an array of characters.
* <p>If the entry is a password field, then it is recommended for
* strong security that each element of the array be set to 0
* after use.
* @param name The name of the entry.
* @return The state of the entry
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry type does not
* have a string representation (this should not be thrown).
* This is a runtime exception, so it need not be declared explicitly.
* @since Ptolemy II 3.1
*/
public char[] getCharArrayValue(String name) throws NoSuchElementException,
IllegalArgumentException {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ "\" in the query box.");
}
 
if (result instanceof JPasswordField) {
// Calling JPasswordField.getText() is deprecated
return ((JPasswordField) result).getPassword();
} else {
return getStringValue(name).toCharArray();
}
}
 
/** Get the current value in the entry with the given name
* and return as a double value. If the entry is not a line,
* then throw an exception. If the value of the entry is not
* a double, then throw an exception.
* @param name The name of the entry.
* @return The value currently in the entry as a double.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception NumberFormatException If the value of the entry cannot
* be converted to a double. This is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* line. This is a runtime exception, so it
* need not be declared explicitly.
*/
public double getDoubleValue(String name) throws IllegalArgumentException,
NoSuchElementException, NumberFormatException {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ " \" in the query box.");
}
 
if (result instanceof JPasswordField) {
// Note that JPasswordField extends JTextField, so
// we should check for JPasswordField first.
throw new IllegalArgumentException("For security reasons, "
+ "calling getDoubleValue() on a password field is "
+ "not permitted. Instead, call getCharArrayValue()");
} else if (result instanceof JTextField) {
return (Double.valueOf(((JTextField) result).getText()))
.doubleValue();
} else {
throw new IllegalArgumentException("Item named \"" + name
+ "\" is not a text line, and hence cannot be converted "
+ "to a double value.");
}
}
 
/** Get the current value in the entry with the given name
* and return as an integer. If the entry is not a line,
* choice, or slider, then throw an exception.
* If it is a choice or radio button, then return the
* index of the first selected item.
* @param name The name of the entry.
* @return The value currently in the entry as an integer.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception NumberFormatException If the value of the entry cannot
* be converted to an integer. This is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* choice, line, or slider. This is a runtime exception, so it
* need not be declared explicitly.
*/
public int getIntValue(String name) throws IllegalArgumentException,
NoSuchElementException, NumberFormatException {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ " \" in the query box.");
}
 
if (result instanceof JPasswordField) {
// Note that JPasswordField extends JTextField, so
// we should check for JPasswordField first.
throw new IllegalArgumentException("For security reasons, "
+ "calling getIntValue() on a password field is "
+ "not permitted. Instead, call getCharArrayValue()");
} else if (result instanceof JTextField) {
return (Integer.valueOf(((JTextField) result).getText()))
.intValue();
} else if (result instanceof JSlider) {
return ((JSlider) result).getValue();
} else if (result instanceof JComboBox) {
return ((JComboBox) result).getSelectedIndex();
} else if (result instanceof JToggleButton[]) {
// Regrettably, ButtonGroup gives no way to determine
// which button is selected, so we have to search...
JToggleButton[] buttons = (JToggleButton[]) result;
 
for (int i = 0; i < buttons.length; i++) {
if (buttons[i].isSelected()) {
return i;
}
}
 
// In theory, we shouldn't get here, but the compiler
// is unhappy without a return.
return -1;
} else {
throw new IllegalArgumentException("Item named \"" + name
+ "\" is not a text line or slider, and hence "
+ "cannot be converted to " + "an integer value.");
}
}
 
/** Return the preferred height, but set the width to the maximum
* possible value. Currently (JDK 1.3), only BoxLayout pays any
* attention to getMaximumSize().
*
* @return The maximum desired size.
*/
public Dimension getMaximumSize() {
// Unfortunately, if we don't have a message, then we end up with
// an empty space that is difficult to control the size of, which
// requires us to set the maximum size to be the same as
// the preferred size
// If you change this, be sure to try applets that have both
// horizontal and vertical layout.
Dimension preferred = getPreferredSize();
preferred.width = Short.MAX_VALUE;
return preferred;
}
 
/** Get the current value in the entry with the given name,
* and return as a String. All entry types support this.
* Note that this method should be called from the event dispatch
* thread, since it needs to query to UI widgets for their current
* values. If it is called from another thread, there is no
* assurance that the value returned will be the current value.
* @param name The name of the entry.
* @return The value currently in the entry as a String.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry type does not
* have a string representation (this should not be thrown).
*/
public String getStringValue(String name) throws NoSuchElementException,
IllegalArgumentException {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ " \" in the query box.");
}
 
if (result instanceof JTextField) {
return ((JTextField) result).getText();
} else if (result instanceof QueryColorChooser) {
return ((QueryColorChooser) result).getSelectedColor();
} else if (result instanceof QueryFileChooser) {
return ((QueryFileChooser) result).getSelectedFileName();
} else if (result instanceof JTextArea) {
return ((JTextArea) result).getText();
} else if (result instanceof JToggleButton) {
// JRadioButton and JCheckButton are subclasses of JToggleButton
JToggleButton toggleButton = (JToggleButton) result;
 
if (toggleButton.isSelected()) {
return "true";
} else {
return "false";
}
} else if (result instanceof JSlider) {
return "" + ((JSlider) result).getValue();
} else if (result instanceof JComboBox) {
return (String) (((JComboBox) result).getSelectedItem());
} else if (result instanceof JToggleButton[]) {
// JRadioButton and JCheckButton are subclasses of JToggleButton
// Regrettably, ButtonGroup gives no way to determine
// which button is selected, so we have to search...
JToggleButton[] buttons = (JToggleButton[]) result;
StringBuffer toReturn = null;
 
for (int i = 0; i < buttons.length; i++) {
if (buttons[i].isSelected()) {
if (toReturn == null) {
toReturn = new StringBuffer(buttons[i].getText());
} else {
toReturn.append(", " + buttons[i].getText());
}
}
}
 
if (toReturn == null) {
toReturn = new StringBuffer();
}
 
return toReturn.toString();
} else if (result instanceof QueryScrollPane) {
return ((QueryScrollPane) result).getText();
} else {
throw new IllegalArgumentException("Query class cannot generate"
+ " a string representation for entries of type "
+ result.getClass());
}
}
 
/** Get the preferred number of lines to be used for entry boxes created
* in using addTextArea(). The preferred height is set using
* setTextHeight().
* @return The preferred height in lines.
* @see #addTextArea(String, String, String)
* @see #setTextHeight(int)
*/
public int getTextHeight() {
return _height;
}
 
/** Get the preferred width in characters to be used for entry
* boxes created in using addLine(). The preferred width is set
* using setTextWidth().
* @return The preferred width of an entry box in characters.
* @see #setTextWidth(int)
*/
public int getTextWidth() {
return _width;
}
 
/** Get the current value in the entry with the given name
* and return as an integer. If the entry is not a line,
* choice, or slider, then throw an exception.
* If it is a choice or radio button, then return the
* index of the first selected item.
* @param name The name of the entry.
* @deprecated Use getIntValue(String name) instead.
* @return The value currently in the entry as an integer.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception NumberFormatException If the value of the entry cannot
* be converted to an integer. This is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* choice, line, or slider. This is a runtime exception, so it
* need not be declared explicitly.
*/
public int intValue(String name) throws IllegalArgumentException,
NoSuchElementException, NumberFormatException {
return getIntValue(name);
}
 
/** Notify listeners of the current value of all entries, unless
* those entries have not changed since the last notification.
*/
public void notifyListeners() {
Iterator names = _entries.keySet().iterator();
 
while (names.hasNext()) {
String name = (String) names.next();
_notifyListeners(name);
}
}
 
/** Remove a listener. If the listener has not been added, then
* do nothing.
* @param listener The listener to remove.
* @see #addQueryListener(QueryListener)
*/
public void removeQueryListener(QueryListener listener) {
if (_listeners == null) {
return;
}
 
_listeners.remove(listener);
}
 
/** Set the value in the entry with the given name.
* The second argument must be a string that can be parsed to the
* proper type for the given entry, or an exception is thrown.
* Note that this does NOT trigger the notification of listeners, and
* intended to allow a way to set the query to reflect the current state.
* @param name The name used to identify the entry (when calling get).
* @param value The value to set the entry to.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the value does not parse
* to the appropriate type.
*/
public void set(String name, String value) throws NoSuchElementException,
IllegalArgumentException {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ " \" in the query box.");
}
 
// FIXME: Surely there is a better way to do this...
// We should define a set of inner classes, one for each entry type.
// Currently, this has to be updated each time a new entry type
// is added.
if (result instanceof JTextField) {
((JTextField) result).setText(value);
} else if (result instanceof JTextArea) {
((JTextArea) result).setText(value);
} else if (result instanceof QueryScrollPane) {
((QueryScrollPane) result).setText(value);
} else if (result instanceof JToggleButton) {
// JRadioButton and JCheckButton are subclasses of JToggleButton
Boolean flag = Boolean.valueOf(value);
setBoolean(name, flag.booleanValue());
} else if (result instanceof JSlider) {
Integer parsed = Integer.valueOf(value);
((JSlider) result).setValue(parsed.intValue());
} else if (result instanceof JComboBox) {
((JComboBox) result).setSelectedItem(value);
} else if (result instanceof JToggleButton[]) {
// First, parse the value, which may be a comma-separated list.
Set selectedValues = new HashSet();
StringTokenizer tokenizer = new StringTokenizer(value, ",");
 
while (tokenizer.hasMoreTokens()) {
selectedValues.add(tokenizer.nextToken().trim());
}
 
JToggleButton[] buttons = (JToggleButton[]) result;
 
for (int i = 0; i < buttons.length; i++) {
if (selectedValues.contains(buttons[i].getText())) {
buttons[i].setSelected(true);
} else {
buttons[i].setSelected(false);
}
}
} else if (result instanceof QueryColorChooser) {
((QueryColorChooser) result).setColor(value);
} else if (result instanceof QueryFileChooser) {
((QueryFileChooser) result).setFileName(value);
} else {
throw new IllegalArgumentException("Query class cannot set"
+ " a string representation for entries of type "
+ result.getClass());
}
 
// Record the new value as if it was the previously notified
// value. Thus, any future change from this value will trigger
// notification.
_previous.put(name, value);
}
 
/** Set the value in the entry with the given name and notify listeners.
* The second argument must be a string that can be parsed to the
* proper type for the given entry, or an exception is thrown.
* @param name The name used to identify the entry (when calling get).
* @param value The value to set the entry to.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the value does not parse
* to the appropriate type.
*/
public void setAndNotify(String name, String value)
throws NoSuchElementException, IllegalArgumentException {
set(name, value);
_notifyListeners(name);
}
 
/** Set the background color for all the widgets.
* @param color The background color.
*/
public void setBackground(Color color) {
super.setBackground(color);
_background = color;
 
// Set the background of any components that already exist.
Component[] components = getComponents();
 
for (int i = 0; i < components.length; i++) {
if (!(components[i] instanceof JTextField)) {
components[i].setBackground(_background);
}
}
}
 
/** Set the current value in the entry with the given name.
* If the entry is not a checkbox, then throw an exception.
* Notify listeners that the value has changed.
* @param name The name of the entry.
* @param value The new value of the entry.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* checkbox. This is a runtime exception, so it
* need not be declared explicitly.
*/
public void setBoolean(String name, boolean value)
throws NoSuchElementException, IllegalArgumentException {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ "\" in the query box.");
}
 
if (result instanceof JToggleButton) {
// JRadioButton and JCheckButton are subclasses of JToggleButton
((JToggleButton) result).setSelected(value);
} else {
throw new IllegalArgumentException("Item named \"" + name
+ "\" is not a radio button, and hence does not have "
+ "a boolean value.");
}
 
_notifyListeners(name);
}
 
/** Specify the number of columns to use.
* The default is one. If an integer larger than one is specified
* here, then the queries will be arranged using the specified number
* of columns. As queries are added, they are put in the first row
* until that row is full. Then they are put in the second row, etc.
* @param columns The number of columns.
*/
public void setColumns(int columns) {
if (columns <= 0) {
throw new IllegalArgumentException(
"Query.setColumns() requires a strictly positive "
+ "argument.");
}
 
_columns = columns;
}
 
/** Set the displayed text of an entry that has been added using
* addDisplay.
* Notify listeners that the value has changed.
* @param name The name of the entry.
* @param value The string to display.
* @exception NoSuchElementException If there is no entry with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* display. This is a runtime exception, so it
* need not be declared explicitly.
*/
public void setDisplay(String name, String value)
throws NoSuchElementException, IllegalArgumentException {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ " \" in the query box.");
}
 
if (result instanceof JTextArea) {
JTextArea label = (JTextArea) result;
label.setText(value);
} else {
throw new IllegalArgumentException("Item named \"" + name
+ "\" is not a display, and hence cannot be set using "
+ "setDisplay().");
}
 
_notifyListeners(name);
}
 
/** For line, display, check box, slider, radio button, or choice
* entries made, if the second argument is false, then it will
* be disabled.
* @param name The name of the entry.
* @param value If false, disables the entry.
*/
public void setEnabled(String name, boolean value) {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ " \" in the query box.");
}
 
if (result instanceof JComponent) {
((JComponent) result).setEnabled(value);
} else if (result instanceof JToggleButton[]) {
JToggleButton[] buttons = (JToggleButton[]) result;
 
for (int i = 0; i < buttons.length; i++) {
buttons[i].setEnabled(value);
}
}
}
 
/** Set the displayed text of an item that has been added using
* addLine. Notify listeners that the value has changed.
* @param name The name of the entry.
* @param value The string to display.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* display. This is a runtime exception, so it
* need not be declared explicitly.
*/
public void setLine(String name, String value) {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ " \" in the query box.");
}
 
if (result instanceof JTextField) {
JTextField line = (JTextField) result;
line.setText(value);
} else {
throw new IllegalArgumentException("Item named \"" + name
+ "\" is not a line, and hence cannot be set using "
+ "setLine().");
}
 
_notifyListeners(name);
}
 
/** Specify a message to be displayed above the query.
* @param message The message to display.
*/
public void setMessage(String message) {
if (!_messageScrollPaneAdded) {
_messageScrollPaneAdded = true;
add(_messageScrollPane, 1);
 
// Add a spacer.
add(Box.createRigidArea(new Dimension(0, 10)), 2);
}
 
_messageArea.setText(message);
 
// I'm not sure why we need to add 1 here?
int lineCount = _messageArea.getLineCount() + 1;
 
// Keep the line count to less than 30 lines. If
// we have more than 30 lines, we get a scroll bar.
if (lineCount > 30) {
lineCount = 30;
}
 
_messageArea.setRows(lineCount);
_messageArea.setColumns(_width);
 
// In case size has changed.
validate();
}
 
/** Set the position of an item that has been added using
* addSlider. Notify listeners that the value has changed.
* @param name The name of the entry.
* @param value The value to set the slider position.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry is not a
* slider. This is a runtime exception, so it
* need not be declared explicitly.
*/
public void setSlider(String name, int value) {
Object result = _entries.get(name);
 
if (result == null) {
throw new NoSuchElementException("No item named \"" + name
+ " \" in the query box.");
}
 
if (result instanceof JSlider) {
JSlider theSlider = (JSlider) result;
 
// Set the new slider position.
theSlider.setValue(value);
} else {
throw new IllegalArgumentException("Item named \"" + name
+ "\" is not a slider, and hence cannot be set using "
+ "setSlider().");
}
 
_notifyListeners(name);
}
 
/** Specify the preferred height to be used for entry boxes created
* in using addTextArea(). If this is called multiple times, then
* it only affects subsequent calls.
* @param characters The preferred height.
* @see #addTextArea(String, String, String)
* @see #getTextHeight()
*/
public void setTextHeight(int characters) {
_height = characters;
}
 
/** Specify the preferred width to be used for entry boxes created
* in using addLine(). If this is called multiple times, then
* it only affects subsequent calls.
* @param characters The preferred width.
* @see #getTextWidth()
*/
public void setTextWidth(int characters) {
_width = characters;
}
 
/** Specify a tool tip to appear when the mouse lingers over the label.
* @param name The name of the entry.
* @param tip The text of the tool tip.
*/
public void setToolTip(String name, String tip) {
JLabel label = (JLabel) _labels.get(name);
 
if (label != null) {
label.setToolTipText(tip);
}
}
 
/** Convert the specified string to a color. The string
* has the form "{r, g, b, a}", where each of the letters
* is a number between 0.0 and 1.0, representing red, green,
* blue, and alpha.
* @param description The description of the color, or white
* if any parse error occurs.
* @return A string representing the color.
*/
public static Color stringToColor(String description) {
String[] specArray = description.split("[{},]");
float red = 0f;
float green = 0f;
float blue = 0f;
float alpha = 1.0f;
 
// If any exceptions occur during the attempt to parse,
// then just use the default color.
try {
int i = 0;
 
// Ignore any blank strings that this simple parsing produces.
while (specArray[i].trim().equals("")) {
i++;
}
 
if (specArray.length > i) {
red = Float.parseFloat(specArray[i]);
}
 
i++;
 
while (specArray[i].trim().equals("")) {
i++;
}
 
if (specArray.length > i) {
green = Float.parseFloat(specArray[i]);
}
 
i++;
 
while (specArray[i].trim().equals("")) {
i++;
}
 
if (specArray.length > i) {
blue = Float.parseFloat(specArray[i]);
}
 
i++;
 
while (specArray[i].trim().equals("")) {
i++;
}
 
if (specArray.length > i) {
alpha = Float.parseFloat(specArray[i]);
}
} catch (Exception ex) {
// Ignore and use default color.
}
return new Color(red, green, blue, alpha);
}
 
/** Get the current value in the entry with the given name,
* and return as a String. All entry types support this.
* Note that this method should be called from the event dispatch
* thread, since it needs to query to UI widgets for their current
* values. If it is called from another thread, there is no
* assurance that the value returned will be the current value.
* @param name The name of the entry.
* @deprecated Use getStringValue(String name) instead.
* @return The value currently in the entry as a String.
* @exception NoSuchElementException If there is no item with the
* specified name. Note that this is a runtime exception, so it
* need not be declared explicitly.
* @exception IllegalArgumentException If the entry type does not
* have a string representation (this should not be thrown).
*/
public String stringValue(String name) throws NoSuchElementException,
IllegalArgumentException {
return getStringValue(name);
}
 
///////////////////////////////////////////////////////////////////
//// public variables ////
 
/** The default height of entries created with addText(). */
public static final int DEFAULT_ENTRY_HEIGHT = 10;
 
/** The default width of entries created with addLine(). */
public static final int DEFAULT_ENTRY_WIDTH = 30;
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
 
/** Add a label and a widget to the panel.
* @param name The name of the entry.
* @param label The label.
* @param widget The interactive entry to the right of the label.
* @param entry The object that contains user data.
*/
protected void _addPair(String name, JLabel label, Component widget,
Object entry) {
// Surely there is a better layout manager in swing...
// Note that Box and BoxLayout do not work because they do not
// support gridded layout.
_constraints.gridwidth = 1;
_constraints.insets = _leftPadding;
_grid.setConstraints(label, _constraints);
_entryPanel.add(label);
 
_constraints.insets = _noPadding;
 
if ((_columns > 1) && (((_entries.size() + 1) % _columns) != 0)) {
_constraints.gridwidth = 1;
} else {
_constraints.gridwidth = GridBagConstraints.REMAINDER;
}
 
_grid.setConstraints(widget, _constraints);
_entryPanel.add(widget);
 
_entries.put(name, entry);
_labels.put(name, label);
_previous.put(name, getStringValue(name));
 
Dimension preferredSize = _entryPanel.getPreferredSize();
 
// Add some slop to the width to take in to account
// the width of the vertical scrollbar.
preferredSize.width += 25;
 
// Applets seem to need this, see CT/SigmaDelta
_widgetsHeight += widget.getPreferredSize().height;
preferredSize.height = _widgetsHeight;
 
Toolkit tk = Toolkit.getDefaultToolkit();
 
if (preferredSize.height > tk.getScreenSize().height) {
// Fudge factor to keep this window smaller than the screen
// height. CGSUnitBase and the Code Generator are good tests.
preferredSize.height = (int) (tk.getScreenSize().height * 0.75);
_entryScrollPane.setPreferredSize(preferredSize);
}
 
_entryScrollPane.setPreferredSize(preferredSize);
 
// Call revalidate for the scrollbar.
_entryPanel.revalidate();
}
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
 
/** The background color as set by setBackground().
* This defaults to null, which indicates that the background
* is the same as the container.
*/
protected Color _background = null;
 
/** Standard constraints for use with _grid. */
protected GridBagConstraints _constraints;
 
/** Layout control. */
protected GridBagLayout _grid;
 
/** List of registered listeners. */
protected Vector _listeners;
 
///////////////////////////////////////////////////////////////////
//// friendly methods ////
 
/** Notify all registered listeners that something changed for the
* specified entry, if it indeed has changed. The getStringValue()
* method is used to check the current value against the previously
* notified value, or the original value if there have been no
* notifications.
* @param name The entry that may have changed.
*/
void _notifyListeners(String name) {
if (_listeners != null) {
String previous = (String) _previous.get(name);
String newValue = getStringValue(name);
 
if (newValue.equals(previous)) {
return;
}
 
// Store the new value to prevent repeated notification.
// This must be done before listeners are notified, because
// the notified listeners might do something that again triggers
// notification, and we do not want that notification to occur
// if the value has not changed.
_previous.put(name, newValue);
 
Enumeration listeners = _listeners.elements();
 
while (listeners.hasMoreElements()) {
QueryListener queryListener = (QueryListener) (listeners
.nextElement());
queryListener.changed(name);
}
}
}
 
///////////////////////////////////////////////////////////////////
//// private variables ////
// The number of columns.
private int _columns = 1;
 
// The hashtable of items in the query.
private Map _entries = new HashMap();
 
// A panel within which the entries are placed.
private JPanel _entryPanel = new JPanel();
 
// A scroll pane that contains the _entryPanel.
private JScrollPane _entryScrollPane;
 
// The number of lines in a text box.
private int _height = DEFAULT_ENTRY_HEIGHT;
 
// The hashtable of labels in the query.
private Map _labels = new HashMap();
 
// Left padding insets.
private Insets _leftPadding = new Insets(0, 10, 0, 0);
 
// Area for messages.
private JTextArea _messageArea = null;
 
// A scroll pane that contains the _messageArea.
private JScrollPane _messageScrollPane;
 
// True if we have added the _messageScrollPane
private boolean _messageScrollPaneAdded = false;
 
// No padding insets.
private Insets _noPadding = new Insets(0, 0, 0, 0);
 
// The hashtable of previous values, indexed by entry name.
private Map _previous = new HashMap();
 
// The sum of the height of the widgets added using _addPair
// If you adjust this, try the GR/Pendulum demo, which has
// only one parameter.
private int _widgetsHeight = 20;
 
// The number of horizontal characters in a text box.
private int _width = DEFAULT_ENTRY_WIDTH;
 
///////////////////////////////////////////////////////////////////
//// inner classes ////
 
/** Listener for "line" and radio button entries.
*/
class QueryActionListener implements ActionListener {
public QueryActionListener(String name) {
_name = name;
}
 
/** Call all registered QueryListeners. */
public void actionPerformed(ActionEvent e) {
_notifyListeners(_name);
}
 
private String _name;
}
 
/** Panel containing an entry box and color chooser.
*/
class QueryColorChooser extends Box implements ActionListener {
public QueryColorChooser(String name, String defaultColor) {
super(BoxLayout.X_AXIS);
//_defaultColor = defaultColor;
_entryBox = new JTextField(defaultColor, _width);
 
JButton button = new JButton("Choose");
button.addActionListener(this);
add(_entryBox);
add(button);
 
// Add the listener last so that there is no notification
// of the first value.
_entryBox.addActionListener(new QueryActionListener(name));
 
// Add a listener for loss of focus. When the entry gains
// and then loses focus, listeners are notified of an update,
// but only if the value has changed since the last notification.
// FIXME: Unfortunately, Java calls this listener some random
// time after the window has been closed. It is not even a
// a queued event when the window is closed. Thus, we have
// a subtle bug where if you enter a value in a line, do not
// hit return, and then click on the X to close the window,
// the value is restored to the original, and then sometime
// later, the focus is lost and the entered value becomes
// the value of the parameter. I don't know of any workaround.
_entryBox.addFocusListener(new QueryFocusListener(name));
 
_name = name;
}
 
public void actionPerformed(ActionEvent e) {
// Read the current color from the text field.
String spec = getSelectedColor().trim();
Color newColor = JColorChooser.showDialog(Query.this,
"Choose Color", stringToColor(spec));
 
if (newColor != null) {
float[] components = newColor.getRGBComponents(null);
StringBuffer string = new StringBuffer("{");
 
// Use the syntax of arrays.
for (int j = 0; j < components.length; j++) {
string.append(components[j]);
 
if (j < (components.length - 1)) {
string.append(",");
} else {
string.append("}");
}
}
 
_entryBox.setText(string.toString());
_notifyListeners(_name);
}
}
 
public String getSelectedColor() {
return _entryBox.getText();
}
 
public void setColor(String name) {
_entryBox.setText(name);
}
 
private JTextField _entryBox;
 
private String _name;
 
//private String _defaultColor;
}
 
/** Panel containing an entry box and file chooser.
*/
class QueryFileChooser extends Box implements ActionListener {
public QueryFileChooser(String name, String defaultName, URI base,
File startingDirectory, boolean allowFiles,
boolean allowDirectories) {
this(name, defaultName, base, startingDirectory, allowFiles,
allowDirectories, Color.white, Color.black);
}
 
public QueryFileChooser(String name, String defaultName, URI base,
File startingDirectory, boolean allowFiles,
boolean allowDirectories, Color background, Color foreground) {
super(BoxLayout.X_AXIS);
_base = base;
_startingDirectory = startingDirectory;
 
if (!allowFiles && !allowDirectories) {
throw new IllegalArgumentException(
"QueryFileChooser: nothing to be chosen.");
}
 
_allowFiles = allowFiles;
_allowDirectories = allowDirectories;
_entryBox = new JTextField(defaultName, _width);
_entryBox.setBackground(background);
_entryBox.setForeground(foreground);
 
JButton button = new JButton("Browse");
button.addActionListener(this);
add(_entryBox);
add(button);
 
// Add the listener last so that there is no notification
// of the first value.
_entryBox.addActionListener(new QueryActionListener(name));
 
// Add a listener for loss of focus. When the entry gains
// and then loses focus, listeners are notified of an update,
// but only if the value has changed since the last notification.
// FIXME: Unfortunately, Java calls this listener some random
// time after the window has been closed. It is not even a
// a queued event when the window is closed. Thus, we have
// a subtle bug where if you enter a value in a line, do not
// hit return, and then click on the X to close the window,
// the value is restored to the original, and then sometime
// later, the focus is lost and the entered value becomes
// the value of the parameter. I don't know of any workaround.
_entryBox.addFocusListener(new QueryFocusListener(name));
 
_name = name;
}
 
public void actionPerformed(ActionEvent e) {
// NOTE: If the last argument is null, then choose a default dir.
JFileChooser fileChooser = new JFileChooser(_startingDirectory);
fileChooser.setApproveButtonText("Select");
 
// FIXME: The following doesn't have any effect.
fileChooser.setApproveButtonMnemonic('S');
 
if (_allowFiles && _allowDirectories) {
fileChooser
.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
} else if (_allowFiles && !_allowDirectories) {
// This is the default.
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
} else if (!_allowFiles && _allowDirectories) {
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} else {
// Usually, we would use InternalErrorException here,
// but if we do, then this package would depend on kernel.util,
// which causes problems when we ship Ptplot.
throw new RuntimeException(
"QueryFileChooser: nothing to be chosen.");
}
 
int returnValue = fileChooser.showOpenDialog(Query.this);
 
if (returnValue == JFileChooser.APPROVE_OPTION) {
if (_base == null) {
// Absolute file name.
try {
_entryBox.setText(fileChooser.getSelectedFile()
.getCanonicalPath());
} catch (IOException ex) {
// If we can't get a path, then just use the name.
_entryBox.setText(fileChooser.getSelectedFile()
.getName());
}
} else {
// Relative file name.
File selectedFile = fileChooser.getSelectedFile();
 
// FIXME: There is a bug here under Windows XP
// at least... Sometimes, the drive ID (like c:)
// is lower case, and sometimes it's upper case.
// When we open a MoML file, it's upper case.
// When we do "save as", it's lower case.
// This despite the fact that both use the same
// file browser to determine the file name.
// Beats me... Consequence is that if you save as,
// then the following relativize call doesn't work
// until you close and reopen the file.
try {
selectedFile = selectedFile.getCanonicalFile();
} catch (IOException ex) {
// Ignore, since we can't do much about it anyway.
}
 
URI relativeURI = _base.relativize(selectedFile.toURI());
_entryBox.setText(relativeURI.toString());
}
 
_notifyListeners(_name);
}
}
 
public String getSelectedFileName() {
return _entryBox.getText();
}
 
public void setFileName(String name) {
_entryBox.setText(name);
}
 
private URI _base;
 
private JTextField _entryBox;
 
private String _name;
 
private File _startingDirectory;
 
private boolean _allowFiles;
 
private boolean _allowDirectories;
}
 
/** Listener for line entries, for when they lose the focus.
*/
class QueryFocusListener implements FocusListener {
public QueryFocusListener(String name) {
_name = name;
}
 
public void focusGained(FocusEvent e) {
// Nothing to do.
}
 
public void focusLost(FocusEvent e) {
// NOTE: Java's lame AWT has no reliable way
// to take action on window closing, so this focus lost
// notification is the only reliable way we have of reacting
// to a closing window. If the previous
// notification was an erroneous one and the value has not
// changed, then no further notification occurs.
// This could be a problem for some users of this class.
_notifyListeners(_name);
}
 
private String _name;
}
 
/** Listener for "CheckBox" and "Choice" entries.
*/
class QueryItemListener implements ItemListener {
public QueryItemListener(String name) {
_name = name;
}
 
/** Call all registered QueryListeners. */
public void itemStateChanged(ItemEvent e) {
_notifyListeners(_name);
}
 
private String _name;
}
 
/** Inner class to tie textArea to scroll pane. */
static class QueryScrollPane extends JScrollPane {
// FindBugs suggests making this class static so as to decrease
// the size of instances and avoid dangling references.
 
public JTextArea textArea;
 
QueryScrollPane(JTextArea c) {
super(c);
textArea = c;
}
 
public String getText() {
String retval = textArea.getText();
return retval;
}
 
public void setText(String s) {
textArea.setText(s);
}
}
 
/** Listener for changes in slider.
*/
class SliderListener implements ChangeListener {
public SliderListener(String name) {
_name = name;
}
 
/** Call all registered QueryListeners. */
public void stateChanged(ChangeEvent event) {
_notifyListeners(_name);
}
 
private String _name;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/gui/CloseListener.java
0,0 → 1,61
/* An interface for listeners that need to be informed when a window closes.
 
Copyright (c) 1998-2005 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.gui;
 
import java.awt.Window;
 
//////////////////////////////////////////////////////////////////////////
//// CloseListener
 
/**
This is an interface for listeners that need to be informed when a
window closes. Note that this is a very small subset of what Java's
WindowListener interface does. This class is a workaround for a bug
in Java's AWT, where components are not informed in any way when the
window that contains them is closed, even though they can have
registered listeners. The listeners are never called, unless the
component is a top-level window. A listener that implements this
interface, by contrast, is informed regardless of whether it is
at the top level. This is used, for example, by the ComponentDialog
class.
@see ComponentDialog
 
@author Edward A. Lee
@version $Id: CloseListener.java,v 1.13 2005/07/08 19:59:07 cxh Exp $
@since Ptolemy II 1.0
@Pt.ProposedRating Green (eal)
@Pt.AcceptedRating Green (janneck)
*/
public interface CloseListener {
/** Notify that the specified window has closed. The second argument,
* if non-null, gives the name of the button that was used to close
* the window.
* @param window The window that closed.
* @param button The name of the button that was used to close the window.
*/
public void windowClosed(Window window, String button);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/gui/QueryListener.java
0,0 → 1,52
/* One line description of file.
 
Copyright (c) 1999-2005 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.gui;
 
import java.util.EventListener;
 
//////////////////////////////////////////////////////////////////////////
//// QueryListener
 
/**
Listener interface for changes in the query box.
 
@author Edward A. Lee
@version $Id: QueryListener.java,v 1.14 2005/07/08 19:59:08 cxh Exp $
@since Ptolemy II 0.3
@Pt.ProposedRating Red (eal)
@Pt.AcceptedRating Red (eal)
*/
public interface QueryListener extends EventListener {
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Called to notify that one of the entries has changed.
* The name of the entry is passed as an argument.
* @param name The name of the entry.
*/
public abstract void changed(String name);
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/gui/ComponentDialog.java
0,0 → 1,303
/* A top-level dialog window containing an arbitrary component.
 
Copyright (c) 1998-2005 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
 
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
 
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
 
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.gui;
 
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
 
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
 
//////////////////////////////////////////////////////////////////////////
//// ComponentDialog
 
/**
 
This class is a modal dialog box that contains an arbitrary component.
It can be used, for example, to put an instance of Query in a
top-level dialog box. The general way to use this class is to create
the component that you wish to have contained in the dialog.
Then pass that component to the constructor of this class. The dialog
is modal, so the statement that creates the dialog will not return
until the user dismisses the dialog. The method buttonPressed()
can then be called to find out whether the user clicked the OK button
or the Cancel button (or any other button specified in the constructor).
Then you can access the component to determine what values were set
by the user.
<p>
If the component that is added implements the CloseListener interface,
then that component is notified when this dialog closes.
 
@see CloseListener
@author Edward A. Lee
@version $Id: ComponentDialog.java,v 1.34 2005/07/08 19:59:07 cxh Exp $
@since Ptolemy II 0.4
@Pt.ProposedRating Yellow (eal)
@Pt.AcceptedRating Yellow (janneck)
*/
public class ComponentDialog extends JDialog {
/** Construct a dialog with the specified owner, title, and component.
* An "OK" and a "Cancel" button are added to the dialog.
* The dialog is placed relative to the owner.
* @param owner The object that, per the user, appears to be
* generating the dialog.
* @param title The title of the dialog.
* @param component The component to insert in the dialog.
*/
public ComponentDialog(Frame owner, String title, Component component) {
this(owner, title, component, null, null);
}
 
/** Construct a dialog with the specified owner, title, component,
* and buttons. The first button is the "default" in that
* it is the one activated by "Enter" or "Return" keys.
* If the last argument is null, then an "OK"
* and a "Cancel" button will be created.
* The dialog is placed relative to the owner.
* @param owner The object that, per the user, appears to be
* generating the dialog.
* @param title The title of the dialog.
* @param component The component to insert in the dialog.
* @param buttons An array of labels for buttons at the bottom
* of the dialog.
*/
public ComponentDialog(Frame owner, String title, Component component,
String[] buttons) {
this(owner, title, component, buttons, null);
}
 
/** Construct a dialog with the specified owner, title, component,
* buttons, and message. The message is placed above the component.
* The first button is the "default" in that
* it is the one activated by "Enter" or "Return" keys.
* If the <i>buttons</i> argument is null, then an "OK"
* and a "Cancel" button will be created.
* The dialog is placed relative to the owner.
* @param owner The object that, per the user, appears to be
* generating the dialog.
* @param title The title of the dialog.
* @param component The component to insert in the dialog.
* @param buttons An array of labels for buttons at the bottom
* of the dialog.
* @param message A message to place above the component, or null
* if no message is needed.
*/
public ComponentDialog(Frame owner, String title, Component component,
String[] buttons, String message) {
super(owner, title, true);
 
// Create a panel that contains the optional message
// and the specified component, separated by a spacing rigid area.
JPanel panel = new JPanel();
 
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
 
if (message != null) {
_messageArea = new JTextArea(message);
_messageArea.setFont(new Font("SansSerif", Font.PLAIN, 12));
_messageArea.setEditable(false);
_messageArea.setLineWrap(true);
_messageArea.setWrapStyleWord(true);
_messageArea.setBackground(getContentPane().getBackground());
 
// Left Justify.
_messageArea.setAlignmentX(0.0f);
panel.add(_messageArea);
panel.add(Box.createRigidArea(new Dimension(0, 10)));
}
 
panel.add(component);
contents = component;
 
if (buttons != null) {
_buttons = buttons;
} else {
_buttons = _defaultButtons;
}
 
_optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_OPTION, null, _buttons, _buttons[0]);
 
// The following code is based on Sun's CustomDialog example...
_optionPane.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
 
// PropertyChange is an extremely non-selective listener,
// so we have to filter...
if (isVisible()
&& (e.getSource() == _optionPane)
&& (prop.equals(JOptionPane.VALUE_PROPERTY) || prop
.equals(JOptionPane.INPUT_VALUE_PROPERTY))) {
Object value = _optionPane.getValue();
 
// Ignore reset.
if (value == JOptionPane.UNINITIALIZED_VALUE) {
return;
}
 
// Reset the JOptionPane's value.
// If you don't do this, then if the user
// presses the same button next time, no
// property change event will be fired.
// Note that this seems to trigger the listener
// again, so the previous line is essential.
_optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
 
if (value instanceof String) {
// A button was pressed...
_buttonPressed = (String) value;
}
 
// Close the window.
setVisible(false);
 
// Take any action that might be associated with
// window closing.
_handleClosing();
 
// Java's AWT yields random results if we do this.
// And anyway, it doesn't work. Components still don't
// have their ComponentListener methods called to indicate
// that they have become invisible.
// dispose();
}
}
});
 
getContentPane().add(_optionPane);
pack();
setResizable(false);
 
if (owner != null) {
setLocationRelativeTo(owner);
} else {
// Center on screen. According to the Java docs,
// passing null to setLocationRelationTo() _may_ result
// in centering on the screen, but it is not required to.
Toolkit tk = Toolkit.getDefaultToolkit();
setLocation((tk.getScreenSize().width - getSize().width) / 2, (tk
.getScreenSize().height - getSize().height) / 2);
}
 
// NOTE: Java's AWT may yield random results if we do the following.
// And anyway, it doesn't work. Components still don't
// have their ComponentListener methods called to indicate
// that they have become invisible.
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 
// Catch closing events so that components are notified if
// the window manager is used to close the window.
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
_handleClosing();
}
});
 
// Make the window visible.
setVisible(true);
}
 
///////////////////////////////////////////////////////////////////
//// public methods ////
 
/** Return the label of the button that triggered closing the
* dialog, or an empty string if none.
* @return The label of the button pressed.
*/
public String buttonPressed() {
return _buttonPressed;
}
 
/** Change the message that was specified in the constructor to
* read as specified. If no message was specified in the constructor,
* then do nothing.
* @param message The new message.
*/
public void setMessage(String message) {
if (_messageArea != null) {
_messageArea.setText(message);
}
}
 
///////////////////////////////////////////////////////////////////
//// protected methods ////
 
/** If the contents of this dialog implements the CloseListener
* interface, then notify it that the window has closed, unless
* notification has already been done (it is guaranteed to be done
* only once).
*/
protected void _handleClosing() {
if ((contents instanceof CloseListener) && !_doneHandleClosing) {
_doneHandleClosing = true;
((CloseListener) contents).windowClosed(this, _buttonPressed);
}
}
 
///////////////////////////////////////////////////////////////////
//// public variables ////
 
/** The component contained by this dialog.
*/
public Component contents;
 
///////////////////////////////////////////////////////////////////
//// protected variables ////
 
/** The label of the button pushed to dismiss the dialog. */
protected String _buttonPressed = "";
 
///////////////////////////////////////////////////////////////////
//// private variables ////
 
/** Button labels. */
private static String[] _buttons;
 
/** Default button labels. */
private static String[] _defaultButtons = { "OK", "Cancel" };
 
/** Indicator that we have notified of window closing. */
private boolean _doneHandleClosing = false;
 
/** The pane with the buttons. */
private JOptionPane _optionPane;
 
/** The container for messages. */
private JTextArea _messageArea;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/FunctionAndName.java
0,0 → 1,32
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
This class is needed because we want to return both a function and its name.
(work-around for java not supporting multi-value return)
*/
 
public class FunctionAndName {
public Function function;
public String name;
 
public FunctionAndName(Function fun, String name) {
this.function = fun;
this.name = name;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Compiler.java
0,0 → 1,76
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Compiles a textual arithmetic expression to a {@link Function}.<p>
*/
class Compiler {
private final SyntaxException exception = new SyntaxException();
private final Lexer lexer = new Lexer(exception);
private final RPN rpn = new RPN(exception);
private final DeclarationParser declParser = new DeclarationParser(exception);
private final OptCodeGen codeGen = new OptCodeGen(exception);
private final SimpleCodeGen simpleCodeGen = new SimpleCodeGen(exception);
private final Declaration decl = new Declaration();
 
double eval(Symbols symbols, String expression) throws SyntaxException {
rpn.setConsumer(simpleCodeGen.setSymbols(symbols));
lexer.scan(expression, rpn);
return simpleCodeGen.getValue();
}
 
FunctionAndName compile(Symbols symbols, String source) throws SyntaxException {
Function fun = null;
decl.parse(source, lexer, declParser);
if (decl.arity == DeclarationParser.UNKNOWN_ARITY) {
try {
double value = eval(symbols, decl.expression);
fun = new Constant(value);
} catch (SyntaxException e) {
if (e != SimpleCodeGen.HAS_ARGUMENTS) {
throw e;
}
// fall-through (see below)
}
}
if (fun == null) { // either decl.arity was set, or an ArityException happened above
symbols.pushFrame();
symbols.addArguments(decl.args);
try {
rpn.setConsumer(codeGen.setSymbols(symbols));
lexer.scan(decl.expression, rpn);
} finally {
symbols.popFrame();
}
int arity = decl.arity;
if (arity == DeclarationParser.UNKNOWN_ARITY) {
arity = codeGen.intrinsicArity;
}
fun = codeGen.getFun(arity);
 
/*
if (decl.name != null && addDefinition) {
symbols.addDefinition(decl.name, fun, decl.arity==DeclarationParser.UNKNOWN_ARITY);
}
*/
}
 
return new FunctionAndName(fun, decl.name);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/FunctionStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class FunctionStack {
private Function[] data = new Function[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(Function b) {
if (size >= data.length) {
Function[] newData = new Function[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
Function[] toArray() {
Function[] trimmed = new Function[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/MoreMath.java
0,0 → 1,183
/*
* Copyright (C) 2006-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
 
package org.javia.arity;
 
class MoreMath extends BaseMath {
private static final double LOG2E = 1.4426950408889634074;
 
public static final double asinh(double x) {
return (x < 0) ? -asinh(-x) : log(x + x + 1/(Math.sqrt(x*x + 1) + x));
}
public static final double acosh(double x) {
return log(x + x - 1/(Math.sqrt(x*x - 1) + x));
}
 
public static final double atanh(double x) {
return (x < 0) ? -atanh(-x) : 0.5 * log(1. + (x + x)/(1 - x));
}
 
public static final double trunc(double x) {
return x >= 0 ? Math.floor(x) : Math.ceil(x);
}
 
public static final double gcd(double x, double y) {
//double remainder = y;
if (Double.isNaN(x) || Double.isNaN(y) ||
Double.isInfinite(x) || Double.isInfinite(y)) {
return Double.NaN;
}
x = Math.abs(x);
y = Math.abs(y);
double save;
while (y > 1e-12) {
save = y;
y = x % y;
x = save;
//Log.log(y);
}
return x > 1e-10 ? x : 0;
}
public static final double lgamma(double x) {
double tmp = x + 5.2421875; //== 607/128. + .5;
return 0.9189385332046727418 //LN_SQRT2PI, ln(sqrt(2*pi))
+ log(
0.99999999999999709182 +
57.156235665862923517 / ++x +
-59.597960355475491248 / ++x +
14.136097974741747174 / ++x +
-0.49191381609762019978 / ++x +
.33994649984811888699e-4 / ++x +
.46523628927048575665e-4 / ++x +
-.98374475304879564677e-4 / ++x +
.15808870322491248884e-3 / ++x +
-.21026444172410488319e-3 / ++x +
.21743961811521264320e-3 / ++x +
-.16431810653676389022e-3 / ++x +
.84418223983852743293e-4 / ++x +
-.26190838401581408670e-4 / ++x +
.36899182659531622704e-5 / ++x
)
+ (tmp-4.7421875)*log(tmp) - tmp
;
}
 
static final double FACT[] = {
1.0,
40320.0,
2.0922789888E13,
6.204484017332394E23,
2.631308369336935E35,
8.159152832478977E47,
1.2413915592536073E61,
7.109985878048635E74,
1.2688693218588417E89,
6.1234458376886085E103,
7.156945704626381E118,
1.8548264225739844E134,
9.916779348709496E149,
1.0299016745145628E166,
1.974506857221074E182,
6.689502913449127E198,
3.856204823625804E215,
3.659042881952549E232,
5.5502938327393044E249,
1.3113358856834524E267,
4.7147236359920616E284,
2.5260757449731984E302,
};
 
public static final double factorial(double x) {
if (x < 0) { // x <= -1 ?
return Double.NaN;
}
if (x <= 170) {
if (Math.floor(x) == x) {
int n = (int)x;
double extra = x;
switch (n & 7) {
case 7: extra *= --x;
case 6: extra *= --x;
case 5: extra *= --x;
case 4: extra *= --x;
case 3: extra *= --x;
case 2: extra *= --x;
case 1: return FACT[n >> 3] * extra;
case 0: return FACT[n >> 3];
}
}
}
return exp(lgamma(x));
}
 
public static final double comb(double n, double k) {
if (n < 0 || k < 0) { return Double.NaN; }
if (n < k) { return 0; }
if (Math.floor(n) == n && Math.floor(k) == k) {
k = Math.min(k, n-k);
if (n <= 170 && 12 < k && k <= 170) {
return factorial(n)/factorial(k)/factorial(n-k);
} else {
double r = 1, diff = n-k;
for (double i = k; i > .5 && r < Double.POSITIVE_INFINITY; --i) {
r *= (diff+i)/i;
}
return r;
}
} else {
return exp(lgamma(n) - lgamma(k) - lgamma(n-k));
}
}
 
public static final double perm(double n, double k) {
if (n < 0 || k < 0) { return Double.NaN; }
if (n < k) { return 0; }
if (Math.floor(n) == n && Math.floor(k) == k) {
if (n <= 170 && 10 < k && k <= 170) {
return factorial(n)/factorial(n-k);
} else {
double r = 1, limit = n-k+.5;
for (double i = n; i > limit && r < Double.POSITIVE_INFINITY; --i) {
r *= i;
}
return r;
}
} else {
return exp(lgamma(n) - lgamma(n-k));
}
}
 
public static final double log2(double x) {
return log(x) * LOG2E;
}
 
private static final boolean isPiMultiple(double x) {
return x % Math.PI == 0;
}
 
public static final int intLog10(double x) {
//an alternative implem is using a for loop.
return (int)Math.floor(log10(x));
//return (int)log10(x);
}
 
public static final double intExp10(int exp) {
return Double.parseDouble("1E" + exp);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Util.java
0,0 → 1,149
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Contains static helper methods for formatting double values.
*/
public class Util {
/*
private static String replace(String str, String what, String repl) {
int pos = str.indexOf(what);
while (pos != -1) {
str = str.substring(0, pos) + repl + str.substring(pos + what.length());
pos = str.indexOf(what);
}
//Log.log("replaced: '"+str+"'");
return str;
}
*/
 
/** Returns a number which is an approximation of v (within maxError)
and which has fewer digits in base-10).
@param value the value to be approximated
@param maxError the maximum deviation from value
@return an approximation with a more compact base-10 representation.
*/
public static double shortApprox(double value, double maxError) {
final double v = Math.abs(value);
final double tail = MoreMath.intExp10(MoreMath.intLog10(Math.abs(maxError)));
final double ret = Math.floor(v/tail +.5)*tail;
return (value < 0) ? -ret : ret;
}
 
/**
Returns an approximation with no more than maxLen chars.
@param str the value to truncate (e.g. "-2.898983455E20")
@param maxLen the maximum number of characters in the returned string
@return a truncation no longer then maxLen (e.g. "-2.8E20" for maxLen=7).
*/
public static String sizeTruncate(String str, int maxLen) {
int ePos = str.lastIndexOf('E');
String tail = (ePos != -1) ? str.substring(ePos) : "";
int tailLen = tail.length();
int maxHeadLen = maxLen - tailLen;
return str.substring(0, Math.min(str.length()-tailLen, maxHeadLen)) + tail;
}
 
/**
Rounds by dropping roundingDigits of double precision
(similar to 'hidden precision digits' on calculators),
and formats to String.
@param v the value to be converted to String
@param roundingDigits the number of 'hidden precision' digits (e.g. 2).
@return a String representation of v
*/
public static String doubleToString(double v, int roundingDigits) {
if (roundingDigits > 13) {
roundingDigits = 0;
}
int roundingStart = roundingDigits == 0 ? 17 : 15 - roundingDigits;
 
String str = Double.toString(Math.abs(v));
StringBuffer buf = new StringBuffer(str);
int ePos = str.lastIndexOf('E');
int exp = (ePos != -1) ? Integer.parseInt(str.substring(ePos + 1)) : 0;
if (ePos != -1) {
buf.setLength(ePos);
}
int len = buf.length();
 
//remove dot
int dotPos;
for (dotPos = 0; dotPos < len && buf.charAt(dotPos) != '.';) ++dotPos;
exp += dotPos;
if (dotPos < len) {
buf.deleteCharAt(dotPos);
--len;
}
 
//round
for (int p = 0; p < len && buf.charAt(p) == '0'; ++p) {
++roundingStart;
}
 
if (roundingStart < len) {
if (buf.charAt(roundingStart) >= '5') {
int p;
for (p = roundingStart-1; p >= 0 && buf.charAt(p)=='9'; --p) {
buf.setCharAt(p, '0');
}
if (p >= 0) {
buf.setCharAt(p, (char)(buf.charAt(p)+1));
} else {
buf.insert(0, '1');
++roundingStart;
++exp;
}
}
buf.setLength(roundingStart);
}
 
//re-insert dot
if ((exp < -5) || (exp > 10)) {
buf.insert(1, '.');
--exp;
} else {
for (int i = len; i < exp; ++i) {
buf.append('0');
}
buf.insert((exp<0)? 0 : exp, '.');
for (int i = exp; i <= 0; ++i) {
buf.insert(0, '0');
}
exp = 0;
}
len = buf.length();
//remove trailing dot and 0s.
int tail;
for (tail = len-1; tail >= 0 && buf.charAt(tail) == '0'; --tail) {
buf.deleteCharAt(tail);
}
if (tail >= 0 && buf.charAt(tail) == '.') {
buf.deleteCharAt(tail);
}
 
if (exp != 0) {
buf.append('E').append(exp);
}
if (v < 0) {
buf.insert(0, '-');
}
return buf.toString();
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/SimpleCodeGen.java
0,0 → 1,99
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/* Non-optimizing Code Generator
Reads tokens in RPN (Reverse Polish Notation) order,
and generates VM opcodes,
without any optimization.
*/
 
class SimpleCodeGen extends TokenConsumer {
private CompiledFunction compiledFunction = new CompiledFunction();
static final SyntaxException HAS_ARGUMENTS = new SyntaxException();
 
ByteStack code = new ByteStack();
DoubleStack consts = new DoubleStack();
FunctionStack funcs = new FunctionStack();
 
//String argNames[];
Symbols symbols;
 
SyntaxException exception;
 
SimpleCodeGen(SyntaxException exception) {
this.exception = exception;
}
 
SimpleCodeGen setSymbols(Symbols symbols) {
this.symbols = symbols;
return this;
}
 
//@Override
void start() {
code.clear();
consts.clear();
funcs.clear();
}
void push(Token token) throws SyntaxException {
byte op;
switch (token.id) {
case Lexer.NUMBER:
op = VM.CONST;
consts.push(token.value);
break;
case Lexer.CONST:
case Lexer.CALL:
Symbol symbol = symbols.lookup(token.name, token.arity);
if (symbol == null) {
throw exception.set("undefined '" + token.name + "' with arity " + token.arity, token.position);
}
if (symbol.op > 0) { // built-in
op = symbol.op;
if (op >= VM.LOAD0 && op <= VM.LOAD4) {
throw HAS_ARGUMENTS.set("eval() on implicit function", exception.position);
}
} else if (symbol.fun != null) { // function call
op = VM.CALL;
funcs.push(symbol.fun);
} else { // variable reference
op = VM.CONST;
consts.push(symbol.value);
}
break;
default:
op = token.vmop;
if (op <= 0) {
throw new Error("wrong vmop: " + op);
}
}
code.push(op);
}
double getValue() {
compiledFunction.init(0, code.toArray(), consts.toArray(), funcs.toArray());
try {
return compiledFunction.eval();
} catch (ArityException e) {
throw new Error("" + e); //never
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/UnitTest.java
0,0 → 1,345
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class EvalCase {
String expr;
double result;
static final double ERR = -2, FUN = -3;
 
EvalCase(String expr, double result) {
this.expr = expr;
this.result = result;
}
}
 
class TestEval {
static EvalCase cases[] = {
new EvalCase(".", 0),
new EvalCase("1+.", 1),
new EvalCase("1", 1),
new EvalCase("\u03c0", Math.PI),
new EvalCase("2\u00d73", 6), //2*3
new EvalCase("1+\u221a9*2", 7), //1+sqrt(9)*2
new EvalCase("3\u221a 4", 6), //3*sqrt(4)
new EvalCase("\u221a16sin(2\u03c0/4)", 4), //sqrt(16)*sin(2pi/4)
new EvalCase("1+", EvalCase.ERR),
new EvalCase("1+1", 2),
new EvalCase("1+-1", 0),
new EvalCase("-0.5", -.5),
new EvalCase("+1e2", 100),
new EvalCase("-2^3!", -64),
new EvalCase("(-2)^3!", 64),
new EvalCase("-2^1^2", -2),
new EvalCase("--1", 1),
new EvalCase("-3^--2", -9),
new EvalCase("1+2)(2+3", 15),
new EvalCase("1+2)!^-2", 1./36),
new EvalCase("sin(0)", 0),
new EvalCase("cos(0)", 1),
new EvalCase("sin(-1--1)", 0),
new EvalCase("-(2+1)*-(4/2)", 6),
new EvalCase("-.5E-1", -.05),
new EvalCase("1E1.5", EvalCase.ERR),
new EvalCase("2 3 4", 24),
new EvalCase("pi", Math.PI),
new EvalCase("e", Math.E),
new EvalCase("sin(pi/2)", 1),
new EvalCase("f=sin(2x)", EvalCase.FUN),
new EvalCase("f(pi/2)", 0),
new EvalCase("a=3", 3),
new EvalCase("b=a+1", 4),
new EvalCase("f(x, y) = x*(y+1)", EvalCase.FUN),
new EvalCase("f(a, b-a)", 6),
new EvalCase(" f(a pi/4)", -1),
new EvalCase("f ( 1 + 1 , a+1)", 10),
new EvalCase("g(foo) = f (f(foo, 1)pi/2)", EvalCase.FUN),
new EvalCase("g(.5*2)", 0),
new EvalCase("NaN", Double.NaN),
new EvalCase("Inf", Double.POSITIVE_INFINITY),
new EvalCase("Infinity", Double.POSITIVE_INFINITY),
new EvalCase("-Inf", Double.NEGATIVE_INFINITY),
new EvalCase("0/0", Double.NaN)
};
 
private static boolean equal(double a, double b) {
return Math.abs(a-b) < 1E-15 ||
Double.doubleToLongBits(a) == Double.doubleToLongBits(b);
}
 
static boolean testEval() throws ArityException {
final String spaces = " ";
boolean allOk = true;
Symbols symbols = new Symbols();
for (int i = 0; i < cases.length; ++i) {
EvalCase c = cases[i];
String strResult;
boolean ok;
try {
double actual;
if (Symbols.isDefinition(c.expr)) {
FunctionAndName fan = symbols.compile(c.expr);
symbols.define(fan);
Function f = fan.function;
actual = f.arity()==0 ? f.eval() : EvalCase.FUN;
strResult = (f.arity()==0 ? Util.doubleToString(actual, 1) : f.toString());
} else {
actual = symbols.eval(c.expr);
strResult = Util.doubleToString(actual, 1);
}
ok = equal(c.result, actual);
} catch (SyntaxException e) {
strResult = e.toString();
ok = c.result == EvalCase.ERR;
}
System.out.println((ok ? "" : "failed (expected " + c.result + "): ")
+ c.expr
+ spaces.substring(0, Math.max(15-c.expr.length(), 0)) + " = "
+ strResult);
if (!ok) {
allOk = false;
}
}
return allOk;
}
}
 
 
class FormatCase {
public FormatCase(int rounding, double v, String s) {
this.rounding = rounding;
this.val = v;
this.res = s;
}
public int rounding;
public double val;
public String res;
}
 
class TestFormat {
static FormatCase cases[] = {
new FormatCase(0, 0.1, "0.1"),
new FormatCase(0, 0.12, "0.12"),
new FormatCase(0, 0.001, "0.001"),
new FormatCase(0, 0.0012, "0.0012"),
new FormatCase(0, 0.0000001, "1E-7"),
new FormatCase(0, 0.00000012, "1.2E-7"),
new FormatCase(0, 0.123456789012345, "0.123456789012345"),
 
new FormatCase(0, 0, "0"),
new FormatCase(0, 1, "1"),
new FormatCase(0, 12, "12"),
new FormatCase(0, 1234567890., "1234567890"),
new FormatCase(0, 1000000000., "1000000000"),
new FormatCase(0, 1.23456789012345, "1.23456789012345"),
new FormatCase(0, 12345.6789012345, "12345.6789012345"),
new FormatCase(0, 1234567890.12345, "1234567890.12345"),
new FormatCase(0, 123456789012345., "1.23456789012345E14"),
new FormatCase(0, 100000000000000., "1E14"),
new FormatCase(0, 120000000000000., "1.2E14"),
new FormatCase(0, 100000000000001., "1.00000000000001E14"),
 
new FormatCase(2, 0.1, "0.1"),
new FormatCase(2, 0.00000012, "1.2E-7"),
new FormatCase(1, 0.123456789012345, "0.12345678901235"),
 
new FormatCase(2, 0, "0"),
new FormatCase(1, 1.23456789012345, "1.2345678901235"),
new FormatCase(2, 1.23456789012345, "1.234567890123"),
new FormatCase(0, 12345.6789012345, "12345.6789012345"),
new FormatCase(1, 1234567890.12345, "1234567890.1235"),
new FormatCase(2, 123456789012345., "1.234567890123E14"),
new FormatCase(1, 100000000000001., "1E14"),
 
new FormatCase(0, 12345678901234567., "1.2345678901234568E16"),
new FormatCase(1, 12345678901234567., "1.2345678901235E16"),
 
new FormatCase(0, 99999999999999999., "1E17"),
new FormatCase(0, 9999999999999999., "1E16"),
new FormatCase(0, 999999999999999., "9.99999999999999E14"),
new FormatCase(1, 999999999999999., "1E15"),
new FormatCase(1, 999999999999994., "9.9999999999999E14"),
 
new FormatCase(1, MoreMath.log2(1+.00002), "00000.28853612282487")
};
 
static boolean testFormat() {
boolean ret = true;
for (int i = 0; i < cases.length; ++i) {
FormatCase c = cases[i];
double v = Double.parseDouble(c.res);
if (c.rounding == 0 && v != c.val) {
System.out.println("wrong test? " + c.res + " " + v + " " + c.val);
}
String res = Util.doubleToString(c.val, c.rounding);
if (!res.equals(c.res)) {
System.out.println("Expected '" + c.res + "', got '" + res + "'. " + Double.toString(c.val));
ret = false;
}
int nKeep = c.rounding == 0 ? 17 : 15 - c.rounding;
//System.out.println("" + Double.toString(c.val) + " " + Util.round(c.val, nKeep) + " " + c.res + ", got " + res);
}
return ret;
}
}
 
/**
Runs unit-tests.<p>
Usage: java -jar arity.jar
*/
public class UnitTest {
/**
Takes a single command-line argument, an expression; compiles and prints it.<p>
Without arguments, runs the unit tests.
@throws SyntaxException if there are errors compiling the expression.
*/
public static void main(String argv[]) throws SyntaxException, ArityException {
int size = argv.length;
if (size == 0) {
runUnitTests();
profile();
} else if (size == 1 && argv[0].equals("-profile")) {
profile();
} else {
Symbols symbols = new Symbols();
for (int i = 0; i < size; ++i) {
FunctionAndName fan = symbols.compile(argv[i]);
symbols.define(fan);
}
profile(symbols, argv[size-1]);
}
}
 
static void profile(Symbols symbols, String str) throws SyntaxException, ArityException {
Function f = symbols.compile(str).function;
System.out.println("\n" + str + ": " + f);
 
Runtime runtime = Runtime.getRuntime();
 
runtime.gc();
/*
long m1 = runtime.freeMemory();
for (int i = 0; i < 200; ++i) {
symbols.compile(str);
}
long m2 = runtime.freeMemory();
System.out.println("compilation memory: " + (m1 - m2)/200 + " bytes");
*/
runtime.gc();
long t1 = System.currentTimeMillis();
for (int i = 0; i < 1000; ++i) {
symbols.compile(str);
}
long t2 = System.currentTimeMillis();
System.out.println("compilation time: " + (t2 - t1) + " us");
double args[] = new double[f.arity()];
/*
runtime.gc();
m1 = runtime.freeMemory();
f.eval(args);
m2 = runtime.freeMemory();
if (m2 != m1) {
System.out.println("execution memory: " + (m1 - m2) + " bytes");
}
*/
runtime.gc();
t1 = System.currentTimeMillis();
for (int i = 0; i < 100000; ++i) {
f.eval(args);
}
t2 = System.currentTimeMillis();
long delta = t2 - t1;
System.out.println("execution time: " + (delta > 100 ? ""+delta/100.+" us" : ""+delta+" ns"));
}
 
private static final String profileCases[] = {
//"1+1",
"(100.5 + 20009.999)*(7+4+3)/(5/2)^3!)*2",
"fun1(x)=(x+2)*(x+3)",
"otherFun(x)=(fun1(x-1)*x+1)*(fun1(2-x)+10)",
"log(x+30.5, 3)^.7*sin(x+.5)"
};
 
private static void profile() {
String cases[] = profileCases;
Symbols symbols = new Symbols();
try {
for (int i = 0; i < cases.length; ++i) {
symbols.define(symbols.compile(cases[i]));
profile(symbols, cases[i]);
}
} catch (Exception e) {
throw new Error("" + e);
}
}
 
static void runUnitTests() {
checkCounter = 0;
 
cheq(MoreMath.log(-1), Double.NaN);
cheq(MoreMath.log(-0.03), Double.NaN);
cheq(MoreMath.intLog10(-0.03), 0);
cheq(MoreMath.intLog10(0.03), -2);
cheq(MoreMath.intExp10(3), 1000);
cheq(MoreMath.intExp10(-1), 0.1);
cheq(Util.shortApprox( 1.235, 0.02), 1.24);
cheq(Util.shortApprox( 1.235, 0.4), 1.2000000000000002);
cheq(Util.shortApprox(-1.235, 0.02), -1.24);
cheq(Util.shortApprox(-1.235, 0.4), -1.2000000000000002);
 
check(TestFormat.testFormat());
try {
check(TestEval.testEval());
} catch (ArityException e) {
System.out.println(""+e);
}
 
if (!allOk) {
System.out.println("\n*** Some tests FAILED ***\n");
System.exit(1);
} else {
System.out.println("\n*** All tests passed OK ***\n");
}
}
 
static void cheq(double v1, double v2) {
++checkCounter;
if (v1 != v2 && !(Double.isNaN(v1) && Double.isNaN(v2))) {
allOk = false;
//Log.log("check equal " + checkCounter + " failed: " + v1 + " " + v2);
}
}
static void check(boolean cond) {
++checkCounter;
if (!cond) {
allOk = false;
//Log.log("check " + checkCounter + " failed");
}
}
 
static boolean allOk = true;
static int checkCounter = 0;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Lexer.java
0,0 → 1,176
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Lexer {
static final int
ADD = 1,
SUB = 2,
MUL = 3,
DIV = 4,
MOD = 5,
UMIN = 6,
POWER = 7,
FACT = 8,
NUMBER = 9,
CONST = 10,
CALL = 11,
COMMA = 12,
LPAREN = 13,
RPAREN = 14,
END = 15,
SQRT = 16;
static final Token
TOK_ADD = new Token(ADD, 3, Token.LEFT, VM.ADD),
TOK_SUB = new Token(SUB, 3, Token.LEFT, VM.SUB),
 
TOK_MUL = new Token(MUL, 4, Token.LEFT, VM.MUL),
TOK_DIV = new Token(DIV, 4, Token.LEFT, VM.DIV),
TOK_MOD = new Token(MOD, 4, Token.LEFT, VM.MOD),
 
TOK_UMIN = new Token(UMIN, 5, Token.PREFIX, VM.UMIN),
 
TOK_POWER = new Token(POWER, 6, Token.RIGHT, VM.POWER),
TOK_FACT = new Token(FACT, 7, Token.SUFIX, VM.FACT),
TOK_SQRT = new Token(SQRT, 8, Token.PREFIX, VM.SQRT),
 
TOK_LPAREN = new Token(LPAREN, 1, Token.PREFIX, 0),
TOK_RPAREN = new Token(RPAREN, 2, 0, 0),
TOK_COMMA = new Token(COMMA, 1, 0, 0),
TOK_END = new Token(END, 0, 0, 0),
 
TOK_NUMBER = new Token(NUMBER, 20, 0, 0),
TOK_CONST = new Token(CONST, 20, 0, 0);
 
private static final String WHITESPACE = " \n\r\t";
private static final char END_MARKER = '$';
private char[] input = new char[32];
private int pos;
private SyntaxException exception;
 
Lexer(SyntaxException exception) {
this.exception = exception;
init("");
}
 
void scan(String str, TokenConsumer consumer) throws SyntaxException {
init(str);
consumer.start();
Token token;
do {
int savePos = pos;
token = nextToken();
token.position = savePos;
consumer.push(token);
} while (token != TOK_END);
}
 
void init(String str) {
exception.expression = str;
int len = str.length();
if (input.length < len + 1) {
input = new char[len+1];
}
str.getChars(0, len, input, 0);
input[len] = END_MARKER;
pos = 0;
}
 
Token nextToken() throws SyntaxException {
while (WHITESPACE.indexOf(input[pos]) != -1) {
++pos;
}
 
char c = input[pos];
int begin = pos++;
 
switch (c) {
case '!': return TOK_FACT;
case END_MARKER: return TOK_END;
case '%': return TOK_MOD;
case '(': return TOK_LPAREN;
case ')': return TOK_RPAREN;
case '*': return TOK_MUL;
case '+': return TOK_ADD;
case ',': return TOK_COMMA;
case '-': return TOK_SUB;
case '/': return TOK_DIV;
}
if (c == '^') {
return TOK_POWER;
}
 
int p = pos;
if (('0' <= c && c <= '9') || c == '.') {
while (('0' <= c && c <= '9') || c == '.' || c == 'E' || c == 'e') {
if ((c == 'E' || c == 'e') && input[p] == '-') { //accept '-' only after E
++p;
}
c = input[p++];
}
pos = p-1;
String nbStr = String.valueOf(input, begin, p-1-begin);
try {
// parse single dot as 0
if (nbStr.equals(".")) {
return TOK_NUMBER.setValue(0);
} else {
double numberValue = Double.parseDouble(nbStr);
return TOK_NUMBER.setValue(numberValue);
}
} catch (NumberFormatException e) {
throw exception.set("invalid number '" + nbStr + "'", begin);
}
} else if (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z')) {
do {
c = input[p++];
} while (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
('0' <= c && c <= '9'));
String nameValue = String.valueOf(input, begin, p-1-begin);
while (WHITESPACE.indexOf(c) != -1) {
c = input[p++];
}
if (c == '(') {
pos = p;
return (new Token(CALL, 0, Token.PREFIX, 0)).setAlpha(nameValue);
} else {
pos = p-1;
return TOK_CONST.setAlpha(nameValue);
}
} else if ((c >= '\u0391' && c <= '\u03a9') || (c >= '\u03b1' && c <= '\u03c9')) {
return TOK_CONST.setAlpha(""+c);
} else {
switch (c) {
case '^':
return TOK_POWER;
case '\u00d7':
return TOK_MUL;
case '\u00f7':
return TOK_DIV;
case '\u2212':
return TOK_SUB;
case '\u221a':
return TOK_SQRT;
default:
throw exception.set("invalid character '" + c + "'", begin);
}
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Token.java
0,0 → 1,71
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Token {
//kind
static final int
PREFIX = 1,
LEFT = 2,
RIGHT = 3,
SUFIX = 4;
 
final int priority;
final int assoc;
final int id;
final byte vmop;
 
double value = 0; //for NUMBER only
String name = null; //for CONST & CALL
int arity;
int position; //pos inside expression
 
Token(int id, int priority, int assoc, int vmop) {
this.id = id;
this.priority = priority;
this.assoc = assoc;
this.vmop = (byte)vmop;
arity = id == Lexer.CALL ? 1 : Symbol.CONST_ARITY;
}
Token setPos(int pos) {
this.position = pos;
return this;
}
 
Token setValue(double value) {
this.value = value;
return this;
}
 
Token setAlpha(String alpha) {
name = alpha;
return this;
}
 
public String toString() {
switch (id) {
case Lexer.NUMBER:
return "" + value;
case Lexer.CALL:
return name + '(' + arity + ')';
case Lexer.CONST:
return name;
}
return "" + id;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/VM.java
0,0 → 1,117
// This file is automatically generated by the build.py script. Do not edit!
 
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class VM {
 
public static final byte
RESERVED = 0,
CONST = 1,
CALL = 2,
ADD = 3,
SUB = 4,
MUL = 5,
DIV = 6,
MOD = 7,
RND = 8,
UMIN = 9,
POWER = 10,
FACT = 11,
SQRT = 12,
CBRT = 13,
EXP = 14,
LOG = 15,
SIN = 16,
COS = 17,
TAN = 18,
ASIN = 19,
ACOS = 20,
ATAN = 21,
SINH = 22,
COSH = 23,
TANH = 24,
ASINH = 25,
ACOSH = 26,
ATANH = 27,
ABS = 28,
FLOOR = 29,
CEIL = 30,
SIGN = 31,
MIN = 32,
MAX = 33,
GCD = 34,
COMB = 35,
PERM = 36,
LOAD0 = 37,
LOAD1 = 38,
LOAD2 = 39,
LOAD3 = 40,
LOAD4 = 41,
BYTECODE_END = 42;
 
public static final String[] opcodeName = {
"reserved",
"const",
"call",
"add",
"sub",
"mul",
"div",
"mod",
"rnd",
"umin",
"power",
"fact",
"sqrt",
"cbrt",
"exp",
"log",
"sin",
"cos",
"tan",
"asin",
"acos",
"atan",
"sinh",
"cosh",
"tanh",
"asinh",
"acosh",
"atanh",
"abs",
"floor",
"ceil",
"sign",
"min",
"max",
"gcd",
"comb",
"perm",
"load0",
"load1",
"load2",
"load3",
"load4",
"bytecode_end"
};
 
public static final byte[] builtinArity =
{-1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1};
 
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/BaseMath.java
0,0 → 1,65
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
 
package org.javia.arity;
 
// This class is a replacement for BaseMath.java to be used on Java 1.5 and later
class BaseMath {
public static final double atan(double x) {
return Math.atan(x);
}
public static final double asin(double x) {
return Math.asin(x);
}
 
public static final double acos(double x) {
return Math.acos(x);
}
 
public static final double exp(double x) {
return Math.exp(x);
}
 
public static final double log(double x) {
return Math.log(x);
}
 
public static final double sinh(double x) {
return Math.sinh(x);
}
 
public static final double cosh(double x) {
return Math.cosh(x);
}
 
public static final double tanh(double x) {
return Math.tanh(x);
}
 
public static final double cbrt(double x) {
return Math.cbrt(x);
}
public static final double pow(double x, double y) {
return Math.pow(x, y);
}
 
public static final double log10(double x) {
return Math.log10(x);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Function.java
0,0 → 1,94
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Abstract base class for functions.<p>
A function has an arity (the number of arguments), and a way for evaluation
given the values of the arguments.<p>
Derive from this class to create user-defined functions.
 
<h3>Thread safety</h3>
Assuming the user didn't subclass Function to define user functions,
the compiled Functions are thread-safe
(the same Function instance can be evaluated from multiple threads without locking).<p>
 
Whatsmore, parallel evaluations of the same instance from multiple threads are not
serialized (good).<p>
 
If the user subclasses Function, he is responsible for the thread-safety of
his user-defined Functions.
*/
 
abstract public class Function {
private int cachedArity = -1;
 
/**
Gives the arity of this function.
@return the arity (the number of arguments). Arity >= 0.
*/
public int arity() {
if (cachedArity == -1) {
cachedArity = 0;
for (int i = 0; i < 5; ++i) {
double args[] = new double[i];
try {
eval(args);
cachedArity = i;
break;
} catch (ArityException e) {
//ignore, continue
}
}
}
return cachedArity;
}
 
/**
Evaluates an arity-0 function (a function with no arguments).
@return the value of the function
*/
public double eval() throws ArityException {
throw new ArityException("Didn't expect 0 args");
}
 
public double eval(double x) throws ArityException {
throw new ArityException("Didn't expect 1 args");
}
 
public double eval(double x, double y) throws ArityException {
throw new ArityException("Didn't expect 2 args");
}
 
/**
Evaluates the function given the argument values.
@param args array containing the arguments.
@return the value of the function
@throws ArityException if args.length != arity.
*/
public double eval(double args[]) throws ArityException {
switch (args.length) {
case 0:
return eval();
case 1:
return eval(args[0]);
case 2:
return eval(args[0], args[1]);
}
throw new ArityException("unexpected " + args.length + " args");
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Declaration.java
0,0 → 1,50
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Declaration {
private static final String NO_ARGS[] = {};
String name;
String args[];
int arity;
String expression;
 
void parse(String source, Lexer lexer, DeclarationParser declParser) throws SyntaxException {
int equalPos = source.indexOf('=');
String decl;
 
if (equalPos == -1) {
decl = null;
expression = source;
name = null;
args = NO_ARGS;
arity = DeclarationParser.UNKNOWN_ARITY;
} else {
decl = source.substring(0, equalPos);
expression = source.substring(equalPos + 1);
lexer.scan(decl, declParser);
name = declParser.name;
args = declParser.argNames();
arity = declParser.arity;
}
/*
if (arity == DeclarationParser.UNKNOWN_ARITY) {
args = IMPLICIT_ARGS;
}
*/
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/OptCodeGen.java
0,0 → 1,108
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/* Optimizing Code Generator
Reads tokens in RPN (Reverse Polish Notation) order,
and generates VM opcodes,
doing constant-folding optimization.
*/
 
class OptCodeGen extends SimpleCodeGen {
double stack[] = new double[CompiledFunction.MAX_STACK_SIZE];
int sp = -1;
 
double traceConsts[] = new double[1];
Function traceFuncs[] = new Function[1];
byte traceCode[] = new byte[1];
CompiledFunction tracer = new CompiledFunction(0, traceCode, traceConsts, traceFuncs);
 
int intrinsicArity;
OptCodeGen(SyntaxException e) {
super(e);
}
 
//@Override
void start() {
super.start();
sp = -1;
intrinsicArity = 0;
}
 
//@Override
void push(Token token) throws SyntaxException {
byte op;
switch (token.id) {
case Lexer.NUMBER:
op = VM.CONST;
traceConsts[0] = token.value;
break;
case Lexer.CONST:
case Lexer.CALL:
Symbol symbol = symbols.lookup(token.name, token.arity);
if (symbol == null) {
throw exception.set("undefined '" + token.name + "' with arity " + token.arity, token.position);
}
if (symbol.op > 0) { // built-in
op = symbol.op;
if (op >= VM.LOAD0 && op <= VM.LOAD4) {
int arg = op - VM.LOAD0;
if (arg + 1 > intrinsicArity) {
intrinsicArity = arg + 1;
}
}
} else if (symbol.fun != null) { // function call
op = VM.CALL;
traceFuncs[0] = symbol.fun;
} else { // variable reference
op = VM.CONST;
traceConsts[0] = symbol.value;
}
break;
default:
op = token.vmop;
if (op <= 0) {
throw new Error("wrong vmop: " + op);
}
}
int oldSP = sp;
traceCode[0] = op;
if (op != VM.RND) {
sp = tracer.execWithoutCheck(stack, sp);
} else {
stack[++sp] = Double.NaN;
}
 
//constant folding
if (!Double.isNaN(stack[sp]) || op == VM.CONST) {
code.pop(oldSP + 1 - sp);
consts.pop(oldSP + 1 - sp);
consts.push(stack[sp]);
op = VM.CONST;
} else if (op == VM.CALL) {
funcs.push(traceFuncs[0]);
}
code.push(op);
}
 
CompiledFunction getFun(int arity) {
return new CompiledFunction(arity, code.toArray(), consts.toArray(), funcs.toArray());
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Symbols.java
0,0 → 1,264
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
 
/**
The collection of names (<em>symbols</em>) used for parsing an expression
(the context in which the parsing takes place).<p>
 
Each symbol maps to either a {@link Function} or a constant.<p>
 
A symbol is identified by the pair (name, arity).
So a constant and a function with the same name,
or two function with the same name but with different arity
are distinct symbols.<p>
 
Symbols functions as a stack of <em>frames</em>:
when you pop the topmost frame, all the symbols added in that frame dissapear
(i.e. all the modifications done between the push and the pop are lost).<p>
 
Example:
<pre>
<code>
Symbols symbols = new Symbols();
symbols.eval("1+1"); //doesn't update symbols
symbols.define(symbols.compile("f(x)=x^2")); //updates symbols
</code>
</pre>
<p>
 
<h3>Thread safety</h3>
The Symbols class is thread-safe
(the same Symbols instance can be used by multiple threads without locking).<p>
 
The compile() methods are synchronized, so parallel compile() calls on the same Symbols
instance are serialized.
*/
 
public class Symbols {
/**
Constructs a Symbols containing the built-in symbols (such as sin, log).
*/
public Symbols() {
for (int i = 0; i < builtin.length; ++i) {
Symbol s = builtin[i];
symbols.put(s, s);
}
try {
for (int i = 0; i < defines.length; ++i) {
define(compile(defines[i]));
}
} catch (SyntaxException e) {
throw new Error(""+e); //never
}
}
 
/**
@param source the expression
@return true if the expression is a definition (i.e. contains a '=').<p>
These are definitions: "a=1+1"; "f(k)=2^k"<p>
These are not definitions: "1+1"; "x+1"
*/
public static boolean isDefinition(String source) {
return source.indexOf('=') != -1;
}
 
/**
Evaluates a simple expression (such as "1+1") and returns its value.
@throws SyntaxException in these cases:
<ul>
<li> the expression is not well-formed
<li> the expression is a definition (such as "a=1+1")
<li> the expression is an implicit function (such as "x+1")
</ul>
*/
public synchronized double eval(String expression) throws SyntaxException {
return getCompiler().eval(this, expression);
}
 
/**
Compiles an expression in the context of this Symbols.
Does not modify the symbols.
<p>
 
An expression is one of these cases (@see Symbols.isDefinition()):
<ul>
<li> constant value: 1+1
<li> implicit function: x+1
<li> constant definition: a=1+1
<li> function definition with explicit arguments: f(a)=a+1
<li> function definition with implicit arguments: f=x+1
</ul>
<p>
 
@param source the expression; may contain '=' to denote a definition (with a name).
@return the function together with its eventual name.<p>
 
If this is not a definition (e.g. "1+1", "x^2"), the name is null.<p>
If the expression is a constant (e.g. "1+1", "a=2"),
the returned Function is an instance of {@link Constant}.
 
@throws SyntaxException if there are errors compiling the expression.
*/
public synchronized FunctionAndName compile(String source) throws SyntaxException {
return getCompiler().compile(this, source);
}
 
/**
Adds a new function symbol to the top-most frame of this Symbols.
@param name the name of the function (e.g. "sin")
@param function the function to which the name maps
*/
synchronized public void define(String name, Function function) {
if (function instanceof Constant) {
addConstant(name, ((Constant) function).eval());
} else {
add(new Symbol(name, function));
}
}
 
/**
Adds a new function symbol to the top-most frame of this Symbols.
@param funAndName structure containing the function and its name
*/
synchronized public void define(FunctionAndName funAndName) {
if (funAndName.name != null) {
define(funAndName.name, funAndName.function);
}
}
 
/**
Adds a new constant symbol to the top-most frame of this Symbols.
@param name the name of the constant (e.g. "pi")
@param value the value of the constant
*/
synchronized public void addConstant(String name, double value) {
add(new Symbol(name, value));
}
 
/**
Pushes a new top frame.<p>
 
All modifications (defining new symbols) happen in the top-most frame.
When the frame is pop-ed the modifications that happened in it are reverted.
*/
synchronized public void pushFrame() {
frames.push(delta);
delta = null;
}
 
/**
Pops the top frame.<p>
 
All the modifications done since this frame was pushed are reverted.
@throws EmptyStackException if there were fewer <code>pushFrame</code> than <code>popFrame</code>.
*/
synchronized public void popFrame() {
if (delta != null) {
for (int i = delta.size() - 1; i >= 0; --i) {
Symbol previous = (Symbol) delta.elementAt(i);
if (previous.isEmpty()) {
symbols.remove(previous);
} else {
symbols.put(previous, previous);
}
}
}
delta = (Vector) frames.pop();
}
 
 
 
//--- non-public below
 
private final static Symbol builtin[];
private static Symbol shell = new Symbol(null, 0);
private static ThreadLocal compilers = new ThreadLocal();
private static Compiler getCompiler() {
Compiler compiler;
if ((compiler = (Compiler) compilers.get()) == null) {
compilers.set(compiler = new Compiler());
}
return compiler;
}
 
private Hashtable symbols = new Hashtable(); //Hashtable<Symbol, Symbol>
private Vector delta = null; //Vector<Symbol>
private Stack frames = new Stack(); //Stack<Vector>
 
static {
Vector vect = new Vector();
int arity;
for (byte i = 0; i < VM.BYTECODE_END; ++i) {
if ((arity = VM.builtinArity[i]) >= 0) {
vect.addElement(new Symbol(VM.opcodeName[i], arity, i));
}
}
 
final String IMPLICIT_ARGS[] = {"x", "y", "z"};
for (byte i = 0; i < IMPLICIT_ARGS.length; ++i) {
vect.addElement(new Symbol(IMPLICIT_ARGS[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
}
 
vect.addElement(new Symbol("pi", Math.PI));
vect.addElement(new Symbol("\u03c0", Math.PI));
vect.addElement(new Symbol("e", Math.E));
 
vect.addElement(new Symbol("Inf", Double.POSITIVE_INFINITY));
vect.addElement(new Symbol("Infinity", Double.POSITIVE_INFINITY));
vect.addElement(new Symbol("NaN", Double.NaN));
 
int size = vect.size();
builtin = new Symbol[size];
vect.copyInto(builtin);
}
 
private static final String defines[] = {
"ln(x) = log(x)",
"log2(x) = log(x) * 1.4426950408889634074", //*log2(e)
"log10(x) = log(x) * 0.43429448190325182765", //*log10(e)
"lg(x) = log10(x)",
"lb(x) = log2(x)",
"log(x, base) = log(x) / log(base)"
};
void addArguments(String args[]) {
for (int i = 0; i < args.length; ++i) {
add(new Symbol(args[i], Symbol.CONST_ARITY, (byte)(VM.LOAD0 + i)));
}
}
 
void add(Symbol s) {
Object previous = symbols.put(s, s);
if (delta == null) {
delta = new Vector();
}
delta.addElement(previous != null ? previous : Symbol.newEmpty(s));
}
 
synchronized Symbol lookup(String name, int arity) {
return (Symbol) symbols.get(shell.setKey(name, arity));
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Constant.java
0,0 → 1,30
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
public class Constant extends Function {
private double value;
 
public Constant(double value) {
this.value = value;
}
 
//@Override
public double eval() {
return value;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/ByteStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class ByteStack {
private byte[] data = new byte[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(byte b) {
if (size >= data.length) {
byte[] newData = new byte[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
byte[] toArray() {
byte[] trimmed = new byte[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/TokenConsumer.java
0,0 → 1,24
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
abstract class TokenConsumer {
void start() {
}
 
abstract void push(Token token) throws SyntaxException;
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/RPN.java
0,0 → 1,161
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Stack;
import java.util.EmptyStackException;
 
/* Reverse Polish Notation
reads tokens in normal infix order (e.g.: 1 + 2)
and outputs them in Reverse Polish order (e.g.: 1 2 +).
See Dijkstra's Shunting Yard algorithm:
http://en.wikipedia.org/wiki/Shunting_yard_algorithm
*/
class RPN extends TokenConsumer {
Stack stack = new Stack();
int prevTokenId = 0;
TokenConsumer consumer;
SyntaxException exception;
 
RPN(SyntaxException exception) {
this.exception = exception;
}
 
void setConsumer(TokenConsumer consumer) {
this.consumer = consumer;
}
 
//@Override
void start() {
stack.removeAllElements();
prevTokenId = 0;
consumer.start();
}
 
private Token top() {
return stack.empty() ? null : (Token) stack.peek();
}
 
private void popHigher(int priority) throws SyntaxException {
Token t = top();
while (t != null && t.priority >= priority) {
consumer.push(t);
//code.push(t);
stack.pop();
t = top();
}
}
 
static final boolean isOperand(int id) {
return
id == Lexer.FACT ||
id == Lexer.RPAREN ||
id == Lexer.NUMBER ||
id == Lexer.CONST;
}
 
void push(Token token) throws SyntaxException {
int priority = token.priority;
int id = token.id;
switch (id) {
case Lexer.NUMBER:
case Lexer.CONST:
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
consumer.push(token);
break;
/*
case Lexer.CALL:
case Lexer.LPAREN:
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
stack.push(token);
break;
*/
case Lexer.RPAREN: {
if (prevTokenId == Lexer.CALL) {
top().arity--;
} else if (!isOperand(prevTokenId)) {
throw exception.set("unexpected ) or END", token.position);
}
 
popHigher(priority);
Token t = top();
if (t != null) {
if (t.id == Lexer.CALL) {
consumer.push(t);
} else if (t != Lexer.TOK_LPAREN) {
throw exception.set("expected LPAREN or CALL", token.position);
}
stack.pop();
}
break;
}
case Lexer.COMMA: {
if (!isOperand(prevTokenId)) {
throw exception.set("misplaced COMMA", token.position);
}
popHigher(priority);
Token t = top();
if (t==null || t.id != Lexer.CALL) {
throw exception.set("COMMA not inside CALL", token.position);
}
t.arity++;
//code.push(stack.pop());
break;
}
case Lexer.END: {
Token t = Lexer.TOK_RPAREN;
t.position = token.position;
do {
push(t);
} while (top() != null);
break;
}
default: //operators, CALL, LPAREN
if (token.assoc == Token.PREFIX) {
if (isOperand(prevTokenId)) {
push(Lexer.TOK_MUL);
}
stack.push(token);
break;
}
if (!isOperand(prevTokenId)) {
if (id == Lexer.SUB) {
//change SUB to unary minus
token = Lexer.TOK_UMIN;
stack.push(token);
break;
} else if (id == Lexer.ADD) {
// ignore, keep prevTokenId unchanged
return;
}
throw exception.set("operator without operand", token.position);
}
popHigher(priority + (token.assoc == Token.RIGHT ? 1 : 0));
stack.push(token);
}
prevTokenId = token.id;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/DoubleStack.java
0,0 → 1,45
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class DoubleStack {
private double[] data = new double[8];
private int size = 0;
 
void clear() {
size = 0;
}
 
void push(double b) {
if (size >= data.length) {
double[] newData = new double[data.length << 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[size++] = b;
}
 
void pop(int cnt) {
size -= cnt;
}
 
double[] toArray() {
double[] trimmed = new double[size];
System.arraycopy(data, 0, trimmed, 0, size);
return trimmed;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/CompiledFunction.java
0,0 → 1,253
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Random;
 
class CompiledFunction extends Function {
//static final int INI_STACK_SIZE = 16;
static final int MAX_STACK_SIZE = 128; //if stack ever grows above this likely something is wrong
private static Random random = new Random();
 
private double consts[];
private Function funcs[];
private byte code[];
private int arity; // >= 0
 
private static final ThreadLocal stacks = new ThreadLocal();
 
CompiledFunction(int arity, byte[] code, double[] consts, Function funcs[]) {
init(arity, code, consts, funcs);
}
 
/* This empty constructor is used only by SimpleCodeGen,
which calls init() explicitly later.
*/
CompiledFunction() {
init(0, null, null, null);
}
 
void init(int arity, byte[] code, double[] consts, Function funcs[]) {
this.arity = arity;
this.code = code;
this.consts = consts;
this.funcs = funcs;
}
 
public int arity() {
return arity;
}
 
public String toString() {
StringBuffer buf = new StringBuffer();
int cpos = 0, fpos = 0;
if (arity != 0) {
buf.append("arity ").append(arity).append("; ");
}
for (int i = 0; i < code.length; ++i) {
byte op = code[i];
buf.append(VM.opcodeName[op]);
if (op == VM.CONST) {
buf.append(' ').append(consts[cpos++]);
} else if (op == VM.CALL) {
++fpos;
//buf.append(" {").append(funcs[fpos++].toString()).append('}');
}
buf.append("; ");
}
if (cpos != consts.length) {
buf.append("\nuses only ").append(cpos).append(" consts out of ").append(consts.length);
}
if (fpos != funcs.length) {
buf.append("\nuses only ").append(fpos).append(" funcs out of ").append(funcs.length);
}
return buf.toString();
}
 
private void checkArity(int nArgs) throws ArityException {
if (arity() != nArgs) {
throw new ArityException("Expected " + arity() + " arguments, got " + nArgs);
}
}
 
private double[] getStack() {
double stack[];
if ((stack = (double[]) stacks.get()) == null) {
stacks.set(stack = new double[MAX_STACK_SIZE]);
}
return stack;
}
static final double NO_ARGS[] = new double[0];
public double eval() throws ArityException {
return eval(NO_ARGS);
}
 
public double eval(double x) throws ArityException {
checkArity(1);
double stack[] = getStack();
stack[0] = x;
exec(stack, 0);
return stack[0];
}
 
public double eval(double x, double y) throws ArityException {
checkArity(2);
double stack[] = getStack();
stack[0] = x;
stack[1] = y;
exec(stack, 1);
return stack[0];
}
 
public double eval(double args[]) throws ArityException {
checkArity(args.length);
double stack[] = getStack();
if (args.length > 0) {
System.arraycopy(args, 0, stack, 0, args.length);
}
exec(stack, args.length - 1);
return stack[0];
}
 
void exec(double s[], int p) {
int finalP = execWithoutCheck(s, p);
int expected = p - arity + 1;
if (finalP != expected) {
throw new Error("stack pointer after exec: expected " +
expected + ", got " + finalP);
}
}
int execWithoutCheck(double s[], int p) {
byte[] code = this.code;
int initialSP = p;
int constp = 0;
int funp = 0;
final double angleFactor = 1; // 1/Calc.cfg.trigFactor;
// arguments, read from stack on exec entry
// we don't use an array in order to avoid the dynamic allocation (new)
// @see Compiler.MAX_ARITY
double a0, a1, a2, a3, a4;
a0 = a1 = a2 = a3 = a4 = Double.NaN;
switch (arity) {
case 5: a4 = s[p--];
case 4: a3 = s[p--];
case 3: a2 = s[p--];
case 2: a1 = s[p--];
case 1: a0 = s[p--];
}
 
//int expectedExitSP = p+1;
int codeLen = code.length;
for (int pc = 0; pc < codeLen; ++pc) {
switch (code[pc]) {
case VM.CONST: s[++p] = consts[constp++]; break;
case VM.CALL: {
Function f = funcs[funp++];
if (f instanceof CompiledFunction) {
p = ((CompiledFunction) f).execWithoutCheck(s, p);
} else {
int arity = f.arity();
p -= arity;
try {
double result;
switch (arity) {
case 0:
result = f.eval();
break;
case 1:
result = f.eval(s[p+1]);
break;
case 2:
result = f.eval(s[p+1], s[p+2]);
break;
default:
double args[] = new double[arity];
System.arraycopy(s, p+1, args, 0, arity);
result = f.eval(args);
}
s[++p] = result;
} catch (ArityException e) {
throw new Error(""+e); //never
}
}
break;
}
case VM.RND: s[++p] = random.nextDouble(); break;
case VM.ADD: s[--p] += s[p+1]; break;
case VM.SUB: s[--p] -= s[p+1]; break;
case VM.MUL: s[--p] *= s[p+1]; break;
case VM.DIV: s[--p] /= s[p+1]; break;
case VM.MOD: s[--p] %= s[p+1]; break;
case VM.POWER: s[--p] = MoreMath.pow(s[p], s[p+1]); break;
case VM.UMIN: s[p] = -s[p]; break;
case VM.FACT: s[p] = MoreMath.factorial(s[p]); break;
case VM.SIN: s[p] = Math.sin(s[p] * angleFactor); break;
case VM.COS: s[p] = Math.cos(s[p] * angleFactor); break;
case VM.TAN: s[p] = Math.tan(s[p] * angleFactor); break;
case VM.ASIN: s[p] = MoreMath.asin(s[p]) / angleFactor; break;
case VM.ACOS: s[p] = MoreMath.acos(s[p]) / angleFactor; break;
case VM.ATAN: s[p] = MoreMath.atan(s[p]) / angleFactor; break;
case VM.EXP: s[p] = MoreMath.exp(s[p]); break;
case VM.LOG: s[p] = MoreMath.log(s[p]); break;
case VM.SQRT: s[p] = Math.sqrt(s[p]); break;
case VM.CBRT: s[p] = MoreMath.cbrt(s[p]); break;
case VM.SINH: s[p] = MoreMath.sinh(s[p]); break;
case VM.COSH: s[p] = MoreMath.cosh(s[p]); break;
case VM.TANH: s[p] = MoreMath.tanh(s[p]); break;
case VM.ASINH: s[p] = MoreMath.asinh(s[p]); break;
case VM.ACOSH: s[p] = MoreMath.acosh(s[p]); break;
case VM.ATANH: s[p] = MoreMath.atanh(s[p]); break;
case VM.ABS: s[p] = Math.abs(s[p]); break;
case VM.FLOOR: s[p] = Math.floor(s[p]); break;
case VM.CEIL: s[p] = Math.ceil(s[p]); break;
case VM.SIGN: s[p] = s[p] > 0 ? 1 : s[p] < 0 ? -1 : 0; break;
case VM.MIN: s[--p] = Math.min(s[p], s[p+1]); break;
case VM.MAX: s[--p] = Math.min(s[p], s[p+1]); break;
case VM.GCD: s[--p] = MoreMath.gcd(s[p], s[p+1]); break;
case VM.COMB: s[--p] = MoreMath.comb(s[p], s[p+1]); break;
case VM.PERM: s[--p] = MoreMath.perm(s[p], s[p+1]); break;
case VM.LOAD0: s[++p] = a0; break;
case VM.LOAD1: s[++p] = a1; break;
case VM.LOAD2: s[++p] = a2; break;
case VM.LOAD3: s[++p] = a3; break;
case VM.LOAD4: s[++p] = a4; break;
default:
throw new Error("Unknown opcode " + code[pc]);
}
}
return p;
/*
if (p != expectedExitSP) {
throw new Error("stack pointer after exec: expected " + expectedExitSP +
" , got " + p);
}
*/
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/DeclarationParser.java
0,0 → 1,88
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
import java.util.Vector;
 
class DeclarationParser extends TokenConsumer {
static final String NO_ARGS[] = new String[0];
static final int UNKNOWN_ARITY = -2;
static final int MAX_ARITY = 5;
String name;
int arity = UNKNOWN_ARITY;
Vector args = new Vector();
 
private SyntaxException exception;
 
DeclarationParser(SyntaxException e) {
this.exception = e;
}
 
//@Override
void start() {
name = null;
args.setSize(0);
}
 
//@Override
void push(Token token) throws SyntaxException {
switch (token.id) {
case Lexer.CALL:
if (name == null) {
name = token.name;
arity = 0;
} else {
throw exception.set("repeated CALL in declaration", token.position);
}
break;
 
case Lexer.CONST:
if (name == null) {
name = token.name;
arity = UNKNOWN_ARITY;
} else if (arity >= 0) {
args.addElement(token.name);
++arity;
if (arity > MAX_ARITY) {
throw exception.set("Arity too large " + arity, token.position);
}
} else {
throw exception.set("Invalid declaration", token.position);
}
break;
 
case Lexer.RPAREN:
case Lexer.COMMA:
case Lexer.END:
break;
 
default:
throw exception.set("invalid token in declaration", token.position);
}
}
String[] argNames() {
if (arity > 0) {
String argNames[] = new String[arity];
args.copyInto(argNames);
return argNames;
} else {
return NO_ARGS;
}
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/SyntaxException.java
0,0 → 1,50
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Thrown when the expression can't be compiled, because it's either not
well-formed (e.g. "1+"), or because some simbols aren't defined (e.g. "foo+2").
*/
public class SyntaxException extends Exception {
/**
The expression which caused the error.
*/
public String expression;
 
/**
Explicative message (cause of error).
*/
public String message;
 
/**
The position inside expression where the error occured.
*/
public int position;
 
public String toString() {
return "SyntaxException: " + message
+ " in '" + expression
+ "' at position " + position;
}
 
SyntaxException set(String str, int pos) {
message = str;
position = pos;
return this;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/Symbol.java
0,0 → 1,66
/*
* Copyright (C) 2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
class Symbol {
static final int CONST_ARITY = -3;
 
private String name;
private int arity;
 
byte op;
Function fun;
double value = 0;
 
Symbol(String name, int arity, byte op) {
setKey(name, arity);
this.op = op;
}
 
Symbol(String name, Function fun) {
setKey(name, fun.arity());
this.fun = fun;
}
 
Symbol(String name, double value) {
setKey(name, CONST_ARITY);
this.value = value;
}
 
static Symbol newEmpty(Symbol s) {
return new Symbol(s.name, s.arity, (byte)0);
}
 
boolean isEmpty() {
return op == 0 && fun == null && value == 0;
}
 
Symbol setKey(String name, int arity) {
this.name = name;
this.arity = arity;
return this;
}
 
public boolean equals(Object other) {
Symbol symbol = (Symbol) other;
return name.equals(symbol.name) && arity == symbol.arity;
}
 
public int hashCode() {
return name.hashCode() + arity;
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/Plot/ptolemy/org/javia/arity/ArityException.java
0,0 → 1,28
/*
* Copyright (C) 2007-2008 Mihai Preda.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
package org.javia.arity;
 
/**
Thrown when a {@link Function} is evaluated with a wrong number of arguments
(when the number of arguments is not equal to the function's arity).
*/
 
public class ArityException extends Exception {
public ArityException(String mes) {
super(mes);
}
}
/trunk/wims/src/Misc/authors/jm.evers/applets/WClock/src/WClock.java
0,0 → 1,572
/*
 
jm.evers 2/2010
No copyrights. All amateur scriblings.
Example usage:
<html>
<body>
<script type="text/javascript">
 
function speakTime(){
var speaktime = document.getElementById('WClock').speakTime();
document.getElementById('showtime').innerHTML='<hr><font color=red><b>'+speaktime+'</b></font>' ;}
 
function ReadThis(){
var reply = document.getElementById('WClock').readApplet();
document.getElementById('showtime').innerHTML='<hr>first value is pupils\'s timeanswer<br>second value is initial time<br><font color=red><b>'+reply+'</b></font><hr>';
}
function increase(t,a){
if(t == 0 ){var reply = document.getElementById('WClock').setApplet("H",a);}
else
if(t == 1 ){var reply = document.getElementById('WClock').setApplet("M",a);}
else
if(t == 2 ){var reply = document.getElementById('WClock').setApplet("S",a);}
}
function reset(){
document.getElementById('WClock').restart();
}
</script>
<table>
<tr>
<td>
<div id="showtime"></div>
<br>
<applet id="WClock" name="WClock" code="WClock.class" archive="WClock.jar" width="300" height="300">
<param name = "language" value="nl"><!-- default english; optional nl,fr (fr is no good) -->
<param name = "user_modify" value="yes"><!-- user sets time : default yes 0,no,1,yes -->
<param name = "use_system_time" value="yes"><!-- optional 1,yes,0,no : overrules other time parameters -->
<param name = "use_seconds" value="yes"><!-- optional 1,yes,0,no -->
<param name = "hours" value="12"><!-- if not set random hour -->
<param name = "minutes" value="15"><!-- if not set: will use random minutes -->
<param name = "seconds" value="43"><!-- if not set: will random seconds -->
<param name = "background_color" value="#dafff6"><!-- optional -->
<param name = "hour_hand_color" value="#007cff"><!-- optional -->
<param name = "minutes_hand_color" value="#00c3ff"><!-- optional -->
<param name = "seconds_hand_color" value="#ff1300"><!-- optional -->
<param name = "numbers_color" value="#ff1300"><!-- optional -->
<param name = "15_min_color" value="#0044ff"><!-- optional -->
<param name = "5_min_color" value="#0044ff"><!-- optional -->
<param name = "1_min_color" value="#0044ff"><!-- optional -->
<param name = "alpha" value="100"><!-- optional -->
<param name = "15_min_type" value="numbers"><!-- optional : diamonds ,lines ,numbers or 0,1,2-->
<param name = "5_min_type" value="0"><!-- optional : diamonds ,lines ,numbers or 0,1,2-->
<param name = "1_min_type" value="lines"><!-- optional : diamonds ,lines ,numbers or 0,1,2-->
</applet>
<br>
<input type="button" name="read_time" value="read time" onclick="javascript:ReadThis();">
<br>
<input type="button" name="speak time" value="speak time" onclick="javascript:speakTime();">
<br>
<input type="button" name="hours +" value="hours +" onclick="javascript:increase(0,1);">
<input type="button" name="min +" value="min +" onclick="javascript:increase(1,1);">
<input type="button" name="sec +" value="sec +" onclick="javascript:increase(2,1);">
<br>
<input type="button" name="hours &minus;" value="hours &minus;" onclick="javascript:increase(0,-1);">
<input type="button" name="min &minus;" value="min &minus;" onclick="javascript:increase(1,-1);">
<input type="button" name="sec &minus;" value="sec &minus;" onclick="javascript:increase(2,-1);">
</td>
<td>
Mouse &amp; Key Controls [if param "user_modify = yes"]
<ul>
<li>seconds
<ul>
<li>s : +1 sec</li>
<li>F3 : +1 sec</li>
<li>r : -1 sec</li>
<li>F4 : -1 sec</li>
</ul>
</li>
<li>minutes
<ul>
<li>F1 : +1 min</li>
<li>m : +1 min</li>
<li>cursor -&gt; : +1 min</li>
<li>cursor &lt;- : -1 min</li>
<li>backspace : -1 min</li>
<li>pageup : -15 min</li>
<li>pagedown : +15 min</li>
<li>space : +1 min</li>
<li>left mousebutton : +1 min</li>
<li>right mousebutton : -1 min</li>
<li>scrollwheel : +/- 1 min</li>
<li>mouse drag : +1 min</li>
</ul>
</li>
<li>hours
<ul>
<li>F2 : +1 hour</li>
<li>h : +1 hour</li>
<li>F5 : -1 hour</li>
<li>- : -1 hour</li>
<li>delete : -1 hour</li>
<li>1,2,3,4,5,6,7,8,9 : +1,2,3,4,5,6,7,8,9 hours</li>
</ul>
</li>
</ul>
</td>
</tr>
</table>
</body>
</html>
 
*/
 
import java.lang.*;
//import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.applet.Applet;
import java.awt.*;
import java.util.*;
import java.io.*;
import java.awt.Color;
import java.awt.event.*;
 
public class WClock extends Applet implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener{
 
public Color hour_hand_color,min_hand_color,sec_hand_color,number_color;
public Color horloge_color,backgroundcolor,ftmin_color,fimin_color,onemin_color;
int xsize,ysize;
double center_x,center_y;
Graphics2D backg;
BufferedImage bg;
Graphics2D horloge;
BufferedImage ggb;
double seconds;
int fifteenminute;
int fiveminute;
int oneminute;
static int diamonds=0;
static int lines=1;
static int numbers=2;
String helptxt;
int H_in=-1;
int M_in=-1;
int S_in=-1;
int alpha=-1;
boolean use_seconds;
boolean user_modify;
public String[] telwoorden = {"zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen",
"fourteen","fifteen","sixteen","seventeen","eightteen","nineteen","twenty","twentyone","twentytwo","twentythree",
"twentyfour","twentyfive","twentysix","twentyseven","twentyeight","twentynine","thirty","thirtyone","thirtytwo",
"thirtythree","thirtyfour","thirtyfive","thirtysix","thirtyseven","thirtyeight","thirtynine","fourty","fourtyone",
"fourtytwo","fourtythree","fourtyfour","fourtyfive","fourtysix","fourtyseven","fourtyeight","fourtynine","fifty"
};
public String[] mtext = {"It is exactly speak_hours O'clock","It is a quarter past speak_hours",
"It is speak_minutes minutes past speak_hours"," It is exactly half past speak_hours",
"It is speak_minutes minutes before half past speak_hours","It is a quarter to speak_hours",
"It is speak_minutes minutes over half past speak_hours","It is speak_minutes minutes to speak_hours",
"and speak_seconds seconds"};
public String [] single_multi_sec = {"second","seconds"};
public String[] single_multi_min = {"minute","minutes"};
public void init(){
helptxt="minuten=F1,M,cursor,muis,spatiebalk uren=F2,H seconden=F3,S ";
String param = getParameter("language");
if(param != null && param.length() == 2){
if(param.equalsIgnoreCase("nl")){
telwoorden = new String[] {"nul","een","twee","drie","vier","vijf","zes","zeven","acht","negen","tien",
"elf","twaalf","dertien","veertien","vijftien","zestien","zeventien","achttien","negentien",
"twintig","eenentwintig","tweeentwintig","drieentwintig","vierentwintig","vijfentwintig",
"zesentwintig ","zevenentwintig"," achtentwintig"," negenentwintig"," dertig",
"eenendertig","tweeendertig","drieendertig","vierendertig","vijfendertig","zesendertig","zevenendertig",
"achtendertig","negenendertig","veertig","eennenveertig","tweeenveertig","drieenveertig","vierenveertig",
"vijfenveertig","zesenveertig","zevenenveertig","achtenveertig","negenenveertig","vijftig"};
mtext = new String[] {"Het is precies speak_hours uur","Het is kwart over speak_hours",
"Het is speak_minutes minuten over speak_hours","Het is half speak_hours",
"Het is speak_minutes minuten voor half speak_hours","Het is kwart voor speak_hours",
"Het is speak_minutes minuten over half speak_hours","Het is speak_minutes minuten voor speak_hours",
"en speak_seconds seconden"};
single_multi_sec = new String[] {"seconde","seconden"};
single_multi_min = new String[] {"minuut","minuten"};
}
else
{
System.out.println("Sorry, no support for other languages than English and Dutch");
}
}
param = getParameter("alpha");
if(param != null && param.length() !=0){
try{alpha = Integer.parseInt(param);}catch(Exception e){System.out.println("Can not set alpha color to"+param);}
}
param = getParameter("user_modify");
if(param != null && param.length() !=0){
if(param.equals("0") || param.equalsIgnoreCase("no")){user_modify = false;}else{user_modify = true;}
}
horloge_color = new Color(255,255,255,0); // do not change : needs to be transparent ... image drawn over number&hand image
hour_hand_color = new Color(255,0,0,120);
min_hand_color = new Color(0,255,0,120);
sec_hand_color = new Color(0,0,255,120);
number_color = new Color(0,50,255,120);
backgroundcolor = new Color(255,255,255);
ftmin_color = new Color(0,10,255,160);
fimin_color = new Color(0,10,255,160);
onemin_color = new Color(0,10,255,160);
// reading params, reverting to default if not set.
backgroundcolor = colorDecodeParam("background_color",backgroundcolor);
hour_hand_color = colorDecodeParam("hour_hand_color",hour_hand_color);
min_hand_color = colorDecodeParam("minutes_hand_color",min_hand_color);
sec_hand_color = colorDecodeParam("seconds_hand_color",sec_hand_color);
number_color = colorDecodeParam("numbers_color",number_color);
ftmin_color = colorDecodeParam("15_min_color",ftmin_color);
fimin_color = colorDecodeParam("5_min_color",fimin_color);
onemin_color = colorDecodeParam("1_min_color",onemin_color);
if(alpha>-1){
hour_hand_color = MakeTransparent(hour_hand_color,alpha);
min_hand_color = MakeTransparent(min_hand_color,alpha);
sec_hand_color = MakeTransparent(sec_hand_color,alpha);
}
fifteenminute = setHorlogeType("15_min_type",2);
fiveminute = setHorlogeType("5_min_type",0);
oneminute = setHorlogeType("1_min_type",1);
Dimension appletSize = this.getSize();
ysize = appletSize.height;xsize = appletSize.width;
center_x=(double) (xsize/2);center_y=(double) (ysize/2);
bg = new BufferedImage(xsize,ysize, BufferedImage.TYPE_INT_ARGB);
backg = (Graphics2D) bg.getGraphics();
ggb = new BufferedImage(xsize,ysize, BufferedImage.TYPE_INT_ARGB);
horloge = (Graphics2D) ggb.getGraphics();
if(user_modify){
addMouseListener(this);
addMouseMotionListener(this);
addMouseWheelListener(this);
addKeyListener(this);
}
prepaint();
getTime();
setTime(0);
//requestFocus();
}
public String speakTime(){
int H = (int) ((seconds/3600) % 12);
int M = (int) ((seconds/60) % 60);
int S = (int) ((seconds) % 60);
//System.out.println("H="+H+" M="+M+" S="+S);
 
String text_m="";
String enzoveelseconden="";
String speak_hours="";
String speak_minutes="";
if( M > 15 ){ H++;}
if( H == 0 || H > 12){ H = 12;}
speak_hours=telwoorden[H];
if( M <= 15 ){
if(M == 0){
text_m=mtext[0].replace("speak_hours",speak_hours);
}
else
{
if(M == 15){
text_m=mtext[1].replace("speak_hours",speak_hours);
}
else
{
speak_minutes=telwoorden[M];
text_m=mtext[2].replace("speak_minutes",speak_minutes);
text_m=text_m.replace("speak_hours",speak_hours);
}
}
}
else
{
if(M <= 30){
if( M == 30){
text_m=mtext[3].replace("speak_hours",speak_hours);
}
else
{
speak_minutes=telwoorden[30 - M];
text_m=mtext[4].replace("speak_minutes",speak_minutes);
text_m=text_m.replace("speak_hours",speak_hours);
}
}
else
{
if( M <= 45 ){
if(M == 45){
text_m=mtext[5].replace("speak_hours",speak_hours);
}
else
{
speak_minutes=telwoorden[M-30];
text_m=mtext[6].replace("speak_minutes",speak_minutes);
text_m=text_m.replace("speak_hours",speak_hours);
}
}
else
{
if( M <= 60 ){
speak_minutes=telwoorden[60-M];
text_m=mtext[7].replace("speak_minutes",speak_minutes);
text_m=text_m.replace("speak_hours",speak_hours);
}
}
}
}
if( M == 1 || M == 29 || M == 31 || M == 59 ){text_m = text_m.replace(single_multi_min[1],single_multi_min[0]);}
if( S != 0 && use_seconds){
enzoveelseconden=mtext[8].replace("speak_seconds",""+S+"");
if( S == 1 ){
enzoveelseconden=enzoveelseconden.replace(single_multi_sec[1],single_multi_sec[0]);
}
}
return text_m+"..."+enzoveelseconden;
}
public void setApplet(String type , int incr){
if(type.equals("H")){setTime((double)(incr*3600));}
else
if(type.equals("M")){setTime((double)(incr*60));}
else
if(type.equals("S") && use_seconds ){setTime((double)(incr*1));}
}
public int setHorlogeType(String param, int d){
String c = getParameter(param);
if(c != null && c.length() !=0){
try{
if(c.equalsIgnoreCase("diamonds") || c.equals("0") ){return diamonds;}
else
if(c.equalsIgnoreCase("lines") || c.equals("1") ){return lines;}
else
if(c.equalsIgnoreCase("numbers") || c.equals("2") ){return numbers;}
}catch(Exception e){System.out.println("Can\'t handle "+param+" = "+c);}
}
return d;
}
public Color MakeTransparent(Color c, int a){
return new Color(c.getRed(),c.getGreen(),c.getBlue(),a);
}
 
public Color colorDecodeParam(String param, Color c0){
String c = getParameter(param);
if( c != null && c.length() !=0){
try{ c0 = Color.decode(c);}catch(Exception e){System.out.println("don\'t know color "+c+" ... setting to default");}
}
return c0;
}
public void getTime(){
String param;
param = getParameter("use_seconds");
if(param != null && param.length() !=0){
if(param.equals("1") || param.equalsIgnoreCase("yes")){use_seconds = true;}else{use_seconds = false;}
}
 
param = getParameter("use_system_time");
if(param != null && param.length() !=0){
if(param.equals("1") || param.equalsIgnoreCase("yes")){
Date date = new Date();
if(use_seconds){ S_in = date.getSeconds(); }else{ S_in = 0; }
M_in = date.getMinutes();
H_in = date.getHours();
seconds = (double) (3600*H_in + 60*M_in + S_in);
return;
}
}
param = getParameter("hours");
if(param != null && param.length() !=0){
H_in = Integer.parseInt(param);
}else{H_in =(int) (Math.round(12*(Math.random())));}
param = getParameter("minutes");
if(param != null && param.length() !=0){
M_in = Integer.parseInt(param);
}else{M_in =(int) (Math.round(60*(Math.random())));}
if(use_seconds){
param = getParameter("seconds");
if(param != null && param.length() !=0){ S_in = Integer.parseInt(param); }else{ S_in = (int) (Math.round(60*(Math.random())));}
}else{ S_in = 0;}
seconds = (double) (3600*H_in + 60*M_in + S_in);
}
 
public String readApplet(){
int H = (int) ((seconds/3600) % 12);
int M = (int) ((seconds/60) % 60);
int S = (int) ((seconds) % 60);
// user set time , initial time
return H+":"+M+":"+S+","+H_in+":"+M_in+":"+S_in;
}
Polygon getDiamond(int seconds,double angle,double forwards,double backwards,double sideways){
Polygon polygon=new Polygon();
double leftsin=Math.sin((seconds-angle)*Math.PI/30);
double leftcos=Math.cos((seconds-angle)*Math.PI/30);
double middlesin=Math.sin(seconds*Math.PI/30);
double middlecos=Math.cos(seconds*Math.PI/30);
double rightsin=Math.sin((seconds+angle)*Math.PI/30);
double rightcos=Math.cos((seconds+angle)*Math.PI/30);
polygon.addPoint((int) (center_x + center_x*forwards*middlesin) , (int) (center_y - center_y*forwards*middlecos));
polygon.addPoint((int) (center_x + center_x*sideways*leftsin) , (int) (center_y - center_y*sideways*leftcos));
polygon.addPoint((int) (center_x + center_x*backwards*middlesin) , (int) (center_y - center_y*backwards*middlecos));
polygon.addPoint((int) (center_x + center_x*sideways*rightsin) , (int) (center_y - center_y*sideways*rightcos));
return polygon;
}
 
void drawNumber(Graphics g,int seconds,int number,double size,double radius){
Font font=new Font("TimesRoman",Font.PLAIN,(int)(Math.min(center_x,center_y)*size));
FontMetrics fontmetrics=getFontMetrics(font);
String string=(new Integer(number)).toString();
int x=(int) (center_x + center_x*radius*Math.sin(seconds*Math.PI/30));
int y=(int) (center_y - center_y*radius*Math.cos(seconds*Math.PI/30));
x-=fontmetrics.stringWidth(string)/2;
y+=fontmetrics.getAscent()/2;
g.setColor(number_color);
g.setFont(font);
g.drawString(string,x,y);
}
public void prepaint(){
backg.setColor(horloge_color);
backg.fillOval(0,0,xsize,ysize);
for(int n=0;n<60;n++){
if(n%15==0&&fifteenminute==diamonds){
backg.setColor(ftmin_color);
backg.fillPolygon(getDiamond(n,.4,1,.8,.9));
}
else if(n%15==0&&fifteenminute==numbers){
backg.setColor(ftmin_color);
drawNumber(backg,n,n==0?12:n/5,.17,.9);
}
else if(n%15==0&&fifteenminute==lines){
backg.setColor(ftmin_color);
drawNumber(backg,n,n==0?12:n/5,.17,.9);
}
else if(n%5==0&&fiveminute==diamonds){
backg.setColor(fimin_color);
backg.fillPolygon(getDiamond(n,.2,.95,.85,.9));
}
else if(n%5==0&&fiveminute==numbers){
backg.setColor(fimin_color);
drawNumber(backg,n,n==0?12:n/5,.1,.9);
}
else if(n%5==0&&fiveminute==lines){
backg.setColor(fimin_color);
drawNumber(backg,n,n==0?12:n/5,.1,.9);
}
else if(oneminute==lines){
double sin=Math.sin(n*Math.PI/30);
double cos=Math.cos(n*Math.PI/30);
backg.setColor(onemin_color);
backg.drawLine((int) (center_x + center_x*.88*sin) ,(int) (center_y - center_y*.88*cos) ,(int) (center_x + center_x*.92*sin),(int) (center_y - center_y*.92*cos));
}
else if(oneminute==numbers){
backg.setColor(onemin_color);
drawNumber(backg,n,n,.05,.9);
}
}
}
 
public void prepainthorloge(){
horloge.setColor(backgroundcolor);
horloge.fillRect(0,0,xsize,ysize);
if(use_seconds){
Polygon S = getWijzer((seconds)%60,0.9,0.02,0.02,30);
drawWijzer(sec_hand_color,horloge,S);
}
Polygon M = getWijzer((seconds/60)%60,0.9,0.04,0.04,30);
Polygon H = getWijzer(5*((seconds/3600)%12),0.6,0.05,0.05,30);
drawWijzer(min_hand_color,horloge,M);
drawWijzer(hour_hand_color,horloge,H);
drawCenter(Color.black,horloge,(int)(0.05*xsize));
}
 
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(ggb,0,0,this);
g2.drawImage(bg,0,0,this);
}
public void paint(Graphics g){
update(g);
}
 
public void update(Graphics g){
prepainthorloge();
paintComponent(g);
}
 
Polygon getWijzer(double time,double forwards,double backwards,double sideways,int div){
Polygon polygon=new Polygon();
double sin = Math.sin(time*Math.PI/div);
double cos = Math.cos(time*Math.PI/div);
polygon.addPoint((int) (center_x + center_x*forwards*sin) ,(int) (center_y - center_y*forwards*cos));
polygon.addPoint((int) (center_x + center_x*sideways*cos) ,(int) (center_y + center_y*sideways*sin));
polygon.addPoint((int) (center_x - center_x*backwards*sin) ,(int) (center_y + center_y*backwards*cos));
polygon.addPoint((int) (center_x - center_x*sideways*cos) ,(int) (center_y - center_y*sideways*sin));
return polygon;
}
void drawCenter(Color c,Graphics g,int w){
g.setColor(c);
g.fillOval((int) (center_x-w/2),(int) (center_y-w/2),w,w);
}
 
void drawWijzer(Color c,Graphics g,Polygon polygon){
g.setColor(c);
g.fillPolygon(polygon);
g.drawLine(polygon.xpoints[0],polygon.ypoints[0],polygon.xpoints[2],polygon.ypoints[2]);
g.drawLine(polygon.xpoints[1],polygon.ypoints[1],polygon.xpoints[2],polygon.ypoints[2]);
g.drawLine(polygon.xpoints[3],polygon.ypoints[3],polygon.xpoints[2],polygon.ypoints[2]);
g.drawLine(polygon.xpoints[0],polygon.ypoints[0],polygon.xpoints[1],polygon.ypoints[1]);
g.drawLine(polygon.xpoints[0],polygon.ypoints[0],polygon.xpoints[3],polygon.ypoints[3]);
}
 
 
public void run(){}
public void start(){}
public void stop(){}
public void restart(){getTime();repaint();}
 
public void mouseDragged(MouseEvent evt){setTime(60);}
public void mouseMoved(MouseEvent evt){}
public void mousePressed(MouseEvent evt){}
public void mouseReleased(MouseEvent evt){}
public void mouseEntered(MouseEvent evt){}
public void mouseExited(MouseEvent evt){}
public void mouseClicked(MouseEvent evt){if(evt.getButton() == MouseEvent.BUTTON1){setTime(60);}else{setTime(-60);}}
public void mouseWheelMoved(MouseWheelEvent evt){setTime(-60*(evt.getWheelRotation()));}
public void keyPressed(java.awt.event.KeyEvent evt){
int key=evt.getKeyCode();
if(key == 37 || key == 8 ){setTime(59*60);}// left arrow
else
if(key == 39 || key ==32 ){setTime(60);}// right arrow
else
if(key == 33){setTime(3*900);}//page down
else
if(key == 34){setTime(900);}//page up
else
if(key > 48 && key < 58){setTime(3600*(key-48));}//1,2,3,4,5,6,7,8,9
else
if(use_seconds && (key == 83 || key == 114) ){setTime(1);}// s , F3
else
if(use_seconds && (key == 82 || key == 115) ){setTime(59);}// r , F4
else
if(key == 77 || key == 112 ){setTime(60);}// m , F1
else
if(key == 85 || key == 113 || key == 72){setTime(3600);}// u , h , F2
else
if(key == 116 || key == 127){setTime(11*3600);}// F5 ,del
//System.out.println(key);
}
public void keyTyped(KeyEvent evt){}
public void keyReleased(KeyEvent evt){}
 
public void setTime(double incr){
seconds = seconds + incr;
repaint();
}
 
}
 
 
 
/trunk/wims/src/Misc/authors/jm.evers/applets/WClock/src/WDClock.java
0,0 → 1,334
 
/*
jm.evers
2/2010
no copyrights :all amateur scriblings
Example usage:
 
<html>
<body>
<script type="text/javascript">
function ReadThis(){
var reply = document.getElementById('WClock').readApplet();
document.getElementById('showtime').innerHTML='<hr>first value is pupils\'s timeanswer<br>second value is initial time<br><font color=red><b>'+reply+'</b></font><hr>';
}
 
function increase(t,a){
if(t == 0 ){var reply = document.getElementById('WDClock').setApplet("H",a);}
else
if(t == 1 ){var reply = document.getElementById('WDClock').setApplet("M",a);}
else
if(t == 2 ){var reply = document.getElementById('WDClock').setApplet("S",a);}
}
function reset(){
document.getElementById('WSClock').restart();
}
</script>
<table>
<tr>
<td>
<div id="showtime"></div>
<br>
<applet id="WDClock" name="WDClock" code="WDClock.class" archive="WClock.jar" width="300" height="60">
<param name = "user_modify" value="yes"><!-- user sets time : default yes 0,no,1,yes -->
<param name = "fontsize" value = "150"><!-- size will be adjusted to xsize if too big -->
<param name = "backgroundcolor" value = "#ffffff"><!-- optional : default white -->
<param name = "displaycolor" value = "#ff00a0"><!-- optional : default red -->
<param name = "fontname" value = "Times"><!-- optional : default Helvetic -->
<param name = "use_system_time" value = "yes"><!-- optional : yes,1,no,0 set the clock to current system time -->
<param name = "clock_type" value="24"><!-- optional :default 12 hour clock -->
<param name = "hours" value="23"><!-- optional : if not set random value will be used -->
<param name = "minutes" value="2"><!-- optional : if not set random value will be used -->
<param name = "seconds" value="17"><!-- optional : if not set random value will be used -->
<param name = "alpha" value="120"><!-- optional : only for displaycolor -->
</applet>
<br>
<input type="button" name="read_time" value="read time" onclick="javascript:ReadThis();">
<br>
Setting time via Javascript :<br>
<input type="button" name="hours +" value="hours +" onclick="javascript:increase(0,1);">
<input type="button" name="min +" value="min +" onclick="javascript:increase(1,1);">
<input type="button" name="sec +" value="sec +" onclick="javascript:increase(2,1);">
<br>
<input type="button" name="hours &minus;" value="hours &minus;" onclick="javascript:increase(0,-1);">
<input type="button" name="min &minus;" value="min &minus;" onclick="javascript:increase(1,-1);">
<input type="button" name="sec &minus;" value="sec &minus;" onclick="javascript:increase(2,-1);">
<br>
</td>
<td>
Mouse &amp; Key Controls [if param "user_modify = yes"]
<ul>
<li> mouse over H,M,S display</li>
<li> space +1 </li>
<li> backspace -1</li>
<li> leftmouse +1</li>
<li> rightmouse -1</li>
<li> scrollmouse +/- 1 </li>
</ul>
</td>
</tr>
</table>
</body>
</html>
 
*/
 
import java.lang.*;
//import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.applet.Applet;
import java.awt.*;
import java.util.*;
import java.io.*;
import java.awt.Color;
import java.awt.event.*;
 
public class WDClock extends Applet implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener{
 
int xsize,ysize,H_in=0,M_in=0,S_in=0;
Graphics2D backg;
BufferedImage bg;
Font font;
int fontsize;
String fontname;
int edit=0;
int clock_type=12;
int uren,minuten,seconden;
Color displaycolor,backgroundcolor;
int alpha = -1;
boolean user_modify = true;
public void init(){
String param = getParameter("user_modify");
if(param != null && param.length() !=0){
if(param.equals("0") || param.equalsIgnoreCase("no")){user_modify = false;}
}
displaycolor = colorDecodeParam("displaycolor", Color.red);
backgroundcolor = colorDecodeParam("backgroundcolor", Color.white);
Dimension appletSize = this.getSize();
ysize = appletSize.height;xsize = appletSize.width;
bg = new BufferedImage(xsize,ysize, BufferedImage.TYPE_INT_ARGB);
backg = (Graphics2D) bg.getGraphics();
font = FitFont(backg,"Helvetica",180);
if(user_modify){
addMouseListener(this);
addMouseMotionListener(this);
addMouseWheelListener(this);
addKeyListener(this);
}
getTime();
uren = H_in;
minuten = M_in;
seconden = S_in;
prepaint();
//requestFocus();
}
public void setApplet(String type , int incr){
if(type.equals("H")){setTime(0,incr);}
else
if(type.equals("M")){setTime(1,incr);}
else
if(type.equals("S")){setTime(2,incr);}
}
public Font FitFont(Graphics g , String default_fontname , int default_fontsize){
fontsize = default_fontsize;
fontname = default_fontname;
String param;
param = getParameter("clock_type");
if(param != null){
if(param.equals("24")){clock_type = 24;}
}
param = getParameter("fontsize");
if(param != null){
try{
fontsize = Integer.parseInt(param);
}catch(Exception e){System.out.println("could not parse fontsize "+param);}
}
param = getParameter("font");
if(param != null){
try{
fontname = param;
}catch(Exception e){System.out.println("could nol load font"+param);}
}
font = new Font(fontname,Font.BOLD,fontsize);
FontMetrics fm = g.getFontMetrics(font);
if(fm.stringWidth("00:00:00") > xsize){
boolean does_not_fit = true;
while(fontsize > 4 && does_not_fit){
fontsize = fontsize - 1;
font = new Font(fontname,Font.BOLD,fontsize);
fm = g.getFontMetrics(font);
if(fm.stringWidth("00:00:00") < xsize){
does_not_fit = false;
}
}
System.out.println("xsize ("+xsize+") of applet too small...adjusting fontsize to "+fontsize);
}
return font;
}
public Color MakeTransparent(Color c, int a){
return new Color(c.getRed(),c.getGreen(),c.getBlue(),a);
}
 
public Color colorDecodeParam(String param, Color c0){
String c = getParameter(param);
if( c != null && c.length() !=0){
try{ c0 = Color.decode(c);}catch(Exception e){System.out.println("don\'t know color "+c+" ... setting to default");}
}
c = getParameter("alpha");
if( c != null && c.length() !=0){
try{ alpha = Integer.parseInt(c);
c0 = MakeTransparent(c0,alpha);
}catch(Exception e){System.out.println("could not parse alpha color "+ c );}
}
return c0;
}
public String MakeTimeString(int h , int m , int s){
String H="";
String M="";
String S="";
if(h>9){H=""+h+"";}else{H="0"+h;}
if(m>9){M=""+m+"";}else{M="0"+m;}
if(s>9){S=""+s+"";}else{S="0"+s;}
return H+":"+M+":"+S;
}
public void getTime(){
String param;boolean readparms=true;
param = getParameter("use_system_time");
if(param != null && param.length() !=0){
if(param.equals("1") || param.equalsIgnoreCase("yes")){
Date date = new Date();
S_in = date.getSeconds();
M_in = date.getMinutes();
H_in = date.getHours();
readparms=false;
}
}
if(readparms){
param = getParameter("hours");
if(param != null && param.length() !=0){
H_in = Integer.parseInt(param);
}else{H_in =(int) (Math.round(clock_type*(Math.random())));}
param = getParameter("minutes");
if(param != null && param.length() !=0){
M_in = Integer.parseInt(param);
}else{M_in =(int) (Math.round(59*(Math.random())));}
param = getParameter("seconds");
if(param != null && param.length() !=0){
S_in = Integer.parseInt(param);
}else{S_in =(int) (Math.round(59*(Math.random())));}
if(H_in > clock_type){H_in = H_in - clock_type;}
if(H_in > clock_type || H_in < 0){System.out.println("hours param "+ H_in+" is not correct");}
if(M_in > 60 || M_in <0){System.out.println("minutes param "+ M_in+" is not correct");}
if(S_in > 60 || S_in <0){System.out.println("seconds param "+ S_in+" is not correct");}
}
}
 
public String readApplet(){
return uren+":"+minuten+":"+seconden+","+H_in+":"+M_in+":"+S_in;
}
public void prepaint(){
backg.setColor(backgroundcolor);
backg.fillRect(0,0,xsize,ysize);
backg.setFont(font);
backg.setColor(displaycolor);
backg.drawString(MakeTimeString(uren,minuten,seconden),0,ysize);
}
 
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(bg,0,0,this);
}
public void paint(Graphics g){
update(g);
}
 
public void update(Graphics g){
prepaint();
paintComponent(g);
}
 
public void run(){}
public void start(){}
public void restart(){
getTime();
uren = H_in;
minuten = M_in;
seconden = S_in;
repaint();
}
public void stop(){}
 
public void mouseDragged(MouseEvent evt){
//setTime(60);
}
public void mouseMoved(MouseEvent evt){
if(evt.getX()>0 && evt.getX()<xsize/3){edit = 0;}
else
if(evt.getX()>xsize/3 && evt.getX()<2*xsize/3){edit = 1;}
else
if(evt.getX()>2*xsize/3 && evt.getX()<xsize){edit = 2;}
}
public void mousePressed(MouseEvent evt){}
public void mouseReleased(MouseEvent evt){}
public void mouseEntered(MouseEvent evt){}
public void mouseExited(MouseEvent evt){}
public void mouseClicked(MouseEvent evt){
edit = -1;
if(evt.getX()>0 && evt.getX()<xsize/3){edit = 0;}
else
if(evt.getX()>xsize/3 && evt.getX()<2*xsize/3){edit = 1;}
else
if(evt.getX()>2*xsize/3 && evt.getX()<xsize){edit = 2;}
if(edit >-1){
if(evt.getButton() == MouseEvent.BUTTON1){
setTime(edit,1);
}
else
if(evt.getButton() == MouseEvent.BUTTON3){
setTime(edit,-1);
}
}
}
public void mouseWheelMoved(MouseWheelEvent evt){setTime(edit,-1*(evt.getWheelRotation()));}
public void keyPressed(java.awt.event.KeyEvent evt){
int key=evt.getKeyCode();
if(key == 32){setTime(edit,1);}
else
if(key == 8){setTime(edit,1);}
//System.out.println(key);
}
public void keyTyped(KeyEvent evt){}
public void keyReleased(KeyEvent evt){}
 
public void setTime(int e , int incr){
if(e == 0){uren = uren + incr;} //uren
else
if(e == 1){minuten = minuten + incr;} // minuten
else
if(e == 2){seconden = seconden + incr;}//seconden
if(seconden <0){seconden = 59;minuten = minuten - 1;}
if(minuten <0){minuten = 59;uren = uren - 1;}
if(uren <0){uren = clock_type-1;}
if(seconden > 59){seconden = seconden%60;minuten++;}
if(minuten > 59){minuten = minuten%60;uren++;}
if(uren >= clock_type){uren = 0;}
repaint();
}
 
}
 
/trunk/wims/src/Misc/authors/jm.evers/applets/WClock/build.xml
0,0 → 1,65
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
 
This is the Ant build script for WClock.jar.
to build ,type:
ant -v
to clean , type
ant -v clean
-->
 
 
<project name="WClock" default="jar" basedir=".">
 
<description>WClock build file</description>
<!-- Set global properties for this build. -->
<property name="version" value="0.1"/>
<property name="source-dir" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="debug" value="true"/>
<property name="debuglevel" value="lines,var,source"/>
<property name="java-level" value="1.4"/>
<!-- Compiles the classes. -->
<target name="compile" description="Compile the source">
<delete includeEmptyDirs="true" quiet="true" dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${source-dir}" destdir="${build}"
deprecation="yes" debug="${debug}" debuglevel="${debuglevel}"
source="${java-level}" target="${java-level}"/>
 
</target>
 
 
<!-- Creates the jar file. -->
 
<target name="jar" depends="compile" description="Create WClock jar">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/WClock.jar">
<fileset dir="${build}"/>
<manifest>
<attribute name="Specification-Title" value="WClock"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="WClock"/>
<attribute name="Implementation-Version" value="${version}"/>
<section name="WClock">
<attribute name="Specification-Title" value="WClock"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Implementation-Title" value="WClock"/>
<attribute name="Implementation-Version" value="${version}"/>
</section>
</manifest>
 
</jar>
</target>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="./build"/>
<delete dir="./dist"/>
</target>
 
 
</project>