# Introduction to Software Enginnering & Development using Java



## JGuru (Aug 17, 2016)

*Introduction to Software Enginnering & Development using Java*

 To write better software you need to engineer the software components,
 use the Core Java API well to write a better software. Here are some sample
 softwares like editor, imageviewer, download manager, calculator, zip archiver etc.,
 In order to write better software you need to study how a good software is written!!
 This tutorial shows how a good software is written!!
 So study these examples and write better software!!
 In order to write better software you need to master OOPS, Master Core Java API thorougly.
 Combine OOPS , API with proper logic to write better software!!!
 So study these examples thoroughly & learn how to program using Java language!!

*Combine OOPS + design patterns + API + Logic = Software (final product)*


1) Write a simple calculator?


```
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;

/**
 * Calculator
 *
 * @author JGuru
 */
public class Calculator extends JComponent {

    private static final String ZERO = "0";

    private static final char DECIMAL_SEPARATOR = ',';

    private final JTextField tfScreen = new JTextField();

    private enum State {

        INPUT_X,
        INPUT_X_FINISHED,
        INPUT_Y,
        INPUT_Y_FINISHED
    }

    private enum Operator {

        ADDITION,
        SUBTRACTION,
        MULTIPLICATION,
        DIVISION,
        SQRT,
        INVERSE,
        EQUALS
    }

    private final Map<Character, Operator> keyMapping = new HashMap<>();

    private String operand_x;

    private Operator operator;

    private State state;

    public Calculator() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException e) {
        }
        keyMapping.put('/', Operator.DIVISION);
        keyMapping.put('*', Operator.MULTIPLICATION);
        keyMapping.put('+', Operator.ADDITION);
        keyMapping.put('-', Operator.SUBTRACTION);
        keyMapping.put('\n', Operator.EQUALS);

        initUI();

        addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                char c = e.getKeyChar();

                if (Character.isDigit(c)) {
                    doProcessChar(c);
                } else if (c == '.' || c == ',') {
                    doProcessChar(DECIMAL_SEPARATOR);
                } else {
                    Operator operator = keyMapping.get(c);

                    if (operator != null) {
                        doProcessOperator(operator);
                    }
                }
            }

            @Override
            public void keyPressed(KeyEvent e) {
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_BACK_SPACE:
                        doProcessBackspace();

                        break;

                    case KeyEvent.VK_DELETE:
                        doReset();
                }
            }
        });

        doReset();
    }

    private void initUI() {
        tfScreen.setHorizontalAlignment(JTextField.RIGHT);

        JButton btnBackspace = new JButton("Backspace");

        btnBackspace.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                doProcessBackspace();
            }
        });

        JButton btnReset = new JButton("C");

        btnReset.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                doReset();
            }
        });

        JPanel pnGridPanel = new JPanel(new GridLayout(1, 2, 8, 8));

        pnGridPanel.add(btnBackspace);
        pnGridPanel.add(btnReset);

        setLayout(new GridBagLayout());

        JButton btnSwapSign = new SquareButton("+/-");

        btnSwapSign.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                doSwapSign();
            }
        });

        addComp(tfScreen, 0, 0, 5, 1);
        addComp(pnGridPanel, 0, 1, 5, 1);

        addComp(new CharButton('7'), 0, 2, 1, 1);
        addComp(new CharButton('8'), 1, 2, 1, 1);
        addComp(new CharButton('9'), 2, 2, 1, 1);
        addComp(new OperatorButton(Operator.DIVISION, "/"), 3, 2, 1, 1);
        addComp(new OperatorButton(Operator.INVERSE, "1/x"), 4, 2, 1, 1);

        addComp(new CharButton('4'), 0, 3, 1, 1);
        addComp(new CharButton('5'), 1, 3, 1, 1);
        addComp(new CharButton('6'), 2, 3, 1, 1);
        addComp(new OperatorButton(Operator.MULTIPLICATION, "*"), 3, 3, 1, 1);
        addComp(new OperatorButton(Operator.SQRT, "sqrt"), 4, 3, 1, 1);

        addComp(new CharButton('1'), 0, 4, 1, 1);
        addComp(new CharButton('2'), 1, 4, 1, 1);
        addComp(new CharButton('3'), 2, 4, 1, 1);
        addComp(new OperatorButton(Operator.SUBTRACTION, "-"), 3, 4, 1, 1);

        addComp(new CharButton('0'), 0, 5, 1, 1);
        addComp(btnSwapSign, 1, 5, 1, 1);
        addComp(new CharButton(DECIMAL_SEPARATOR), 2, 5, 1, 1);
        addComp(new OperatorButton(Operator.ADDITION, "+"), 3, 5, 1, 1);
        addComp(new OperatorButton(Operator.EQUALS, "="), 4, 5, 1, 1);

        // Set focusable false
        resetFocusable(this);

        setFocusable(true);
    }

    private static void resetFocusable(Component component) {
        component.setFocusable(false);

        if (component instanceof Container) {
            for (Component c : ((Container) component).getComponents()) {
                resetFocusable(c);
            }
        }
    }

    private void doReset() {
        operand_x = null;
        operator = null;
        state = State.INPUT_X;

        tfScreen.setText(ZERO);
    }

    private void doProcessChar(char c) {
        String text = tfScreen.getText();

        String newValue;

        if (state == State.INPUT_X || state == State.INPUT_Y) {
            newValue = attachChar(text, c);

            if (stringToValue(newValue) == null) {
                return;
            }
        } else {
            newValue = attachChar("0", c);

            if (stringToValue(newValue) == null) {
                return;
            }

            if (operator == null) {
                operand_x = null;

                state = State.INPUT_X;
            } else {
                operand_x = text;

                state = State.INPUT_Y;
            }
        }

        tfScreen.setText(newValue);
    }

    private static String attachChar(String s, char c) {
        if (Character.isDigit(c)) {
            if (s.equals(ZERO)) {
                return Character.toString(c);
            }

            if (s.equals("-" + ZERO)) {
                return "-" + Character.toString(c);
            }

            return s + Character.toString(c);
        } else {
            return s + Character.toString(c);
        }
    }

    private void doSwapSign() {
        String text = tfScreen.getText();

        tfScreen.setText(text.startsWith("-") ? text.substring(1) : "-" + text);
    }

    private void doProcessBackspace() {
        String text = tfScreen.getText();

        if (text.length() > 0) {
            text = text.substring(0, text.length() - 1);
        }

        if (text.length() == 0 || text.equals("-")) {
            text = ZERO;
        }

        if (stringToValue(text) != null) {
            tfScreen.setText(text);
        }
    }

    private void doProcessOperator(Operator operator) {
        double y = stringToValue(tfScreen.getText());

        // Process unary operators
        boolean isUnary;

        switch (operator) {
            case SQRT:
                tfScreen.setText(valueToString(Math.sqrt(y)));

                isUnary = true;

                break;

            case INVERSE:
                tfScreen.setText(valueToString(1 / y));

                isUnary = true;

                break;

            default:
                isUnary = false;
        }

        if (isUnary) {
            if (state == State.INPUT_X) {
                state = State.INPUT_X_FINISHED;
            }

            if (state == State.INPUT_Y) {
                state = State.INPUT_Y_FINISHED;
            }

            return;
        }

        // Process binary operators
        if (state == State.INPUT_Y || state == State.INPUT_Y_FINISHED) {
            double x = stringToValue(operand_x);
            double result;

            switch (this.operator) {
                case ADDITION:
                    result = x + y;

                    break;

                case SUBTRACTION:
                    result = x - y;

                    break;

                case MULTIPLICATION:
                    result = x * y;

                    break;

                case DIVISION:
                    result = x / y;

                    break;

                default:
                    throw new IllegalStateException("Unsupported operation " + operator);
            }

            tfScreen.setText(valueToString(result));
        }

        this.operator = operator == Operator.EQUALS ? null : operator;
        operand_x = null;

        state = State.INPUT_X_FINISHED;
    }

    private static Double stringToValue(String value) {
        try {
            return new Double(value.replace(DECIMAL_SEPARATOR, '.'));
        } catch (NumberFormatException e) {
            // Continue convertion
        }

        if (value.endsWith(String.valueOf(DECIMAL_SEPARATOR))) {
            try {
                // Try convert uncompleted value
                return new Double(value.substring(0, value.length() - 1));
            } catch (NumberFormatException e) {
                // Continue convertion
            }
        }

        return null;
    }

    private static String valueToString(Double value) {
        if (value == null) {
            return ZERO;
        } else {
            String result = value.toString();

            if (result.endsWith(".0")) {
                result = result.substring(0, result.length() - 2);
            }

            if (result.equals("-0")) {
                result = ZERO;
            }

            return result;
        }
    }

    private void addComp(Component comp, int gridx, int gridy,
            int gridwidth, int gridheight) {
        add(comp, new GridBagConstraints(gridx, gridy, gridwidth, gridheight,
                1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                new Insets(4, 4, 4, 4), 0, 0));
    }

    private static class SquareButton extends JButton {

        private SquareButton(String text) {
            super(text);

            setMargin(new Insets(2, 0, 2, 0));
        }

        @Override
        public Dimension getMinimumSize() {
            Dimension result = super.getMinimumSize();

            if (result.width < result.height) {
                result.width = result.height;
            }

            return result;
        }

        @Override
        public Dimension getPreferredSize() {
            return getMinimumSize();
        }
    }

    private class CharButton extends SquareButton {

        private CharButton(final char c) {
            super(String.valueOf(c));

            addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    doProcessChar(c);
                }
            });
        }
    }

    private class OperatorButton extends SquareButton {

        private OperatorButton(final Operator operator, String text) {
            super(text);

            addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    doProcessOperator(operator);
                }
            });
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame f = new JFrame("Calculator");
                f.add(new Calculator());
                f.setSize(300, 350);
                f.setLocationRelativeTo(null);
                f.setVisible(true);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        });
    }
}
```

*s3.postimg.org/7stm62tq7/Calculator.png

explanation: 

 A simple calculator. We add a KeyListener to listen for user input keys.initUI() method initialises the UI of the program.
 doReset() resets the operator, clears the text screen. doProcessChar() processes the user input characters. doProcessBackspace() method
 processes the backspace (pressed by the user).doProcessOperator() processes the operator (addition, subtraction, multiplication, division). 
 addComp() method adds the Components (Buttons 0 to 9) to the panel. 


2) Write a program to download a file from the URL also display its download progress using a progressbar?


```
/**
 * Created with IntelliJ IDEA.
 * User: JGuru
 * Date: 7/17/16
 * Time: 2:41 PM
 * To change this template use File | Settings | File Templates.
 */
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import javax.swing.*;

public class Downloader extends JPanel implements Runnable {

    protected URL downloadURL;
    protected InputStream inputStream;
    protected OutputStream outputStream;
    protected byte[] buffer;
    protected int fileSize;
    protected int bytesRead;
    protected JTextField urlTextField;
    protected JLabel sizeLabel;
    protected JLabel completeLabel;
    protected JProgressBar progressBar;
    public final static int BUFFER_SIZE = 1000;
    protected boolean stopped;
    protected Thread thread;
    private Font font = new Font("Serif", Font.PLAIN, 16);

    public Downloader() {

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            // Do nothing
        }
        thread = new Thread(this);
        buildLayout();

        stopped = false;
    }

    protected void buildLayout() {
        JLabel label;
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 10, 5, 10);

        gbc.gridx = 0;
        label = new JLabel("URL:", JLabel.LEFT);
        label.setFont(font);
        add(label, gbc);

        label = new JLabel("Complete:", JLabel.LEFT);
        label.setFont(font);
        add(label, gbc);

        label = new JLabel("Downloaded:", JLabel.LEFT);
        label.setFont(font);
        add(label, gbc);

        gbc.gridx = 1;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;
        urlTextField = new JTextField(23);
        urlTextField.setFont(font);
        urlTextField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //To change body of implemented methods use File | Settings | File Templates.
                try {
                    urlTextField.setEnabled(false);
                    downloadURL = new URL(urlTextField.getText());
                    thread.start();
                } catch (MalformedURLException e1) {
                    JOptionPane.showMessageDialog(null, "Not a valid URL!!", "Error", JOptionPane.ERROR_MESSAGE);
                }
            }
        });

        add(urlTextField, gbc);

        progressBar = new JProgressBar(0, fileSize);
        progressBar.setPreferredSize(new Dimension(160, 32));
        //progressBar.setStringPainted(true);
        add(progressBar, gbc);

        gbc.gridwidth = 1;
        completeLabel = new JLabel(Integer.toString(bytesRead));
        add(completeLabel, gbc);

        gbc.gridx = 2;
        gbc.weightx = 0;
        gbc.anchor = GridBagConstraints.EAST;
        label = new JLabel("Size:", JLabel.LEFT);
        add(label, gbc);

        gbc.gridx = 3;
        gbc.weightx = 1;
        sizeLabel = new JLabel(Integer.toString(fileSize));
        add(sizeLabel, gbc);
    }

    public void run() {
        try {
            performDownload();
        } catch (IOException e) {
            // Do nothing
        }
    }

    // Get file name portion of URL.
    private String getFileName(URL url) {
        String fileName = url.getFile();
        return fileName.substring(fileName.lastIndexOf('/') + 1);
    }

    public void performDownload() throws IOException {

        // Store it in the current directory
        outputStream = new FileOutputStream(getFileName(downloadURL));
        bytesRead = 0;
        URLConnection urlConnection = downloadURL.openConnection();
        fileSize = urlConnection.getContentLength();
        if (fileSize == -1) {
            throw new FileNotFoundException(downloadURL.toString());
        }
        inputStream = new BufferedInputStream(
                urlConnection.getInputStream());
        buffer = new byte[BUFFER_SIZE];
        int byteCount;
        while ((bytesRead < fileSize) && (!stopped)) {
            try {
                byteCount = inputStream.read(buffer);
                if (byteCount == -1) {
                    stopped = true;
                    break;
                }
                else {
                    outputStream.write(buffer, 0,
                            byteCount);
                    bytesRead += byteCount;
                    progressBar.setValue(bytesRead);
                    completeLabel.setText(
                            Integer.toString(
                                    bytesRead));
                }
            } catch (IOException ioe) {
                stopped = true;
                JOptionPane.showMessageDialog(this,
                        ioe.getMessage(),
                        "I/O Error",
                        JOptionPane.ERROR_MESSAGE);
                break;
            }
        }
        try {
            outputStream.close();
            inputStream.close();
        } catch (IOException ioe) {};
        urlTextField.setEnabled(true);
        // In case the user wants to fetch from another URL
        thread = null;
        thread = new Thread(this);
    }

    public static void main(String[] args) throws Exception {

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //To change body of implemented methods use File | Settings | File Templates.
                JFrame f = new JFrame();
                f.getContentPane().add(new Downloader());
                f.setSize(750, 450);
                f.setTitle("Downloader");
                f.setLocationRelativeTo(null);
                f.setResizable(false);
                f.setVisible(true);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        });
     }
}
```

*s3.postimg.org/yj11gsn4f/Downloader.png

 Type a URL or Copy(Ctrl + C) & Paste (Ctrl + V) like **media1.santabanta.com/full5/Indian  Celebrities(F)/Hanna Love/hanna-love-6a.jpg*
 press the Enter key. The program will fetch the file from the URL and display it's progress. The downloaded file will be stored in the current directory.



