Compare commits

...

13 Commits

Author SHA1 Message Date
Zukero
00c05e7507 Fixed Dialogue Tree bug and spacing issues.
v0.6.14 released.
Dialogue Tree bug caused by copy-pasting code created NPEs when not
activating translator mode. Made Dialogue Tree node spacing double when
activating translator mode.
2018-09-17 20:55:18 +02:00
Zukero
1b01ecd37d Version number missing in that file.... 2018-09-15 15:05:53 +02:00
Zukero
da5b686672 v0.6.13 2018-09-15 14:39:56 +02:00
Zukero
0a3da17d47 First implementation of a bookmarks system.
Not persistent yet, so you lose them all when you close ATCS.
2018-09-13 13:34:04 +02:00
Zukero
bf42f86408 Made dialogue-tree translations loading asynchronous.
Fixed quote escaping issue in english.pot generation tool.
2018-09-13 09:39:42 +02:00
Zukero
aa543bc111 Merge pull request #6 from zizkin/master
Translations
2018-09-10 10:07:27 +02:00
Jiri Zizkin Zizka
f4041ee2c7 Add myself to contributors 2018-09-10 10:02:16 +02:00
Zukero
3e8d578474 Enhanced translation-related tools.
No UI, because there's limited interest for typical users, so it's a
beanshell-only tool for now.
2018-09-08 15:37:29 +02:00
Jiri Zizkin Zizka
67b8acd20b Code more human readable 2018-09-06 22:16:33 +02:00
Jiri Zizkin Zizka
d1612269c0 Update to translation in DialogueGraphView 2018-09-06 16:12:58 +02:00
Jiri Zizkin Zizka
f95327bd12 Show translated text from Weblate in DialogueGraphView 2018-08-29 20:45:47 +02:00
Jiri Zizkin Zizka
e0425e335d Bugfix: Add missing listener in WorkspaceSettingsEditor for more intuitive behaviour of translator mode 2018-08-29 20:33:37 +02:00
Zukero
3800bf8ff0 Added code to generate new english.pot file and some tools to ease
transition of existing translations towards the new content.
2018-08-10 23:45:50 +02:00
35 changed files with 1801 additions and 13 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jardesc>
<jar path="ATContentStudio/ATCS_v0.6.12.jar"/>
<jar path="ATContentStudio/ATCS_v0.6.14.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/ATContentStudio/ATCS_JAR.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
<selectedProjects/>

Binary file not shown.

View File

@@ -1 +1 @@
v0.6.11
v0.6.14

View File

@@ -1,6 +1,6 @@
!include MUI2.nsh
!define VERSION "0.6.12"
!define VERSION "0.6.14"
!define TRAINER_VERSION "0.1.4"
!define JAVA_BIN "javaw"

View File

