mirror of https://github.com/weisJ/darklaf.git
weisj
3 years ago
8 changed files with 0 additions and 1187 deletions
@ -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; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -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()); |
|
||||||
} |
|
||||||
} |
|
@ -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; |
|
||||||
} |
|
||||||
} |
|
@ -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) {} |
|
||||||
} |
|
@ -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 |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -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(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
@ -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(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -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…
Reference in new issue