3) Write a download manager program (that can download files & display it's progress)?


```
/**
 * Created with IntelliJ IDEA.
 * User: JGuru
 * Date: 7/22/16
 * Time: 8:12 PM
 * To change this template use File | Settings | File Templates.
 */

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

// The Download Manager.
public class DownloadManager extends JFrame
        implements Observer {
    // Add download text field.
    private JTextField addTextField;

    // Download table's data model.
    private DownloadsTableModel tableModel;

    // Table showing downloads.
    private JTable table;

    // These are the buttons for managing the selected download.
    private JButton pauseButton, resumeButton;
    private JButton cancelButton, clearButton;

    // Currently selected download.
    private Download selectedDownload;

    // Flag for whether or not table selection is being cleared.
    private boolean clearing;

    // Constructor for Download Manager.
    public DownloadManager() {
        // Set application title.
        setTitle("Download Manager");
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            // Do nothing
        }

        // Set window size.
        setSize(750, 600);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        // Create the Menubar
        setJMenuBar(createMenuBar());
        // Create the Table
        createTable();

        // Add panels to display.
        add(createAddPanel(), BorderLayout.NORTH);
        add(createDownloadsPanel(), BorderLayout.CENTER);
        add(createButtonsPanel(), BorderLayout.SOUTH);
    }

    // Create a menubar
    private JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        fileMenu.setMnemonic(KeyEvent.VK_F);
        JMenuItem fileExitMenuItem = new JMenuItem("Exit",
                KeyEvent.VK_X);
        fileExitMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ExitAction();
            }
        });
        fileMenu.add(fileExitMenuItem);
        menuBar.add(fileMenu);
        return menuBar;
    }

    // Create a add panel on the top
    private JPanel createAddPanel() {
        // Set up add panel.
        JPanel addPanel = new JPanel();
        addPanel.add(new JLabel("Enter URL : "));
        addTextField = new JTextField(30);
        addPanel.add(addTextField);
        JButton addButton = new JButton("Add Download");
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                AddAction();
            }
        });
        addPanel.add(addButton);
        return addPanel;
    }

    // Set up downloads panel.
    private JPanel createDownloadsPanel() {
        JPanel downloadsPanel = new JPanel();
        downloadsPanel.setBorder(
                BorderFactory.createTitledBorder("Downloads"));
        downloadsPanel.setLayout(new BorderLayout());
        downloadsPanel.add(new JScrollPane(table),
                BorderLayout.CENTER);
        return downloadsPanel;
    }

    // Create a buttons panel to pause, resume, cancel, clear
    private JPanel createButtonsPanel() {
        // Set up buttons panel.
        JPanel buttonsPanel = new JPanel();
        pauseButton = new JButton("Pause");
        pauseButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                PauseAction();
            }
        });
        pauseButton.setEnabled(false);
        buttonsPanel.add(pauseButton);
        resumeButton = new JButton("Resume");
        resumeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ResumeAction();
            }
        });
        resumeButton.setEnabled(false);
        buttonsPanel.add(resumeButton);
        cancelButton = new JButton("Cancel");
        cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                CancelAction();
            }
        });
        cancelButton.setEnabled(false);
        buttonsPanel.add(cancelButton);
        clearButton = new JButton("Clear");
        clearButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ClearAction();
            }
        });
        clearButton.setEnabled(false);
        buttonsPanel.add(clearButton);
        return buttonsPanel;
    }

    // Create a Table to display the progress of the download
    private void createTable() {
        // Set up Downloads table.
        tableModel = new DownloadsTableModel();
        table = new JTable(tableModel);
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                tableSelectionChanged();
            }
        });
        // Allow only one row at a time to be selected.
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        // Set up ProgressBar as renderer for progress column.
        ProgressRenderer renderer = new ProgressRenderer(0, 100);
        renderer.setStringPainted(true); // show progress text
        table.setDefaultRenderer(JProgressBar.class, renderer);

        // Set table's row height large enough to fit JProgressBar.
        table.setRowHeight(
                (int) renderer.getPreferredSize().getHeight());

    }

    // Exit the application.
    private void ExitAction() {
        System.exit(0);
    }

    // Add a new download.
    private void AddAction() {
        URL verifiedUrl = verifyUrl(addTextField.getText());
        if (verifiedUrl != null) {
            tableModel.addDownload(new Download(verifiedUrl));
            addTextField.setText(""); // reset add text field
        } else {
            JOptionPane.showMessageDialog(this,
                    "Invalid Download URL", "Error",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    // Verify download URL.
    private URL verifyUrl(String url) {
        // Only allow HTTP URLs.
        if (!url.toLowerCase().startsWith("*"))
            return null;

        // Verify format of URL.
        URL verifiedUrl = null;
        try {
            verifiedUrl = new URL(url);
        } catch (Exception e) {
            return null;
        }

        // Make sure URL specifies a file.
        if (verifiedUrl.getFile().length() < 2)
            return null;

        return verifiedUrl;
    }

    // Called when table row selection changes.
    private void tableSelectionChanged() {
    /* Unregister from receiving notifications
       from the last selected download. */
        if (selectedDownload != null)
            selectedDownload.deleteObserver(DownloadManager.this);

    /* If not in the middle of clearing a download,
       set the selected download and register to
       receive notifications from it. */
        if (!clearing && table.getSelectedRow() > -1) {
            selectedDownload =
                    tableModel.getDownload(table.getSelectedRow());
            selectedDownload.addObserver(DownloadManager.this);
            updateButtons();
        }
    }

    // Pause the selected download.
    private void PauseAction() {
        selectedDownload.pause();
        updateButtons();
    }

    // Resume the selected download.
    private void ResumeAction() {
        selectedDownload.resume();
        updateButtons();
    }

    // Cancel the selected download.
    private void CancelAction() {
        selectedDownload.cancel();
        updateButtons();
    }

    // Clear the selected download.
    private void ClearAction() {
        clearing = true;
        tableModel.clearDownload(table.getSelectedRow());
        clearing = false;
        selectedDownload = null;
        updateButtons();
    }

    /* Update each button's state based off of the
       currently selected download's status. */
    private void updateButtons() {
        if (selectedDownload != null) {
            int status = selectedDownload.getStatus();
            switch (status) {
                case Download.DOWNLOADING:
                    pauseButton.setEnabled(true);
                    resumeButton.setEnabled(false);
                    cancelButton.setEnabled(true);
                    clearButton.setEnabled(false);
                    break;
                case Download.PAUSED:
                    pauseButton.setEnabled(false);
                    resumeButton.setEnabled(true);
                    cancelButton.setEnabled(true);
                    clearButton.setEnabled(false);
                    break;
                case Download.ERROR:
                    pauseButton.setEnabled(false);
                    resumeButton.setEnabled(true);
                    cancelButton.setEnabled(false);
                    clearButton.setEnabled(true);
                    break;
                default: // COMPLETE or CANCELLED
                    pauseButton.setEnabled(false);
                    resumeButton.setEnabled(false);
                    cancelButton.setEnabled(false);
                    clearButton.setEnabled(true);
            }
        } else {
            // No download is selected in table.
            pauseButton.setEnabled(false);
            resumeButton.setEnabled(false);
            cancelButton.setEnabled(false);
            clearButton.setEnabled(false);
        }
    }

    /* Update is called when a Download notifies its
       observers of any changes. */
    public void update(Observable o, Object arg) {
        // Update buttons if the selected download has changed.
        if (selectedDownload != null && selectedDownload.equals(o))
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    updateButtons();
                }
            });
    }

    // Run the Download Manager.
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                DownloadManager manager = new DownloadManager();
                manager.setVisible(true);
            }
        });
    }
}

// This class downloads a file from a URL.
class Download extends Observable implements Runnable {
    // Max size of download buffer.
    private static final int MAX_BUFFER_SIZE = 1024;

    // These are the status names.
    public static final String STATUSES[] = {"Downloading",
            "Paused", "Complete", "Cancelled", "Error"};

    // These are the status codes.
    public static final int DOWNLOADING = 0;
    public static final int PAUSED = 1;
    public static final int COMPLETE = 2;
    public static final int CANCELLED = 3;
    public static final int ERROR = 4;

    private URL url; // download URL
    private int size; // size of download in bytes
    private int downloaded; // number of bytes downloaded
    private int status; // current status of download

    // Constructor for Download.
    public Download(URL url) {
        this.url = url;
        size = -1;
        downloaded = 0;
        status = DOWNLOADING;

        // Begin the download.
        download();
    }

    // Get this download's URL.
    public String getUrl() {
        return url.toString();
    }

    // Get this download's size.
    public int getSize() {
        return size;
    }

    // Get this download's progress.
    public float getProgress() {
        return ((float) downloaded / size) * 100;
    }

    // Get this download's status.
    public int getStatus() {
        return status;
    }

    // Pause this download.
    public void pause() {
        status = PAUSED;
        stateChanged();
    }

    // Resume this download.
    public void resume() {
        status = DOWNLOADING;
        stateChanged();
        download();
    }

    // Cancel this download.
    public void cancel() {
        status = CANCELLED;
        stateChanged();
    }

    // Mark this download as having an error.
    private void error() {
        status = ERROR;
        stateChanged();
    }

    // Start or resume downloading.
    private void download() {
        Thread thread = new Thread(this);
        thread.start();
    }

    // Get file name portion of URL.
    private String getFileName(URL url) {
        String fileName = url.getFile();
        return fileName.substring(fileName.lastIndexOf('/') + 1);
    }

    // Download file.
    public void run() {
        RandomAccessFile file = null;
        InputStream stream = null;

        try {
            // Open connection to URL.
            HttpURLConnection connection =
                    (HttpURLConnection) url.openConnection();

            // Specify what portion of file to download.
            connection.setRequestProperty("Range",
                    "bytes=" + downloaded + "-");

            // Connect to server.
            connection.connect();

            // Make sure response code is in the 200 range.
            if (connection.getResponseCode() / 100 != 2) {
                error();
            }

            // Check for valid content length.
            int contentLength = connection.getContentLength();
            if (contentLength < 1) {
                error();
            }

      /* Set the size for this download if it
         hasn't been already set. */
            if (size == -1) {
                size = contentLength;
                stateChanged();
            }

            // Open file and seek to the end of it.
            file = new RandomAccessFile(getFileName(url), "rw");
            file.seek(downloaded);

            stream = connection.getInputStream();
            while (status == DOWNLOADING) {
        /* Size buffer according to how much of the
           file is left to download. */
                byte buffer[];
                if (size - downloaded > MAX_BUFFER_SIZE) {
                    buffer = new byte[MAX_BUFFER_SIZE];
                } else {
                    buffer = new byte[size - downloaded];
                }

                // Read from server into buffer.
                int read = stream.read(buffer);
                if (read == -1)
                    break;

                // Write buffer to file.
                file.write(buffer, 0, read);
                downloaded += read;
                stateChanged();
            }

      /* Change status to complete if this point was
         reached because downloading has finished. */
            if (status == DOWNLOADING) {
                status = COMPLETE;
                stateChanged();
            }
        } catch (Exception e) {
            error();
        } finally {
            // Close file.
            if (file != null) {
                try {
                    file.close();
                } catch (Exception e) {
                }
            }

            // Close connection to server.
            if (stream != null) {
                try {
                    stream.close();
                } catch (Exception e) {
                }
            }
        }
    }

    // Notify observers that this download's status has changed.
    private void stateChanged() {
        setChanged();
        notifyObservers();
    }
}

// This class manages the download table's data.
class DownloadsTableModel extends AbstractTableModel
        implements Observer {
    // These are the names for the table's columns.
    private static final String[] columnNames = {"URL", "Size",
            "Progress", "Status"};

    // These are the classes for each column's values.
    private static final Class[] columnClasses = {String.class,
            String.class, JProgressBar.class, String.class};

    // The table's list of downloads.
    private ArrayList<Download> downloadList =
            new ArrayList<Download>();

    // Add a new download to the table.
    public void addDownload(Download download) {
        // Register to be notified when the download changes.
        download.addObserver(this);

        downloadList.add(download);

        // Fire table row insertion notification to table.
        fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1);
    }

    // Get a download for the specified row.
    public Download getDownload(int row) {
        return (Download) downloadList.get(row);
    }

    // Remove a download from the list.
    public void clearDownload(int row) {
        downloadList.remove(row);

        // Fire table row deletion notification to table.
        fireTableRowsDeleted(row, row);
    }

    // Get table's column count.
    public int getColumnCount() {
        return columnNames.length;
    }

    // Get a column's name.
    public String getColumnName(int col) {
        return columnNames[col];
    }

    // Get a column's class.
    public Class<?> getColumnClass(int col) {
        return columnClasses[col];
    }

    // Get table's row count.
    public int getRowCount() {
        return downloadList.size();
    }

    // Get value for a specific row and column combination.
    public Object getValueAt(int row, int col) {
        Download download = downloadList.get(row);
        switch (col) {
            case 0: // URL
                return download.getUrl();
            case 1: // Size
                int size = download.getSize();
                return (size == -1) ? "" : Integer.toString(size);
            case 2: // Progress
                return new Float(download.getProgress());
            case 3: // Status
                return Download.STATUSES[download.getStatus()];
        }
        return "";
    }

    /* Update is called when a Download notifies its
       observers of any changes */
    public void update(Observable o, Object arg) {
        int index = downloadList.indexOf(o);
        // Fire table row update notification to table.
        fireTableRowsUpdated(index, index);
    }
}

// This class renders a JProgressBar in a table cell.
class ProgressRenderer extends JProgressBar
        implements TableCellRenderer {
    // Constructor for ProgressRenderer.
    public ProgressRenderer(int min, int max) {
        super(min, max);
    }

    /* Returns this JProgressBar as the renderer
       for the given table cell. */
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column) {
        // Set JProgressBar's percent complete value.
        setValue((int) ((Float) value).floatValue());
        return this;
    }
}
```

*s15.postimg.org/96auehwg7/Download_Manager.png

class Downloader is the main class of this application (Download manager) .TextField urlTextField accepts the url (from the user).
buildLayout() method builds the layout arrangement of the application.performDownload() method downloads the file from the url(specified by the user).
DownloadManager class has createMenuBar() that creates the menubar. createAddPanel() method adds the add button. createButtonsPanel() adds the buttons resume, pause,
cancel, clear. createTable() method Creates a Table to display the progress of the download. verifyUrl() method verifies the url entered by the user.
class Download - downloads a file from a URL. getProgress() method get the progress of the download. pause() method pauses the download, resume() - resumes the download,
cancel() - cancels the download.download() method creates a new Thread & starts the download. 
class DownloadsTableModel - This class manages the download table's data.

Enter the URL in the textfield & click on the 'Add Download' button. You can enter as many URLs as you like. The Program will fetch the file from the URL & display the
download progress using a progressbar. 


4) Write a program to do various image filters like blur, emboss, threshold, ripples etc.,


