# Java Development Made Easy!!: Step-by-step Guide



## JGuru (Apr 25, 2018)

Writing great software is not that difficult!!! If you are a budding programmer then surely programming will look like daunting task!!!
 Here in this tutorial I'm going to show you how easy it is to write software, once you master the basics.

 The Basics are as follows:

 1. Master Core Java API
 2. Learn OOPS (Object Oriented Programming System
 3. Learn problem solving logic - logical reasoning
 4. design patterns - how to design a software program

 You need atleast Java 8 or higher to run these programs. Also configure the IDE for Java 8.
 You should be familiar with the new Java 8 features like lambda expressions, foreach method etc.,
 Let's get started!!!


 Lets look at how a program is written in Java.


```
import java.io.File;

public class SampleApp {

    // Variables declaration goes here
    private File file;
    private String filename;

    public SampleApp(){

    }

    // public methods also called functions in C/C++

    //opens the file for processing
    public void open(){

    }
    // saves the file to the disk, overwrites the current file
    public void save(){

    }
    // saves the file with a different name or under other directory
    public void saveAs(){

    }
    // prints the file
    public void print(){

    }
    // exits the application
    public void exit(){

    }

    public static void main(String[] args) {
        new SampleApp();
    }
}
```

 The SampleApp has 5 functions or methods called open(), save(), saveAs(), print(), exit(). This called the skeleton code. You must write the skeleton code first.

 You can also write the same program as follows:


```
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.File;

public class SampleApp {

    // Variables declaration goes here
    private File file;
    private String filename;

    public SampleApp(){

    }

    // AbstractAction - defines the action for a specific Component.
    //This class provides default implementations for the JFC Action interface. Standard behaviors like the get and set methods for Action
    // object properties (icon, text, and enabled) are defined here. The developer need only subclass this abstract class and define the
    // actionPerformed method.

    //opens the file for processing
    class OpenAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {

        }
    }
    // saves the file to the disk, overwrites the current file
    class SaveAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {

        }
    }

    // saves the file with a different name or under other directory
    class SaveAsAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {

        }
    }

    // prints the file
    class PrintAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {

        }
    }

    // exits the application
    class ExitAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {

        }
    }


    public static void main(String[] args) {
        new SampleApp();
    }
}
```

 This program written in Java style where you define an action for specific Components - buttons in this case.
 So the objective is to understand how to write a program. You define functions or methods , more utility classes for your application.

 You need icons (small images used by the programs) for almost all the programs you can download the JIDE Demo icons from here : *www.jidesoft.com/products/1.4/jide_demo.zip

 Unzip the jar file to directory (search for png, gif, jpg files). You can use them for your programs!!!
 These icons are needed for the programs to run!!!!

 For the program to run you must create a directory called 'Icons' under the Source (src) directory and place the required icons there!!
If the icons are not found , then the program won't run!!!

the icons are loaded from the Jar file using getIcon() method.


1. Write a program to download the resource from a url and also display its progress?
 The resource can be anything like a image, zip file, mp3, mp4, video etc.,

 Downloader.java


```
/*
 * 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.
 */

import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.*;
import java.net.*;
import javax.swing.*;

// The signed long has a minimum value of -2^63 and a maximum value of 2^63-1.
// Bug fixed : changed the fileSize bytesRead from int to long!!!

/*  Sample urls to download!!!

    *download.netbeans.org/netbeans/8.2/final/bundles/netbeans-8.2-linux.sh

    *ftp.kaist.ac.kr/eclipse/technology/epp/downloads/release/neon/2/eclipse-java-neon-2-win32.zip

    *download-cf.jetbrains.com/idea/ideaIC-2018.1.1.tar.gz
 */

class Downloader extends JFrame implements Runnable {

    private URL downloadURL;
    private InputStream inputStream;
    private OutputStream outputStream;
    private byte[] buffer;
    private long fileSize = 0;
    private long bytesRead;
    private JTextField urlTextField;
    private JLabel sizeLabel;
    private JLabel completeLabel;
    private JProgressBar progressBar;
    private final static int BUFFER_SIZE = 1024;
    private boolean isStopped = false;
    private Thread thread;
    private final Font font = new Font("Serif", Font.PLAIN, 12);

    private Downloader() {

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ignored) {
            // Do nothing
        }
        thread = new Thread(this);
        buildLayout();
        Dimension scrDim = Toolkit.getDefaultToolkit().getScreenSize();
        setSize(scrDim.width / 2, scrDim.height / 2);
        setTitle("Downloader");
        setResizable(false);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private 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((ActionEvent e) -> {

            try {
                urlTextField.setEnabled(false);
                downloadURL = new URL(urlTextField.getText());
                //Start the thread
                thread.start();
            } catch (MalformedURLException e1) {
                JOptionPane.showMessageDialog(null, "Not a valid URL!!", "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        add(urlTextField, gbc);

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

        gbc.gridwidth = 1;
        completeLabel = new JLabel(Integer.toString((int)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(Long.toString(fileSize));
        add(sizeLabel, gbc);
    }

    @Override
    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);
    }

    private void performDownload() throws IOException {
        // Store (write data) it in the current directory
        outputStream = new FileOutputStream(getFileName(downloadURL));
        bytesRead = 0;
        URLConnection urlConnection = downloadURL.openConnection();
        // Get the file size of the url resource
        fileSize = urlConnection.getContentLengthLong();
        sizeLabel.setText(Long.toString(toMB(fileSize)) + " MB");
        // If the file doesn't exists returns -1 !!!
        if (fileSize == -1) {

            JOptionPane.showMessageDialog(null, "Not a valid URL!!", "Error", JOptionPane.ERROR_MESSAGE);
            urlTextField.setEnabled(true);
            progressBar.setValue(0);
            completeLabel.setText("0");
            urlTextField.selectAll();
        }
        inputStream = new BufferedInputStream(
                urlConnection.getInputStream());
        buffer = new byte[BUFFER_SIZE];
        int byteCount;
        while ((bytesRead < fileSize) && (!isStopped)) {
            try {
                // Read bytes from the InputStream
                byteCount = inputStream.read(buffer);
                if (byteCount == -1) {
                    isStopped = true;
                    break;
                } else {
                    outputStream.write(buffer, 0, byteCount);
                    bytesRead += byteCount;
                    progressBar.setValue((int)((bytesRead * 100) / fileSize));
                    completeLabel.setText(Long.toString(toMB(bytesRead)) + " MB");
                }
            } catch (IOException ioe) {
                isStopped = true;
                JOptionPane.showMessageDialog(this,
                        ioe.getMessage(),
                        "I/O Error",
                        JOptionPane.ERROR_MESSAGE);
                break;
            }
        }
        try {
            // Close the input/output streams
            outputStream.close();
            inputStream.close();
        } catch (IOException ignored) {
        }
        urlTextField.setEnabled(true);
        // In case the user wants to fetch from another URL
        thread = null;
        thread = new Thread(this);
    }
    // Converts bytes to MB !!
    private long toMB(long bytes){
        return bytes/1000000;
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(Downloader::new);
    }
}
```

ScreenShot : Imgur

 Run the program , enter a url in the textfield , press the Enter key.
 The program will fetch the resource from the url and display its progress.

 Explanation :

 How the program works:

 buildLayout() - build the UI of the program

 getFileName(Url url) - Gets the filename paortion of the url

 performDownload() - downloads the url resource from the Web

 toMB(long bytes) - converts the bytes to MB.

 We implement the Runnable interface , so that this task can be performed in a separate Thread.

 Any long running task must execute in a separate Thread.

 we use the OutputStream class to write the data (bytes read) to the disk.

 progressbar is used to display the download progress.

 we use the URLConnection class to connect to a particular url and fetch it.
 getContentLengthLong() returns the file size and is stored in variable fileSize.

 we use the InputStream class to read data (bytes) from the url

 A while loop is used to loop until bytesRead < fileSize.

 byteCount - read bytes from the inputstream

 bytesRead = bytesRead + byteCount.

 We update the progressbar value in the loop, to show the current progress.

 isStopped is a flag variable used to exit the loop under some conditions.
 Like for eg ., if the url doesn't exists!!!, then fileSize returns -1.
 In that case exit the loop.


----------



## JGuru (Apr 25, 2018)

2. Write a program to show a download manager in action?


```
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.net.URL;
import java.util.Observable;
import java.util.Observer;

// The Download Manager.
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.
    private 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);
        setVisible(true);
    }

    // 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(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(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(e -> PauseAction());
        pauseButton.setEnabled(false);
        buttonsPanel.add(pauseButton);
        resumeButton = new JButton("Resume");
        resumeButton.addActionListener(e -> ResumeAction());
        resumeButton.setEnabled(false);
        buttonsPanel.add(resumeButton);
        cancelButton = new JButton("Cancel");
        cancelButton.addActionListener(e -> CancelAction());
        cancelButton.setEnabled(false);
        buttonsPanel.add(cancelButton);
        clearButton = new JButton("Clear");
        clearButton.addActionListener(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(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(this::updateButtons);
    }

    // Run the Download Manager.
    public static void main(String[] args) {
        SwingUtilities.invokeLater(DownloadManager::new);
    }
}
```

ScreenShot : Imgur

 textfield to enter the url

 add button - to perform the download action

 pause button - to pause the download

 resume button - to resume the download

 cancel button - to cancel the download

 clear button - to clear the contents

 The user can go on entering the urls , press the 'Add' button, the url resources will be downloaded parallely.

 This program also needs the following classes

 ProgressRenderer - To render progress in a JTable

 DownloadsTableModel - a table model to display Url, Size, progress, and status.

 Download class - performs the actual download

 We implement the Runnable interface since we must use a separate Thread to perform the download.

 getUrl() - returns the url resource

 getSize() - returns the size of the url resource

 getProgress() - returns the current progress of the download

 getStatus() - returns the current status of the download

 download() - performs the actual download

 run() method - performs the actual download. The program connects to a url.
 fetches the bytes of data and writes it to the disk.

 ProgressRenderer.java


```
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import java.awt.*;

// 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;
    }
}
```

 DownloadsTableModel.java


```
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

// 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 final ArrayList<Download> downloadList = new ArrayList<>();

    // 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 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);
    }
}
```

 Download.java


```
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Observable;

// This class downloads a file from a URL.
@SuppressWarnings({"ALL", "deprecation"})
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;
    private static final int COMPLETE = 2;
    private static final int CANCELLED = 3;
    public static final int ERROR = 4;

    private final 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 ignored) {
                }
            }

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

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


----------



## JGuru (Apr 25, 2018)

3) Write a program to view an image and also perform various operations like rotateLeft, rotateRight, flip horizontal, flip vertical, save , print etc., ?


```
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: JGuru
 *  Date: 4/21/18 Time: 1:11 PM To change
 * this template use File | Settings | File Templates.
 */
class ImageViewer extends JFrame implements Printable {

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

    private ImageViewer() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception 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
    @Override
    public int print(Graphics g, PageFormat pf, int page) {

        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() {
        return (image != null)? image : null;
    }

    // Create a JMenuBar with file & edit menus
    private 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));
        }
    }

    private 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 (String aFormat : format) {
                    // Show directory & images files only
                    if (fileName.endsWith(aFormat) || file.isDirectory()) {
                        return true;
                    }
                }
                return false;
            }

            // Show something like "*.jpg,*.jpeg,*.bmp,*.tiff,*.gif,*.jpeg2000" etc.,
            @Override
            public String getDescription() {
                StringBuilder str = new StringBuilder();
                for (String aFormat : format) {
                    str.append("*.").append(aFormat).append(",");
                }
                return str.toString();
            }
        });
    }

    // Create a simple JToolBar with some buttons
    private 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;
    }

    private ImageIcon getIcon(String iconName){
        return new ImageIcon(getClass().getResource("Icons/" + iconName));
    }

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

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

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

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

    private Action getRotateLeftAction() {
        return rotateLeftAction;
    }

    private Action getRotateRightAction() {
        return rotateRightAction;
    }

    private Action getFlipHorizontalAction() {
        return flipHorizontalAction;
    }

    private Action getFlipVerticalAction() {
        return flipVerticalAction;
    }

    private Action getExitAction() {
        return exitAction;
    }

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

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

        ExitAction() {
            super("Exit", getIcon("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 {

        OpenAction() {
            super("Open", getIcon("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 {

        SaveAction() {
            super("Save", getIcon("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!!");
            }
        }
    }
    // An action that saves the document to a file

    class SaveAsAction extends AbstractAction {

        SaveAsAction() {
            super("Save As", getIcon("saveas.png"));
            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!!");
            }
        }
    }

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

        PrintAction() {
            super("Print", getIcon("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!!");
            }
        }
    }

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

        RotateLeftAction() {
            super("Rotate Left", getIcon("rotateleft.gif"));
            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 {

        RotateRightAction() {
            super("Rotate Right", getIcon("rotateright.gif"));
            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 {

        FlipHorizontalAction() {
            super("Flip Horizontal", getIcon("fliphoriz.gif"));
            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 {

        FlipVerticalAction() {
            super("Flip Vertical", getIcon("flipvert.gif"));
            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
    private 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
    private 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
    private void showMessage(String message) {
        JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE);
    }

    // Get supported Image formats (remove duplicate entries)
    private 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() {
        return (imageLabel != null) ? imageLabel : null;
    }

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

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

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

    public static void main(String[] args) {
        SwingUtilities.invokeLater(ImageViewer::new);
    }
}
```

ScreenShot : Imgur

 This program also needs an accessory class ImagePreview.java

 Explanation :

 How the program works:

 createMenuBar() - creates the menubar for this program

 createLabel() - creates the label to display the image

 createStatusBar() - creates the statusbar

 OpenAction() - Opens a image for processing

 SaveAction() - Saves the image to the same file.

 SaveAsAction() - Saves the image to different directory path

 PrintAction() - prints the current image

 RotateLeftAction() - rotate the image 90 degrees to the left

 RotateRightAction() - rotate the image 90 degrees to the right

 FlipHorizontalAction() - flips the image horizontally

 FlipVerticalAction() - flips the image vertically

 saveImage() - Saves the current image to the disk.

 doAffineTransform() - perform various transformations on the image like rotating it to 90 degrees to the right, left etc.,

 ImagePreview.java


```
ImageViewer needs an accessory class ImagePreview
```


----------



## JGuru (Apr 25, 2018)

ImagePreview.java


```
// ImageViewer needs an accessory class ImagePreview

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 JGuru
 */
class ImagePreview extends JComponent implements PropertyChangeListener {

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

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

    private 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 ignored) {

            }
        }
    }

    private 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);
        }
    }
}
```


----------



## JGuru (Apr 25, 2018)

6) Write a program to show a simple webbrowser in action?

SimpleBrowser.java


```
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.concurrent.Worker;
import javafx.embed.swing.JFXPanel;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.image.WritableImage;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebHistory;
import javafx.scene.web.WebView;

import javax.imageio.ImageIO;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.swing.*;
import javax.swing.border.EtchedBorder;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.image.RenderedImage;
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.net.MalformedURLException;
import java.net.URL;

import static javafx.concurrent.Worker.State.FAILED;

// *docs.oracle.com/javafx/2/webview/jfxpub-webview.htm - Detailed explanations with examples!!!

public class SimpleBrowser extends JFrame implements Printable {

    private final JFXPanel jfxPanel = new JFXPanel();
    private WebEngine webEngine;

    private final JPanel panel = new JPanel(new BorderLayout());
    private final JLabel lblStatus = new JLabel(" Ready ");

    private final JButton goBtn = new JButton(getIcon("Go.png"));
    private final JTextField textField = new JTextField(40);
    private final JProgressBar progressBar = new JProgressBar();
    private WebView webView;
    private final JButton backBtn = new JButton(getIcon("Back.png"));
    private final JButton forwardBtn = new JButton(getIcon("Forward.png"));
    private final JButton homeBtn = new JButton(getIcon("Home.png"));
    private final JButton reloadBtn = new JButton(getIcon("Reload.png"));
    private final JButton stopBtn = new JButton(getIcon("Stop.png"));
    private final JButton saveBtn = new JButton(getIcon("Save.png"));
    private final JButton printBtn = new JButton(getIcon("Print.png"));
    private final JLabel historyLabel = new JLabel("History");
    private final JComboBox<String> historyComboBox = new JComboBox<>();
    private final String[] zoomFactor = {"10%", "20%", "40%", "60%", "80%", "100%", "120%"};
    private final JComboBox<String> zoomComboBox = new JComboBox<>(zoomFactor);
    private final JLabel zoomLabel = new JLabel("Zoom Factor :");
    private final Dimension btnDim = new Dimension(32, 32);
    private WebHistory history;
    private int nEntries = 0;
    private final JCheckBox javaScript = new JCheckBox("JavaScript", true); // JavaScript
    private Worker<Void> worker;

    public SimpleBrowser() {
        super();
        initComponents();
    }

    // Update the UI
    public void updateUI() {
        backBtn.updateUI();
        forwardBtn.updateUI();
        stopBtn.updateUI();
        reloadBtn.updateUI();
        printBtn.updateUI();
        textField.updateUI();
        goBtn.updateUI();
        saveBtn.updateUI();
        zoomComboBox.updateUI();
        zoomLabel.updateUI();
        lblStatus.updateUI();
        progressBar.updateUI();
        historyLabel.updateUI();
        historyComboBox.updateUI();
        javaScript.updateUI();
    }

    private void initComponents() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ignored) {

        } catch (UnsupportedLookAndFeelException e) {
            System.out.println("System Look 'n feel not supported!!!");
        }
        updateUI();
        createScene();

        ActionListener al = e -> {
            String userInput = textField.getText();
            if (!userInput.equals("")) {
                loadURL(textField.getText());
            }
        };

        textField.setFont(new Font("Dialog", Font.BOLD, 11));
        textField.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
        textField.setPreferredSize(new Dimension(270, 30));
        historyComboBox.setPreferredSize(new Dimension(300, 24));
        goBtn.addActionListener(al);
        textField.addActionListener(al);

        printBtn.addActionListener(ae -> {
            try {
                print();
            } catch (Exception ignored) {

            }
        });
        // Save the captured image to a file in the disk
        saveBtn.addActionListener(e -> Platform.runLater(() -> {
            File destFile = new File("WebPageImage.png");
            WritableImage snapshot = webView.snapshot(null, null); // new SnapshotParameters()
            RenderedImage renderedImage = SwingFXUtils.fromFXImage(snapshot, null);
            try {
                ImageIO.write(renderedImage, "png", destFile);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, "Error Saving WebPage Image to disk!!!");
            }
        }));
        historyComboBox.addItemListener(e -> {
            String urlSelected = historyComboBox.getSelectedItem().toString();
            loadURL(urlSelected);
        });

        zoomComboBox.addItemListener(e -> {
            String zoomfactor = zoomComboBox.getSelectedItem().toString();
            zoomfactor = zoomfactor.substring(0, zoomfactor.length() - 1);
            int zoomValue = 1;
            try {
                zoomValue = Integer.parseInt(zoomfactor);
            } catch (NumberFormatException ignored) {

            }
            Platform.runLater(() -> {
                System.out.println("Font Scale : " + webView.getFontScale());
                webView.setFontScale(webView.getFontScale() + 0.10);
                webView.setZoom(webView.getFontScale() + 0.10);
            });

        });
        progressBar.setPreferredSize(new Dimension(150, 18));
        progressBar.setStringPainted(true);

        // Set the size of the buttons
        backBtn.setPreferredSize(btnDim);
        forwardBtn.setPreferredSize(btnDim);
        homeBtn.setPreferredSize(btnDim);
        printBtn.setPreferredSize(btnDim);
        stopBtn.setPreferredSize(btnDim);
        reloadBtn.setPreferredSize(btnDim);
        goBtn.setPreferredSize(btnDim);
        saveBtn.setPreferredSize(btnDim);
        // Set tooltip text
        backBtn.setToolTipText("Back");
        forwardBtn.setToolTipText("Forward");
        homeBtn.setToolTipText("Home");
        stopBtn.setToolTipText("Stop");
        printBtn.setToolTipText("Print");
        reloadBtn.setToolTipText("Reload");
        goBtn.setToolTipText("Go");
        saveBtn.setToolTipText("Save");

        // Buttons initial state
        backBtn.setEnabled(false);
        forwardBtn.setEnabled(false);
        stopBtn.setEnabled(false);
        reloadBtn.setEnabled(false);
        printBtn.setEnabled(false);

        JPanel topBar = new JPanel(new FlowLayout(FlowLayout.LEFT));
        topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
        topBar.add(backBtn);
        topBar.add(forwardBtn);
        topBar.add(reloadBtn);
        topBar.add(stopBtn);
        topBar.add(saveBtn);
        topBar.add(printBtn);
        topBar.add(textField);
        topBar.add(goBtn);
        topBar.add(zoomLabel);
        topBar.add(zoomComboBox);
        topBar.add(historyLabel);
        topBar.add(historyComboBox);
        topBar.add(javaScript);


        JPanel statusBar = new JPanel(new BorderLayout(5, 0));
        statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
        statusBar.add(lblStatus, BorderLayout.WEST);
        statusBar.add(progressBar, BorderLayout.CENTER);

        panel.add(topBar, BorderLayout.NORTH);
        panel.add(jfxPanel, BorderLayout.CENTER);
        panel.add(statusBar, BorderLayout.SOUTH);

        add(panel);

        setSize(Toolkit.getDefaultToolkit().getScreenSize());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        loadURL("*oracle.com/index.html");
    }

    // Go to the previous webpage
    public void goBack() {
        Platform.runLater(() -> history.go(-1));
    }

    // Go to the next webpage
    public void goForward() {
        Platform.runLater(() -> history.go(1));
    }

    // Reloads the current webpage
    public void reload() {
        Platform.runLater(() -> webEngine.reload());
    }

    // Stop loading the current webpage!!
    public void stop() {
        Platform.runLater(() -> worker.cancel());
    }

    // Go to the Oracle home webpage
    public void goHome() {
        loadURL("*oracle.com/index.html");
    }

    // Is the javafx worker Thread still running in the background?
    public boolean isRunning() {
        return worker.isRunning();
    }

    private void createScene() {

        Platform.runLater(() -> {

            webView = new WebView();
            // Disable the context menu
            webView.setContextMenuEnabled(false);
            // Set font smoothing type to GRAY
            webView.setFontSmoothingType(FontSmoothingType.GRAY);
            webEngine = webView.getEngine();
            // Background Thread worker for webpage rendering in javafx
            worker = webEngine.getLoadWorker();
            history = webEngine.getHistory();
            // Show the previous webpage
            backBtn.addActionListener(e -> goBack());
            // Show the next webpage
            forwardBtn.addActionListener(e -> goForward());
            // Reload the current webpage
            reloadBtn.addActionListener(e -> reload());
            // Stop loading the webpage
            stopBtn.addActionListener(e -> stop());

            homeBtn.addActionListener(e -> goHome());

            history.getEntries().addListener((ListChangeListener<WebHistory.Entry>) c -> {
                        c.next();
                        for (WebHistory.Entry e : c.getRemoved()) {
                            historyComboBox.removeItem(e.getUrl());
                        }
                        for (WebHistory.Entry e : c.getAddedSubList()) {
                            historyComboBox.addItem(e.getUrl());
                        }
                    }
            );
            // Update the frame title with the webpage title
            webEngine.titleProperty().addListener((observable, oldValue, newValue) -> SwingUtilities.invokeLater(() -> {
                SimpleBrowser.this.setTitle(newValue);
                javaScript.addActionListener(e -> Platform.runLater(() -> webEngine.setJavaScriptEnabled(javaScript.isSelected())));
            }));

            // Update the statusbar
            webEngine.setOnStatusChanged(event -> SwingUtilities.invokeLater(() -> lblStatus.setText(event.getData())));

            // Update the textfield data to the new link address
            webEngine.locationProperty().addListener((ov, oldValue, newValue) -> SwingUtilities.invokeLater(() -> textField.setText(newValue)));


            // Update the webpage loading progress in progressbar
            worker.workDoneProperty().addListener((observableValue, oldValue, newValue) -> SwingUtilities.invokeLater(() -> {
                Platform.runLater(() -> {
                    if (isRunning()) {
                        stopBtn.setEnabled(true);
                    } else {
                        stopBtn.setEnabled(false);
                    }
                });
                validateButtons();
                //System.out.println("Entries = " + nEntries + " Index = " + index);
                // Update the webpage loading progress
                progressBar.setValue(newValue.intValue());
            }));

            worker
                    .exceptionProperty()
                    .addListener((o, old, value) -> {
                        if (webEngine.getLoadWorker().getState() == FAILED) {
                            SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(
                                    panel,
                                    (value != null)
                                            ? webEngine.getLocation() + "\n" + value.getMessage()
                                            : webEngine.getLocation() + "\nUnexpected error.",
                                    "Loading error...",
                                    JOptionPane.ERROR_MESSAGE));
                        }
                    });

            jfxPanel.setScene(new Scene(webView));
        });
    }

    void print(String msg){
        System.out.println(msg);
    }
    // Validate the button states to enabled/disabled
    private void validateButtons() {
        nEntries = history.getEntries().size();
        int index = history.getCurrentIndex();
        Platform.runLater(() -> {
            // If the webpage is still loading disable print button
            if (isRunning()) {
                printBtn.setEnabled(false);
            } else {   // If the webpage has finished loading then enable print button
                printBtn.setEnabled(true);
            }
        });
        //print("Entries = " + nEntries + " , Index = " + index);
        if(index == 0) {
            if(nEntries == 0) {
                backBtn.setEnabled(false);
                forwardBtn.setEnabled(false);
                reloadBtn.setEnabled(true);
                printBtn.setEnabled(false);
            }
            else if(nEntries == 1){
                backBtn.setEnabled(false);
                forwardBtn.setEnabled(false);
                reloadBtn.setEnabled(true);
                printBtn.setEnabled(true);
            }
            else if(nEntries > 1){
                backBtn.setEnabled(false);
                forwardBtn.setEnabled(true);
                reloadBtn.setEnabled(true);
                printBtn.setEnabled(true);
            }
        }
        else if(index == 1 || nEntries == 2){
            backBtn.setEnabled(true);
            forwardBtn.setEnabled(false);
        }
        else if(index > 1 || index < nEntries){
            backBtn.setEnabled(true);
            forwardBtn.setEnabled(true);
            reloadBtn.setEnabled(true);
        }
        else if(index == nEntries-1) {
            backBtn.setEnabled(true);
            forwardBtn.setEnabled(false);
            reloadBtn.setEnabled(true);
        }
    }

    private ImageIcon getIcon(String iconName){
        return new ImageIcon(getClass().getResource("Icons/" + iconName));
    }

    public void loadURL(final String url) {
        Platform.runLater(() -> {

            String tempUrl = toURL(url);

            if (tempUrl == null) {
                tempUrl = toURL("*" + url);
            }

            webEngine.load(tempUrl);
        });
    }

    // Print the current document
    public void print() {
        PrinterJob job = PrinterJob.getPrinterJob();
        PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
        PageFormat pf = job.pageDialog(aset);
        job.setPrintable(null, pf);
        boolean ok = job.printDialog(aset);
        if (ok) {
            try {
                job.print(aset);
            } catch (PrinterException ex) {
                /* The job did not successfully complete */
            }
        }
    }

    private static String toURL(String str) {
        try {
            return new URL(str).toExternalForm();
        } catch (MalformedURLException exception) {
            return null;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SimpleBrowser::new);
    }

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
        if (pageIndex > 0) { /* We have only one page, and 'page' is zero-based */
            return NO_SUCH_PAGE;
        }

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

