package jp.crwdev.app.gui;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.JWindow;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import jp.crwdev.app.EventObserver;
import jp.crwdev.app.EventObserver.OnEventListener;
import jp.crwdev.app.constant.Constant;
import jp.crwdev.app.setting.FileListItem;
import jp.crwdev.app.util.InifileProperty;
import jp.crwdev.app.util.SerializeArrayUtil;
@SuppressWarnings("serial")
public class FileListTable extends JTable implements OnEventListener {
private DefaultTableModel mTableModel = null;
private HashMap<String, String> mThumbnailMap = new HashMap<String, String>();
private EventObserver mEventSender = null;
public void setEventObserver(EventObserver observer){
mEventSender = observer;
}
public FileListTable(){
initialize();
}
private void initialize(){
mTableModel = new DefaultTableModel(Constant.TABLE_HEADER_FILELIST_COLUMNS, 0){
@Override
public boolean isCellEditable(int row, int column) {
return (column == 0); // 編集禁止
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Class getColumnClass(int col){
return getValueAt(0, col).getClass();
}
};
setModel(mTableModel);
setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for(int i=0; i<Constant.TABLE_HEADER_FILELIST_COLUMNS.length; i++){
TableColumn col = getColumnModel().getColumn( i );
if(i == Constant.TABLE_HEADER_FILELIST_COLUMN_LOCK){
col.setMinWidth(20);
col.setMaxWidth(40);
}else{
col.setMinWidth(100);
}
}
getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if(e.getValueIsAdjusting()){
return;
}
int selected = getSelectedRow();
if(selected >= 0){
onItemSelected(selected);
}
}
});
if(InifileProperty.getInstance().isEnableFolderListThumbnail()){
ThumbnailMouseMotionAdapter adapter = new ThumbnailMouseMotionAdapter(this);
this.addMouseMotionListener(adapter);
this.addMouseListener(adapter);
setEventListener();
}
}
public class ThumbnailMouseMotionAdapter extends MouseMotionAdapter implements MouseListener {
private FileListTable table;
private Point currentCell;
private JWindow popupWindow;
public ThumbnailMouseMotionAdapter(FileListTable table){
this.table = table;
}
@Override
public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
int row = table.rowAtPoint(p);
int col = table.columnAtPoint(p);
if (col != 1){
currentCell = null;
return;
}
if ((row > -1 && row < table.getRowCount()) && (col > -1 && col < table.getColumnCount())) {
if(currentCell == null || currentCell.x != col || currentCell.y != row){
currentCell = new Point(col, row);
String thumbname = null;
String filepath = (String)table.getValueAt(row, Constant.TABLE_HEADER_FILELIST_COLUMN_FILEPATH);
if(mThumbnailMap != null && mThumbnailMap.containsKey(filepath)){
thumbname = mThumbnailMap.get(filepath);
}
if(thumbname != null){
File file = new File("thumbnail", thumbname);
if(!file.exists()){
return;
}
Rectangle cellRect = table.getCellRect(row, 1, false);
if(popupWindow == null){
popupWindow = new JWindow();
}else{
popupWindow.setVisible(false);
}
BufferedImage thumbnail;
try {
FileInputStream fis = new FileInputStream(file);
thumbnail = ImageIO.read(fis);
fis.close();
} catch (IOException e1) {
return;
}
JLabel label = new JLabel(new ImageIcon(thumbnail));
Point screenPos = table.getLocationOnScreen();
popupWindow.setSize(thumbnail.getWidth() , thumbnail.getHeight());
popupWindow.setLocation(screenPos.x + cellRect.x+cellRect.width, screenPos.y + cellRect.y);
popupWindow.getContentPane().removeAll();
popupWindow.getContentPane().add(label);
popupWindow.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
popupWindow.setVisible(false);
}
});
popupWindow.setVisible(true);
}
else{
if(popupWindow != null && popupWindow.isVisible()){
popupWindow.setVisible(false);
}
}
}
}
else{
if(popupWindow != null && popupWindow.isVisible()){
popupWindow.setVisible(false);
currentCell = null;
}
}
}
@Override
public void mouseExited(MouseEvent e) {
if(popupWindow != null && popupWindow.isVisible()){
popupWindow.setVisible(false);
currentCell = null;
}
}
@Override
public void mouseClicked(MouseEvent e) {
// NOP
}
@Override
public void mousePressed(MouseEvent e) {
// NOP
}
@Override
public void mouseReleased(MouseEvent e) {
// NOP
}
@Override
public void mouseEntered(MouseEvent e) {
// NOP
}
}
// Table Event
private void onItemSelected(int index){
System.out.println("select " + index);
String filepath = (String)mTableModel.getValueAt(index, Constant.TABLE_HEADER_FILELIST_COLUMN_FILEPATH);
if(mThumbnailMap != null && mThumbnailMap.containsKey(filepath)){
index = -1; // no need thumbnail
}
mEventSender.sendEvent(EventObserver.EventTarget_Main, EventObserver.EventType_OpenFile, index, (Object)filepath);
}
@SuppressWarnings("unchecked")
public void loadList(){
if(InifileProperty.getInstance().isEnableFolderList()){
ArrayList<FileListItem> list = SerializeArrayUtil.loadList("filelist.dat");
if(list != null){
for(FileListItem item : list){
addData(true, item.getName(), item.getPath());
}
}
if(InifileProperty.getInstance().isEnableFolderListThumbnail()){
HashMap<String, String> map = SerializeArrayUtil.loadMap("thumbnail/thumbnail.dat");
if(map != null){
mThumbnailMap = map;
}
}
}
}
public void saveList(){
if(InifileProperty.getInstance().isEnableFolderList()){
ArrayList<FileListItem> list = getLockedFileItem();
SerializeArrayUtil.save("filelist.dat", list);
if(InifileProperty.getInstance().isEnableFolderListThumbnail()){
SerializeArrayUtil.save("thumbnail/thumbnail.dat", mThumbnailMap);
}
}
}
public void clearData(){
ArrayList<FileListItem> items = getLockedFileItem();
mTableModel.setRowCount(0);
for(FileListItem item : items){
addData(true, item.getName(), item.getPath());
}
}
private ArrayList<FileListItem> getLockedFileItem(){
ArrayList<FileListItem> items = new ArrayList<FileListItem>();
for(int i=0; i<mTableModel.getRowCount(); i++){
Boolean lock = (Boolean)mTableModel.getValueAt(i, Constant.TABLE_HEADER_FILELIST_COLUMN_LOCK);
if(lock){
String name = (String)mTableModel.getValueAt(i, Constant.TABLE_HEADER_FILELIST_COLUMN_FILENAME);
String path = (String)mTableModel.getValueAt(i, Constant.TABLE_HEADER_FILELIST_COLUMN_FILEPATH);
items.add(new FileListItem(name, path));
}
}
return items;
}
private Thread mThread = null;
private boolean mThreadInterrupt = false;
public void scanFolder(String filepath){
clearData();
File file = new File(filepath);
if(!file.exists()){
return;
}
final File folder = file.getParentFile();
mThreadInterrupt = true;
if(mThread != null){
try {
mThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mThread = new Thread(){
public void run(){
mThreadInterrupt = false;
File[] files = folder.listFiles();
for(File file : files){
if(mThreadInterrupt){
break;
}
if(file.isDirectory()){
File[] result = file.listFiles(new FileFilter(){
@Override
public boolean accept(File pathname) {
if(mThreadInterrupt){
return false;
}
String name = pathname.getName().toLowerCase();
if(name.length() < 3){
return false;
}
String suffix = name.substring(name.length()-3);
return Constant.SUPPORT_IMAGE_PREFIX.contains(suffix);
}
});
if(result != null && result.length > 0){
addData(false, file.getAbsolutePath());
}
}
else if(file.isFile()){
String name = file.getName().toLowerCase();
if(name.length() >= 3){
String suffix = name.substring(name.length()-3);
if(Constant.SUPPORT_INPUT_PREFIX.contains(suffix)){
addData(false, file.getAbsolutePath());
}
}
}
}
}
};
mThread.start();
}
public void addData(boolean lock, String filepath){
File file = new File(filepath);
if(file.exists()){
addData(lock, file.getName(), file.getAbsolutePath());
}
}
public void addData(boolean lock, String filename, String path){
int updateRow = -1;
Boolean lockValue = new Boolean(lock);
for(int row = 0; row < mTableModel.getRowCount(); row++){
if(path.equals(mTableModel.getValueAt(row, Constant.TABLE_HEADER_FILELIST_COLUMN_FILEPATH))){
updateRow = row;
lockValue = (Boolean)mTableModel.getValueAt(row, Constant.TABLE_HEADER_FILELIST_COLUMN_LOCK);
break;
}
}
Object[] record = new Object[]{ lockValue, filename, path };
if(updateRow >= 0){
updateData(updateRow, lockValue, filename, path);
}else{
mTableModel.addRow(record);
}
}
public void updateData(int row, boolean lock, String filename, String path){
Object[] record = new Object[]{ new Boolean(lock), filename, path };
for(int col=0; col<record.length; col++){
mTableModel.setValueAt(record[col], row, col);
}
}
public void addThumbnailMap(String filepath, String thumnail){
if(mThumbnailMap != null){
if(mThumbnailMap.containsKey(filepath)){
mThumbnailMap.remove(filepath);
}
mThumbnailMap.put(filepath, thumnail);
}
}
public boolean existThumbnail(String filename){
if(mThumbnailMap != null){
return mThumbnailMap.containsKey(filename);
}
return false;
}
private void setEventListener(){
final JTable table = this;
getTableHeader().addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e) {
if(javax.swing.SwingUtilities.isRightMouseButton(e)){
if(table.getSelectedRowCount() > 0){
JPopupMenu popup = new JPopupMenu();
JMenuItem item0 = new JMenuItem("サムネイル削除");
item0.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
int rowCount = table.getRowCount();
for(int i=0; i<rowCount; i++){
if(table.isRowSelected(i)){
String filepath = (String)mTableModel.getValueAt(i, Constant.TABLE_HEADER_FILELIST_COLUMN_FILEPATH);
String thumbnail = mThumbnailMap.remove(filepath);
if(thumbnail != null){
File file = new File("thumbnail", thumbnail);
if(file.exists()){
if(!file.delete()){
file.deleteOnExit();
}
}
}
}
}
}
});
popup.add(item0);
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
});
}
@Override
public void onEventReceived(int type, int arg1, int arg2, Object obj) {
switch(type){
case EventObserver.EventType_UpdateThumbnail:
String filepath = (String)mTableModel.getValueAt(arg1, Constant.TABLE_HEADER_FILELIST_COLUMN_FILEPATH);
addThumbnailMap(filepath, (String)obj);
break;
default:
break;
}
}
}