view dwtexamples/addressbook/AddressBook.d @ 106:396a9fa07672

Added addressbook example. Does not yet compile
author Frank Benoit <benoit@tionex.de>
date Fri, 18 Jan 2008 20:53:49 +0100
parents
children 3476fddbb4c8
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
module dwtexamples.addressbook.AddressBook;


// /* Imports */
// import java.io.BufferedReader;
// import java.io.File;
// import java.io.FileNotFoundException;
// import java.io.FileReader;
// import java.io.FileWriter;
// import java.io.IOException;
// import java.util.Arrays;
// import java.util.Comparator;
// import java.util.ResourceBundle;


import dwt.DWT;
import dwt.events.MenuAdapter;
import dwt.events.MenuEvent;
import dwt.events.SelectionAdapter;
import dwt.events.SelectionEvent;
import dwt.events.ShellAdapter;
import dwt.events.ShellEvent;
import dwt.graphics.Cursor;
import dwt.layout.FillLayout;
import dwt.widgets.Display;
import dwt.widgets.FileDialog;
import dwt.widgets.Menu;
import dwt.widgets.MenuItem;
import dwt.widgets.MessageBox;
import dwt.widgets.Shell;
import dwt.widgets.Table;
import dwt.widgets.TableColumn;
import dwt.widgets.TableItem;

import dwtexamples.addressbook.SearchDialog;
import dwtexamples.addressbook.DataEntryDialog;

import dwt.dwthelper.ResourceBundle;

void main() {
    Display display = new Display();
    AddressBook application = new AddressBook();
    Shell shell = application.open(display);
    while(!shell.isDisposed()){
        if(!display.readAndDispatch())
            display.sleep();
    }
    display.dispose();
}

/**
 * AddressBookExample is an example that uses <code>org.eclipse.swt</code>
 * libraries to implement a simple address book.  This application has
 * save, load, sorting, and searching functions common
 * to basic address books.
 */
public class AddressBook {

    private static ResourceBundle resAddressBook;
    private Shell shell;

    private Table table;
    private SearchDialog searchDialog;

    private File file;
    private bool isModified;

    private char[][] copyBuffer;

    private int lastSortColumn= -1;

