AppleCommander/lib/ac-swt-common/src/main/java/com/webcodepro/applecommander/ui/swt/FileViewerWindow.java

445 lines
18 KiB
Java

/*
* AppleCommander - An Apple ][ image utility.
* Copyright (C) 2003-2022 by Robert Greene
* robgreene at users.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.webcodepro.applecommander.ui.swt;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FileFilter;
import com.webcodepro.applecommander.storage.filters.AppleWorksDataBaseFileFilter;
import com.webcodepro.applecommander.storage.filters.AppleWorksSpreadSheetFileFilter;
import com.webcodepro.applecommander.storage.filters.AppleWorksWordProcessorFileFilter;
import com.webcodepro.applecommander.storage.filters.ApplesoftFileFilter;
import com.webcodepro.applecommander.storage.filters.AssemblySourceFileFilter;
import com.webcodepro.applecommander.storage.filters.BusinessBASICFileFilter;
import com.webcodepro.applecommander.storage.filters.DisassemblyFileFilter;
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
import com.webcodepro.applecommander.storage.filters.GutenbergFileFilter;
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
import com.webcodepro.applecommander.storage.filters.PascalTextFileFilter;
import com.webcodepro.applecommander.storage.filters.ShapeTableFileFilter;
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
import com.webcodepro.applecommander.ui.UiBundle;
import com.webcodepro.applecommander.ui.swt.filteradapter.ApplesoftFilterAdapter;
import com.webcodepro.applecommander.ui.swt.filteradapter.BusinessBASICFilterAdapter;
import com.webcodepro.applecommander.ui.swt.filteradapter.DisassemblyFilterAdapter;
import com.webcodepro.applecommander.ui.swt.filteradapter.FilterAdapter;
import com.webcodepro.applecommander.ui.swt.filteradapter.GraphicsFilterAdapter;
import com.webcodepro.applecommander.ui.swt.filteradapter.HexFilterAdapter;
import com.webcodepro.applecommander.ui.swt.filteradapter.RawDumpFilterAdapter;
import com.webcodepro.applecommander.ui.swt.filteradapter.ShapeTableFilterAdapter;
import com.webcodepro.applecommander.ui.swt.filteradapter.TextFilterAdapter;
import com.webcodepro.applecommander.ui.swt.util.ImageManager;
import com.webcodepro.applecommander.ui.swt.util.SwtUtil;
import com.webcodepro.applecommander.ui.swt.util.contentadapter.ContentTypeAdapter;
import com.webcodepro.applecommander.util.TextBundle;
/**
* View a particular files content.
* <p>
* Date created: Dec 7, 2003
* @author Rob Greene
*/
public class FileViewerWindow {
private static final char CTRL_A = 'A' - '@';
private static final char CTRL_P = 'P' - '@';
private static final char CTRL_C = 'C' - '@';
private TextBundle textBundle = UiBundle.getInstance();
private Shell parentShell;
private ImageManager imageManager;
private Shell shell;
private FileEntry fileEntry;
private FileFilter nativeFilter;
private ScrolledComposite content;
private ToolBar toolBar;
private ToolItem nativeToolItem;
private ToolItem hexDumpToolItem;
private ToolItem rawDumpToolItem;
private ToolItem copyToolItem;
// May or may not be setup
private Optional<ToolItem> disassemblyToolItem = Optional.empty();
private Optional<ToolItem> shapeTableToolItem = Optional.empty();
private Font courier;
private ContentTypeAdapter contentTypeAdapter;
private Map<Class<?>,FilterAdapter> nativeFilterAdapterMap;
private FilterAdapter nativeFilterAdapter;
private FilterAdapter hexFilterAdapter;
private FilterAdapter rawDumpFilterAdapter;
private FilterAdapter disassemblyFilterAdapter;
private FilterAdapter shapeTableFilterAdapter;
/**
* Construct the file viewer window.
*/
public FileViewerWindow(Shell parentShell, FileEntry fileEntry, ImageManager imageManager) {
this(parentShell, fileEntry, imageManager, fileEntry.getSuggestedFilter());
}
/**
* Construct the file viewer window.
*/
public FileViewerWindow(Shell parentShell, FileEntry fileEntry, ImageManager imageManager, FileFilter nativeFilter) {
this.parentShell = shell;
this.fileEntry = fileEntry;
this.imageManager = imageManager;
this.nativeFilter = nativeFilter;
createFilterAdapterMap();
}
/**
* Setup the File Viewer window and display (open) it.
*/
public void open() {
shell = new Shell(parentShell, SWT.SHELL_TRIM);
shell.setLayout(new FillLayout());
shell.setImage(imageManager.get(ImageManager.ICON_DISK));
shell.setText(textBundle.format("FileViewerWindow.Title", //$NON-NLS-1$
fileEntry.getFilename()));
shell.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent event) {
dispose(event);
}
});
Composite composite = new Composite(shell, SWT.NULL);
GridLayout gridLayout = new GridLayout(1, false);
composite.setLayout(gridLayout);
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
createToolBar(composite, gridData);
content = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
gridData = new GridData(GridData.FILL_BOTH);
content.setLayoutData(gridData);
content.addListener(SWT.KeyUp, createToolbarCommandHandler());
courier = new Font(shell.getDisplay(), "Courier", 10, SWT.NORMAL); //$NON-NLS-1$
nativeFilterAdapter.display();
shell.open();
SwtUtil.setupPagingInformation(content);
}
/**
* Setup all possible specialized FilterAdapters.
*/
protected void createFilterAdapterMap() {
nativeFilterAdapterMap = new HashMap<>();
nativeFilterAdapterMap.put(ApplesoftFileFilter.class,
new ApplesoftFilterAdapter(this, textBundle.get("FileViewerWindow.ApplesoftButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.ApplesoftTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_BASIC_PROGRAM)
));
nativeFilterAdapterMap.put(BusinessBASICFileFilter.class,
new BusinessBASICFilterAdapter(this, textBundle.get("FileViewerWindow.BusinessBASICButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.BusinessBASICTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_BASIC_PROGRAM)
));
nativeFilterAdapterMap.put(AppleWorksDataBaseFileFilter.class,
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.DatabaseButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.DatabaseTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_DATABASE)
));
nativeFilterAdapterMap.put(AppleWorksSpreadSheetFileFilter.class,
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.SpreadsheetButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.SpreadsheetTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_SPREADSHEET)
));
nativeFilterAdapterMap.put(AppleWorksWordProcessorFileFilter.class,
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.WordprocessorButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.WordprocessorTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_WORDPROCESSOR)
));
nativeFilterAdapterMap.put(GutenbergFileFilter.class,
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.WordprocessorButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.WordprocessorTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_WORDPROCESSOR)
));
nativeFilterAdapterMap.put(AssemblySourceFileFilter.class,
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.AssemblyButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.AssemblyTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_TEXTFILE)
));
nativeFilterAdapterMap.put(GraphicsFileFilter.class,
new GraphicsFilterAdapter(this, textBundle.get("FileViewerWindow.ImageButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.ImageTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_IMAGE)
));
nativeFilterAdapterMap.put(IntegerBasicFileFilter.class,
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.IntegerBasicButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.IntegerBasicTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_BASIC_PROGRAM)
));
nativeFilterAdapterMap.put(PascalTextFileFilter.class,
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.PascalTextButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.PascalTextTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_TEXTFILE)
));
nativeFilterAdapterMap.put(TextFileFilter.class,
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.TextButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.TextTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_AS_TEXTFILE)
));
nativeFilterAdapterMap.put(DisassemblyFileFilter.class,
new DisassemblyFilterAdapter(this, textBundle.get("FileViewerWindow.DisassemblyButton"),
textBundle.get("FileViewerWindow.DisassemblyTooltip"),
imageManager.get(ImageManager.ICON_COMPILE_FILE)
));
nativeFilterAdapterMap.put(ShapeTableFileFilter.class,
new ShapeTableFilterAdapter(this, textBundle.get("FileViewerWindow.ShapeTableButton"),
textBundle.get("FileViewerWindow.ShapeTableTooltip"),
imageManager.get(ImageManager.ICON_SHAPE_TABLE)
));
}
/**
* Dispose of all shared resources.
*/
protected void dispose(DisposeEvent event) {
courier.dispose();
if (nativeFilterAdapter != null) nativeFilterAdapter.dispose();
hexFilterAdapter.dispose();
rawDumpFilterAdapter.dispose();
System.gc();
}
/**
* Creates the toolbar.
*/
private void createToolBar(Composite composite, Object layoutData) {
toolBar = new ToolBar(composite, SWT.FLAT);
toolBar.addListener(SWT.KeyUp, createToolbarCommandHandler());
if (layoutData != null) toolBar.setLayoutData(layoutData);
if (nativeFilter != null) {
nativeFilterAdapter = (FilterAdapter) nativeFilterAdapterMap.get(nativeFilter.getClass());
if (nativeFilterAdapter != null) {
nativeToolItem = nativeFilterAdapter.create(toolBar);
nativeToolItem.setSelection(true);
}
}
hexDumpToolItem = createHexDumpToolItem();
if (nativeFilterAdapter == null) {
// Default button changes for these instances.
hexDumpToolItem.setSelection(true);
// Prevent NullPointerExceptions if the nativeFilterAdapter does not apply.
nativeFilterAdapter = hexFilterAdapter;
}
rawDumpToolItem = createRawDumpToolItem();
// Add the disassembly button only if it's not the default and if this filetype has a start address.
if (fileEntry != null && fileEntry.needsAddress() && !(nativeFilter instanceof DisassemblyFileFilter)) {
disassemblyToolItem = Optional.of(createDisassemblyToolItem());
shapeTableToolItem = Optional.of(createShapeTableToolItem());
}
new ToolItem(toolBar, SWT.SEPARATOR);
copyToolItem = createCopyToolItem();
new ToolItem(toolBar, SWT.SEPARATOR);
createPrintToolItem();
toolBar.pack();
}
/**
* Create the hex dump tool item (button).
*/
protected ToolItem createHexDumpToolItem() {
hexFilterAdapter = new HexFilterAdapter(this, textBundle.get("FileViewerWindow.HexDumpButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.HexDumpTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_IN_HEX));
hexFilterAdapter.setHexSelected();
ToolItem toolItem = hexFilterAdapter.create(toolBar);
return toolItem;
}
/**
* Create the raw dump tool item (button).
*/
protected ToolItem createRawDumpToolItem() {
rawDumpFilterAdapter = new RawDumpFilterAdapter(this, textBundle.get("FileViewerWindow.RawDumpButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.RawDumpTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_VIEW_IN_RAW_HEX));
rawDumpFilterAdapter.setDumpSelected();
ToolItem toolItem = rawDumpFilterAdapter.create(toolBar);
return toolItem;
}
/**
* Create the disassembly tool item (button).
*/
protected ToolItem createDisassemblyToolItem() {
disassemblyFilterAdapter = new DisassemblyFilterAdapter(this, textBundle.get("FileViewerWindow.DisassemblyButton"), //$NON-NLS-1$
textBundle.get("FileViewerWindow.DisassemblyTooltip"), //$NON-NLS-1$
imageManager.get(ImageManager.ICON_COMPILE_FILE));
disassemblyFilterAdapter.setDisassemblySelected();
ToolItem toolItem = disassemblyFilterAdapter.create(toolBar);
return toolItem;
}
/**
* Create the shape table tool item (button).
*/
protected ToolItem createShapeTableToolItem() {
shapeTableFilterAdapter = new ShapeTableFilterAdapter(this, textBundle.get("FileViewerWindow.ShapeTableButton"),
textBundle.get("FileViewerWindow.ShapeTableTooltip"),
imageManager.get(ImageManager.ICON_SHAPE_TABLE));
shapeTableFilterAdapter.setShapeTableSelected();
ToolItem toolItem = shapeTableFilterAdapter.create(toolBar);
return toolItem;
}
/**
* Create the copy tool item (button).
*/
protected ToolItem createCopyToolItem() {
ToolItem toolItem = new ToolItem(toolBar, SWT.PUSH);
toolItem.setImage(imageManager.get(ImageManager.ICON_COPY));
toolItem.setText(textBundle.get("FileViewerWindow.CopyButton")); //$NON-NLS-1$
toolItem.setToolTipText(textBundle.get("FileViewerWindow.CopyTooltip")); //$NON-NLS-1$
toolItem.setEnabled(true);
toolItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
getContentTypeAdapter().copy();
}
});
return toolItem;
}
/**
* Create the print tool item (button).
*/
protected ToolItem createPrintToolItem() {
ToolItem toolItem = new ToolItem(toolBar, SWT.PUSH);
toolItem.setImage(imageManager.get(ImageManager.ICON_PRINT_FILE));
toolItem.setText(textBundle.get("PrintButton")); //$NON-NLS-1$
toolItem.setToolTipText(textBundle.get("FileViewerWindow.PrintTooltip")); //$NON-NLS-1$
toolItem.setEnabled(true);
toolItem.addSelectionListener(new SelectionAdapter () {
public void widgetSelected(SelectionEvent e) {
getContentTypeAdapter().print();
}
});
return toolItem;
}
/**
* The toolbar command handler contains the global toolbar
* actions. The intent is that the listener is then added to
* multiple visual components.
*/
public Listener createToolbarCommandHandler() {
return new Listener() {
public void handleEvent(Event event) {
if (event.type == SWT.KeyUp) {
if ((event.stateMask & SWT.CTRL) != 0) { // CTRL+key
switch (event.character) {
case CTRL_C:
getContentTypeAdapter().copy();
break;
case CTRL_A:
getContentTypeAdapter().selectAll();
break;
case CTRL_P:
getContentTypeAdapter().print();
break;
}
} else if ((event.stateMask & SWT.ALT) == 0) { // key alone
switch (event.keyCode) {
case SWT.F2: // the "native" file format (image, text, etc)
getNativeFilterAdapter().display();
setFilterToolItemSelection(true, false, false, false, false);
break;
case SWT.F3: // Hex format
getHexFilterAdapter().display();
setFilterToolItemSelection(false, true, false, false, false);
break;
case SWT.F4: // "Raw" hex format
getRawDumpFilterAdapter().display();
setFilterToolItemSelection(false, false, true, false, false);
break;
}
}
}
}
};
}
public FileFilter getFileFilter() {
return nativeFilter;
}
public FileEntry getFileEntry() {
return fileEntry;
}
public ToolItem getCopyToolItem() {
return copyToolItem;
}
public ScrolledComposite getComposite() {
return content;
}
public void setContentTypeAdapter(ContentTypeAdapter adapter) {
this.contentTypeAdapter = adapter;
}
public Font getCourierFont() {
return courier;
}
public void setFilterToolItemSelection(boolean nativeSelected, boolean hexSelected, boolean dumpSelected,
boolean disassemblySelected, boolean shapeTableSelected) {
if (nativeToolItem != null) nativeToolItem.setSelection(nativeSelected);
hexDumpToolItem.setSelection(hexSelected);
rawDumpToolItem.setSelection(dumpSelected);
disassemblyToolItem.ifPresent(toolItem -> toolItem.setSelection(disassemblySelected));
shapeTableToolItem.ifPresent(toolItem -> toolItem.setSelection(shapeTableSelected));
}
protected ContentTypeAdapter getContentTypeAdapter() {
return contentTypeAdapter;
}
protected FilterAdapter getHexFilterAdapter() {
return hexFilterAdapter;
}
protected FilterAdapter getNativeFilterAdapter() {
return nativeFilterAdapter;
}
protected FilterAdapter getRawDumpFilterAdapter() {
return rawDumpFilterAdapter;
}
}