| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache 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.apache.org/licenses/LICENSE-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 org.netbeans.modules.web.jsf.navigation; |
| |
| import java.awt.Image; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import javax.swing.Action; |
| import javax.swing.event.ChangeEvent; |
| import javax.swing.event.ChangeListener; |
| import org.netbeans.modules.web.jsf.navigation.graph.PageFlowSceneElement; |
| import org.netbeans.modules.web.jsf.navigation.pagecontentmodel.PageContentItem; |
| import org.netbeans.modules.web.jsf.navigation.pagecontentmodel.PageContentModel; |
| import org.netbeans.modules.web.jsf.navigation.pagecontentmodel.PageContentModelProvider; |
| import org.openide.nodes.Node; |
| import org.openide.nodes.Node.Cookie; |
| import org.openide.util.HelpCtx; |
| import org.openide.util.ImageUtilities; |
| import org.openide.util.NbBundle; |
| import org.openide.DialogDescriptor; |
| import org.openide.cookies.SaveCookie; |
| import org.openide.filesystems.FileObject; |
| import org.openide.loaders.DataNode; |
| import org.openide.nodes.AbstractNode; |
| import org.openide.nodes.Children; |
| import org.openide.util.Exceptions; |
| import org.openide.util.Utilities; |
| import org.openide.util.actions.SystemAction; |
| |
| /** |
| * |
| * @author joelle |
| */ |
| public class Page extends PageFlowSceneElement implements SaveCookie { |
| |
| public final PageFlowController pc; |
| private Node original; |
| private PageContentModel pageContentModel = null; |
| |
| /** |
| * Creates a PageFlowNode |
| * @param pc |
| * @param original |
| */ |
| public Page(PageFlowController pc, Node original) { |
| super(); |
| this.pc = pc; |
| setNode(original); |
| /* Update the page only at request |
| updateContentModel(); |
| initListeners(); |
| */ |
| } |
| |
| public void updateContentModel() { |
| if (!isDataNode()) { |
| return; |
| } |
| |
| FileObject fileObject = ((DataNode) original).getDataObject().getPrimaryFile(); |
| |
| destroyListeners(); /* Otherwise initlisteners will not work */ |
| |
| for (PageContentModelProvider provider : PageFlowController.getPageContentModelProviders()) { |
| pageContentModel = provider.getPageContentModel(fileObject); |
| //exit when you find one. |
| if (pageContentModel != null) { |
| initListeners(); |
| return; |
| } |
| } |
| } |
| // public Node getWrappedNode() { |
| // return original; |
| // } |
| private String nodeDisplayName; |
| |
| private void setNode(Node newNode) { |
| String oldDisplayName = nodeDisplayName; |
| original = newNode; |
| nodeDisplayName = original.getDisplayName(); |
| //HACK sometimes the datanode name isn't updated as fast as the filename. |
| if (original instanceof DataNode) { |
| assert pc != null; |
| |
| FileObject fileObj = ((DataNode) original).getDataObject().getPrimaryFile(); |
| assert fileObj != null; |
| nodeDisplayName = getFolderDisplayName(pc.getWebFolder(), fileObj); |
| } |
| if (!nodeDisplayName.equals(oldDisplayName)) { |
| if (oldDisplayName != null) { |
| pc.removePageName2Page(oldDisplayName, false); |
| } |
| pc.putPageName2Page(nodeDisplayName, this); |
| } |
| } |
| |
| public void updateNode_HACK() { |
| setNode(original); |
| } |
| |
| /* We may want this to notify listeners of changes.*/ |
| public void replaceWrappedNode(Node newNode) { |
| // pc.pageName2Node.remove(getDisplayName()); |
| //pc.removePageName2Page(getDisplayName(), false); |
| setNode(newNode); |
| pc.putPageName2Page(getDisplayName(), this); |
| // pc.putPageName2Node(getDisplayName(), this); |
| } |
| private boolean renaming = false; |
| { |
| } |
| |
| public boolean isRenaming() { |
| return renaming; |
| } |
| |
| @Override |
| public void setName(String s) { |
| |
| String oldDisplayName = getDisplayName(); |
| try { |
| if (!pc.isPageInAnyFacesConfig(oldDisplayName)) { |
| original.setName(s); |
| } else { |
| renaming = true; |
| original.setName(s); |
| String newDisplayName = original.getDisplayName(); |
| if (isDataNode()) { |
| newDisplayName = getFolderDisplayName(pc.getWebFolder(), ((DataNode) original).getDataObject().getPrimaryFile()); |
| } |
| pc.saveLocation(oldDisplayName, newDisplayName); |
| renaming = false; |
| pc.renamePageInModel(oldDisplayName, newDisplayName); |
| } |
| } catch (IllegalArgumentException iae) { |
| |
| // determine if "printStackTrace" and "new annotation" of this exception is needed |
| boolean needToAnnotate = Exceptions.findLocalizedMessage(iae) == null; |
| |
| // annotate new localized message only if there is no localized message yet |
| if (needToAnnotate) { |
| Exceptions.attachLocalizedMessage(iae, NbBundle.getMessage(Page.class, "MSG_BadFormat", oldDisplayName, s)); |
| } |
| |
| Exceptions.printStackTrace(iae); |
| } |
| } |
| |
| public String getDisplayName() { |
| return nodeDisplayName; |
| // return original.getDisplayName(); |
| } |
| |
| @Override |
| public String getName() { |
| // Thread.dumpStack(); |
| return original.getName(); |
| // return nodeDisplayName; |
| } |
| |
| /** |
| * |
| * @return |
| */ |
| @Override |
| public boolean canRename() { |
| return isModifiable(); |
| } |
| |
| @Override |
| public boolean canDestroy() { |
| return true; |
| } |
| |
| /* Joelle: Temporarily I need not use destroy for the other purpose. I plan to fix after stabilization */ |
| public void destroy2() { |
| destroyListeners(); |
| if ( original instanceof NonDataNode) { |
| original = null; |
| } |
| pccl = null; |
| pageContentModel = null; |
| } |
| |
| public void destroy() throws IOException { |
| |
| Object input = DialogDescriptor.NO_OPTION; //This should be the default option especially if not a DataNode. |
| boolean removePageName2NodeReference = true; //By default remove it. |
| if (isDataNode()) { |
| //Don't even ask unless DataNode. |
| DialogDescriptor dialog = new DialogDescriptor(NbBundle.getMessage(Page.class, "MSG_DELETE_QUESTION", getDisplayName()), NbBundle.getMessage(Page.class, "MSG_DELETE_TITLE"), true, DialogDescriptor.YES_NO_CANCEL_OPTION, DialogDescriptor.NO_OPTION, null); |
| java.awt.Dialog d = org.openide.DialogDisplayer.getDefault().createDialog(dialog); |
| d.setVisible(true); |
| input = dialog.getValue(); |
| if (pc != null && pc.isCurrentScope(PageFlowToolbarUtilities.Scope.SCOPE_PROJECT)) { |
| removePageName2NodeReference = false; //if it is a data node and we are in project scope make sure to not remove it. |
| } |
| } |
| |
| String displayName = getDisplayName(); |
| // Would you like to delete this file too? |
| if (input == DialogDescriptor.YES_OPTION) { |
| pc.removeSceneNodeEdges(this); |
| original.destroy(); |
| destroyListeners(); |
| } else if (input == DialogDescriptor.NO_OPTION) { |
| // XXX #142726 In case of deleting the node via PageFlowDeleteAction, do not delete the edges. |
| // pc.removeSceneNodeEdges(this); |
| // if ( removePageName2NodeReference ) { //HACK Should I remove the node myself until Petr fixes this bug? |
| // // pc.removePageName2Node(displayName); |
| // destroy(); |
| // } |
| // System.out.println("Only Node Removed"); |
| } else if (input == DialogDescriptor.CANCEL_OPTION) { |
| // System.out.println("Cancel... Do Nothing."); |
| } |
| // destroyListeners(); |
| // |
| // original.destroy(); |
| // pc.pageName2Node.remove(getDisplayName()); |
| } |
| private static final Image ABSTRACTNODE = ImageUtilities.loadImage("org/netbeans/modules/web/jsf/navigation/graph/resources/abstract.gif"); // NOI18N |
| |
| public Image getIcon(int type) { |
| if (!isDataNode()) { |
| return ABSTRACTNODE; |
| } |
| return original.getIcon(type); |
| } |
| |
| @Override |
| public HelpCtx getHelpCtx() { |
| return original.getHelpCtx(); |
| } |
| |
| public Node getNode() { |
| if (isDataNode()) { |
| return original; |
| } else { |
| return new NonDataNode(original.getName()); |
| } |
| } |
| |
| public boolean isDataNode() { |
| return original instanceof DataNode; |
| } |
| |
| public void save() throws IOException { |
| // pc.getConfigDataObject().getEditorSupport().saveDocument(); |
| getCookie(SaveCookie.class).save(); |
| } |
| |
| // @Override |
| public <T extends Cookie> T getCookie(Class<T> type) { |
| if (type.equals(SaveCookie.class)) { |
| return pc.getConfigDataObject().getCookie(type); |
| } |
| return original.getCookie(type); |
| } |
| |
| /** |
| * Solves a fileobjects display name. |
| * @param webFolder |
| * @param fileObject |
| * @return |
| */ |
| public static String getFolderDisplayName(FileObject webFolder, FileObject fileObject) { |
| String folderpath = webFolder.getPath(); |
| String filepath = fileObject.getPath(); |
| return filepath.replaceFirst(folderpath + "/", ""); |
| } |
| |
| public static String getFolderDisplayName(FileObject webFolder, String path, String fileNameExt) { |
| String folderpath = webFolder.getPath(); |
| return path.replaceFirst(folderpath + "/", "") + fileNameExt; |
| } |
| |
| public Collection<PageContentItem> getPageContentItems() { |
| if (pageContentModel == null) { |
| return new ArrayList<PageContentItem>(); |
| } |
| return pageContentModel.getPageContentItems(); |
| } |
| private boolean hasPageContentModelBeenChecked = false; |
| |
| public Collection<Pin> getPinNodes() { |
| if (!hasPageContentModelBeenChecked) { |
| updateContentModel(); |
| hasPageContentModelBeenChecked = true; |
| } |
| if (pageContentModel == null) { |
| return Collections.emptyList(); |
| } |
| Collection<PageContentItem> pageContentItems = pageContentModel.getPageContentItems(); |
| Collection<Pin> pinNodes = new ArrayList<Pin>(pageContentItems.size()); |
| for (PageContentItem pageContentItem : pageContentItems) { |
| pinNodes.add(new Pin(this, pageContentItem)); |
| } |
| return pinNodes; |
| } |
| private PageContentChangeListener pccl; |
| /** |
| * Before using this method, it is good to make sure all listeners |
| * are destroyed. Use destroyListeners(). |
| **/ |
| private void initListeners() { |
| if (pageContentModel != null && pccl == null) { |
| pccl = new PageContentChangeListener(); |
| pageContentModel.addChangeListener(pccl); |
| } |
| } |
| |
| /** |
| * Removes any content model listeners |
| **/ |
| private void destroyListeners() { |
| if (pccl != null && pageContentModel != null) { |
| try { |
| pageContentModel.removeChangeListener(pccl); |
| pageContentModel.destroy(); |
| pageContentModel = null; |
| pccl = null; |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| } |
| |
| private final Page getInstance() { |
| return this; |
| } |
| private class PageContentChangeListener implements ChangeListener { |
| |
| public void stateChanged(ChangeEvent arg0) { |
| if( !pc.getView().isShowing()){ //Don't do anything except let PFC know that the graph is dirty if the graph is not showing. |
| pc.setGraphDirty(); |
| } else { |
| pc.updatePageItems(getInstance()); |
| } |
| } |
| } |
| |
| public Action[] getActions(boolean context) { |
| if (pageContentModel != null) { |
| return pageContentModel.getActions(); |
| } |
| return new SystemAction[]{}; |
| // if( pageContentModel != null ){ |
| // SystemAction[] pageModelActions = pageContentModel.getActions(); |
| // SystemAction[] nodeActions = super.getActions(); |
| // |
| // if( pageModelActions == null || pageModelActions.length == 0 ){ |
| // return nodeActions; |
| // } else if ( nodeActions == null || nodeActions.length == 0 ){ |
| // return pageModelActions; |
| // } else { |
| // int size = pageModelActions.length + nodeActions.length; |
| // SystemAction[] sysActions = new SystemAction[size]; |
| // System.arraycopy(nodeActions, 0, sysActions, 0, nodeActions.length); |
| // System.arraycopy(pageModelActions, 0, sysActions, nodeActions.length, pageModelActions.length); |
| // return sysActions; |
| // } |
| // } else { |
| // return super.getActions(); |
| // } |
| } |
| |
| public boolean equals(Object obj) { |
| return this == obj; |
| } |
| |
| @Override |
| public int hashCode() { |
| return System.identityHashCode(this); |
| } |
| // |
| // public final NonDataNode createNonDataNode() { |
| // return new NonDataNode(this); |
| // } |
| |
| |
| |
| public final class NonDataNode extends AbstractNode { |
| |
| |
| public NonDataNode( String pageName) { |
| super(Children.LEAF); |
| super.setName(pageName); |
| } |
| |
| @Override |
| public boolean canRename() { |
| return true; |
| } |
| |
| @Override |
| public String getName() { |
| return getInstance().getName(); |
| } |
| |
| @Override |
| public void setName(String s) { |
| super.setName(s); |
| getInstance().setName(s); |
| } |
| } |
| } |