```
// You need to download the Jerry Huxtable's Image Filters from www.jhlabs.com

package com.jhlabs.util;

import com.jhlabs.image.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class ImageProcessor extends JFrame implements Printable {

    // Variables declaration
    private JFileChooser fileChooser;
    private BufferedImage image = null;
    private JLabel label;
    private File file;
    private BufferedImage filteredImage;
    private String fileName;
    private int imgWidth, imgHeight;
    private JLabel statusBar;

    public ImageProcessor() {
        super("ImageProcessor");
        // Set the System look 'n feel
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
            // Do nothing
        }
        createFileChooser();
        add(createToolBar(), BorderLayout.NORTH);
        add(createLabelComponent());

        setJMenuBar(createMenuBar());
        add(createStatusBar(), BorderLayout.SOUTH);
        setSize(650, 750);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    // Create a JMenuBar with file & effects menus
    protected JMenuBar createMenuBar() {
        JMenuBar menubar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenu effects = new JMenu("Effects");
        menubar.add(fileMenu);
        menubar.add(effects);

        fileMenu.add(getOpenAction());
        fileMenu.add(getSaveAction());
        fileMenu.add(getSaveAsAction());
        fileMenu.add(getPrintAction());
        fileMenu.add(getRevertAction());
        fileMenu.add(getExitAction());

        effects.add(getBlurFilterAction());
        effects.add(getLensBlurFilterAction());
        effects.add(getCrystallizeFilterAction());
        effects.add(getEmbossFilterAction());
        effects.add(getGrayFilterAction());
        effects.add(getEdgeFilterAction());
        effects.add(getInvertFilterAction());
        effects.add(getLightFilterAction());
        effects.add(getSolarizeFilterAction());
        effects.add(getSphereFilterAction());
        effects.add(getThresholdFilterAction());
        effects.add(getSharpenFilterAction());
        effects.add(getMarbleFilterAction());
        effects.add(getNoiseFilterAction());
        effects.add(getRippleFilterAction());
        effects.add(getMotionBlurFilterAction());
        effects.add(getOilFilterAction());
        effects.add(getSparkleFilterAction());
        effects.add(getTwirlFilterAction());
        effects.add(getWaterRipplesFilterAction());
        effects.add(getTileFilterAction());

        return menubar;
    }

    //Create the statusBar
    private JLabel createStatusBar() {
        statusBar = new JLabel("Ready");
        return statusBar;
    }

    // Get the current Label
    private JLabel getLabel() {
        if (label != null) {
            return label;
        }
        return null;
    }

    // Subclass can override to use a different open action
    protected Action getOpenAction() {
        return openAction;
    }

    protected Action getSaveAction() {
        return saveAction;
    }

    protected Action getSaveAsAction() {
        return saveAsAction;
    }

    protected Action getPrintAction() {
        return printAction;
    }

    protected Action getRevertAction() {
        return revertAction;
    }

    protected Action getExitAction() {
        return exitAction;
    }

    protected Action getBlurFilterAction() {
        return blurAction;
    }

    protected Action getLensBlurFilterAction() {
        return lensBlurAction;
    }

    protected Action getCrystallizeFilterAction() {
        return crystallizeAction;
    }

    protected Action getEmbossFilterAction() {
        return embossAction;
    }

    protected Action getGrayFilterAction() {
        return grayAction;
    }

    protected Action getEdgeFilterAction() {
        return edgeAction;
    }

    protected Action getInvertFilterAction() {
        return invertAction;
    }

    protected Action getLightFilterAction() {
        return lightAction;
    }

    protected Action getSolarizeFilterAction() {
        return solarizeAction;
    }

    protected Action getSphereFilterAction() {
        return sphereAction;
    }

    protected Action getThresholdFilterAction() {
        return thresholdAction;
    }

    protected Action getSharpenFilterAction() {
        return sharpenAction;
    }

    protected Action getMarbleFilterAction() {
        return marbleAction;
    }

    protected Action getNoiseFilterAction() {
        return noiseAction;
    }

    protected Action getRippleFilterAction() {
        return rippleAction;
    }

    protected Action getMotionBlurFilterAction() {
        return motionBlurAction;
    }

    protected Action getOilFilterAction() {
        return oilAction;
    }

    protected Action getSparkleFilterAction() {
        return sparkleAction;
    }

    protected Action getTwirlFilterAction() {
        return twirlAction;
    }

    protected Action getWaterRipplesFilterAction() {
        return waterRipplesAction;
    }

    protected Action getTileFilterAction() {
        return tileAction;
    }

    // Create a simple JToolBar with some buttons
    protected JToolBar createToolBar() {
        JToolBar bar = new JToolBar();

        // Add simple actions for opening & saving
        bar.add(getOpenAction()).setText("");
        bar.add(getSaveAction()).setText("");
        bar.add(getSaveAsAction()).setText("");
        bar.add(getPrintAction()).setText("");
        bar.add(getRevertAction()).setText("");
        bar.add(getExitAction()).setText("");

        return bar;
    }

    private Action openAction = new OpenAction();
    private Action saveAction = new SaveAction();
    private Action saveAsAction = new SaveAsAction();
    private Action printAction = new PrintAction();
    private Action revertAction = new RevertAction();
    private Action exitAction = new ExitAction();

    private Action blurAction = new BlurFilterAction();
    private Action lensBlurAction = new LensBlurAction();
    private Action crystallizeAction = new CrystallizeFilterAction();
    private Action embossAction = new EmbossFilterAction();
    private Action grayAction = new GrayScaleFilterAction();
    private Action edgeAction = new EdgeFilterAction();
    private Action invertAction = new InvertFilterAction();
    private Action lightAction = new LightFilterAction();
    private Action solarizeAction = new SolarizeFilterAction();
    private Action sphereAction = new SphereFilterAction();
    private Action thresholdAction = new ThresholdFilterAction();
    private Action sharpenAction = new SharpenFilterAction();
    private Action marbleAction = new MarbleFilterAction();
    private Action noiseAction = new NoiseFilterAction();
    private Action rippleAction = new RippleFilterAction();
    private Action motionBlurAction = new MotionBlurFilterAction();
    private Action oilAction = new OilFilterAction();
    private Action sparkleAction = new SparkleFilterAction();
    private Action twirlAction = new TwirlFilterAction();
    private Action waterRipplesAction = new WaterFilterAction();
    private Action tileAction = new TileFilterAction();

    // Create a FileChooser
    public void createFileChooser() {
        fileChooser = new JFileChooser();
        fileChooser.setAccessory(new ImagePreview(fileChooser));
        fileChooser.setPreferredSize(new Dimension(800, 500));
        fileChooser.setAcceptAllFileFilterUsed(false);
        fileChooser.setCurrentDirectory(new File("Samples"));
        final String[] format = getReaderFormats();
        fileChooser.addChoosableFileFilter(new FileFilter() {

            @Override
            public boolean accept(File file) {
                String fileName = file.getName();
                for (int i = 0; i < format.length; i++) {
                    // Show directory & images files only
                    if (fileName.endsWith(format[i]) || file.isDirectory()) {
                        return true;
                    }
                }
                return false;
            }

            // Show something like "*.jpg,*.jpeg,*.bmp,*.tiff,*.gif,*.jpeg2000" etc.,
            @Override
            public String getDescription() {
                String str = "";
                for (int i = 0; i < format.length; i++) {
                    str += "*." + format[i] + ",";
                }
                return str;
            }
        });
    }

    // Get supported Image formats (remove duplicate entries)
    public String[] getReaderFormats() {
        String[] rFormat = ImageIO.getReaderFormatNames();
        Set<String> set = new HashSet<>();
        String imgformat = "";
        for (String rFormat1 : rFormat) {
            imgformat = rFormat1;
            imgformat = imgformat.toLowerCase();
            set.add(imgformat);
        }
        String[] frmt = new String[set.size()];
        return set.toArray(frmt);
    }

    // Get the Image from the disk
    public BufferedImage getImage(String fileName) {
        //Fetch the Image for processing
        try {
            return ImageIO.read(new File(fileName));
        } catch (IOException ioe) {
            JOptionPane.showMessageDialog(null, "Not a valid Image!!!", "Error", JOptionPane.ERROR_MESSAGE);
            //Disable menu items other than 'Open' & 'Exit"!
            // Since there is no Image to process!!
            setEnabled(false);
        }
        // In case of error
        return null;
    }

    // Get the filteredImage (processed image)
    public BufferedImage getFilteredImage() {
        if (filteredImage != null) {
            return filteredImage;
        }
        return null;
    }

    // Get the current image
    public BufferedImage getImage() {
        if (image != null) {
            return image;
        }
        return image;
    }

    // Set the initial filtered image
    public void setFilteredImage(BufferedImage bufferedImage) {
        filteredImage = bufferedImage;
    }

    // Create the JLabel
    protected JScrollPane createLabelComponent() {
        label = new JLabel();
        label.setVerticalAlignment(SwingConstants.TOP);
        label.setHorizontalAlignment(SwingConstants.LEFT);
        return new JScrollPane(label);
    }

    private JLabel getStatusBar() {
        if (statusBar != null) {
            return statusBar;
        }
        return null;
    }

    // Update the Image in the label & the statusBar message
    public void setImage(BufferedImage buff, String msg) {
        if (buff != null) {
            if (label != null) {
                label.setIcon(new ImageIcon(buff));
                setFilteredImage(buff);
                setStatus(msg);
            }
        }
    }

    private void setStatus(String message) {
        if (getStatusBar() != null) {
            getStatusBar().setText(message);
        }
    }
    // Save Image to the disk

    public void saveImage() {
        try {
            String format = fileName.substring(fileName.lastIndexOf(".") + 1);
            ImageIO.write(getFilteredImage(), format, new File(fileName));

        } catch (IOException ioe) {
            JOptionPane.showMessageDialog(null, "The Image can't be saved!!", "Message", JOptionPane.ERROR_MESSAGE);
        }
    }

    // ********** ACTION INNER CLASSES ********** //
    // A very simple "exit" action
    class ExitAction extends AbstractAction {

        public ExitAction() {
            super("Exit", new ImageIcon("Icons/close.png"));
            putValue(Action.SHORT_DESCRIPTION, "Exit Application");
        }

        @Override
        public void actionPerformed(ActionEvent ev) {
            System.exit(0);
        }
    }

    // An action that opens an existing file
    class OpenAction extends AbstractAction {

        public OpenAction() {
            super("Open", new ImageIcon("icons/open.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Open Image");
        }

        // Query user for a filename and attempt to open and read the file into the
        // text component
        @Override
        public void actionPerformed(ActionEvent ev) {

            int result = fileChooser.showOpenDialog(null);

            if (result != 0) {
                return;
            }

            file = fileChooser.getSelectedFile();
            fileName = file.toString();

            if (file == null) {
                return;
            } else {
                //Fetch the Image for processing
                image = getImage(fileName);
                if (image != null) {
                    imgWidth = image.getWidth(null);
                    imgHeight = image.getHeight(null);
                    // Update the label
                    if (getLabel() != null) {
                        //Initialize the filtered image, otherwise it will theow NullPointerException!!
                        setFilteredImage(image);
                        getLabel().setIcon(new ImageIcon(getImage()));
                    }
                    pack();
                } else {
                    JOptionPane.showMessageDialog(null, "Not a valid Image!!!", "Error", JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }

    // An action that saves the document to a file
    class SaveAction extends AbstractAction {

        public SaveAction() {
            super("Save", new ImageIcon("icons/save.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Save Image");
        }

        @Override
        public void actionPerformed(ActionEvent ev) {

            if (getFilteredImage() != null) {
                if (getFile() != null) {
                    String filename = getFile().getPath();
                    if (filename == null) {
                        return;
                    }
                    saveImage();
                }
            } else {
                showErrorMessage();
            }
        }
    }

    // An action that saves the document to a file
    class SaveAsAction extends AbstractAction {

        public SaveAsAction() {
            super("SaveAs", new ImageIcon("icons/saveas.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Save As another Image");
        }

        // Query user for a filename and attempt to open and write the text
        // component's content to the file
        @Override
        public void actionPerformed(ActionEvent ev) {
            if (getFilteredImage() != null) {
                int returnVal = fileChooser.showSaveDialog(ImageProcessor.this);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    File file = fileChooser.getSelectedFile();
                    // Check whether the file with the same name already exists in the selected directory?
                    if (file.exists()) {
                        int value = JOptionPane.showConfirmDialog(
                                null, "A File with the same name exists!!! Do you want to overwrite it?", "Confirm",
                                JOptionPane.YES_NO_OPTION);

                        if (value == JOptionPane.YES_OPTION) {
                            // Overwrite the existing file!!
                            String filename = file.getPath();
                            if (filename == null) {
                                return;
                            }
                            saveImage();

                        } else {
                            getSaveAsAction();
                        }

                    } else {
                        String filename = file.getPath();
                        if (filename == null) {
                            return;
                        }
                        file = fileChooser.getSelectedFile();
                        fileName = file.toString();
                        saveImage();
                    }
                }
            } else {
                showErrorMessage();
            }
        }
    }

    class PrintAction extends AbstractAction {

        public PrintAction() {
            super("Print", new ImageIcon("icons/print.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Print Image");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            if (getFilteredImage() != null) {
                // Print the Image
                PrinterJob job = PrinterJob.getPrinterJob();
                job.setPrintable(ImageProcessor.this);
                boolean ok = job.printDialog();
                if (ok) {
                    try {
                        job.print();
                    } catch (PrinterException ex) {
                        /* The job did not successfully complete */
                    }
                }
            } else {
                showErrorMessage();
            }
        }
    }

    // Revert to original image
    class RevertAction extends AbstractAction {

        public RevertAction() {
            super("Revert", new ImageIcon("Icons/revert.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Revert to Original Image");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            // Revert to original Image
            if (getImage() != null) {
                BufferedImage filteredSrc = getFilteredImage();
                setImage(getImage(), "Image reverted to original");
                setFilteredImage(filteredSrc);
                setSize(imgWidth, imgHeight);

            } else {
                showErrorMessage();
            }
        }
    }

    //Redo the previous action
    class RedoAction extends AbstractAction {

        public RedoAction() {
            super("Redo", new ImageIcon("Icons/redo.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Redo the last Action");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            // Revert to original Image
            if (getFilteredImage() != null) {
                setImage(getFilteredImage(), "Image reverted to original");
                setSize(imgWidth, imgHeight);

            } else {
                showErrorMessage();
            }
        }
    }

    class BlurFilterAction extends AbstractAction {

        public BlurFilterAction() {
            super("Blur");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            BlurFilter blurFilter = new BlurFilter();
            if (getFilteredImage() != null) {
                setImage(blurFilter.filter(getFilteredImage(), null), "Blur Filter");
            }
        }
    }

    class LensBlurAction extends AbstractAction {

        public LensBlurAction() {
            super("Lens Blur");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            new Thread(new Runnable() {

                @Override
                public void run() {

                    LensBlurFilter lFilter = new LensBlurFilter();
                    lFilter.setBloom(1f);
                    lFilter.setBloomThreshold(5f);
                    lFilter.setRadius(15);
                    if (getFilteredImage() != null) {
                        setImage(lFilter.filter(getFilteredImage(), null), "Lens Blur - Bloom = 1f, BloomThreshold = 5f, Radius = 15");
                    }

                }
            }).start();
        }
    }

    class CrystallizeFilterAction extends AbstractAction {

        public CrystallizeFilterAction() {
            super("Crystallize");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    CrystallizeFilter cFilter = new CrystallizeFilter();
                    cFilter.setAmount(40f);
                    cFilter.setGridType(CrystallizeFilter.HEXAGONAL);
                    cFilter.setScale(20);
                    if (getFilteredImage() != null) {
                        setImage(cFilter.filter(getFilteredImage(), null), "Crystallized - Amount = 40f , Scale = 20");
                    }
                }
            }).start();
        }
    }

    class OilFilterAction extends AbstractAction {

        public OilFilterAction() {
            super("Oil");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            // This takes a bit longer to process
            new Thread(new Runnable() {

                @Override
                public void run() {
                    setEnabled(false);
                    OilFilter oFilter = new OilFilter();
                    if (getFilteredImage() != null) {
                        setImage(oFilter.filter(getFilteredImage(), null), "Image Oil Filter");
                    }
                    setEnabled(true);
                }
            }).start();
        }
    }

    class RippleFilterAction extends AbstractAction {

        public RippleFilterAction() {
            super("Ripple");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            try {

                RippleFilter rFilter = new RippleFilter();
                // WaveType - SINE, SAWTOOTH, TRIANGLE, NOISE
                rFilter.setWaveType(RippleFilter.SINE);
                rFilter.setXAmplitude(5f);
                rFilter.setYAmplitude(5f);
                rFilter.setXWavelength(6f);
                if (getFilteredImage() != null) {
                    setImage(rFilter.filter(getFilteredImage(), null), "Ripples - WaveType = SINE, XAmplitude = 5f, YAmplitude = 5f, XWaveLength = 6f");
                }

            } catch (Exception ex) {
            }
        }
    }

    class SparkleFilterAction extends AbstractAction {

        public SparkleFilterAction() {
            super("Sparkle");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            new Thread(new Runnable() {

                @Override
                public void run() {

                    SparkleFilter spFilter = new SparkleFilter();
                    spFilter.setAmount(40);
                    spFilter.setRadius(50);
                    spFilter.setRandomness(10 * 2);
                    spFilter.setRays(55);
                    if (getFilteredImage() != null) {
                        setImage(spFilter.filter(getImage(), null), "Sparkle");
                    }
                }
            }).start();
        }
    }

    class EmbossFilterAction extends AbstractAction {

        public EmbossFilterAction() {
            super("Emboss");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            // Emboss the Image (like in the back side of a Rupee coin)
            EmbossFilter eFilter = new EmbossFilter();
            eFilter.setAzimuth(5f);
            eFilter.setElevation(0.5f);
            eFilter.setBumpHeight(1.8f);
            if (getImage() != null) {
                setImage(eFilter.filter(getImage(), null), "Embossed - Azimuth = 5f , Elevation = 0.5f , BumpHeight = 1.8f");
            }
        }
    }

    class GrayScaleFilterAction extends AbstractAction {

        public GrayScaleFilterAction() {
            super("GrayScale");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            GrayscaleFilter grayscaleFilter = new GrayscaleFilter();
            if (getImage() != null) {
                setImage(grayscaleFilter.filter(getImage(), null), "GrayScale");
            }
        }
    }

    class LightFilterAction extends AbstractAction {

        public LightFilterAction() {
            super("Light");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            LightFilter lightFilter = new LightFilter();
            lightFilter.setDiffuseColor(15);
            lightFilter.setBumpSource(LightFilter.BUMPS_FROM_BEVEL);
            lightFilter.setViewDistance(60f);
            if (getImage() != null) {
                setImage(lightFilter.filter(getImage(), null), "Light Filter");
            }
        }
    }

    class InvertFilterAction extends AbstractAction {

        public InvertFilterAction() {
            super("Invert");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            InvertFilter invertFilter = new InvertFilter();
            if (getImage() != null) {
                setImage(invertFilter.filter(getImage(), null), "Invert Filter");
            }
        }
    }

    class SolarizeFilterAction extends AbstractAction {

        public SolarizeFilterAction() {
            super("Solarize");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            SolarizeFilter solarizeFilter = new SolarizeFilter();
            if (getImage() != null) {
                setImage(solarizeFilter.filter(getImage(), null), "Solarize");
            }
        }
    }

    class SphereFilterAction extends AbstractAction {

        public SphereFilterAction() {
            super("Sphere");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            SphereFilter sphereFilter = new SphereFilter();
            sphereFilter.setRefractionIndex(1.5f);
            sphereFilter.setRadius(200f);
            if (getImage() != null) {
                setImage(sphereFilter.filter(getImage(), null), "Sphere Filter");
            }
        }
    }

    class ThresholdFilterAction extends AbstractAction {

        public ThresholdFilterAction() {
            super("Threshold");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            ThresholdFilter thresholdFilter = new ThresholdFilter();
            if (getImage() != null) {
                setImage(thresholdFilter.filter(getImage(), null), "Threshold Filter");
            }
        }
    }

    class SharpenFilterAction extends AbstractAction {

        public SharpenFilterAction() {
            super("Sharpen");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            SharpenFilter sharpenFilter = new SharpenFilter();
            if (getImage() != null) {
                setImage(sharpenFilter.filter(getImage(), null), "Sharpen Filter");
            }
        }
    }

    class MarbleFilterAction extends AbstractAction {

        public MarbleFilterAction() {
            super("Marble");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            MarbleFilter marbleFilter = new MarbleFilter();
            if (getImage() != null) {
                setImage(marbleFilter.filter(getImage(), null), "Marble Filter");
            }
        }
    }

    class NoiseFilterAction extends AbstractAction {

        public NoiseFilterAction() {
            super("Noise");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            NoiseFilter noiseFilter = new NoiseFilter();
            noiseFilter.setAmount(50);
            noiseFilter.setDensity(25f);
            noiseFilter.setDistribution(35);
            if (getImage() != null) {
                setImage(noiseFilter.filter(getImage(), null), "Noise Filter");
            }
        }
    }

    class EdgeFilterAction extends AbstractAction {

        public EdgeFilterAction() {
            super("Edge Detect");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            EdgeFilter edgeFilter = new EdgeFilter();
            edgeFilter.setHEdgeMatrix(EdgeFilter.ROBERTS_H);
            edgeFilter.setVEdgeMatrix(EdgeFilter.FREI_CHEN_V);
            if (getImage() != null) {
                setImage(edgeFilter.filter(getImage(), null), "Edge Filter");
            }
        }
    }

    class MotionBlurFilterAction extends AbstractAction {

        public MotionBlurFilterAction() {
            super("MotionBlur");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    // Motion blur takes a lot of time!!, For faster Motion blur use MotionBlurOp
                    setEnabled(false);
                    MotionBlurFilter mFilter = new MotionBlurFilter();
                    mFilter.setDistance(120);
                    mFilter.setAngle(20);
                    if (getImage() != null) {
                        setImage(mFilter.filter(getImage(), null), "Motion Blur - Angle = 120f");
                    }
                    setEnabled(true);
                }
            }).start();
        }
    }

    class TwirlFilterAction extends AbstractAction {

        public TwirlFilterAction() {
            super("Twirl");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            setEnabled(false);
            TwirlFilter tFilter = new TwirlFilter();
            tFilter.setAngle(3);
            tFilter.setRadius(250f);
            if (getImage() != null) {
                setImage(tFilter.filter(getImage(), null), "Twirl - Angle = 3 radians");
            }
            setEnabled(true);
        }
    }

    class TileFilterAction extends AbstractAction {

        public TileFilterAction() {
            super("Tile");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    TileImageFilter tileImageFilter = new TileImageFilter();
                    tileImageFilter.setWidth(imgWidth * 3);
                    tileImageFilter.setHeight(imgHeight * 3);
                    if (getImage() != null) {
                        setImage(tileImageFilter.filter(getImage(), null), "Tile Image");
                        setSize(Toolkit.getDefaultToolkit().getScreenSize());
                    }
                }
            }).start();
        }
    }

    class WaterFilterAction extends AbstractAction {

        public WaterFilterAction() {
            super("Water");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            setEnabled(false);
            // Water ripple effect
            WaterFilter wFilter = new WaterFilter();
            wFilter.setAmplitude(20);
            wFilter.setPhase(8f);
            wFilter.setWavelength(120f);
            wFilter.setRadius(250f);
            if (getImage() != null) {
                setImage(wFilter.filter(getImage(), null), "Water Ripples - Amplitude = 20, Phase = 8f, WaveLength = 120f, Radius = 250f");
            }
            setEnabled(true);
        }
    }

    // Print the Image
    @Override
    public int print(Graphics g, PageFormat pf, int page) throws
            PrinterException {

        if (page > 0) { /* We have only one page, and 'page' is zero-based */

            return NO_SUCH_PAGE;
        }

        /* User (0,0) is typically outside the imageable area, so we must
         * translate by the X and Y values in the PageFormat to avoid clipping
         */
        Graphics2D g2d = (Graphics2D) g;
        g2d.translate(pf.getImageableX(), pf.getImageableY());

        if (getFilteredImage() != null) {
            g2d.drawImage(getFilteredImage(), 0, 0, this);
        }

        /* tell the caller that this page is part of the printed document */
        return PAGE_EXISTS;
    }

    // Get the currently selected File
    private File getFile() {
        if (file != null) {
            return file;
        }
        return null;
    }

    private void showErrorMessage() {
        JOptionPane.showMessageDialog(null, "Oops!!, No Image to Process!!!", "Error", JOptionPane.ERROR_MESSAGE);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ImageProcessor();
            }
        });
    }
}
```

You also need an accesory class ImagePreview


```
package com.jhlabs.util;

/**
 * Created with IntelliJ IDEA.
 * User: Sowndar
 * Date: 8/2/14
 * Time: 8:45 PM
 * To change this template use File | Settings | File Templates.
 */

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;

/**
 * @author Sowndar
 */
public class ImagePreview extends JComponent implements PropertyChangeListener {

    ImageIcon thumbnail = null;
    int width = 180;

    public ImagePreview(JFileChooser fc) {
        setPreferredSize(new Dimension(width, 50));
        fc.addPropertyChangeListener(this);
        setBorder(new BevelBorder(BevelBorder.LOWERED));
    }

    public void loadImage(File f) {
        if (f == null) {
            thumbnail = null;
        } else {
            ImageIcon tmpIcon = new ImageIcon(getImage(f.getPath()));
            if (tmpIcon.getIconWidth() > width) {
                thumbnail = new ImageIcon(
                        tmpIcon.getImage().getScaledInstance(width, -1, Image.SCALE_SMOOTH));
            } else {
                thumbnail = tmpIcon;
            }
        }
    }

    public BufferedImage getImage(String fileName) {
        try {
            return ImageIO.read(new File(fileName));
        } catch (IOException ioe) {
            System.err.println("Error loading Image!!");
        }
        return null;
    }

    @Override
    public void propertyChange(PropertyChangeEvent e) {
        String prop = e.getPropertyName();
        if (prop == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY) {
            if (isShowing()) {
                loadImage((File) e.getNewValue());
                repaint();
            }
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (thumbnail != null) {
            int x = getWidth() / 2 - thumbnail.getIconWidth() / 2;
            int y = getHeight() / 2 - thumbnail.getIconHeight() / 2;
            if (y < 0) {
                y = 0;
            }

            if (x < 5) {
                x = 5;
            }
            thumbnail.paintIcon(this, g, x, y);
        }
    }
}
```

*s3.postimg.org/6oxjhkrr3/Image_Processor.png

createMenuBar() creates the menubar of the application. createStatusBar() method creates the statusbar of the application. getLabel() method get the current label
(displaying the image) . createToolBar() creates a toolbar with open, save, saveAs, print, revert, exit buttons. 

OpenAction() - opens the filechooser dialog (user selects an image)
SaveAction() - Saves the image to the disk.
SaveAsAction() - Saves the image file with a different name.
PrintAction() - Prints the Image. (Goes to the printer)
RevertAction() - Reverts the image to the original image.
ExitAction() - Exits the application.

Next we have various filters that do various image processing filters..- blur, emboss, edgeDetect, invert, solarize,threshold, oil, twirl, tile etc..,