ScreenShot : Imgur


----------



## JGuru (Apr 25, 2018)

Explanation :

This is a JavaFX WebView Example. JavaFX provides a web component that can be used as an embedded web browser in a JavaFX application. It is based on WebKit, which is an open source web browser engine. It supports:

Viewing HTML5 content with CSS and JavaScript
Access to the DOM of the HTML content
Browsing history maintenance
Executing JavaScript code from JavaFX and vice versa

The component handles most of the work of web browsing, for example, rendering the HTML content, maintaining a history of the visited web pages,
navigating to a URL when links are clicked, displaying pop-up contents, among others.

 The web browser component comprises a simple API consisting of a few classes in the javafx.scene.web package:

WebView
WebEngine
WebHistory
WebHistory.Entry
WebEvent
PopupFeatures
PromptData

The WebView class inherits from the Parent class. It is a node, not a control. It is added to a Scene Graph for viewing web pages using local or remote URLs. A WebView displays one web page at a time and it can be styled using a CSS.
A WebView uses a WebEngine for the core processing of its content. A WebEngine manages one web page at a time. The WebView handles user input events such as mouse and keyboard events and other tasks, for example, loading the web page content,
 applying a CSS, and creating a DOM, that are performed by the WebEngine. When using a WebView component, you will be working with its WebEngine most of the time.
