Home | History | Annotate | Download | only in ui
      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  *******************************************************************************/
     11 package org.eclipse.test.internal.performance.results.ui;
     12 
     13 import java.io.File;
     14 import java.util.Arrays;
     15 import java.util.Iterator;
     16 
     17 import org.osgi.service.prefs.BackingStoreException;
     18 
     19 import org.eclipse.test.internal.performance.PerformanceTestPlugin;
     20 import org.eclipse.test.internal.performance.results.db.DB_Results;
     21 import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
     22 import org.eclipse.test.internal.performance.results.utils.Util;
     23 import org.eclipse.test.performance.ui.UiPlugin;
     24 
     25 import org.eclipse.swt.SWT;
     26 import org.eclipse.swt.custom.CCombo;
     27 import org.eclipse.swt.events.ModifyEvent;
     28 import org.eclipse.swt.events.ModifyListener;
     29 import org.eclipse.swt.events.SelectionEvent;
     30 import org.eclipse.swt.events.SelectionListener;
     31 import org.eclipse.swt.layout.GridData;
     32 import org.eclipse.swt.layout.GridLayout;
     33 import org.eclipse.swt.widgets.Button;
     34 import org.eclipse.swt.widgets.Composite;
     35 import org.eclipse.swt.widgets.Control;
     36 import org.eclipse.swt.widgets.DirectoryDialog;
     37 import org.eclipse.swt.widgets.Display;
     38 import org.eclipse.swt.widgets.Group;
     39 import org.eclipse.swt.widgets.Label;
     40 import org.eclipse.swt.widgets.List;
     41 import org.eclipse.swt.widgets.Text;
     42 
     43 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
     44 import org.eclipse.core.runtime.preferences.InstanceScope;
     45 
     46 import org.eclipse.jface.dialogs.MessageDialog;
     47 import org.eclipse.jface.preference.IPreferenceStore;
     48 import org.eclipse.jface.preference.PreferencePage;
     49 
     50 import org.eclipse.ui.IWorkbench;
     51 import org.eclipse.ui.IWorkbenchPreferencePage;
     52 
     53 /**
     54  * Defines the 'Performances' preferences page.
     55  */
     56 public class PerformanceResultsPreferencePage extends PreferencePage
     57 	implements IWorkbenchPreferencePage, SelectionListener, ModifyListener, IPerformancesConstants {
     58 
     59 	private Button mVersionRadioButton;
     60 	private Button dVersionRadionButton;
     61 	private CCombo databaseLocationCombo;
     62 	private Button dbConnectionCheckBox;
     63 	private Button dbLocalBrowseButton;
     64 	private Button dbRelengRadioButton;
     65 	private Button dbLocalRadioButton;
     66 	private CCombo defaultDimensionCombo;
     67 	private CCombo lastBuildCombo;
     68 	private List resultsDimensionsList;
     69 	private CCombo milestonesCombo;
     70 	private Label dbLocationLabel;
     71 
     72 	// Status SWT objects
     73 	private Button statusValuesCheckBox;
     74 	private Button statusErrorNoneRadioButton;
     75 	private Button statusErrorNoticeableRadioButton;
     76 	private Button statusErrorSuspiciousRadioButton;
     77 	private Button statusErrorWeirdRadioButton;
     78 	private Button statusErrorInvalidRadioButton;
     79 	private Button statusSmallBuildValueCheckBox;
     80 	private Button statusSmallDeltaValueCheckBox;
     81 	private Button statusStatisticNoneRadioButton;
     82 	private Button statusStatisticErraticRadioButton;
     83 	private Button statusStatisticUnstableRadioButton;
     84 	private Text statusBuildsToConfirm;
     85 
     86 	// TODO See whether config descriptors need to be set as preferences or not...
     87 	// private Table configDescriptorsTable;
     88 
     89 	private BuildsView buildsView;
     90 
     91 /**
     92  * Utility method that creates a push button instance and sets the default
     93  * layout data.
     94  *
     95  * @param parent
     96  *            the parent for the new button
     97  * @param label
     98  *            the label for the new button
     99  * @return the newly-created button
    100  */
    101 private Button createCheckBox(Composite parent, String label) {
    102 	Button button = new Button(parent, SWT.CHECK);
    103 	button.setText(label);
    104 	button.addSelectionListener(this);
    105 	GridData data = new GridData();
    106 	data.horizontalAlignment = GridData.FILL;
    107 	data.horizontalSpan = 5;
    108 	button.setLayoutData(data);
    109 	return button;
    110 }
    111 
    112 /**
    113  * Create a text field specific for this application
    114  *
    115  * @param parent
    116  *            the parent of the new text field
    117  * @return the new text field
    118  */
    119 private CCombo createCombo(Composite parent) {
    120 	CCombo combo= new CCombo(parent, SWT.BORDER);
    121 	combo.addModifyListener(this);
    122 	GridData data = new GridData();
    123 	data.horizontalSpan = 3;
    124 	data.horizontalAlignment = GridData.FILL;
    125 	data.grabExcessHorizontalSpace = true;
    126 	data.verticalAlignment = GridData.CENTER;
    127 	data.grabExcessVerticalSpace = false;
    128 	combo.setLayoutData(data);
    129 	return combo;
    130 }
    131 
    132 
    133 /**
    134  * Creates composite control and sets the default layout data.
    135  *
    136  * @param parent
    137  *            the parent of the new composite
    138  * @param numColumns
    139  *            the number of columns for the new composite
    140  * @param hSpan TODO
    141  * @return the newly-created coposite
    142  */
    143 private Composite createComposite(Composite parent, int numColumns, int hSpan) {
    144 	Composite composite = new Composite(parent, SWT.NULL);
    145 
    146 	// GridLayout
    147 	GridLayout layout = new GridLayout();
    148 	layout.numColumns = numColumns;
    149 	composite.setLayout(layout);
    150 
    151 	// GridData
    152 	GridData data = new GridData();
    153 	data.verticalAlignment = GridData.FILL;
    154 	data.horizontalAlignment = GridData.FILL;
    155 	data.horizontalSpan = hSpan;
    156 	composite.setLayoutData(data);
    157 	return composite;
    158 }
    159 
    160 /**
    161  * (non-Javadoc) Method declared on PreferencePage
    162  */
    163 protected Control createContents(Composite parent) {
    164 
    165 	this.buildsView = (BuildsView) PerformancesView.getWorkbenchView("org.eclipse.test.internal.performance.results.ui.BuildsView");
    166 	if (this.buildsView == null) {
    167 		Label errorLabel = createLabel(parent, "No performances preferences can be set because the build view has not been created yet!", false);
    168 		errorLabel.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
    169 	} else {
    170 		// Eclipse version choice
    171 		Composite composite_eclipseVersion = createComposite(parent, 5, 1);
    172 		createLabel(composite_eclipseVersion, "Eclipse version", false);
    173 		Composite composite_versionChoice = createComposite(composite_eclipseVersion, 5, 1);
    174 		this.mVersionRadioButton = createRadioButton(composite_versionChoice, "v"+ECLIPSE_MAINTENANCE_VERSION);
    175 		this.dVersionRadionButton = createRadioButton(composite_versionChoice, "v"+ECLIPSE_DEVELOPMENT_VERSION);
    176 
    177 		// Database location
    178 		Composite compositeDatabase = createComposite(parent, 5, 1);
    179 		Group databaseGroup = createGroup(compositeDatabase, "Database", 5);
    180 		Composite compositeDatabaseConnection = createComposite(databaseGroup, 3, 5);
    181 		this.dbConnectionCheckBox = createCheckBox(compositeDatabaseConnection, "Connected");
    182 		this.dbRelengRadioButton = createRadioButton(compositeDatabaseConnection, "Releng");
    183 		this.dbLocalRadioButton = createRadioButton(compositeDatabaseConnection, "Local");
    184 		this.dbLocationLabel = createLabel(databaseGroup, "Location", false);
    185 		this.databaseLocationCombo = createCombo(databaseGroup);
    186 		this.databaseLocationCombo.setEditable(false);
    187 	    this.dbLocalBrowseButton = createPushButton(databaseGroup, "Browse");
    188 
    189 		// Status
    190 		Composite compositeStatus = createComposite(parent, 1, 3);
    191 		Group statusGroup = createGroup(compositeStatus, "Status", 1);
    192 		this.statusValuesCheckBox = createCheckBox(statusGroup, "Values");
    193 		this.statusValuesCheckBox.setToolTipText("Include numbers while writing status");
    194 		Group statusErrorGroup = createGroup(statusGroup, "Error level", 5);
    195 		statusErrorGroup.setToolTipText("Exclude from the written status failures depending on their build result error...");
    196 		this.statusErrorNoneRadioButton = createRadioButton(statusErrorGroup, "None");
    197 		this.statusErrorNoneRadioButton.setToolTipText("Do not exclude failures if they have a noticeable error");
    198 		this.statusErrorInvalidRadioButton = createRadioButton(statusErrorGroup, "Invalid");
    199 		this.statusErrorInvalidRadioButton.setToolTipText("Exclude all invalid failures (i.e. result error is over 100%)");
    200 		this.statusErrorWeirdRadioButton = createRadioButton(statusErrorGroup, "Weird");
    201 		this.statusErrorWeirdRadioButton.setToolTipText("Exclude all weird failures (i.e. result error is over 50%)");
    202 		this.statusErrorSuspiciousRadioButton = createRadioButton(statusErrorGroup, "Suspicious");
    203 		this.statusErrorSuspiciousRadioButton.setToolTipText("Exclude all suspicious failures (i.e. result error is over 25%)");
    204 		this.statusErrorNoticeableRadioButton = createRadioButton(statusErrorGroup, "Noticeable");
    205 		this.statusErrorNoticeableRadioButton.setToolTipText("Exclude all failures which have a noticeable error (i.e result error is over 3%)");
    206 		Group statusSmallGroup = createGroup(statusGroup, "Small value", 5);
    207 		statusErrorGroup.setToolTipText("Exclude from the written status failures depending on their value");
    208 		this.statusSmallBuildValueCheckBox = createCheckBox(statusSmallGroup, "Build value");
    209 		this.statusSmallBuildValueCheckBox.setToolTipText("Exclude all failures which have a build result value smaller than 100ms");
    210 		this.statusSmallDeltaValueCheckBox = createCheckBox(statusSmallGroup, "Delta value");
    211 		this.statusSmallDeltaValueCheckBox.setToolTipText("Exclude all failures which have a delta result value smaller than 100ms");
    212 		Group statusStatisticsGroup = createGroup(statusGroup, "Statistics", 5);
    213 		statusStatisticsGroup.setToolTipText("Exclude from the written status failures depending on build results statistics...");
    214 		this.statusStatisticNoneRadioButton = createRadioButton(statusStatisticsGroup, "None");
    215 		this.statusStatisticNoneRadioButton.setToolTipText("Do not exclude failures which have bad baseline results statistics (i.e. variation is over 10%)");
    216 		this.statusStatisticUnstableRadioButton = createRadioButton(statusStatisticsGroup, "Unstable");
    217 		this.statusStatisticUnstableRadioButton.setToolTipText("Exclude all failures which have unstable baseline results statistics (i.e. variation is between 10% and 20%)");
    218 		this.statusStatisticErraticRadioButton = createRadioButton(statusStatisticsGroup, "Erratic");
    219 		this.statusStatisticErraticRadioButton.setToolTipText("Exclude all failures which have erratic baseline results statistics (i.e. variation is over 20%)");
    220 		createLabel(statusGroup, "Builds to confirm:", false);
    221 		this.statusBuildsToConfirm = createTextField(statusGroup);
    222 		this.statusBuildsToConfirm.setToolTipText("The number of previous builds to take into account to confirm a regression");
    223 
    224 		// Milestones
    225 		Composite compositeMilestones = createComposite(parent, 3, 1);
    226 		createLabel(compositeMilestones, "Milestones", false);
    227 		this.milestonesCombo = createCombo(compositeMilestones);
    228 		this.milestonesCombo.setToolTipText("Enter the date of the milestone as yyyymmddHHMM");
    229 
    230 		// Last build
    231 		StringBuffer tooltip = new StringBuffer("Select the last build to display performance results\n");
    232 		tooltip.append("If set then performance results won't be displayed for any build after this date...");
    233 		String tooltipText = tooltip.toString();
    234 		Composite compositeLastBuild = createComposite(parent, 3, 1);
    235 	//	this.lastBuildCheckBox = createCheckBox(compositeLastBuild, "Until last build");
    236 		createLabel(compositeLastBuild, "Last build: ", false);
    237 		this.lastBuildCombo = createCombo(compositeLastBuild);
    238 		this.lastBuildCombo.setEditable(false);
    239 		this.lastBuildCombo.setToolTipText(tooltipText);
    240 		this.lastBuildCombo.add("");
    241 		initBuildsList();
    242 
    243 		// Default dimension layout
    244 		tooltip = new StringBuffer("Select the default dimension which will be used for performance results\n");
    245 		tooltip.append("When changed, the new selected dimension is automatically added to the dimensions list below...");
    246 		tooltipText = tooltip.toString();
    247 		Composite compositeDefaultDimension = createComposite(parent, 3, 1);
    248 		createLabel(compositeDefaultDimension, "Default dimension: ", false);
    249 		this.defaultDimensionCombo = createCombo(compositeDefaultDimension);
    250 		this.defaultDimensionCombo.setEditable(false);
    251 		this.defaultDimensionCombo.setToolTipText(tooltipText);
    252 
    253 		// Results dimensions layout
    254 		tooltip = new StringBuffer("Select the dimensions which will be used while generating performance results\n");
    255 		tooltip.append("When changed, the default dimension above is automatically added to the new list...");
    256 		tooltipText = tooltip.toString();
    257 		Composite compositeResultsDimensions = createComposite(parent, 3, 1);
    258 		createLabel(compositeResultsDimensions, "Results dimensions: ", true/*beginning*/);
    259 		this.resultsDimensionsList = createList(compositeResultsDimensions);
    260 		this.resultsDimensionsList.setToolTipText(tooltipText);
    261 
    262 		// Config descriptors layout
    263 		/* TODO See whether config descriptors need to be set as preferences or not...
    264 		Composite compositeConfigDescriptors = createComposite(parent, 3);
    265 		createLabel(compositeConfigDescriptors, "Config descriptors: ", false);
    266 		this.configDescriptorsTable = createTable(compositeConfigDescriptors);
    267 		TableColumn firstColumn = new TableColumn(this.configDescriptorsTable, SWT.LEFT);
    268 		firstColumn.setText ("Name");
    269 		firstColumn.setWidth(50);
    270 		TableColumn secondColumn = new TableColumn(this.configDescriptorsTable, SWT.FILL | SWT.LEFT);
    271 		secondColumn.setText ("Description");
    272 		secondColumn.setWidth(300);
    273 		*/
    274 
    275 		// init values
    276 		initializeValues();
    277 	}
    278 
    279 	// font = null;
    280 	Composite contents = new Composite(parent, SWT.NULL);
    281 	contents.pack(true);
    282 	return contents;
    283 }
    284 
    285 /**
    286  * Utility method that creates a label instance and sets the default layout
    287  * data.
    288  *
    289  * @param parent
    290  *            the parent for the new label
    291  * @param text
    292  *            the text for the new label
    293  * @return the new label
    294  */
    295 private Group createGroup(Composite parent, String text, int columns) {
    296 	Group group = new Group(parent, SWT.NONE);
    297 	group.setLayout(new GridLayout(columns, false));
    298 	group.setText(text);
    299 	GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
    300 //	data.horizontalSpan = 1;
    301 	group.setLayoutData(data);
    302 	return group;
    303 }
    304 
    305 /**
    306  * Utility method that creates a label instance and sets the default layout
    307  * data.
    308  *
    309  * @param parent
    310  *            the parent for the new label
    311  * @param text
    312  *            the text for the new label
    313  * @param beginning TODO
    314  * @return the new label
    315  */
    316 private Label createLabel(Composite parent, String text, boolean beginning) {
    317 	Label label = new Label(parent, SWT.BEGINNING|SWT.LEFT);
    318 	label.setText(text);
    319 	GridData data = new GridData();
    320 	data.horizontalAlignment = GridData.FILL;
    321 	data.verticalAlignment = beginning ? GridData.BEGINNING : GridData.CENTER;
    322 	label.setLayoutData(data);
    323 	return label;
    324 }
    325 
    326 /**
    327  * Create a text field specific for this application
    328  *
    329  * @param parent
    330  *            the parent of the new text field
    331  * @return the new text field
    332  */
    333 private List createList(Composite parent) {
    334 	List list = new List(parent, SWT.MULTI | SWT.BORDER);
    335 	list.addSelectionListener(this);
    336 	GridData data = new GridData();
    337 	data.horizontalSpan = 2;
    338 	data.horizontalAlignment = GridData.FILL;
    339 	data.grabExcessHorizontalSpace = true;
    340 	data.verticalAlignment = GridData.CENTER;
    341 	data.grabExcessVerticalSpace = false;
    342 	list.setLayoutData(data);
    343 	return list;
    344 }
    345 
    346 /**
    347  * Utility method that creates a push button instance and sets the default
    348  * layout data.
    349  *
    350  * @param parent
    351  *            the parent for the new button
    352  * @param label
    353  *            the label for the new button
    354  * @return the newly-created button
    355  */
    356 private Button createPushButton(Composite parent, String label) {
    357 	Button button = new Button(parent, SWT.PUSH);
    358 	button.setText(label);
    359 	button.addSelectionListener(this);
    360 	GridData data = new GridData();
    361 	data.horizontalAlignment = SWT.LEFT;
    362 	data.grabExcessHorizontalSpace = true;
    363 //	data.horizontalSpan = 2;
    364 	data.minimumWidth = 100;
    365 	button.setLayoutData(data);
    366 	return button;
    367 }
    368 
    369 /**
    370  * Utility method that creates a radio button instance and sets the default
    371  * layout data.
    372  *
    373  * @param parent
    374  *            the parent for the new button
    375  * @param label
    376  *            the label for the new button
    377  * @return the newly-created button
    378  */
    379 private Button createRadioButton(Composite parent, String label) {
    380 	Button button = new Button(parent, SWT.RADIO | SWT.LEFT);
    381 	button.setText(label);
    382 	button.addSelectionListener(this);
    383 	GridData data = new GridData();
    384 	button.setLayoutData(data);
    385 	return button;
    386 }
    387 
    388 /*
    389  * Create a text field specific for this application
    390  *
    391  * @param parent
    392  *            the parent of the new text field
    393  * @return the new text field
    394  *
    395 private Table createTable(Composite parent) {
    396 	Table table = new Table(parent, SWT.BORDER);
    397 	table.setLinesVisible (true);
    398 	table.setHeaderVisible (true);
    399 	GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
    400 	gridData.heightHint = 150;
    401 	table.setLayoutData(gridData);
    402 	return table;
    403 }
    404 */
    405 
    406 /*
    407  * Create a text field specific for this application
    408  *
    409  * @param parent
    410  *            the parent of the new text field
    411  * @return the new text field
    412  */
    413 private Text createTextField(Composite parent) {
    414 	Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
    415 	text.addModifyListener(this);
    416 	GridData data = new GridData();
    417 	data.horizontalAlignment = GridData.FILL;
    418 	data.grabExcessHorizontalSpace = true;
    419 	data.verticalAlignment = GridData.CENTER;
    420 	data.grabExcessVerticalSpace = false;
    421 	text.setLayoutData(data);
    422 	return text;
    423 }
    424 
    425 /**
    426  * The <code>ReadmePreferencePage</code> implementation of this
    427  * <code>PreferencePage</code> method returns preference store that belongs to
    428  * the our plugin. This is important because we want to store our preferences
    429  * separately from the workbench.
    430  */
    431 protected IPreferenceStore doGetPreferenceStore() {
    432 	return UiPlugin.getDefault().getPreferenceStore();
    433 }
    434 
    435 /**
    436  * @return The dialog title
    437  */
    438 String getDialogTitle() {
    439 	String title = DB_Results.getDbTitle();
    440 	if (title == null) {
    441 		// DB is not connected
    442 		int version;
    443 		if (this.mVersionRadioButton.getSelection()) {
    444 			version = ECLIPSE_MAINTENANCE_VERSION;
    445 		} else {
    446 			version = ECLIPSE_DEVELOPMENT_VERSION;
    447 		}
    448 		title = "Eclipse " + version + " - DB not connected";
    449 	}
    450 	return title;
    451 }
    452 
    453 /*
    454  * Get the directory path using the given location as default.
    455  */
    456 private String getDirectoryPath(String location) {
    457 	DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.OPEN);
    458 	dialog.setText(getDialogTitle());
    459 	dialog.setMessage("Select local database directory:");
    460 	dialog.setFilterPath(location);
    461 	String path = dialog.open();
    462 	if (path != null) {
    463 		File dir = new File(path);
    464 		if (dir.exists() && dir.isDirectory()) {
    465 			return dir.getAbsolutePath();
    466 		}
    467 	}
    468 	return null;
    469 }
    470 
    471 /*
    472  * (non-Javadoc) Method declared on IWorkbenchPreferencePage
    473  */
    474 public void init(IWorkbench workbench) {
    475 	// do nothing
    476 }
    477 
    478 /*
    479  * Init he contents of the dimensions list controls.
    480  */
    481 void initDimensionsLists() {
    482 	// Dimensions lists
    483 	java.util.List dimensions = PerformanceTestPlugin.getDimensions();
    484 	Iterator names = dimensions.iterator();
    485 	while (names.hasNext()) {
    486 		String name = (String) names.next();
    487 		this.defaultDimensionCombo.add(name);
    488 		this.resultsDimensionsList.add(name);
    489 	}
    490 }
    491 
    492 /*
    493  * Init he contents of the dimensions list controls.
    494  */
    495 private void initBuildsList() {
    496 	String[] builds = DB_Results.getBuilds();
    497 	Arrays.sort(builds, Util.BUILD_DATE_COMPARATOR);
    498 	int length = builds.length;
    499 	for (int i=length-1; i>=0; i--) {
    500 		this.lastBuildCombo.add(builds[i]);
    501 	}
    502 }
    503 
    504 /**
    505  * Initializes states of the controls using default values in the preference
    506  * store.
    507  */
    508 private void initializeDefaults() {
    509 	IPreferenceStore store = getPreferenceStore();
    510 
    511 	// Init default database values
    512 	this.dbConnectionCheckBox.setSelection(store.getDefaultBoolean(PRE_DATABASE_CONNECTION));
    513 	this.dbRelengRadioButton.setSelection(false);
    514 	this.dbLocalRadioButton.setSelection(false);
    515 	final boolean dbLocal = store.getDefaultBoolean(PRE_DATABASE_LOCAL);
    516 	if (dbLocal) {
    517 		this.dbLocalRadioButton.setSelection(true);
    518 	} else {
    519 		this.dbRelengRadioButton.setSelection(true);
    520 	}
    521 	this.databaseLocationCombo.removeAll();
    522 	this.databaseLocationCombo.setText(store.getDefaultString(PRE_DATABASE_LOCATION));
    523 	updateDatabaseGroup();
    524 
    525 	// Init default status values
    526 	int writeStatus = store.getDefaultInt(PRE_WRITE_STATUS);
    527 	initStatusValues(writeStatus);
    528 
    529 	// Init eclipse version
    530 	this.mVersionRadioButton.setSelection(false);
    531 	this.dVersionRadionButton.setSelection(false);
    532 	int version = store.getDefaultInt(PRE_ECLIPSE_VERSION);
    533 	if (version == ECLIPSE_MAINTENANCE_VERSION) {
    534 		this.mVersionRadioButton.setSelection(true);
    535 	} else {
    536 		this.dVersionRadionButton.setSelection(true);
    537 	}
    538     updateBrowseButtonToolTip(version);
    539 
    540 	// Milestones
    541 	this.milestonesCombo.removeAll();
    542 	String prefix = PRE_MILESTONE_BUILDS + "." + version;
    543 	String milestone = store.getDefaultString(prefix + "0");
    544 	int index = 0;
    545 	while (milestone != null && milestone.length() > 0) {
    546 		this.milestonesCombo.add(milestone);
    547 		milestone = store.getDefaultString(prefix + ++index);
    548 	}
    549 
    550 	// Init last build
    551 	String lastBuild = store.getDefaultString(PRE_LAST_BUILD);
    552 //	if (lastBuild.length() == 0) {
    553 //		this.lastBuildCheckBox.setSelection(false);
    554 //		this.lastBuildCombo.setEnabled(false);
    555 //	} else {
    556 //		this.lastBuildCombo.setEnabled(true);
    557 //	}
    558 	this.lastBuildCombo.setText(lastBuild);
    559 
    560 	// Init default default dimension
    561 	String defaultDimension = store.getDefaultString(PRE_DEFAULT_DIMENSION);
    562 	this.defaultDimensionCombo.setText(defaultDimension);
    563 
    564 	// Init default generated dimensions
    565 	this.resultsDimensionsList.add(store.getDefaultString(PRE_RESULTS_DIMENSION+".0"));
    566 	this.resultsDimensionsList.add(store.getDefaultString(PRE_RESULTS_DIMENSION+".1"));
    567 }
    568 
    569 /**
    570  * Initializes states of the controls from the preference store.
    571  */
    572 private void initializeValues() {
    573 	IPreferenceStore store = getPreferenceStore();
    574 
    575 	// Init database info
    576 	this.dbConnectionCheckBox.setSelection(store.getBoolean(PRE_DATABASE_CONNECTION));
    577 	final boolean dbLocal = store.getBoolean(PRE_DATABASE_LOCAL);
    578 	if (dbLocal) {
    579 		this.dbLocalRadioButton.setSelection(true);
    580 		this.dbRelengRadioButton.setToolTipText("");
    581 	} else {
    582 		this.dbRelengRadioButton.setSelection(true);
    583 		this.dbRelengRadioButton.setToolTipText(NETWORK_DATABASE_LOCATION);
    584 	}
    585 	this.databaseLocationCombo.removeAll();
    586 	this.databaseLocationCombo.setText(store.getString(PRE_DATABASE_LOCATION));
    587 	for (int i = 0; i < 3; i++) {
    588 		String history = store.getString(PRE_DATABASE_LOCATION + "." + i);
    589 		if (history.length() == 0)
    590 			break;
    591 		this.databaseLocationCombo.add(history);
    592 	}
    593 	updateDatabaseGroup();
    594 
    595 	// Init status values
    596 	int writeStatus = store.getInt(PRE_WRITE_STATUS);
    597 	initStatusValues(writeStatus);
    598 
    599 	// Init eclipse version
    600 	int version = store.getInt(PRE_ECLIPSE_VERSION);
    601 	if (version == ECLIPSE_MAINTENANCE_VERSION) {
    602 		this.mVersionRadioButton.setSelection(true);
    603 	} else {
    604 		this.dVersionRadionButton.setSelection(true);
    605 	}
    606     updateBrowseButtonToolTip(version);
    607 
    608 	// Milestones
    609 	String prefix = PRE_MILESTONE_BUILDS + "." + version;
    610 	int index = 0;
    611 	String milestone = store.getString(prefix + index);
    612 	while (milestone != null && milestone.length() > 0) {
    613 		this.milestonesCombo.add(milestone);
    614 		milestone = store.getString(prefix + ++index);
    615 	}
    616 
    617 	// Init last build
    618 	String lastBuild = store.getString(PRE_LAST_BUILD);
    619 //	if (lastBuild.length() == 0) {
    620 //		this.lastBuildCheckBox.setSelection(false);
    621 //		this.lastBuildCombo.setEnabled(false);
    622 //	} else {
    623 //		this.lastBuildCombo.setEnabled(true);
    624 //	}
    625 	this.lastBuildCombo.setText(lastBuild);
    626 
    627 	// Init composite lists
    628 	initDimensionsLists();
    629 
    630 	// Init default dimension
    631 	String defaultDimension = store.getString(PRE_DEFAULT_DIMENSION);
    632 	this.defaultDimensionCombo.setText(defaultDimension);
    633 
    634 	// Init generated dimensions
    635 	int count = this.resultsDimensionsList.getItemCount();
    636 	int[] indices = new int[count];
    637 	int n = 0;
    638 	String resultsDimension = store.getString(PRE_RESULTS_DIMENSION + "." + n);
    639 	while (resultsDimension.length() > 0) {
    640 		indices[n++] = this.resultsDimensionsList.indexOf(resultsDimension);
    641 		resultsDimension = store.getString(PRE_RESULTS_DIMENSION + "." + n);
    642 	}
    643 	if (n < count) {
    644 		System.arraycopy(indices, 0, indices = new int[n], 0, n);
    645 	}
    646 	this.resultsDimensionsList.select(indices);
    647 
    648 	// Init config descriptors
    649 	/* TODO See whether config descriptors need to be set as preferences or not...
    650 	this.configDescriptorsTable.clearAll();
    651 	int d = 0;
    652 	String descriptorName = store.getString(PRE_CONFIG_DESCRIPTOR_NAME + "." + d);
    653 	String descriptorDescription = store.getString(PRE_CONFIG_DESCRIPTOR_DESCRIPTION + "." + d++);
    654 	while (descriptorName.length() > 0) {
    655 		TableItem tableItem = new TableItem (this.configDescriptorsTable, SWT.NONE);
    656 		tableItem.setText (0, descriptorName);
    657 		tableItem.setText (1, descriptorDescription);
    658 		descriptorName = store.getString(PRE_CONFIG_DESCRIPTOR_NAME + "." + d);
    659 		descriptorDescription = store.getString(PRE_CONFIG_DESCRIPTOR_DESCRIPTION + "." + d++);
    660 	}
    661 	*/
    662 }
    663 
    664 /**
    665  * @param writeStatus The observed status to write
    666  */
    667 private void initStatusValues(int writeStatus) {
    668 	this.statusValuesCheckBox.setSelection((writeStatus & STATUS_VALUES) != 0);
    669 	this.statusErrorNoneRadioButton.setSelection(false);
    670 	this.statusErrorNoticeableRadioButton.setSelection(false);
    671 	this.statusErrorSuspiciousRadioButton.setSelection(false);
    672 	this.statusErrorWeirdRadioButton.setSelection(false);
    673 	this.statusErrorInvalidRadioButton.setSelection(false);
    674 	switch (writeStatus & STATUS_ERROR_LEVEL_MASK) {
    675 		case STATUS_ERROR_NONE:
    676 			this.statusErrorNoneRadioButton.setSelection(true);
    677 			break;
    678 		case STATUS_ERROR_NOTICEABLE:
    679 			this.statusErrorNoticeableRadioButton.setSelection(true);
    680 			break;
    681 		case STATUS_ERROR_SUSPICIOUS:
    682 			this.statusErrorSuspiciousRadioButton.setSelection(true);
    683 			break;
    684 		case STATUS_ERROR_WEIRD:
    685 			this.statusErrorWeirdRadioButton.setSelection(true);
    686 			break;
    687 		case STATUS_ERROR_INVALID:
    688 			this.statusErrorInvalidRadioButton.setSelection(true);
    689 			break;
    690 	}
    691 	this.statusSmallBuildValueCheckBox.setSelection(false);
    692 	this.statusSmallDeltaValueCheckBox.setSelection(false);
    693 	switch (writeStatus & STATUS_SMALL_VALUE_MASK) {
    694 		case STATUS_SMALL_VALUE_BUILD:
    695 			this.statusSmallBuildValueCheckBox.setSelection(true);
    696 			break;
    697 		case STATUS_SMALL_VALUE_DELTA:
    698 			this.statusSmallDeltaValueCheckBox.setSelection(true);
    699 			break;
    700 	}
    701 	this.statusStatisticNoneRadioButton.setSelection(false);
    702 	this.statusStatisticErraticRadioButton.setSelection(false);
    703 	this.statusStatisticUnstableRadioButton.setSelection(false);
    704 	switch (writeStatus & STATUS_STATISTICS_MASK) {
    705 		case 0:
    706 			this.statusStatisticNoneRadioButton.setSelection(true);
    707 			break;
    708 		case STATUS_STATISTICS_ERRATIC:
    709 			this.statusStatisticErraticRadioButton.setSelection(true);
    710 			break;
    711 		case STATUS_STATISTICS_UNSTABLE:
    712 			this.statusStatisticUnstableRadioButton.setSelection(true);
    713 			break;
    714 	}
    715 	this.statusBuildsToConfirm.setText(String.valueOf(writeStatus & STATUS_BUILDS_NUMBER_MASK));
    716 }
    717 
    718 /**
    719  * (non-Javadoc) Method declared on ModifyListener
    720  */
    721 public void modifyText(ModifyEvent event) {
    722 
    723 	// Add default dimension to results if necessary
    724 	if (event.getSource() == this.defaultDimensionCombo) {
    725 		String[] resultsDimensions = this.resultsDimensionsList.getSelection();
    726 		int length = resultsDimensions.length;
    727 		String defaultDimension = this.defaultDimensionCombo.getText();
    728 		for (int i = 0; i < length; i++) {
    729 			if (resultsDimensions[i].equals(defaultDimension)) {
    730 				// Default dim is already set as a results dimension, hence nothing has to be done
    731 				return;
    732 			}
    733 		}
    734 		System.arraycopy(resultsDimensions, 0, resultsDimensions = new String[length + 1], 0, length);
    735 		resultsDimensions[length] = defaultDimension;
    736 		this.resultsDimensionsList.setSelection(resultsDimensions);
    737 	}
    738 
    739 	// Add default dimension to results if necessary
    740 	if (event.getSource() == this.milestonesCombo) {
    741 
    742 		// Verify the only digits are entered
    743 		String milestoneDate = this.milestonesCombo.getText();
    744 		final int mLength = milestoneDate.length();
    745 		if (mLength > 0) {
    746 			for (int i=0; i<mLength; i++) {
    747 				if (!Character.isDigit(milestoneDate.charAt(i))) {
    748 					String[] items = this.milestonesCombo.getItems();
    749 					int length = items.length;
    750 					for (int j=0; j<length; j++) {
    751 						if (items[j].equals(milestoneDate)) {
    752 							// already existing milestone, leave silently
    753 							if (MessageDialog.openQuestion(getShell(), getDialogTitle(), "Do you want to select milestone "+milestoneDate+" as the last build?")) {
    754 								String builds[] = this.lastBuildCombo.getItems();
    755 								int bLength = builds.length;
    756 								String milestone = milestoneDate.substring(milestoneDate.indexOf('-')+1);
    757 								for (int b=0; b<bLength; b++) {
    758 									if (builds[b].length() > 0 && Util.getBuildDate(builds[b]).equals(milestone)) {
    759 										this.lastBuildCombo.select(b);
    760 										break;
    761 									}
    762 								}
    763 							}
    764 							return;
    765 						}
    766 					}
    767 					openMilestoneErrorMessage(milestoneDate);
    768 					return;
    769 				}
    770 			}
    771 		}
    772 
    773 		// Do not verify further until a complete milestone date is entered
    774 		if (mLength < 12) return;
    775 
    776 		// Verify the digits
    777 		try {
    778 			String str = milestoneDate.substring(0, 4);
    779 			int year = Integer.parseInt(str);
    780 			if (year < 2009 || year > 2020) { // 2020 should be enough!
    781 				MessageDialog.openError(getShell(), getDialogTitle(), milestoneDate+": "+str+" is an invalid year, only value between 2009 and 2020 is accepted!");
    782 				return;
    783 			}
    784 			str = milestoneDate.substring(4, 6);
    785 			int month = Integer.parseInt(str);
    786 			if (month <= 0 || month > 12) {
    787 				MessageDialog.openError(getShell(), getDialogTitle(), milestoneDate+": "+str+" is an invalid month, it should be only from 01 to 12!");
    788 				return;
    789 			}
    790 			str = milestoneDate.substring(6, 8);
    791 			int day = Integer.parseInt(str);
    792 			if (day <= 0 || day > 31) {
    793 				// TODO improve this verification
    794 				MessageDialog.openError(getShell(), getDialogTitle(), milestoneDate+": "+str+" is an invalid day, it should be only from 01 to 31!");
    795 				return;
    796 			}
    797 			str = milestoneDate.substring(8, 10);
    798 			int hour = Integer.parseInt(str);
    799 			if (hour < 0 || hour > 23) {
    800 				MessageDialog.openError(getShell(), getDialogTitle(), milestoneDate+": "+str+" is an invalid hour, it should be only from 00 to 23!");
    801 				return;
    802 			}
    803 			str = milestoneDate.substring(10, 12);
    804 			int min = Integer.parseInt(str);
    805 			if (min < 0 || min > 59) {
    806 				MessageDialog.openError(getShell(), getDialogTitle(), milestoneDate+": "+str+" is invalid minutes, it should be only from 00 to 59!");
    807 				return;
    808 			}
    809 		}
    810 		catch (NumberFormatException nfe) {
    811 			openMilestoneErrorMessage(milestoneDate);
    812 		}
    813 
    814 		// Get combo info
    815 		String[] milestones = this.milestonesCombo.getItems();
    816 		int length = milestones.length;
    817 		String lastMilestone = length == 0 ? null : milestones[length-1];
    818 
    819 		// Verify that the added milestone is valid
    820 		final String databaseLocation = this.databaseLocationCombo.getText();
    821 		char version = databaseLocation.charAt(databaseLocation.length()-1);
    822 
    823 		// Verify that the milestone follow the last one
    824 		String milestoneName;
    825 		if (lastMilestone == null) {
    826 			// No previous last milestone
    827 			milestoneName = "M1";
    828 		} else {
    829 			// Compare with last milestone
    830 			if (lastMilestone.charAt(0) == 'M') {
    831 				char digit = lastMilestone.charAt(1);
    832 				if (digit == '6') {
    833 					// M6 is the last dvpt milestone
    834 					milestoneName = "RC1";
    835 				} else {
    836 					milestoneName = "M" +((char)(digit+1));
    837 				}
    838 			} else if (lastMilestone.startsWith("RC")) {
    839 				char digit = lastMilestone.charAt(2);
    840 				if (digit == '4') {
    841 					// RC4 is the last release candidate milestone
    842 					milestoneName = "R3_"+version;
    843 				} else {
    844 					milestoneName = "RC" +((char)(digit+1));
    845 				}
    846 			} else if (lastMilestone.startsWith("R3_"+version+"-")) {
    847 				milestoneName = "R3_" + version + "_1";
    848 			} else if (lastMilestone.startsWith("R3_"+version+"_")) {
    849 				char digit = lastMilestone.charAt(5);
    850 				milestoneName = "R3_" + version + "_" + ((char)(digit+1));
    851 			} else {
    852 				MessageDialog.openError(getShell(), getDialogTitle(), "Unexpected last milestone name: "+lastMilestone+"!");
    853 				return;
    854 			}
    855 
    856 			// Verify the date of the new milestone
    857 			int lastMilestoneDash = lastMilestone.indexOf('-');
    858 			final String lastMilestoneDate = lastMilestone.substring(lastMilestoneDash+1);
    859 			if (milestoneDate.compareTo(lastMilestoneDate) <= 0) {
    860 				// TODO improve this verification
    861 				MessageDialog.openError(getShell(), getDialogTitle(), "Milestone "+milestoneDate+" should be after the last milestone: "+lastMilestoneDate+"!");
    862 				return;
    863 			}
    864 		}
    865 
    866 		// Verification are ok, ask to add the milestone
    867 		final String milestone = milestoneName + "-" + milestoneDate;
    868 		if (MessageDialog.openConfirm(getShell(), getDialogTitle(), milestoneDate+" is a valid milestone date.\n\nDo you want to add the milestone '"+milestone+"' to the preferences?")) {
    869 			this.milestonesCombo.add(milestone);
    870 			this.milestonesCombo.setText("");
    871 		}
    872 	}
    873 
    874 	// Verify the 'builds to confirm' number
    875 	if (event.getSource() == this.statusBuildsToConfirm) {
    876 		try {
    877 			int number = Integer.parseInt(this.statusBuildsToConfirm.getText());
    878 			if (number < 1 ) {
    879 				this.statusBuildsToConfirm.setText("1");
    880 			} else {
    881 				int buildsNumber = DB_Results.getBuildsNumber();
    882 				if (number > buildsNumber) {
    883 					this.statusBuildsToConfirm.setText(String.valueOf(buildsNumber));
    884 				}
    885 			}
    886 		}
    887 		catch (NumberFormatException nfe) {
    888 			this.statusBuildsToConfirm.setText("1");
    889 		}
    890 	}
    891 }
    892 
    893 
    894 /**
    895  * @param milestone
    896  */
    897 void openMilestoneErrorMessage(String milestone) {
    898 	MessageDialog.openError(getShell(), getDialogTitle(), milestone+" is an invalid milestone date. Only 'yyyymmddHHMM' format is accepted!");
    899 }
    900 
    901 /*
    902  * (non-Javadoc) Method declared on PreferencePage
    903  */
    904 protected void performDefaults() {
    905 	super.performDefaults();
    906 	initializeDefaults();
    907 }
    908 
    909 /*
    910  * (non-Javadoc) Method declared on PreferencePage
    911  */
    912 public boolean performOk() {
    913 	final boolean hasBuildsView = this.buildsView != null;
    914 	if (hasBuildsView) {
    915 		storeValues();
    916 		try {
    917 			IEclipsePreferences preferences = new InstanceScope().getNode(PLUGIN_ID);
    918 			preferences.flush();
    919 			this.buildsView.resetView();
    920 		} catch (BackingStoreException e) {
    921 			e.printStackTrace();
    922 			return false;
    923 		}
    924 	}
    925 	return true;
    926 }
    927 
    928 /**
    929  * Stores the values of the controls back to the preference store.
    930  */
    931 private void storeValues() {
    932 	IPreferenceStore store = getPreferenceStore();
    933 
    934 	// Set version
    935 	int version;
    936 	if (this.mVersionRadioButton.getSelection()) {
    937 		version = ECLIPSE_MAINTENANCE_VERSION;
    938 	} else {
    939 		version = ECLIPSE_DEVELOPMENT_VERSION;
    940 	}
    941 	store.setValue(PRE_ECLIPSE_VERSION, version);
    942 
    943 	// Set database values
    944 	store.setValue(PRE_DATABASE_CONNECTION, this.dbConnectionCheckBox.getSelection());
    945 	final boolean dbLocal = this.dbLocalRadioButton.getSelection();
    946 	store.setValue(PRE_DATABASE_LOCAL, dbLocal);
    947 	String location = this.databaseLocationCombo.getText();
    948 	if (dbLocal) {
    949 		store.setValue(PRE_DATABASE_LOCATION, location);
    950 	} else {
    951 		store.setValue(PRE_DATABASE_LOCATION, NETWORK_DATABASE_LOCATION);
    952 	}
    953 	int count = this.databaseLocationCombo.getItemCount();
    954 	for (int i=0; i<count; i++) {
    955 		String item = this.databaseLocationCombo.getItem(i);
    956 		if (item.equals(location)) {
    957 			this.databaseLocationCombo.remove(i);
    958 			break;
    959 		}
    960 	}
    961 	if (dbLocal) {
    962 		this.databaseLocationCombo.add(location, 0);
    963 	}
    964 	int i=0;
    965 	for (; i<count; i++) {
    966 		String item = this.databaseLocationCombo.getItem(i);
    967 		if (item.length() == 0) break;
    968 		store.setValue(PRE_DATABASE_LOCATION+"."+i, item);
    969 	}
    970 	while (store.getString(PRE_DATABASE_LOCATION+"."+i).length() > 0) {
    971 		store.setToDefault(PRE_DATABASE_LOCATION+"."+i);
    972 		i++;
    973 	}
    974 
    975 	// Set status values
    976 	int writeStatus = 0;
    977 	if (this.statusValuesCheckBox.getSelection()) {
    978 		writeStatus |= STATUS_VALUES;
    979 	}
    980 	if (this.statusErrorNoneRadioButton.getSelection()) {
    981 		writeStatus |= STATUS_ERROR_NONE;
    982 	} else if (this.statusErrorNoticeableRadioButton.getSelection()) {
    983 		writeStatus |= STATUS_ERROR_NOTICEABLE;
    984 	} else if (this.statusErrorSuspiciousRadioButton.getSelection()) {
    985 		writeStatus |= STATUS_ERROR_SUSPICIOUS;
    986 	} else if (this.statusErrorWeirdRadioButton.getSelection()) {
    987 		writeStatus |= STATUS_ERROR_WEIRD;
    988 	} else if (this.statusErrorInvalidRadioButton.getSelection()) {
    989 		writeStatus |= STATUS_ERROR_INVALID;
    990 	}
    991 	if (this.statusSmallBuildValueCheckBox.getSelection()) {
    992 		writeStatus |= STATUS_SMALL_VALUE_BUILD;
    993 	}
    994 	if (this.statusSmallDeltaValueCheckBox.getSelection()) {
    995 		writeStatus |= STATUS_SMALL_VALUE_DELTA;
    996 	}
    997 	if (this.statusStatisticNoneRadioButton.getSelection()) {
    998 		writeStatus &= ~STATUS_STATISTICS_MASK;
    999 	} else if (this.statusStatisticErraticRadioButton.getSelection()) {
   1000 		writeStatus |= STATUS_STATISTICS_ERRATIC;
   1001 	} else if (this.statusStatisticUnstableRadioButton.getSelection()) {
   1002 		writeStatus |= STATUS_STATISTICS_UNSTABLE;
   1003 	}
   1004 	writeStatus += Integer.parseInt(this.statusBuildsToConfirm.getText());
   1005 	store.setValue(PRE_WRITE_STATUS, writeStatus);
   1006 
   1007 	// Set milestones
   1008 	String prefix = PRE_MILESTONE_BUILDS + "." + version;
   1009 	count  = this.milestonesCombo.getItemCount();
   1010 	for (i=0; i<count; i++) {
   1011 		store.putValue(prefix + i, this.milestonesCombo.getItem(i));
   1012 	}
   1013 	Util.setMilestones(this.milestonesCombo.getItems());
   1014 
   1015 	// Unset previous additional milestones
   1016 	String milestone = store.getString(prefix + count);
   1017 	while (milestone != null && milestone.length() > 0) {
   1018 		store.putValue(prefix + count++, "");
   1019 		milestone = store.getString(prefix + count);
   1020 	}
   1021 
   1022 	// Set last build
   1023 	String lastBuild = this.lastBuildCombo.getText();
   1024 	store.putValue(PRE_LAST_BUILD, lastBuild);
   1025 
   1026 	// Set default dimension
   1027 	String defaultDimension = this.defaultDimensionCombo.getText();
   1028 	store.putValue(PRE_DEFAULT_DIMENSION, defaultDimension);
   1029 	DB_Results.setDefaultDimension(defaultDimension);
   1030 
   1031 	// Set generated dimensions
   1032 	int[] indices = this.resultsDimensionsList.getSelectionIndices();
   1033 	int length = indices.length;
   1034 	String[] dimensions = new String[length];
   1035 	if (length > 0) {
   1036 		for (i = 0; i < indices.length; i++) {
   1037 			dimensions[i] = this.resultsDimensionsList.getItem(indices[i]);
   1038 			store.putValue(PRE_RESULTS_DIMENSION + "." + i, dimensions[i]);
   1039 		}
   1040 	}
   1041 	int currentLength = DB_Results.getResultsDimensions().length;
   1042 	if (currentLength > length) {
   1043 		for (i = currentLength - 1; i >= length; i--) {
   1044 			store.putValue(PRE_RESULTS_DIMENSION + "." + i, ""); // reset extra dimensions
   1045 		}
   1046 	}
   1047 	DB_Results.setResultsDimensions(dimensions);
   1048 
   1049 	// Set config descriptors
   1050 	/* TODO See whether config descriptors need to be set as preferences or not...
   1051 	TableItem[] items = this.configDescriptorsTable.getItems();
   1052 	length = items.length;
   1053 	for (int i = 0; i < length; i++) {
   1054 		TableItem item = items[i];
   1055 		store.putValue(PRE_CONFIG_DESCRIPTOR_NAME + "." + i, item.getText(0));
   1056 		store.putValue(PRE_CONFIG_DESCRIPTOR_DESCRIPTION + "." + i, item.getText(1));
   1057 	}
   1058 	*/
   1059 }
   1060 
   1061 /**
   1062  * (non-Javadoc) Method declared on SelectionListener
   1063  */
   1064 public void widgetDefaultSelected(SelectionEvent event) {
   1065 }
   1066 
   1067 /**
   1068  * (non-Javadoc) Method declared on SelectionListener
   1069  */
   1070 public void widgetSelected(SelectionEvent event) {
   1071 
   1072 	// As for directory when 'Local' button is pushed
   1073 	final Object source = event.getSource();
   1074 	if (source == this.dbLocalBrowseButton) {
   1075 		String location = this.databaseLocationCombo.getText();
   1076 		String path = getDirectoryPath(location);
   1077 		if (path != null) {
   1078 			// First verify that the selected dir was correct
   1079 			int version;
   1080 			if (this.mVersionRadioButton.getSelection()) {
   1081 				version = ECLIPSE_MAINTENANCE_VERSION;
   1082 			} else {
   1083 				version = ECLIPSE_DEVELOPMENT_VERSION;
   1084 			}
   1085 			File dbDir = new File(path, "perfDb"+version);
   1086 			if (!dbDir.exists() || !dbDir.isDirectory()) {
   1087 				StringBuffer message = new StringBuffer("Invalid performance database directory\n");
   1088 				message.append(path+" should contain 'perfDb");
   1089 				message.append(version);
   1090 				message.append("' directory and none was found!");
   1091 				MessageDialog.openError(getShell(), getDialogTitle(), message.toString());
   1092 				return;
   1093 			}
   1094 
   1095 			// Look for selected dir in combo box list
   1096 			int count = this.databaseLocationCombo.getItemCount();
   1097 			int index = -1;
   1098 			for (int i = 0; i < count; i++) {
   1099 				String item = this.databaseLocationCombo.getItem(i);
   1100 				if (item.length() == 0) { // nothing in the combo-box list
   1101 					break;
   1102 				}
   1103 				if (item.equals(path)) {
   1104 					index = i;
   1105 					break;
   1106 				}
   1107 			}
   1108 			// Set the selected dir the more recent in the previous dirs list
   1109 			if (index !=  0) {
   1110 				if (index > 0) {
   1111 					// the dir was used before, but not recently => remove it from previous dirs list
   1112 					this.databaseLocationCombo.remove(index);
   1113 				}
   1114 				// add the selected dir on the top of the previous dirs list
   1115 				this.databaseLocationCombo.add(path, 0);
   1116 			}
   1117 			// Set combo box text
   1118 			this.databaseLocationCombo.setText(path);
   1119 			updateLocalDb();
   1120 		}
   1121 	}
   1122 
   1123 	// Reset dabase location when 'Releng' button is pushed
   1124 	if (source == this.dbConnectionCheckBox) {
   1125 		updateDatabaseGroup();
   1126 	}
   1127 
   1128 	// Reset dabase location when 'Releng' check-box is checked
   1129 	if (source == this.dbLocalRadioButton) {
   1130 		updateLocalDb();
   1131 	}
   1132 
   1133 	// Add default dimension to results if necessary
   1134 	if (source == this.resultsDimensionsList) {
   1135 		String[] resultsDimensions = this.resultsDimensionsList.getSelection();
   1136 		int length = resultsDimensions.length;
   1137 		String defaultDimension = this.defaultDimensionCombo.getText();
   1138 		for (int i = 0; i < length; i++) {
   1139 			if (resultsDimensions[i].equals(defaultDimension)) {
   1140 				// Default dim is already set as a results dimension, hence nothing has to be done
   1141 				return;
   1142 			}
   1143 		}
   1144 		System.arraycopy(resultsDimensions, 0, resultsDimensions = new String[length + 1], 0, length);
   1145 		resultsDimensions[length] = defaultDimension;
   1146 		this.resultsDimensionsList.setSelection(resultsDimensions);
   1147 	}
   1148 
   1149 //	if (source == this.lastBuildCheckBox) {
   1150 //		this.lastBuildCombo.setEnabled(this.lastBuildCheckBox.getSelection());
   1151 //	}
   1152 
   1153 	if (source == this.mVersionRadioButton) {
   1154 		if (this.mVersionRadioButton.getSelection()) {
   1155 		    updateBrowseButtonToolTip(ECLIPSE_MAINTENANCE_VERSION);
   1156 		}
   1157 	}
   1158 
   1159 	if (source == this.dVersionRadionButton) {
   1160 		if (this.dVersionRadionButton.getSelection()) {
   1161 		    updateBrowseButtonToolTip(ECLIPSE_DEVELOPMENT_VERSION);
   1162 		}
   1163 	}
   1164 }
   1165 
   1166 /*
   1167  * Update browse tooltip
   1168  */
   1169 void updateBrowseButtonToolTip(int version) {
   1170 	this.dbLocalBrowseButton.setToolTipText("Select the directory where the database was unzipped\n(i.e. should contain the perfDb"+version+" subdirectory)");
   1171 }
   1172 
   1173 /*
   1174  * Update database group controls.
   1175  */
   1176 void updateDatabaseGroup() {
   1177 	if (this.dbConnectionCheckBox.getSelection()) {
   1178 		this.dbRelengRadioButton.setEnabled(true);
   1179 		this.dbLocalRadioButton.setEnabled(true);
   1180 		updateLocalDb();
   1181 	} else {
   1182 		this.dbRelengRadioButton.setEnabled(false);
   1183 		this.dbLocalRadioButton.setEnabled(false);
   1184 		this.databaseLocationCombo.setEnabled(false);
   1185 		this.dbLocalBrowseButton.setEnabled(false);
   1186 		setValid(true);
   1187 	}
   1188 }
   1189 
   1190 /*
   1191  * Update database location controls.
   1192  */
   1193 void updateLocalDb() {
   1194 	if (this.dbLocalRadioButton.getSelection()) {
   1195 		this.databaseLocationCombo.setEnabled(true);
   1196 		this.dbLocalBrowseButton.setEnabled(true);
   1197 		if (this.databaseLocationCombo.getItemCount() == 0) {
   1198 			this.databaseLocationCombo.setText("");
   1199 			setValid(false);
   1200 		} else {
   1201 			this.databaseLocationCombo.select(0);
   1202 			setValid(true);
   1203 		}
   1204 		this.dbRelengRadioButton.setToolTipText("");
   1205 		this.dbLocationLabel.setEnabled(true);
   1206 	} else {
   1207 		this.dbRelengRadioButton.setToolTipText(NETWORK_DATABASE_LOCATION);
   1208 		this.databaseLocationCombo.setText("");
   1209 		this.databaseLocationCombo.setEnabled(false);
   1210 		this.dbLocalBrowseButton.setEnabled(false);
   1211 		setValid(true);
   1212 		this.dbLocationLabel.setEnabled(false);
   1213 	}
   1214 }
   1215 
   1216 }
   1217