sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/internal/ui/graph/GraphSettingsThresholdComposite.java
author Matti Laitinen <matti.t.laitinen@nokia.com>
Tue, 24 Aug 2010 12:16:27 +0300
changeset 15 0367d2db2c06
permissions -rw-r--r--
AnalyzeTool Carbide extension 1.10.0

/*
 * Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description:  Definitions for the class AnalyzeToolGraph
 *
 */
package com.nokia.s60tools.analyzetool.internal.ui.graph;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * Composite for entering the graph's threshold value. This is intended to go
 * onto the GraphSettingsDialog.
 */
public class GraphSettingsThresholdComposite extends Composite {
	private static final String B = "b";
	private static final String GB = "gb";
	private static final String BYTE = "byte";
	private static final String BYTES = "bytes";
	private static final String MB = "mb";
	private static final String KB = "kb";
	private static final String DIALOG_MESSAGE = "Only show allocations on the graph which are";
	private static final String ABOVE = "above or equals the threshold";
	private static final String BELOW = "below or equals the threshold";
	private static final String DIALOG_MESSAGE2 = "Examples for valid entries are 20B, 4KB, or 1MB.  Leaving the value empty will clear the threshold.";
	private static final String THRESHOLD_LABEL = "Threshold:";
	private static final String INVALID_INPUT_VALUE = "Invalid input value.";
	private static final String OUT_OF_RANGE_VALUE = "The value is out of range.";

	private GraphSettingsDialog parentDialog;
	private boolean aboveValue;
	private IInputValidator validator;

	/** Threshold Value text entry widget */
	private Text text;
	private String value;
	/** Error message label widget. */
	private Text errorMessageText;
	private Button radioAbove;

	/**
	 * Constructor
	 * 
	 * @param parent
	 *            the parent composite
	 * @param parentDialog
	 *            The calling dialog
	 * @param oldThreshold
	 *            previous threshold value as user entered it
	 * @param above
	 *            true if previous threshold was filtering "above" the threshold
	 */
	public GraphSettingsThresholdComposite(Composite parent,
			GraphSettingsDialog parentDialog, String oldThreshold, boolean above) {
		super(parent, SWT.NONE);
		this.parentDialog = parentDialog;
		value = oldThreshold == null ? "" : oldThreshold;
		aboveValue = above;
		validator = new ThresholdEntryValidator();
	}

	/**
	 * Creates the content of this composite
	 */
	public void createControl() {
		setLayout(GridLayoutFactory.fillDefaults().create());

		Group group = new Group(this, SWT.NONE);
		group.setText("Graph Threshold");
		group.setLayout(GridLayoutFactory.fillDefaults().numColumns(3).margins(
				10, 10).equalWidth(false).create());
		GridDataFactory.fillDefaults().hint(350, SWT.DEFAULT).applyTo(group);

		Label message = new Label(group, SWT.WRAP);
		message.setText(DIALOG_MESSAGE);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(3, 1)
				.grab(true, true).applyTo(message);

		radioAbove = new Button(group, SWT.RADIO);
		radioAbove.setText(ABOVE);
		radioAbove.setSelection(aboveValue);
		GridDataFactory.fillDefaults().span(3, 1).indent(10, 0).applyTo(
				radioAbove);

		Button radioBelow = new Button(group, SWT.RADIO);
		radioBelow.setText(BELOW);
		radioBelow.setSelection(!aboveValue);
		GridDataFactory.fillDefaults().span(3, 1).indent(10, 0).applyTo(
				radioBelow);

		Label thresholdLabel = new Label(group, SWT.NONE);
		thresholdLabel.setText(THRESHOLD_LABEL);
		GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.CENTER).grab(
				false, false).indent(0, 10).applyTo(thresholdLabel);