    private static const char[] DELIMITER = "\t";
    private static char[][] columnNames;

public this(){
    if( resAddressBook is null ){
        resAddressBook = ResourceBundle.getBundle("examples_addressbook");
        columnNames = [
            resAddressBook.getString("Last_name"),
            resAddressBook.getString("First_name"),
            resAddressBook.getString("Business_phone"),
            resAddressBook.getString("Home_phone"),
            resAddressBook.getString("Email"),
            resAddressBook.getString("Fax") ];
    }
}
public Shell open(Display display) {
    shell = new Shell(display);
    shell.setLayout(new FillLayout());
    shell.addShellListener(new class() ShellAdapter {
        public void shellClosed(ShellEvent e) {
            e.doit = closeAddressBook();
        }
    });

    createMenuBar();

    searchDialog = new SearchDialog(shell);
    searchDialog.setSearchAreaNames(columnNames);
    searchDialog.setSearchAreaLabel(resAddressBook.getString("Column"));
    searchDialog.addFindListener(new class() FindListener {
        public bool find() {
            return findEntry();
        }
    });

    table = new Table(shell, DWT.SINGLE | DWT.BORDER | DWT.FULL_SELECTION);
    table.setHeaderVisible(true);
    table.setMenu(createPopUpMenu());
    table.addSelectionListener(new class() SelectionAdapter {
        public void widgetDefaultSelected(SelectionEvent e) {
            TableItem[] items = table.getSelection();
            if (items.length > 0) editEntry(items[0]);
        }
    });
    for(int i = 0; i < columnNames.length; i++) {
        TableColumn column = new TableColumn(table, DWT.NONE);
        column.setText(columnNames[i]);
        column.setWidth(150);
        final int columnIndex = i;
        column.addSelectionListener(new class() SelectionAdapter {
            public void widgetSelected(SelectionEvent e) {
                sort(columnIndex);
            }
        });
    }

    newAddressBook();

    shell.setSize(table.computeSize(DWT.DEFAULT, DWT.DEFAULT).x, 300);
    shell.open();
    return shell;
}

private bool closeAddressBook() {
    if(isModified) {
        //ask user if they want to save current address book
        MessageBox box = new MessageBox(shell, DWT.ICON_WARNING | DWT.YES | DWT.NO | DWT.CANCEL);
        box.setText(shell.getText());
        box.setMessage(resAddressBook.getString("Close_save"));

        int choice = box.open();
        if(choice is DWT.CANCEL) {
            return false;
        } else if(choice is DWT.YES) {
            if (!save()) return false;
        }
    }

    TableItem[] items = table.getItems();
    for (int i = 0; i < items.length; i ++) {
        items[i].dispose();
    }

    return true;
}
/**
 * Creates the menu at the top of the shell where most
 * of the programs functionality is accessed.
 *
 * @return      The <code>Menu</code> widget that was created
 */
private Menu createMenuBar() {
    Menu menuBar = new Menu(shell, DWT.BAR);
    shell.setMenuBar(menuBar);

    //create each header and subMenu for the menuBar
    createFileMenu(menuBar);
    createEditMenu(menuBar);
    createSearchMenu(menuBar);
    createHelpMenu(menuBar);

    return menuBar;
}

/**
 * Converts an encoded <code>char[]</code> to a char[] array representing a table entry.
 */
private char[][] decodeLine(char[] line) {
    if(line is null) return null;

    char[][] parsedLine = new char[][table.getColumnCount()];
    for(int i = 0; i < parsedLine.length - 1; i++) {
        int index = line.indexOf(DELIMITER);
        if (index > -1) {
            parsedLine[i] = line.substring(0, index);
            line = line.substring(index + DELIMITER.length(), line.length());
        } else {
            return null;
        }
    }

    if (line.indexOf(DELIMITER) !is -1) return null;

    parsedLine[parsedLine.length - 1] = line;

    return parsedLine;
}
private void displayError(char[] msg) {
    MessageBox box = new MessageBox(shell, DWT.ICON_ERROR);
    box.setMessage(msg);
    box.open();
}
private void editEntry(TableItem item) {
    DataEntryDialog dialog = new DataEntryDialog(shell);
    dialog.setLabels(columnNames);
    char[][] values = new char[][table.getColumnCount()];
    for (int i = 0; i < values.length; i++) {
        values[i] = item.getText(i);
    }
    dialog.setValues(values);
    values = dialog.open();
    if (values !is null) {
        item.setText(values);
        isModified = true;
    }
}
private char[] encodeLine(char[][] tableItems) {
    char[] line = "";
    for (int i = 0; i < tableItems.length - 1; i++) {
        line += tableItems[i] + DELIMITER;
    }
    line += tableItems[tableItems.length - 1] + "\n";

    return line;
}
private bool findEntry() {
    Cursor waitCursor = new Cursor(shell.getDisplay(), DWT.CURSOR_WAIT);
    shell.setCursor(waitCursor);

    bool matchCase = searchDialog.getMatchCase();
    bool matchWord = searchDialog.getMatchWord();
    char[] searchString = searchDialog.getSearchString();
    int column = searchDialog.getSelectedSearchArea();

    searchString = matchCase ? searchString : searchString.toLowerCase();

    bool found = false;
    if (searchDialog.getSearchDown()) {
        for(int i = table.getSelectionIndex() + 1; i < table.getItemCount(); i++) {
            if (found = findMatch(searchString, table.getItem(i), column, matchWord, matchCase)){
                table.setSelection(i);
                break;
            }
        }
    } else {
        for(int i = table.getSelectionIndex() - 1; i > -1; i--) {
            if (found = findMatch(searchString, table.getItem(i), column, matchWord, matchCase)){
                table.setSelection(i);
                break;
            }
        }
    }

    shell.setCursor(null);
    waitCursor.dispose();

    return found;
}
private bool findMatch(char[] searchString, TableItem item, int column, bool matchWord, bool matchCase) {

    char[] tableText = matchCase ? item.getText(column) : item.getText(column).toLowerCase();
    if (matchWord) {
        if (tableText !is null && tableText.equals(searchString)) {
            return true;
        }

    } else {
        if(tableText!is null && tableText.indexOf(searchString) !is -1) {
            return true;
        }
    }
    return false;
}
private void newAddressBook() {
    shell.setText(resAddressBook.getString("Title_bar") + resAddressBook.getString("New_title"));
    file = null;
    isModified = false;
}
private void newEntry() {
    DataEntryDialog dialog = new DataEntryDialog(shell);
    dialog.setLabels(columnNames);
    char[][] data = dialog.open();
    if (data !is null) {
        TableItem item = new TableItem(table, DWT.NONE);
        item.setText(data);
        isModified = true;
    }
}

private void openAddressBook() {
    FileDialog fileDialog = new FileDialog(shell, DWT.OPEN);

    fileDialog.setFilterExtensions(["*.adr;", "*.*"]);
    fileDialog.setFilterNames(new char[][] [resAddressBook.getString("Book_filter_name") + " (*.adr)",
                                            resAddressBook.getString("All_filter_name") + " (*.*)"]);
    char[] name = fileDialog.open();

    if(name is null) return;
    File file = new File(name);
    if (!file.exists()) {
        displayError(resAddressBook.getString("File")~file.getName()~" "~resAddressBook.getString("Does_not_exist"));
        return;
    }

    Cursor waitCursor = new Cursor(shell.getDisplay(), DWT.CURSOR_WAIT);
    shell.setCursor(waitCursor);

    FileReader fileReader = null;
    BufferedReader bufferedReader = null;
    char[][] data = new char[][0];
    try {
        fileReader = new FileReader(file.getAbsolutePath());
        bufferedReader = new BufferedReader(fileReader);
        char[] nextLine = bufferedReader.readLine();
        while (nextLine !is null){
            char[][] newData = new char[][data.length + 1];
            System.arraycopy(data, 0, newData, 0, data.length);
            newData[data.length] = nextLine;
            data = newData;
            nextLine = bufferedReader.readLine();
        }
    } catch(FileNotFoundException e) {
        displayError(resAddressBook.getString("File_not_found") ~ "\n" ~ file.getName());
        return;
    } catch (IOException e ) {
        displayError(resAddressBook.getString("IO_error_read") ~ "\n" ~ file.getName());
        return;
    } finally {

        shell.setCursor(null);
        waitCursor.dispose();

        if(fileReader !is null) {
            try {
                fileReader.close();
            } catch(IOException e) {
                displayError(resAddressBook.getString("IO_error_close") ~ "\n" ~file.getName());
                return;
            }
        }
    }

    char[][][] tableInfo = new char[][data.length][table.getColumnCount()];
    int writeIndex = 0;
    for (int i = 0; i < data.length; i++) {
        char[][] line = decodeLine(data[i]);
        if (line !is null) tableInfo[writeIndex++] = line;
    }
    if (writeIndex !is data.length) {
        char[][][] result = new char[][writeIndex][table.getColumnCount()];
        System.arraycopy(tableInfo, 0, result, 0, writeIndex);
        tableInfo = result;
    }
    Arrays.sort(tableInfo, new RowComparator(0));

    for (int i = 0; i < tableInfo.length; i++) {
        TableItem item = new TableItem(table, DWT.NONE);
        item.setText(tableInfo[i]);
    }
    shell.setText(resAddressBook.getString("Title_bar")~fileDialog.getFileName());
    isModified = false;
    this.file = file;
}
private bool save() {
    if(file is null) return saveAs();

    Cursor waitCursor = new Cursor(shell.getDisplay(), DWT.CURSOR_WAIT);
    shell.setCursor(waitCursor);

    TableItem[] items = table.getItems();
    char[][] lines = new char[][items.length];
    for(int i = 0; i < items.length; i++) {
        char[][] itemText = new char[][table.getColumnCount()];
        for (int j = 0; j < itemText.length; j++) {
            itemText[j] = items[i].getText(j);
        }
        lines[i] = encodeLine(itemText);
    }

    FileWriter fileWriter = null;
    try {
        fileWriter = new FileWriter(file.getAbsolutePath(), false);
        for (int i = 0; i < lines.length; i++) {
            fileWriter.write(lines[i]);
        }
    } catch(FileNotFoundException e) {
        displayError(resAddressBook.getString("File_not_found") ~ "\n" ~ file.getName());
        return false;
    } catch(IOException e ) {
        displayError(resAddressBook.getString("IO_error_write") ~ "\n" ~ file.getName());
        return false;
    } finally {
        shell.setCursor(null);
        waitCursor.dispose();

        if(fileWriter !is null) {
            try {
                fileWriter.close();
            } catch(IOException e) {
                displayError(resAddressBook.getString("IO_error_close") ~ "\n" ~ file.getName());
                return false;
            }
        }
    }

    shell.setText(resAddressBook.getString("Title_bar")+file.getName());
    isModified = false;
    return true;
}
private bool saveAs() {

    FileDialog saveDialog = new FileDialog(shell, DWT.SAVE);
    saveDialog.setFilterExtensions(["*.adr;",  "*.*"]);
    saveDialog.setFilterNames(["Address Books (*.adr)", "All Files "]);

    saveDialog.open();
    char[] name = saveDialog.getFileName();

    if(name.equals("")) return false;

    if(name.indexOf(".adr") !is name.length() - 4) {
        name += ".adr";
    }

    File file = new File(saveDialog.getFilterPath(), name);
    if(file.exists()) {
        MessageBox box = new MessageBox(shell, DWT.ICON_WARNING | DWT.YES | DWT.NO);
        box.setText(resAddressBook.getString("Save_as_title"));
        box.setMessage(resAddressBook.getString("File") ~ file.getName()~" "~resAddressBook.getString("Query_overwrite"));
        if(box.open() !is DWT.YES) {
            return false;
        }
    }
    this.file = file;
    return save();
}
private void sort(int column) {
    if(table.getItemCount() <= 1) return;

    TableItem[] items = table.getItems();
    char[][][] data = new char[][items.length][table.getColumnCount()];
    for(int i = 0; i < items.length; i++) {
        for(int j = 0; j < table.getColumnCount(); j++) {
            data[i][j] = items[i].getText(j);
        }
    }

    Arrays.sort(data, new RowComparator(column));

    if (lastSortColumn !is column) {
        table.setSortColumn(table.getColumn(column));
        table.setSortDirection(DWT.DOWN);
        for (int i = 0; i < data.length; i++) {
            items[i].setText(data[i]);
        }
        lastSortColumn = column;
    } else {
        // reverse order if the current column is selected again
        table.setSortDirection(DWT.UP);
        int j = data.length -1;
        for (int i = 0; i < data.length; i++) {
            items[i].setText(data[j--]);
        }
        lastSortColumn = -1;
    }

}
/**
 * Creates all the items located in the File submenu and
 * associate all the menu items with their appropriate
 * functions.
 *
 * @param   menuBar Menu
 *              the <code>Menu</code> that file contain
 *              the File submenu.
 */
private void createFileMenu(Menu menuBar) {
    //File menu.
    MenuItem item = new MenuItem(menuBar, DWT.CASCADE);
    item.setText(resAddressBook.getString("File_menu_title"));
    Menu menu = new Menu(shell, DWT.DROP_DOWN);
    item.setMenu(menu);
    /**
     * Adds a listener to handle enabling and disabling
     * some items in the Edit submenu.
     */
    menu.addMenuListener(new class() MenuAdapter {
        public void menuShown(MenuEvent e) {
            Menu menu = cast(Menu)e.widget;
            MenuItem[] items = menu.getItems();
            items[1].setEnabled(table.getSelectionCount() !is 0); // edit contact
            items[5].setEnabled((file !is null) && isModified); // save
            items[6].setEnabled(table.getItemCount() !is 0); // save as
        }
    });


    //File -> New Contact
    MenuItem subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("New_contact"));
    subItem.setAccelerator(DWT.MOD1 + 'N');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            newEntry();
        }
    });
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("Edit_contact"));
    subItem.setAccelerator(DWT.MOD1 + 'E');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            TableItem[] items = table.getSelection();
            if (items.length is 0) return;
            editEntry(items[0]);
        }
    });


    new MenuItem(menu, DWT.SEPARATOR);

    //File -> New Address Book
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("New_address_book"));
    subItem.setAccelerator(DWT.MOD1 + 'B');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            if (closeAddressBook()) {
                newAddressBook();
            }
        }
    });

    //File -> Open
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("Open_address_book"));
    subItem.setAccelerator(DWT.MOD1 + 'O');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            if (closeAddressBook()) {
                openAddressBook();
            }
        }
    });

    //File -> Save.
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("Save_address_book"));
    subItem.setAccelerator(DWT.MOD1 + 'S');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            save();
        }
    });

    //File -> Save As.
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("Save_book_as"));
    subItem.setAccelerator(DWT.MOD1 + 'A');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            saveAs();
        }
    });


    new MenuItem(menu, DWT.SEPARATOR);

    //File -> Exit.
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("Exit"));
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            shell.close();
        }
    });
}

