Mercurial > projects > dwt-samples
view jface/Librarian.d @ 143:42c3056512ba
redirect the jface examples to the new collection wrappers
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Thu, 07 Aug 2008 22:21:50 +0200 |
parents | 9ff9b8f7284b |
children |
line wrap: on
line source
module jface.Librarian; import dwtx.core.runtime.IProgressMonitor; import dwtx.jface.action.MenuManager; import dwtx.jface.action.StatusLineManager; import dwtx.jface.action.ToolBarManager; import dwtx.jface.action.CoolBarManager; import dwtx.jface.action.Action; import dwtx.jface.action.IAction; import dwtx.jface.dialogs.MessageDialog; import dwtx.jface.operation.IRunnableWithProgress; import dwtx.jface.operation.ModalContext; import dwtx.jface.util.IPropertyChangeListener; import dwtx.jface.util.PropertyChangeEvent; import dwtx.jface.viewers.TableViewer; import dwtx.jface.viewers.Viewer; import dwtx.jface.viewers.ITableLabelProvider; import dwtx.jface.viewers.IStructuredContentProvider; import dwtx.jface.viewers.ICellModifier; import dwtx.jface.viewers.ILabelProviderListener; import dwtx.jface.viewers.TextCellEditor; import dwtx.jface.viewers.CellEditor; import dwtx.jface.viewers.CheckboxCellEditor; import dwtx.jface.action.Separator; import dwtx.jface.viewers.IStructuredSelection; import dwtx.jface.window.ApplicationWindow; import dwtx.jface.resource.ImageDescriptor; import dwt.DWT; import dwt.graphics.Image; import dwt.graphics.ImageData; import dwt.layout.GridData; import dwt.layout.GridLayout; import dwt.widgets.Display; import dwt.widgets.FileDialog; import dwt.widgets.MessageBox; import dwt.widgets.Shell; import dwt.widgets.Table; import dwt.widgets.TableColumn; import dwt.widgets.Control; import dwt.widgets.Composite; import dwt.widgets.Item; import dwt.dwthelper.utils; import dwt.dwthelper.ByteArrayInputStream; import tango.text.convert.Format; import tango.io.FilePath; import tango.io.File; import tango.io.Print; import tango.io.stream.FileStream; import tango.text.Util; import tango.text.stream.LineIterator; import tango.util.log.Trace; import dwtx.dwtxhelper.Collection; version(JIVE) import jive.stacktrace; /** * The application entry point * * @param args the command line arguments */ void main() { (new Librarian()).run(); } /** * This class keeps track of you library, and who you've loaned books to */ public class Librarian : ApplicationWindow { // A static instance to the running application private static Librarian APP; // Table column names/properties public static const String TITLE = "Title"; public static const String CHECKED_OUT = "?"; public static const String WHO = "By Whom"; public static const String[] PROPS = [ TITLE, CHECKED_OUT, WHO ]; // The viewer private TableViewer viewer; // The current library private Library library; // The actions private NewAction newAction; private OpenAction openAction; private SaveAction saveAction; private SaveAsAction saveAsAction; private ExitAction exitAction; private AddBookAction addBookAction; private RemoveBookAction removeBookAction; private AboutAction aboutAction; private ShowBookCountAction showBookCountAction; /** * Gets the running application */ public static Librarian getApp() { return APP; } /** * Librarian constructor */ public this() { super(null); APP = this; // Create the data model library = new Library(); // Create the actions newAction = new NewAction(); openAction = new OpenAction(); saveAction = new SaveAction(); saveAsAction = new SaveAsAction(); exitAction = new ExitAction(); addBookAction = new AddBookAction(); removeBookAction = new RemoveBookAction(); aboutAction = new AboutAction(); showBookCountAction = new ShowBookCountAction(); addMenuBar(); //addCoolBar(DWT.NONE); addToolBar(DWT.FLAT); addStatusLine(); } /** * Runs the application */ public void run() { // Don't return from open() until window closes setBlockOnOpen(true); // Open the main window open(); // Dispose the display Display.getCurrent().dispose(); } /** * Configures the shell * * @param shell the shell */ protected void configureShell(Shell shell) { super.configureShell(shell); // Set the title bar text shell.setText("Librarian"); } /** * Creates the main window's contents * * @param parent the main window * @return Control */ protected Control createContents(Composite parent) { Composite composite = new Composite(parent, DWT.NONE); composite.setLayout(new GridLayout(1, false)); viewer = new TableViewer(composite, DWT.FULL_SELECTION | DWT.BORDER); Table table = viewer.getTable(); table.setLayoutData(new GridData(GridData.FILL_BOTH)); // Set up the viewer viewer.setContentProvider(new LibraryContentProvider()); viewer.setLabelProvider(new LibraryLabelProvider()); viewer.setInput(library); viewer.setColumnProperties(PROPS); viewer.setCellEditors( [ cast(CellEditor) new TextCellEditor(table), new CheckboxCellEditor(table), new TextCellEditor(table)]); viewer.setCellModifier(new LibraryCellModifier()); // Set up the table for (int i = 0, n = PROPS.length; i < n; i++) (new TableColumn(table, DWT.LEFT)).setText(PROPS[i]); table.setHeaderVisible(true); table.setLinesVisible(true); // Add code to hide or display the book count based on the action showBookCountAction.addPropertyChangeListener(new class IPropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { // The value has changed; refresh the view refreshView(); } }); // Rfresh the view to get the columns right-sized refreshView(); return composite; } /** * Creates the menu for the application * * @return MenuManager */ protected MenuManager createMenuManager() { // Create the main menu MenuManager mm = new MenuManager(); // Create the File menu MenuManager fileMenu = new MenuManager("File"); mm.add(fileMenu); // Add the actions to the File menu fileMenu.add(newAction); fileMenu.add(openAction); fileMenu.add(saveAction); fileMenu.add(saveAsAction); fileMenu.add(new Separator()); fileMenu.add(exitAction); // Create the Book menu MenuManager bookMenu = new MenuManager("Book"); mm.add(bookMenu); // Add the actions to the Book menu bookMenu.add(addBookAction); bookMenu.add(removeBookAction); // Create the View menu MenuManager viewMenu = new MenuManager("View"); mm.add(viewMenu); // Add the actions to the View menu viewMenu.add(showBookCountAction); // Create the Help menu MenuManager helpMenu = new MenuManager("Help"); mm.add(helpMenu); // Add the actions to the Help menu helpMenu.add(aboutAction); return mm; } /** * Creates the toolbar for the application */ protected ToolBarManager createToolBarManager(int style) { // Create the toolbar manager ToolBarManager tbm = new ToolBarManager(style); // Add the file actions tbm.add(newAction); tbm.add(openAction); tbm.add(saveAction); tbm.add(saveAsAction); // Add a separator tbm.add(new Separator()); // Add the book actions tbm.add(addBookAction); tbm.add(removeBookAction); // Add a separator tbm.add(new Separator()); // Add the show book count, which will appear as a toggle button tbm.add(showBookCountAction); // Add a separator tbm.add(new Separator()); // Add the about action tbm.add(aboutAction); return tbm; } /+ /** * Creates the coolbar for the application */ protected CoolBarManager createCoolBarManager(int style) { // Create the coolbar manager CoolBarManager cbm = new CoolBarManager(style); // Add the toolbar cbm.add(createToolBarManager(DWT.FLAT)); return cbm; } +/ /** * Creates the status line manager */ protected StatusLineManager createStatusLineManager() { return new StatusLineManager(); } /** * Adds a book */ public void addBook() { library.add(new Book("[Enter Title]")); refreshView(); } /** * Removes the selected book */ public void removeSelectedBook() { Book book = cast(Book) (cast(IStructuredSelection) viewer.getSelection()) .getFirstElement(); if (book !is null) library.remove(book); refreshView(); } /** * Opens a file * * @param fileName the file name */ public void openFile(String fileName) { if (checkOverwrite()) { // Disable the actions, so user can't change library while loading enableActions(false); library = new Library(); try { // Launch the Open runnable ModalContext.run( dgIRunnableWithProgress( &internalOpen, fileName ), true, getStatusLineManager().getProgressMonitor(), getShell().getDisplay()); } catch (InterruptedException e) { } catch (InvocationTargetException e) { } finally { // Enable actions enableActions(true); } } } private void internalOpen( IProgressMonitor progressMonitor,String filename ){ try { progressMonitor.beginTask("Loading", IProgressMonitor.UNKNOWN); library.load(filename); progressMonitor.done(); viewer.setInput(library); refreshView(); } catch (IOException e) { showError( Format("Can't load file {}\r{}", filename, e.msg)); } } /** * Creates a new file */ public void newFile() { if (checkOverwrite()) { library = new Library(); viewer.setInput(library); } } /** * Saves the current file */ public void saveFile() { String fileName = library.getFileName(); if (fileName is null) { fileName = (new SafeSaveDialog(getShell())).open(); } if (fileName is null) { return; } saveFileAs(fileName); } /** * Saves the current file using the specified file name * * @param fileName the file name */ public void saveFileAs(String fileName) { // Disable the actions, so user can't change file while it's saving enableActions(false); try { auto pm = getStatusLineManager().getProgressMonitor(); auto disp = getShell().getDisplay(); // Launch the Save runnable ModalContext.run( dgIRunnableWithProgress( &internalSave, fileName ), true, pm, disp); } catch (InterruptedException e) { } catch (InvocationTargetException e) { } finally { // Enable the actions enableActions(true); } } private void internalSave(IProgressMonitor progressMonitor,String filename ){ try { progressMonitor.beginTask("Saving", IProgressMonitor.UNKNOWN ); library.save(filename); progressMonitor.done(); } catch (IOException e) { showError(Format("Can't save file {}\r{}", library.getFileName(), e.msg )); } } /** * Shows an error * * @param msg the error */ public void showError(String msg) { MessageDialog.openError(getShell(), "Error", msg); } /** * Refreshes the view */ public void refreshView() { // Refresh the view viewer.refresh(); // Repack the columns for (int i = 0, n = viewer.getTable().getColumnCount(); i < n; i++) { viewer.getTable().getColumn(i).pack(); } getStatusLineManager().setMessage( showBookCountAction.isChecked() ? Format( "Book Count: {}", library.getBooks().size()) : ""); } /** * Checks the current file for unsaved changes. If it has unsaved changes, * confirms that user wants to overwrite * * @return bool */ public bool checkOverwrite() { bool proceed = true; if (library.isDirty()) { proceed = MessageDialog.openConfirm(getShell(), "Are you sure?", "You have unsaved changes--are you sure you want to lose them?"); } return proceed; } /** * Sets the current library dirty */ public void setLibraryDirty() { library.setDirty(); } /** * Closes the application */ public bool close() { if (checkOverwrite()) return super.close(); return false; } /** * Enables or disables the actions * * @param enable true to enable, false to disable */ private void enableActions(bool enable) { newAction.setEnabled(enable); openAction.setEnabled(enable); saveAction.setEnabled(enable); saveAsAction.setEnabled(enable); exitAction.setEnabled(enable); addBookAction.setEnabled(enable); removeBookAction.setEnabled(enable); aboutAction.setEnabled(enable); showBookCountAction.setEnabled(enable); } } /** * This action class responds to requests to save a file */ public class SaveAction : Action { /** * SaveAction constructor */ public this() { super("&Save@Ctrl+S", ImageDescriptor.createFromFile( getImportData!("jface.librarian.save.gif"))); setDisabledImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.disabledSave.gif"))); setToolTipText("Save"); } /** * Saves the file */ public void run() { Librarian.getApp().saveFile(); } } /** * This action class responds to requests open a file */ public class OpenAction : Action { /** * OpenAction constructor */ public this() { super("&Open...@Ctrl+O", ImageDescriptor.createFromFile(getImportData!("jface.librarian.open.gif"))); setDisabledImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.disabledOpen.gif"))); setToolTipText("Open"); } /** * Opens an existing file */ public void run() { // Use the file dialog FileDialog dlg = new FileDialog(Librarian.getApp().getShell(), DWT.OPEN); String fileName = dlg.open(); if (fileName !is null) { Librarian.getApp().openFile(fileName); } } } /** * This action class reponds to requests for a new file */ public class NewAction : Action { /** * NewAction constructor */ public this() { super("&New@Ctrl+N", ImageDescriptor.createFromFile(getImportData!("jface.librarian.new.gif"))); setDisabledImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.disabledNew.gif"))); setToolTipText("New"); } /** * Creates a new file */ public void run() { Librarian.getApp().newFile(); } } /** * This action class responds to requests to save a file as . . . */ public class SaveAsAction : Action { /** * SaveAsAction constructor */ public this() { super("Save As...", ImageDescriptor.createFromFile(getImportData!("jface.librarian.saveAs.gif"))); setDisabledImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.disabledSaveAs.gif"))); setToolTipText("Save As"); } /** * Saves the file */ public void run() { SafeSaveDialog dlg = new SafeSaveDialog(Librarian.getApp().getShell()); String fileName = dlg.open(); if (fileName !is null) { Librarian.getApp().saveFileAs(fileName); } } } /** * This action class deletes a book */ public class RemoveBookAction : Action { /** * RemoveBookAction constructor */ public this() { super("&Remove Book@Ctrl+X", ImageDescriptor.createFromFile(getImportData!("jface.librarian.removeBook.gif"))); setDisabledImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.disabledRemoveBook.gif"))); setToolTipText("Remove"); } /** * Removes the selected book after confirming */ public void run() { if (MessageDialog.openConfirm(Librarian.getApp().getShell(), "Are you sure?", "Are you sure you want to remove the selected book?")) { Librarian.getApp().removeSelectedBook(); } } } /** * This action class adds a book */ public class AddBookAction : Action { /** * AddBookAction constructor */ public this() { super("&Add Book@Ctrl+B", ImageDescriptor.createFromFile(getImportData!("jface.librarian.addBook.gif"))); setDisabledImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.disabledAddBook.gif"))); setToolTipText("Add"); } /** * Adds a book to the current library */ public void run() { Librarian.getApp().addBook(); } } /** * This action class exits the application */ public class ExitAction : Action { /** * ExitAction constructor */ public this() { super("E&xit@Alt+F4"); setToolTipText("Exit"); } /** * Exits the application */ public void run() { Librarian.getApp().close(); } } /** * This action class shows an About box */ public class AboutAction : Action { /** * AboutAction constructor */ public this() { super("&About@Ctrl+A", ImageDescriptor.createFromFile(getImportData!("jface.librarian.about.gif"))); setDisabledImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.disabledAbout.gif"))); setToolTipText("About"); } /** * Shows an about box */ public void run() { MessageDialog.openInformation(Librarian.getApp().getShell(), "About", "Librarian--to manage your books"); } } /** * This action class determines whether to show the book count */ public class ShowBookCountAction : Action { public this() { super("&Show Book Count@Ctrl+C", IAction.AS_CHECK_BOX); setChecked(true); setImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.count.gif"))); setDisabledImageDescriptor(ImageDescriptor.createFromFile(getImportData!("jface.librarian.disabledCount.gif"))); } } /** * This class represents a book */ public class Book { private String title; private String checkedOutTo; /** * Book constructor * @param title the title */ public this(String title) { setTitle(title); } /** * Sets the title * @param title the title */ public void setTitle(String title) { this.title = title; } /** * Gets the title * @return String */ public String getTitle() { return title; } /** * Check out * @param who the person checking this book out */ public void checkOut(String who) { checkedOutTo = who; if (checkedOutTo.length is 0) checkedOutTo = null; } public bool isCheckedOut() { return checkedOutTo !is null && checkedOutTo.length > 0; } public void checkIn() { checkedOutTo = null; } /** * Gets who this book is checked out to * @return String */ public String getCheckedOutTo() { return checkedOutTo; } } /** * This class provides a facade for the "save" * FileDialog class. If the selected file already * exists, the user is asked to confirm before * overwriting. */ public class SafeSaveDialog { // The wrapped FileDialog private FileDialog dlg; /** * SafeSaveDialog constructor * @param shell the parent shell */ public this(Shell shell) { dlg = new FileDialog(shell, DWT.SAVE); } public String open() { // We store the selected file name in fileName String fileName = null; // The user has finished when one of the // following happens: // 1) The user dismisses the dialog by pressing Cancel // 2) The selected file name does not exist // 3) The user agrees to overwrite existing file bool done = false; while (!done) { // Open the File Dialog fileName = dlg.open(); if (fileName is null) { // User has cancelled, so quit and return done = true; } else { // User has selected a file; see if it already exists FilePath file = new FilePath(fileName); if (file.exists()) { // The file already exists; asks for confirmation MessageBox mb = new MessageBox(dlg.getParent(), DWT.ICON_WARNING | DWT.YES | DWT.NO); // We really should read this string from a // resource bundle mb.setMessage(fileName ~ " already exists. Do you want to replace it?"); // If they click Yes, we're done and we drop out. If // they click No, we redisplay the File Dialog done = mb.open() is DWT.YES; } else { // File does not exist, so drop out done = true; } } } return fileName; } public String getFileName() { return dlg.getFileName(); } public String[] getFileNames() { return dlg.getFileNames(); } public String[] getFilterExtensions() { return dlg.getFilterExtensions(); } public String[] getFilterNames() { return dlg.getFilterNames(); } public String getFilterPath() { return dlg.getFilterPath(); } public void setFileName(String string) { dlg.setFileName(string); } public void setFilterExtensions(String[] extensions) { dlg.setFilterExtensions(extensions); } public void setFilterNames(String[] names) { dlg.setFilterNames(names); } public void setFilterPath(String string) { dlg.setFilterPath(string); } public Shell getParent() { return dlg.getParent(); } public int getStyle() { return dlg.getStyle(); } public String getText() { return dlg.getText(); } public void setText(String string) { dlg.setText(string); } } /** * This class is the cell modifier for the Librarian program */ public class LibraryCellModifier : ICellModifier { /** * Gets whether the specified property can be modified * * @param element the book * @param property the property * @return bool */ public bool canModify(Object element, String property) { return true; } /** * Gets the value for the property * * @param element the book * @param property the property * @return Object */ public Object getValue(Object element, String property) { Book book = cast(Book) element; if (Librarian.TITLE.equals(property)) return stringcast(book.getTitle()); else if (Librarian.CHECKED_OUT.equals(property)) return Boolean.valueOf(book.isCheckedOut()); else if (Librarian.WHO.equals(property)) return stringcast( book.getCheckedOutTo() is null ? "" : book.getCheckedOutTo()); else return null; } /** * Modifies the element * * @param element the book * @param property the property * @param value the new value */ public void modify(Object element, String property, Object value) { if ( auto item = cast(Item)element ){ element = item.getData(); } Book book = cast(Book) element; if (Librarian.TITLE.equals(property)) book.setTitle(stringcast(value)); else if (Librarian.CHECKED_OUT.equals(property)) { bool b = (cast(Boolean) value).booleanValue(); if (b) book.checkOut("[Enter Name]"); else book.checkIn(); } else if (Librarian.WHO.equals(property)) book.checkOut(stringcast(value)); // Refresh the view Librarian.getApp().refreshView(); // Set the library dirty Librarian.getApp().setLibraryDirty(); } } /** * This class holds all the books in a library. It also handles loading from and * saving to disk */ public class Library { private static const String SEP = "|"; // The filename private String filename; // The books private LinkedList books; // The dirty flag private bool dirty; /** * Library constructor Note the signature :-) */ public this() { books = new LinkedList(); } /** * Loads the library from a file * * @param filename the filename * @throws IOException */ public void load(String filename) { auto istr = (new FileInput(filename)).input; auto lines = new LineIterator!(char)(istr); String line; foreach (line; lines ) { auto tokens = tango.text.Util.delimit(line, SEP); Book book = null; if ( tokens.length > 0 ) book = new Book( tokens[0].dup ); if (tokens.length > 1) book.checkOut(tokens[1].dup ); if (book !is null) add(book); } istr.close(); this.filename = filename; dirty = false; } /** * Saves the library to a file * * @param filename the filename * @throws IOException */ public void save(String filename) { scope ostr = (new FileOutput(filename)).output; scope printer = new Print!(char)( Format, ostr ); foreach ( o; books ) { Book book = cast(Book)o; printer.formatln( "{}|{}",book.getTitle(), (book.getCheckedOutTo() is null ? "" : book.getCheckedOutTo())); } ostr.close(); this.filename = filename; dirty = false; } /** * Adds a book * * @param book the book to add * @return bool */ public bool add(Book book) { books.add(book); setDirty(); return true; } /** * Removes a book * * @param book the book to remove */ public void remove(Book book) { books.remove(book); setDirty(); } /** * Gets the books * * @return Collection */ public LinkedList getBooks() { return books; } /** * Gets the file name * * @return String */ public String getFileName() { return filename; } /** * Gets whether this file is dirty * * @return bool */ public bool isDirty() { return dirty; } /** * Sets this file as dirty */ public void setDirty() { dirty = true; } } /** * This class provides the content for the library table */ public class LibraryContentProvider : IStructuredContentProvider { /** * Gets the books * * @param inputElement the library * @return Object[] */ public Object[] getElements(Object inputElement) { return (cast(Library) inputElement).getBooks().toArray(); } /** * Disposes any resources */ public void dispose() { // Do nothing } /** * Called when the input changes * * @param viewer the viewer * @param oldInput the old library * @param newInput the new library */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // Ignore } } /** * This class provides the labels for the library table */ public class LibraryLabelProvider : ITableLabelProvider { private Image checked; private Image unchecked; /** * LibraryLabelProvider constructor */ public this() { // Create the check mark images checked = new Image(null, new ImageData( new ByteArrayInputStream( cast(byte[])import("jface.librarian.checked.gif")))); unchecked = new Image(null,new ImageData( new ByteArrayInputStream( cast(byte[])import("jface.librarian.unchecked.gif")))); } /** * Gets the column image * * @param element the book * @param columnIndex the column index * @return Image */ public Image getColumnImage(Object element, int columnIndex) { // For the "Checked Out" column, return the check mark // if the book is checked out if (columnIndex is 1) return (cast(Book) element).isCheckedOut() ? checked : unchecked; return null; } /** * Gets the column text * * @param element the book * @param columnIndex the column index * @return String */ public String getColumnText(Object element, int columnIndex) { Book book = cast(Book) element; String text = null; switch (columnIndex) { case 0: text = book.getTitle(); break; case 2: text = book.getCheckedOutTo(); break; default: } return text is null ? "" : text; } /** * Adds a listener */ public void addListener(ILabelProviderListener listener) { // Ignore } /** * Disposes any resources */ public void dispose() { if (checked !is null) checked.dispose(); if (unchecked !is null) unchecked.dispose(); } /** * Gets whether this is a label property * * @param element the book * @param property the property * @return bool */ public bool isLabelProperty(Object element, String property) { return false; } /** * Removes a listener * * @param listener the listener */ public void removeListener(ILabelProviderListener listener) { // Ignore } }