A WebEngine maintains the browsing history of all visited web pages for a session in an instance of the WebHistory class. An instance of the inner class WebHistory.Entry
represents an entry in the browsing history. An instance of the WebEvent class represents an event generated by a WebEngine while it processes a web page.

An instance of the WebView class represents a web browser. The class contains only one constructor, which is a no-args constructor:

1
WebView webView = new WebView();
The constructor of the WebView class creates a WebEngine automatically and you cannot change it. The getEngine() method of the WebView class returns the reference of the WebEngine:


WebEngine webEngine = webView.getEngine();
A WebEngine can load content from a URL or a string in memory. You would use the load() method of the WebEngine class to load content from a URL. The URL is specified as a String. It can be a local or remote URL. You would use the reload() method of the WebEngine to reload the current page, as shown in the following code:


// Load the Google web page

webEngine.load("Oracle | Integrated Cloud Applications and Platform Services");

WebEngine loads a web page asynchronously in the background threads using a Worker object. Submitting a request to load a web page before the previous request is fulfilled cancels the previous request. You can find the reference of the Worker object loading the web page using the getLoadWorker() method.

The following snippet of code sets the title of a successfully loaded web page as the title of the stage showing the WebView:

```
// Create the WebView

WebView webView = new WebView();

// Create the WebEngine

final WebEngine webEngine = webView.getEngine();
The WebEngine class contains a title property, which is updated at some point while a web page is being loaded. You can achieve the same effect as above by listening to the change in the title property of the WebEngine:

// Update the stage title when a new web page title is available

webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>()
{
    public void changed(ObservableValue<? extends State> ov, State oldState, State newState)
    {

        if (newState == State.SUCCEEDED)
   {
       //stage.setTitle(webEngine.getLocation());

            stage.setTitle(webEngine.getTitle());
   }
    }

});
```