@@ -43,7 +43,7 @@ import com.gpl.rpg.atcontentstudio.ui.WorkspaceSelector;
public class ATContentStudio {
public static final String APP_NAME = "Andor's Trail Content Studio";
public static final String APP_VERSION = "v0.6.12";
public static final String APP_VERSION = "v0.6.14";
public static final String CHECK_UPDATE_URL = "https://andorstrail.com/static/ATCS_latest";
public static final String DOWNLOAD_URL = "https://andorstrail.com/viewtopic.php?f=6&t=4806";

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -11,6 +11,8 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.model.bookmarks.BookmarkEntry;
public abstract class GameDataElement implements ProjectTreeNode, Serializable {
private static final long serialVersionUID = 2028934451226743389L;
@@ -31,6 +33,8 @@ public abstract class GameDataElement implements ProjectTreeNode, Serializable {
public boolean writable = false;
public BookmarkEntry bookmark = null;
//List of objects whose transition to "linked" state made them point to this instance.
private Map<GameDataElement, Integer> backlinks = new ConcurrentHashMap<GameDataElement, Integer>();

View File

@@ -48,6 +48,7 @@ import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.io.JsonPrettyWriter;
import com.gpl.rpg.atcontentstudio.io.SettingsSave;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.bookmarks.BookmarksRoot;
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
@@ -87,6 +88,8 @@ public class Project implements ProjectTreeNode, Serializable {
public GameSource referencedContent; //Pointers to base content
public transient GameSource alteredContent; //Copied from base content (does not overwrite yet)
public transient GameSource createdContent; //Stand-alone.
public transient BookmarksRoot bookmarks;
public SavedGamesSet saves; //For simulations.
@@ -135,6 +138,7 @@ public class Project implements ProjectTreeNode, Serializable {
alteredContent = new GameSource(this, GameSource.Type.altered);
createdContent = new GameSource(this, GameSource.Type.created);
bookmarks = new BookmarksRoot(this);
saves = new SavedGamesSet(this);
@@ -143,6 +147,7 @@ public class Project implements ProjectTreeNode, Serializable {
// v.add(referencedContent);
v.add(baseContent);
v.add(saves);
v.add(bookmarks);
linkAll();
@@ -262,6 +267,7 @@ public class Project implements ProjectTreeNode, Serializable {
// referencedContent.refreshTransients(this);
alteredContent = new GameSource(this, GameSource.Type.altered);
createdContent = new GameSource(this, GameSource.Type.created);
bookmarks = new BookmarksRoot(this);
saves.refreshTransients();
@@ -271,6 +277,7 @@ public class Project implements ProjectTreeNode, Serializable {
// v.add(referencedContent);
v.add(baseContent);
v.add(saves);
v.add(bookmarks);
linkAll();
@@ -970,6 +977,10 @@ public class Project implements ProjectTreeNode, Serializable {
fireElementAdded(node, getNodeIndex(node));
}
public void bookmark(GameDataElement gde) {
bookmarks.addBookmark(gde);
}
@Override
public GameDataSet getDataSet() {

View File

@@ -38,7 +38,7 @@ public class WorkspaceSettings {
public static String DEFAULT_IMG_EDITOR_COMMAND = "gimp";
public Setting<String> imageEditorCommand = new PrimitiveSetting<String>("imageEditorCommand", DEFAULT_IMG_EDITOR_COMMAND);
public static String[] LANGUAGE_LIST = new String[]{null, "de", "ru", "pl", "fr", "it", "es", "nl", "uk", "ca", "sv", "pt", "pt_BR", "zh_Hant", "zh_Hans", "ja", "cs", "tr", "ko", "hu", "sl", "bg", "id", "fi", "th", "gl", "ms" ,"pa", "az"};
public static String[] LANGUAGE_LIST = new String[]{null, "de", "ru", "pl", "fr", "it", "es", "nl", "uk", "ca", "sv", "pt", "pt_BR", "zh_Hant", "zh_Hans", "ja", "cs", "tr", "ko", "hu", "sl", "bg", "id", "fi", "th", "gl", "ms" ,"pa", "az", "nb"};
public Setting<String> translatorLanguage = new NullDefaultPrimitiveSetting<String>("translatorLanguage");
public static Boolean DEFAULT_ALLOW_INTERNET = true;
public Setting<Boolean> useInternet = new PrimitiveSetting<Boolean>("useInternet", DEFAULT_ALLOW_INTERNET);

View File

@@ -0,0 +1,155 @@
package com.gpl.rpg.atcontentstudio.model.bookmarks;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage;
public class BookmarkEntry implements BookmarkNode {
public GameDataElement bookmarkedElement;
public BookmarkFolder parent;
public BookmarkEntry(BookmarkFolder parent, GameDataElement target) {
this.parent = parent;
this.bookmarkedElement = target;
target.bookmark = this;
parent.contents.add(this);
}
@Override
public Enumeration<ProjectTreeNode> children() {
return null;
}
@Override
public boolean getAllowsChildren() {
return false;
}
@Override
public TreeNode getChildAt(int childIndex) {
return null;
}
@Override
public int getChildCount() {
return 0;
}
@Override
public int getIndex(TreeNode node) {
return 0;
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenAdded(path);
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenChanged(path);
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenRemoved(path);
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
}
@Override
public String getDesc() {
if (bookmarkedElement instanceof QuestStage) {
String text = ((GameDataElement)bookmarkedElement).getDesc();
if (text.length() > 60) {
text = text.substring(0, 57)+"...";
}
return ((GameDataElement)bookmarkedElement).getDataType().toString()+"/"+((Quest)((QuestStage)bookmarkedElement).parent).id+"#"+((QuestStage)bookmarkedElement).progress+":"+text;
} else {
return ((GameDataElement)bookmarkedElement).getDataType().toString()+"/"+((GameDataElement)bookmarkedElement).getDesc();
}
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Image getIcon() {
return bookmarkedElement.getIcon();
}
@Override
public Image getOpenIcon() {
return null;
}
@Override
public Image getClosedIcon() {
return null;
}
@Override
public Image getLeafIcon() {
return getIcon();
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean needsSaving() {
return false;
}
public void delete() {
bookmarkedElement.bookmark = null;
parent.delete(this);
}
@Override
public void save() {
parent.save();
}
}

View File

@@ -0,0 +1,168 @@
package com.gpl.rpg.atcontentstudio.model.bookmarks;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
public class BookmarkFolder implements BookmarkNode {
List<BookmarkNode> contents = new LinkedList<BookmarkNode>();
BookmarkNode parent;
String name;
Image closedIcon, openIcon;
public BookmarkFolder(BookmarkNode parent, String name) {
this(parent, name, DefaultIcons.getStdClosedIcon(), DefaultIcons.getStdOpenIcon());
}
public BookmarkFolder(BookmarkNode parent, String name, Image closedIcon, Image openIcon) {
this.parent = parent;
this.name = name;
this.closedIcon = closedIcon;
this.openIcon = openIcon;
}
@Override
public Enumeration<? extends ProjectTreeNode> children() {
return Collections.enumeration(contents);
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int childIndex) {
return contents.get(childIndex);
}
@Override
public int getChildCount() {
return contents.size();
}
@Override
public int getIndex(TreeNode node) {
return contents.indexOf(node);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenAdded(path);
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0,this);
parent.childrenChanged(path);
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
if (path.size() == 1 && this.getChildCount() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
}
@Override
public String getDesc() {
return name;
}
@Override
public Project getProject() {
return parent.getProject();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Image getIcon() {
return getClosedIcon();
}
@Override
public Image getOpenIcon() {
return openIcon;
}
@Override
public Image getClosedIcon() {
return closedIcon;
}
@Override
public Image getLeafIcon() {
return getClosedIcon();
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return contents.isEmpty();
}
@Override
public boolean needsSaving() {
return false;
}
public void delete(BookmarkEntry bookmarkEntry) {
if (contents.contains(bookmarkEntry)) {
bookmarkEntry.childrenRemoved(new ArrayList<ProjectTreeNode>());
contents.remove(bookmarkEntry);
save();
}
}
public void delete(BookmarkFolder bookmarkFolder) {
// TODO Auto-generated method stub
}
public void save() {
parent.save();
}
public void delete() {
}
}

View File

@@ -0,0 +1,10 @@
package com.gpl.rpg.atcontentstudio.model.bookmarks;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
public interface BookmarkNode extends ProjectTreeNode{
public void save();
public void delete();
}

View File

@@ -0,0 +1,210 @@
package com.gpl.rpg.atcontentstudio.model.bookmarks;
import java.awt.Image;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.SavedSlotCollection;
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.GameDataSet;
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
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.sprites.Spritesheet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
public class BookmarksRoot implements BookmarkNode {
SavedSlotCollection v = new SavedSlotCollection();
public transient Project parent = null;
BookmarkFolder ac, diag, dl, it, ic, npc, q, tmx, sp, wm;
public BookmarksRoot(Project parent) {
this.parent = parent;
v.add(ac = new BookmarkFolder(this, ActorCondition.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(diag = new BookmarkFolder(this, Dialogue.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(dl = new BookmarkFolder(this, Droplist.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(it = new BookmarkFolder(this, Item.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(ic = new BookmarkFolder(this, ItemCategory.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(npc = new BookmarkFolder(this, NPC.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(q = new BookmarkFolder(this, Quest.getStaticDesc(), DefaultIcons.getJsonClosedIcon(), DefaultIcons.getJsonOpenIcon()));
v.add(tmx = new BookmarkFolder(this, "TMX Maps", DefaultIcons.getTmxClosedIcon(), DefaultIcons.getTmxOpenIcon()));
v.add(sp = new BookmarkFolder(this, "Spritesheets", DefaultIcons.getSpriteClosedIcon(), DefaultIcons.getSpriteOpenIcon()));
v.add(wm = new BookmarkFolder(this, "Worldmap", DefaultIcons.getSpriteClosedIcon(), DefaultIcons.getSpriteOpenIcon()));
}
@Override
public Enumeration<ProjectTreeNode> children() {
return v.getNonEmptyElements();
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public TreeNode getChildAt(int arg0) {
return v.getNonEmptyElementAt(arg0);
}
@Override
public int getChildCount() {
return v.getNonEmptySize();
}
@Override
public int getIndex(TreeNode arg0) {
return v.getNonEmptyIndexOf((ProjectTreeNode) arg0);
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public void childrenAdded(List<ProjectTreeNode> path) {
path.add(0, this);
parent.childrenAdded(path);
}
@Override
public void childrenChanged(List<ProjectTreeNode> path) {
path.add(0, this);
parent.childrenChanged(path);
}
@Override
public void childrenRemoved(List<ProjectTreeNode> path) {
if (path.size() == 1 && this.v.getNonEmptySize() == 1) {
childrenRemoved(new ArrayList<ProjectTreeNode>());
} else {
path.add(0, this);
parent.childrenRemoved(path);
}
}
@Override
public void notifyCreated() {
childrenAdded(new ArrayList<ProjectTreeNode>());
for (ProjectTreeNode node : v.getNonEmptyIterable()) {
node.notifyCreated();
}
}
@Override
public String getDesc() {
return (needsSaving() ? "*" : "")+"Bookmarks";
}
@Override
public Project getProject() {
return parent == null ? null : parent.getProject();
}
@Override
public GameDataSet getDataSet() {
return null;
}
@Override
public Image getIcon() {
return getOpenIcon();
}
@Override
public Image getOpenIcon() {
return DefaultIcons.getBookmarkOpenIcon();
}
@Override
public Image getClosedIcon() {
return DefaultIcons.getBookmarkClosedIcon();
}
@Override
public Image getLeafIcon() {
return getClosedIcon();
}
@Override
public Type getDataType() {
return null;
}
@Override
public boolean isEmpty() {
return v.isEmpty();
}
@Override
public boolean needsSaving() {
return false;
}
public void save() {
}
@Override
public void delete() {}
public void addBookmark(GameDataElement target) {
BookmarkEntry node;
BookmarkFolder folder = null;
if (target instanceof ActorCondition) {
folder = ac;
} else if (target instanceof Dialogue) {
folder = diag;
} else if (target instanceof Droplist) {
folder = dl;
} else if (target instanceof Item) {
folder = it;
} else if (target instanceof ItemCategory) {
folder = ic;
} else if (target instanceof NPC) {
folder = npc;
} else if (target instanceof Quest) {
folder = q;
} else if (target instanceof TMXMap) {
folder = tmx;
} else if (target instanceof Spritesheet) {
folder = sp;
} else if (target instanceof WorldmapSegment) {
folder = wm;
} else {
return;
}
ProjectTreeNode higherEmptyParent = folder;
while (higherEmptyParent != null) {
if (higherEmptyParent.getParent() != null && ((ProjectTreeNode)higherEmptyParent.getParent()).isEmpty()) higherEmptyParent = (ProjectTreeNode)higherEmptyParent.getParent();
else break;
}
if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null;
node = new BookmarkEntry(folder, target);
if (higherEmptyParent != null) higherEmptyParent.notifyCreated();
else node.notifyCreated();
}
}

View File

@@ -51,6 +51,7 @@ public class AboutEditor extends Editor {
"<br/>" +
"Contributors: <br/>" +
"Quentin Delvallet<br/>" +
"<EFBFBD>i<EFBFBD>kin<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/>" +
@@ -78,6 +79,9 @@ public class AboutEditor extends Editor {
"<a href=\"https://jsoup.org/\">jsoup</a> by Jonathan Hedley<br/>" +
"License: <a href=\"https://jsoup.org/license\">MIT License</a><br/>" +
"<br/>" +
"A slightly modified version of <a href=\"https://launchpad.net/po-parser\">General PO Parser</a> by Bal<61>zs T<>th<br/>" +
"License: <a href=\"http://www.gnu.org/licenses/gpl-3.0.html\">GPL v3</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/>" +
@@ -129,6 +133,7 @@ public class AboutEditor extends Editor {
editorTabsHolder.add("BeanShell License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.LGPLv3.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
editorTabsHolder.add("SipHash for Java License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.siphash-zackehh.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
editorTabsHolder.add("jsoup License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.jsoup.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
editorTabsHolder.add("General PO Parser License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.GPLv3.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"));
}

View File

@@ -75,6 +75,14 @@ public class DefaultIcons {
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 FOLDER_BOOKMARK_CLOSED_RES = "/com/gpl/rpg/atcontentstudio/img/folder_bookmark_closed.png";
public static Image getBookmarkClosedImage() { return getImage(FOLDER_BOOKMARK_CLOSED_RES); }
public static Image getBookmarkClosedIcon() { return getIcon(FOLDER_BOOKMARK_CLOSED_RES); }
private static String FOLDER_BOOKMARK_OPEN_RES = "/com/gpl/rpg/atcontentstudio/img/folder_bookmark_open.png";
public static Image getBookmarkOpenImage() { return getImage(FOLDER_BOOKMARK_OPEN_RES); }
public static Image getBookmarkOpenIcon() { return getIcon(FOLDER_BOOKMARK_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); }
@@ -276,6 +284,14 @@ public class DefaultIcons {
public static Image getStatusUnknownImage() { return getImage(STATUS_UNKNOWN_RES); }
public static Image getStatusUnknownIcon() { return getIcon(STATUS_UNKNOWN_RES); }
private static String BOOKMARK_INACTIVE = "/com/gpl/rpg/atcontentstudio/img/bookmark_inactive.png";
public static Image getBookmarkInactiveImage() { return getImage(BOOKMARK_INACTIVE); }
public static Image getBookmarkInactiveIcon() { return getIcon(BOOKMARK_INACTIVE); }
private static String BOOKMARK_ACTIVE = "/com/gpl/rpg/atcontentstudio/img/bookmark_active.png";
public static Image getBookmarkActiveImage() { return getImage(BOOKMARK_ACTIVE); }
public static Image getBookmarkActiveIcon() { return getIcon(BOOKMARK_ACTIVE); }
private static Image getImage(String res) {
if (imageCache.get(res) == null) {

View File

@@ -812,7 +812,7 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
if (text.length() > 60) {
text = text.substring(0, 57)+"...";
}
label.setText(((GameDataElement)value).getDataType().toString()+"/"+((Quest)((QuestStage)value).parent).id+":"+text);
label.setText(((GameDataElement)value).getDataType().toString()+"/"+((Quest)((QuestStage)value).parent).id+"#"+((QuestStage)value).progress+":"+text);
} else {
label.setText(((GameDataElement)value).getDataType().toString()+"/"+((GameDataElement)value).getDesc());
}

View File

@@ -33,6 +33,7 @@ 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.bookmarks.BookmarkEntry;
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
@@ -595,6 +596,8 @@ public class ProjectsTree extends JPanel {
ATContentStudio.frame.openEditor((WorldmapSegment)node);
} else if (node instanceof WriterModeData) {
ATContentStudio.frame.openEditor((WriterModeData)node);
} else if (node instanceof BookmarkEntry) {
ATContentStudio.frame.openEditor(((BookmarkEntry)node).bookmarkedElement);
} else if (node instanceof SavedGame) {
if (konamiCodeEntered) {
ATContentStudio.frame.openEditor((SavedGame)node);

View File

@@ -213,6 +213,8 @@ public class StudioFrame extends JFrame {
openEditor((Spritesheet) node);
} else if (node instanceof TMXMap) {
openEditor((TMXMap) node);
} else if (node instanceof WorldmapSegment) {
openEditor((WorldmapSegment) node);
} else if (node instanceof WriterModeData) {
openEditor((WriterModeData) node);
}

View File

@@ -182,12 +182,19 @@ public class WorkspaceSettingsEditor extends JDialog {
useInternetBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
translatorLanguagesBox.setEnabled(useInternetBox.isSelected());
translatorLanguagesBox.setEnabled(useInternetBox.isSelected() && translatorModeBox.isSelected());
translatorModeBox.setEnabled(useInternetBox.isSelected());
checkUpdatesBox.setEnabled(useInternetBox.isSelected());
}
});
translatorModeBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
translatorLanguagesBox.setEnabled(translatorModeBox.isSelected());
}
});
return pane;
}

View File

@@ -204,6 +204,7 @@ public abstract class JSONElementEditor extends Editor {
}
});
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);
@@ -242,8 +243,10 @@ public abstract class JSONElementEditor extends Editor {
}
JButton prev = new JButton(new ImageIcon(DefaultIcons.getArrowLeftIcon()));
JButton next = new JButton(new ImageIcon(DefaultIcons.getArrowRightIcon()));
final JButton bookmark = new JButton(new ImageIcon(node.bookmark != null ? DefaultIcons.getBookmarkActiveIcon() : DefaultIcons.getBookmarkInactiveIcon()));
savePane.add(prev, JideBoxLayout.FIX);
savePane.add(next, JideBoxLayout.FIX);
savePane.add(bookmark, JideBoxLayout.FIX);
if (node.getParent().getIndex(node) == 0) {
prev.setEnabled(false);
}
@@ -268,6 +271,20 @@ public abstract class JSONElementEditor extends Editor {
}
}
});
bookmark.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (node.bookmark == null) {
node.getProject().bookmark(node);
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkActiveIcon()));
} else {
node.bookmark.delete();
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkInactiveIcon()));
}
}
});
//Placeholder. Fills the eventual remaining space.
savePane.add(new JPanel(), JideBoxLayout.VARY);
pane.add(savePane, JideBoxLayout.FIX);

View File

@@ -49,11 +49,14 @@ import prefuse.visual.expression.InGroupPredicate;
import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.Workspace;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.DialogueEditor;
import com.gpl.rpg.atcontentstudio.utils.WeblateIntegration;
import com.gpl.rpg.atcontentstudio.utils.WeblateIntegration.WeblateTranslationUnit;
import com.jidesoft.swing.JideBoxLayout;
public class DialogueGraphView extends Display {
@@ -72,11 +75,16 @@ public class DialogueGraphView extends Display {
public static final String HIDDEN_REPLY = "hidden_reply";
public static final String HAS_REQS = "has_reqs";
private static final String TRANSLATION_LOADING="Loading translation...";
private String translationHeader="\n---[ Translation from weblate ]---\n";
private static final Schema DECORATOR_SCHEMA = PrefuseLib.getVisualItemSchema();
private Dialogue dialogue;
private Image npcIcon;
private Graph graph;
private Boolean translatorMode;
private Map<Dialogue, Node> cells = new HashMap<Dialogue, Node>();
@@ -88,6 +96,10 @@ public class DialogueGraphView extends Display {
} else {
npcIcon = DefaultIcons.getNPCIcon();
}
translatorMode = Workspace.activeWorkspace.settings.useInternet.getCurrentValue() && Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null;
if (translatorMode) {
translationHeader = "\n---[ Translation in "+Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue()+" ]---\n";
}
loadGraph();
// add visual data groups
@@ -148,7 +160,7 @@ public class DialogueGraphView extends Display {
// 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);
NodeLinkTreeLayout treeLayout = new NodeLinkTreeLayout(GRAPH, prefuse.Constants.ORIENT_LEFT_RIGHT, 120, translatorMode ? 80 : 40, translatorMode ? 80 : 40);
treeLayout.setLayoutAnchor(new Point2D.Double(25,300));
layout.add(treeLayout);
layout.add(new EdgesLabelDecoratorLayout(EDGES_LABELS));
@@ -186,9 +198,26 @@ public class DialogueGraphView extends Display {
if (dialogue.switch_to_npc != null) {
npcIcon = dialogue.switch_to_npc.getIcon();
}
Node dNode = graph.addNode();
final Node dNode = graph.addNode();
cells.put(dialogue, dNode);
dNode.setString(LABEL, dialogue.message != null ? dialogue.message : "[Selector]");
String label;
Thread t = null;
if (dialogue.message == null) {
label = "[Selector]";
} else if (translatorMode) {
label = dialogue.message+translationHeader+TRANSLATION_LOADING;
final String message = dialogue.message;
t = new Thread("Get weblate translation for "+message) {
public void run() {
WeblateTranslationUnit unit = WeblateIntegration.getTranslationUnit(message);
dNode.setString(LABEL, message+translationHeader+unit.translatedText);
};
};
} else {
label = dialogue.message;
}
dNode.setString(LABEL, label);
if (t != null) t.start();
dNode.set(ICON, npcIcon);
dNode.set(TARGET, dialogue);
if (dialogue.replies != null) {
@@ -206,11 +235,27 @@ public class DialogueGraphView extends Display {
}
public Node addReply(Dialogue d, Dialogue.Reply r, Image npcIcon) {
Node rNode;
final 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.setString(LABEL, translatorMode ? r.text + "\n---\n" + WeblateIntegration.getTranslationUnit(r.text).translatedText : r.text);
String label;
Thread t = null;
if (translatorMode) {
label = r.text+translationHeader+TRANSLATION_LOADING;
final String message = r.text;
t = new Thread("Get weblate translation for "+message) {
public void run() {
WeblateTranslationUnit unit = WeblateIntegration.getTranslationUnit(message);
rNode.setString(LABEL, message+translationHeader+unit.translatedText);
};
};
} else {
label = r.text;
}
rNode.setString(LABEL, label);
if (t != null) t.start();
rNode.set(ICON, DefaultIcons.getHeroIcon());
rNode.set(TARGET, d);
rNode.set(REPLY, r);

View File

@@ -1779,6 +1779,20 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
}
});
savePane.add(delete, JideBoxLayout.FIX);
final JButton bookmark = new JButton(new ImageIcon(map.bookmark != null ? DefaultIcons.getBookmarkActiveIcon() : DefaultIcons.getBookmarkInactiveIcon()));
savePane.add(bookmark, JideBoxLayout.FIX);
bookmark.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (map.bookmark == null) {
map.getProject().bookmark(map);
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkActiveIcon()));
} else {
map.bookmark.delete();
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkInactiveIcon()));
}
}
});
} else {
if (proj.getMap(map.id) != map) {
savePane.add(message = new JLabel(ALTERED_EXISTS_MESSAGE), JideBoxLayout.FIX);
@@ -1842,6 +1856,20 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
}
}
});
final JButton bookmark = new JButton(new ImageIcon(map.bookmark != null ? DefaultIcons.getBookmarkActiveIcon() : DefaultIcons.getBookmarkInactiveIcon()));
savePane.add(bookmark, JideBoxLayout.FIX);
bookmark.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (map.bookmark == null) {
map.getProject().bookmark(map);
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkActiveIcon()));
} else {
map.bookmark.delete();
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkInactiveIcon()));
}
}
});
//Placeholder. Fills the eventual remaining space.
savePane.add(new JPanel(), JideBoxLayout.VARY);
pane.add(savePane, JideBoxLayout.FIX);

View File

@@ -986,6 +986,20 @@ public class WorldMapEditor extends Editor implements FieldUpdateListener {
}
}
});
final JButton bookmark = new JButton(new ImageIcon(node.bookmark != null ? DefaultIcons.getBookmarkActiveIcon() : DefaultIcons.getBookmarkInactiveIcon()));
savePane.add(bookmark, JideBoxLayout.FIX);
bookmark.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (node.bookmark == null) {
node.getProject().bookmark(node);
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkActiveIcon()));
} else {
node.bookmark.delete();
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkInactiveIcon()));
}
}
});
//Placeholder. Fills the eventual remaining space.
savePane.add(new JPanel(), JideBoxLayout.VARY);
return savePane;