BlurFilterAction(), LensBlurAction(), EmbossFilterAction(), InvertFilterAction(), ThresholdFilterAction(), NoiseFilterAction(), TileFilterAction() etc.,

createFileChooser() creates the filechooser.getImage(String fileName) gets the image from disk. getFilteredImage() gets the currently filtered image.
getImage() - gets the current the image. setImage() sets the image in the label & statusbar message. saveImage() method saves the image to the disk.

You need to download Jerry Huxtable's various image processing filters from Download Java Image Processing Classes *jhlabs.com/ip/filters/Filters.zip
and use them for this program.


5) Write a program to show a simple imageviewer in action?


```
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

/**
 * Created with IntelliJ IDEA. User: raghu Date: 7/21/16 Time: 1:11 PM To change
 * this template use File | Settings | File Templates.
 */
public class ImageViewer extends JFrame implements Printable {

    private JLabel imageLabel;
    private JLabel statusBar;
    private JFileChooser fileChooser;
    private File file;
    private BufferedImage image;
    private String fileName;

    public ImageViewer() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
            // Do nothing
        }
        createFileChooser();

        setJMenuBar(createMenuBar());
        add(createToolBar(), BorderLayout.NORTH);
        add(createLabel(), BorderLayout.CENTER);
        add(createStatusBar(), BorderLayout.SOUTH);
        setSize(Toolkit.getDefaultToolkit().getScreenSize());
        setTitle("ImageViewer");
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    // Print the Image in the JLabel
    @Override
    public int print(Graphics g, PageFormat pf, int page) throws
            PrinterException {

        if (page > 0) { /* We have only one page, and 'page' is zero-based */

            return NO_SUCH_PAGE;
        }

        /* User (0,0) is typically outside the imageable area, so we must
         * translate by the X and Y values in the PageFormat to avoid clipping
         */
        Graphics2D g2d = (Graphics2D) g;
        g2d.translate(pf.getImageableX(), pf.getImageableY());

        if (getImage() != null) {
            g2d.drawImage(getImage(), 0, 0, this);
        }

        /* tell the caller that this page is part of the printed document */
        return PAGE_EXISTS;
    }

    private JScrollPane createLabel() {
        imageLabel = new JLabel();
        imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
        imageLabel.setVerticalAlignment(SwingConstants.CENTER);
        return new JScrollPane(imageLabel);
    }

    // Get the current Image displayed by the JLabel
    private BufferedImage getImage() {
        if (image != null) {
            return image;
        }
        return null;
    }

    // Create a JMenuBar with file & edit menus
    protected JMenuBar createMenuBar() {
        JMenuBar menubar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenu imaging = new JMenu("Image");
        menubar.add(fileMenu);
        menubar.add(imaging);

        fileMenu.add(getOpenAction());
        fileMenu.add(getSaveAction());
        fileMenu.add(getSaveAsAction());
        fileMenu.add(getPrintAction());
        fileMenu.add(getExitAction());

        imaging.add(getRotateLeftAction());
        imaging.add(getRotateRightAction());
        imaging.add(getFlipHorizontalAction());
        imaging.add(getFlipVerticalAction());

        return menubar;
    }

    // Do various transformations
    private void doAffineTransform(int width, int height, AffineTransform transform) {
        BufferedImage newImage = new BufferedImage(image.getColorModel(),
                image.getRaster().createCompatibleWritableRaster(width, height),
                image.isAlphaPremultiplied(), new Hashtable<>());

        ((Graphics2D) newImage.getGraphics()).drawRenderedImage(image, transform);

        image = newImage;
        if (getLabel() != null) {
            getLabel().setIcon(new ImageIcon(image));
        }
    }

    public void createFileChooser() {
        fileChooser = new JFileChooser();
        fileChooser.setAccessory(new ImagePreview(fileChooser));
        fileChooser.setPreferredSize(new Dimension(800, 500));
        fileChooser.setAcceptAllFileFilterUsed(false);
        fileChooser.setCurrentDirectory(new File("Samples"));
        final String[] format = getReaderFormats();
        fileChooser.addChoosableFileFilter(new FileFilter() {

            @Override
            public boolean accept(File file) {
                String fileName = file.getName();
                for (int i = 0; i < format.length; i++) {
                    // Show directory & images files only
                    if (fileName.endsWith(format[i]) || file.isDirectory()) {
                        return true;
                    }
                }
                return false;
            }

            // Show something like "*.jpg,*.jpeg,*.bmp,*.tiff,*.gif,*.jpeg2000" etc.,
            @Override
            public String getDescription() {
                String str = "";
                for (int i = 0; i < format.length; i++) {
                    str += "*." + format[i] + ",";
                }
                return str;
            }
        });
    }

    // Create a simple JToolBar with some buttons
    protected JToolBar createToolBar() {
        JToolBar bar = new JToolBar();

        // Add simple actions for opening & saving
        bar.add(getOpenAction()).setText("");
        bar.add(getSaveAction()).setText("");
        bar.add(getSaveAsAction()).setText("");
        bar.add(getPrintAction()).setText("");
        bar.addSeparator();
        bar.add(getRotateLeftAction()).setText("");
        bar.add(getRotateRightAction()).setText("");
        bar.add(getFlipHorizontalAction()).setText("");
        bar.add(getFlipVerticalAction()).setText("");
        bar.add(getExitAction()).setText("");

        return bar;
    }

    // Subclass can override to use a different open action
    protected Action getOpenAction() {
        return openAction;
    }

    // Subclass can override to use a different save action
    protected Action getSaveAction() {
        return saveAction;
    }

    // Subclass can override to use a different save action
    protected Action getSaveAsAction() {
        return saveAsAction;
    }

    // Subclass can override to use a different save action
    protected Action getPrintAction() {
        return printAction;
    }

    protected Action getRotateLeftAction() {
        return rotateLeftAction;
    }

    protected Action getRotateRightAction() {
        return rotateRightAction;
    }

    protected Action getFlipHorizontalAction() {
        return flipHorizontalAction;
    }

    protected Action getFlipVerticalAction() {
        return flipVerticalAction;
    }

    protected Action getExitAction() {
        return exitAction;
    }

    // Define our Actions
    private Action openAction = new OpenAction();
    private Action saveAction = new SaveAction();
    private Action saveAsAction = new SaveAsAction();
    private Action printAction = new PrintAction();
    private Action exitAction = new ExitAction();
    private Action rotateLeftAction = new RotateLeftAction();
    private Action rotateRightAction = new RotateRightAction();
    private Action flipVerticalAction = new FlipVerticalAction();
    private Action flipHorizontalAction = new FlipHorizontalAction();

    // A very simple "exit" action
    class ExitAction extends AbstractAction {

        public ExitAction() {
            super("Exit", new ImageIcon("icons/Close.png"));
            putValue(Action.SHORT_DESCRIPTION, "Exit Application");
        }

        @Override
        public void actionPerformed(ActionEvent ev) {
            System.exit(0);
        }
    }

    // An action that opens an existing file
    class OpenAction extends AbstractAction {

        public OpenAction() {
            super("Open", new ImageIcon("icons/open.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Open File");
        }

        // Query user for a filename and attempt to open and read the file into the
        // text component
        @Override
        public void actionPerformed(ActionEvent ev) {

            int returnVal = fileChooser.showOpenDialog(ImageViewer.this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                file = fileChooser.getSelectedFile();

                fileName = file.getPath();
                if (fileName == null) {
                    return;
                }
                image = getImage(fileName);
                if (image != null) {
                    getLabel().setIcon(new ImageIcon(image));
                }
            }
        }
    }

    // An action that saves the document to a file
    class SaveAction extends AbstractAction {

        public SaveAction() {
            super("Save", new ImageIcon("icons/save.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Save");
        }

        @Override
        public void actionPerformed(ActionEvent ev) {

            if (getImage() != null) {
                if (getFile() != null) {
                    String filename = getFile().getPath();
                    if (filename == null) {
                        return;
                    }
                    saveImage();
                }
            } else {
                showMessage("Error Saving Image!!", "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
    // An action that saves the document to a file

    class SaveAsAction extends AbstractAction {

        public SaveAsAction() {
            super("Save As", new ImageIcon("icons/saveas.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Save As");
        }

        // Query user for a filename and attempt to open and write the text
        // component's content to the file
        @Override
        public void actionPerformed(ActionEvent ev) {
            if (getImage() != null) {
                fileChooser.setDialogTitle("Save As");
                int returnVal = fileChooser.showSaveDialog(ImageViewer.this);

                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    File file = fileChooser.getSelectedFile();
                    String filename = file.getPath();
                    // Check whether the file with the same name already exists in the selected directory?
                    if (file.exists()) {
                        int value = JOptionPane.showConfirmDialog(
                                null, "A File with the same name exists!!! Do you want to overwrite it?", "Confirm",
                                JOptionPane.YES_NO_OPTION);

                        if (value == JOptionPane.YES_OPTION) {
                            // Overwrite the existing file!!

                            if (filename == null) {
                                return;
                            }
                            saveImage(filename);

                        } else {
                            getSaveAsAction();
                        }

                    } else {
                        //filename = file.getPath();
                        if (filename == null) {
                            return;
                        }
                        file = fileChooser.getSelectedFile();
                        //String fileName = file.toString();
                        saveImage(filename);
                    }
                }
            } else {
                showMessage("Error Saving Image!!", "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    // An action that prints the image
    class PrintAction extends AbstractAction {

        public PrintAction() {
            super("Print", new ImageIcon("icons/print.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Print File");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            if (getImage() != null) {
                // Print the Image
                PrinterJob job = PrinterJob.getPrinterJob();
                job.setPrintable(ImageViewer.this);
                boolean ok = job.printDialog();
                if (ok) {
                    try {
                        job.print();
                    } catch (PrinterException ex) {
                        /* The job did not successfully complete */
                    }
                }
            } else {
                showMessage("Error Printing the Image file!!", "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    // Rotate the Image to the Left
    class RotateLeftAction extends AbstractAction {

        public RotateLeftAction() {
            super("Rotate Left", new ImageIcon("Icons/rotateleft.png"));
            putValue(Action.SHORT_DESCRIPTION, "Rotate Left");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (getImage() != null) {
                doAffineTransform(image.getHeight(), image.getWidth(),
                        new AffineTransform(0, -1, 1, 0, 0, image.getWidth()));
            }
            setStatus("Image Rotate Left");
        }
    }

    // Rotate the Image to the Right
    class RotateRightAction extends AbstractAction {

        public RotateRightAction() {
            super("Rotate Right", new ImageIcon("Icons/rotateright.png"));
            putValue(Action.SHORT_DESCRIPTION, "Rotate Right");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (getImage() != null) {
                doAffineTransform(image.getHeight(), image.getWidth(),
                        new AffineTransform(0, 1, -1, 0, image.getHeight(), 0));
            }
            setStatus("Image Rotate Right");
        }
    }

    // Flip the Image horizontally
    class FlipHorizontalAction extends AbstractAction {

        public FlipHorizontalAction() {
            super("Flip Horizontal", new ImageIcon("Icons/fliphor.png"));
            putValue(Action.SHORT_DESCRIPTION, "Flip Horizontal");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (getImage() != null) {
                doAffineTransform(image.getWidth(), image.getHeight(),
                        new AffineTransform(-1, 0, 0, 1, image.getWidth(), 0));
            }
            setStatus("Image flipped horizontally");
        }
    }

    // Flip the Image vertically
    class FlipVerticalAction extends AbstractAction {

        public FlipVerticalAction() {
            super("Flip Vertical", new ImageIcon("Icons/flipvert.png"));
            putValue(Action.SHORT_DESCRIPTION, "Flip Vertical");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (getImage() != null) {
                doAffineTransform(image.getWidth(), image.getHeight(),
                        new AffineTransform(1, 0, 0, -1, 0, image.getHeight()));
            }
            setStatus("Image flipped vertically");
        }
    }

    // Save Image to the disk
    public void saveImage() {
        try {

            String format = fileName.substring(fileName.lastIndexOf(".") + 1);
            if (getImage() != null) {
                ImageIO.write(getImage(), format, new File(fileName));
            }
            setStatus("The Image is saved");
        } catch (IOException ioe) {
            JOptionPane.showMessageDialog(null, "The Image can't be saved!!", "Message", JOptionPane.ERROR_MESSAGE);
            setStatus("The Image is not saved!!!");
        }
    }

    // Save Image to the disk
    public void saveImage(String fileName) {
        try {

            String format = fileName.substring(fileName.lastIndexOf(".") + 1);
            if (getImage() != null) {
                ImageIO.write(getImage(), format, new File(fileName));
            }
            setStatus("The Image is saved");
        } catch (IOException ioe) {
            JOptionPane.showMessageDialog(null, "The Image can't be saved!!", "Message", JOptionPane.ERROR_MESSAGE);
            setStatus("The Image is not saved!!!");
        }
    }

    // Get the currently open file
    private File getFile() {
        if (file != null) {
            return file;
        }
        return null;
    }

    // Display the message dialog on the screen
    public void showMessage(String message, String title, int messageType) {
        JOptionPane.showMessageDialog(null, message, title, messageType);
    }

    // Get supported Image formats (remove duplicate entries)
    public String[] getReaderFormats() {
        String[] rFormat = ImageIO.getReaderFormatNames();
        Set<String> set = new HashSet<>();
        String imgformat = "";
        for (String rFormat1 : rFormat) {
            imgformat = rFormat1;
            imgformat = imgformat.toLowerCase();
            set.add(imgformat);
        }
        String[] frmt = new String[set.size()];
        return set.toArray(frmt);
    }

    // Create a status bar
    private JLabel createStatusBar() {
        statusBar = new JLabel();
        return statusBar;
    }

    // Get the JLabel that holds the Image
    private JLabel getLabel() {
        if (imageLabel != null) {
            return imageLabel;
        }
        return null;
    }

    // Get the Image from the disk
    private BufferedImage getImage(String fileName) {
        try {
            return ImageIO.read(new File(fileName));
        } catch (IOException ioe) {
        }
        return null;
    }

    // Get the statusbar
    private JLabel getStatusBar() {
        if (statusBar != null) {
            return statusBar;
        }
        return null;
    }

    // Post some messages on the statusbar
    private void setStatus(String message) {
        getStatusBar().setText(message);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ImageViewer();
            }
        });
    }
}
```

ImageViewer needs an accessory class ImagePreview

ImagePreview.java


```
/**
 * Created with IntelliJ IDEA.
 * User: JGuru
 * Date: 7/21/16
 * Time: 1:40 PM
 * To change this template use File | Settings | File Templates.
 */

import java.awt.*;
import java.awt.image.BufferedImage;
import java.beans.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.*;

/**
 *
 * @author Sowndar
 */
public class ImagePreview extends JComponent implements PropertyChangeListener {

    private ImageIcon thumbnail = null;
    private int width = 180;

    public ImagePreview(JFileChooser fc) {
        setPreferredSize(new Dimension(width, 50));
        fc.addPropertyChangeListener(this);
        setBorder(new BevelBorder(BevelBorder.LOWERED));
    }

    public void loadImage(File f) {
        if (f == null) {
            thumbnail = null;
        } else {
            try
            {
                ImageIcon tmpIcon = new ImageIcon(getImage(f.getPath()));
                if (tmpIcon.getIconWidth() > width) {
                    thumbnail = new ImageIcon(
                            tmpIcon.getImage().getScaledInstance(width, -1, Image.SCALE_SMOOTH));
                } else {
                    thumbnail = tmpIcon;
                }
            } catch (Exception e) {

            }
        }
    }

    public BufferedImage getImage(String fileName) {
        try {
            return ImageIO.read(new File(fileName));
        } catch (IOException ioe) {
            System.err.println("Error loading Image!!");
        }
        return null;
    }

    @Override
    public void propertyChange(PropertyChangeEvent e) {
        String prop = e.getPropertyName();
        if (prop == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY) {
            if (isShowing()) {
                loadImage((File) e.getNewValue());
                repaint();
            }
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (thumbnail != null) {
            int x = getWidth() / 2 - thumbnail.getIconWidth() / 2;
            int y = getHeight() / 2 - thumbnail.getIconHeight() / 2;
            if (y < 0) {
                y = 0;
            }

            if (x < 5) {
                x = 5;
            }
            thumbnail.paintIcon(this, g, x, y);
        }
    }
}
```

*s3.postimg.org/k44vwh27j/Image_Viewer.png


createMenuBar() creates the menubar of the application. createStatusBar() method creates the statusbar of the application. getLabel() method get the current label
(displaying the image) .doAffineTransform() does various transformations. createToolBar() creates a toolbar with open, save, saveAs, print, revert, exit buttons. 

OpenAction() - opens the filechooser dialog (user selects an image)
SaveAction() - Saves the image to the disk.
SaveAsAction() - Saves the image file with a different name.
PrintAction() - Prints the Image. (Goes to the printer)
RotateLeftAction() - Rotates the image to the Left
RotateRightAction() - Rotates the image to the right
FlipHorizontalAction() - Flips the image horizontally
FlipVerticalAction() - Flips the image vertically
RevertAction() - Reverts the image to the original image.
ExitAction() - Exits the application.


createFileChooser() creates the filechooser.getImage(String fileName) gets the image from disk. getFilteredImage() gets the currently filtered image.
getImage() - gets the current the image. setImage() sets the image in the label & statusbar message. saveImage() method saves the image to the disk.


6) Write a program to show a zip file archiver in Java?

Ans. This is similar in spirit to WinZip!!

// NOTE: You need to create a directory called 'Icons' and place some WinZip icons there!!!
// for this program to work!!

JZipDemo.java