Explanation :

 initComponents() - initialises the components of the web browser

 goBack() - goes to the previous webpage

 goForward() - goes to the forward webpage in the WebHistory

 reload() - reloads the current webpage

 stop() - stops loading the current webpage

 goHome() - loads the www.oracle.com webpage

 isRunning() - returns the status of the webbrowser worker Thread, whether it is running or not?

 createScene() - creates the webView & the webEngine.

 validateButtons() - validates the buttons - back, forward, reload, print , home etc., to enabled/disabled

 int index = history.getCurrentIndex() - denotes the current index of the webhistory

 loadURL(String url) - loads the specified url in the web browser

 nEntries - number of entries in the webHistory (if the user has visited 10 web pages , then nEntries will be 10)

 getIcon() - fetches the imageicons from the jar file!!! (You must place the icons in the Src folder!!!)

  For eg., if your login name is jguru , then /home/jguru/IdeaProjects/WebBrowser/src/Icons (Linux or Mac OS) - IntelliJ IDEA

  In Windows it is

 print() - prints the current webpage

 save() - saves the currently viewing webpage as a png image file to the disk.


----------



## JGuru (Apr 25, 2018)

7) Write a program to show a text editor in action using Java Swing?

 TextEditor.java


```
/**
 * 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.event.*;
import java.awt.print.PrinterException;
import java.io.*;
import java.util.Hashtable;
import javax.swing.*;
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.
class TextEditor extends JFrame {

    private JFileChooser fileChooser;
    private File file;

    // Create an editor
    private 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.
    private 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.
    private 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]);
        }
    }

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

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

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

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

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

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

        a = getHashedAction(DefaultEditorKit.pasteAction);
        a.putValue(Action.SMALL_ICON, getIcon("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
    private 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
    private 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
    private 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
    private Action getOpenAction() {
        return openAction;
    }

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

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

    // Subclass can override to use a different save action
    private 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 {

        ExitAction() {
            super("Exit", getIcon("close.png"));
            putValue(Action.SHORT_DESCRIPTION, "Exit Application");
        }

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

    private ImageIcon getIcon(String iconName){
        return new ImageIcon(getClass().getResource("Icons/" + iconName));
    }

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

        OpenAction() {
            super("Open", getIcon("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 ignored) {
                        }
                    }
                }
            }

        }
    }

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

        SaveAction() {
            super("Save", getIcon("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) {
                } 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 ignored) {
                            }
                        }
                    }
                }
            } else {
                showMessage("No File open yet!!!", "Information", JOptionPane.INFORMATION_MESSAGE);
            }

        }
    }

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

        SaveAsAction() {
            super("SaveAs", getIcon("saveas.png"));
            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 ignored) {
                                    }
                                }
                            }
                        } else {
                            showMessage("No File Open Yet!!!", "Information", JOptionPane.INFORMATION_MESSAGE);
                        }

                    } else {
                        getSaveAsAction();
                    }

                } else {
                    String filename = getFile().getPath();
                    if (filename == null) {
                    } 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 ignored) {
                                }
                            }
                        }
                    }

                }
            }
        }
    }

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

        PrintAction() {
            super("Print", getIcon("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;
    }

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

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new TextEditor());
    }
}
```