		text = new Text(group, SWT.SINGLE | SWT.BORDER);
		GridDataFactory.fillDefaults().indent(0, 7).align(SWT.BEGINNING,
				SWT.END).hint(80, SWT.DEFAULT).applyTo(text);
		text.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				validateInput();
			}
		});
		text.setText(value);
		text.setFocus();
		text.selectAll();

		errorMessageText = new Text(group, SWT.READ_ONLY | SWT.WRAP);
		GridDataFactory.fillDefaults().grab(true, false).indent(0, 10).applyTo(
				errorMessageText);
		errorMessageText.setBackground(errorMessageText.getDisplay()
				.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
		errorMessageText.setForeground(Display.getDefault().getSystemColor(
				SWT.COLOR_RED));

		Label examplesLabel = new Label(group, SWT.WRAP);
		examplesLabel.setText(DIALOG_MESSAGE2);
		GridDataFactory.fillDefaults().span(3, 1).grab(true, false).indent(0,
				10).applyTo(examplesLabel);

		validateInput();
	}

	private void validateInput() {
		setErrorMessage(validator.isValid(text.getText()));
	}

	/**
	 * Sets or clears the error message. If not <code>null</code>, the OK button
	 * is disabled.
	 * 
	 * @param errorMessage
	 *            the error message, or <code>null</code> to clear
	 * @since 3.0
	 */
	public void setErrorMessage(String errorMessage) {
		if (errorMessageText != null && !errorMessageText.isDisposed()) {
			errorMessageText.setText(errorMessage == null ? "" : errorMessage); //$NON-NLS-1$

			// Disable the error message text control if there is no error, or
			// no error text (empty or whitespace only). Hide it also to avoid
			// color change.
			// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=130281
			boolean hasError = errorMessage != null
					&& (StringConverter.removeWhiteSpaces(errorMessage))
							.length() > 0;
			errorMessageText.setEnabled(hasError);
			errorMessageText.setVisible(hasError);
			errorMessageText.getParent().update();

			Control button = parentDialog.getOkButton();
			if (button != null) {
				button.setEnabled(errorMessage == null);
			}
		}
	}

	private static long parseValue(String value) throws NumberFormatException {
		String tmpVal = value.trim().toLowerCase();
		int factor = 1;
		if (tmpVal.endsWith(KB)) {
			tmpVal = tmpVal.substring(0, tmpVal.lastIndexOf(KB)).trim();
			factor = 1024;
		} else if (tmpVal.endsWith(MB)) {
			tmpVal = tmpVal.substring(0, tmpVal.lastIndexOf(MB)).trim();
			factor = 1024 * 1024;
		} else if (tmpVal.endsWith(BYTES)) {
			tmpVal = tmpVal.substring(0, tmpVal.lastIndexOf(BYTES)).trim();
		} else if (tmpVal.endsWith(BYTE)) {
			tmpVal = tmpVal.substring(0, tmpVal.lastIndexOf(BYTE)).trim();
		} else if (tmpVal.endsWith(GB)) {
			tmpVal = tmpVal.substring(0, tmpVal.lastIndexOf(GB)).trim();
			factor = 1024 * 1024 * 1024;
		} else if (tmpVal.endsWith(B)) {
			tmpVal = tmpVal.substring(0, tmpVal.lastIndexOf(B)).trim();
		}
		return Long.parseLong(tmpVal) * factor;
	}

	/**
	 * Returns the threshold value as entered by the user
	 * 
	 * @return the threshold value as entered by the user
	 */
	public String getThresholdString() {
		return value;
	};

	/**
	 * Returns the threshold value in bytes
	 * 
	 * @return the threshold value in bytes
	 */
	public long getThreshold() {
		if (value == null || value.length() == 0) {
			return 0;
		}
		return parseValue(value);
	}

	/**
	 * Returns filtering direction for threshold, true for
	 * "above and equals threshold", false for "below and equals threshold"
	 * 
	 * @return
	 */
	public boolean getAbove() {
		return aboveValue;
	}

	/**
	 * Called from the dialog's buttonPressed() method
	 * 
	 * @param buttonId
	 *            the ID of the button that was pressed
	 */
	public void buttonPressed(int buttonId) {
		value = buttonId == IDialogConstants.OK_ID ? text.getText() : null;
		aboveValue = radioAbove.getSelection();
	}

	/**
	 * This class validates the user-entered threshold value
	 * 
	 */
	class ThresholdEntryValidator implements IInputValidator {

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.eclipse.jface.dialogs.IInputValidator#isValid(java.lang.String)
		 */
		public String isValid(String newText) {
			if (newText.length() == 0) {
				return null;
			}

			try {
				long value = parseValue(newText);
				if (value < 0 || value > 4294967296L) {
					return OUT_OF_RANGE_VALUE;
				}
			} catch (NumberFormatException e) {
				return INVALID_INPUT_VALUE;
			}
			return null;
		}
	}
}