Browse Source

Remove deprecated FileTree

macos/dialog_size
weisj 3 years ago
parent
commit
425289e4a5
No known key found for this signature in database
GPG Key ID: 31124CB75461DA2A
  1. 207
      core/src/main/java/com/github/weisj/darklaf/components/filetree/FileNode.java
  2. 98
      core/src/main/java/com/github/weisj/darklaf/components/filetree/FileTree.java
  3. 70
      core/src/main/java/com/github/weisj/darklaf/components/filetree/FileTreeCellRenderer.java
  4. 103
      core/src/main/java/com/github/weisj/darklaf/components/filetree/FileTreeModel.java
  5. 356
      core/src/main/java/com/github/weisj/darklaf/components/filetree/FileTreeNode.java
  6. 84
      core/src/main/java/com/github/weisj/darklaf/components/filetree/WatchFileTree.java
  7. 186
      core/src/main/java/com/github/weisj/darklaf/components/filetree/WatchFileTreeModel.java
  8. 83
      core/src/test/java/com/github/weisj/darklaf/ui/tree/FileTreeDemo.java

207
core/src/main/java/com/github/weisj/darklaf/components/filetree/FileNode.java

@ -1,207 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.components.filetree;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
/**
* @deprecated {@link FileTree} will be moved to https://github.com/weisJ/swing-dsl
*/
@Deprecated
public class FileNode implements Comparable<FileNode> {
private static final AtomicBoolean LOCKED = new AtomicBoolean(false);
private final Object lock = new Object();
private volatile File file;
private final Path path;
private final String pathName;
private boolean empty;
private boolean valid;
private Icon icon;
public FileNode(final File file, final Path path) {
this.file = file;
this.path = path;
this.pathName = this.file != null ? this.file.getAbsolutePath() : null;
if (this.file == null) {
this.file = getFile();
}
}
public void invalidate() {
valid = false;
icon = null;
}
protected boolean validateEmptyFlag(final boolean showHiddenFiles) {
if (!valid && path != null) {
try (Stream<Path> s = Files.list(path)) {
empty = s.filter(Files::isReadable).noneMatch(p -> showHiddenFiles || !isHidden(p));
valid = true;
} catch (final IOException ignored) {
}
}
return valid;
}
public static FileNode fromPath(final Path path) {
return new FileNode(null, path);
}
public static FileNode fromFile(final File file) {
return new FileNode(file, toPath(file));
}
private static Path toPath(final File file) {
try {
return file.toPath();
} catch (final InvalidPathException e) {
return null;
}
}
public boolean isDirectory() {
if (path != null) return Files.isDirectory(path);
return file != null && file.isDirectory();
}
public boolean exists() {
if (path != null) return Files.exists(path);
return file != null && file.exists();
}
public boolean notExists() {
if (path != null) return Files.notExists(path);
return file == null || !file.exists();
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FileNode on = (FileNode) o;
if (this.path != null && on.path != null) return path.equals(on.path);
return Objects.equals(pathName, ((FileNode) o).pathName);
}
@Override
public int hashCode() {
if (path != null) return path.hashCode();
return Objects.hashCode(pathName);
}
@Override
public String toString() {
return path != null ? path.toString() : file != null ? pathName : "null node";
}
@Override
public int compareTo(final FileNode o) {
if (o == null) return -1;
if (path != null && o.path != null) {
return path.compareTo(o.path);
}
return pathName.compareTo(o.pathName);
}
public boolean isHidden() {
boolean hidden;
hidden = isHidden(path);
if (file != null) {
hidden = hidden || file.isHidden();
}
return hidden;
}
private static boolean isHidden(final Path path) {
if (path != null) {
try {
return Files.isHidden(path);
} catch (final IOException ignored) {
}
}
return false;
}
public boolean isEmpty(final boolean showHiddenFiles) {
if (path != null && validateEmptyFlag(showHiddenFiles)) {
return empty;
}
return file == null || !file.isDirectory();
}
public boolean isReadable() {
if (path != null) return Files.isReadable(path);
return file != null && file.canRead();
}
public Stream<FileNode> list(final FileTreeModel model) throws IOException {
Stream<FileNode> stream;
if (path != null) {
stream = Files.list(path).map(FileNode::fromPath);
} else if (file != null) {
LOCKED.set(true);
File[] files = model.fsv.getFiles(file, !model.showHiddenFiles);
stream = Arrays.stream(files).map(FileNode::fromFile).onClose(() -> LOCKED.set(false));
} else {
stream = Stream.empty();
}
return stream;
}
public Icon getSystemIcon(final FileSystemView fsv) {
if (icon == null) {
icon = fsv.getSystemIcon(getFile());
}
return icon;
}
public String getSystemDisplayName(final FileSystemView fsv) {
File f = getFile();
if (f == null) return path != null ? String.valueOf(path.getFileName()) : "";
return fsv.getSystemDisplayName(f);
}
public Path getPath() {
return path;
}
public File getFile() {
synchronized (lock) {
if (file == null && this.path != null && !LOCKED.get()) {
file = path.toFile();
}
return file;
}
}
}