ScreenShot : Imgur

Explanation:

 createTextComponent() - creates a new JTextArea for editing the document

 hashDefaultActions() - Get all of the actions defined for our text component. Hash each one by name

 createFileChooser() - creates a filechooser dialog

 makeActionsPretty() - update the icon name & tool tips

 createToolBar() - creates a toolbar at the top

 createMenuBar() - creates a menubar with menu items

 OpenAction() - opens the text file for processing

 SaveAction() - Saves the updated document to the same file

 SaveAsAction() - Save the current document with a different name under some other directory.

 PrintAction() - prints the current document

 ExitAction() - exits the application

 getIcon() - loads the icons from the 'Icons' folder in the Src directory.

 getFile() - returns the currently open file, since we need to save the document contents to the same file!!!


----------



## JGuru (Apr 25, 2018)

8) Write a Java program to display the contents of a table in a table format?

TableExample.java


```
/*
 * 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.
 */

import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.logging.Level;
import java.util.logging.Logger;

// Download Apache Derby database from here : *www-eu.apache.org/dist//db/derby/db-derby-10.14.1.0/db-derby-10.14.1.0-bin.zip (for Java 8 or higher)
// Note you must include the file derby.jar in the classpath , better use a IDE like NetBeans or IntelliJ IDEA and add the jar file to the library!!

final class TableExample implements LayoutManager {

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

    /**
     * Brigs up a JDialog using JOptionPane containing the connectionPanel. If
     * the user clicks on the 'Connect' button the connection is reset.
     */
    private 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.
     */
    private 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);
    }

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

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

        // Create the buttons.
        showConnectionInfoButton = new JButton("Configuration");
        showConnectionInfoButton.addActionListener(e -> activateConnectionDialog());

        fetchButton = new JButton("Fetch");
        fetchButton.addActionListener(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();
    }

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

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

    private 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);

        return new JScrollPane(table);
    }

    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));
    }
}
```

activateConnectionDialog() - brings the connection dialog box

createConnectionDialog() - create the connection dialog UI

The fetch button fetches the results of the sql query and displays the result as a table.

 connect() - connects to the specified database (Apache Derby in this case)

 fetch() - fetches the sql query result

 createTable() - creates a table to display the database result in a table format

 JDBCAdapter.java - An adaptor, transforming the JDBC interface to the TableModel interface.


```
/*
 * 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.
 */

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
 */

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);
        }
    }

    private 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);
    }

    private 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 ? "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);
            StringBuilder query
                    = new StringBuilder("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.append(" and ");
                }
                query.append(colName).append(" = ").append(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);

    }
}
```


----------



## JGuru (Apr 25, 2018)

TableMap.java


```
/*
 * 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.
 */

import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;

   
class TableMap extends AbstractTableModel implements TableModelListener {

    TableModel model;

    public TableModel getModel() {
        return model;
    }

    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);
    }
}
```

 TableSorter.java - A sorter for TableModels. The sorter has a model (conforming to TableModel) and itself implements TableModel.


```
/*
 * 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.
 */

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
 */
   
public final class TableSorter extends TableMap {

    private int[] indexes;
    private final List<Integer> sortingColumns = new ArrayList<>();
    private boolean ascending = true;
    private 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();
    }

    private 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();

            return Double.compare(d1, d2);
        } 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();

            return Long.compare(n1, n2);
        } else if (type == String.class) {
            String s1 = (String) data.getValueAt(row1, column);
            String s2 = (String) data.getValueAt(row2, column);
            int result = s1.compareTo(s2);

            return Integer.compare(result, 0);
        } else if (type == Boolean.class) {
            Boolean bool1 = (Boolean) data.getValueAt(row1, column);
            boolean b1 = bool1;
            Boolean bool2 = (Boolean) data.getValueAt(row2, column);
            boolean b2 = bool2;

            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);

            return Integer.compare(result, 0);
        }
    }

    private int compare(int row1, int row2) {
        compares++;
        for (Integer column : sortingColumns) {
            int result = compareRowsByColumn(row1, row2, column);
            if (result != 0) {
                return ascending ? result : -result;
            }
        }
        return 0;
    }

    private 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);
    }

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

    private 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.
    private 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++];
            }
        }
    }

    private 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);
    }

    private 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);
    }
}
```

ScreenShot: Imgur

Since this program uses the Apache Derby database , you must include derby.jar in the classpath. Otherwise this program won't run!!!

 Download Apache Derby database from here : *www-eu.apache.org/dist//db/derby/db-derby-10.14.1.0/db-derby-10.14.1.0-bin.zip (for Java 8 or higher)

 Better use a Java IDE , create a 'lib' folder under the project folder , add the jar files in the lib directory to the library. (NetBeans , IntelliJ IDEA or Eclipse)


----------



## JGuru (Apr 25, 2018)

9) Write a BreakOut Java2D game where the player moves a paddle on the screen and bounces a ball or balls. The objective is to destroy bricks in the top of the window?

 Breakout is an arcade game originally developed by Atari Inc. The game was created in 1976.

 In this game, the player moves a paddle on the screen and bounces a ball or balls. The objective is to destroy bricks in the top of the window.

 In our game, we have one paddle, one ball and 30 bricks.

 We do not work with angles, we simply change directions. Top, bottom, left and right. I was inspired by the pybreakout game. It was developed in PyGame library by Nathan Dawson.

The game consists of seven files: Commons.java, Sprite.java, Ball.java, Paddle.java, Brick.java, Board.java, and Breakout.java.

Commons.java


```
interface Commons {

    final int WIDTH = 500;
    final int HEIGHT = 550;
    final int BOTTOM_EDGE = HEIGHT - 10;
    final int N_OF_BRICKS = 30;
    final int INIT_PADDLE_X = 200;
    final int INIT_PADDLE_Y = HEIGHT - 40;
    final int INIT_BALL_X = 230;
    final int INIT_BALL_Y = 355;
    final int DELAY = 600;
    final int PERIOD = 5;
}
```

The Commons.java file has some common constants. The WIDTH and HEIGHT constants store the dimensions of the board. When the ball passes the BOTTOM_EDGE, the game is over.
The N_OF_BRICKS is the number of bricks in the game. The INIT_PADDLE_X and INIT_PADDLE_Y are initial coordinates of the paddle object. The INIT_BALL_X and INIT_BALL_Y are
initial coordinates of the ball object. The DELAY is the initial delay in milliseconds before task is to be executed and the PERIOD is the time in milliseconds between
successive task executions that form game cycles.

Sprite.java


```
import java.awt.Image;
import java.awt.Rectangle;

class Sprite {
    int x;
    int y;
    int i_width;
    int i_heigth;
    Image image;

    public void setX(int x) {
        this.x = x;
    }

    public int getX() {
        return x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return i_width;
    }

    public int getHeight() {
        return i_heigth;
    }

    Image getImage() {
        return image;
    }

    Rectangle getRect() {
        return new Rectangle(x, y,
                image.getWidth(null), image.getHeight(null));
    }
}
```

The Sprite class is a base class for all objects in the Board. We put here all methods and variables that are in Ball, Brick, and Paddle objects, like getImage() or getX() methods.

Brick.java


```
import javax.swing.ImageIcon;
import java.awt.*;
import java.awt.image.BufferedImage;

class Brick extends Sprite {

    private boolean destroyed;
    private int brickWidth = 32, brickHeight = 8;

    public Brick(int x, int y) {

        this.x = x;
        this.y = y;

        ImageIcon icon = createBrick();
        image = icon.getImage();

        i_width = image.getWidth(null);
        i_heigth = image.getHeight(null);

        destroyed = false;
    }

    private ImageIcon createBrick() {
        BufferedImage buff = new BufferedImage(brickWidth, brickHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = buff.createGraphics();
        Breakout.setRenderingHints(g2d);
        g2d.setColor(Color.red);
        g2d.fillRect(0, 0, brickWidth, brickHeight);
        return new ImageIcon(buff);
    }

    public boolean isDestroyed() {

        return destroyed;
    }

    public void setDestroyed(boolean val) {

        destroyed = val;
    }
}
```