```
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import javax.swing.*;
import javax.swing.border.EtchedBorder;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

/**
 * Created with IntelliJ IDEA. User: JGuru Date: 7/16/16 Time: 9:03 PM To change
 * this template use File | Settings | File Templates.
 */
// This is just a demo JZip program!!
public class JZipDemo extends JFrame {

    private JFileChooser fileChooser;
    private File file;
    private ZipFile zipFile;
    private boolean error;
    private final Vector<Date> modDate = new Vector<>();
    private final Vector<Long> entrySize = new Vector<>();
    private final Vector<Long> packed = new Vector<>();
    private Vector<String> archiveContents = new Vector<>();
    private JTable table;
    private JScrollPane scrollPane;
    private JPanel statusBar;
    private JLabel statusLabel;

    public JZipDemo() {

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
            // Do nothing
        }
        setJMenuBar(createMenuBar());
        createFileChooser();
        add(createToolBar(), BorderLayout.NORTH);
        add(createScrollPane(), BorderLayout.CENTER);
        add(createStatusBar(), BorderLayout.SOUTH);
        setTitle("JZipDemo");
        setSize(900, 950);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    // Create the statusBar
    public JPanel createStatusBar() {
        statusBar = new JPanel(new FlowLayout(FlowLayout.LEFT));
        statusLabel = new JLabel("Ready");
        statusBar.add(statusLabel);
        return statusBar;
    }

    // Create the FileChooser
    public void createFileChooser() {
        fileChooser = new JFileChooser(".");
        fileChooser.setAcceptAllFileFilterUsed(false);
        fileChooser.addChoosableFileFilter(new FileFilter() {
            @Override
            public boolean accept(File file) {
                String fileName = file.getName();
                if (fileName.endsWith("zip") || file.isDirectory()) {
                    return true;
                }
                return false;
            }

            @Override
            public String getDescription() {
                return "Zip Files";  //To change body of implemented methods use File | Settings | File Templates.
            }
        });
    }

    // Create the ScrollPane
    private JScrollPane createScrollPane() {
        scrollPane = new JScrollPane();
        return scrollPane;
    }

    //Get the ScrollPane
    private JScrollPane getScrollPane() {
        return scrollPane;
    }

    // Ger the statusBar
    private JPanel getStatusBarPanel() {
        if (statusBar != null) {
            return statusBar;
        }
        return null;
    }

    private JLabel getStatusBar() {
        if (statusLabel != null) {
            return statusLabel;
        }
        return null;
    }

    private void setStatus(String message) {
        if (getStatusBar() != null) {
            getStatusBar().setText(message);
        }
    }

    // Create a simple JToolBar with some buttons
    protected JToolBar createToolBar() {
        JToolBar bar = new JToolBar();

        // Add simple actions for opening & saving
        bar.add(getNewAction()).setText("");
        bar.add(getOpenAction()).setText("");

        bar.add(getFavoritesAction()).setText("");
        bar.add(getAddAction()).setText("");
        bar.add(getExtractAction()).setText("");
        bar.add(getMailAction()).setText("");
        bar.add(getEncryptAction()).setText("");
        bar.add(getViewAction()).setText("");
        bar.add(getCheckOutAction()).setText("");
        bar.add(getWizardAction()).setText("");
        bar.addSeparator();

        return bar;
    }

    // Create a JMenuBar with file & other menus
    protected JMenuBar createMenuBar() {
        JMenuBar menubar = new JMenuBar();

        JMenu fileMenu = new JMenu("File");
        JMenu actions = new JMenu("Actions");
        JMenu view = new JMenu("View");
        JMenu jobs = new JMenu("Jobs");
        JMenu options = new JMenu("Options");
        JMenu help = new JMenu("Help");

        menubar.add(fileMenu);
        menubar.add(actions);
        menubar.add(view);
        menubar.add(jobs);
        menubar.add(options);
        menubar.add(options);
        menubar.add(help);

        fileMenu.add(getMenuNewArchiveAction());
        fileMenu.add(getMenuOpenArchiveAction());
        fileMenu.add(getMenuFavoritesAction());
        fileMenu.add(getMenuCloseArchiveAction());
        fileMenu.add(getMenuSaveAsAction());
        fileMenu.add(getMenuPrintAction());
        fileMenu.add(getMenuPropertiesAction());
        fileMenu.add(getMenuWizardAction());
        fileMenu.add(getMenuExitAction());

        actions.add(getMenuAddAction());
        actions.add(getMenuDeleteAction());
        actions.add(getMenuExtractAction());
        actions.add(getMenuSelectAllAction());

        view.add(getMenuAllFilesAction());
        view.add(getMenuFilesByFolderAction());

        jobs.add(getMenuCreateAction());
        jobs.add(getMenuEditAction());
        jobs.add(getMenuRunAction());
        jobs.add(getMenuZipMyDocsAction());
        jobs.add(getMenuZipAllLibrariesAction());

        help.add(getMenuHelpContentsAction());
        help.add(getMenuAboutAction());

        options.add(getMenuConfigurationAction());
        return menubar;
    }

    protected Action getMenuHelpContentsAction() {
        return menuHelpAction;
    }

    protected Action getMenuAboutAction() {
        return menuAboutAction;
    }

    protected Action getMenuConfigurationAction() {
        return menuConfigurationAction;
    }

    protected Action getMenuAddAction() {
        return menuAddAction;
    }

    protected Action getMenuDeleteAction() {
        return menuDeleteAction;
    }

    protected Action getMenuExtractAction() {
        return menuExtractAction;
    }

    protected Action getNewAction() {
        return newAction;
    }

    protected Action getOpenAction() {
        return openAction;
    }

    protected Action getFavoritesAction() {
        return favoritesAction;
    }

    protected Action getAddAction() {
        return addAction;
    }

    protected Action getExtractAction() {
        return extractAction;
    }

    protected Action getMailAction() {
        return mailAction;
    }

    protected Action getEncryptAction() {
        return encryptAction;
    }

    protected Action getViewAction() {
        return viewAction;
    }

    protected Action getCheckOutAction() {
        return checkOutAction;
    }

    protected Action getWizardAction() {
        return wizardAction;
    }

    protected Action getViewStyleAction() {
        return viewStyleAction;
    }

    protected Action getMenuNewArchiveAction() {
        return menuNewArchiveAction;
    }

    protected Action getMenuOpenArchiveAction() {
        return menuOpenArchiveAction;
    }

    protected Action getMenuFavoritesAction() {
        return menuFavoritesAction;
    }

    protected Action getMenuCloseArchiveAction() {
        return menuCloseArchiveAction;
    }

    protected Action getMenuSaveAsAction() {
        return menuSaveAsAction;
    }

    protected Action getMenuPrintAction() {
        return menuPrintAction;
    }

    protected Action getMenuPropertiesAction() {
        return menuPropertiesAction;
    }

    protected Action getMenuWizardAction() {
        return menuWizardAction;
    }

    protected Action getMenuExitAction() {
        return menuExitAction;
    }

    protected Action getMenuViewAction() {
        return menuViewAction;
    }

    protected Action getMenuSelectAllAction() {
        return menuselectAllAction;
    }

    protected Action getMenuAllFilesAction() {
        return menuAllFilesAction;
    }

    protected Action getMenuFilesByFolderAction() {
        return menuFilesByFolderAction;
    }

    protected Action getMenuCreateAction() {
        return menuCreateAction;
    }

    protected Action getMenuEditAction() {
        return menuEditAction;
    }

    protected Action getMenuRunAction() {
        return menuRunAction;
    }

    protected Action getMenuZipMyDocsAction() {
        return menuZipMyDocsAction;
    }

    protected Action getMenuZipAllLibrariesAction() {
        return menuZipMyLibsAction;
    }

    // Actions declaration
    private Action newAction = new NewAction();
    private Action openAction = new OpenAction();
    private Action favoritesAction = new FavoritesAction();
    private Action addAction = new AddAction();
    private Action extractAction = new ExtractAction();
    private Action mailAction = new MailAction();
    private Action encryptAction = new EncryptAction();
    private Action viewAction = new ViewAction();
    private Action checkOutAction = new CheckOutAction();
    private Action wizardAction = new WizardAction();
    private Action viewStyleAction = new ViewStyleAction();

    private Action menuNewArchiveAction = new MenuNewArchiveAction();
    private Action menuOpenArchiveAction = new MenuOpenArchiveAction();
    private Action menuFavoritesAction = new MenuFavoritesAction();
    private Action menuCloseArchiveAction = new MenuCloseArchiveAction();
    private Action menuSaveAsAction = new MenuSaveAsAction();
    private Action menuPrintAction = new MenuPrintAction();
    private Action menuPropertiesAction = new MenuPropertiesAction();
    private Action menuWizardAction = new MenuWizardAction();
    private Action menuExitAction = new MenuExitAction();
    private Action menuAddAction = new MenuAddAction();
    private Action menuDeleteAction = new MenuDeleteAction();
    private Action menuExtractAction = new MenuExtractAction();
    private Action menuViewAction = new MenuViewAction();
    private Action menuselectAllAction = new MenuSelectAllAction();

    private Action menuAllFilesAction = new MenuAllFilesAction();
    private Action menuFilesByFolderAction = new MenuFilesByFolderAction();

    private Action menuCreateAction = new MenuCreateAction();
    private Action menuEditAction = new MenuEditAction();
    private Action menuRunAction = new MenuRunAction();

    private Action menuZipMyDocsAction = new MenuZipMyDocumentsAction();
    private Action menuZipMyLibsAction = new MenuZipAllLibrariesAction();

    private Action menuConfigurationAction = new MenuConfigurationAction();

    private Action menuHelpAction = new MenuHelpAction();
    private Action menuAboutAction = new MenuAboutAction();

    // ********** ACTION INNER CLASSES ********** //
    // A very simple "exit" action
    public class ExitAction extends AbstractAction {

        public ExitAction() {
            super("Exit", new ImageIcon("icons/Close.png"));
            putValue(Action.SHORT_DESCRIPTION, "Exit");
        }

        @Override
        public void actionPerformed(ActionEvent ev) {
            System.exit(0);
        }
    }

    // Convert the zip file contents to table format
    private JTable createTable(File file) {
        // Open the Zip file
        try {
            zipFile = new ZipFile(file);
        } catch (IOException ex) {
            Logger.getLogger(JZipDemo.class.getName()).log(Level.FINE, null, ex);
            JOptionPane.showMessageDialog(null, "Error processing the Zip file.", "Error", JOptionPane.ERROR_MESSAGE);
            error = true;

        }
        if (!error) {
            //Clear the previous contents of the previous archive (Vector contents!)
            archiveContents.clear();
            entrySize.clear();
            packed.clear();
            modDate.clear();
            String tmpEntry = "";
            ZipEntry zEntry = null;
            String fileName = "";
            String fullPath = "";

            try {
                for (Enumeration<?> entries = zipFile.entries(); entries.hasMoreElements();) {
                    //Don't add the empty directory structure!
                    zEntry = ((ZipEntry) entries.nextElement());
                    tmpEntry = zEntry.getName();
                    if (!tmpEntry.endsWith("/")) {
                        archiveContents.addElement(tmpEntry);
                    }
                    modDate.addElement(new Date(zEntry.getTime()));
                    entrySize.addElement(new Long(zEntry.getSize()));
                    packed.addElement(new Long(zEntry.getCompressedSize()));
                }
                zipFile.close();
                int MAX = archiveContents.size();
                setStatus("" + MAX + " entries found");
                final String[] names = {"Name", "Type", "Modified", "Size", "Packed", "Path"};
                final Vector<String> colData = new Vector<>();
                colData.clear();
                //Create a Vector for storing the Zip file elements
                for (int i = 0; i < names.length; i++) {
                    colData.addElement(names[i]);
                }
                final Object[][] data = new Object[MAX][6];
                //Create the Table
                int count = 0;
                for (int i = 0; i < MAX; i++) {
                    for (int j = 0; j < colData.size(); j++) {
                        // Shows the percentage of the work done
                        try {
                            count = (i * 100) / (MAX - 1);
                            // Show progress if you use a progressBar
                        } catch (Exception e) {
                        }

                        fileName = archiveContents.get(i);
                        fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
                        data[i][0] = "    " + fileName;
                        fileName = fileName.toLowerCase();
                        if (fileName.endsWith("jpg") || fileName.endsWith("jpeg")) {
                            fileName = "  JPEG Image";

                        } else if (fileName.endsWith("png")) {
                            fileName = "  PNG Image";

                        } else if (fileName.endsWith("gif")) {
                            fileName = "  GIF Image";

                        } else if (fileName.endsWith("bmp")) {
                            fileName = "  BMP Image";

                        } else if (fileName.endsWith("tif")) {
                            fileName = "  TIFF Image";

                        } else if (fileName.endsWith("dll")) {
                            fileName = "Dynamic Link Library file";

                        } else if (fileName.endsWith("bat")) {
                            fileName = "  BATCH file";

                        } else if (fileName.endsWith("pdf")) {
                            fileName = "PDF Document";

                        } else if (fileName.endsWith("zip")) {
                            fileName = " ZIP Archive";

                        } else if (fileName.endsWith("tar")) {
                            fileName = " TAR Archive";

                        } else if (fileName.endsWith("rpm")) {
                            fileName = " RPM file";

                        } else if (fileName.endsWith("mp3") || fileName.endsWith("wav") || fileName.endsWith("au") || fileName.endsWith("aiff")) {
                            fileName = " Music file";

                        } else if (fileName.endsWith("mpg") || fileName.endsWith("mpeg") || fileName.endsWith("mov") || fileName.endsWith("avi")) {
                            fileName = " Movie file";

                        } else if (fileName.endsWith("class")) {
                            fileName = "  Java class";

                        } else if (fileName.endsWith("java")) {
                            fileName = "  Java source";

                        } else if (fileName.endsWith("htm") || fileName.endsWith("html")) {
                            fileName = " HTML Document";

                        } else if (fileName.endsWith("xml")) {
                            fileName = " XML Document";

                        } else if (fileName.endsWith("log")) {
                            fileName = "  Log file";

                        } else if (fileName.endsWith("txt")) {
                            fileName = "  Text file";

                        } else if (fileName.endsWith("exe")) {
                            fileName = "Executable file(Windows)";

                        } else if (fileName.endsWith("sh")) {
                            fileName = " ShellScript file";

                        } else if (fileName.endsWith("bin")) {
                            fileName = "Unix executable file";

                        } else {
                            String lastThree = fileName.substring(fileName.length() - 3);
                            lastThree = lastThree.toUpperCase();
                            fileName = "  " + lastThree + "  file";

                        }
                        data[i][1] = "   " + fileName;
                        data[i][2] = modDate.get(i);
                        data[i][3] = entrySize.get(i);
                        data[i][4] = packed.get(i);
                        fullPath = archiveContents.get(i);
                        fullPath = fullPath.substring(0, fullPath.lastIndexOf("/") + 1);
                        data[i][5] = fullPath;

                    } //close for loop
                } // Cloae outer loop

                //Create a table
                // Create a model of the data
                TableModel dataModel = new AbstractTableModel() {
                    @Override
                    public int getColumnCount() {
                        return names.length;
                    }

                    @Override
                    public int getRowCount() {
                        return data.length;
                    }

                    @Override
                    public Object getValueAt(int row, int col) {
                        return data[row][col];
                    }

                    @Override
                    public String getColumnName(int column) {
                        return names[column];
                    }

                    @Override
                    public Class getColumnClass(int c) {
                        return getValueAt(0, c).getClass();
                    }

                    @Override
                    public boolean isCellEditable(int row, int col) {
                        return false;
                    }

                    @Override
                    public void setValueAt(Object aValue, int row, int column) {
                        data[row][column] = aValue;
                    }
                };

                table = new JTable(dataModel);
                table.setCellSelectionEnabled(false);
                table.setColumnSelectionAllowed(false);
                table.setRowSelectionAllowed(true);
                table.setRowHeight(20);
                table.setRowMargin(5);
                table.setFont(new Font("Dialog", Font.BOLD, 11));
                table.setBackground(Color.white);
                table.setDragEnabled(false);
                table.setShowHorizontalLines(false);
                table.setShowVerticalLines(false);
                table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
                TableColumn column = null;
                for (int i = 0; i < names.length; i++) {
                    column = table.getColumnModel().getColumn(i);
                    if (i == 0) {
                        column.setPreferredWidth(200);
                    } else if (i == 1) {
                        column.setPreferredWidth(128);
                    } else if (i == 2) {
                        column.setPreferredWidth(160);
                    } else if (i == 3) {
                        column.setPreferredWidth(80);
                    } else if (i == 4) {
                        column.setPreferredWidth(80);
                    } else {
                        column.setPreferredWidth(280);
                    }
                }
                table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
                return table;

            } catch (IOException e) {
            }
        } // End error
        return null;
    }

    // An action that opens an existing file
    class OpenAction extends AbstractAction {

        public OpenAction() {
            super("Open", new ImageIcon("icons/Open.png"));
            putValue(Action.SHORT_DESCRIPTION, "Open an Archive");
        }

        // Query user for a filename and attempt to open and read the file into the
        // text component
        @Override
        public void actionPerformed(ActionEvent ev) {
            openZipFile();
        }
    }

    private void openZipFile() {
        error = false;
        int returnVal = fileChooser.showOpenDialog(JZipDemo.this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            file = fileChooser.getSelectedFile();

            String filename = file.getPath();
            if (filename == null) {
                return;
            }
            table = createTable(file);
            // Add the table to the scrollpane
            getScrollPane().getViewport().add(table);
        }
    }

    // An action that saves the document to a file
    class SaveAsAction extends AbstractAction {

        public SaveAsAction() {
            super("SaveAs", new ImageIcon("icons/saveas.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Save As");
        }

        // Query user for a filename and attempt to open and write the text
        // component's content to the file
        @Override
        public void actionPerformed(ActionEvent ev) {
            int returnVal = fileChooser.showSaveDialog(JZipDemo.this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fileChooser.getSelectedFile();
                // Check whether the file with the same name already exists in the selected directory?
                if (file.exists()) {
                    int value = JOptionPane.showConfirmDialog(
                            null, "A File with the same name exists!!! Do you want to overwrite it?", "Confirm",
                            JOptionPane.YES_NO_OPTION);

                    if (value == JOptionPane.YES_OPTION) {
                        // Overwrite the existing file!!
                        String filename = file.getPath();
                        if (filename == null) {
                            return;
                        }
                    } else {
                        //getSaveAsAction();
                    }

                } else {
                }
            }
        }
    }

    class NewAction extends AbstractAction {

        public NewAction() {
            super("New", new ImageIcon("Icons/New.png"));
            putValue(Action.SHORT_DESCRIPTION, "Create a new archive");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    class FavoritesAction extends AbstractAction {

        public FavoritesAction() {
            super("Favorites", new ImageIcon("Icons/Favorites.png"));
            putValue(Action.SHORT_DESCRIPTION, "List archives in your favorite zip folder");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    class AddAction extends AbstractAction {

        public AddAction() {
            super("Add", new ImageIcon("Icons/Add.png"));
            putValue(Action.SHORT_DESCRIPTION, "Add files to archive");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    class ExtractAction extends AbstractAction {

        public ExtractAction() {
            super("Extract", new ImageIcon("Icons/Extract.png"));
            putValue(Action.SHORT_DESCRIPTION, "Extract files from archive");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            extract();
        }
    }

    class MailAction extends AbstractAction {

        public MailAction() {
            super("Mail", new ImageIcon("Icons/Mail.png"));
            putValue(Action.SHORT_DESCRIPTION, "Mail archive");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    class EncryptAction extends AbstractAction {

        public EncryptAction() {
            super("Encrypt", new ImageIcon("Icons/Encrypt.png"));
            putValue(Action.SHORT_DESCRIPTION, "Encrypt files in the archive");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    class ViewAction extends AbstractAction {

        public ViewAction() {
            super("View", new ImageIcon("Icons/View.png"));
            putValue(Action.SHORT_DESCRIPTION, "View files inside archive");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    class CheckOutAction extends AbstractAction {

        public CheckOutAction() {
            super("CheckOut", new ImageIcon("Icons/CheckOut.png"));
            putValue(Action.SHORT_DESCRIPTION, "create icons for files in the archive");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    class WizardAction extends AbstractAction {

        public WizardAction() {
            super("Wizard", new ImageIcon("Icons/Wizard.png"));
            putValue(Action.SHORT_DESCRIPTION, "Activate the JZip wizard");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    class ViewStyleAction extends AbstractAction {

        public ViewStyleAction() {
            super("View Style", new ImageIcon("Icons/View Style.png"));
            putValue(Action.SHORT_DESCRIPTION, "Toggle the display style");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            showMessage("This is just a demo!!");
        }
    }

    // Menu actions
    class MenuNewArchiveAction extends AbstractAction {

        public MenuNewArchiveAction() {
            super("New Archive", new ImageIcon("Icons/menu/New.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuOpenArchiveAction extends AbstractAction {

        public MenuOpenArchiveAction() {
            super("Open Archive", new ImageIcon("Icons/menu/Open.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            openZipFile();
        }
    }

    class MenuFavoritesAction extends AbstractAction {

        public MenuFavoritesAction() {
            super("Favorites", new ImageIcon("Icons/menu/Favorite.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuCloseArchiveAction extends AbstractAction {

        public MenuCloseArchiveAction() {
            super("Close Archive", new ImageIcon("Icons/menu/Close.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuSaveAsAction extends AbstractAction {

        public MenuSaveAsAction() {
            super("Save As", new ImageIcon("Icons/menu/saveas.gif"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuPrintAction extends AbstractAction {

        public MenuPrintAction() {
            super("Print", new ImageIcon("Icons/menu/Print.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuPropertiesAction extends AbstractAction {

        public MenuPropertiesAction() {
            super("Properties", new ImageIcon("Icons/menu/Properties.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuWizardAction extends AbstractAction {

        public MenuWizardAction() {
            super("Wizard", new ImageIcon("Icons/menu/Wizard.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuExitAction extends AbstractAction {

        public MenuExitAction() {
            super("Exit");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }

    class MenuAddAction extends AbstractAction {

        public MenuAddAction() {
            super("Add", new ImageIcon("Icons/menu/Add.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuDeleteAction extends AbstractAction {

        public MenuDeleteAction() {
            super("Delete", new ImageIcon("Icons/menu/Delete.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuExtractAction extends AbstractAction {

        public MenuExtractAction() {
            super("Extract", new ImageIcon("Icons/menu/Extract.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            extract();
        }
    }

    class MenuViewAction extends AbstractAction {

        public MenuViewAction() {
            super("View", new ImageIcon("Icons/menu/View.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuSelectAllAction extends AbstractAction {

        public MenuSelectAllAction() {
            super("Select All");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuAllFilesAction extends AbstractAction {

        public MenuAllFilesAction() {
            super("All Files");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuFilesByFolderAction extends AbstractAction {

        public MenuFilesByFolderAction() {
            super("Files By Folder");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuCreateAction extends AbstractAction {

        public MenuCreateAction() {
            super("Create", new ImageIcon("Icons/menu/Create.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuEditAction extends AbstractAction {

        public MenuEditAction() {
            super("Edit", new ImageIcon("Icons/menu/Edit.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuHelpAction extends AbstractAction {

        public MenuHelpAction() {
            super("Help Contents");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            new HelpContents();
        }
    }

    class MenuRunAction extends AbstractAction {

        public MenuRunAction() {
            super("Run", new ImageIcon("Icons/menu/Run.png"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuZipMyDocumentsAction extends AbstractAction {

        public MenuZipMyDocumentsAction() {
            super("Zip My Documents");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuZipAllLibrariesAction extends AbstractAction {

        public MenuZipAllLibrariesAction() {
            super("Zip All Libraries");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuConfigurationAction extends AbstractAction {

        public MenuConfigurationAction() {
            super("Configuration");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            showMessage("This is just a demo!!");
        }
    }

    class MenuAboutAction extends AbstractAction {

        public MenuAboutAction() {
            super("About");
        }

        @Override
        public void actionPerformed(ActionEvent e) {

            aboutDialog();
        }
    }

    // Show the about dialog
    private void aboutDialog() {

        final JDialog dialog = new JDialog(new Frame(), "About", true);
        dialog.setLayout(new BorderLayout());

        JButton ordrInfo = new JButton("Ordering Info");
        JButton showlicense = new JButton("License");
        JButton acknowledge = new JButton("Acknowledgments");
        JButton sysInfo = new JButton("System Info");
        JButton register = new JButton("Register");
        JButton web = new JButton("Web Site");
        JButton faqs = new JButton("FAQs");
        JButton ok = new JButton("OK");
        ok.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //To change body of implemented methods use File | Settings | File Templates.
                dialog.dispose();
            }
        });

        final JPanel bPanel = new JPanel();
        bPanel.setLayout(new GridLayout(8, 1));
        bPanel.add(ordrInfo);
        bPanel.add(showlicense);
        bPanel.add(acknowledge);
        bPanel.add(sysInfo);
        bPanel.add(register);
        bPanel.add(web);
        bPanel.add(faqs);
        bPanel.add(ok);

        //Add the bPanel to the EAST
        dialog.add(bPanel, BorderLayout.EAST);

        Font font = new Font("Dialog", Font.PLAIN, 10);
        JPanel top = new JPanel(new BorderLayout());
        JLabel label1 = new JLabel("JZip 2.0", JLabel.CENTER);

        label1.setFont(font);

        top.add(label1, BorderLayout.NORTH);
        JLabel label2 = new JLabel("<html> Copyright &copy 2002-2016 JZip Computing Inc.</html>", JLabel.CENTER);

        label2.setFont(font);

        top.add(label2);
        JLabel label3 = new JLabel("All Rights reserved", JLabel.CENTER);

        label3.setFont(font);
        JPanel upper = new JPanel(new BorderLayout());

        upper.add(
                new JLabel(new ImageIcon("Icons/JZip.png")), BorderLayout.NORTH);
        upper.add(top, BorderLayout.SOUTH);

        dialog.add(upper, BorderLayout.NORTH);

        JPanel middle = new JPanel(new BorderLayout());
        JLabel msg = new JLabel("<html><body> This is an unregistered copy for evaluation use only. <br>    Please remember that any other use of this <br>  software requires payment of the registration fee. <br>    &nbsp Click 'License' or 'Ordering Info' for details. </body></html>", JLabel.CENTER);

        msg.setFont(font);
        //Add a dummy panel to the TOP and BOTTOM to reduce the height of the Etched middle panel!
        JPanel mTop = new JPanel(new FlowLayout());

        mTop.setPreferredSize(
                new Dimension(288, 56));
        middle.add(mTop, BorderLayout.NORTH);

        middle.add(msg, BorderLayout.CENTER);
        //Add the second dummy panel
        JPanel mBottom = new JPanel(new FlowLayout());

        mBottom.setPreferredSize(
                new Dimension(288, 56));
        middle.add(mBottom, BorderLayout.SOUTH);

        msg.setBorder(
                new EtchedBorder());
        dialog.add(middle, BorderLayout.CENTER);

        JPanel bottom = new JPanel(new BorderLayout());
        JLabel cLabel1 = new JLabel("Contact points are:", JLabel.CENTER);

        cLabel1.setFont(font);

        bottom.add(cLabel1, BorderLayout.NORTH);
        JLabel cLabel2 = new JLabel("Internet www.jzip.com   Email: support@jzip.com", JLabel.CENTER);

        cLabel2.setFont(font);

        bottom.add(cLabel2, BorderLayout.CENTER);
        JLabel cLabel3 = new JLabel("Postal Mail: P. O Box 55, Thippasandra, Bangalore , Karnataka(INDIA)", JLabel.CENTER);

        cLabel3.setFont(font);

        bottom.add(cLabel3, BorderLayout.SOUTH);

        dialog.add(bottom, BorderLayout.SOUTH);

        dialog.setSize(
                500, 450);
        dialog.setLocationRelativeTo(
                null);
        dialog.setVisible(
                true);
    }

    // Get the currently selected file;
    private File getFile() {
        if (file != null) {
            return file;
        }
        return null;
    }

    // Get the current zip file
    private ZipFile getZipFile() {
        if (zipFile != null) {
            return zipFile;
        }
        return null;
    }

    // Extract the zip file to the user selected directory
    public void extract() {

        String separator = System.getProperty("file.separator");
        fileChooser.setDialogTitle("Extract");
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int returnVal = fileChooser.showSaveDialog(JZipDemo.this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File myFile = fileChooser.getSelectedFile();

            String filename = myFile.getPath();
            System.out.println("FileName : " + filename);
            if (filename == null) {
                return;
            }

            //Decompressing a File
            try {
                File inputFile = new File(getFile().toString());
                if (!inputFile.exists()) {
                    showMessage("The specified file doesn't exist!!!");
                }
                //Get the Zip file entries first!
                ZipFile zf = null;
                try {
                    zf = new ZipFile(inputFile);
                } catch (IOException e) {
                }
                Vector<String> vector = new Vector<>();

                for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements();) {
                    vector.addElement(((ZipEntry) entries.nextElement()).getName());
                }
                int MAX = vector.size();
                File[] outputFile = new File[MAX];

                ZipInputStream in = new ZipInputStream(new FileInputStream(inputFile));
                OutputStream out = null;

                ZipEntry entry;
                byte[] buf = new byte[1024];
                int len;
                int i = 0;
                File destinationFile = myFile;
                System.err.println("Destination : " + destinationFile);
                // If the destination directory doesn't exist then create it
                if (!destinationFile.exists()) {
                    destinationFile.mkdir();
                }

                while ((entry = in.getNextEntry()) != null) {
                    if (entry.isDirectory()) {
                        //Create that directory in the destination directory also!
                        File dir = new File(myFile.getAbsolutePath() + separator + entry.getName());
                        dir.mkdir();
                    } else {
                        outputFile[i] = new File(myFile.getAbsolutePath() + separator + entry.getName());
                        setStatus("Extracting : " + entry.getName());
                        out = new FileOutputStream(outputFile[i]);

                        while ((len = in.read(buf)) > 0) {
                            out.write(buf, 0, len);
                        }
                        i++;
                    }
                }
                out.close();
                in.close();

            } catch (IOException ioe) {
                System.err.println("Error decompressing the zip file!");
            }
        }
    }

    // Get the current table
    private JTable getTable() {
        if (table != null) {
            return table;
        }
        return null;
    }

    //Display the information message
    private void showMessage(String message) {
        if (message != null) {
            JOptionPane.showMessageDialog(null, message, "Information", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //To change body of implemented methods use File | Settings | File Templates.
                new JZipDemo();
            }
        });
    }
}
```

