import com.symbian.devnet.util.TaskSwitch; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Canvas; import java.awt.Color; import java.awt.Dialog; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.FileDialog; import java.awt.FlowLayout; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Frame; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Label; import java.awt.Panel; import java.awt.Point; import java.awt.Scrollbar; import java.awt.SystemColor; import java.awt.TextField; import java.awt.Toolkit; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class JFastReader extends Frame implements ActionListener, AdjustmentListener { final int WND_W=208, WND_H=276; // initial window size final String APPNAME="jFastReader"; final String APPVERSION="1.0"; private static JFastReader jFastReader = null; Font ftPlain8 = new Font("Dialog", Font.PLAIN, 8); Font ftPlain10 = new Font("Dialog", Font.PLAIN, 10); Font ftBold12 = new Font("Dialog", Font.BOLD, 12); File curFile; int curWord = 1; int maxWord = 1; int defWordLen = 5; int sleepWPM = 120; int sleepWPMDelta = 5; MySeeker seeker = new MySeeker(); Panel pnMain = new Panel(new BorderLayout()); Panel pnTop = new Panel(new BorderLayout()); Panel pnTopLeft = new Panel(new FlowLayout(FlowLayout.LEFT,1,1)); Panel pnTopRight = new Panel(new FlowLayout(FlowLayout.RIGHT,1,1)); Panel pnBottom = new Panel(new BorderLayout()); Panel pnBottom2 = new Panel(new GridLayout(3,2,2,1)); Panel pnSpeed = new Panel(new BorderLayout()); Panel pnOptBook = new Panel(new GridLayout(1,2,1,1)); Panel pnSlowFast = new Panel(new GridLayout(1,2,1,1)); Panel pnBackForw = new Panel(new GridLayout(1,2,1,1)); Panel pnReadPaus = new Panel(new GridLayout(1,2,1,1)); Panel pnReptButt = new Panel(new GridLayout(1,2,1,1)); Panel pnButtons = new Panel(new GridLayout(2,1,1,1)); Label lbGo = new Label("Word:", Label.RIGHT); TextField tfGo = new TextField("", 4); Button btGo = new Button("Go"); Button btAbout = new Button("?"); Button btText = new Button("Go Text"); MyCanvas cvFR = new MyCanvas(); Scrollbar sbProgress = new Scrollbar(Scrollbar.HORIZONTAL, 0, 0, 0, 0); Label lbSpeedTag = new Label("Speed (wpm.)", Label.LEFT); MyProgBar cvSpeed = new MyProgBar(10,600,(long)sleepWPM, MyProgBar.PQ2); Label lbSpeed = new Label(String.valueOf(sleepWPM), Label.LEFT); Button btOptions = new Button("Opt."); Button btBookmark = new Button("Bkmk"); Button btSlower = new Button("<<\nSlwr"); Button btFaster = new Button(">>\nFstr"); Button btBack = new Button("<\nBKW"); Button btForw = new Button(">\nFWD"); Button btRead = new Button(">\nREAD"); Button btPause = new Button("||\nPAUS"); Button btRepeat = new Button("REPT"); Button btLoad = new Button("Load"); Button btQuit = new Button("Exit"); Dialog diAbout = new Dialog(this, "About...", true); Panel pnAboutText = new Panel(new GridLayout(0,1,0,0)); Panel pnAboutButt = new Panel(new FlowLayout(FlowLayout.RIGHT)); Label lbAbout1 = new Label(APPNAME, Label.CENTER); Label lbAbout2 = new Label("by Markus Birth", Label.CENTER); Label lbAbout3 = new Label("mbirth@webwriters.de", Label.CENTER); Label lbAbout4 = new Label("http://www.webwriters.de/mbirth/", Label.CENTER); Button btOk = new Button("OK"); Dimension dmScreen = Toolkit.getDefaultToolkit().getScreenSize(); // get Screen dimensions MyInfoPrint MIP = new MyInfoPrint(this); PlayThread ptRead = new PlayThread(); private class MainWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent we) { // TODO: Insert commands to execute upon shutdown MIP.infoPrint("Goodbye..."); MIP.hide(); System.exit(0); } } private class DummyWindowAdapter extends WindowAdapter { public void windowActivated(WindowEvent we) { } public void windowDeactivated(WindowEvent we) { if (we.getSource().equals(diAbout)) { diAbout.setVisible(false); } } public void windowClosing(WindowEvent we) { if (we.getSource().equals(diAbout)) { // System.out.println("About manually closed."); diAbout.setVisible(false); jFastReader.dispatchEvent(new WindowEvent(jFastReader, 201)); } } } // handler for ActionListener public void actionPerformed(ActionEvent ae) { if (ae.getSource().equals(btOk)) { // OK button on AboutScreen System.out.println("The user clicked OK. Trying to close the dialog."); diAbout.setVisible(false); } else if (ae.getSource().equals(btAbout)) { // About-Button System.out.println("The user clicked 'About' button."); diAbout.setVisible(true); btOk.requestFocus(); } else if (ae.getSource().equals(btQuit)) { // Quit-Button System.out.println("Exit button clicked. Sending event..."); dispatchEvent(new WindowEvent(this, 201)); } else if (ae.getSource().equals(btLoad)) { // Load-Button FileDialog fdLoad = new FileDialog(jFastReader, "Load file", FileDialog.LOAD); fdLoad.show(); if (fdLoad.getFile() != null) { System.out.println("Directory: "+fdLoad.getDirectory()); System.out.println("File: "+fdLoad.getFile()); curFile = new File(fdLoad.getDirectory() + fdLoad.getFile()); seeker = new MySeeker(); sbProgress.setMinimum(1); sbProgress.setValue(1); sbProgress.setVisibleAmount(1); sbProgress.setUnitIncrement(1); sbProgress.setBlockIncrement(10); curWord = 1; maxWord = 1; getWord(1); showWord(curWord); } else { MIP.infoPrint("Cancelled."); } } else if (ae.getSource().equals(btGo)) { try { int nw = Integer.parseInt(tfGo.getText()); if (nw >= 1 && nw <= maxWord) { curWord = nw; showWord(curWord); } else { MIP.infoPrint("Out of range"); } } catch (NumberFormatException nfe) { MIP.infoPrint("Not a number"); } } else if (ae.getSource().equals(btBack)) { System.out.println("<<< BACK"); if (curWord > 1) { showWord(--curWord); } } else if (ae.getSource().equals(btForw)) { System.out.println(">>> FORW"); if (curWord < maxWord) { showWord(++curWord); } } else if (ae.getSource().equals(btRead)) { ptRead.stopNow(); ptRead = new PlayThread(); ptRead.start(); } else if (ae.getSource().equals(btPause)) { ptRead.stopNow(); } else if (ae.getSource().equals(btSlower)) { if (sleepWPM-sleepWPMDelta>=10) { sleepWPM -= sleepWPMDelta; } lbSpeed.setText(String.valueOf(sleepWPM)); cvSpeed.setPos((long)sleepWPM); } else if (ae.getSource().equals(btFaster)) { if (sleepWPM+sleepWPMDelta<=600) { sleepWPM += sleepWPMDelta; } lbSpeed.setText(String.valueOf(sleepWPM)); cvSpeed.setPos((long)sleepWPM); } // TODO: more events } // handler for AdjustmentListener // used for Scrollbar sbProgress public void adjustmentValueChanged(AdjustmentEvent ae) { curWord = sbProgress.getValue(); showWord(curWord); } private String[] splitString(String str, String delim) { str = str.trim(); int i = 1; int lastIndex = 0; int idx; // System.out.println("sS: Input string is >"+str+"<, delimiter >"+delim+"<"); // System.out.println("sS: Counting words..."); while ((idx=str.indexOf(delim, lastIndex)) >= 0) { i++; lastIndex = idx+1; } // System.out.println("sS: Counted "+i+" words."); String[] result = new String[i]; lastIndex = 0; i = 0; while ((idx=str.indexOf(delim, lastIndex)) >= 0) { result[i] = str.substring(lastIndex, idx); // System.out.println("sS: Word #"+i+" >"+result[i]+"<"); lastIndex = idx+1; i++; } result[i] = str.substring(lastIndex); // System.out.println("sS: Word #"+i+" >"+result[i]+"<"); return result; } public String getWord(int w) { String result = ""; if (curFile != null && curFile.exists() && curFile.isFile()) { try { RandomAccessFile f = new RandomAccessFile(curFile, "r"); String tmp; long lastPos = 0; int wordcount = 1; if (seeker.len <= 0) { // get wordcounts MIP.busy("Indexing..."); while ((tmp = f.readLine()) != null) { // System.out.println("Read line: >" + tmp + "<"); tmp = tmp.trim(); tmp = strReplace(tmp, " ", " "); String[] words = splitString(tmp, " "); // System.out.println("Setting index for word #"+wordcount+" to pos. "+lastPos); seeker.add(wordcount, lastPos); wordcount += words.length; // System.out.println("New wordcount is now "+wordcount); lastPos = f.getFilePointer(); } maxWord = --wordcount; sbProgress.setMaximum(maxWord+1); MIP.hide(); MIP.infoPrint(String.valueOf(maxWord)+" words"); // System.out.println("Words at all: "+maxWord); } long[] seekpos = seeker.getSeekForWord(w); f.seek(seekpos[1]); String myLine = f.readLine().trim(); myLine = strReplace(myLine, " ", " "); int indexl = 0; while (seekpos[0]=0) { // System.out.println("Need word: "+w+"; cur: "+seekpos[0]); indexl = myLine.indexOf(" ", indexl+1)+1; seekpos[0]++; } // System.out.println("Need word: "+w+"; got: "+seekpos[0]); int indexr = myLine.indexOf(" ", indexl+1); if (indexr <= 0) { indexr = myLine.length(); } result = myLine.substring(indexl, indexr); f.close(); } catch (IOException ioe) { System.out.println("IOException while reading file: "+ioe.toString()); MIP.infoPrint("File IO error"); } } return result; } private String strReplace(String input, String search, String replace) { String output = input; while (output.indexOf(search)>=0) { int i = output.indexOf(search); int j = i+search.length(); output = output.substring(0,i)+replace+output.substring(j); } return output; } private void showWord(int w) { String wrd = getWord(w); int sleeplen = (int)((double)wrd.length()/(double)defWordLen*(double)60000/(double)sleepWPM); // System.out.println("Sleep for >"+wrd+"< is "+sleeplen); ptRead.setSleep(sleeplen); tfGo.setText(String.valueOf(w)); sbProgress.setValue(w); cvFR.setWord(wrd); } public JFastReader() { // Constructor addWindowListener(new MainWindowAdapter()); setTitle(APPNAME+" "+APPVERSION+" by Markus Birth"); // set Frame title //setResizable(false); setSize(WND_W, WND_H); // set Frame size setLocation((dmScreen.width-WND_W)/2, (dmScreen.height-WND_H)/2); // center Frame MIP.busy(APPNAME+" loading..."); doAbout(); btGo.addActionListener(this); btAbout.addActionListener(this); btLoad.addActionListener(this); btQuit.addActionListener(this); btBack.addActionListener(this); btForw.addActionListener(this); btRead.addActionListener(this); btPause.addActionListener(this); btSlower.addActionListener(this); btFaster.addActionListener(this); sbProgress.addAdjustmentListener(this); pnMain.setFont(ftPlain8); pnTopLeft.add(lbGo); pnTopLeft.add(tfGo); pnTopLeft.add(btGo); pnTopRight.add(btAbout); pnTopRight.add(btText); pnTop.add(pnTopLeft, BorderLayout.WEST); pnTop.add(pnTopRight, BorderLayout.EAST); pnSpeed.add(lbSpeedTag, BorderLayout.NORTH); pnSpeed.add(cvSpeed, BorderLayout.CENTER); pnSpeed.add(lbSpeed, BorderLayout.EAST); pnOptBook.add(btOptions); pnOptBook.add(btBookmark); pnSlowFast.add(btSlower); pnSlowFast.add(btFaster); pnBackForw.add(btBack); pnBackForw.add(btForw); pnReadPaus.add(btRead); pnReadPaus.add(btPause); pnButtons.add(btLoad); pnButtons.add(btQuit); pnReptButt.add(btRepeat); pnReptButt.add(pnButtons); pnBottom2.add(pnSpeed); pnBottom2.add(pnOptBook); pnBottom2.add(pnSlowFast); pnBottom2.add(pnBackForw); pnBottom2.add(pnReadPaus); pnBottom2.add(pnReptButt); pnBottom.add(sbProgress, BorderLayout.CENTER); pnBottom.add(pnBottom2, BorderLayout.SOUTH); pnMain.add(pnTop, BorderLayout.NORTH); pnMain.add(cvFR, BorderLayout.CENTER); pnMain.add(pnBottom, BorderLayout.SOUTH); add(pnMain); btOk.addActionListener(this); // TODO: more initialization commands show(); // automagically calls paint(Graphics g) MIP.hide(); // init done, hide infoPrint } public static void main(String args[]) { try { jFastReader = new JFastReader(); } catch (Exception ex) { System.out.println("Caught exception: "+ex.toString()); ex.printStackTrace(); System.exit(1); } } public final void doAbout() { pnAboutButt.add(btOk); lbAbout1.setFont(ftBold12); lbAbout2.setFont(ftPlain10); lbAbout3.setFont(ftPlain10); lbAbout4.setFont(ftPlain10); diAbout.setLayout(new BorderLayout()); diAbout.setBackground(SystemColor.control); pnAboutText.add(lbAbout1); pnAboutText.add(lbAbout2); pnAboutText.add(lbAbout3); pnAboutText.add(lbAbout4); diAbout.add(pnAboutText, "North"); diAbout.add(pnAboutButt, "South"); diAbout.addWindowListener(new DummyWindowAdapter()); diAbout.pack(); // without it, the Dialog won't get displayed!! Dimension dmAboutBox = diAbout.getSize(); Dimension dmWindow = this.getSize(); Point ptWindow = this.getLocation(); diAbout.setLocation(ptWindow.x+(dmWindow.width-dmAboutBox.width)/2, ptWindow.y+dmWindow.height-dmAboutBox.height); } private class MySeeker { int[] poses = new int[0]; long[] seeker = new long[0]; int len = 0; public void add(int word, long pos) { int[] newp = new int[len+1]; long[] news = new long[len+1]; for (int i=0;i0) { int i=0; while (i0) { i--; } // System.out.println("gSFW: Nearest word is #"+poses[i]+" at pos. "+seeker[i]); result[0] = poses[i]; result[1] = seeker[i]; } else { System.out.println("gSFW: No data."); result[0] = 0; result[1] = 0; } return result; } } private class PlayThread extends Thread { private boolean stopnow; private int sleeper = 1; public void run() { this.stopnow = false; try { while (!this.stopnow && curWord<=maxWord) { showWord(curWord++); try { Thread.sleep(sleeper); } catch (InterruptedException exIE) { System.out.println("PlayThread interrupted."); } } curWord--; if (!this.stopnow) { MIP.infoPrint("Text end."); } return; } catch (Exception ex) { System.out.println("Exception in PlayThread: "+ex.toString()); ex.printStackTrace(); } } public void setSleep(int s) { this.sleeper = s; } public void stopNow() { while (isAlive()) { this.stopnow = true; try { Thread.sleep(100); } catch (InterruptedException exIE) { System.out.println("stopNow interrupted."); } } } } }