package jffile;
/**
* Created : Aug 11, 2012
*
* @author pquiring
*/
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javaforce.*;
import javaforce.jbus.*;
import javaforce.linux.*;
import javaforce.utils.*;
public class JFileBrowser extends javax.swing.JComponent implements MouseListener, MouseMotionListener, KeyListener, monitordir.Listener {
/**
* Creates new form JFileBrowser
* @param view - any of the VIEW_... types
* @param path - initial path to view (local system only)
* @param desktopMenu - popup menu for unused areas of panel
* @param fileMenu - popup menu for files
* @param wallPaperFile - PNG file to wallpaper panel (optional)
* @param wallPaperView - WALLPAPER_VIEW_... types
* @param saveConfig - saves layout to .desktop file
* @param openFolder - program to open folders with (else just navigates to them) (optional)
* @param openFile - program to open files
* @param backClr - background color (selections) and (if no wallpaper)
* @param foreClr - text color
* @param useScrolling - use scroll bars?
* @param arrangeIconsVertical - arrange icons vertical (else horizontal)
* @param showHidden - show hidden files (files that begin with a period)
* @param autoArrange - auto arrange by name
* @param jbusClient - a JBusClient client
* @param desktopMode - desktopMode (always use openFile for files)
* @param fileClipboard - file selection storage
*/
public JFileBrowser(int view, String path, JPopupMenu desktopMenu, JPopupMenu fileMenu
, String wallPaperFile, int wallPaperView, boolean saveConfig
, String openFolder, String openFile, Color backClr, Color foreClr
, boolean useScrolling, boolean arrangeIconsVertical, boolean showHidden, boolean autoArrange
, JBusClient jbusClient, boolean desktopMode, FileClipboard fileClipboard)
{
setView(view);
this.desktopMenu = desktopMenu;
this.fileMenu = fileMenu;
this.wallPaperFile = wallPaperFile;
this.wallPaperView = wallPaperView;
this.saveConfig = saveConfig;
this.openFolder = openFolder;
this.openFile = openFile;
this.backClr = backClr;
this.foreClr = foreClr;
this.useScrolling = useScrolling;
this.arrangeIconsVertical = arrangeIconsVertical;
this.showHidden = showHidden;
this.autoArrange = autoArrange;
this.jbusClient = jbusClient;
this.desktopMode = desktopMode;
this.fileClipboard = fileClipboard;
filterRegex = ".*";
filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.matches(filterRegex);
}
};
loadWallPaper();
setLayout(null);
setFocusable(true);
setPath(path); //must do last since it calls refresh()
addKeyListener(this);
}
public static final int VIEW_ICONS = 1;
public static final int VIEW_LIST = 2;
public static final int VIEW_DETAILS = 3;
public static final int WALLPAPER_VIEW_CENTER = 0;
public static final int WALLPAPER_VIEW_TILE = 1;
public static final int WALLPAPER_VIEW_FULL = 2;
public static final int WALLPAPER_VIEW_FILL = 3;
private int view;
private String path;
private String mount;
private JPopupMenu desktopMenu, fileMenu;
private String wallPaperFile;
private int wallPaperView;
private boolean saveConfig;
private String openFolder, openFile;
public Color backClr, foreClr;
private boolean useScrolling, arrangeIconsVertical;
private boolean showHidden;
private boolean autoArrange;
private boolean desktopMode;
private JFileBrowserListener listener;
private JBusClient jbusClient;
private FilenameFilter filter;
private String filterRegex;
private FileClipboard fileClipboard;
private JFImage wallPaper;
//icon view dimensions
public static int ix, iy; //icon image size
public static int bx, by; //icon size
private int nx, ny; //next position
private int mx, my; //last mouse pressed
private ArrayList<FileEntry> entries = new ArrayList<FileEntry>();
private JScrollPane scroll;
private JPanel panel;
private boolean iconsVisible = true;
public void setBounds(int x,int y,int w,int h) {
super.setBounds(x,y,w,h);
// JFLog.log("setBounds:" + getWidth() + "," + getHeight());
if (scroll != null) {
scroll.setBounds(0,0,getWidth(),getHeight());
calcPanelSize();
} else if (panel != null) {
panel.setBounds(0,0,getWidth(),getHeight());
}
if (listener != null) listener.browserResized(this);
update();
}
public void setListener(JFileBrowserListener listener) {
this.listener = listener;
}
private void initGUI() {
// JFLog.log("initGUI:" + getWidth() + "," + getHeight());
panel = new JPanel() {
public Dimension getPreferredSize() {
return getSize();
}
public void paintChildren(Graphics g) {
if (!iconsVisible) return;
super.paintChildren(g);
}
public void paintComponent(Graphics g) {
// JFLog.log("JFB:paint");
g.setColor(backClr);
int px = getWidth();
int py = getHeight();
g.fillRect(0,0,px,py);
if (wallPaper != null) {
//paint wallpaper
int wx = wallPaper.getWidth();
int wy = wallPaper.getHeight();
switch (wallPaperView) {
case WALLPAPER_VIEW_CENTER:
g.drawImage(wallPaper.getImage(), (px - wx) / 2, (py - wy) / 2, null);
break;
case WALLPAPER_VIEW_TILE:
Image img = wallPaper.getImage();
for(int x=0;x<px;x+=wx) {
for(int y=0;y<py;y+=wy) {
g.drawImage(img, x, y, null);
}
}
break;
case WALLPAPER_VIEW_FULL:
//maintains aspect ratio
int dx = px - wx;
int dy = py - wy;
if (dx > dy) {
//image touches top/bottom (bars left/right)
g.drawImage(wallPaper.getImage(), dx/2, 0, null);
} else {
//image touches left/right (bars top/bottom)
g.drawImage(wallPaper.getImage(), 0, dy/2, null);
}
break;
case WALLPAPER_VIEW_FILL:
//ignore aspect ration : can distort image
g.drawImage(wallPaper.getImage(), 0, 0, px, py, null);
break;
}
}
if (dragselection) {
g.setColor(new Color(0x77003377, true));
int x1, y1, x2, y2;
if (dragX < selX) {
x1 = dragX;
x2 = selX;
} else {
x2 = dragX;
x1 = selX;
}
if (dragY < selY) {
y1 = dragY;
y2 = selY;
} else {
y2 = dragY;
y1 = selY;
}
g.fillRect(x1,y1,x2-x1,y2-y1);
}
}
};
panel.addMouseListener(this);
panel.addMouseMotionListener(this);
panel.addKeyListener(this);
panel.setLayout(null);
panel.setBounds(0,0,getWidth(),getHeight());
if (useScrolling) {
scroll = new JScrollPane(panel);
scroll.setBounds(0,0,getWidth(),getHeight());
add(scroll);
} else {
add(panel);
}
}
private void listFiles() {
// JFLog.log("path=" + path);
// JFLog.log("JFileBrowser:listFiles():size=" + getWidth() + "," + getHeight());
File file = new File(path);
File files[] = file.listFiles(filter);
if (files == null) return;
Arrays.sort(files);
if (view != VIEW_ICONS) {
bx = 0;
by = 18;
JFImage tmp = new JFImage(1,1);
for(int a=0;a<files.length;a++) {
int w = ix + tmp.getGraphics().getFontMetrics().stringWidth(files[a].getName());
if (w > bx) bx = w;
}
}
for(int a=0;a<files.length;a++) {
String fullfile = files[a].getAbsolutePath();
if (fullfile.endsWith("/.desktop")) continue;
int idx = fullfile.lastIndexOf(File.separatorChar);
if (fullfile.substring(idx+1).startsWith(".")) {
if (!showHidden) continue;
}
if (files[a].isDirectory()) {
addFolder(fullfile);
} else {
if (fullfile.endsWith(".desktop")) {
addDesktopFile(fullfile);
} else {
addFile(fullfile);
}
}
}
}
private void nextPosition(FileEntry entry, boolean check) {
switch (view) {
case VIEW_ICONS:
nextPositionIcons(entry, check);
break;
case VIEW_LIST:
nextPositionList(entry);
break;
case VIEW_DETAILS:
nextPositionDetails(entry);
break;
}
}
private void nextPositionIcons(FileEntry entry, boolean check) {
boolean noRoom = false;
boolean tooClose;
int px = getWidth();
int py = getHeight();
do {
entry.x = nx;
entry.y = ny;
if (arrangeIconsVertical) {
ny += by + 5;
if (ny + by > py) {
nx += bx + 5;
ny = 5;
}
if (nx + bx > px && !useScrolling) {
if (noRoom) {
entry.x = 5;
entry.y = 5;
return;
}
nx = 5;
noRoom = true;
}
} else {
nx += bx + 5;
if (nx + bx > px) {
ny += by + 5;
nx = 5;
}
if (ny + by > py && !useScrolling) {
if (noRoom) {
entry.x = 5;
entry.y = 5;
return;
}
ny = 5;
noRoom = true;
}
}
tooClose = false;
if (check) {
tooClose = checkProximity(entry);
}
} while(tooClose);
}
private void nextPositionList(FileEntry entry) {
entry.x = nx;
entry.y = ny;
int px = getWidth();
int py = getHeight();
if ((arrangeIconsVertical) || (true)) {
ny += by;
if (ny + by > py) {
nx += bx;
ny = 0;
}
} else {
//doesn't make sense to use this ever
nx += bx;
if (nx + bx > px) {
ny += by;
nx = 0;
}
}
}
private void nextPositionDetails(FileEntry entry) {
entry.x = nx;
entry.y = ny;
ny += by;
}
public boolean checkProximity(FileEntry entry) {
for(int a=0;a<entries.size();a++) {
FileEntry otherEntry = entries.get(a);
if (otherEntry == entry) continue;
int dx = entry.x - otherEntry.x;
int dy = entry.y - otherEntry.y;
int len = (int)Math.sqrt(dx * dx + dy * dy);
if (len < bx) return true;
}
return false;
}
private void addDetails(FileEntry entry) {
File file = new File(entry.file);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(file.lastModified());
String date = String.format("%d-%d-%d", c.get(Calendar.YEAR), c.get(Calendar.MONTH)+1, c.get(Calendar.DAY_OF_MONTH));
String time = String.format("%02d:%02d", c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));
String size = "" + file.length();
entry.details_date = new JLabel(date);
entry.details_date.setForeground(foreClr);
panel.add(entry.details_date);
Dimension dim = entry.details_date.getPreferredSize();
entry.details_date.setBounds(entry.x + bx, entry.y, dim.width, dim.height);
entry.details_time = new JLabel(time);
entry.details_time.setForeground(foreClr);
panel.add(entry.details_time);
dim = entry.details_time.getPreferredSize();
entry.details_time.setBounds(entry.x + bx + 96, entry.y, dim.width, dim.height);
entry.details_size = new JLabel(size);
entry.details_size.setForeground(foreClr);
panel.add(entry.details_size);
dim = entry.details_size.getPreferredSize();
entry.details_size.setBounds(entry.x + bx + 96 + 64, entry.y, dim.width, dim.height);
}
private JFileIcon addIcon(FileEntry entry) {
for(int a=0;a<entries.size();a++) {
if (entries.get(a).file.equals(entry.file)) {
return entries.get(a).button;
}
}
if (!new File(entry.file).exists()) {
JFLog.log("Error:File not found:" + entry.file);
return null;
}
int px = getWidth();
int py = getHeight();
JFImage buttonImage = IconCache.loadIcon(entry.icon);
buttonImage = IconCache.scaleIcon(buttonImage, ix, iy);
entry.button = new JFileIcon(this, buttonImage, entry, view == VIEW_ICONS);
entry.button.setToolTipText(entry.name);
entry.button.addKeyListener(this);
entry.button.addMouseListener(this);
entry.button.addMouseMotionListener(this);
if ((!useScrolling) && (view == VIEW_ICONS)) {
if ((entry.x + bx > px) || (entry.y + by > py)) {
nextPosition(entry, true);
}
}
panel.add(entry.button);
entry.button.setLocation(entry.x, entry.y);
entries.add(entry);
if (view == VIEW_DETAILS) {
addDetails(entry);
}
return entry.button;
}
private JFileIcon addNewIcon(String icon, String name, String file) {
FileEntry entry = new FileEntry();
nextPosition(entry, false);
entry.icon = icon;
entry.name = name;
entry.file = file;
return addIcon(entry);
}
private JFileIcon addNewIconDesktop(String fn) {
String name = null, icon = null;
try {
FileInputStream fis = new FileInputStream(fn);
byte data[] = JF.readAll(fis);
fis.close();
String str = new String(data);
String lns[] = str.split("\n");
boolean desktopEntry = false;
for(int a=0;a<lns.length;a++) {
if (lns[a].startsWith("[Desktop Entry]")) {
desktopEntry = true;
continue;
}
if (lns[a].startsWith("[")) desktopEntry = false;
if (!desktopEntry) continue;
if (lns[a].startsWith("Name=")) {
name = lns[a].substring(5);
}
if (lns[a].startsWith("Icon=")) {
icon = lns[a].substring(5);
}
}
if (name == null) JFLog.log("Warning:No NAME field for icon:" + fn);
if (icon == null) icon = "jfile-404";
int i1 = fn.lastIndexOf(File.separatorChar);
name = fn.substring(i1+1, fn.length() - 8); //.desktop
return addNewIcon(icon, name, fn);
} catch (FileNotFoundException e) {
JFLog.log("File not found:" + fn);
return null;
} catch (Exception e) {
JFLog.log(e);
return null;
}
}
private String getFileName(String fn) {
int idx;
idx = fn.lastIndexOf(File.separatorChar);
if (idx != -1) fn = fn.substring(idx+1);
if (!fn.endsWith(".desktop")) return fn;
//remove .desktop extension
idx = fn.lastIndexOf(".");
if (idx == -1) return fn;
return fn.substring(0, idx);
}
private String getFolderName(String fn) {
int idx = fn.lastIndexOf(File.separatorChar);
if (idx == -1) return fn;
return fn.substring(idx+1);
}
private void addFile(String fn) {
switch (view) {
case VIEW_ICONS:
case VIEW_LIST:
case VIEW_DETAILS:
addNewIcon(IconCache.findIcon(fn), getFileName(fn), fn);
break;
}
}
private void addDesktopFile(String fn) {
switch (view) {
case VIEW_ICONS:
case VIEW_LIST:
case VIEW_DETAILS:
addNewIconDesktop(fn);
break;
}
}
private void addFolder(String fn) {
JFileIcon fi = null;
String icon = NetworkShares.isShared(fn) ? "jfile-folder-shared" : "jfile-folder";
switch (view) {
case VIEW_ICONS:
case VIEW_LIST:
case VIEW_DETAILS:
fi = addNewIcon(icon, getFolderName(fn), fn);
break;
}
if (fi == null) return;
fi.entry.isDir = true;
}
private void loadWallPaper() {
if (wallPaperFile == null) return;
wallPaper = new JFImage();
if (!wallPaper.load(wallPaperFile)) {
wallPaper = null;
}
}
public void setWallPaper(String file, int mode) {
wallPaperFile = file;
wallPaperView = mode;
loadWallPaper();
repaint();
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
int mods = e.getModifiers();
// JFLog.log("keyPressed:" + mods + "," + (char)keycode);
if (mods == KeyEvent.CTRL_MASK) {
switch (keycode) {
case KeyEvent.VK_C:
copy();
break;
case KeyEvent.VK_X:
cut();
break;
case KeyEvent.VK_V:
paste();
break;
}
}
if (mods == 0) {
switch (keycode) {
case KeyEvent.VK_DELETE: delete(); break;
}
}
}
public void keyReleased(KeyEvent e) {
}
public class Config {
public FileEntry file[];
}
private void loadConfig() {
if (!saveConfig) return;
try {
String fn = path + "/.desktop";
Config config = new Config();
if (!new File(fn).exists()) {
JFLog.log("Error:File not found:" + fn);
return;
}
FileInputStream fis = new FileInputStream(fn);
XML xml = new XML();
xml.read(fis);
xml.writeClass(config);
fis.close();
for(int a=0;a<config.file.length;a++) {
addIcon(config.file[a]);
}
} catch (Exception e) {
JFLog.log(e);
}
}
private void saveConfig() {
if (!saveConfig) return;
//save Entries to .desktop file
try {
Config config = new Config();
config.file = entries.toArray(new FileEntry[0]);
FileOutputStream fos = new FileOutputStream(path + "/.desktop");
XML xml = new XML();
xml.readClass("desktop", config);
xml.write(fos);
fos.close();
} catch (Exception e) {
JFLog.log(e);
}
}
@SuppressWarnings("unchecked")
public void arrangeByName() {
if (view != VIEW_ICONS) return;
try {
nx = 5;
ny = 5;
//place Home first
FileEntry entry;
Object list[] = panel.getComponents();
Arrays.sort(list, new Comparator() {
public int compare(Object t1, Object t2) {
if (!(t1 instanceof JFileIcon)) return 1;
if (!(t2 instanceof JFileIcon)) return -1;
JFileIcon b1 = (JFileIcon)t1;
JFileIcon b2 = (JFileIcon)t2;
String s1 = b1.getText();
if (s1.equals("Home")) return -1;
String s2 = b2.getText();
if (s2.equals("Home")) return 1;
return s1.compareTo(s2);
}
});
for(int a=0;a<list.length;a++) {
if (!(list[a] instanceof JFileIcon)) continue;
JFileIcon button = (JFileIcon)list[a];
entry = button.entry;
if (entry == null) continue;
nextPosition(entry, false);
button.setLocation(entry.x, entry.y);
}
saveConfig();
update();
} catch (Exception e) {
JFLog.log(e);
}
}
public void arrangeByGrid() {
if (view != VIEW_ICONS) return;
try {
FileEntry entry;
Object list[] = panel.getComponents();
int xx = 5 + bx;
int yy = 5 + by;
for(int a=0;a<list.length;a++) {
if (!(list[a] instanceof JFileIcon)) continue;
JFileIcon button = (JFileIcon)list[a];
entry = button.entry;
if (entry == null) continue;
entry.x = ((((entry.x-5) + (xx/2)) / xx) * xx) + 5;
entry.y = ((((entry.y-5) + (yy/2)) / yy) * yy) + 5;
if (checkProximity(entry)) {
nx = entry.x;
ny = entry.y;
nextPosition(entry, true);
}
button.setLocation(entry.x, entry.y);
}
saveConfig();
update();
} catch (Exception e) {
JFLog.log(e);
}
}
private void calcPanelSize() {
int px = 0, py = 0;
int w = bx;
if (view == VIEW_DETAILS) {
w += 256; //details columns
}
for(int a=0;a<entries.size();a++) {
FileEntry entry = entries.get(a);
int x = entry.x + w;
if (x > px) px = x;
int y = entry.y + by;
if (y > py) py = y;
}
panel.setSize(px, py);
}
public void refresh() {
if (path == null) return;
// JFLog.log("JFileBrowser:refresh");
try {
stopFolderListener();
removeAll();
entries.clear();
switch (view) {
case VIEW_ICONS:
nx = 5;
ny = 5;
break;
case VIEW_LIST:
nx = 0;
ny = 0;
break;
case VIEW_DETAILS:
nx = 0;
ny = 0;
break;
}
initGUI();
initDND();
loadConfig();
listFiles();
if (useScrolling) calcPanelSize();
update();
startFolderListener();
} catch (Exception e) {
JFLog.log(e);
}
}
public void setFilter(String regex) {
filterRegex = regex;
refresh();
}
private void clearSelection() {
int cnt = panel.getComponentCount();
for(int a=0;a<cnt;a++) {
JComponent c = (JComponent)panel.getComponent(a);
if (!(c instanceof JFileIcon)) continue;
JFileIcon b = (JFileIcon)c;
b.setSelected(false);
b.setTransparent(false);
}
repaint();
}
private void selectIcons() {
//select icons from dragX/Y to selX/Y
int x1, y1, x2, y2;
if (dragX < selX) {
x1 = dragX;
x2 = selX;
} else {
x2 = dragX;
x1 = selX;
}
if (dragY < selY) {
y1 = dragY;
y2 = selY;
} else {
y2 = dragY;
y1 = selY;
}
int cnt = panel.getComponentCount();
for(int a=0;a<cnt;a++) {
JComponent c = (JComponent)panel.getComponent(a);
if (!(c instanceof JFileIcon)) continue;
JFileIcon b = (JFileIcon)c;
Point p = b.getLocation();
p.x += b.getWidth()/2;
p.y += b.getHeight()/2;
if ((p.x >= x1) && (p.x <= x2) && (p.y >= y1) && (p.y <= y2)) {
b.setSelected(true);
} else {
b.setSelected(false);
}
}
}
public void setPath(String newpath) {
if (newpath == null) return;
try {
if (mount != null) {
if (!newpath.startsWith(mount)) {
closeFile();
}
}
if (new File(newpath).isDirectory()) {
path = newpath;
} else {
openFile(newpath);
}
refresh();
if (listener != null) listener.browserChangedPath(this, newpath);
} catch (Exception e) {
JFLog.log(e);
}
}
public String getPath() {
return path;
}
private void execute(String cmd[], boolean wait) {
try {
if (wait) {
ProcessBuilder pb = new ProcessBuilder();
pb.command(cmd);
Process p = pb.start();
p.waitFor();
} else {
Runtime.getRuntime().exec(cmd);
}
} catch (Exception e) {
JFLog.log(e);
}
}
private void openEntry(FileEntry entry) {
File file = new File(entry.file);
if (!file.exists()) return;
if (file.isDirectory()) {
if (openFolder == null) {
setPath(entry.file);
} else {
execute(new String[] {openFolder, entry.file}, false);
}
} else {
if (entry.file.endsWith(".desktop")) {
//execute desktop file
try {
Linux.executeDesktop(entry.file, null);
} catch (Exception e) {
JFLog.log(e);
}
} else if (!desktopMode && entry.file.toLowerCase().endsWith(".iso")) {
openFile(entry.file);
} else if (!desktopMode && entry.file.toLowerCase().endsWith(".zip")) {
openFile(entry.file);
} else {
if (openFile == null) return;
execute(new String[] {openFile, entry.file}, false);
}
}
}
public void invoke(JFileIcon b) {
openEntry(b.entry);
}
private java.util.Timer refreshTimer;
private Vector<String> newFiles = new Vector<String>();
private Vector<String> removeFiles = new Vector<String>();
private final Object lock = new Object();
public void folderChangeEvent(String event, String file) {
// JFLog.log("folderChangeEvent:" + event + ":" + file);
try {
if (event.equals("CREATED") || event.equals("MOVED_TO")) {
if ((file.startsWith(".")) && (!showHidden)) return;
newFiles.add(file);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
while (newFiles.size() > 0) {
String fn = path + "/" + newFiles.remove(0);
File file = new File(fn);
if (file.isDirectory()) {
addFolder(fn);
} else {
if (fn.endsWith(".desktop")) {
addDesktopFile(fn);
} else {
addFile(fn);
}
}
}
saveConfig();
update();
}
});
} else if (event.equals("DELETED") || event.equals("MOVED_FROM")) {
if (/*view == VIEW_LIST ||*/ view == VIEW_DETAILS) {
//need to do a refresh in 100ms (just removing the icon would look bad)
synchronized(lock) {
if (refreshTimer == null) {
refreshTimer = new java.util.Timer();
refreshTimer.schedule(new TimerTask() {
public void run() {
synchronized(lock) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
refreshTimer = null;
refresh();
}
});
}
}
}, 100);
}
}
} else {
//just remove the icon
removeFiles.add(file);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Component list[] = panel.getComponents();
while (removeFiles.size() > 0) {
String fn = removeFiles.remove(0);
for(int a=0;a<list.length;a++) {
if (!(list[a] instanceof JFileIcon)) continue;
JFileIcon icon = (JFileIcon)list[a];
if (icon.entry.name.equals(fn)) {
panel.remove(list[a]);
break;
}
}
for(int a=0;a<entries.size();a++) {
if (entries.get(a).name.equals(fn)) {
entries.remove(a);
break;
}
}
}
saveConfig();
update();
}
});
}
} else if (event.equals("DELETE_SELF") || event.equals("MOVED_SELF")) {
if (!desktopMode) {
System.exit(0);
}
}
} catch (Exception e) {
JFLog.log(e);
}
}
private int monitor = -1;
private void startFolderListener() {
monitor = monitordir.add(path);
monitordir.setListener(monitor, this);
}
private void stopFolderListener() {
if (monitor == -1) return;
monitordir.remove(monitor);
monitor = -1;
}
public void setIconsVisible(boolean state) {
iconsVisible = state;
repaint();
}
public FileEntry createIcon(String name, String exec, String icon, String fn, boolean nextPos) {
try {
FileOutputStream fos = new FileOutputStream(fn);
fos.write("[Desktop Entry]\n".getBytes());
fos.write(("Name=" + name + "\n").getBytes());
fos.write(("Exec=" + exec + "\n").getBytes());
fos.write(("Icon=" + icon + "\n").getBytes());
fos.close();
FileEntry entry = new FileEntry();
if (nextPos) {
nextPosition(entry, true);
} else {
entry.x = mx;
entry.y = my;
}
entry.file = fn;
entry.name = name;
entry.icon = icon;
addIcon(entry);
saveConfig();
update();
return entry;
} catch (Exception e) {
JFLog.log(e);
}
return null;
}
public static void runCmd(final JFileBrowser browser,final String cmd[]) {
new Thread() {
public void run() {
try {
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
if (browser != null) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
browser.refresh();
}
});
}
} catch (Exception e) {
JFLog.log(e);
}
}
}.start();
}
public static int cntFiles(String fn) {
File file = new File(fn);
int cnt = 1;
if (file.isDirectory()) {
File files[] = file.listFiles();
for(int a=0;a<files.length;a++) {
if (files[a].isDirectory()) {
cnt += cntFiles(files[a].getAbsolutePath());
} else {
cnt++;
}
}
}
return cnt;
}
private JFileIcon dragTarget;
private void initDND() {
panel.setTransferHandler(new TransferHandler() {
public boolean canImport(TransferHandler.TransferSupport info) {
// we only import Files
if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
DropLocation dl = (DropLocation) info.getDropLocation();
Point pt = dl.getDropPoint();
JComponent c = (JComponent)panel.getComponentAt(pt);
if (dragTarget != null) {
dragTarget.setSelected(false);
dragTarget = null;
}
if (c != null) {
if (c instanceof JFileIcon) {
JFileIcon fi = (JFileIcon)c;
if (!fi.isTransparent()) {
fi.setSelected(true);
dragTarget = fi;
}
}
}
return true;
}
public boolean importData(TransferHandler.TransferSupport info) {
if (!info.isDrop()) {
return false;
}
// Check for file flavor
if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
DropLocation dl = info.getDropLocation();
Point pt = dl.getDropPoint();
JComponent c = (JComponent)panel.getComponentAt(pt);
if (dragTarget != null) {
dragTarget.setSelected(false);
dragTarget = null;
}
if (c != null) {
if (c instanceof JFileIcon) {
JFileIcon fi = (JFileIcon)c;
if (!fi.isTransparent()) {
fi.setSelected(true);
dragTarget = fi;
}
}
}
String folder = path;
if (dragTarget != null) {
FileEntry entry = dragTarget.entry;
if (entry.isLink) return false;
if (entry.isDir) {
folder += File.separatorChar;
folder += entry.name;
}
}
// Get the file(s) that are being dropped.
Transferable t = info.getTransferable();
java.util.List<File> data;
try {
data = (java.util.List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
} catch (Exception e) {
return false;
}
// Perform the actual import.
ArrayList<String> cmd = new ArrayList<String>();
boolean move = false;
boolean copy = false;
String fn;
for(int a=0;a<data.size();a++) {
switch (info.getDropAction()) {
case COPY:
if (move) return false; //Can that happen?
copy = true;
fn = ((File)data.get(a)).getAbsolutePath();
cmd.add(fn);
break;
case MOVE:
if (copy) return false; //Can that happen?
move = true;
cmd.add(((File)data.get(a)).getAbsolutePath());
break;
case LINK:
return false; //BUG : not supported : ???
}
}
if (cmd.isEmpty()) return false;
if (copy) {
cmd.add(0, "jcp");
} else if (move) {
cmd.add(0, "jmv");
} else {
return false;
}
cmd.add(folder);
runCmd(JFileBrowser.this, cmd.toArray(new String[0]));
return true;
}
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
protected Transferable createTransferable(JComponent c) {
FileEntry fefiles[] = getSelected();
final ArrayList<File> files = new ArrayList<File>();
for (int i = 0; i < fefiles.length; i++) {
files.add(new File(fefiles[i].file));
}
return new Transferable() {
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] {DataFlavor.javaFileListFlavor};
}
public boolean isDataFlavorSupported(DataFlavor df) {
return (df == DataFlavor.javaFileListFlavor);
}
public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException {
return files;
}
};
}
protected void exportDone(JComponent source, Transferable data, int action) {
clearSelection();
}
});
}
public void deleteFile(String filename) {
for(int a=0;a<entries.size();a++) {
if (entries.get(a).file.equals(filename)) {
FileEntry entry = entries.get(a);
File file = new File(filename);
file.delete();
if (file.exists()) {
//access denied
if (file.isDirectory()) {
JF.showError("Error", "Can not delete folder");
} else {
JF.showError("Error", "Can not delete file");
}
return;
}
panel.remove(entry.button);
if (view == VIEW_DETAILS) {
panel.remove(entry.details_date);
panel.remove(entry.details_time);
panel.remove(entry.details_size);
}
entries.remove(a);
saveConfig();
update();
return;
}
}
}
public FileEntry[] getSelected() {
ArrayList<FileEntry> list = new ArrayList<FileEntry>();
int cnt = panel.getComponentCount();
for(int a=0;a<cnt;a++) {
JComponent c = (JComponent)panel.getComponent(a);
if (!(c instanceof JFileIcon)) continue;
JFileIcon b = (JFileIcon)c;
if (b.isSelected()) {
list.add(b.entry);
}
}
return list.toArray(new FileEntry[0]);
}
public FileEntry[] getFolders() {
ArrayList<FileEntry> list = new ArrayList<FileEntry>();
int cnt = panel.getComponentCount();
for(int a=0;a<cnt;a++) {
JComponent c = (JComponent)panel.getComponent(a);
if (!(c instanceof JFileIcon)) continue;
JFileIcon b = (JFileIcon)c;
if (b.entry.isDir) {
list.add(b.entry);
}
}
return list.toArray(new FileEntry[0]);
}
//also returns to org position from drag
private void setSelectedTransparent(boolean undrag) {
int cnt = panel.getComponentCount();
for(int a=0;a<cnt;a++) {
JComponent c = (JComponent)panel.getComponent(a);
if (!(c instanceof JFileIcon)) continue;
JFileIcon b = (JFileIcon)c;
if (b.isSelected()) {
b.setTransparent(true);
if (undrag) b.setLocation(b.dragX, b.dragY);
}
}
}
public void setSelectedTransparent() {
setSelectedTransparent(false);
}
public void trash() {
if (JF.isWindows()) {
//TODO
return;
} else {
FileEntry list[] = getSelected();
if ((list == null) || (list.length == 0)) return;
ArrayList<String> cmd = new ArrayList<String>();
cmd.add("jmv");
for(int a=0;a<list.length;a++) cmd.add(list[a].file);
cmd.add(JF.getUserPath() + "/.local/share/Trash");
runCmd(this, cmd.toArray(new String[0]));
}
}
public void delete() {
FileEntry list[] = getSelected();
if ((list == null) || (list.length == 0)) return;
ArrayList<String> cmd = new ArrayList<String>();
cmd.add("jrm");
for(int a=0;a<list.length;a++) cmd.add(list[a].file);
runCmd(this, cmd.toArray(new String[0]));
}
public int getCount() {
return entries.size();
}
public int getSelectedCount() {
return getSelected().length;
}
public FileEntry[] getAll() {
return entries.toArray(new FileEntry[0]);
}
public void selectFile(FileEntry entry) {
clearSelection();
entry.button.setSelected(true);
entry.button.repaint();
}
public void setView(int newview) {
view = newview;
switch (view) {
case VIEW_ICONS:
ix = 48;
iy = 48;
bx = ix + 32;
by = iy + 32;
break;
case VIEW_LIST:
case VIEW_DETAILS:
ix = 18;
iy = 18;
//bx,by calc later in listFiles()
break;
}
}
public void setShowHidden(boolean state) {
showHidden = state;
}
public void setAutoArrange(boolean state) {
autoArrange = state;
}
private boolean dragselection, dragicon;
private int dragX, dragY;
private int selX, selY;
private boolean iconMoved;
// private JComponent dragOverlay;
public void mouseClicked(MouseEvent me) {
JComponent c = (JComponent)me.getSource();
int mod = me.getModifiers();
if (c == panel) {
if ((me.getButton() == me.BUTTON3) && (me.getClickCount() == 1)) {
if (desktopMenu == null) return;
mx = me.getX();
my = me.getY();
desktopMenu.show(panel, me.getX(), me.getY());
//TODO : make desktopMenu on top - how ???
}
if ((mod & KeyEvent.CTRL_MASK) == 0) clearSelection();
return;
}
if (c instanceof JFileIcon) {
JFileIcon b = (JFileIcon)c;
switch (me.getClickCount()) {
case 1:
if ((mod & KeyEvent.CTRL_MASK) == 0) clearSelection();
b.setSelected(true);
break;
case 2:
clearSelection();
openEntry(b.entry);
break;
}
}
}
public void mousePressed(MouseEvent me) {
int mod = me.getModifiers();
requestFocus();
dragicon = false;
dragselection = false;
JComponent c = (JComponent)me.getSource();
if (c instanceof JFileIcon) {
JFileIcon b = (JFileIcon)c;
if (!b.isSelected()) {
if ((mod & KeyEvent.CTRL_MASK) == 0) clearSelection();
b.setSelected(true);
}
if (me.getButton() == MouseEvent.BUTTON3) {
if (fileMenu != null) {
mx = me.getX();
my = me.getY();
fileMenu.show(b, me.getX(), me.getY());
}
return;
}
if (me.getButton() != MouseEvent.BUTTON1) return;
dragicon = true;
dragX = me.getXOnScreen();
dragY = me.getYOnScreen();
int cnt = panel.getComponentCount();
for(int a=0;a<cnt;a++) {
c = (JComponent)panel.getComponent(a);
if (!(c instanceof JFileIcon)) continue;
b = (JFileIcon)c;
if (!b.isSelected()) continue;
b.dragX = b.getX();
b.dragY = b.getY();
}
} else {
if (me.getButton() != MouseEvent.BUTTON1) return;
dragX = me.getX();
dragY = me.getY();
selX = dragX;
selY = dragY;
dragselection = true;
}
}
public void mouseReleased(MouseEvent me) {
if (iconMoved) {
if (autoArrange) {
arrangeByGrid();
} else {
if (useScrolling) calcPanelSize();
}
saveConfig();
iconMoved = false;
/* if (dragOverlay != null) {
panel.remove(dragOverlay);
dragOverlay = null;
}*/
}
dragselection = false;
dragicon = false;
repaint();
}
public void mouseEntered(MouseEvent me) {
}
public void mouseExited(MouseEvent me) {
if (dragicon) {
panel.getTransferHandler().exportAsDrag(panel, me, TransferHandler.MOVE);
setSelectedTransparent(true);
dragicon = false;
repaint();
jbusClient.call("org.jflinux.jdesktop." + System.getenv("JID"), "show", "");
/* if (dragOverlay != null) {
panel.remove(dragOverlay);
dragOverlay = null;
}*/
}
}
public void mouseDragged(MouseEvent me) {
if (dragicon) {
iconMoved = true;
int x = me.getXOnScreen();
int y = me.getYOnScreen();
Point pt1 = null;
if (useScrolling) {
pt1 = scroll.getLocationOnScreen();
} else {
pt1 = panel.getLocationOnScreen();
}
Point pt2 = new Point();
pt2.x = pt1.x + getWidth();
pt2.y = pt1.y + getHeight();
if ((x < pt1.x) || (y < pt1.y) || (x > pt2.x) || (y > pt2.y) || (view != VIEW_ICONS) || (!desktopMode)) {
panel.getTransferHandler().exportAsDrag(panel, me, TransferHandler.MOVE);
setSelectedTransparent(true);
dragicon = false;
repaint();
jbusClient.call("org.jflinux.jdesktop." + System.getenv("JID"), "show", "");
/* if (dragOverlay != null) {
panel.remove(dragOverlay);
dragOverlay = null;
}*/
return;
}
int dx = x - dragX;
int dy = y - dragY;
int cnt = panel.getComponentCount();
for(int a=0;a<cnt;a++) {
JComponent c = (JComponent)panel.getComponent(a);
if (!(c instanceof JFileIcon)) continue;
JFileIcon b = (JFileIcon)c;
if (!b.isSelected()) continue;
FileEntry entry = b.entry;
entry.x = b.dragX + dx;
entry.y = b.dragY + dy;
b.setLocation(entry.x, entry.y);
panel.setComponentZOrder(b, 0); //or getComponentCount()
}
/* dragOverlay = new JComponent() {}; //
panel.add(dragOverlay);
panel.setComponentZOrder(dragOverlay, 0);
dragOverlay.setBounds(0,0,getWidth(),getHeight());*/
} else if (dragselection) {
selX = me.getX();
selY = me.getY();
selectIcons();
repaint();
}
}
public void mouseMoved(MouseEvent me) {
}
private void openFile(String file) {
//file = .iso or .zip
if (mount != null) return; //can not open a file in a file (!recursive)
String name;
int idx = file.lastIndexOf("/");
if (idx == -1) {
name = file;
} else {
name = file.substring(idx+1);
}
String mount = JF.getUserPath() + "/.gfvs/" + name;
String fullmount = mount;
int cnt = 1;
while (new File(fullmount).exists()) {
fullmount = mount + "(" + cnt++ + ")";
}
new File(fullmount).mkdirs();
final String args[] = new String[] {file, fullmount, "-f"};
if (file.toLowerCase().endsWith(".iso")) {
//TODO : send msg to jfDesktop.mount
} else if (file.toLowerCase().endsWith(".zip")) {
//TODO : send msg to jfDesktop.mount
} else {
JFLog.log("Error:Can not open:" + file);
setPath(JF.getUserPath());
return;
}
this.mount = fullmount;
JF.sleep(100); //wait for thread to start
setPath(fullmount);
}
public void closeFile() {
if (mount == null) return;
//TODO : send msg to jfDesktop.unmount
mount = null;
}
private void update() {
if (panel == null) return; //refresh not called yet
repaint();
panel.repaint();
}
//use clipboard or jdesktop
public void cut() {
FileEntry list[] = getSelected();
if ((list == null) || (list.length == 0)) return;
String fs = "cut";
for(int a=0;a<list.length;a++) {
fs += ":" + list[a].file;
}
fileClipboard.set(fs);
setSelectedTransparent();
}
public void copy() {
FileEntry list[] = getSelected();
if ((list == null) || (list.length == 0)) return;
String fs = "copy";
for(int a=0;a<list.length;a++) {
fs += ":" + list[a].file;
}
fileClipboard.set(fs);
}
public void paste() {
fileClipboard.get();
}
public void paste(String fileSelection) {
if (fileSelection == null) return;
String f[] = fileSelection.split(":");
ArrayList<String> cmd = new ArrayList<String>();
if (f[0].equals("cut")) {
//cut
cmd.add("jmv");
} else if (f[0].equals("copy")) {
//copy
cmd.add("jcp");
} else {
JFLog.log("Error:unknown clipboard operation=" + f[0]);
}
for(int a=1;a<f.length;a++) {
cmd.add(f[a]);
}
cmd.add(path);
runCmd(this, cmd.toArray(new String[0]));
}
public void close() {
stopFolderListener();
}
}