001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 /*******************************************************************************
021 * Copyright (c) 2003, 2007 IBM Corporation and others.
022 * All rights reserved. This program and the accompanying materials
023 * are made available under the terms of the Eclipse Public License v1.0
024 * which accompanies this distribution, and is available at
025 * http://www.eclipse.org/legal/epl-v10.html
026 *
027 * Contributors:
028 * IBM Corporation - Initial API and implementation
029 *******************************************************************************/
030 package org.apache.directory.studio.apacheds.views;
031
032
033 import java.util.ArrayList;
034 import java.util.List;
035
036 import org.apache.directory.studio.apacheds.model.ServerEvent;
037 import org.apache.directory.studio.apacheds.model.ServerEventEnum;
038 import org.apache.directory.studio.apacheds.model.Server;
039 import org.apache.directory.studio.apacheds.model.ServerListener;
040 import org.apache.directory.studio.apacheds.model.ServerStateEnum;
041 import org.apache.directory.studio.apacheds.model.ServersHandler;
042 import org.apache.directory.studio.apacheds.model.ServersHandlerListener;
043 import org.eclipse.jface.viewers.ISelection;
044 import org.eclipse.jface.viewers.TreeViewer;
045 import org.eclipse.swt.SWT;
046 import org.eclipse.swt.widgets.Display;
047 import org.eclipse.swt.widgets.Tree;
048 import org.eclipse.swt.widgets.TreeColumn;
049 import org.eclipse.swt.widgets.TreeItem;
050 import org.eclipse.swt.widgets.Widget;
051 import org.eclipse.ui.PlatformUI;
052
053
054 /**
055 * This class implements a {@link TreeViewer} that displays the servers.
056 *
057 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
058 * @version $Rev$, $Date$
059 */
060 public class ServersTableViewer extends TreeViewer
061 {
062 /** The root element */
063 protected static final String ROOT = "root"; //$NON-NLS-1$
064
065 /** The label provider */
066 private ServersViewLabelProvider labelProvider;
067
068 /** The server handler listener */
069 private ServersHandlerListener serversHandlerListener;
070
071 /** The server listener */
072 private ServerListener serverListener;
073
074 /** A flag to stop the animation */
075 private boolean stopAnimation;
076
077 /** The list of server needing animation */
078 private List<Server> serversNeedingAnimation = new ArrayList<Server>();
079
080
081 public ServersTableViewer( Tree tree )
082 {
083 super( tree );
084
085 labelProvider = new ServersViewLabelProvider();
086 setLabelProvider( labelProvider );
087 setContentProvider( new ServersViewContentProvider() );
088
089 setComparator( new ServersViewerComparator( labelProvider ) );
090
091 setInput( ROOT );
092
093 addListeners();
094 }
095
096
097 /**
098 * Adds the listener
099 */
100 private void addListeners()
101 {
102 // The server handler listener
103 serversHandlerListener = new ServersHandlerListener()
104 {
105 public void serverAdded( Server server )
106 {
107 addServer( server );
108 server.addListener( serverListener );
109 }
110
111
112 public void serverRemoved( Server server )
113 {
114 refreshServer( server );
115 }
116
117
118 public void serverUpdated( Server server )
119 {
120 removeServer( server );
121 server.removeListener( serverListener );
122
123 }
124 };
125
126 // Adding the listener to the servers handler
127 ServersHandler.getDefault().addListener( serversHandlerListener );
128
129 // The server listener
130 serverListener = new ServerListener()
131 {
132 public void serverChanged( ServerEvent event )
133 {
134 // Checking if the event is null
135 if ( event == null )
136 {
137 return;
138 }
139
140 // Getting the kind of event and the associated server
141 ServerEventEnum kind = event.getKind();
142 Server server = event.getServer();
143 switch ( kind )
144 {
145 // The server state has changed
146 case STATE_CHANGED:
147 // First, we refresh the server
148 refreshServer( server );
149
150 // Then, we get the state of the server to see if we
151 // need to start or stop the animation thread
152 ServerStateEnum state = server.getState();
153
154 // If the state is STARTING or STOPPING, we need to
155 // add the server to the list of servers needing
156 // animation and eventually start the animation thread
157 if ( ( state == ServerStateEnum.STARTING ) || ( state == ServerStateEnum.STOPPING ) )
158 {
159 boolean startAnimationThread = false;
160
161 synchronized ( serversNeedingAnimation )
162 {
163 if ( !serversNeedingAnimation.contains( server ) )
164 {
165 if ( serversNeedingAnimation.isEmpty() )
166 startAnimationThread = true;
167 serversNeedingAnimation.add( server );
168 }
169 }
170
171 if ( startAnimationThread )
172 {
173 startAnimationThread();
174 }
175 }
176
177 // If the state is *not* STARTING or STOPPING, we need
178 // to remove the server from the list of servers
179 // needing animation and eventually stop the animation
180 // if this list is empty
181 else
182 {
183 boolean stopAnimationThread = false;
184
185 synchronized ( serversNeedingAnimation )
186 {
187 if ( serversNeedingAnimation.contains( server ) )
188 {
189 serversNeedingAnimation.remove( server );
190 if ( serversNeedingAnimation.isEmpty() )
191 stopAnimationThread = true;
192 }
193 }
194
195 if ( stopAnimationThread )
196 {
197 stopAnimationThread();
198 }
199 }
200 break;
201 // The server has been renamed
202 case RENAMED:
203 // We simply refresh the server
204 refreshServer( server );
205 break;
206 }
207
208 }
209 };
210
211 // Adding the listener to the servers
212 for ( Server server : ServersHandler.getDefault().getServersList() )
213 {
214 server.addListener( serverListener );
215 }
216 }
217
218
219 /**
220 * Adds a server.
221 *
222 * @param server
223 * the server
224 */
225 private void addServer( final Server server )
226 {
227 Display.getDefault().asyncExec( new Runnable()
228 {
229 public void run()
230 {
231 add( ROOT, server );
232 }
233 } );
234 }
235
236
237 /**
238 * Refreshes a server.
239 *
240 * @param server
241 * the server
242 */
243 private void refreshServer( final Server server )
244 {
245 Display.getDefault().asyncExec( new Runnable()
246 {
247 public void run()
248 {
249 try
250 {
251 refresh( server );
252 ISelection sel = ServersTableViewer.this.getSelection();
253 ServersTableViewer.this.setSelection( sel );
254 }
255 catch ( Exception e )
256 {
257 // ignore
258 }
259 }
260 } );
261 }
262
263
264 /**
265 * Removes a server.
266 *
267 * @param server
268 * the server
269 */
270 private void removeServer( final Server server )
271 {
272 Display.getDefault().asyncExec( new Runnable()
273 {
274 public void run()
275 {
276 remove( server );
277 }
278 } );
279 }
280
281
282 /**
283 * Starts the animation thread.
284 */
285 private void startAnimationThread()
286 {
287 stopAnimation = false;
288
289 final Display display = getTree().getDisplay();
290 final int SLEEP = 200;
291 final Runnable[] animatorThread = new Runnable[1];
292 animatorThread[0] = new Runnable()
293 {
294 public void run()
295 {
296 // Checking if we need to stop the animation
297 if ( !stopAnimation )
298 {
299 try
300 {
301 // Changing the animation state on the label provider
302 labelProvider.animate();
303
304 // Looping on the currently starting servers
305 for ( Server server : serversNeedingAnimation.toArray( new Server[0] ) )
306 {
307 if ( server != null && getTree() != null && !getTree().isDisposed() )
308 {
309 updateAnimation( server );
310 }
311 }
312 }
313 catch ( Exception e )
314 {
315 // Trace.trace( Trace.FINEST, "Error in Servers view animation", e ); TODO
316 }
317
318 // Re-launching the animation
319 display.timerExec( SLEEP, animatorThread[0] );
320 }
321 }
322 };
323
324 // Launching the animation asynchronously
325 Display.getDefault().asyncExec( new Runnable()
326 {
327 public void run()
328 {
329 display.timerExec( SLEEP, animatorThread[0] );
330 }
331 } );
332 }
333
334
335 /**
336 * Stops the animation thread.
337 */
338 private void stopAnimationThread()
339 {
340 stopAnimation = true;
341 }
342
343
344 /**
345 * Updates the animation for the given server
346 *
347 * @param server
348 * the server
349 */
350 private void updateAnimation( Server server )
351 {
352 try
353 {
354 Widget widget = doFindItem( server );
355 TreeItem item = ( TreeItem ) widget;
356 item.setText( 1, labelProvider.getColumnText( server, 1 ) );
357 item.setImage( 1, labelProvider.getColumnImage( server, 1 ) );
358 }
359 catch ( Exception e )
360 {
361 // Trace.trace( Trace.WARNING, "Error in optimized animation", e );
362 //TODO
363 }
364 }
365
366
367 /**
368 * Resorts the table based on field.
369 *
370 * @param column
371 * the column being updated
372 * @param col
373 * the column
374 */
375 protected void resortTable( final TreeColumn column, int col )
376 {
377 ServersViewerComparator sorter = ( ServersViewerComparator ) getComparator();
378
379 if ( col == sorter.getTopPriority() )
380 sorter.reverseTopPriority();
381 else
382 sorter.setTopPriority( col );
383
384 PlatformUI.getWorkbench().getDisplay().asyncExec( new Runnable()
385 {
386 public void run()
387 {
388 refresh();
389 updateDirectionIndicator( column );
390 }
391 } );
392 }
393
394
395 /**
396 * Updates the direction indicator as column is now the primary column.
397 *
398 * @param column
399 */
400 protected void updateDirectionIndicator( TreeColumn column )
401 {
402 getTree().setSortColumn( column );
403 if ( ( ( ServersViewerComparator ) getComparator() ).getTopPriorityDirection() == ServersViewerComparator.ASCENDING )
404 getTree().setSortDirection( SWT.UP );
405 else
406 getTree().setSortDirection( SWT.DOWN );
407 }
408 }