mirror of
https://github.com/OMGeeky/ATCS.git
synced 2026-01-19 09:51:19 +01:00
Initial commit
This commit is contained in:
152
src/com/gpl/rpg/atcontentstudio/ui/AboutEditor.java
Normal file
152
src/com/gpl/rpg/atcontentstudio/ui/AboutEditor.java
Normal file
@@ -0,0 +1,152 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Desktop;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkEvent.EventType;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
public class AboutEditor extends Editor {
|
||||
|
||||
private static final long serialVersionUID = 6230549148222457139L;
|
||||
|
||||
public static final String WELCOME_STRING =
|
||||
"<html><body>" +
|
||||
"<table><tr valign=\"top\">" +
|
||||
"<td><img src=\""+ATContentStudio.class.getResource("/com/gpl/rpg/atcontentstudio/img/atcs_border_banner.png")+"\"/></td>" +
|
||||
"<td><font size=+1>Welcome to "+ATContentStudio.APP_NAME+" "+ATContentStudio.APP_VERSION+"</font><br/>" +
|
||||
"<br/>" +
|
||||
"This is a content editor for Andor's Trail.<br/>" +
|
||||
"<b>Right click on the left area or use the \"File\" menu to create a project.</b><br/>" +
|
||||
"<br/>" +
|
||||
"Play <a href=\"https://play.google.com/store/apps/details?id=com.gpl.rpg.AndorsTrail\">Andor's Trail</a> for free on your Android device.<br/>" +
|
||||
"Visit <a href=\"http://andorstrail.com/\">the official forum</a> to give or receive help.<br/>" +
|
||||
"Open the project's <a href=\"https://code.google.com/p/andors-trail/\">Google Code page</a> to check out the game's source code.<br/>" +
|
||||
"<br/>" +
|
||||
"For content creation help, make sure to use the following resources:<br/>" +
|
||||
"<a href=\"http://andorstrail.com/viewtopic.php?f=6&t=4560\">The contribution guide on the forums</a><br/>" +
|
||||
"<a href=\"http://andorstrail.com/wiki/doku.php?id=andors_trail_wiki:developer_section\">The developer section of the Andor's Trail wiki</a><br/>" +
|
||||
"<a href=\"https://docs.google.com/document/d/1BwWD1tLgPcmA2bwudrVnOc6f2dkPLFCjWdn7tXlIp5g\">The design outline document on Google Drive/Docs</a><br/>" +
|
||||
"<br/>" +
|
||||
"<font size=+1>Credits:</font><br/>" +
|
||||
"<br/>" +
|
||||
"Author: <a href=\"http://andorstrail.com/memberlist.php?mode=viewprofile&u=2875\">Zukero</a><br/>" +
|
||||
"Licence: <a href=\"http://www.gnu.org/licenses/gpl-3.0.html\">GPL v3</a><br/>" +
|
||||
"Sources are included in this package.<br/>" +
|
||||
"<br/>" +
|
||||
"This project uses the following libraries:<br/>" +
|
||||
"<a href=\"http://code.google.com/p/json-simple/\">JSON.simple</a> by Yidong Fang & Chris Nokleberg.<br/>" +
|
||||
"License: <a href=\"http://www.apache.org/licenses/LICENSE-2.0\">Apache License 2.0</a><br/>" +
|
||||
"<br/>" +
|
||||
"<a href=\"http://fifesoft.com/rsyntaxtextarea/\">RSyntaxTextArea</a> by Robert Futrell.<br/>" +
|
||||
"License: <a href=\"http://fifesoft.com/rsyntaxtextarea/RSyntaxTextArea.License.txt\">Modified BSD License (a.k.a. 3-Clause BSD)</a><br/>" +
|
||||
"<br/>" +
|
||||
"<a href=\"http://www.jidesoft.com/products/oss.htm\">JIDE Common Layer</a> by JIDE Software.<br/>" +
|
||||
"License: <a href=\"http://openjdk.java.net/legal/gplv2+ce.html\">GPL v2 with classpath exception</a><br/>" +
|
||||
"<br/>" +
|
||||
"A modified version of <a href=\"https://github.com/bjorn/tiled/tree/master/util/java/libtiled-java\">libtiled-java</a> by Adam Turk & Thorbjorn Lindeijer.<br/>" +
|
||||
"License: <a href=\"https://github.com/bjorn/tiled/blob/master/LICENSE.BSD\">Simplified BSD License (a.k.a 2-Clause BSD)</a><br/>" +
|
||||
"Sources of the modified version are included in this package.<br/>" +
|
||||
"<br/>" +
|
||||
"<a href=\"http://prefuse.org/\">Prefuse</a> by the Berkeley Institue of Design.<br/>" +
|
||||
"License: <a href=\"http://prefuse.org/license-prefuse.txt\">Modified BSD License (a.k.a 3-Clause BSD)</a><br/>" +
|
||||
"<br/>" +
|
||||
"See the tabs below to find the full license text for each of these.<br/>" +
|
||||
"<br/>" +
|
||||
"The Windows installer was created with:<br/>" +
|
||||
"<a href=\"http://nsis.sourceforge.net/Main_Page\">NSIS (Nullsoft Scriptable Install System) v2.46</a>" +
|
||||
"</td></tr></table>" +
|
||||
"</body></html>";
|
||||
|
||||
|
||||
public static final AboutEditor instance = new AboutEditor();
|
||||
private AboutEditor() {
|
||||
this.name="About "+ATContentStudio.APP_NAME;
|
||||
this.icon = new ImageIcon(DefaultIcons.getMainIconIcon());
|
||||
this.target = new GameDataElement(){
|
||||
private static final long serialVersionUID = -227480102288529682L;
|
||||
@Override
|
||||
public GameDataSet getDataSet() {return null;}
|
||||
@Override
|
||||
public String getDesc() {return null;}
|
||||
@Override
|
||||
public void parse() {}
|
||||
@Override
|
||||
public void link() {}
|
||||
@Override
|
||||
public GameDataElement clone() {return null;}
|
||||
@Override
|
||||
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {}
|
||||
@Override
|
||||
public String getProjectFilename() {return null;}
|
||||
@Override
|
||||
public void save() {}
|
||||
@Override
|
||||
public List<SaveEvent> attemptSave() {return null;}
|
||||
};
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
JideTabbedPane editorTabsHolder = new JideTabbedPane(JideTabbedPane.BOTTOM);
|
||||
editorTabsHolder.setTabShape(JideTabbedPane.SHAPE_FLAT);
|
||||
editorTabsHolder.setUseDefaultShowCloseButtonOnTab(false);
|
||||
editorTabsHolder.setShowCloseButtonOnTab(false);
|
||||
add(editorTabsHolder, BorderLayout.CENTER);
|
||||
|
||||
editorTabsHolder.add("Welcome", getInfoPane(WELCOME_STRING, "text/html"));
|
||||
editorTabsHolder.add("JSON.simple License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.JSON.simple.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
editorTabsHolder.add("RSyntaxTextArea License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/RSyntaxTextArea.License.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
editorTabsHolder.add("JIDE Common Layer License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.JIDE.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
editorTabsHolder.add("libtiled-java License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.libtiled.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
editorTabsHolder.add("prefuse License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/license-prefuse.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
editorTabsHolder.add("ATCS License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.GPLv3.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
|
||||
}
|
||||
|
||||
private JPanel getInfoPane(String content, String mime) {
|
||||
JEditorPane welcome = new JEditorPane();
|
||||
welcome.setContentType(mime);
|
||||
welcome.setText(content);
|
||||
welcome.setEditable(false);
|
||||
welcome.addHyperlinkListener(new HyperlinkListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(HyperlinkEvent arg0) {
|
||||
arg0.getEventType();
|
||||
if (arg0.getEventType() == EventType.ACTIVATED) {
|
||||
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
|
||||
try {
|
||||
Desktop.getDesktop().browse(arg0.getURL().toURI());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
JPanel pane = new JPanel();
|
||||
pane.setLayout(new BorderLayout());
|
||||
pane.add(new JScrollPane(welcome), BorderLayout.CENTER);
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void targetUpdated() {}
|
||||
|
||||
}
|
||||
17
src/com/gpl/rpg/atcontentstudio/ui/BooleanBasedCheckBox.java
Normal file
17
src/com/gpl/rpg/atcontentstudio/ui/BooleanBasedCheckBox.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
public class BooleanBasedCheckBox extends JCheckBox {
|
||||
|
||||
private static final long serialVersionUID = 3941646360487399554L;
|
||||
|
||||
public Boolean getBooleanValue() {
|
||||
return isSelected() ? Boolean.TRUE : null;
|
||||
}
|
||||
|
||||
public void setBooleanValue(Boolean val) {
|
||||
setSelected(val != null && val);
|
||||
}
|
||||
|
||||
}
|
||||
160
src/com/gpl/rpg/atcontentstudio/ui/CollapsiblePanel.java
Normal file
160
src/com/gpl/rpg/atcontentstudio/ui/CollapsiblePanel.java
Normal file
@@ -0,0 +1,160 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
public class CollapsiblePanel extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 319384990345722150L;
|
||||
|
||||
String title;
|
||||
TitledBorder border;
|
||||
|
||||
public CollapsiblePanel(String title) {
|
||||
super();
|
||||
this.title = title;
|
||||
border = BorderFactory.createTitledBorder(title);
|
||||
setBorder(border);
|
||||
BorderLayout borderLayout = new BorderLayout();
|
||||
setLayout(borderLayout);
|
||||
addMouseListener(mouseListener);
|
||||
}
|
||||
|
||||
MouseListener mouseListener = new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
toggleVisibility();
|
||||
}
|
||||
};
|
||||
|
||||
ComponentListener contentComponentListener = new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
updateBorderTitle();
|
||||
}
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {
|
||||
updateBorderTitle();
|
||||
}
|
||||
};
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
String oldTitle = this.title;
|
||||
this.title = title;
|
||||
firePropertyChange("title", oldTitle, this.title);
|
||||
updateBorderTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component add(Component comp) {
|
||||
comp.addComponentListener(contentComponentListener);
|
||||
Component r = super.add(comp);
|
||||
updateBorderTitle();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component add(String name, Component comp) {
|
||||
comp.addComponentListener(contentComponentListener);
|
||||
Component r = super.add(name, comp);
|
||||
updateBorderTitle();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component add(Component comp, int index) {
|
||||
comp.addComponentListener(contentComponentListener);
|
||||
Component r = super.add(comp, index);
|
||||
updateBorderTitle();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Component comp, Object constraints) {
|
||||
comp.addComponentListener(contentComponentListener);
|
||||
super.add(comp, constraints);
|
||||
updateBorderTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Component comp, Object constraints, int index) {
|
||||
comp.addComponentListener(contentComponentListener);
|
||||
super.add(comp, constraints, index);
|
||||
updateBorderTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(int index) {
|
||||
Component comp = getComponent(index);
|
||||
comp.removeComponentListener(contentComponentListener);
|
||||
super.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Component comp) {
|
||||
comp.removeComponentListener(contentComponentListener);
|
||||
super.remove(comp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll() {
|
||||
for (Component c : getComponents()) {
|
||||
c.removeComponentListener(contentComponentListener);
|
||||
}
|
||||
super.removeAll();
|
||||
}
|
||||
|
||||
protected void toggleVisibility() {
|
||||
toggleVisibility(hasInvisibleComponent());
|
||||
}
|
||||
|
||||
protected void toggleVisibility(boolean visible) {
|
||||
for (Component c : getComponents()) {
|
||||
c.setVisible(visible);
|
||||
}
|
||||
updateBorderTitle();
|
||||
}
|
||||
|
||||
protected void updateBorderTitle() {
|
||||
String arrow = "";
|
||||
if (getComponentCount() > 0) {
|
||||
arrow = (hasInvisibleComponent()?"[+] ":"[-] ");
|
||||
}
|
||||
border.setTitle(arrow+title);
|
||||
repaint();
|
||||
}
|
||||
|
||||
protected final boolean hasInvisibleComponent() {
|
||||
for (Component c : getComponents()) {
|
||||
if (!c.isVisible()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void collapse() {
|
||||
toggleVisibility(false);
|
||||
}
|
||||
public void expand() {
|
||||
toggleVisibility(true);
|
||||
}
|
||||
public void setExpanded(boolean expand) {
|
||||
toggleVisibility(expand);
|
||||
}
|
||||
|
||||
}
|
||||
254
src/com/gpl/rpg/atcontentstudio/ui/DefaultIcons.java
Normal file
254
src/com/gpl/rpg/atcontentstudio/ui/DefaultIcons.java
Normal file
@@ -0,0 +1,254 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.Notification;
|
||||
|
||||
public class DefaultIcons {
|
||||
|
||||
private static Map<String, Image> imageCache = new HashMap<String, Image>();
|
||||
private static Map<String, Image> iconCache = new HashMap<String, Image>();
|
||||
|
||||
|
||||
private static String MAIN_ICON_RES = "/com/gpl/rpg/atcontentstudio/img/andorstrainer.png";
|
||||
public static Image getMainIconImage() { return getImage(MAIN_ICON_RES); }
|
||||
public static Image getMainIconIcon() { return getIcon(MAIN_ICON_RES); }
|
||||
|
||||
private static String FOLDER_STD_CLOSED_RES = "/com/gpl/rpg/atcontentstudio/img/folder_std_closed.png";
|
||||
public static Image getStdClosedImage() { return getImage(FOLDER_STD_CLOSED_RES); }
|
||||
public static Image getStdClosedIcon() { return getIcon(FOLDER_STD_CLOSED_RES); }
|
||||
|
||||
private static String FOLDER_STD_OPEN_RES = "/com/gpl/rpg/atcontentstudio/img/folder_std_open.png";
|
||||
public static Image getStdOpenImage() { return getImage(FOLDER_STD_OPEN_RES); }
|
||||
public static Image getStdOpenIcon() { return getIcon(FOLDER_STD_OPEN_RES); }
|
||||
|
||||
private static String FOLDER_JSON_CLOSED_RES = "/com/gpl/rpg/atcontentstudio/img/folder_json_closed.png";
|
||||
public static Image getJsonClosedImage() { return getImage(FOLDER_JSON_CLOSED_RES); }
|
||||
public static Image getJsonClosedIcon() { return getIcon(FOLDER_JSON_CLOSED_RES); }
|
||||
|
||||
private static String FOLDER_JSON_OPEN_RES = "/com/gpl/rpg/atcontentstudio/img/folder_json_open.png";
|
||||
public static Image getJsonOpenImage() { return getImage(FOLDER_JSON_OPEN_RES); }
|
||||
public static Image getJsonOpenIcon() { return getIcon(FOLDER_JSON_OPEN_RES); }
|
||||
|
||||
private static String FOLDER_SAV_CLOSED_RES = "/com/gpl/rpg/atcontentstudio/img/folder_sav_closed.png";
|
||||
public static Image getSavClosedImage() { return getImage(FOLDER_SAV_CLOSED_RES); }
|
||||
public static Image getSavClosedIcon() { return getIcon(FOLDER_SAV_CLOSED_RES); }
|
||||
|
||||
private static String FOLDER_SAV_OPEN_RES = "/com/gpl/rpg/atcontentstudio/img/folder_sav_open.png";
|
||||
public static Image getSavOpenImage() { return getImage(FOLDER_SAV_OPEN_RES); }
|
||||
public static Image getSavOpenIcon() { return getIcon(FOLDER_SAV_OPEN_RES); }
|
||||
|
||||
private static String FOLDER_SPRITE_CLOSED_RES = "/com/gpl/rpg/atcontentstudio/img/folder_sprite_closed.png";
|
||||
public static Image getSpriteClosedImage() { return getImage(FOLDER_SPRITE_CLOSED_RES); }
|
||||
public static Image getSpriteClosedIcon() { return getIcon(FOLDER_SPRITE_CLOSED_RES); }
|
||||
|
||||
private static String FOLDER_SPRITE_OPEN_RES = "/com/gpl/rpg/atcontentstudio/img/folder_sprite_open.png";
|
||||
public static Image getSpriteOpenImage() { return getImage(FOLDER_SPRITE_OPEN_RES); }
|
||||
public static Image getSpriteOpenIcon() { return getIcon(FOLDER_SPRITE_OPEN_RES); }
|
||||
|
||||
private static String FOLDER_TMX_CLOSED_RES = "/com/gpl/rpg/atcontentstudio/img/folder_tmx_closed.png";
|
||||
public static Image getTmxClosedImage() { return getImage(FOLDER_TMX_CLOSED_RES); }
|
||||
public static Image getTmxClosedIcon() { return getIcon(FOLDER_TMX_CLOSED_RES); }
|
||||
|
||||
private static String FOLDER_TMX_OPEN_RES = "/com/gpl/rpg/atcontentstudio/img/folder_tmx_open.png";
|
||||
public static Image getTmxOpenImage() { return getImage(FOLDER_TMX_OPEN_RES); }
|
||||
public static Image getTmxOpenIcon() { return getIcon(FOLDER_TMX_OPEN_RES); }
|
||||
|
||||
private static String FOLDER_MAP_CLOSED_RES = "/com/gpl/rpg/atcontentstudio/img/folder_map_closed.png";
|
||||
public static Image getMapClosedImage() { return getImage(FOLDER_MAP_CLOSED_RES); }
|
||||
public static Image getMapClosedIcon() { return getIcon(FOLDER_MAP_CLOSED_RES); }
|
||||
|
||||
private static String FOLDER_MAP_OPEN_RES = "/com/gpl/rpg/atcontentstudio/img/folder_map_open.png";
|
||||
public static Image getMapOpenImage() { return getImage(FOLDER_MAP_OPEN_RES); }
|
||||
public static Image getMapOpenIcon() { return getIcon(FOLDER_MAP_OPEN_RES); }
|
||||
|
||||
private static String FOLDER_AT_CLOSED_RES = "/com/gpl/rpg/atcontentstudio/img/folder_at_closed.png";
|
||||
public static Image getATClosedImage() { return getImage(FOLDER_AT_CLOSED_RES); }
|
||||
public static Image getATClosedIcon() { return getIcon(FOLDER_AT_CLOSED_RES); }
|
||||
|
||||
private static String FOLDER_AT_OPEN_RES = "/com/gpl/rpg/atcontentstudio/img/folder_at_open.png";
|
||||
public static Image getATOpenImage() { return getImage(FOLDER_AT_OPEN_RES); }
|
||||
public static Image getATOpenIcon() { return getIcon(FOLDER_AT_OPEN_RES); }
|
||||
|
||||
private static String TILED_ICON_RES = "/com/gpl/rpg/atcontentstudio/img/tiled-icon.png";
|
||||
public static Image getTiledIconImage() { return getImage(TILED_ICON_RES); }
|
||||
public static Image getTiledIconIcon() { return getIcon(TILED_ICON_RES); }
|
||||
|
||||
private static String UI_MAP_RES = "/com/gpl/rpg/atcontentstudio/img/ui_icon_map.png";
|
||||
public static Image getUIMapImage() { return getImage(UI_MAP_RES); }
|
||||
public static Image getUIMapIcon() { return getIcon(UI_MAP_RES); }
|
||||
|
||||
private static String HERO_RES = "/com/gpl/rpg/atcontentstudio/img/char_hero.png";
|
||||
public static Image getHeroImage() { return getImage(HERO_RES); }
|
||||
public static Image getHeroIcon() { return getIcon(HERO_RES); }
|
||||
|
||||
private static String TILE_LAYER_RES = "/com/gpl/rpg/atcontentstudio/img/tile_layer.png";
|
||||
public static Image getTileLayerImage() { return getImage(TILE_LAYER_RES); }
|
||||
public static Image getTileLayerIcon() { return getIcon(TILE_LAYER_RES); }
|
||||
|
||||
private static String OBJECT_LAYER_RES = "/com/gpl/rpg/atcontentstudio/img/object_layer.png";
|
||||
public static Image getObjectLayerImage() { return getImage(OBJECT_LAYER_RES); }
|
||||
public static Image getObjectLayerIcon() { return getIcon(OBJECT_LAYER_RES); }
|
||||
|
||||
private static String ACTOR_CONDITION_RES = "/com/gpl/rpg/atcontentstudio/img/actor_condition.png";
|
||||
public static Image getActorConditionImage() { return getImage(ACTOR_CONDITION_RES); }
|
||||
public static Image getActorConditionIcon() { return getIcon(ACTOR_CONDITION_RES); }
|
||||
|
||||
private static String ITEM_RES = "/com/gpl/rpg/atcontentstudio/img/item.png";
|
||||
public static Image getItemImage() { return getImage(ITEM_RES); }
|
||||
public static Image getItemIcon() { return getIcon(ITEM_RES); }
|
||||
|
||||
private static String NPC_RES = "/com/gpl/rpg/atcontentstudio/img/npc.png";
|
||||
public static Image getNPCImage() { return getImage(NPC_RES); }
|
||||
public static Image getNPCIcon() { return getIcon(NPC_RES); }
|
||||
|
||||
private static String NPC_CLOSE_RES = "/com/gpl/rpg/atcontentstudio/img/npc_close.png";
|
||||
public static Image getNPCCloseImage() { return getImage(NPC_CLOSE_RES); }
|
||||
public static Image getNPCCloseIcon() { return getIcon(NPC_CLOSE_RES); }
|
||||
|
||||
private static String DIALOGUE_RES = "/com/gpl/rpg/atcontentstudio/img/dialogue.png";
|
||||
public static Image getDialogueImage() { return getImage(DIALOGUE_RES); }
|
||||
public static Image getDialogueIcon() { return getIcon(DIALOGUE_RES); }
|
||||
|
||||
private static String QUEST_RES = "/com/gpl/rpg/atcontentstudio/img/ui_icon_quest.png";
|
||||
public static Image getQuestImage() { return getImage(QUEST_RES); }
|
||||
public static Image getQuestIcon() { return getIcon(QUEST_RES); }
|
||||
|
||||
private static String DROPLIST_RES = "/com/gpl/rpg/atcontentstudio/img/ui_icon_equipment.png";
|
||||
public static Image getDroplistImage() { return getImage(DROPLIST_RES); }
|
||||
public static Image getDroplistIcon() { return getIcon(DROPLIST_RES); }
|
||||
|
||||
private static String COMBAT_RES = "/com/gpl/rpg/atcontentstudio/img/ui_icon_combat.png";
|
||||
public static Image getCombatImage() { return getImage(COMBAT_RES); }
|
||||
public static Image getCombatIcon() { return getIcon(COMBAT_RES); }
|
||||
|
||||
private static String GOLD_RES = "/com/gpl/rpg/atcontentstudio/img/ui_icon_coins.png";
|
||||
public static Image getGoldImage() { return getImage(GOLD_RES); }
|
||||
public static Image getGoldIcon() { return getIcon(GOLD_RES); }
|
||||
|
||||
private static String ITEM_CATEGORY_RES = "/com/gpl/rpg/atcontentstudio/img/equip_weapon.png";
|
||||
public static Image getItemCategoryImage() { return getImage(ITEM_CATEGORY_RES); }
|
||||
public static Image getItemCategoryIcon() { return getIcon(ITEM_CATEGORY_RES); }
|
||||
|
||||
private static String NULLIFY_RES = "/com/gpl/rpg/atcontentstudio/img/nullify.png";
|
||||
public static Image getNullifyImage() { return getImage(NULLIFY_RES); }
|
||||
public static Image getNullifyIcon() { return getIcon(NULLIFY_RES); }
|
||||
|
||||
private static String CREATE_RES = "/com/gpl/rpg/atcontentstudio/img/file_create.png";
|
||||
public static Image getCreateImage() { return getImage(CREATE_RES); }
|
||||
public static Image getCreateIcon() { return getIcon(CREATE_RES); }
|
||||
|
||||
private static String ARROW_UP_RES = "/com/gpl/rpg/atcontentstudio/img/arrow_up.png";
|
||||
public static Image getArrowUpImage() { return getImage(ARROW_UP_RES); }
|
||||
public static Image getArrowUpIcon() { return getIcon(ARROW_UP_RES); }
|
||||
|
||||
private static String ARROW_DOWN_RES = "/com/gpl/rpg/atcontentstudio/img/arrow_down.png";
|
||||
public static Image getArrowDownImage() { return getImage(ARROW_DOWN_RES); }
|
||||
public static Image getArrowDownIcon() { return getIcon(ARROW_DOWN_RES); }
|
||||
|
||||
private static String ARROW_LEFT_RES = "/com/gpl/rpg/atcontentstudio/img/arrow_left.png";
|
||||
public static Image getArrowLeftImage() { return getImage(ARROW_LEFT_RES); }
|
||||
public static Image getArrowLeftIcon() { return getIcon(ARROW_LEFT_RES); }
|
||||
|
||||
private static String ARROW_RIGHT_RES = "/com/gpl/rpg/atcontentstudio/img/arrow_right.png";
|
||||
public static Image getArrowRightImage() { return getImage(ARROW_RIGHT_RES); }
|
||||
public static Image getArrowRightIcon() { return getIcon(ARROW_RIGHT_RES); }
|
||||
|
||||
private static String CONTAINER_RES = "/com/gpl/rpg/atcontentstudio/img/container.png";
|
||||
public static Image getContainerImage() { return getImage(CONTAINER_RES); }
|
||||
public static Image getContainerIcon() { return getIcon(CONTAINER_RES); }
|
||||
|
||||
private static String KEY_RES = "/com/gpl/rpg/atcontentstudio/img/key.png";
|
||||
public static Image getKeyImage() { return getImage(KEY_RES); }
|
||||
public static Image getKeyIcon() { return getIcon(KEY_RES); }
|
||||
|
||||
private static String MAPCHANGE_RES = "/com/gpl/rpg/atcontentstudio/img/mapchange.png";
|
||||
public static Image getMapchangeImage() { return getImage(MAPCHANGE_RES); }
|
||||
public static Image getMapchangeIcon() { return getIcon(MAPCHANGE_RES); }
|
||||
|
||||
private static String REPLACE_RES = "/com/gpl/rpg/atcontentstudio/img/replace.png";
|
||||
public static Image getReplaceImage() { return getImage(REPLACE_RES); }
|
||||
public static Image getReplaceIcon() { return getIcon(REPLACE_RES); }
|
||||
|
||||
private static String REST_RES = "/com/gpl/rpg/atcontentstudio/img/rest.png";
|
||||
public static Image getRestImage() { return getImage(REST_RES); }
|
||||
public static Image getRestIcon() { return getIcon(REST_RES); }
|
||||
|
||||
private static String SCRIPT_RES = "/com/gpl/rpg/atcontentstudio/img/script.png";
|
||||
public static Image getScriptImage() { return getImage(SCRIPT_RES); }
|
||||
public static Image getScriptIcon() { return getIcon(SCRIPT_RES); }
|
||||
|
||||
private static String SIGN_RES = "/com/gpl/rpg/atcontentstudio/img/sign.png";
|
||||
public static Image getSignImage() { return getImage(SIGN_RES); }
|
||||
public static Image getSignIcon() { return getIcon(SIGN_RES); }
|
||||
|
||||
private static String CREATE_CONTAINER_RES = "/com/gpl/rpg/atcontentstudio/img/create_container.png";
|
||||
public static Image getCreateContainerImage() { return getImage(CREATE_CONTAINER_RES); }
|
||||
public static Image getCreateContainerIcon() { return getIcon(CREATE_CONTAINER_RES); }
|
||||
|
||||
private static String CREATE_KEY_RES = "/com/gpl/rpg/atcontentstudio/img/create_key.png";
|
||||
public static Image getCreateKeyImage() { return getImage(CREATE_KEY_RES); }
|
||||
public static Image getCreateKeyIcon() { return getIcon(CREATE_KEY_RES); }
|
||||
|
||||
private static String CREATE_REPLACE_RES = "/com/gpl/rpg/atcontentstudio/img/create_replace.png";
|
||||
public static Image getCreateReplaceImage() { return getImage(CREATE_REPLACE_RES); }
|
||||
public static Image getCreateReplaceIcon() { return getIcon(CREATE_REPLACE_RES); }
|
||||
|
||||
private static String CREATE_REST_RES = "/com/gpl/rpg/atcontentstudio/img/create_rest.png";
|
||||
public static Image getCreateRestImage() { return getImage(CREATE_REST_RES); }
|
||||
public static Image getCreateRestIcon() { return getIcon(CREATE_REST_RES); }
|
||||
|
||||
private static String CREATE_SCRIPT_RES = "/com/gpl/rpg/atcontentstudio/img/create_script.png";
|
||||
public static Image getCreateScriptImage() { return getImage(CREATE_SCRIPT_RES); }
|
||||
public static Image getCreateScriptIcon() { return getIcon(CREATE_SCRIPT_RES); }
|
||||
|
||||
private static String CREATE_SIGN_RES = "/com/gpl/rpg/atcontentstudio/img/create_sign.png";
|
||||
public static Image getCreateSignImage() { return getImage(CREATE_SIGN_RES); }
|
||||
public static Image getCreateSignIcon() { return getIcon(CREATE_SIGN_RES); }
|
||||
|
||||
private static String CREATE_SPAWNAREA_RES = "/com/gpl/rpg/atcontentstudio/img/create_spawnarea.png";
|
||||
public static Image getCreateSpawnareaImage() { return getImage(CREATE_SPAWNAREA_RES); }
|
||||
public static Image getCreateSpawnareaIcon() { return getIcon(CREATE_SPAWNAREA_RES); }
|
||||
|
||||
private static String CREATE_MAPCHANGE_RES = "/com/gpl/rpg/atcontentstudio/img/create_tiled.png";
|
||||
public static Image getCreateMapchangeImage() { return getImage(CREATE_MAPCHANGE_RES); }
|
||||
public static Image getCreateMapchangeIcon() { return getIcon(CREATE_MAPCHANGE_RES); }
|
||||
|
||||
private static String CREATE_OBJECT_GROUP_RES = "/com/gpl/rpg/atcontentstudio/img/create_object_group.png";
|
||||
public static Image getCreateObjectGroupImage() { return getImage(CREATE_OBJECT_GROUP_RES); }
|
||||
public static Image getCreateObjectGroupIcon() { return getIcon(CREATE_OBJECT_GROUP_RES); }
|
||||
|
||||
private static String CREATE_TILE_LAYER_RES = "/com/gpl/rpg/atcontentstudio/img/create_tile_layer.png";
|
||||
public static Image getCreateTileLayerImage() { return getImage(CREATE_TILE_LAYER_RES); }
|
||||
public static Image getCreateTileLayerIcon() { return getIcon(CREATE_TILE_LAYER_RES); }
|
||||
|
||||
private static String ZOOM_RES = "/com/gpl/rpg/atcontentstudio/img/zoom.png";
|
||||
public static Image getZoomImage() { return getImage(ZOOM_RES); }
|
||||
public static Image getZoomIcon() { return getIcon(ZOOM_RES); }
|
||||
|
||||
private static Image getImage(String res) {
|
||||
if (imageCache.get(res) == null) {
|
||||
try {
|
||||
Image img = ImageIO.read(DefaultIcons.class.getResourceAsStream(res));
|
||||
imageCache.put(res, img);
|
||||
} catch (IOException e) {
|
||||
Notification.addError("Failed to load image "+res);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return imageCache.get(res);
|
||||
}
|
||||
|
||||
private static Image getIcon(String res) {
|
||||
if (iconCache.get(res) == null) {
|
||||
Image icon = getImage(res).getScaledInstance(16, 16, Image.SCALE_SMOOTH);
|
||||
iconCache.put(res, icon);
|
||||
}
|
||||
return iconCache.get(res);
|
||||
}
|
||||
}
|
||||
735
src/com/gpl/rpg/atcontentstudio/ui/Editor.java
Normal file
735
src/com/gpl/rpg/atcontentstudio/ui/Editor.java
Normal file
@@ -0,0 +1,735 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.AbstractListModel;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JSpinner.NumberEditor;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import javax.swing.text.DefaultFormatter;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.Notification;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectElementListener;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||
import com.jidesoft.swing.ComboBoxSearchable;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
public abstract class Editor extends JPanel implements ProjectElementListener {
|
||||
|
||||
private static final long serialVersionUID = 241750514033596878L;
|
||||
private static final FieldUpdateListener nullListener = new FieldUpdateListener() {@Override public void valueChanged(JComponent source, Object value) {}};
|
||||
|
||||
public static final String SAVE = "Save";
|
||||
public static final String DELETE = "Delete";
|
||||
public static final String REVERT = "Revert to original";
|
||||
public static final String ALTER = "Alter";
|
||||
public static final String GO_TO_ALTERED = "Go to altered";
|
||||
|
||||
|
||||
public static final String READ_ONLY_MESSAGE =
|
||||
"<html><i>" +
|
||||
"This element is not modifiable.<br/>" +
|
||||
"Click on the \"Alter\" button to create a writable copy." +
|
||||
"</i></html>";
|
||||
|
||||
public static final String ALTERED_EXISTS_MESSAGE =
|
||||
"<html><i>" +
|
||||
"This element is not modifiable.<br/>" +
|
||||
"A writable copy exists in this project. Click on \"Go to altered\" to open it." +
|
||||
"</i></html>";
|
||||
|
||||
public static final String ALTERED_MESSAGE =
|
||||
"<html><i>" +
|
||||
"This element is a writable copy of an element of the referenced game source.<br/>" +
|
||||
"Take care not to break existing content when modifying it." +
|
||||
"</i></html>";
|
||||
|
||||
public static final String CREATED_MESSAGE =
|
||||
"<html><i>" +
|
||||
"This element is a creation of yours.<br/>" +
|
||||
"Do as you please." +
|
||||
"</i></html>";
|
||||
|
||||
|
||||
public String name = "Editor";
|
||||
public Icon icon = null;
|
||||
public GameDataElement target = null;
|
||||
|
||||
public JLabel message = null;
|
||||
|
||||
|
||||
public static JTextField addLabelField(JPanel pane, String label, String value) {
|
||||
return addTextField(pane, label, value, false, nullListener);
|
||||
}
|
||||
|
||||
public static JTextField addTextField(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
|
||||
JPanel tfPane = new JPanel();
|
||||
tfPane.setLayout(new JideBoxLayout(tfPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
JLabel tfLabel = new JLabel(label);
|
||||
tfPane.add(tfLabel, JideBoxLayout.FIX);
|
||||
final JTextField tfField = new JTextField(initialValue);
|
||||
tfField.setEditable(editable);
|
||||
tfPane.add(tfField, JideBoxLayout.VARY);
|
||||
JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
tfPane.add(nullify, JideBoxLayout.FIX);
|
||||
nullify.setEnabled(editable);
|
||||
pane.add(tfPane, JideBoxLayout.FIX);
|
||||
|
||||
nullify.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
tfField.setText("");
|
||||
listener.valueChanged(tfField, null);
|
||||
}
|
||||
});
|
||||
tfField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
listener.valueChanged(tfField, tfField.getText());
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
listener.valueChanged(tfField, tfField.getText());
|
||||
}
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
listener.valueChanged(tfField, tfField.getText());
|
||||
}
|
||||
});
|
||||
tfField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
listener.valueChanged(tfField, tfField.getText());
|
||||
}
|
||||
});
|
||||
return tfField;
|
||||
}
|
||||
|
||||
// public static JSpinner addIntegerField(JPanel pane, String label, Integer initialValue, boolean allowNegatives, boolean editable) {
|
||||
// return addIntegerField(pane, label, initialValue, allowNegatives, editable, nullListener);
|
||||
// }
|
||||
|
||||
public static JSpinner addIntegerField(JPanel pane, String label, Integer initialValue, boolean allowNegatives, boolean editable, final FieldUpdateListener listener) {
|
||||
JPanel tfPane = new JPanel();
|
||||
tfPane.setLayout(new JideBoxLayout(tfPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
JLabel tfLabel = new JLabel(label);
|
||||
tfPane.add(tfLabel, JideBoxLayout.FIX);
|
||||
final JSpinner spinner = new JSpinner(new SpinnerNumberModel(initialValue != null ? initialValue.intValue() : 0, allowNegatives ? Integer.MIN_VALUE : 0, Integer.MAX_VALUE, 1));
|
||||
((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().setHorizontalAlignment(JTextField.LEFT);
|
||||
spinner.setEnabled(editable);
|
||||
((DefaultFormatter)((NumberEditor)spinner.getEditor()).getTextField().getFormatter()).setCommitsOnValidEdit(true);
|
||||
tfPane.add(spinner, JideBoxLayout.VARY);
|
||||
JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
tfPane.add(nullify, JideBoxLayout.FIX);
|
||||
nullify.setEnabled(editable);
|
||||
pane.add(tfPane, JideBoxLayout.FIX);
|
||||
spinner.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
listener.valueChanged(spinner, spinner.getValue());
|
||||
}
|
||||
});
|
||||
nullify.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
spinner.setValue(0);
|
||||
listener.valueChanged(spinner, null);
|
||||
}
|
||||
});
|
||||
return spinner;
|
||||
}
|
||||
|
||||
// public static JSpinner addDoubleField(JPanel pane, String label, Double initialValue, boolean editable) {
|
||||
// return addDoubleField(pane, label, initialValue, editable, nullListener);
|
||||
// }
|
||||
|
||||
public static JSpinner addDoubleField(JPanel pane, String label, Double initialValue, boolean editable, final FieldUpdateListener listener) {
|
||||
JPanel tfPane = new JPanel();
|
||||
tfPane.setLayout(new JideBoxLayout(tfPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
JLabel tfLabel = new JLabel(label);
|
||||
tfPane.add(tfLabel, JideBoxLayout.FIX);
|
||||
final JSpinner spinner = new JSpinner(new SpinnerNumberModel(initialValue != null ? initialValue.doubleValue() : 0.0d, 0.0d, new Float(Float.MAX_VALUE).doubleValue(), 1.0d));
|
||||
((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().setHorizontalAlignment(JTextField.LEFT);
|
||||
spinner.setEnabled(editable);
|
||||
((DefaultFormatter)((NumberEditor)spinner.getEditor()).getTextField().getFormatter()).setCommitsOnValidEdit(true);
|
||||
tfPane.add(spinner, JideBoxLayout.VARY);
|
||||
JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
tfPane.add(nullify, JideBoxLayout.FIX);
|
||||
nullify.setEnabled(editable);
|
||||
pane.add(tfPane, JideBoxLayout.FIX);
|
||||
pane.add(tfPane, JideBoxLayout.FIX);
|
||||
spinner.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
listener.valueChanged(spinner, spinner.getValue());
|
||||
}
|
||||
});
|
||||
nullify.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
spinner.setValue(0.0d);
|
||||
listener.valueChanged(spinner, null);
|
||||
}
|
||||
});
|
||||
return spinner;
|
||||
}
|
||||
|
||||
public static IntegerBasedCheckBox addIntegerBasedCheckBox(JPanel pane, String label, Integer initialValue, boolean editable) {
|
||||
return addIntegerBasedCheckBox(pane, label, initialValue, editable, nullListener);
|
||||
}
|
||||
|
||||
public static IntegerBasedCheckBox addIntegerBasedCheckBox(JPanel pane, String label, Integer initialValue, boolean editable, final FieldUpdateListener listener) {
|
||||
JPanel ibcbPane = new JPanel();
|
||||
ibcbPane.setLayout(new BorderLayout());
|
||||
final IntegerBasedCheckBox ibcb = new IntegerBasedCheckBox();
|
||||
ibcb.setText(label);
|
||||
ibcb.setIntegerValue(initialValue);
|
||||
ibcb.setEnabled(editable);
|
||||
ibcbPane.add(ibcb, BorderLayout.WEST);
|
||||
ibcbPane.add(new JPanel(), BorderLayout.CENTER);
|
||||
pane.add(ibcbPane, JideBoxLayout.FIX);
|
||||
ibcb.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
listener.valueChanged(ibcb, ibcb.getIntegerValue());
|
||||
}
|
||||
});
|
||||
return ibcb;
|
||||
}
|
||||
|
||||
public static BooleanBasedCheckBox addBooleanBasedCheckBox(JPanel pane, String label, Boolean initialValue, boolean editable, final FieldUpdateListener listener) {
|
||||
JPanel bbcbPane = new JPanel();
|
||||
bbcbPane.setLayout(new BorderLayout());
|
||||
final BooleanBasedCheckBox bbcb = new BooleanBasedCheckBox();
|
||||
bbcb.setText(label);
|
||||
bbcb.setBooleanValue(initialValue);
|
||||
bbcb.setEnabled(editable);
|
||||
bbcbPane.add(bbcb, BorderLayout.WEST);
|
||||
bbcbPane.add(new JPanel(), BorderLayout.CENTER);
|
||||
pane.add(bbcbPane, JideBoxLayout.FIX);
|
||||
bbcb.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
listener.valueChanged(bbcb, bbcb.isSelected());
|
||||
}
|
||||
});
|
||||
return bbcb;
|
||||
}
|
||||
|
||||
public static JComboBox addEnumValueBox(JPanel pane, String label, @SuppressWarnings("rawtypes") Enum[] values, @SuppressWarnings("rawtypes") Enum initialValue, boolean writable) {
|
||||
return addEnumValueBox(pane, label, values, initialValue, writable, new FieldUpdateListener() {@Override public void valueChanged(JComponent source, Object value) {}});
|
||||
}
|
||||
|
||||
public static JComboBox addEnumValueBox(JPanel pane, String label, @SuppressWarnings("rawtypes") Enum[] values, @SuppressWarnings("rawtypes") Enum initialValue, boolean writable, final FieldUpdateListener listener) {
|
||||
JPanel comboPane = new JPanel();
|
||||
comboPane.setLayout(new JideBoxLayout(comboPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
JLabel comboLabel = new JLabel(label);
|
||||
comboPane.add(comboLabel, JideBoxLayout.FIX);
|
||||
final JComboBox enumValuesCombo = new JComboBox(values);
|
||||
enumValuesCombo.setEnabled(writable);
|
||||
enumValuesCombo.setSelectedItem(initialValue);
|
||||
comboPane.add(enumValuesCombo, JideBoxLayout.VARY);
|
||||
enumValuesCombo.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
listener.valueChanged(enumValuesCombo, e.getItem());
|
||||
}
|
||||
}
|
||||
});
|
||||
JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
comboPane.add(nullify, JideBoxLayout.FIX);
|
||||
nullify.setEnabled(writable);
|
||||
nullify.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
enumValuesCombo.setSelectedItem(null);
|
||||
listener.valueChanged(enumValuesCombo, null);
|
||||
}
|
||||
});
|
||||
|
||||
pane.add(comboPane, JideBoxLayout.FIX);
|
||||
return enumValuesCombo;
|
||||
}
|
||||
|
||||
|
||||
public MyComboBox addNPCBox(JPanel pane, Project proj, String label, NPC npc, boolean writable, FieldUpdateListener listener) {
|
||||
final GDEComboModel<NPC> comboModel = new GDEComboModel<NPC>(proj, npc){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getNPC(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getNPCCount()+1;
|
||||
}
|
||||
};
|
||||
return addGDEBox(pane, label, npc, NPC.class, comboModel, writable, listener);
|
||||
}
|
||||
|
||||
public MyComboBox addActorConditionBox(JPanel pane, Project proj, String label, ActorCondition acond, boolean writable, FieldUpdateListener listener) {
|
||||
final GDEComboModel<ActorCondition> comboModel = new GDEComboModel<ActorCondition>(proj, acond){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getActorCondition(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getActorConditionCount()+1;
|
||||
}
|
||||
};
|
||||
return addGDEBox(pane, label, acond, ActorCondition.class, comboModel, writable, listener);
|
||||
}
|
||||
|
||||
public MyComboBox addItemBox(JPanel pane, Project proj, String label, Item item, boolean writable, FieldUpdateListener listener) {
|
||||
final GDEComboModel<Item> comboModel = new GDEComboModel<Item>(proj, item){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getItem(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getItemCount()+1;
|
||||
}
|
||||
};
|
||||
return addGDEBox(pane, label, item, Item.class, comboModel, writable, listener);
|
||||
}
|
||||
|
||||
public MyComboBox addItemCategoryBox(JPanel pane, Project proj, String label, ItemCategory ic, boolean writable, FieldUpdateListener listener) {
|
||||
final GDEComboModel<ItemCategory> comboModel = new GDEComboModel<ItemCategory>(proj, ic){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getItemCategory(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getItemCategoryCount()+1;
|
||||
}
|
||||
};
|
||||
return addGDEBox(pane, label, ic, ItemCategory.class, comboModel, writable, listener);
|
||||
}
|
||||
|
||||
public MyComboBox addQuestBox(JPanel pane, Project proj, String label, Quest quest, boolean writable, FieldUpdateListener listener) {
|
||||
final GDEComboModel<Quest> comboModel = new GDEComboModel<Quest>(proj, quest){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getQuest(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getQuestCount()+1;
|
||||
}
|
||||
};
|
||||
return addGDEBox(pane, label, quest, Quest.class, comboModel, writable, listener);
|
||||
}
|
||||
|
||||
public MyComboBox addDroplistBox(JPanel pane, Project proj, String label, Droplist droplist, boolean writable, FieldUpdateListener listener) {
|
||||
final GDEComboModel<Droplist> comboModel = new GDEComboModel<Droplist>(proj, droplist){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getDroplist(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getDroplistCount()+1;
|
||||
}
|
||||
};
|
||||
return addGDEBox(pane, label, droplist, Droplist.class, comboModel, writable, listener);
|
||||
}
|
||||
|
||||
public MyComboBox addDialogueBox(JPanel pane, Project proj, String label, Dialogue dialogue, boolean writable, final FieldUpdateListener listener) {
|
||||
final GDEComboModel<Dialogue> comboModel = new GDEComboModel<Dialogue>(proj, dialogue){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getDialogue(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getDialogueCount()+1;
|
||||
}
|
||||
};
|
||||
return addGDEBox(pane, label, dialogue, Dialogue.class, comboModel, writable, listener);
|
||||
}
|
||||
|
||||
public MyComboBox addMapBox(JPanel pane, Project proj, String label, TMXMap map, boolean writable, final FieldUpdateListener listener) {
|
||||
final GDEComboModel<TMXMap> comboModel = new GDEComboModel<TMXMap>(proj, map){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getMap(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getMapCount()+1;
|
||||
}
|
||||
};
|
||||
return addGDEBox(pane, label, map, TMXMap.class, comboModel, writable, listener);
|
||||
}
|
||||
|
||||
public MyComboBox addGDEBox(JPanel pane, String label, GameDataElement gde, final Class<? extends GameDataElement> dataClass, final GDEComboModel<? extends GameDataElement> comboModel, final boolean writable, final FieldUpdateListener listener) {
|
||||
JPanel gdePane = new JPanel();
|
||||
gdePane.setLayout(new JideBoxLayout(gdePane, JideBoxLayout.LINE_AXIS, 6));
|
||||
JLabel gdeLabel = new JLabel(label);
|
||||
gdePane.add(gdeLabel, JideBoxLayout.FIX);
|
||||
final MyComboBox gdeBox = new MyComboBox(dataClass, comboModel);
|
||||
gdeBox.setRenderer(new GDERenderer(false, writable));
|
||||
new ComboBoxSearchable(gdeBox){
|
||||
@Override
|
||||
protected String convertElementToString(Object object) {
|
||||
if (object == null) return "none";
|
||||
else return ((GameDataElement)object).getDesc();
|
||||
}
|
||||
};
|
||||
gdeBox.setEnabled(writable);
|
||||
gdePane.add(gdeBox, JideBoxLayout.VARY);
|
||||
final JButton goToGde = new JButton((Icon) ((gde != null) ? new ImageIcon(gde.getIcon()) : (writable ? new ImageIcon(DefaultIcons.getCreateIcon()) : null)));
|
||||
goToGde.setEnabled(gde != null || writable);
|
||||
goToGde.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
GameDataElement selected = ((GameDataElement)comboModel.getSelectedItem());
|
||||
if (selected != null) {
|
||||
ATContentStudio.frame.openEditor(((GameDataElement)comboModel.getSelectedItem()));
|
||||
ATContentStudio.frame.selectInTree((GameDataElement)comboModel.getSelectedItem());
|
||||
} else if (writable) {
|
||||
JSONCreationWizard wizard = new JSONCreationWizard(((GameDataElement)target).getProject(), dataClass);
|
||||
wizard.addCreationListener(new JSONCreationWizard.CreationCompletedListener() {
|
||||
|
||||
@Override
|
||||
public void elementCreated(JSONElement created) {
|
||||
gdeBox.setSelectedItem(created);
|
||||
}
|
||||
});
|
||||
wizard.setVisible(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
gdePane.add(goToGde, JideBoxLayout.FIX);
|
||||
gdeBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (gdeBox.getModel().getSelectedItem() == null) {
|
||||
goToGde.setIcon((writable ? new ImageIcon(DefaultIcons.getCreateIcon()) : null));
|
||||
goToGde.setEnabled(writable);
|
||||
} else {
|
||||
goToGde.setIcon(new ImageIcon(((GameDataElement)comboModel.getSelectedItem()).getIcon()));
|
||||
goToGde.setEnabled(true);
|
||||
}
|
||||
listener.valueChanged(gdeBox, gdeBox.getModel().getSelectedItem());
|
||||
}
|
||||
});
|
||||
JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
gdePane.add(nullify, JideBoxLayout.FIX);
|
||||
nullify.setEnabled(writable);
|
||||
nullify.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
gdeBox.setSelectedItem(null);
|
||||
}
|
||||
});
|
||||
pane.add(gdePane, JideBoxLayout.FIX);
|
||||
|
||||
return gdeBox;
|
||||
}
|
||||
|
||||
public JList addBacklinksList(JPanel pane, GameDataElement gde) {
|
||||
final JList list = new JList(new GDEBacklinksListModel(gde));
|
||||
list.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 2) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement)list.getSelectedValue());
|
||||
ATContentStudio.frame.selectInTree((GameDataElement)list.getSelectedValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
list.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement)list.getSelectedValue());
|
||||
ATContentStudio.frame.selectInTree((GameDataElement)list.getSelectedValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
list.setCellRenderer(new GDERenderer(true, false));
|
||||
CollapsiblePanel colPane = new CollapsiblePanel("Elements linking to this one");
|
||||
colPane.setLayout(new JideBoxLayout(colPane, JideBoxLayout.PAGE_AXIS));
|
||||
colPane.add(new JScrollPane(list), JideBoxLayout.FIX);
|
||||
colPane.add(new JPanel(), JideBoxLayout.FIX);
|
||||
if (gde.getBacklinks() == null || gde.getBacklinks().isEmpty()) {
|
||||
colPane.collapse();
|
||||
}
|
||||
pane.add(colPane, JideBoxLayout.FIX);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static abstract class GDEComboModel<E extends GameDataElement> extends AbstractListModel implements ComboBoxModel {
|
||||
|
||||
private static final long serialVersionUID = -5854574666510314715L;
|
||||
|
||||
public Project project;
|
||||
public E selected;
|
||||
|
||||
public GDEComboModel(Project proj, E initial) {
|
||||
this.project = proj;
|
||||
this.selected = initial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract int getSize();
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
if (index == 0) {
|
||||
return null;
|
||||
}
|
||||
return getTypedElementAt(index - 1);
|
||||
}
|
||||
|
||||
public abstract Object getTypedElementAt(int index);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void setSelectedItem(Object anItem) {
|
||||
selected = (E) anItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSelectedItem() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void itemAdded(E item, int index) {
|
||||
fireIntervalAdded(this, index, index);
|
||||
}
|
||||
|
||||
public void itemRemoved(E item, int index) {
|
||||
fireIntervalRemoved(this, index, index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class GDERenderer extends DefaultListCellRenderer {
|
||||
|
||||
private static final long serialVersionUID = 6819681566800482793L;
|
||||
|
||||
private boolean includeType = false;
|
||||
private boolean writable = false;
|
||||
|
||||
public GDERenderer(boolean includeType, boolean writable) {
|
||||
super();
|
||||
this.includeType = includeType;
|
||||
this.writable = writable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (value == null) {
|
||||
label.setText("None"+(writable ? ". Click on the button to create one." : ""));
|
||||
} else {
|
||||
if (includeType && ((GameDataElement)value).getDataType() != null) {
|
||||
label.setText(((GameDataElement)value).getDataType().toString()+"/"+((GameDataElement)value).getDesc());
|
||||
} else {
|
||||
label.setText(((GameDataElement)value).getDesc());
|
||||
}
|
||||
if (((GameDataElement)value).getIcon() == null) {
|
||||
Notification.addError("Unable to find icon for "+((GameDataElement)value).getDesc());
|
||||
} else {
|
||||
label.setIcon(new ImageIcon(((GameDataElement)value).getIcon()));
|
||||
}
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class GDEBacklinksListModel implements ListModel {
|
||||
|
||||
GameDataElement source;
|
||||
|
||||
public GDEBacklinksListModel(GameDataElement source) {
|
||||
super();
|
||||
this.source = source;
|
||||
source.addBacklinkListener(new GameDataElement.BacklinksListener() {
|
||||
@Override
|
||||
public void backlinkRemoved(GameDataElement gde) {
|
||||
fireListChanged();
|
||||
}
|
||||
@Override
|
||||
public void backlinkAdded(GameDataElement gde) {
|
||||
fireListChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return source.getBacklinks().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
for (GameDataElement gde : source.getBacklinks()) {
|
||||
if (index == 0) return gde;
|
||||
index --;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
public void fireListChanged() {
|
||||
for (ListDataListener l : listeners) {
|
||||
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, this.getSize()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MyComboBox extends JComboBox implements ProjectElementListener {
|
||||
|
||||
private static final long serialVersionUID = -4184228604170642567L;
|
||||
|
||||
Class<? extends GameDataElement> dataType;
|
||||
|
||||
public MyComboBox(Class<? extends GameDataElement> dataType, ComboBoxModel model) {
|
||||
super(model);
|
||||
this.dataType = dataType;
|
||||
Editor.this.addElementListener(dataType, this);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public void elementAdded(GameDataElement added, int index) {
|
||||
((GDEComboModel)getModel()).itemAdded(added, index);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public void elementRemoved(GameDataElement removed, int index) {
|
||||
((GDEComboModel)getModel()).itemRemoved(removed, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends GameDataElement> getDataType() {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract void targetUpdated();
|
||||
|
||||
|
||||
|
||||
transient Map<Class<? extends GameDataElement>, List<ProjectElementListener>> projectElementListeners = new HashMap<Class<? extends GameDataElement>, List<ProjectElementListener>>();
|
||||
|
||||
public void addElementListener(Class<? extends GameDataElement> interestingType, ProjectElementListener listener) {
|
||||
if (projectElementListeners.get(interestingType) == null) {
|
||||
projectElementListeners.put(interestingType, new ArrayList<ProjectElementListener>());
|
||||
target.getProject().addElementListener(interestingType, this);
|
||||
}
|
||||
projectElementListeners.get(interestingType).add(listener);
|
||||
}
|
||||
|
||||
public void removeElementListener(ProjectElementListener listener) {
|
||||
if (listener == null) return;
|
||||
if (projectElementListeners.get(listener.getDataType()) != null) {
|
||||
projectElementListeners.get(listener.getDataType()).remove(listener);
|
||||
if (projectElementListeners.get(listener.getDataType()).isEmpty()) {
|
||||
target.getProject().removeElementListener(listener.getDataType(), this);
|
||||
projectElementListeners.remove(listener.getDataType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void elementAdded(GameDataElement element, int index) {
|
||||
if (projectElementListeners.get(element.getClass()) != null) {
|
||||
for (ProjectElementListener l : projectElementListeners.get(element.getClass())) {
|
||||
l.elementAdded(element, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void elementRemoved(GameDataElement element, int index) {
|
||||
if (projectElementListeners.get(element.getClass()) != null) {
|
||||
for (ProjectElementListener l : projectElementListeners.get(element.getClass())) {
|
||||
l.elementRemoved(element, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearElementListeners() {
|
||||
for (Class<? extends GameDataElement> type : projectElementListeners.keySet()) {
|
||||
target.getProject().removeElementListener(type, this);
|
||||
}
|
||||
}
|
||||
|
||||
public Class<? extends GameDataElement> getDataType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
187
src/com/gpl/rpg/atcontentstudio/ui/EditorsArea.java
Normal file
187
src/com/gpl/rpg/atcontentstudio/ui/EditorsArea.java
Normal file
@@ -0,0 +1,187 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
|
||||
import com.gpl.rpg.atcontentstudio.model.saves.SavedGame;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.ActorConditionEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.DialogueEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.DroplistEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.ItemCategoryEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.ItemEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.NPCEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.QuestEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.map.TMXMapEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.map.WorldMapEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.saves.SavedGameEditor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.sprites.SpritesheetEditor;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
public class EditorsArea extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 8801849846876081538L;
|
||||
|
||||
private Map<Object, Editor> editors = new HashMap<Object, Editor>();
|
||||
private JideTabbedPane tabHolder;
|
||||
|
||||
public EditorsArea() {
|
||||
super();
|
||||
setLayout(new BorderLayout());
|
||||
tabHolder = new JideTabbedPane();
|
||||
tabHolder.setTabPlacement(JideTabbedPane.TOP);
|
||||
tabHolder.setTabShape(JideTabbedPane.SHAPE_FLAT);
|
||||
tabHolder.setUseDefaultShowCloseButtonOnTab(false);
|
||||
tabHolder.setShowCloseButtonOnTab(true);
|
||||
tabHolder.setCloseAction(new Action() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
closeEditor((Editor) e.getSource());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean b) {
|
||||
}
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
}
|
||||
@Override
|
||||
public void putValue(String key, Object value) {
|
||||
}
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public Object getValue(String key) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
}
|
||||
});
|
||||
add(tabHolder, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void openEditor(Editor e) {
|
||||
if (!editors.containsKey(e.target) && !editors.containsValue(e)) {
|
||||
editors.put(e.target, e);
|
||||
tabHolder.addTab(e.name, e.icon, e);
|
||||
tabHolder.setSelectedComponent(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeEditor(Editor e) {
|
||||
if (editors.containsValue(e)) {
|
||||
tabHolder.remove(e);
|
||||
editors.remove(e.target);
|
||||
e.clearElementListeners();
|
||||
}
|
||||
}
|
||||
|
||||
public void openEditor(JSONElement node) {
|
||||
if (editors.containsKey(node)) {
|
||||
tabHolder.setSelectedComponent(editors.get(node));
|
||||
return;
|
||||
}
|
||||
if (node instanceof Quest) {
|
||||
openEditor(new QuestEditor((Quest)node));
|
||||
} else if (node instanceof Dialogue) {
|
||||
openEditor(new DialogueEditor((Dialogue) node));
|
||||
} else if (node instanceof Droplist) {
|
||||
openEditor(new DroplistEditor((Droplist) node));
|
||||
} else if (node instanceof ActorCondition) {
|
||||
openEditor(new ActorConditionEditor((ActorCondition) node));
|
||||
} else if (node instanceof ItemCategory) {
|
||||
openEditor(new ItemCategoryEditor((ItemCategory) node));
|
||||
} else if (node instanceof Item) {
|
||||
openEditor(new ItemEditor((Item) node));
|
||||
} else if (node instanceof NPC) {
|
||||
openEditor(new NPCEditor((NPC) node));
|
||||
}
|
||||
}
|
||||
|
||||
public void openEditor(Spritesheet node) {
|
||||
if (editors.containsKey(node)) {
|
||||
tabHolder.setSelectedComponent(editors.get(node));
|
||||
return;
|
||||
}
|
||||
node.link();
|
||||
openEditor(new SpritesheetEditor((Spritesheet) node));
|
||||
}
|
||||
|
||||
public void openEditor(TMXMap node) {
|
||||
if (editors.containsKey(node)) {
|
||||
tabHolder.setSelectedComponent(editors.get(node));
|
||||
return;
|
||||
}
|
||||
node.link();
|
||||
openEditor(new TMXMapEditor(node));
|
||||
}
|
||||
|
||||
|
||||
public void openEditor(SavedGame save) {
|
||||
if (editors.containsKey(save)) {
|
||||
tabHolder.setSelectedComponent(editors.get(save));
|
||||
return;
|
||||
}
|
||||
openEditor(new SavedGameEditor(save));
|
||||
}
|
||||
|
||||
|
||||
public void openEditor(WorldmapSegment node) {
|
||||
if (editors.containsKey(node)) {
|
||||
tabHolder.setSelectedComponent(editors.get(node));
|
||||
return;
|
||||
}
|
||||
node.link();
|
||||
openEditor(new WorldMapEditor(node));
|
||||
}
|
||||
|
||||
public void closeEditor(ProjectTreeNode node) {
|
||||
if (editors.containsKey(node)) {
|
||||
closeEditor(editors.get(node));
|
||||
}
|
||||
}
|
||||
|
||||
public void editorTabChanged(Editor e) {
|
||||
int index = tabHolder.indexOfComponent(e);
|
||||
if (index >= 0) {
|
||||
tabHolder.setTitleAt(index, e.name);
|
||||
tabHolder.setIconAt(index, e.icon);
|
||||
}
|
||||
}
|
||||
|
||||
public void editorTabChanged(ProjectTreeNode node) {
|
||||
if (editors.get(node) != null) {
|
||||
editors.get(node).targetUpdated();
|
||||
editorTabChanged(editors.get(node));
|
||||
}
|
||||
}
|
||||
|
||||
public void showAbout() {
|
||||
if (editors.containsKey(AboutEditor.instance)) {
|
||||
tabHolder.setSelectedComponent(AboutEditor.instance);
|
||||
return;
|
||||
}
|
||||
openEditor(AboutEditor.instance);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
public interface FieldUpdateListener {
|
||||
|
||||
public void valueChanged(JComponent source, Object value);
|
||||
|
||||
}
|
||||
19
src/com/gpl/rpg/atcontentstudio/ui/IntegerBasedCheckBox.java
Normal file
19
src/com/gpl/rpg/atcontentstudio/ui/IntegerBasedCheckBox.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
public class IntegerBasedCheckBox extends JCheckBox {
|
||||
|
||||
private static final long serialVersionUID = 3941646360487399554L;
|
||||
|
||||
static final Integer one = 1;
|
||||
|
||||
public Integer getIntegerValue() {
|
||||
return isSelected() ? one : null;
|
||||
}
|
||||
|
||||
public void setIntegerValue(Integer val) {
|
||||
setSelected(val != null && val.equals(one));
|
||||
}
|
||||
|
||||
}
|
||||
96
src/com/gpl/rpg/atcontentstudio/ui/JMovingIdler.java
Normal file
96
src/com/gpl/rpg/atcontentstudio/ui/JMovingIdler.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.GradientPaint;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
|
||||
public class JMovingIdler extends JComponent {
|
||||
|
||||
private static final long serialVersionUID = -2980521421870322717L;
|
||||
|
||||
int position = 0;
|
||||
boolean destroyed=false, running=false;
|
||||
Thread moverThread = new Thread(){
|
||||
public void run() {
|
||||
while (!destroyed) {
|
||||
boolean back = false;
|
||||
while (running) {
|
||||
if (back) {
|
||||
position = --position % 100;
|
||||
if (position == 0) {
|
||||
back = false;
|
||||
}
|
||||
} else {
|
||||
position = ++position % 100;
|
||||
if (position == 99) {
|
||||
back = true;
|
||||
}
|
||||
}
|
||||
try {
|
||||
sleep(10);
|
||||
} catch (InterruptedException e) {}
|
||||
JMovingIdler.this.revalidate();
|
||||
JMovingIdler.this.repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void start() {
|
||||
if (!moverThread.isAlive()) {
|
||||
moverThread.start();
|
||||
}
|
||||
running = true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
destroyed = true;
|
||||
running = false;
|
||||
try {
|
||||
moverThread.join();
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
int w = this.getWidth();
|
||||
int h = this.getHeight();
|
||||
|
||||
g2.setColor(getBackground());
|
||||
g2.fillRect(0,0,w,h);
|
||||
|
||||
int x = w * position / 100;
|
||||
|
||||
Paint p = new GradientPaint(x - (w/8), 0, getBackground(), x , 0, getForeground());
|
||||
g2.setPaint(p);
|
||||
g2.fillRect(Math.max(0,x-(w/8)),0, Math.min(x, w), h);
|
||||
|
||||
p = new GradientPaint(x, 0, getForeground(), x + (w/8), 0, getBackground());
|
||||
g2.setPaint(p);
|
||||
g2.fillRect(Math.max(0,x),0, Math.min(x+(w/8), w), h);
|
||||
|
||||
g2.setColor(Color.BLACK);
|
||||
g2.drawLine(0,0,0,h);
|
||||
g2.drawLine(0,0,w,0);
|
||||
g2.drawLine(w,0,w,h);
|
||||
g2.drawLine(0,h,w,h);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean aFlag) {
|
||||
super.setVisible(aFlag);
|
||||
if (!aFlag) destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
593
src/com/gpl/rpg/atcontentstudio/ui/JSONCreationWizard.java
Normal file
593
src/com/gpl/rpg/atcontentstudio/ui/JSONCreationWizard.java
Normal file
@@ -0,0 +1,593 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.event.ListDataListener;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameSource;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
import com.gpl.rpg.atcontentstudio.ui.sprites.SpriteChooser;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
public class JSONCreationWizard extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = -5744628699021314026L;
|
||||
|
||||
public static enum DataType {
|
||||
none,
|
||||
actorCondition,
|
||||
dialogue,
|
||||
droplist,
|
||||
item,
|
||||
itemCategory,
|
||||
npc,
|
||||
quest
|
||||
}
|
||||
|
||||
private JSONElement creation = null;
|
||||
final JLabel message;
|
||||
final JComboBox dataTypeCombo;
|
||||
final JTextField idField;
|
||||
final JTextField nameField;
|
||||
final JButton ok;
|
||||
final Project proj;
|
||||
|
||||
public JSONCreationWizard(final Project proj, Class<? extends GameDataElement> dataClass) {
|
||||
this(proj);
|
||||
if (dataClass == ActorCondition.class) {
|
||||
dataTypeCombo.setSelectedItem(DataType.actorCondition);
|
||||
} else if (dataClass == Dialogue.class) {
|
||||
dataTypeCombo.setSelectedItem(DataType.dialogue);
|
||||
} else if (dataClass == Droplist.class) {
|
||||
dataTypeCombo.setSelectedItem(DataType.droplist);
|
||||
} else if (dataClass == Item.class) {
|
||||
dataTypeCombo.setSelectedItem(DataType.item);
|
||||
} else if (dataClass == ItemCategory.class) {
|
||||
dataTypeCombo.setSelectedItem(DataType.itemCategory);
|
||||
} else if (dataClass == NPC.class) {
|
||||
dataTypeCombo.setSelectedItem(DataType.npc);
|
||||
} else if (dataClass == Quest.class) {
|
||||
dataTypeCombo.setSelectedItem(DataType.quest);
|
||||
}
|
||||
dataTypeCombo.setEnabled(false);
|
||||
}
|
||||
|
||||
public JSONCreationWizard(final Project proj) {
|
||||
super(ATContentStudio.frame);
|
||||
this.proj = proj;
|
||||
setTitle("Create Game Data Element (JSON)");
|
||||
|
||||
JPanel pane = new JPanel();
|
||||
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
|
||||
|
||||
pane.add(new JLabel("Create a new game data element."), JideBoxLayout.FIX);
|
||||
|
||||
message = new JLabel("Select a data type below:");
|
||||
pane.add(message, JideBoxLayout.FIX);
|
||||
|
||||
dataTypeCombo = new JComboBox(new DataTypeComboModel());
|
||||
dataTypeCombo.setRenderer(new DataTypeComboCellRenderer());
|
||||
pane.add(dataTypeCombo);
|
||||
|
||||
final JPanel idPane = new JPanel();
|
||||
idPane.setLayout(new BorderLayout());
|
||||
JLabel idLabel = new JLabel("Internal ID: ");
|
||||
idPane.add(idLabel, BorderLayout.WEST);
|
||||
idField = new JTextField("");
|
||||
idField.setEditable(true);
|
||||
idPane.add(idField, BorderLayout.CENTER);
|
||||
pane.add(idPane, JideBoxLayout.FIX);
|
||||
|
||||
final JPanel namePane = new JPanel();
|
||||
namePane.setLayout(new BorderLayout());
|
||||
JLabel nameLabel = new JLabel("Display name: ");
|
||||
namePane.add(nameLabel, BorderLayout.WEST);
|
||||
nameField = new JTextField("");
|
||||
nameField.setEditable(true);
|
||||
namePane.add(nameField, BorderLayout.CENTER);
|
||||
pane.add(namePane, JideBoxLayout.FIX);
|
||||
|
||||
final JPanel iconPane = new JPanel();
|
||||
iconPane.setLayout(new BorderLayout());
|
||||
final JLabel iconLabel = new JLabel("Icon: ");
|
||||
iconPane.add(iconLabel, BorderLayout.WEST);
|
||||
final JButton iconButton = new JButton(new ImageIcon(DefaultIcons.getActorConditionImage()));
|
||||
iconPane.add(iconButton, BorderLayout.CENTER);
|
||||
pane.add(iconPane, JideBoxLayout.FIX);
|
||||
iconPane.setVisible(true);
|
||||
|
||||
dataTypeCombo.addItemListener(new ItemListener() {
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
idPane.setVisible(true);
|
||||
switch ((DataType)e.getItem()) {
|
||||
case actorCondition:
|
||||
iconPane.setVisible(true);
|
||||
namePane.setVisible(true);
|
||||
iconButton.setIcon(new ImageIcon(DefaultIcons.getActorConditionImage()));
|
||||
creation = new ActorCondition();
|
||||
break;
|
||||
case dialogue:
|
||||
iconPane.setVisible(false);
|
||||
namePane.setVisible(false);
|
||||
creation = new Dialogue();
|
||||
break;
|
||||
case droplist:
|
||||
iconPane.setVisible(false);
|
||||
namePane.setVisible(false);
|
||||
creation = new Droplist();
|
||||
break;
|
||||
case item:
|
||||
iconPane.setVisible(true);
|
||||
namePane.setVisible(true);
|
||||
creation = new Item();
|
||||
iconButton.setIcon(new ImageIcon(DefaultIcons.getItemImage()));
|
||||
break;
|
||||
case itemCategory:
|
||||
iconPane.setVisible(false);
|
||||
namePane.setVisible(true);
|
||||
creation = new ItemCategory();
|
||||
break;
|
||||
case npc:
|
||||
iconPane.setVisible(true);
|
||||
namePane.setVisible(true);
|
||||
creation = new NPC();
|
||||
iconButton.setIcon(new ImageIcon(DefaultIcons.getNPCImage()));
|
||||
break;
|
||||
case quest:
|
||||
iconPane.setVisible(false);
|
||||
namePane.setVisible(true);
|
||||
creation = new Quest();
|
||||
break;
|
||||
default:
|
||||
idPane.setVisible(false);
|
||||
iconPane.setVisible(false);
|
||||
namePane.setVisible(false);
|
||||
creation = null;
|
||||
break;
|
||||
}
|
||||
updateStatus();
|
||||
idPane.revalidate();
|
||||
namePane.revalidate();
|
||||
iconPane.revalidate();
|
||||
idPane.repaint();
|
||||
namePane.repaint();
|
||||
iconPane.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
iconButton.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Spritesheet.Category cat = null;
|
||||
switch ((DataType)dataTypeCombo.getSelectedItem()) {
|
||||
case actorCondition:
|
||||
cat = Spritesheet.Category.actorcondition;
|
||||
break;
|
||||
case dialogue:
|
||||
break;
|
||||
case droplist:
|
||||
break;
|
||||
case item:
|
||||
cat = Spritesheet.Category.item;
|
||||
break;
|
||||
case itemCategory:
|
||||
break;
|
||||
case npc:
|
||||
cat = Spritesheet.Category.monster;
|
||||
break;
|
||||
case quest:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
if (cat == null) return;
|
||||
SpriteChooser chooser = SpriteChooser.getChooser(proj, cat);
|
||||
chooser.setSelectionListener(new SpriteChooser.SelectionListener() {
|
||||
@Override
|
||||
public void iconSelected(String selected) {
|
||||
if (selected != null) {
|
||||
switch ((DataType)dataTypeCombo.getSelectedItem()) {
|
||||
case actorCondition:
|
||||
((ActorCondition)creation).icon_id = selected;
|
||||
break;
|
||||
case item:
|
||||
((Item)creation).icon_id = selected;
|
||||
break;
|
||||
case npc:
|
||||
((NPC)creation).icon_id = selected;
|
||||
break;
|
||||
case dialogue:
|
||||
case droplist:
|
||||
case itemCategory:
|
||||
case quest:
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
iconButton.setIcon(new ImageIcon(proj.getImage(selected)));
|
||||
iconButton.revalidate();
|
||||
iconButton.repaint();
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
});
|
||||
chooser.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
pane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new JideBoxLayout(buttonPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
buttonPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
JButton cancel = new JButton("Cancel");
|
||||
buttonPane.add(cancel, JideBoxLayout.FIX);
|
||||
ok = new JButton("Ok");
|
||||
buttonPane.add(ok, JideBoxLayout.FIX);
|
||||
pane.add(buttonPane, JideBoxLayout.FIX);
|
||||
|
||||
ok.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch ((DataType)dataTypeCombo.getSelectedItem()) {
|
||||
case actorCondition:
|
||||
((ActorCondition)creation).display_name = nameField.getText();
|
||||
break;
|
||||
case item:
|
||||
((Item)creation).name = nameField.getText();
|
||||
break;
|
||||
case npc:
|
||||
((NPC)creation).name = nameField.getText();
|
||||
break;
|
||||
case dialogue:
|
||||
case droplist:
|
||||
break;
|
||||
case itemCategory:
|
||||
((ItemCategory)creation).name = nameField.getText();
|
||||
break;
|
||||
case quest:
|
||||
((Quest)creation).name = nameField.getText();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
creation.id = idField.getText();
|
||||
JSONCreationWizard.this.setVisible(false);
|
||||
JSONCreationWizard.this.dispose();
|
||||
proj.createElement(creation);
|
||||
notifyCreated();
|
||||
ATContentStudio.frame.selectInTree(creation);
|
||||
ATContentStudio.frame.openEditor(creation);
|
||||
}
|
||||
});
|
||||
|
||||
cancel.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
creation = null;
|
||||
JSONCreationWizard.this.setVisible(false);
|
||||
JSONCreationWizard.this.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
DocumentListener statusUpdater = new DocumentListener() {
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
updateStatus();
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
updateStatus();
|
||||
}
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
updateStatus();
|
||||
}
|
||||
};
|
||||
idField.getDocument().addDocumentListener(statusUpdater);
|
||||
nameField.getDocument().addDocumentListener(statusUpdater);
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
getContentPane().add(pane, BorderLayout.CENTER);
|
||||
|
||||
setMinimumSize(new Dimension(350,250));
|
||||
idPane.setVisible(false);
|
||||
iconPane.setVisible(false);
|
||||
namePane.setVisible(false);
|
||||
updateStatus();
|
||||
pack();
|
||||
|
||||
Dimension sdim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
Dimension wdim = getSize();
|
||||
setLocation((sdim.width - wdim.width)/2, (sdim.height - wdim.height)/2);
|
||||
}
|
||||
|
||||
public void updateStatus() {
|
||||
boolean trouble = false;
|
||||
message.setText("<html><font color=\"#00AA00\">Looks OK to me.</font></html>");
|
||||
if (creation == null) {
|
||||
message.setText("<html><font color=\"#FF0000\">Select a data type below:</font></html>");
|
||||
trouble = true;
|
||||
} else if (idField.getText() == null || idField.getText().length() <= 0) {
|
||||
message.setText("<html><font color=\"#FF0000\">Internal ID must not be empty.</font></html>");
|
||||
trouble = true;
|
||||
} else {
|
||||
switch ((DataType)dataTypeCombo.getSelectedItem()) {
|
||||
case actorCondition:
|
||||
if(nameField.getText() == null || nameField.getText().length() <= 0) {
|
||||
message.setText("<html><font color=\"#FF0000\">An actor condition must have a name.</font></html>");
|
||||
trouble = true;
|
||||
} else if (((ActorCondition)creation).icon_id == null) {
|
||||
message.setText("<html><font color=\"#FF0000\">An actor condition must have an icon.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getActorCondition(idField.getText()) != null) {
|
||||
if (proj.getActorCondition(idField.getText()).getDataType() == GameSource.Type.created) {
|
||||
message.setText("<html><font color=\"#FF0000\">An actor condition with the same ID was already created in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getActorCondition(idField.getText()).getDataType() == GameSource.Type.altered) {
|
||||
message.setText("<html><font color=\"#FF0000\">An actor condition with the same ID exists in the game and is already altered in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getActorCondition(idField.getText()).getDataType() == GameSource.Type.source) {
|
||||
message.setText("<html><font color=\"#FF9000\">An actor condition with the same ID exists in the game. It will be added under \"altered\".</font></html>");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case item:
|
||||
if(nameField.getText() == null || nameField.getText().length() <= 0) {
|
||||
message.setText("<html><font color=\"#FF0000\">An item must have a name.</font></html>");
|
||||
trouble = true;
|
||||
} else if (((Item)creation).icon_id == null) {
|
||||
message.setText("<html><font color=\"#FF0000\">An item must have an icon.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getItem(idField.getText()) != null) {
|
||||
if (proj.getItem(idField.getText()).getDataType() == GameSource.Type.created) {
|
||||
message.setText("<html><font color=\"#FF0000\">An item with the same ID was already created in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getItem(idField.getText()).getDataType() == GameSource.Type.altered) {
|
||||
message.setText("<html><font color=\"#FF0000\">An item with the same ID exists in the game and is already altered in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getItem(idField.getText()).getDataType() == GameSource.Type.source) {
|
||||
message.setText("<html><font color=\"#FF9000\">An item with the same ID exists in the game. It will be added under \"altered\".</font></html>");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case npc:
|
||||
if(nameField.getText() == null || nameField.getText().length() <= 0) {
|
||||
message.setText("<html><font color=\"#FF0000\">A NPC must have a name.</font></html>");
|
||||
trouble = true;
|
||||
} else if (((NPC)creation).icon_id == null) {
|
||||
message.setText("<html><font color=\"#FF0000\">A NPC must have an icon.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getNPC(idField.getText()) != null) {
|
||||
if (proj.getNPC(idField.getText()).getDataType() == GameSource.Type.created) {
|
||||
message.setText("<html><font color=\"#FF0000\">A NPC with the same ID was already created in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getNPC(idField.getText()).getDataType() == GameSource.Type.altered) {
|
||||
message.setText("<html><font color=\"#FF0000\">A NPC with the same ID exists in the game and is already altered in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getNPC(idField.getText()).getDataType() == GameSource.Type.source) {
|
||||
message.setText("<html><font color=\"#FF9000\">A NPC with the same ID exists in the game. It will be added under \"altered\".</font></html>");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case dialogue:
|
||||
if (proj.getDialogue(idField.getText()) != null) {
|
||||
if (proj.getDialogue(idField.getText()).getDataType() == GameSource.Type.created) {
|
||||
message.setText("<html><font color=\"#FF0000\">A dialogue with the same ID was already created in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getDialogue(idField.getText()).getDataType() == GameSource.Type.altered) {
|
||||
message.setText("<html><font color=\"#FF0000\">A dialogue with the same ID exists in the game and is already altered in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getDialogue(idField.getText()).getDataType() == GameSource.Type.source) {
|
||||
message.setText("<html><font color=\"#FF9000\">A dialogue with the same ID exists in the game. It will be added under \"altered\".</font></html>");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case droplist:
|
||||
if (proj.getDroplist(idField.getText()) != null) {
|
||||
if (proj.getDroplist(idField.getText()).getDataType() == GameSource.Type.created) {
|
||||
message.setText("<html><font color=\"#FF0000\">A droplist with the same ID was already created in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getDroplist(idField.getText()).getDataType() == GameSource.Type.altered) {
|
||||
message.setText("<html><font color=\"#FF0000\">A droplist with the same ID exists in the game and is already altered in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getDroplist(idField.getText()).getDataType() == GameSource.Type.source) {
|
||||
message.setText("<html><font color=\"#FF9000\">A droplist with the same ID exists in the game. It will be added under \"altered\".</font></html>");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case itemCategory:
|
||||
if(nameField.getText() == null || nameField.getText().length() <= 0) {
|
||||
message.setText("<html><font color=\"#FF0000\">An item category must have a name.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getItemCategory(idField.getText()) != null) {
|
||||
if (proj.getItemCategory(idField.getText()).getDataType() == GameSource.Type.created) {
|
||||
message.setText("<html><font color=\"#FF0000\">An item category with the same ID was already created in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getItemCategory(idField.getText()).getDataType() == GameSource.Type.altered) {
|
||||
message.setText("<html><font color=\"#FF0000\">An item category with the same ID exists in the game and is already altered in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getItemCategory(idField.getText()).getDataType() == GameSource.Type.source) {
|
||||
message.setText("<html><font color=\"#FF9000\">An item category with the same ID exists in the game. It will be added under \"altered\".</font></html>");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case quest:
|
||||
if(nameField.getText() == null || nameField.getText().length() <= 0) {
|
||||
message.setText("<html><font color=\"#FF0000\">A quest must have a name.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getQuest(idField.getText()) != null) {
|
||||
if (proj.getQuest(idField.getText()).getDataType() == GameSource.Type.created) {
|
||||
message.setText("<html><font color=\"#FF0000\">A quest with the same ID was already created in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getQuest(idField.getText()).getDataType() == GameSource.Type.altered) {
|
||||
message.setText("<html><font color=\"#FF0000\">A quest with the same ID exists in the game and is already altered in this project.</font></html>");
|
||||
trouble = true;
|
||||
} else if (proj.getQuest(idField.getText()).getDataType() == GameSource.Type.source) {
|
||||
message.setText("<html><font color=\"#FF9000\">A quest with the same ID exists in the game. It will be added under \"altered\".</font></html>");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ok.setEnabled(!trouble);
|
||||
|
||||
message.revalidate();
|
||||
message.repaint();
|
||||
}
|
||||
|
||||
public static String dataTypeDesc(DataType type) {
|
||||
switch (type) {
|
||||
case actorCondition:
|
||||
return "Actor Condition";
|
||||
case dialogue:
|
||||
return "Dialogue";
|
||||
case droplist:
|
||||
return "Droplist";
|
||||
case item:
|
||||
return "Item";
|
||||
case itemCategory:
|
||||
return "Item Category";
|
||||
case npc:
|
||||
return "NPC";
|
||||
case quest:
|
||||
return "Quest";
|
||||
default:
|
||||
return "Select below";
|
||||
}
|
||||
}
|
||||
|
||||
public static class DataTypeComboModel implements ComboBoxModel {
|
||||
|
||||
DataType selected = DataType.none;
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return DataType.values().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
return DataType.values()[index];
|
||||
}
|
||||
|
||||
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anItem) {
|
||||
selected = (DataType) anItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSelectedItem() {
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DataTypeComboCellRenderer extends DefaultListCellRenderer {
|
||||
private static final long serialVersionUID = 5621373849299980998L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (c instanceof JLabel) {
|
||||
((JLabel)c).setText(JSONCreationWizard.dataTypeDesc((DataType) value));
|
||||
switch ((DataType)value) {
|
||||
case actorCondition:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getActorConditionIcon()));
|
||||
break;
|
||||
case dialogue:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getDialogueIcon()));
|
||||
break;
|
||||
case droplist:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getDroplistIcon()));
|
||||
break;
|
||||
case item:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getItemIcon()));
|
||||
break;
|
||||
case itemCategory:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getDroplistIcon()));
|
||||
break;
|
||||
case npc:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getNPCIcon()));
|
||||
break;
|
||||
case quest:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getQuestIcon()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface CreationCompletedListener {
|
||||
public void elementCreated(JSONElement created);
|
||||
}
|
||||
|
||||
private List<CreationCompletedListener> listeners = new ArrayList<JSONCreationWizard.CreationCompletedListener>();
|
||||
|
||||
public void addCreationListener(CreationCompletedListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
public void notifyCreated() {
|
||||
for (CreationCompletedListener l : listeners) {
|
||||
l.elementCreated(creation);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
720
src/com/gpl/rpg/atcontentstudio/ui/JSONImportWizard.java
Normal file
720
src/com/gpl/rpg/atcontentstudio/ui/JSONImportWizard.java
Normal file
@@ -0,0 +1,720 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.Notification;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameSource;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
public class JSONImportWizard extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = 661234868711700156L;
|
||||
|
||||
public static enum DataType {
|
||||
none,
|
||||
actorCondition,
|
||||
dialogue,
|
||||
droplist,
|
||||
item,
|
||||
itemCategory,
|
||||
npc,
|
||||
quest
|
||||
}
|
||||
|
||||
Project proj;
|
||||
|
||||
JPanel pane;
|
||||
JLabel message;
|
||||
JComboBox dataTypeCombo;
|
||||
JRadioButton importFromFile;
|
||||
JRadioButton importPasted;
|
||||
JPanel fileSelectionPane;
|
||||
JTextField jsonFileName;
|
||||
JButton browse;
|
||||
RSyntaxTextArea jsonPasteArea;
|
||||
JScrollPane scroller;
|
||||
JList createdPreview;
|
||||
JPanel buttonPane;
|
||||
JButton ok, cancel;
|
||||
ActionListener okListener, cancelListener;
|
||||
|
||||
public JSONImportWizard(Project proj) {
|
||||
|
||||
super(ATContentStudio.frame);
|
||||
setTitle("Import data from JSON");
|
||||
|
||||
this.proj = proj;
|
||||
|
||||
pane = new JPanel();
|
||||
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
|
||||
|
||||
pane.add(new JLabel("Import data in JSON format."), JideBoxLayout.FIX);
|
||||
|
||||
message = new JLabel();
|
||||
|
||||
dataTypeCombo = new JComboBox(new DataTypeComboModel());
|
||||
dataTypeCombo.setRenderer(new DataTypeComboCellRenderer());
|
||||
|
||||
dataTypeCombo.addItemListener(new ItemListener() {
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
checkEnableNext();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
importPasted = new JRadioButton("Paste JSON text");
|
||||
importFromFile = new JRadioButton("Select .json file");
|
||||
importPasted.setSelected(true);
|
||||
ButtonGroup radioGroup = new ButtonGroup();
|
||||
radioGroup.add(importPasted);
|
||||
radioGroup.add(importFromFile);
|
||||
|
||||
importPasted.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (importPasted.isSelected()) {
|
||||
scroller.setVisible(true);
|
||||
fileSelectionPane.setVisible(false);
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
importFromFile.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (importFromFile.isSelected()) {
|
||||
scroller.setVisible(false);
|
||||
fileSelectionPane.setVisible(true);
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jsonFileName = new JTextField();
|
||||
jsonFileName.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
checkEnableNext();
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
checkEnableNext();
|
||||
}
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
checkEnableNext();
|
||||
}
|
||||
});
|
||||
browse = new JButton("Browse");
|
||||
browse.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JFileChooser jfc = new JFileChooser(){
|
||||
private static final long serialVersionUID = -3001082967957619011L;
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
if (f.isDirectory() || f.getName().endsWith(".json") || f.getName().endsWith(".JSON")) {
|
||||
return super.accept(f);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
jfc.setMultiSelectionEnabled(false);
|
||||
int result = jfc.showOpenDialog(ATContentStudio.frame);
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
jsonFileName.setText(jfc.getSelectedFile().getAbsolutePath());
|
||||
checkEnableNext();
|
||||
}
|
||||
}
|
||||
});
|
||||
fileSelectionPane = new JPanel();
|
||||
fileSelectionPane.setLayout(new JideBoxLayout(fileSelectionPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
fileSelectionPane.add(new JLabel("JSON File: "), JideBoxLayout.FIX);
|
||||
fileSelectionPane.add(jsonFileName, JideBoxLayout.VARY);
|
||||
fileSelectionPane.add(browse, JideBoxLayout.FIX);
|
||||
|
||||
jsonPasteArea = new RSyntaxTextArea();
|
||||
jsonPasteArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JSON);
|
||||
|
||||
jsonPasteArea.getDocument().addDocumentListener(new DocumentListener() {
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
checkEnableNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
checkEnableNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
checkEnableNext();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new JideBoxLayout(buttonPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
buttonPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
cancel = new JButton("Cancel");
|
||||
buttonPane.add(cancel, JideBoxLayout.FIX);
|
||||
ok = new JButton("Next");
|
||||
buttonPane.add(ok, JideBoxLayout.FIX);
|
||||
|
||||
createdPreview = new JList(new GDEListModel(new ArrayList<GameDataElement>()));
|
||||
|
||||
showFirstScreen();
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
getContentPane().add(pane, BorderLayout.CENTER);
|
||||
|
||||
setMinimumSize(new Dimension(450,350));
|
||||
pack();
|
||||
|
||||
Dimension sdim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
Dimension wdim = getSize();
|
||||
setLocation((sdim.width - wdim.width)/2, (sdim.height - wdim.height)/2);
|
||||
|
||||
}
|
||||
|
||||
private void showFirstScreen() {
|
||||
pane.removeAll();
|
||||
message.setText("Select a data type & paste your JSON data below:");
|
||||
pane.add(message, JideBoxLayout.FIX);
|
||||
pane.add(dataTypeCombo, JideBoxLayout.FIX);
|
||||
pane.add(importPasted, JideBoxLayout.FIX);
|
||||
pane.add(importFromFile, JideBoxLayout.FIX);
|
||||
pane.add(fileSelectionPane, JideBoxLayout.FIX);
|
||||
scroller = new JScrollPane(jsonPasteArea);
|
||||
scroller.getVerticalScrollBar().setUnitIncrement(16);
|
||||
JPanel scrollHolder = new JPanel();
|
||||
scrollHolder.setLayout(new BorderLayout());
|
||||
scrollHolder.add(scroller, BorderLayout.CENTER);
|
||||
pane.add(scrollHolder, JideBoxLayout.VARY);
|
||||
pane.add(buttonPane, JideBoxLayout.FIX);
|
||||
ok.setText("Next");
|
||||
ok.setEnabled(jsonPasteArea.getText() != null && jsonPasteArea.getText().length() > 0 && dataTypeCombo.getSelectedItem() != null && dataTypeCombo.getSelectedItem() != DataType.none);
|
||||
ok.removeActionListener(okListener);
|
||||
okListener = new ActionListener() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
List<String> errors = new ArrayList<String>();
|
||||
List<String> warnings = new ArrayList<String>();
|
||||
List<JSONElement> created = new ArrayList<JSONElement>();
|
||||
Object jsonParserOutput = null;
|
||||
try {
|
||||
if (importPasted.isSelected()) {
|
||||
jsonParserOutput = new JSONParser().parse(jsonPasteArea.getText());
|
||||
} else if (importFromFile.isSelected()) {
|
||||
jsonParserOutput = new JSONParser().parse(new FileReader(new File(jsonFileName.getText())));
|
||||
}
|
||||
} catch (ParseException e1) {
|
||||
errors.add("Invalid JSON content: "+e1.getMessage());
|
||||
} catch (FileNotFoundException e1) {
|
||||
errors.add("Unable to access file: "+e1.getMessage());
|
||||
} catch (IOException e1) {
|
||||
errors.add("Error while accessing file: "+e1.getMessage());
|
||||
}
|
||||
if (jsonParserOutput != null) {
|
||||
List<Map> jsonObjects = null;
|
||||
if (jsonParserOutput instanceof List) {
|
||||
jsonObjects = (List)jsonParserOutput;
|
||||
} else if (jsonParserOutput instanceof Map) {
|
||||
jsonObjects = new ArrayList<Map>();
|
||||
jsonObjects.add((Map) jsonParserOutput);
|
||||
} else {
|
||||
errors.add("Invalid JSON content: neither an array nor an object.");
|
||||
}
|
||||
if (jsonObjects != null) {
|
||||
JSONElement node = null;
|
||||
JSONElement existingNode = null;
|
||||
int i = 0;
|
||||
for (Map jsonObject : jsonObjects) {
|
||||
switch ((DataType)dataTypeCombo.getSelectedItem()) {
|
||||
case actorCondition:
|
||||
node = ActorCondition.fromJson(jsonObject);
|
||||
existingNode = proj.getActorCondition(node.id);
|
||||
break;
|
||||
case item:
|
||||
node = Item.fromJson(jsonObject);
|
||||
existingNode = proj.getItem(node.id);
|
||||
break;
|
||||
case npc:
|
||||
node = NPC.fromJson(jsonObject);
|
||||
existingNode = proj.getNPC(node.id);
|
||||
break;
|
||||
case dialogue:
|
||||
node = Dialogue.fromJson(jsonObject);
|
||||
existingNode = proj.getDialogue(node.id);
|
||||
break;
|
||||
case droplist:
|
||||
node = Droplist.fromJson(jsonObject);
|
||||
existingNode = proj.getDroplist(node.id);
|
||||
break;
|
||||
case itemCategory:
|
||||
node = ItemCategory.fromJson(jsonObject);
|
||||
existingNode = proj.getItemCategory(node.id);
|
||||
break;
|
||||
case quest:
|
||||
node = Quest.fromJson(jsonObject);
|
||||
existingNode = proj.getQuest(node.id);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
if (node instanceof JSONElement) {
|
||||
node.parse(jsonObject);
|
||||
created.add(node);
|
||||
if (existingNode != null) {
|
||||
if (existingNode.getDataType() == GameSource.Type.created) {
|
||||
errors.add("An item with id "+node.id+" is already created in this project.");
|
||||
} else if (existingNode.getDataType() == GameSource.Type.altered) {
|
||||
errors.add("An item with id "+node.id+" is already altered in this project.");
|
||||
} else {
|
||||
warnings.add("An item with id "+node.id+" exists in the used game source. This one will be inserted as \"altered\"");
|
||||
}
|
||||
existingNode = null;
|
||||
}
|
||||
node = null;
|
||||
} else {
|
||||
warnings.add("Failed to load element #"+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors.isEmpty() && warnings.isEmpty()) {
|
||||
showImportPreviewScreen(created);
|
||||
} else if (!errors.isEmpty()) {
|
||||
showErrorScreen(errors);
|
||||
} else {
|
||||
showWarningScreen(warnings, created);
|
||||
}
|
||||
}
|
||||
};
|
||||
ok.addActionListener(okListener);
|
||||
cancel.setText("Cancel");
|
||||
cancel.removeActionListener(cancelListener);
|
||||
cancelListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JSONImportWizard.this.setVisible(false);
|
||||
JSONImportWizard.this.dispose();
|
||||
}
|
||||
};
|
||||
cancel.addActionListener(cancelListener);
|
||||
if (importPasted.isSelected()) {
|
||||
scroller.setVisible(true);
|
||||
fileSelectionPane.setVisible(false);
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
} else if (importFromFile.isSelected()) {
|
||||
scroller.setVisible(false);
|
||||
fileSelectionPane.setVisible(true);
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
|
||||
private void checkEnableNext() {
|
||||
if (dataTypeCombo.getSelectedItem() != null && dataTypeCombo.getSelectedItem() != DataType.none) {
|
||||
if (importPasted.isSelected()) {
|
||||
ok.setEnabled(jsonPasteArea.getText() != null && jsonPasteArea.getText().length() > 0);
|
||||
} else if (importFromFile.isSelected()) {
|
||||
ok.setEnabled(jsonFileName.getText() != null && jsonFileName.getText().length() > 0 && new File(jsonFileName.getText()).exists() && !(new File(jsonFileName.getText()).isDirectory()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showImportPreviewScreen(final List<JSONElement> created) {
|
||||
pane.removeAll();
|
||||
message.setText("The following data has been found. Click \"Ok\" to confirm.");
|
||||
pane.add(message, JideBoxLayout.FIX);
|
||||
createdPreview.setModel(new GDEListModel(created));
|
||||
createdPreview.setCellRenderer(new GDERenderer(false));
|
||||
pane.add(new JScrollPane(createdPreview), JideBoxLayout.FIX);
|
||||
pane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
pane.add(buttonPane, JideBoxLayout.FIX);
|
||||
ok.setText("Ok");
|
||||
ok.removeActionListener(okListener);
|
||||
okListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JSONElement lastNode = null;
|
||||
for (JSONElement node : created) {
|
||||
proj.createElement(node);
|
||||
lastNode = node;
|
||||
}
|
||||
if (lastNode != null) {
|
||||
lastNode.save();
|
||||
ATContentStudio.frame.selectInTree(lastNode);
|
||||
}
|
||||
JSONImportWizard.this.setVisible(false);
|
||||
JSONImportWizard.this.dispose();
|
||||
}
|
||||
};
|
||||
ok.addActionListener(okListener);
|
||||
cancel.setText("Back");
|
||||
cancel.removeActionListener(cancelListener);
|
||||
cancelListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showFirstScreen();
|
||||
}
|
||||
};
|
||||
cancel.addActionListener(cancelListener);
|
||||
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
|
||||
private void showErrorScreen(List<String> errors) {
|
||||
pane.removeAll();
|
||||
message.setText("Failed to import. The following error(s) have been encountered:");
|
||||
pane.add(message, JideBoxLayout.FIX);
|
||||
createdPreview.setModel(new GDEListModel(errors));
|
||||
createdPreview.setCellRenderer(new ErrorRenderer());
|
||||
pane.add(new JScrollPane(createdPreview), JideBoxLayout.VARY);
|
||||
pane.add(buttonPane, JideBoxLayout.FIX);
|
||||
cancel.setText("Back");
|
||||
cancel.removeActionListener(cancelListener);
|
||||
cancelListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showFirstScreen();
|
||||
}
|
||||
};
|
||||
cancel.addActionListener(cancelListener);
|
||||
ok.setText("Close");
|
||||
ok.removeActionListener(okListener);
|
||||
okListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JSONImportWizard.this.setVisible(false);
|
||||
JSONImportWizard.this.dispose();
|
||||
}
|
||||
};
|
||||
ok.addActionListener(okListener);
|
||||
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
|
||||
private void showWarningScreen(List<String> warnings, final List<JSONElement> created) {
|
||||
pane.removeAll();
|
||||
message.setText("The following warnings(s) were raised while importing:");
|
||||
pane.add(message, JideBoxLayout.FIX);
|
||||
createdPreview.setModel(new GDEListModel(warnings));
|
||||
createdPreview.setCellRenderer(new WarningRenderer());
|
||||
pane.add(new JScrollPane(createdPreview), JideBoxLayout.VARY);
|
||||
pane.add(buttonPane, JideBoxLayout.FIX);
|
||||
|
||||
ok.setText("Continue anyway");
|
||||
ok.removeActionListener(okListener);
|
||||
okListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showImportPreviewScreen(created);
|
||||
}
|
||||
};
|
||||
ok.addActionListener(okListener);
|
||||
|
||||
cancel.setText("Close");
|
||||
cancel.removeActionListener(cancelListener);
|
||||
cancelListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JSONImportWizard.this.setVisible(false);
|
||||
JSONImportWizard.this.dispose();
|
||||
}
|
||||
};
|
||||
cancel.addActionListener(cancelListener);
|
||||
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
|
||||
public class GDERenderer extends DefaultListCellRenderer {
|
||||
|
||||
private static final long serialVersionUID = 6819681566800482793L;
|
||||
|
||||
private boolean includeType = false;
|
||||
|
||||
public GDERenderer(boolean includeType) {
|
||||
super();
|
||||
this.includeType = includeType;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (value == null) {
|
||||
label.setText("none");
|
||||
} else {
|
||||
if (includeType && ((GameDataElement)value).getDataType() != null) {
|
||||
label.setText(((GameDataElement)value).getDataType().toString()+"/"+((GameDataElement)value).getDesc());
|
||||
} else {
|
||||
label.setText(((GameDataElement)value).getDesc());
|
||||
}
|
||||
switch ((DataType)dataTypeCombo.getSelectedItem()) {
|
||||
case actorCondition:
|
||||
label.setIcon(new ImageIcon(proj.getIcon(((ActorCondition)value).icon_id)));
|
||||
break;
|
||||
case item:
|
||||
label.setIcon(new ImageIcon(proj.getIcon(((Item)value).icon_id)));
|
||||
break;
|
||||
case npc:
|
||||
label.setIcon(new ImageIcon(proj.getIcon(((NPC)value).icon_id)));
|
||||
break;
|
||||
case dialogue:
|
||||
label.setIcon(new ImageIcon(((Dialogue)value).getIcon()));
|
||||
break;
|
||||
case droplist:
|
||||
label.setIcon(new ImageIcon(((Droplist)value).getIcon()));
|
||||
break;
|
||||
case itemCategory:
|
||||
label.setIcon(new ImageIcon(((ItemCategory)value).getIcon()));
|
||||
break;
|
||||
case quest:
|
||||
label.setIcon(new ImageIcon(((Quest)value).getIcon()));
|
||||
break;
|
||||
default:
|
||||
Notification.addError("Unable to find icon for "+((GameDataElement)value).getDesc());
|
||||
}
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ErrorRenderer extends DefaultListCellRenderer {
|
||||
private static final long serialVersionUID = -4265342800284721660L;
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (c instanceof JLabel) {
|
||||
((JLabel)c).setIcon(NotificationsPane.icons.get(Notification.Type.ERROR));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class WarningRenderer extends DefaultListCellRenderer {
|
||||
private static final long serialVersionUID = -3836045237946111606L;
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (c instanceof JLabel) {
|
||||
((JLabel)c).setIcon(NotificationsPane.icons.get(Notification.Type.WARN));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GDEListModel implements ListModel {
|
||||
|
||||
List<? extends Object> source;
|
||||
|
||||
public GDEListModel(List<? extends Object> source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return source.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
for (Object obj : source) {
|
||||
if (index == 0) return obj;
|
||||
index --;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
public void fireListChanged() {
|
||||
for (ListDataListener l : listeners) {
|
||||
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, this.getSize()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class DataTypeComboModel implements ComboBoxModel {
|
||||
|
||||
DataType selected = DataType.none;
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return DataType.values().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
return DataType.values()[index];
|
||||
}
|
||||
|
||||
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anItem) {
|
||||
selected = (DataType) anItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSelectedItem() {
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DataTypeComboCellRenderer extends DefaultListCellRenderer {
|
||||
private static final long serialVersionUID = 5621373849299980998L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (c instanceof JLabel) {
|
||||
((JLabel)c).setText(dataTypeDesc((DataType) value));
|
||||
switch ((DataType)value) {
|
||||
case actorCondition:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getActorConditionIcon()));
|
||||
break;
|
||||
case dialogue:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getDialogueIcon()));
|
||||
break;
|
||||
case droplist:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getDroplistIcon()));
|
||||
break;
|
||||
case item:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getItemIcon()));
|
||||
break;
|
||||
case itemCategory:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getDroplistIcon()));
|
||||
break;
|
||||
case npc:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getNPCIcon()));
|
||||
break;
|
||||
case quest:
|
||||
((JLabel)c).setIcon(new ImageIcon(DefaultIcons.getQuestIcon()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
public static String dataTypeDesc(DataType type) {
|
||||
switch (type) {
|
||||
case actorCondition:
|
||||
return "Actor Condition";
|
||||
case dialogue:
|
||||
return "Dialogue";
|
||||
case droplist:
|
||||
return "Droplist";
|
||||
case item:
|
||||
return "Item";
|
||||
case itemCategory:
|
||||
return "Item Category";
|
||||
case npc:
|
||||
return "NPC";
|
||||
case quest:
|
||||
return "Quest";
|
||||
default:
|
||||
return "Select below";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
113
src/com/gpl/rpg/atcontentstudio/ui/NotificationsPane.java
Normal file
113
src/com/gpl/rpg/atcontentstudio/ui/NotificationsPane.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.Notification;
|
||||
import com.gpl.rpg.atcontentstudio.NotificationListener;
|
||||
|
||||
|
||||
public class NotificationsPane extends JList {
|
||||
|
||||
private static final long serialVersionUID = -1100364214372392608L;
|
||||
|
||||
public static final String success_img_name = "/com/gpl/rpg/atcontentstudio/img/success.png";
|
||||
public static final String info_img_name = "/com/gpl/rpg/atcontentstudio/img/info.png";
|
||||
public static final String warn_img_name = "/com/gpl/rpg/atcontentstudio/img/warn.png";
|
||||
public static final String error_img_name = "/com/gpl/rpg/atcontentstudio/img/error.png";
|
||||
|
||||
public static final Map<Notification.Type, Icon> icons = new HashMap<Notification.Type, Icon>(Notification.Type.values().length);
|
||||
|
||||
static {
|
||||
try {
|
||||
icons.put(Notification.Type.SUCCESS, new ImageIcon(ImageIO.read(NotificationsPane.class.getResourceAsStream(success_img_name))));
|
||||
icons.put(Notification.Type.INFO, new ImageIcon(ImageIO.read(NotificationsPane.class.getResourceAsStream(info_img_name))));
|
||||
icons.put(Notification.Type.WARN, new ImageIcon(ImageIO.read(NotificationsPane.class.getResourceAsStream(warn_img_name))));
|
||||
icons.put(Notification.Type.ERROR, new ImageIcon(ImageIO.read(NotificationsPane.class.getResourceAsStream(error_img_name))));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public NotificationsPane() {
|
||||
super();
|
||||
MyListModel model = new MyListModel();
|
||||
setModel(model);
|
||||
setCellRenderer(new ListCellRenderer(){
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JLabel label = new JLabel();
|
||||
Font f = label.getFont();
|
||||
label.setIcon(NotificationsPane.icons.get(((Notification)value).type));
|
||||
label.setText(((Notification)value).text);
|
||||
if (isSelected) {
|
||||
// label.setBackground(Color.RED);
|
||||
label.setBorder(BorderFactory.createLineBorder(Color.BLUE));
|
||||
// label.setForeground(Color.WHITE);
|
||||
}
|
||||
f = f.deriveFont(10f);
|
||||
label.setFont(f);
|
||||
return label;
|
||||
}
|
||||
});
|
||||
Notification.addNotificationListener(model);
|
||||
}
|
||||
|
||||
|
||||
private class MyListModel implements ListModel, NotificationListener {
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
return Notification.notifs.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return Notification.notifs.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewNotification(Notification n) {
|
||||
for (ListDataListener l : listeners) {
|
||||
l.intervalAdded(new ListDataEvent(NotificationsPane.this, ListDataEvent.INTERVAL_ADDED, Notification.notifs.size() - 1 , Notification.notifs.size() - 1));
|
||||
}
|
||||
NotificationsPane.this.ensureIndexIsVisible(Notification.notifs.indexOf(n));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListCleared(int i) {
|
||||
for (ListDataListener l : listeners) {
|
||||
l.intervalRemoved(new ListDataEvent(NotificationsPane.this, ListDataEvent.INTERVAL_REMOVED, 0 , i));
|
||||
}
|
||||
}
|
||||
|
||||
private List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
250
src/com/gpl/rpg/atcontentstudio/ui/ProjectCreationWizard.java
Normal file
250
src/com/gpl/rpg/atcontentstudio/ui/ProjectCreationWizard.java
Normal file
@@ -0,0 +1,250 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.Workspace;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.SpriteSheetSet;
|
||||
|
||||
public class ProjectCreationWizard extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = -2854969975146867119L;
|
||||
|
||||
final JTextField projectNameField;
|
||||
final JComboBox atSourceSelectionCombo;
|
||||
|
||||
final JButton browse;
|
||||
final JButton okButton;
|
||||
final JButton cancelButton;
|
||||
|
||||
final JLabel errorLabel;
|
||||
|
||||
public ProjectCreationWizard() {
|
||||
super(ATContentStudio.frame);
|
||||
setTitle("Create project");
|
||||
projectNameField = new JTextField();
|
||||
atSourceSelectionCombo = new JComboBox();
|
||||
browse = new JButton("Browse...");
|
||||
okButton = new JButton("Ok");
|
||||
cancelButton = new JButton("Cancel");
|
||||
errorLabel = new JLabel("Enter the following information about your project.");
|
||||
|
||||
projectNameField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
updateOkButtonEnablement();
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
updateOkButtonEnablement();
|
||||
}
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
updateOkButtonEnablement();
|
||||
}
|
||||
});
|
||||
for (File f : Workspace.activeWorkspace.knownMapSourcesFolders) {
|
||||
atSourceSelectionCombo.addItem(f.getAbsolutePath());
|
||||
}
|
||||
atSourceSelectionCombo.setEditable(true);
|
||||
atSourceSelectionCombo.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updateOkButtonEnablement();
|
||||
}
|
||||
});
|
||||
browse.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
boolean keepTrying = true;
|
||||
if (atSourceSelectionCombo.getSelectedItem() != null && ((String)atSourceSelectionCombo.getSelectedItem()).length() > 0) {
|
||||
File f = new File((String)atSourceSelectionCombo.getSelectedItem());
|
||||
if (f.exists()) {
|
||||
chooser.setCurrentDirectory(f);
|
||||
keepTrying = false;
|
||||
}
|
||||
}
|
||||
if (keepTrying && Workspace.activeWorkspace.knownMapSourcesFolders != null && !Workspace.activeWorkspace.knownMapSourcesFolders.isEmpty()) {
|
||||
chooser.setCurrentDirectory(Workspace.activeWorkspace.knownMapSourcesFolders.iterator().next());
|
||||
}
|
||||
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
int result = chooser.showOpenDialog(ProjectCreationWizard.this);
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
atSourceSelectionCombo.setSelectedItem(chooser.getSelectedFile().getAbsolutePath());
|
||||
updateOkButtonEnablement();
|
||||
}
|
||||
}
|
||||
});
|
||||
okButton.setEnabled(false);
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
File atSourceFolder = new File((String) atSourceSelectionCombo.getSelectedItem());
|
||||
if (!Workspace.activeWorkspace.knownMapSourcesFolders.contains(atSourceFolder)) {
|
||||
Workspace.activeWorkspace.knownMapSourcesFolders.add(atSourceFolder);
|
||||
}
|
||||
Workspace.createProject(projectNameField.getText(), atSourceFolder);
|
||||
ProjectCreationWizard.this.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ProjectCreationWizard.this.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c =new GridBagConstraints();
|
||||
|
||||
c.anchor = GridBagConstraints.NORTHWEST;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.gridheight = 1;
|
||||
c.gridwidth = 3;
|
||||
c.gridx = 1;
|
||||
c.gridy = 1;
|
||||
c.weightx = 100;
|
||||
c.weighty = 100;
|
||||
panel.add(errorLabel, c);
|
||||
|
||||
c.gridy++;
|
||||
c.gridx = 1;
|
||||
c.gridwidth = 1;
|
||||
c.weightx = 20;
|
||||
panel.add(new JLabel("Project name: "), c);
|
||||
|
||||
c.gridx++;
|
||||
c.gridwidth = 2;
|
||||
c.weightx = 80;
|
||||
panel.add(projectNameField, c);
|
||||
|
||||
c.gridy++;
|
||||
c.gridx = 1;
|
||||
c.gridwidth = 1;
|
||||
c.weightx = 20;
|
||||
panel.add(new JLabel("AT Source: "), c);
|
||||
|
||||
c.gridx++;
|
||||
c.weightx = 60;
|
||||
panel.add(atSourceSelectionCombo, c);
|
||||
|
||||
c.gridx++;
|
||||
c.weightx = 20;
|
||||
panel.add(browse, c);
|
||||
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c2 = new GridBagConstraints();
|
||||
c2.fill = GridBagConstraints.HORIZONTAL;
|
||||
c2.gridx = 1;
|
||||
c2.weightx = 80;
|
||||
|
||||
c2.gridx = 1;
|
||||
c2.weightx = 80;
|
||||
buttonPane.add(new JLabel(), c2);
|
||||
|
||||
c2.gridx++;
|
||||
c2.weightx = 10;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
buttonPane.add(cancelButton, c2);
|
||||
|
||||
c2.gridx++;
|
||||
c2.weightx = 10;
|
||||
buttonPane.add(okButton, c2);
|
||||
|
||||
c.gridy++;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.gridwidth = 3;
|
||||
panel.add(buttonPane, c);
|
||||
|
||||
updateOkButtonEnablement();
|
||||
|
||||
setContentPane(panel);
|
||||
|
||||
pack();
|
||||
Dimension sdim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
Dimension wdim = getSize();
|
||||
setLocation((sdim.width - wdim.width)/2, (sdim.height - wdim.height)/2);
|
||||
}
|
||||
|
||||
|
||||
protected void updateOkButtonEnablement() {
|
||||
if (projectNameField.getText() == null || projectNameField.getText().length() <= 0) {
|
||||
errorLabel.setText("<html><font color=\"#FF0000\">Select a project name.</font></html>");
|
||||
this.okButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (atSourceSelectionCombo.getSelectedItem() == null || ((String)atSourceSelectionCombo.getSelectedItem()).length() <= 0) {
|
||||
errorLabel.setText("<html><font color=\"#FF0000\">Select an AT source root folder.</font></html>");
|
||||
this.okButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
File projFolder = new File(Workspace.activeWorkspace.baseFolder, projectNameField.getText()+File.separator);
|
||||
File sourceFolder = new File((String) atSourceSelectionCombo.getSelectedItem());
|
||||
if (projFolder.exists()) {
|
||||
errorLabel.setText("<html><font color=\"#FF0000\">A project with this name already exists.</font></html>");
|
||||
this.okButton.setEnabled(false);
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
projFolder.getCanonicalPath();
|
||||
} catch (IOException ioe) {
|
||||
errorLabel.setText("<html><font color=\"#FF0000\">"+projectNameField.getText()+" is not a valid project name.</font></html>");
|
||||
this.okButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!sourceFolder.exists()) {
|
||||
errorLabel.setText("<html><font color=\"#FF0000\">The selected AT source root folder does not exist.</font></html>");
|
||||
this.okButton.setEnabled(false);
|
||||
return;
|
||||
} else {
|
||||
File res = new File(sourceFolder, GameDataSet.DEFAULT_REL_PATH_IN_SOURCE);
|
||||
if (!res.exists()) {
|
||||
errorLabel.setText("<html><font color=\"#FF0000\">The selected AT source root folder does not contain the \"res\" folder.</font></html>");
|
||||
this.okButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
File drawable = new File(sourceFolder, SpriteSheetSet.DEFAULT_REL_PATH_IN_SOURCE);
|
||||
if (!drawable.exists()) {
|
||||
errorLabel.setText("<html><font color=\"#FF0000\">The selected AT source root folder does not contain the \"drawable\" folder.</font></html>");
|
||||
this.okButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
File xml = new File(sourceFolder, TMXMapSet.DEFAULT_REL_PATH_IN_SOURCE);
|
||||
if (!xml.exists()) {
|
||||
errorLabel.setText("<html><font color=\"#FF0000\">The selected AT source root folder does not contain the \"xml\" folder.</font></html>");
|
||||
this.okButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!projFolder.exists() && sourceFolder.exists()) {
|
||||
errorLabel.setText("<html><font color=\"#00AA00\">Everything looks good !</font></html>");
|
||||
this.okButton.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
739
src/com/gpl/rpg/atcontentstudio/ui/ProjectsTree.java
Normal file
739
src/com/gpl/rpg/atcontentstudio/ui/ProjectsTree.java
Normal file
@@ -0,0 +1,739 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeModelEvent;
|
||||
import javax.swing.event.TreeModelListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
import javax.swing.tree.TreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.gpl.rpg.andorstrainer.AndorsTrainer;
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.Workspace;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
|
||||
import com.gpl.rpg.atcontentstudio.model.saves.SavedGame;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
import com.jidesoft.swing.TreeSearchable;
|
||||
|
||||
public class ProjectsTree extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 6332593891796576708L;
|
||||
|
||||
private JTree projectsTree;
|
||||
|
||||
private JPopupMenu popupMenu;
|
||||
|
||||
private Thread konamiTimeout = null;
|
||||
private boolean exit = false;
|
||||
private int timeout = 200;
|
||||
private Integer[] konamiBuffer = new Integer[]{null, null, null, null, null, null, null, null, null, null};
|
||||
private boolean konamiCodeEntered = false;
|
||||
|
||||
public ProjectsTree() {
|
||||
super();
|
||||
setLayout(new BorderLayout());
|
||||
projectsTree = new JTree(new ProjectsTreeModel());
|
||||
new TreeSearchable(projectsTree){
|
||||
@Override
|
||||
protected String convertElementToString(Object object) {
|
||||
return ((ProjectTreeNode)((TreePath)object).getLastPathComponent()).getDesc();
|
||||
}
|
||||
};
|
||||
add(projectsTree, BorderLayout.CENTER);
|
||||
projectsTree.setRootVisible(false);
|
||||
projectsTree.setShowsRootHandles(true);
|
||||
projectsTree.setExpandsSelectedPaths(true);
|
||||
|
||||
popupMenu = new JPopupMenu();
|
||||
makePopupMenu();
|
||||
|
||||
projectsTree.setCellRenderer(new ProjectsTreeCellRenderer());
|
||||
projectsTree.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
if (projectsTree.getSelectionPath() != null) {
|
||||
itemAction((ProjectTreeNode) projectsTree.getSelectionPath().getLastPathComponent());
|
||||
}
|
||||
} else {
|
||||
if (konamiTimeout == null) {
|
||||
startKonamiCount();
|
||||
}
|
||||
int i = 0;
|
||||
while (i < konamiBuffer.length && konamiBuffer[i] != null) {
|
||||
i++;
|
||||
}
|
||||
if (i < konamiBuffer.length) {
|
||||
konamiBuffer[i] = e.getKeyCode();
|
||||
if (!compareBuffers()) {
|
||||
exit = true;
|
||||
} else {
|
||||
resetTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
projectsTree.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
popupActivated(e);
|
||||
} else if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
|
||||
TreePath path = projectsTree.getPathForLocation (e.getX(), e.getY());
|
||||
projectsTree.setSelectionPath(path);
|
||||
if (path != null) {
|
||||
itemAction((ProjectTreeNode) path.getLastPathComponent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
popupActivated(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
popupActivated(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
popupActivated(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
projectsTree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
List<TreePath> newPaths = new ArrayList<TreePath>();
|
||||
for (TreePath path : e.getPaths()) {
|
||||
if (e.isAddedPath(path)) newPaths.add(path);
|
||||
}
|
||||
if (e.getPath() == null) {
|
||||
ATContentStudio.frame.actions.selectionChanged(null, newPaths.toArray(new TreePath[newPaths.size()]));
|
||||
} else {
|
||||
ATContentStudio.frame.actions.selectionChanged((ProjectTreeNode) e.getPath().getLastPathComponent(), newPaths.toArray(new TreePath[newPaths.size()]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void makePopupMenu() {
|
||||
popupMenu.removeAll();
|
||||
|
||||
if (ATContentStudio.frame == null || ATContentStudio.frame.actions == null) return;
|
||||
WorkspaceActions actions = ATContentStudio.frame.actions;
|
||||
|
||||
boolean addNextSeparator = false;
|
||||
if (actions.createProject.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.createProject));
|
||||
}
|
||||
if (actions.openProject.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.openProject));
|
||||
}
|
||||
if (actions.closeProject.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.closeProject));
|
||||
}
|
||||
if (actions.deleteProject.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.deleteProject));
|
||||
}
|
||||
if (addNextSeparator) {
|
||||
popupMenu.add(new JSeparator());
|
||||
addNextSeparator = false;
|
||||
}
|
||||
|
||||
if (actions.saveElement.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.saveElement));
|
||||
}
|
||||
if (actions.deleteSelected.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.deleteSelected));
|
||||
}
|
||||
if (addNextSeparator) {
|
||||
popupMenu.add(new JSeparator());
|
||||
addNextSeparator = false;
|
||||
}
|
||||
|
||||
if (actions.createGDE.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.createGDE));
|
||||
}
|
||||
if (actions.importJSON.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.importJSON));
|
||||
}
|
||||
if (actions.loadSave.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.loadSave));
|
||||
}
|
||||
if (addNextSeparator) {
|
||||
popupMenu.add(new JSeparator());
|
||||
addNextSeparator = false;
|
||||
}
|
||||
|
||||
|
||||
if (actions.compareItems.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.compareItems));
|
||||
}
|
||||
if (actions.compareNPCs.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.compareNPCs));
|
||||
}
|
||||
if (actions.exportProject.isEnabled()) {
|
||||
addNextSeparator = true;
|
||||
popupMenu.add(new JMenuItem(actions.exportProject));
|
||||
}
|
||||
if (addNextSeparator) {
|
||||
popupMenu.add(new JSeparator());
|
||||
addNextSeparator = false;
|
||||
}
|
||||
|
||||
if (konamiCodeEntered) {
|
||||
JMenuItem openTrainer = new JMenuItem("Start Andor's Trainer...");
|
||||
popupMenu.add(openTrainer);
|
||||
popupMenu.addSeparator();
|
||||
openTrainer.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
AndorsTrainer.startApp(false);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// if (projectsTree.getSelectionPath() == null || projectsTree.getSelectionPath().getLastPathComponent() == null) {
|
||||
// JMenuItem addProject = new JMenuItem("Create project...");
|
||||
// popupMenu.add(addProject);
|
||||
// addProject.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// new ProjectCreationWizard().setVisible(true);
|
||||
// }
|
||||
// });
|
||||
// popupMenu.addSeparator();
|
||||
// } else if (projectsTree.getSelectionPaths().length > 1) {
|
||||
// boolean deleteAll = false;
|
||||
// final List<GameDataElement> elementsToDelete = new ArrayList<GameDataElement>();
|
||||
// for (TreePath selected : projectsTree.getSelectionPaths()) {
|
||||
// if (selected.getLastPathComponent() instanceof GameDataElement && ((GameDataElement)selected.getLastPathComponent()).writable) {
|
||||
// elementsToDelete.add((GameDataElement) selected.getLastPathComponent());
|
||||
// deleteAll = true;
|
||||
// } else {
|
||||
// deleteAll = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (deleteAll) {
|
||||
// JMenuItem deleteItems = new JMenuItem("Delete all selected elements");
|
||||
// popupMenu.add(deleteItems);
|
||||
// deleteItems.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// final Map<GameDataCategory<JSONElement>, Set<File>> impactedCategories = new IdentityHashMap<GameDataCategory<JSONElement>, Set<File>>();
|
||||
// for (GameDataElement element : elementsToDelete) {
|
||||
// ATContentStudio.frame.closeEditor(element);
|
||||
// element.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
||||
// if (element instanceof JSONElement) {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// GameDataCategory<JSONElement> category = (GameDataCategory<JSONElement>) element.getParent();
|
||||
// category.remove(element);
|
||||
// if (impactedCategories.get(category) == null) {
|
||||
// impactedCategories.put(category, new HashSet<File>());
|
||||
// }
|
||||
// impactedCategories.get(category).add(((JSONElement) element).jsonFile);
|
||||
// } else if (element instanceof TMXMap) {
|
||||
// TMXMapSet parent = (TMXMapSet) element.getParent();
|
||||
// parent.tmxMaps.remove(element);
|
||||
// }
|
||||
// }
|
||||
// new Thread() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// final List<SaveEvent> events = new ArrayList<SaveEvent>();
|
||||
// List<SaveEvent> catEvents = null;
|
||||
// for (GameDataCategory<JSONElement> category : impactedCategories.keySet()) {
|
||||
// for (File f : impactedCategories.get(category)) {
|
||||
// catEvents = category.attemptSave(true, f.getName());
|
||||
// if (catEvents.isEmpty()) {
|
||||
// category.save(f);
|
||||
// } else {
|
||||
// events.addAll(catEvents);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (!events.isEmpty()) {
|
||||
// new SaveItemsWizard(events, null).setVisible(true);
|
||||
// }
|
||||
// }
|
||||
// }.start();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// popupMenu.addSeparator();
|
||||
// } else {
|
||||
// final ProjectTreeNode selected = (ProjectTreeNode) projectsTree.getSelectionPath().getLastPathComponent();
|
||||
// if (selected instanceof Project) {
|
||||
// JMenuItem closeProject = new JMenuItem("Close Project...");
|
||||
// JMenuItem deleteProject = new JMenuItem("Delete Project...");
|
||||
// popupMenu.add(closeProject);
|
||||
// popupMenu.add(deleteProject);
|
||||
// popupMenu.addSeparator();
|
||||
// closeProject.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// Workspace.closeProject((Project) selected);
|
||||
// }
|
||||
// });
|
||||
// deleteProject.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// int confirm = JOptionPane.showConfirmDialog(ProjectsTree.this, "Are you sure you wish to delete this project ?\nAll files created for it will be deleted too...", "Delete this project ?", JOptionPane.OK_CANCEL_OPTION);
|
||||
// if (confirm == JOptionPane.OK_OPTION) {
|
||||
// Workspace.deleteProject(((Project)projectsTree.getSelectionPath().getLastPathComponent()));
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// if (selected instanceof ClosedProject) {
|
||||
// JMenuItem openProject = new JMenuItem("Open Project...");
|
||||
// JMenuItem deleteProject = new JMenuItem("Delete Project...");
|
||||
// popupMenu.add(openProject);
|
||||
// popupMenu.add(deleteProject);
|
||||
// popupMenu.addSeparator();
|
||||
// openProject.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// Workspace.openProject(((ClosedProject)selected));
|
||||
// }
|
||||
// });
|
||||
// deleteProject.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// int confirm = JOptionPane.showConfirmDialog(ProjectsTree.this, "Are you sure you wish to delete this project ?\nAll files created for it will be deleted too...", "Delete this project ?", JOptionPane.OK_CANCEL_OPTION);
|
||||
// if (confirm == JOptionPane.OK_OPTION) {
|
||||
// Workspace.deleteProject(((ClosedProject)selected));
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// if (selected.getProject() != null) {
|
||||
// final Project proj = ((ProjectTreeNode)selected).getProject();
|
||||
// JMenuItem createGDE = new JMenuItem("Create Game Data Element (JSON)");
|
||||
// popupMenu.add(createGDE);
|
||||
// createGDE.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// new JSONCreationWizard(proj).setVisible(true);
|
||||
// }
|
||||
// });
|
||||
// JMenuItem importJson = new JMenuItem("Import JSON data");
|
||||
// popupMenu.add(importJson);
|
||||
// importJson.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// new JSONImportWizard(proj).setVisible(true);
|
||||
// }
|
||||
// });
|
||||
// //TODO move somewhere else
|
||||
// JMenu compareElementsMenu = new JMenu("Open comparator for...");
|
||||
// JMenuItem compareItems = new JMenuItem("Items");
|
||||
// compareElementsMenu.add(compareItems);
|
||||
// compareItems.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// ATContentStudio.frame.editors.openEditor(new ItemsTableView(selected.getProject()));
|
||||
// }
|
||||
// });
|
||||
// JMenuItem compareNPCs = new JMenuItem("NPCs");
|
||||
// compareElementsMenu.add(compareNPCs);
|
||||
// compareNPCs.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// ATContentStudio.frame.editors.openEditor(new NPCsTableView(selected.getProject()));
|
||||
// }
|
||||
// });
|
||||
// popupMenu.add(compareElementsMenu);
|
||||
//
|
||||
// JMenuItem exportProjectPackage = new JMenuItem("Export project");
|
||||
// exportProjectPackage.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// JFileChooser chooser = new JFileChooser() {
|
||||
// private static final long serialVersionUID = 8039332384370636746L;
|
||||
// public boolean accept(File f) {
|
||||
// return f.isDirectory() || f.getName().endsWith(".zip") || f.getName().endsWith(".ZIP");
|
||||
// }
|
||||
// };
|
||||
// chooser.setMultiSelectionEnabled(false);
|
||||
// int result = chooser.showSaveDialog(ATContentStudio.frame);
|
||||
// if (result == JFileChooser.APPROVE_OPTION) {
|
||||
// selected.getProject().generateExportPackage(chooser.getSelectedFile());
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// popupMenu.add(exportProjectPackage);
|
||||
// popupMenu.addSeparator();
|
||||
// }
|
||||
// if (selected instanceof GameDataElement) {
|
||||
// final GameDataElement node = ((GameDataElement)selected);
|
||||
// if (node.state == GameDataElement.State.modified){
|
||||
// JMenuItem saveItem = new JMenuItem("Save this element");
|
||||
// saveItem.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// node.save();
|
||||
// ATContentStudio.frame.nodeChanged(node);
|
||||
// }
|
||||
// });
|
||||
// popupMenu.add(saveItem);
|
||||
// }
|
||||
//
|
||||
// JMenuItem deleteItem = null;
|
||||
// if (node.getDataType() == GameSource.Type.created) {
|
||||
// deleteItem = new JMenuItem("Delete this element");
|
||||
// } else if (node.getDataType() == GameSource.Type.altered) {
|
||||
// deleteItem = new JMenuItem("Revert to original");
|
||||
// }
|
||||
// if (deleteItem != null) {
|
||||
// popupMenu.add(deleteItem);
|
||||
// deleteItem.addActionListener(new ActionListener() {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// ATContentStudio.frame.closeEditor(node);
|
||||
// new Thread() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// node.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
||||
// if (node.getParent() instanceof GameDataCategory<?>) {
|
||||
// ((GameDataCategory<?>)node.getParent()).remove(node);
|
||||
// List<SaveEvent> events = node.attemptSave();
|
||||
// if (events == null || events.isEmpty()) {
|
||||
// node.save();
|
||||
// } else {
|
||||
// new SaveItemsWizard(events, null).setVisible(true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }.start();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// popupMenu.addSeparator();
|
||||
//
|
||||
// }
|
||||
// if (selected instanceof Project || selected instanceof SavedGamesSet) {
|
||||
// JMenuItem addSave = new JMenuItem("Load saved game...");
|
||||
// popupMenu.add(addSave);
|
||||
// popupMenu.addSeparator();
|
||||
// addSave.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// JFileChooser chooser = new JFileChooser("Select an Andor's Trail save file");
|
||||
// if (chooser.showOpenDialog(ATContentStudio.frame) == JFileChooser.APPROVE_OPTION) {
|
||||
// selected.getProject().addSave(chooser.getSelectedFile());
|
||||
// selected.getProject().save();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// if (konamiCodeEntered) {
|
||||
// JMenuItem openTrainer = new JMenuItem("Start Andor's Trainer...");
|
||||
// popupMenu.add(openTrainer);
|
||||
// popupMenu.addSeparator();
|
||||
// openTrainer.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// new Thread() {
|
||||
// public void run() {
|
||||
// AndorsTrainer.startApp(false);
|
||||
// }
|
||||
// }.start();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// JMenu changeLaF = new JMenu("Change Look and Feel");
|
||||
// for (final LookAndFeelInfo i : UIManager.getInstalledLookAndFeels()) {
|
||||
// final JMenuItem lafItem = new JMenuItem("Switch to "+i.getName());
|
||||
// changeLaF.add(lafItem);
|
||||
// lafItem.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// try {
|
||||
// UIManager.setLookAndFeel(i.getClassName());
|
||||
// SwingUtilities.updateComponentTreeUI(ATContentStudio.frame);
|
||||
// ConfigCache.setFavoriteLaFClassName(i.getClassName());
|
||||
// } catch (ClassNotFoundException e1) {
|
||||
// e1.printStackTrace();
|
||||
// } catch (InstantiationException e1) {
|
||||
// e1.printStackTrace();
|
||||
// } catch (IllegalAccessException e1) {
|
||||
// e1.printStackTrace();
|
||||
// } catch (UnsupportedLookAndFeelException e1) {
|
||||
// e1.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// popupMenu.add(changeLaF);
|
||||
// popupMenu.addSeparator();
|
||||
// JMenuItem showAbout = new JMenuItem("About...");
|
||||
// popupMenu.add(showAbout);
|
||||
// popupMenu.addSeparator();
|
||||
// showAbout.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// ATContentStudio.frame.showAbout();
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
public void popupActivated(MouseEvent e) {
|
||||
TreePath path = projectsTree.getPathForLocation (e.getX(), e.getY());
|
||||
TreePath[] allSelected = projectsTree.getSelectionPaths();
|
||||
boolean selectClickedItem = true;
|
||||
if (allSelected != null) {
|
||||
for (TreePath selected : allSelected) {
|
||||
if (selected.equals(path)) {
|
||||
selectClickedItem = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selectClickedItem) projectsTree.setSelectionPath(path);
|
||||
makePopupMenu();
|
||||
if (popupMenu.getComponentCount() > 0) {
|
||||
popupMenu.show(projectsTree, e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
|
||||
public void itemAction(ProjectTreeNode node) {
|
||||
if (node instanceof JSONElement) {
|
||||
ATContentStudio.frame.openEditor((JSONElement)node);
|
||||
} else if (node instanceof Spritesheet) {
|
||||
ATContentStudio.frame.openEditor((Spritesheet)node);
|
||||
} else if (node instanceof TMXMap) {
|
||||
ATContentStudio.frame.openEditor((TMXMap)node);
|
||||
} else if (node instanceof WorldmapSegment) {
|
||||
ATContentStudio.frame.openEditor((WorldmapSegment)node);
|
||||
} else if (node instanceof SavedGame) {
|
||||
if (konamiCodeEntered) {
|
||||
ATContentStudio.frame.openEditor((SavedGame)node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ProjectsTreeModel implements TreeModel {
|
||||
|
||||
public ProjectsTreeModel() {
|
||||
Workspace.activeWorkspace.projectsTreeModel = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRoot() {
|
||||
return Workspace.activeWorkspace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getChild(Object parent, int index) {
|
||||
return ((ProjectTreeNode)parent).getChildAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildCount(Object parent) {
|
||||
return ((ProjectTreeNode)parent).getChildCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf(Object node) {
|
||||
return ((ProjectTreeNode)node).isLeaf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueForPathChanged(TreePath path, Object newValue) {
|
||||
//Unused
|
||||
}
|
||||
|
||||
public void insertNode(TreePath node) {
|
||||
for (TreeModelListener l : listeners) {
|
||||
l.treeNodesInserted(new TreeModelEvent(node.getLastPathComponent(), node.getParentPath().getPath(), new int[]{((ProjectTreeNode)node.getParentPath().getLastPathComponent()).getIndex((ProjectTreeNode)node.getLastPathComponent())}, new Object[]{node.getLastPathComponent()} ));
|
||||
}
|
||||
}
|
||||
|
||||
public void changeNode(TreePath node) {
|
||||
for (TreeModelListener l : listeners) {
|
||||
l.treeNodesChanged(new TreeModelEvent(node.getLastPathComponent(), node.getParentPath(), new int[]{((ProjectTreeNode)node.getParentPath().getLastPathComponent()).getIndex((ProjectTreeNode)node.getLastPathComponent())}, new Object[]{node.getLastPathComponent()} ));
|
||||
}
|
||||
}
|
||||
|
||||
public void removeNode(TreePath node) {
|
||||
for (TreeModelListener l : listeners) {
|
||||
l.treeNodesRemoved(new TreeModelEvent(node.getLastPathComponent(), node.getParentPath(), new int[]{((ProjectTreeNode)node.getParentPath().getLastPathComponent()).getIndex((ProjectTreeNode)node.getLastPathComponent())}, new Object[]{node.getLastPathComponent()} ));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexOfChild(Object parent, Object child) {
|
||||
return ((ProjectTreeNode)parent).getIndex((ProjectTreeNode) child);
|
||||
}
|
||||
|
||||
List<TreeModelListener> listeners = new ArrayList<TreeModelListener>();
|
||||
|
||||
@Override
|
||||
public void addTreeModelListener(TreeModelListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTreeModelListener(TreeModelListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ProjectsTreeCellRenderer extends DefaultTreeCellRenderer {
|
||||
|
||||
private static final long serialVersionUID = 8100380694034797135L;
|
||||
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
Component c = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
|
||||
if (c instanceof JLabel) {
|
||||
JLabel label = (JLabel)c;
|
||||
String text = ((ProjectTreeNode)value).getDesc();
|
||||
if (text != null) label.setText(text);
|
||||
Image img = null;
|
||||
if (leaf) img = ((ProjectTreeNode)value).getLeafIcon();
|
||||
else if (expanded) img = ((ProjectTreeNode)value).getOpenIcon();
|
||||
else img = ((ProjectTreeNode)value).getClosedIcon();
|
||||
|
||||
if (img != null) {
|
||||
label.setIcon(new ImageIcon(img));
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelectedNode(ProjectTreeNode node) {
|
||||
List<TreeNode> path = new ArrayList<TreeNode>();
|
||||
path.add(node);
|
||||
TreeNode parent = node.getParent();
|
||||
while (parent != null) {
|
||||
path.add(0, parent);
|
||||
parent = parent.getParent();
|
||||
}
|
||||
TreePath tp = new TreePath(path.toArray());
|
||||
projectsTree.setSelectionPath(tp);
|
||||
projectsTree.scrollPathToVisible(tp);
|
||||
}
|
||||
|
||||
protected void startKonamiCount() {
|
||||
resetTimeout();
|
||||
exit = false;
|
||||
konamiTimeout = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!exit && timeout > 0) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {}
|
||||
timeout -= 10;
|
||||
}
|
||||
konamiTimeout = null;
|
||||
konamiBuffer = new Integer[]{null, null, null, null, null, null, null, null, null, null};
|
||||
}
|
||||
};
|
||||
konamiTimeout.start();
|
||||
}
|
||||
|
||||
protected void resetTimeout() {
|
||||
timeout = 400;
|
||||
}
|
||||
|
||||
protected boolean compareBuffers() {
|
||||
if (konamiBuffer[0] == null) return true;
|
||||
else if (konamiBuffer[0] != KeyEvent.VK_UP) return false;
|
||||
|
||||
if (konamiBuffer[1] == null) return true;
|
||||
else if (konamiBuffer[1] != KeyEvent.VK_UP) return false;
|
||||
|
||||
if (konamiBuffer[2] == null) return true;
|
||||
else if (konamiBuffer[2] != KeyEvent.VK_DOWN) return false;
|
||||
|
||||
if (konamiBuffer[3] == null) return true;
|
||||
else if (konamiBuffer[3] != KeyEvent.VK_DOWN) return false;
|
||||
|
||||
if (konamiBuffer[4] == null) return true;
|
||||
else if (konamiBuffer[4] != KeyEvent.VK_LEFT) return false;
|
||||
|
||||
if (konamiBuffer[5] == null) return true;
|
||||
else if (konamiBuffer[5] != KeyEvent.VK_RIGHT) return false;
|
||||
|
||||
if (konamiBuffer[6] == null) return true;
|
||||
else if (konamiBuffer[6] != KeyEvent.VK_LEFT) return false;
|
||||
|
||||
if (konamiBuffer[7] == null) return true;
|
||||
else if (konamiBuffer[7] != KeyEvent.VK_RIGHT) return false;
|
||||
|
||||
if (konamiBuffer[8] == null) return true;
|
||||
else if (konamiBuffer[8] != KeyEvent.VK_B) return false;
|
||||
|
||||
if (konamiBuffer[9] == null) return true;
|
||||
else if (konamiBuffer[9] != KeyEvent.VK_A) return false;
|
||||
|
||||
konamiCodeEntered = true;
|
||||
|
||||
exit = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
271
src/com/gpl/rpg/atcontentstudio/ui/SaveItemsWizard.java
Normal file
271
src/com/gpl/rpg/atcontentstudio/ui/SaveItemsWizard.java
Normal file
@@ -0,0 +1,271 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
public class SaveItemsWizard extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = -3301878024575930527L;
|
||||
|
||||
List<SaveEvent> events;
|
||||
|
||||
JList movedToCreated;
|
||||
JList movedToAltered;
|
||||
JList willBeSaved;
|
||||
|
||||
|
||||
public SaveItemsWizard(List<SaveEvent> events, GameDataElement originalRequester) {
|
||||
super(ATContentStudio.frame);
|
||||
this.events = events;
|
||||
final List<SaveEvent> movedToAlteredList = new ArrayList<SaveEvent>();
|
||||
final List<SaveEvent> movedToCreatedList = new ArrayList<SaveEvent>();
|
||||
final List<SaveEvent> alsoSavedList = new ArrayList<SaveEvent>();
|
||||
final List<SaveEvent> errors = new ArrayList<SaveEvent>();
|
||||
for (SaveEvent event : events) {
|
||||
if (event.error) {
|
||||
errors.add(event);
|
||||
} else {
|
||||
switch (event.type) {
|
||||
case alsoSave:
|
||||
alsoSavedList.add(event);
|
||||
break;
|
||||
case moveToAltered:
|
||||
movedToAlteredList.add(event);
|
||||
break;
|
||||
case moveToCreated:
|
||||
movedToCreatedList.add(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
setTitle("Errors in project. Cannot save.");
|
||||
JPanel pane = new JPanel();
|
||||
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
|
||||
if (originalRequester != null) {
|
||||
pane.add(new JLabel(" While trying to save: "), JideBoxLayout.FIX);
|
||||
JLabel origItemDesc = new JLabel();
|
||||
origItemDesc.setIcon(new ImageIcon(originalRequester.getIcon()));
|
||||
origItemDesc.setText(originalRequester.getDataType().toString()+"/"+originalRequester.id);
|
||||
pane.add(origItemDesc, JideBoxLayout.FIX);
|
||||
pane.add(new JLabel(" the following errors have been encountered and must be corrected before saving can occur: "), JideBoxLayout.FIX);
|
||||
} else {
|
||||
pane.add(new JLabel("After deleting element(s), the following errors have been encountered and must be coorected before saving can occur: "), JideBoxLayout.FIX);
|
||||
}
|
||||
|
||||
movedToCreated = new JList(errors.toArray());
|
||||
movedToCreated.setCellRenderer(new SaveEventsListCellRenderer());
|
||||
JPanel movedToCreatedPane = new JPanel();
|
||||
movedToCreatedPane.setLayout(new BorderLayout());
|
||||
movedToCreatedPane.add(new JScrollPane(movedToCreated), BorderLayout.CENTER);
|
||||
pane.add(movedToCreatedPane, JideBoxLayout.FLEXIBLE);
|
||||
|
||||
pane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new JideBoxLayout(buttonPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
buttonPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
JButton cancelButton = new JButton("Ok, back to work...");
|
||||
buttonPane.add(cancelButton, JideBoxLayout.FIX);
|
||||
pane.add(buttonPane, JideBoxLayout.FIX);
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SaveItemsWizard.this.setVisible(false);
|
||||
SaveItemsWizard.this.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
getContentPane().add(pane, BorderLayout.CENTER);
|
||||
|
||||
} else {
|
||||
setTitle("Other elements impacted.");
|
||||
JPanel pane = new JPanel();
|
||||
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
|
||||
if (originalRequester != null) {
|
||||
pane.add(new JLabel(" While trying to save: "), JideBoxLayout.FIX);
|
||||
JLabel origItemDesc = new JLabel();
|
||||
origItemDesc.setIcon(new ImageIcon(originalRequester.getIcon()));
|
||||
origItemDesc.setText(originalRequester.getDataType().toString()+"/"+originalRequester.id);
|
||||
pane.add(origItemDesc, JideBoxLayout.FIX);
|
||||
pane.add(new JLabel(" the following side-effects have been identified and must be applied to the project before saving: "), JideBoxLayout.FIX);
|
||||
} else {
|
||||
pane.add(new JLabel("After deleting element(s), the following side-effects have been identified and must be applied to the project before saving: "), JideBoxLayout.FIX);
|
||||
}
|
||||
|
||||
if (!movedToCreatedList.isEmpty()) {
|
||||
movedToCreated = new JList(movedToCreatedList.toArray());
|
||||
movedToCreated.setCellRenderer(new SaveEventsListCellRenderer());
|
||||
JPanel movedToCreatedPane = new JPanel();
|
||||
movedToCreatedPane.setLayout(new BorderLayout());
|
||||
movedToCreatedPane.setBorder(BorderFactory.createTitledBorder("The following elements will be moved under the \"Created\" folder and saved:"));
|
||||
movedToCreatedPane.add(new JScrollPane(movedToCreated), BorderLayout.CENTER);
|
||||
pane.add(movedToCreatedPane, JideBoxLayout.FLEXIBLE);
|
||||
}
|
||||
|
||||
if (!movedToAlteredList.isEmpty()) {
|
||||
movedToAltered = new JList(movedToAlteredList.toArray());
|
||||
movedToAltered.setCellRenderer(new SaveEventsListCellRenderer());
|
||||
JPanel movedToAlteredPane = new JPanel();
|
||||
movedToAlteredPane.setLayout(new BorderLayout());
|
||||
movedToAlteredPane.setBorder(BorderFactory.createTitledBorder("The following elements will be moved under the \"Altered\" folder and saved:"));
|
||||
movedToAlteredPane.add(new JScrollPane(movedToAltered), BorderLayout.CENTER);
|
||||
pane.add(movedToAlteredPane, JideBoxLayout.FLEXIBLE);
|
||||
}
|
||||
|
||||
if (!alsoSavedList.isEmpty()) {
|
||||
willBeSaved = new JList(alsoSavedList.toArray());
|
||||
willBeSaved.setCellRenderer(new SaveEventsListCellRenderer());
|
||||
JPanel willBeSavedPane = new JPanel();
|
||||
willBeSavedPane.setLayout(new BorderLayout());
|
||||
willBeSavedPane.setBorder(BorderFactory.createTitledBorder("The following elements will be saved too:"));
|
||||
willBeSavedPane.add(new JScrollPane(willBeSaved), BorderLayout.CENTER);
|
||||
pane.add(willBeSavedPane, JideBoxLayout.FLEXIBLE);
|
||||
}
|
||||
|
||||
pane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new JideBoxLayout(buttonPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
buttonPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
JButton cancelButton = new JButton("Cancel");
|
||||
buttonPane.add(cancelButton, JideBoxLayout.FIX);
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SaveItemsWizard.this.setVisible(false);
|
||||
SaveItemsWizard.this.dispose();
|
||||
}
|
||||
});
|
||||
JButton okButton = new JButton("Apply all changes and save");
|
||||
buttonPane.add(okButton, JideBoxLayout.FIX);
|
||||
pane.add(buttonPane, JideBoxLayout.FIX);
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
Map<GameDataCategory<JSONElement>, Set<File>> jsonToSave = new IdentityHashMap<GameDataCategory<JSONElement>, Set<File>>();
|
||||
for (SaveEvent event : movedToCreatedList) {
|
||||
if (event.target instanceof JSONElement) {
|
||||
if (!jsonToSave.containsKey(event.target.getParent())){
|
||||
jsonToSave.put((GameDataCategory<JSONElement>) event.target.getParent(), new HashSet<File>());
|
||||
}
|
||||
jsonToSave.get((GameDataCategory<JSONElement>) event.target.getParent()).add(((JSONElement)event.target).jsonFile);
|
||||
|
||||
event.target.getProject().moveToCreated((JSONElement) event.target);
|
||||
|
||||
if (!jsonToSave.containsKey(event.target.getParent())){
|
||||
jsonToSave.put((GameDataCategory<JSONElement>) event.target.getParent(), new HashSet<File>());
|
||||
}
|
||||
jsonToSave.get((GameDataCategory<JSONElement>) event.target.getParent()).add(((JSONElement)event.target).jsonFile);
|
||||
}
|
||||
//TODO movable maps, when ID is editable.
|
||||
|
||||
}
|
||||
for (SaveEvent event : movedToAlteredList) {
|
||||
if (event.target instanceof JSONElement) {
|
||||
if (!jsonToSave.containsKey(event.target.getParent())){
|
||||
jsonToSave.put((GameDataCategory<JSONElement>) event.target.getParent(), new HashSet<File>());
|
||||
}
|
||||
jsonToSave.get((GameDataCategory<JSONElement>) event.target.getParent()).add(((JSONElement)event.target).jsonFile);
|
||||
|
||||
event.target.getProject().moveToAltered((JSONElement) event.target);
|
||||
|
||||
if (!jsonToSave.containsKey(event.target.getParent())){
|
||||
jsonToSave.put((GameDataCategory<JSONElement>) event.target.getParent(), new HashSet<File>());
|
||||
}
|
||||
jsonToSave.get((GameDataCategory<JSONElement>) event.target.getParent()).add(((JSONElement)event.target).jsonFile);
|
||||
}
|
||||
//TODO movable maps, when ID is editable.
|
||||
}
|
||||
for (SaveEvent event : alsoSavedList) {
|
||||
if (event.target instanceof JSONElement) {
|
||||
if (!jsonToSave.containsKey(event.target.getParent())){
|
||||
jsonToSave.put((GameDataCategory<JSONElement>) event.target.getParent(), new HashSet<File>());
|
||||
}
|
||||
jsonToSave.get((GameDataCategory<JSONElement>) event.target.getParent()).add(((JSONElement)event.target).jsonFile);
|
||||
}
|
||||
}
|
||||
|
||||
for (GameDataCategory<JSONElement> cat : jsonToSave.keySet()) {
|
||||
if (jsonToSave.get(cat) != null && !jsonToSave.get(cat).isEmpty()) {
|
||||
for (File f : jsonToSave.get(cat)) {
|
||||
cat.save(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (SaveEvent event : movedToCreatedList) {
|
||||
ATContentStudio.frame.nodeChanged(event.target);
|
||||
}
|
||||
for (SaveEvent event : movedToAlteredList) {
|
||||
ATContentStudio.frame.nodeChanged(event.target);
|
||||
}
|
||||
for (SaveEvent event : alsoSavedList) {
|
||||
ATContentStudio.frame.nodeChanged(event.target);
|
||||
}
|
||||
SaveItemsWizard.this.setVisible(false);
|
||||
SaveItemsWizard.this.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
getContentPane().add(pane, BorderLayout.CENTER);
|
||||
|
||||
}
|
||||
|
||||
pack();
|
||||
}
|
||||
|
||||
public class SaveEventsListCellRenderer extends DefaultListCellRenderer {
|
||||
private static final long serialVersionUID = 5764079243906396333L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (c instanceof JLabel) {
|
||||
JLabel label = (JLabel) c;
|
||||
SaveEvent event = (SaveEvent) value;
|
||||
label.setIcon(new ImageIcon(event.target.getIcon()));
|
||||
if (event.error) {
|
||||
label.setText(event.target.getDataType().toString()+"/"+event.target.id+": "+event.errorText);
|
||||
} else {
|
||||
label.setText(event.target.getDataType().toString()+"/"+event.target.id);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
338
src/com/gpl/rpg/atcontentstudio/ui/ScrollablePanel.java
Normal file
338
src/com/gpl/rpg/atcontentstudio/ui/ScrollablePanel.java
Normal file
@@ -0,0 +1,338 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.Scrollable;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
public class ScrollablePanel extends JPanel implements Scrollable, SwingConstants {
|
||||
|
||||
private static final long serialVersionUID = 6498229143202972325L;
|
||||
|
||||
public enum ScrollableSizeHint
|
||||
{
|
||||
NONE,
|
||||
FIT,
|
||||
STRETCH;
|
||||
}
|
||||
|
||||
public enum IncrementType
|
||||
{
|
||||
PERCENT,
|
||||
PIXELS;
|
||||
}
|
||||
|
||||
private ScrollableSizeHint scrollableHeight = ScrollableSizeHint.NONE;
|
||||
private ScrollableSizeHint scrollableWidth = ScrollableSizeHint.NONE;
|
||||
|
||||
private IncrementInfo horizontalBlock;
|
||||
private IncrementInfo horizontalUnit;
|
||||
private IncrementInfo verticalBlock;
|
||||
private IncrementInfo verticalUnit;
|
||||
|
||||
/**
|
||||
* Default constructor that uses a FlowLayout
|
||||
*/
|
||||
public ScrollablePanel()
|
||||
{
|
||||
this( new FlowLayout() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constuctor for specifying the LayoutManager of the panel.
|
||||
*
|
||||
* @param layout the LayountManger for the panel
|
||||
*/
|
||||
public ScrollablePanel(LayoutManager layout)
|
||||
{
|
||||
super( layout );
|
||||
|
||||
IncrementInfo block = new IncrementInfo(IncrementType.PERCENT, 100);
|
||||
IncrementInfo unit = new IncrementInfo(IncrementType.PERCENT, 10);
|
||||
|
||||
setScrollableBlockIncrement(HORIZONTAL, block);
|
||||
setScrollableBlockIncrement(VERTICAL, block);
|
||||
setScrollableUnitIncrement(HORIZONTAL, unit);
|
||||
setScrollableUnitIncrement(VERTICAL, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height ScrollableSizeHint enum
|
||||
*
|
||||
* @return the ScrollableSizeHint enum for the height
|
||||
*/
|
||||
public ScrollableSizeHint getScrollableHeight()
|
||||
{
|
||||
return scrollableHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ScrollableSizeHint enum for the height. The enum is used to
|
||||
* determine the boolean value that is returned by the
|
||||
* getScrollableTracksViewportHeight() method. The valid values are:
|
||||
*
|
||||
* ScrollableSizeHint.NONE - return "false", which causes the height
|
||||
* of the panel to be used when laying out the children
|
||||
* ScrollableSizeHint.FIT - return "true", which causes the height of
|
||||
* the viewport to be used when laying out the children
|
||||
* ScrollableSizeHint.STRETCH - return "true" when the viewport height
|
||||
* is greater than the height of the panel, "false" otherwise.
|
||||
*
|
||||
* @param scrollableHeight as represented by the ScrollableSizeHint enum.
|
||||
*/
|
||||
public void setScrollableHeight(ScrollableSizeHint scrollableHeight)
|
||||
{
|
||||
this.scrollableHeight = scrollableHeight;
|
||||
revalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width ScrollableSizeHint enum
|
||||
*
|
||||
* @return the ScrollableSizeHint enum for the width
|
||||
*/
|
||||
public ScrollableSizeHint getScrollableWidth()
|
||||
{
|
||||
return scrollableWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ScrollableSizeHint enum for the width. The enum is used to
|
||||
* determine the boolean value that is returned by the
|
||||
* getScrollableTracksViewportWidth() method. The valid values are:
|
||||
*
|
||||
* ScrollableSizeHint.NONE - return "false", which causes the width
|
||||
* of the panel to be used when laying out the children
|
||||
* ScrollableSizeHint.FIT - return "true", which causes the width of
|
||||
* the viewport to be used when laying out the children
|
||||
* ScrollableSizeHint.STRETCH - return "true" when the viewport width
|
||||
* is greater than the width of the panel, "false" otherwise.
|
||||
*
|
||||
* @param scrollableWidth as represented by the ScrollableSizeHint enum.
|
||||
*/
|
||||
public void setScrollableWidth(ScrollableSizeHint scrollableWidth)
|
||||
{
|
||||
this.scrollableWidth = scrollableWidth;
|
||||
revalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block IncrementInfo for the specified orientation
|
||||
*
|
||||
* @return the block IncrementInfo for the specified orientation
|
||||
*/
|
||||
public IncrementInfo getScrollableBlockIncrement(int orientation)
|
||||
{
|
||||
return orientation == SwingConstants.HORIZONTAL ? horizontalBlock : verticalBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the information needed to do block scrolling.
|
||||
*
|
||||
* @param orientation specify the scrolling orientation. Must be either:
|
||||
* SwingContants.HORIZONTAL or SwingContants.VERTICAL.
|
||||
* @paran type specify how the amount parameter in the calculation of
|
||||
* the scrollable amount. Valid values are:
|
||||
* IncrementType.PERCENT - treat the amount as a % of the viewport size
|
||||
* IncrementType.PIXEL - treat the amount as the scrollable amount
|
||||
* @param amount a value used with the IncrementType to determine the
|
||||
* scrollable amount
|
||||
*/
|
||||
public void setScrollableBlockIncrement(int orientation, IncrementType type, int amount)
|
||||
{
|
||||
IncrementInfo info = new IncrementInfo(type, amount);
|
||||
setScrollableBlockIncrement(orientation, info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the information needed to do block scrolling.
|
||||
*
|
||||
* @param orientation specify the scrolling orientation. Must be either:
|
||||
* SwingContants.HORIZONTAL or SwingContants.VERTICAL.
|
||||
* @param info An IncrementInfo object containing information of how to
|
||||
* calculate the scrollable amount.
|
||||
*/
|
||||
public void setScrollableBlockIncrement(int orientation, IncrementInfo info)
|
||||
{
|
||||
switch(orientation)
|
||||
{
|
||||
case SwingConstants.HORIZONTAL:
|
||||
horizontalBlock = info;
|
||||
break;
|
||||
case SwingConstants.VERTICAL:
|
||||
verticalBlock = info;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid orientation: " + orientation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unit IncrementInfo for the specified orientation
|
||||
*
|
||||
* @return the unit IncrementInfo for the specified orientation
|
||||
*/
|
||||
public IncrementInfo getScrollableUnitIncrement(int orientation)
|
||||
{
|
||||
return orientation == SwingConstants.HORIZONTAL ? horizontalUnit : verticalUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the information needed to do unit scrolling.
|
||||
*
|
||||
* @param orientation specify the scrolling orientation. Must be either:
|
||||
* SwingContants.HORIZONTAL or SwingContants.VERTICAL.
|
||||
* @paran type specify how the amount parameter in the calculation of
|
||||
* the scrollable amount. Valid values are:
|
||||
* IncrementType.PERCENT - treat the amount as a % of the viewport size
|
||||
* IncrementType.PIXEL - treat the amount as the scrollable amount
|
||||
* @param amount a value used with the IncrementType to determine the
|
||||
* scrollable amount
|
||||
*/
|
||||
public void setScrollableUnitIncrement(int orientation, IncrementType type, int amount)
|
||||
{
|
||||
IncrementInfo info = new IncrementInfo(type, amount);
|
||||
setScrollableUnitIncrement(orientation, info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the information needed to do unit scrolling.
|
||||
*
|
||||
* @param orientation specify the scrolling orientation. Must be either:
|
||||
* SwingContants.HORIZONTAL or SwingContants.VERTICAL.
|
||||
* @param info An IncrementInfo object containing information of how to
|
||||
* calculate the scrollable amount.
|
||||
*/
|
||||
public void setScrollableUnitIncrement(int orientation, IncrementInfo info)
|
||||
{
|
||||
switch(orientation)
|
||||
{
|
||||
case SwingConstants.HORIZONTAL:
|
||||
horizontalUnit = info;
|
||||
break;
|
||||
case SwingConstants.VERTICAL:
|
||||
verticalUnit = info;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid orientation: " + orientation);
|
||||
}
|
||||
}
|
||||
|
||||
//Implement Scrollable interface
|
||||
|
||||
public Dimension getPreferredScrollableViewportSize()
|
||||
{
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
public int getScrollableUnitIncrement(
|
||||
Rectangle visible, int orientation, int direction)
|
||||
{
|
||||
switch(orientation)
|
||||
{
|
||||
case SwingConstants.HORIZONTAL:
|
||||
return getScrollableIncrement(horizontalUnit, visible.width);
|
||||
case SwingConstants.VERTICAL:
|
||||
return getScrollableIncrement(verticalUnit, visible.height);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid orientation: " + orientation);
|
||||
}
|
||||
}
|
||||
|
||||
public int getScrollableBlockIncrement(
|
||||
Rectangle visible, int orientation, int direction)
|
||||
{
|
||||
switch(orientation)
|
||||
{
|
||||
case SwingConstants.HORIZONTAL:
|
||||
return getScrollableIncrement(horizontalBlock, visible.width);
|
||||
case SwingConstants.VERTICAL:
|
||||
return getScrollableIncrement(verticalBlock, visible.height);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid orientation: " + orientation);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getScrollableIncrement(IncrementInfo info, int distance)
|
||||
{
|
||||
if (info.getIncrement() == IncrementType.PIXELS)
|
||||
return info.getAmount();
|
||||
else
|
||||
return distance * info.getAmount() / 100;
|
||||
}
|
||||
|
||||
public boolean getScrollableTracksViewportWidth()
|
||||
{
|
||||
if (scrollableWidth == ScrollableSizeHint.NONE)
|
||||
return false;
|
||||
|
||||
if (scrollableWidth == ScrollableSizeHint.FIT)
|
||||
return true;
|
||||
|
||||
// STRETCH sizing, use the greater of the panel or viewport width
|
||||
|
||||
if (getParent() instanceof JViewport)
|
||||
{
|
||||
return (((JViewport)getParent()).getWidth() > getPreferredSize().width);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getScrollableTracksViewportHeight()
|
||||
{
|
||||
if (scrollableHeight == ScrollableSizeHint.NONE)
|
||||
return false;
|
||||
|
||||
if (scrollableHeight == ScrollableSizeHint.FIT)
|
||||
return true;
|
||||
|
||||
// STRETCH sizing, use the greater of the panel or viewport height
|
||||
|
||||
|
||||
if (getParent() instanceof JViewport)
|
||||
{
|
||||
return (((JViewport)getParent()).getHeight() > getPreferredSize().height);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to hold the information required to calculate the scroll amount.
|
||||
*/
|
||||
static class IncrementInfo
|
||||
{
|
||||
private IncrementType type;
|
||||
private int amount;
|
||||
|
||||
public IncrementInfo(IncrementType type, int amount)
|
||||
{
|
||||
this.type = type;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public IncrementType getIncrement()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getAmount()
|
||||
{
|
||||
return amount;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return
|
||||
"ScrollablePanel[" +
|
||||
type + ", " +
|
||||
amount + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
239
src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java
Normal file
239
src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java
Normal file
@@ -0,0 +1,239 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UIManager.LookAndFeelInfo;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.ConfigCache;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.Workspace;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
|
||||
import com.gpl.rpg.atcontentstudio.model.saves.SavedGame;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
|
||||
public class StudioFrame extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = -3391514100319186661L;
|
||||
|
||||
|
||||
final ProjectsTree projectTree;
|
||||
final EditorsArea editors;
|
||||
|
||||
final WorkspaceActions actions = new WorkspaceActions();
|
||||
|
||||
public StudioFrame(String name) {
|
||||
super(name);
|
||||
setIconImage(DefaultIcons.getMainIconImage());
|
||||
|
||||
final JSplitPane topDown = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||
final JSplitPane leftRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||
|
||||
JList notifs = new NotificationsPane();
|
||||
projectTree = new ProjectsTree();
|
||||
editors = new EditorsArea();
|
||||
|
||||
setJMenuBar(new JMenuBar());
|
||||
buildMenu();
|
||||
|
||||
JScrollPane treeScroller = new JScrollPane(projectTree);
|
||||
treeScroller.getVerticalScrollBar().setUnitIncrement(16);
|
||||
leftRight.setLeftComponent(treeScroller);
|
||||
leftRight.setRightComponent(editors);
|
||||
leftRight.setName("StudioFrame.leftRight");
|
||||
topDown.setTopComponent(leftRight);
|
||||
JScrollPane notifScroller = new JScrollPane(notifs);
|
||||
notifScroller.getVerticalScrollBar().setUnitIncrement(16);
|
||||
topDown.setBottomComponent(notifScroller);
|
||||
topDown.setName("StudioFrame.topDown");
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
getContentPane().add(topDown, BorderLayout.CENTER);
|
||||
|
||||
addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
Workspace.activeWorkspace.preferences.windowSize = StudioFrame.this.getSize();
|
||||
}
|
||||
});
|
||||
|
||||
pack();
|
||||
if (Workspace.activeWorkspace.preferences.windowSize != null) {
|
||||
setSize(Workspace.activeWorkspace.preferences.windowSize);
|
||||
} else {
|
||||
setSize(800, 600);
|
||||
}
|
||||
|
||||
if (Workspace.activeWorkspace.preferences.splittersPositions.get(topDown.getName()) != null) {
|
||||
topDown.setDividerLocation(Workspace.activeWorkspace.preferences.splittersPositions.get(topDown.getName()));
|
||||
} else {
|
||||
topDown.setDividerLocation(0.2);
|
||||
}
|
||||
topDown.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
Workspace.activeWorkspace.preferences.splittersPositions.put(topDown.getName(), topDown.getDividerLocation());
|
||||
}
|
||||
});
|
||||
if (Workspace.activeWorkspace.preferences.splittersPositions.get(leftRight.getName()) != null) {
|
||||
leftRight.setDividerLocation(Workspace.activeWorkspace.preferences.splittersPositions.get(leftRight.getName()));
|
||||
} else {
|
||||
leftRight.setDividerLocation(0.3);
|
||||
}
|
||||
leftRight.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
Workspace.activeWorkspace.preferences.splittersPositions.put(leftRight.getName(), leftRight.getDividerLocation());
|
||||
}
|
||||
});
|
||||
|
||||
showAbout();
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
Workspace.saveActive();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void buildMenu() {
|
||||
JMenu fileMenu = new JMenu("File");
|
||||
fileMenu.add(new JMenuItem(actions.createProject));
|
||||
fileMenu.add(new JMenuItem(actions.openProject));
|
||||
fileMenu.add(new JMenuItem(actions.closeProject));
|
||||
fileMenu.add(new JMenuItem(actions.deleteProject));
|
||||
fileMenu.add(new JSeparator());
|
||||
fileMenu.add(new JMenuItem(actions.exitATCS));
|
||||
getJMenuBar().add(fileMenu);
|
||||
|
||||
JMenu projectMenu = new JMenu("Project");
|
||||
projectMenu.add(new JMenuItem(actions.saveElement));
|
||||
projectMenu.add(new JMenuItem(actions.deleteSelected));
|
||||
projectMenu.add(new JSeparator());
|
||||
projectMenu.add(new JMenuItem(actions.createGDE));
|
||||
projectMenu.add(new JMenuItem(actions.importJSON));
|
||||
projectMenu.add(new JMenuItem(actions.loadSave));
|
||||
getJMenuBar().add(projectMenu);
|
||||
|
||||
JMenu toolsMenu = new JMenu("Tools");
|
||||
toolsMenu.add(new JMenuItem(actions.compareItems));
|
||||
toolsMenu.add(new JMenuItem(actions.compareNPCs));
|
||||
toolsMenu.add(new JSeparator());
|
||||
toolsMenu.add(new JMenuItem(actions.exportProject));
|
||||
getJMenuBar().add(toolsMenu);
|
||||
|
||||
JMenu viewMenu = new JMenu("View");
|
||||
JMenu changeLaF = new JMenu("Change Look and Feel");
|
||||
for (final LookAndFeelInfo i : UIManager.getInstalledLookAndFeels()) {
|
||||
final JMenuItem lafItem = new JMenuItem("Switch to "+i.getName());
|
||||
changeLaF.add(lafItem);
|
||||
lafItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
UIManager.setLookAndFeel(i.getClassName());
|
||||
SwingUtilities.updateComponentTreeUI(ATContentStudio.frame);
|
||||
ConfigCache.setFavoriteLaFClassName(i.getClassName());
|
||||
} catch (ClassNotFoundException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (InstantiationException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (IllegalAccessException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (UnsupportedLookAndFeelException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
viewMenu.add(changeLaF);
|
||||
viewMenu.add(new JSeparator());
|
||||
viewMenu.add(new JMenuItem(actions.showAbout));
|
||||
getJMenuBar().add(viewMenu);
|
||||
}
|
||||
|
||||
public void openEditor(JSONElement node) {
|
||||
node.link();
|
||||
editors.openEditor(node);
|
||||
}
|
||||
|
||||
public void openEditor(Spritesheet node) {
|
||||
editors.openEditor(node);
|
||||
}
|
||||
|
||||
public void openEditor(TMXMap node) {
|
||||
node.parse();
|
||||
editors.openEditor(node);
|
||||
}
|
||||
|
||||
|
||||
public void openEditor(GameDataElement node) {
|
||||
if (node instanceof JSONElement) {
|
||||
openEditor((JSONElement) node);
|
||||
} else if (node instanceof Spritesheet) {
|
||||
openEditor((Spritesheet) node);
|
||||
} else if (node instanceof TMXMap) {
|
||||
openEditor((TMXMap) node);
|
||||
}
|
||||
}
|
||||
|
||||
public void openEditor(SavedGame save) {
|
||||
editors.openEditor(save);
|
||||
}
|
||||
|
||||
public void openEditor(WorldmapSegment node) {
|
||||
editors.openEditor(node);
|
||||
}
|
||||
|
||||
public void closeEditor(ProjectTreeNode node) {
|
||||
editors.closeEditor(node);
|
||||
}
|
||||
|
||||
public void selectInTree(ProjectTreeNode node) {
|
||||
projectTree.setSelectedNode(node);
|
||||
}
|
||||
|
||||
public void editorChanged(Editor e) {
|
||||
editors.editorTabChanged(e);
|
||||
}
|
||||
|
||||
public void editorChanged(ProjectTreeNode node) {
|
||||
editors.editorTabChanged(node);
|
||||
}
|
||||
|
||||
public void nodeChanged(ProjectTreeNode node) {
|
||||
node.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(node);
|
||||
}
|
||||
|
||||
public void showAbout() {
|
||||
editors.showAbout();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
53
src/com/gpl/rpg/atcontentstudio/ui/WorkerDialog.java
Normal file
53
src/com/gpl/rpg/atcontentstudio/ui/WorkerDialog.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Toolkit;
|
||||
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
|
||||
public class WorkerDialog extends JDialog {
|
||||
private static final long serialVersionUID = 8239669104275145995L;
|
||||
|
||||
private WorkerDialog(String message, Frame parent) {
|
||||
super(parent, "Loading...");
|
||||
this.setIconImage(DefaultIcons.getMainIconImage());
|
||||
this.getContentPane().setLayout(new JideBoxLayout(this.getContentPane(), JideBoxLayout.PAGE_AXIS, 6));
|
||||
this.getContentPane().add(new JLabel("<html><font size=5>Please wait.<br/>"+message+"</font></html>"), JideBoxLayout.VARY);
|
||||
JMovingIdler idler = new JMovingIdler();
|
||||
idler.setBackground(Color.WHITE);
|
||||
idler.setForeground(Color.GREEN);
|
||||
idler.start();
|
||||
this.getContentPane().add(idler, JideBoxLayout.FIX);
|
||||
this.pack();
|
||||
Dimension sdim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
Dimension wdim = this.getSize();
|
||||
idler.setPreferredSize(new Dimension(wdim.width, 10));
|
||||
this.pack();
|
||||
wdim = this.getSize();
|
||||
this.setLocation((sdim.width - wdim.width)/2, (sdim.height - wdim.height)/2);
|
||||
this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
|
||||
}
|
||||
|
||||
public static void showTaskMessage(String message, Frame parent, Runnable workload) {
|
||||
showTaskMessage(message, parent, false, workload);
|
||||
}
|
||||
|
||||
public static void showTaskMessage(final String message, final Frame parent, final boolean showConfirm, final Runnable workload) {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
WorkerDialog info = new WorkerDialog(message, parent);
|
||||
info.setVisible(true);
|
||||
workload.run();
|
||||
info.dispose();
|
||||
if (showConfirm) JOptionPane.showMessageDialog(parent, "<html><font size=5>Done !</font></html>");
|
||||
};
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
389
src/com/gpl/rpg/atcontentstudio/ui/WorkspaceActions.java
Normal file
389
src/com/gpl/rpg/atcontentstudio/ui/WorkspaceActions.java
Normal file
@@ -0,0 +1,389 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.ClosedProject;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameSource;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
|
||||
import com.gpl.rpg.atcontentstudio.model.Workspace;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
|
||||
import com.gpl.rpg.atcontentstudio.model.saves.SavedGamesSet;
|
||||
import com.gpl.rpg.atcontentstudio.ui.tools.ItemsTableView;
|
||||
import com.gpl.rpg.atcontentstudio.ui.tools.NPCsTableView;
|
||||
|
||||
public class WorkspaceActions {
|
||||
|
||||
ProjectTreeNode selectedNode = null;
|
||||
TreePath[] selectedPaths = null;
|
||||
|
||||
public ATCSAction createProject = new ATCSAction("Create project...", "Opens the project creation wizard") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
new ProjectCreationWizard().setVisible(true);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
public ATCSAction closeProject = new ATCSAction("Close project", "Closes the project, unloading all resources from memory") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!(selectedNode instanceof Project)) return;
|
||||
Workspace.closeProject((Project) selectedNode);
|
||||
};
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode instanceof Project);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
public ATCSAction openProject = new ATCSAction("Open project", "Opens the project, loading all necessary resources in memory") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!(selectedNode instanceof ClosedProject)) return;
|
||||
Workspace.openProject((ClosedProject) selectedNode);
|
||||
};
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode instanceof ClosedProject);
|
||||
};
|
||||
};
|
||||
|
||||
public ATCSAction deleteProject = new ATCSAction("Delete project", "Deletes the project, and all created/altered data, from disk") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedNode instanceof Project) {
|
||||
if (JOptionPane.showConfirmDialog(ATContentStudio.frame, "Are you sure you wish to delete this project ?\nAll files created for it will be deleted too...", "Delete this project ?", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
|
||||
Workspace.deleteProject((Project)selectedNode);
|
||||
}
|
||||
} else if (selectedNode instanceof ClosedProject) {
|
||||
if (JOptionPane.showConfirmDialog(ATContentStudio.frame, "Are you sure you wish to delete this project ?\nAll files created for it will be deleted too...", "Delete this project ?", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
|
||||
Workspace.deleteProject((ClosedProject)selectedNode);
|
||||
}
|
||||
}
|
||||
};
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode instanceof Project || selectedNode instanceof ClosedProject);
|
||||
};
|
||||
};
|
||||
|
||||
public ATCSAction saveElement = new ATCSAction("Save this element", "Saves the current state of this element on disk"){
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!(selectedNode instanceof GameDataElement)) return;
|
||||
final GameDataElement node = ((GameDataElement)selectedNode);
|
||||
if (node.state == GameDataElement.State.modified){
|
||||
node.save();
|
||||
ATContentStudio.frame.nodeChanged(node);
|
||||
}
|
||||
};
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
if (selectedNode instanceof GameDataElement) {
|
||||
setEnabled(((GameDataElement)selectedNode).state == GameDataElement.State.modified);
|
||||
} else {
|
||||
setEnabled(false);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
public ATCSAction deleteSelected = new ATCSAction("Delete", "Deletes the selected items") {
|
||||
boolean multiMode = false;
|
||||
List<GameDataElement> elementsToDelete = null;
|
||||
public void init() {
|
||||
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
|
||||
};
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (multiMode) {
|
||||
if (elementsToDelete == null) return;
|
||||
final Map<GameDataCategory<JSONElement>, Set<File>> impactedCategories = new IdentityHashMap<GameDataCategory<JSONElement>, Set<File>>();
|
||||
for (GameDataElement element : elementsToDelete) {
|
||||
ATContentStudio.frame.closeEditor(element);
|
||||
element.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
||||
if (element instanceof JSONElement) {
|
||||
@SuppressWarnings("unchecked")
|
||||
GameDataCategory<JSONElement> category = (GameDataCategory<JSONElement>) element.getParent();
|
||||
category.remove(element);
|
||||
if (impactedCategories.get(category) == null) {
|
||||
impactedCategories.put(category, new HashSet<File>());
|
||||
}
|
||||
impactedCategories.get(category).add(((JSONElement) element).jsonFile);
|
||||
} else if (element instanceof TMXMap) {
|
||||
TMXMapSet parent = (TMXMapSet) element.getParent();
|
||||
parent.tmxMaps.remove(element);
|
||||
}
|
||||
}
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
final List<SaveEvent> events = new ArrayList<SaveEvent>();
|
||||
List<SaveEvent> catEvents = null;
|
||||
for (GameDataCategory<JSONElement> category : impactedCategories.keySet()) {
|
||||
for (File f : impactedCategories.get(category)) {
|
||||
catEvents = category.attemptSave(true, f.getName());
|
||||
if (catEvents.isEmpty()) {
|
||||
category.save(f);
|
||||
} else {
|
||||
events.addAll(catEvents);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!events.isEmpty()) {
|
||||
new SaveItemsWizard(events, null).setVisible(true);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
} else {
|
||||
if (!(selectedNode instanceof GameDataElement)) return;
|
||||
final GameDataElement node = ((GameDataElement)selectedNode);
|
||||
ATContentStudio.frame.closeEditor(node);
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
node.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
||||
if (node.getParent() instanceof GameDataCategory<?>) {
|
||||
((GameDataCategory<?>)node.getParent()).remove(node);
|
||||
List<SaveEvent> events = node.attemptSave();
|
||||
if (events == null || events.isEmpty()) {
|
||||
node.save();
|
||||
} else {
|
||||
new SaveItemsWizard(events, null).setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
};
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
elementsToDelete = null;
|
||||
if (selectedPaths != null && selectedPaths.length > 1) {
|
||||
multiMode = false;
|
||||
elementsToDelete = new ArrayList<GameDataElement>();
|
||||
for (TreePath selected : selectedPaths) {
|
||||
if (selected.getLastPathComponent() instanceof GameDataElement && ((GameDataElement)selected.getLastPathComponent()).writable) {
|
||||
elementsToDelete.add((GameDataElement) selected.getLastPathComponent());
|
||||
multiMode = true;
|
||||
} else {
|
||||
multiMode = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
putValue(Action.NAME, "Delete all selected elements");
|
||||
setEnabled(multiMode);
|
||||
} else if (selectedNode instanceof GameDataElement && ((GameDataElement)selectedNode).writable) {
|
||||
multiMode = false;
|
||||
if (selectedNode.getDataType() == GameSource.Type.created) {
|
||||
putValue(Action.NAME, "Delete this element");
|
||||
setEnabled(true);
|
||||
} else if (selectedNode.getDataType() == GameSource.Type.altered) {
|
||||
putValue(Action.NAME, "Revert to original");
|
||||
setEnabled(true);
|
||||
} else {
|
||||
setEnabled(false);
|
||||
}
|
||||
} else {
|
||||
setEnabled(false);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
public ATCSAction createGDE = new ATCSAction("Create Game Data Element (JSON)", "Opens the game object creation wizard") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedNode == null || selectedNode.getProject() == null) return;
|
||||
new JSONCreationWizard(selectedNode.getProject()).setVisible(true);
|
||||
}
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode != null && selectedNode.getProject() != null);
|
||||
}
|
||||
};
|
||||
|
||||
public ATCSAction importJSON = new ATCSAction("Import JSON data", "Opens the JSON import wizard") {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedNode == null || selectedNode.getProject() == null) return;
|
||||
new JSONImportWizard(selectedNode.getProject()).setVisible(true);
|
||||
}
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode != null && selectedNode.getProject() != null);
|
||||
}
|
||||
};
|
||||
|
||||
public ATCSAction loadSave = new ATCSAction("Load saved game...", "Opens the saved game loading wizard"){
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if(!(selectedNode instanceof Project || selectedNode instanceof SavedGamesSet)) return;
|
||||
JFileChooser chooser = new JFileChooser("Select an Andor's Trail save file");
|
||||
if (chooser.showOpenDialog(ATContentStudio.frame) == JFileChooser.APPROVE_OPTION) {
|
||||
selectedNode.getProject().addSave(chooser.getSelectedFile());
|
||||
selectedNode.getProject().save();
|
||||
}
|
||||
};
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode instanceof Project || selectedNode instanceof SavedGamesSet);
|
||||
};
|
||||
};
|
||||
|
||||
public ATCSAction compareItems = new ATCSAction("Items comparator", "Opens an editor showing all the items of the project in a table"){
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedNode == null || selectedNode.getProject() == null) return;
|
||||
ATContentStudio.frame.editors.openEditor(new ItemsTableView(selectedNode.getProject()));
|
||||
}
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode != null && selectedNode.getProject() != null);
|
||||
}
|
||||
};
|
||||
|
||||
public ATCSAction compareNPCs = new ATCSAction("NPCs comparator", "Opens an editor showing all the NPCs of the project in a table"){
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedNode == null || selectedNode.getProject() == null) return;
|
||||
ATContentStudio.frame.editors.openEditor(new NPCsTableView(selectedNode.getProject()));
|
||||
}
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode != null && selectedNode.getProject() != null);
|
||||
}
|
||||
};
|
||||
|
||||
public ATCSAction exportProject = new ATCSAction("Export project", "Generates a zip file containing all the created & altered resources of the project, ready to merge with the game source."){
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedNode == null || selectedNode.getProject() == null) return;
|
||||
JFileChooser chooser = new JFileChooser() {
|
||||
private static final long serialVersionUID = 8039332384370636746L;
|
||||
public boolean accept(File f) {
|
||||
return f.isDirectory() || f.getName().endsWith(".zip") || f.getName().endsWith(".ZIP");
|
||||
}
|
||||
};
|
||||
chooser.setMultiSelectionEnabled(false);
|
||||
int result = chooser.showSaveDialog(ATContentStudio.frame);
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
File f = chooser.getSelectedFile();
|
||||
if (!f.getAbsolutePath().substring(f.getAbsolutePath().length() - 4, f.getAbsolutePath().length()).equalsIgnoreCase(".zip")) {
|
||||
f = new File(f.getAbsolutePath()+".zip");
|
||||
}
|
||||
selectedNode.getProject().generateExportPackage(f);
|
||||
}
|
||||
};
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths) {
|
||||
setEnabled(selectedNode != null && selectedNode.getProject() != null);
|
||||
};
|
||||
};
|
||||
|
||||
public ATCSAction showAbout = new ATCSAction("About...", "Displays credits and other informations about ATCS"){
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ATContentStudio.frame.showAbout();
|
||||
};
|
||||
};
|
||||
|
||||
public ATCSAction exitATCS = new ATCSAction("Exit", "Closes the program"){
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
//TODO ouch.
|
||||
System.exit(0);
|
||||
};
|
||||
};
|
||||
|
||||
List<ATCSAction> actions = new ArrayList<WorkspaceActions.ATCSAction>();
|
||||
|
||||
public WorkspaceActions() {
|
||||
actions.add(createProject);
|
||||
actions.add(closeProject);
|
||||
actions.add(openProject);
|
||||
actions.add(deleteProject);
|
||||
actions.add(saveElement);
|
||||
actions.add(deleteSelected);
|
||||
actions.add(createGDE);
|
||||
actions.add(importJSON);
|
||||
actions.add(loadSave);
|
||||
actions.add(compareItems);
|
||||
actions.add(compareNPCs);
|
||||
actions.add(exportProject);
|
||||
actions.add(showAbout);
|
||||
actions.add(exitATCS);
|
||||
selectionChanged(null, null);
|
||||
}
|
||||
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths){
|
||||
this.selectedNode = selectedNode;
|
||||
this.selectedPaths = selectedPaths;
|
||||
synchronized(actions) {
|
||||
for (ATCSAction action : actions) {
|
||||
action.selectionChanged(selectedNode, selectedPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ATCSAction implements Action {
|
||||
|
||||
boolean enabled = true;
|
||||
|
||||
|
||||
public ATCSAction(String name, String desc) {
|
||||
putValue(Action.NAME, name);
|
||||
putValue(Action.SHORT_DESCRIPTION, desc);
|
||||
init();
|
||||
}
|
||||
|
||||
public void init(){}
|
||||
|
||||
public void selectionChanged(ProjectTreeNode selectedNode, TreePath[] selectedPaths){}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {};
|
||||
|
||||
public Map<String, Object> values = new HashMap<String, Object>();
|
||||
|
||||
@Override
|
||||
public Object getValue(String key) {
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putValue(String key, Object value) {
|
||||
PropertyChangeEvent event = new PropertyChangeEvent(this, key, values.get(key), value);
|
||||
values.put(key, value);
|
||||
for (PropertyChangeListener l : listeners) {
|
||||
l.propertyChange(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean b) {
|
||||
PropertyChangeEvent event = new PropertyChangeEvent(this, "enabled", isEnabled(), b);
|
||||
enabled = b;
|
||||
for (PropertyChangeListener l : listeners) {
|
||||
l.propertyChange(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
private Set<PropertyChangeListener> listeners = new HashSet<PropertyChangeListener>();
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
143
src/com/gpl/rpg/atcontentstudio/ui/WorkspaceSelector.java
Normal file
143
src/com/gpl/rpg/atcontentstudio/ui/WorkspaceSelector.java
Normal file
@@ -0,0 +1,143 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ConfigCache;
|
||||
|
||||
public class WorkspaceSelector extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 7518745499760748574L;
|
||||
|
||||
public String selected = null;
|
||||
|
||||
public WorkspaceSelector() {
|
||||
super("Select your workspace");
|
||||
setIconImage(DefaultIcons.getMainIconImage());
|
||||
|
||||
//Data
|
||||
final List<File> workspaces = ConfigCache.getKnownWorkspaces();
|
||||
final List<String> wsPaths = new ArrayList<String>();
|
||||
|
||||
//Active widgets declaration
|
||||
final JComboBox combo = new JComboBox();
|
||||
final JButton browse = new JButton("Browse...");
|
||||
final JButton cancel = new JButton("Cancel");
|
||||
final JButton ok = new JButton("Ok");
|
||||
|
||||
//Widgets behavior
|
||||
combo.setEditable(true);
|
||||
for (File f : workspaces) {
|
||||
String path = f.getAbsolutePath();
|
||||
wsPaths.add(path);
|
||||
combo.addItem(path);
|
||||
}
|
||||
if (ConfigCache.getLatestWorkspace() != null) {
|
||||
combo.setSelectedItem(wsPaths.get(workspaces.indexOf(ConfigCache.getLatestWorkspace())));
|
||||
}
|
||||
combo.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (combo.getSelectedItem() != null) {
|
||||
ok.setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ok.setEnabled(ConfigCache.getLatestWorkspace() != null);
|
||||
ok.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
WorkspaceSelector.this.selected = (String) combo.getSelectedItem();
|
||||
WorkspaceSelector.this.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
cancel.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
WorkspaceSelector.this.selected = null;
|
||||
WorkspaceSelector.this.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
browse.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JFileChooser fc;
|
||||
if(workspaces.isEmpty()) {
|
||||
fc = new JFileChooser();
|
||||
} else {
|
||||
if (ConfigCache.getLatestWorkspace() != null) {
|
||||
fc = new JFileChooser(ConfigCache.getLatestWorkspace());
|
||||
} else {
|
||||
fc = new JFileChooser(workspaces.get(0));
|
||||
}
|
||||
}
|
||||
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
fc.setAcceptAllFileFilterUsed(false);
|
||||
int result = fc.showSaveDialog(WorkspaceSelector.this);
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
String selected = fc.getSelectedFile().getAbsolutePath();
|
||||
for (String s : wsPaths) {
|
||||
if (s.equals(selected)) {
|
||||
selected = s;
|
||||
}
|
||||
}
|
||||
combo.setSelectedItem(selected);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//Layout, labels and dialog behavior.
|
||||
setTitle("Select your workspace");
|
||||
|
||||
JPanel dialogPane = new JPanel();
|
||||
dialogPane.setLayout(new BorderLayout());
|
||||
|
||||
dialogPane.add(new JLabel("Workspace : "), BorderLayout.WEST);
|
||||
dialogPane.add(combo, BorderLayout.CENTER);
|
||||
dialogPane.add(browse, BorderLayout.EAST);
|
||||
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.anchor = GridBagConstraints.EAST;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.weightx = 1;
|
||||
buttonPane.add(new JLabel(), c);
|
||||
|
||||
c.fill = GridBagConstraints.VERTICAL;
|
||||
c.weightx = 0;
|
||||
c.gridx++;
|
||||
buttonPane.add(cancel, c);
|
||||
|
||||
c.gridx++;
|
||||
buttonPane.add(ok, c);
|
||||
|
||||
dialogPane.add(buttonPane, BorderLayout.SOUTH);
|
||||
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
setContentPane(dialogPane);
|
||||
setResizable(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,526 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
import com.gpl.rpg.atcontentstudio.ui.CollapsiblePanel;
|
||||
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
|
||||
import com.gpl.rpg.atcontentstudio.ui.IntegerBasedCheckBox;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
public class ActorConditionEditor extends JSONElementEditor {
|
||||
|
||||
private static final long serialVersionUID = 799130864545495819L;
|
||||
|
||||
private static final String form_view_id = "Form";
|
||||
private static final String json_view_id = "JSON";
|
||||
|
||||
private JButton acIcon;
|
||||
private JTextField idField;
|
||||
private JTextField nameField;
|
||||
private JComboBox categoryBox;
|
||||
private IntegerBasedCheckBox positiveBox;
|
||||
private IntegerBasedCheckBox stackingBox;
|
||||
|
||||
private JTextField roundVisualField;
|
||||
private JSpinner roundHpMinField;
|
||||
private JSpinner roundHpMaxField;
|
||||
private JSpinner roundApMinField;
|
||||
private JSpinner roundApMaxField;
|
||||
|
||||
private JTextField fullRoundVisualField;
|
||||
private JSpinner fullRoundHpMinField;
|
||||
private JSpinner fullRoundHpMaxField;
|
||||
private JSpinner fullRoundApMinField;
|
||||
private JSpinner fullRoundApMaxField;
|
||||
|
||||
private JSpinner abilityHpField;
|
||||
private JSpinner abilityApField;
|
||||
private JSpinner abilityMoveCost;
|
||||
private JSpinner abilityUseCost;
|
||||
private JSpinner abilityReequipCost;
|
||||
private JSpinner abilityAttackCost;
|
||||
private JSpinner abilityAttackChance;
|
||||
private JSpinner abilityDamageMinField;
|
||||
private JSpinner abilityDamageMaxField;
|
||||
private JSpinner abilityCriticalSkill;
|
||||
private JSpinner abilityBlockChance;
|
||||
private JSpinner abilityDamageResistance;
|
||||
|
||||
|
||||
public ActorConditionEditor(ActorCondition ac) {
|
||||
super(ac, ac.getDesc(), ac.getIcon());
|
||||
addEditorTab(form_view_id, getFormView());
|
||||
addEditorTab(json_view_id, getJSONView());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertFormViewDataField(JPanel pane) {
|
||||
final ActorCondition ac = ((ActorCondition)target);
|
||||
|
||||
final FieldUpdateListener listener = new ActorConditionFieldUpdater();
|
||||
|
||||
acIcon = createButtonPane(pane, ac.getProject(), ac, ActorCondition.class, ac.getImage(), Spritesheet.Category.actorcondition, listener);
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", ac.id, ac.writable, listener);
|
||||
nameField = addTextField(pane, "Display name: ", ac.display_name, ac.writable, listener);
|
||||
categoryBox = addEnumValueBox(pane, "Category: ", ActorCondition.ACCategory.values(), ac.category, ac.writable, listener);
|
||||
positiveBox = addIntegerBasedCheckBox(pane, "Positive", ac.positive, ac.writable, listener);
|
||||
stackingBox = addIntegerBasedCheckBox(pane, "Stacking", ac.stacking, ac.writable, listener);
|
||||
|
||||
|
||||
CollapsiblePanel roundEffectPane = new CollapsiblePanel("Effect every round (4s): ");
|
||||
roundEffectPane.setLayout(new JideBoxLayout(roundEffectPane, JideBoxLayout.PAGE_AXIS));
|
||||
final ActorCondition.RoundEffect roundEffect;
|
||||
if (ac.round_effect != null) {
|
||||
roundEffect = ac.round_effect;
|
||||
} else {
|
||||
roundEffect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
roundVisualField = addTextField(roundEffectPane, "Visual effect ID: ", roundEffect.visual_effect, ac.writable, listener);
|
||||
roundHpMinField = addIntegerField(roundEffectPane, "HP Bonus Min: ", roundEffect.hp_boost_min, true, ac.writable, listener);
|
||||
roundHpMaxField = addIntegerField(roundEffectPane, "HP Bonus Max: ", roundEffect.hp_boost_max, true, ac.writable, listener);
|
||||
roundApMinField = addIntegerField(roundEffectPane, "AP Bonus Min: ", roundEffect.ap_boost_min, true, ac.writable, listener);
|
||||
roundApMaxField = addIntegerField(roundEffectPane, "AP Bonus Max: ", roundEffect.ap_boost_max, true, ac.writable, listener);
|
||||
roundEffectPane.setExpanded(ac.round_effect != null);
|
||||
pane.add(roundEffectPane, JideBoxLayout.FIX);
|
||||
|
||||
|
||||
CollapsiblePanel fullRoundEffectPane = new CollapsiblePanel("Effect every full round (20s): ");
|
||||
fullRoundEffectPane.setLayout(new JideBoxLayout(fullRoundEffectPane, JideBoxLayout.PAGE_AXIS));
|
||||
final ActorCondition.RoundEffect fullRoundEffect;
|
||||
if (ac.full_round_effect != null) {
|
||||
fullRoundEffect = ac.full_round_effect;
|
||||
} else {
|
||||
fullRoundEffect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
fullRoundVisualField = addTextField(fullRoundEffectPane, "Visual effect ID: ", fullRoundEffect.visual_effect, ac.writable, listener);
|
||||
fullRoundHpMinField = addIntegerField(fullRoundEffectPane, "HP Bonus min: ", fullRoundEffect.hp_boost_min, true, ac.writable, listener);
|
||||
fullRoundHpMaxField = addIntegerField(fullRoundEffectPane, "HP Bonus max: ", fullRoundEffect.hp_boost_max, true, ac.writable, listener);
|
||||
fullRoundApMinField = addIntegerField(fullRoundEffectPane, "AP Bonus min: ", fullRoundEffect.ap_boost_min, true, ac.writable, listener);
|
||||
fullRoundApMaxField = addIntegerField(fullRoundEffectPane, "AP Bonus max: ", fullRoundEffect.ap_boost_max, true, ac.writable, listener);
|
||||
fullRoundEffectPane.setExpanded(ac.full_round_effect != null);
|
||||
pane.add(fullRoundEffectPane, JideBoxLayout.FIX);
|
||||
|
||||
CollapsiblePanel abilityEffectPane = new CollapsiblePanel("Constant ability effect: ");
|
||||
abilityEffectPane.setLayout(new JideBoxLayout(abilityEffectPane, JideBoxLayout.PAGE_AXIS));
|
||||
ActorCondition.AbilityEffect abilityEffect;
|
||||
if (ac.constant_ability_effect != null) {
|
||||
abilityEffect = ac.constant_ability_effect;
|
||||
} else {
|
||||
abilityEffect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
abilityHpField = addIntegerField(abilityEffectPane, "Boost max HP: ", abilityEffect.max_hp_boost, true, ac.writable, listener);
|
||||
abilityApField = addIntegerField(abilityEffectPane, "Boost max AP: ", abilityEffect.max_ap_boost, true, ac.writable, listener);
|
||||
abilityDamageMinField = addIntegerField(abilityEffectPane, "Boost min damage: ", abilityEffect.increase_damage_min, true, ac.writable, listener);
|
||||
abilityDamageMaxField = addIntegerField(abilityEffectPane, "Boost max damage: ", abilityEffect.increase_damage_max, true, ac.writable, listener);
|
||||
abilityAttackChance = addIntegerField(abilityEffectPane, "Boost attack chance: ", abilityEffect.increase_attack_chance, true, ac.writable, listener);
|
||||
abilityBlockChance = addIntegerField(abilityEffectPane, "Boost block chance: ", abilityEffect.increase_block_chance, true, ac.writable, listener);
|
||||
abilityCriticalSkill = addIntegerField(abilityEffectPane, "Boost critical skill: ", abilityEffect.increase_critical_skill, true, ac.writable, listener);
|
||||
abilityDamageResistance = addIntegerField(abilityEffectPane, "Boost damage resistance: ", abilityEffect.increase_damage_resistance, true, ac.writable, listener);
|
||||
abilityMoveCost = addIntegerField(abilityEffectPane, "Increase move cost: ", abilityEffect.increase_move_cost, true, ac.writable, listener);
|
||||
abilityAttackCost = addIntegerField(abilityEffectPane, "Increase attack cost: ", abilityEffect.increase_attack_cost, true, ac.writable, listener);
|
||||
abilityUseCost = addIntegerField(abilityEffectPane, "Increase item use cost: ", abilityEffect.increase_use_cost, true, ac.writable, listener);
|
||||
abilityReequipCost = addIntegerField(abilityEffectPane, "Increase reequip cost: ", abilityEffect.increase_reequip_cost, true, ac.writable, listener);
|
||||
abilityEffectPane.setExpanded(ac.constant_ability_effect != null);
|
||||
pane.add(abilityEffectPane, JideBoxLayout.FIX);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//TODO enhancement. Split this in smaller pieces (one for each base field, and one for each "*Effect". later, later....
|
||||
public class ActorConditionFieldUpdater implements FieldUpdateListener {
|
||||
@Override
|
||||
public void valueChanged(JComponent source, Object value) {
|
||||
ActorCondition aCond = (ActorCondition)target;
|
||||
if (source == idField) {
|
||||
aCond.id = (String) value;
|
||||
ActorConditionEditor.this.name = aCond.getDesc();
|
||||
aCond.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(ActorConditionEditor.this);
|
||||
} else if (source == nameField) {
|
||||
aCond.display_name = (String) value;
|
||||
ActorConditionEditor.this.name = aCond.getDesc();
|
||||
aCond.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(ActorConditionEditor.this);
|
||||
} else if (source == acIcon) {
|
||||
aCond.icon_id = (String) value;
|
||||
aCond.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ActorConditionEditor.this.icon = new ImageIcon(aCond.getProject().getIcon((String) value));
|
||||
ATContentStudio.frame.editorChanged(ActorConditionEditor.this);
|
||||
acIcon.setIcon(new ImageIcon(aCond.getProject().getImage((String) value)));
|
||||
acIcon.revalidate();
|
||||
acIcon.repaint();
|
||||
} else if (source == positiveBox) {
|
||||
aCond.positive = (Integer) value;
|
||||
} else if (source == stackingBox) {
|
||||
aCond.positive = (Integer) value;
|
||||
} else if (source == categoryBox) {
|
||||
aCond.category = (ActorCondition.ACCategory) value;
|
||||
} else if (source == roundVisualField) {
|
||||
if (value == null) {
|
||||
if (aCond.round_effect != null) {
|
||||
aCond.round_effect.visual_effect = null;
|
||||
if (isEmpty(aCond.round_effect)) {
|
||||
aCond.round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.round_effect == null) {
|
||||
aCond.round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.round_effect.visual_effect = (String) value;
|
||||
}
|
||||
} else if (source == roundHpMinField) {
|
||||
if (value == null) {
|
||||
if (aCond.round_effect != null) {
|
||||
aCond.round_effect.hp_boost_min = null;
|
||||
if (isEmpty(aCond.round_effect)) {
|
||||
aCond.round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.round_effect == null) {
|
||||
aCond.round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.round_effect.hp_boost_min = (Integer) value;
|
||||
}
|
||||
} else if (source == roundHpMaxField) {
|
||||
if (value == null) {
|
||||
if (aCond.round_effect != null) {
|
||||
aCond.round_effect.hp_boost_max = null;
|
||||
if (isEmpty(aCond.round_effect)) {
|
||||
aCond.round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.round_effect == null) {
|
||||
aCond.round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.round_effect.hp_boost_max = (Integer) value;
|
||||
}
|
||||
} else if (source == roundApMinField) {
|
||||
if (value == null) {
|
||||
if (aCond.round_effect != null) {
|
||||
aCond.round_effect.ap_boost_min = null;
|
||||
if (isEmpty(aCond.round_effect)) {
|
||||
aCond.round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.round_effect == null) {
|
||||
aCond.round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.round_effect.ap_boost_min = (Integer) value;
|
||||
}
|
||||
} else if (source == roundApMaxField) {
|
||||
if (value == null) {
|
||||
if (aCond.round_effect != null) {
|
||||
aCond.round_effect.ap_boost_max = null;
|
||||
if (isEmpty(aCond.round_effect)) {
|
||||
aCond.round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.round_effect == null) {
|
||||
aCond.round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.round_effect.ap_boost_max = (Integer) value;
|
||||
}
|
||||
} else if (source == fullRoundVisualField) {
|
||||
if (value == null) {
|
||||
if (aCond.full_round_effect != null) {
|
||||
aCond.full_round_effect.visual_effect = null;
|
||||
if (isEmpty(aCond.full_round_effect)) {
|
||||
aCond.full_round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.full_round_effect == null) {
|
||||
aCond.full_round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.full_round_effect.visual_effect = (String) value;
|
||||
}
|
||||
} else if (source == fullRoundHpMinField) {
|
||||
if (value == null) {
|
||||
if (aCond.full_round_effect != null) {
|
||||
aCond.full_round_effect.hp_boost_min = null;
|
||||
if (isEmpty(aCond.full_round_effect)) {
|
||||
aCond.full_round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.full_round_effect == null) {
|
||||
aCond.full_round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.full_round_effect.hp_boost_min = (Integer) value;
|
||||
}
|
||||
} else if (source == fullRoundHpMaxField) {
|
||||
if (value == null) {
|
||||
if (aCond.full_round_effect != null) {
|
||||
aCond.full_round_effect.hp_boost_max = null;
|
||||
if (isEmpty(aCond.full_round_effect)) {
|
||||
aCond.full_round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.full_round_effect == null) {
|
||||
aCond.full_round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.full_round_effect.hp_boost_max = (Integer) value;
|
||||
}
|
||||
} else if (source == fullRoundApMinField) {
|
||||
if (value == null) {
|
||||
if (aCond.full_round_effect != null) {
|
||||
aCond.full_round_effect.ap_boost_min = null;
|
||||
if (isEmpty(aCond.full_round_effect)) {
|
||||
aCond.full_round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.full_round_effect == null) {
|
||||
aCond.full_round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.full_round_effect.ap_boost_min = (Integer) value;
|
||||
}
|
||||
} else if (source == fullRoundApMaxField) {
|
||||
if (value == null) {
|
||||
if (aCond.full_round_effect != null) {
|
||||
aCond.full_round_effect.ap_boost_max = null;
|
||||
if (isEmpty(aCond.full_round_effect)) {
|
||||
aCond.full_round_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.full_round_effect == null) {
|
||||
aCond.full_round_effect = new ActorCondition.RoundEffect();
|
||||
}
|
||||
aCond.full_round_effect.ap_boost_max = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityHpField) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.max_hp_boost = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.max_hp_boost = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityApField) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.max_ap_boost = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.max_ap_boost = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityMoveCost) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_move_cost = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_move_cost = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityUseCost) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_use_cost = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_use_cost = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityReequipCost) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_reequip_cost = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_reequip_cost = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityAttackCost) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_attack_cost = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_attack_cost = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityAttackChance) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_attack_chance = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_attack_chance = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityDamageMinField) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_damage_min = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_damage_min = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityDamageMaxField) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_damage_max = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_damage_max = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityCriticalSkill) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_critical_skill = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_critical_skill = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityBlockChance) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_block_chance = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_block_chance = (Integer) value;
|
||||
}
|
||||
} else if (source == abilityDamageResistance) {
|
||||
if (value == null) {
|
||||
if (aCond.constant_ability_effect != null) {
|
||||
aCond.constant_ability_effect.increase_damage_resistance = null;
|
||||
if (isEmpty(aCond.constant_ability_effect)) {
|
||||
aCond.constant_ability_effect = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aCond.constant_ability_effect == null) {
|
||||
aCond.constant_ability_effect = new ActorCondition.AbilityEffect();
|
||||
}
|
||||
aCond.constant_ability_effect.increase_damage_resistance = (Integer) value;
|
||||
}
|
||||
}
|
||||
|
||||
if (aCond.state != GameDataElement.State.modified) {
|
||||
aCond.state = GameDataElement.State.modified;
|
||||
ActorConditionEditor.this.name = aCond.getDesc();
|
||||
aCond.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(ActorConditionEditor.this);
|
||||
}
|
||||
updateJsonViewText(aCond.toJsonString());
|
||||
}
|
||||
|
||||
private boolean isEmpty(ActorCondition.RoundEffect round_effect) {
|
||||
return round_effect == null || (
|
||||
round_effect.visual_effect == null &&
|
||||
round_effect.hp_boost_min == null &&
|
||||
round_effect.hp_boost_max == null &&
|
||||
round_effect.ap_boost_min == null &&
|
||||
round_effect.ap_boost_max == null
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isEmpty(ActorCondition.AbilityEffect ability_effect) {
|
||||
return ability_effect == null || (
|
||||
ability_effect.max_hp_boost == null &&
|
||||
ability_effect.max_ap_boost == null &&
|
||||
ability_effect.increase_move_cost == null &&
|
||||
ability_effect.increase_use_cost == null &&
|
||||
ability_effect.increase_reequip_cost == null &&
|
||||
ability_effect.increase_attack_cost == null &&
|
||||
ability_effect.increase_attack_chance == null &&
|
||||
ability_effect.increase_damage_min == null &&
|
||||
ability_effect.increase_damage_max == null &&
|
||||
ability_effect.increase_critical_skill == null &&
|
||||
ability_effect.increase_block_chance == null &&
|
||||
ability_effect.increase_damage_resistance == null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,285 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist.DroppedItem;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
|
||||
import com.gpl.rpg.atcontentstudio.ui.CollapsiblePanel;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
public class DroplistEditor extends JSONElementEditor {
|
||||
|
||||
private static final long serialVersionUID = 1139455254096811058L;
|
||||
|
||||
private static final String form_view_id = "Form";
|
||||
private static final String json_view_id = "JSON";
|
||||
|
||||
private Droplist.DroppedItem selectedItem;
|
||||
|
||||
private JTextField idField;
|
||||
private MyComboBox itemCombo;
|
||||
private DroppedItemsListModel droppedItemsListModel;
|
||||
private JSpinner qtyMinField;
|
||||
private JSpinner qtyMaxField;
|
||||
private JSpinner chanceField;
|
||||
|
||||
public DroplistEditor(Droplist droplist) {
|
||||
super(droplist, droplist.getDesc(), droplist.getIcon());
|
||||
addEditorTab(form_view_id, getFormView());
|
||||
addEditorTab(json_view_id, getJSONView());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertFormViewDataField(JPanel pane) {
|
||||
|
||||
final Droplist droplist = (Droplist)target;
|
||||
final FieldUpdateListener listener = new DroplistFieldUpdater();
|
||||
|
||||
createButtonPane(pane, droplist.getProject(), droplist, Droplist.class, Droplist.getImage(), null, listener);
|
||||
|
||||
idField = addTextField(pane, "Droplist ID: ", droplist.id, droplist.writable, listener);
|
||||
|
||||
CollapsiblePanel itemsPane = new CollapsiblePanel("Items in this droplist: ");
|
||||
itemsPane.setLayout(new JideBoxLayout(itemsPane, JideBoxLayout.PAGE_AXIS));
|
||||
droppedItemsListModel = new DroppedItemsListModel(droplist);
|
||||
final JList itemsList = new JList(droppedItemsListModel);
|
||||
itemsList.setCellRenderer(new DroppedItemsCellRenderer());
|
||||
itemsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
itemsPane.add(new JScrollPane(itemsList), JideBoxLayout.FIX);
|
||||
final JPanel droppedItemsEditorPane = new JPanel();
|
||||
final JButton createDroppedItem = new JButton(new ImageIcon(DefaultIcons.getCreateIcon()));
|
||||
final JButton deleteDroppedItem = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
deleteDroppedItem.setEnabled(false);
|
||||
itemsList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
selectedItem = (Droplist.DroppedItem) itemsList.getSelectedValue();
|
||||
if (selectedItem == null) {
|
||||
deleteDroppedItem.setEnabled(false);
|
||||
} else {
|
||||
deleteDroppedItem.setEnabled(true);
|
||||
}
|
||||
updateDroppedItemsEditorPane(droppedItemsEditorPane, selectedItem, listener);
|
||||
}
|
||||
});
|
||||
if (droplist.writable) {
|
||||
JPanel listButtonsPane = new JPanel();
|
||||
listButtonsPane.setLayout(new JideBoxLayout(listButtonsPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
createDroppedItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Droplist.DroppedItem tempItem = new Droplist.DroppedItem();
|
||||
droppedItemsListModel.addItem(tempItem);
|
||||
itemsList.setSelectedValue(tempItem, true);
|
||||
listener.valueChanged(new JLabel(), null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff.
|
||||
}
|
||||
});
|
||||
deleteDroppedItem.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedItem != null) {
|
||||
droppedItemsListModel.removeItem(selectedItem);
|
||||
selectedItem = null;
|
||||
itemsList.clearSelection();
|
||||
listener.valueChanged(new JLabel(), null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff.
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
listButtonsPane.add(createDroppedItem, JideBoxLayout.FIX);
|
||||
listButtonsPane.add(deleteDroppedItem, JideBoxLayout.FIX);
|
||||
listButtonsPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
itemsPane.add(listButtonsPane, JideBoxLayout.FIX);
|
||||
}
|
||||
droppedItemsEditorPane.setLayout(new JideBoxLayout(droppedItemsEditorPane, JideBoxLayout.PAGE_AXIS));
|
||||
itemsPane.add(droppedItemsEditorPane, JideBoxLayout.FIX);
|
||||
if (droplist.dropped_items == null || droplist.dropped_items.isEmpty()) {
|
||||
itemsPane.collapse();
|
||||
}
|
||||
|
||||
pane.add(itemsPane, JideBoxLayout.FIX);
|
||||
|
||||
}
|
||||
|
||||
public void updateDroppedItemsEditorPane(JPanel pane, DroppedItem di, FieldUpdateListener listener) {
|
||||
boolean writable = ((Droplist)target).writable;
|
||||
Project proj = ((Droplist)target).getProject();
|
||||
pane.removeAll();
|
||||
if (itemCombo != null) {
|
||||
removeElementListener(itemCombo);
|
||||
}
|
||||
if (di != null) {
|
||||
itemCombo = addItemBox(pane, proj, "Item: ", di.item, writable, listener);
|
||||
qtyMinField = addIntegerField(pane, "Quantity min: ", di.quantity_min, false, writable, listener);
|
||||
qtyMaxField = addIntegerField(pane, "Quantity max: ", di.quantity_max, false, writable, listener);
|
||||
chanceField = addDoubleField(pane, "Chance: ", di.chance, writable, listener);
|
||||
}
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
|
||||
public class DroppedItemsListModel implements ListModel {
|
||||
|
||||
Droplist source;
|
||||
|
||||
public DroppedItemsListModel(Droplist droplist) {
|
||||
this.source = droplist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
if (source.dropped_items == null) return 0;
|
||||
return source.dropped_items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
if (source.dropped_items == null) return null;
|
||||
return source.dropped_items.get(index);
|
||||
}
|
||||
|
||||
public void addItem(Droplist.DroppedItem item) {
|
||||
if (source.dropped_items == null) {
|
||||
source.dropped_items = new ArrayList<Droplist.DroppedItem>();
|
||||
}
|
||||
source.dropped_items.add(item);
|
||||
int index = source.dropped_items.indexOf(item);
|
||||
for (ListDataListener l : listeners) {
|
||||
l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
public void removeItem(Droplist.DroppedItem item) {
|
||||
int index = source.dropped_items.indexOf(item);
|
||||
source.dropped_items.remove(item);
|
||||
if (source.dropped_items.isEmpty()) {
|
||||
source.dropped_items = null;
|
||||
}
|
||||
for (ListDataListener l : listeners) {
|
||||
l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
public void itemChanged(Droplist.DroppedItem item) {
|
||||
int index = source.dropped_items.indexOf(item);
|
||||
for (ListDataListener l : listeners) {
|
||||
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DroppedItemsCellRenderer extends DefaultListCellRenderer {
|
||||
private static final long serialVersionUID = 7987880146189575234L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (c instanceof JLabel) {
|
||||
JLabel label = ((JLabel)c);
|
||||
Droplist.DroppedItem di = (Droplist.DroppedItem)value;
|
||||
if (di.item != null) {
|
||||
label.setIcon(new ImageIcon(di.item.getIcon()));
|
||||
label.setText(di.chance+"% to get "+di.quantity_min+"-"+di.quantity_max+" "+di.item.getDesc());
|
||||
} else if (!isNull(di)) {
|
||||
label.setText(di.chance+"% to get "+di.quantity_min+"-"+di.quantity_max+" "+di.item_id);
|
||||
} else {
|
||||
label.setText("New, undefined, dropped item.");
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public boolean isNull(Droplist.DroppedItem item) {
|
||||
return ((item == null) || (
|
||||
item.item == null &&
|
||||
item.item_id == null &&
|
||||
item.quantity_min == null &&
|
||||
item.quantity_max == null &&
|
||||
item.chance == null
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class DroplistFieldUpdater implements FieldUpdateListener {
|
||||
@Override
|
||||
public void valueChanged(JComponent source, Object value) {
|
||||
Droplist droplist = ((Droplist)target);
|
||||
if (source == idField) {
|
||||
droplist.id = (String) value;
|
||||
DroplistEditor.this.name = droplist.getDesc();
|
||||
droplist.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(DroplistEditor.this);
|
||||
} else if (source == itemCombo) {
|
||||
if (selectedItem.item != null) {
|
||||
selectedItem.item.removeBacklink(droplist);
|
||||
}
|
||||
selectedItem.item = (Item) value;
|
||||
if (selectedItem.item != null) {
|
||||
selectedItem.item_id = selectedItem.item.id;
|
||||
selectedItem.item.addBacklink(droplist);
|
||||
} else {
|
||||
selectedItem.item_id = null;
|
||||
}
|
||||
droppedItemsListModel.itemChanged(selectedItem);
|
||||
} else if (source == qtyMinField) {
|
||||
selectedItem.quantity_min = (Integer) value;
|
||||
droppedItemsListModel.itemChanged(selectedItem);
|
||||
} else if (source == qtyMaxField) {
|
||||
selectedItem.quantity_max = (Integer) value;
|
||||
droppedItemsListModel.itemChanged(selectedItem);
|
||||
} else if (source == chanceField) {
|
||||
selectedItem.chance = (Double) value;
|
||||
droppedItemsListModel.itemChanged(selectedItem);
|
||||
}
|
||||
|
||||
if (droplist.state != GameDataElement.State.modified) {
|
||||
droplist.state = GameDataElement.State.modified;
|
||||
DroplistEditor.this.name = droplist.getDesc();
|
||||
droplist.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(DroplistEditor.this);
|
||||
}
|
||||
updateJsonViewText(droplist.toJsonString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
|
||||
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
|
||||
|
||||
public class ItemCategoryEditor extends JSONElementEditor {
|
||||
|
||||
private static final long serialVersionUID = -2893876158803488355L;
|
||||
|
||||
private static final String form_view_id = "Form";
|
||||
private static final String json_view_id = "JSON";
|
||||
|
||||
public ItemCategoryEditor(ItemCategory ic) {
|
||||
super(ic, ic.getDesc(), ic.getIcon());
|
||||
addEditorTab(form_view_id, getFormView());
|
||||
addEditorTab(json_view_id, getJSONView());
|
||||
}
|
||||
|
||||
private JButton icIcon;
|
||||
private JTextField idField;
|
||||
private JTextField nameField;
|
||||
private JComboBox slotBox;
|
||||
private JComboBox typeBox;
|
||||
private JComboBox sizeBox;
|
||||
|
||||
@Override
|
||||
public void insertFormViewDataField(JPanel pane) {
|
||||
final ItemCategory ic = ((ItemCategory)target);
|
||||
final FieldUpdateListener listener = new ItemCategoryFieldUpdater();
|
||||
|
||||
icIcon = createButtonPane(pane, ic.getProject(), ic, ItemCategory.class, ic.getImage(), null, listener);
|
||||
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", ic.id, ic.writable, listener);
|
||||
nameField = addTextField(pane, "Display name: ", ic.name, ic.writable, listener);
|
||||
typeBox = addEnumValueBox(pane, "Action type: ", ItemCategory.ActionType.values(), ic.action_type, ic.writable, listener);
|
||||
slotBox = addEnumValueBox(pane, "Inventory slot: ", ItemCategory.InventorySlot.values(), ic.slot, ic.writable, listener);
|
||||
sizeBox = addEnumValueBox(pane, "Item size: ", ItemCategory.Size.values(), ic.size, ic.writable, listener);
|
||||
if (ic.action_type != ItemCategory.ActionType.equip) {
|
||||
slotBox.setEnabled(false);
|
||||
}
|
||||
slotBox.setRenderer(new SlotCellRenderer());
|
||||
}
|
||||
|
||||
public class SlotCellRenderer extends DefaultListCellRenderer {
|
||||
private static final long serialVersionUID = -8359181274986492979L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (c instanceof JLabel) {
|
||||
((JLabel)c).setIcon(new ImageIcon(ItemCategory.getIcon((ItemCategory.InventorySlot) value)));
|
||||
if (value == null) {
|
||||
if (typeBox.getSelectedItem() == ItemCategory.ActionType.equip) {
|
||||
((JLabel)c).setText("Undefined. Select the slot to use when equipped.");
|
||||
} else {
|
||||
((JLabel)c).setText("Non equippable. Select \"equip\" action type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
public class ItemCategoryFieldUpdater implements FieldUpdateListener {
|
||||
@Override
|
||||
public void valueChanged(JComponent source, Object value) {
|
||||
ItemCategory ic = (ItemCategory)target;
|
||||
if (source == idField) {
|
||||
ic.id = (String) value;
|
||||
ItemCategoryEditor.this.name = ic.getDesc();
|
||||
ic.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(ItemCategoryEditor.this);
|
||||
} else if (source == nameField) {
|
||||
ic.name = (String) value;
|
||||
ItemCategoryEditor.this.name = ic.getDesc();
|
||||
ic.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(ItemCategoryEditor.this);
|
||||
} else if (source == slotBox) {
|
||||
ic.slot = (ItemCategory.InventorySlot) value;
|
||||
icIcon.setIcon(new ImageIcon(ic.getImage()));
|
||||
ItemCategoryEditor.this.icon = new ImageIcon(ic.getIcon());
|
||||
ic.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(ItemCategoryEditor.this);
|
||||
} else if (source == typeBox) {
|
||||
ic.action_type = (ItemCategory.ActionType) value;
|
||||
if (ic.action_type != ItemCategory.ActionType.equip && ic.slot != null) {
|
||||
ic.slot = null;
|
||||
slotBox.setSelectedItem(null);
|
||||
slotBox.setEnabled(false);
|
||||
icIcon.setIcon(new ImageIcon(ic.getImage()));
|
||||
ItemCategoryEditor.this.icon = new ImageIcon(ic.getIcon());
|
||||
ic.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(ItemCategoryEditor.this);
|
||||
} else if (ic.action_type == ItemCategory.ActionType.equip) {
|
||||
slotBox.setEnabled(true);
|
||||
}
|
||||
} else if (source == sizeBox) {
|
||||
ic.size = (ItemCategory.Size) value;
|
||||
}
|
||||
|
||||
if (ic.state != GameDataElement.State.modified) {
|
||||
ic.state = GameDataElement.State.modified;
|
||||
ItemCategoryEditor.this.name = ic.getDesc();
|
||||
ic.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(ItemCategoryEditor.this);
|
||||
}
|
||||
updateJsonViewText(ic.toJsonString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1102
src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemEditor.java
Normal file
1102
src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/ItemEditor.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,269 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameSource;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
import com.gpl.rpg.atcontentstudio.ui.Editor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
|
||||
import com.gpl.rpg.atcontentstudio.ui.SaveItemsWizard;
|
||||
import com.gpl.rpg.atcontentstudio.ui.sprites.SpriteChooser;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
public abstract class JSONElementEditor extends Editor {
|
||||
|
||||
private static final long serialVersionUID = -5889046987755079563L;
|
||||
|
||||
|
||||
Map<String, JPanel> editorTabs = new HashMap<String, JPanel>();
|
||||
JideTabbedPane editorTabsHolder;
|
||||
RSyntaxTextArea jsonEditorPane;
|
||||
|
||||
public JSONElementEditor(JSONElement target, String desc, Image icon) {
|
||||
super();
|
||||
this.target = target;
|
||||
this.name = desc;
|
||||
this.icon = new ImageIcon(icon);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
editorTabsHolder = new JideTabbedPane(JideTabbedPane.BOTTOM);
|
||||
editorTabsHolder.setTabShape(JideTabbedPane.SHAPE_FLAT);
|
||||
editorTabsHolder.setUseDefaultShowCloseButtonOnTab(false);
|
||||
editorTabsHolder.setShowCloseButtonOnTab(false);
|
||||
add(editorTabsHolder, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void addEditorTab(String id, JPanel editor) {
|
||||
JScrollPane scroller = new JScrollPane(editor);
|
||||
scroller.getVerticalScrollBar().setUnitIncrement(16);
|
||||
editorTabsHolder.addTab(id, scroller);
|
||||
editorTabs.put(id, editor);
|
||||
}
|
||||
|
||||
public JPanel getJSONView() {
|
||||
jsonEditorPane = new RSyntaxTextArea();
|
||||
jsonEditorPane.setText(((JSONElement)target).toJsonString());
|
||||
jsonEditorPane.setEditable(((JSONElement)target).writable);
|
||||
jsonEditorPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JSON);
|
||||
JPanel result = new JPanel();
|
||||
result.setLayout(new BorderLayout());
|
||||
result.add(jsonEditorPane, BorderLayout.CENTER);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void updateJsonViewText(String text) {
|
||||
jsonEditorPane.setText(text);
|
||||
}
|
||||
|
||||
public JPanel getFormView() {
|
||||
JPanel pane = new JPanel();
|
||||
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
|
||||
if (((JSONElement)target).jsonFile != null) {
|
||||
addLabelField(pane, "JSON File: ", ((JSONElement)target).jsonFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
insertFormViewDataField(pane);
|
||||
|
||||
addBacklinksList(pane, (JSONElement) target);
|
||||
|
||||
//Placeholder. Fills the eventual remaining space.
|
||||
pane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
public abstract void insertFormViewDataField(JPanel pane);
|
||||
|
||||
|
||||
|
||||
public JButton createButtonPane(JPanel pane, final Project proj, final JSONElement node, final Class<? extends JSONElement> concreteNodeClass, Image icon, final Spritesheet.Category iconCat, final FieldUpdateListener listener) {
|
||||
final JButton gdeIcon = new JButton(new ImageIcon(icon));
|
||||
JPanel savePane = new JPanel();
|
||||
savePane.add(gdeIcon, JideBoxLayout.FIX);
|
||||
savePane.setLayout(new JideBoxLayout(savePane, JideBoxLayout.LINE_AXIS, 6));
|
||||
if (node.writable) {
|
||||
if (iconCat != null) {
|
||||
gdeIcon.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SpriteChooser chooser = SpriteChooser.getChooser(proj, iconCat);
|
||||
chooser.setSelectionListener(new SpriteChooser.SelectionListener() {
|
||||
@Override
|
||||
public void iconSelected(String selected) {
|
||||
if (selected != null) {
|
||||
listener.valueChanged(gdeIcon, selected);
|
||||
}
|
||||
}
|
||||
});
|
||||
chooser.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (node.getDataType() == GameSource.Type.altered) {
|
||||
savePane.add(message = new JLabel(ALTERED_MESSAGE), JideBoxLayout.FIX);
|
||||
} else if (node.getDataType() == GameSource.Type.created) {
|
||||
savePane.add(message = new JLabel(CREATED_MESSAGE), JideBoxLayout.FIX);
|
||||
}
|
||||
JButton save = new JButton(SAVE);
|
||||
save.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (node.getParent() instanceof GameDataCategory<?>) {
|
||||
if (node.state != GameDataElement.State.saved) {
|
||||
final List<SaveEvent> events = node.attemptSave();
|
||||
if (events == null) {
|
||||
ATContentStudio.frame.nodeChanged(node);
|
||||
} else {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
new SaveItemsWizard(events, node).setVisible(true);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
savePane.add(save, JideBoxLayout.FIX);
|
||||
JButton delete = new JButton(DELETE);
|
||||
if (node.getDataType() == GameSource.Type.altered) {
|
||||
delete.setText(REVERT);
|
||||
}
|
||||
delete.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ATContentStudio.frame.closeEditor(node);
|
||||
node.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
||||
if (node.getParent() instanceof GameDataCategory<?>) {
|
||||
((GameDataCategory<?>)node.getParent()).remove(node);
|
||||
node.save();
|
||||
for (GameDataElement backlink : node.getBacklinks()) {
|
||||
backlink.elementChanged(node, proj.getGameDataElement(node.getClass(), node.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
savePane.add(delete, JideBoxLayout.FIX);
|
||||
} else {
|
||||
if (proj.alteredContent.gameData.getGameDataElement(concreteNodeClass, node.id) != null) {
|
||||
savePane.add(message = new JLabel(ALTERED_EXISTS_MESSAGE), JideBoxLayout.FIX);
|
||||
JButton makeWritable = new JButton("Go to altered");
|
||||
makeWritable.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (node.getProject().getGameDataElement(concreteNodeClass, node.id) != node) {
|
||||
ATContentStudio.frame.openEditor(node.getProject().getGameDataElement(concreteNodeClass, node.id));
|
||||
ATContentStudio.frame.closeEditor(node);
|
||||
ATContentStudio.frame.selectInTree(node.getProject().getGameDataElement(concreteNodeClass, node.id));
|
||||
}
|
||||
}
|
||||
});
|
||||
savePane.add(makeWritable, JideBoxLayout.FIX);
|
||||
|
||||
} else {
|
||||
savePane.add(message = new JLabel(READ_ONLY_MESSAGE), JideBoxLayout.FIX);
|
||||
JButton makeWritable = new JButton("Alter");
|
||||
makeWritable.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (node.getProject().getGameDataElement(concreteNodeClass, node.id) == node) {
|
||||
node.getProject().makeWritable(node);
|
||||
}
|
||||
if (node.getProject().getGameDataElement(concreteNodeClass, node.id) != node) {
|
||||
ATContentStudio.frame.openEditor(node.getProject().getGameDataElement(concreteNodeClass, node.id));
|
||||
ATContentStudio.frame.closeEditor(node);
|
||||
ATContentStudio.frame.selectInTree(node.getProject().getGameDataElement(concreteNodeClass, node.id));
|
||||
}
|
||||
updateMessage();
|
||||
}
|
||||
});
|
||||
savePane.add(makeWritable, JideBoxLayout.FIX);
|
||||
}
|
||||
}
|
||||
JButton prev = new JButton(new ImageIcon(DefaultIcons.getArrowLeftIcon()));
|
||||
JButton next = new JButton(new ImageIcon(DefaultIcons.getArrowRightIcon()));
|
||||
savePane.add(prev, JideBoxLayout.FIX);
|
||||
savePane.add(next, JideBoxLayout.FIX);
|
||||
if (node.getParent().getIndex(node) == 0) {
|
||||
prev.setEnabled(false);
|
||||
}
|
||||
if (node.getParent().getIndex(node) == node.getParent().getChildCount() - 1) {
|
||||
next.setEnabled(false);
|
||||
}
|
||||
prev.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ProjectTreeNode prevNode = (ProjectTreeNode) node.getParent().getChildAt(node.getParent().getIndex(node) - 1);
|
||||
if (prevNode != null && prevNode instanceof GameDataElement) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement) prevNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
next.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ProjectTreeNode nextNode = (ProjectTreeNode) node.getParent().getChildAt(node.getParent().getIndex(node) + 1);
|
||||
if (nextNode != null && nextNode instanceof GameDataElement) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement) nextNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
//Placeholder. Fills the eventual remaining space.
|
||||
savePane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
pane.add(savePane, JideBoxLayout.FIX);
|
||||
return gdeIcon;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void targetUpdated() {
|
||||
this.icon = new ImageIcon(((GameDataElement)target).getIcon());
|
||||
this.name = ((GameDataElement)target).getDesc();
|
||||
updateMessage();
|
||||
}
|
||||
|
||||
public void updateMessage() {
|
||||
|
||||
//TODO make this a full update of the button panel.
|
||||
JSONElement node = (JSONElement) target;
|
||||
if (node.writable) {
|
||||
if (node.getDataType() == GameSource.Type.altered) {
|
||||
message.setText(ALTERED_MESSAGE);
|
||||
} else if (node.getDataType() == GameSource.Type.created) {
|
||||
message.setText(CREATED_MESSAGE);
|
||||
}
|
||||
} else if (node.getProject().alteredContent.gameData.getGameDataElement(node.getClass(), node.id) != null) {
|
||||
message.setText(ALTERED_EXISTS_MESSAGE);
|
||||
} else {
|
||||
message.setText(READ_ONLY_MESSAGE);
|
||||
}
|
||||
message.revalidate();
|
||||
message.repaint();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,612 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
import com.gpl.rpg.atcontentstudio.ui.CollapsiblePanel;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
|
||||
import com.gpl.rpg.atcontentstudio.ui.IntegerBasedCheckBox;
|
||||
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.dialoguetree.DialogueGraphView;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
public class NPCEditor extends JSONElementEditor {
|
||||
|
||||
private static final long serialVersionUID = 4001483665523721800L;
|
||||
|
||||
private static final String form_view_id = "Form";
|
||||
private static final String json_view_id = "JSON";
|
||||
|
||||
private NPC.TimedConditionEffect selectedHitEffectSourceCondition;
|
||||
private NPC.TimedConditionEffect selectedHitEffectTargetCondition;
|
||||
|
||||
private JButton npcIcon;
|
||||
private JTextField idField;
|
||||
private JTextField nameField;
|
||||
private JTextField spawnGroupField;
|
||||
private JSpinner experienceField;
|
||||
private MyComboBox dialogueBox;
|
||||
private MyComboBox droplistBox;
|
||||
private JComboBox monsterClassBox;
|
||||
private IntegerBasedCheckBox uniqueBox;
|
||||
private JComboBox moveTypeBox;
|
||||
|
||||
private CollapsiblePanel combatTraitPane;
|
||||
private JSpinner maxHP;
|
||||
private JSpinner maxAP;
|
||||
private JSpinner moveCost;
|
||||
private JSpinner atkDmgMin;
|
||||
private JSpinner atkDmgMax;
|
||||
private JSpinner atkCost;
|
||||
private JSpinner atkChance;
|
||||
private JSpinner critSkill;
|
||||
private JSpinner critMult;
|
||||
private JSpinner blockChance;
|
||||
private JSpinner dmgRes;
|
||||
|
||||
private NPC.HitEffect hitEffect;
|
||||
private CollapsiblePanel hitEffectPane;
|
||||
private JSpinner hitEffectHPMin;
|
||||
private JSpinner hitEffectHPMax;
|
||||
private JSpinner hitEffectAPMin;
|
||||
private JSpinner hitEffectAPMax;
|
||||
|
||||
private SourceTimedConditionsListModel hitSourceConditionsListModel;
|
||||
private JList hitSourceConditionsList;
|
||||
private MyComboBox sourceConditionBox;
|
||||
private JSpinner sourceConditionMagnitude;
|
||||
private JSpinner sourceConditionDuration;
|
||||
private JSpinner sourceConditionChance;
|
||||
|
||||
private TargetTimedConditionsListModel hitTargetConditionsListModel;
|
||||
private JList hitTargetConditionsList;
|
||||
private MyComboBox targetConditionBox;
|
||||
private JSpinner targetConditionMagnitude;
|
||||
private JSpinner targetConditionDuration;
|
||||
private JSpinner targetConditionChance;
|
||||
|
||||
public NPCEditor(NPC npc) {
|
||||
super(npc, npc.getDesc(), npc.getIcon());
|
||||
addEditorTab(form_view_id, getFormView());
|
||||
addEditorTab(json_view_id, getJSONView());
|
||||
if (npc.dialogue != null) {
|
||||
JPanel pane = new JPanel();
|
||||
pane.setLayout(new BorderLayout());
|
||||
pane.add(new JScrollPane(new DialogueGraphView(npc.dialogue, npc)), BorderLayout.CENTER);
|
||||
addEditorTab("Dialogue Tree", pane);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertFormViewDataField(JPanel pane) {
|
||||
final NPC npc = (NPC) target;
|
||||
|
||||
final FieldUpdateListener listener = new NPCFieldUpdate();
|
||||
|
||||
npcIcon = createButtonPane(pane, npc.getProject(), npc, NPC.class, npc.getImage(), Spritesheet.Category.monster, listener);
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", npc.id, npc.writable, listener);
|
||||
nameField = addTextField(pane, "Display name: ", npc.name, npc.writable, listener);
|
||||
spawnGroupField = addTextField(pane, "Spawn group ID: ", npc.spawngroup_id, npc.writable, listener);
|
||||
experienceField = addIntegerField(pane, "Experience reward: ", npc.getMonsterExperience(), false, false, listener);
|
||||
dialogueBox = addDialogueBox(pane, npc.getProject(), "Initial phrase: ", npc.dialogue, npc.writable, listener);
|
||||
droplistBox = addDroplistBox(pane, npc.getProject(), "Droplist / Shop inventory: ", npc.droplist, npc.writable, listener);
|
||||
monsterClassBox = addEnumValueBox(pane, "Monster class: ", NPC.MonsterClass.values(), npc.monster_class, npc.writable, listener);
|
||||
uniqueBox = addIntegerBasedCheckBox(pane, "Unique", npc.unique, npc.writable, listener);
|
||||
moveTypeBox = addEnumValueBox(pane, "Movement type: ", NPC.MovementType.values(), npc.movement_type, npc.writable, listener);
|
||||
combatTraitPane = new CollapsiblePanel("Combat traits: ");
|
||||
combatTraitPane.setLayout(new JideBoxLayout(combatTraitPane, JideBoxLayout.PAGE_AXIS, 6));
|
||||
maxHP = addIntegerField(combatTraitPane, "Max HP: ", npc.max_hp, false, npc.writable, listener);
|
||||
maxAP = addIntegerField(combatTraitPane, "Max AP: ", npc.max_ap, false, npc.writable, listener);
|
||||
moveCost = addIntegerField(combatTraitPane, "Move cost: ", npc.move_cost, false, npc.writable, listener);
|
||||
atkDmgMin = addIntegerField(combatTraitPane, "Attack Damage min: ", npc.attack_damage_min, false, npc.writable, listener);
|
||||
atkDmgMax = addIntegerField(combatTraitPane, "Attack Damage max: ", npc.attack_damage_max, false, npc.writable, listener);
|
||||
atkCost = addIntegerField(combatTraitPane, "Attack cost: ", npc.attack_cost, false, npc.writable, listener);
|
||||
atkChance = addIntegerField(combatTraitPane, "Attack chance: ", npc.attack_chance, false, npc.writable, listener);
|
||||
critSkill = addIntegerField(combatTraitPane, "Critical skill: ", npc.critical_skill, false, npc.writable, listener);
|
||||
critMult = addDoubleField(combatTraitPane, "Critical multiplier: ", npc.critical_multiplier, npc.writable, listener);
|
||||
blockChance = addIntegerField(combatTraitPane, "Block chance: ", npc.block_chance, false, npc.writable, listener);
|
||||
dmgRes = addIntegerField(combatTraitPane, "Damage resistance: ", npc.damage_resistance, false, npc.writable, listener);
|
||||
hitEffectPane = new CollapsiblePanel("Effect on every hit: ");
|
||||
hitEffectPane.setLayout(new JideBoxLayout(hitEffectPane, JideBoxLayout.PAGE_AXIS));
|
||||
if (npc.hit_effect == null) {
|
||||
hitEffect = new NPC.HitEffect();
|
||||
} else {
|
||||
hitEffect = npc.hit_effect;
|
||||
}
|
||||
hitEffectHPMin = addIntegerField(hitEffectPane, "HP bonus min: ", hitEffect.hp_boost_min, true, npc.writable, listener);
|
||||
hitEffectHPMax = addIntegerField(hitEffectPane, "HP bonus max: ", hitEffect.hp_boost_max, true, npc.writable, listener);
|
||||
hitEffectAPMin = addIntegerField(hitEffectPane, "AP bonus min: ", hitEffect.ap_boost_min, true, npc.writable, listener);
|
||||
hitEffectAPMax = addIntegerField(hitEffectPane, "AP bonus max: ", hitEffect.ap_boost_max, true, npc.writable, listener);
|
||||
|
||||
CollapsiblePanel hitSourceConditionsPane = new CollapsiblePanel("Actor Conditions applied to the source: ");
|
||||
hitSourceConditionsPane.setLayout(new JideBoxLayout(hitSourceConditionsPane, JideBoxLayout.PAGE_AXIS));
|
||||
hitSourceConditionsListModel = new SourceTimedConditionsListModel(hitEffect);
|
||||
hitSourceConditionsList = new JList(hitSourceConditionsListModel);
|
||||
hitSourceConditionsList.setCellRenderer(new TimedConditionsCellRenderer());
|
||||
hitSourceConditionsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
hitSourceConditionsPane.add(new JScrollPane(hitSourceConditionsList), JideBoxLayout.FIX);
|
||||
final JPanel sourceTimedConditionsEditorPane = new JPanel();
|
||||
final JButton createHitSourceCondition = new JButton(new ImageIcon(DefaultIcons.getCreateIcon()));
|
||||
final JButton deleteHitSourceCondition = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
hitSourceConditionsList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
selectedHitEffectSourceCondition = (NPC.TimedConditionEffect) hitSourceConditionsList.getSelectedValue();
|
||||
updateSourceTimedConditionEditorPane(sourceTimedConditionsEditorPane, selectedHitEffectSourceCondition, listener);
|
||||
}
|
||||
});
|
||||
if (npc.writable) {
|
||||
JPanel listButtonsPane = new JPanel();
|
||||
listButtonsPane.setLayout(new JideBoxLayout(listButtonsPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
createHitSourceCondition.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
NPC.TimedConditionEffect condition = new NPC.TimedConditionEffect();
|
||||
hitSourceConditionsListModel.addItem(condition);
|
||||
hitSourceConditionsList.setSelectedValue(condition, true);
|
||||
listener.valueChanged(hitSourceConditionsList, null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff.
|
||||
}
|
||||
});
|
||||
deleteHitSourceCondition.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedHitEffectSourceCondition != null) {
|
||||
hitSourceConditionsListModel.removeItem(selectedHitEffectSourceCondition);
|
||||
selectedHitEffectSourceCondition = null;
|
||||
hitSourceConditionsList.clearSelection();
|
||||
listener.valueChanged(hitSourceConditionsList, null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff.
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
listButtonsPane.add(createHitSourceCondition, JideBoxLayout.FIX);
|
||||
listButtonsPane.add(deleteHitSourceCondition, JideBoxLayout.FIX);
|
||||
listButtonsPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
hitSourceConditionsPane.add(listButtonsPane, JideBoxLayout.FIX);
|
||||
}
|
||||
sourceTimedConditionsEditorPane.setLayout(new JideBoxLayout(sourceTimedConditionsEditorPane, JideBoxLayout.PAGE_AXIS));
|
||||
hitSourceConditionsPane.add(sourceTimedConditionsEditorPane, JideBoxLayout.FIX);
|
||||
if (npc.hit_effect == null || npc.hit_effect.conditions_source == null || npc.hit_effect.conditions_source.isEmpty()) {
|
||||
hitSourceConditionsPane.collapse();
|
||||
}
|
||||
hitEffectPane.add(hitSourceConditionsPane, JideBoxLayout.FIX);
|
||||
final CollapsiblePanel hitTargetConditionsPane = new CollapsiblePanel("Actor Conditions applied to the target: ");
|
||||
hitTargetConditionsPane.setLayout(new JideBoxLayout(hitTargetConditionsPane, JideBoxLayout.PAGE_AXIS));
|
||||
hitTargetConditionsListModel = new TargetTimedConditionsListModel(hitEffect);
|
||||
hitTargetConditionsList = new JList(hitTargetConditionsListModel);
|
||||
hitTargetConditionsList.setCellRenderer(new TimedConditionsCellRenderer());
|
||||
hitTargetConditionsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
hitTargetConditionsPane.add(new JScrollPane(hitTargetConditionsList), JideBoxLayout.FIX);
|
||||
final JPanel targetTimedConditionsEditorPane = new JPanel();
|
||||
final JButton createHitTargetCondition = new JButton(new ImageIcon(DefaultIcons.getCreateIcon()));
|
||||
final JButton deleteHitTargetCondition = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
hitTargetConditionsList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
selectedHitEffectTargetCondition = (NPC.TimedConditionEffect) hitTargetConditionsList.getSelectedValue();
|
||||
updateTargetTimedConditionEditorPane(targetTimedConditionsEditorPane, selectedHitEffectTargetCondition, listener);
|
||||
}
|
||||
});
|
||||
if (npc.writable) {
|
||||
JPanel listButtonsPane = new JPanel();
|
||||
listButtonsPane.setLayout(new JideBoxLayout(listButtonsPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
createHitTargetCondition.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
NPC.TimedConditionEffect condition = new NPC.TimedConditionEffect();
|
||||
hitTargetConditionsListModel.addItem(condition);
|
||||
hitTargetConditionsList.setSelectedValue(condition, true);
|
||||
listener.valueChanged(hitTargetConditionsList, null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff.
|
||||
}
|
||||
});
|
||||
deleteHitTargetCondition.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (selectedHitEffectTargetCondition != null) {
|
||||
hitTargetConditionsListModel.removeItem(selectedHitEffectTargetCondition);
|
||||
selectedHitEffectTargetCondition = null;
|
||||
hitTargetConditionsList.clearSelection();
|
||||
listener.valueChanged(hitTargetConditionsList, null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff.
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
listButtonsPane.add(createHitTargetCondition, JideBoxLayout.FIX);
|
||||
listButtonsPane.add(deleteHitTargetCondition, JideBoxLayout.FIX);
|
||||
listButtonsPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
hitTargetConditionsPane.add(listButtonsPane, JideBoxLayout.FIX);
|
||||
}
|
||||
targetTimedConditionsEditorPane.setLayout(new JideBoxLayout(targetTimedConditionsEditorPane, JideBoxLayout.PAGE_AXIS));
|
||||
hitTargetConditionsPane.add(targetTimedConditionsEditorPane, JideBoxLayout.FIX);
|
||||
hitEffectPane.add(hitTargetConditionsPane, JideBoxLayout.FIX);
|
||||
if (npc.hit_effect == null || npc.hit_effect.conditions_target == null || npc.hit_effect.conditions_target.isEmpty()) {
|
||||
hitTargetConditionsPane.collapse();
|
||||
}
|
||||
combatTraitPane.add(hitEffectPane, JideBoxLayout.FIX);
|
||||
|
||||
pane.add(combatTraitPane, JideBoxLayout.FIX);
|
||||
}
|
||||
|
||||
public void updateSourceTimedConditionEditorPane(JPanel pane, NPC.TimedConditionEffect condition, FieldUpdateListener listener) {
|
||||
pane.removeAll();
|
||||
if (sourceConditionBox != null) {
|
||||
removeElementListener(sourceConditionBox);
|
||||
}
|
||||
|
||||
boolean writable = ((NPC)target).writable;
|
||||
Project proj = ((NPC)target).getProject();
|
||||
|
||||
sourceConditionBox = addActorConditionBox(pane, proj, "Actor Condition: ", condition.condition, writable, listener);
|
||||
sourceConditionMagnitude = addIntegerField(pane, "Magnitude: ", condition.magnitude, false, writable, listener);
|
||||
sourceConditionDuration = addIntegerField(pane, "Duration: ", condition.duration, false, writable, listener);
|
||||
sourceConditionChance = addDoubleField(pane, "Chance: ", condition.chance, writable, listener);
|
||||
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
|
||||
public void updateTargetTimedConditionEditorPane(JPanel pane, NPC.TimedConditionEffect condition, FieldUpdateListener listener) {
|
||||
pane.removeAll();
|
||||
if (targetConditionBox != null) {
|
||||
removeElementListener(targetConditionBox);
|
||||
}
|
||||
|
||||
boolean writable = ((NPC)target).writable;
|
||||
Project proj = ((NPC)target).getProject();
|
||||
|
||||
targetConditionBox = addActorConditionBox(pane, proj, "Actor Condition: ", condition.condition, writable, listener);
|
||||
targetConditionMagnitude = addIntegerField(pane, "Magnitude: ", condition.magnitude, false, writable, listener);
|
||||
targetConditionDuration = addIntegerField(pane, "Duration: ", condition.duration, false, writable, listener);
|
||||
targetConditionChance = addDoubleField(pane, "Chance: ", condition.chance, writable, listener);
|
||||
|
||||
pane.revalidate();
|
||||
pane.repaint();
|
||||
}
|
||||
|
||||
public static class TargetTimedConditionsListModel implements ListModel {
|
||||
|
||||
NPC.HitEffect source;
|
||||
|
||||
public TargetTimedConditionsListModel(NPC.HitEffect effect) {
|
||||
this.source = effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
if (source.conditions_target == null) return 0;
|
||||
return source.conditions_target.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
if (source.conditions_target == null) return null;
|
||||
return source.conditions_target.get(index);
|
||||
}
|
||||
|
||||
public void addItem(NPC.TimedConditionEffect item) {
|
||||
if (source.conditions_target == null) {
|
||||
source.conditions_target = new ArrayList<NPC.TimedConditionEffect>();
|
||||
}
|
||||
source.conditions_target.add(item);
|
||||
int index = source.conditions_target.indexOf(item);
|
||||
for (ListDataListener l : listeners) {
|
||||
l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
public void removeItem(NPC.TimedConditionEffect item) {
|
||||
int index = source.conditions_target.indexOf(item);
|
||||
source.conditions_target.remove(item);
|
||||
if (source.conditions_target.isEmpty()) {
|
||||
source.conditions_target = null;
|
||||
}
|
||||
for (ListDataListener l : listeners) {
|
||||
l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
public void itemChanged(NPC.TimedConditionEffect item) {
|
||||
int index = source.conditions_target.indexOf(item);
|
||||
for (ListDataListener l : listeners) {
|
||||
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SourceTimedConditionsListModel implements ListModel {
|
||||
|
||||
NPC.HitEffect source;
|
||||
|
||||
public SourceTimedConditionsListModel(NPC.HitEffect effect) {
|
||||
this.source = effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
if (source.conditions_source == null) return 0;
|
||||
return source.conditions_source.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
if (source.conditions_source == null) return null;
|
||||
return source.conditions_source.get(index);
|
||||
}
|
||||
|
||||
public void addItem(NPC.TimedConditionEffect item) {
|
||||
if (source.conditions_source == null) {
|
||||
source.conditions_source = new ArrayList<NPC.TimedConditionEffect>();
|
||||
}
|
||||
source.conditions_source.add(item);
|
||||
int index = source.conditions_source.indexOf(item);
|
||||
for (ListDataListener l : listeners) {
|
||||
l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
public void removeItem(NPC.TimedConditionEffect item) {
|
||||
int index = source.conditions_source.indexOf(item);
|
||||
source.conditions_source.remove(item);
|
||||
if (source.conditions_source.isEmpty()) {
|
||||
source.conditions_source = null;
|
||||
}
|
||||
for (ListDataListener l : listeners) {
|
||||
l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
public void itemChanged(NPC.TimedConditionEffect item) {
|
||||
int index = source.conditions_source.indexOf(item);
|
||||
for (ListDataListener l : listeners) {
|
||||
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index));
|
||||
}
|
||||
}
|
||||
|
||||
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TimedConditionsCellRenderer extends DefaultListCellRenderer {
|
||||
private static final long serialVersionUID = 7987880146189575234L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (c instanceof JLabel) {
|
||||
JLabel label = ((JLabel)c);
|
||||
NPC.TimedConditionEffect effect = (NPC.TimedConditionEffect) value;
|
||||
|
||||
if (effect.condition != null) {
|
||||
label.setIcon(new ImageIcon(effect.condition.getIcon()));
|
||||
label.setText(effect.chance+"% chances to give "+effect.duration+" rounds of "+effect.condition.getDesc()+" x"+effect.magnitude);
|
||||
} else {
|
||||
label.setText("New, undefined actor condition effect.");
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isNull(NPC.HitEffect effect) {
|
||||
if (effect.ap_boost_min != null) return false;
|
||||
if (effect.ap_boost_max != null) return false;
|
||||
if (effect.hp_boost_min != null) return false;
|
||||
if (effect.hp_boost_max != null) return false;
|
||||
if (effect.conditions_source != null) return false;
|
||||
if (effect.conditions_target != null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public class NPCFieldUpdate implements FieldUpdateListener {
|
||||
|
||||
@Override
|
||||
public void valueChanged(JComponent source, Object value) {
|
||||
NPC npc = (NPC)target;
|
||||
boolean updateHit = false;
|
||||
if (source == idField) {
|
||||
npc.id = (String) value;
|
||||
NPCEditor.this.name = npc.getDesc();
|
||||
npc.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(NPCEditor.this);
|
||||
} else if (source == nameField) {
|
||||
npc.name = (String) value;
|
||||
NPCEditor.this.name = npc.getDesc();
|
||||
npc.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(NPCEditor.this);
|
||||
} else if (source == npcIcon) {
|
||||
npc.icon_id = (String) value;
|
||||
npc.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
NPCEditor.this.icon = new ImageIcon(npc.getProject().getIcon((String) value));
|
||||
ATContentStudio.frame.editorChanged(NPCEditor.this);
|
||||
npcIcon.setIcon(new ImageIcon(npc.getProject().getImage((String) value)));
|
||||
npcIcon.revalidate();
|
||||
npcIcon.repaint();
|
||||
} else if (source == spawnGroupField) {
|
||||
npc.spawngroup_id = (String) value;
|
||||
} else if (source == dialogueBox) {
|
||||
if (npc.dialogue != null) {
|
||||
npc.dialogue.removeBacklink(npc);
|
||||
}
|
||||
npc.dialogue = (Dialogue) value;
|
||||
if (npc.dialogue != null) {
|
||||
npc.dialogue_id =npc.dialogue.id;
|
||||
npc.dialogue.addBacklink(npc);
|
||||
} else {
|
||||
npc.dialogue_id = null;
|
||||
}
|
||||
} else if (source == droplistBox) {
|
||||
if (npc.droplist != null) {
|
||||
npc.droplist.removeBacklink(npc);
|
||||
}
|
||||
npc.droplist = (Droplist) value;
|
||||
if (npc.droplist != null) {
|
||||
npc.droplist_id = npc.droplist.id;
|
||||
npc.droplist.addBacklink(npc);
|
||||
} else {
|
||||
npc.droplist_id = null;
|
||||
}
|
||||
} else if (source == monsterClassBox) {
|
||||
npc.monster_class = (NPC.MonsterClass) value;
|
||||
} else if (source == uniqueBox) {
|
||||
npc.unique = (Integer) value;
|
||||
} else if (source == moveTypeBox) {
|
||||
npc.movement_type = (NPC.MovementType) value;
|
||||
} else if (source == maxHP) {
|
||||
npc.max_hp = (Integer) value;
|
||||
} else if (source == maxAP) {
|
||||
npc.max_ap = (Integer) value;
|
||||
} else if (source == moveCost) {
|
||||
npc.move_cost = (Integer) value;
|
||||
} else if (source == atkDmgMin) {
|
||||
npc.attack_damage_min = (Integer) value;
|
||||
} else if (source == atkDmgMax) {
|
||||
npc.attack_damage_max = (Integer) value;
|
||||
} else if (source == atkCost) {
|
||||
npc.attack_cost = (Integer) value;
|
||||
} else if (source == atkChance) {
|
||||
npc.attack_chance = (Integer) value;
|
||||
} else if (source == critSkill) {
|
||||
npc.critical_skill = (Integer) value;
|
||||
} else if (source == critMult) {
|
||||
npc.critical_multiplier = (Double) value;
|
||||
} else if (source == blockChance) {
|
||||
npc.block_chance = (Integer) value;
|
||||
} else if (source == dmgRes) {
|
||||
npc.damage_resistance = (Integer) value;
|
||||
} else if (source == hitEffectHPMin) {
|
||||
hitEffect.hp_boost_min = (Integer) value;
|
||||
updateHit = true;
|
||||
} else if (source == hitEffectHPMax) {
|
||||
hitEffect.hp_boost_max = (Integer) value;
|
||||
updateHit = true;
|
||||
} else if (source == hitEffectAPMin) {
|
||||
hitEffect.ap_boost_min = (Integer) value;
|
||||
updateHit = true;
|
||||
} else if (source == hitEffectAPMax) {
|
||||
hitEffect.ap_boost_max = (Integer) value;
|
||||
updateHit = true;
|
||||
} else if (source == hitSourceConditionsList) {
|
||||
//TODO
|
||||
} else if (source == sourceConditionBox) {
|
||||
if (selectedHitEffectSourceCondition.condition != null) {
|
||||
selectedHitEffectSourceCondition.condition.removeBacklink(npc);
|
||||
}
|
||||
selectedHitEffectSourceCondition.condition = (ActorCondition) value;
|
||||
if (selectedHitEffectSourceCondition.condition != null) {
|
||||
selectedHitEffectSourceCondition.condition.addBacklink(npc);
|
||||
selectedHitEffectSourceCondition.condition_id = selectedHitEffectSourceCondition.condition.id;
|
||||
} else {
|
||||
selectedHitEffectSourceCondition.condition_id = null;
|
||||
}
|
||||
hitSourceConditionsListModel.itemChanged(selectedHitEffectSourceCondition);
|
||||
} else if (source == sourceConditionMagnitude) {
|
||||
selectedHitEffectSourceCondition.magnitude = (Integer) value;
|
||||
hitSourceConditionsListModel.itemChanged(selectedHitEffectSourceCondition);
|
||||
} else if (source == sourceConditionDuration) {
|
||||
selectedHitEffectSourceCondition.duration = (Integer) value;
|
||||
hitSourceConditionsListModel.itemChanged(selectedHitEffectSourceCondition);
|
||||
} else if (source == sourceConditionChance) {
|
||||
selectedHitEffectSourceCondition.chance = (Double) value;
|
||||
hitSourceConditionsListModel.itemChanged(selectedHitEffectSourceCondition);
|
||||
} else if (source == hitTargetConditionsList) {
|
||||
//TODO
|
||||
} else if (source == targetConditionBox) {
|
||||
if (selectedHitEffectTargetCondition.condition != null) {
|
||||
selectedHitEffectTargetCondition.condition.removeBacklink(npc);
|
||||
}
|
||||
selectedHitEffectTargetCondition.condition = (ActorCondition) value;
|
||||
if (selectedHitEffectTargetCondition.condition != null) {
|
||||
selectedHitEffectTargetCondition.condition_id = selectedHitEffectTargetCondition.condition.id;
|
||||
selectedHitEffectTargetCondition.condition.addBacklink(npc);
|
||||
} else {
|
||||
selectedHitEffectTargetCondition.condition_id = null;
|
||||
}
|
||||
hitTargetConditionsListModel.itemChanged(selectedHitEffectTargetCondition);
|
||||
} else if (source == targetConditionMagnitude) {
|
||||
selectedHitEffectTargetCondition.magnitude = (Integer) value;
|
||||
hitTargetConditionsListModel.itemChanged(selectedHitEffectTargetCondition);
|
||||
} else if (source == targetConditionDuration) {
|
||||
selectedHitEffectTargetCondition.duration = (Integer) value;
|
||||
hitTargetConditionsListModel.itemChanged(selectedHitEffectTargetCondition);
|
||||
} else if (source == targetConditionChance) {
|
||||
selectedHitEffectTargetCondition.chance = (Double) value;
|
||||
hitTargetConditionsListModel.itemChanged(selectedHitEffectTargetCondition);
|
||||
}
|
||||
|
||||
if (updateHit) {
|
||||
if (isNull(hitEffect)) {
|
||||
npc.hit_effect = null;
|
||||
} else {
|
||||
npc.hit_effect = hitEffect;
|
||||
}
|
||||
}
|
||||
|
||||
experienceField.setValue(npc.getMonsterExperience());
|
||||
|
||||
if (npc.state != GameDataElement.State.modified) {
|
||||
npc.state = GameDataElement.State.modified;
|
||||
NPCEditor.this.name = npc.getDesc();
|
||||
npc.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(NPCEditor.this);
|
||||
}
|
||||
updateJsonViewText(npc.toJsonString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.event.TableModelEvent;
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
|
||||
import com.gpl.rpg.atcontentstudio.ui.IntegerBasedCheckBox;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
public class QuestEditor extends JSONElementEditor {
|
||||
|
||||
private static final long serialVersionUID = 5701667955210615366L;
|
||||
|
||||
private static final Integer one = 1;
|
||||
|
||||
private static final String form_view_id = "Form";
|
||||
private static final String json_view_id = "JSON";
|
||||
|
||||
private JTextField idField;
|
||||
private JTextField nameField;
|
||||
private IntegerBasedCheckBox visibleBox;
|
||||
private QuestStageTableModel stagesModel;
|
||||
private JTable stagesTable;
|
||||
private JButton createStage;
|
||||
private JButton deleteStage;
|
||||
private JButton moveUp;
|
||||
private JButton moveDown;
|
||||
|
||||
|
||||
public QuestEditor(Quest quest) {
|
||||
super(quest, quest.getDesc(), quest.getIcon());
|
||||
addEditorTab(form_view_id, getFormView());
|
||||
addEditorTab(json_view_id, getJSONView());
|
||||
}
|
||||
|
||||
public void insertFormViewDataField(JPanel pane) {
|
||||
final Quest quest = ((Quest)target);
|
||||
|
||||
final FieldUpdateListener listener = new QuestFieldUpdater();
|
||||
|
||||
createButtonPane(pane, quest.getProject(), quest, Quest.class, quest.getImage(), null, listener);
|
||||
|
||||
|
||||
addTextField(pane, "Internal ID: ", quest.id, quest.writable, listener);
|
||||
addTextField(pane, "Quest Name: ", quest.name, quest.writable, listener);
|
||||
addIntegerBasedCheckBox(pane, "Visible in quest log", quest.visible_in_log, quest.writable, listener);
|
||||
|
||||
JPanel stagesPane = new JPanel();
|
||||
stagesPane.setLayout(new JideBoxLayout(stagesPane, JideBoxLayout.PAGE_AXIS, 6));
|
||||
stagesModel = new QuestStageTableModel(quest, listener);
|
||||
stagesTable = new JTable(stagesModel);
|
||||
stagesTable.getColumnModel().getColumn(0).setMinWidth(100);
|
||||
stagesTable.getColumnModel().getColumn(0).setMaxWidth(100);
|
||||
// stagesTable.getColumnModel().getColumn(1).setPreferredWidth(40);
|
||||
// stagesTable.getColumnModel().getColumn(1).setPreferredWidth(40);
|
||||
stagesTable.getColumnModel().getColumn(2).setMinWidth(100);
|
||||
stagesTable.getColumnModel().getColumn(2).setMaxWidth(100);
|
||||
stagesTable.getColumnModel().getColumn(3).setMinWidth(130);
|
||||
stagesTable.getColumnModel().getColumn(3).setMaxWidth(130);
|
||||
stagesTable.setCellSelectionEnabled(true);
|
||||
stagesPane.add(new JScrollPane(stagesTable), BorderLayout.CENTER);
|
||||
if (quest.writable) {
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new JideBoxLayout(buttonPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
createStage = new JButton(new ImageIcon(DefaultIcons.getCreateIcon()));
|
||||
deleteStage = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
|
||||
moveUp = new JButton(new ImageIcon(DefaultIcons.getArrowUpIcon()));
|
||||
moveDown = new JButton(new ImageIcon(DefaultIcons.getArrowDownIcon()));
|
||||
buttonPane.add(createStage, JideBoxLayout.FIX);
|
||||
buttonPane.add(deleteStage, JideBoxLayout.FIX);
|
||||
buttonPane.add(moveUp, JideBoxLayout.FIX);
|
||||
buttonPane.add(moveDown, JideBoxLayout.FIX);
|
||||
buttonPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
deleteStage.setEnabled(false);
|
||||
moveUp.setEnabled(false);
|
||||
moveDown.setEnabled(false);
|
||||
|
||||
stagesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
updateTableButtons();
|
||||
}
|
||||
});
|
||||
|
||||
createStage.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
stagesModel.createStage();
|
||||
listener.valueChanged(stagesTable, null);
|
||||
stagesTable.revalidate();
|
||||
stagesTable.repaint();
|
||||
}
|
||||
});
|
||||
deleteStage.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
stagesModel.deleteRow(stagesTable.getSelectedRow());
|
||||
listener.valueChanged(stagesTable, null);
|
||||
stagesTable.revalidate();
|
||||
stagesTable.repaint();
|
||||
updateTableButtons();
|
||||
}
|
||||
});
|
||||
moveUp.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
stagesModel.moveRow(stagesTable.getSelectedRow(), true);
|
||||
listener.valueChanged(stagesTable, null);
|
||||
stagesTable.setRowSelectionInterval(stagesTable.getSelectedRow() - 1, stagesTable.getSelectedRow() - 1);
|
||||
updateTableButtons();
|
||||
}
|
||||
});
|
||||
moveDown.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
stagesModel.moveRow(stagesTable.getSelectedRow(), false);
|
||||
listener.valueChanged(stagesTable, null);
|
||||
stagesTable.setRowSelectionInterval(stagesTable.getSelectedRow() + 1, stagesTable.getSelectedRow() + 1);
|
||||
updateTableButtons();
|
||||
}
|
||||
});
|
||||
stagesPane.add(buttonPane, JideBoxLayout.FIX);
|
||||
}
|
||||
pane.add(stagesPane, JideBoxLayout.FIX);
|
||||
|
||||
}
|
||||
|
||||
public void updateTableButtons() {
|
||||
|
||||
if (stagesTable.getSelectedRow() >= 0 && stagesTable.getSelectedRow() < stagesModel.getRowCount()) {
|
||||
deleteStage.setEnabled(true);
|
||||
if (stagesTable.getSelectedRow() == 0) {
|
||||
moveUp.setEnabled(false);
|
||||
} else {
|
||||
moveUp.setEnabled(true);
|
||||
}
|
||||
if (stagesTable.getSelectedRow() >= stagesModel.getRowCount() - 1) {
|
||||
moveDown.setEnabled(false);
|
||||
} else {
|
||||
moveDown.setEnabled(true);
|
||||
}
|
||||
} else {
|
||||
deleteStage.setEnabled(false);
|
||||
moveUp.setEnabled(false);
|
||||
moveDown.setEnabled(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class QuestStageTableModel implements TableModel {
|
||||
|
||||
Quest quest;
|
||||
FieldUpdateListener listener;
|
||||
|
||||
public QuestStageTableModel(Quest q, FieldUpdateListener listener) {
|
||||
this.quest = q;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
if (quest.stages == null) return 0;
|
||||
return quest.stages.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
return "Progress ID";
|
||||
case 1:
|
||||
return "Log text";
|
||||
case 2:
|
||||
return "XP reward";
|
||||
case 3:
|
||||
return "Finishes quest";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
return Integer.class;
|
||||
case 1:
|
||||
return String.class;
|
||||
case 2:
|
||||
return Integer.class;
|
||||
case 3:
|
||||
return Boolean.class;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return quest.writable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
return quest.stages.get(rowIndex).progress;
|
||||
case 1:
|
||||
return quest.stages.get(rowIndex).log_text;
|
||||
case 2:
|
||||
return quest.stages.get(rowIndex).exp_reward;
|
||||
case 3:
|
||||
return quest.stages.get(rowIndex).finishes_quest != null && quest.stages.get(rowIndex).finishes_quest.equals(1);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
quest.stages.get(rowIndex).progress = (Integer)aValue;
|
||||
break;
|
||||
case 1:
|
||||
quest.stages.get(rowIndex).log_text = (String)aValue;
|
||||
break;
|
||||
case 2:
|
||||
quest.stages.get(rowIndex).exp_reward = (Integer)aValue;
|
||||
break;
|
||||
case 3:
|
||||
quest.stages.get(rowIndex).finishes_quest = ((Boolean)aValue) ? one : null;
|
||||
break;
|
||||
}
|
||||
listener.valueChanged(stagesTable, aValue);
|
||||
}
|
||||
|
||||
public void createStage() {
|
||||
quest.stages.add(new Quest.QuestStage());
|
||||
for (TableModelListener l: listeners) {
|
||||
l.tableChanged(new TableModelEvent(this, quest.stages.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
public void moveRow(int rowNumber, boolean moveUp) {
|
||||
Quest.QuestStage stage = quest.stages.get(rowNumber);
|
||||
quest.stages.remove(stage);
|
||||
quest.stages.add(rowNumber + (moveUp ? -1 : 1), stage);
|
||||
for (TableModelListener l : listeners) {
|
||||
l.tableChanged(new TableModelEvent(this, rowNumber + (moveUp ? -1 : 0), rowNumber + (moveUp ? 0 : 1)));
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteRow(int rowNumber) {
|
||||
quest.stages.remove(rowNumber);
|
||||
for (TableModelListener l: listeners) {
|
||||
l.tableChanged(new TableModelEvent(this, rowNumber, quest.stages.size()));
|
||||
}
|
||||
}
|
||||
|
||||
public List<TableModelListener> listeners = new ArrayList<TableModelListener>();
|
||||
|
||||
@Override
|
||||
public void addTableModelListener(TableModelListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTableModelListener(TableModelListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class QuestFieldUpdater implements FieldUpdateListener {
|
||||
|
||||
@Override
|
||||
public void valueChanged(JComponent source, Object value) {
|
||||
Quest quest = (Quest) target;
|
||||
if (source == idField) {
|
||||
quest.id = (String) value;
|
||||
QuestEditor.this.name = quest.getDesc();
|
||||
quest.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(QuestEditor.this);
|
||||
} else if (source == nameField) {
|
||||
quest.name = (String) value;
|
||||
QuestEditor.this.name = quest.getDesc();
|
||||
quest.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(QuestEditor.this);
|
||||
} else if (source == visibleBox) {
|
||||
quest.visible_in_log = (Integer) value;
|
||||
}
|
||||
|
||||
|
||||
if (quest.state != GameDataElement.State.modified) {
|
||||
quest.state = GameDataElement.State.modified;
|
||||
QuestEditor.this.name = quest.getDesc();
|
||||
quest.childrenChanged(new ArrayList<ProjectTreeNode>());
|
||||
ATContentStudio.frame.editorChanged(QuestEditor.this);
|
||||
}
|
||||
updateJsonViewText(quest.toJsonString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors.dialoguetree;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import prefuse.Display;
|
||||
import prefuse.Visualization;
|
||||
import prefuse.action.ActionList;
|
||||
import prefuse.action.RepaintAction;
|
||||
import prefuse.action.assignment.ColorAction;
|
||||
import prefuse.action.assignment.FontAction;
|
||||
import prefuse.action.assignment.StrokeAction;
|
||||
import prefuse.action.layout.Layout;
|
||||
import prefuse.action.layout.graph.NodeLinkTreeLayout;
|
||||
import prefuse.activity.Activity;
|
||||
import prefuse.controls.ControlAdapter;
|
||||
import prefuse.controls.PanControl;
|
||||
import prefuse.controls.WheelZoomControl;
|
||||
import prefuse.controls.ZoomControl;
|
||||
import prefuse.data.Edge;
|
||||
import prefuse.data.Graph;
|
||||
import prefuse.data.Node;
|
||||
import prefuse.data.Schema;
|
||||
import prefuse.render.DefaultRendererFactory;
|
||||
import prefuse.render.EdgeRenderer;
|
||||
import prefuse.render.LabelRenderer;
|
||||
import prefuse.util.ColorLib;
|
||||
import prefuse.util.GraphicsLib;
|
||||
import prefuse.util.PrefuseLib;
|
||||
import prefuse.visual.DecoratorItem;
|
||||
import prefuse.visual.EdgeItem;
|
||||
import prefuse.visual.VisualItem;
|
||||
import prefuse.visual.expression.InGroupPredicate;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
|
||||
public class DialogueGraphView extends Display {
|
||||
|
||||
private static final long serialVersionUID = -6431503090775579301L;
|
||||
|
||||
public static final String GRAPH = "graph";
|
||||
public static final String NODES = "graph.nodes";
|
||||
public static final String EDGES = "graph.edges";
|
||||
public static final String EDGES_LABELS = "edgesLabels";
|
||||
public static final String AGGR = "aggregates";
|
||||
|
||||
public static final String LABEL = "label";
|
||||
public static final String ICON = "icon";
|
||||
public static final String TARGET = "target";
|
||||
public static final String REPLY = "reply";
|
||||
public static final String HAS_REQS = "has_reqs";
|
||||
|
||||
private static final Schema DECORATOR_SCHEMA = PrefuseLib.getVisualItemSchema();
|
||||
|
||||
private Dialogue dialogue;
|
||||
private Image npcIcon;
|
||||
private Graph graph;
|
||||
|
||||
private Map<Dialogue, Node> cells = new HashMap<Dialogue, Node>();
|
||||
|
||||
public DialogueGraphView(Dialogue dialogue, NPC npc) {
|
||||
super(new Visualization());
|
||||
this.dialogue = dialogue;
|
||||
if (npc != null) {
|
||||
npcIcon = npc.getIcon();
|
||||
} else {
|
||||
npcIcon = DefaultIcons.getNPCIcon();
|
||||
}
|
||||
loadGraph();
|
||||
|
||||
// add visual data groups
|
||||
m_vis.addGraph(GRAPH, graph);
|
||||
m_vis.setInteractive(EDGES, null, false);
|
||||
|
||||
LabelRenderer nodeR = new MyLabelRenderer(LABEL);
|
||||
nodeR.setHorizontalTextAlignment(prefuse.Constants.LEFT);
|
||||
|
||||
EdgeRenderer edgeR = new EdgeRenderer(prefuse.Constants.EDGE_TYPE_LINE, prefuse.Constants.EDGE_ARROW_FORWARD);
|
||||
// edgeR.setEdgeType(prefuse.Constants.EDGE_TYPE_CURVE);
|
||||
|
||||
LabelRenderer edgeLabelR = new LabelRenderer(LABEL);
|
||||
edgeLabelR.setRenderType(LabelRenderer.RENDER_TYPE_DRAW);
|
||||
|
||||
DefaultRendererFactory drf = new DefaultRendererFactory();
|
||||
drf.setDefaultRenderer(nodeR);
|
||||
drf.setDefaultEdgeRenderer(edgeR);
|
||||
drf.add(new InGroupPredicate(EDGES_LABELS), edgeLabelR);
|
||||
m_vis.setRendererFactory(drf);
|
||||
DECORATOR_SCHEMA.setDefault(VisualItem.FILLCOLOR, ColorLib.gray(255));
|
||||
DECORATOR_SCHEMA.setDefault(VisualItem.STROKECOLOR, ColorLib.rgba(0, 0, 0, 0));
|
||||
DECORATOR_SCHEMA.setDefault(VisualItem.TEXTCOLOR, ColorLib.gray(0));
|
||||
m_vis.addDecorators(EDGES_LABELS, EDGES, DECORATOR_SCHEMA);
|
||||
|
||||
// set up the visual operators
|
||||
// first set up all the color actions
|
||||
ColorAction nStrokeColor = new ColorAction(NODES, VisualItem.STROKECOLOR);
|
||||
nStrokeColor.setDefaultColor(ColorLib.gray(100));
|
||||
nStrokeColor.add("_hover", ColorLib.rgb(255,100,100));
|
||||
StrokeAction nStroke = new EdgesStrokeAction(NODES);
|
||||
|
||||
ColorAction nFill = new NPCPhraseColorAction(NODES, VisualItem.FILLCOLOR);
|
||||
|
||||
ColorAction eEdges = new ConnectedEdgeColorAction(EDGES, VisualItem.STROKECOLOR);
|
||||
ColorAction eArrows = new ConnectedEdgeColorAction(EDGES, VisualItem.FILLCOLOR);
|
||||
ColorAction eEdgesLabels = new ConnectedEdgeColorAction(EDGES_LABELS, VisualItem.TEXTCOLOR);
|
||||
|
||||
StrokeAction eStroke = new EdgesStrokeAction(EDGES);
|
||||
|
||||
FontAction aFont = new FontAction();
|
||||
ColorAction aFontColor = new ColorAction(NODES, VisualItem.TEXTCOLOR);
|
||||
aFontColor.setDefaultColor(ColorLib.rgb(0, 0, 0));
|
||||
|
||||
// bundle the color actions
|
||||
ActionList colors = new ActionList(Activity.INFINITY);
|
||||
colors.add(nStrokeColor);
|
||||
colors.add(nFill);
|
||||
colors.add(nStroke);
|
||||
colors.add(eEdges);
|
||||
colors.add(eArrows);
|
||||
colors.add(eEdgesLabels);
|
||||
colors.add(eStroke);
|
||||
colors.add(aFont);
|
||||
colors.add(aFontColor);
|
||||
colors.add(new RepaintAction());
|
||||
m_vis.putAction("colors", colors);
|
||||
|
||||
// now create the main layout routine
|
||||
ActionList layout = new ActionList();//Activity.INFINITY);
|
||||
NodeLinkTreeLayout treeLayout = new NodeLinkTreeLayout(GRAPH, prefuse.Constants.ORIENT_LEFT_RIGHT, 120, 40, 40);
|
||||
treeLayout.setLayoutAnchor(new Point2D.Double(25,300));
|
||||
layout.add(treeLayout);
|
||||
layout.add(new EdgesLabelDecoratorLayout(EDGES_LABELS));
|
||||
layout.add(new RepaintAction());
|
||||
m_vis.putAction("layout", layout);
|
||||
|
||||
// set up the display
|
||||
setSize(500,500);
|
||||
pan(250, 250);
|
||||
setHighQuality(true);
|
||||
addControlListener(new DoubleClickControl());
|
||||
addControlListener(new WheelZoomControl());
|
||||
addControlListener(new ZoomControl());
|
||||
addControlListener(new PanControl());
|
||||
|
||||
// set things running
|
||||
m_vis.run("colors");
|
||||
m_vis.run("layout");
|
||||
}
|
||||
|
||||
public void loadGraph() {
|
||||
graph = new Graph(true);
|
||||
graph.addColumn(LABEL, String.class, "");
|
||||
graph.addColumn(ICON, Image.class, DefaultIcons.getNullifyIcon());
|
||||
graph.addColumn(TARGET, GameDataElement.class, null);
|
||||
graph.addColumn(REPLY, Dialogue.Reply.class, null);
|
||||
graph.addColumn(HAS_REQS, boolean.class, false);
|
||||
addDialogue(dialogue, npcIcon);
|
||||
}
|
||||
|
||||
public Node addDialogue(Dialogue dialogue, Image npcIcon) {
|
||||
if (cells.get(dialogue) == null) {
|
||||
if (dialogue.switch_to_npc != null) {
|
||||
npcIcon = dialogue.switch_to_npc.getIcon();
|
||||
}
|
||||
Node dNode = graph.addNode();
|
||||
cells.put(dialogue, dNode);
|
||||
dNode.setString(LABEL, dialogue.message != null ? dialogue.message : "[Selector]");
|
||||
dNode.set(ICON, npcIcon);
|
||||
dNode.set(TARGET, dialogue);
|
||||
if (dialogue.replies != null) {
|
||||
Node rNode;
|
||||
int i = 1;
|
||||
for (Dialogue.Reply r : dialogue.replies) {
|
||||
rNode = addReply(dialogue, r, npcIcon);
|
||||
Edge e = graph.addEdge(dNode, rNode);
|
||||
e.setString(LABEL, "#"+i++);
|
||||
e.setBoolean(HAS_REQS, r.requirements != null && !r.requirements.isEmpty());
|
||||
}
|
||||
}
|
||||
}
|
||||
return cells.get(dialogue);
|
||||
}
|
||||
|
||||
public Node addReply(Dialogue d, Dialogue.Reply r, Image npcIcon) {
|
||||
Node rNode;
|
||||
if (r.text != null && !r.text.equals(Dialogue.Reply.GO_NEXT_TEXT)) {
|
||||
//Normal reply...
|
||||
rNode = graph.addNode();
|
||||
rNode.setString(LABEL, r.text);
|
||||
rNode.set(ICON, DefaultIcons.getHeroIcon());
|
||||
rNode.set(TARGET, d);
|
||||
rNode.set(REPLY, r);
|
||||
if (r.next_phrase != null) {
|
||||
//...that leads to another phrase
|
||||
Node dNode = addDialogue(r.next_phrase, npcIcon);
|
||||
graph.addEdge(rNode, dNode);
|
||||
} else if (Dialogue.Reply.KEY_PHRASE_ID.contains(r.next_phrase_id)) {
|
||||
//...that leads to a key phrase
|
||||
Node kNode = addKeyPhraseNode(d, r.next_phrase_id);
|
||||
kNode.set(REPLY, r);
|
||||
graph.addEdge(rNode, kNode);
|
||||
}
|
||||
} else if (r.next_phrase != null) {
|
||||
//Go directly to next phrase
|
||||
rNode = addDialogue(r.next_phrase, npcIcon);
|
||||
} else if (Dialogue.Reply.KEY_PHRASE_ID.contains(r.next_phrase_id)) {
|
||||
//Go directly to key phrase
|
||||
rNode = addKeyPhraseNode(d, r.next_phrase_id);
|
||||
rNode.set(REPLY, r);
|
||||
} else {
|
||||
//Incomplete.
|
||||
rNode = graph.addNode();
|
||||
rNode.setString(LABEL, "[Incomplete reply]");
|
||||
rNode.set(ICON, DefaultIcons.getNullifyIcon());
|
||||
}
|
||||
return rNode;
|
||||
}
|
||||
|
||||
public Node addKeyPhraseNode(Dialogue d, String key) {
|
||||
Node kNode = graph.addNode();
|
||||
if (key.equals(Dialogue.Reply.EXIT_PHRASE_ID)) {
|
||||
kNode.setString(LABEL, "[Ends dialogue]");
|
||||
kNode.set(ICON, DefaultIcons.getNullifyIcon());
|
||||
} else if (key.equals(Dialogue.Reply.FIGHT_PHRASE_ID)) {
|
||||
kNode.setString(LABEL, "[Starts fight]");
|
||||
kNode.set(ICON, DefaultIcons.getCombatIcon());
|
||||
} else if (key.equals(Dialogue.Reply.REMOVE_PHRASE_ID)) {
|
||||
kNode.setString(LABEL, "[NPC vanishes]");
|
||||
kNode.set(ICON, DefaultIcons.getNPCCloseIcon());
|
||||
} else if (key.equals(Dialogue.Reply.SHOP_PHRASE_ID)) {
|
||||
kNode.setString(LABEL, "[Start trading]");
|
||||
kNode.set(ICON, DefaultIcons.getGoldIcon());
|
||||
} else {
|
||||
//Should never reach, unless new key phrase ID are added to the model, but not here...
|
||||
kNode.setString(LABEL, "[WTF !!]"+key);
|
||||
}
|
||||
kNode.set(TARGET, d);
|
||||
return kNode;
|
||||
}
|
||||
|
||||
class MyLabelRenderer extends LabelRenderer {
|
||||
public MyLabelRenderer(String label) {
|
||||
super(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Image getImage(VisualItem item) {
|
||||
return (Image) item.get(ICON);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getText(VisualItem item) {
|
||||
return wordWrap(super.getText(item), 40);
|
||||
}
|
||||
|
||||
public String wordWrap(String in, int length) {
|
||||
final String newline = "\n";
|
||||
//:: Trim
|
||||
while(in.length() > 0 && (in.charAt(0) == '\t' || in.charAt(0) == ' ')) in = in.substring(1);
|
||||
//:: If Small Enough Already, Return Original
|
||||
if(in.length() < length) return in;
|
||||
//:: If Next length Contains Newline, Split There
|
||||
if(in.substring(0, length).contains(newline)) return in.substring(0, in.indexOf(newline)).trim() + newline + wordWrap(in.substring(in.indexOf("\n") + 1), length);
|
||||
//:: Otherwise, Split Along Nearest Previous Space/Tab/Dash
|
||||
int spaceIndex = Math.max(Math.max( in.lastIndexOf(" ", length), in.lastIndexOf("\t", length)), in.lastIndexOf("-", length));
|
||||
//:: If No Nearest Space, Split At length
|
||||
if(spaceIndex == -1) spaceIndex = length;
|
||||
//:: Split
|
||||
return in.substring(0, spaceIndex).trim() + newline + wordWrap(in.substring(spaceIndex), length);
|
||||
}
|
||||
}
|
||||
|
||||
class ConnectedEdgeColorAction extends ColorAction {
|
||||
|
||||
final int outgoing = ColorLib.rgb(255, 100, 100);
|
||||
final int incoming = ColorLib.rgb(100, 255, 100);
|
||||
final int none = ColorLib.gray(100);
|
||||
|
||||
public ConnectedEdgeColorAction(String group, String field) {
|
||||
super(group, field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor(VisualItem item) {
|
||||
if (item instanceof DecoratorItem) {
|
||||
item = ((DecoratorItem) item).getDecoratedItem();
|
||||
}
|
||||
if (item instanceof EdgeItem) {
|
||||
if (((EdgeItem) item).getSourceItem().isHover()) {
|
||||
return outgoing;
|
||||
} else if (((EdgeItem) item).getTargetItem().isHover()) {
|
||||
return incoming;
|
||||
}
|
||||
}
|
||||
|
||||
return none;
|
||||
}
|
||||
}
|
||||
|
||||
class NPCPhraseColorAction extends ColorAction {
|
||||
|
||||
final int none = ColorLib.gray(255);
|
||||
final int hover = ColorLib.gray(200);
|
||||
final int has_rewards = ColorLib.rgb(255, 255, 0);
|
||||
final int has_rewards_hover = ColorLib.rgb(200, 200, 0);
|
||||
|
||||
|
||||
public NPCPhraseColorAction(String group, String field) {
|
||||
super(group, field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor(VisualItem item) {
|
||||
// Change color for Dialogues, not replies.
|
||||
if (item.get(TARGET) != null && item.get(REPLY) == null) {
|
||||
Dialogue d = (Dialogue) item.get(TARGET);
|
||||
if (d.rewards != null && !d.rewards.isEmpty()) {
|
||||
if (item.isHover()) {
|
||||
return has_rewards_hover;
|
||||
} else {
|
||||
return has_rewards;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item.isHover()) {
|
||||
return hover;
|
||||
} else {
|
||||
return none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EdgesStrokeAction extends StrokeAction {
|
||||
|
||||
public final BasicStroke req_stroke = new BasicStroke(2.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[]{3.5f, 2.5f}, 1.0f);
|
||||
public final BasicStroke hover_stroke = new BasicStroke(3.0f);
|
||||
public final BasicStroke hover_req_stroke = new BasicStroke(4.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[]{3.5f, 2.5f}, 1.0f);
|
||||
|
||||
public EdgesStrokeAction(String group) {
|
||||
super(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicStroke getStroke(VisualItem item) {
|
||||
if (item.getBoolean(HAS_REQS)) {
|
||||
if (item instanceof EdgeItem) {
|
||||
if (((EdgeItem) item).getSourceItem().isHover()) {
|
||||
return hover_req_stroke;
|
||||
} else if (((EdgeItem) item).getTargetItem().isHover()) {
|
||||
return hover_req_stroke;
|
||||
}
|
||||
}
|
||||
return req_stroke;
|
||||
} else {
|
||||
if (item.isHover()) {
|
||||
return hover_stroke;
|
||||
} else if (item instanceof EdgeItem) {
|
||||
if (((EdgeItem) item).getSourceItem().isHover()) {
|
||||
return hover_stroke;
|
||||
} else if (((EdgeItem) item).getTargetItem().isHover()) {
|
||||
return hover_stroke;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getStroke(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class EdgesLabelDecoratorLayout extends Layout {
|
||||
public EdgesLabelDecoratorLayout(String group) {
|
||||
super(group);
|
||||
}
|
||||
public void run(double frac) {
|
||||
Iterator<?> iter = m_vis.items(m_group);
|
||||
while ( iter.hasNext() ) {
|
||||
DecoratorItem decorator = (DecoratorItem)iter.next();
|
||||
if( decorator.getDecoratedItem() instanceof EdgeItem) {
|
||||
EdgeItem edgeItem = (EdgeItem) decorator.getDecoratedItem();
|
||||
double deltaX = edgeItem.getTargetItem().getX() - edgeItem.getSourceItem().getX();
|
||||
double deltaY = edgeItem.getTargetItem().getY() - edgeItem.getSourceItem().getY();
|
||||
double hypo = Math.hypot(deltaX, deltaY);
|
||||
|
||||
double edgePropX = deltaX / hypo;
|
||||
double edgePropY = deltaY / hypo;
|
||||
|
||||
Point2D start = new Point2D.Double(edgeItem.getSourceItem().getBounds().getCenterX(), edgeItem.getSourceItem().getBounds().getCenterY());
|
||||
Point2D end = new Point2D.Double(edgeItem.getTargetItem().getBounds().getCenterX(), edgeItem.getTargetItem().getBounds().getCenterY());
|
||||
Point2D[] realStart = new Point2D[]{new Point2D.Double(), new Point2D.Double()};
|
||||
// Point2D[] realEnd = new Point2D[]{new Point2D.Double(), new Point2D.Double()};
|
||||
|
||||
int i = GraphicsLib.intersectLineRectangle(start, end, edgeItem.getSourceItem().getBounds(), realStart);
|
||||
if (i > 0) {
|
||||
start = realStart[0];
|
||||
}
|
||||
// i = GraphicsLib.intersectLineRectangle(start, end, edgeItem.getTargetItem().getBounds(), realEnd);
|
||||
// if (i > 0) {
|
||||
// end = realEnd[0];
|
||||
// }
|
||||
|
||||
double coef = 20 * Math.atan(hypo / 100.0) + 20;
|
||||
|
||||
setX(decorator, null, start.getX() + coef * edgePropX + 6 * Math.random() - 3);
|
||||
setY(decorator, null, start.getY() + coef * edgePropY + 6 * Math.random() - 3);
|
||||
} else {
|
||||
VisualItem decoratedItem = decorator.getDecoratedItem();
|
||||
Rectangle2D bounds = decoratedItem.getBounds();
|
||||
double x = bounds.getCenterX();
|
||||
double y = bounds.getCenterY();
|
||||
setX(decorator, null, x + 10 * Math.random() - 5);
|
||||
setY(decorator, null, y + 10 * Math.random() - 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DoubleClickControl extends ControlAdapter {
|
||||
@Override
|
||||
public void itemClicked(VisualItem item, MouseEvent e) {
|
||||
if (e.getClickCount() == 2) {
|
||||
if (item.get(TARGET) != null) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement)item.get(TARGET));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
1434
src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java
Normal file
1434
src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java
Normal file
File diff suppressed because it is too large
Load Diff
511
src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java
Normal file
511
src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java
Normal file
@@ -0,0 +1,511 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.map;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameSource;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.Worldmap;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
import com.gpl.rpg.atcontentstudio.ui.Editor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.SaveItemsWizard;
|
||||
import com.jidesoft.swing.ComboBoxSearchable;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
public class WorldMapEditor extends Editor {
|
||||
|
||||
private static final long serialVersionUID = -8358238912588729094L;
|
||||
|
||||
public EditMode editMode = EditMode.moveViewSelect;
|
||||
|
||||
public enum EditMode {
|
||||
moveViewSelect,
|
||||
moveMaps,
|
||||
deleteMaps,
|
||||
addMap
|
||||
}
|
||||
|
||||
public String mapBeingAddedID = null;
|
||||
|
||||
public WorldMapEditor(WorldmapSegment worldmap) {
|
||||
target = worldmap;
|
||||
this.name = worldmap.id;
|
||||
this.icon = new ImageIcon(worldmap.getIcon());
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
JideTabbedPane editorTabsHolder = new JideTabbedPane(JideTabbedPane.BOTTOM);
|
||||
editorTabsHolder.setTabShape(JideTabbedPane.SHAPE_FLAT);
|
||||
editorTabsHolder.setUseDefaultShowCloseButtonOnTab(false);
|
||||
editorTabsHolder.setShowCloseButtonOnTab(false);
|
||||
add(editorTabsHolder, BorderLayout.CENTER);
|
||||
|
||||
editorTabsHolder.add("Map", buildSegmentTab(worldmap));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void targetUpdated() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
private JPanel buildSegmentTab(final WorldmapSegment worldmap) {
|
||||
JPanel pane = new JPanel();
|
||||
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS));
|
||||
|
||||
addLabelField(pane, "Worldmap File: ", ((Worldmap)worldmap.getParent()).worldmapFile.getAbsolutePath());
|
||||
pane.add(createButtonPane(worldmap), JideBoxLayout.FIX);
|
||||
|
||||
final WorldMapView mapView = new WorldMapView(worldmap);
|
||||
JScrollPane mapScroller = new JScrollPane(mapView);
|
||||
final JViewport vPort = mapScroller.getViewport();
|
||||
|
||||
final JSlider zoomSlider = new JSlider(WorldMapView.MIN_ZOOM, WorldMapView.MAX_ZOOM, (int)(mapView.zoomLevel / WorldMapView.ZOOM_RATIO));
|
||||
zoomSlider.setSnapToTicks(true);
|
||||
zoomSlider.setMinorTickSpacing(WorldMapView.INC_ZOOM);
|
||||
zoomSlider.setOrientation(JSlider.VERTICAL);
|
||||
JPanel zoomSliderPane = new JPanel();
|
||||
zoomSliderPane.setLayout(new JideBoxLayout(zoomSliderPane, JideBoxLayout.PAGE_AXIS));
|
||||
zoomSliderPane.add(zoomSlider, JideBoxLayout.VARY);
|
||||
zoomSliderPane.add(new JLabel(new ImageIcon(DefaultIcons.getZoomIcon())), JideBoxLayout.FIX);
|
||||
|
||||
if (target.writable) {
|
||||
JPanel mapToolsPane = new JPanel();
|
||||
mapToolsPane.setLayout(new JideBoxLayout(mapToolsPane, JideBoxLayout.LINE_AXIS));
|
||||
ButtonGroup mapToolsGroup = new ButtonGroup();
|
||||
JRadioButton moveView = new JRadioButton("Select maps");
|
||||
mapToolsGroup.add(moveView);
|
||||
mapToolsPane.add(moveView, JideBoxLayout.FIX);
|
||||
JRadioButton moveMaps = new JRadioButton("Move selected map(s)");
|
||||
mapToolsGroup.add(moveMaps);
|
||||
mapToolsPane.add(moveMaps, JideBoxLayout.FIX);
|
||||
JRadioButton deleteMaps = new JRadioButton("Delete maps");
|
||||
mapToolsGroup.add(deleteMaps);
|
||||
mapToolsPane.add(deleteMaps, JideBoxLayout.FIX);
|
||||
JRadioButton addMap = new JRadioButton("Add map");
|
||||
mapToolsGroup.add(addMap);
|
||||
mapToolsPane.add(addMap, JideBoxLayout.FIX);
|
||||
final GDEComboModel<TMXMap> mapComboModel = new GDEComboModel<TMXMap>(worldmap.getProject(), null){
|
||||
private static final long serialVersionUID = 2638082961277241764L;
|
||||
@Override
|
||||
public Object getTypedElementAt(int index) {
|
||||
return project.getMap(index);
|
||||
}
|
||||
@Override
|
||||
public int getSize() {
|
||||
return project.getMapCount()+1;
|
||||
}
|
||||
};
|
||||
final MyComboBox mapBox = new MyComboBox(TMXMap.class, mapComboModel);
|
||||
mapBox.setRenderer(new GDERenderer(false, false));
|
||||
new ComboBoxSearchable(mapBox){
|
||||
@Override
|
||||
protected String convertElementToString(Object object) {
|
||||
if (object == null) return "none";
|
||||
else return ((GameDataElement)object).getDesc();
|
||||
}
|
||||
};
|
||||
mapBox.setEnabled(false);
|
||||
mapToolsPane.add(mapBox, JideBoxLayout.FIX);
|
||||
|
||||
mapToolsPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
moveView.setSelected(true);
|
||||
pane.add(mapToolsPane, JideBoxLayout.FIX);
|
||||
|
||||
moveView.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editMode = EditMode.moveViewSelect;
|
||||
mapBox.setEnabled(false);
|
||||
if (mapBeingAddedID != null) {
|
||||
mapView.mapLocations.remove(mapBeingAddedID);
|
||||
mapBeingAddedID = null;
|
||||
mapView.revalidate();
|
||||
mapView.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
moveMaps.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editMode = EditMode.moveMaps;
|
||||
mapBox.setEnabled(false);
|
||||
if (mapBeingAddedID != null) {
|
||||
mapView.mapLocations.remove(mapBeingAddedID);
|
||||
mapBeingAddedID = null;
|
||||
mapView.revalidate();
|
||||
mapView.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
deleteMaps.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editMode = EditMode.deleteMaps;
|
||||
mapBox.setEnabled(false);
|
||||
if (mapBeingAddedID != null) {
|
||||
mapView.mapLocations.remove(mapBeingAddedID);
|
||||
mapBeingAddedID = null;
|
||||
mapView.revalidate();
|
||||
mapView.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addMap.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editMode = EditMode.addMap;
|
||||
mapBox.setEnabled(true);
|
||||
if (mapBox.getSelectedItem() != null) {
|
||||
mapBeingAddedID = ((TMXMap)mapBox.getSelectedItem()).id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mapBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (mapBox.getSelectedItem() == null) {
|
||||
mapBeingAddedID = null;
|
||||
} else {
|
||||
mapBeingAddedID = ((TMXMap)mapBox.getSelectedItem()).id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
JPanel mapZoomPane = new JPanel();
|
||||
mapZoomPane.setLayout(new BorderLayout());
|
||||
mapZoomPane.add(zoomSliderPane, BorderLayout.WEST);
|
||||
mapZoomPane.add(mapScroller, BorderLayout.CENTER);
|
||||
pane.add(mapZoomPane, JideBoxLayout.VARY);
|
||||
|
||||
zoomSlider.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
|
||||
Rectangle view = vPort.getViewRect();
|
||||
|
||||
float oldZoomLevel = mapView.zoomLevel;
|
||||
mapView.zoomLevel = zoomSlider.getValue() * WorldMapView.ZOOM_RATIO;
|
||||
|
||||
int newCenterX = (int) (view.getCenterX() / oldZoomLevel * mapView.zoomLevel);
|
||||
int newCenterY = (int) (view.getCenterY() / oldZoomLevel * mapView.zoomLevel);
|
||||
|
||||
view.x = newCenterX - (view.width / 2);
|
||||
view.y = newCenterY - (view.height / 2);
|
||||
|
||||
mapView.scrollRectToVisible(view);
|
||||
mapView.revalidate();
|
||||
mapView.repaint();
|
||||
}
|
||||
});
|
||||
|
||||
MouseAdapter mouseListener = new MouseAdapter() {
|
||||
final int skipRecomputeDefault = 5;
|
||||
Point dragStart = null;
|
||||
int skipRecompute = 0;
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
String selectedMap = null;
|
||||
boolean update = false;
|
||||
int x = (int) (e.getX() / mapView.zoomLevel);
|
||||
int y = (int) (e.getY() / mapView.zoomLevel);
|
||||
for (String s : mapView.mapLocations.keySet()) {
|
||||
if (mapView.mapLocations.get(s).contains(x, y)) {
|
||||
selectedMap = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (editMode == EditMode.moveViewSelect) {
|
||||
if (selectedMap == null) return;
|
||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||
if (e.isControlDown() || e.isShiftDown()) {
|
||||
if (mapView.selected.contains(selectedMap)) {
|
||||
mapView.selected.remove(selectedMap);
|
||||
update = true;
|
||||
} else {
|
||||
mapView.selected.add(selectedMap);
|
||||
update = true;
|
||||
}
|
||||
} else {
|
||||
mapView.selected.clear();
|
||||
mapView.selected.add(selectedMap);
|
||||
update = true;
|
||||
}
|
||||
if (e.getClickCount() == 2) {
|
||||
ATContentStudio.frame.openEditor(worldmap.getProject().getMap(selectedMap));
|
||||
}
|
||||
}
|
||||
} else if (editMode == EditMode.deleteMaps) {
|
||||
worldmap.mapLocations.remove(selectedMap);
|
||||
worldmap.labelLocations.remove(selectedMap);
|
||||
mapView.selected.remove(selectedMap);
|
||||
mapView.updateFromModel();
|
||||
update = true;
|
||||
} else if (editMode == EditMode.addMap && mapBeingAddedID != null) {
|
||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||
mapView.recomputeSize();
|
||||
mapView.pushToModel();
|
||||
}
|
||||
mapView.updateFromModel();
|
||||
update = true;
|
||||
mapBeingAddedID = null;
|
||||
}
|
||||
if (update) {
|
||||
mapView.revalidate();
|
||||
mapView.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||
dragStart = e.getLocationOnScreen();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
dragStart = null;
|
||||
if (editMode == EditMode.moveMaps) {
|
||||
mapView.pushToModel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (editMode == EditMode.addMap && mapBeingAddedID != null) {
|
||||
int x = (int) (e.getX() / mapView.zoomLevel);
|
||||
int y = (int) (e.getY() / mapView.zoomLevel);
|
||||
TMXMap map = target.getProject().getMap(mapBeingAddedID);
|
||||
int w = map.tmxMap.getWidth() * WorldMapView.TILE_SIZE;
|
||||
int h = map.tmxMap.getHeight() * WorldMapView.TILE_SIZE;
|
||||
x -= w / 2;
|
||||
x -= x % WorldMapView.TILE_SIZE;
|
||||
y -= h / 2;
|
||||
y -= y % WorldMapView.TILE_SIZE;
|
||||
mapView.mapLocations.put(mapBeingAddedID, new Rectangle(x, y, w, h));
|
||||
if (--skipRecompute <= 0) {
|
||||
if (mapView.recomputeSize()) {
|
||||
skipRecompute = skipRecomputeDefault;
|
||||
}
|
||||
}
|
||||
mapView.revalidate();
|
||||
mapView.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
if (dragStart == null) return;
|
||||
int deltaX = e.getXOnScreen() - dragStart.x;
|
||||
int deltaY = e.getYOnScreen() - dragStart.y;
|
||||
|
||||
if (editMode != EditMode.moveMaps) {
|
||||
Rectangle view = vPort.getViewRect();
|
||||
view.setLocation(view.x - deltaX, view.y - deltaY);
|
||||
mapView.scrollRectToVisible(view);
|
||||
|
||||
dragStart = e.getLocationOnScreen();
|
||||
} else {
|
||||
int mapDeltaX = (int) ((deltaX / mapView.zoomLevel));
|
||||
int mapDeltaY = (int) ((deltaY / mapView.zoomLevel));
|
||||
|
||||
mapDeltaX -= mapDeltaX % WorldMapView.TILE_SIZE;
|
||||
mapDeltaY -= mapDeltaY % WorldMapView.TILE_SIZE;
|
||||
|
||||
for (String s : mapView.selected) {
|
||||
mapView.mapLocations.get(s).x = (worldmap.mapLocations.get(s).x * WorldMapView.TILE_SIZE) + mapDeltaX;
|
||||
mapView.mapLocations.get(s).y = (worldmap.mapLocations.get(s).y * WorldMapView.TILE_SIZE) + mapDeltaY;
|
||||
}
|
||||
|
||||
if (--skipRecompute <= 0) {
|
||||
if (mapView.recomputeSize()) {
|
||||
skipRecompute = skipRecomputeDefault;
|
||||
}
|
||||
}
|
||||
|
||||
mapView.revalidate();
|
||||
mapView.repaint();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mapView.addMouseListener(mouseListener);
|
||||
mapView.addMouseMotionListener(mouseListener);
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
public JPanel createButtonPane(final WorldmapSegment node) {
|
||||
final JButton gdeIcon = new JButton(new ImageIcon(DefaultIcons.getUIMapImage()));
|
||||
JPanel savePane = new JPanel();
|
||||
savePane.add(gdeIcon, JideBoxLayout.FIX);
|
||||
savePane.setLayout(new JideBoxLayout(savePane, JideBoxLayout.LINE_AXIS, 6));
|
||||
if (node.writable) {
|
||||
if (node.getDataType() == GameSource.Type.altered) {
|
||||
savePane.add(message = new JLabel(ALTERED_MESSAGE), JideBoxLayout.FIX);
|
||||
} else if (node.getDataType() == GameSource.Type.created) {
|
||||
savePane.add(message = new JLabel(CREATED_MESSAGE), JideBoxLayout.FIX);
|
||||
}
|
||||
JButton save = new JButton(SAVE);
|
||||
save.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (node.getParent() instanceof Worldmap) {
|
||||
if (node.state != GameDataElement.State.saved) {
|
||||
final List<SaveEvent> events = node.attemptSave();
|
||||
if (events == null) {
|
||||
ATContentStudio.frame.nodeChanged(node);
|
||||
} else {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
new SaveItemsWizard(events, node).setVisible(true);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
savePane.add(save, JideBoxLayout.FIX);
|
||||
JButton delete = new JButton(DELETE);
|
||||
if (node.getDataType() == GameSource.Type.altered) {
|
||||
delete.setText(REVERT);
|
||||
}
|
||||
delete.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ATContentStudio.frame.closeEditor(node);
|
||||
node.childrenRemoved(new ArrayList<ProjectTreeNode>());
|
||||
if (node.getParent() instanceof Worldmap) {
|
||||
((Worldmap)node.getParent()).remove(node);
|
||||
node.save();
|
||||
for (GameDataElement backlink : node.getBacklinks()) {
|
||||
backlink.elementChanged(node, node.getProject().getWorldmapSegment(node.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
savePane.add(delete, JideBoxLayout.FIX);
|
||||
} else {
|
||||
if (node.getProject().alteredContent.getWorldmapSegment(node.id) != null) {
|
||||
savePane.add(message = new JLabel(ALTERED_EXISTS_MESSAGE), JideBoxLayout.FIX);
|
||||
JButton makeWritable = new JButton("Go to altered");
|
||||
makeWritable.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (node.getProject().getWorldmapSegment(node.id) != node) {
|
||||
ATContentStudio.frame.openEditor(node.getProject().getWorldmapSegment(node.id));
|
||||
ATContentStudio.frame.closeEditor(node);
|
||||
ATContentStudio.frame.selectInTree(node.getProject().getWorldmapSegment(node.id));
|
||||
}
|
||||
}
|
||||
});
|
||||
savePane.add(makeWritable, JideBoxLayout.FIX);
|
||||
|
||||
} else {
|
||||
savePane.add(message = new JLabel(READ_ONLY_MESSAGE), JideBoxLayout.FIX);
|
||||
JButton makeWritable = new JButton("Alter");
|
||||
makeWritable.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (node.getProject().getWorldmapSegment(node.id) == node) {
|
||||
node.getProject().makeWritable(node);
|
||||
}
|
||||
if (node.getProject().getWorldmapSegment(node.id) != node) {
|
||||
ATContentStudio.frame.openEditor(node.getProject().getWorldmapSegment(node.id));
|
||||
ATContentStudio.frame.closeEditor(node);
|
||||
ATContentStudio.frame.selectInTree(node.getProject().getWorldmapSegment(node.id));
|
||||
}
|
||||
updateMessage();
|
||||
}
|
||||
});
|
||||
savePane.add(makeWritable, JideBoxLayout.FIX);
|
||||
}
|
||||
}
|
||||
JButton prev = new JButton(new ImageIcon(DefaultIcons.getArrowLeftIcon()));
|
||||
JButton next = new JButton(new ImageIcon(DefaultIcons.getArrowRightIcon()));
|
||||
savePane.add(prev, JideBoxLayout.FIX);
|
||||
savePane.add(next, JideBoxLayout.FIX);
|
||||
if (node.getParent().getIndex(node) == 0) {
|
||||
prev.setEnabled(false);
|
||||
}
|
||||
if (node.getParent().getIndex(node) == node.getParent().getChildCount() - 1) {
|
||||
next.setEnabled(false);
|
||||
}
|
||||
prev.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ProjectTreeNode prevNode = (ProjectTreeNode) node.getParent().getChildAt(node.getParent().getIndex(node) - 1);
|
||||
if (prevNode != null && prevNode instanceof GameDataElement) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement) prevNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
next.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ProjectTreeNode nextNode = (ProjectTreeNode) node.getParent().getChildAt(node.getParent().getIndex(node) + 1);
|
||||
if (nextNode != null && nextNode instanceof GameDataElement) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement) nextNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
//Placeholder. Fills the eventual remaining space.
|
||||
savePane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
return savePane;
|
||||
}
|
||||
|
||||
public void updateMessage() {
|
||||
|
||||
//TODO make this a full update of the button panel.
|
||||
WorldmapSegment node = (WorldmapSegment) target;
|
||||
if (node.writable) {
|
||||
if (node.getDataType() == GameSource.Type.altered) {
|
||||
message.setText(ALTERED_MESSAGE);
|
||||
} else if (node.getDataType() == GameSource.Type.created) {
|
||||
message.setText(CREATED_MESSAGE);
|
||||
}
|
||||
} else if (node.getProject().alteredContent.getWorldmapSegment(node.id) != null) {
|
||||
message.setText(ALTERED_EXISTS_MESSAGE);
|
||||
} else {
|
||||
message.setText(READ_ONLY_MESSAGE);
|
||||
}
|
||||
message.revalidate();
|
||||
message.repaint();
|
||||
}
|
||||
|
||||
}
|
||||
245
src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapView.java
Normal file
245
src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapView.java
Normal file
@@ -0,0 +1,245 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.map;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.Scrollable;
|
||||
|
||||
import tiled.view.MapRenderer;
|
||||
import tiled.view.OrthogonalRenderer;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
|
||||
|
||||
public class WorldMapView extends JComponent implements Scrollable {
|
||||
|
||||
private static final long serialVersionUID = -4111374378777093799L;
|
||||
|
||||
public static final int TILE_SIZE = 32;
|
||||
public static final int MIN_ZOOM = 5;
|
||||
public static final int MAX_ZOOM = 250;
|
||||
public static final int INC_ZOOM = 5;
|
||||
public static final float ZOOM_RATIO = 0.01f;
|
||||
|
||||
WorldmapSegment worldmap;
|
||||
Project proj;
|
||||
|
||||
|
||||
public Map<String, Rectangle> mapLocations = new HashMap<String, Rectangle>();
|
||||
|
||||
public Set<String> selected = new HashSet<String>();
|
||||
|
||||
public float zoomLevel = 0.1f;
|
||||
int sizeX = 0, sizeY = 0;
|
||||
int offsetX = 0, offsetY = 0;
|
||||
|
||||
public WorldMapView(WorldmapSegment worldmap) {
|
||||
this.worldmap = worldmap;
|
||||
this.proj = worldmap.getProject();
|
||||
updateFromModel();
|
||||
}
|
||||
|
||||
private void paintOnGraphics(Graphics2D g2) {
|
||||
g2.setPaint(new Color(100, 100, 100));
|
||||
g2.fillRect(0, 0, sizeX, sizeY);
|
||||
|
||||
g2.setPaint(new Color(255, 0, 0));
|
||||
g2.setStroke(new BasicStroke(4));
|
||||
|
||||
for (String s : mapLocations.keySet()) {
|
||||
|
||||
int x = mapLocations.get(s).x;
|
||||
int y = mapLocations.get(s).y;
|
||||
|
||||
g2.translate(x, y);
|
||||
|
||||
|
||||
TMXMap map = proj.getMap(s);
|
||||
if (map == null) continue;
|
||||
MapRenderer renderer = new OrthogonalRenderer(map.tmxMap);
|
||||
|
||||
// Draw each tile map layer
|
||||
for (tiled.core.MapLayer layer : ((TMXMap)map).tmxMap) {
|
||||
if (layer instanceof tiled.core.TileLayer && layer.isVisible()) {
|
||||
if (layer.getName().equalsIgnoreCase("walkable")) continue;
|
||||
renderer.paintTileLayer(g2, (tiled.core.TileLayer) layer);
|
||||
} else if (layer instanceof tiled.core.ObjectGroup && layer.isVisible()) {
|
||||
// paintObjectGroup(g2, map, (tiled.core.ObjectGroup) layer);
|
||||
}
|
||||
}
|
||||
if (selected.contains(s)) {
|
||||
g2.drawRect(0, 0, map.tmxMap.getWidth() * TILE_SIZE, map.tmxMap.getHeight() * TILE_SIZE);
|
||||
}
|
||||
|
||||
g2.translate(-x, -y);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
Graphics2D g2 = (Graphics2D)g.create();
|
||||
try {
|
||||
g2.scale(zoomLevel, zoomLevel);
|
||||
// g2.drawImage(img, 0, 0, null);
|
||||
paintOnGraphics(g2);
|
||||
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// private boolean paintObjectGroup(Graphics2D g2d, TMXMap map, tiled.core.ObjectGroup layer) {
|
||||
// boolean paintSelected = false;
|
||||
// for (MapObjectGroup group : map.groups) {
|
||||
// if (group.tmxGroup == layer) {
|
||||
// for (MapObject object : group.mapObjects) {
|
||||
// drawObject(object, g2d, new Color(20, 20, 190));
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// return paintSelected;
|
||||
// }
|
||||
//
|
||||
// private void drawObject(MapObject object, Graphics2D g2d, Color color) {
|
||||
// g2d.setPaint(color);
|
||||
// g2d.drawRect(object.x+1, object.y+1, object.w-3, object.h-3);
|
||||
// g2d.drawRect(object.x+2, object.y+2, object.w-5, object.h-5);
|
||||
// g2d.setPaint(color.darker().darker());
|
||||
// g2d.drawLine(object.x, object.y + object.h - 1, object.x + object.w - 1, object.y + object.h - 1);
|
||||
// g2d.drawLine(object.x + object.w - 1, object.y, object.x + object.w - 1, object.y + object.h - 1);
|
||||
// g2d.drawLine(object.x + 3, object.y + 3, object.x + object.w - 4, object.y + 3);
|
||||
// g2d.drawLine(object.x + 3, object.y + 3, object.x + 3, object.y + object.h - 4);
|
||||
// g2d.setPaint(color.brighter().brighter().brighter());
|
||||
// g2d.drawLine(object.x, object.y, object.x + object.w - 1, object.y);
|
||||
// g2d.drawLine(object.x, object.y, object.x, object.y + object.h - 1);
|
||||
// g2d.drawLine(object.x + 3, object.y + object.h - 4, object.x + object.w - 4, object.y + object.h - 4);
|
||||
// g2d.drawLine(object.x + object.w - 4, object.y + 3, object.x + object.w - 4, object.y + object.h - 4);
|
||||
// Image img = object.getIcon();
|
||||
// g2d.setColor(new Color(255, 255, 255, 120));
|
||||
// g2d.fillRect(object.x + 2, object.y + 2, img.getWidth(null), img.getHeight(null));
|
||||
// g2d.drawImage(object.getIcon(), object.x + 2, object.y + 2, null);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension((int)(zoomLevel * sizeX), (int)(zoomLevel * sizeY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
return TILE_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
return 4 * TILE_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportWidth() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportHeight() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean recomputeSize() {
|
||||
sizeX = sizeY = 0;
|
||||
boolean originMoved = false;
|
||||
int minX = Integer.MAX_VALUE, minY= Integer.MAX_VALUE;
|
||||
for (String s : mapLocations.keySet()) {
|
||||
int x = mapLocations.get(s).x;
|
||||
int w = proj.getMap(s).tmxMap.getWidth() * TILE_SIZE;
|
||||
int y = mapLocations.get(s).y;
|
||||
int h = proj.getMap(s).tmxMap.getHeight() * TILE_SIZE;
|
||||
|
||||
sizeX = Math.max(sizeX, x + w);
|
||||
sizeY = Math.max(sizeY, y + h);
|
||||
minX = Math.min(minX, x);
|
||||
minY = Math.min(minY, y);
|
||||
}
|
||||
|
||||
if (minX != 0) {
|
||||
for (String s : mapLocations.keySet()) {
|
||||
mapLocations.get(s).x -= minX;
|
||||
}
|
||||
sizeX -= minX;
|
||||
offsetX += minX;
|
||||
originMoved = true;
|
||||
}
|
||||
|
||||
if (minY != 0) {
|
||||
for (String s : mapLocations.keySet()) {
|
||||
mapLocations.get(s).y -= minY;
|
||||
}
|
||||
sizeY -= minY;
|
||||
offsetY += minY;
|
||||
originMoved = true;
|
||||
}
|
||||
return originMoved;
|
||||
}
|
||||
|
||||
public void updateFromModel() {
|
||||
mapLocations.clear();
|
||||
sizeX = sizeY = 0;
|
||||
offsetX = worldmap.segmentX * TILE_SIZE;
|
||||
offsetY = worldmap.segmentY * TILE_SIZE;
|
||||
for (String s : worldmap.mapLocations.keySet()) {
|
||||
int x = worldmap.mapLocations.get(s).x * TILE_SIZE;
|
||||
int w = proj.getMap(s).tmxMap.getWidth() * TILE_SIZE;
|
||||
int y = worldmap.mapLocations.get(s).y * TILE_SIZE;
|
||||
int h = proj.getMap(s).tmxMap.getHeight() * TILE_SIZE;
|
||||
|
||||
sizeX = Math.max(sizeX, x + w);
|
||||
sizeY = Math.max(sizeY, y + h);
|
||||
|
||||
mapLocations.put(s, new Rectangle(x, y, w, h));
|
||||
}
|
||||
}
|
||||
|
||||
public void pushToModel() {
|
||||
worldmap.segmentX = offsetX / TILE_SIZE;
|
||||
worldmap.segmentY = offsetY / TILE_SIZE;
|
||||
worldmap.mapLocations.clear();
|
||||
for (String s : mapLocations.keySet()) {
|
||||
int x = mapLocations.get(s).x / TILE_SIZE;
|
||||
int y = mapLocations.get(s).y / TILE_SIZE;
|
||||
|
||||
worldmap.mapLocations.put(s, new Point(x, y));
|
||||
}
|
||||
|
||||
List<String> toRemove = new ArrayList<String>();
|
||||
for (String s : worldmap.labelLocations.keySet()) {
|
||||
if (!mapLocations.containsKey(s)) {
|
||||
toRemove.add(s);
|
||||
}
|
||||
}
|
||||
for (String s : toRemove) {
|
||||
worldmap.labelLocations.remove(s);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.saves;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.saves.SavedGame;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
import com.gpl.rpg.atcontentstudio.ui.Editor;
|
||||
|
||||
public class SavedGameEditor extends Editor {
|
||||
|
||||
private static final long serialVersionUID = 6055910379650778737L;
|
||||
|
||||
public SavedGameEditor(SavedGame save) {
|
||||
this.name = save.loadedSave.displayInfo;
|
||||
this.icon = new ImageIcon(DefaultIcons.getHeroIcon());
|
||||
this.target = save;
|
||||
setLayout(new BorderLayout());
|
||||
add(new JScrollPane(new com.gpl.rpg.andorstrainer.ui.SavedGameEditor(save.loadedSave, ATContentStudio.frame)), BorderLayout.CENTER);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void targetUpdated() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
235
src/com/gpl/rpg/atcontentstudio/ui/sprites/SpriteChooser.java
Normal file
235
src/com/gpl/rpg/atcontentstudio/ui/sprites/SpriteChooser.java
Normal file
@@ -0,0 +1,235 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.sprites;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet.Category;
|
||||
|
||||
|
||||
public class SpriteChooser extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = -6018113265015159521L;
|
||||
|
||||
private static final int STD_WIDTH = 32;
|
||||
private static final int STD_HEIGHT = 32;
|
||||
private static final int MAX_PER_ROW = 10;
|
||||
|
||||
public static Map<Project, Map<Spritesheet.Category, SpriteChooser>> cache = new HashMap<Project, Map<Spritesheet.Category,SpriteChooser>>();
|
||||
|
||||
public static SpriteChooser getChooser(Project proj, Spritesheet.Category category) {
|
||||
if (cache.get(proj) == null) {
|
||||
cache.put(proj, new HashMap<Spritesheet.Category, SpriteChooser>());
|
||||
}
|
||||
if (cache.get(proj).get(category) == null) {
|
||||
cache.get(proj).put(category, new SpriteChooser(proj, category));
|
||||
}
|
||||
SpriteChooser wanted = cache.get(proj).get(category);
|
||||
wanted.group.clearSelection();
|
||||
wanted.selectedIconId = null;
|
||||
// wanted.selectedOne = null;
|
||||
wanted.listener = null;
|
||||
// wanted.ok.setEnabled(false);
|
||||
wanted.pack();
|
||||
return wanted;
|
||||
}
|
||||
|
||||
private ButtonGroup group;
|
||||
// private IconButton selectedOne = null;
|
||||
// private JButton ok;
|
||||
// private JButton cancel;
|
||||
|
||||
public String selectedIconId = null;
|
||||
|
||||
public SpriteChooser(Project proj, Category category) {
|
||||
super(ATContentStudio.frame);
|
||||
setTitle("Select a sprite");
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
List<Spritesheet> spritesheets = new ArrayList<Spritesheet>();
|
||||
for (Spritesheet sheet : proj.baseContent.gameSprites.spritesheets) {
|
||||
if (sheet.category == category) {
|
||||
spritesheets.add(sheet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JPanel pane = new JPanel();
|
||||
pane.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.weightx = 1;
|
||||
c.weighty = 1;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.gridwidth = 1;
|
||||
c.gridheight = 1;
|
||||
c.anchor = GridBagConstraints.NORTHWEST;
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
|
||||
List<Point> reservedSlots = new ArrayList<Point>();
|
||||
Point nextFreeSlot = new Point(0, 0);
|
||||
|
||||
int i;
|
||||
Image img;
|
||||
group = new ButtonGroup();
|
||||
for (Spritesheet sheet : spritesheets) {
|
||||
i = 0;
|
||||
while ((img = sheet.getImage(i)) != null) {
|
||||
IconButton button = new IconButton(img, sheet.id, i);
|
||||
group.add(button);
|
||||
if (sheet.spriteWidth == STD_WIDTH && sheet.spriteHeight == STD_HEIGHT) {
|
||||
pane.add(button, c);
|
||||
c.gridx++;
|
||||
if (c.gridx >= MAX_PER_ROW) {
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
}
|
||||
nextFreeSlot.setLocation(c.gridx, c.gridy);
|
||||
} else {
|
||||
c.gridwidth = (sheet.spriteWidth / STD_WIDTH) + (sheet.spriteWidth % STD_WIDTH == 0 ? 0 : 1);
|
||||
c.gridheight = (sheet.spriteHeight / STD_HEIGHT) + (sheet.spriteHeight % STD_HEIGHT == 0 ? 0 : 1);
|
||||
boolean slotOk = false;
|
||||
while (!slotOk) {
|
||||
slotOk = true;
|
||||
for (int x = c.gridx; x < c.gridx + c.gridwidth; x++) {
|
||||
for (int y = c.gridy; y < c.gridy + c.gridwidth; y++) {
|
||||
if (reservedSlots.contains(new Point(x, y))) {
|
||||
slotOk = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (slotOk && c.gridx + c.gridwidth > MAX_PER_ROW) {
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
slotOk = false;
|
||||
}
|
||||
}
|
||||
pane.add(button, c);
|
||||
for (int x = c.gridx; x < c.gridx + c.gridwidth; x++) {
|
||||
for (int y = c.gridy; y < c.gridy + c.gridwidth; y++) {
|
||||
reservedSlots.add(new Point(x, y));
|
||||
}
|
||||
}
|
||||
c.gridwidth = 1;
|
||||
c.gridheight = 1;
|
||||
c.gridx = nextFreeSlot.x;
|
||||
c.gridy = nextFreeSlot.y;
|
||||
}
|
||||
while (reservedSlots.contains(nextFreeSlot)) {
|
||||
c.gridx++;
|
||||
if (c.gridx >= MAX_PER_ROW) {
|
||||
c.gridx = 0;
|
||||
c.gridy++;
|
||||
}
|
||||
nextFreeSlot.setLocation(c.gridx, c.gridy);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// ok = new JButton("Ok");
|
||||
// cancel = new JButton("Cancel");
|
||||
|
||||
c.gridx = 0;
|
||||
boolean emptyLine = false;
|
||||
while (!emptyLine) {
|
||||
c.gridy++;
|
||||
emptyLine = true;
|
||||
for (i = MAX_PER_ROW - 1; i >= 0; i--) {
|
||||
if (reservedSlots.contains(new Point(i, c.gridy))) {
|
||||
emptyLine = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JPanel buttonPane = new JPanel();
|
||||
// buttonPane.add(cancel, BorderLayout.WEST);
|
||||
// buttonPane.add(ok, BorderLayout.EAST);
|
||||
|
||||
JPanel wrapper = new JPanel();
|
||||
wrapper.setLayout(new BorderLayout());
|
||||
JScrollPane scroller = new JScrollPane(pane);
|
||||
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
wrapper.add(scroller, BorderLayout.CENTER);
|
||||
// wrapper.add(buttonPane, BorderLayout.SOUTH);
|
||||
|
||||
// ok.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// selectedIconId = selectedOne.sheetId+":"+selectedOne.spriteIndex;
|
||||
// SpriteChooser.this.setVisible(false);
|
||||
// SpriteChooser.this.dispose();
|
||||
// if (listener != null) listener.iconSelected(selectedIconId);
|
||||
// }
|
||||
// });
|
||||
|
||||
// cancel.addActionListener(new ActionListener() {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// selectedIconId = null;
|
||||
// SpriteChooser.this.setVisible(false);
|
||||
// SpriteChooser.this.dispose();
|
||||
// if (listener != null) listener.iconSelected(null);
|
||||
// }
|
||||
// });
|
||||
|
||||
setContentPane(wrapper);
|
||||
}
|
||||
|
||||
private SpriteChooser.SelectionListener listener = null;
|
||||
|
||||
public void setSelectionListener(SpriteChooser.SelectionListener l) {
|
||||
listener = l;
|
||||
}
|
||||
|
||||
|
||||
public class IconButton extends JToggleButton {
|
||||
|
||||
private static final long serialVersionUID = 7559407153561178455L;
|
||||
|
||||
public String sheetId;
|
||||
public int spriteIndex;
|
||||
|
||||
public IconButton(Image img, String sheetId, int spriteIndex) {
|
||||
super(new ImageIcon(img));
|
||||
this.sheetId = sheetId;
|
||||
this.spriteIndex = spriteIndex;
|
||||
setToolTipText(sheetId+":"+spriteIndex);
|
||||
addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (IconButton.this.isSelected()) {
|
||||
selectedIconId = IconButton.this.sheetId+":"+IconButton.this.spriteIndex;
|
||||
SpriteChooser.this.setVisible(false);
|
||||
SpriteChooser.this.dispose();
|
||||
if (listener != null) listener.iconSelected(selectedIconId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static interface SelectionListener {
|
||||
public void iconSelected(String selected);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.sprites;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||
import com.gpl.rpg.atcontentstudio.Notification;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
|
||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
|
||||
import com.gpl.rpg.atcontentstudio.ui.Editor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
public class SpritesheetEditor extends Editor {
|
||||
|
||||
private static final long serialVersionUID = 3956109815682889863L;
|
||||
|
||||
Map<String, JPanel> editorTabs = new HashMap<String, JPanel>();
|
||||
JideTabbedPane editorTabsHolder;
|
||||
|
||||
private JSpinner widthField;
|
||||
private JSpinner heightField;
|
||||
private JCheckBox animatedBox;
|
||||
private JComboBox categoryBox;
|
||||
private JPanel spriteViewPane;
|
||||
|
||||
|
||||
public static JComponent getWarningLabel() {
|
||||
JLabel label = new JLabel(
|
||||
"<html><i>" +
|
||||
"The data presented here is not part of the game.<br/>" +
|
||||
"What you change here will be changed in your ATCS project.<br/>" +
|
||||
"None of this is exported to JSON or TMX, although it must be set correctly in order to choose tiles & icons correctly.<br/>" +
|
||||
"</i></html>");
|
||||
return label;
|
||||
}
|
||||
|
||||
public SpritesheetEditor(Spritesheet sheet) {
|
||||
super();
|
||||
this.icon = new ImageIcon(sheet.getIcon(0));
|
||||
this.name = sheet.id;
|
||||
this.target = sheet;
|
||||
|
||||
JPanel pane = new JPanel();
|
||||
|
||||
final FieldUpdateListener listener = new SpritesheetFieldUpdater();
|
||||
|
||||
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
|
||||
|
||||
add(getWarningLabel(), JideBoxLayout.FIX);
|
||||
addLabelField(pane, "Spritesheet ID: ", sheet.id);
|
||||
addLabelField(pane, "File: ", sheet.spritesheetFile.getAbsolutePath());
|
||||
widthField = addIntegerField(pane, "Sprite width (px): ", sheet.spriteWidth, false, true, listener);
|
||||
heightField = addIntegerField(pane, "Sprite height (px): ", sheet.spriteHeight, false, true, listener);
|
||||
animatedBox = addBooleanBasedCheckBox(pane, "Is an animation", sheet.animated, true, listener);
|
||||
categoryBox = addEnumValueBox(pane, "Category: ", Spritesheet.Category.values(), sheet.category, true, listener);
|
||||
|
||||
spriteViewPane = new JPanel();
|
||||
updateView(spriteViewPane);
|
||||
pane.add(spriteViewPane, JideBoxLayout.FIX);
|
||||
|
||||
addBacklinksList(pane, sheet);
|
||||
|
||||
//Placeholder. Fills the eventual remaining space.
|
||||
pane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
editorTabsHolder = new JideTabbedPane(JideTabbedPane.BOTTOM);
|
||||
editorTabsHolder.setTabShape(JideTabbedPane.SHAPE_FLAT);
|
||||
editorTabsHolder.setUseDefaultShowCloseButtonOnTab(false);
|
||||
editorTabsHolder.setShowCloseButtonOnTab(false);
|
||||
add(editorTabsHolder, BorderLayout.CENTER);
|
||||
|
||||
JScrollPane sheetScroller = new JScrollPane(pane);
|
||||
sheetScroller.getVerticalScrollBar().setUnitIncrement(16);
|
||||
editorTabsHolder.add("Spritesheet",sheetScroller);
|
||||
JScrollPane rawScroller = new JScrollPane(new JLabel(new ImageIcon(sheet.spritesheet)));
|
||||
rawScroller.getVerticalScrollBar().setUnitIncrement(16);
|
||||
editorTabsHolder.add("Raw image", rawScroller);
|
||||
}
|
||||
|
||||
private Thread animator = new Thread();
|
||||
private boolean animate = true;
|
||||
private JLabel iconLabel;
|
||||
private List<ImageIcon> icons = null;
|
||||
|
||||
public void updateView(JPanel pane) {
|
||||
Spritesheet sheet = (Spritesheet)target;
|
||||
pane.removeAll();
|
||||
pane.setLayout(new BorderLayout());
|
||||
if (sheet.animated) {
|
||||
iconLabel = new JLabel();
|
||||
iconLabel.setBackground(Color.WHITE);
|
||||
if (icons == null) {
|
||||
icons = new ArrayList<ImageIcon>();
|
||||
} else {
|
||||
icons.clear();
|
||||
}
|
||||
int i = 0;
|
||||
Image img;
|
||||
while ((img = sheet.getImage(i++)) != null) {
|
||||
icons.add(new ImageIcon(img));
|
||||
}
|
||||
if (i > 0) {
|
||||
iconLabel.setIcon(icons.get(0));
|
||||
}
|
||||
pane.add(iconLabel, BorderLayout.CENTER);
|
||||
resetAnimator();
|
||||
} else {
|
||||
JTable spritesTable = new JTable(new SpritesheetTableModel(sheet));
|
||||
spritesTable.setDefaultRenderer(Image.class, new SpritesheetCellRenderer(sheet));
|
||||
spritesTable.setCellSelectionEnabled(true);
|
||||
spritesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
spritesTable.getTableHeader().setVisible(false);
|
||||
Enumeration<TableColumn> columns = spritesTable.getColumnModel().getColumns();
|
||||
TableColumn col;
|
||||
while (columns.hasMoreElements()) {
|
||||
col = columns.nextElement();
|
||||
col.setMinWidth(sheet.spriteWidth + 1);
|
||||
col.setMaxWidth(sheet.spriteWidth + 1);
|
||||
}
|
||||
spritesTable.setRowHeight(sheet.spriteHeight + 1);
|
||||
pane.add(new JScrollPane(spritesTable), BorderLayout.CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static JList addBacklinksList(JPanel pane, Spritesheet sheet) {
|
||||
final JList list = new JList(new SpritesheetsBacklinksListModel(sheet));
|
||||
list.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 2) {
|
||||
if (list.getSelectedValue() instanceof TMXMap) {
|
||||
ATContentStudio.frame.openEditor((TMXMap)list.getSelectedValue());
|
||||
ATContentStudio.frame.selectInTree((TMXMap)list.getSelectedValue());
|
||||
} else if (list.getSelectedValue() instanceof GameDataElement) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement)list.getSelectedValue());
|
||||
ATContentStudio.frame.selectInTree((GameDataElement)list.getSelectedValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
list.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
if (list.getSelectedValue() instanceof TMXMap) {
|
||||
ATContentStudio.frame.openEditor((TMXMap)list.getSelectedValue());
|
||||
ATContentStudio.frame.selectInTree((TMXMap)list.getSelectedValue());
|
||||
} else if (list.getSelectedValue() instanceof GameDataElement) {
|
||||
ATContentStudio.frame.openEditor((GameDataElement)list.getSelectedValue());
|
||||
ATContentStudio.frame.selectInTree((GameDataElement)list.getSelectedValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
list.setCellRenderer(new BacklinkCellRenderer(true));
|
||||
JScrollPane scroller = new JScrollPane(list);
|
||||
scroller.setBorder(BorderFactory.createTitledBorder("Elements pointing to this spritesheet."));
|
||||
pane.add(scroller, JideBoxLayout.FIX);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static class SpritesheetTableModel implements TableModel {
|
||||
|
||||
Spritesheet sheet;
|
||||
|
||||
public SpritesheetTableModel(Spritesheet sheet) {
|
||||
this.sheet = sheet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return (sheet.spritesheet.getHeight() / sheet.spriteHeight) + ((sheet.spritesheet.getHeight() % sheet.spriteHeight) == 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return (sheet.spritesheet.getWidth() / sheet.spriteWidth) + ((sheet.spritesheet.getWidth() % sheet.spriteWidth) == 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
return Image.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
return sheet.getImage((rowIndex * getColumnCount()) + columnIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
|
||||
}
|
||||
|
||||
List<TableModelListener> listeners = new ArrayList<TableModelListener>();
|
||||
|
||||
@Override
|
||||
public void addTableModelListener(TableModelListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTableModelListener(TableModelListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SpritesheetCellRenderer extends DefaultTableCellRenderer {
|
||||
private static final long serialVersionUID = -4213756343124247612L;
|
||||
Spritesheet sheet;
|
||||
public SpritesheetCellRenderer(Spritesheet sheet) {
|
||||
super();
|
||||
this.sheet = sheet;
|
||||
}
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
if (c instanceof JLabel) {
|
||||
((JLabel)c).setText("");
|
||||
if (value != null) {
|
||||
((JLabel)c).setIcon(new ImageIcon((Image)value));
|
||||
((JLabel)c).setToolTipText(sheet.id+":"+((row * table.getColumnCount())+column));
|
||||
}
|
||||
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean aFlag) {
|
||||
super.setVisible(aFlag);
|
||||
animate = aFlag;
|
||||
if (aFlag && animator != null) {
|
||||
resetAnimator();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetAnimator() {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
if (animator != null && animator.isAlive()) {
|
||||
try {
|
||||
animator.join();
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
animate = true;
|
||||
animator = new Thread() {
|
||||
public void run() {
|
||||
int i = -1;
|
||||
while (animate) {
|
||||
if (icons != null) {
|
||||
synchronized (icons) {
|
||||
i = (i + 1) % icons.size();
|
||||
iconLabel.setIcon(icons.get(i));
|
||||
}
|
||||
iconLabel.revalidate();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
};
|
||||
};
|
||||
animator.start();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
|
||||
public static class SpritesheetsBacklinksListModel implements ListModel {
|
||||
|
||||
Spritesheet sheet;
|
||||
|
||||
public SpritesheetsBacklinksListModel(Spritesheet sheet) {
|
||||
this.sheet = sheet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return sheet.getBacklinks().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
for (ProjectTreeNode node : sheet.getBacklinks()) {
|
||||
if (index == 0) return node;
|
||||
index --;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
public void fireListChanged() {
|
||||
for (ListDataListener l : listeners) {
|
||||
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, this.getSize()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class BacklinkCellRenderer extends DefaultListCellRenderer {
|
||||
|
||||
private static final long serialVersionUID = 6819681566800482793L;
|
||||
|
||||
private boolean includeType = false;
|
||||
|
||||
public BacklinkCellRenderer(boolean includeType) {
|
||||
super();
|
||||
this.includeType = includeType;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (value == null) {
|
||||
label.setText("none");
|
||||
} else {
|
||||
if (includeType && ((ProjectTreeNode)value).getDataType() != null) {
|
||||
label.setText(((ProjectTreeNode)value).getDataType().toString()+"/"+((ProjectTreeNode)value).getDesc());
|
||||
} else {
|
||||
label.setText(((ProjectTreeNode)value).getDesc());
|
||||
}
|
||||
if (((ProjectTreeNode)value).getIcon() == null) {
|
||||
Notification.addError("Unable to find icon for "+((ProjectTreeNode)value).getDesc());
|
||||
} else {
|
||||
label.setIcon(new ImageIcon(((ProjectTreeNode)value).getIcon()));
|
||||
}
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void targetUpdated() {
|
||||
this.icon = new ImageIcon(((Spritesheet)target).getIcon(0));
|
||||
this.name = ((Spritesheet)target).id;
|
||||
}
|
||||
|
||||
public class SpritesheetFieldUpdater implements FieldUpdateListener {
|
||||
@Override
|
||||
public void valueChanged(JComponent source, Object value) {
|
||||
Spritesheet sheet = (Spritesheet) target;
|
||||
if (source == widthField) {
|
||||
sheet.spriteWidth = (Integer) value;
|
||||
sheet.clearCache();
|
||||
updateView(spriteViewPane);
|
||||
spriteViewPane.revalidate();
|
||||
spriteViewPane.repaint();
|
||||
} else if (source == heightField) {
|
||||
sheet.spriteHeight = (Integer) value;
|
||||
sheet.clearCache();
|
||||
updateView(spriteViewPane);
|
||||
spriteViewPane.revalidate();
|
||||
spriteViewPane.repaint();
|
||||
} else if (source == animatedBox) {
|
||||
sheet.animated = (Boolean) value;
|
||||
if (!sheet.animated) {
|
||||
animate = false;
|
||||
}
|
||||
updateView(spriteViewPane);
|
||||
spriteViewPane.revalidate();
|
||||
spriteViewPane.repaint();
|
||||
} else if (source == categoryBox) {
|
||||
sheet.category = (Spritesheet.Category) value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.tools;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
|
||||
import com.gpl.rpg.atcontentstudio.ui.Editor;
|
||||
|
||||
public class ElementTableView extends Editor {
|
||||
|
||||
private static final long serialVersionUID = 8048693233599125878L;
|
||||
|
||||
public ElementTableView(TableModel elementTableModel, String title, Icon icon) {
|
||||
this.target = new DummyGDE();
|
||||
this.name = title;
|
||||
this.icon = icon;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
JTable table = new JTable(elementTableModel) {
|
||||
private static final long serialVersionUID = -2738230330859706440L;
|
||||
public boolean getScrollableTracksViewportWidth() {
|
||||
return getPreferredSize().width < getParent().getWidth();
|
||||
}
|
||||
};
|
||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
table.setAutoCreateRowSorter(true);
|
||||
table.setAutoscrolls(true);
|
||||
table.setCellSelectionEnabled(false);
|
||||
table.setRowSelectionAllowed(true);
|
||||
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
add(new JScrollPane(table), BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void targetUpdated() {
|
||||
|
||||
}
|
||||
|
||||
class DummyGDE extends GameDataElement {
|
||||
|
||||
private static final long serialVersionUID = 5889666999423783180L;
|
||||
|
||||
@Override
|
||||
public GameDataSet getDataSet() {return null;}
|
||||
|
||||
@Override
|
||||
public String getDesc() {return null;}
|
||||
|
||||
@Override
|
||||
public void parse() {}
|
||||
|
||||
@Override
|
||||
public void link() {}
|
||||
|
||||
@Override
|
||||
public GameDataElement clone() {return null;}
|
||||
|
||||
@Override
|
||||
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {}
|
||||
|
||||
@Override
|
||||
public String getProjectFilename() {return null;}
|
||||
|
||||
@Override
|
||||
public void save() {}
|
||||
|
||||
@Override
|
||||
public List<SaveEvent> attemptSave() {return null;}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
214
src/com/gpl/rpg/atcontentstudio/ui/tools/ItemsTableView.java
Normal file
214
src/com/gpl/rpg/atcontentstudio/ui/tools/ItemsTableView.java
Normal file
@@ -0,0 +1,214 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.tools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
|
||||
public class ItemsTableView extends ElementTableView {
|
||||
|
||||
private static final long serialVersionUID = 1474255176349837609L;
|
||||
|
||||
public ItemsTableView(Project proj) {
|
||||
super(new ItemsTableModel(proj), "Compare "+proj.getItemCount()+" items.", new ImageIcon(DefaultIcons.getItemIcon()));
|
||||
}
|
||||
|
||||
private static class ItemsTableModel implements TableModel {
|
||||
|
||||
Project proj;
|
||||
|
||||
public ItemsTableModel(Project proj) {
|
||||
this.proj = proj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
// return proj.getItemCount() + 1;
|
||||
return proj.getItemCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0: return "Icon"; //Icon
|
||||
case 1: return "ID"; //ID
|
||||
case 2: return "Name"; //Name
|
||||
case 3: return "Folder type"; //Source type (created, altered, source)
|
||||
case 4: return "Use type"; //Use type ("none", "use", or equip slot name).
|
||||
case 5: return "Category"; //Category id.
|
||||
case 6: return "Manually set price ?"; //Has manual price
|
||||
case 7: return "Price"; //Price
|
||||
case 8: return "On use/hit - HP min";
|
||||
case 9: return "On use/hit - HP max";
|
||||
case 10: return "On use/hit - AP min";
|
||||
case 11: return "On use/hit - AP max";
|
||||
case 12: return "On use/hit - # conditions";
|
||||
case 13: return "On kill - HP min";
|
||||
case 14: return "On kill - HP max";
|
||||
case 15: return "On kill - AP min";
|
||||
case 16: return "On kill - AP max";
|
||||
case 17: return "On kill - # conditions";
|
||||
case 18: return "AD min";
|
||||
case 19: return "AD max";
|
||||
case 20: return "Max HP";
|
||||
case 21: return "Max AP";
|
||||
case 22: return "Attack cost";
|
||||
case 23: return "AC";
|
||||
case 24: return "BC";
|
||||
case 25: return "DR";
|
||||
case 26: return "CS";
|
||||
case 27: return "CM";
|
||||
case 28: return "Move cost";
|
||||
case 29: return "Use cost";
|
||||
case 30: return "Reequip cost";
|
||||
case 31: return "# conditions";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
// return String.class;
|
||||
switch (columnIndex) {
|
||||
case 0: return Icon.class; // Icon
|
||||
case 1: return String.class; //ID
|
||||
case 2: return String.class; //Name
|
||||
case 3: return String.class; //Source type (created, altered, source)
|
||||
case 4: return String.class; //Use type ("none", "use", or equip slot name).
|
||||
case 5: return String.class; //Category id.
|
||||
case 6: return Boolean.class; //Has manual price
|
||||
case 7: return Integer.class; //Price
|
||||
case 8: return Integer.class;//"On use/hit - HP min";
|
||||
case 9: return Integer.class;//"On use/hit - HP max";
|
||||
case 10: return Integer.class;//"On use/hit - AP min";
|
||||
case 11: return Integer.class;//"On use/hit - AP max";
|
||||
case 12: return Integer.class;//"On use/hit - # conditions";
|
||||
case 13: return Integer.class;//"On kill - HP min";
|
||||
case 14: return Integer.class;//"On kill - HP max";
|
||||
case 15: return Integer.class;//"On kill - AP min";
|
||||
case 16: return Integer.class;//"On kill - AP max";
|
||||
case 17: return Integer.class;//"On kill - # conditions";
|
||||
case 18: return Integer.class;//"AD min";
|
||||
case 19: return Integer.class;//"AD max";
|
||||
case 20: return Integer.class;//"Max HP";
|
||||
case 21: return Integer.class;//"Max AP";
|
||||
case 22: return Integer.class;//"Attack cost";
|
||||
case 23: return Integer.class;//"AC";
|
||||
case 24: return Integer.class;//"BC";
|
||||
case 25: return Integer.class;//"DR";
|
||||
case 26: return Integer.class;//"CS";
|
||||
case 27: return Double.class;//"CM";
|
||||
case 28: return Integer.class;//"Move cost";
|
||||
case 29: return Integer.class;//"Use cost";
|
||||
case 30: return Integer.class;//"Reequip cost";
|
||||
case 31: return Integer.class;//"# conditions";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
// if (rowIndex == 0) {
|
||||
// return getColumnName(columnIndex);
|
||||
// }
|
||||
// Item item = proj.getItem(rowIndex - 1);
|
||||
Item item = proj.getItem(rowIndex);
|
||||
boolean canUse = item.category != null && item.category.action_type == ItemCategory.ActionType.use;
|
||||
boolean canEquip = item.category != null && item.category.action_type == ItemCategory.ActionType.equip;
|
||||
switch (columnIndex) {
|
||||
case 0: return new ImageIcon(item.getIcon()); //Icon
|
||||
case 1: return item.id; //ID
|
||||
case 2: return item.name; //Name
|
||||
case 3: return item.getDataType().toString(); //Source type (created, altered, source)
|
||||
case 4: //Use type ("none", "use", or equip slot name).
|
||||
if (item.category == null) return "none";
|
||||
if (item.category.action_type == null) return "none";
|
||||
if (item.category.action_type != ItemCategory.ActionType.equip) return item.category.action_type.toString();
|
||||
return item.category.slot.toString();
|
||||
case 5: return item.category != null ? item.category.id : (item.category_id != null ? item.category_id : null ); //Category id.
|
||||
case 6: return item.has_manual_price == null ? false : (item.has_manual_price == 1); //Has manual price
|
||||
case 7: //Price
|
||||
if (item.has_manual_price == null || item.has_manual_price != 1) return item.computePrice();
|
||||
return item.base_market_cost;
|
||||
case 8: return canUse ? (item.kill_effect != null ? item.kill_effect.hp_boost_min : null) : (item.hit_effect != null ? item.hit_effect.hp_boost_min : null);//"On use/hit - HP min";
|
||||
case 9: return canUse ? (item.kill_effect != null ? item.kill_effect.hp_boost_max : null) : (item.hit_effect != null ? item.hit_effect.hp_boost_max : null);//"On use/hit - HP max";
|
||||
case 10: return canUse ? (item.kill_effect != null ? item.kill_effect.ap_boost_min : null) : (item.hit_effect != null ? item.hit_effect.ap_boost_min : null);//"On use/hit - AP min";
|
||||
case 11: return canUse ? (item.kill_effect != null ? item.kill_effect.ap_boost_max : null) : (item.hit_effect != null ? item.hit_effect.ap_boost_max : null);//"On use/hit - AP max";
|
||||
case 12: //"On use/hit - # conditions";
|
||||
if (canUse) {
|
||||
if (item.kill_effect != null && item.kill_effect.conditions_source != null) {
|
||||
return item.kill_effect.conditions_source.size();
|
||||
}
|
||||
return 0;
|
||||
} else if (item.hit_effect != null) {
|
||||
int val = 0;
|
||||
if (item.hit_effect.conditions_source != null) {
|
||||
val += item.hit_effect.conditions_source.size();
|
||||
}
|
||||
if (item.hit_effect.conditions_target != null) {
|
||||
val += item.hit_effect.conditions_target.size();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
return null;
|
||||
case 13: return (!canUse && item.kill_effect != null) ? item.kill_effect.hp_boost_min : null;//"On kill - HP min";
|
||||
case 14: return (!canUse && item.kill_effect != null) ? item.kill_effect.hp_boost_max : null;//"On kill - HP max";
|
||||
case 15: return (!canUse && item.kill_effect != null) ? item.kill_effect.ap_boost_min : null;//"On kill - AP min";
|
||||
case 16: return (!canUse && item.kill_effect != null) ? item.kill_effect.ap_boost_max : null;//"On kill - AP max";
|
||||
case 17: return (!canUse && item.kill_effect != null && item.kill_effect.conditions_source != null) ? item.kill_effect.conditions_source.size() : null;//"On kill - # conditions";
|
||||
case 18: return (canEquip && item.equip_effect != null) ? item.equip_effect.damage_boost_min : null;//"AD min";
|
||||
case 19: return (canEquip && item.equip_effect != null) ? item.equip_effect.damage_boost_max : null;//"AD max";
|
||||
case 20: return (canEquip && item.equip_effect != null) ? item.equip_effect.max_hp_boost : null;//"Max HP";
|
||||
case 21: return (canEquip && item.equip_effect != null) ? item.equip_effect.max_ap_boost : null;//"Max AP";
|
||||
case 22: return (canEquip && item.equip_effect != null) ? item.equip_effect.increase_attack_cost : null;//"Attack cost";
|
||||
case 23: return (canEquip && item.equip_effect != null) ? item.equip_effect.increase_attack_chance : null;//"AC";
|
||||
case 24: return (canEquip && item.equip_effect != null) ? item.equip_effect.increase_block_chance : null;//"BC";
|
||||
case 25: return (canEquip && item.equip_effect != null) ? item.equip_effect.increase_damage_resistance : null;//"DR";
|
||||
case 26: return (canEquip && item.equip_effect != null) ? item.equip_effect.increase_critical_skill : null;//"CS";
|
||||
case 27: return (canEquip && item.equip_effect != null) ? item.equip_effect.critical_multiplier : null;//"CM";
|
||||
case 28: return (canEquip && item.equip_effect != null) ? item.equip_effect.increase_move_cost : null;//"Move cost";
|
||||
case 29: return (canEquip && item.equip_effect != null) ? item.equip_effect.increase_use_item_cost : null;//"Use cost";
|
||||
case 30: return (canEquip && item.equip_effect != null) ? item.equip_effect.increase_reequip_cost : null;//"Reequip cost";
|
||||
case 31: return (canEquip && item.equip_effect != null && item.equip_effect.conditions != null) ? item.equip_effect.conditions.size() : null;//"# conditions";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
//not editable.
|
||||
}
|
||||
|
||||
List<TableModelListener> listeners = new ArrayList<TableModelListener>();
|
||||
|
||||
@Override
|
||||
public void addTableModelListener(TableModelListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTableModelListener(TableModelListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
175
src/com/gpl/rpg/atcontentstudio/ui/tools/NPCsTableView.java
Normal file
175
src/com/gpl/rpg/atcontentstudio/ui/tools/NPCsTableView.java
Normal file
@@ -0,0 +1,175 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.tools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
||||
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
|
||||
|
||||
public class NPCsTableView extends ElementTableView {
|
||||
|
||||
private static final long serialVersionUID = -4196852140899079621L;
|
||||
|
||||
public NPCsTableView(Project proj) {
|
||||
super(new NPCsTableModel(proj), "Compare "+proj.getNPCCount()+" NPCs.", new ImageIcon(DefaultIcons.getNPCIcon()));
|
||||
}
|
||||
|
||||
private static class NPCsTableModel implements TableModel {
|
||||
|
||||
Project proj;
|
||||
|
||||
public NPCsTableModel(Project proj) {
|
||||
this.proj = proj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return proj.getNPCCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 25;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0: return "Icon"; //Icon
|
||||
case 1: return "ID"; //ID
|
||||
case 2: return "Name"; //Name
|
||||
case 3: return "Category type"; //Source type (created, altered, source)
|
||||
case 4: return "Unique";
|
||||
case 5: return "Class";
|
||||
case 6: return "Movement type";
|
||||
case 7: return "Spawngroup";
|
||||
case 8: return "Faction";
|
||||
case 9: return "HP";
|
||||
case 10: return "AP";
|
||||
case 11: return "Attack Cost";
|
||||
case 12: return "AC";
|
||||
case 13: return "BC";
|
||||
case 14: return "AD min";
|
||||
case 15: return "AD max";
|
||||
case 16: return "DR";
|
||||
case 17: return "CS";
|
||||
case 18: return "CM";
|
||||
case 19: return "On hit - HP min";
|
||||
case 20: return "On hit - HP max";
|
||||
case 21: return "On hit - AP min";
|
||||
case 22: return "On hit - AP max";
|
||||
case 23: return "On hit - # conditions";
|
||||
case 24: return "Experience reward";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 0: return Icon.class; //Icon
|
||||
case 1: return String.class; //ID
|
||||
case 2: return String.class; //Name
|
||||
case 3: return String.class; //Source type (created, altered, source)
|
||||
case 4: return Boolean.class; //"Unique";
|
||||
case 5: return String.class; //"Class";
|
||||
case 6: return String.class; //"Movement type";
|
||||
case 7: return String.class; //"Spawngroup";
|
||||
case 8: return String.class; //"Faction";
|
||||
case 9: return Integer.class; //"HP";
|
||||
case 10: return Integer.class; //"AP";
|
||||
case 11: return Integer.class; //"Attack Cost";
|
||||
case 12: return Integer.class; //"AC";
|
||||
case 13: return Integer.class; //"BC";
|
||||
case 14: return Integer.class; //"AD min";
|
||||
case 15: return Integer.class; //"AD max";
|
||||
case 16: return Integer.class; //"DR";
|
||||
case 17: return Integer.class; //"CS";
|
||||
case 18: return Double.class; //"CM";
|
||||
case 19: return Integer.class; //"On hit - HP min";
|
||||
case 20: return Integer.class; //"On hit - HP max";
|
||||
case 21: return Integer.class; //"On hit - AP min";
|
||||
case 22: return Integer.class; //"On hit - AP max";
|
||||
case 23: return Integer.class; //"On hit - # conditions";
|
||||
case 24: return Integer.class; //"Experience reward";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
NPC npc = proj.getNPC(rowIndex);
|
||||
switch (columnIndex) {
|
||||
case 0: return new ImageIcon(npc.getIcon()); // Icon
|
||||
case 1: return npc.id; //ID
|
||||
case 2: return npc.name; //Name
|
||||
case 3: return npc.getDataType().toString(); //Source type (created, altered, source)
|
||||
case 4: return npc.unique != null && npc.unique == 1;//"Unique";
|
||||
case 5: return npc.monster_class != null ? npc.monster_class.toString() : null; //"Class";
|
||||
case 6: return npc.movement_type != null ? npc.movement_type.toString() : null; //"Movement type";
|
||||
case 7: return npc.spawngroup_id; //"Spawngroup";
|
||||
case 8: return npc.faction_id; //"Faction";
|
||||
case 9: return npc.max_hp; //"HP";
|
||||
case 10: return npc.max_ap; //"AP";
|
||||
case 11: return npc.attack_cost; //"Attack Cost";
|
||||
case 12: return npc.attack_chance; //"AC";
|
||||
case 13: return npc.block_chance; //"BC";
|
||||
case 14: return npc.attack_damage_min; //"AD min";
|
||||
case 15: return npc.attack_damage_max; //"AD max";
|
||||
case 16: return npc.damage_resistance; //"DR";
|
||||
case 17: return npc.critical_skill; //"CS";
|
||||
case 18: return npc.critical_multiplier; //"CM";
|
||||
case 19: return npc.hit_effect != null ? npc.hit_effect.hp_boost_min : null; //"On hit - HP min";
|
||||
case 20: return npc.hit_effect != null ? npc.hit_effect.hp_boost_max : null; //"On hit - HP max";
|
||||
case 21: return npc.hit_effect != null ? npc.hit_effect.ap_boost_min : null; //"On hit - AP min";
|
||||
case 22: return npc.hit_effect != null ? npc.hit_effect.ap_boost_max : null; //"On hit - AP max";
|
||||
case 23: //"On hit - # conditions";
|
||||
if (npc.hit_effect != null) {
|
||||
Integer val = null;
|
||||
if (npc.hit_effect.conditions_source != null) {
|
||||
val = npc.hit_effect.conditions_source.size();
|
||||
}
|
||||
if (npc.hit_effect.conditions_target != null) {
|
||||
if (val == null) val = npc.hit_effect.conditions_target.size();
|
||||
else val += npc.hit_effect.conditions_target.size();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
return null;
|
||||
case 24: return npc.getMonsterExperience();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
//not editable.
|
||||
}
|
||||
|
||||
List<TableModelListener> listeners = new ArrayList<TableModelListener>();
|
||||
|
||||
@Override
|
||||
public void addTableModelListener(TableModelListener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTableModelListener(TableModelListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user