This program needs a accessory class HelpContents.java


```
/**
 * Created with IntelliJ IDEA.
 * User: raghu
 * Date: 7/20/16
 * Time: 12:24 PM
 * To change this template use File | Settings | File Templates.
 */
import java.awt.*;
import javax.swing.*;
import java.net.*;
import java.io.*;

public class HelpContents extends JFrame {

    JEditorPane html;
    public HelpContents() {

        try {
            URL url = null;
            // System.getProperty("user.dir") +
            // System.getProperty("file.separator");
            String path = null;
            try {
                path = "/resources/helpcontents.html";
                url = getClass().getResource(path);
            } catch (Exception e) {
                System.err.println("Failed to open " + path);
                url = null;
            }

            if(url != null) {
                html = new JEditorPane(url);
                html.setEditable(false);
                //html.addHyperlinkListener(createHyperLinkListener());

                JScrollPane scroller = new JScrollPane();
                JViewport vp = scroller.getViewport();
                vp.add(html);
                add(scroller, BorderLayout.CENTER);
            }
        } catch (MalformedURLException e) {
            System.out.println("Malformed URL: " + e);
        } catch (IOException e) {
            System.out.println("IOException: " + e);
        }
        setTitle("Help");
        setSize(800, 600);
        setLocation(50, 100);
        setVisible(true);
        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
    }
}
```

It also needs a HTML file called helpconents.html in the 'resources' directory

helpcontents.html


```
What's New
<html lang="en-US">
<body>
<h1>
<b>JZip 14.0</b>
</h1>

<p>
Microsoft Windows 7 is here, and JZip® 14 is ready for it. We're taking advantage of Windows 7's key features, and we've streamlined and improved many of our dialogs and operations to make JZip easier to use and better than ever. We've enhanced security too, by automatically wiping any files that were temporarily extracted from your encrypted Zip files.
<p>
Windows 7 support
Windows 7 includes many significant enhancements that simplify working with documents, folders, and programs. JZip 14 takes full advantage of these new features to make working with your Zip files effortless:
<p>
Libraries
<p>
JZip 14 provides support for Windows 7 libraries. Libraries group together folders with a common theme regardless of where the folders reside. For instance, the Windows 7 Pictures library groups all your separate folders that contain pictures in one convenient place. JZip allows you to create and open Zip files in these convenient, themed libraries, add files from libraries to a Zip file, and extract to libraries. This makes many activities much easier. For example, you can zip all of your pictures, no matter where they are, by simply selecting the Pictures library.
<p>
With the JZip Job Wizard, you can automate zipping of your libraries using jobs that you create or jobs that are provided with JZip 14. Windows 7 also lets you define your own libraries, and you can take advantage of those with JZip. For example, you might create a "Backup" library containing a collection of folders with content that you frequently back up in Zip files. Or you might create an "Archive" library that contains a collection of folders in which you have stored Zip files.
<p>
Jump Lists
<p>
Windows 7 provides easy access to your documents and programs with taskbar icon jump lists. Pin the JZip 14 icon to your taskbar for quick and easy access to frequently used zip features, recently used Zip files, and your favorite JZip jobs. JZip 14 even supports the new taskbar progress meter, which lets you keep an eye on the progress of extensive zip operations right on the taskbar while you work.
<p>
Explorer Preview
<p>
With a simple click in Windows 7 Explorer, you can activate a preview pane, allowing you to view the contents of certain file types. JZip 14 adds Zip files to the list of supported files, so you simply select a Zip file in Explorer and the preview pane shows what's inside your Zip file. See a file in your Zip file that you want to view? Double-click it in the preview pane and your file is extracted and opened. Plus, if you use Outlook 2007, you can now use its preview pane to see the contents of zipped attachments and open files inside an attached Zip file.
<p>
Touch Screens
<p>
JZip 14 fully supports gestures-simple finger movements-on your touch screen PC. Using gestures, you can easily scroll through the contents of your Zip files. And using Windows 7's new multi-touch (two finger) gestures, you can even pan, zoom, and rotate your images in JZip Pro's built-in Image Viewer without touching your keyboard or mouse!
<p>
Common Dialogs and Task Dialogs
<p>
Many JZip dialogs, including the New, Open, Add, and Extract dialogs, have been updated to use the Windows 7 style and to provide new filtering and organizational support for finding your files and archives. New task dialogs provide clear and easy-to-follow instructions throughout JZip 14.
<p>
Security
<p>
A key reason why many users purchase JZip is its powerful, easy-to-use AES encryption. JZip 14 introduces automatic wiping, which helps you to keep your confidential information confidential. To open an encrypted file, JZip must create a temporary copy of the file on your disk. This temporary copy is deleted when you close the file, but, before doing so, JZip 14 "wipes" (or "shreds") it using the U.S. Department of Defense standard (DoD 5220.22-M). This prevents temporarily extracted copies of encrypted files from being recovered. It is safe and simple and secure.
<p>
In addition, JZip 14 recognizes Intel-based computers with built-in AES encryption and uses the available hardware support to make encryption operations two to three times faster.
<p>
Zipping Simplicity
<p>
JZip has always been focused on making compression and encryption as easy as possible. Most operations can be accessed directly with a right click in Windows Explorer. Inside JZip 14, the following updated dialogs for Windows 7 and Vista users provide even more power and simplicity:
<p>
Add
<p>
In the Add dialog you can use the new Organize and Views features to help you find the files, folders, and libraries you want to add to your Zip file. With a few clicks, you can elect to add only specific types of files, such as documents or spreadsheets. You can create your own custom filter to control which files are added and modify other options for how they are added as well.
<p>
Extract
<p>
As in the Add dialog, the Organize and Views features in the Extract dialog allow you to easily navigate and find the libraries or folders to which you want to extract the content of your Zip files. Just pick a folder or library and click Extract; it's as simple as that.
<p>
A list of features introduced in earlier versions of JZip is available from the JZip web site.

<p>
What is an Archive?
<p>
Archives are files that contain other files. Typically the files in an archive are compressed. Archives usually have file names ending with ZIP, ZIPX, LZH, LHA, GZ or CAB, depending on how they were created. Archives make it easy to group files and make transporting and copying these files faster.
<p>
Typical Uses for Archives:
<p>
Most files available on the Internet and on electronic services like America Online are distributed as archives. Two benefits of using archives for electronic file distribution are that only one file transfer operation ("download") is required to obtain all related files and file transfer time is minimized because the files in an archive are compressed.
It is often useful to send a group of related files to an associate. Rather than distributing individual files it is often easier to distribute the files as an archive to benefit from the file grouping and compression.
Some files are important but not used often. To save disk space simply compress these files into an archive when they are not used and decompress them only when needed.
What is a Self-Extracting Zip File?
<p>
A self-extracting Zip file is an executable program file (.EXE file) that includes both a Zip file and software to extract or "unzip" the contents of the Zip file. Users can extract the contents of a self-extracting Zip file by simply running it. This is convenient because the end user does not need an unzip program (like JZip®) to extract files from these self-extracting archives.
<p>
JZip Self-Extractor Personal Edition, included with JZip, creates Windows self-extracting Zip files.
<p>
Archive formats:
<p>
Zip files are the most common archive format. Zip files can span multiple disks and provide both compression and file grouping. Zip files created by JZip can have a .zip or .zipx file extension.
<p>
TAR, Z, GZ, TAZ, and TGZ files are often found on Unix-based Internet sites. TAR stands for "Tape ARchive". The TAR format does not provide compression; it is used only to group files. GZ and Z files
are gzip files. GZ and Z files cannot contain multiple files. TAZ and TGZ files are TAR files compressed in the gzip format. Since almost all new archives are created in Zip format, JZip does not
provide facilities to add to or create files in these formats (however, all other JZip functions are supported).
<p>
File formats such as UUencoded, XXencoded, BinHex, and MIME are used primarily to transfer binary files by Internet e-mail. If you encounter one of these files, you can open it and extract its contents with JZip.
You can UUencode an archive using the UUencode entry in the JZip Actions pull-down menu.
<p>
JZip also handles most files in the old Microsoft Compress format (also known as LZEXPAND format). However, there are several variations on this format, and Microsoft has not released documentation on these variations.
JZip issues an appropriate message if you attempt to decompress a file not supported by your version of Windows. Microsoft Compress files usually end with a trailing underscore, for example, "commdlg.dl_". Like Z and GZ files,
Microsoft Compress format files contain only one file. This format is used for many files on the Windows 3.1 distribution disks and many older Microsoft products. Note that not all files ending with an underscore are Microsoft Compress format files.
The Microsoft CAB (short for Cabinet) format is used by most Microsoft setup programs, including those used to install Windows. CAB files provide both file compression and file grouping. You can use JZip to open and extract the contents of CAB files. JZip will handle most self-extracting CAB files.
<p>
LZH and LHA are older file formats that provide both grouping and compression, like Zip files.
<p>
Files with the .BZ2 extension represent individual files that have been compressed using the bzip2 program typically found on UNIX or Linux systems. Bzip2 is a data compressor and not an archiver. Therefore, .BZ2 files do not contain multiple files. JZip does not provide facilities to create .BZ2 files, but you can use JZip to open and extract the contents of .BZ2 files.
<p>
RAR is a compression and archiving format. The compression technology is proprietary however the decompression technology is not. JZip does not create .rar files, but JZip can view and extract the contents of .rar files.
<p>
7Z is a compression and archiving format. The compression technology is proprietary; however, the decompression technology is publicly available under the GNU Lesser General Public License. JZip does not create .7z files, but JZip can view and extract the contents of .7z files.
<p>
IMG is an archive format used for creating images of disks. The images can then be stored and used to restore the disks. JZip does not create .img files, but it can view and extract the contents of .img files.
<p>
ISO is an archive format that is used to make images of optical disks. These images can be stored and used to replicate the disks. JZip does not create .iso files, but it can view and extract the contents of .iso files.
```

