package frame; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Component; import java.awt.Desktop; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Line2D; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.net.URL; import javax.swing.ImageIcon; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.event.MouseInputListener; import filesystem.Extensions; import filesystem.FSUtil; /** * Main JPanel that acts as the content pane and workspace * for visual file browsing * * @author * @version */ @SuppressWarnings("serial") public class SlideBrowserPanel extends JPanel { //Class variables private ArrayList nodeList; private ArrayList hiddenNodeList; private ArrayList selectedNodeList; private int selectedNodeIndex; private JPopupMenu backgroundPopUp; private JPopupMenu nodePopUp; private SlideBrowser sb; private boolean showHitBox; private boolean showHiddenFiles; private MouseInputListener mouse; private Point initialClick; private Point rClickPoint; private JMenuItem expandNodeMenuItem; private JMenuItem foldNodeMenuItem; private JMenuItem openMenuItem; private JMenuItem makeDirMenuItem; private JMenuItem deleteMenuItem; private JMenuItem copyMenuItem; private JMenuItem cutMenuItem; private JMenuItem pasteMenuItem; private JMenuItem renameMenuItem; private JMenuItem openInTabMenuItem; private Desktop dTop; private Extensions ext; /** * Default constructor for the panel. Takes in the frame * that made/added the panel in order to call methods from * other frames * * @param Initial file to make first root node * @param frame = root frame that contains the panel */ public SlideBrowserPanel(File f, SlideBrowser frame) { //Ability to call methods in frame //Is this already possible without the parameter? sb = frame; //Focus the panel setFocusable(true); //Set background setBackground(Color.GRAY); //Add MouseListener mouseAction mouse = new mouseAction(this); addMouseListener(mouse); addMouseMotionListener(mouse); //ArrayList for the nodes of this panel nodeList = new ArrayList(); hiddenNodeList = new ArrayList(); //Add given directory/file to nodeList nodeList.add(new NodeItem(f)); //Set icon and initial position/size nodeList.get(0).setIcon(getImage("/resources/32x32/folder.png")); nodeList.get(0).setPosition(10, 10); nodeList.get(0).sethbSize(32); ext = new Extensions(); //Expand initial root node expandNode(nodeList, 0); //Make popup menu for background context menu backgroundPopUp = new JPopupMenu(); //Add item "Add Root Node" JMenuItem menuAddRoot = new JMenuItem("New Root Node", new ImageIcon(getClass().getResource("/resources/16x16/folder_add.png"))); menuAddRoot.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { addRootNode(); } }); //Add item "Remove Tab" JMenuItem menuRemoveTab = new JMenuItem("Remove Tab", new ImageIcon(getClass().getResource("/resources/16x16/tab_delete.png"))); menuRemoveTab.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { sb.removeTab(); } }); //Add everything to background popup menu backgroundPopUp.add(menuAddRoot); backgroundPopUp.addSeparator(); backgroundPopUp.add(menuRemoveTab); //Make popup menu for node context menu nodePopUp = new JPopupMenu(); //Add item "Expand node" expandNodeMenuItem = new JMenuItem("Expand node", new ImageIcon(getClass().getResource("/resources/16x16/folders_explorer.png"))); expandNodeMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { expandNode(selectedNodeList, selectedNodeIndex); } }); expandNodeMenuItem.setVisible(true); //Add item "Fold node" foldNodeMenuItem = new JMenuItem("Fold node", new ImageIcon(getClass().getResource("/resources/16x16/folders.png"))); foldNodeMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { foldNode(selectedNodeList, selectedNodeIndex); } }); foldNodeMenuItem.setVisible(false); openInTabMenuItem = new JMenuItem("Open In Tab", new ImageIcon(getClass().getResource("/resources/16x16/tab_go.png"))); openInTabMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { File f = selectedNodeList.get(selectedNodeIndex).getFile(); sb.newTab(f); } }); openInTabMenuItem.setVisible(false); //Add item "Open File" openMenuItem = new JMenuItem("Open file", new ImageIcon(getClass().getResource("/resources/16x16/arrow_right.png"))); openMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { openFile(selectedNodeList, selectedNodeIndex); } }); openMenuItem.setVisible(false); //Add item "Delete" deleteMenuItem = new JMenuItem("Delete", new ImageIcon(getClass().getResource("/resources/16x16/delete.png"))); deleteMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { int result = JOptionPane.showConfirmDialog(sb, new JLabel("Delete File?"), "Confirmation", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (result == JOptionPane.YES_OPTION) { sb.terminalMessage("Deleting File: " + selectedNodeList.get(selectedNodeIndex).getFile().getAbsolutePath()); FSUtil.getInstance().delete(selectedNodeList.get(selectedNodeIndex).getFile()); //TODO: does delete files properly but doesn't update the nodeList repaint(); } //openFile(selectedNodeList, selectedNodeIndex); } }); deleteMenuItem.setVisible(false); //Add item "Cut" cutMenuItem = new JMenuItem("Cut", new ImageIcon(getClass().getResource("/resources/16x16/cut.png"))); cutMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { sb.terminalMessage("Cut File: " + selectedNodeList.get(selectedNodeIndex).getFile().getAbsolutePath()); FSUtil.getInstance().cut(selectedNodeList.get(selectedNodeIndex).getFile()); } }); cutMenuItem.setVisible(false); //Add item "Copy" copyMenuItem = new JMenuItem("Copy", new ImageIcon(getClass().getResource("/resources/16x16/copying_and_distribution.png"))); copyMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { sb.terminalMessage("Copy File: " + selectedNodeList.get(selectedNodeIndex).getFile().getAbsolutePath()); FSUtil.getInstance().copy(selectedNodeList.get(selectedNodeIndex).getFile()); } }); copyMenuItem.setVisible(false); //Add item "Paste" pasteMenuItem = new JMenuItem("Paste", new ImageIcon(getClass().getResource("/resources/16x16/paste_plain.png"))); pasteMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { sb.terminalMessage("Paste File: " + selectedNodeList.get(selectedNodeIndex).getFile().getAbsolutePath()); FSUtil.getInstance().paste(selectedNodeList.get(selectedNodeIndex).getFile()); //TODO also need to fold/expand cut directory if cut command used. foldNode(selectedNodeList, selectedNodeIndex); expandNode(selectedNodeList, selectedNodeIndex); repaint(); } }); pasteMenuItem.setVisible(false); //Add item "Rename" renameMenuItem = new JMenuItem("Rename", new ImageIcon(getClass().getResource("/resources/16x16/textfield_rename.png"))); renameMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { sb.terminalMessage("Rename File: " + selectedNodeList.get(selectedNodeIndex).getFile().getAbsolutePath()); new RenameWindow(selectedNodeList.get(selectedNodeIndex).getFile()); //TODO also need to fold/expand cut directory if cut command used. //foldNode(selectedNodeList, selectedNodeIndex); //expandNode(selectedNodeList, selectedNodeIndex); //repaint(); } }); renameMenuItem.setVisible(false); //Add item "Make Directory" makeDirMenuItem = new JMenuItem("Make Directory", new ImageIcon(getClass().getResource("/resources/16x16/folder_add.png"))); makeDirMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { makeDir(selectedNodeList, selectedNodeIndex); } }); //Add item "Remove node" //TODO make a different icon JMenuItem removeNodeMenuItem = new JMenuItem("Remove node", new ImageIcon(getClass().getResource("/resources/16x16/folder_delete.png"))); removeNodeMenuItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { removeNode(selectedNodeList, selectedNodeIndex); } }); //Add everything to node menu nodePopUp.add(openMenuItem); nodePopUp.add(openInTabMenuItem); nodePopUp.addSeparator(); nodePopUp.add(expandNodeMenuItem); nodePopUp.add(foldNodeMenuItem); nodePopUp.add(removeNodeMenuItem); nodePopUp.addSeparator(); nodePopUp.add(makeDirMenuItem); nodePopUp.add(cutMenuItem); nodePopUp.add(copyMenuItem); nodePopUp.add(pasteMenuItem); nodePopUp.add(renameMenuItem); nodePopUp.addSeparator(); nodePopUp.add(deleteMenuItem); //Instantiate other values: showHitBox = false; showHiddenFiles = false; rClickPoint = new Point(); selectedNodeList = new ArrayList(); selectedNodeIndex = 0; dTop = Desktop.getDesktop(); ext.addExtensionList(new File((getClass().getResource("/resources/photosExt.txt")).getPath()), "Photos"); ext.addExtensionList(new File((getClass().getResource("/resources/musicExt.txt")).getPath()), "Music"); ext.addExtensionList(new File((getClass().getResource("/resources/videoExt.txt")).getPath()), "Video"); ext.addExtensionList(new File((getClass().getResource("/resources/documentsExt.txt")).getPath()), "Documents"); } /** * Adds a directory under selected node * */ protected void makeDir(ArrayList selectedNodeList, int selectedNodeIndex) { NodeItem parent = selectedNodeList.get(selectedNodeIndex); if(!parent.getFile().isDirectory()) { selectedNodeList = parent.getParentList(); selectedNodeIndex = parent.getParentIndex(); parent = selectedNodeList.get(selectedNodeIndex); } String dirname = JOptionPane.showInputDialog(null, "New Directory", "Name of directory", JOptionPane.QUESTION_MESSAGE); String path = parent.getFile().getAbsolutePath(); path += "\\" + dirname; new File(path).mkdir(); //Temporary method of showing new directory via //refreshing directory node by folding and expanding foldNode(selectedNodeList, selectedNodeIndex); expandNode(selectedNodeList, selectedNodeIndex); } /** * Adds another root node to the workspace * */ private void addRootNode() { JFileChooser fc = new JFileChooser(); fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); int val = fc.showOpenDialog(this); if (val == JFileChooser.APPROVE_OPTION) { File myFile = fc.getSelectedFile(); NodeItem temp = new NodeItem(myFile); if(myFile.isHidden()) { hiddenNodeList.add(temp); int index = hiddenNodeList.indexOf(temp); hiddenNodeList.get(index).setPosition((int)rClickPoint.getX(), (int)rClickPoint.getY()); hiddenNodeList.get(index).sethbSize(32); //TODO change to icon chooser when it is made if(temp.getFile().isDirectory()) { hiddenNodeList.get(index).setIcon(getImage("/resources/32x32/folder.png")); } else { hiddenNodeList.get(index).setIcon(getImage("/resources/32x32/page.png")); } } else { nodeList.add(temp); int index = nodeList.indexOf(temp); nodeList.get(index).setPosition((int)rClickPoint.getX(), (int)rClickPoint.getY()); nodeList.get(index).sethbSize(32); //TODO change to icon chooser when it is made if(temp.getFile().isDirectory()) { nodeList.get(index).setIcon(getImage("/resources/32x32/folder.png")); } else { nodeList.get(index).setIcon(getImage("/resources/32x32/page.png")); } } } } /** * Custom paintComponent method to draw all components within * this panel * * @param Graphics component to draw */ @Override //TODO: Fix Nested Block depth. Safe is 0-5 this is @6. protected void paintComponent(Graphics g) { //Set Graphics2d for additional graphical painting super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); //If the user wants the hidden files shown. Paint in the following way if(showHiddenFiles) { //Paint child node lines for(int i = 0; i < nodeList.size(); i++) { //Draw child node lines, draw them first so that the lines are behind icons ArrayList childNodes = nodeList.get(i).getChildNodes(); if(childNodes.size() > 0) { for(int x = 0; x < childNodes.size(); x++) { g.drawLine(nodeList.get(i).getX()+((nodeList.get(i).gethbSize())/2), nodeList.get(i).getY()+((nodeList.get(i).gethbSize())/2), childNodes.get(x).getX()+((childNodes.get(i).gethbSize())/2), childNodes.get(x).getY()+((childNodes.get(i).gethbSize())/2)); //Set the chileNodes line instance variable to specific coordinates //because g.drawLine does not return a modifiable line, it simply draws one. //The line object will be used to find where it intersects with a hitbox. Line2D childLine = childNodes.get(x).getLine(); childLine.setLine((double)nodeList.get(i).getX()+((nodeList.get(i).gethbSize())/2), (double)nodeList.get(i).getY()+((nodeList.get(i).gethbSize())/2), (double)childNodes.get(x).getX()+ ((childNodes.get(x).gethbSize())/2), (double)childNodes.get(x).getY() + ((childNodes.get(x).gethbSize())/2)); //The HitBox's (x,y) position is referring to the top //left corner of the HitBox. CalculateArrowHead theArrowHead = new CalculateArrowHead(childNodes.get(x).getHitBox(), childNodes.get(x).getLine(), 130, 15); childNodes.get(x).setArrowHead(theArrowHead.makeArrow()); g.fillPolygon(childNodes.get(x).getArrowHead()); g.drawPolygon(childNodes.get(x).getArrowHead()); } } } for(int i = 0; i < hiddenNodeList.size(); i++) { //Draw child node lines, draw them first so that the lines are behind icons ArrayList childNodes = hiddenNodeList.get(i).getChildNodes(); if(childNodes.size() > 0) { for(int x = 0; x < childNodes.size(); x++) { g.drawLine(hiddenNodeList.get(i).getX()+((hiddenNodeList.get(i).gethbSize())/2), hiddenNodeList.get(i).getY()+((hiddenNodeList.get(i).gethbSize())/2), childNodes.get(x).getX()+((childNodes.get(i).gethbSize())/2), childNodes.get(x).getY()+((childNodes.get(i).gethbSize())/2)); //Set the chileNodes line instance variable to specific coordinates //because g.drawLine does not return a modifiable line, it simply draws one. //The line object will be used to find where it intersects with a hitbox. Line2D childLine = childNodes.get(x).getLine(); childLine.setLine((double)nodeList.get(i).getX()+((nodeList.get(i).gethbSize())/2), (double)nodeList.get(i).getY()+((nodeList.get(i).gethbSize())/2), (double)childNodes.get(x).getX()+ ((childNodes.get(x).gethbSize())/2), (double)childNodes.get(x).getY() + ((childNodes.get(x).gethbSize())/2)); //The HitBox's (x,y) position is referring to the top //left corner of the HitBox. CalculateArrowHead theArrowHead = new CalculateArrowHead(childNodes.get(x).getHitBox(), childNodes.get(x).getLine(), 130, 15); childNodes.get(x).setArrowHead(theArrowHead.makeArrow()); g.fillPolygon(childNodes.get(x).getArrowHead()); g.drawPolygon(childNodes.get(x).getArrowHead()); } } } for(int i = 0; i < nodeList.size(); i++) { //Draw node image //TODO figure out what observer is for g.drawImage(nodeList.get(i).getIcon(), nodeList.get(i).getX(), nodeList.get(i).getY(), nodeList.get(i).gethbSize(), nodeList.get(i).gethbSize(), this); //Draw hit box if(showHitBox){ g2d.draw(nodeList.get(i).getHitBox()); } //Draw file/directory name label g.drawString(nodeList.get(i).getFile().getName(), nodeList.get(i).getX(), nodeList.get(i).getY()+(nodeList.get(i).gethbSize())+12); } for(int i = 0; i < hiddenNodeList.size(); i++) { //Draw node image float alpha = 0.60f; int type = AlphaComposite.SRC_OVER; AlphaComposite composite = AlphaComposite.getInstance(type, alpha); g2d.setComposite(composite); g2d.drawImage(hiddenNodeList.get(i).getIcon(), hiddenNodeList.get(i).getX(), hiddenNodeList.get(i).getY(), hiddenNodeList.get(i).gethbSize(), hiddenNodeList.get(i).gethbSize(), this); composite = AlphaComposite.getInstance(type, 1); g2d.setComposite(composite); //Draw hit box if(showHitBox){ g2d.draw(hiddenNodeList.get(i).getHitBox()); } //Draw file/directory name label g.drawString(hiddenNodeList.get(i).getFile().getName(), hiddenNodeList.get(i).getX(), hiddenNodeList.get(i).getY()+(hiddenNodeList.get(i).gethbSize())+12); } } else {//If the user does not want the hidden files shown. Paint the following way. //Paint Nodes and selected attributes for(int i = 0; i < nodeList.size(); i++) { //Draw child node lines, draw them first so that the lines are behind icons ArrayList childNodes = nodeList.get(i).getChildNodes(); if(childNodes.size() > 0) { for(int x = 0; x < childNodes.size(); x++) { //The actual drawing of the line. if(!(childNodes.get(x).getFile().isHidden())) { g.drawLine(nodeList.get(i).getX()+((nodeList.get(i).gethbSize())/2), nodeList.get(i).getY()+((nodeList.get(i).gethbSize())/2), childNodes.get(x).getX()+((childNodes.get(x).gethbSize())/2), childNodes.get(x).getY()+((childNodes.get(x).gethbSize())/2)); //Set the chileNodes line instance variable to specific coordinates //because g.drawLine does not return a modifiable line, it simply draws one. //The line object will be used to find where it intersects with a hitbox. Line2D childLine = childNodes.get(x).getLine(); childLine.setLine((double)nodeList.get(i).getX()+((nodeList.get(i).gethbSize())/2), (double)nodeList.get(i).getY()+((nodeList.get(i).gethbSize())/2), (double)childNodes.get(x).getX()+ ((childNodes.get(x).gethbSize())/2), (double)childNodes.get(x).getY() + ((childNodes.get(x).gethbSize())/2)); //The HitBox's (x,y) position is referring to the top //left corner of the HitBox. CalculateArrowHead theArrowHead = new CalculateArrowHead(childNodes.get(x).getHitBox(), childNodes.get(x).getLine(), 130, 15); childNodes.get(x).setArrowHead(theArrowHead.makeArrow()); g.fillPolygon(childNodes.get(x).getArrowHead()); g.drawPolygon(childNodes.get(x).getArrowHead()); } } } //Draw node image //TODO figure out what observer is for g.drawImage(nodeList.get(i).getIcon(), nodeList.get(i).getX(), nodeList.get(i).getY(), nodeList.get(i).gethbSize(), nodeList.get(i).gethbSize(), this); //Draw hit box if(showHitBox){ g2d.draw(nodeList.get(i).getHitBox()); } //Draw file/directory name label g.drawString(nodeList.get(i).getFile().getName(), nodeList.get(i).getX(), nodeList.get(i).getY()+(nodeList.get(i).gethbSize())+12); } } } /** * Update position of a selected Node to the new position using * point given. Acts for dragging with mouse * * @return Point to where Node needs to be moved to */ public void updatePosition(Point p) { int index = 0; ArrayList list = nodeList; boolean selected = false; for(int i = 0; i < nodeList.size(); i++) { if(nodeList.get(i).isSelected()) { index = i; selected = true; break; } } if(showHiddenFiles) { for(int i = 0; i < hiddenNodeList.size(); i++) { if(hiddenNodeList.get(i).isSelected()) { index = i; list = hiddenNodeList; selected = true; break; } } } if(selected) { //Boundary + Collision Checker //TODO fix invisible wall error //TODO non-hard-coded way //Rectangle bounds = (Rectangle) this.getBounds().clone(); //Rectangle bounds = new Rectangle(0, 0, 2000, 2000); //bounds.grow(-5, -5); boolean collision = false; //TODO fix collision detection //possibly use separating axis test /*Rectangle newHitBox = (Rectangle) nodeList.get(index).getHitBox().clone(); Rectangle newHitBoxX = new Rectangle((int)(newHitBox.getX()+p.getX()), (int)newHitBox.getY(), nodeList.get(index).gethbSize(), nodeList.get(index).gethbSize()); Rectangle newHitBoxY = new Rectangle(((int)newHitBox.getX()), (int)(newHitBox.getY()+p.getY()), nodeList.get(index).gethbSize(), nodeList.get(index).gethbSize()); for(int i = 0; i < nodeList.size(); i++) { if(i != index) { if(nodeList.get(i).getHitBox().intersects(newHitBoxX) || nodeList.get(i).getHitBox().intersects(newHitBoxY)) { collision = true; } } }*/ //TODO fix bounds for hit detection if(!collision){ //if(bounds.contains(nodeList.get(index).getX()+(int)p.getX(),10)) //{ list.get(index).setPosition((int)p.getX(), list.get(index).getY()); //} //if(bounds.contains(10, nodeList.get(index).getY()+(int)p.getY())) //{ list.get(index).setPosition(list.get(index).getX(), (int)p.getY()); //} } } else { JScrollPane scroll = sb.getScrollPane(); JScrollBar vScroll = scroll.getVerticalScrollBar(); JScrollBar hScroll = scroll.getHorizontalScrollBar(); int x = (int) (p.getX() - initialClick.getX()); int y = (int) (p.getY() - initialClick.getY()); vScroll.setValue(vScroll.getValue() - (int) (y / 15)); hScroll.setValue(hScroll.getValue() - (int) (x / 15)); } } /** * Check if a point is within a node's hit box * If true, the node is considered selected * Else, the node is unselected * For use to see if a node is clicked on * * @param Point of where the mouse clicked */ public void checkNodeClick(Point p){ initialClick = p; if(showHiddenFiles) { for(int i = 0; i < hiddenNodeList.size(); i++) { if(hiddenNodeList.get(i).getHitBox().contains(p)) { hiddenNodeList.get(i).selectNode(); } else { hiddenNodeList.get(i).unselectNode(); } } for(int i = 0; i < nodeList.size(); i++) { if(nodeList.get(i).getHitBox().contains(p)) { nodeList.get(i).selectNode(); } else { nodeList.get(i).unselectNode(); } } } else { for(int i = 0; i < nodeList.size(); i++) { if(nodeList.get(i).getHitBox().contains(p)) { nodeList.get(i).selectNode(); } else { nodeList.get(i).unselectNode(); } } } } /** * Check if a node has been double clicked * If true, the node is expanded * * @param Point of where the mouse clicked */ //TODO: Fix Cyclomatic Complexity ? Should be 0-10 but is 11. public void checkNodeDoubleClick(Point p) { if(showHiddenFiles) { for(int i = 0; i < hiddenNodeList.size(); i++) { if(hiddenNodeList.get(i).getHitBox().contains(p)) { if(hiddenNodeList.get(i).isExpanded()) { foldNode(hiddenNodeList, i); } else { expandNode(hiddenNodeList, i); } } else { hiddenNodeList.get(i).unselectNode(); } } for(int i = 0; i < nodeList.size(); i++) { if(nodeList.get(i).getHitBox().contains(p)) { if(nodeList.get(i).isExpanded()) { foldNode(nodeList, i); } else { expandNode(nodeList, i); } } } } else { for(int i = 0; i < nodeList.size(); i++) { if(nodeList.get(i).getHitBox().contains(p)) { if(nodeList.get(i).isExpanded()) { foldNode(nodeList, i); } else { expandNode(nodeList, i); } } } } } /** * Removes a node and its entire child tree from the workspace * * @param ArrayList that contains node to be folded * @param int index of the Node in the given ArrayList */ private void removeNode(ArrayList list, int index) { //Remove all child nodes recursively removeAllChildNodes(list, index); //Remove node from associated parent node if it has one if(list.get(index).getParentIndex() != -1) { NodeItem parent = list.get(index).getParentList().get(list.get(index).getParentIndex()); parent.removeChildNode(list.get(index)); } //Remove the node itself last list.remove(index); } /** * Opens the node's attached file using the desktop * * @param ArrayList that contains file's node to be opened * @param int index of the Node in the given ArrayList */ private void openFile(ArrayList list, int index) { try { dTop.open(list.get(index).getFile()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Removes all child nodes from the given list * and recursively goes through child node list * to remove the entire tree below given node * * @param ArrayList that contains node to be removed * @param int index of the Node in the given ArrayList */ private void removeAllChildNodes(ArrayList list, int index) { ArrayList childNodes = list.get(index).getChildNodes(); if(childNodes.size() > 0) { for(int i = 0; i < childNodes.size(); i++) { if(childNodes.get(i).getChildNodes().size() > 0) { removeAllChildNodes(childNodes, i); } //Fold the node foldNode(childNodes, i); } } //Once all others have been folded, fold the given node foldNode(list, index); } /** * Folds a node by grabbing a list of all child nodes * within the Node Item's directory and removing them from the * frame's list of nodes then removes the child nodes * * @param ArrayList that contains node to be folded * @param int index of the Node in the given ArrayList */ private void foldNode(ArrayList list, int index) { if(list.get(index).getFile().isDirectory()) { //Set expand to false so that it can be expanded list.get(index).setExpanded(false); //Sending terminal message try { sb.terminalMessage("Folding Directory: " + list.get(index).getFile().getCanonicalPath()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } ArrayList childNodes = list.get(index).getChildNodes(); for(int i = 0; i < childNodes.size(); i++) { if(childNodes.get(i).getChildNodes().size() > 0) { foldNode(childNodes, i); } if(childNodes.get(i).getFile().isHidden()) { hiddenNodeList.remove(childNodes.get(i)); } else { nodeList.remove(childNodes.get(i)); } } list.get(index).clearChildNodes(); } } /** * Retrieves image resource from within jar/project * Just specify the path of the image resource to get * * @return String fName is the path to the image resource */ private Image getImage(String fName){ URL url = getClass().getResource(fName); ImageIcon icon = new ImageIcon(url); return icon.getImage(); } /** * Determines popup menu to display based on context * of mouse click location * * @param Component to draw on * @param Point at which to display popup */ //TODO: Fix Nested Block depth. Safe is 0-5 this is @6. public void showPopUp(Component e, Point p){ boolean node = false; if(showHiddenFiles) { for(int i = 0; i < hiddenNodeList.size(); i++) { if(hiddenNodeList.get(i).getHitBox().contains(p)) { setRClickPoint(p); node = true; deleteMenuItem.setVisible(true); cutMenuItem.setVisible(true); copyMenuItem.setVisible(true); pasteMenuItem.setVisible(true); renameMenuItem.setVisible(true); pasteMenuItem.setEnabled(false); if(hiddenNodeList.get(i).getFile().isDirectory()) { openInTabMenuItem.setVisible(true); openMenuItem.setVisible(false); if(hiddenNodeList.get(i).isExpanded()) { expandNodeMenuItem.setVisible(false); foldNodeMenuItem.setVisible(true); } else { expandNodeMenuItem.setVisible(true); foldNodeMenuItem.setVisible(false); } } else { expandNodeMenuItem.setVisible(false); foldNodeMenuItem.setVisible(false); openMenuItem.setVisible(true); openInTabMenuItem.setVisible(false); } nodePopUp.show(e, (int)p.getX(), (int)p.getY()); selectedNodeIndex = i; selectedNodeList = hiddenNodeList; break; } } } for(int i = 0; i < nodeList.size(); i++) { if(nodeList.get(i).getHitBox().contains(p)) { setRClickPoint(p); node = true; deleteMenuItem.setVisible(true); cutMenuItem.setVisible(true); copyMenuItem.setVisible(true); pasteMenuItem.setVisible(true); renameMenuItem.setVisible(true); pasteMenuItem.setEnabled(false); if(nodeList.get(i).getFile().isDirectory()) { openInTabMenuItem.setVisible(true); if(!FSUtil.getInstance().isClipBoardEmpty()) pasteMenuItem.setEnabled(true); openMenuItem.setVisible(false); if(nodeList.get(i).isExpanded()) { expandNodeMenuItem.setVisible(false); foldNodeMenuItem.setVisible(true); } else { expandNodeMenuItem.setVisible(true); foldNodeMenuItem.setVisible(false); } } else { openInTabMenuItem.setVisible(false); expandNodeMenuItem.setVisible(false); foldNodeMenuItem.setVisible(false); openMenuItem.setVisible(true); } nodePopUp.show(e, (int)p.getX(), (int)p.getY()); selectedNodeIndex = i; selectedNodeList = nodeList; break; } } if(!node) { setRClickPoint(p); backgroundPopUp.show(e, (int)p.getX(), (int)p.getY()); } } /** * Returns an array list of all nodes within the panel * * @return Entire Node List within this panel */ public ArrayList getNodeList(){ return nodeList; } /** * Toggles boolean for displaying hit boxes * */ public void toggleShowHitBoxes(){ if(showHitBox) { showHitBox = false; } else showHitBox = true; } /** * Toggles boolean for displaying hidden files * */ public void toggleShowHiddenFiles() { if(showHiddenFiles) { showHiddenFiles = false; } else showHiddenFiles = true; } /** * Expands a node by grabbing a list of all files/directories * within a Node Item's directory and associates all new * NodeItem objects as child nodes of the expanded node as * well as adds NodeItems to the total nodeList for the frame * * @param ArrayList that contains node to be expanded * @param int index of the Node in the given ArrayList */ private void expandNode(ArrayList list, int index) { //Only expand for directories if(list.get(index).getFile().isDirectory()) { //Only expand once list.get(index).setExpanded(true); //Sending terminal message try { sb.terminalMessage("Expanding Directory: " + list.get(index).getFile().getCanonicalPath()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //Get list of files File[] fList = list.get(index).getFile().listFiles(); //TODO temporary square view; use until we have a //setting variable to determine how to space new node items int rowOffset = 40; int columnOffset = 40; int counter = 0; NodeItem tNode; try { for(int i = 0; i < fList.length; i++){ tNode = new NodeItem(fList[i]); //Add node to appropriate frame list, depending on if it is hidden or not if(fList[i].isHidden()) { hiddenNodeList.add(tNode); int tIndex = hiddenNodeList.indexOf(tNode); //Set hbsize and position hiddenNodeList.get(tIndex).sethbSize(32); hiddenNodeList.get(tIndex).setPosition(list.get(index).getX()+columnOffset, list.get(index).getY()+rowOffset); //Set icon if(hiddenNodeList.get(tIndex).getFile().isDirectory()) { hiddenNodeList.get(tIndex).setIcon(getImage("/resources/32x32/folder.png")); } else { hiddenNodeList.get(tIndex).setIcon(getImage(ext.getExtensionIcon(hiddenNodeList.get(tIndex).getFile().getName()))); } //Add child node and set parent list.get(index).addChildNode(hiddenNodeList.get(tIndex)); hiddenNodeList.get(tIndex).setParentNode(nodeList, index); } else { nodeList.add(tNode); int tIndex = nodeList.indexOf(tNode); //Set hbsize and position nodeList.get(tIndex).sethbSize(32); nodeList.get(tIndex).setPosition(list.get(index).getX()+columnOffset, list.get(index).getY()+rowOffset); //Set icon if(nodeList.get(tIndex).getFile().isDirectory()) { nodeList.get(tIndex).setIcon(getImage("/resources/32x32/folder.png")); } else { String name = nodeList.get(tIndex).getFile().getName(); String path = ext.getExtensionIcon(name); nodeList.get(tIndex).setIcon(getImage(path)); } //Add child node and set parent list.get(index).addChildNode(nodeList.get(tIndex)); nodeList.get(tIndex).setParentNode(nodeList, index); } //TODO increases temporary offset if(counter == 14) { columnOffset = 40; rowOffset += 40; counter = 0; } else { counter++; columnOffset += 40; rowOffset += 20; } } } catch(NullPointerException e) { System.out.println("Could not expand " +list.get(index).getFile().getAbsolutePath()); System.out.println("Null list of files. Probably a permissions error."); } } else { File temp = list.get(index).getFile(); openFile(list, index); sb.terminalMessage("Double clicked: " + temp.getName()); } } /** * Sets point where a right clicked occured * * @param Point where click occured */ public void setRClickPoint(Point p) { rClickPoint = p; } }