From 0a3da17d47e20bc95a054c0941d666ae90325ecb Mon Sep 17 00:00:00 2001 From: Zukero Date: Thu, 13 Sep 2018 13:34:04 +0200 Subject: [PATCH] First implementation of a bookmarks system. Not persistent yet, so you lose them all when you close ATCS. --- folderIconBase.xcf | Bin 57130 -> 60090 bytes .../atcontentstudio/img/bookmark_active.png | Bin 0 -> 2370 bytes .../atcontentstudio/img/bookmark_inactive.png | Bin 0 -> 3363 bytes .../img/folder_bookmark_closed.png | Bin 0 -> 2530 bytes .../img/folder_bookmark_open.png | Bin 0 -> 3418 bytes .../model/GameDataElement.java | 4 + .../rpg/atcontentstudio/model/Project.java | 11 + .../model/bookmarks/BookmarkEntry.java | 155 +++++++++++++ .../model/bookmarks/BookmarkFolder.java | 168 ++++++++++++++ .../model/bookmarks/BookmarkNode.java | 10 + .../model/bookmarks/BookmarksRoot.java | 210 ++++++++++++++++++ .../rpg/atcontentstudio/ui/DefaultIcons.java | 16 ++ .../gpl/rpg/atcontentstudio/ui/Editor.java | 2 +- .../rpg/atcontentstudio/ui/ProjectsTree.java | 3 + .../rpg/atcontentstudio/ui/StudioFrame.java | 2 + .../ui/gamedataeditors/JSONElementEditor.java | 17 ++ .../atcontentstudio/ui/map/TMXMapEditor.java | 28 +++ .../ui/map/WorldMapEditor.java | 14 ++ .../ui/sprites/SpritesheetEditor.java | 14 ++ 19 files changed, 653 insertions(+), 1 deletion(-) create mode 100644 src/com/gpl/rpg/atcontentstudio/img/bookmark_active.png create mode 100644 src/com/gpl/rpg/atcontentstudio/img/bookmark_inactive.png create mode 100644 src/com/gpl/rpg/atcontentstudio/img/folder_bookmark_closed.png create mode 100644 src/com/gpl/rpg/atcontentstudio/img/folder_bookmark_open.png create mode 100644 src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkEntry.java create mode 100644 src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkFolder.java create mode 100644 src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkNode.java create mode 100644 src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarksRoot.java diff --git a/folderIconBase.xcf b/folderIconBase.xcf index 6ee67cf2c80c1b2c39ac3743195f75129cd6c83f..1a0a6c26f7b00842c1bd3e9001f769863558baa7 100644 GIT binary patch delta 3919 zcmc&%YmgLI6+YcF-F;`@!0sk2D=h5puq?13k(Y%qAhJn}iYbW;#40gTB}sTxtYAfd zbok*9po}I1!91{n1k_L^k0HxzX70?gEO}r=*cB=ZE>;W`kW>Q7&Z{4Or>7TO|M|ms zc2D1PzkANP=icu7b>>(K~Sv7)HmzA=<3h^R}b z{H5Wz`YEu@jG5YNlyhaeyVImOq{Nk^9sf1WqCvCsgp`SR%%z!RcgB+{1`bmj-997_ zOS%8Vk>d%e$XwD)9FyG#VA?$PaV_P!e{hOO2E}bX>}mOerZ% z=94m&Od`rkCXOO3+jAs=eo~gmESf|-{suKu?vFB+Mu?EXq?I^e(nKnp?oOp-skGAa z2u-1Uj|qpAG^E{?L3M=_+|y(M^Yn24LUB|{ITBlIkLtqos&rB^Ac37mijQ5Mf(uJw zer~%NeJ71R{=5Hj(zDWxIx?-Kt>k+y?nTz+@wAx+Ubt|o=QQb*ce{Juy-udG92@&r zDg<>sKyxXNRtsW(bE>Wzx<<1p8wlzKo72b%YC+9{i=h}6{P5=lC`?X3*LBAbs!$9~ zw~-)BRzTB@prMH%yK2-zW(9^7-41HhO15r@a$#fADP${#C=rf<8SH=|LPgWjM450j zj9Y?qQ7UZ1a~2#3XRI+Gf}&ukWT16|oJkJ}h0P$T!U_ouJ85Y_oeZ*c6BC=tiqCAl z|G8ZAGhXkV<>K5ZWuxoN3YBl{JwMp{$^)f*aMb#z&fL7Pag2h4Gg$HH*_?Czxp4}% zv7nSxji^$pZdHzcc>hhuzP97Os`BzOrOXbgI0AoD$E|%~$BWyyZGZjzZQF4&7k59m zb<38`o0iome0oYAe(P2yn^7`$&URJTb}ZP+pjo(m`RS2-@`COAuH|h5NQhCFXtRrxEUw^(L1}A*Qq#1`QV7J#0CN83+J936XNpp1&O??yM{1zbQy-BD5CDQWL?2l}R%+M4F(-S zmK6*s9!JX(DXIW>gBe8!0e2yBFr`Z)Wg}S==dbq13Z0-! zIYQcT2@>%5t3p~S^je5H6oX~bJ}yB4c^4d(lp$%w2V4|UkS4em{pqNVEl?$@1MMUb zGab_c6G(?A<6UI~gx zjthUEg7clsvZQ%+%T7E>sw<$T@+)llafsd7Ukt zEg!>j3_Zwfslmmwuu(RWj1s1eM9myj!$GhNwhTDbib+&0CX-??t+Y{v_&kq#TzS`; z&R8i&U>fF3WZ?;mSQ}d&cTVL|%ujsLv76|EyiIVaVt57PnLtU3&_SeJ6}FX^3m)ah zR4)H7w!p+5{6DwA{i!Mt1$ zLcK-uiay9P^A=a@m8tLq-%n++-eN4cx3zbr<8p14UZLJjd9YI~uUKs#Qct05*M3!Bx=saM%UJ9;qagQu?SjL#DwwP?@0t#X!v$)`Iret^wFBt z(T^syhTDc}Y{qys6ftdav@AZ>b|yBbF|UVbzEy+?zcoCC?@ZM0iI2^^5$kAe5z!4b z9np(38pHFS_s1h>SrIdT4_cN;QRlxI8-L$R0`JNV(bjpT;r4fV5EAhfG3^5kKq5tL z|0K3@-fR(G+QJ|t;wyZY&SL-)DeBUP;QN9Reej|E;f|m40A#wa@bB2|A$PEjSZv(a z+?w#Z!#*BC%L?ChLwn$3>n_HoY^)v`?Rfh4;Z3i?hb7`G{5Kt701_$crWE`WBg5NF z1|j?`;kO#+-WFv5;$z!($0|4fM1*%Xc<7xR?7Q;|!?B%hIoLk{6(&bS{Oi8rNwQe?;lonB$m6l~aWQ0;VgdVaGQtClF z24)ZTP!Sf{c6t))B?{N`q*4e(5VMD{N3HBTyGP@G@ZJC2?|lDr@3}i?Y|=9F&e9h& zJ&x|ZXgX>7OO$q(D6^X=>jIIhoG9luQT|b);x3{chl#3si1sfK)rN`Aw-R+6C+gWl z)Hh2sw2>$}NEF{dlqeyZx<j@hFS@)BQk%&6K@*1`5Rc9xSDy&%Iv$< zn1(8i9{V9wDNVQijQHg$O!YhNNC=&Sy)d$lVXUMj%3 zJarO4nr=^%SY-KDUTDtc2f{~qr{BlCn`8hgfU{xrdACadDdr7`3I9?m^T~IS%27tv zSDPej%-1O9%ZqH7znyml(^(nTmXwC8GWFRA@DI*`*ihC(dccc{gw^^*`r-YE)Px3!N zw$~y7q*$+03=iC}vHm_Cug)Q}{ZEXn{|&xjtBsF5eP1~=tH!EP_rb^yE#m~;GxA6B zRC(Y|xEo`<`D4BK{cOQq8EZ5~c3m48Yj36Mz0sQR3#$tr`4vVwlB0 zs1^-X8dJr;qDpDHi} diff --git a/src/com/gpl/rpg/atcontentstudio/img/bookmark_active.png b/src/com/gpl/rpg/atcontentstudio/img/bookmark_active.png new file mode 100644 index 0000000000000000000000000000000000000000..4ad606cd0337dcf3ee4207b390775a30ad8bfc4d GIT binary patch literal 2370 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 literal 0 HcmV?d00001 diff --git a/src/com/gpl/rpg/atcontentstudio/img/folder_bookmark_closed.png b/src/com/gpl/rpg/atcontentstudio/img/folder_bookmark_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..718313df84af4a5fe50d485da7ac287f2fcaec99 GIT binary patch literal 2530 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 literal 0 HcmV?d00001 diff --git a/src/com/gpl/rpg/atcontentstudio/model/GameDataElement.java b/src/com/gpl/rpg/atcontentstudio/model/GameDataElement.java index 534b715..5643f57 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/GameDataElement.java +++ b/src/com/gpl/rpg/atcontentstudio/model/GameDataElement.java @@ -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 backlinks = new ConcurrentHashMap(); diff --git a/src/com/gpl/rpg/atcontentstudio/model/Project.java b/src/com/gpl/rpg/atcontentstudio/model/Project.java index 31e4f61..e8182ca 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/Project.java +++ b/src/com/gpl/rpg/atcontentstudio/model/Project.java @@ -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() { diff --git a/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkEntry.java b/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkEntry.java new file mode 100644 index 0000000..17f811d --- /dev/null +++ b/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkEntry.java @@ -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 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 path) { + path.add(0,this); + parent.childrenAdded(path); + } + + @Override + public void childrenChanged(List path) { + path.add(0,this); + parent.childrenChanged(path); + } + + @Override + public void childrenRemoved(List path) { + path.add(0,this); + parent.childrenRemoved(path); + } + @Override + public void notifyCreated() { + childrenAdded(new ArrayList()); + } + + @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(); + } + +} diff --git a/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkFolder.java b/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkFolder.java new file mode 100644 index 0000000..c34be73 --- /dev/null +++ b/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkFolder.java @@ -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 contents = new LinkedList(); + 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 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 path) { + path.add(0,this); + parent.childrenAdded(path); + } + + @Override + public void childrenChanged(List path) { + path.add(0,this); + parent.childrenChanged(path); + } + + @Override + public void childrenRemoved(List path) { + if (path.size() == 1 && this.getChildCount() == 1) { + childrenRemoved(new ArrayList()); + } else { + path.add(0, this); + parent.childrenRemoved(path); + } + } + @Override + public void notifyCreated() { + childrenAdded(new ArrayList()); + } + + @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()); + contents.remove(bookmarkEntry); + save(); + } + } + + public void delete(BookmarkFolder bookmarkFolder) { + // TODO Auto-generated method stub + + } + + public void save() { + parent.save(); + } + + public void delete() { + + } + +} diff --git a/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkNode.java b/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkNode.java new file mode 100644 index 0000000..4b64420 --- /dev/null +++ b/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarkNode.java @@ -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(); + +} diff --git a/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarksRoot.java b/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarksRoot.java new file mode 100644 index 0000000..501cfff --- /dev/null +++ b/src/com/gpl/rpg/atcontentstudio/model/bookmarks/BookmarksRoot.java @@ -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 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 path) { + path.add(0, this); + parent.childrenAdded(path); + } + @Override + public void childrenChanged(List path) { + path.add(0, this); + parent.childrenChanged(path); + } + @Override + public void childrenRemoved(List path) { + if (path.size() == 1 && this.v.getNonEmptySize() == 1) { + childrenRemoved(new ArrayList()); + } else { + path.add(0, this); + parent.childrenRemoved(path); + } + } + @Override + public void notifyCreated() { + childrenAdded(new ArrayList()); + 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(); + } + +} diff --git a/src/com/gpl/rpg/atcontentstudio/ui/DefaultIcons.java b/src/com/gpl/rpg/atcontentstudio/ui/DefaultIcons.java index 2035460..fd29106 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/DefaultIcons.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/DefaultIcons.java @@ -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) { diff --git a/src/com/gpl/rpg/atcontentstudio/ui/Editor.java b/src/com/gpl/rpg/atcontentstudio/ui/Editor.java index d40be0a..edb5912 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/Editor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/Editor.java @@ -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()); } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/ProjectsTree.java b/src/com/gpl/rpg/atcontentstudio/ui/ProjectsTree.java index 577ba15..0d8148b 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/ProjectsTree.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/ProjectsTree.java @@ -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); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java b/src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java index 2af28da..25ccaa5 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/StudioFrame.java @@ -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); } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java index c70b5e8..e313805 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java @@ -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); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java index 945da13..edf68a8 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java @@ -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); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java index bdcdf17..7e1afdd 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/map/WorldMapEditor.java @@ -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; diff --git a/src/com/gpl/rpg/atcontentstudio/ui/sprites/SpritesheetEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/sprites/SpritesheetEditor.java index 89692e5..d3f9a3f 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/sprites/SpritesheetEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/sprites/SpritesheetEditor.java @@ -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);