/* * 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.ldapservers.views; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import org.apache.directory.studio.ldapservers.LdapServersManager; import org.apache.directory.studio.ldapservers.LdapServersManagerListener; import org.apache.directory.studio.ldapservers.model.LdapServer; import org.apache.directory.studio.ldapservers.model.LdapServerEvent; import org.apache.directory.studio.ldapservers.model.LdapServerEventType; import org.apache.directory.studio.ldapservers.model.LdapServerListener; import org.apache.directory.studio.ldapservers.model.LdapServerStatus; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.PlatformUI; /** * This class implements a {@link TreeViewer} that displays the servers. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class ServersTableViewer extends TreeViewer { /** The root element */ protected static final String ROOT = "root"; //$NON-NLS-1$ /** The label provider */ private ServersViewLabelProvider labelProvider; /** The comparator */ private ServersComparator comparator; /** The server handler listener */ private LdapServersManagerListener serversHandlerListener; /** The server listener */ private LdapServerListener serverListener; /** A flag to stop the animation */ private boolean stopAnimation; /** The list of server needing animation */ private List<LdapServer> serversNeedingAnimation = new ArrayList<LdapServer>(); /** * Creates a new instance of ServersTableViewer. * * @param tree * the associated tree */ public ServersTableViewer( Tree tree ) { super( tree ); labelProvider = new ServersViewLabelProvider(); setLabelProvider( labelProvider ); setContentProvider( new ServersViewContentProvider() ); comparator = new ServersComparator(); setComparator( new ViewerComparator( comparator ) ); setInput( ROOT ); addListeners(); } /** * Adds the listener */ private void addListeners() { // The server handler listener serversHandlerListener = new LdapServersManagerListener() { public void serverAdded( LdapServer server ) { addServer( server ); server.addListener( serverListener ); } public void serverRemoved( LdapServer server ) { refreshServer( server ); } public void serverUpdated( LdapServer server ) { removeServer( server ); server.removeListener( serverListener ); } }; // Adding the listener to the servers handler LdapServersManager.getDefault().addListener( serversHandlerListener ); // The server listener serverListener = new LdapServerListener() { public void serverChanged( LdapServerEvent event ) { // Checking if the event is null if ( event == null ) { return; } // Getting the kind of event and the associated server LdapServerEventType kind = event.getKind(); LdapServer server = event.getServer(); switch ( kind ) { // The server status has changed case STATUS_CHANGED: // First, we refresh the server refreshServer( server ); // Then, we get the status of the server to see if we // need to start or stop the animation thread LdapServerStatus state = server.getStatus(); // If the state is STARTING or STOPPING, we need to // add the server to the list of servers needing // animation and eventually start the animation thread if ( ( state == LdapServerStatus.STARTING ) || ( state == LdapServerStatus.STOPPING ) || ( state == LdapServerStatus.REPAIRING ) ) { boolean startAnimationThread = false; synchronized ( serversNeedingAnimation ) { if ( !serversNeedingAnimation.contains( server ) ) { if ( serversNeedingAnimation.isEmpty() ) startAnimationThread = true; serversNeedingAnimation.add( server ); } } if ( startAnimationThread ) { startAnimationThread(); } } // If the state is *not* STARTING or STOPPING, we need // to remove the server from the list of servers // needing animation and eventually stop the animation // if this list is empty else { boolean stopAnimationThread = false; synchronized ( serversNeedingAnimation ) { if ( serversNeedingAnimation.contains( server ) ) { serversNeedingAnimation.remove( server ); if ( serversNeedingAnimation.isEmpty() ) stopAnimationThread = true; } } if ( stopAnimationThread ) { stopAnimationThread(); } } break; // The server has been renamed case RENAMED: // We simply refresh the server refreshServer( server ); break; } } }; // Adding the listener to the servers for ( LdapServer server : LdapServersManager.getDefault().getServersList() ) { server.addListener( serverListener ); } } /** * Adds a server. * * @param server * the server */ private void addServer( final LdapServer server ) { Display.getDefault().asyncExec( new Runnable() { public void run() { add( ROOT, server ); } } ); } /** * Refreshes a server. * * @param server * the server */ private void refreshServer( final LdapServer server ) { Display.getDefault().asyncExec( new Runnable() { public void run() { refresh( server ); ISelection sel = ServersTableViewer.this.getSelection(); ServersTableViewer.this.setSelection( sel ); } } ); } /** * Removes a server. * * @param server * the server */ private void removeServer( final LdapServer server ) { Display.getDefault().asyncExec( new Runnable() { public void run() { remove( server ); } } ); } /** * Starts the animation thread. */ private void startAnimationThread() { stopAnimation = false; final Display display = getTree().getDisplay(); final int SLEEP = 200; final Runnable[] animatorThread = new Runnable[1]; animatorThread[0] = new Runnable() { public void run() { // Checking if we need to stop the animation if ( !stopAnimation ) { // Changing the animation state on the label provider labelProvider.animate(); // Looping on the currently starting servers for ( LdapServer server : serversNeedingAnimation.toArray( new LdapServer[0] ) ) { if ( server != null && getTree() != null && !getTree().isDisposed() ) { updateAnimation( server ); } } // Re-launching the animation display.timerExec( SLEEP, animatorThread[0] ); } } }; // Launching the animation asynchronously Display.getDefault().asyncExec( new Runnable() { public void run() { display.timerExec( SLEEP, animatorThread[0] ); } } ); } /** * Stops the animation thread. */ private void stopAnimationThread() { stopAnimation = true; } /** * Updates the animation for the given server * * @param server * the server */ private void updateAnimation( LdapServer server ) { Widget widget = doFindItem( server ); TreeItem item = ( TreeItem ) widget; item.setText( 1, labelProvider.getColumnText( server, 1 ) ); item.setImage( 1, labelProvider.getColumnImage( server, 1 ) ); } /** * Sorts the table. * * @param treeColumn the tree column * @param column the column number */ public void sort( final TreeColumn treeColumn, int column ) { if ( column == comparator.column ) { comparator.reverseOrdering(); } else { comparator.column = column; } PlatformUI.getWorkbench().getDisplay().asyncExec( new Runnable() { public void run() { refresh(); Tree tree = getTree(); tree.setSortColumn( treeColumn ); if ( comparator.order == ServersComparator.ASCENDING ) { tree.setSortDirection( SWT.UP ); } else { tree.setSortDirection( SWT.DOWN ); } } } ); } /** * This class implements a comparator for servers. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ private class ServersComparator implements Comparator<Object> { public static final int ASCENDING = 1; /** The comparison order */ int order = ASCENDING; /** The column used to compare objects */ int column = 0; /** * Reverses the order. */ public void reverseOrdering() { order = order * -1; } /** * {@inheritDoc} */ public int compare( Object o1, Object o2 ) { String s1 = labelProvider.getColumnText( o1, column ); String s2 = labelProvider.getColumnText( o2, column ); return s1.compareToIgnoreCase( s2 ) * order; } } }