Package HackGUI

Source Code of HackGUI.MemoryComponent$MemoryTableModel

/********************************************************************************
* The contents of this file are subject to the GNU General Public License      *
* (GPL) Version 2 or later (the "License"); you may not use this file except   *
* in compliance with the License. You may obtain a copy of the License at      *
* http://www.gnu.org/copyleft/gpl.html                                         *
*                                                                              *
* Software distributed under the License is distributed on an "AS IS" basis,   *
* without warranty of any kind, either expressed or implied. See the License   *
* for the specific language governing rights and limitations under the         *
* License.                                                                     *
*                                                                              *
* This file was originally developed as part of the software suite that        *
* supports the book "The Elements of Computing Systems" by Nisan and Schocken, *
* MIT Press 2005. If you modify the contents of this file, please document and *
* mark your changes clearly, for the benefit of others.                        *
********************************************************************************/

package HackGUI;

import Hack.ComputerParts.ComputerPartEvent;
import Hack.ComputerParts.ComputerPartEventListener;
import Hack.ComputerParts.MemoryGUI;
import Hack.Events.ClearEvent;
import Hack.Events.ClearEventListener;
import Hack.Events.ErrorEvent;
import Hack.Events.ErrorEventListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

/**
* This class represents the GUI of a memory.
*/
public class MemoryComponent extends JPanel implements MemoryGUI {
   
    private static final String FIND_GIF_RESOURCE = "resources/find.gif";
    private static final String SMALLNEW_GIF_RESOURCE = "resources/smallnew.gif";

    // The default number of visible rows.
    protected static final int DEFAULT_VISIBLE_ROWS = 10;

    /**
     * The current format.
     */
    public int dataFormat;

    // A vector containing the listeners to this object.
    private Vector listeners;

    // A vector containing the clear listeners to this object.
    private Vector clearListeners;

    // A vector containing the error listeners to this object.
    private Vector errorEventListeners;

    // A vector containing the repaint listeners to this object.
    private Vector changeListeners;

    // The table representing the memory.
    protected JTable memoryTable;

    // The model of the table.
    private MemoryTableModel tableModel = new MemoryTableModel();

    // The values of this memory in a string representation.
    protected String[] valuesStr;

    // The values of this memory in a short representation.
    protected short[] values;

    // The addresses of this memory.
    protected String[] addresses;

    // Creating buttons and icons.
    protected MouseOverJButton  searchButton = new MouseOverJButton();
    protected MouseOverJButton clearButton = new MouseOverJButton();
    private ImageIcon searchIcon = new ImageIcon(MemoryComponent.class.getResource(FIND_GIF_RESOURCE));
    private ImageIcon clearIcon = new ImageIcon(MemoryComponent.class.getResource(SMALLNEW_GIF_RESOURCE));

    // The window of searching a specific location in memory.
    private SearchMemoryWindow searchWindow;

    // The scrollpane on which the table is placed.
    protected JScrollPane scrollPane;

    // A vector containing the highlighted rows.
    protected Vector highlightIndex;

    // The index of the flashed row.
    protected int flashIndex = -1;

    // The location of this component relative to its top level ancestor.
    protected Point topLevelLocation;

    // The name of this component.
    protected JLabel nameLbl = new JLabel();

    // A boolean field specifying if the user can enter values into the table.
    protected boolean isEnabled = true;

    // The null value of this component
    protected short nullValue;

    // A boolean field specifying if the null value should be activated or not.
    protected boolean hideNullValue;

    // The start and end row indices of the enabled region.
    protected int startEnabling, endEnabling;

    // If true, the disbaled region is shaded.
    protected boolean grayDisabledRange;

