import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.text.*; import java.util.*; /* * TreeFrame - DO NOT CHANGE THIS FILE * * This file is used in Part 1 of HW 3. In this part, you only need to * define the necessary methods inside the DJIABinarySearchTree class. * * Author: Richard McKenna * CSE 214 * Stony Brook University */ public class DJIATreeFrame extends JFrame implements ActionListener { // HERE'S THE tree WE'RE GOING TO PLAY AROUND WITH private DJIABinarySearchTree tree = new DJIABinarySearchTree(); // NORTH TOOLBAR private JPanel northPanel = new JPanel(); private JButton addButton = new JButton("Add Company"); private JButton rebalanceButton = new JButton("Rebalance Tree"); private JButton emptytreeButton = new JButton("Empty the Tree"); // THIS WILL RENDER OUR tree private DJIAPanel djiaPanel = new DJIAPanel(); // THIS IS FOR READING DJIA DATA FROM A FILE private BufferedReader reader; /* * Default Constructor, it sets up the GUI. */ public DJIATreeFrame() { super("DJIATreeFrame"); JOptionPane.showMessageDialog(this, "NOTE: If your computer has problems rendering the tree, try increasing your screen resolution"); setDefaultCloseOperation(EXIT_ON_CLOSE); setExtendedState(MAXIMIZED_BOTH); layoutGUI(); initFileReader(); } /* * This method initializes a text file reader so that the * Dow Jones Industrial Average (DJIA) data can be read in * and used. */ public void initFileReader() { // SETUP THE READER SO IT CAN READ DATA WHEN NEEDED String fileName = "DJIA.txt"; try { FileInputStream fis = new FileInputStream(fileName); InputStreamReader isr = new InputStreamReader(fis); reader = new BufferedReader(isr); } catch (IOException ioe) { // TheHittree FILE WAS NOT FOUND, IT MIGHT BE IN THE WRONG DIRECTORY JOptionPane.showMessageDialog(this, fileName + " not found"); System.exit(0); } } /* * Layout the buttons and other GUI components. */ public void layoutGUI() { northPanel.add(addButton); northPanel.add(rebalanceButton); northPanel.add(emptytreeButton); add(northPanel, BorderLayout.NORTH); add(djiaPanel, BorderLayout.CENTER); addButton.addActionListener(this); rebalanceButton.addActionListener(this); emptytreeButton.addActionListener(this); } /* * We respond to button clicks here. */ public void actionPerformed(ActionEvent ae) { // WHICH BUTTON WAS CLICKED? Object source = ae.getSource(); // READ IN INFO ABOUT THE NEXT DJIA COMPANY FROM THE // FILE AND ADD IT TO THE tree if (source == addButton) { try { String line = reader.readLine(); if (line == null) { JOptionPane.showMessageDialog(this, "No more data to read"); } else { StringTokenizer st = new StringTokenizer(line, ","); String name = st.nextToken(); String symbol = st.nextToken(); double price = Double.parseDouble(st.nextToken()); DJIACompany company = new DJIACompany(name, symbol, price); tree.addCompany(company); djiaPanel.repaint(); } } catch(IOException ioe) { JOptionPane.showMessageDialog(this, "No more Web Sites to read"); } } // CALCULATE AND DISPLAY THE DJIA, ALL 30 COMPANIES MUST // BE ADDED TO DO THIS else if (source == rebalanceButton) { tree.rebalance(); djiaPanel.repaint(); } // EMPTY THE tree else if (source == emptytreeButton) { tree.clear(); initFileReader(); djiaPanel.repaint(); } } // THIS CLASS PROVIDES ALL OF OUR tree RENDERING class DJIAPanel extends JPanel { static final int TEXT_Y_OFFSET = 20; static final int TEXT_X_OFFSET = 10; static final int RECT_WIDTH = 50; static final int RECT_HEIGHT = 30; static final int RECT_X_OFFSET = 30; static final int RECT_Y_OFFSET = 50; static final int NODES_PER_ROW = 6; static final int MAX_NODES = 30; static final int ARROW_TAIL_LENGTH = 10; int NODES_PER_COLUMN; Font nodeFont = new Font("console",Font.BOLD, 11); public DJIAPanel() { NODES_PER_COLUMN = MAX_NODES/NODES_PER_ROW; } public int logBase2(int num) { int counter = 0; while (num > 1) { counter++; num /= 2; } return counter; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setFont(nodeFont); // HOW MANY LEVELS ARE THERE? int treeLevels = tree.calculateTreeLevels(); g.drawString("Tree Levels: " + treeLevels, 0, 20); g.drawString("Tree Nodes: " + tree.size(), 0, 40); // WHAT ARE THE PANEL DIMENSIONS int panelWidth = getWidth(); int panelHeight = getHeight(); // CALCULATE THE SIZE OF EVERYTHING WE NEED TO DRAW int arrowX1, arrowY1, arrowX2, arrowY2; // CALCULATE THE PANEL LOCATION OF THE FIRST NODE int rectX = (panelWidth/2) - (RECT_WIDTH/2); int rectY = RECT_HEIGHT; int x1, y1, x2, y2, row; boolean drawingComplete = false; int counter = 0; Iterator it = tree.treeIterator(); while (!drawingComplete) { if (!it.hasNext()) { drawingComplete = true; } else { DJIACompany company = (DJIACompany)it.next(); int treeIndex = tree.calculateTreeIndex(company); int treeLevel = logBase2(treeIndex+1); int nodesOnLevel = (int)(Math.pow(2, treeLevel)); int levelIndex = (treeIndex + 1) % nodesOnLevel; int spacing = (int)(panelWidth/Math.pow(2, treeLevel+1)); rectX = (spacing + (spacing * 2 * levelIndex)) - (RECT_WIDTH/2); rectY = RECT_HEIGHT + (treeLevel*2*RECT_HEIGHT); g.drawRect(rectX, rectY, RECT_WIDTH, RECT_HEIGHT); g.drawString(company.getSymbol(), rectX+TEXT_X_OFFSET, rectY+TEXT_Y_OFFSET); // TOP OF THIS NODE x2 = rectX + (RECT_WIDTH/2); y2 = rectY; if (treeIndex == 0) x1 = rectX + (RECT_WIDTH/2); // LEFT NODE else if ((treeIndex % 2) == 1) { x1 = x2 + spacing; } // RIGHT NODE else { x1 = x2 - spacing; } y1 = rectY - (2*RECT_HEIGHT) + RECT_HEIGHT; g.drawLine(x1, y1, x2, y2); } } } } public static void main(String[] args) { DJIATreeFrame frame = new DJIATreeFrame(); frame.setVisible(true); } }