/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package tufts.vue;
import tufts.Util;
import tufts.vue.action.ActionUtil;
import tufts.vue.gui.WindowDisplayAction;
import tufts.vue.ui.ResourceList;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.tree.*;
import java.util.*;
import java.io.*;
// castor classes
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ValidationException;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
import org.xml.sax.InputSource;
import osid.dr.*;
/**
*
* @author Ranjani Saigal
* Modified by Anoop Kumar 04/29/06
*/
public class FavoritesWindow extends JPanel implements ActionListener, ItemListener,KeyListener
{
private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(FavoritesWindow.class);
public static final String NEW_FAVORITES = VueResources.getString("dialog.favoriteswindow.newfFavoritesfolder");
public static final String ADD_FAVORITES = VueResources.getString("dialog.favoriteswindow.addfavoritesfolder");
public static final String REMOVE_FAVORITES = VueResources.getString("dialog.favoriteswindow.removefavoritesfolder");
public static final String RESOURCE_INFO = VueResources.getString("dialog.favoriteswindow.resourceinfo");
public static final String OPEN_RESOURCE = VueResources.getString("dialog.favoriteswindow.openresource");
public static final String ADD_TO_MAP = VueResources.getString("dialog.favoriteswindow.addtomap");
public static final String ADD_TO_NODE = VueResources.getString("dialog.favoriteswindow.addtoselectednode");
public static final String REPLACE_ON_NODE = VueResources.getString("dialog.favoriteswindow.replaceresourceonnode");
public static final String ADD_TO_SLIDE = VueResources.getString("dialog.favoriteswindow.addtoslide");
public static final String REMOVE_RESOURCE = VueResources.getString("dialog.favoriteswindow.removeresource");
public static final String CONFIRM_DEL_RESOURCE =VueResources.getString("dialog.favoriteswindow.deleteresource");
public static final String TITLE_DEL_RESOURCE = VueResources.getString("dialog.favoriteswindow.delresourceconf");
// public static final String SAVE_FILE = VueUtil.getDefaultUserFolder().getAbsolutePath()+File.separatorChar+VueResources.getString("save.favorites");
protected final static int MAX_LABEL_LINE_LENGTH = 30;
private String saveFile;
public static final int DEFAULT_SELECTION_ROW = 0;
private DisplayAction displayAction = null;
public VueDandDTree favoritesTree ;
//private JScrollPane browsePane;
private static int FAVORITES = Resource.FAVORITES;
JTextField keywords;
boolean fileOpen = false;
protected JMenuItem addToNodeMenuItem,
addToSlideMenuItem;
/** Creates a new instance of HierarchyTreeWindow */
public FavoritesWindow(String displayName, String saveFile ) {
setLayout(new BorderLayout());
this.saveFile = saveFile;
load();
if (!fileOpen){
Log.info("Creating new favorites: " + displayName);
// todo: refactor such that we don't need to create this dummy "name only" resource
// (e.g., create the FavoritesNode directly, which might subclass the new "RootNode")
URLResource favResource = (URLResource) Resource.getFactory().get(displayName);
favResource.setClientType(FAVORITES);
favoritesTree = new VueDandDTree(new FavoritesNode(favResource));
favoritesTree.setRootVisible(false);
}
createPopupMenu();
if (true) {
// now that entire Resource DockWindow is in a scroll pane,
// this is just messy -- SMF 2008-04-15
add(favoritesTree, BorderLayout.CENTER);
} else {
// re-enabled in case we really want the left-right scroll ability:
add(new JScrollPane(favoritesTree), BorderLayout.CENTER);
}
// // browsePane = new JScrollPane(favoritesTree);
// // add(browsePane,BorderLayout.CENTER);
}
public VueDandDTree getFavoritesTree(){
return (this.favoritesTree);
}
public void setFavoritesTree(VueDandDTree favoritesTree){
this.favoritesTree = favoritesTree;
}
public Action getDisplayAction(String displayName) {
if (displayAction == null)
displayAction = new DisplayAction(displayName);
return (Action)displayAction;
}
private class DisplayAction extends AbstractAction {
private AbstractButton aButton;
public DisplayAction(String label) {
super(label);
}
public void actionPerformed(ActionEvent e) {
aButton = (AbstractButton) e.getSource();
setVisible(aButton.isSelected());
}
public void setButton(boolean state) {
aButton.setSelected(state);
}
}
public void createPopupMenu() {
JMenuItem menuItem;
JPopupMenu popup = new JPopupMenu();
menuItem = new JMenuItem(ADD_FAVORITES);
menuItem.addActionListener(this);
popup.add(menuItem);
menuItem = new JMenuItem(REMOVE_FAVORITES);
menuItem.addActionListener(this);
popup.add(menuItem);
JPopupMenu popupResource = new JPopupMenu();
WindowDisplayAction infoAction = new WindowDisplayAction(VUE.getInfoDock());
JCheckBoxMenuItem infoCheckBox = new JCheckBoxMenuItem(infoAction);
infoCheckBox.setText(RESOURCE_INFO);
infoCheckBox.setSelected(VUE.getInfoDock().isShowing());
popupResource.add(infoCheckBox);
popupResource.addSeparator();
menuItem = new JMenuItem(OPEN_RESOURCE);
menuItem.addActionListener(this);
popupResource.add(menuItem);
popupResource.addSeparator();
menuItem = new JMenuItem(ADD_TO_MAP);
menuItem.addActionListener(this);
popupResource.add(menuItem);
addToNodeMenuItem = new JMenuItem(ADD_TO_NODE);
addToNodeMenuItem.addActionListener(this);
popupResource.add(addToNodeMenuItem);
addToSlideMenuItem = new JMenuItem(ADD_TO_SLIDE);
addToSlideMenuItem.addActionListener(this);
popupResource.add(addToSlideMenuItem);
popupResource.addSeparator();
menuItem = new JMenuItem(REMOVE_RESOURCE);
menuItem.addActionListener(this);
popupResource.add(menuItem);
JPopupMenu popupAdd = new JPopupMenu();
menuItem = new JMenuItem(ADD_FAVORITES);
menuItem.addActionListener(this);
popupAdd.add(menuItem);
MouseListener popupListener = new PopupListener(popup,popupResource,popupAdd);
favoritesTree.addMouseListener(popupListener);
enablePopupMenu();
}
public void enablePopupMenu() {
LWSelection sel = VUE.getActiveViewer().getSelection();
LWComponent comp = sel.only();
boolean isNode = (comp != null && comp instanceof LWNode),
isSlide = (comp != null && comp instanceof LWSlide),
hasResource = isNode && comp.hasResource();
addToNodeMenuItem.setText(hasResource? REPLACE_ON_NODE : ADD_TO_NODE);
addToNodeMenuItem.setEnabled(isNode);
addToSlideMenuItem.setEnabled(isSlide);
}
public void actionPerformed(ActionEvent e) {
ResourceNode resNode;
FavoritesNode favresNode;
ResourceNode temp;
if (e.getSource() instanceof JMenuItem){
JMenuItem source = (JMenuItem)(e.getSource());
TreePath tp = favoritesTree.getSelectionPath();
DefaultTreeModel model = (DefaultTreeModel)favoritesTree.getModel();
if (tp == null){ resNode = (ResourceNode)model.getRoot();
} else{
resNode = (ResourceNode)tp.getLastPathComponent();
}
if (e.getActionCommand().toString().equals(REMOVE_RESOURCE) | e.getActionCommand().toString().equals(REMOVE_FAVORITES)) {
if (!resNode.isRoot()) {
if(VueUtil.confirm(this,CONFIRM_DEL_RESOURCE,TITLE_DEL_RESOURCE) == JOptionPane.OK_OPTION) {
TreePath parent = tp.getParentPath();
model.removeNodeFromParent(resNode);
if(parent.getPathCount()!=1)
favoritesTree.setSelectionPath(parent);
else
favoritesTree.setSelectionRow(DEFAULT_SELECTION_ROW);
}
}
} else if (e.getActionCommand().toString().equals(ADD_TO_MAP)){
String label = Util.formatLines(resNode.getResource().getName(), MAX_LABEL_LINE_LENGTH);
LWNode end = NodeTool.NodeModeTool.createNewNode(label);
end.setResource(resNode.getResource());
VUE.getActiveMap().addNode(end);
if (true)
tufts.vue.VueUtil.setXYByClustering(end);
else
ResourceList.setXYByClustering(end);
} else if (e.getActionCommand().toString().equals(ADD_TO_NODE) ||
e.getActionCommand().toString().equals(REPLACE_ON_NODE)){
LWSelection sel = VUE.getActiveViewer().getSelection();
LWComponent c = sel.only();
VUE.setActive(LWComponent.class, this, null);
c.setResource(resNode.getResource());
c.setLabel(resNode.getResource().getName());
VUE.setActive(LWComponent.class, this, c);
} else if (e.getActionCommand().toString().equals(ADD_TO_SLIDE)){
LWSelection sel = VUE.getActiveViewer().getSelection();
LWSlide c = (LWSlide)sel.only();
LWImage end = new LWImage();
end.setResource(resNode.getResource());
end.setStyle(c);
end.setResource(resNode.getResource());
end.setLabel(resNode.getResource().getName());
c.addChild(end);
} else {
if (resNode instanceof FileNode) { ((FileNode)resNode).displayContent();} else {
resNode.getResource().displayContent();
}
}
} else {
performSearch();
}
}
private void addFavorites(DefaultTreeModel model, ResourceNode resNode){
TreePath tp = new TreePath(resNode.getPath());
FavoritesNode favresNode = (FavoritesNode)tp.getLastPathComponent();
URLResource favResource = (URLResource) Resource.getFactory().get(NEW_FAVORITES);
favResource.setTitle(NEW_FAVORITES);
favResource.setClientType(FAVORITES);
FavoritesNode favNode = new FavoritesNode(favResource);
model.insertNodeInto(favNode,favresNode, (favresNode.getChildCount()));
if ((favresNode.isLeaf())){
if (model.getRoot() != resNode){
favoritesTree.expandPath(new TreePath(favresNode.getPath()));
favoritesTree.startEditingAtPath(new TreePath(favNode.getPath()));
favoritesTree.setRootVisible(true);
} else {
favoritesTree.setRootVisible(true);
favoritesTree.expandRow(0);
favoritesTree.startEditingAtPath(new TreePath(favNode.getPath()));
}
} else{
favoritesTree.setRootVisible(true);
favoritesTree.expandPath(new TreePath(favresNode.getPath()));
favoritesTree.startEditingAtPath(new TreePath(favNode.getPath()));
}
favoritesTree.setRootVisible(false);
}
public void itemStateChanged(ItemEvent e) {
JMenuItem source = (JMenuItem)(e.getSource());
}
//Saves to favorites.xml in applications default directory. May want to have a separate file for every favorites
public void save() {
if (favoritesTree != null) {
tufts.vue.VueDandDTree ft = this.getFavoritesTree();
ft.setRootVisible(true);
tufts.vue.SaveVueJTree sFavTree = new tufts.vue.SaveVueJTree(ft);
File favFile = new File(saveFile);
marshallFavorites(favFile,sFavTree);
}
}
public void load() {
File f = new File(saveFile);
if(f.exists()) {
//try {
SaveVueJTree restorefavtree = unMarshallFavorites(f);
fileOpen = true;
favoritesTree =restorefavtree.restoreTree();
favoritesTree.setRootVisible(true);
favoritesTree.expandRow(0);
favoritesTree.setRootVisible(false);
this.setFavoritesTree(favoritesTree);
// } catch (Exception t) {
// Log.error("load " + this, t);
// fileOpen = false;
// }
} else {
System.out.println("Favorites file not found: "+ f);
}
}
public static void marshallFavorites(File file,SaveVueJTree favoritesTree) {
Marshaller marshaller = null;
Mapping mapping = new Mapping();
try {
if (DEBUG.IO) Log.debug("writing " + file);
FileWriter writer = new FileWriter(file);
marshaller = new Marshaller(writer);
if (DEBUG.IO) Log.debug("got marshaller " + marshaller);
marshaller.setValidation(false); // SMF: added 2008-04-13 -- was getting exceptions
marshaller.setEncoding("US-ASCII");
marshaller.setMarshalListener(new tufts.vue.action.ActionUtil.VueMarshalListener());
marshaller.setMapping(ActionUtil.getDefaultMapping());
if (DEBUG.IO) Log.debug("marshalling " + favoritesTree + "...");
marshaller.marshal(favoritesTree);
if (DEBUG.IO) Log.debug("marshalled " + favoritesTree);
writer.flush();
writer.close();
} catch (Throwable t) {
Log.error("marshallFavorites to " + tufts.Util.tags(file), t);
}
}
public SaveVueJTree unMarshallFavorites(File file) {
Unmarshaller unmarshaller = null;
SaveVueJTree sTree = null;
try {
//unmarshaller = new Unmarshaller(ActionUtil.getDefaultMapping());
unmarshaller = ActionUtil.getDefaultUnmarshaller(file.toString());
FileReader reader = new FileReader(file);
sTree= (SaveVueJTree) unmarshaller.unmarshal(new InputSource(reader));
reader.close();
} catch (Exception e) {
// e.printStackTrace();
//System.err.println("FavoritesWindow.unmarshallFavorites: " + e);
sTree = null;
}
return sTree;
}
public void performSearch(){
int index = 0;
JScrollPane jsp = new JScrollPane();
String searchString = keywords.getText();
//VueDragTree serResultTree = new VueDragTree("Search", "No Hits");
VueDragTree serResultTree = new VueDragTree(null, "Search:No Hits"); // is this used anywhere???
if (!searchString.equals("")){
boolean foundit = false;
// VueDragTree serResultTree = new VueDragTree("Search", "Search Results");
DefaultTreeModel serTreeModel = (DefaultTreeModel)serResultTree.getModel();
ResourceNode serRoot = (ResourceNode)serTreeModel.getRoot();
TreeModel favTreeModel = this.favoritesTree.getModel();
ResourceNode favRoot = (ResourceNode)favTreeModel.getRoot();
int childCount = favRoot.getChildCount();
if (childCount > 0){
for (int outi = 0; outi < childCount ; ++outi){
if (favRoot.getChildAt(outi) instanceof FileNode){
FileNode childNode = (FileNode)favRoot.getChildAt(outi);
childNode.explore();
}
ResourceNode childNode = (ResourceNode)favRoot.getChildAt(outi);
foundit = compareNode(searchString,childNode,serRoot,false);
// System.out.println("And here "+ childNode.toString()+foundit);
}
}
serResultTree.setRootVisible(true);
serResultTree.setShowsRootHandles(true);
serResultTree.expandRow(0);
serResultTree.setRootVisible(false);
}
}
public boolean compareNode(String searchString, ResourceNode Node, ResourceNode serRoot, boolean foundsomething) {
if (searchString.compareToIgnoreCase(Node.toString()) == 0){
addSearchNode(serRoot,Node);
foundsomething = true;
} else {
int startIndex = 0;
int lenSearchString = searchString.length();
String thisString = Node.toString();
int lenthisString = thisString.length();
int endIndex = startIndex + lenSearchString;
boolean found = false;
while ((endIndex <= lenthisString) && !found){
String testString = thisString.substring(startIndex,endIndex);
if (searchString.compareToIgnoreCase(testString)== 0){
addSearchNode(serRoot,Node);
found = true;
foundsomething = true;
}
startIndex = startIndex + 1;
endIndex = endIndex + 1;
}
}
if (!(Node.isLeaf())){
int childCount = Node.getChildCount();
if (childCount > 0){
for (int i = 0; i < childCount; ++i){
ResourceNode childNode = (ResourceNode)Node.getChildAt(i);
if(compareNode(searchString,childNode,serRoot,foundsomething)) {
foundsomething = true;
}
}
}
}
return foundsomething;
}
public void addSearchNode(ResourceNode topNode, ResourceNode Node) {
ResourceNode newNode = (ResourceNode)Node.clone();
if (!(Node.isLeaf())){
for(int inni = 0; inni < Node.getChildCount(); ++ inni){
ResourceNode child = (ResourceNode)Node.getChildAt(inni);
addSearchNode(newNode,child);
}
}
topNode.add(newNode);
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
if(e.getKeyChar()== KeyEvent.VK_ENTER) {
performSearch();
}
}
class PopupListener extends MouseAdapter {
JPopupMenu popup,popupResource,popupAdd;
VueDandDTree vtree = FavoritesWindow.this.getFavoritesTree();
PopupListener(JPopupMenu popupMenu, JPopupMenu popupMenu2, JPopupMenu popupMenu3 ) {
popup = popupMenu;
popupResource = popupMenu2;
popupAdd = popupMenu3;
}
public void mousePressed(MouseEvent e) {
showPopup(e);
}
public void mouseClicked(MouseEvent e) {
if (vtree.getSelectionPath() != null){
DefaultMutableTreeNode selTreeNode = (DefaultMutableTreeNode)vtree.getSelectionPath().getLastPathComponent();
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)vtree.getClosestPathForLocation(e.getX(), e.getY()).getLastPathComponent();
if (treeNode != selTreeNode) { vtree.clearSelection();}
TreeModel vmodel = vtree.getModel();
if(e.getClickCount() == 2) {
if (((DefaultMutableTreeNode)vmodel.getRoot()).getChildCount() == 1) vtree.clearSelection();
if (!(selTreeNode instanceof FavoritesNode)) vtree.clearSelection();
if((selTreeNode instanceof ResourceNode)) {
TreePath path = vtree.getPathForLocation(e.getX(), e.getY());
if (path == null)
return;
Object uo = selTreeNode.getUserObject();
if (DEBUG.Enabled) System.out.println("instance of favorites node- res class"+ tufts.Util.tags(uo));
if (uo instanceof Resource)
((Resource)uo).displayContent();
}
}
}
showPopup(e);
}
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
private void showPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
if (vtree.getSelectionPath() != null){
if (vtree.getSelectionPath().getLastPathComponent() instanceof FavoritesNode){
popup.show(e.getComponent(),e.getX(), e.getY());
} else{
enablePopupMenu();
popupResource.show(e.getComponent(),e.getX(), e.getY());
}
} else {
popupAdd.show(e.getComponent(),e.getX(), e.getY());
}
}
}
}
public static void main(String args[]) {
VUE.init(args);
new Frame("An Active Frame").setVisible(true);
FavoritesWindow fw = new FavoritesWindow("http://www.tufts.edu","favorites.xml");
fw.setVisible(true);
tufts.Util.displayComponent(fw);
}
}