Copyright (C) 2000, 2001, Geert Vernaeve. All Rights Reserved.
package gve.calc.formula; import java.awt.*; import awt.*; import awt.Button; import java.awt.event.*; public class TabularView extends Container implements View,HasCursorPos,MouseSensitive,KeydnListener,CreatesPopup { private Tabular model;
Possible values: Somewhere_LEFT, Somewhere_RIGHT, 0 (off)
private int cursorPos; public TabularView(Tabular model, FormulaView view) { this.model = model; int w = model.getWidth(); int h = model.getHeight(); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { Part p = model.elementAt(i,j); Component comp = view.getView(p); add(comp); } } MVC.registerView(model,this); setLayout(new TabularLayout(h,w)); } public void updateView(Object with) { if (with instanceof TabularModified) { TabularModified mod = (TabularModified)with; if (mod.added) { if (mod.row) addRow(mod.i); else addCol(mod.i); } else { // removed // Must remove last elements first (else later elements shift back ...) if (mod.row) remRow(mod.i); else remCol(mod.i); } } } public void remRow(int row) { for (int j = model.getWidth()-1; j>=0; j--) remove(j + model.getWidth() * row); TabularLayout layout = (TabularLayout)getLayout(); layout.setRows(model.getHeight()); } public void remCol(int col) { for (int i = model.getHeight(); i>=0; i--) remove(col + model.getWidth() * i); TabularLayout layout = (TabularLayout)getLayout(); layout.setCols(model.getWidth()); } public void addRow(int row) { FormulaView view = FormulaView.get(this); for (int j = 0; j < model.getWidth(); j++) add(view.getView(model.elementAt(row,j)),j + model.getWidth() * row); TabularLayout layout = (TabularLayout)getLayout(); layout.setRows(model.getHeight()); } public void addCol(int col) { FormulaView view = FormulaView.get(this); for (int i = 0; i < model.getHeight(); i++) add(view.getView(model.elementAt(i,col)),col + model.getWidth() * i); TabularLayout layout = (TabularLayout)getLayout(); layout.setCols(model.getWidth()); } public Object getModel() { return model; } public void activate() {} public void deactivate() { cursorPos = 0; invalidate(); } public int getCursorPos() { return cursorPos; } public void setCursorPos(int pos) { switch (pos) { case Somewhere_LEFT: case Somewhere_RIGHT: cursorPos = pos; break; default: cursorPos = Somewhere_LEFT; break; } invalidate(); } public void paint(Graphics g) { super.paint(g); if (cursorPos == Somewhere_LEFT) { FontMetrics fm = getFontMetrics(getFont()); int fonth = fm.getHeight(); int spatwidth = fm.charWidth(' '); Dimension siz = getSize(); g.fillRect(0,(siz.height - fonth)/2,spatwidth,fonth); } else if (cursorPos == Somewhere_RIGHT) { FontMetrics fm = getFontMetrics(getFont()); int fonth = fm.getHeight(); int spatwidth = fm.charWidth(' '); Dimension siz = getSize(); g.fillRect(siz.width - spatwidth,(siz.height - fonth)/2,spatwidth,fonth); } } public boolean mousePressed(int flags,int x,int y) { return false; } public void mouseDown(int flags,int x,int y) { Dimension siz = getSize(); int spatwidth = getFontMetrics(getFont()).charWidth(' '); if (x<siz.width/2 && x<spatwidth*2) FormulaView.get(this).setCursorComp(this,Somewhere_LEFT); else if ((siz.width-x)<siz.width/2 && (siz.width-x)<spatwidth*2) FormulaView.get(this).setCursorComp(this,Somewhere_RIGHT); } public Component createPopup(int x,int y) { Button b; TabularListener listen = new TabularListener(this,x,y); Container cont = new Panel(); cont.setLayout(new GridPackLayout(0,1)); cont.add(b = new Button("Insert row")); b.addActionListener(listen); cont.add(b = new Button("Insert column")); b.addActionListener(listen); return cont; } public boolean keydn(int key) { FormulaView view = FormulaView.get(this); switch (key) { case Key_LEFT: if (cursorPos == Somewhere_RIGHT) { view.setCursorPart(model.elementAt(0,model.getWidth()-1),Somewhere_RIGHT); return true; } else if (cursorPos == 0) { Part p = view.getCursorPart(); Point which = model.whichOffspring(p); if (which.x > 0) view.setCursorPart(model.elementAt(which.y,which.x-1),Somewhere_RIGHT); else view.setCursorComp(this,Somewhere_LEFT); return true; } return false; case Key_RIGHT: if (cursorPos == Somewhere_LEFT) { // Go to leftmost element of the table which is not an Uneditable int j = 0; Part p; while (true) { p = model.elementAt(0,j); if (!(p instanceof Uneditable)) break; j++; } view.setCursorPart(p,Somewhere_LEFT); return true; } else if (cursorPos == 0) { Part p = view.getCursorPart(); Point which = model.whichOffspring(p); if (which.x+1 < model.getWidth()) view.setCursorPart(model.elementAt(which.y,which.x+1),Somewhere_LEFT); else view.setCursorComp(this,Somewhere_RIGHT); return true; } return false; case Key_UP: if (cursorPos == 0) { Part p = view.getCursorPart(); Point which = model.whichOffspring(p); if (which.y > 0) { view.setCursorPart(model.elementAt(which.y-1,which.x)); return true; } } return false; case Key_DOWN: if (cursorPos == 0) { Part p = view.getCursorPart(); Point which = model.whichOffspring(p); if (which.y < model.getHeight()-1) { view.setCursorPart(model.elementAt(which.y+1,which.x)); return true; } } return false; case Key_BS: if (cursorPos == Somewhere_RIGHT) { // PENDING: register an Undo action Formula f = view.getFormula(); Part empty; f.replace(model,empty = new Identifier("")); view.addUndoAction(new ReplaceUndo(f,empty,model)); return true; } return true; case Key_TAB: if (cursorPos == 0) { Point which = model.whichOffspring(view.getCursorPart()); // Find next element which is not Uneditable while (true) { Part p; if (which.x+1 < model.getWidth()) which.x++; else if (which.y+1 < model.getHeight()) { which.x = 0; which.y++; } else return false; p = model.elementAt(which.y,which.x); if (p instanceof Uneditable) continue; view.setCursorPart(p,Somewhere_LEFT); return true; } } return false; case Key_SHTAB: if (cursorPos == 0) { Point which = model.whichOffspring(view.getCursorPart()); // Find next element which is not Uneditable while (true) { Part p; if (which.x > 0) which.x--; else if (which.y > 0) { which.x = model.getWidth()-1; which.y--; } else return false; p = model.elementAt(which.y,which.x); if (p instanceof Uneditable) continue; view.setCursorPart(p,Somewhere_LEFT); return true; } } return false; } // end case if (cursorPos == Somewhere_LEFT) return view.splitleft(model,key); else if (cursorPos == Somewhere_RIGHT) return view.splitright(model,key); return false; } public void insertColAtPixel(int xpixel) { TabularLayout layout = (TabularLayout)getLayout(); model.insertCol(layout.pixel2colBetween(xpixel)); } public void insertRowAtPixel(int ypixel) { TabularLayout layout = (TabularLayout)getLayout(); model.insertRow(layout.pixel2rowBetween(ypixel)); } } class TabularListener implements ActionListener { TabularView tabview; int xpos,ypos; // point of mouse click public TabularListener(TabularView m,int x,int y) { tabview = m; xpos = x; ypos = y; } public void actionPerformed(ActionEvent evt) { String cmd = evt.getActionCommand(); if (cmd.equals("Insert row")) { tabview.insertRowAtPixel(ypos); } else if (cmd.equals("Insert column")) { tabview.insertColAtPixel(xpos); } } }