98
core/src/main/java/com/github/weisj/darklaf/components/filetree/FileTree.java

@ -1,98 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.components.filetree;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
/**
* @deprecated {@link FileTree} will be moved to https://github.com/weisJ/swing-dsl
*/
@Deprecated
public class FileTree extends JTree {
public FileTree() {
this((File[]) null);
}
public FileTree(final File... rootFile) {
this(false, rootFile);
}
public FileTree(final boolean showHiddenFiles, final File... rootFiles) {
FileSystemView fileSystemView = FileSystemView.getFileSystemView();
setFileTreeModel(createModel(fileSystemView, showHiddenFiles, rootFiles));
setCellRenderer(new FileTreeCellRenderer(fileSystemView));
setRootVisible(false);
}
protected FileTreeModel createModel(final FileSystemView fsv, final boolean showHiddenFiles,
final File... rootFiles) {
return new FileTreeModel(fsv, showHiddenFiles, rootFiles);
}
public boolean isShowHiddenFiles() {
return getModel().isShowHiddenFiles();
}
public void setShowHiddenFiles(final boolean showHiddenFiles) {
getModel().setShowHiddenFiles(showHiddenFiles);
}
@Override
public FileTreeModel getModel() {
return (FileTreeModel) super.getModel();
}
public void setFileTreeModel(final FileTreeModel fileTreeModel) {
super.setModel(fileTreeModel);
}
@Override
public void setModel(final TreeModel newModel) {}
public void reload() {
getModel().reload();
}
public FileNode getSelectedFile() {
TreePath path = getSelectionPath();
if (path == null) return null;
return ((FileTreeNode) path.getLastPathComponent()).getFile();
}
public List<FileNode> getSelectedFiles() {
TreePath[] paths = getSelectionPaths();
if (paths == null) return Collections.emptyList();
return Arrays.stream(getSelectionPaths()).map(TreePath::getLastPathComponent).map(FileTreeNode.class::cast)
.map(FileTreeNode::getFile).collect(Collectors.toList());
}
}

70
core/src/main/java/com/github/weisj/darklaf/components/filetree/FileTreeCellRenderer.java

