fix display of default file
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 30 May 2008 12:20:09 +0000 (14:20 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 30 May 2008 12:20:09 +0000 (14:20 +0200)
src/net/pterodactylus/jsite/gui/FileManager.java

index 0c714c5..6bd83fc 100644 (file)
@@ -33,6 +33,8 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -46,6 +48,7 @@ import javax.swing.JButton;
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JDialog;
 import javax.swing.JLabel;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
@@ -63,6 +66,7 @@ import net.pterodactylus.jsite.i18n.I18n;
 import net.pterodactylus.jsite.i18n.I18nable;
 import net.pterodactylus.jsite.i18n.gui.I18nAction;
 import net.pterodactylus.jsite.i18n.gui.I18nLabel;
+import net.pterodactylus.jsite.project.FileOverride;
 import net.pterodactylus.jsite.project.Project;
 import net.pterodactylus.jsite.project.ProjectFile;
 import net.pterodactylus.util.logging.Logging;
@@ -70,7 +74,7 @@ import net.pterodactylus.util.swing.SwingUtils;
 
 /**
  * Manages physical and virtual files in a project.
- * 
+ *
  * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
  */
 public class FileManager extends JDialog implements I18nable, ActionListener, TreeSelectionListener, MouseListener {
@@ -140,7 +144,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
 
        /**
         * Creates a new file manager.
-        * 
+        *
         * @param swingInterface
         *            The Swing interface
         * @param project
@@ -152,6 +156,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                this.swingInterface = swingInterface;
                this.project = project;
                fileTreeModel = new ProjectFileTreeModel();
+               project.addPropertyChangeListener(fileTreeModel);
                fileCellRenderer = new FileCellRenderer();
                initActions();
                initComponents();
@@ -206,8 +211,25 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                        /**
                         * {@inheritDoc}
                         */
-                       public void actionPerformed(ActionEvent e) {
-                               /* TODO */
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               TreePath selectedPath = fileTree.getSelectionPath();
+                               if (selectedPath == null) {
+                                       logger.log(Level.WARNING, "nothing selected!");
+                                       return;
+                               }
+                               ProjectFileWrapper projectFileWrapper = (ProjectFileWrapper) selectedPath.getLastPathComponent();
+                               if (isHidden(projectFileWrapper)) {
+                                       /* TODO - i18n */
+                                       JOptionPane.showMessageDialog(FileManager.this, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
+                                       return;
+                               }
+                               if (projectFileWrapper.getProjectFile().isDirectory()) {
+                                       /* TODO - i18n */
+                                       JOptionPane.showMessageDialog(FileManager.this, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
+                                       return;
+                               }
+                               String completePath = projectFileWrapper.getProjectFile().getCompletePath();
+                               project.setDefaultFile(completePath);
                        }
                };
                insertAction = new I18nAction("fileManager.menu.item.insert") {
@@ -241,7 +263,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
 
        /**
         * Creates the main panel with the file tree and the file properties.
-        * 
+        *
         * @return The mail panel
         */
        private Component createFileManagerPanel() {
@@ -311,7 +333,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
 
        /**
         * Creates the button panel.
-        * 
+        *
         * @return The button panel
         */
        private Component createButtonPanel() {
@@ -353,7 +375,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
        /**
         * Checks whether the given mouse event is a popup trigger and occured over
         * a file. If so, the context menu is shown.
-        * 
+        *
         * @param mouseEvent
         *            The mouse event to check
         */
@@ -367,9 +389,26 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                        return;
                }
                fileTree.setSelectionPath(clickedPath);
+               ProjectFileWrapper projectFileWrapper = (ProjectFileWrapper) clickedPath.getLastPathComponent();
+               insertCheckBoxMenuItem.setSelected(!isHidden(projectFileWrapper));
                treeContextMenu.show(fileTree, eventLocation.x, eventLocation.y);
        }
 
+       /**
+        * Finds whether the {@link ProjectFile} given by
+        * <code>projectFileWrapper</code> is hidden.
+        *
+        * @param projectFileWrapper
+        *            The wrapped project file
+        * @return <code>true</code> if the file is hidden and should not be
+        *         inserted, <code>false</code> otherwise
+        */
+       private boolean isHidden(ProjectFileWrapper projectFileWrapper) {
+               ProjectFile projectFile = projectFileWrapper.getProjectFile();
+               FileOverride fileOverride = project.getFileOverrides().get(projectFile.getCompletePath());
+               return ((fileOverride == null) && projectFile.isHidden()) || ((fileOverride != null) && (fileOverride.isInsert()));
+       }
+
        //
        // INTERFACE I18nable
        //
@@ -393,7 +432,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
         */
        public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
                TreePath[] selectedPaths = fileTree.getSelectionPaths();
-               if (selectedPaths.length == 1) {
+               if ((selectedPaths != null) && (selectedPaths.length == 1)) {
                        Object lastPathComponent = selectedPaths[0].getLastPathComponent();
                        if (!(lastPathComponent instanceof ProjectFileWrapper)) {
                                logger.log(Level.SEVERE, "lastPathComponent is not a ProjectFileWrapper!");
@@ -461,7 +500,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
        /**
         * Tree cell renderer that takes care of certain display properties for
         * project-specific stuff.
-        * 
+        *
         * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
         */
        private class FileCellRenderer extends DefaultTreeCellRenderer {
@@ -492,15 +531,26 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                        ProjectFileWrapper projectFileWrapper = (ProjectFileWrapper) value;
                        ProjectFile projectFile = projectFileWrapper.getProjectFile();
                        String completePath = projectFile.getCompletePath();
-                       if (projectFile.isHidden()) {
+                       boolean paintBold = false;
+                       boolean paintHalfColor = false;
+                       if (projectFile.isFile() && projectFile.isHidden()) {
                                /* TODO - check override */
+                               paintHalfColor = true;
+                       } else if (completePath.equals(project.getDefaultFile())) {
+                               paintBold = true;
+                       } else if (projectFile.getParents().size() == 1) {
+                               paintBold = true;
+                       }
+                       if (paintHalfColor) {
+                               /* TODO - cache colors */
                                Color foreground = superCellRenderer.getForeground();
                                Color background = selected ? getBackgroundSelectionColor() : getBackgroundNonSelectionColor();
                                Color averageColor = new Color((foreground.getRed() + background.getRed()) / 2, (foreground.getGreen() + background.getGreen()) / 2, (foreground.getBlue() + background.getBlue()) / 2);
                                superCellRenderer.setForeground(averageColor);
-                       } else if (completePath.equals(project.getDefaultFile())) {
-                               superCellRenderer.setFont(superCellRenderer.getFont().deriveFont(Font.BOLD));
-                       } else if (projectFile.getParents().size() == 1) {
+                       } else {
+                               superCellRenderer.setForeground(selected ? getTextSelectionColor() : getTextNonSelectionColor());
+                       }
+                       if (paintBold) {
                                superCellRenderer.setFont(superCellRenderer.getFont().deriveFont(Font.BOLD));
                        } else {
                                superCellRenderer.setFont(superCellRenderer.getFont().deriveFont(Font.PLAIN));
@@ -512,10 +562,10 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
 
        /**
         * TreeModel that is based on {@link Project#getBaseFile()}.
-        * 
+        *
         * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
         */
-       private class ProjectFileTreeModel implements TreeModel {
+       private class ProjectFileTreeModel implements TreeModel, PropertyChangeListener {
 
                /** Tree model listeners. */
                private final List<TreeModelListener> treeModelListeners = Collections.synchronizedList(new ArrayList<TreeModelListener>());
@@ -523,6 +573,9 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                /** The base project file. */
                private ProjectFile baseProjectFile;
 
+               /** Maps path names to project files. */
+               private final Map<String, ProjectFile> pathProjectFiles = Collections.synchronizedMap(new HashMap<String, ProjectFile>());
+
                /** Maps project files to wrappers. */
                private final Map<ProjectFile, ProjectFileWrapper> projectFileWrappers = Collections.synchronizedMap(new HashMap<ProjectFile, ProjectFileWrapper>());
 
@@ -552,14 +605,35 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                }
 
                /**
+                * Notifies all listeners that a node has changed.
+                *
+                * @param changedProjectFileWrapper
+                *            The wrapper around the changed project file
+                */
+               protected void fireTreeNodesChanged(ProjectFileWrapper changedProjectFileWrapper) {
+                       ProjectFile changedProjectFile = changedProjectFileWrapper.getProjectFile();
+                       ProjectFile changedProjectFileParent = changedProjectFile.getParent();
+                       ProjectFile currentProjectFileParent = changedProjectFile;
+                       List<ProjectFileWrapper> parentProjectFileWrappers = new ArrayList<ProjectFileWrapper>();
+                       do {
+                               parentProjectFileWrappers.add(0, projectFileWrappers.get(currentProjectFileParent));
+                               currentProjectFileParent = currentProjectFileParent.getParent();
+                       } while (currentProjectFileParent != null);
+                       TreeModelEvent treeModelEvent = new TreeModelEvent(this, parentProjectFileWrappers.toArray(), new int[] { getIndexOfChild(projectFileWrappers.get(changedProjectFileParent), changedProjectFileWrapper) }, new Object[] { changedProjectFileWrapper });
+                       for (TreeModelListener treeModelListener : treeModelListeners) {
+                               treeModelListener.treeNodesChanged(treeModelEvent);
+                       }
+               }
+
+               /**
                 * Notifies all listeners that the tree structure has changed
                 * significantly.
-                * 
+                *
                 * @see TreeModelListener#treeStructureChanged(TreeModelEvent)
                 * @param newRootNode
                 */
                protected void fireTreeStructureChanged(ProjectFileWrapper newRootNode) {
-                       for (TreeModelListener treeModelListener: treeModelListeners) {
+                       for (TreeModelListener treeModelListener : treeModelListeners) {
                                treeModelListener.treeStructureChanged(new TreeModelEvent(this, new Object[] { newRootNode }));
                        }
                }
@@ -570,7 +644,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
 
                /**
                 * Sets the new base project file. This causes the model to reload.
-                * 
+                *
                 * @param baseProjectFile
                 *            The new base project file
                 */
@@ -578,6 +652,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                public synchronized void setBaseProjectFile(ProjectFile baseProjectFile) {
                        this.baseProjectFile = baseProjectFile;
                        projectFileWrappers.clear();
+                       pathProjectFiles.clear();
                        createWrappers(baseProjectFile);
                        projectFileWrappers.get(baseProjectFile).setNameOverride(project.getName());
                        fireTreeStructureChanged(projectFileWrappers.get(baseProjectFile));
@@ -590,18 +665,20 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                /**
                 * Creates {@link ProjectFileWrapper}s for all files below the given
                 * project file.
-                * 
+                *
                 * @param projectFile
                 *            The base project file for all project files to create
                 *            wrappers for
                 */
                private void createWrappers(ProjectFile projectFile) {
                        projectFileWrappers.put(projectFile, new ProjectFileWrapper(projectFile));
-                       for (ProjectFile projectFileChild: projectFile.getFiles()) {
+                       pathProjectFiles.put(projectFile.getCompletePath(), projectFile);
+                       for (ProjectFile projectFileChild : projectFile.getFiles()) {
                                if (projectFileChild.isDirectory()) {
                                        createWrappers(projectFileChild);
                                }
                                projectFileWrappers.put(projectFileChild, new ProjectFileWrapper(projectFileChild));
+                               pathProjectFiles.put(projectFileChild.getCompletePath(), projectFileChild);
                        }
                }
 
@@ -683,12 +760,36 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                        /* ignore, items will not be modified in tree. */
                }
 
+               //
+               // INTERFACE PropertyChangeListener
+               //
+
+               /**
+                * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+                */
+               public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
+                       if (Project.PROPERTY_DEFAULT_FILE.equals(propertyChangeEvent.getPropertyName())) {
+                               String oldCompletePath = (String) propertyChangeEvent.getOldValue();
+                               String newCompletePath = (String) propertyChangeEvent.getNewValue();
+                               ProjectFile oldProjectFile = pathProjectFiles.get(oldCompletePath);
+                               ProjectFile newProjectFile = pathProjectFiles.get(newCompletePath);
+                               ProjectFileWrapper oldProjectFileWrapper = projectFileWrappers.get(oldProjectFile);
+                               ProjectFileWrapper newProjectFileWrapper = projectFileWrappers.get(newProjectFile);
+                               System.out.println("oldProjectFileWrapper: " + oldProjectFileWrapper);
+                               System.out.println("newProjectFileWrapper: " + newProjectFileWrapper);
+                               fireTreeNodesChanged(oldProjectFileWrapper);
+                               fireTreeNodesChanged(newProjectFileWrapper);
+                               /* HACK - swing sucks a bit. */
+                               fileTree.setShowsRootHandles(false);
+                       }
+               }
+
        }
 
        /**
         * Wrapper around a {@link ProjectFile} that overwrites
         * {@link Object#toString()} to return the project file’s name.
-        * 
+        *
         * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
         */
        private static class ProjectFileWrapper {
@@ -701,7 +802,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
 
                /**
                 * Creates a new wrapper around a project file.
-                * 
+                *
                 * @param projectFile
                 *            The project file to wrap
                 */
@@ -711,7 +812,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
 
                /**
                 * Returns the wrapped project file.
-                * 
+                *
                 * @return The wrapped project file
                 */
                public ProjectFile getProjectFile() {
@@ -721,7 +822,7 @@ public class FileManager extends JDialog implements I18nable, ActionListener, Tr
                /**
                 * Sets the name override. If the name override is not <code>null</code>
                 * it will be shown insted of the project file’s name.
-                * 
+                *
                 * @param nameOverride
                 *            The name override
                 */