    /**
     * Constructs a new MemoryComponent.
     */
    public MemoryComponent() {
        dataFormat = Format.DEC_FORMAT;
        startEnabling = -1;
        endEnabling = -1;

        JTextField tf = new JTextField();
        tf.setFont(Utilities.bigBoldValueFont);
        tf.setBorder(null);
        DefaultCellEditor editor = new DefaultCellEditor(tf);

        listeners = new Vector();
        clearListeners = new Vector();
        errorEventListeners = new Vector();
        changeListeners = new Vector();
        highlightIndex = new Vector();
        memoryTable = new JTable(getTableModel());
        memoryTable.setDefaultRenderer(memoryTable.getColumnClass(0), getCellRenderer());
        memoryTable.getColumnModel().getColumn(getValueColumnIndex()).setCellEditor(editor);
        memoryTable.setTableHeader(null);

        values = new short[0];
        addresses = new String[0];
        valuesStr = new String[0];
        searchWindow = new SearchMemoryWindow(this, memoryTable);

        jbInit();
    }

    /**
     * Sets the null value of this component.
     */
    public void setNullValue (short value, boolean hideNullValue) {
        nullValue = value;
        this.hideNullValue = hideNullValue;
    }

    /**
     * Enables user input into the source.
     */
    public void enableUserInput() {
        isEnabled = true;
    }

    /**
     * Disables user input into the source.
     */
    public void disableUserInput() {
        isEnabled = false;
    }

    /**
     * Returns the index of the values column.
     */
    protected int getValueColumnIndex() {
        return 1;
    }

    /**
     * Returns the table model of this component.
     */
    protected TableModel getTableModel() {
        return new MemoryTableModel();
    }

    /**
     * Returns the cell renderer of this component.
     */
    protected DefaultTableCellRenderer getCellRenderer() {
        return new MemoryTableCellRenderer();
    }

    /**
     * Sets the name of this component.
     */
     public void setName(String name) {
        nameLbl.setText(name);
     }

    /**
     * Sets the location of this component relative to its top level ancestor.
     */
    public void setTopLevelLocation(Component top) {
        topLevelLocation = Utilities.getTopLevelLocation(top, memoryTable);
    }

    public void addListener(ComputerPartEventListener listener) {
        listeners.addElement(listener);
    }

    public void removeListener(ComputerPartEventListener listener) {
        listeners.removeElement(listener);
    }

    public void notifyListeners(int address, short value) {
        ComputerPartEvent event = new ComputerPartEvent(this,address,value);
        for (int i=0;i<listeners.size();i++) {
           ((ComputerPartEventListener)listeners.elementAt(i)).valueChanged(event);
        }
    }

    public void notifyListeners() {
        ComputerPartEvent event = new ComputerPartEvent(this);
        for (int i=0;i<listeners.size();i++) {
           ((ComputerPartEventListener)listeners.elementAt(i)).guiGainedFocus();
        }
    }

    public void addClearListener (ClearEventListener listener) {
        clearListeners.addElement(listener);
    }
    public void removeClearListener (ClearEventListener listener) {
        clearListeners.removeElement(listener);
    }

    public void notifyClearListeners() {
        ClearEvent clearEvent = new ClearEvent(this);
        for(int i=0; i<clearListeners.size();i++)
            ((ClearEventListener)clearListeners.elementAt(i)).clearRequested(clearEvent);
    }

    /**
     * Registers the given ErrorEventListener as a listener to this GUI.
     */
    public void addErrorListener(ErrorEventListener listener) {
        errorEventListeners.addElement(listener);
    }

    /**
     * Un-registers the given ErrorEventListener from being a listener to this GUI.
     */
    public void removeErrorListener(ErrorEventListener listener) {
        errorEventListeners.removeElement(listener);
    }

   /**
     * Notifies all the ErrorEventListener on an error in this gui by
     * creating an ErrorEvent (with the error message) and sending it
     * using the errorOccured method to all the listeners.
     */
    public void notifyErrorListeners(String errorMessage) {
        ErrorEvent event = new ErrorEvent(this, errorMessage);
        for (int i=0; i<errorEventListeners.size(); i++)
            ((ErrorEventListener)errorEventListeners.elementAt(i)).errorOccured(event);
    }

    /**
     * Registers the given MemoryChangeListener as a listener to this GUI.
     */
    public void addChangeListener(MemoryChangeListener listener) {
        changeListeners.addElement(listener);
    }