@ -1,70 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.components.filetree;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultTreeCellRenderer;
/**
* @deprecated {@link FileTree} will be moved to https://github.com/weisJ/swing-dsl
*/
@Deprecated
public class FileTreeCellRenderer extends DefaultTreeCellRenderer {
private final FileSystemView fsv;
protected Icon fileIcon;
protected Icon directoryIcon;
public FileTreeCellRenderer(final FileSystemView fileSystemView) {
this.fsv = fileSystemView;
}
@Override
public void updateUI() {
super.updateUI();
fileIcon = UIManager.getIcon("FileView.fileIcon");
directoryIcon = UIManager.getIcon("FileView.directoryIcon");
}
@Override
public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean selected,
final boolean expanded, final boolean leaf, final int row, final boolean hasFocus) {
FileTreeNode node = ((FileTreeNode) value);
FileNode f = node.getFile();
if (f != null) {
setIcon(getFileIcon(f));
setText(f.getSystemDisplayName(fsv));
}
return this;
}
protected Icon getFileIcon(final FileNode f) {
Icon icon = f.getSystemIcon(fsv);
if (icon == null && f.exists()) {
icon = f.isDirectory() ? directoryIcon : fileIcon;
}
return icon;
}
}

103
core/src/main/java/com/github/weisj/darklaf/components/filetree/FileTreeModel.java

@ -1,103 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.components.filetree;
import java.io.File;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultTreeModel;
/**
* @deprecated {@link FileTree} will be moved to https://github.com/weisJ/swing-dsl
*/
@Deprecated
public class FileTreeModel extends DefaultTreeModel {
protected final FileSystemView fsv;
protected boolean showHiddenFiles;
public FileTreeModel(final FileSystemView fileSystemView) {
this(fileSystemView, false, (Path[]) null);
}
public FileTreeModel(final FileSystemView fileSystemView, final boolean showHiddenFiles, final File... roots) {
super(null);
init();
this.showHiddenFiles = showHiddenFiles;
this.fsv = fileSystemView;
this.root = createRoot(roots);
}
public FileTreeModel(final FileSystemView fileSystemView, final boolean showHiddenFiles, final Path... roots) {
super(null);
init();
this.showHiddenFiles = showHiddenFiles;
this.fsv = fileSystemView;
this.root = createRoot(roots);
}
protected void init() {}
protected FileTreeNode createRoot(final Path... roots) {
List<FileNode> nodes =
roots != null ? Arrays.stream(roots).map(FileNode::fromPath).collect(Collectors.toList()) : null;
return new FileTreeNode.RootNode(this, nodes);
}
protected FileTreeNode createRoot(final File... roots) {
List<FileNode> nodes =
roots != null ? Arrays.stream(roots).map(FileNode::fromFile).collect(Collectors.toList()) : null;
return new FileTreeNode.RootNode(this, nodes);
}
@Override
public void reload() {
getRoot().reload();
}
@Override
public FileTreeNode getRoot() {
return (FileTreeNode) super.getRoot();
}
public void setShowHiddenFiles(final boolean showHiddenFiles) {
if (showHiddenFiles == this.showHiddenFiles) return;
this.showHiddenFiles = showHiddenFiles;
reload();
}
public boolean isShowHiddenFiles() {
return showHiddenFiles;
}
protected FileTreeNode createNode(final FileTreeNode parent, final FileNode fileNode) {
return new FileTreeNode(parent, fileNode, this);
}
protected void register(final FileTreeNode node) {}
protected void unregister(final FileTreeNode node) {}
}

356
core/src/main/java/com/github/weisj/darklaf/components/filetree/FileTreeNode.java

