import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import javax.swing.*;

/** An illustration of class Vector<Character>. This frame contains a visual
 representation of a Vector along with the elements it contains.
 
 If you are using the Java 1.4 compiler, this file will not
 compile. To compile it, Remove the three instances of
 "<Character>" --on lines 20, 25, and 33. Then continue with
 the assignment. When you compile, you will get some warning
 messages. Then, continue with the assignment knowing that
 Vector v is compiled as if its declaration was
 
     public Vector<Object> v= null;
     
 That is, all elements of Vector v are assumed to be of
 class Object. When an element is retrieved, it may have
 to be cast to its real type.
 */

public class Lab05 extends JFrame {
    /** The list of objects that will be displayed. */
    public Vector<Character> v= null;
    
    /** Constructor: a JFrame with a Vector that has default properties. */
    public Lab05() {
        super("CS100J Lab 05: An illustration of class Vector");
        v= new Vector<Character>();
        createGUI();
        
    }
    
    /** Constructor: a JFrame with a Vector with initial capacity c
     and capacity increment ci.  */
    public Lab05(int c, int ci) {
        super("CS100J Lab 05: An illustration of class Vector");
        v= new Vector<Character>(c, ci);
        createGUI();
    }
    
    /** Swap the objects at v[first] and v[second]
     * Precondition: first and second are in range 0..v.size()-1. */
    public void swap(int first, int second) {
        
        //-------- IMPLEMENT ME! --------//
    }
    
    /** = "there is more than one occurrence of obj in v" */
    public boolean moreThanOne(Object obj) {
        
        //-------- IMPLEMENT ME! --------//
       
        
        
        return false; // This is only here so that the stub method compiles
        
    }
    
    /** = "v has unused space" */
    public boolean hasExtraSpace() {
        
        //-------- IMPLEMENT ME! --------//
        
        
        
        return false; // This is only here so that the stub method compiles
        
    }
    
    /** = a String that contains the characters of Vector v */
    public String toString() {
        //-------- IMPLEMENT ME! --------//
        
        
        
        
        return "";  // This is here only so that the method compiles
    }
    
    /** Set the total capacity of v to 10 and fill it completely
     with Character objects. */
    public void initializeV() {
        v.clear();
        v.trimToSize();
        v.ensureCapacity(10);
        v.add(new Character('X'));
        v.add(new Character('Y'));
        v.add(new Character('Z'));
        v.add(new Character('1'));
        v.add(new Character('2'));
        v.add(new Character('3'));
        v.add(new Character('$'));
        v.add(new Character('#'));
        v.add(new Character('3'));
        v.add(new Character('2'));
    }
    
    /*********************************************************************
     * You do NOT need to read the code below here  *
     * This code displays the graphical vector inside a JFrame.          *  
     * *******************************************************************/
    
    private JPanel panel;
    private JScrollBar scrollbar;
    private Font indexFont= new Font("Arial", Font.BOLD, 16);
    private int indexFontSize= indexFont.getSize();
    private Font charFont= new Font("TimesRoman", Font.BOLD, 25);
    private int cellSize= charFont.getSize();
    private int xOffset= 20;
    private int yOffset= 20;
    private int cellPadding= 15;
    private Thread repaintThread;
    private Image offscreenImage;
    private Graphics offscreenGraphics;
    private Dimension screen= Toolkit.getDefaultToolkit().getScreenSize();
    
    /** Create a GUI that graphically displays Vector v. */
    private void createGUI() {
        // Create thread to continually repaint
        repaintThread= new Thread() {
            
            public void run() {
                while (Lab05.this.isVisible()) {
                    Lab05.this.pack();
                    if (panel.getGraphics() != null)
                        panel.update(panel.getGraphics());
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ie) {}
                }
            }
        };
        
        repaintThread.setDaemon(true);
        
