1/*******************************************************************************
2 * Copyright (c) 2000, 2009 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *     IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.test.internal.performance.results.ui;
12
13
14import java.io.File;
15import java.lang.reflect.InvocationTargetException;
16import java.text.NumberFormat;
17import java.util.HashSet;
18import java.util.Locale;
19import java.util.Set;
20
21import org.eclipse.core.runtime.IProgressMonitor;
22import org.eclipse.core.runtime.preferences.IEclipsePreferences;
23import org.eclipse.core.runtime.preferences.InstanceScope;
24import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
25import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
26import org.eclipse.jface.action.Action;
27import org.eclipse.jface.action.IAction;
28import org.eclipse.jface.action.IMenuListener;
29import org.eclipse.jface.action.IMenuManager;
30import org.eclipse.jface.action.IToolBarManager;
31import org.eclipse.jface.action.MenuManager;
32import org.eclipse.jface.dialogs.MessageDialog;
33import org.eclipse.jface.dialogs.ProgressMonitorDialog;
34import org.eclipse.jface.operation.IRunnableWithProgress;
35import org.eclipse.jface.viewers.ISelectionChangedListener;
36import org.eclipse.jface.viewers.SelectionChangedEvent;
37import org.eclipse.jface.viewers.TreeViewer;
38import org.eclipse.jface.viewers.Viewer;
39import org.eclipse.jface.viewers.ViewerFilter;
40import org.eclipse.swt.SWT;
41import org.eclipse.swt.graphics.Color;
42import org.eclipse.swt.widgets.Composite;
43import org.eclipse.swt.widgets.DirectoryDialog;
44import org.eclipse.swt.widgets.Display;
45import org.eclipse.swt.widgets.Menu;
46import org.eclipse.swt.widgets.Shell;
47import org.eclipse.test.internal.performance.results.db.DB_Results;
48import org.eclipse.test.internal.performance.results.model.BuildResultsElement;
49import org.eclipse.test.internal.performance.results.model.PerformanceResultsElement;
50import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
51import org.eclipse.test.internal.performance.results.utils.Util;
52import org.eclipse.ui.IActionBars;
53import org.eclipse.ui.IMemento;
54import org.eclipse.ui.IViewPart;
55import org.eclipse.ui.IViewSite;
56import org.eclipse.ui.IWorkbench;
57import org.eclipse.ui.IWorkbenchPage;
58import org.eclipse.ui.IWorkbenchWindow;
59import org.eclipse.ui.PartInitException;
60import org.eclipse.ui.PlatformUI;
61import org.eclipse.ui.part.ViewPart;
62import org.eclipse.ui.views.properties.IPropertySheetPage;
63import org.eclipse.ui.views.properties.PropertySheetPage;
64import org.osgi.service.prefs.BackingStoreException;
65
66
67/**
68 * Abstract view for performance results.
69 */
70public abstract class PerformancesView extends ViewPart implements ISelectionChangedListener, IPreferenceChangeListener {
71
72	// Format
73	static final NumberFormat DOUBLE_FORMAT = NumberFormat.getNumberInstance(Locale.US);
74	static {
75		DOUBLE_FORMAT.setMaximumFractionDigits(3);
76	}
77
78	// Graphic constants
79	static final Display DEFAULT_DISPLAY = Display.getDefault();
80	static final Color BLACK= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_BLACK);
81	static final Color BLUE= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_BLUE);
82	static final Color GREEN= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_GREEN);
83	static final Color RED = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_RED);
84	static final Color GRAY = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_GRAY);
85	static final Color DARK_GRAY = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_DARK_GRAY);
86	static final Color YELLOW = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_YELLOW);
87	static final Color WHITE = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_WHITE);
88
89	// Viewer filters
90	static final ViewerFilter[] NO_FILTER = new ViewerFilter[0];
91	final static ViewerFilter FILTER_BASELINE_BUILDS = new ViewerFilter() {
92		public boolean select(Viewer v, Object parentElement, Object element) {
93			if (element instanceof BuildResultsElement) {
94				BuildResultsElement buildElement = (BuildResultsElement) element;
95				return !buildElement.getName().startsWith(DB_Results.getDbBaselinePrefix());
96			}
97			return true;
98		}
99	};
100	public final static ViewerFilter FILTER_NIGHTLY_BUILDS = new ViewerFilter() {
101		public boolean select(Viewer v, Object parentElement, Object element) {
102			if (element instanceof BuildResultsElement) {
103				BuildResultsElement buildElement = (BuildResultsElement) element;
104				return buildElement.getName().charAt(0) != 'N';
105			}
106			return true;
107		}
108	};
109	final static ViewerFilter FILTER_OLD_BUILDS = new ViewerFilter() {
110		public boolean select(Viewer v, Object parentElement, Object element) {
111			if (element instanceof BuildResultsElement) {
112				BuildResultsElement buildElement = (BuildResultsElement) element;
113				return buildElement.isImportant();
114			}
115	        return true;
116        }
117	};
118	static String LAST_BUILD;
119	final static ViewerFilter FILTER_LAST_BUILDS = new ViewerFilter() {
120		public boolean select(Viewer v, Object parentElement, Object element) {
121			if (LAST_BUILD != null && element instanceof BuildResultsElement) {
122				BuildResultsElement buildElement = (BuildResultsElement) element;
123				return buildElement.isBefore(LAST_BUILD);
124			}
125	        return true;
126        }
127	};
128	Set viewFilters = new HashSet();
129
130	// SWT resources
131	Shell shell;
132	Display display;
133	TreeViewer viewer;
134	IPropertySheetPage propertyPage;
135
136	// Data info
137	File dataDir;
138
139	// Views
140	IMemento viewState;
141
142	// Results model information
143	PerformanceResultsElement results;
144
145	// Actions
146	Action changeDataDir;
147	Action filterBaselineBuilds;
148	Action filterNightlyBuilds;
149	Action filterOldBuilds;
150	Action filterLastBuilds;
151//	Action dbConnection;
152
153	// Eclipse preferences
154	IEclipsePreferences preferences;
155
156/**
157 * Get a view from its ID.
158 *
159 * @param viewId The ID of the view
160 * @return The found view or <code>null</null> if not found.
161 */
162static IViewPart getWorkbenchView(String viewId) {
163	IWorkbench workbench = PlatformUI.getWorkbench();
164	IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
165	int length = windows.length;
166	for (int i=0; i<length; i++) {
167		IWorkbenchWindow window = windows[i];
168		IWorkbenchPage[] pages = window.getPages();
169		int pLength = pages.length;
170		for (int j=0; j<pLength; j++) {
171			IWorkbenchPage page = pages[i];
172			IViewPart view = page.findView(viewId);
173			if (view != null) {
174				return view;
175			}
176		}
177	}
178	return null;
179}
180
181/**
182 * The constructor.
183 */
184public PerformancesView() {
185
186	// Get preferences
187	this.preferences = new InstanceScope().getNode(IPerformancesConstants.PLUGIN_ID);
188
189	// Init db constants
190	int eclipseVersion = this.preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
191	String databaseLocation = this.preferences.get(IPerformancesConstants.PRE_DATABASE_LOCATION, IPerformancesConstants.NETWORK_DATABASE_LOCATION);
192	boolean connected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
193	DB_Results.updateDbConstants(connected, eclipseVersion, databaseLocation);
194	this.preferences.addPreferenceChangeListener(this);
195
196	// Init tool tip
197	setTitleToolTip();
198
199	// Init milestones
200	Util.initMilestones(this.preferences);
201
202	// Init last build
203	String lastBuild = this.preferences.get(IPerformancesConstants.PRE_LAST_BUILD, null);
204	LAST_BUILD = lastBuild == null || lastBuild.length() == 0 ? null : lastBuild;
205}
206
207File changeDataDir() {
208	String localDataDir = this.preferences.get(IPerformancesConstants.PRE_LOCAL_DATA_DIR, "");
209	String filter = (this.dataDir == null) ? localDataDir : this.dataDir.getPath();
210	File dir = this.dataDir;
211	this.dataDir = changeDir(filter, "Select directory for data local files");
212	boolean refresh = false;
213	if (this.dataDir != null) {
214		this.preferences.put(IPerformancesConstants.PRE_LOCAL_DATA_DIR, this.dataDir.getAbsolutePath());
215		if (dir != null && dir.getPath().equals(this.dataDir.getPath())) {
216			refresh = MessageDialog.openQuestion(this.shell, getTitleToolTip(), "Do you want to read local file again?");
217		} else {
218			refresh = true;
219		}
220		if (refresh) {
221			// Confirm the read when there's a last build set
222			if (LAST_BUILD != null) {
223				if (!MessageDialog.openConfirm(PerformancesView.this.shell, getTitleToolTip(), "Only builds before "+LAST_BUILD+" will be taken into account!\nDo you want to continue?")) {
224					return null;
225				}
226			}
227
228			// Read local files
229			readLocalFiles();
230
231			// Refresh views
232			refreshInput();
233			PerformancesView resultsView = getSiblingView();
234			resultsView.refreshInput();
235			return resultsView.dataDir = this.dataDir;
236		}
237	}
238	return null;
239}
240
241/*
242 * Select a directory.
243 */
244File changeDir(String filter, String msg) {
245    DirectoryDialog dialog = new DirectoryDialog(getSite().getShell(), SWT.OPEN);
246    dialog.setText(getTitleToolTip());
247    dialog.setMessage(msg);
248    if (filter != null) {
249    	dialog.setFilterPath(filter);
250    }
251    String path = dialog.open();
252    if (path != null) {
253	    File dir = new File(path);
254	    if (dir.exists() && dir.isDirectory()) {
255    		return dir;
256	    }
257    }
258    return null;
259}
260
261/*
262 * Contribute actions to bars.
263 */
264void contributeToActionBars() {
265	IActionBars bars = getViewSite().getActionBars();
266	fillLocalPullDown(bars.getMenuManager());
267	fillLocalToolBar(bars.getToolBarManager());
268}
269
270/*
271 * (non-Javadoc)
272 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
273 */
274public void createPartControl(Composite parent) {
275	// Cache the shell and display.
276	this.shell = parent.getShell ();
277	this.display = this.shell.getDisplay ();
278}
279
280/*
281 * Fill the context menu.
282 */
283void fillContextMenu(IMenuManager manager) {
284	// no default contextual action
285}
286
287/*
288 * Fill the filters drop-down menu.
289 */
290void fillFiltersDropDown(IMenuManager manager) {
291	manager.add(this.filterBaselineBuilds);
292	manager.add(this.filterNightlyBuilds);
293}
294
295/*
296 * Fill the local data drop-down menu
297 */
298void fillLocalDataDropDown(IMenuManager manager) {
299	manager.add(this.changeDataDir);
300}
301
302/*
303 * Fill the local pull down menu.
304 */
305void fillLocalPullDown(IMenuManager manager) {
306
307	// Filters menu
308	MenuManager filtersManager= new MenuManager("Filters");
309	fillFiltersDropDown(filtersManager);
310	manager.add(filtersManager);
311
312	// Local data menu
313	MenuManager localDataManager= new MenuManager("Local data");
314	fillLocalDataDropDown(localDataManager);
315	manager.add(localDataManager);
316}
317
318/*
319 * Fill the local toolbar.
320 */
321void fillLocalToolBar(IToolBarManager manager) {
322	// no default toolbar action
323}
324
325/*
326 * Filter non fingerprints scenarios action run.
327 */
328void filterLastBuilds(boolean filter, boolean updatePreference) {
329	if (filter) {
330		this.viewFilters.add(FILTER_LAST_BUILDS);
331	} else {
332		this.viewFilters.remove(FILTER_LAST_BUILDS);
333	}
334	this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_LAST_BUILDS, filter);
335	updateFilters();
336}
337
338/*
339 * Filter non milestone builds action run.
340 */
341void filterNightlyBuilds(boolean filter, boolean updatePreference) {
342	if (filter) {
343		this.viewFilters.add(FILTER_NIGHTLY_BUILDS);
344	} else {
345		this.viewFilters.remove(FILTER_NIGHTLY_BUILDS);
346	}
347	this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_NIGHTLY_BUILDS, filter);
348	updateFilters();
349}
350
351/*
352 * Filter non milestone builds action run.
353 */
354void filterOldBuilds(boolean filter, boolean updatePreference) {
355	if (filter) {
356		this.viewFilters.add(FILTER_OLD_BUILDS);
357	} else {
358		this.viewFilters.remove(FILTER_OLD_BUILDS);
359	}
360	this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_OLD_BUILDS, filter);
361	updateFilters();
362}
363
364/*
365 * Finalize the viewer creation
366 */
367void finalizeViewerCreation() {
368	makeActions();
369	hookContextMenu();
370	contributeToActionBars();
371	restoreState();
372	updateFilters();
373	this.viewer.setInput(getViewSite());
374	this.viewer.addSelectionChangedListener(this);
375}
376
377/* (non-Javadoc)
378 * Method declared on IAdaptable
379 */
380public Object getAdapter(Class adapter) {
381    if (adapter.equals(IPropertySheetPage.class)) {
382        return getPropertySheet();
383    }
384    return super.getAdapter(adapter);
385}
386
387/**
388 * Returns the property sheet.
389 */
390protected IPropertySheetPage getPropertySheet() {
391	if (this.propertyPage == null) {
392		this.propertyPage = new PropertySheetPage();
393	}
394    return this.propertyPage;
395}
396
397/*
398 * Get the sibling view (see subclasses).
399 */
400abstract PerformancesView getSiblingView();
401
402/*
403 * Hook the context menu.
404 */
405void hookContextMenu() {
406	MenuManager menuMgr = new MenuManager("#PopupMenu");
407	menuMgr.setRemoveAllWhenShown(true);
408	menuMgr.addMenuListener(new IMenuListener() {
409		public void menuAboutToShow(IMenuManager manager) {
410			fillContextMenu(manager);
411		}
412	});
413	Menu menu = menuMgr.createContextMenu(this.viewer.getControl());
414	this.viewer.getControl().setMenu(menu);
415	getSite().registerContextMenu(menuMgr, this.viewer);
416}
417
418/*
419 * (non-Javadoc)
420 * @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento)
421 */
422public void init(IViewSite site, IMemento memento) throws PartInitException {
423	super.init(site, memento);
424	this.viewState = memento;
425}
426
427/*
428 * Init results
429 */
430void initResults() {
431	this.results = PerformanceResultsElement.PERF_RESULTS_MODEL;
432	if (this.results.isInitialized()) {
433		this.dataDir = getSiblingView().dataDir;
434	} else {
435		String localDataDir = this.preferences.get(IPerformancesConstants.PRE_LOCAL_DATA_DIR, null);
436		if (localDataDir != null) {
437			File dir = new File(localDataDir);
438			if (dir.exists() && dir.isDirectory()) {
439				this.dataDir = dir;
440				readLocalFiles();
441			}
442		}
443	}
444}
445
446/*
447 * Make common actions to performance views.
448 */
449void makeActions() {
450
451	// Change data dir action
452	this.changeDataDir = new Action("&Read...") {
453		public void run() {
454			changeDataDir();
455		}
456	};
457	this.changeDataDir.setToolTipText("Change the directory of the local data files");
458//	this.changeDataDir.setImageDescriptor(ResultsElement.FOLDER_IMAGE_DESCRIPTOR);
459
460	// Filter baselines action
461	this.filterBaselineBuilds = new Action("&Baselines", IAction.AS_CHECK_BOX) {
462		public void run() {
463			if (isChecked()) {
464				PerformancesView.this.viewFilters.add(FILTER_BASELINE_BUILDS);
465			} else {
466				PerformancesView.this.viewFilters.remove(FILTER_BASELINE_BUILDS);
467			}
468			updateFilters();
469        }
470	};
471	this.filterBaselineBuilds.setToolTipText("Filter baseline builds");
472
473	// Filter baselines action
474	this.filterNightlyBuilds = new Action("&Nightly", IAction.AS_CHECK_BOX) {
475		public void run() {
476			filterNightlyBuilds(isChecked(), true/*update preference*/);
477		}
478	};
479	this.filterNightlyBuilds.setToolTipText("Filter nightly builds");
480
481	// Filter non-important builds action
482	this.filterOldBuilds = new Action("&Old Builds", IAction.AS_CHECK_BOX) {
483		public void run() {
484			filterOldBuilds(isChecked(), true/*update preference*/);
485		}
486	};
487	this.filterOldBuilds.setChecked(false);
488	this.filterOldBuilds.setToolTipText("Filter old builds (i.e. before last milestone) but keep all previous milestones)");
489
490	// Filter non-important builds action
491	this.filterLastBuilds = new Action("&Last Builds", IAction.AS_CHECK_BOX) {
492		public void run() {
493			filterLastBuilds(isChecked(), true/*update preference*/);
494		}
495	};
496	final String lastBuild = this.preferences.get(IPerformancesConstants.PRE_LAST_BUILD, null);
497	this.filterLastBuilds.setChecked(false);
498	if (lastBuild == null) {
499		this.filterLastBuilds.setEnabled(false);
500	} else {
501		this.filterLastBuilds.setToolTipText("Filter last builds (i.e. after "+lastBuild+" build)");
502	}
503}
504
505/* (non-Javadoc)
506 * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
507 */
508public void preferenceChange(PreferenceChangeEvent event) {
509	String propertyName = event.getKey();
510//	String newValue = (String) event.getNewValue();
511
512	// Eclipse version change
513	if (propertyName.equals(IPerformancesConstants.PRE_ECLIPSE_VERSION)) {
514//		int eclipseVersion = newValue == null ? IPerformancesConstants.DEFAULT_ECLIPSE_VERSION : Integer.parseInt(newValue);
515//		String databaseLocation = this.preferences.get(IPerformancesConstants.PRE_DATABASE_LOCATION, IPerformancesConstants.NETWORK_DATABASE_LOCATION);
516//		boolean connected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
517//		DB_Results.updateDbConstants(connected, eclipseVersion, databaseLocation);
518//		setTitleToolTip();
519	}
520
521	// Database location change
522	if (propertyName.equals(IPerformancesConstants.PRE_DATABASE_LOCATION)) {
523//		boolean connected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
524//		int eclipseVersion = this.preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
525//		DB_Results.updateDbConstants(connected, eclipseVersion, newValue);
526//		setTitleToolTip();
527	}
528
529	// Database connection
530	if (propertyName.equals(IPerformancesConstants.PRE_DATABASE_CONNECTION)) {
531//		boolean connected = newValue == null ? IPerformancesConstants.DEFAULT_DATABASE_CONNECTION : newValue.equals(Boolean.TRUE);
532//		int eclipseVersion = this.preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
533//		String databaseLocation = this.preferences.get(IPerformancesConstants.PRE_DATABASE_LOCATION, IPerformancesConstants.NETWORK_DATABASE_LOCATION);
534//		DB_Results.updateDbConstants(connected, eclipseVersion, databaseLocation);
535//		setTitleToolTip();
536	}
537
538	// Last build
539	if (propertyName.equals(IPerformancesConstants.PRE_LAST_BUILD)) {
540//		if (newValue == null || newValue.length() == 0) {
541//			this.filterLastBuilds.setEnabled(false);
542//			LAST_BUILD = null;
543//		} else {
544//			this.filterLastBuilds.setEnabled(true);
545//			this.filterLastBuilds.setToolTipText("Filter last builds (i.e. after "+newValue+" build)");
546//			LAST_BUILD = newValue;
547//		}
548	}
549}
550
551/*
552 * Read local files
553 */
554void readLocalFiles() {
555
556	// Create runnable to read local files
557	IRunnableWithProgress runnable = new IRunnableWithProgress() {
558		public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
559			try {
560				monitor.beginTask("Read local files", 1000);
561				PerformancesView.this.results.readLocal(PerformancesView.this.dataDir, monitor, LAST_BUILD);
562				monitor.done();
563			} catch (Exception e) {
564				e.printStackTrace();
565			}
566		}
567	};
568
569	// Execute the runnable with progress
570	ProgressMonitorDialog readProgress = new ProgressMonitorDialog(getSite().getShell());
571	try {
572		readProgress.run(true, true, runnable);
573	} catch (InvocationTargetException e) {
574		// skip
575	} catch (InterruptedException e) {
576		// skip
577	}
578}
579
580/*
581 * Refresh the entire view by resetting its input.
582 */
583void refreshInput() {
584	this.viewer.setInput(getViewSite());
585	this.viewer.refresh();
586}
587
588/*
589 * Clear view content.
590 */
591void resetInput() {
592	this.results.reset(null);
593	this.viewer.setInput(getViewSite());
594	this.viewer.refresh();
595}
596
597/*
598 * Restore the view state from the memento information.
599 */
600void restoreState() {
601
602	// Filter baselines action state
603	if (this.viewState != null) {
604		Boolean filterBaselinesState = this.viewState.getBoolean(IPerformancesConstants.PRE_FILTER_BASELINE_BUILDS);
605		boolean filterBaselinesValue = filterBaselinesState == null ? false : filterBaselinesState.booleanValue();
606		this.filterBaselineBuilds.setChecked(filterBaselinesValue);
607		if (filterBaselinesValue) {
608			this.viewFilters.add(FILTER_BASELINE_BUILDS);
609		}
610	}
611
612	// Filter nightly builds action
613	boolean checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_NIGHTLY_BUILDS, IPerformancesConstants.DEFAULT_FILTER_NIGHTLY_BUILDS);
614	this.filterNightlyBuilds.setChecked(checked);
615	if (checked) {
616		this.viewFilters.add(FILTER_NIGHTLY_BUILDS);
617	}
618
619	// Filter non important builds action state
620	checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_OLD_BUILDS, IPerformancesConstants.DEFAULT_FILTER_OLD_BUILDS);
621	this.filterOldBuilds.setChecked(checked);
622	if (checked) {
623		this.viewFilters.add(FILTER_OLD_BUILDS);
624	}
625
626	// Filter last builds action state
627	checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_LAST_BUILDS, IPerformancesConstants.DEFAULT_FILTER_LAST_BUILDS);
628	this.filterLastBuilds.setChecked(checked);
629	if (checked) {
630		this.viewFilters.add(FILTER_LAST_BUILDS);
631	}
632}
633
634public void saveState(IMemento memento) {
635	super.saveState(memento);
636	memento.putBoolean(IPerformancesConstants.PRE_FILTER_BASELINE_BUILDS, this.filterBaselineBuilds.isChecked());
637	try {
638		this.preferences.flush();
639	} catch (BackingStoreException e) {
640		// ignore
641	}
642}
643
644/*
645 * (non-Javadoc)
646 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
647 */
648public void selectionChanged(SelectionChangedEvent event) {
649	if (this.propertyPage != null) {
650		this.propertyPage.selectionChanged(this, event.getSelection());
651	}
652}
653
654/**
655 * Passing the focus request to the viewer's control.
656 */
657public void setFocus() {
658	this.viewer.getControl().setFocus();
659}
660
661/*
662 * Set the view tooltip to reflect the DB connection kind.
663 */
664void setTitleToolTip() {
665	String title = DB_Results.getDbTitle();
666	if (title == null) {
667		// DB is not connected
668		int version = this.preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
669		title = "Eclipse v" + version + " - DB not connected";
670	}
671	setTitleToolTip(title);
672}
673
674/*
675 * Set/unset the database connection.
676 *
677void toogleDbConnection() {
678
679	// Toogle DB connection and store new state
680	boolean dbConnected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
681	DB_Results.DB_CONNECTION = !dbConnected;
682	getSiblingView().dbConnection.setChecked(DB_Results.DB_CONNECTION);
683	this.preferences.putBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, DB_Results.DB_CONNECTION);
684
685	// First close DB connection
686	if (!DB_Results.DB_CONNECTION) {
687		DB_Results.shutdown();
688	}
689
690	// Read local files if any
691	if (this.dataDir != null) {
692		readLocalFiles();
693	}
694
695	// Refresh views
696	refreshInput();
697	getSiblingView().refreshInput();
698}
699*/
700
701/*
702 * Update the filters from the stored list and apply them to the view.
703 */
704final void updateFilters() {
705	ViewerFilter[] filters = new ViewerFilter[this.viewFilters.size()];
706	this.viewFilters.toArray(filters);
707	this.viewer.setFilters(filters);
708}
709
710}