package bmsi.fsp; import java.awt.*; import java.awt.event.*; import java.awt.peer.*; import java.awt.image.*; import java.io.*; abstract class FSComponent extends PWin implements Focus, ComponentPeer { protected Component target; protected FSToolkit toolkit; private int fg = 2; // foreground "color" private int bg = 0; // background "color" private int cursorType; private boolean enabled; private FSContainer parentpeer; int posx,posy; private static final char attr[] = { TI.A_DIM, // dark on black TI.A_DIM, // gray on black TI.A_NORMAL, // white on black TI.A_INVIS, // xprnt text (char)(TI.A_REVERSE|TI.A_DIM), // dark on gray (char)(TI.A_REVERSE|TI.A_DIM), // gray on gray (char)(TI.A_REVERSE|TI.A_DIM), // white on gray (sorry) (char)(TI.A_REVERSE|TI.A_DIM), // xprnt on gray (sorry) TI.A_REVERSE, TI.A_REVERSE, TI.A_REVERSE, TI.A_REVERSE, TI.A_DIM, // dark on xprnt TI.A_DIM, // gray on xprnt TI.A_NORMAL, // white on xprnt TI.A_INVIS, // xprnt text }; /** Return text attribute based on foreground and background "color"s. */ protected char getAttr(int fg) { return getAttr(fg,bg); } protected static char getAttr(int fg,int bg) { return attr[bg*4+fg]; } protected FSComponent(Component comp,FSToolkit toolkit) { super(toolkit.wm); this.toolkit = toolkit; target = comp; Container parent = target.getParent(); while (parent != null) { ComponentPeer peer = parent.getPeer(); if (peer instanceof FSContainer) { parentpeer = (FSContainer)parent.getPeer(); break; } parent = parent.getParent(); } initialize(); } /** This and all derived peer classes must define initialize() to copy all relevant attributes from the target component. */ protected void initialize() { Color c = target.getForeground(); if (c != null) setForeground(c); c = target.getBackground(); if (c != null) setBackground(c); Font f = target.getFont(); if (f != null) setFont(f); if (!target.isEnabled()) setEnabled(false); try { // jdk 1.0 has getCursor in frame only Cursor cursor = target.getCursor(); if (cursor.getType() != Cursor.DEFAULT_CURSOR) setCursor(cursor); } catch (NoSuchMethodError e) { } Rectangle r = target.getBounds(); if (!r.isEmpty()) setBounds(r.x,r.y,r.width,r.height); if (target.isVisible()) setVisible(true); } protected void finalize() { dispose(); } public void dispose() { toolkit.removeFocus(this); setVisible(false); target = null; } public void setEnabled(boolean a) { enabled = a; } abstract public void paint(Graphics g); /** Implement paint for Pwin. */ public void paint(int x,int y,int w,int h) { Graphics g = getGraphics(); //g.setClip(x,y,w,h); try { paint(g); } finally { g.dispose(); } } /** Add rectangle to list of areas to be repainted in ms time. * @see TUICanvas */ public void repaint(long ms,int x,int y,int w,int h) { int sx = toolkit.scale.width; int sy = toolkit.scale.height; try { repaint(x/sx,y/sy,w/sx+1,h/sy+1); } catch (IOException e) { throw new AWTError("TermIO"); } } public void print(Graphics g) { g.setColor(target.getForeground()); g.setFont(target.getFont()); // draw box around component for printing Dimension dim = target.getSize(); g.drawRect(0,0,dim.width - 1,dim.height - 1); target.print(g); } public Point getLocationOnScreen() { Point loc = target.getLocation(); Point ploc = parentpeer.getLocationOnScreen(); ploc.translate(loc.x,loc.y); return ploc; } /** Set component location by quantizing scaled coords to physical coords. */ public void setBounds(int x,int y,int w,int h) { int sx = toolkit.scale.width; int sy = toolkit.scale.height; posx = x/sx; posy = y/sy; if (parentpeer != null) super.setBounds( posx + parentpeer.loc.x,posy + parentpeer.loc.y,w/sx,h/sy); else super.setBounds(posx,posy,w/sx,h/sy); } /** Since most ASCII terminals don't have a mouse, most components need to be tabbed to to be useful. */ public boolean isFocusTraversable() { return enabled; } //public Object getTarget() { return target; } public Dimension getMinimumSize() { return target.getSize(); } public Dimension getPreferredSize() { return getMinimumSize(); } public ColorModel getColorModel() { return toolkit.getColorModel(); } public Toolkit getToolkit() { return toolkit; } public Graphics getGraphics() { Graphics g = toolkit.createGraphics(this); return g; } public FontMetrics getFontMetrics(Font font) { return toolkit.getFontMetrics(font); } final int pixelFromColor(Color c) { return toolkit.colorModel.getPixel(c); } public void setCursor(Cursor cursor) { cursorType = cursor.getType(); } public void setForeground(Color c) { fg = pixelFromColor(c); } public void setBackground(Color c) { bg = pixelFromColor(c); } /** Our TUI has only one font for now. */ public void setFont(Font f) { } public void requestFocus() { toolkit.setFocus(this); } public Image createImage(ImageProducer prod) { return null; } public Image createImage(int w,int h) { return null; } public boolean prepareImage(Image img,int w,int h,ImageObserver obs) { return false; } public int checkImage(Image img,int w,int h,ImageObserver obs) { return ImageObserver.ERROR | ImageObserver.ABORT; } public void handleEvent(AWTEvent e) { //System.err.println(e); /* if ( (e instanceof KeyEvent) && !((KeyEvent)e).isConsumed()) { Container p = target.getParent(); if (p != null) p.dispatchEvent(e); } */ } /* jdk 1.0 compatibility */ public final boolean handleEvent(Event e) { return false; } public final void reshape(int x,int y,int w,int h) { setBounds(x,y,w,h); } public final void show() { setVisible(true); } public final void hide() { setVisible(false); } public final void enable() { setEnabled(true); } public final void disable() { setEnabled(false); } public final Dimension minimumSize() { return getMinimumSize(); } public final Dimension preferredSize() { return getPreferredSize(); } /* Focus interface */ private void postVK(int vk,int mod,int k) { long ts = System.currentTimeMillis(); toolkit.theQueue.postEvent( new KeyEvent(target,KeyEvent.KEY_PRESSED,ts-1,mod,vk,(char)k)); toolkit.theQueue.postEvent( new KeyEvent(target,KeyEvent.KEY_RELEASED,ts,mod,vk,(char)k)); } /** Translate terminfo key to a KeyEvent. Called for each terminfo key. Can use terminfo keys directly to implement L&F, otherwise keys are translated to java.awt.KeyEvent. */ public void postKey(int k) { switch (k) { case 27: postVK(KeyEvent.VK_ESCAPE,0,k); break; case 127: postVK(KeyEvent.VK_DELETE,0,k); break; default: if (k > 0 && k < 27) { // map control keys to virtual keys int kc = KeyEvent.VK_A + k - 1; postVK(KeyEvent.VK_A + k - 1,KeyEvent.CTRL_MASK,k); } if (k < 128) { long ts = System.currentTimeMillis(); int kc = KeyEvent.VK_UNDEFINED; int modifiers = 0; if (k < ' ') modifiers = KeyEvent.CTRL_MASK; else if (Character.isUpperCase((char)k)) modifiers = KeyEvent.SHIFT_MASK; toolkit.theQueue.postEvent( new KeyEvent(target,KeyEvent.KEY_TYPED,ts,modifiers,kc,(char)k)); } else if (k > 256) { /* we should use a table to map terminfo keys, but we pick a few important ones for now. What should we do with KEY_F0?? Notice that f0-f10 are *not* in order in terminfo! */ switch (k -= 256) { case TI.KEY_TAB: postVK(KeyEvent.VK_TAB,0,9); return; case TI.KEY_BACK_TAB: case TI.KEY_BTAB: postVK(KeyEvent.VK_TAB,KeyEvent.SHIFT_MASK,0); return; case TI.KEY_F1: postVK(KeyEvent.VK_F1,0,0); return; case TI.KEY_F2: postVK(KeyEvent.VK_F2,0,0); return; case TI.KEY_F3: postVK(KeyEvent.VK_F3,0,0); return; case TI.KEY_F4: postVK(KeyEvent.VK_F4,0,0); return; case TI.KEY_F5: postVK(KeyEvent.VK_F5,0,0); return; case TI.KEY_F6: postVK(KeyEvent.VK_F6,0,0); return; case TI.KEY_F7: postVK(KeyEvent.VK_F7,0,0); return; case TI.KEY_F8: postVK(KeyEvent.VK_F8,0,0); return; case TI.KEY_F9: postVK(KeyEvent.VK_F9,0,0); return; case TI.KEY_F10: postVK(KeyEvent.VK_F10,0,0); return; case TI.KEY_F11: postVK(KeyEvent.VK_F11,0,0); return; case TI.KEY_F12: postVK(KeyEvent.VK_F12,0,0); return; case TI.KEY_UP: postVK(KeyEvent.VK_UP,0,0); return; case TI.KEY_DOWN: postVK(KeyEvent.VK_DOWN,0,0); return; case TI.KEY_LEFT: postVK(KeyEvent.VK_LEFT,0,0); return; case TI.KEY_RIGHT: postVK(KeyEvent.VK_RIGHT,0,0); return; } // shifted/special function keys if (k >= TI.KEY_SF1 && k < TI.KEY_SF1+10) { postVK(KeyEvent.VK_F1 + k - TI.KEY_SF1,KeyEvent.SHIFT_MASK,0); return; } } } } public void loseFocus() { toolkit.theQueue.postEvent(new FocusEvent(target,FocusEvent.FOCUS_LOST)); } public void gainFocus() { toolkit.theQueue.postEvent(new FocusEvent(target,FocusEvent.FOCUS_GAINED)); } }