/**
 * Creates all the items located in the Edit submenu and
 * associate all the menu items with their appropriate
 * functions.
 *
 * @param   menuBar Menu
 *              the <code>Menu</code> that file contain
 *              the Edit submenu.
 *
 * @see #createSortMenu()
 */
private MenuItem createEditMenu(Menu menuBar) {
    //Edit menu.
    MenuItem item = new MenuItem(menuBar, DWT.CASCADE);
    item.setText(resAddressBook.getString("Edit_menu_title"));
    Menu menu = new Menu(shell, DWT.DROP_DOWN);
    item.setMenu(menu);

    /**
     * Add a listener to handle enabling and disabling
     * some items in the Edit submenu.
     */
    menu.addMenuListener(new class() MenuAdapter {
        public void menuShown(MenuEvent e) {
            Menu menu = cast(Menu)e.widget;
            MenuItem[] items = menu.getItems();
            int count = table.getSelectionCount();
            items[0].setEnabled(count !is 0); // edit
            items[1].setEnabled(count !is 0); // copy
            items[2].setEnabled(copyBuffer !is null); // paste
            items[3].setEnabled(count !is 0); // delete
            items[5].setEnabled(table.getItemCount() !is 0); // sort
        }
    });

    //Edit -> Edit
    MenuItem subItem = new MenuItem(menu, DWT.PUSH);
    subItem.setText(resAddressBook.getString("Edit"));
    subItem.setAccelerator(DWT.MOD1 + 'E');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            TableItem[] items = table.getSelection();
            if (items.length is 0) return;
            editEntry(items[0]);
        }
    });

    //Edit -> Copy
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("Copy"));
    subItem.setAccelerator(DWT.MOD1 + 'C');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            TableItem[] items = table.getSelection();
            if (items.length is 0) return;
            copyBuffer = new char[][table.getColumnCount()];
            for (int i = 0; i < copyBuffer.length; i++) {
                copyBuffer[i] = items[0].getText(i);
            }
        }
    });

    //Edit -> Paste
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("Paste"));
    subItem.setAccelerator(DWT.MOD1 + 'V');
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            if (copyBuffer is null) return;
            TableItem item = new TableItem(table, DWT.NONE);
            item.setText(copyBuffer);
            isModified = true;
        }
    });

    //Edit -> Delete
    subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("Delete"));
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            TableItem[] items = table.getSelection();
            if (items.length is 0) return;
            items[0].dispose();
            isModified = true;      }
    });

    new MenuItem(menu, DWT.SEPARATOR);

    //Edit -> Sort(Cascade)
    subItem = new MenuItem(menu, DWT.CASCADE);
    subItem.setText(resAddressBook.getString("Sort"));
    Menu submenu = createSortMenu();
    subItem.setMenu(submenu);

    return item;

}