This is the Brick class.

private boolean destroyed;
In the destroyed variable we keep the state of a brick.
createBrick() method creates a brick programmatically

Ball.java


```
import javax.swing.ImageIcon;
import java.awt.*;
import java.awt.image.BufferedImage;

class Ball extends Sprite implements Commons {

    private int xdir;
    private int ydir;
    private int ballWidth = 13, ballHeight = 13;

    public Ball() {

        xdir = 1;
        ydir = -1;

        ImageIcon icon = createBall();
        image = icon.getImage();

        i_width = image.getWidth(null);
        i_heigth = image.getHeight(null);

        resetState();
    }

    private ImageIcon createBall() {
        BufferedImage buff = new BufferedImage(ballWidth, ballHeight, BufferedImage.TYPE_INT_BGR);
        Graphics2D g2d = buff.createGraphics();
        Breakout.setRenderingHints(g2d);
        g2d.setColor(Color.green);
        g2d.fillOval(0, 0, ballWidth, ballHeight);
        return new ImageIcon(buff);
    }
    public void move() {

        x += xdir;
        y += ydir;

        if (x == 0) {
            setXDir(1);
        }

        if (x == WIDTH - i_width) {
            setXDir(-1);
        }

        if (y == 0) {
            setYDir(1);
        }
    }

    private void resetState() {

        x = INIT_BALL_X;
        y = INIT_BALL_Y;
    }

    public void setXDir(int x) {
        xdir = x;
    }

    public void setYDir(int y) {
        ydir = y;
    }

    public int getYDir() {
        return ydir;
    }
}
```

createBall() - creates a small ball programmatically

The move() method moves the ball on the Board. If the ball hits the borders, the directions are changed accordingly using setXDir() & setYDir() methods

These two methods are called when the ball hits the paddle or a brick.


----------



## JGuru (Apr 25, 2018)

Paddle.java


```
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;

class Paddle extends Sprite implements Commons {

    private int dx;
    private int paddleWidth = 114, paddleHeight = 14;

    public Paddle() {

        ImageIcon icon = createPaddle();
        image = icon.getImage();

        i_width = image.getWidth(null);
        i_heigth = image.getHeight(null);

        resetState();
    }

    private ImageIcon createPaddle(){
        BufferedImage buff = new BufferedImage(paddleWidth, paddleHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = buff.createGraphics();
        Breakout.setRenderingHints(g2d);
        g2d.setColor(Color.blue);
        g2d.fillRect(0, 0, paddleWidth, paddleHeight);
        return new ImageIcon(buff);
    }

    public void move() {

        x += dx;

        if (x <= 0) {
            x = 0;
        }

        if (x >= WIDTH - i_width) {
            x = WIDTH - i_width;
        }
    }

    public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            dx = -1;
        }

        if (key == KeyEvent.VK_RIGHT) {
            dx = 1;
        }
    }

    public void keyReleased(KeyEvent e) {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            dx = 0;
        }

        if (key == KeyEvent.VK_RIGHT) {
            dx = 0;
        }
    }

    private void resetState() {

        x = INIT_PADDLE_X;
        y = INIT_PADDLE_Y;
    }
}
```

createPaddle() - creates a paddle programmatically

his is the Paddle class. It encapsulates the paddle object in the Breakout game. The paddle is controlled with left and right arrow keys.
By pressing the arrow key, we set the direction variable. By releasing the arrow key, we set the dx variable to zero. This way the paddle stops moving.

The paddle moves only in the horizontal direction, so we only update the x coordinate. The if conditions ensure that the paddle does not pass the window edges.

Board.java


```
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;

class Board extends JPanel implements Commons {

    private Timer timer;
    private String message = "Game Over!!!";
    private Ball ball;
    private Paddle paddle;
    private Brick bricks[];
    private boolean ingame = true;

    public Board() {

        initBoard();
    }

    private void initBoard() {

        addKeyListener(new TAdapter());
        setFocusable(true);

        bricks = new Brick[N_OF_BRICKS];
        setDoubleBuffered(true);
        timer = new Timer();
        timer.scheduleAtFixedRate(new ScheduleTask(), DELAY, PERIOD);
    }

    @Override
    public void addNotify() {
        super.addNotify();
        gameInit();
    }

    private void gameInit() {

        ball = new Ball();
        paddle = new Paddle();

        int k = 0;
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 6; j++) {
                bricks[k] = new Brick(j * 40 + 140, i * 10 + 50);
                k++;
            }
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        // Black background
        g2d.setColor(Color.black);
        g2d.fillRect(0, 0, getWidth(), getHeight());
        Breakout.setRenderingHints(g2d);
        if (ingame) {

            drawObjects(g2d);
        } else {

            gameFinished(g2d);
        }
        Toolkit.getDefaultToolkit().sync();
    }

    private void drawObjects(Graphics2D g2d) {

        g2d.drawImage(ball.getImage(), ball.getX(), ball.getY(),
                ball.getWidth(), ball.getHeight(), this);
        g2d.drawImage(paddle.getImage(), paddle.getX(), paddle.getY(),
                paddle.getWidth(), paddle.getHeight(), this);

        for (int i = 0; i < N_OF_BRICKS; i++) {
            if (!bricks[i].isDestroyed()) {
                g2d.drawImage(bricks[i].getImage(), bricks[i].getX(),
                        bricks[i].getY(), bricks[i].getWidth(),
                        bricks[i].getHeight(), this);
            }
        }
    }

    private void gameFinished(Graphics2D g2d) {

        Font font = new Font("Verdana", Font.BOLD, 18);
        FontMetrics metrics = this.getFontMetrics(font);

        g2d.setColor(Color.yellow);
        g2d.setFont(font);
        g2d.drawString(message,
                (Commons.WIDTH - metrics.stringWidth(message)) / 2,
                Commons.WIDTH / 2);
    }

    private class TAdapter extends KeyAdapter {

        @Override
        public void keyReleased(KeyEvent e) {
            paddle.keyReleased(e);
        }

        @Override
        public void keyPressed(KeyEvent e) {
            paddle.keyPressed(e);
        }
    }

    private class ScheduleTask extends TimerTask {

        @Override
        public void run() {
            ball.move();
            paddle.move();
            checkCollision();
            repaint();
        }
    }

    private void stopGame() {

        ingame = false;
        timer.cancel();
    }

    private void checkCollision() {

        if (ball.getRect().getMaxY() > Commons.BOTTOM_EDGE) {
            stopGame();
        }

        for (int i = 0, j = 0; i < N_OF_BRICKS; i++) {

            if (bricks[i].isDestroyed()) {
                j++;
            }

            if (j == N_OF_BRICKS) {
                message = "Victory";
                stopGame();
            }
        }

        if ((ball.getRect()).intersects(paddle.getRect())) {

            int paddleLPos = (int) paddle.getRect().getMinX();
            int ballLPos = (int) ball.getRect().getMinX();

            int first = paddleLPos + 8;
            int second = paddleLPos + 16;
            int third = paddleLPos + 24;
            int fourth = paddleLPos + 32;

            if (ballLPos < first) {
                ball.setXDir(-1);
                ball.setYDir(-1);
            }

            if (ballLPos >= first && ballLPos < second) {
                ball.setXDir(-1);
                ball.setYDir(-1 * ball.getYDir());
            }

            if (ballLPos >= second && ballLPos < third) {
                ball.setXDir(0);
                ball.setYDir(-1);
            }

            if (ballLPos >= third && ballLPos < fourth) {
                ball.setXDir(1);
                ball.setYDir(-1 * ball.getYDir());
            }

            if (ballLPos > fourth) {
                ball.setXDir(1);
                ball.setYDir(-1);
            }
        }

        for (int i = 0; i < N_OF_BRICKS; i++) {

            if ((ball.getRect()).intersects(bricks[i].getRect())) {

                int ballLeft = (int) ball.getRect().getMinX();
                int ballHeight = (int) ball.getRect().getHeight();
                int ballWidth = (int) ball.getRect().getWidth();
                int ballTop = (int) ball.getRect().getMinY();

                Point pointRight = new Point(ballLeft + ballWidth + 1, ballTop);
                Point pointLeft = new Point(ballLeft - 1, ballTop);
                Point pointTop = new Point(ballLeft, ballTop - 1);
                Point pointBottom = new Point(ballLeft, ballTop + ballHeight + 1);

                if (!bricks[i].isDestroyed()) {
                    if (bricks[i].getRect().contains(pointRight)) {
                        ball.setXDir(-1);
                    } else if (bricks[i].getRect().contains(pointLeft)) {
                        ball.setXDir(1);
                    }

                    if (bricks[i].getRect().contains(pointTop)) {
                        ball.setYDir(1);
                    } else if (bricks[i].getRect().contains(pointBottom)) {
                        ball.setYDir(-1);
                    }

                    bricks[i].setDestroyed(true);
                }
            }
        }
    }
}
```