        // Create panel to draw vector
        panel= new JPanel() {
            public void paint(Graphics g) {
                if (offscreenGraphics != null) {
                    g.drawImage(offscreenImage, -1*scrollbar.getValue(), 0, null);
                }
            }
            
            // Prepare the image and paint it
            public void update(Graphics g) {
                // prepare offscreen image
                try {
                    if (offscreenImage != null) {
                        offscreenImage.flush();
                        offscreenGraphics.finalize();
                        offscreenImage= null;
                        offscreenGraphics= null;
                    }
                    offscreenImage= 
                        createImage(Math.max(cellSize * v.capacity() + 2*xOffset, panel.getWidth()),
                                    cellSize + 2*yOffset + indexFont.getSize());
                    offscreenGraphics= offscreenImage.getGraphics();
                } catch (Exception e) { return; /*the window had 0-dimensions*/ }
                
                // clear image
                offscreenGraphics.setColor(Color.white);
                
                offscreenGraphics.fillRect(0, 0,
                                           offscreenImage.getWidth(null),
                                           offscreenImage.getHeight(null));
                
                // adjust scrollbar settings
                scrollbar.setMaximum(Math.max(offscreenImage.getWidth(null) - panel.getWidth(), 0));
                scrollbar.setUnitIncrement(cellSize);
                
                // Draw the Character objects in v.  If a cell contains
                // an object besides Character, draw a red question mark.
                FontRenderContext frc= ((Graphics2D)offscreenGraphics).getFontRenderContext();
                offscreenGraphics.setFont(charFont);
                offscreenGraphics.setColor(Color.blue);
                
                for (int i= 0; i < v.size(); i= i+1) {
                    Object item= v.get(i);
                    GlyphVector glyph= null; //will contain char to be printed
                    if (item instanceof Character) {
                        // get the glyph associated with this character
                        glyph= charFont.createGlyphVector
                            (frc, new char[] {((Character) item).charValue()});
                    }
                    else {// get the glyph associated with '?'
                        glyph= charFont.createGlyphVector(frc, new char[] {'?'});
                        offscreenGraphics.setColor(Color.red);
                        item= "?";
                    }
                    
                    // get the bounds of the glyph
                    Rectangle bounds= glyph.getOutline().getBounds();
                    
                    int charWidth= (int) bounds.getWidth();
                    int charHeight= (int) bounds.getHeight();
                    int maxBound= Math.max(charWidth, charHeight);
                    if (maxBound + cellPadding > cellSize)
                        cellSize= maxBound + cellPadding;
                    
                    offscreenGraphics.drawString(item.toString(),
                            xOffset + cellSize * i + (cellSize - charWidth)/2,
                            yOffset + charHeight + (cellSize - charHeight)/2 + indexFontSize);
                    offscreenGraphics.setColor(Color.blue);
                }
                
                // Draw the vector
                offscreenGraphics.setColor(Color.black);
                int capacity= v.capacity();
                offscreenGraphics.drawRect(xOffset, yOffset + indexFontSize, capacity * cellSize, cellSize);
                for (int i= 0; i < capacity; i= i+1)
                    offscreenGraphics.drawLine(xOffset + cellSize * i, yOffset + indexFontSize,                       
                                               xOffset + cellSize * i, yOffset + cellSize + indexFontSize);
                
                // Draw the indices above their corresponding cells
                offscreenGraphics.setFont(indexFont);
                offscreenGraphics.setXORMode(getContentPane().getBackground());  
                for (int i= 0; i < v.capacity(); i= i+1)
                    offscreenGraphics.drawString(String.valueOf(i), xOffset + cellSize * i + cellSize / 2,
                                                 yOffset  + indexFont.getSize());
                paint(g);   
            }
            
            public Dimension getPreferredSize() {
                return new Dimension(screen.width-10, 
                                     cellSize + yOffset * 2 + indexFont.getSize() + cellPadding);
            }
        };
        
        // Create scrollbar to pan along vector
        scrollbar= new JScrollBar(JScrollBar.HORIZONTAL);
        
        // Add panel and scrollbar to the frame
        Container c= getContentPane();
        c.setBackground(Color.white);
        c.setLayout(new BorderLayout());
        c.add(panel, BorderLayout.CENTER);
        c.add(scrollbar, BorderLayout.SOUTH);    
        setResizable(false);
        pack();
        setVisible(true);
        
        // start the thread
        repaintThread.start();
    }
    
}