@ -1,356 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.components.filetree;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.WatchKey;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.swing.*;
import javax.swing.tree.TreeNode;
import com.github.weisj.darklaf.util.Lambdas;
import com.github.weisj.darklaf.util.StreamUtil;
/**
* @deprecated {@link FileTree} will be moved to https://github.com/weisJ/swing-dsl
*/
@Deprecated
public class FileTreeNode implements TreeNode, Comparable<FileTreeNode> {
protected final FileTreeNode parent;
protected final FileTreeModel model;
protected final FileNode fileNode;
protected AtomicInteger taskCount = new AtomicInteger();
protected AtomicReference<List<FileTreeNode>> children;
protected WatchKey watchKey;
public FileTreeNode(final FileTreeNode parent, final FileNode fileNode, final FileTreeModel model) {
if (fileNode == null) throw new IllegalArgumentException("File node is null");
this.model = model;
this.fileNode = fileNode;
this.parent = parent;
this.children = new AtomicReference<>();
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FileTreeNode that = (FileTreeNode) o;
return Objects.equals(fileNode, that.fileNode);
}
@Override
public int hashCode() {
return fileNode.hashCode();
}
public FileNode getFile() {
return fileNode;
}
private int addSorted(final List<FileTreeNode> nodes, final FileTreeNode node) {
int index = Collections.binarySearch(nodes, node);
if (index < 0) index = ~index;
nodes.add(index, node);
model.register(node);
return index;
}
private int remove(final List<FileTreeNode> nodes, final FileTreeNode node) {
int index = nodes.indexOf(node);
if (index >= 0) {
nodes.remove(node);
model.unregister(node);
}
return index;
}
public void reload() {
reload(Integer.MAX_VALUE);
}
protected void reload(final int depth) {
if (depth < 0) return;
if (children.get() == null) return;
List<FileTreeNode> fileList = children.get();
this.<ReloadOp>doInBackground(pub -> {
this.traverseChildren(s -> Stream.concat(s.map(this::toNode), fileList.stream()).map(n -> {
if (n.fileNode.notExists()) {
return ReloadOp.remove(n, remove(fileList, n));
} else {
if (model.showHiddenFiles) {
if (!fileList.contains(n)) {
return ReloadOp.add(n, addSorted(fileList, n));
}
} else {
if (n.fileNode.isHidden()) {
return ReloadOp.remove(n, remove(fileList, n));
} else if (!fileList.contains(n)) {
return ReloadOp.add(n, addSorted(fileList, n));
}
}
}
return null;
}).forEach(pub));
}, chunk -> {
for (ReloadOp op : chunk) {
if (op != null && op.index >= 0) {
switch (op.type) {
case ADD:
model.nodesWereInserted(FileTreeNode.this, new int[] {op.index});
break;
case REMOVE:
model.nodesWereRemoved(FileTreeNode.this, new int[] {op.index}, new Object[] {op.node});
break;
}
}
}
}, () -> {
fileNode.invalidate();
if (depth > 0) fileList.forEach(n -> n.reload(depth - 1));
});
}
private List<FileTreeNode> getChildren() {
return children.updateAndGet(list -> {
if (list != null) {
return list;
}
List<FileTreeNode> fileList = Collections.synchronizedList(new ArrayList<>());
this.<Integer>doInBackground(pub -> {
traverseChildren(s -> {
s.filter(p -> model.showHiddenFiles || !p.isHidden()).map(this::toNode).sorted()
.map(n -> addSorted(fileList, n)).forEach(pub);
});
}, chunks -> {
int[] indices = chunks.stream().mapToInt(Integer::intValue).toArray();
model.nodesWereInserted(FileTreeNode.this, indices);
}, () -> model.nodeChanged(FileTreeNode.this));
return fileList;
});
}
@Override
public String toString() {
return fileNode.toString();
}
protected FileTreeNode toNode(final FileNode fileNode) {
return model.createNode(FileTreeNode.this, fileNode);
}
protected void traverseChildren(final Consumer<Stream<FileNode>> consumer) {
if (fileNode.isDirectory()) {
try (Stream<FileNode> files = fileNode.list(model)) {
consumer.accept(files.filter(FileNode::isReadable));
} catch (final IOException ignored) {
}
}
}
protected <T> void doInBackground(final Consumer<Consumer<T>> task, final Consumer<List<T>> processor) {
doInBackground(task, processor, Lambdas.DO_NOTHING);
}
protected <T> void doInBackground(final Consumer<Consumer<T>> task, final Consumer<List<T>> processor,
final Runnable doneTask) {
taskCount.getAndIncrement();
SwingWorker<Void, T> worker = new SwingWorker<Void, T>() {
@Override
public Void doInBackground() {
task.accept(this::publish);
return null;
}
@Override
protected void process(final List<T> chunks) {
processor.accept(chunks);
}
@Override
protected void done() {
doneTask.run();
taskCount.getAndDecrement();
}
};
worker.execute();
}
@Override
public TreeNode getChildAt(final int childIndex) {
return getChildren().get(childIndex);
}
@Override
public int getChildCount() {
return getChildren().size();
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public int getIndex(final TreeNode node) {
if (node == null) {
throw new IllegalArgumentException("argument is null");
}
if (!isNodeChild(node)) {
return -1;
}
return getChildren().indexOf(node);
}
@Override
public boolean getAllowsChildren() {
return fileNode.isDirectory();
}
@Override
public boolean isLeaf() {
if (!fileNode.isDirectory()) return true;
if (children.get() != null && !isBusy()) {
return children.get().size() == 0;
}
return fileNode.isEmpty(model.showHiddenFiles);
}
@Override
public Enumeration<? extends TreeNode> children() {
return Collections.enumeration(children.get());
}
public boolean isNodeChild(final TreeNode aNode) {
if (aNode == null) return false;
return (aNode.getParent() == this);
}
@Override
public int compareTo(final FileTreeNode o) {
if (o == null) return -1;
boolean thisDir = fileNode.isDirectory();
boolean oDir = fileNode.isDirectory();
if (thisDir == oDir) {
return fileNode.compareTo(o.fileNode);
} else {
return thisDir ? -1 : 1;
}
}
public boolean isBusy() {
return taskCount.get() > 0;
}
public static class RootNode extends FileTreeNode {
private final List<FileNode> rootPaths;
public RootNode(final FileTreeModel model, final List<FileNode> rootPaths) {
super(null, new FileNode(null, null), model);
this.rootPaths = rootPaths != null ? rootPaths : Collections.emptyList();
init();
}
protected Stream<FileNode> createInitialDirectories() {
return rootPaths.size() > 0 ? rootPaths.stream()
: StreamUtil.iterableAsStream(FileSystems.getDefault().getRootDirectories())
.map(FileNode::fromPath);
}
protected void init() {
List<FileTreeNode> nodes = new ArrayList<>();
createInitialDirectories().forEach(p -> {
FileTreeNode node = model.createNode(RootNode.this, p);
model.register(node);
nodes.add(node);
});
children.set(nodes);
}
@Override
protected void reload(final int depth) {
if (depth < 0) return;
List<FileTreeNode> nodes = children.get();
createInitialDirectories().forEach(p -> {
FileTreeNode node = model.createNode(this, p);
if (!nodes.contains(node)) {
model.register(node);
nodes.add(node);
}
});
nodes.removeIf(n -> {
if (n.fileNode.notExists()) {
model.unregister(n);
return true;
}
return false;
});
if (depth > 0) children.get().forEach(n -> n.reload(depth - 1));
fileNode.invalidate();
}
@Override
public boolean isLeaf() {
return children.get().size() == 0;
}
@Override
public boolean getAllowsChildren() {
return true;
}
}
private static class ReloadOp {
private final Type type;
private final FileTreeNode node;
private final int index;
private ReloadOp(final Type type, final FileTreeNode node, final int index) {
this.type = type;
this.node = node;
this.index = index;
}
private static ReloadOp add(final FileTreeNode n, final int index) {
return new ReloadOp(Type.ADD, n, index);
}
private static ReloadOp remove(final FileTreeNode n, final int index) {
return new ReloadOp(Type.REMOVE, n, index);
}
private enum Type {
ADD,
REMOVE
}
}
}

84
core/src/main/java/com/github/weisj/darklaf/components/filetree/WatchFileTree.java

@ -1,84 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.components.filetree;
import java.io.File;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
/**
* @deprecated {@link FileTree} will be moved to https://github.com/weisJ/swing-dsl
*/
@Deprecated
public class WatchFileTree extends FileTree {
public WatchFileTree() {
super();
}
public WatchFileTree(final File... rootFiles) {
super(rootFiles);
}
public WatchFileTree(final boolean showHiddenFiles, final File... rootFiles) {
super(showHiddenFiles, rootFiles);
}
@Override
protected FileTreeModel createModel(final FileSystemView fsv, final boolean showHiddenFiles,
final File... rootFiles) {
return new WatchFileTreeModel(fsv, showHiddenFiles, rootFiles);
}
@Override
public void setFileTreeModel(final FileTreeModel fileTreeModel) {
if (getModel() == fileTreeModel) return;
if (getModel() instanceof WatchFileTreeModel) {
((WatchFileTreeModel) getModel()).stopWatching();
}
if (isVisible() && fileTreeModel instanceof WatchFileTreeModel) {
((WatchFileTreeModel) fileTreeModel).startWatching();
}
super.setFileTreeModel(fileTreeModel);
}
@Override
public void addNotify() {
super.addNotify();
SwingUtilities.invokeLater(() -> {
if (getModel() instanceof WatchFileTreeModel) {
((WatchFileTreeModel) getModel()).startWatching();
}
});
}
@Override
public void removeNotify() {
super.removeNotify();
SwingUtilities.invokeLater(() -> {
if (getModel() instanceof WatchFileTreeModel) {
((WatchFileTreeModel) getModel()).stopWatching();
}
});
}
}

186
core/src/main/java/com/github/weisj/darklaf/components/filetree/WatchFileTreeModel.java

@ -1,186 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.components.filetree;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.swing.filechooser.FileSystemView;
import com.github.weisj.darklaf.util.LogUtil;
/**
* @deprecated {@link FileTree} will be moved to https://github.com/weisJ/swing-dsl
*/
@Deprecated
public class WatchFileTreeModel extends FileTreeModel {
private static final Logger LOGGER = LogUtil.getLogger(WatchFileTreeModel.class);
private static final ScheduledExecutorService scheduler = createScheduler();
private WatchService watchService;
private Map<Watchable, FileTreeNode> nodeMap;
private Object lock;
private final AtomicBoolean isScheduled = new AtomicBoolean(false);
private ScheduledFuture<?> watchTask;
private static WatchService createWatchService() {
WatchService ws = null;
try {
ws = FileSystems.getDefault().newWatchService();
} catch (final IOException e) {
e.printStackTrace();
}
return ws;
}
private static ScheduledExecutorService createScheduler() {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, r -> {
final Thread thread = new Thread(r, "File Tree Watch Thread");
thread.setDaemon(true);
thread.setPriority(Thread.MIN_PRIORITY);
return thread;
});
executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
return executor;
}
public WatchFileTreeModel(final FileSystemView fileSystemView) {
super(fileSystemView);
}
public WatchFileTreeModel(final FileSystemView fileSystemView, final boolean showHiddenFiles, final File... roots) {
super(fileSystemView, showHiddenFiles, roots);
}
public WatchFileTreeModel(final FileSystemView fileSystemView, final boolean showHiddenFiles, final Path... roots) {
super(fileSystemView, showHiddenFiles, roots);
}
@Override
protected void init() {
lock = new Object();
watchService = createWatchService();
nodeMap = Collections.synchronizedMap(new HashMap<>());
}
private Object getLock() {
return lock;
}
protected WatchService getWatchService() {
return watchService;
}
protected Map<Watchable, FileTreeNode> getNodeMap() {
return nodeMap;
}
public void startWatching() {
if (watchTask != null) return;
isScheduled.set(true);
watchTask = scheduler.schedule(this::watch, 0, TimeUnit.SECONDS);
}
public void stopWatching() {
if (watchTask != null) {
isScheduled.set(false);
watchTask.cancel(true);
watchTask = null;
}
}
private void watch() {
while (isScheduled.get()) {
WatchKey key;
try {
key = watchService.take();
} catch (final InterruptedException x) {
x.printStackTrace();
return;
}
FileTreeNode parent = getNodeMap().get(key.watchable());
if (parent != null) {
LOGGER.fine(() -> "Event for \"" + parent + "\"");
if (parent.parent != null) {
parent.parent.reload(1);
} else {
parent.reload(0);
}
}
List<WatchEvent<?>> watchEventList = key.pollEvents();
for (WatchEvent<?> event : watchEventList) {
WatchEvent.Kind<?> kind = event.kind();
Path path = (Path) event.context();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
LOGGER.finer("Event Type " + kind.name());
FileTreeNode node = getNodeMap().get(((Path) key.watchable()).resolve(path));
if (node != null) {
LOGGER.finer(() -> "Affected node \"" + node + "\"");
node.reload(0);
}
}
key.reset();
}
}
protected void register(final FileTreeNode node) {
synchronized (getLock()) {
WatchService ws = getWatchService();
if (ws == null || !node.fileNode.isDirectory()) return;
Path path = node.fileNode.getPath();
if (path == null) return;
if (getNodeMap().containsKey(path)) return;
try {
LOGGER.finer(() -> "Register watch service for \"" + node + "\"");
node.watchKey = path.register(ws, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
getNodeMap().put(path, node);
} catch (final IOException ignored) {
}
}
}
protected void unregister(final FileTreeNode node) {
synchronized (getLock()) {
if (node.watchKey == null) return;
LOGGER.finer(() -> "Unregister watch service for \"" + node + "\"");
getNodeMap().remove(node.fileNode.getPath());
node.watchKey.cancel();
}
}
}

83
core/src/test/java/com/github/weisj/darklaf/ui/tree/FileTreeDemo.java

@ -1,83 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2021 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.github.weisj.darklaf.ui.tree;
import java.awt.*;
import java.io.File;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import com.github.weisj.darklaf.components.OverlayScrollPane;
import com.github.weisj.darklaf.components.filetree.FileTree;
import com.github.weisj.darklaf.core.test.DelicateDemo;
import com.github.weisj.darklaf.ui.DemoPanel;
import com.github.weisj.darklaf.ui.button.ButtonConstants;
import com.github.weisj.darklaf.ui.demo.BaseComponentDemo;
import com.github.weisj.darklaf.ui.demo.DemoExecutor;
@DelicateDemo(reason = "Deprecated")
public class FileTreeDemo extends BaseComponentDemo {
public static void main(final String[] args) {
DemoExecutor.showDemo(new FileTreeDemo());
}
@Override
public JComponent createComponent() {
FileSystemView fsv = FileSystemView.getFileSystemView();
File[] rootFiles = fsv.getFiles(fsv.getRoots()[0], true);
FileTree tree = new FileTree(false, rootFiles);
DemoPanel panel = new DemoPanel(new OverlayScrollPane(tree), new BorderLayout(), 0);
JPanel controlPanel = panel.addControls();
controlPanel.add(new JCheckBox("Show hidden files") {
{
setSelected(tree.isShowHiddenFiles());
addActionListener(e -> tree.setShowHiddenFiles(isSelected()));
}
});
controlPanel.add(new JButton("Reload") {
{
putClientProperty(ButtonConstants.KEY_THIN, true);
addActionListener(e -> tree.reload());
}
});
controlPanel = panel.addControls();
controlPanel.add(new JLabel(DarkTreeUI.KEY_LINE_STYLE + ":", JLabel.RIGHT));
controlPanel.add(new JComboBox<String>() {
{
addItem(DarkTreeUI.STYLE_LINE);
addItem(DarkTreeUI.STYLE_DASHED);
addItem(DarkTreeUI.STYLE_NONE);
setSelectedItem(DarkTreeUI.STYLE_LINE);
addItemListener(e -> tree.putClientProperty(DarkTreeUI.KEY_LINE_STYLE, e.getItem()));
}
});
return panel;
}
@Override
public String getName() {
return "File Tree Demo";
}
}
Loading…
Cancel
Save