package com.kartoflane.superluminal2.ui.sidebar;
import java.util.ArrayList;
import java.util.HashMap;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import com.kartoflane.superluminal2.Superluminal;
import com.kartoflane.superluminal2.components.enums.BoardingStrategies;
import com.kartoflane.superluminal2.components.enums.OS;
import com.kartoflane.superluminal2.components.enums.PlayerShipBlueprints;
import com.kartoflane.superluminal2.components.enums.Races;
import com.kartoflane.superluminal2.components.enums.Systems;
import com.kartoflane.superluminal2.core.Cache;
import com.kartoflane.superluminal2.core.Database;
import com.kartoflane.superluminal2.core.Manager;
import com.kartoflane.superluminal2.ftl.AugmentObject;
import com.kartoflane.superluminal2.ftl.DroneList;
import com.kartoflane.superluminal2.ftl.DroneObject;
import com.kartoflane.superluminal2.ftl.ShipObject;
import com.kartoflane.superluminal2.ftl.SystemObject;
import com.kartoflane.superluminal2.ftl.WeaponList;
import com.kartoflane.superluminal2.ftl.WeaponObject;
import com.kartoflane.superluminal2.mvc.controllers.AbstractController;
import com.kartoflane.superluminal2.mvc.controllers.ShipController;
import com.kartoflane.superluminal2.mvc.controllers.SystemController;
import com.kartoflane.superluminal2.ui.AugmentSelectionDialog;
import com.kartoflane.superluminal2.ui.CrewMenu;
import com.kartoflane.superluminal2.ui.DroneSelectionDialog;
import com.kartoflane.superluminal2.ui.EditorWindow;
import com.kartoflane.superluminal2.ui.ShipContainer;
import com.kartoflane.superluminal2.ui.WeaponSelectionDialog;
import com.kartoflane.superluminal2.ui.sidebar.data.DataComposite;
import com.kartoflane.superluminal2.utils.UIUtils;
import com.kartoflane.superluminal2.utils.Utils;
public class PropertiesToolComposite extends Composite implements DataComposite {
private static int selectedTab = 0;
private ShipContainer container;
private Text txtName;
private Text txtClass;
private Text txtDesc;
private Spinner spHealth;
private Spinner spPower;
private TabItem tbtmCrew;
private Composite compCrew;
private Label lblDesc;
private Spinner spMinSec;
private Spinner spMaxSec;
private TabFolder tabFolder;
private ArrayList<Button> btnWeapons = new ArrayList<Button>();
private ArrayList<Button> btnDrones = new ArrayList<Button>();
private ArrayList<Button> btnAugments = new ArrayList<Button>();
private ArrayList<Button> btnArtilleries = new ArrayList<Button>();
private ArrayList<Button> btnCrewMembers = new ArrayList<Button>();
private HashMap<Races, Spinner> spCrewMin = new HashMap<Races, Spinner>();
private HashMap<Races, Spinner> spCrewMax = new HashMap<Races, Spinner>();
private Spinner spMissiles;
private Spinner spWeaponSlots;
private Button btnWeaponByList;
private Button btnDroneByList;
private Button btnWeaponList;
private Button btnDroneList;
private Group grpWeapons;
private Composite compArm;
private Group grpDrones;
private Spinner spDrones;
private Spinner spDroneSlots;
private Label lblBlueprint;
private Text txtBlueprint;
private Combo cmbShips;
private Text txtLayout;
private Text txtImage;
private Group grpAugments;
private CrewMenu crewMenu;
private Label lblHullHelp;
private Label lblReactorInfo;
private Label lblLayoutInfo;
private Label lblImageHelp;
private Label lblBlueprintHelp;
private Combo cmbBoardingAI;
private Group grpArtillery;
private Spinner spArtillerySlots;
public PropertiesToolComposite(Composite parent) {
super(parent, SWT.NONE);
setLayout(new GridLayout(1, false));
container = Manager.getCurrentShip();
Image helpImage = Cache.checkOutImage(this, "cpath:/assets/help.png");
final 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, 1, 1));
lblPropertiesTool.setText("Ship Loadout and Properties");
Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL);
separator.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
tabFolder = new TabFolder(this, SWT.NONE);
tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
tabFolder.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (created[0])
selectedTab = tabFolder.getSelectionIndex();
}
});
/*
* =========================================================================
* XXX: General tab
* =========================================================================
*/
TabItem tbtmGeneral = new TabItem(tabFolder, SWT.NONE);
tbtmGeneral.setText("General");
Composite compGeneral = new Composite(tabFolder, SWT.NONE);
tbtmGeneral.setControl(compGeneral);
compGeneral.setLayout(new GridLayout(4, false));
lblBlueprint = new Label(compGeneral, SWT.NONE);
lblBlueprint.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
lblBlueprint.setText("Blueprint:");
lblBlueprintHelp = new Label(compGeneral, SWT.NONE);
lblBlueprintHelp.setImage(helpImage);
if (ship.isPlayerShip()) {
lblBlueprint.setText("Replaced Ship:");
String msg = "This determines which ship your ship is going to replace. " +
"Currently, there is no way to add new player ships, so you " +
"have to replace one that already exists.";
UIUtils.addTooltip(lblBlueprintHelp, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
cmbShips = new Combo(compGeneral, SWT.READ_ONLY);
cmbShips.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1));
for (PlayerShipBlueprints blueprint : PlayerShipBlueprints.values()) {
cmbShips.add(blueprint.toString());
}
cmbShips.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setBlueprintName(cmbShips.getText());
}
});
Label lblName = new Label(compGeneral, SWT.NONE);
lblName.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
lblName.setText("Name:");
txtName = new Text(compGeneral, SWT.BORDER);
txtName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1));
txtName.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
ship.setShipName(txtName.getText());
}
});
} else {
lblBlueprint.setText("Blueprint Name:");
String msg = "This determines your ship's blueprint name. " +
"Blueprint name is a unique identifier of the " +
"ship, that the game uses internally.";
UIUtils.addTooltip(lblBlueprintHelp, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
txtBlueprint = new Text(compGeneral, SWT.BORDER);
txtBlueprint.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1));
txtBlueprint.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
ship.setBlueprintName(txtBlueprint.getText());
}
});
}
Label lblClass = new Label(compGeneral, SWT.NONE);
lblClass.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
lblClass.setText("Class:");
txtClass = new Text(compGeneral, SWT.BORDER);
txtClass.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1));
txtClass.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
ship.setShipClass(txtClass.getText());
}
});
if (ship.isPlayerShip()) {
lblDesc = new Label(compGeneral, SWT.NONE);
lblDesc.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1));
lblDesc.setText("Description: (0/255)");
txtDesc = new Text(compGeneral, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI);
GridData gd_txtDesc = new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1);
gd_txtDesc.heightHint = 80;
txtDesc.setLayoutData(gd_txtDesc);
txtDesc.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
lblDesc.setText("Description: (" + txtDesc.getText().length() + "/255)");
ship.setShipDescription(txtDesc.getText());
}
});
}
Label lblLayout = new Label(compGeneral, SWT.NONE);
lblLayout.setText("Layout Filename:");
lblLayoutInfo = new Label(compGeneral, SWT.NONE);
lblLayoutInfo.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 3, 1));
lblLayoutInfo.setImage(helpImage);
String msg = "This field specifies the name of the ship's layout files, " +
"like kestral.txt and kestral.xml";
UIUtils.addTooltip(lblLayoutInfo, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
txtLayout = new Text(compGeneral, SWT.BORDER);
txtLayout.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1));
txtLayout.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
ship.setLayout(txtLayout.getText());
}
});
Label lblImageNamespace = new Label(compGeneral, SWT.NONE);
lblImageNamespace.setText("Image Namespace:");
lblImageHelp = new Label(compGeneral, SWT.NONE);
lblImageHelp.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 3, 1));
lblImageHelp.setImage(helpImage);
msg = "This field specifies the name of the ship's image files, " +
"like kestral_base.png";
UIUtils.addTooltip(lblImageHelp, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
txtImage = new Text(compGeneral, SWT.BORDER);
txtImage.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1));
txtImage.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
ship.setImageNamespace(txtImage.getText());
}
});
Label lblHealth = new Label(compGeneral, SWT.NONE);
lblHealth.setText("Hull Health:");
spHealth = new Spinner(compGeneral, SWT.BORDER);
spHealth.setTextLimit(3);
spHealth.setMinimum(0);
GridData gd_spHealth = new GridData(SWT.RIGHT, SWT.CENTER, true, false, 2, 1);
gd_spHealth.widthHint = 25;
spHealth.setLayoutData(gd_spHealth);
spHealth.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setHealth(spHealth.getSelection());
}
});
lblHullHelp = new Label(compGeneral, SWT.NONE);
lblHullHelp.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblHullHelp.setImage(helpImage);
msg = "This defines the amount of health your ship starts with. " +
"The default is 30 for a player ship.";
UIUtils.addTooltip(lblHullHelp, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
Label lblReactor = new Label(compGeneral, SWT.NONE);
lblReactor.setText("Reactor Power:");
spPower = new Spinner(compGeneral, SWT.BORDER);
spPower.setTextLimit(3);
spPower.setMinimum(0);
GridData gd_spPower = new GridData(SWT.RIGHT, SWT.CENTER, true, false, 2, 1);
gd_spPower.widthHint = 25;
spPower.setLayoutData(gd_spPower);
spPower.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setPower(spPower.getSelection());
}
});
lblReactorInfo = new Label(compGeneral, SWT.NONE);
lblReactorInfo.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblReactorInfo.setImage(helpImage);
msg = "This sets the amount of power the ship starts with. " +
"The reactor can only be upgraded to level 25 ingame, " +
"but can be set to a higher value when creating your " +
"ship in this editor.";
UIUtils.addTooltip(lblReactorInfo, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
if (!ship.isPlayerShip()) {
Label lblMinSector = new Label(compGeneral, SWT.NONE);
lblMinSector.setText("Min Sector:");
spMinSec = new Spinner(compGeneral, SWT.BORDER);
spMinSec.setTextLimit(1);
spMinSec.setMaximum(8);
spMinSec.setMinimum(1);
GridData gd_spMinSec = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 2, 1);
gd_spMinSec.widthHint = 25;
spMinSec.setLayoutData(gd_spMinSec);
spMinSec.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setMinSector(spMinSec.getSelection());
}
});
Label lblMinSecInfo = new Label(compGeneral, SWT.NONE);
lblMinSecInfo.setImage(helpImage);
msg = "This determines the minimum sector in which the enemy can be encountered.";
UIUtils.addTooltip(lblMinSecInfo, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
Label lblMaxSector = new Label(compGeneral, SWT.NONE);
lblMaxSector.setText("Max Sector:");
spMaxSec = new Spinner(compGeneral, SWT.BORDER);
spMaxSec.setTextLimit(1);
spMaxSec.setMaximum(8);
spMaxSec.setMinimum(1);
GridData gd_spMaxSec = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 2, 1);
gd_spMaxSec.widthHint = 25;
spMaxSec.setLayoutData(gd_spMaxSec);
spMaxSec.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setMaxSector(spMaxSec.getSelection());
}
});
Label lblMaxSecInfo = new Label(compGeneral, SWT.NONE);
lblMaxSecInfo.setImage(helpImage);
msg = "This determines the maximum sector in which the enemy can be encountered.";
UIUtils.addTooltip(lblMaxSecInfo, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
Label lblBoardingAI = new Label(compGeneral, SWT.NONE);
lblBoardingAI.setText("Boarding AI:");
cmbBoardingAI = new Combo(compGeneral, SWT.READ_ONLY);
cmbBoardingAI.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
for (BoardingStrategies ai : BoardingStrategies.values()) {
cmbBoardingAI.add(ai.toString());
}
cmbBoardingAI.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setBoardingAI(BoardingStrategies.values()[cmbBoardingAI.getSelectionIndex()]);
}
});
Label lblBoardingAIInfo = new Label(compGeneral, SWT.NONE);
lblBoardingAIInfo.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
lblBoardingAIInfo.setImage(helpImage);
msg = "This determines the strategy that the ship's crew is going to use when boarding.";
UIUtils.addTooltip(lblBoardingAIInfo, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
}
/*
* =========================================================================
* XXX: Armaments tab
* =========================================================================
*/
TabItem tbtmArmaments = new TabItem(tabFolder, 0);
tbtmArmaments.setText("Armaments");
compArm = new Composite(tabFolder, SWT.NONE);
tbtmArmaments.setControl(compArm);
compArm.setLayout(new GridLayout(1, false));
/*
* =========================================================================
* XXX: Weapons
* =========================================================================
*/
grpWeapons = new Group(compArm, SWT.NONE);
grpWeapons.setLayout(new GridLayout(2, false));
grpWeapons.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
grpWeapons.setText("Weapons");
Label lblMissiles = new Label(grpWeapons, SWT.NONE);
lblMissiles.setText("Starting Missiles");
spMissiles = new Spinner(grpWeapons, SWT.BORDER);
spMissiles.setMaximum(999);
GridData gd_spMissiles = new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1);
gd_spMissiles.widthHint = 25;
spMissiles.setLayoutData(gd_spMissiles);
spMissiles.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setMissilesAmount(spMissiles.getSelection());
}
});
if (!ship.isPlayerShip()) {
btnWeaponByList = new Button(grpWeapons, SWT.CHECK);
btnWeaponByList.setLayoutData(new GridData(SWT.FILL, SWT.LEFT, true, false, 1, 1));
btnWeaponByList.setText("Weapons By List");
btnWeaponByList.setSelection(ship.getWeaponsByList());
Label lblWeaponByListInfo = new Label(grpWeapons, SWT.NONE);
lblWeaponByListInfo.setImage(helpImage);
lblWeaponByListInfo.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
msg = "Unchecking this allows you to define this ship's weapons directly, like in player ships.";
UIUtils.addTooltip(lblWeaponByListInfo, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
btnWeaponByList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
btnWeaponList.dispose();
clearWeaponSlots();
ship.setWeaponsByList(btnWeaponByList.getSelection());
if (ship.getWeaponsByList()) {
createWeaponList(ship);
} else {
createWeaponSlots(ship.getWeaponSlots());
}
updateData();
container.updateMounts();
EditorWindow.getInstance().updateSidebarScroll();
}
});
}
Label lblWeaponSlots = new Label(grpWeapons, SWT.NONE);
lblWeaponSlots.setText("Slots");
spWeaponSlots = new Spinner(grpWeapons, SWT.BORDER);
spWeaponSlots.setMaximum(8);
GridData gd_spWeaponSlots = new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1);
gd_spWeaponSlots.widthHint = 25;
spWeaponSlots.setLayoutData(gd_spWeaponSlots);
spWeaponSlots.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (ship.getWeaponsByList()) {
ship.setWeaponSlots(spWeaponSlots.getSelection());
updateData();
} else {
if (spWeaponSlots.getSelection() > 4 && ship.getWeaponSlots() <= 4 && !Manager.shownSlotWarning) {
String msg = "Giving a ship more than 4 weapon slots will cause ingame UI to break.\n" +
"On top of that, toggling autofire on weapons assigned to slots >4 will crash the game.\n" +
"While it's possible for a ship to have any number of weapon slots, the\n" +
"option to have more than 4 should only be used by experienced modders.";
UIUtils.showWarningDialog(EditorWindow.getInstance().getShell(), null, msg);
Manager.shownSlotWarning = true;
}
int slots = spWeaponSlots.getSelection();
ship.setWeaponSlots(slots);
clearWeaponSlots();
createWeaponSlots(slots);
updateData();
container.updateMounts();
EditorWindow.getInstance().updateSidebarScroll();
}
}
});
if (ship.getWeaponsByList()) {
createWeaponList(ship);
} else {
createWeaponSlots(ship.getWeaponSlots());
}
/*
* =========================================================================
* XXX: Drones
* =========================================================================
*/
grpDrones = new Group(compArm, SWT.NONE);
grpDrones.setLayout(new GridLayout(2, false));
grpDrones.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
grpDrones.setText("Drones");
Label lblDrones = new Label(grpDrones, SWT.NONE);
lblDrones.setText("Starting Drone Parts");
spDrones = new Spinner(grpDrones, SWT.BORDER);
spDrones.setMaximum(999);
GridData gd_spDrones = new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1);
gd_spDrones.widthHint = 25;
spDrones.setLayoutData(gd_spDrones);
spDrones.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setDronePartsAmount(spDrones.getSelection());
}
});
if (!ship.isPlayerShip()) {
btnDroneByList = new Button(grpDrones, SWT.CHECK);
btnDroneByList.setLayoutData(new GridData(SWT.FILL, SWT.LEFT, true, false, 1, 1));
btnDroneByList.setText("Drones By List");
btnDroneByList.setSelection(ship.getDronesByList());
Label lblDroneByListInfo = new Label(grpDrones, SWT.NONE);
lblDroneByListInfo.setImage(helpImage);
lblDroneByListInfo.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
msg = "Unchecking this allows you to define this ship's drones directly, like in player ships.";
UIUtils.addTooltip(lblDroneByListInfo, Utils.wrapOSNot(msg, Superluminal.WRAP_WIDTH, Superluminal.WRAP_TOLERANCE, OS.MACOSX()));
btnDroneByList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
btnDroneList.dispose();
clearDroneSlots();
ship.setDronesByList(btnDroneByList.getSelection());
if (ship.getDronesByList()) {
createDroneList(ship);
} else {
createDroneSlots(ship.getDroneSlots());
}
updateData();
EditorWindow.getInstance().updateSidebarScroll();
}
});
}
Label lblDroneSlots = new Label(grpDrones, SWT.NONE);
lblDroneSlots.setText("Slots");
spDroneSlots = new Spinner(grpDrones, SWT.BORDER);
spDroneSlots.setMaximum(8);
GridData gd_spDroneSlots = new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1);
gd_spDroneSlots.widthHint = 25;
spDroneSlots.setLayoutData(gd_spDroneSlots);
spDroneSlots.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (ship.getDronesByList()) {
ship.setDroneSlots(spDroneSlots.getSelection());
updateData();
} else {
if (spDroneSlots.getSelection() > 4 && ship.getDroneSlots() <= 4 && !Manager.shownSlotWarning) {
String msg = "Giving a ship more than 4 drone slots will cause ingame UI to break.\n" +
"While it's possible for a ship to have any number of drone slots, this\n" +
"option should only be used by experienced modders.";
UIUtils.showWarningDialog(EditorWindow.getInstance().getShell(), null, msg);
Manager.shownSlotWarning = true;
}
int slots = spDroneSlots.getSelection();
ship.setDroneSlots(slots);
clearDroneSlots();
createDroneSlots(slots);
updateData();
EditorWindow.getInstance().updateSidebarScroll();
}
}
});
if (ship.getDronesByList()) {
createDroneList(ship);
} else {
createDroneSlots(ship.getDroneSlots());
}
/*
* =========================================================================
* XXX: Augments
* =========================================================================
*/
grpAugments = new Group(compArm, SWT.NONE);
grpAugments.setLayout(new GridLayout(1, false));
grpAugments.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
grpAugments.setText("Augments");
SelectionAdapter augmentListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int i = btnAugments.indexOf(e.getSource());
if (i != -1) {
ShipObject ship = container.getShipController().getGameObject();
AugmentObject current = ship.getAugments()[i];
AugmentSelectionDialog dialog = new AugmentSelectionDialog(EditorWindow.getInstance().getShell());
AugmentObject neu = dialog.open(current);
if (neu != null) {
// If the augment is the default dummy, then replace the first occurence of
// the dummy aug, so that there are no gaps
if (current == Database.DEFAULT_AUGMENT_OBJ)
ship.changeAugment(current, neu);
else
ship.changeAugment(i, neu);
updateData();
}
}
}
};
for (int i = 0; i < 3; i++) {
Button btn = new Button(grpAugments, SWT.NONE);
btn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
btn.setText("<augment slot>");
btn.addSelectionListener(augmentListener);
btnAugments.add(btn);
}
/*
* =========================================================================
* XXX: Artillery
* =========================================================================
*/
grpArtillery = new Group(compArm, SWT.NONE);
grpArtillery.setLayout(new GridLayout(2, false));
grpArtillery.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
grpArtillery.setText("Artillery");
Label lblArtillerySlots = new Label(grpArtillery, SWT.NONE);
lblArtillerySlots.setText("Slots:");
spArtillerySlots = new Spinner(grpArtillery, SWT.BORDER);
spArtillerySlots.setMaximum(8);
spArtillerySlots.setMinimum(1);
GridData gd_spArtillerySlots = new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1);
gd_spArtillerySlots.widthHint = 25;
spArtillerySlots.setLayoutData(gd_spArtillerySlots);
spArtillerySlots.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ArrayList<SystemObject> systems = ship.getSystems(Systems.ARTILLERY);
int slots = spArtillerySlots.getSelection();
if (slots > 1 && systems.size() <= 1 && !Manager.shownArtilleryWarning) {
String msg = "The player can only control power of the first artillery system.\n" +
"All the other artillery systems will be permanently powered, and cannot be upgraded.";
UIUtils.showWarningDialog(EditorWindow.getInstance().getShell(), null, msg);
Manager.shownArtilleryWarning = true;
}
if (systems.size() < slots) {
for (int i = systems.size(); i < slots; i++) {
SystemObject system = new SystemObject(Systems.ARTILLERY, ship);
system.setAlias("#" + (i + 1));
SystemController sysC = SystemController.newInstance(container, system);
ship.add(system);
container.add(sysC);
container.store(sysC);
}
} else {
for (int i = systems.size() - 1; i >= slots; i--) {
SystemObject system = systems.get(i);
SystemController sysC = (SystemController) container.getController(system);
container.unassign(system);
container.remove(sysC);
container.dispose(sysC);
ship.remove(system);
}
}
clearArtillerySlots();
createArtillerySlots(slots);
updateData();
container.updateMounts();
EditorWindow.getInstance().updateSidebarScroll();
}
});
createArtillerySlots(ship.getSystems(Systems.ARTILLERY).size());
/*
* =========================================================================
* XXX: Crew tab
* =========================================================================
*/
tbtmCrew = new TabItem(tabFolder, SWT.NONE);
tbtmCrew.setText("Crew");
compCrew = new Composite(tabFolder, SWT.NONE);
tbtmCrew.setControl(compCrew);
compCrew.setLayout(new GridLayout(3, false));
if (ship.isPlayerShip()) {
SelectionAdapter listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int i = btnCrewMembers.indexOf(e.getSource());
if (i != -1) {
ShipObject ship = container.getShipController().getGameObject();
Races current = ship.getCrew()[i];
crewMenu = new CrewMenu(compCrew);
Races neu = crewMenu.open();
if (neu != null) {
if (current == Races.NO_CREW)
ship.changeCrew(current, neu);
else
ship.changeCrew(i, neu);
updateData();
}
}
}
};
btnCrewMembers.clear();
for (int i = 0; i < 8; i++) {
Button btn = new Button(compCrew, SWT.NONE);
btn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
btn.setText("<crew slot>");
btn.addSelectionListener(listener);
btnCrewMembers.add(btn);
}
} else {
spCrewMin.clear();
spCrewMax.clear();
Label lbl = new Label(compCrew, SWT.NONE);
lbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
lbl.setText("Race");
lbl = new Label(compCrew, SWT.NONE);
lbl.setText("Min");
lbl = new Label(compCrew, SWT.NONE);
lbl.setText("Max");
for (Races race : Races.getRaces()) {
final Races r = race;
lbl = new Label(compCrew, SWT.NONE);
lbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
lbl.setText(race.toString());
final Spinner spMin = new Spinner(compCrew, SWT.BORDER);
spMin.setMaximum(10);
spCrewMin.put(race, spMin);
final Spinner spMax = new Spinner(compCrew, SWT.BORDER);
spMax.setMaximum(10);
spCrewMax.put(race, spMax);
spMin.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setCrewMin(r, spMin.getSelection());
if (ship.getCrewMax(r) < ship.getCrewMin(r)) {
spMax.setSelection(ship.getCrewMin(r));
spMax.notifyListeners(SWT.Selection, null);
}
}
});
spMax.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ship.setCrewMax(r, spMax.getSelection());
}
});
}
}
pack();
updateData();
created[0] = true;
tabFolder.setSelection(selectedTab);
}
public void updateData() {
ShipController controller = container.getShipController();
ShipObject ship = controller.getGameObject();
String content = null;
// General tab
content = ship.getShipClass();
txtClass.setText(content == null ? "Ship Class" : content);
content = ship.getLayout();
txtLayout.setText(content == null ? "myship" : content);
content = ship.getImageNamespace();
txtImage.setText(content == null ? "myship" : content);
spHealth.setSelection(ship.getHealth());
spPower.setSelection(ship.getPower());
if (ship.isPlayerShip()) {
int index = cmbShips.indexOf(ship.getBlueprintName());
cmbShips.select(index == -1 ? 0 : index);
content = ship.getShipName();
txtName.setText(ship.isPlayerShip() && content == null ? "The Nameless One" : content);
content = ship.getShipDescription();
txtDesc.setText(ship.isPlayerShip() && content == null ? "Ship Class" : content);
lblDesc.setText("Description: (" + txtDesc.getText().length() + "/255)");
} else {
txtBlueprint.setText(ship.getBlueprintName());
spMinSec.setSelection(ship.getMinSector());
spMaxSec.setSelection(ship.getMaxSector());
cmbBoardingAI.select(ship.getBoardingAI().ordinal());
}
// Armaments tab
spMissiles.setSelection(ship.getMissilesAmount());
spWeaponSlots.setSelection(ship.getWeaponSlots());
spDrones.setSelection(ship.getDronePartsAmount());
spDroneSlots.setSelection(ship.getDroneSlots());
int count = 0;
if (ship.getWeaponsByList()) {
WeaponList wList = ship.getWeaponList();
btnWeaponList.setText(wList.getBlueprintName());
} else {
count = 0;
for (WeaponObject weapon : ship.getWeapons()) {
if (count < ship.getWeaponSlots()) {
btnWeapons.get(count).setText(weapon.toString());
count++;
}
}
}
if (ship.getDronesByList()) {
DroneList dList = ship.getDroneList();
btnDroneList.setText(dList.getBlueprintName());
} else {
count = 0;
for (DroneObject drone : ship.getDrones()) {
if (count < ship.getDroneSlots()) {
btnDrones.get(count).setText(drone.toString());
count++;
}
}
}
count = 0;
for (AugmentObject augment : ship.getAugments()) {
btnAugments.get(count).setText(augment.toString());
count++;
}
spArtillerySlots.setSelection(ship.getSystems(Systems.ARTILLERY).size());
count = 0;
for (SystemObject system : ship.getSystems(Systems.ARTILLERY)) {
WeaponObject weapon = system.getWeapon();
btnArtilleries.get(count).setText(weapon.toString());
count++;
}
// Crew tab
if (ship.isPlayerShip()) {
count = 0;
for (Races race : ship.getCrew()) {
btnCrewMembers.get(count).setText(race.toString());
count++;
}
} else {
for (Races race : Races.getRaces()) {
spCrewMin.get(race).setSelection(ship.getCrewMin(race));
spCrewMax.get(race).setSelection(ship.getCrewMax(race));
}
}
}
private void clearWeaponSlots() {
for (Button b : btnWeapons)
b.dispose();
btnWeapons.clear();
compArm.layout();
}
private void clearDroneSlots() {
for (Button b : btnDrones)
b.dispose();
btnDrones.clear();
compArm.layout();
}
private void clearArtillerySlots() {
for (Button b : btnArtilleries)
b.dispose();
btnArtilleries.clear();
compArm.layout();
}
private void createWeaponList(final ShipObject ship) {
btnWeaponList = new Button(grpWeapons, SWT.NONE);
btnWeaponList.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
btnWeaponList.setText("<weapon list>");
btnWeaponList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
WeaponList current = ship.getWeaponList();
WeaponSelectionDialog dialog = new WeaponSelectionDialog(EditorWindow.getInstance().getShell());
WeaponList neu = dialog.open(current);
if (neu != null) {
ship.setWeaponList(neu);
updateData();
}
}
});
compArm.layout();
}
private void createWeaponSlots(int n) {
SelectionAdapter listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int i = btnWeapons.indexOf(e.getSource());
if (i != -1) {
ShipObject ship = container.getShipController().getGameObject();
WeaponObject current = ship.getWeapons()[i];
WeaponSelectionDialog dialog = new WeaponSelectionDialog(EditorWindow.getInstance().getShell());
WeaponObject neu = dialog.open(current);
if (neu != null) {
// If the weapon is the default dummy, then replace the first occurence of
// the dummy weapon, so that there are no gaps
if (current == Database.DEFAULT_WEAPON_OBJ)
container.changeWeapon(current, neu);
else
container.changeWeapon(i, neu);
updateData();
}
}
}
};
for (int i = 0; i < n; i++) {
Button b = new Button(grpWeapons, SWT.NONE);
b.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
b.setText("<weapon slot>");
b.addSelectionListener(listener);
btnWeapons.add(b);
}
compArm.layout();
}
private void createDroneList(final ShipObject ship) {
btnDroneList = new Button(grpDrones, SWT.NONE);
btnDroneList.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
btnDroneList.setText("<drone list>");
btnDroneList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
DroneList current = ship.getDroneList();
DroneSelectionDialog dialog = new DroneSelectionDialog(EditorWindow.getInstance().getShell());
DroneList neu = dialog.open(current);
if (neu != null) {
ship.setDroneList(neu);
updateData();
}
}
});
compArm.layout();
}
private void createDroneSlots(int n) {
SelectionAdapter listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int i = btnDrones.indexOf(e.getSource());
if (i != -1) {
ShipObject ship = container.getShipController().getGameObject();
DroneObject current = ship.getDrones()[i];
DroneSelectionDialog dialog = new DroneSelectionDialog(EditorWindow.getInstance().getShell());
DroneObject neu = dialog.open(current);
if (neu != null) {
// If the drone is the default dummy, then replace the first occurence of
// the dummy drone, so that there are no gaps
if (current == Database.DEFAULT_DRONE_OBJ)
ship.changeDrone(current, neu);
else
ship.changeDrone(i, neu);
updateData();
}
}
}
};
for (int i = 0; i < n; i++) {
Button b = new Button(grpDrones, SWT.NONE);
b.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
b.setText("<drone slot>");
b.addSelectionListener(listener);
btnDrones.add(b);
}
compArm.layout();
}
private void createArtillerySlots(int n) {
SelectionAdapter listener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int i = btnArtilleries.indexOf(e.getSource());
if (i != -1) {
ShipObject ship = container.getShipController().getGameObject();
SystemObject system = ship.getSystems(Systems.ARTILLERY).get(i);
WeaponObject current = system.getWeapon();
WeaponSelectionDialog dialog = new WeaponSelectionDialog(EditorWindow.getInstance().getShell());
WeaponObject neu = dialog.open(current);
if (neu != null) {
// If no weapon was selected, default to ARTILLERY_FED
Database db = Database.getInstance();
if (neu == Database.DEFAULT_WEAPON_OBJ && db != null) {
neu = db.getWeapon("ARTILLERY_FED");
}
system.setWeapon(neu);
updateData();
container.updateMounts();
}
}
}
};
for (int i = 0; i < n; i++) {
Button btn = new Button(grpArtillery, SWT.NONE);
btn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
btn.setText("<artillery slot>");
btn.addSelectionListener(listener);
btnArtilleries.add(btn);
}
compArm.layout();
}
@Override
public boolean isFocusControl() {
Control c = UIUtils.getDisplay().getFocusControl();
boolean result = c == txtClass || c == spHealth || c == spPower || c == spMissiles || c == spWeaponSlots ||
c == spDrones || c == spDroneSlots || c == txtLayout || c == txtImage;
if (container.getShipController().isPlayerShip()) {
result |= c == txtName || c == txtDesc;
} else {
result |= c == spMinSec || c == spMaxSec || c == txtBlueprint;
}
return result;
}
public void setController(AbstractController c) {
throw new UnsupportedOperationException();
}
public void reloadController() {
}
@Override
public void dispose() {
super.dispose();
Cache.checkInImage(this, "cpath:/assets/help.png");
}
}