/******************************************************************************* * Copyright (c) 2009 STMicroelectronics. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Marzia Maugeri <marzia.maugeri@st.com> - initial API and implementation *******************************************************************************/ package org.eclipse.linuxtools.internal.dataviewers.charts.dialogs; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.linuxtools.dataviewers.abstractviewers.AbstractSTViewer; import org.eclipse.linuxtools.dataviewers.abstractviewers.ISTDataViewersField; import org.eclipse.linuxtools.dataviewers.charts.provider.ChartFactory; import org.eclipse.linuxtools.dataviewers.charts.provider.IChartField; import org.eclipse.linuxtools.internal.dataviewers.charts.Activator; import org.eclipse.linuxtools.internal.dataviewers.charts.Messages; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.swtchart.Chart; /** * The dialog used to customize the chart before creating it. */ public class ChartDialog extends Dialog { /** The section name of the viewer's dialog settings where the chart dialog save its state */ private static final String TAG_SECTION_CHARTS_STATE = "charts_section"; //$NON-NLS-1$ /** * The key used by the column buttons to save their state. For example the button i will use the key * <code>TAG_COLUMN_BUTTON_+i</code> */ private static final String TAG_COLUMN_BUTTON_ = "COLUMN_BUTTON_"; //$NON-NLS-1$ /** The key used by the bar graph button to save its state */ private static final String TAG_BAR_GRAPH_BUTTON = "BAR_GRAPH_BUTTON"; //$NON-NLS-1$ /** The key used by the vertical bars button to save its state */ private static final String TAG_VERTICAL_BARS_BUTTON = "VERTICAL_BARS_BUTTON"; //$NON-NLS-1$ /** The default value of the column buttons */ private static final boolean DEFAULT_COLUMN_BUTTON = true; /** The default value of the bar graph button */ private static final boolean DEFAULT_BAR_GRAPH_BUTTON = true; /** The default value of the vertical bars button */ private static final boolean DEFAULT_VERTICAL_BARS_BUTTON = false; private final AbstractSTViewer stViewer; private Chart chart; private Text errorMessageText; private Button verticalBarsButton; private Button pieChartButton; private Button barGraphButton; private Button okButton; private List<Button> columnButtons; /** * The constructor. * * @param shell Parent shell. * @param stViewer The viewer this dialog fetch data from. */ public ChartDialog(Shell shell, AbstractSTViewer stViewer) { super(shell); this.stViewer = stViewer; } /** * Restores the state of this dialog */ private void restoreState() { IDialogSettings settings = stViewer.getViewerSettings().getSection(TAG_SECTION_CHARTS_STATE); if (settings == null) { stViewer.getViewerSettings().addNewSection(TAG_SECTION_CHARTS_STATE); return; } for (int i = 0; i < columnButtons.size(); i++) { boolean selected = Boolean.parseBoolean(settings.get(TAG_COLUMN_BUTTON_ + i)); columnButtons.get(i).setSelection(selected); } boolean barGraph = Boolean.parseBoolean(settings.get(TAG_BAR_GRAPH_BUTTON)); barGraphButton.setSelection(barGraph); pieChartButton.setSelection(!barGraph); boolean vBars = Boolean.parseBoolean(settings.get(TAG_VERTICAL_BARS_BUTTON)); verticalBarsButton.setSelection(vBars); verticalBarsButton.setEnabled(barGraph); } /** * Saves the state of this dialog */ private void saveState() { IDialogSettings settings = stViewer.getViewerSettings().getSection(TAG_SECTION_CHARTS_STATE); if (settings == null) { stViewer.getViewerSettings().addNewSection(TAG_SECTION_CHARTS_STATE); } for (int i = 0; i < columnButtons.size(); i++) { boolean selected = columnButtons.get(i).getSelection(); settings.put(TAG_COLUMN_BUTTON_ + i, selected); } boolean barGraph = barGraphButton.getSelection(); settings.put(TAG_BAR_GRAPH_BUTTON, barGraph); boolean vBars = verticalBarsButton.getSelection(); settings.put(TAG_VERTICAL_BARS_BUTTON, vBars); } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.ChartConstants_CREATE_NEW_CHART_FROM_SELECTION); } @Override protected void buttonPressed(int buttonId) { if (buttonId == IDialogConstants.OK_ID) { chart = produceChart(); saveState(); } else { chart = null; } super.buttonPressed(buttonId); } @Override protected void createButtonsForButtonBar(Composite parent) { // create OK and Cancel buttons by default okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); } @Override protected Control createContents(Composite parent) { Control c = super.createContents(parent); this.validateInput(); return c; } @Override protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); Composite titleComp = new Composite(composite, SWT.NONE); titleComp.setLayout(new RowLayout(SWT.HORIZONTAL)); Label icon = new Label(titleComp, SWT.NONE); icon.setImage(Activator.getImage("icons/chart_icon.png")); //$NON-NLS-1$ Label label = new Label(titleComp, SWT.WRAP); label.setText(Messages.ChartConstants_CHART_BUILDER); GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER); data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH); titleComp.setLayoutData(data); Group chartTypeGroup = new Group(composite, SWT.NONE); data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL); chartTypeGroup.setLayoutData(data); chartTypeGroup.setLayout(new GridLayout(2, false)); chartTypeGroup.setText(Messages.ChartConstants_SELECT_YOUR_CHART_TYPE); ValidateSelectionListener listener = new ValidateSelectionListener(); barGraphButton = new Button(chartTypeGroup, SWT.RADIO); barGraphButton.setText(Messages.ChartConstants_BAR_GRAPH); barGraphButton.addSelectionListener(listener); barGraphButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { verticalBarsButton.setEnabled(barGraphButton.getSelection()); } }); data = new GridData(); barGraphButton.setLayoutData(data); verticalBarsButton = new Button(chartTypeGroup, SWT.CHECK); verticalBarsButton.setText(Messages.ChartConstants_VERTICAL_BARS); data = new GridData(); verticalBarsButton.setLayoutData(data); pieChartButton = new Button(chartTypeGroup, SWT.RADIO); pieChartButton.setText(Messages.ChartConstants_PIE_CHART); pieChartButton.addSelectionListener(listener); data = new GridData(); data.horizontalSpan = 2; pieChartButton.setLayoutData(data); Group chartColumnGroup = new Group(composite, SWT.NONE); chartColumnGroup.setLayout(new GridLayout(1, true)); data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL); chartColumnGroup.setLayoutData(data); chartColumnGroup.setText(Messages.ChartConstants_SELECT_COLUMNS_TO_SHOW); addColumnButtons(chartColumnGroup, listener); errorMessageText = new Text(composite, SWT.READ_ONLY); errorMessageText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); errorMessageText.setBackground(errorMessageText.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); applyDialogFont(composite); setWidgetsValues(); return composite; } /** * Sets the widgets values */ private void setWidgetsValues() { // set default values barGraphButton.setSelection(DEFAULT_BAR_GRAPH_BUTTON); verticalBarsButton.setEnabled(barGraphButton.getSelection()); verticalBarsButton.setSelection(DEFAULT_VERTICAL_BARS_BUTTON); for (Button button : columnButtons) { button.setSelection(DEFAULT_COLUMN_BUTTON); } // restore state if there is one saved restoreState(); } /** * Adds one check button for each column implementing the IChartField interface. * * @see IChartField * @param comp * @param listener */ private void addColumnButtons(Composite comp, SelectionListener listener) { columnButtons = new LinkedList<>(); for (ISTDataViewersField field : stViewer.getAllFields()) { if (field instanceof IChartField) { IChartField cField = (IChartField) field; Button b = new Button(comp, SWT.CHECK); b.setText(cField.getColumnHeaderText()); b.setData(cField); b.addSelectionListener(listener); GridData dt = new GridData(); b.setLayoutData(dt); columnButtons.add(b); } } Label sep = new Label(comp, SWT.SEPARATOR | SWT.HORIZONTAL); GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL); sep.setLayoutData(data); Composite buttonComposite = new Composite(comp, SWT.NONE); data = new GridData(); buttonComposite.setLayoutData(data); FillLayout l = new FillLayout(); l.spacing = 5; buttonComposite.setLayout(l); final Button b1 = new Button(buttonComposite, SWT.PUSH); b1.setText(Messages.ChartConstants_SELECT_ALL); final Button b2 = new Button(buttonComposite, SWT.PUSH); b2.setText(Messages.ChartConstants_DESELECT_ALL); SelectionListener sl = new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } @Override public void widgetSelected(SelectionEvent e) { boolean b = (e.getSource() == b1); for (Button button : columnButtons) { button.setSelection(b); } validateInput(); } }; b1.addSelectionListener(sl); b2.addSelectionListener(sl); } /** * Returns the Chart built by this dialog * * @return the chart */ public Chart getValue() { return chart; } /** * Validates the input. * <p> * The default implementation of this framework method delegates the request to the supplied input validator object; * if it finds the input invalid, the error message is displayed in the dialog's message line. This hook method is * called whenever the text changes in the input field. * </p> */ private void validateInput() { String errorMessage = null; int selectedNum = 0; for (Button button : columnButtons) { if (button.getSelection()) selectedNum++; } if (selectedNum == 0) { errorMessage = Messages.ChartConstants_NO_COLUMN_SELECTED; } /* * else if (pieChartButton.getSelection() && selectedNum != 1) { errorMessage = * "PieChart: Please select only one column"; } */ // Bug 16256: important not to treat "" (blank error) the same as null // (no error) setErrorMessage(errorMessage); } /** * 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 */ private void setErrorMessage(String errorMessage) { errorMessageText.setText(errorMessage == null ? "" : errorMessage); //$NON-NLS-1$ okButton.setEnabled(errorMessage == null); errorMessageText.getParent().update(); } /** * Build the chart from configuration * * @return a new chart */ private Chart produceChart() { IStructuredSelection selection = (IStructuredSelection) stViewer.getViewer().getSelection(); if (selection == StructuredSelection.EMPTY) return null; Object[] objects = selection.toArray(); ISTDataViewersField labelField = getLabelField(stViewer); List<IChartField> selectedFields = new ArrayList<>(); for (Button button : columnButtons) { if (button.getSelection()) { selectedFields.add((IChartField) button.getData()); } } boolean barChartType = barGraphButton.getSelection(); boolean horizontalBars = !verticalBarsButton.getSelection(); if (barChartType) { return ChartFactory .produceBarChart(objects, labelField, selectedFields, Messages.ChartConstants_BAR_GRAPH, horizontalBars); } else { return ChartFactory.producePieChart(objects, labelField, selectedFields, Messages.ChartConstants_PIE_CHART); } } private class ValidateSelectionListener extends SelectionAdapter { @Override public void widgetSelected(SelectionEvent e) { validateInput(); } } /** * @param viewer * @return the field used to provide the labels to the series */ private ISTDataViewersField getLabelField(AbstractSTViewer viewer) { return viewer.getAllFields()[0]; } }