View File

@@ -100,6 +100,20 @@ public class SpritesheetEditor extends Editor {
});
buttonPane.add(openImage, JideBoxLayout.FIX);
buttonPane.add(getWarningLabel(), JideBoxLayout.FIX);
final JButton bookmark = new JButton(new ImageIcon(sheet.bookmark != null ? DefaultIcons.getBookmarkActiveIcon() : DefaultIcons.getBookmarkInactiveIcon()));
buttonPane.add(bookmark, JideBoxLayout.FIX);
bookmark.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (target.bookmark == null) {
target.getProject().bookmark(target);
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkActiveIcon()));
} else {
target.bookmark.delete();
bookmark.setIcon(new ImageIcon(DefaultIcons.getBookmarkInactiveIcon()));
}
}
});
buttonPane.add(new JPanel(), JideBoxLayout.VARY);
pane.add(buttonPane, JideBoxLayout.FIX);
addLabelField(pane, "Spritesheet ID: ", sheet.id);

View File

@@ -0,0 +1,86 @@
package com.gpl.rpg.atcontentstudio.ui.tools.i18n;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class PoPotWriter {
Map<String, List<String>> stringsResources = new LinkedHashMap<String, List<String>>();
Map<String, String> translations = new LinkedHashMap<String, String>();
File f;
public static void writePoFile(Map<String, List<String>> stringsResources, Map<String, String> translations, File destination) {
try {
FileWriter fw = new FileWriter(destination);
if (translations.get("") != null) {
fw.write(translations.get(""));
writeEndOfEntry(fw);
}
if (translations.get("translator-credits") != null) {
List<String> refs = new LinkedList<String>();
refs.add("[none]");
writeReferences(fw, refs);
writeMsgId(fw, "translator-credits");
writeMsgStr(fw, translations.get("translator-credits"));
writeEndOfEntry(fw);
}
for (String msg : stringsResources.keySet()) {
writeReferences(fw, stringsResources.get(msg));
writeMsgId(fw, msg);
writeMsgStr(fw, translations.get(msg));
writeEndOfEntry(fw);
}
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writePotFile(Map<String, List<String>> stringsResources, File destination) {
try {
FileWriter fw = new FileWriter(destination);
for (String msg : stringsResources.keySet()) {
writeReferences(fw, stringsResources.get(msg));
writeMsgId(fw, msg);
writeMsgStr(fw, "");
writeEndOfEntry(fw);
}
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeReferences(Writer w, List<String> references) throws IOException {
for (String ref : references) {
w.write("#: ");
w.write(ref);
w.write("\n");
}
}
private static void writeMsgId(Writer w, String msg) throws IOException {
w.write("msgid \"");
w.write(msg);
w.write("\"\n");
}
private static void writeMsgStr(Writer w, String translation) throws IOException {
w.write("msgstr \"");
w.write(translation == null ? "" : translation);
w.write("\"\n");
}
private static void writeEndOfEntry(Writer w) throws IOException {
w.write("\n");
}
}

View File

@@ -0,0 +1,310 @@
package com.gpl.rpg.atcontentstudio.ui.tools.i18n;
import java.io.File;
import java.io.FileFilter;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.swing.JOptionPane;
import com.gpl.rpg.atcontentstudio.model.Project;
import net.launchpad.tobal.poparser.POEntry;
import net.launchpad.tobal.poparser.POFile;
import net.launchpad.tobal.poparser.POParser;
/**
*
* @author Kevin
*
* To use this, paste the following script in the beanshell console of ATCS.
* Don't forget to change the project number to suit your needs.
*
* import com.gpl.rpg.atcontentstudio.model.Workspace;
* import com.gpl.rpg.atcontentstudio.ui.tools.i18n.PotGenerator;
* import com.gpl.rpg.atcontentstudio.ui.tools.i18n.PotComparator;
*
* proj = Workspace.activeWorkspace.projects.get(7);
* PotGenerator.generatePotFileForProject(proj);
* comp = new PotComparator(proj);
* comp.compare();
* comp.updatePoFiles(proj);
*
*
*
*/
public class PotComparator {
Map<String, List<String>> stringsResourcesNew = new LinkedHashMap<String, List<String>>();
Map<String, String> resourcesStringsNew = new LinkedHashMap<String, String>();
Map<String, List<String>> stringsResourcesOld = new LinkedHashMap<String, List<String>>();
Map<String, String> resourcesStringsOld = new LinkedHashMap<String, String>();
Map<String, String> msgIdToReplace = new LinkedHashMap<String, String>();
List<String> msgIdToReview = new LinkedList<String>();
List<String> msgIdOutdated = new LinkedList<String>();
public PotComparator(Project proj) {
POParser parser = new POParser();
POFile newPot = parser.parseFile(new File(proj.alteredContent.baseFolder.getAbsolutePath()+File.separator+"english.pot"));
if (newPot == null) {
System.err.println("Cannot locate new english.pot file at "+proj.alteredContent.baseFolder.getAbsolutePath()+File.separator);
}
extractFromPoFile(newPot, stringsResourcesNew, resourcesStringsNew);
POFile oldPot = parser.parseFile(new File(proj.baseContent.baseFolder.getAbsolutePath()+File.separator+"assets"+File.separator+"translation"+File.separator+"english.pot"));
if (oldPot == null) {
System.err.println("Cannot locate old english.pot file at "+proj.baseContent.baseFolder.getAbsolutePath()+File.separator+"assets"+File.separator+"translations"+File.separator);
}
extractFromPoFile(oldPot, stringsResourcesOld, resourcesStringsOld);
}
private void extractFromPoFile(POFile po, Map<String, List<String>> stringsResources, Map<String, String> resourcesStrings) {
for (POEntry entry : po.getEntryArray()) {
Vector<String> resources = entry.getStringsByType(POEntry.StringType.REFERENCE);
Vector<String> msgids = entry.getStringsByType(POEntry.StringType.MSGID);
if (resources == null || resources.size() == 0 || msgids == null || msgids.size() == 0) continue;
String msgid = msgids.get(0);
if (msgids.size() > 1) {
for (int i = 1; i < msgids.size(); i++) {
msgid += msgids.get(i);
}
}
if (msgid.contains("\\n")) {
msgid = msgid.replaceAll("\\\\n", "\\\\n\"\n\"");
msgid = "\"\n\""+msgid;
}
for (String resLine : resources) {
String[] resArray = resLine.split(" ");
for (String res : resArray) {
resourcesStrings.put(res, msgid);
if (stringsResources.get(msgid) == null) {
stringsResources.put(msgid, new LinkedList<String>());
}
stringsResources.get(msgid).add(res);
}
}
}
}
public void compare() {
for (String oldRes : resourcesStringsOld.keySet()) {
String newString = resourcesStringsNew.get(oldRes);
String oldString = resourcesStringsOld.get(oldRes);
if (newString != null) {
if (!newString.equals(oldString)) {
List<String> allOldResources = stringsResourcesOld.get(oldString);
List<String> allNewResources = stringsResourcesNew.get(oldString);
StringBuffer sb = new StringBuffer();
sb.append("---------------------------------------------\n");
sb.append("--- TYPO CHECK ------------------------------\n");
sb.append("---------------------------------------------\n");
sb.append("String at: "+oldRes+"\n");
if (allOldResources.size() > 1) {
sb.append("Also present at:\n");
for (String res : allOldResources) {
if (!res.equals(oldRes)) {
sb.append("- "+res+"\n");
}
}
}
if (allNewResources != null) {
sb.append("Still present at: \n");
for (String res : allNewResources) {
sb.append("- "+res+"\n");
}
}
sb.append("Was : \""+oldString+"\"\n");
sb.append("Now : \""+newString+"\"\n");
System.out.println(sb.toString());
showTypoDialog(oldString, newString, sb.toString());
}
} else {
List<String> allOldResources = stringsResourcesOld.get(oldString);
List<String> allNewResources = stringsResourcesNew.get(oldString);
if (allOldResources.size() >= 1) {
System.out.println("---------------------------------------------");
System.out.println("--- REMOVED RESOURCE ------------------------");
System.out.println("---------------------------------------------");
System.out.println("String at: "+oldRes);
if (allOldResources.size() > 1) {
System.out.println("And also at:");
for (String res : allOldResources) {
if (!res.equals(oldRes)) {
System.out.println("- "+res);
}
}
}
System.out.println("Was: \""+oldString+"\"");
if (allNewResources == null) {
System.out.println("Absent from new.");
} else {
System.out.println("Still present at: ");
for (String res : allNewResources) {
System.out.println("- "+res);
}
}
}
}
}
removedStrings: for (String oldString : stringsResourcesOld.keySet()) {
if (stringsResourcesNew.get(oldString) == null) {
List<String> allOldResources = stringsResourcesOld.get(oldString);
if (allOldResources.size() >= 1) {
if (allOldResources.size() > 0) {
for (String res : allOldResources) {
String newString = resourcesStringsNew.get(res);
if (newString != null) {
continue removedStrings;
}
}
}
System.out.println("---------------------------------------------");
System.out.println("--- REMOVED STRING --------------------------");
System.out.println("---------------------------------------------");
System.out.println("String: \""+oldString+"\"");
if (allOldResources.size() > 0) {
System.out.println("Was at:");
for (String res : allOldResources) {
System.out.println("- "+res);
}
}
System.out.println("This string is absent from the new file, and its attached resources are missing too.");
}
}
}
}
private void showTypoDialog(String oldMsg, String newMsg, String checkReport) {
String typo = "Typo";
String review = "Review";
String outdated = "Outdated";
String none = "None";
Object[] options = new Object[] {typo, review, outdated, none};
int result = JOptionPane.showOptionDialog(null, checkReport, "Choose action", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, typo);
if (result < 0 || result >= options.length) {
System.out.println("No decision");
return;
}
System.out.println("Decision: "+options[result]);
if (options[result] != none) {
msgIdToReplace.put(oldMsg, newMsg);
if (options[result] == review) {
msgIdToReview.add(newMsg);
} else if (options[result] == outdated) {
msgIdOutdated.add(newMsg);
}
}
}
public void updatePoFiles(Project proj) {
File poFolder = new File(proj.baseContent.baseFolder.getAbsolutePath()+File.separator+"assets"+File.separator+"translation");
File[] poFiles = poFolder.listFiles(new FileFilter() {
@Override
public boolean accept(File arg0) {
return arg0.isFile() && arg0.getName().endsWith(".po");
}
});
for (File f : poFiles) {
updatePoFile(proj, f);
}
}
private void updatePoFile(Project proj, File f) {
POParser parser = new POParser();
POFile poFile = parser.parseFile(f);
Map<String, String> translations = new LinkedHashMap<String, String>();
//Collect existing translations
if (poFile.getHeader() != null) {
Vector<String> msgstrs = poFile.getHeader().getStringsByType(POEntry.StringType.HEADER);
String header = "";
if (!msgstrs.isEmpty()) {
if (msgstrs.size() == 1) {
header = msgstrs.get(0);
} else {
for (String msgstr : msgstrs) {
header += msgstr;
header += "\n";
}
}
}
translations.put("", header);
}
for (POEntry entry : poFile.getEntryArray()) {
Vector<String> msgids = entry.getStringsByType(POEntry.StringType.MSGID);
Vector<String> msgstrs = entry.getStringsByType(POEntry.StringType.MSGSTR);
if (msgids == null || msgids.size() == 0) continue;
String msgid = msgids.get(0);
if (msgids.size() > 1) {
for (int i = 1; i < msgids.size(); i++) {
msgid += msgids.get(i);
}
}
if (msgid.contains("\\n")) {
msgid = msgid.replaceAll("\\\\n", "\\\\n\"\n\"");
msgid = "\"\n\""+msgid;
}
String translation = "";
if (!msgstrs.isEmpty()) {
if (msgstrs.size() == 1) {
translation = msgstrs.get(0);
} else {
for (String msgstr : msgstrs) {
translation += msgstr;
}
}
if (translation.contains("\\n")) {
translation = translation.replaceAll("\\\\n", "\\\\n\"\n\"");
translation = "\"\n\""+translation;
}
}
translations.put(msgid, translation);
}
//Patch data
for (String oldId : msgIdToReplace.keySet()) {
String newId = msgIdToReplace.get(oldId);
if (translations.containsKey(oldId)) {
String trans = translations.get(oldId);
translations.remove(oldId);
translations.put(newId, trans);
}
}
for (String msgid : msgIdToReview) {
if (translations.containsKey(msgid)) {
String trans = translations.get(msgid);
if (trans != null && trans.length() >= 1) translations.put(msgid, "[REVIEW]"+trans);
}
}
for (String msgid : msgIdOutdated) {
if (translations.containsKey(msgid)) {
String trans = translations.get(msgid);
if (trans != null && trans.length() >= 1) translations.put(msgid, "[OUTDATED]"+trans);
}
}
PoPotWriter.writePoFile(stringsResourcesNew, translations, new File(proj.alteredContent.baseFolder.getAbsolutePath()+File.separator+f.getName()));
}
}

View File

@@ -0,0 +1,100 @@
package com.gpl.rpg.atcontentstudio.ui.tools.i18n;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
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.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.gamedata.QuestStage;
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
public class PotGenerator {
public static void generatePotFileForProject(Project proj) {
Map<String, List<String>> stringsResources = new LinkedHashMap<String, List<String>>();
Map<String, String> resourcesStrings = new LinkedHashMap<String, String>();
GameSource gsrc = proj.baseContent;
for (ActorCondition ac : gsrc.gameData.actorConditions) {
pushString(stringsResources, resourcesStrings, ac.display_name, getPotContextComment(ac));
}
for (Dialogue d : gsrc.gameData.dialogues ) {
pushString(stringsResources, resourcesStrings, d.message, getPotContextComment(d));
if (d.replies == null) continue;
for (Dialogue.Reply r : d.replies) {
if (r.text != null && !r.text.equals(Dialogue.Reply.GO_NEXT_TEXT) ) {
pushString(stringsResources, resourcesStrings, r.text, getPotContextComment(d)+":"+d.replies.indexOf(r));
}
}
}
for (ItemCategory ic : gsrc.gameData.itemCategories) {
pushString(stringsResources, resourcesStrings, ic.name, getPotContextComment(ic));
}
for (Item i : gsrc.gameData.items) {
pushString(stringsResources, resourcesStrings, i.name, getPotContextComment(i));
pushString(stringsResources, resourcesStrings, i.description, getPotContextComment(i)+":description");
}
for (NPC npc : gsrc.gameData.npcs ) {
pushString(stringsResources, resourcesStrings, npc.name, getPotContextComment(npc));
}
for (Quest q : gsrc.gameData.quests) {
if (q.visible_in_log != null && q.visible_in_log != 0) {
pushString(stringsResources, resourcesStrings, q.name, getPotContextComment(q));
for (QuestStage qs : q.stages) {
pushString(stringsResources, resourcesStrings, qs.log_text, getPotContextComment(q)+":"+Integer.toString(qs.progress));
}
}
}
for (WorldmapSegment ws : gsrc.worldmap) {
for (WorldmapSegment.NamedArea area : ws.labels.values()) {
pushString(stringsResources, resourcesStrings, area.name, gsrc.worldmap.worldmapFile.getName()+":"+ws.id+":"+area.id);
}
}
File f = new File(proj.alteredContent.baseFolder, "english.pot");
PoPotWriter.writePotFile(stringsResources, f);
}
private static void pushString (Map<String, List<String>> stringsResources, Map<String, String> resourcesStrings, String translatableString, String resourceIdentifier) {
if (translatableString == null) return;
if (translatableString.length() == 0) return;
if (translatableString.contains("\"")) {
translatableString = translatableString.replaceAll("\"", "\\\\\"");
}
if (translatableString.contains("\n")) {
translatableString = translatableString.replaceAll("\n", "\\\\n\"\n\"");
translatableString = "\"\n\""+translatableString;
}
resourcesStrings.put(resourceIdentifier, translatableString);
List<String> resourceIdentifiers = stringsResources.get(translatableString);
if (resourceIdentifiers == null) {
resourceIdentifiers = new LinkedList<String>();
stringsResources.put(translatableString, resourceIdentifiers);
}
resourceIdentifiers.add(resourceIdentifier);
}
private static String getPotContextComment(JSONElement e) {
return e.jsonFile.getName()+":"+e.id;
}
}

View File

@@ -0,0 +1,100 @@
/**
*
* @author Balázs Tóth (tobal17@gmail.com)
*
* Modified by Kevin POCHAT for ATCS
*/
package net.launchpad.tobal.poparser;
import java.util.Vector;
public class POEntry
{
private POLine[] Lines;
public enum StringType
{
/**translator comments*/
TRLCMNT,
/**extracted comments*/
EXTCMNT,
/**reference*/
REFERENCE,
/**flag*/
FLAG,
/**previous context*/
PREVCTXT,
/**previous untranslated string singular*/
PREVUNTRSTRSING,
/**previous untranslated string plural*/
PREVUNTRSTRPLUR,
/**untranslated string singular*/
MSGID,
/**translated string*/
MSGSTR,
/**context*/
MSGCTXT,
/**header line*/
HEADER
// TODO: support for plural untranslated strings,
// and translated string cases
}
POEntry()
{
Lines = new POLine[0];
}
public void addLine(StringType type, String string)
{
boolean hasType = false;
POLine line = null;
for(int i = 0; i < Lines.length; i++)
{
if(Lines[i].getType() == type)
{
hasType = true;
line = Lines[i];
break;
}
}
if(hasType)
{
line.addString(string);
}
else
{
line = new POLine(type, string);
POLine[] templines = Lines.clone();
Lines = new POLine[Lines.length+1];
for(int i = 0; i < Lines.length-1; i++)
{
Lines[i] = templines[i];
}
Lines[Lines.length-1] = line;
}
}
public POLine[] getLines()
{
return Lines;
}
public Vector<String> getStringsFromLine(int index)
{
return Lines[index].getStrings();
}
public Vector<String> getStringsByType(POEntry.StringType type)
{
for(int i = 0; i < Lines.length; i++)
{
if(Lines[i].getType() == type)
{
return Lines[i].getStrings();
}
}
return null;
}
}

View File

@@ -0,0 +1,143 @@
/**
*
* @author Balázs Tóth (tobal17@gmail.com)
*
* Modified by Kevin POCHAT for ATCS
*/
package net.launchpad.tobal.poparser;
import java.io.File;
import java.util.Vector;
public class POFile
{
private POEntry[] entries;
private POEntry header;
private File file;
POFile(POEntry[] entries, POEntry header, File file)
{
this.entries = entries;
this.header = header;
this.file = file;
}
/**
* Returns with the name of the po file
* @return name of po file
*/
public String getFileName()
{
return file == null ? null : file.getAbsolutePath();
}
/**
* Returns with the POEntry object array
* @return POEntry array
*/
public POEntry[] getEntryArray()
{
return entries;
}
/**
* Gets the POEntry object specified by the index
* @param index, index of the entry
* @return one POEntry object
*/
public POEntry getEntry(int index)
{
return entries[index];
}
/**
* Returns how many entries are there in the po file
* @return count of entries
*/
public int getEntryLength()
{
return entries.length;
}
public POEntry getHeader() {
return header;
}
/**
* Checks if the specified flag is set in the entry,
* given by the entry index.
* @param flag, string representing the flag
* @param entryIndex, index of the entry to examine
* @return true, if the flag is set, false otherwise
*/
public boolean checkFlag(String flag, int entryIndex)
{
boolean status = false;
Vector<String> strings = new Vector<String>();
strings = entries[entryIndex].getStringsByType(POEntry.StringType.FLAG);
if (strings != null)
{
for(int i = 0; i < strings.size(); i++)
{
if (strings.get(i).contains(flag))
{
status = true;
}
}
}
return status;
}
/**
* Returns with all the strings of the given type, from
* the specified entry.
* @param entryIndex
* @param type
* @return String array of specified type
*/
public String[] getStringsFromEntryByType(int entryIndex, POEntry.StringType type)
{
Vector<String> vector = entries[entryIndex].getStringsByType(type);
String[] str = new String[vector.size()];
for(int i = 0; i < str.length; i++)
{
str[i] = vector.get(i);
}
return str;
}
/**
* For debug purposes
*/
public void printFile()
{
for(int i = 0; i < entries.length; i++)
{
POLine[] lines = entries[i].getLines();
for(int j = 0; j < lines.length; j++)
{
Vector<String> strings = lines[j].getStrings();
for(int k = 0; k < strings.size(); k++)
{
System.out.println(strings.get(k));
}
}
}
}
/**
* For debug purposes
*/
public void printHeader()
{
POLine[] lines = header.getLines();
for(int j = 0; j < lines.length; j++)
{
Vector<String> strings = lines[j].getStrings();
for(int k = 0; k < strings.size(); k++)
{
System.out.println(strings.get(k));
}
}
}
}

View File

@@ -0,0 +1,42 @@
/**
*
* @author Balázs Tóth (tobal17@gmail.com)
*
* Modified by Kevin POCHAT for ATCS
*/
package net.launchpad.tobal.poparser;
import java.util.Vector;
public class POLine
{
private POEntry.StringType type;
private Vector<String> strings;
POLine(POEntry.StringType type, String string)
{
this.type = type;
this.strings = new Vector<String>();
this.strings.add(string);
}
public void addString(String string)
{
strings.add(string);
}
public Vector<String> getStrings()
{
return strings;
}
public POEntry.StringType getType()
{
return type;
}
public int getVectorSize()
{
return strings.size();
}
}

View File

@@ -0,0 +1,274 @@
/**
*
* @author Balázs Tóth (tobal17@gmail.com)
*
* Based on the work of István Nyitrai
*
* Modified by Kevin POCHAT for ATCS
*/
package net.launchpad.tobal.poparser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Vector;
public class POParser
{
private POEntry[] entries;
private POEntry header;
// private File file;
private POEntry.StringType parserMode;
/**
* Creates a POParser object. Use getPOFile() method,
* to access parsed data.
* @param file, File object of the PO file
*/
public POParser()
{
parserMode = null;
}
public POFile parseFile(File file)
{
return parse(file);
}
public POFile parseStream(BufferedReader br) throws IOException {
return parse(br);
}
private String unQuote(String string)
{
String str = new String();
if(string.startsWith("\""))
{
str = string.substring(1);
string = str;
}
if(string.endsWith("\""))
{
str = string.substring(0, string.length()-1);
}
return str;
}
private POFile parse(File file)
{
POFile result = null;
try
{
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
result = parse(br);
br.close();
fr.close();
}
catch (java.io.FileNotFoundException e)
{
System.out.println(e.toString());
}
catch (java.io.IOException e) {
System.out.println(e.toString());
}
return result;
}
private POFile parse(BufferedReader br) throws IOException {
Vector<String> rawentry = new Vector<String>(1, 1);
Vector<Vector<String>> rawentries = new Vector<Vector<String>>();
String line;
int id = 0;
while((line = br.readLine()) != null)
{
if(!line.equals(""))
{
if(!line.startsWith("#~")) // ignore
{
rawentry.add(line);
}
}
else
{
if(rawentry.size() > 0)
{
rawentry.add(0, String.valueOf(id));
id++;
rawentries.add(new Vector<String>(rawentry));
rawentry = new Vector<String>(1, 1);
}
}
}
if(!rawentry.equals(rawentries.lastElement()) && rawentry.size() > 0)
{
rawentry.add(0, String.valueOf(id));
rawentries.add(new Vector<String>(rawentry));
}
this.header = parseHeader(rawentries);
this.entries = parseEntries(rawentries);
return new POFile(entries, header, null);
}
private POEntry parseHeader(Vector<Vector<String>> vectors)
{
POEntry tempheader = new POEntry();
// is this header?
Vector<String> rawentry = vectors.get(0);
if(new Integer(rawentry.get(0)) == 0 && rawentry.contains("msgid \"\""))
{
for(int i = 1; i < rawentry.size(); i++)
{
String str = rawentry.get(i);
tempheader.addLine(POEntry.StringType.HEADER, str);
str = new String();
}
return tempheader;
}
else
{
return null;
}
}
private POEntry[] parseEntries(Vector<Vector<String>> vectors)
{
String line = new String();
boolean thereIsHeader = false;
// is this header
Vector<String> rawentry = vectors.get(0);
if(new Integer(rawentry.get(0)) == 0 && rawentry.contains("msgid \"\""))
{
thereIsHeader = true;
}
int size;
if(thereIsHeader)
{
size = vectors.size()-1;
}
else
{
size = vectors.size();
}
POEntry[] tempentries = new POEntry[size];
for(int i = 0; i < size; i++)
{
POEntry entry = new POEntry();
if(thereIsHeader)
rawentry = vectors.get(i+1);
else
rawentry = vectors.get(i);
rawentry.remove(0);
for(int j = 0; j < rawentry.size(); j++)
{
line = rawentry.get(j);
POEntry.StringType strType = null;
int subStrIndex = 0;
if(line.startsWith("#"))
{
parserMode = null;
if(line.startsWith("# "))
{
strType = POEntry.StringType.TRLCMNT;
if (line.startsWith("# "))
{
subStrIndex = 3;
}
else
{
subStrIndex = 2;
}
}
if(line.startsWith("#."))
{
strType = POEntry.StringType.EXTCMNT;
subStrIndex = 3;
}
if(line.startsWith("#:"))
{
strType = POEntry.StringType.REFERENCE;
subStrIndex = 3;
}
if(line.startsWith("#,"))
{
strType = POEntry.StringType.FLAG;
subStrIndex = 3;
}
if(line.startsWith("#|"))
{
// TODO: can these comments be multi line? if no,
// drop support for it
if(line.startsWith("#| msgctxt "))
{
strType = POEntry.StringType.PREVCTXT;
parserMode = strType;
subStrIndex = 11;
}
if(line.startsWith("#| msgid "))
{
strType = POEntry.StringType.PREVUNTRSTRSING;
parserMode = strType;
subStrIndex = 9;
}
if(line.startsWith("#| msgid_plural "))
{
strType = POEntry.StringType.PREVUNTRSTRPLUR;
parserMode = strType;
subStrIndex = 16;
}
}
String str = new String();
str = line.substring(subStrIndex);
entry.addLine(strType, str);
}
else if(line.startsWith("msg"))
{
parserMode = null;
if(line.startsWith("msgctxt "))
{
strType = POEntry.StringType.MSGCTXT;
parserMode = strType;
subStrIndex = 8;
}
if(line.startsWith("msgid "))
{
strType = POEntry.StringType.MSGID;
parserMode = strType;
subStrIndex = 6;
}
if(line.startsWith("msgstr "))
{
strType = POEntry.StringType.MSGSTR;
parserMode = strType;
subStrIndex = 7;
}
String str = new String();
// TODO: is unquoting nessessary?
str = unQuote(line.substring(subStrIndex));
entry.addLine(strType, str);
}
else
{
if(parserMode != null)
{
entry.addLine(parserMode, unQuote(line));
}
}
}
tempentries[i] = entry;
}
return tempentries;
}
}

View File

@@ -0,0 +1,24 @@
/**
* @author Balázs Tóth (tobal17@gmail.com)
*
* Modified by Kevin POCHAT for ATCS
*/
package net.launchpad.tobal.poparser;
import java.io.File;
public class ParserTest
{
public static void main(String args[])
{
File file = new File("C:\\file.po");
POParser parser = new POParser();
POFile po = parser.parseFile(file);
po.printHeader();
po.printFile();
// is the 3th entry fuzzy?
boolean fuzzy = po.checkFlag("fuzzy", 3);
// give me the msgid of the 4th entry
String[] str = po.getStringsFromEntryByType(4, POEntry.StringType.MSGID);
}
}