20 package net.sf.gridarta.gui.mapmenu;
22 import java.io.IOException;
23 import java.util.ArrayDeque;
24 import java.util.Deque;
25 import javax.swing.JTree;
26 import javax.swing.event.TreeModelEvent;
27 import javax.swing.event.TreeModelListener;
28 import javax.swing.tree.DefaultMutableTreeNode;
29 import javax.swing.tree.DefaultTreeModel;
30 import javax.swing.tree.MutableTreeNode;
31 import javax.swing.tree.TreeNode;
32 import javax.swing.tree.TreePath;
35 import org.apache.log4j.Category;
36 import org.apache.log4j.Logger;
37 import org.jetbrains.annotations.NotNull;
38 import org.jetbrains.annotations.Nullable;
50 private static final Category
LOG = Logger.getLogger(
MapMenu.class);
62 private final DefaultMutableTreeNode
root =
new DefaultMutableTreeNode(
new MapMenuEntryDir(
"Bookmarks"),
true);
68 private final DefaultTreeModel
treeModel =
new DefaultTreeModel(root);
74 private final Deque<DeletedNode>
deletedNodes =
new ArrayDeque<>();
89 public void treeNodesChanged(
final TreeModelEvent e) {
90 treeModelModified =
true;
94 public void treeNodesInserted(
final TreeModelEvent e) {
95 treeModelModified =
true;
99 public void treeNodesRemoved(
final TreeModelEvent e) {
100 treeModelModified =
true;
104 public void treeStructureChanged(
final TreeModelEvent e) {
105 treeModelModified =
true;
116 if (LOG.isDebugEnabled()) {
118 LOG.debug(System.identityHashCode(
this) +
" new " + key);
121 treeModel.addTreeModelListener(treeModelListener);
129 if (LOG.isDebugEnabled()) {
130 LOG.debug(System.identityHashCode(
this) +
" load: root.removeAllChildren");
132 root.removeAllChildren();
133 for (
int i = 0; i < num; i++) {
137 }
catch (
final IOException ex) {
138 LOG.warn(
"dropping invalid bookmark: " + ex.getMessage());
143 treeModelModified =
false;
150 if (!treeModelModified) {
153 treeModelModified =
false;
165 for (
int i = num; i < prevNum; i++) {
177 private int saveEntries(@NotNull
final DefaultMutableTreeNode treeNode,
final int startIndex, @NotNull
final String directory) {
178 final int[] index = { startIndex };
179 for (
int i = 0; i < treeModel.getChildCount(treeNode); i++) {
180 final DefaultMutableTreeNode childTreeNode = (DefaultMutableTreeNode) treeModel.getChild(treeNode, i);
182 final String title = childMapMenuEntry.
getTitle();
188 index[0] =
saveEntries(childTreeNode, index[0], directory.isEmpty() ? title : directory +
"/" + title);
198 childMapMenuEntry.
visit(mapMenuEntryVisitor);
210 addMapMenuEntry(directory,
new DefaultMutableTreeNode(mapMenuEntry, mapMenuEntry.allowsChildren()));
221 public TreePath
addMapMenuEntry(@NotNull
final String directory, @NotNull
final DefaultMutableTreeNode treeNode) {
222 if (LOG.isDebugEnabled()) {
223 LOG.debug(System.identityHashCode(
this) +
" addMapMenuEntry(" + directory +
", " + treeNode +
")");
226 DefaultMutableTreeNode dir2 =
root;
227 for (
final String path : paths) {
228 if (!path.isEmpty()) {
232 treeModel.insertNodeInto(treeNode, dir2, dir2.getChildCount());
233 return new TreePath(treeModel.getPathToRoot(treeNode));
244 public DefaultMutableTreeNode
getOrCreateDirectory(@NotNull
final MutableTreeNode this2, @NotNull
final String path) {
246 if (LOG.isDebugEnabled()) {
247 LOG.debug(System.identityHashCode(
this) +
" getOrCreateDirectory(" + this2 +
", " + path +
")=invalid directory name");
249 throw new IllegalArgumentException(
"invalid directory name '" + path +
"'");
252 for (
int i = this2.getChildCount() - 1; i >= 0; i--) {
253 final DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) this2.getChildAt(i);
256 if (LOG.isDebugEnabled()) {
257 LOG.debug(System.identityHashCode(
this) +
" getOrCreateDirectory(" + this2 +
", " + path +
")=existing " + treeNode);
263 final DefaultMutableTreeNode new2 =
new DefaultMutableTreeNode(
new MapMenuEntryDir(path),
true);
264 treeModel.insertNodeInto(new2, this2, this2.getChildCount());
265 if (LOG.isDebugEnabled()) {
266 LOG.debug(System.identityHashCode(
this) +
" getOrCreateDirectory(" + this2 +
", " + path +
")=new " + new2);
281 if (LOG.isDebugEnabled()) {
282 LOG.debug(System.identityHashCode(
this) +
" insertNodeInto(" + mapEntry +
", " + parent +
", " + index +
")");
284 final DefaultMutableTreeNode treeNode =
new DefaultMutableTreeNode(mapEntry, mapEntry.allowsChildren());
285 treeModel.insertNodeInto(treeNode, parent, index);
287 return new TreePath(treeModel.getPathToRoot(treeNode));
295 public void removeNode(@NotNull
final DefaultMutableTreeNode treeNode) {
296 if (treeNode != root) {
297 if (LOG.isDebugEnabled()) {
298 LOG.debug(System.identityHashCode(
this) +
" removeNode " + treeNode);
301 treeModel.removeNodeFromParent(treeNode);
302 deletedNodes.addFirst(
new DeletedNode(directory, treeNode));
303 while (deletedNodes.size() > 10) {
304 deletedNodes.removeLast();
308 if (LOG.isDebugEnabled()) {
309 LOG.debug(System.identityHashCode(
this) +
" removeNode: not removing root " + treeNode);
321 final TreeNode[] treePath = treeModel.getPathToRoot(treeNode);
322 if (treePath == null) {
323 throw new IllegalArgumentException();
325 final StringBuilder sb =
new StringBuilder();
326 for (
int i = 1; i + 1 < treePath.length; i++) {
327 final TreeNode tmp = treePath[i];
329 if (sb.length() > 0) {
344 return delete ? deletedNodes.pollFirst() : deletedNodes.peekFirst();
360 private int size(@NotNull
final TreeNode root) {
361 final int childCount = treeModel.getChildCount(root);
362 int result = childCount;
363 for (
int i = 0; i < childCount; i++) {
364 final DefaultMutableTreeNode childTreeNode = (DefaultMutableTreeNode) treeModel.getChild(root, i);
367 result +=
size(childTreeNode);
370 if (LOG.isDebugEnabled()) {
371 LOG.debug(System.identityHashCode(
this) +
" size(" + root +
")=" + result);
418 private DeletedNode(@NotNull
final String directory, @NotNull
final DefaultMutableTreeNode treeNode) {
Utility class for string manipulation.
This class contains methods for converting relative map paths to absolute map paths and vice versa...
Reading and writing of maps, handling of paths.
Base package of all Gridarta classes.
File getFile()
Returns a File for this map file.
static final Pattern PATTERN_SLASH
The pattern that matches a single slash ("/").