/* * � Copyright IBM Corp. 2011 * * Licensed 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 com.ibm.xsp.extlib.designer.tooling.utils; import java.util.ArrayList; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import com.ibm.commons.iloader.node.lookups.api.ILookup; import com.ibm.commons.iloader.node.lookups.api.LookupListener; import com.ibm.commons.util.QuickSort; import com.ibm.commons.util.StringUtil; import com.ibm.designer.domino.ide.resources.extensions.DesignerDesignElement; import com.ibm.designer.domino.ide.resources.extensions.DesignerProject; import com.ibm.designer.domino.ui.commons.extensions.DesignerResource; /** * @author mblout * * This class will evolve to include other element types, but for now * it only really returns XPages, and changes based on additions and removals of XPages. * * @deprecated Use com.ibm.designer.domino.ide.resources.DesignerDELookup instead * */ public class ExtLibDesignElementLookup implements ILookup { IResourceChangeListener resListener = new IResourceChangeListener() { public void resourceChanged(IResourceChangeEvent event) { // @TODO: need to filter resource events! try { IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() { boolean keepVisiting = true; public boolean visit(IResourceDelta delta) { if (!keepVisiting || null == designerProject) return false; int k = delta.getKind(); if ( ! (IResourceDelta.ADDED == k || IResourceDelta.REMOVED == k || IResourceDelta.CHANGED == k) ) // an update could be a name change return true; // if ((delta.getFlags() ...? IResource resource = delta.getResource(); if (resource.getType() == IResource.FILE && resource.getProject().equals(designerProject.getProject())) { String resExt = resource.getFileExtension(); String typeExt = extForType(); if (typeExt.length() > 0 && resExt.length() > 0 && typeExt.equalsIgnoreCase(resExt)) { keepVisiting = false; updateDesignElements(); } } return keepVisiting; } }; event.getDelta().accept(visitor); } catch(Exception e) { ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.error(e, e.toString()); } } }; // add things as we need them private String extForType() { if (StringUtil.equals(typeId, DesignerResource.TYPE_XPAGE)) { return ".xsp"; // $NON-NLS-1$ } else if (StringUtil.equals(typeId, DesignerResource.TYPE_THEME)) { return ".theme"; // $NON-NLS-1$ } return ""; } /* (non-Javadoc) * @see com.ibm.commons.iloader.node.lookups.api.ILookup#getLabelFromCode(java.lang.String) */ public String getLabelFromCode(String code) { return null; } /* (non-Javadoc) * @see com.ibm.commons.iloader.node.lookups.api.ILookup#getImage(int) */ public Image getImage(int index) { return null; } protected DesignerDesignElement[] designElements = null; protected DesignerProject designerProject; protected String typeId; protected DesignerDesignElementFilter filter; protected int folderCount; private boolean showExtension = false; private boolean bStartResultWithSep = true; public interface DesignerDesignElementFilter{ public boolean accept(DesignerDesignElement de); } /** * */ public ExtLibDesignElementLookup(DesignerProject designerProject, String typeId) { this(designerProject, typeId, false, null); } private ExtLibDesignElementLookup(DesignerProject designerProject, String typeId, boolean showExtension, DesignerDesignElementFilter filter) { this(designerProject, typeId, false, true, null); } public ExtLibDesignElementLookup(DesignerProject designerProject, String typeId, boolean showExtension, boolean bIncludeSep, DesignerDesignElementFilter filter) { this.designerProject = designerProject; this.typeId = typeId; this.filter = filter; this.bStartResultWithSep = bIncludeSep; updateDesignElements(); } protected DesignerDesignElement[] getDesignElements() { return designElements; } protected void setDesignElements(DesignerDesignElement[] elements) { designElements = elements; } /** * */ protected void updateDesignElements() { designElements = designerProject.getDesignElements(typeId); folderCount = getNavigatorFolderCount(); new QuickSort.ObjectArray(designElements) { public int compare(Object o1, Object o2) { if(null != o1 && null != o2){ return StringUtil.compareToIgnoreCase(o1.toString(),o2.toString()); } return 0; } }.sort(); notifyLookupChanged(); } /* (non-Javadoc) * @see com.ibm.commons.swt.node.ILookup#size() */ public int size() { return designElements.length; } /* (non-Javadoc) * @see com.ibm.commons.swt.node.ILookup#getCode(int) */ public String getCode(int index) { DesignerDesignElement designElement = getDesignElement( index ); IPath desPath = designElement.getResource().getProjectRelativePath(); if (bStartResultWithSep) return IPath.SEPARATOR + desPath.removeFirstSegments(folderCount).toString(); else return desPath.removeFirstSegments(folderCount).toString(); } /** * @param index * @return */ public DesignerDesignElement getDesignElement(int index) { if ( index < 0 || index >= designElements.length ){ return null; } return designElements[ index ]; } /* (non-Javadoc) * @see com.ibm.commons.swt.node.ILookup#getLabel(int) */ public String getLabel(int index) { DesignerDesignElement designElement = getDesignElement( index ); String name = designElement == null ? "" : designElement.getName(); if(StringUtil.isNotEmpty(name)){ if(!showExtension){ int i = name.lastIndexOf("."); if(i > 0){ return name.substring(0, i); } } } return name; } /** * adds a DisposeListener to the given control to remove workspace listener. * Normally, the workspace listener will be removed when all LookupListeners are removed, * but this gives us another way to insure it is removed. * @param c */ public void setControl(Control c) { c.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { listeners.clear(); removeNotify(); } }); } /** * @todo: revisit the ILookup and LookupListener interface in the API * need to make this easier. */ private DesignerDesignElement[] cachedElements; protected void notifyLookupChanged() { DesignerDesignElement[] elements = getDesignElements(); if(null == cachedElements){ cachedElements = elements; } else { //weird refresh issue here. When you do a save of the xpage with the computed combos, it fires a refresh, which //in turn fires this notifyLookupChanged which causes a selection event in the combo, which causes the value of the //attribute to be set in the source again. So when you save an xpage, it saves, but then dirties itself again immediately //as the attribute is set again. //The workaround is to check for the old design list and new design list - if the elements are the //same then it was not really and update and does not need a refresh if(cachedElements.length == elements.length){ boolean equal = true; try{ int i = 0; for(DesignerDesignElement cachedElement : cachedElements){ if(!(cachedElement.equals(elements[i]))){ equal = false; break; } if(!StringUtil.equals(cachedElement.getName(), elements[i].getName())){ equal = false; break; } if(!StringUtil.equals(cachedElement.getAlias(), elements[i].getAlias())){ equal = false; break; } i++; } } catch(Exception e){ //if there are any errors, do the update as normal. Should never happen, but want to handle any //IndexOutOfBounds exceptions etc.. if they arise. equal = false; } if(equal){ return; } } } notifyLookupChangedInternal(); } public static ExtLibDesignElementLookup getXPagesLookup(DesignerProject project){ return new ExtLibDesignElementLookup(project, DesignerResource.TYPE_XPAGE); } public static ExtLibDesignElementLookup getThemeLookup(DesignerProject project){ return new ExtLibDesignElementLookup(project, DesignerResource.TYPE_THEME); } private ArrayList<LookupListener> listeners; protected void addNotify() { ResourcesPlugin.getWorkspace().addResourceChangeListener(resListener); } protected void removeNotify() { ResourcesPlugin.getWorkspace().removeResourceChangeListener(resListener); } /* * (non-Javadoc) * @see com.ibm.commons.iloader.node.lookups.api.ILookup#addLookupListener(com.ibm.commons.iloader.node.lookups.api.LookupListener) */ public void addLookupListener( LookupListener listener ) { if(listeners==null) { listeners = new ArrayList<LookupListener>(); } listeners.add(listener); if(listeners.size()==1) { addNotify(); } } /* * (non-Javadoc) * @see com.ibm.commons.iloader.node.lookups.api.ILookup#removeLookupListener(com.ibm.commons.iloader.node.lookups.api.LookupListener) */ public void removeLookupListener( LookupListener listener ) { if(listeners!=null) { listeners.remove(listener); if(listeners.size()==0) { removeNotify(); } } } /* * Called when the lookup is changed, to notify listeners in an syncExec. * */ protected void notifyLookupChangedInternal() { if(listeners!=null) { // Ensure that we execute in the SWT thread Display.getDefault().syncExec( new Runnable() { public void run() { int count = listeners.size(); for( int i=0; i<count; i++ ) { LookupListener l = listeners.get(i); l.lookupChanged(ExtLibDesignElementLookup.this); } } }); } } protected int getNavigatorFolderCount() { if (typeId.equals(DesignerResource.TYPE_FRAMESET) || typeId.equals(DesignerResource.TYPE_FORM) || typeId.equals(DesignerResource.TYPE_XPAGE) || typeId.equals(DesignerResource.TYPE_VIEW) || typeId.equals(DesignerResource.TYPE_FOLDER) || typeId.equals(DesignerResource.TYPE_CUSTOMCTRL) || typeId.equals(DesignerResource.TYPE_PAGE)) return 1; else return 2; } }