    /**
     * Un-registers the given MemoryChangeListener from being a listener to this GUI.
     */
    public void removeChangeListener(MemoryChangeListener listener) {
        changeListeners.removeElement(listener);
    }

    /**
     * Notifies all the changeListeners on a need to repaint themselves.
     */
    public void notifyRepaintListeners() {
        for (int i=0;i<changeListeners.size();i++) {
           ((MemoryChangeListener)changeListeners.elementAt(i)).repaintChange();
        }
    }

    /**
     * Notifies all the changeListeners on a need to revalidate themselves.
     */
    public void notifyRevalidateListeners() {
        for (int i=0;i<changeListeners.size();i++) {
           ((MemoryChangeListener)changeListeners.elementAt(i)).revalidateChange();
        }
    }

    /**
     * Sets the memory contents with the given values array. (assumes that the
     * length of the given array equals to the gui's size)
     */
    public void setContents(short[] newValues) {
        values = new short[newValues.length];
        addresses = new String[newValues.length];
        valuesStr = new String[newValues.length];

        System.arraycopy(newValues, 0, values, 0, newValues.length);
        for(int i=0;i<values.length;i++) {
            addresses[i] = Format.translateValueToString((short)i, Format.DEC_FORMAT);
            valuesStr[i] = translateValueToString(values[i]);
        }
        memoryTable.revalidate();
        repaint();
        notifyRevalidateListeners();
    }

    /**
     * Updates the values of the table memory.
     */
    protected void updateTable(short value, int row) {
        values[row] = value;
        valuesStr[row] = translateValueToString(value);
    }

    /**
     * Sets the contents of the memory in the given index with the given value.
     * (Assumes legal index - between 0 and getSize()-1).
     */
    public void setValueAt(int index, short value) {
        updateTable(value,index);
        repaint();
        notifyRepaintListeners();
    }

    /**
     * Resets the contents of this MemoryComponent.
     */
    public void reset() {
        for(int i= 0; i<values.length;i++){
            updateTable(nullValue, i);
        }
        repaint();
        notifyRepaintListeners();
        memoryTable.clearSelection();

        hideFlash();
        hideHighlight();
    }

    /**
     * Hides all highlightes.
     */
    public void hideHighlight() {
        highlightIndex.removeAllElements();
        repaint();
    }

    /**
     * Highlights the value at the given index.
     */
    public void highlight(int index) {
        highlightIndex.addElement(new Integer(index));
        repaint();
    }

    /**
     * hides the existing flash.
     */
    public void hideFlash () {
        flashIndex = -1;
        repaint();
    }

    /**
     * flashes the value at the given index.
     */
    public void flash (int index) {
        flashIndex = index;
        Utilities.tableCenterScroll(this, memoryTable, index);
    }

    /**
     * Sets the enabled range of this segment.
     * Any address outside this range will be disabled for user input.
     * If gray is true, addresses outside the range will be gray colored.
     */
    public void setEnabledRange(int start, int end, boolean gray) {
        startEnabling = start;
        endEnabling = end;
        grayDisabledRange = gray;
        repaint();
    }

    /**
     * Returns the size (number of elements) of the memory.
     */
    public int getMemorySize() {
        return values != null ? values.length : 0;
    }

    /**
     * Returns the value at the given index in its string representation.
     */
    public String getValueAsString(int index) {
        return Format.translateValueToString(values[index], dataFormat);
    }

    /**
     * Selects the commands in the range fromIndex..toIndex
     */
    public void select(int fromIndex,int toIndex) {
        memoryTable.setRowSelectionInterval(fromIndex,toIndex);
        Utilities.tableCenterScroll(this, memoryTable, fromIndex);
    }

    /**
     * Hides all selections.
     */
    public void hideSelect() {
        memoryTable.clearSelection();
        repaint();
    }

    /**
     * Returns the coordinates of the top left corner of the value at the given index.
     */
    public Point getCoordinates (int index) {
        JScrollBar bar = scrollPane.getVerticalScrollBar();
        Rectangle r = memoryTable.getCellRect(index, getValueColumnIndex(), true);
        memoryTable.scrollRectToVisible(r);
        return new Point((int)(r.getX() + topLevelLocation.getX()),
                         (int)(r.getY() + topLevelLocation.getY() - bar.getValue()));
    }