/**
 * Creates all the items located in the Sort cascading submenu and
 * associate all the menu items with their appropriate
 * functions.
 *
 * @return  Menu
 *          The cascading menu with all the sort menu items on it.
 */
private Menu createSortMenu() {
    Menu submenu = new Menu(shell, DWT.DROP_DOWN);
    MenuItem subitem;
    for(int i = 0; i < columnNames.length; i++) {
        subitem = new MenuItem (submenu, DWT.NONE);
        subitem.setText(columnNames [i]);
        final int column = i;
        subitem.addSelectionListener(new class() SelectionAdapter {
            public void widgetSelected(SelectionEvent e) {
                sort(column);
            }
        });

    }

    return submenu;
}

/**
 * Creates all the items located in the Search submenu and
 * associate all the menu items with their appropriate
 * functions.
 *
 * @param   menuBar Menu
 *              the <code>Menu</code> that file contain
 *              the Search submenu.
 */
private void createSearchMenu(Menu menuBar) {
    //Search menu.
    MenuItem item = new MenuItem(menuBar, DWT.CASCADE);
    item.setText(resAddressBook.getString("Search_menu_title"));
    Menu searchMenu = new Menu(shell, DWT.DROP_DOWN);
    item.setMenu(searchMenu);

    //Search -> Find...
    item = new MenuItem(searchMenu, DWT.NONE);
    item.setText(resAddressBook.getString("Find"));
    item.setAccelerator(DWT.MOD1 + 'F');
    item.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            searchDialog.setMatchCase(false);
            searchDialog.setMatchWord(false);
            searchDialog.setSearchDown(true);
            searchDialog.setSearchString("");
            searchDialog.setSelectedSearchArea(0);
            searchDialog.open();
        }
    });

    //Search -> Find Next
    item = new MenuItem(searchMenu, DWT.NONE);
    item.setText(resAddressBook.getString("Find_next"));
    item.setAccelerator(DWT.F3);
    item.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            searchDialog.open();
        }
    });
}

