package com.kartoflane.superluminal2.ui.sidebar; import java.io.File; import java.util.HashMap; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Text; import com.kartoflane.superluminal2.components.enums.Images; import com.kartoflane.superluminal2.core.Manager; import com.kartoflane.superluminal2.ftl.GibObject; import com.kartoflane.superluminal2.ftl.ShipObject; import com.kartoflane.superluminal2.mvc.controllers.AbstractController; import com.kartoflane.superluminal2.mvc.controllers.GibController; import com.kartoflane.superluminal2.ui.BrowseMenu; import com.kartoflane.superluminal2.ui.DatabaseFileDialog; import com.kartoflane.superluminal2.ui.EditorWindow; import com.kartoflane.superluminal2.ui.GibWidget; import com.kartoflane.superluminal2.ui.ImageViewerDialog; import com.kartoflane.superluminal2.ui.ShipContainer; import com.kartoflane.superluminal2.ui.sidebar.data.DataComposite; import com.kartoflane.superluminal2.undo.UndoablePropertyEdit; import com.kartoflane.superluminal2.utils.IOUtils; import com.kartoflane.superluminal2.utils.UIUtils; @SuppressWarnings("serial") public class ImagesToolComposite extends Composite implements DataComposite { private static String prevImagesPath = System.getProperty("user.home"); private static String prevGibsPath = System.getProperty("user.home"); private static int selectedTab = 0; private ShipContainer container; private Images tempType = null; private Text txtHull; private Button btnHullBrowse; private Button btnHullClear; private Button btnHullView; private Text txtFloor; private Button btnFloorBrowse; private Button btnFloorClear; private Button btnFloorView; private Text txtCloak; private Button btnCloakBrowse; private Button btnCloakClear; private Button btnCloakView; private Text txtShield; private Button btnShieldBrowse; private Button btnShieldClear; private Button btnShieldView; private Text txtMini; private Button btnMiniBrowse; private Button btnMiniClear; private Button btnMiniView; private TabFolder tabFolder; private TabItem tbtmImages; private TabItem tbtmGibs; private Composite compImages; private Composite compGibs; private Button btnNew; private HashMap<GibController, GibWidget> gibWidgetMap; private BrowseMenu mnbImages; private BrowseMenu mnbGibs; public ImagesToolComposite(Composite parent) { super(parent, SWT.NONE); setLayout(new GridLayout(4, false)); gibWidgetMap = new HashMap<GibController, GibWidget>(); container = Manager.getCurrentShip(); ShipObject ship = container.getShipController().getGameObject(); final boolean[] created = { false }; Label lblPropertiesTool = new Label(this, SWT.NONE); lblPropertiesTool.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false, 4, 1)); lblPropertiesTool.setText("Ship Images"); Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL); separator.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 4, 1)); mnbImages = new BrowseMenu(this); mnbGibs = new BrowseMenu(this); mnbImages.addDataListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DatabaseFileDialog dialog = new DatabaseFileDialog(EditorWindow.getInstance().getShell()); dialog.setFilterExtensions(new String[] { "*.png" }); dialog.setText("FTL Archive Browser"); boolean exit = false; while (!exit) { String path = dialog.open(); // path == null only when user cancels if (path == null) { exit = true; } else { exit = setImage(tempType, "db:", path); } } } }); mnbImages.addSystemListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { FileDialog dialog = new FileDialog(EditorWindow.getInstance().getShell(), SWT.OPEN); dialog.setFilterExtensions(new String[] { "*.png" }); dialog.setFilterPath(prevImagesPath); dialog.setFileName(prevImagesPath); boolean exit = false; while (!exit) { String path = dialog.open(); // path == null only when user cancels if (path != null) { prevImagesPath = path; exit = setImage(tempType, "file:", path); } else { exit = true; } } } }); SelectionAdapter browseMenuListener = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Button source = (Button) e.getSource(); tempType = null; if (source == btnHullBrowse) tempType = Images.HULL; else if (source == btnFloorBrowse) tempType = Images.FLOOR; else if (source == btnCloakBrowse) tempType = Images.CLOAK; else if (source == btnShieldBrowse) tempType = Images.SHIELD; else if (source == btnMiniBrowse) tempType = Images.THUMBNAIL; mnbImages.setLocation(source.toDisplay(0, source.getSize().y)); mnbImages.setVisible(true); } }; SelectionAdapter imageViewListener = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Images type = null; if (e.getSource() == btnHullView) type = Images.HULL; else if (e.getSource() == btnFloorView) type = Images.FLOOR; else if (e.getSource() == btnCloakView) type = Images.CLOAK; else if (e.getSource() == btnShieldView) type = Images.SHIELD; else if (e.getSource() == btnMiniView) type = Images.THUMBNAIL; String path = container.getImage(type); if (path != null) { ImageViewerDialog dialog = new ImageViewerDialog(EditorWindow.getInstance().getShell()); dialog.open(path); } } }; SelectionAdapter imageClearListener = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Images type = null; if (e.getSource() == btnHullClear) type = Images.HULL; else if (e.getSource() == btnFloorClear) type = Images.FLOOR; else if (e.getSource() == btnCloakClear) type = Images.CLOAK; else if (e.getSource() == btnShieldClear) type = Images.SHIELD; else if (e.getSource() == btnMiniClear) type = Images.THUMBNAIL; final Images fType = type; UndoablePropertyEdit<String> edit = new UndoablePropertyEdit<String>(container) { public void callback(String arg) { container.setImage(fType, arg); if (!isDisposed()) updateData(); } @Override public String getPresentationName() { return String.format("clear %s image", fType.toString()); } }; edit.setOld(container.getImage(type)); edit.setCurrent(null); container.setImage(type, null); updateData(); if (!edit.isValuesEqual()) Manager.getCurrentShip().postEdit(edit); } }; tabFolder = new TabFolder(this, SWT.NONE); tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1)); tabFolder.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (created[0]) selectedTab = tabFolder.getSelectionIndex(); } }); /* * =============================================== * IMAGES TAB * =============================================== */ tbtmImages = new TabItem(tabFolder, SWT.NONE); tbtmImages.setText("Images"); compImages = new Composite(tabFolder, SWT.NONE); tbtmImages.setControl(compImages); compImages.setLayout(new GridLayout(4, false)); // Hull widgets Label lblHull = new Label(compImages, SWT.NONE); lblHull.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); lblHull.setText("Hull"); btnHullView = new Button(compImages, SWT.NONE); btnHullView.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); btnHullView.setEnabled(false); btnHullView.setText("View"); btnHullView.addSelectionListener(imageViewListener); btnHullBrowse = new Button(compImages, SWT.NONE); btnHullBrowse.setText("Browse"); btnHullBrowse.addSelectionListener(browseMenuListener); btnHullClear = new Button(compImages, SWT.NONE); btnHullClear.setText("Clear"); btnHullClear.addSelectionListener(imageClearListener); txtHull = new Text(compImages, SWT.BORDER | SWT.READ_ONLY); txtHull.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); if (ship.isPlayerShip()) { // Floor widgets Label lblFloor = new Label(compImages, SWT.NONE); lblFloor.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); lblFloor.setText("Floor"); btnFloorView = new Button(compImages, SWT.NONE); btnFloorView.setEnabled(false); btnFloorView.setText("View"); btnFloorView.addSelectionListener(imageViewListener); btnFloorBrowse = new Button(compImages, SWT.NONE); btnFloorBrowse.setText("Browse"); btnFloorBrowse.addSelectionListener(browseMenuListener); btnFloorClear = new Button(compImages, SWT.NONE); btnFloorClear.setText("Clear"); btnFloorClear.addSelectionListener(imageClearListener); txtFloor = new Text(compImages, SWT.BORDER | SWT.READ_ONLY); txtFloor.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); } // Cloak widgets Label lblCloak = new Label(compImages, SWT.NONE); lblCloak.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); lblCloak.setText("Cloak"); btnCloakView = new Button(compImages, SWT.NONE); btnCloakView.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); btnCloakView.setEnabled(false); btnCloakView.setText("View"); btnCloakView.addSelectionListener(imageViewListener); btnCloakBrowse = new Button(compImages, SWT.NONE); btnCloakBrowse.setText("Browse"); btnCloakBrowse.addSelectionListener(browseMenuListener); btnCloakClear = new Button(compImages, SWT.NONE); btnCloakClear.setText("Clear"); txtCloak = new Text(compImages, SWT.BORDER | SWT.READ_ONLY); txtCloak.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); btnCloakClear.addSelectionListener(imageClearListener); if (ship.isPlayerShip()) { // Shield widgets Label lblShield = new Label(compImages, SWT.NONE); lblShield.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); lblShield.setText("Shield"); btnShieldView = new Button(compImages, SWT.NONE); btnShieldView.setEnabled(false); btnShieldView.setText("View"); btnShieldView.addSelectionListener(imageViewListener); btnShieldBrowse = new Button(compImages, SWT.NONE); btnShieldBrowse.setText("Browse"); btnShieldBrowse.addSelectionListener(browseMenuListener); btnShieldClear = new Button(compImages, SWT.NONE); btnShieldClear.setText("Clear"); btnShieldClear.addSelectionListener(imageClearListener); txtShield = new Text(compImages, SWT.BORDER | SWT.READ_ONLY); txtShield.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); // Thumbnail widgets Label lblMini = new Label(compImages, SWT.NONE); lblMini.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); lblMini.setText("Thumbnail"); btnMiniView = new Button(compImages, SWT.NONE); btnMiniView.setEnabled(false); btnMiniView.setText("View"); btnMiniView.addSelectionListener(imageViewListener); btnMiniBrowse = new Button(compImages, SWT.NONE); btnMiniBrowse.setText("Browse"); btnMiniBrowse.addSelectionListener(browseMenuListener); btnMiniClear = new Button(compImages, SWT.NONE); btnMiniClear.setText("Clear"); btnMiniClear.addSelectionListener(imageClearListener); txtMini = new Text(compImages, SWT.BORDER | SWT.READ_ONLY); txtMini.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1)); } /* * =============================================== * GIBS TAB * =============================================== */ tbtmGibs = new TabItem(tabFolder, SWT.NONE); tbtmGibs.setText("Gibs"); compGibs = new Composite(tabFolder, SWT.NONE); tbtmGibs.setControl(compGibs); compGibs.setLayout(new GridLayout(1, false)); btnNew = new Button(compGibs, SWT.NONE); btnNew.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); btnNew.setText("New Gib"); mnbGibs.addTo(btnNew); mnbGibs.addSystemListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { FileDialog dialog = new FileDialog(EditorWindow.getInstance().getShell(), SWT.OPEN); dialog.setFilterExtensions(new String[] { "*.png" }); dialog.setFilterPath(prevGibsPath); dialog.setFileName(prevGibsPath); boolean exit = false; while (!exit) { String path = dialog.open(); // path == null only when user cancels if (path != null) { prevGibsPath = path; exit = createGib("file:", path); } else { exit = true; } } } }); mnbGibs.addDataListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DatabaseFileDialog dialog = new DatabaseFileDialog(EditorWindow.getInstance().getShell()); dialog.setFilterExtensions(new String[] { "*.png" }); dialog.setText("FTL Archive Browser"); boolean exit = false; while (!exit) { String path = dialog.open(); // path == null only when user cancels if (path == null) { exit = true; } else { exit = createGib("db:", path); } } } }); for (GibController gc : container.getGibControllers()) { GibWidget gw = new GibWidget(compGibs, gc); gibWidgetMap.put(gc, gw); } pack(); updateData(); created[0] = true; tabFolder.setSelection(selectedTab); } public void updateData() { ShipObject ship = container.getShipController().getGameObject(); // Update image path text fields and scroll them to the end to show the file's name String content = container.getImage(Images.HULL); txtHull.setText(content == null ? "" : IOUtils.trimProtocol(content)); txtHull.selectAll(); txtHull.clearSelection(); btnHullView.setEnabled(content != null); content = container.getImage(Images.CLOAK); txtCloak.setText(content == null ? "" : IOUtils.trimProtocol(content)); txtCloak.selectAll(); txtCloak.clearSelection(); btnCloakView.setEnabled(content != null); if (ship.isPlayerShip()) { content = container.getImage(Images.FLOOR); txtFloor.setText(content == null ? "" : IOUtils.trimProtocol(content)); txtFloor.selectAll(); txtFloor.clearSelection(); btnFloorView.setEnabled(content != null); content = container.getImage(Images.SHIELD); txtShield.setText(content == null ? "" : IOUtils.trimProtocol(content)); txtShield.selectAll(); txtShield.clearSelection(); btnShieldView.setEnabled(content != null); content = container.getImage(Images.THUMBNAIL); txtMini.setText(content == null || !ship.isPlayerShip() ? "" : IOUtils.trimProtocol(content)); txtMini.selectAll(); txtMini.clearSelection(); btnMiniView.setEnabled(content != null); } for (GibWidget gw : gibWidgetMap.values()) { gw.updateData(); } } public void setController(AbstractController c) { throw new UnsupportedOperationException(); } public void reloadController() { } public static void setPrevGibsPath(String path) { prevGibsPath = path; } public static String getPrevGibsPath() { return prevGibsPath; } private boolean setImage(Images type, String protocol, String path) { if (type == null) throw new IllegalArgumentException("Type must not be null!"); if (protocol.equals("file:") && !new File(path).exists()) { UIUtils.showWarningDialog(EditorWindow.getInstance().getShell(), null, "The file you have selected does not exist."); return false; } final Images fType = type; UndoablePropertyEdit<String> edit = new UndoablePropertyEdit<String>(container) { public void callback(String arg) { container.setImage(fType, arg); if (!isDisposed()) updateData(); } @Override public String getPresentationName() { return String.format("change %s image", fType.toString()); } }; edit.setOld(container.getImage(type)); edit.setCurrent(protocol + path); container.setImage(type, protocol + path); EditorWindow.getInstance().canvasRedraw(); updateData(); if (!edit.isValuesEqual()) Manager.getCurrentShip().postEdit(edit); return true; } private boolean createGib(String protocol, String path) { if (protocol.equals("file:") && !new File(path).exists()) { UIUtils.showWarningDialog(EditorWindow.getInstance().getShell(), null, "The file you have selected does not exist."); return false; } GibObject gib = new GibObject(); gib.setId(container.getGibControllers().length + 1); gib.setImagePath(protocol + path); GibController gc = GibController.newInstance(container, gib); gc.updateFollower(); gc.setParent(container.getImageController(Images.HULL)); gc.updateFollowOffset(); gc.redraw(); container.add(gc); container.store(gc); GibWidget gw = new GibWidget(compGibs, gc); gibWidgetMap.put(gc, gw); compGibs.layout(); return true; } }