*s4.postimg.org/xnx7ihhx5/JZip_Demo.png

Explanation: 

createStatusBar() - creates the statusbar, createFileChooser() creates the filechooser, getScrollPane() - gets the current scrollpane.
getStatusBar() - gets the current statusbar. createToolBar() method creates a toolbar with buttons (New, Open, Favorites, Add, Extract, Mail, Encrypt, View, CheckOut, Wizard)

createMenuBar() - Create a JMenuBar with file & other menus.

NewAction() - Create a new zip file
OpenAction() - Opens a zip file for viewing its contents
FavoritesAction() - add to the favorites
AddAction() - Add files to the zip file
ExtractAction() - Extract the contents of the zip file to a directory
MailAction() - Send the zip file to the user specified  mail address
EncryptAction() - Encrypt the zip file
WizardAction() - Show a wizard dialog to create a zip file
SaveAsAction() - Saves as another file

createTable() - Converts the zip file contents to table format.
aboutDialog() - Shows a about dialog.
getTable() - Get the current table.


7) Write a program to display the contents of a RDBMS table in a tabular format (using JTable)?


Here is the code!!


```
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author JGuru
 */
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;

/**
 * An adaptor, transforming the JDBC interface to the TableModel interface.
 *
 * @author JGuru
 */
    [MENTION=139512]Sup[/MENTION]pressWarnings("serial")
public class JDBCAdapter extends AbstractTableModel {

    private Connection connection;
    private Statement statement;
    private ResultSet resultSet;
    private String[] columnNames = {};
    private List<List<Object>> rows = new ArrayList<>();
    private ResultSetMetaData metaData;

    public JDBCAdapter(String url, String driverName,
            String user, String passwd) {
        try {
            Class.forName(driverName);
            System.out.println("Opening db connection");

            connection = DriverManager.getConnection(url, user, passwd);
            statement = connection.createStatement();
        } catch (ClassNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Cannot find the database driver classes.", "Error", JOptionPane.WARNING_MESSAGE);

        } catch (SQLException ex) {
            JOptionPane.showMessageDialog(null, "Cannot connect to this database!!", "Error", JOptionPane.WARNING_MESSAGE);
        }
    }

    public void executeQuery(String query) {
        if (connection == null || statement == null) {
            JOptionPane.showMessageDialog(null, "There is no database to execute the query!!", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }
        try {
            resultSet = statement.executeQuery(query);
            metaData = resultSet.getMetaData();

            int numberOfColumns = metaData.getColumnCount();
            columnNames = new String[numberOfColumns];
            // Get the column names and cache them.
            // Then we can close the connection.
            for (int column = 0; column < numberOfColumns; column++) {
                columnNames[column] = metaData.getColumnLabel(column + 1);
            }

            // Get all rows.
            rows = new ArrayList<>();
            while (resultSet.next()) {
                List<Object> newRow = new ArrayList<>();
                for (int i = 1; i <= getColumnCount(); i++) {
                    newRow.add(resultSet.getObject(i));
                }
                rows.add(newRow);
            }
            //  close(); Need to copy the metaData, bug in jdbc:odbc driver.

            // Tell the listeners a new table has arrived.
            fireTableChanged(null);
        } catch (SQLException ex) {
            System.err.println(ex);
        }
    }

    public void close() throws SQLException {
        System.out.println("Closing db connection");
        resultSet.close();
        statement.close();
        connection.close();
    }

    @Override
    protected void finalize() throws Throwable {
        close();
        super.finalize();
    }

    //////////////////////////////////////////////////////////////////////////
    //
    //             Implementation of the TableModel Interface
    //
    //////////////////////////////////////////////////////////////////////////
    // MetaData
    @Override
    public String getColumnName(int column) {
        if (columnNames[column] != null) {
            return columnNames[column];
        } else {
            return "";
        }
    }

    @Override
    public Class<?> getColumnClass(int column) {
        int type;
        try {
            type = metaData.getColumnType(column + 1);
        } catch (SQLException e) {
            return super.getColumnClass(column);
        }

        switch (type) {
            case Types.CHAR:
            case Types.VARCHAR:
            case Types.LONGVARCHAR:
                return String.class;

            case Types.BIT:
                return Boolean.class;

            case Types.TINYINT:
            case Types.SMALLINT:
            case Types.INTEGER:
                return Integer.class;

            case Types.BIGINT:
                return Long.class;

            case Types.FLOAT:
            case Types.DOUBLE:
                return Double.class;

            case Types.DATE:
                return java.sql.Date.class;

            default:
                return Object.class;
        }
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        try {
            return metaData.isWritable(column + 1);
        } catch (SQLException e) {
            return false;
        }
    }

    @Override
    public int getColumnCount() {
        return columnNames.length;
    }

    // Data methods
    @Override
    public int getRowCount() {
        return rows.size();
    }

    @Override
    public Object getValueAt(int aRow, int aColumn) {
        List<Object> row = rows.get(aRow);
        return row.get(aColumn);
    }

    public String dbRepresentation(int column, Object value) {
        int type;

        if (value == null) {
            return "null";
        }

        try {
            type = metaData.getColumnType(column + 1);
        } catch (SQLException e) {
            return value.toString();
        }

        switch (type) {
            case Types.INTEGER:
            case Types.DOUBLE:
            case Types.FLOAT:
                return value.toString();
            case Types.BIT:
                return ((Boolean) value).booleanValue() ? "1" : "0";
            case Types.DATE:
                return value.toString(); // This will need some conversion.
            default:
                return """ + value.toString() + """;
        }

    }

    @Override
    public void setValueAt(Object value, int row, int column) {
        try {
            String tableName = metaData.getTableName(column + 1);
            // Some of the drivers seem buggy, tableName should not be null.
            if (tableName == null) {
                System.out.println("Table name returned null.");
            }
            String columnName = getColumnName(column);
            String query
                    = "update " + tableName + " set " + columnName + " = "
                    + dbRepresentation(column, value) + " where ";
            // We don't have a model of the schema so we don't know the
            // primary keys or which columns to lock on. To demonstrate
            // that editing is possible, we'll just lock on everything.
            for (int col = 0; col < getColumnCount(); col++) {
                String colName = getColumnName(col);
                if (colName.equals("")) {
                    continue;
                }
                if (col != 0) {
                    query = query + " and ";
                }
                query = query + colName + " = " + dbRepresentation(col,
                        getValueAt(row, col));
            }
            System.out.println(query);
            System.out.println("Not sending update to database");
            // statement.executeQuery(query);
        } catch (SQLException e) {
            System.err.println("Update failed");
        }
        List<Object> dataRow = rows.get(row);
        dataRow.set(column, value);

    }
}
```


```
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Sowndar
 */
/**
 * A a UI around the JDBCAdaptor, allowing database data to be interactively
 * fetched, sorted and displayed using Swing.
 *
 * NOTE: This example uses a modal dialog via the static convenience methods in
 * the JOptionPane. Use of modal dialogs requires JDK 1.1.4 or greater.
 *
 * @author Philip Milne
 */
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.BevelBorder;

public final class TableExample implements LayoutManager {

    private static String[] ConnectOptionNames = {"Connect"};
    private static String ConnectTitle = "Connection Information";
    private Dimension origin = new Dimension(0, 0);
    private JButton fetchButton;
    private JButton showConnectionInfoButton;
    private JPanel connectionPanel;
    private JFrame frame; // The query/results window.
    private JLabel userNameLabel;
    private JTextField userNameField;
    private JLabel passwordLabel;
    private JTextField passwordField;
    private JTextArea queryTextArea;
    private JComponent queryAggregate;
    private JLabel serverLabel;
    private JTextField serverField;
    private JLabel driverLabel;
    private JTextField driverField;
    private JPanel mainPanel;
    private TableSorter sorter;
    private JDBCAdapter dataBase;
    private JScrollPane tableAggregate;

    /**
     * Brigs up a JDialog using JOptionPane containing the connectionPanel. If
     * the user clicks on the 'Connect' button the connection is reset.
     */
    void activateConnectionDialog() {
        if (JOptionPane.showOptionDialog(tableAggregate, connectionPanel,
                ConnectTitle,
                JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
                null, ConnectOptionNames, ConnectOptionNames[0]) == 0) {
            connect();
            frame.setVisible(true);
        } else if (!frame.isVisible()) {
            System.exit(0);
        }
    }

    /**
     * Creates the connectionPanel, which will contain all the fields for the
     * connection information.
     */
    public void createConnectionDialog() {
        // Create the labels and text fields.
        userNameLabel = new JLabel("User name: ", JLabel.RIGHT);
        userNameField = new JTextField("app");

        passwordLabel = new JLabel("Password: ", JLabel.RIGHT);
        passwordField = new JTextField("app");

        serverLabel = new JLabel("Database URL: ", JLabel.RIGHT);
        serverField = new JTextField("jdbc:derby://localhost:1527/sample");

        driverLabel = new JLabel("Driver: ", JLabel.RIGHT);
        driverField = new JTextField("org.apache.derby.jdbc.ClientDriver");

        connectionPanel = new JPanel(false);
        connectionPanel.setLayout(new BoxLayout(connectionPanel,
                BoxLayout.X_AXIS));

        JPanel namePanel = new JPanel(false);
        namePanel.setLayout(new GridLayout(0, 1));
        namePanel.add(userNameLabel);
        namePanel.add(passwordLabel);
        namePanel.add(serverLabel);
        namePanel.add(driverLabel);

        JPanel fieldPanel = new JPanel(false);
        fieldPanel.setLayout(new GridLayout(0, 1));
        fieldPanel.add(userNameField);
        fieldPanel.add(passwordField);
        fieldPanel.add(serverField);
        fieldPanel.add(driverField);

        connectionPanel.add(namePanel);
        connectionPanel.add(fieldPanel);
    }

    public TableExample() {
        mainPanel = new JPanel();

        // Create the panel for the connection information
        createConnectionDialog();

        // Create the buttons.
        showConnectionInfoButton = new JButton("Configuration");
        showConnectionInfoButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                activateConnectionDialog();
            }
        });

        fetchButton = new JButton("Fetch");
        fetchButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                fetch();
            }
        });

        // Create the query text area and label.
        queryTextArea = new JTextArea("SELECT * FROM APP.CUSTOMER", 25, 25);
        queryAggregate = new JScrollPane(queryTextArea);
        queryAggregate.setBorder(new BevelBorder(BevelBorder.LOWERED));

        // Create the table.
        tableAggregate = createTable();
        tableAggregate.setBorder(new BevelBorder(BevelBorder.LOWERED));

        // Add all the components to the main panel.
        mainPanel.add(fetchButton);
        mainPanel.add(showConnectionInfoButton);
        mainPanel.add(queryAggregate);
        mainPanel.add(tableAggregate);
        mainPanel.setLayout(this);

        // Create a Frame and put the main panel in it.
        frame = new JFrame("TableExample");
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        frame.setBackground(Color.lightGray);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setVisible(false);
        frame.setBounds(200, 200, 640, 480);

        activateConnectionDialog();
    }

    public void connect() {
        dataBase = new JDBCAdapter(
                serverField.getText(),
                driverField.getText(),
                userNameField.getText(),
                passwordField.getText());
        sorter.setModel(dataBase);
    }

    public void fetch() {
        dataBase.executeQuery(queryTextArea.getText());
    }

    public JScrollPane createTable() {
        sorter = new TableSorter();

        //connect();
        //fetch();
        // Create the table
        JTable table = new JTable(sorter);
        // Use a scrollbar, in case there are many columns.
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        // Install a mouse listener in the TableHeader as the sorter UI.
        sorter.addMouseListenerToHeaderInTable(table);

        JScrollPane scrollpane = new JScrollPane(table);

        return scrollpane;
    }

    public static void main(String s[]) {
        // Trying to set Nimbus look and feel
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException ex) {
            Logger.getLogger(TableExample.class.getName()).log(Level.SEVERE,
                    "Failed to apply Nimbus look and feel", ex);
        }

        new TableExample();
    }

    @Override
    public Dimension preferredLayoutSize(Container c) {
        return origin;
    }

    @Override
    public Dimension minimumLayoutSize(Container c) {
        return origin;
    }

    @Override
    public void addLayoutComponent(String s, Component c) {
    }

    @Override
    public void removeLayoutComponent(Component c) {
    }

    @Override
    public void layoutContainer(Container c) {
        Rectangle b = c.getBounds();
        int topHeight = 90;
        int inset = 4;
        showConnectionInfoButton.setBounds(b.width - 2 * inset - 120, inset, 120,
                25);
        fetchButton.setBounds(b.width - 2 * inset - 120, 60, 120, 25);
        // queryLabel.setBounds(10, 10, 100, 25);
        queryAggregate.setBounds(inset, inset, b.width - 2 * inset - 150, 80);
        tableAggregate.setBounds(new Rectangle(inset,
                inset + topHeight,
                b.width - 2 * inset,
                b.height - 2 * inset - topHeight));
    }
}
```


```
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Sowndar
 */
/**
 * In a chain of data manipulators some behaviour is common. TableMap provides
 * most of this behavour and can be subclassed by filters that only need to
 * override a handful of specific methods. TableMap implements TableModel by
 * routing all requests to its model, and TableModelListener by routing all
 * events to its listeners. Inserting a TableMap which has not been subclassed
 * into a chain of table filters should have no effect.
 *
 * @author Philip Milne
 */
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;

    [MENTION=139512]Sup[/MENTION]pressWarnings("serial")
public class TableMap extends AbstractTableModel implements TableModelListener {

    protected TableModel model;

    public TableModel getModel() {
        return model;
    }

    public void setModel(TableModel model) {
        this.model = model;
        model.addTableModelListener(this);
    }

    // By default, Implement TableModel by forwarding all messages
    // to the model.
    @Override
    public Object getValueAt(int aRow, int aColumn) {
        return model.getValueAt(aRow, aColumn);
    }

    @Override
    public void setValueAt(Object aValue, int aRow, int aColumn) {
        model.setValueAt(aValue, aRow, aColumn);
    }

    @Override
    public int getRowCount() {
        return (model == null) ? 0 : model.getRowCount();
    }

    @Override
    public int getColumnCount() {
        return (model == null) ? 0 : model.getColumnCount();
    }

    @Override
    public String getColumnName(int aColumn) {
        return model.getColumnName(aColumn);
    }

    @Override
    public Class<?> getColumnClass(int aColumn) {
        return model.getColumnClass(aColumn);
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        return model.isCellEditable(row, column);
    }
// Implementation of the TableModelListener interface,
// By default forward all events to all the listeners.

    @Override
    public void tableChanged(TableModelEvent e) {
        fireTableChanged(e);
    }
}
```