/**
 * Creates all items located in the popup menu and associates
 * all the menu items with their appropriate functions.
 *
 * @return  Menu
 *          The created popup menu.
 */
private Menu createPopUpMenu() {
    Menu popUpMenu = new Menu(shell, DWT.POP_UP);

    /**
     * Adds a listener to handle enabling and disabling
     * some items in the Edit submenu.
     */
    popUpMenu.addMenuListener(new class() MenuAdapter {
        public void menuShown(MenuEvent e) {
            Menu menu = cast(Menu)e.widget;
            MenuItem[] items = menu.getItems();
            int count = table.getSelectionCount();
            items[2].setEnabled(count !is 0); // edit
            items[3].setEnabled(count !is 0); // copy
            items[4].setEnabled(copyBuffer !is null); // paste
            items[5].setEnabled(count !is 0); // delete
            items[7].setEnabled(table.getItemCount() !is 0); // find
        }
    });

    //New
    MenuItem item = new MenuItem(popUpMenu, DWT.PUSH);
    item.setText(resAddressBook.getString("Pop_up_new"));
    item.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            newEntry();
        }
    });

    new MenuItem(popUpMenu, DWT.SEPARATOR);

    //Edit
    item = new MenuItem(popUpMenu, DWT.PUSH);
    item.setText(resAddressBook.getString("Pop_up_edit"));
    item.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            TableItem[] items = table.getSelection();
            if (items.length is 0) return;
            editEntry(items[0]);
        }
    });

    //Copy
    item = new MenuItem(popUpMenu, DWT.PUSH);
    item.setText(resAddressBook.getString("Pop_up_copy"));
    item.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            TableItem[] items = table.getSelection();
            if (items.length is 0) return;
            copyBuffer = new char[][table.getColumnCount()];
            for (int i = 0; i < copyBuffer.length; i++) {
                copyBuffer[i] = items[0].getText(i);
            }
        }
    });

    //Paste
    item = new MenuItem(popUpMenu, DWT.PUSH);
    item.setText(resAddressBook.getString("Pop_up_paste"));
    item.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            if (copyBuffer is null) return;
            TableItem item = new TableItem(table, DWT.NONE);
            item.setText(copyBuffer);
            isModified = true;
        }
    });

    //Delete
    item = new MenuItem(popUpMenu, DWT.PUSH);
    item.setText(resAddressBook.getString("Pop_up_delete"));
    item.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            TableItem[] items = table.getSelection();
            if (items.length is 0) return;
            items[0].dispose();
            isModified = true;
        }
    });

    new MenuItem(popUpMenu, DWT.SEPARATOR);

    //Find...
    item = new MenuItem(popUpMenu, DWT.PUSH);
    item.setText(resAddressBook.getString("Pop_up_find"));
    item.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            searchDialog.open();
        }
    });

    return popUpMenu;
}