This is the Board class. Here we put the game logic.

In the gameInit() method we create a ball, a paddle, and thirty bricks.


```
if (ingame) {
   
    drawObjects(g2d);
} else {

    gameFinished(g2d);
}
```

Depending on the ingame variable, we either draw all the objects in the drawObjects() method or finish the game with the gameFinished() method.

The drawObjects() method draws all the objects of the game. The sprites are drawn with the drawImage() method.

The gameFinished() method draws "Game over" or "Victory" to the middle of the window.

The ScheduleTask is triggerd every PERIOD ms. In its run() method, we move the ball and the paddle. We check for possible collisions and repaint the screen.

If the ball hits the bottom, we stop the game.

We check how many bricks are destroyed. If we destroyed all N_OF_BRICKS bricks, we win the game.

If the ball hits the first part of the paddle, we change the direction of the ball to the north-west.

If the ball hits the bottom of the brick, we change the y direction of the ball; it goes down.

Breakout.java


```
import java.awt.*;
import javax.swing.*;

class Breakout extends JFrame {

    private Breakout() {
        initUI();
    }

    private void initUI() {

        add(new Board());
        setTitle("Breakout");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(Commons.WIDTH, Commons.HEIGHT);
        setLocationRelativeTo(null);
        setResizable(false);
        setVisible(true);
    }

    // Set RenderingHints properties
    public static void setRenderingHints(Graphics2D g2d){
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(() -> new Breakout());
    }
}
```

ScreenShot : Imgur

And finally, this is the Breakout class which has the main entry method so that we can run it as an application.


----------



## JGuru (Apr 25, 2018)

4) Write a program to perform various filters like sharpen , emboss, crystallize, edge detect, threshold, marble, motion blur, oil, twirl, tile etc.,?

 You need to download the Jerry Huxtable's Image Filters from *jhlabs.com/ip/filters/Filters.zip

ImageProcessor.java


```
// You need to download the Jerry Huxtable's Image Filters from *jhlabs.com/ip/filters/Filters.zip

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 (Exception ignored) {
            // 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(getRedoAction());
        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 getRedoAction(){
        return redoAction;
    }

    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(getRedoAction()).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 redoAction = new RedoAction();
    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();
```


----------



## JGuru (Apr 25, 2018)

```
// 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) ||
                            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 + ",";
                }
                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);
        }
    }

    public ImageIcon getIcon(String iconName){
        return new ImageIcon(getClass().getResource("Icons/" + iconName));
    }

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

        public ExitAction() {
            super("Exit", getIcon("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", getIcon("open.gif"));
            putValue(Action.SHORT_DESCRIPTION, "Open Image");
        }

        // Query user for a filename and attempt to open and read the file

        @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 throw 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", getIcon("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", getIcon("saveas.png"));
            putValue(Action.SHORT_DESCRIPTION, "Save As another Image");
        }

        // Query user for a filename and attempt to open and write the 
                // 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", getIcon("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", getIcon("undo.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", getIcon("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();
            }
        }
    }
```


----------



## JGuru (Apr 25, 2018)

```
class BlurFilterAction extends AbstractAction {

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

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

    class LensBlurAction extends AbstractAction {

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

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

                LensBlurFilter lFilter = new LensBlurFilter();
                lFilter.setBloom(1f);
                lFilter.setBloomThreshold(5f);
                lFilter.setRadius(15);
                if (getImage() != null) {
                    setImage(lFilter.filter(getImage(),
                            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(() -> {
                CrystallizeFilter cFilter = new CrystallizeFilter();
                cFilter.setAmount(40f);
                cFilter.setGridType(CrystallizeFilter.HEXAGONAL);
                cFilter.setScale(20);
                if (getImage() != null) {
                    setImage(cFilter.filter(getImage(),
                            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(() -> {
                setEnabled(false);
                OilFilter oFilter = new OilFilter();
                if (getImage() != null) {
                    setImage(oFilter.filter(getImage(),
                            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 (getImage() != null) {
                    setImage(rFilter.filter(getImage(), 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(() -> {

                SparkleFilter spFilter = new SparkleFilter();
                spFilter.setAmount(40);
                spFilter.setRadius(50);
                spFilter.setRandomness(10 * 2);
                spFilter.setRays(55);
                if (getImage() != 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), "LightFilter");
            }
        }
    }

    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), "InvertFilter");
            }
        }
    }

    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), "SphereFilter");
            }
        }
    }

    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(() -> {
                // 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();
        }
    }
```


----------



## JGuru (Apr 25, 2018)

```
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(() -> {
                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 ImageProcessor());
    }
}
```

 ScreenShot : Imgur

Explanation:

createToolBar() - creates the toolbar with various butttons

createFileChooser() - creates the filechooser dialog

createLabelComponent() - create a label to display the image

createMenuBar() - creates the menubar with various menuitems

OpenAction() - opens the image for processing

SaveAction() - saves the image to the disk

SaveAsAction() - Saves the image to different directory path

PrintAction() - prints the image

RevertAction() - display the original image

RedoAction() - redo the last filter action

ExitAction() - exits the application

Various Filter effects:

BlurFilterAction() - apply the blur filter

CrystallizeFilterAction() - apply the crystallize filter

EmbossFilterAction() - emboss the image

EdgeFilterAction() - edge detect filter

LightFilterAction() - light filter

ThresholdFilterAction() - threshold filter

SharpenFilterAction() - sharpens the image

RippleFilterAction() - ripple effect filter

OilFilterAction() - oil filter

TwirlFilterAction() - twirl effect filter

TileFilterAction() - tile image filter

This program also need an accessory class called ImagePreview.java


```
/**
 * Created with IntelliJ IDEA.
 * User: JGuru
 * 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 JGuru
 */
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);
        }
    }
}
```

Run the program. Open the image using File->Open, perform various filters from the menu filter.
You can save, revert, print, redo the operation.


----------



## JGuru (Apr 25, 2018)

5) Write a program to read a zip file (similar to WinZip) and unzip the file contents?

JZipDemo.java


