package tarau.jinnigui; import tarau.jinni.*; import java.util.*; import java.awt.*; import java.awt.image.*; import java.applet.*; import java.net.URL; /** Registers Jinni builtins for GUI programs */ public class GuiBuiltins extends Builtins { GuiBuiltins() { super(); register(new new_frame()); register(new new_button()); register(new new_label()); register(new set_label()); register(new dialog()); register(new file_dialog()); register(new new_panel()); register(new new_color()); register(new set_fg()); register(new set_bg()); register(new set_color()); register(new add_to()); register(new remove_from()); register(new destroy()); register(new remove_all()); register(new set_layout()); register(new show()); register(new resize()); register(new move()); register(new new_console()); register(new get_applet()); register(new new_text()); register(new get_text()); register(new add_text()); register(new clear_text()); register(new new_image()); register(new new_canvas()); register(new draw()); } /* public static void register(Const proto) { Init.builtinDict.register(proto); } */ static LayoutManager to_layout(Term L) { LayoutManager M=null; if(L instanceof Fun) { Fun F=(Fun)L; int x=(int)((Int)F.getArg(0)).getValue(); int y=(int)((Int)F.getArg(1)).getValue(); M=new GridLayout(x,y,5,5); } else { String m=((Const)L).name(); if(m.equals("border")) { M=new BorderLayout(); //IO.mes("border"); } //else if(m.equals("card")) { // M=new CardLayout(); //} else M=new FlowLayout(); } return M; } static public void add_it(Container P,Component C) { LayoutManager M=P.getLayout(); //IO.mes("layout:"+M); if(M instanceof BorderLayout) { int n=P.countComponents(); //IO.mes("comp: "+n); switch(n) { case 0: P.add("Center",C); break; case 1: P.add("North",C); break; case 2: P.add("South",C); break; case 3: P.add("East",C); break; case 4: P.add("West",C); break; default: IO.errmes("component not added:" +C); } } else P.add(C); } } /** Generic and portable event handling through interfaces If component implements Runable2 than its run/2 method will be called by the action event dispatcher. */ interface Runnable2 { void run(Event evt,Object arg); } interface Runnable1 { void run(Object arg); } interface JinniContainer { public void add_it(Component C); public void show_it(); } class JinniFrame extends Frame implements JinniContainer { JinniFrame(String title,LayoutManager L) { super(title); setLayout(L); // hgap=10,vgap=10 resize(400,200); // reasonable initial default size } public void show_it() { validate(); //pack(); do not add this - makes the frame shrink super.show(); } public void add_it(Component L) { GuiBuiltins.add_it(this,L); } public boolean action(Event evt, Object arg) { if(evt.target instanceof Runnable) { //new Thread((Runnable)evt.target).start(); // the Runnable should take care to launch new thread, if needed ((Runnable)evt.target).run(); } else if(evt.target instanceof Runnable1) { ((Runnable1)evt.target).run(arg); } else if(evt.target instanceof Runnable2) { ((Runnable2)evt.target).run(evt,arg); } else { IO.println("UNEXPECTED TARGET: "+evt.target); return false; } return true; } public boolean handleEvent(Event event) { if (event.id == Event.WINDOW_DESTROY) { removeNotify(); //Runtime.getRuntime().exit(0); //dispose(); } return super.handleEvent(event); } } class new_frame extends FunBuiltin { public new_frame() {super("new_frame",3);} public int exec(Prog p) { String title=getArg(0).toUnquoted(); LayoutManager L=GuiBuiltins.to_layout(getArg(1)); Term frameTerm=new JavaObject(new JinniFrame(title,L)); return putArg(2,frameTerm,p); } } /* Examples of Jinni GUI components - add more ! */ /** Button with attached Jinni action. Runs action on new thread, when Button pushed. */ class JinniButton extends Button implements Runnable { JinniButton(String name,Term action) { super(name); this.name=name; this.action=action; // copy() called in corresponding builtin prog=null; } private String name; private Term action; private Prog prog; /** Passes action to Jinni when Button is pushed */ public void run() { if(prog!=null) prog.stop(); //prog=Prog.bg(action); prog=Prog.new_engine(action,action); prog.getElement(); prog.stop(); } } /** new_button(JinniContainer,Name,Action,Button): creates a Button with label Name and attaches to it an action Action */ class new_button extends FunBuiltin { public new_button() {super("new_button",4);} // arg 0=container, arg 1=name, arg 2=action, arg 3=button public int exec(Prog p) { JinniContainer C =(JinniContainer)(((JavaObject)getArg(0)).toObject()); String name=getArg(1).toUnquoted(); JinniButton JB=new JinniButton(name,getArg(2).copy()); C.add_it(JB); return putArg(3,new JavaObject(JB),p); } } class new_label extends FunBuiltin { public new_label() {super("new_label",3);} public int exec(Prog p) { // 0=frame 1=name 2=action 3=button Container C =(Container)(((JavaObject)getArg(0)).toObject()); String name=getArg(1).toUnquoted(); Label L=new Label(name); L.setAlignment(Label.CENTER); return putArg(2,new JavaObject(C.add(L)),p); } } /* writes new text to a Label */ class set_label extends FunBuiltin { public set_label() {super("set_label",2);} public int exec(Prog p) { //get the handle to the wrapped Label JavaObject wrapper=(JavaObject)getArg(0); //get the Label Label L=(Label)(wrapper.toObject()); L.setText(getArg(1).toUnquoted()); return 1; } } class JinniDialog extends Dialog { TextField field; Frame parent; Button setButton; dialog caller; private boolean finished; JinniDialog(Frame parent, String title,dialog caller,int x,int y) { super(parent, title, false); this.parent = parent; this.caller = caller; setFinished(false); move(x,y); //Create middle section. Panel p1 = new Panel(); Label label = new Label("Enter your answer:"); p1.add(label); field = new TextField(40); p1.add(field); add("Center", p1); //Create bottom row. Panel p2 = new Panel(); p2.setLayout(new FlowLayout(FlowLayout.RIGHT)); setButton = new Button("Submit"); //Button b = new Button("Cancel"); p2.add(setButton); //p2.add(b); add("South", p2); //Initialize this dialog to its preferred size. validate(); pack(); } synchronized private void setFinished(boolean x) { finished=x; notify(); } synchronized void waitAction() { while(!finished) { try { wait(); } catch(InterruptedException e) {} } } public boolean action(Event event, Object arg) { if ( (event.target == setButton) || (event.target == field)) { caller.setAnswer(field.getText()); } field.selectAll(); hide(); setFinished(true); return true; } public boolean handleEvent(Event event) { if (event.id == Event.WINDOW_DESTROY) { //Runtime.getRuntime().exit(0); caller.setAnswer(null); setFinished(true); dispose(); } return super.handleEvent(event); } } /** dialog(Query,X,Y,Answer): ask a question and collects trhe answer through a modal dialog in a window at X,Y */ class dialog extends FunBuiltin { public dialog() {super("dialog",4);} private String answer=null; public void setAnswer(String answer) { this.answer=answer; } public int exec(Prog p) { Frame F=new Frame(); String title=getArg(0).toUnquoted(); int x=(int)((Int)getArg(1)).getValue(); int y=(int)((Int)getArg(2)).getValue(); JinniDialog D=new JinniDialog(F,title,this,x,y); D.show(); D.waitAction(); F.dispose(); if(null==answer) return 0; return putArg(3,new Const(answer),p); } } class JinniPanel extends Panel implements JinniContainer { JinniPanel(LayoutManager L) { super(); setLayout(L); } JinniPanel() { this(new FlowLayout()); } public void show_it() { validate(); super.show(); } public void add_it(Component C) { GuiBuiltins.add_it(this,C); } } class file_dialog extends FunBuiltin { public file_dialog() {super("file_dialog",3);} public int exec(Prog p) { Frame C=new Frame("File Dialog"); int mode=(int)((Int)getArg(0)).getValue(); FileDialog D; if(0==mode) { D=new FileDialog(C,"Jinni Read File Dialog",FileDialog.LOAD); } else { D=new FileDialog(C,"Jinni File Saving Dialog",FileDialog.SAVE); } D.show(); String fname=D.getFile(); if(null==fname) return 0; String dname=D.getDirectory(); if(null==dname) return 0; int ok=putArg(1,new Const(dname),p); if(1==ok) ok=putArg(2,new Const(fname),p); D.dispose(); C.dispose(); return ok; } } class new_panel extends FunBuiltin { public new_panel() {super("new_panel",3);} public int exec(Prog p) { JinniContainer C=(JinniContainer)(((JavaObject)getArg(0)).toObject()); LayoutManager L=GuiBuiltins.to_layout(getArg(1)); JinniPanel P=new JinniPanel(L); C.add_it(P); return putArg(2,new JavaObject(P),p); } } class JinniText extends TextArea { JinniText(String oldText,int lines,int cols) { super(oldText,lines,cols); } public boolean handleEvent(Event event) { if (event.id == Event.KEY_PRESS) { setBackground(Color.white); } return super.handleEvent(event); } } /** new(ParentContainer,oldText,JavaObject): initialises a textArea with oldText and returns a handle to it ARGS: 1=Parent Container 2=initial text content 3=rows 4=cols 5=returned handles */ class new_text extends FunBuiltin { public new_text() {super("new_text",5);} public int exec(Prog p) { JinniContainer C=(JinniContainer)(((JavaObject)getArg(0)).toObject()); String oldText=getArg(1).toUnquoted(); int rows=(int)((Int)getArg(2)).getValue(); int cols=(int)((Int)getArg(3)).getValue(); JinniText T=new JinniText(oldText,rows,cols); C.add_it(T); return putArg(4,new JavaObject(T),p); } } /** get_text(JinniText,Answer): collects the cpntent of thext area to new constant Answer */ class get_text extends FunBuiltin { public get_text() {super("get_text",2);} public int exec(Prog p) { JinniText T=(JinniText)(((JavaObject)getArg(0)).toObject()); String content=T.getText(); return putArg(1,new Const(content),p); } } /** add_text */ class clear_text extends FunBuiltin { public clear_text() {super("clear_text",1);} public int exec(Prog p) { JinniText T=(JinniText)(((JavaObject)getArg(0)).toObject()); T.setText(""); return 1; } } /** add_text */ class add_text extends FunBuiltin { public add_text() {super("add_text",2);} public int exec(Prog p) { JinniText T=(JinniText)(((JavaObject)getArg(0)).toObject()); String content=getArg(1).toUnquoted(); T.appendText(content); return 1; } } class new_color extends FunBuiltin { public new_color() {super("new_color",4);} public int exec(Prog p) { double r=((Num)getArg(0)).getValue(); double g=((Num)getArg(1)).getValue(); double b=((Num)getArg(2)).getValue(); if(r>1||r<0) {IO.errmes("new_color arg 1 should be in 0..1->"+r);} if(g>1||g<0) {IO.errmes("new_color arg 2 should be in 0..1->"+g);} if(b>1||b<0) {IO.errmes("new_color arg 3 should be in 0..1->"+b);} int R=(int)(r*255.0); int G=(int)(g*255.0); int B=(int)(b*255.0); Color C=new Color(R,G,B); Term ColorTerm=new JavaObject(C); return putArg(3,ColorTerm,p); } } class set_fg extends FunBuiltin { public set_fg() {super("set_fg",2);} public int exec(Prog p) { //get the handle and then the wrapped Component Component component=(Component)(((JavaObject)getArg(0)).toObject()); Color color=(Color)(((JavaObject)getArg(1)).toObject()); component.setForeground(color); return 1; } } class set_color extends FunBuiltin { public set_color() {super("set_color",2);} public int exec(Prog p) { JinniCanvas component=(JinniCanvas)(((JavaObject)getArg(0)).toObject()); Color color=(Color)(((JavaObject)getArg(1)).toObject()); component.setColor(color); return 1; } } class set_bg extends FunBuiltin { public set_bg() {super("set_bg",2);} public int exec(Prog p) { //get the handle and then the wrapped Component Component component=(Component)(((JavaObject)getArg(0)).toObject()); Color color=(Color)(((JavaObject)getArg(1)).toObject()); component.setBackground(color); return 1; } } /** add_to(Container,What,Where) adds component What at a place Where. Where is a numerical position (-1 to indicate at the end). or a direction keyword: 'North', 'South', 'Center' etc.) */ class add_to extends FunBuiltin { public add_to() {super("add_to",3);} public int exec(Prog p) { Container container=(Container)(((JavaObject)getArg(0)).toObject()); Component component=(Component)(((JavaObject)getArg(1)).toObject()); Term Where=getArg(2); if(Where instanceof Const) { String direction=((Const)Where).name(); container.add(direction,component); } else { int position=(int)((Int)Where).getValue(); container.add(component,position); // -1 means at end } return 1; } } class remove_from extends FunBuiltin { public remove_from() {super("remove_from",2);} public int exec(Prog p) { Container container=(Container)(((JavaObject)getArg(0)).toObject()); Component component=(Component)(((JavaObject)getArg(1)).toObject()); container.remove(component); return 1; } } class destroy extends FunBuiltin { public destroy() {super("destroy",1);} public int exec(Prog p) { Component C=(Component)(((JavaObject)getArg(0)).toObject()); C.removeNotify(); return 1; } } class remove_all extends FunBuiltin { public remove_all() {super("remove_all",1);} public int exec(Prog p) { Container C=(Container)(((JavaObject)getArg(0)).toObject()); C.removeAll(); return 1; } } class set_layout extends FunBuiltin { public set_layout() {super("set_layout",2);} public int exec(Prog p) { Container C=(Container)(((JavaObject)getArg(0)).toObject()); C.removeAll(); String layoutName=getArg(1).toUnquoted(); if("border".equals(layoutName)) C.setLayout(new BorderLayout()); else if("grid".equals(layoutName)) C.setLayout(new GridLayout(1,1)); else if("flow".equals(layoutName)) C.setLayout(new FlowLayout()); else return 0; return 1; } } class show extends FunBuiltin { public show() {super("show",1);} public int exec(Prog p) { JinniContainer C=(JinniContainer)(((JavaObject)getArg(0)).toObject()); C.show_it(); return 1; } } class resize extends FunBuiltin { public resize() {super("resize",3);} public int exec(Prog p) { Component C=(Component)(((JavaObject)getArg(0)).toObject()); int h=(int)((Int)getArg(1)).getValue(); int v=(int)((Int)getArg(2)).getValue(); C.resize(h,v); return 1; } } class move extends FunBuiltin { public move() {super("move",3);} public int exec(Prog p) { Component C=(Component)(((JavaObject)getArg(0)).toObject()); int hpos=(int)((Int)getArg(1)).getValue(); int vpos=(int)((Int)getArg(2)).getValue(); C.move(hpos,vpos); return 1; } } /* Jinni Console providing a simple toplevel inherits run() from GuiEngine which is used to start it on its own thread. */ class JinniConsole extends GuiEngine { private String first; JinniConsole(Container container,String first) { super(container); this.first=first; } /** Initializes Jinni input area with this */ public String firstQuery() { return first; } } class new_console extends FunBuiltin { public new_console() {super("new_console",3);} public int exec(Prog p) { Container C=(Container)(((JavaObject)getArg(0)).toObject()); String query=getArg(1).toUnquoted(); JinniConsole E=new JinniConsole(C,query); C.add(E); C.show(); JavaObject I=new JavaObject(E); new Thread(E).start(); return putArg(2,I,p); } } /** detects if applet and gets applet container */ class get_applet extends FunBuiltin { public get_applet() {super("get_applet",1);} public int exec(Prog p) { if(null==IO.applet) return 0; Applet applet = (Applet)IO.applet; return putArg(0,new JavaObject(applet),p); } } class JinniImagePanel extends Canvas { private String sourceName; private Image image; private int width; private int height; JinniImagePanel(String sourceName,int width,int height) { this.sourceName=sourceName; this.width=width; this.height=height; if(null!=IO.applet) { Applet applet=(Applet)IO.applet; URL url=applet.getCodeBase(); image=applet.getImage(url,sourceName); } else image=Toolkit.getDefaultToolkit().getImage(sourceName); } // see also (inherited) ImageObserver public void paint(Graphics g) { if(width<=0 || height <=0) { width=image.getWidth(this); height=image.getHeight(this); } resize(width,height); g.drawImage(image, 0,0, width, height, this); } } class new_image extends FunBuiltin { public new_image() {super("new_image",5);} public int exec(Prog p) { JinniContainer C=(JinniContainer)(((JavaObject)getArg(0)).toObject()); String src=((Const)getArg(1)).name(); int width=(int)((Int)getArg(2)).getValue(); int height=(int)((Int)getArg(3)).getValue(); JinniImagePanel P=new JinniImagePanel(src,width,height); C.add_it(P); JavaObject JP=new JavaObject(P); return putArg(4,JP,p); } } class JinniCanvas extends Canvas { JinniCanvas() { V=new Vector(); } Vector V; Color color=null; void setColor(Color color) { this.color=color; } void to_draw(Fun C) { V.addElement(C); } // see also (inherited) ImageObserver public void paint(Graphics g) { if(null!=color) g.setColor(color); Enumeration E=V.elements(); while(E.hasMoreElements()) { Fun T=(Fun)E.nextElement(); IO.mes("drawing: "+T); int x=T.getIntArg(0); int y=T.getIntArg(1); int dx=T.getIntArg(2); int dy=T.getIntArg(3); g.fill3DRect(x,y,dx,dy,true); } } } class new_canvas extends FunBuiltin { public new_canvas() {super("new_canvas",2);} public int exec(Prog p) { JinniContainer C=(JinniContainer)(((JavaObject)getArg(0)).toObject()); JinniCanvas P=new JinniCanvas(); C.add_it(P); JavaObject JP=new JavaObject(P); return putArg(1,JP,p); } } class draw extends FunBuiltin { public draw() {super("draw",2);} public int exec(Prog p) { JinniCanvas C=(JinniCanvas)(((JavaObject)getArg(0)).toObject()); Fun D=(Fun)getArg(1); C.to_draw(D); return 1; } }