/**
 * Creates all the items located in the Help submenu and
 * associate all the menu items with their appropriate
 * functions.
 *
 * @param   menuBar Menu
 *              the <code>Menu</code> that file contain
 *              the Help submenu.
 */
private void createHelpMenu(Menu menuBar) {

    //Help Menu
    MenuItem item = new MenuItem(menuBar, DWT.CASCADE);
    item.setText(resAddressBook.getString("Help_menu_title"));
    Menu menu = new Menu(shell, DWT.DROP_DOWN);
    item.setMenu(menu);

    //Help -> About Text Editor
    MenuItem subItem = new MenuItem(menu, DWT.NONE);
    subItem.setText(resAddressBook.getString("About"));
    subItem.addSelectionListener(new class() SelectionAdapter {
        public void widgetSelected(SelectionEvent e) {
            MessageBox box = new MessageBox(shell, DWT.NONE);
            box.setText(resAddressBook.getString("About_1") + shell.getText());
            box.setMessage(shell.getText() + resAddressBook.getString("About_2"));
            box.open();
        }
    });
}

/**
 * To compare entries (rows) by the given column
 */
private class RowComparator : Comparator {
    private int column;

    /**
     * Constructs a RowComparator given the column index
     * @param col The index (starting at zero) of the column
     */
    public this(int col) {
        column = col;
    }

    /**
     * Compares two rows (type char[][]) using the specified
     * column entry.
     * @param obj1 First row to compare
     * @param obj2 Second row to compare
     * @return negative if obj1 less than obj2, positive if
     *          obj1 greater than obj2, and zero if equal.
     */
    public int compare(Object obj1, Object obj2) {
        char[][] row1 = cast(char[][])obj1;
        char[][] row2 = cast(char[][])obj2;

        return row1[column].compareTo(row2[column]);
    }
}
}