```
import java.awt.*;
import java.awt.event.ActionEvent;
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: 4/22/18 Time: 9:03 PM To change
 * this template use File | Settings | File Templates.
 */

// This is just a demo JZip program!!
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 final Vector<String> archiveContents = new Vector<>();
    private JTable table;
    private JScrollPane scrollPane;
    private JPanel statusBar;
    private JLabel statusLabel;

    private 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
    private JPanel createStatusBar() {
        statusBar = new JPanel(new FlowLayout(FlowLayout.LEFT));
        statusLabel = new JLabel("Ready");
        statusBar.add(statusLabel);
        return statusBar;
    }

    // Create the FileChooser
    private 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
    private 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
    private 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;
    }

    // Load the icon from the JAR file!!!
    private ImageIcon getIcon(String iconName){
        return new ImageIcon(getClass().getResource("Icons/" + iconName));
    }

    private Action getMenuHelpContentsAction() {
        return menuHelpAction;
    }

    private Action getMenuAboutAction() {
        return menuAboutAction;
    }

    private Action getMenuConfigurationAction() {
        return menuConfigurationAction;
    }

    private Action getMenuAddAction() {
        return menuAddAction;
    }

    private Action getMenuDeleteAction() {
        return menuDeleteAction;
    }

    private Action getMenuExtractAction() {
        return menuExtractAction;
    }

    private Action getNewAction() {
        return newAction;
    }

    private Action getOpenAction() {
        return openAction;
    }

    private Action getFavoritesAction() {
        return favoritesAction;
    }

    private Action getAddAction() {
        return addAction;
    }

    private Action getExtractAction() {
        return extractAction;
    }

    private Action getMailAction() {
        return mailAction;
    }

    private Action getEncryptAction() {
        return encryptAction;
    }

    private Action getViewAction() {
        return viewAction;
    }

    private Action getCheckOutAction() {
        return checkOutAction;
    }

    private Action getWizardAction() {
        return wizardAction;
    }

    protected Action getViewStyleAction() {
        return viewStyleAction;
    }

    private Action getMenuNewArchiveAction() {
        return menuNewArchiveAction;
    }

    private Action getMenuOpenArchiveAction() {
        return menuOpenArchiveAction;
    }

    private Action getMenuFavoritesAction() {
        return menuFavoritesAction;
    }

    private Action getMenuCloseArchiveAction() {
        return menuCloseArchiveAction;
    }

    private Action getMenuSaveAsAction() {
        return menuSaveAsAction;
    }

    private Action getMenuPrintAction() {
        return menuPrintAction;
    }

    private Action getMenuPropertiesAction() {
        return menuPropertiesAction;
    }

    private Action getMenuWizardAction() {
        return menuWizardAction;
    }

    private Action getMenuExitAction() {
        return menuExitAction;
    }

    protected Action getMenuViewAction() {
        return menuViewAction;
    }

    private Action getMenuSelectAllAction() {
        return menuselectAllAction;
    }

    private Action getMenuAllFilesAction() {
        return menuAllFilesAction;
    }

    private Action getMenuFilesByFolderAction() {
        return menuFilesByFolderAction;
    }

    private Action getMenuCreateAction() {
        return menuCreateAction;
    }

    private Action getMenuEditAction() {
        return menuEditAction;
    }

    private Action getMenuRunAction() {
        return menuRunAction;
    }

    private Action getMenuZipMyDocsAction() {
        return menuZipMyDocsAction;
    }

    private Action getMenuZipAllLibrariesAction() {
        return menuZipMyLibsAction;
    }
```


----------



## JGuru (Apr 25, 2018)

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

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

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

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

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

    private final Action menuConfigurationAction = new MenuConfigurationAction();

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

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

        public ExitAction() {
            super("Exit", getIcon("menu/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(zEntry.getSize());
                    packed.addElement(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 (String name : names) {
                    colData.addElement(name);
                }
                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 ignored) {
                        }

                        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("editorPane")) {
                            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
                } // Close 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 ignored) {
            }
        } // End error
        return null;
    }
```


----------



## JGuru (Apr 25, 2018)

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

        OpenAction() {
            super("Open", getIcon("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(getTable());
        }
    }

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

        public SaveAsAction() {
            super("SaveAs", getIcon("menu/saveas.png"));
            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) {
                        }
                    } else {
                        //getSaveAsAction();
                    }

                } else {
                }
            }
        }
    }

    class NewAction extends AbstractAction {

        NewAction() {
            super("New", getIcon("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 {

        FavoritesAction() {
            super("Favorites", getIcon("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 {

        AddAction() {
            super("Add", getIcon("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 {

        ExtractAction() {
            super("Extract", getIcon("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 {

        MailAction() {
            super("Mail", getIcon("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 {

        EncryptAction() {
            super("Encrypt", getIcon("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 {

        ViewAction() {
            super("View", getIcon("View Style.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 {

        CheckOutAction() {
            super("CheckOut", getIcon("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 {

        WizardAction() {
            super("Wizard", getIcon("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 {

        ViewStyleAction() {
            super("View Style", getIcon("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 {

        MenuNewArchiveAction() {
            super("New Archive", getIcon("menu/New.png"));
        }

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

    class MenuOpenArchiveAction extends AbstractAction {

        MenuOpenArchiveAction() {
            super("Open Archive", getIcon("menu/Open.png"));
        }

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

    class MenuFavoritesAction extends AbstractAction {

        MenuFavoritesAction() {
            super("Favorites", getIcon("menu/Favorites.png"));
        }

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

    class MenuCloseArchiveAction extends AbstractAction {

        MenuCloseArchiveAction() {
            super("Close Archive", getIcon("menu/close.png"));
        }

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

    class MenuSaveAsAction extends AbstractAction {

        MenuSaveAsAction() {
            super("Save As", getIcon("menu/saveas.png"));
        }

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

    class MenuPrintAction extends AbstractAction {

        MenuPrintAction() {
            super("Print", getIcon("menu/print.gif"));
        }

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

    class MenuPropertiesAction extends AbstractAction {

        MenuPropertiesAction() {
            super("Properties", getIcon("menu/Properties.png"));
        }

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

    class MenuWizardAction extends AbstractAction {

        MenuWizardAction() {
            super("Wizard", getIcon("menu/Wizard.png"));
        }

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

    class MenuExitAction extends AbstractAction {

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

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

    class MenuAddAction extends AbstractAction {

        MenuAddAction() {
            super("Add", getIcon("menu/Add.png"));
        }

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

    class MenuDeleteAction extends AbstractAction {

        MenuDeleteAction() {
            super("Delete", getIcon("menu/delete.png"));
        }

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

    class MenuExtractAction extends AbstractAction {

        MenuExtractAction() {
            super("Extract", getIcon("menu/Extract.png"));
        }

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

    class MenuViewAction extends AbstractAction {

        MenuViewAction() {
            super("View", getIcon("menu/View.png"));
        }

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

    class MenuSelectAllAction extends AbstractAction {

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

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

    class MenuAllFilesAction extends AbstractAction {

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

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

    class MenuFilesByFolderAction extends AbstractAction {

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

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

    class MenuCreateAction extends AbstractAction {

        MenuCreateAction() {
            super("Create", getIcon("menu/New.png"));
        }

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

    class MenuEditAction extends AbstractAction {

        MenuEditAction() {
            super("Edit", getIcon("menu/Edit.png"));
        }

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


----------



## JGuru (Apr 25, 2018)

```
class MenuHelpAction extends AbstractAction {

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

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

    class MenuRunAction extends AbstractAction {

        MenuRunAction() {
            super("Run", getIcon("menu/Run.png"));
        }

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

    class MenuZipMyDocumentsAction extends AbstractAction {

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

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

    class MenuZipAllLibrariesAction extends AbstractAction {

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

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

    class MenuConfigurationAction extends AbstractAction {

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

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

    class MenuAboutAction extends AbstractAction {

        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(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("Copyright &copy 2002-2016 JZip Computing Inc.", 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(getIcon("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
    private 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 ignored) {
                }
                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;
                System.err.println("Destination : " + myFile);
                // If the destination directory doesn't exist then create it
                if (!myFile.exists()) {
                    myFile.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() {
        return (table != null) ? table : 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) {
        //To change body of implemented methods use File | Settings | File Templates.
        SwingUtilities.invokeLater(JZipDemo::new);
    }
}
```

ScreenShot : Imgur

We read a zip file and display its contents in a table format similar to WinZip.

createMenuBar() - creates a menubar with menu items

createFileChooser() - creates a fileChooser dialog

createToolBar() - creates a toolbar with various buttons

createStatusBar() - creates a statusbar

NewAction() - create a new archive

OpenAction() - opens a existing zip archive

FavoritesAction() - Add the zip files as favorites

ExtractAction() - extract the contents of the zip file

MailAction() - send the created archive to someone using mail

EncryptAction() - encrypt the zip archive

WizardAction() - show the wizard interface to add, zip, or unzip an archive.

ViewStyleAction() - View different style

createTable(File file) - creates a table from the zip file archive showing different information like name, type, last modified, size, packed, path etc.,

 The program also needs two accessory files HelpContents.java and helpcontents.html


----------



## JGuru (Apr 25, 2018)

HelpContents.java


```
/**
 * Created with IntelliJ IDEA.
 * User: JGuru
 * Date: 7/20/18
 * 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 {

    private JEditorPane editorPane;
    private URL url;

    public HelpContents() {

        try {

            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) {
                editorPane = new JEditorPane(url);
                editorPane.setEditable(false);
                JScrollPane scroller = new JScrollPane();
                JViewport vp = scroller.getViewport();
                vp.add(editorPane);
                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);
    }
}
```

 helpcontents.html

 The file helpcontents.html must be placed under the 'resources' directory under the Source (Src) folder of your Java IDE


```
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.
```


----------



## JGuru (Apr 25, 2018)

Thats's it. Hope you guys like my tutorial!!!
Happy Coding!!!


----------



## icebags (Jan 17, 2019)

Great job, doing all the hard work.will go through it soon.


----------

