/* -*- c++ -*- * %W% %E% * * Applet: Cryptogram (Java 1.2) * Author: Ralph Morelli, Trinity College (ralph.morelli@mail.trincoll.edu) * Description: Displays a weekly cryptogram and provides a simple GUI * for solving it. * * Copyright (c) 1996 Ralph Morelli. All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes and * without fee is hereby granted. */ import java.applet.*; import java.awt.*; import java.awt.event.*; import java.lang.InterruptedException; import java.net.*; import java.io.*; import java.util.*; // StringTokenizer, Calendar classes public class CryptoGramApplet extends Applet implements MouseListener, KeyListener { // REFERENCE CONSTANTS FOR PAINTING final static int kTopCrypto = 45, kLeftCrypto = 20; final static int kBlockWidth = 30, kBlockHeight = 30, kBlocksWide = 13, kBlocksHigh = 2; final static int kTopKey = kTopCrypto + 10 + kBlockHeight*kBlocksHigh+8; final static int kLeftKey = 20; final static int kLeftPlain = 20; final static int kTopPlain = kTopKey + 10 + kBlockHeight*kBlocksHigh+8; final static int kAppWidth = 40 + (kBlockWidth * kBlocksWide); // 430 final static int kAppHeight = 3 * (kBlockHeight * kBlocksHigh + 30); // 270 final static int kButtonWidth = 100, kButtonHeight = 25, kPadding = 20; final static Font bigFont = new Font("TimesRoman",0,18); final static Font regularFont = new Font("TimesRoman", 0, 12); final static int kRegFontSize = 12, kLineLength = 56, kMaxLines = 4, kMaxKeys = 26, kMaxChars = 2048; final static String cgrams = "cgrams/"; // where cryptograms are stored final static Color appletbGround = new Color(100,30,255); // dark blue final static Color textbGround = Color.yellow; final static Color titleColor = Color.yellow; final static Color textColor = Color.blue; final static Color buttonbGround = Color.yellow; final static Color buttonFocusColor = Color.white; final static Color labelColor = Color.red; private CryptoGram cryptoGram; private Point mouse; private String hintPrompt = "For a hint, type and the letter you want to know."; private String hintString = ""; private String weekString; public String getAppletInfo() { return "Cryptogram of the Week by Ralph Morelli"; } /*** Parameter Info */ public String[][] getParameterInfo() { String[][] info = {{"cryptosource","url","text file containing the cryptogram"},}; return info; } /** * init() initializes the applet. Most of the applet is painted. */ public void init() { Calendar calendar = Calendar.getInstance(); // Find what week it is weekString = "week" + calendar.get(Calendar.WEEK_OF_YEAR); cryptoGram = new CryptoGram(new String(downloadCryptogram())); setLayout(new FlowLayout (FlowLayout.LEFT)); addMouseListener(this); // Set up listeners addKeyListener(this); } // init() /** * downloadCryptogram() gets the cryptogram from the server by * using a URL to create an input stream to the applet's home base. * @return a String giving the contents of cryptogram file */ private String downloadCryptogram() { String cryptogram = null; // Build URL for cryptogram String urlString = getDocumentBase() + ""; urlString = urlString.substring(0,urlString.lastIndexOf('/')); urlString = urlString + "/" + cgrams + weekString + ".txt"; try { // Set up the URL URL cryptoSource = new URL (urlString); InputStream is = cryptoSource.openStream(); // Get URL's input stream byte cryptoBytes[] = new byte[kMaxChars]; int count = is.read(cryptoBytes); is.close(); cryptogram = new String(cryptoBytes); } catch (IOException e) { e.printStackTrace(); } return cryptogram; } /** * paintString() paints the cryptogram or the plaingtext string in a rectangular region * on the applet. * @param cString the cryptogram * @param left, top -- reference points for the painting * @param linelen -- the length of each line */ public void paintString(Graphics g, String cString,int left,int top,int linelen) { String tmpString = ""; g.setFont(regularFont); g.setColor(textbGround); // Draw rectangular area g.draw3DRect(left-4,top-4,kBlockWidth*kBlocksWide+8,kBlockHeight*kBlocksHigh+8,true); g.setColor(textbGround); // Fill rectangular area g.fillRect(left-4+1,top-4+1,kBlockWidth*kBlocksWide+8-1,kBlockHeight*kBlocksHigh+8-1); g.setColor(textColor); StringTokenizer st = new StringTokenizer(cString, "\n\r\f"); // Linefeed tokens StringBuffer buf = new StringBuffer(); int k = 1; while (st.hasMoreTokens()) { g.drawString(st.nextToken(), left + 2, top + (kRegFontSize +1) * k++); } } // paintString() /** * paint() draws the applet's GUI */ public void paint(Graphics g) { g.draw3DRect(0,0,kAppWidth,kAppHeight,true); // Paint background g.setColor(appletbGround); // Fill outer rectangle g.fillRect(0+1,0+1,kAppWidth-1,kAppHeight-1); g.setColor(titleColor); // Title g.setFont(bigFont); g.drawString("Cryptogram of the Week (" + weekString + ")", 110 ,20 ); g.setFont(regularFont); g.drawString(hintPrompt, 95, 35); g.drawString(hintString, 10, 15); String cryptoString = cryptoGram.getCipherText(); paintString(g, cryptoString, kLeftCrypto,kTopCrypto, kLineLength); // Cryptogram g.setColor(textbGround); // Keyboard g.draw3DRect(kLeftKey-4,kTopKey-4,kBlockWidth*kBlocksWide+8,kBlockHeight*kBlocksHigh+8,true); g.setColor(appletbGround); g.fillRect(kLeftKey-4+1,kTopKey-4+1,kBlockWidth*kBlocksWide+8-1,kBlockHeight*kBlocksHigh+8-1); for (int j = 0 ; j < kBlocksHigh ; j++) { // draw 26 letter keys for (int i = 0 ; i < kBlocksWide ; i++) { paintCell(g,i,j); } // for i } // for j String plainText = cryptoGram.getPlainText(); paintString(g, plainText, kLeftPlain, kTopPlain, kLineLength); // Plaintext message } // paint /** * paintCell() paints an individual cell on the painted keyboard. * @param x, y are the horizontal and vertical coordinates of the cell * in a 2 x 13 grid. */ private void paintCell(Graphics g, int x, int y) { // x is col, y is row g.setFont(regularFont); int tempLeft = kLeftKey + (x * kBlockWidth); // Compute coordinates int tempTop = kTopKey + (y * kBlockHeight); if (cryptoGram.inActiveBlock(x,y)) // Set Cell's color g.setColor(buttonFocusColor); else g.setColor(buttonbGround); g.fillRect(tempLeft+1, tempTop+1, kBlockWidth-1, kBlockHeight-1); // Paint cell g.setColor(appletbGround); g.draw3DRect(tempLeft,tempTop,kBlockWidth, kBlockHeight,true); Character chobj = new Character(getCellLabel(x,y)); // Draw cell's label g.setColor(labelColor); g.drawString(chobj.toString(), tempLeft + 2, tempTop + 11); g.setColor(textColor); // Draw cell's letter chobj = new Character(cryptoGram.getCellContents(x,y)); g.drawString(chobj.toString(), tempLeft + 12, tempTop + 20); } // paintCell() /** getCellLabel() computes the cell's label based on its position in * the 2 x 13 grid of cells. * @param x and y are the horizontal and vertical coordinates of the cell */ private char getCellLabel(int x, int y) { int m = x + 13 * y; // Use x, y to compute the cell number return((char) ((int)'A' + m) ); // and return the corresponding letter } // getCellLabel() public void mousePressed (MouseEvent e) { } // Unimplemented method of MouseListener Interface public void mouseReleased (MouseEvent e) { } public void mouseEntered (MouseEvent e) { } public void mouseExited (MouseEvent e) { } /** * mouseCicked() is from MouseListener interface. It moves the * focus to one of the keys on the painted keyboard. */ public void mouseClicked (MouseEvent e) { System.out.println("Mouse clicked"); Point mouse = e.getPoint(); requestFocus(); if (mouse.x < kLeftKey) // if the click was not in the key area return; if (mouse.y < kTopKey) return; int j = mouse.y - kTopKey; // get row and column indexes of the block j /= kBlockHeight; int i = mouse.x - kLeftKey; i /= kBlockWidth; if (i >= 0 && i < kBlocksWide && j >= 0 && j < kBlocksHigh) { if (!cryptoGram.inActiveBlock(i,j)) { int old_i = cryptoGram.gCurX, old_j = cryptoGram.gCurY; cryptoGram.setActiveBlock(i, j); paintCell(getGraphics(), i,j); paintCell(getGraphics(), old_i,old_j); } return; } } // mouseClicked() /** * keyPressed() is from the KeyListener Interface and is used * to handle control keys such as arrows and shift. */ public void keyPressed(KeyEvent e) { if (e.isShiftDown()) displayHint(e.getKeyChar()); // Shift means hint else moveFocus(e); // Otherwise arrow keys } public void keyReleased(KeyEvent e) { } /** * keyTypted() is from the KeyListener Interface and is used * to handle an alphabetic key, whose value is painted on * the current key cell in the painted keyboard. */ public void keyTyped(KeyEvent e) { char key = e.getKeyChar(); if (e.isShiftDown() && key != CryptoGram.NULL_CHAR) displayHint(key); else displayLetter(key); } // keyDown /** displayHint() sets the hintString to the secret value of * of its char parameter. The hintString is painted in the applet's * upper left corner. * @param -- a char giving a letter between 'A' and 'Z' */ public void displayHint(char key) { Graphics g = getGraphics(); g.setColor(appletbGround); g.drawString(hintString, 10, 15); hintString = new String("hint " + key + " = " + cryptoGram.getHint(key)); g.setColor(titleColor); g.drawString(hintString, 10, 15); } /** displayLetter() displays its parameter as the label of the current * key on the applet's painted keyboard. * @param -- a char giving a letter between 'A' and 'Z' or 'a' and 'z' */ private void displayLetter(char key) { if (key >= 'A' && key <= 'Z') key = (char) (key + 32); // convert to lower case if (cryptoGram.keyIsValid(key)) { // System.out.println("valid key = " + key); cryptoGram.setKeyChar(key); paintCell(getGraphics(), cryptoGram.gCurX, cryptoGram.gCurY); paintString(getGraphics(), cryptoGram.getPlainText(), kLeftPlain, kTopPlain, kLineLength); return; } //if valid } // displayLetter() /** * moveFocus() moves the keyboard focus up, down, left or right based on which * arrow key was pressed. The event's keyCode is used to determine which arrow * key was pressed. * @param the KeyEvent from which the keyCode is extracted */ private void moveFocus (KeyEvent e) { // x is column, y is row int keyCode = e.getKeyCode(); int oldx = cryptoGram.gCurX, oldy = cryptoGram.gCurY; int x = oldx, y = oldy; int m = x + 13 * y; // cells are numbered 0..25 // System.out.println("col " + x + " row " + y + " cell " + m ); switch (keyCode) { case e.VK_UP: { if (m >= 13 && m <= 25) { y--; } break; } case e.VK_DOWN: { if (m >= 0 && m <= 12) { y++; } break; } case e.VK_LEFT: { if ( (m > 0 && m <= 12) || (m > 13 && m <= 25) ) { x--; } if (m == 0) { x = 12; y = 1;} if (m == 13) { x = 12; y = 0; } break; } case e.VK_RIGHT: { if ( (m >= 0 && m < 12) || (m >= 13 && m < 25) ) { x++; } if (m == 12) { x = 0; y = 1; } if (m == 25) { x = 0; y = 0; } break; } } // switch cryptoGram.setActiveBlock(x,y); paintCell(getGraphics(), x,y); paintCell(getGraphics(), oldx,oldy); } // moveFocus() } // CryptoGramApplet