You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by fe...@apache.org on 2007/11/05 17:48:54 UTC

svn commit: r592079 [11/17] - in /directory/sandbox/felixk/studio-ldapbrowser-common: ./ META-INF/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/directory/ src/main/java/org/apache/directory/studio/...

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserEntryPage.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserEntryPage.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserEntryPage.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserEntryPage.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,209 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import java.util.Arrays;
+
+import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
+
+
+/**
+ * A BrowserEntryPage is a container for entries or other nested browser entry pages.
+ * It is used when folding large branches. 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BrowserEntryPage
+{
+    /** The tree sorter */
+    private BrowserSorter sorter;
+
+    /** The index of the first child entry in this page */ 
+    private int first;
+
+    /** The index of the last child entry in this page */
+    private int last;
+
+    /** The parent entry */
+    private IEntry entry;
+
+    /** The parent entry page or null if not nested */
+    private BrowserEntryPage parentEntryPage;
+
+    /** The sub pages */
+    private BrowserEntryPage[] subpages;
+
+
+    /**
+     * Creates a new instance of BrowserEntryPage.
+     *
+     * @param entry the parent entry
+     * @param first the index of the first child entry in this page
+     * @param last the index of the last child entry in this page
+     * @param subpages the sub pages
+     * @param sorter the sorter
+     */
+    public BrowserEntryPage( IEntry entry, int first, int last, BrowserEntryPage[] subpages, BrowserSorter sorter )
+    {
+        this.entry = entry;
+        this.first = first;
+        this.last = last;
+        this.subpages = subpages;
+        this.sorter = sorter;
+
+        if ( subpages != null )
+        {
+            for ( int i = 0; i < subpages.length; i++ )
+            {
+                subpages[i].parentEntryPage = this;
+            }
+        }
+    }
+
+
+    /**
+     * Gets the children, either the sub pages or 
+     * the entries contained in this page.
+     *
+     * @return the children
+     */
+    public Object[] getChildren()
+    {
+        if ( subpages != null )
+        {
+            return subpages;
+        }
+        else
+        {
+            // 1. get children
+            IEntry[] children = entry.getChildren();
+
+            // 2. sort
+            sorter.sort( null, children );
+
+            // 3. extraxt range
+            if ( children != null )
+            {
+                IEntry[] childrenRange = new IEntry[last - first + 1];
+                for ( int i = first; i <= last; i++ )
+                {
+                    childrenRange[i - first] = children[i];
+                }
+                return childrenRange;
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+
+
+    
+    /**
+     * Gets the first.
+     * 
+     * @return the first
+     */
+    public int getFirst()
+    {
+        return first;
+    }
+
+
+    /**
+     * Gets the last.
+     * 
+     * @return the last
+     */
+    public int getLast()
+    {
+        return last;
+    }
+
+
+    /**
+     * Gets the parent entry.
+     * 
+     * @return the parent entry
+     */
+    public IEntry getEntry()
+    {
+        return entry;
+    }
+
+
+    /**
+     * Gets the parent page if the given entry is contained in this page
+     * or one of the sub pages.
+     * 
+     * @param entry the entry
+     * 
+     * @return the parent page of the given entry.
+     */
+    public BrowserEntryPage getParentOf( IEntry entry )
+    {
+        if ( subpages != null )
+        {
+            BrowserEntryPage ep = null;
+            for ( int i = 0; i < subpages.length && ep == null; i++ )
+            {
+                ep = subpages[i].getParentOf( entry );
+            }
+            return ep;
+        }
+        else
+        {
+            IEntry[] sr = ( IEntry[] ) getChildren();
+            if ( sr != null && Arrays.asList( sr ).contains( entry ) )
+            {
+                return this;
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+
+
+    /**
+     * Gets the direct parent, either a page or the entry.
+     * 
+     * @return the direct parent
+     */
+    public Object getParent()
+    {
+        return ( parentEntryPage != null ) ? ( Object ) parentEntryPage : ( Object ) entry;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString()
+    {
+        return entry.toString() + "[" + first + "..." + last + "]" + hashCode();
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserEntryPage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserLabelProvider.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserLabelProvider.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserLabelProvider.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserLabelProvider.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,516 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import java.util.Iterator;
+
+import org.apache.directory.shared.ldap.name.AttributeTypeAndValue;
+import org.apache.directory.shared.ldap.name.Rdn;
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
+import org.apache.directory.studio.ldapbrowser.core.model.IBookmark;
+import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.IRootDSE;
+import org.apache.directory.studio.ldapbrowser.core.model.ISearch;
+import org.apache.directory.studio.ldapbrowser.core.model.ISearchResult;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.AliasBaseEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.BaseDNEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.DirectoryMetadataEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.ReferralBaseEntry;
+import org.apache.directory.studio.ldapbrowser.core.utils.Utils;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+
+/**
+ * The BrowserLabelProvider implements the label provider for
+ * the browser widget.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BrowserLabelProvider extends LabelProvider implements IFontProvider, IColorProvider
+{
+
+    /** The preferences. */
+    private BrowserPreferences preferences;
+
+
+    /**
+     * Creates a new instance of BrowserLabelProvider.
+     *
+     * @param preferences the preferences
+     */
+    public BrowserLabelProvider( BrowserPreferences preferences )
+    {
+        this.preferences = preferences;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getText( Object obj )
+    {
+        if ( obj instanceof IEntry )
+        {
+            IEntry entry = ( IEntry ) obj;
+
+            StringBuffer append = new StringBuffer();
+            if ( entry instanceof IRootDSE )
+            {
+                append.append( "Root DSE" );
+            }
+            if ( entry.isChildrenInitialized() && ( entry.getChildrenCount() > 0 ) || entry.getChildrenFilter() != null )
+            {
+                append.append( " (" ).append( entry.getChildrenCount() );
+                if ( entry.hasMoreChildren() )
+                {
+                    append.append( "+" );
+                }
+                if ( entry.getChildrenFilter() != null )
+                {
+                    append.append( ", filtered" );
+                }
+                append.append( ")" );
+            }
+
+            if ( entry instanceof ReferralBaseEntry )
+            {
+                return entry.getUrl().toString() + " " + append.toString();
+            }
+            else if ( entry instanceof AliasBaseEntry )
+            {
+                return entry.getDn().getUpName() + " " + append.toString();
+            }
+            else if ( entry instanceof BaseDNEntry )
+            {
+                return entry.getDn().getUpName() + " " + append.toString();
+            }
+            else if ( entry.hasParententry() )
+            {
+
+                String label = "";
+                if ( preferences.getEntryLabel() == BrowserCommonConstants.SHOW_DN )
+                {
+                    label = entry.getDn().getUpName();
+                }
+                else if ( preferences.getEntryLabel() == BrowserCommonConstants.SHOW_RDN )
+                {
+                    label = entry.getRdn().getUpName();
+                }
+                else if ( preferences.getEntryLabel() == BrowserCommonConstants.SHOW_RDN_VALUE )
+                {
+                    label = ( String ) entry.getRdn().getUpValue();
+                }
+
+                label += append.toString();
+
+                if ( preferences.isEntryAbbreviate() && label.length() > preferences.getEntryAbbreviateMaxLength() )
+                {
+                    label = Utils.shorten( label, preferences.getEntryAbbreviateMaxLength() );
+                }
+
+                return label;
+            }
+            else
+            {
+                return entry.getDn().getUpName() + append.toString();
+            }
+        }
+        else if ( obj instanceof BrowserEntryPage )
+        {
+            BrowserEntryPage container = ( BrowserEntryPage ) obj;
+            return "[" + ( container.getFirst() + 1 ) + "..." + ( container.getLast() + 1 ) + "]";
+        }
+        else if ( obj instanceof BrowserSearchResultPage )
+        {
+            BrowserSearchResultPage container = ( BrowserSearchResultPage ) obj;
+            return "[" + ( container.getFirst() + 1 ) + "..." + ( container.getLast() + 1 ) + "]";
+        }
+        else if ( obj instanceof ISearch )
+        {
+            ISearch search = ( ISearch ) obj;
+            ISearchResult[] results = search.getSearchResults();
+            StringBuffer append = new StringBuffer( search.getName() );
+            if ( results != null )
+            {
+                append.append( " (" ).append( results.length );
+                if ( search.isCountLimitExceeded() )
+                {
+                    append.append( "+" );
+                }
+                append.append( ")" );
+            }
+            return append.toString();
+        }
+        else if ( obj instanceof IBookmark )
+        {
+            IBookmark bookmark = ( IBookmark ) obj;
+            return bookmark.getName();
+        }
+        else if ( obj instanceof ISearchResult )
+        {
+            ISearchResult sr = ( ISearchResult ) obj;
+
+            if ( !sr.getSearch().getBrowserConnection().equals( sr.getEntry().getBrowserConnection() ) )
+            {
+                return sr.getEntry().getUrl().toString();
+            }
+            else if ( sr.getEntry().hasParententry() || sr.getEntry() instanceof IRootDSE )
+            {
+                String label = "";
+                if ( sr.getEntry() instanceof IRootDSE )
+                {
+                    label = "Root DSE";
+                }
+                else if ( preferences.getSearchResultLabel() == BrowserCommonConstants.SHOW_DN )
+                {
+                    label = sr.getEntry().getDn().getUpName();
+                }
+                else if ( preferences.getSearchResultLabel() == BrowserCommonConstants.SHOW_RDN )
+                {
+                    label = sr.getEntry().getRdn().getUpName();
+                }
+                else if ( preferences.getSearchResultLabel() == BrowserCommonConstants.SHOW_RDN_VALUE )
+                {
+                    label = ( String ) sr.getEntry().getRdn().getUpValue();
+                }
+
+                if ( preferences.isSearchResultAbbreviate()
+                    && label.length() > preferences.getSearchResultAbbreviateMaxLength() )
+                {
+                    label = Utils.shorten( label, preferences.getSearchResultAbbreviateMaxLength() );
+                }
+
+                return label;
+            }
+            else
+            {
+                return sr.getEntry().getDn().getUpName();
+            }
+
+        }
+        else if ( obj instanceof BrowserCategory )
+        {
+            BrowserCategory category = ( BrowserCategory ) obj;
+            return category.getTitle();
+        }
+        else if ( obj != null )
+        {
+            return obj.toString();
+        }
+        else
+        {
+            return "";
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Image getImage( Object obj )
+    {
+        if ( obj instanceof IEntry )
+        {
+            IEntry entry = ( IEntry ) obj;
+            return getImageByRdn( entry );
+        }
+        else if ( obj instanceof BrowserEntryPage )
+        {
+            return PlatformUI.getWorkbench().getSharedImages().getImage( ISharedImages.IMG_OBJ_FOLDER );
+        }
+        else if ( obj instanceof BrowserSearchResultPage )
+        {
+            return PlatformUI.getWorkbench().getSharedImages().getImage( ISharedImages.IMG_OBJ_FOLDER );
+        }
+        else if ( obj instanceof ISearch )
+        {
+            ISearch search = ( ISearch ) obj;
+            if ( search.getSearchResults() != null )
+            {
+                return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_SEARCH );
+            }
+            else
+            {
+                return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_SEARCH_UNPERFORMED );
+            }
+        }
+        else if ( obj instanceof IBookmark )
+        {
+            return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_BOOKMARK );
+        }
+        else if ( obj instanceof ISearchResult )
+        {
+            ISearchResult sr = ( ISearchResult ) obj;
+            IEntry entry = sr.getEntry();
+            return getImageByRdn( entry );
+        }
+        else if ( obj instanceof BrowserCategory )
+        {
+            BrowserCategory category = ( BrowserCategory ) obj;
+            if ( category.getType() == BrowserCategory.TYPE_DIT )
+            {
+                return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_DIT );
+            }
+            else if ( category.getType() == BrowserCategory.TYPE_SEARCHES )
+            {
+                return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_SEARCHES );
+            }
+            else if ( category.getType() == BrowserCategory.TYPE_BOOKMARKS )
+            {
+                return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_BOOKMARKS );
+            }
+            else
+            {
+                return null;
+            }
+        }
+        else
+        {
+            // return
+            // Activator.getDefault().getImage("icons/sandglass.gif");
+            return null;
+        }
+    }
+
+
+    /**
+     * Gets the image depending on the RDN attribute
+     *
+     * @param entry the entry
+     * @return the image
+     */
+    private Image getImageByRdn( IEntry entry )
+    {
+        if ( entry instanceof IRootDSE )
+        {
+            return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_ENTRY_ROOT );
+        }
+        else if ( entry instanceof DirectoryMetadataEntry && ( ( DirectoryMetadataEntry ) entry ).isSchemaEntry() )
+        {
+            return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_BROWSER_SCHEMABROWSEREDITOR );
+        }
+        else if ( entry.getDn().equals( entry.getBrowserConnection().getSchema().getDn() ) )
+        {
+            return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_BROWSER_SCHEMABROWSEREDITOR );
+        }
+        else if ( preferences.isDerefAliasesAndReferralsWhileBrowsing() && entry.isAlias() )
+        {
+            return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_ENTRY_ALIAS );
+        }
+        else if ( preferences.isDerefAliasesAndReferralsWhileBrowsing() && entry.isReferral() )
+        {
+            return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_ENTRY_REF );
+        }
+        else if ( entry.isSubentry() )
+        {
+            return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_BROWSER_SCHEMABROWSEREDITOR );
+        }
+        else
+        {
+            Rdn rdn = entry.getRdn();
+            Iterator<AttributeTypeAndValue> atavIterator = rdn.iterator();
+            while(atavIterator.hasNext())
+            {
+                AttributeTypeAndValue atav = atavIterator.next();
+                if ( "cn".equals( atav.getUpType() ) || "sn".equals( atav.getUpType() ) || "uid".equals( atav.getUpType() )
+                    || "userid".equals( atav.getUpType() ) )
+                {
+                    return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_ENTRY_PERSON );
+                }
+                else if ( "ou".equals( atav.getUpType() ) || "o".equals( atav.getUpType() ) )
+                {
+                    return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_ENTRY_ORG );
+                }
+                else if ( "dc".equals( atav.getUpType() ) || "c".equals( atav.getUpType() ) || "l".equals( atav.getUpType() ) )
+                {
+                    return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_ENTRY_DC );
+                }
+            }
+        }
+
+        return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_ENTRY );
+    }
+
+
+    // private Image getImageByObjectclass(IEntry entry) {
+    // IAttribute oc = entry.getAttribute(IAttribute.OBJECTCLASS_ATTRIBUTE);
+    // if(oc != null && oc.getStringValues() != null) {
+    // String[] ocValues = oc.getStringValues();
+    // Set ocSet = new HashSet();
+    // for(int i=0; i<ocValues.length; i++) {
+    // ocSet.add(ocValues[i].toUpperCase());
+    // }
+    //			
+    // if(entry instanceof IRootDSE) {
+    // return
+    // Activator.getDefault().getImage(BrowserWidgetsConstants.IMG_ENTRY_ROOT);
+    // }
+    // else
+    // if(entry.getDn().equals(entry.getConnection().getSchema().getDn()))
+    // {
+    // return
+    // Activator.getDefault().getImage(BrowserWidgetsConstants.IMG_BROWSER_SCHEMABROWSEREDITOR);
+    // }
+    // else if(ocSet.contains(ObjectClassDescription.OC_ALIAS.toUpperCase())
+    // || ocSet.contains(ObjectClassDescription.OC_REFERRAL.toUpperCase()))
+    // {
+    // return
+    // Activator.getDefault().getImage(BrowserWidgetsConstants.IMG_ENTRY_REF);
+    // }
+    // else
+    // if(ocSet.contains(ObjectClassDescription.OC_PERSON.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_ORGANIZATIONALPERSON.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_INETORGPERSON.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_RESIDENTIALPERSON.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_PILOTPERSON.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_NEWPILOTPERSON.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_ORGANIZATIONALROLE.toUpperCase())
+    // || ocSet.contains(ObjectClassDescription.OC_ACCOUNT.toUpperCase())) {
+    // return
+    // Activator.getDefault().getImage(BrowserWidgetsConstants.IMG_ENTRY_PERSON);
+    // }
+    // else
+    // if(ocSet.contains(ObjectClassDescription.OC_ORGANIZATION.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_ORGANIZATIONALUNIT.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_PILOTORGANIZATION.toUpperCase())
+    // || ocSet.contains(ObjectClassDescription.OC_DMD.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_APPLICATIONPROCESS.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_APPLICATIONENTITY.toUpperCase()))
+    // {
+    // return
+    // Activator.getDefault().getImage(BrowserWidgetsConstants.IMG_ENTRY_ORG);
+    // }
+    // else
+    // if(ocSet.contains(ObjectClassDescription.OC_COUNTRY.toUpperCase())
+    // || ocSet.contains(ObjectClassDescription.OC_LOCALITY.toUpperCase())
+    // || ocSet.contains(ObjectClassDescription.OC_DCOBJECT.toUpperCase())
+    // || ocSet.contains(ObjectClassDescription.OC_DOMAIN.toUpperCase())) {
+    // return
+    // Activator.getDefault().getImage(BrowserWidgetsConstants.IMG_ENTRY_DC);
+    // }
+    // else
+    // if(ocSet.contains(ObjectClassDescription.OC_GROUPOFNAMES.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_GROUPOFUNIQUENAMES.toUpperCase())
+    // ||
+    // ocSet.contains(ObjectClassDescription.OC_POSIXGROUP.toUpperCase())) {
+    // return
+    // Activator.getDefault().getImage(BrowserWidgetsConstants.IMG_ENTRY_GROUP);
+    // }
+    //			
+    // }
+    //		
+    // return
+    // Activator.getDefault().getImage(BrowserWidgetsConstants.IMG_ENTRY);
+    // }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Font getFont( Object element )
+    {
+
+        IEntry entry = null;
+        if ( element instanceof IEntry )
+        {
+            entry = ( IEntry ) element;
+        }
+        else if ( element instanceof ISearchResult )
+        {
+            entry = ( ( ISearchResult ) element ).getEntry();
+        }
+
+        if ( entry != null )
+        {
+            if ( !entry.isConsistent() )
+            {
+                FontData[] fontData = PreferenceConverter.getFontDataArray( BrowserCommonActivator.getDefault()
+                    .getPreferenceStore(), BrowserCommonConstants.PREFERENCE_ERROR_FONT );
+                return BrowserCommonActivator.getDefault().getFont( fontData );
+            }
+        }
+
+        return null;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Color getForeground( Object element )
+    {
+
+        IEntry entry = null;
+        if ( element instanceof IEntry )
+        {
+            entry = ( IEntry ) element;
+        }
+        else if ( element instanceof ISearchResult )
+        {
+            entry = ( ( ISearchResult ) element ).getEntry();
+        }
+
+        if ( entry != null )
+        {
+            if ( !entry.isConsistent() )
+            {
+                RGB rgb = PreferenceConverter.getColor( BrowserCommonActivator.getDefault().getPreferenceStore(),
+                    BrowserCommonConstants.PREFERENCE_ERROR_COLOR );
+                return BrowserCommonActivator.getDefault().getColor( rgb );
+            }
+        }
+
+        return null;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Color getBackground( Object element )
+    {
+        return null;
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserLabelProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserPreferences.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserPreferences.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserPreferences.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserPreferences.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,361 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreConstants;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+
+
+/**
+ * This class is a wrapper for the preferences of the browser widget.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BrowserPreferences implements IPropertyChangeListener, Preferences.IPropertyChangeListener
+{
+
+    /** The tree viewer */
+    protected TreeViewer viewer;
+
+
+    /**
+     * Creates a new instance of BrowserPreferences.
+     */
+    public BrowserPreferences()
+    {
+        BrowserCommonActivator.getDefault().getPreferenceStore().addPropertyChangeListener( this );
+        BrowserCorePlugin.getDefault().getPluginPreferences().addPropertyChangeListener( this );
+    }
+
+
+    /**
+     * Connects the tree viewer to this preferences.
+     *
+     * @param viewer the tree viewer
+     */
+    public void connect( TreeViewer viewer )
+    {
+        this.viewer = viewer;
+    }
+
+
+    /**
+     * Disposes this preferences.
+     */
+    public void dispose()
+    {
+        BrowserCommonActivator.getDefault().getPreferenceStore().removePropertyChangeListener( this );
+        BrowserCorePlugin.getDefault().getPluginPreferences().removePropertyChangeListener( this );
+        viewer = null;
+    }
+
+
+    /**
+     * Gets the sort by, one of BrowserCoreConstants.SORT_BY_NONE, 
+     * BrowserCoreConstants.SORT_BY_RDN or BrowserCoreConstants.SORT_BY_RDN_VALUE.
+     * 
+     * @return the sort by
+     */
+    public int getSortBy()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getInt( BrowserCommonConstants.PREFERENCE_BROWSER_SORT_BY );
+    }
+
+
+    /**
+     * Gets the sort order, one of one of BrowserCoreConstants.SORT_ORDER_NONE, 
+     * BrowserCoreConstants.SORT_ORDER_ASCENDING or BrowserCoreConstants.SORT_ORDER_DESCENDING.
+     * 
+     * @return the sort order
+     */
+    public int getSortOrder()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getInt(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SORT_ORDER );
+    }
+
+
+    /**
+     * Gets the sort limit.
+     * 
+     * @return the sort limit
+     */
+    public int getSortLimit()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getInt(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SORT_LIMIT );
+    }
+
+
+    /**
+     * Returns true if leaf entries should be shown before non-leaf entries.
+     * 
+     * @return true, if leaf entries should be shown first
+     */
+    public boolean isLeafEntriesFirst()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_LEAF_ENTRIES_FIRST );
+    }
+
+
+    /**
+     * Returns true if meta entries should be shown after non-meta entries.
+     * 
+     * @return true, if meta entries should be shown first
+     */
+    public boolean isMetaEntriesLast()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_META_ENTRIES_LAST );
+    }
+
+
+    /**
+     * Returns true if the bookmark category should be visible.
+     *
+     * @return true if the bookmark category should be visible
+     */
+    public boolean isShowBookmarks()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SHOW_BOOKMARKS );
+    }
+
+
+    /**
+     * Returns true if the DIT category should be visible.
+     *
+     * @return true if the DIT category should be visible
+     */
+    public boolean isShowDIT()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SHOW_DIT );
+    }
+
+
+    /**
+     * Returns true if the searches category should be visible.
+     *
+     * @return true if the searches category should be visible
+     */
+    public boolean isShowSearches()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SHOW_SEARCHES );
+    }
+
+
+    /**
+     * Gets the folding size.
+     * 
+     * @return the folding size
+     */
+    public int getFoldingSize()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getInt(
+            BrowserCommonConstants.PREFERENCE_BROWSER_FOLDING_SIZE );
+    }
+
+
+    /**
+     * Returns true if folding is enabled.
+     *
+     * @return true if folding is enabled
+     */
+    public boolean isUseFolding()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_ENABLE_FOLDING );
+    }
+
+
+    /**
+     * Returns true if meta entries should be visible.
+     *
+     * @return true if meta entries should be visible
+     */
+    public boolean isShowDirectoryMetaEntries()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SHOW_DIRECTORY_META_ENTRIES );
+    }
+
+
+    /**
+     * Returns true if entry lables should be abbreviated.
+     *
+     * @return true if entry lables should be abbreviated
+     */
+    public boolean isEntryAbbreviate()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_ENTRY_ABBREVIATE );
+    }
+
+
+    /**
+     * Gets the entry's maximum label length.
+     * 
+     * @return the entry's maximum label length
+     */
+    public int getEntryAbbreviateMaxLength()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getInt(
+            BrowserCommonConstants.PREFERENCE_BROWSER_ENTRY_ABBREVIATE_MAX_LENGTH );
+    }
+
+
+    /**
+     * Gets the entry label, one of BrowserWidgetsConstants.SHOW_DN, 
+     * BrowserWidgetsConstants.SHOW_RDN or BrowserWidgetsConstants.SHOW_RDN_VALUE.
+     * 
+     * @return the entry label
+     */
+    public int getEntryLabel()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getInt(
+            BrowserCommonConstants.PREFERENCE_BROWSER_ENTRY_LABEL );
+    }
+
+
+    /**
+     * Returns true if search result lables should be abbreviated.
+     *
+     * @return true if search result lables should be abbreviated
+     */
+    public boolean isSearchResultAbbreviate()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SEARCH_RESULT_ABBREVIATE );
+    }
+
+
+    /**
+     * Gets the search result's maximum label length.
+     * 
+     * @return the search result's maximum label length
+     */
+    public int getSearchResultAbbreviateMaxLength()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getInt(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SEARCH_RESULT_ABBREVIATE_MAX_LENGTH );
+    }
+
+
+    /**
+     * Gets the search result label, one of BrowserWidgetsConstants.SHOW_DN, 
+     * BrowserWidgetsConstants.SHOW_RDN or BrowserWidgetsConstants.SHOW_RDN_VALUE.
+     * 
+     * @return the entry label
+     */
+    public int getSearchResultLabel()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getInt(
+            BrowserCommonConstants.PREFERENCE_BROWSER_SEARCH_RESULT_LABEL );
+    }
+
+
+    /**
+     * Returns true if the base entries should be expanded when
+     * opening connection.
+     *
+     * @return true if the base entries should be expanded
+     */
+    public boolean isExpandBaseEntries()
+    {
+        return BrowserCommonActivator.getDefault().getPreferenceStore().getBoolean(
+            BrowserCommonConstants.PREFERENCE_BROWSER_EXPAND_BASE_ENTRIES );
+    }
+
+
+    /**
+     * Returns true if the browser should check for children
+     * while browsing the directory.
+     *
+     * @return true if the browser should check for children
+     */
+    public boolean isCheckForChildren()
+    {
+        Preferences coreStore = BrowserCorePlugin.getDefault().getPluginPreferences();
+        return coreStore.getBoolean( BrowserCoreConstants.PREFERENCE_CHECK_FOR_CHILDREN );
+    }
+
+
+    /**
+     * Returns true if the browser should dereference aliases and referrals.
+     * 
+     *
+     * @return true if the browser should dereference aliases and referrals
+     */
+    public boolean isDerefAliasesAndReferralsWhileBrowsing()
+    {
+        Preferences coreStore = BrowserCorePlugin.getDefault().getPluginPreferences();
+        return coreStore.getBoolean( BrowserCoreConstants.PREFERENCE_SHOW_ALIAS_AND_REFERRAL_OBJECTS );
+    }
+
+
+    /**
+     * Returns true if subentries should be fetched while browsing.
+     * 
+     *
+     * @return true if subentries should be fetched while browsing
+     */
+    public boolean isFetchSubentries()
+    {
+        Preferences coreStore = BrowserCorePlugin.getDefault().getPluginPreferences();
+        return coreStore.getBoolean( BrowserCoreConstants.PREFERENCE_FETCH_SUBENTRIES );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void propertyChange( PropertyChangeEvent event )
+    {
+        if ( viewer != null )
+        {
+            viewer.refresh();
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void propertyChange( org.eclipse.core.runtime.Preferences.PropertyChangeEvent event )
+    {
+        if ( viewer != null )
+        {
+            viewer.refresh();
+        }
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserPreferences.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSearchResultPage.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSearchResultPage.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSearchResultPage.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSearchResultPage.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,211 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import java.util.Arrays;
+
+import org.apache.directory.studio.ldapbrowser.core.model.ISearch;
+import org.apache.directory.studio.ldapbrowser.core.model.ISearchResult;
+
+
+/**
+ * A BrowserSearchResultPage is a container for search results or other nested browser search result pages.
+ * It is used when folding searches with many results. 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BrowserSearchResultPage
+{
+
+    /** The tree sorter */
+    private BrowserSorter sorter;
+
+    /** The index of the first child search result in this page */
+    private int first;
+
+    /** The index of the last child search result in this page */
+    private int last;
+
+    /** The parent search */
+    private ISearch search;
+
+    /** The parent search result page or null if not nested */
+    private BrowserSearchResultPage parentSearchResultPage;
+
+    /** The sub pages */
+    private BrowserSearchResultPage[] subpages;
+
+
+    /**
+     * Creates a new instance of BrowserSearchResultPage.
+     *
+     * @param search the parent search
+     * @param first the index of the first child search result in this page
+     * @param last the index of the last child search result in this page
+     * @param subpages the sub pages
+     * @param sorter the sorter
+     */
+    public BrowserSearchResultPage( ISearch search, int first, int last, BrowserSearchResultPage[] subpages,
+        BrowserSorter sorter )
+    {
+        this.search = search;
+        this.first = first;
+        this.last = last;
+        this.subpages = subpages;
+        this.sorter = sorter;
+
+        if ( subpages != null )
+        {
+            for ( int i = 0; i < subpages.length; i++ )
+            {
+                subpages[i].parentSearchResultPage = this;
+            }
+        }
+    }
+
+
+    /**
+     * Gets the children, either the sub pages or 
+     * the search results contained in this page.
+     *
+     * @return the children
+     */
+    public Object[] getChildren()
+    {
+        if ( subpages != null )
+        {
+            return subpages;
+        }
+        else
+        {
+            // 1. get children
+            ISearchResult[] children = search.getSearchResults();
+
+            // 2. sort
+            sorter.sort( null, children );
+
+            // 3. extraxt range
+            if ( children != null )
+            {
+                ISearchResult[] childrenRange = new ISearchResult[last - first + 1];
+                for ( int i = first; i <= last; i++ )
+                {
+                    childrenRange[i - first] = children[i];
+                }
+                return childrenRange;
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+
+
+    /**
+     * Gets the first.
+     * 
+     * @return the first
+     */
+    public int getFirst()
+    {
+        return first;
+    }
+
+
+    /**
+     * Gets the last.
+     * 
+     * @return the last
+     */
+    public int getLast()
+    {
+        return last;
+    }
+
+
+    /**
+     * Gets the search.
+     * 
+     * @return the search
+     */
+    public ISearch getSearch()
+    {
+        return search;
+    }
+
+
+    /**
+     * Gets the parent page if the given search result is contained in this page
+     * or one of the sub pages.
+     * 
+     * @param searchResult the search result
+     * 
+     * @return the parent page of the given search result.
+     */
+    public BrowserSearchResultPage getParentOf( ISearchResult searchResult )
+    {
+        if ( subpages != null )
+        {
+            BrowserSearchResultPage ep = null;
+            for ( int i = 0; i < subpages.length && ep == null; i++ )
+            {
+                ep = subpages[i].getParentOf( searchResult );
+            }
+            return ep;
+        }
+        else
+        {
+            ISearchResult[] sr = ( ISearchResult[] ) getChildren();
+            if ( sr != null && Arrays.asList( sr ).contains( searchResult ) )
+            {
+                return this;
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+
+
+    /**
+     * Gets the direct parent, either a page or the search.
+     * 
+     * @return the direct parent
+     */
+    public Object getParent()
+    {
+        return ( parentSearchResultPage != null ) ? ( Object ) parentSearchResultPage : ( Object ) search;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString()
+    {
+        return search.toString() + "[" + first + "..." + last + "]" + hashCode();
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSearchResultPage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorter.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorter.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorter.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorter.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,405 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import java.math.BigInteger;
+
+import org.apache.directory.shared.ldap.name.Rdn;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreConstants;
+import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.ISearchResult;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.DirectoryMetadataEntry;
+import org.apache.directory.studio.ldapbrowser.core.model.impl.RootDSE;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+
+
+/**
+ * The BrowserSorter implements the sorter for the browser widget. 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BrowserSorter extends ViewerSorter
+{
+
+    /** The browser preferences, used to get the sort settings */
+    private BrowserPreferences preferences;
+
+
+    /**
+     * Creates a new instance of BrowserSorter.
+     *
+     * @param preferences the browser preferences, used to get the sort settings
+     */
+    public BrowserSorter( BrowserPreferences preferences )
+    {
+        this.preferences = preferences;
+    }
+
+
+    /**
+     * Connects the tree viewer to this sorter.
+     *
+     * @param viewer the tree viewer
+     */
+    public void connect( TreeViewer viewer )
+    {
+        viewer.setSorter( this );
+    }
+
+
+    /**
+     * Disposes this sorter.
+     */
+    public void dispose()
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * For performance reasons this implemention first checks if sorting is enabled 
+     * and if the number of elements is less than the sort limit.
+     */
+    public void sort( final Viewer viewer, final Object[] elements )
+    {
+        if ( elements != null && ( preferences.getSortLimit() <= 0 || elements.length < preferences.getSortLimit() )
+            && ( preferences.getSortBy() != BrowserCoreConstants.SORT_BY_NONE || preferences.isLeafEntriesFirst() ) )
+        {
+            BrowserSorter.super.sort( viewer, elements );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * This method is used to categorize leaf entries, meta entries and normal entries.
+     */
+    public int category( Object element )
+    {
+        if ( preferences.isLeafEntriesFirst() || preferences.isMetaEntriesLast() )
+        {
+            if ( element instanceof IEntry )
+            {
+                IEntry entry = ( IEntry ) element;
+                if ( ( entry instanceof DirectoryMetadataEntry || entry instanceof RootDSE || entry.isAlias() || entry
+                    .isReferral() )
+                    && preferences.isMetaEntriesLast() )
+                {
+                    return 3;
+                }
+                else if ( entry.isSubentry() && preferences.isLeafEntriesFirst() )
+                {
+                    return 0;
+                }
+                else if ( !entry.hasChildren() && preferences.isLeafEntriesFirst() )
+                {
+                    return 1;
+                }
+                else
+                {
+                    return 2;
+                }
+            }
+            else
+            {
+                return 4;
+            }
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * This implementation compares IEntry or ISearchResult objects. Depending on
+     * the sort settings it delegates comparation to {@link #compareRdns(IEntry, IEntry)}
+     * or {@link #compareRdnValues(IEntry, IEntry)}.
+     */
+    public int compare( Viewer viewer, Object o1, Object o2 )
+    {
+        if ( o1 == null && o2 == null )
+        {
+            return equal();
+        }
+        else if ( o1 == null && o2 != null )
+        {
+            return lessThan();
+        }
+        else if ( o1 != null && o2 == null )
+        {
+            return greaterThan();
+        }
+        else if ( o1 instanceof IEntry || o2 instanceof IEntry )
+        {
+            if ( !( o1 instanceof IEntry ) && !( o2 instanceof IEntry ) )
+            {
+                return equal();
+            }
+            else if ( !( o1 instanceof IEntry ) && ( o2 instanceof IEntry ) )
+            {
+                return lessThan();
+            }
+            else if ( ( o1 instanceof IEntry ) && !( o2 instanceof IEntry ) )
+            {
+                return greaterThan();
+            }
+            else
+            {
+                IEntry entry1 = ( IEntry ) o1;
+                IEntry entry2 = ( IEntry ) o2;
+
+                int cat1 = category( entry1 );
+                int cat2 = category( entry2 );
+                if ( cat1 != cat2 )
+                {
+                    return cat1 - cat2;
+                }
+                else if ( preferences.getSortBy() == BrowserCoreConstants.SORT_BY_NONE )
+                {
+                    return equal();
+                }
+                else if ( preferences.getSortBy() == BrowserCoreConstants.SORT_BY_RDN )
+                {
+                    return compareRdns( entry1, entry2 );
+                }
+                else if ( preferences.getSortBy() == BrowserCoreConstants.SORT_BY_RDN_VALUE )
+                {
+                    return compareRdnValues( entry1, entry2 );
+                }
+                else
+                {
+                    return equal();
+                }
+            }
+        }
+        else if ( o1 instanceof ISearchResult || o2 instanceof ISearchResult )
+        {
+            if ( !( o1 instanceof ISearchResult ) && !( o2 instanceof ISearchResult ) )
+            {
+                return equal();
+            }
+            else if ( !( o1 instanceof ISearchResult ) && ( o2 instanceof ISearchResult ) )
+            {
+                return lessThan();
+            }
+            else if ( ( o1 instanceof ISearchResult ) && !( o2 instanceof ISearchResult ) )
+            {
+                return greaterThan();
+            }
+            else
+            {
+                ISearchResult sr1 = ( ISearchResult ) o1;
+                ISearchResult sr2 = ( ISearchResult ) o2;
+
+                int cat1 = category( sr1 );
+                int cat2 = category( sr2 );
+                if ( cat1 != cat2 )
+                {
+                    return cat1 - cat2;
+                }
+                else if ( preferences.getSortBy() == BrowserCoreConstants.SORT_BY_NONE )
+                {
+                    return equal();
+                }
+                else if ( preferences.getSortBy() == BrowserCoreConstants.SORT_BY_RDN )
+                {
+                    return compareRdns( sr1.getEntry(), sr2.getEntry() );
+                }
+                else if ( preferences.getSortBy() == BrowserCoreConstants.SORT_BY_RDN_VALUE )
+                {
+                    return compareRdnValues( sr1.getEntry(), sr2.getEntry() );
+                }
+                else
+                {
+                    return equal();
+                }
+            }
+        }
+        else
+        {
+            return equal();
+        }
+    }
+
+
+    /**
+     * Compares the string representation of the RDNs of two IEntry objects.
+     *  
+     * @param entry1 the first entry
+     * @param entry2 the second entry
+     * @return a negative integer, zero, or a positive integer
+     */
+    private int compareRdns( IEntry entry1, IEntry entry2 )
+    {
+        Rdn rdn1 = entry1.getRdn();
+        Rdn rdn2 = entry2.getRdn();
+
+        if ( rdn1 == null && rdn2 == null )
+        {
+            return equal();
+        }
+        else if ( rdn1 == null && rdn2 != null )
+        {
+            return greaterThan();
+        }
+        else if ( rdn1 != null && rdn2 == null )
+        {
+            return lessThan();
+        }
+        else
+        {
+            return compare( rdn1.getUpName(), rdn2.getUpName() );
+        }
+    }
+
+
+    /**
+     * Compares the RDN values of two IEntry objects.
+     * Numeric values are compared as numeric.
+     *  
+     * @param entry1 the first entry
+     * @param entry2 the second entry
+     * @return a negative integer, zero, or a positive integer
+     */
+    private int compareRdnValues( IEntry entry1, IEntry entry2 )
+    {
+        Rdn rdn1 = entry1.getRdn();
+        Rdn rdn2 = entry2.getRdn();
+
+        if ( ( rdn1 == null || rdn1.getValue() == null || "".equals( rdn1.getValue() ) )
+            && ( rdn2 == null || rdn2.getValue() == null || "".equals( rdn2.getValue() ) ) )
+        {
+            return equal();
+        }
+        else if ( ( rdn1 == null || rdn1.getValue() == null || "".equals( rdn1.getValue() ) )
+            && !( rdn2 == null || rdn2.getValue() == null || "".equals( rdn2.getValue() ) ) )
+        {
+            return greaterThan();
+        }
+        else if ( !( rdn1 == null || rdn1.getValue() == null || "".equals( rdn1.getValue() ) )
+            && ( rdn2 == null || rdn2.getValue() == null || "".equals( rdn2.getValue() ) ) )
+        {
+            return lessThan();
+        }
+
+        String rdn1Value = ( String ) rdn1.getUpValue();
+        String rdn2Value = ( String ) rdn2.getUpValue();
+        if ( rdn1Value.matches( "\\d*" ) && !rdn2Value.matches( "\\d*" ) )
+        {
+            // return lessThan();
+            return compare( rdn1Value, rdn2Value );
+        }
+        else if ( !rdn1Value.matches( "\\d*" ) && rdn2Value.matches( "\\d*" ) )
+        {
+            // return greaterThan();
+            return compare( rdn1Value, rdn2Value );
+        }
+        else if ( rdn2Value.matches( "\\d*" ) && rdn2Value.matches( "\\d*" ) )
+        {
+            BigInteger bi1 = new BigInteger( rdn1Value );
+            BigInteger bi2 = new BigInteger( rdn2Value );
+            return compare( bi1, bi2 );
+            // return Integer.parseInt(rdn1.getValue()) -
+            // Integer.parseInt(rdn2.getValue());
+        }
+        else
+        {
+            return compare( rdn1Value, rdn2Value );
+        }
+    }
+
+
+    /**
+     * Returns +1 or -1, depending on the sort order.
+     *
+     * @return +1 or -1, depending on the sort order
+     */
+    private int lessThan()
+    {
+        return preferences.getSortOrder() == BrowserCoreConstants.SORT_ORDER_ASCENDING ? -1 : 1;
+    }
+
+
+    /**
+     * Returns 0.
+     *
+     * @return 0
+     */
+    private int equal()
+    {
+        return 0;
+    }
+
+
+    /**
+     * Returns +1 or -1, depending on the sort order.
+     *
+     * @return +1 or -1, depending on the sort order
+     */
+    private int greaterThan()
+    {
+        return preferences.getSortOrder() == BrowserCoreConstants.SORT_ORDER_ASCENDING ? 1 : -1;
+    }
+
+
+    /**
+     * Compares the two strings using the Strings's compareToIgnoreCase method, 
+     * pays attention for the sort order.
+     *
+     * @param s1 the first string to compare
+     * @param s2 the second string to compare
+     * @return a negative integer, zero, or a positive integer
+     * @see java.lang.String#compareToIgnoreCase(String)
+     */
+    private int compare( String s1, String s2 )
+    {
+        return preferences.getSortOrder() == BrowserCoreConstants.SORT_ORDER_ASCENDING ? s1.compareToIgnoreCase( s2 )
+            : s2.compareToIgnoreCase( s1 );
+    }
+
+
+    /**
+     * Compares the two numbers using the BigInteger compareTo method, 
+     * pays attention for the sort order.
+     *
+     * @param bi1 the first number to compare
+     * @param bi1 the second number to compare
+     * @return -1, 0 or 1 as this BigInteger is numerically less than, equal
+     *         to, or greater than
+     * @see java.math.BigInteger#compareTo(BigInteger)
+     */
+    private int compare( BigInteger bi1, BigInteger bi2 )
+    {
+        return preferences.getSortOrder() == BrowserCoreConstants.SORT_ORDER_ASCENDING ? bi1.compareTo( bi2 ) : bi2
+            .compareTo( bi1 );
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorterDialog.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorterDialog.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorterDialog.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorterDialog.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,225 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
+import org.apache.directory.studio.ldapbrowser.common.widgets.BaseWidgetUtils;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreConstants;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+/**
+ * This class represents the dialog used to change the browser's sort settings.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BrowserSorterDialog extends Dialog
+{
+
+    /** The dialog title. */
+    public static final String DIALOG_TITLE = "Browser Sorting";
+
+    /** The Constant SORT_BY_NONE. */
+    public static final String SORT_BY_NONE = "No Sorting";
+
+    /** The Constant SORT_BY_RDN. */
+    public static final String SORT_BY_RDN = "RDN";
+
+    /** The Constant SORT_BY_RDN_VALUE. */
+    public static final String SORT_BY_RDN_VALUE = "RDN Value";
+
+    /** The browser preferences. */
+    private BrowserPreferences preferences;
+
+    /** The sort by combo. */
+    private Combo sortByCombo;
+
+    /** The sort acending button. */
+    private Button sortAcendingButton;
+
+    /** The sort descending button. */
+    private Button sortDescendingButton;
+
+    /** The leaf entries first button. */
+    private Button leafEntriesFirstButton;
+
+    /** The meta entries last button. */
+    private Button metaEntriesLastButton;
+
+    /** The sort limit text. */
+    private Text sortLimitText;
+
+
+    /**
+     * Creates a new instance of BrowserSorterDialog.
+     *
+     * @param parentShell the parent shell
+     * @param preferences the browser preferences
+     */
+    public BrowserSorterDialog( Shell parentShell, BrowserPreferences preferences )
+    {
+        super( parentShell );
+        this.preferences = preferences;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * This implementation calls its super implementation and sets the dialog title.
+     */
+    protected void configureShell( Shell newShell )
+    {
+        super.configureShell( newShell );
+        newShell.setText( DIALOG_TITLE );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * This implementation save the changed settings when OK is pressed.
+     */
+    protected void buttonPressed( int buttonId )
+    {
+        if ( buttonId == IDialogConstants.OK_ID )
+        {
+            int sortLimit = preferences.getSortLimit();
+            try
+            {
+                sortLimit = Integer.parseInt( sortLimitText.getText().trim() );
+            }
+            catch ( NumberFormatException nfe )
+            {
+            }
+
+            IPreferenceStore store = BrowserCommonActivator.getDefault().getPreferenceStore();
+            store.setValue( BrowserCommonConstants.PREFERENCE_BROWSER_LEAF_ENTRIES_FIRST, leafEntriesFirstButton
+                .getSelection() );
+            store.setValue( BrowserCommonConstants.PREFERENCE_BROWSER_META_ENTRIES_LAST, metaEntriesLastButton
+                .getSelection() );
+            store.setValue( BrowserCommonConstants.PREFERENCE_BROWSER_SORT_LIMIT, sortLimit );
+            store.setValue( BrowserCommonConstants.PREFERENCE_BROWSER_SORT_ORDER,
+                sortDescendingButton.getSelection() ? BrowserCoreConstants.SORT_ORDER_DESCENDING
+                    : BrowserCoreConstants.SORT_ORDER_ASCENDING );
+            store.setValue( BrowserCommonConstants.PREFERENCE_BROWSER_SORT_BY,
+                sortByCombo.getSelectionIndex() == 2 ? BrowserCoreConstants.SORT_BY_RDN_VALUE : sortByCombo
+                    .getSelectionIndex() == 1 ? BrowserCoreConstants.SORT_BY_RDN : BrowserCoreConstants.SORT_BY_NONE );
+        }
+        else
+        {
+            // no changes
+        }
+
+        super.buttonPressed( buttonId );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    protected Control createDialogArea( Composite parent )
+    {
+
+        Composite composite = ( Composite ) super.createDialogArea( parent );
+        GridData gd = new GridData( GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL );
+        gd.widthHint = convertHorizontalDLUsToPixels( IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH );
+        composite.setLayoutData( gd );
+
+        Group groupingGroup = BaseWidgetUtils.createGroup( composite, "Group entries", 1 );
+
+        leafEntriesFirstButton = BaseWidgetUtils.createCheckbox( groupingGroup, "Leaf enties first", 1 );
+        leafEntriesFirstButton
+            .setToolTipText( "This option displays entries without children before entries with children." );
+        leafEntriesFirstButton.setSelection( preferences.isLeafEntriesFirst() );
+
+        metaEntriesLastButton = BaseWidgetUtils.createCheckbox( groupingGroup, "Meta entries last", 1 );
+        metaEntriesLastButton
+            .setToolTipText( "This option displays meta entries after normal entries. Meta entries are e.g. the root DSE or the schema entry." );
+        metaEntriesLastButton.setSelection( preferences.isMetaEntriesLast() );
+
+        Group sortingGroup = BaseWidgetUtils.createGroup( composite, "Sort entries", 1 );
+
+        Composite sortByComposite = BaseWidgetUtils.createColumnContainer( sortingGroup, 4, 1 );
+        BaseWidgetUtils.createLabel( sortByComposite, "Sort by", 1 );
+        sortByCombo = BaseWidgetUtils.createReadonlyCombo( sortByComposite, new String[]
+            { SORT_BY_NONE, SORT_BY_RDN, SORT_BY_RDN_VALUE }, 0, 1 );
+        sortByCombo.select( preferences.getSortBy() == BrowserCoreConstants.SORT_BY_RDN_VALUE ? 2 : preferences
+            .getSortBy() == BrowserCoreConstants.SORT_BY_RDN ? 1 : 0 );
+        sortByCombo.addSelectionListener( new SelectionAdapter()
+        {
+            public void widgetSelected( SelectionEvent e )
+            {
+                sortAcendingButton.setEnabled( sortByCombo.getSelectionIndex() != 0 );
+                sortDescendingButton.setEnabled( sortByCombo.getSelectionIndex() != 0 );
+                sortLimitText.setEnabled( sortByCombo.getSelectionIndex() != 0 );
+            }
+        } );
+
+        sortAcendingButton = BaseWidgetUtils.createRadiobutton( sortByComposite, "Ascending", 1 );
+        sortAcendingButton.setSelection( preferences.getSortOrder() == BrowserCoreConstants.SORT_ORDER_ASCENDING );
+        sortAcendingButton.setEnabled( sortByCombo.getSelectionIndex() != 0 );
+
+        sortDescendingButton = BaseWidgetUtils.createRadiobutton( sortByComposite, "Descending", 1 );
+        sortDescendingButton.setSelection( preferences.getSortOrder() == BrowserCoreConstants.SORT_ORDER_DESCENDING );
+        sortDescendingButton.setEnabled( sortByCombo.getSelectionIndex() != 0 );
+
+        Composite sortLimitComposite = BaseWidgetUtils.createColumnContainer( sortingGroup, 2, 1 );
+        String sortLimitTooltip = "If there are more than the specified number of children they won't be sorted. Hint: For performance reason the maximum value should be 10.000!";
+        Label sortLimitLabel = BaseWidgetUtils.createLabel( sortLimitComposite, "Sort limit:", 1 );
+        sortLimitLabel.setToolTipText( sortLimitTooltip );
+        sortLimitText = BaseWidgetUtils.createText( sortLimitComposite, "" + preferences.getSortLimit(), 5, 1 );
+        sortLimitText.setToolTipText( sortLimitTooltip );
+        sortLimitText.setEnabled( sortByCombo.getSelectionIndex() != 0 );
+        sortLimitText.addVerifyListener( new VerifyListener()
+        {
+            public void verifyText( VerifyEvent e )
+            {
+                if ( !e.text.matches( "[0-9]*" ) )
+                {
+                    e.doit = false;
+                }
+            }
+        } );
+
+        applyDialogFont( composite );
+        return composite;
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserSorterDialog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,228 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import org.apache.directory.studio.connection.core.Connection;
+import org.apache.directory.studio.connection.core.ConnectionFolder;
+import org.apache.directory.studio.connection.core.event.ConnectionEventRegistry;
+import org.apache.directory.studio.connection.core.event.ConnectionUpdateListener;
+import org.apache.directory.studio.connection.ui.ConnectionUIPlugin;
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
+import org.apache.directory.studio.ldapbrowser.core.events.AttributesInitializedEvent;
+import org.apache.directory.studio.ldapbrowser.core.events.EntryModificationEvent;
+import org.apache.directory.studio.ldapbrowser.core.events.EntryUpdateListener;
+import org.apache.directory.studio.ldapbrowser.core.events.EventRegistry;
+import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ITreeViewerListener;
+import org.eclipse.jface.viewers.TreeExpansionEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+
+
+/**
+ * The BrowserUniversalListener manages all events for the browser widget.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BrowserUniversalListener implements ConnectionUpdateListener, EntryUpdateListener
+{
+
+    /** The tree viewer */
+    protected TreeViewer viewer;
+
+    /** The tree viewer listener */
+    private ITreeViewerListener treeViewerListener = new ITreeViewerListener()
+    {
+        /**
+         * {@inheritDoc}
+         *
+         * This implementation checks if the collapsed entry more children
+         * than currently fetched. If this is the case cached children are
+         * cleared an must be fetched newly when expanding the tree.
+         *
+         * This could happen when first using a search that returns
+         * only some of an entry's children.
+         */
+        public void treeCollapsed( TreeExpansionEvent event )
+        {
+            if ( event.getElement() instanceof IEntry )
+            {
+                IEntry entry = ( IEntry ) event.getElement();
+                if ( entry.isChildrenInitialized() && entry.hasMoreChildren()
+                    && entry.getChildrenCount() < entry.getBrowserConnection().getCountLimit() )
+                {
+                    entry.setChildrenInitialized( false );
+                }
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        public void treeExpanded( TreeExpansionEvent event )
+        {
+        }
+    };
+
+    /** The double click listener. */
+    private IDoubleClickListener doubleClickListener = new IDoubleClickListener()
+    {
+
+        public void doubleClick( DoubleClickEvent event )
+        {
+            if ( event.getSelection() instanceof IStructuredSelection )
+            {
+                Object obj = ( ( IStructuredSelection ) event.getSelection() ).getFirstElement();
+                if ( viewer.getExpandedState( obj ) )
+                {
+                    viewer.collapseToLevel( obj, 1 );
+                }
+                else if ( ( ( ITreeContentProvider ) viewer.getContentProvider() ).hasChildren( obj ) )
+                {
+                    viewer.expandToLevel( obj, 1 );
+                }
+            }
+        }
+
+    };
+
+
+    /**
+     * Creates a new instance of BrowserUniversalListener.
+     *
+     * @param viewer the tree viewer
+     */
+    public BrowserUniversalListener( TreeViewer viewer )
+    {
+        this.viewer = viewer;
+
+        viewer.addTreeListener( treeViewerListener );
+        viewer.addDoubleClickListener( doubleClickListener );
+
+        ConnectionEventRegistry.addConnectionUpdateListener( this, ConnectionUIPlugin.getDefault().getEventRunner() );
+        EventRegistry.addEntryUpdateListener( this, BrowserCommonActivator.getDefault().getEventRunner() );
+    }
+
+
+    /**
+     * Disposes this listener.
+     */
+    public void dispose()
+    {
+        if ( viewer != null )
+        {
+            viewer.removeTreeListener( treeViewerListener );
+            viewer.removeDoubleClickListener( doubleClickListener );
+
+            ConnectionEventRegistry.removeConnectionUpdateListener( this );
+            EventRegistry.removeEntryUpdateListener( this );
+
+            viewer = null;
+        }
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionOpened(org.apache.directory.studio.connection.core.Connection)
+     */
+    public void connectionOpened( Connection connection )
+    {
+        viewer.refresh();
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionClosed(org.apache.directory.studio.connection.core.Connection)
+     */
+    public void connectionClosed( Connection connection )
+    {
+        viewer.collapseAll();
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionUpdated(org.apache.directory.studio.connection.core.Connection)
+     */
+    public void connectionUpdated( Connection connection )
+    {
+        viewer.refresh();
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionAdded(org.apache.directory.studio.connection.core.Connection)
+     */
+    public void connectionAdded( Connection connection )
+    {
+        viewer.refresh();
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionRemoved(org.apache.directory.studio.connection.core.Connection)
+     */
+    public void connectionRemoved( Connection connection )
+    {
+        viewer.refresh();
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionFolderModified(org.apache.directory.studio.connection.core.ConnectionFolder)
+     */
+    public void connectionFolderModified( ConnectionFolder connectionFolder )
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     *
+     * This implementation refreshes the tree.
+     */
+    public void entryUpdated( EntryModificationEvent event )
+    {
+        // Don't handle attribute initalization, could cause double
+        // retrieval of children.
+        //
+        // When double-clicking an entry two Jobs/Threads are started:
+        // - InitializeAttributesJob and
+        // - InitializeChildrenJob
+        // If the InitializeAttributesJob is finished first the
+        // AttributesInitializedEvent is fired. If this causes
+        // a refresh of the tree before the children are initialized
+        // another InitializeChildrenJob is executed.
+        if ( event instanceof AttributesInitializedEvent )
+        {
+            return;
+        }
+
+        viewer.refresh( event.getModifiedEntry(), true );
+
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserUniversalListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,214 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import org.apache.directory.studio.ldapbrowser.common.widgets.ViewFormWidget;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.IActionBars;
+
+
+/**
+ * The BrowserWidget is a reusable widget that displays the DIT, searches
+ * and bookmarks of a connection a tree viewer.
+ * It is used by {@link BrowserView} and {@link SelectEntryDialog}.
+ * 
+ * It provides a context menu and a local toolbar with actions to
+ * manage entries, searches and bookmarks.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BrowserWidget extends ViewFormWidget
+{
+
+    /** The widget's configuration with the content provider, label provider and menu manager */
+    private BrowserConfiguration configuration;
+
+    /** The action bars. */
+    private IActionBars actionBars;
+
+    /** The tree widget used by the tree viewer */
+    private Tree tree;
+
+    /** The tree viewer. */
+    private TreeViewer viewer;
+
+
+    /**
+     * Creates a new instance of BrowserWidget.
+     *
+     * @param configuration the configuration
+     * @param actionBars the action bars
+     */
+    public BrowserWidget( BrowserConfiguration configuration, IActionBars actionBars )
+    {
+        this.configuration = configuration;
+        this.actionBars = actionBars;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void createWidget( Composite parent )
+    {
+        if ( actionBars == null )
+        {
+            super.createWidget( parent );
+        }
+        else
+        {
+            createContent( parent );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public IToolBarManager getToolBarManager()
+    {
+        if ( actionBars == null )
+        {
+            return super.getToolBarManager();
+        }
+        else
+        {
+            return actionBars.getToolBarManager();
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public IMenuManager getMenuManager()
+    {
+        if ( actionBars == null )
+        {
+            return super.getMenuManager();
+        }
+        else
+        {
+            return actionBars.getMenuManager();
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public IMenuManager getContextMenuManager()
+    {
+        if ( actionBars == null )
+        {
+            return super.getContextMenuManager();
+        }
+        else
+        {
+            return configuration.getContextMenuManager( viewer );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    protected Control createContent( Composite parent )
+    {
+
+        // create tree widget and viewer
+        tree = new Tree( parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER );
+        GridData data = new GridData( GridData.FILL_BOTH );
+        data.widthHint = 450;
+        data.heightHint = 250;
+        tree.setLayoutData( data );
+        viewer = new TreeViewer( tree );
+        viewer.setUseHashlookup( true );
+
+        // setup sorter, filter and layout
+        configuration.getSorter().connect( viewer );
+        configuration.getPreferences().connect( viewer );
+
+        // setup providers
+        viewer.setContentProvider( configuration.getContentProvider( viewer ) );
+        viewer.setLabelProvider( configuration.getLabelProvider( viewer ) );
+
+        return tree;
+    }
+
+
+    /**
+     * Sets the input to the tree viewer.
+     *
+     * @param input the input
+     */
+    public void setInput( Object input )
+    {
+        viewer.setInput( input );
+    }
+
+
+    /**
+     * Sets focus to the table viewer.
+     */
+    public void setFocus()
+    {
+        viewer.getTree().setFocus();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void dispose()
+    {
+        if ( this.viewer != null )
+        {
+            this.configuration.dispose();
+            this.configuration = null;
+
+            this.tree.dispose();
+            this.tree = null;
+            this.viewer = null;
+        }
+    }
+
+
+    /**
+     * Gets the tree viewer.
+     * 
+     * @return the tree viewer
+     */
+    public TreeViewer getViewer()
+    {
+        return viewer;
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/BrowserWidget.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/OpenSortDialogAction.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/OpenSortDialogAction.java?rev=592079&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/OpenSortDialogAction.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/OpenSortDialogAction.java Mon Nov  5 08:48:35 2007
@@ -0,0 +1,76 @@
+/*
+ *  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.apache.directory.studio.ldapbrowser.common.widgets.browser;
+
+
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
+import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.PlatformUI;
+
+
+/**
+ * This action opens the {@link BrowserSorterDialog}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class OpenSortDialogAction extends Action
+{
+
+    /** The preferences. */
+    private BrowserPreferences preferences;
+
+
+    /**
+     * Creates a new instance of OpenSortDialogAction.
+     *
+     * @param preferences the preferences
+     */
+    public OpenSortDialogAction( BrowserPreferences preferences )
+    {
+        super( "Sorting...", BrowserCommonActivator.getDefault().getImageDescriptor( BrowserCommonConstants.IMG_SORT ) );
+        super.setEnabled( true );
+
+        this.preferences = preferences;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void run()
+    {
+        BrowserSorterDialog dlg = new BrowserSorterDialog( PlatformUI.getWorkbench().getDisplay().getActiveShell(),
+            preferences );
+        dlg.open();
+    }
+
+
+    /**
+     * Disposes this action.
+     */
+    public void dispose()
+    {
+        preferences = null;
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-common/src/main/java/org/apache/directory/studio/ldapbrowser/common/widgets/browser/OpenSortDialogAction.java
------------------------------------------------------------------------------
    svn:eol-style = native