JScratch
Loading...
Searching...
No Matches
FileManagerPanel.java
Go to the documentation of this file.
1package com.jscratch.ui;
2
3import com.jscratch.WorkspaceManager;
4import javax.swing.*;
5import javax.swing.tree.*;
6import java.awt.*;
7import java.awt.event.*;
8import java.io.File;
9import java.io.IOException;
10import java.nio.file.Files;
11import java.util.Arrays;
12
13public class FileManagerPanel extends JPanel {
14 private JTree fileTree;
15 private DefaultTreeModel treeModel;
16
18 setLayout(new BorderLayout());
19 setBackground(Color.WHITE);
20
22 refresh();
23 }
24
25 private void setupToolbar() {
26 JToolBar toolBar = new JToolBar();
27 toolBar.setFloatable(false);
28 toolBar.setBackground(new Color(240, 240, 240));
29
30 JButton refreshBtn = new JButton("Refresh");
31 refreshBtn.addActionListener(e -> refresh());
32 toolBar.add(refreshBtn);
33
34 toolBar.addSeparator();
35
36 JButton deleteBtn = new JButton("Delete");
37 deleteBtn.addActionListener(e -> deleteSelected());
38 toolBar.add(deleteBtn);
39
40 JButton renameBtn = new JButton("Rename");
41 renameBtn.addActionListener(e -> renameSelected());
42 toolBar.add(renameBtn);
43
44 add(toolBar, BorderLayout.NORTH);
45 }
46
47 public void refresh() {
48 File rootDir = WorkspaceManager.getRoot();
49 if (!rootDir.exists()) {
51 }
52
53 DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(new FileNode(rootDir));
54 buildTree(rootDir, rootNode);
55
56 if (fileTree == null) {
57 treeModel = new DefaultTreeModel(rootNode);
58 fileTree = new JTree(treeModel);
59 fileTree.setCellRenderer(new FileTreeCellRenderer());
60 fileTree.addMouseListener(new MouseAdapter() {
61 public void mousePressed(MouseEvent e) {
62 if (SwingUtilities.isRightMouseButton(e)) {
63 int selRow = fileTree.getRowForLocation(e.getX(), e.getY());
64 if (selRow != -1) {
65 fileTree.setSelectionRow(selRow);
66 showContextMenu(e.getComponent(), e.getX(), e.getY());
67 }
68 }
69 }
70 public void mouseClicked(MouseEvent e) {
71 if (e.getClickCount() == 2) {
73 }
74 }
75 });
76 JScrollPane scrollPane = new JScrollPane(fileTree);
77 scrollPane.setBorder(BorderFactory.createEmptyBorder());
78 add(scrollPane, BorderLayout.CENTER);
79 } else {
80 treeModel.setRoot(rootNode);
81 treeModel.reload();
82 }
83 revalidate();
84 repaint();
85 }
86
87 private void buildTree(File file, DefaultMutableTreeNode node) {
88 File[] list = file.listFiles();
89 if (list == null) return;
90
91 Arrays.sort(list, (a, b) -> {
92 if (a.isDirectory() && !b.isDirectory()) return -1;
93 if (!a.isDirectory() && b.isDirectory()) return 1;
94 return a.getName().compareToIgnoreCase(b.getName());
95 });
96
97 for (File f : list) {
98 DefaultMutableTreeNode child = new DefaultMutableTreeNode(new FileNode(f));
99 node.add(child);
100 if (f.isDirectory()) buildTree(f, child);
101 }
102 }
103
104 private void showContextMenu(Component invoker, int x, int y) {
105 JPopupMenu menu = new JPopupMenu();
106
107 JMenuItem view = new JMenuItem("View Content");
108 view.addActionListener(e -> viewSelectedFile());
109 menu.add(view);
110
111 JMenuItem rename = new JMenuItem("Rename");
112 rename.addActionListener(e -> renameSelected());
113 menu.add(rename);
114
115 menu.addSeparator();
116
117 JMenuItem delete = new JMenuItem("Delete");
118 delete.addActionListener(e -> deleteSelected());
119 menu.add(delete);
120
121 menu.show(invoker, x, y);
122 }
123
124 private void viewSelectedFile() {
125 File f = getSelectedFile();
126 if (f != null && f.isFile()) {
127 try {
128 String content = new String(Files.readAllBytes(f.toPath()));
129 JTextArea textArea = new JTextArea(content);
130 textArea.setEditable(false);
131 textArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
132 JScrollPane scroll = new JScrollPane(textArea);
133 scroll.setPreferredSize(new Dimension(600, 400));
134 JOptionPane.showMessageDialog(this, scroll, "Viewing: " + f.getName(), JOptionPane.PLAIN_MESSAGE);
135 } catch (Exception e) {
136 JOptionPane.showMessageDialog(this, "Could not read file: " + e.getMessage());
137 }
138 }
139 }
140
141 private void renameSelected() {
142 File f = getSelectedFile();
143 if (f == null) return;
144
145 String newName = JOptionPane.showInputDialog(this, "Enter new name:", f.getName());
146 if (newName != null && !newName.trim().isEmpty()) {
147 File dest = new File(f.getParentFile(), newName.trim());
148 if (f.renameTo(dest)) {
149 refresh();
150 } else {
151 JOptionPane.showMessageDialog(this, "Rename failed. Ensure the name is valid and not in use.");
152 }
153 }
154 }
155
156 private void deleteSelected() {
157 File f = getSelectedFile();
158 if (f == null) return;
159
160 int res = JOptionPane.showConfirmDialog(this, "Delete " + f.getName() + "?", "Confirm Delete", JOptionPane.YES_NO_OPTION);
161 if (res == JOptionPane.YES_OPTION) {
162 if (deleteRecursively(f)) {
163 refresh();
164 } else {
165 JOptionPane.showMessageDialog(this, "Delete failed.");
166 }
167 }
168 }
169
170 private boolean deleteRecursively(File f) {
171 if (f.isDirectory()) {
172 File[] children = f.listFiles();
173 if (children != null) {
174 for (File child : children) deleteRecursively(child);
175 }
176 }
177 return f.delete();
178 }
179
180 private File getSelectedFile() {
181 DefaultMutableTreeNode node = (DefaultMutableTreeNode) fileTree.getLastSelectedPathComponent();
182 if (node == null) return null;
183 FileNode fileNode = (FileNode) node.getUserObject();
184 return fileNode.file;
185 }
186
187 private static class FileNode {
188 File file;
189 FileNode(File file) { this.file = file; }
190 @Override public String toString() {
191 return file.getName().isEmpty() ? file.getPath() : file.getName();
192 }
193 }
194
195 private class FileTreeCellRenderer extends DefaultTreeCellRenderer {
196 private Icon folderIcon = UIManager.getIcon("FileView.directoryIcon");
197 private Icon fileIcon = UIManager.getIcon("FileView.fileIcon");
198
199 @Override
200 public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean exp, boolean leaf, int row, boolean hasFocus) {
201 super.getTreeCellRendererComponent(tree, value, sel, exp, leaf, row, hasFocus);
202
203 DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
204 if (node.getUserObject() instanceof FileNode) {
205 File file = ((FileNode) node.getUserObject()).file;
206 if (file.isDirectory()) {
207 setIcon(folderIcon);
208 } else {
209 setIcon(fileIcon);
210 }
211 }
212 return this;
213 }
214 }
215}
Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean exp, boolean leaf, int row, boolean hasFocus)
void buildTree(File file, DefaultMutableTreeNode node)
void showContextMenu(Component invoker, int x, int y)