    /**
     * Returns the address string at a specific address.
     */
    public String getAddressStr (short address) {
        return addresses[address];
    }

    /**
     * Returns the value (in a string representation) at a specific address.
     */
    public String getValueStr (short address) {
        return valuesStr[address];
    }

    /**
     * Returns the value (in a short representation) at a specific address.
     */
    public short getValueAsShort (short address) {
        return values[address];
    }

    /**
     * Translates a given string to a short according to the current format.
     * Throws a TranslationException if can't be translated.
     */
    protected short translateValueToShort(String data) throws TranslationException {
        short result = 0;
        try {
            result = Format.translateValueToShort(data,dataFormat);
        } catch (NumberFormatException nfe) {
            throw new TranslationException("Illegal value: " + data);
        }

        return result;
    }

    /**
     * Translates a given short to a string according to the current format.
     */
    protected String translateValueToString(short value) {
        if(hideNullValue) {
            if(value == nullValue)
                return "";
            else
                return Format.translateValueToString(value, dataFormat);
        }
        else
            return Format.translateValueToString(value, dataFormat);
    }

    /**
     * Sets the font of the table.
     */
    public void setTableFont (Font font) {
        memoryTable.setFont(font);
    }

    // Initializes this memory.
    private void jbInit(){

        memoryTable.addFocusListener(new FocusListener() {
            public void focusGained(FocusEvent e) {
                memoryTable_focusGained(e);
            }

            public void focusLost(FocusEvent e) {
                memoryTable_focusLost(e);
            }
        });

        scrollPane = new JScrollPane(memoryTable);
        this.setLayout(null);
        searchButton.setToolTipText("Search");
        searchButton.setIcon(searchIcon);
        searchButton.setBounds(new Rectangle(159, 2, 31, 25));
        searchButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                searchButton_actionPerformed(e);
            }
        });
        memoryTable.setFont(Utilities.valueFont);
        nameLbl.setBounds(new Rectangle(3, 5, 70, 23));
        nameLbl.setFont(Utilities.labelsFont);
        determineColumnWidth();
        setBorder(BorderFactory.createEtchedBorder());
        scrollPane.setLocation(0,27);

        clearButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                clearButton_actionPerformed(e);
            }
        });
        clearButton.setIcon(clearIcon);
        clearButton.setBounds(new Rectangle(128, 2, 31, 25));
        clearButton.setToolTipText("Clear");
        this.add(scrollPane, null);
        this.add(searchButton, null);
        this.add(nameLbl, null);
        this.add(clearButton, null);
    }

    /**
     * Returns the width of the table.
     */
    public int getTableWidth() {
        return 193;
    }

    /**
     * Sets the number of visible rows.
     */
    public void setVisibleRows(int num) {
        int tableHeight = num * memoryTable.getRowHeight();
        scrollPane.setSize(getTableWidth(), tableHeight + 3);
        setPreferredSize(new Dimension(getTableWidth(), tableHeight + 30));
        setSize(getTableWidth(), tableHeight + 30);
    }

    // Determines the width of each column in the table.
    protected void determineColumnWidth() {
        TableColumn column = null;
        for (int i = 0; i < 2; i++) {
            column = memoryTable.getColumnModel().getColumn(i);
            if (i == 0) {
                column.setPreferredWidth(30);
            } else {
                column.setPreferredWidth(100);
            }
        }
    }

    public void scrollTo(int index) {
        Utilities.tableCenterScroll(this, memoryTable, index);
    }

    /**
     * Implementing the action of the table gaining the focus.
     */
    public void memoryTable_focusGained(FocusEvent e) {
        memoryTable.clearSelection();
        notifyListeners();
    }

    /**
     * Implementing the action of the table loosing the focus.
     */
    public void memoryTable_focusLost(FocusEvent e) {
        memoryTable.clearSelection();
    }

    /**
     * Implementing the action of pressing the search button.
     */
    public void searchButton_actionPerformed(ActionEvent e) {
        searchWindow.showWindow();
    }

    /**
     * Implementing the action of pressing the clear button.
     */
    public void clearButton_actionPerformed(ActionEvent e) {

        Object[] options = {"Yes", "No","Cancel"};
        int pressedButtonValue = JOptionPane.showOptionDialog(this.getParent(),
            "Are you sure you want to clear ?",
            "Warning Message",
            JOptionPane.YES_NO_CANCEL_OPTION,
            JOptionPane.WARNING_MESSAGE,
            null,
            options,
            options[2]);

        if(pressedButtonValue==JOptionPane.YES_OPTION)
            notifyClearListeners();
    }

    // An inner class representing the model of this table.
    class MemoryTableModel extends AbstractTableModel {

        /**
         * Returns the number of columns.
         */
        public int getColumnCount() {
            return 2;
        }

        /**
         * Returns the number of rows.
         */
        public int getRowCount() {
            return getMemorySize();
        }

        /**
         * Returns the names of the columns.
         */
        public String getColumnName(int col) {
            return null;
        }

        /**
         * Returns the value at a specific row and column.
         */
        public Object getValueAt(int row, int col) {
            if(col==0)
                return addresses[row];
            else
                return valuesStr[row];
        }

        /**
         * Returns true of this table cells are editable, false -
         * otherwise.
         */
        public boolean isCellEditable(int row, int col) {
            boolean result = false;
            if(isEnabled && col == 1 &&
                (endEnabling == -1 || (row>= startEnabling && row <= endEnabling)))
                result = true;

            return result;
        }

        /**
         * Sets the value at a specific row and column.
         */
        public void setValueAt(Object value, int row, int col) {
            String data = ((String)value).trim();
            if (!valuesStr[row].equals(data)) {
                try {
                    valuesStr[row] = data;
                    if(data.equals("") && hideNullValue)
                        values[row] = nullValue;
                    else
                        values[row] = translateValueToShort(data);
                    notifyListeners((short)row,values[row]);
                } catch(TranslationException te) {
                    notifyErrorListeners(te.getMessage());
                    valuesStr[row] = translateValueToString(values[row]);
                }
                repaint();
                notifyRepaintListeners();
            }
        }
    }

    /**
     * Sets the numeric format with the given code (out of the format constants
     * in HackController).
     */
    public void setNumericFormat(int formatCode) {
        dataFormat = formatCode;
        for(int i=0;i<values.length; i++)
            valuesStr[i] = translateValueToString(values[i]);
        repaint();
        notifyRepaintListeners();

    }

    /**
     * Sets the size of the name label according to the size constants.
     */
    public void setNameLabelSize() {
        nameLbl.setBounds(new Rectangle(3, 7, 150, 23));
    }

    // An inner class which implemets the cell renderer of the memory table, giving
    // the feature of aligning the text in the cells.
    class MemoryTableCellRenderer extends DefaultTableCellRenderer {

        public Component getTableCellRendererComponent
            (JTable table, Object value, boolean selected, boolean focused, int row, int column)
        {
            setForeground(null);
            setBackground(null);

            setRenderer(row, column);
            super.getTableCellRendererComponent(table, value, selected, focused, row, column);

            return this;
        }

        public void setRenderer(int row, int column) {

            if(column == 0)
                setHorizontalAlignment(SwingConstants.CENTER);
            else if (column == 1) {
                setHorizontalAlignment(SwingConstants.RIGHT);

                for (int i=0;i<highlightIndex.size(); i++) {
                    if(row == ((Integer)highlightIndex.elementAt(i)).intValue()) {
                        setForeground(Color.blue);
                        break;
                    }
                }

                if (row == flashIndex)
                    setBackground(Color.orange);
            }
            if (row < startEnabling || row > endEnabling && grayDisabledRange)
                    setForeground(Color.lightGray);
        }
    }
}
TOP

Related Classes of HackGUI.MemoryComponent$MemoryTableModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.