package info.opencards.ui.catui;
import info.opencards.CardFileBackend;
import info.opencards.OpenCards;
import info.opencards.Utils;
import info.opencards.core.CardFile;
import info.opencards.core.CardFileCache;
import info.opencards.core.categories.Category;
import info.opencards.core.categories.CategoryUtils;
import info.opencards.ui.CardFilesPreloader;
import info.opencards.util.ScaleableIcon;
import info.opencards.util.UIUtils;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.*;
import java.util.List;
/**
* DOCUMENT ME!
*
* @author Holger Brandl
*/
public abstract class CategoryAction extends AbstractAction {
final CategoryTree categoryTree;
CategoryAction(CategoryTree categoryTree) {
this.categoryTree = categoryTree;
}
}
class CreateCategoryAction extends CategoryAction {
CreateCategoryAction(CategoryTree categoryTree) {
super(categoryTree);
putValue(NAME, Utils.getRB().getString("CatAction.newCategory")); //$NON-NLS-1$
putValue(SMALL_ICON, new ScaleableIcon("icons/category_add.png"));
// putValue(SHORT_DESCRIPTION, "cuts the selected category");
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
}
public void actionPerformed(ActionEvent e) {
String newCatname = JOptionPane.showInputDialog(UIUtils.getOwnerDialog(categoryTree), Utils.getRB().getString("CategoryTree.addNewCategory.text"), Utils.getRB().getString("CategoryTree.addNewCategory.default"));
if (newCatname == null || newCatname.trim().length() == 0) {
return;
}
Category parentCategory = categoryTree.getSelectedCategory();
Category newCategory = new Category(newCatname);
parentCategory.addChildCategory(newCategory);
}
}
class DeleteCategoryAction extends CategoryAction {
public DeleteCategoryAction(CategoryTree categoryTree) {
super(categoryTree);
putValue(NAME, Utils.getRB().getString("CatAction.delete"));
putValue(SMALL_ICON, new ScaleableIcon("icons/category_remove.png"));
// putValue(SHORT_DESCRIPTION, "cuts the selected category");
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
}
public void actionPerformed(ActionEvent e) {
Category category = categoryTree.getSelectedCategory();
if (category.getRootCategory().equals(category))
return;
// ensure that the user really want to remove this category
// Set<CardFile> relatedCardfiles = CategoryUtils.recursiveCardFileCollect(category);
ResourceBundle rb = Utils.getRB();
String reallyDelete = rb.getString("CatAction.reallyDelete").replace("<<CATEGORY_NAME>>", "'" + category.getName() + "'");
int status = JOptionPane.showConfirmDialog(UIUtils.getOwnerDialog(categoryTree),
reallyDelete, rb.getString("OpenCards.reallyCleanAllTitle"),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (status == JOptionPane.YES_OPTION)
category.remove();
}
}
class AddCardSetAction extends CategoryAction {
private final PasteCategoryAction pasteAction;
public AddCardSetAction(CategoryTree categoryTree, PasteCategoryAction pasteAction) {
super(categoryTree);
this.pasteAction = pasteAction;
putValue(NAME, Utils.getRB().getString("CatAction.addCardSet"));
putValue(SMALL_ICON, new ScaleableIcon("icons/category_addcardset.png"));
// putValue(SHORT_DESCRIPTION, "cuts the selected category");
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
}
public void actionPerformed(ActionEvent e) {
Category category = categoryTree.getSelectedCategory();
final String DEFAULT_DIR = "addcat.defdir";
File defDir = new File(Utils.getPrefs().get(DEFAULT_DIR, System.getProperty("user.home")));
if (!defDir.isDirectory())
defDir = new File(".");
JFileChooser jfc = new JFileChooser(defDir);
jfc.setMultiSelectionEnabled(true);
jfc.setFileFilter(new FileFilter() {
public boolean accept(File f) {
String fileName = f.getName();
// return (fileName.endsWith(".odp") || fileName.endsWith(".ppt")) || f.isDirectory();
return fileName.endsWith(".ppt") || fileName.endsWith(".md") || f.isDirectory();
}
public String getDescription() {
// return "Flashcard presentations (*.odp, *.ppt)";
return "PowerPoint Presentations (*.ppt), Markdown (*.md)";
}
});
int status = jfc.showOpenDialog(UIUtils.getOwnerDialog(categoryTree));
if (status == JFileChooser.APPROVE_OPTION) {
File[] selectedFiles = jfc.getSelectedFiles();
// collect all files and create new files only if necessary
Set<CardFile> allFiles = new HashSet<CardFile>();
if (pasteAction.getPasteCategory() != null)
allFiles.addAll(CategoryUtils.recursiveCardFileCollect(pasteAction.getPasteCategory()));
allFiles.addAll(CategoryUtils.recursiveCardFileCollect(categoryTree.getRootCategory()));
List<CardFile> cardFilesBuffer = new ArrayList<CardFile>();
for (File file : selectedFiles) {
if (file.isFile() && CardFileBackend.hasSupportedExtension(file)) {
CardFile cardFile = getCard(allFiles, file);
if (cardFile == null) {
cardFile = CardFileCache.getCardFile(file);
}
cardFilesBuffer.add(cardFile);
}
}
Dialog owner = UIUtils.getOwnerDialog(categoryTree);
// we cannot remove this one, because the preloader of the tree would process each file in a single run,
// which wouldn't look nice because the the progress-bar would flicker for each file
new CardFilesPreloader(owner, OpenCards.getCardSetManager().getBackend().getSerializer()).categorySelectionChanged(cardFilesBuffer, null);
for (CardFile cardFile : cardFilesBuffer) {
category.registerCardSet(cardFile);
}
// remember chosen directory as default for the next time
if (selectedFiles.length > 0 && selectedFiles[0].getParentFile().isDirectory())
Utils.getPrefs().put(DEFAULT_DIR, selectedFiles[0].getParentFile().getAbsolutePath());
}
}
private CardFile getCard(Set<CardFile> allFiles, File file) {
for (CardFile curFile : allFiles) {
if (curFile.getFileLocation().equals(file))
return curFile;
}
return null;
}
}
class PopulateSubCatTreeFromDirectoryAction extends CategoryAction {
public PopulateSubCatTreeFromDirectoryAction(CategoryTree categoryTree) {
super(categoryTree);
putValue(NAME, Utils.getRB().getString("CatAction.parseDirectory") + " ...");
putValue(SMALL_ICON, new ScaleableIcon("icons/category_add_dirtree.png"));
putValue(SHORT_DESCRIPTION, Utils.getRB().getString("CatAction.parseDirDescription"));
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
}
public void actionPerformed(ActionEvent e) {
Category baseCategory = categoryTree.getSelectedCategory();
final String DEFAULT_DIR = "addcat.defdir";
File defDir = new File(Utils.getPrefs().get(DEFAULT_DIR, System.getProperty("user.home")));
if (!defDir.isDirectory())
defDir = new File(".");
JFileChooser jfc = new JFileChooser(defDir);
jfc.setMultiSelectionEnabled(false);
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
// jfc.setFileFilter(new FileFilter() {
//
// public boolean accept(File f) {
// String fileName = f.getName();
//// return (fileName.endsWith(".odp") || fileName.endsWith(".ppt")) || f.isDirectory();
// return f.isDirectory();
// }
//
//
// public String getDescription() {
//// return "Flashcard presentations (*.odp, *.ppt)";
// return "roots of your card-file directory strucutre";
// }
// });
// do nothing if the user canceled the operation
if (jfc.showOpenDialog(UIUtils.getOwnerDialog(categoryTree)) != JFileChooser.APPROVE_OPTION) {
return;
}
// now collect all files
File rootDirectory = jfc.getSelectedFile();
assert rootDirectory.isDirectory() : "selected file must be a directory";
// Category rootCategory = baseCategory.getOrCreateChildCategoryByName(rootDirectory.getName());
List<File> allFilesInSubDirectory = new ArrayList<>();
allFilesInSubDirectory.addAll(Utils.findFiles(rootDirectory, ".ppt"));
allFilesInSubDirectory.addAll(Utils.findFiles(rootDirectory, ".md"));
// collect all already registered cardfiles and create new files only if necessary
Set<CardFile> allFiles = new HashSet<CardFile>();
allFiles.addAll(CategoryUtils.recursiveCardFileCollect(categoryTree.getRootCategory()));
List<CardFile> newCardFiles = new ArrayList<CardFile>();
for (File file : allFilesInSubDirectory) {
if (file.isFile() && CardFileBackend.hasSupportedExtension(file)) {
CardFile cardFile = getCard(allFiles, file);
if (cardFile == null) {
cardFile = CardFileCache.getCardFile(file);
}
newCardFiles.add(cardFile);
}
}
Dialog owner = UIUtils.getOwnerDialog(categoryTree);
// we cannot remove this one, because the preloader of the tree would process each file in a single run,
// which wouldn't look nice because the the progress-bar would flicker for each file
new CardFilesPreloader(owner, OpenCards.getCardSetManager().getBackend().getSerializer()).categorySelectionChanged(newCardFiles, null);
// attach all files and create new subcategories if necessary
for (CardFile cardFile : newCardFiles) {
// get the category path to the add-category and add the file there
File parentCat = cardFile.getFileLocation();
List<File> parentCatDirs = new ArrayList<File>();
while (parentCatDirs.isEmpty() || !parentCatDirs.get(0).equals(rootDirectory)) {
parentCat = parentCat.getParentFile();
parentCatDirs.add(0, parentCat);
}
// remove the first one in order to avoid the selected folder to be created as category
// parentCatDirs.remove(0);
// now recurse down the the appropriate category and attach the file
Category addCategory = baseCategory;
for (File parentCatDir : parentCatDirs) {
addCategory = addCategory.getOrCreateChildCategoryByName(parentCatDir.getName());
}
// register only if not previously done
if (!addCategory.getCardSets().contains(cardFile))
addCategory.registerCardSet(cardFile);
}
// remember chosen directory as default for the next time
if (rootDirectory.getParentFile().isDirectory())
Utils.getPrefs().put(DEFAULT_DIR, rootDirectory.getParentFile().getAbsolutePath());
}
private CardFile getCard(Set<CardFile> allFiles, File file) {
for (CardFile curFile : allFiles) {
if (curFile.getFileLocation().equals(file))
return curFile;
}
return null;
}
}
class CutCategoryAction extends CategoryAction {
private final PasteCategoryAction pasteAction;
public CutCategoryAction(CategoryTree categoryTree, PasteCategoryAction pasteAction) {
super(categoryTree);
this.pasteAction = pasteAction;
putValue(NAME, Utils.getRB().getString("CatAction.cut"));
putValue(SMALL_ICON, new ScaleableIcon("icons/category_cut.png"));
// putValue(SHORT_DESCRIPTION, "cuts the selected category");
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
}
public void actionPerformed(ActionEvent e) {
Category category = categoryTree.getSelectedCategory();
if (category.getRootCategory().equals(category))
return;
pasteAction.setPasteCategory(category);
category.setParent(null);
}
}
class CopyCategoryAction extends CategoryAction {
private final PasteCategoryAction pasteAction;
public CopyCategoryAction(CategoryTree categoryTree, PasteCategoryAction pasteAction) {
super(categoryTree);
this.pasteAction = pasteAction;
putValue(NAME, Utils.getRB().getString("CatAction.copy"));
putValue(SMALL_ICON, new ScaleableIcon("icons/category_copy.png"));
// putValue(SHORT_DESCRIPTION, "cuts the selected category");
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
}
public void actionPerformed(ActionEvent e) {
Category category = categoryTree.getSelectedCategory();
try {
pasteAction.setPasteCategory((Category) category.clone());
} catch (CloneNotSupportedException e1) {
e1.printStackTrace();
}
}
}
class PasteCategoryAction extends CategoryAction {
private Category pasteCategory;
public PasteCategoryAction(CategoryTree categoryTree) {
super(categoryTree);
putValue(NAME, Utils.getRB().getString("CatAction.paste"));
putValue(SMALL_ICON, new ScaleableIcon("icons/category_paste.png"));
// putValue(SHORT_DESCRIPTION, "cuts the selected category");
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
setEnabled(false);
}
public void actionPerformed(ActionEvent e) {
Category category = categoryTree.getSelectedCategory();
// don't add the category if there's already a same named child
if (category.hasChildNamed(pasteCategory.getName()))
return;
category.addChildCategory(pasteCategory);
setEnabled(false);
}
public Category getPasteCategory() {
return pasteCategory;
}
public void setPasteCategory(Category pasteCategory) {
this.pasteCategory = pasteCategory;
setEnabled(pasteCategory != null);
}
}
class RenameCategoryAction extends CategoryAction {
private final CategoryTree categoryTree;
public RenameCategoryAction(CategoryTree categoryTree) {
super(categoryTree);
this.categoryTree = categoryTree;
putValue(NAME, Utils.getRB().getString("CatAction.rename"));
putValue(SMALL_ICON, new ScaleableIcon("icons/category_rename.png"));
// putValue(SHORT_DESCRIPTION, "cuts the selected category");
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
}
public void actionPerformed(ActionEvent e) {
Category category = categoryTree.getSelectedCategory();
String catName = category.getName();
if (category.getRootCategory().equals(category))
return;
String newName = JOptionPane.showInputDialog(UIUtils.getOwnerDialog(categoryTree), "New category name", catName);
category.setName(newName);
// unfortunately this does not work as expected
// categoryTree.getModel().valueForPathChanged(categoryTree.getSelectionModel().getSelectionPath(), newName);
}
}
class ResolveChildsAction extends CategoryAction {
private final CategoryTree categoryTree;
public ResolveChildsAction(CategoryTree categoryTree) {
super(categoryTree);
this.categoryTree = categoryTree;
putValue(NAME, Utils.getRB().getString("CatAction.resolveChilds"));
// putValue(SMALL_ICON, new ScaleableIcon("icons/category_rename.png"));
// putValue(SHORT_DESCRIPTION, "cuts the selected category");
// putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK));
putValue(MNEMONIC_KEY, 2);
}
public void actionPerformed(ActionEvent e) {
// write the new value of the chckbox to the system properties
JCheckBoxMenuItem source = (JCheckBoxMenuItem) e.getSource();
Utils.getPrefs().putBoolean(CategoryUtils.INCLUDE_CHILDS, source.isSelected());
categoryTree.refire(categoryTree.getSelectionPath()); //this is hacky in case of multiple selections
OpenCards.getCardSetManager().refreshFileViews();
}
}