```
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Sowndar
 */
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

/**
 * A sorter for TableModels. The sorter has a model (conforming to TableModel)
 * and itself implements TableModel. TableSorter does not store or copy the data
 * in the TableModel, instead it maintains an array of integers which it keeps
 * the same size as the number of rows in its model. When the model changes it
 * notifies the sorter that something has changed eg. "rowsAdded" so that its
 * internal array of integers can be reallocated. As requests are made of the
 * sorter (like getValueAt(row, col) it redirects them to its model via the
 * mapping array. That way the TableSorter appears to hold another copy of the
 * table with the rows in a different order. The sorting algorthm used is stable
 * which means that it does not move around rows when its comparison function
 * returns 0 to denote that they are equivalent.
 *
 * @author Philip Milne
 */
    [MENTION=139512]Sup[/MENTION]pressWarnings("serial")
public final class TableSorter extends TableMap {

    int indexes[];
    List<Integer> sortingColumns = new ArrayList<>();
    boolean ascending = true;
    int compares;

    public TableSorter() {
        indexes = new int[0]; // For consistency.
    }

    public TableSorter(TableModel model) {
        setModel(model);
    }

    @Override
    public void setModel(TableModel model) {
        super.setModel(model);
        reallocateIndexes();
    }

    public int compareRowsByColumn(int row1, int row2, int column) {
        Class<?> type = model.getColumnClass(column);
        TableModel data = model;

        // Check for nulls
        Object o1 = data.getValueAt(row1, column);
        Object o2 = data.getValueAt(row2, column);

        // If both values are null return 0
        if (o1 == null && o2 == null) {
            return 0;
        } else if (o1 == null) { // Define null less than everything.
            return -1;
        } else if (o2 == null) {
            return 1;
        }

        /* We copy all returned values from the getValue call in case
         an optimised model is reusing one object to return many values.
         The Number subclasses in the JDK are immutable and so will not be used
         in this way but other subclasses of Number might want to do this to save
         space and avoid unnecessary heap allocation.
         */
        if (type.getSuperclass() == java.lang.Number.class) {
            Number n1 = (Number) data.getValueAt(row1, column);
            double d1 = n1.doubleValue();
            Number n2 = (Number) data.getValueAt(row2, column);
            double d2 = n2.doubleValue();

            if (d1 < d2) {
                return -1;
            } else if (d1 > d2) {
                return 1;
            } else {
                return 0;
            }
        } else if (type == java.util.Date.class) {
            Date d1 = (Date) data.getValueAt(row1, column);
            long n1 = d1.getTime();
            Date d2 = (Date) data.getValueAt(row2, column);
            long n2 = d2.getTime();

            if (n1 < n2) {
                return -1;
            } else if (n1 > n2) {
                return 1;
            } else {
                return 0;
            }
        } else if (type == String.class) {
            String s1 = (String) data.getValueAt(row1, column);
            String s2 = (String) data.getValueAt(row2, column);
            int result = s1.compareTo(s2);

            if (result < 0) {
                return -1;
            } else if (result > 0) {
                return 1;
            } else {
                return 0;
            }
        } else if (type == Boolean.class) {
            Boolean bool1 = (Boolean) data.getValueAt(row1, column);
            boolean b1 = bool1.booleanValue();
            Boolean bool2 = (Boolean) data.getValueAt(row2, column);
            boolean b2 = bool2.booleanValue();

            if (b1 == b2) {
                return 0;
            } else if (b1) // Define false < true
            {
                return 1;
            } else {
                return -1;
            }
        } else {
            Object v1 = data.getValueAt(row1, column);
            String s1 = v1.toString();
            Object v2 = data.getValueAt(row2, column);
            String s2 = v2.toString();
            int result = s1.compareTo(s2);

            if (result < 0) {
                return -1;
            } else if (result > 0) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public int compare(int row1, int row2) {
        compares++;
        for (int level = 0; level < sortingColumns.size(); level++) {
            Integer column = sortingColumns.get(level);
            int result = compareRowsByColumn(row1, row2, column.intValue());
            if (result != 0) {
                return ascending ? result : -result;
            }
        }
        return 0;
    }

    public void reallocateIndexes() {
        int rowCount = model.getRowCount();

        // Set up a new array of indexes with the right number of elements
        // for the new data model.
        indexes = new int[rowCount];

        // Initialise with the identity mapping.
        for (int row = 0; row < rowCount; row++) {
            indexes[row] = row;
        }
    }

    @Override
    public void tableChanged(TableModelEvent e) {
        System.out.println("Sorter: tableChanged");
        reallocateIndexes();

        super.tableChanged(e);
    }

    public void checkModel() {
        if (indexes.length != model.getRowCount()) {
            System.err.println("Sorter not informed of a change in model.");
        }
    }

    public void sort(Object sender) {
        checkModel();

        compares = 0;
        // n2sort();
        // qsort(0, indexes.length-1);
        shuttlesort(indexes.clone(), indexes, 0, indexes.length);
        System.out.println("Compares: " + compares);
    }

    public void n2sort() {
        for (int i = 0; i < getRowCount(); i++) {
            for (int j = i + 1; j < getRowCount(); j++) {
                if (compare(indexes[i], indexes[j]) == -1) {
                    swap(i, j);
                }
            }
        }
    }

    // This is a home-grown implementation which we have not had time
    // to research - it may perform poorly in some circumstances. It
    // requires twice the space of an in-place algorithm and makes
    // NlogN assigments shuttling the values between the two
    // arrays. The number of compares appears to vary between N-1 and
    // NlogN depending on the initial order but the main reason for
    // using it here is that, unlike qsort, it is stable.
    public void shuttlesort(int from[], int to[], int low, int high) {
        if (high - low < 2) {
            return;
        }
        int middle = (low + high) / 2;
        shuttlesort(to, from, low, middle);
        shuttlesort(to, from, middle, high);

        int p = low;
        int q = middle;

        /* This is an optional short-cut; at each recursive call,
         check to see if the elements in this subset are already
         ordered.  If so, no further comparisons are needed; the
         sub-array can just be copied.  The array must be copied rather
         than assigned otherwise sister calls in the recursion might
         get out of sinc.  When the number of elements is three they
         are partitioned so that the first set, [low, mid), has one
         element and and the second, [mid, high), has two. We skip the
         optimisation when the number of elements is three or less as
         the first compare in the normal merge will produce the same
         sequence of steps. This optimisation seems to be worthwhile
         for partially ordered lists but some analysis is needed to
         find out how the performance drops to Nlog(N) as the initial
         order diminishes - it may drop very quickly.  */
        if (high - low >= 4 && compare(from[middle - 1], from[middle]) <= 0) {
            System.arraycopy(from, low, to, low, high - low);
            return;
        }

        // A normal merge.
        for (int i = low; i < high; i++) {
            if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
                to[i] = from[p++];
            } else {
                to[i] = from[q++];
            }
        }
    }

    public void swap(int i, int j) {
        int tmp = indexes[i];
        indexes[i] = indexes[j];
        indexes[j] = tmp;
    }

    // The mapping only affects the contents of the data rows.
    // Pass all requests to these rows through the mapping array: "indexes".
    @Override
    public Object getValueAt(int aRow, int aColumn) {
        checkModel();
        return model.getValueAt(indexes[aRow], aColumn);
    }

    @Override
    public void setValueAt(Object aValue, int aRow, int aColumn) {
        checkModel();
        model.setValueAt(aValue, indexes[aRow], aColumn);
    }

    public void sortByColumn(int column) {
        sortByColumn(column, true);
    }

    public void sortByColumn(int column, boolean ascending) {
        this.ascending = ascending;
        sortingColumns.clear();
        sortingColumns.add(column);
        sort(this);
        super.tableChanged(new TableModelEvent(this));
    }

    // There is no-where else to put this.
    // Add a mouse listener to the Table to trigger a table sort
    // when a column heading is clicked in the JTable.
    public void addMouseListenerToHeaderInTable(JTable table) {
        final TableSorter sorter = this;
        final JTable tableView = table;
        tableView.setColumnSelectionAllowed(false);
        MouseAdapter listMouseListener = new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                TableColumnModel columnModel = tableView.getColumnModel();
                int viewColumn = columnModel.getColumnIndexAtX(e.getX());
                int column = tableView.convertColumnIndexToModel(viewColumn);
                if (e.getClickCount() == 1 && column != -1) {
                    System.out.println("Sorting ...");
                    int shiftPressed = e.getModifiers() & InputEvent.SHIFT_MASK;
                    boolean ascending = (shiftPressed == 0);
                    sorter.sortByColumn(column, ascending);
                }
            }
        };
        JTableHeader th = tableView.getTableHeader();
        th.addMouseListener(listMouseListener);
    }
}
```

*s4.postimg.org/x1blfjq2x/Table_Example.png

You need 4 files JDBCAdapter.java , TableExample.java, TableMap.java, TableSorter.java
for this program to work!!

8) Write a program to show a simple text editor in Java?

Ans) Here is the solution!!


```
/**
 * Created with IntelliJ IDEA. User: raghu Date: 7/20/16 Time: 8:11 PM To change
 * this template use File | Settings | File Templates.
 */
/**
 * Created with IntelliJ IDEA. User: raghu Date: 7/14/16 Time: 8:04 PM To change
 * this template use File | Settings | File Templates.
 */
// TextEditor.java
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.awt.print.PrinterException;
import java.io.*;
import java.util.Hashtable;
import javax.swing.*;
import javax.swing.filechooser.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.*;

// An example showing several DefaultEditorKit features. This class is designed
// to be easily extended to add additional functionality.
public class TextEditor extends JFrame {

    JFileChooser fileChooser;
    File file;
    // Create an editor

    public TextEditor() {
        super("TextEditor");
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            // Do nothing
        }
        textComp = createTextComponent();
        createFileChooser();

        hashDefaultActions();
        makeActionsPretty();
        updateKeymap();
        Container content = getContentPane();
        JScrollPane scroll = new JScrollPane(textComp);
        content.add(scroll, BorderLayout.CENTER);
        content.add(createToolBar(), BorderLayout.NORTH);

        setJMenuBar(createMenuBar());
        setSize(Toolkit.getDefaultToolkit().getScreenSize());
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    // Create the JTextComponent subclass.
    protected JTextComponent createTextComponent() {
        JTextArea ta = new JTextArea("", 15, 35);
        ta.setLineWrap(false); // no line wrapping.
        return ta;
    }

    // Get all of the actions defined for our text component. Hash each one by name
    // so we can look for it later.
    protected void hashDefaultActions() {
        Action[] actions = textComp.getActions();
        for (int i = 0; i < actions.length; i++) {
            String name = (String) actions[i].getValue(Action.NAME);
            actionHash.put(name, actions[i]);
        }
    }

    public void createFileChooser() {
        fileChooser = new JFileChooser(".");
        fileChooser.setAcceptAllFileFilterUsed(false);
        fileChooser.addChoosableFileFilter(new FileFilter() {
            @Override
            public boolean accept(File file) {
                String fileName = file.getName();
                if (fileName.endsWith("java") || fileName.endsWith("txt") || file.isDirectory()) {
                    return true;
                }
                return false;
            }

            @Override
            public String getDescription() {
                return "Text Filter";  //To change body of implemented methods use File | Settings | File Templates.
            }
        });
    }

    // Get an action by name
    protected Action getHashedAction(String name) {
        return (Action) actionHash.get(name);
    }

    // Add icons and friendly names to actions we care about
    protected void makeActionsPretty() {

        Action a;
        a = getHashedAction(DefaultEditorKit.cutAction);
        a.putValue(Action.SMALL_ICON, new ImageIcon("icons/cut.gif"));
        a.putValue(Action.NAME, "Cut");
        // Show ToolTip
        a.putValue(Action.SHORT_DESCRIPTION, "Cut");

        a = getHashedAction(DefaultEditorKit.copyAction);
        a.putValue(Action.SMALL_ICON, new ImageIcon("icons/copy.gif"));
        a.putValue(Action.NAME, "Copy");
        // Show ToolTip
        a.putValue(Action.SHORT_DESCRIPTION, "Copy");

        a = getHashedAction(DefaultEditorKit.pasteAction);
        a.putValue(Action.SMALL_ICON, new ImageIcon("icons/paste.gif"));
        a.putValue(Action.NAME, "Paste");
        // Show ToolTip
        a.putValue(Action.SHORT_DESCRIPTION, "Paste");

        a = getHashedAction(DefaultEditorKit.selectAllAction);
        a.putValue(Action.NAME, "Select All");
        // Show ToolTip
        a.putValue(Action.SHORT_DESCRIPTION, "Select All");
    }

    // Add some key->Action mappings
    protected void updateKeymap() {

        // Create a new child Keymap
        Keymap map = JTextComponent.addKeymap("NextPrevMap",
                textComp.getKeymap());

        // Define the keystrokes to be added
        KeyStroke next = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,
                InputEvent.CTRL_MASK, false);
        KeyStroke prev = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,
                InputEvent.CTRL_MASK, false);
        KeyStroke selNext = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,
                InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK, false);
        KeyStroke selPrev = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,
                InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK, false);

        // Add the new mappings used DefaultEditorKit actions
        map.addActionForKeyStroke(next, getHashedAction(
                DefaultEditorKit.nextWordAction));
        map.addActionForKeyStroke(prev, getHashedAction(
                DefaultEditorKit.previousWordAction));
        map.addActionForKeyStroke(selNext, getHashedAction(
                DefaultEditorKit.selectionNextWordAction));
        map.addActionForKeyStroke(selPrev, getHashedAction(
                DefaultEditorKit.selectionPreviousWordAction));

        // Set the Keymap for the text component
        textComp.setKeymap(map);
    }

    // Create a simple JToolBar with some buttons
    protected JToolBar createToolBar() {
        JToolBar bar = new JToolBar();

        // Add simple actions for opening & saving
        bar.add(getOpenAction()).setText("");
        bar.add(getSaveAction()).setText("");
        bar.add(getSaveAsAction()).setText("");
        bar.add(getPrintAction()).setText("");
        bar.addSeparator();

        // Add cut/copy/paste buttons
        bar.add(getHashedAction(DefaultEditorKit.cutAction)).setText("");
        bar.add(getHashedAction(DefaultEditorKit.copyAction)).setText("");
        bar.add(getHashedAction(DefaultEditorKit.pasteAction)).setText("");
        return bar;
    }

    // Create a JMenuBar with file & edit menus
    protected JMenuBar createMenuBar() {
        JMenuBar menubar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenu edit = new JMenu("Edit");
        menubar.add(fileMenu);
        menubar.add(edit);

        fileMenu.add(getOpenAction());
        fileMenu.add(getSaveAction());
        fileMenu.add(getSaveAsAction());
        fileMenu.add(getPrintAction());
        fileMenu.add(new ExitAction());
        edit.add(getHashedAction(DefaultEditorKit.cutAction));
        edit.add(getHashedAction(DefaultEditorKit.copyAction));
        edit.add(getHashedAction(DefaultEditorKit.pasteAction));
        edit.add(getHashedAction(DefaultEditorKit.selectAllAction));
        return menubar;
    }

    // Subclass can override to use a different open action
    protected Action getOpenAction() {
        return openAction;
    }

    // Subclass can override to use a different save action
    protected Action getSaveAction() {
        return saveAction;
    }

    // Subclass can override to use a different save action
    protected Action getSaveAsAction() {
        return saveAsAction;
    }

    // Subclass can override to use a different save action
    protected Action getPrintAction() {
        return printAction;
    }

    protected JTextComponent getTextComponent() {
        return textComp;
    }

    private Action openAction = new OpenAction();
    private Action saveAction = new SaveAction();
    private Action saveAsAction = new SaveAsAction();
    private Action printAction = new PrintAction();

    private JTextComponent textComp;

    private Hashtable<String, Action> actionHash = new Hashtable<>();

    // ********** ACTION INNER CLASSES ********** //
    // A very simple "exit" action
    class ExitAction extends AbstractAction {

        public ExitAction() {
            super("Exit", new ImageIcon("icons/Close.png"));
            putValue(Action.SHORT_DESCRIPTION, "Exit Application");
        }

        @Override
        public void actionPerformed(ActionEvent ev) {
            System.exit(0);
        }
    }

    // An action that opens an existing file
    class OpenAction extends AbstractAction {

        public OpenAction() {
            super("Open", new ImageIcon("icons/open.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Open File");
        }

        // Query user for a filename and attempt to open and read the file into the
        // text component
        @Override
        public void actionPerformed(ActionEvent ev) {

            int returnVal = fileChooser.showOpenDialog(TextEditor.this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                file = fileChooser.getSelectedFile();

                String filename = file.getPath();
                if (filename == null) {
                    return;
                }
                FileReader reader = null;

                try {
                    reader = new FileReader(filename);
                    textComp.read(reader, null);

                } catch (IOException ex) {
                    showMessage("File Not Found!!!", "Error", JOptionPane.ERROR_MESSAGE);
                } finally {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (IOException x) {
                        }
                    }
                }
            }

        }
    }

    // An action that saves the document to a file
    class SaveAction extends AbstractAction {

        public SaveAction() {
            super("Save", new ImageIcon("icons/save.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Save File");
        }

        // Query user for a filename and attempt to open and write the text
        // component's content to the file
        @Override
        public void actionPerformed(ActionEvent ev) {
            if (getFile() != null) {
                String filename = getFile().getPath();
                if (filename == null) {
                    return;
                } else {
                    FileWriter writer = null;
                    try {
                        writer = new FileWriter(filename);
                        textComp.write(writer);
                    } catch (IOException ex) {
                        showMessage("File Not Saved!!!", "Error", JOptionPane.ERROR_MESSAGE);
                    } finally {
                        if (writer != null) {
                            try {
                                writer.close();
                            } catch (IOException x) {
                            }
                        }
                    }
                }
            } else {
                showMessage("No File open yet!!!", "Information", JOptionPane.INFORMATION_MESSAGE);
            }

        }
    }

    // An action that saves the document to another new file
    class SaveAsAction extends AbstractAction {

        public SaveAsAction() {
            super("SaveAs", new ImageIcon("icons/saveas.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Save As Another File");
        }

        // Query user for a filename and attempt to open and write the text
        // component's content to the file
        @Override
        public void actionPerformed(ActionEvent ev) {
            int returnVal = fileChooser.showSaveDialog(TextEditor.this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fileChooser.getSelectedFile();
                // Check whether the file with the same name already exists in the selected directory?
                if (file.exists()) {
                    int value = JOptionPane.showConfirmDialog(
                            null, "A File with the same name exists!!! Do you want to overwrite it?", "Confirm",
                            JOptionPane.YES_NO_OPTION);

                    if (value == JOptionPane.YES_OPTION) {
                        if (file != null) {
                            // Overwrite the existing file!!
                            String filename = file.getPath();
                            if (filename == null) {
                                return;
                            }

                            FileWriter writer = null;
                            try {
                                writer = new FileWriter(filename);
                                textComp.write(writer);
                            } catch (IOException ex) {
                                showMessage("File Not Saved!!!", "Error", JOptionPane.ERROR_MESSAGE);

                            } finally {
                                if (writer != null) {
                                    try {
                                        writer.close();
                                    } catch (IOException x) {
                                    }
                                }
                            }
                        } else {
                            showMessage("No File Open Yet!!!", "Information", JOptionPane.INFORMATION_MESSAGE);
                        }

                    } else {
                        getSaveAsAction();
                    }

                } else {
                    String filename = getFile().getPath();
                    if (filename == null) {
                        return;
                    } else {
                        FileWriter writer = null;
                        try {
                            writer = new FileWriter(filename);
                            textComp.write(writer);
                        } catch (IOException ex) {
                            showMessage("File Not Saved!!", "Error", JOptionPane.ERROR_MESSAGE);

                        } finally {
                            if (writer != null) {
                                try {
                                    writer.close();
                                } catch (IOException x) {
                                }
                            }
                        }
                    }

                }
            }
        }
    }

    // An action that prints the document
    class PrintAction extends AbstractAction {

        public PrintAction() {
            super("Print", new ImageIcon("icons/print.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Print File");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //To change body of implemented methods use File | Settings | File Templates.
            if (getFile() != null) {
                try {
                    textComp.print();
                } catch (PrinterException e1) {
                    showMessage("Error Printing File!!", "Error", JOptionPane.ERROR_MESSAGE);
                }
            } else {
                showMessage("No File Open Yet!!!", "Information", JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }

    // Get the currently open file
    private File getFile() {
        if (file != null) {
            return file;
        }
        return null;
    }

    public void showMessage(String message, String title, int messageType) {
        JOptionPane.showMessageDialog(null, message, title, messageType);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TextEditor();
            }
        });
    }
}
```

*s4.postimg.org/3mrqxp7ux/Text_Editor.png

Note: You need to create a directory called 'icons' and place the icons image files like open.gif, 
save.gif, saveas.gif, print.gif, cut.gif, copy.gif, paste.gif etc..,

A simple Text editor. 
hashDefaultActions() - adds the hashMap for this Component.
createFileChooser() - creates a filechooser dialog
makeActionsPretty() - Add icons and friendly names to actions
updateKeymap() - Add some key->Action mappings

createToolBar() - creates a toolbar with open, save, saveAs, print, cut, copy, paste 
createMenuBar() - creates a menubar with file & edit menus

OpenAction() - Open a text file
SaveAction() - Saves the file to the disk
SaveAsAction() - Saves the current file with a different name
PrintAction() - Prints the text file


*Better Books for Better Programming*

  1) Head First Design Patterns

  2) Head First Object oriented Analysis And Design

  3) Design Patterns : Elements of Reusable Object-Oriented Software

  4) Software Architecture Design Patterns in Java

  5) Core J2EE Patterns: Best Preactices & Design Strategies

  6) Real World Java EE Patterns by Adam Bien

  7) Java Developers Almanac 1.4 4/e (2 volumes)

  8) Pro Java 8 Programming by Brett Spell

  9) Graphic Java 2 :  Mastering the JFC by Geary 3/e Volume 2

  10) Core Swing : Advanced Programming by Kim Topley


  This wraps up this tutorial on Software development & Engineering. Hope you guys find it useful.


----------



## anirbandd (Aug 17, 2016)

you are just copy pasting codes. 

is this some kind of tutorial?


----------



## RCuber (Aug 17, 2016)

[MENTION=10170]JGuru[/MENTION] I would recommend you to use a online repository like GitHub to upload your projects/Snippets and share the link as it would be much easier for people to pull the source code.

BTW Thanks for sharing


----------



## anirbandd (Aug 17, 2016)

my point is, if you are not explaining things, what is the point of posting "Introduction to Software Enginnering & Development using Java"?

staggering number of codes for java is already available online.


----------



## nisargshah95 (Aug 30, 2016)

anirbandd said:


> my point is, if you are not explaining things, what is the point of posting "Introduction to Software Enginnering & Development using Java"?
> 
> staggering number of codes for java is already available online.


Agree. IMO, this is a poor way to teach software engineering. I would suggest better get a good book on software engineering. Wikibooks has one which is available for free. Look up Google and do some digging.


----------



## JGuru (Aug 31, 2016)

Sorry for the little delay. This is a tutorial for writing Java projects using Java Swing!!
Here are lots of books available. But I want to show how a good Java Swing project with Source Code.
I hope this serves the purpose well enough!!!


----------

