/[gzz]/gzz/gzz/client/FallbackBinder.java
ViewVC logotype

Diff of /gzz/gzz/client/FallbackBinder.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.12 by tjl, Mon Aug 19 14:18:05 2002 UTC revision 1.13 by benja, Wed Oct 2 18:40:43 2002 UTC
# Line 1  Line 1 
1  /*  //(c):Benja Fallenstein
 Fallback.java  
  *  
  *    Copyright (c) 1999-2001, Ted Nelson and Tuomas Lukka  
  *  
  *    You may use and distribute under the terms of either the GNU Lesser  
  *    General Public License, either version 2 of the license or,  
  *    at your choice, any later version. Alternatively, you may use and  
  *    distribute under the terms of the XPL.  
  *  
  *    See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of  
  *    the licenses.  
  *  
  *    This software 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 README  
  *    file for more details.  
  *  
  */  
 /*  
  * Written by Tuomas Lukka  
  */  
2  package gzz.client;  package gzz.client;
3  import gzz.*;  import gzz.*;
 import gzz.errors.*;  
 import gzz.impl.*;  
 import gzz.mediaserver.*;  
 import gzz.mediaserver.storage.*;  
 import java.util.*;  
 import java.io.*;  
 import gzz.vob.VobScene;  
4  import java.awt.event.*;  import java.awt.event.*;
 import org.python.util.PythonInterpreter;  
 import gzz.vob.*;  
   
 import java.awt.*;  
   
 /** Keybindings for the Fallback client.  
  */  
 public class FallbackBinder extends AbstractBinder {  
 public static final String rcsid = "$Id$";  
     public static boolean dbg = true;  
     private static void p(String s) { if(dbg) pa(s); }  
     private static void pa(String s) { System.err.println(s); }  
   
     static final int NORMAL = Fallback.NORMAL;  
     static final int TEXT_1 = Fallback.TEXT_1;  
   
     // Directional operations  
     static final int NONE = 0;  
     static final int CONNECT = 1;  
     static final int DISCONNECT = 2;  
     static final int HOP = 3;  
     static final int NEW = 4;  
     static final int CLONE_R = 5;  
     static final int CLONE_L = 6;  
   
     /** The current operation waiting for a directional operation.  
      */  
     int directOp;  
   
     /** Our <code>Fallback</code> client.  
      */  
     Fallback fallback;  
   
     /** The text buffer for entering search strings.  
      */  
     String buffer;  
   
     Cell searchStart;  
   
     public FallbackBinder(Fallback fallback) {  
         this.fallback = fallback;  
     }  
   
   
     void dir(int win, int dim, int dir) {  
         Fallback.Win w = fallback.windows[win];  
         Dim[] dims = w.dims;  
   
         Cell n = dims[dim].s(w.cursor, dir);  
         Cell c;  
         p("Dir: "+dim+" "+dir+" '"+n+"'");  
         switch(directOp) {  
         case NONE: if(n != null) w.cursor = n; break;  
         case CONNECT: dims[dim].connect(w.cursor, dir, w.other.cursor); break;  
         case DISCONNECT: dims[dim].disconnect(w.cursor, dir); break;  
         case HOP: dims[dim].hop(w.cursor, dir); break;  
         case NEW: w.cursor = w.cursor.N(dims[dim], dir); break;  
         case CLONE_R:  
             c = fallback.windows[1].cursor.zzclone();  
             w.cursor.insert(dims[dim], dir, c);  
             w.cursor = c;  
             break;  
         case CLONE_L:  
             c = fallback.windows[0].cursor.zzclone();  
             w.cursor.insert(dims[dim], dir, c);  
             w.cursor = c;  
             break;  
         default:  
                   pa("???");  
         }  
         directOp = NONE;  
         AbstractUpdateManager.prioritize(this.screen);  
     }  
   
     void op(int op) {  
         directOp = op;  
     }  
   
     boolean save() {  
             try {  
                 gzz.slices.SliceSpace sp = (gzz.slices.SliceSpace)fallback.space;  
                 fallback.filers.saveAll(sp.getSlicer().exportAll());  
                 pa("Saved.");  
                 return true;  
             } catch(IOException e) {  
                 pa("Exception while saving: "+e);  
                 e.printStackTrace();  
                 return false;  
             }  
     }  
   
     public void keystroke(String k) {  
         p("Key: "+k);  
   
         if(k.equals("\uFFFF")) {  
             p("That strange \\uFFFF again-- ignore");  
             return;  
         }  
   
         try {  
             if(fallback.mode == NORMAL)  
                 normalModeKeystroke(k);  
             else if(fallback.mode == TEXT_1)  
                 textModeKeystroke(k);  
             else if(fallback.mode == fallback.SEARCH)  
                 searchModeKeystroke(k);  
             else {  
                 System.err.println("Oops, don't know this mode: "+fallback.mode);  
                 System.err.println("Resetting to NORMAL.");  
   
                 fallback.mode = NORMAL;  
             }  
         } catch(Error e) {  
             // when a directOp throws an exception, reset the state  
             // so that the next keypress doesn't throw  
             // the same exception again...  
             directOp = NONE; throw e;  
         } catch(RuntimeException e) {  
             directOp = NONE; throw e;  
         } finally {  
             AbstractUpdateManager.chg();  
         }  
     }  
   
     public void normalModeKeystroke(String k) {  
         if(k.equals("Tab")) {  
             p("Switching to text edit mode.");  
             fallback.mode = TEXT_1;  
             fallback.windows[1].textCursor = 0;  
         } else if(k.equals("Backspace")) {  
             directOp = NONE;  
         } else if(k.equals("Left")) {  
             dir(1, 0, -1);  
         } else if(k.equals("Right")) {  
             dir(1, 0, 1);  
         } else if(k.equals("Up")) {  
             dir(1, 1, -1);  
         } else if(k.equals("Down")) {  
             dir(1, 1, 1);  
         } else if(k.equals("Ctrl-S")) {  
             save();  
         } else if(k.equals("Ctrl-E")) {  
             editPlainText(fallback.windows[1].cursor);  
         } else if(k.equals("Ctrl-F")) {  
             fallback.mode = fallback.SEARCH;  
             buffer = "";  
             searchStart = fallback.windows[1].cursor;  
         } else if(k.length() == 1) {  
             switch(k.charAt(0)) {  
                 // Right Rose  
                 case 'i': case 'I': dir(1, 1, -1); break;  
                 case 'j': case 'J': dir(1, 0, -1); break;  
                 case 'l': case 'L': dir(1, 0, 1); break;  
                 case ',': case '<': dir(1, 1, 1); break;  
                 case 'k': dir(1, 2, 1); break;  
                 case 'K': dir(1, 2, -1); break;  
   
                 // Left Rose  
                 case 'e': case 'E': dir(0, 1, -1); break;  
                 case 's': case 'S': dir(0, 0, -1); break;  
                 case 'f': case 'F': dir(0, 0, 1); break;  
                 case 'c': case 'C': dir(0, 1, 1); break;  
                 case 'd': dir(0, 2, 1); break;  
                 case 'D': dir(0, 2, -1); break;  
   
                 // Ops  
                 case 'n': op(NEW); break;  
                 case '-': op(CONNECT); break;  
                 case 'b': op(DISCONNECT); break;  
                 case 'h': op(HOP); break;  
                 case 't': op(CLONE_R); break;  
                 case 'T': op(CLONE_L); break;  
   
                 // Dims  
                 case 'x': rotate(1, 0, 1); break;  
                 case 'X': rotate(0, 0, 1); break;  
                 case 'y': rotate(1, 1, 1); break;  
                 case 'Y': rotate(0, 1, 1); break;  
                 case 'z': rotate(1, 2, 1); break;  
                 case 'Z': rotate(0, 2, 1); break;  
   
                 // Special  
                 case 'v': changeView(1, 1); break;  
                 case 'V': changeView(0, 1); break;  
                 case 'r':  
                     fallback.windows[1].cursor =  
                         fallback.windows[1].cursor.getRootclone();  
                     break;  
                 case 'R':  
                     fallback.windows[0].cursor =  
                         fallback.windows[0].cursor.getRootclone();  
                     break;  
                 case 'q': if(save()) System.exit(0);  
             }  
         } else if(k.length() == 5 && k.startsWith("Alt-")) {  
             switch(k.charAt(4)) {  
                 case 'X': rotate(1, 0, -1); break;  
                 case 'Y': rotate(1, 1, -1); break;  
                 case 'Z': rotate(1, 2, -1); break;  
                 case 'V': changeView(1, -1); break;  
             }  
         } else if(k.length() == 11 && k.startsWith("Alt-Shift-")) {  
             switch(k.charAt(10)) {  
                 case 'X': rotate(0, 0, -1); break;  
                 case 'Y': rotate(0, 1, -1); break;  
                 case 'Z': rotate(0, 2, -1); break;  
                 case 'V': changeView(0, -1); break;  
             }  
         }  
     }  
   
     public void textModeKeystroke(String k) {  
         if(k.equals("Tab")) {  
             p("Switching to normal mode.");  
             fallback.mode = NORMAL;  
             fallback.windows[1].textCursor = -1;  
         } else if(k.equals("Left"))  
             fallback.windows[1].moveTextCursor(-1);  
         else if(k.equals("Right"))  
             fallback.windows[1].moveTextCursor(1);  
         else if(k.equals("Home") || k.equals("Ctrl-A"))  
             fallback.windows[1].textCursor = 0;  
         else if(k.equals("End") || k.equals("Ctrl-E"))  
             fallback.windows[1].textCursor =  
                 fallback.windows[1].cursor.t().length();  
         else if(k.equals("Backspace"))  
             fallback.windows[1].backspaceTextCursor();  
         else if(k.length() == 1)  
             fallback.windows[1].insertText(""+k);  
     }  
   
     void searchModeKeystroke(String k) {  
         if(k.equals("Enter")) { fallback.mode = NORMAL; return; }  
         if(k.equals("Shift-Enter")) {  
             fallback.windows[0].cursor = fallback.windows[1].cursor;  
             fallback.windows[1].cursor = searchStart;  
             fallback.mode = NORMAL;  
             return;  
         }  
         if(k.equals("ESC")) {  
             fallback.windows[1].cursor = searchStart;  
             fallback.mode = NORMAL;  
             return;  
         }  
   
         if(k.length() == 1) buffer += k;  
         else if(k.equals("Backspace")) {  
             if(buffer.equals("")) return;  
             buffer = buffer.substring(0, buffer.length()-1);  
         }  
   
         if(buffer.length() == 0) {  
             fallback.windows[1].cursor = searchStart; return;  
         }  
   
         SearchableCellTexter ct =  
             (SearchableCellTexter)fallback.space.getCellTexter();  
         Collection cs = ct.getStringSearcher().search(buffer);  
         if(cs == null || cs.isEmpty()) {  
             fallback.windows[1].cursor = searchStart; return;  
         }  
         Cell c = (Cell)cs.iterator().next();  
         fallback.windows[1].cursor = c;  
     }  
   
     void rotate(int win, int dim, int dir) {  
         int[] ind = fallback.windows[win].dimsIndices;  
         ind[dim] += dir;  
         if(ind[dim] < 0) ind[dim] = fallback.dimList.length - 1;  
         else if(ind[dim] >= fallback.dimList.length) ind[dim] = 0;  
         fallback.windows[win].updateDims();  
     }  
   
     void changeView(int win, int dir) {  
         Fallback.Win w = fallback.windows[win];  
         w.viewIndex += dir;  
         if(w.viewIndex < 0) w.viewIndex = fallback.viewList.length - 1;  
         else if(w.viewIndex >= fallback.viewList.length) w.viewIndex = 0;  
     }  
   
     /** Edit a cell's content as plain text.  
      *  This opens either an external editor, if one is specified in the  
      *  system property <code>user.editor</code>, or alternatively uses  
      *  an AWT window with a multiline text area (XXX not implemented).  
      */  
     public void editPlainText(Cell c) {  
         VStreamCellTexter texter = (VStreamCellTexter)c.space.getCellTexter();  
         gzz.media.EnfiladeAligner.Instance aligner =  
             texter.startEnfiladeAligner(c);  
         String editor = System.getProperty("user.editor", null);  
         String text = aligner.getString();  
         if(editor != null) {  
             text = execExternalEditor(editor, text, "UTF-8");  
         } else {  
             final Dialog win =  
                 new Dialog(new Frame(), "Gzz text editor", true);  
             win.setLocation(0, 0);  
             win.setSize(600, 400);  
             TextArea ta = new TextArea(text);  
             win.add(BorderLayout.CENTER, ta);  
             Panel p = new Panel(), q = new Panel();  
             win.add(BorderLayout.SOUTH, p);  
             p.setLayout(new BorderLayout());  
             p.add(q, BorderLayout.CENTER);  
             q.setLayout(new FlowLayout());  
             Button ok = new Button("OK"), cancel = new Button("Cancel");  
             q.add(ok); q.add(cancel);  
             /*p.add(new Label("(You can use Ctrl-E to close this box.)"),  
                   BorderLayout.SOUTH);*/  
   
             is_ok = false;  
             ok.addActionListener(new ActionListener() {  
                 public void actionPerformed(ActionEvent e) {  
                     is_ok = true; win.setVisible(false);  
                 }  
             });  
             cancel.addActionListener(new ActionListener() {  
                 public void actionPerformed(ActionEvent e) {  
                     is_ok = false; win.setVisible(false);  
                 }  
             });  
   
             /*  
             KeyListener kl = new KeyListener() {  
                 public void keyPressed(KeyEvent e) {}  
                 public void keyTyped(KeyEvent e) {}  
                 public void keyReleased(KeyEvent e) {  
                     if(e.getKeyCode() == (e.VK_CONTROL | e.VK_E)) {  
                         is_ok = true; win.setVisible(false);  
                     } else if(e.getKeyCode() == (e.VK_ESCAPE)) {  
                         is_ok = false; win.setVisible(false);  
                     }  
                 }  
             };  
             win.addKeyListener(kl);  
             ta.addKeyListener(kl);  
             */  
   
             win.setVisible(true);  
             if(!is_ok) return;  
             text = ta.getText();  
         }  
         texter.setEnfilade(c, aligner.getEnfilade(text));  
     }  
     private boolean is_ok;  
   
     /** Execute the external editor with the given input and return the  
      * output.  
      * @param editor The name of the editor. The filename is appended  
      *          to this after a space, so the editor can be something like  
      * <pre>  
      *          perl -pi -es/bcd/foo/g  
      * </pre>  
      *          The important point is that it has to put its output in the  
      *          same file as it got its input from.  
      * @param text The text to be edited.  
      * @param encoding The encoding to use when writing the characters  
      *                  to the disk.  
      *                  Currently recommended: ISO8859_1, but others  
      *                  may well work.  
      * @returns The edited text.  
      */  
     String execExternalEditor(String editor, String text, String encoding) {  
         File tmp = null;  
   
         try {  
             File dir = new File(System.getProperty("user.dir"));  
             tmp = gzz.util.TestingUtil.tmpFile(dir);  
   
             byte[] out = text.getBytes(encoding);  
             FileOutputStream fout = new FileOutputStream(tmp);  
             fout.write(out);  
             fout.close();  
   
             Process p = Runtime.getRuntime()  
                             .exec(editor+" "+tmp.getAbsolutePath());  
             p.waitFor();  
   
             int l = (int)tmp.length();  
             FileInputStream fin = new FileInputStream(tmp);  
             byte[] in = new byte[l];  
             if(fin.read(in) != in.length)  
                 throw new Error("Couldn't read fully");  
             fin.close();  
   
             return new String(in, encoding);  
         } catch(Exception e) {  
             e.printStackTrace();  
             throw new Error("Execing editor "+e);  
         } finally {  
             p("deleting "+tmp+" now");  
             if(tmp != null) tmp.delete();  
         }  
     }  
   
     public void timeout(Object o) {  
     }  
 }  
5    
6    public interface FallbackBinder {
7        void keystroke(String k, Fallback.Win win);
8        void mouse(MouseEvent e, Fallback.Win win);
9        void windowClosed(Fallback.Win win);
10    }

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26