/*******************************************************************************
* 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.dataviewers.dialogs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.linuxtools.dataviewers.abstractviewers.ISTDataViewersField;
import org.eclipse.linuxtools.dataviewers.abstractviewers.STDataViewersComparator;
import org.eclipse.linuxtools.dataviewers.abstractviewers.STDataViewersMessages;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
/**
* This dialog is used to choose how the data is sorted in the viewer
*
*/
public class STDataViewersSortDialog extends TrayDialog {
private final STDataViewersComparator sorter;
private Combo[] priorityCombos;
private Button[] ascendingButtons;
private Button[] descendingButtons;
private boolean dirty;
/**
* Create a new instance of the receiver.
*
* @param parentShell The parent shell for the dialog.
* @param sorter The sorter to be used
*/
public STDataViewersSortDialog(Shell parentShell, STDataViewersComparator sorter) {
super(parentShell);
this.sorter = sorter;
this.dirty = false;
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(STDataViewersMessages.sortDialog_title);
}
@Override
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
if (sorter == null) {
return composite;
}
initializeDialogUnits(composite);
createPrioritiesArea(composite);
createRestoreDefaultsButton(composite);
createSeparatorLine(composite);
Dialog.applyDialogFont(composite);
return composite;
}
/**
* Create the proirities area.
*
* @param parent
*/
private void createPrioritiesArea(Composite parent) {
Composite prioritiesArea = new Composite(parent, SWT.NULL);
prioritiesArea.setLayout(new GridLayout(3, false));
int[] priorities = sorter.getPriorities();
ascendingButtons = new Button[priorities.length];
descendingButtons = new Button[priorities.length];
priorityCombos = new Combo[Math.min(priorities.length, STDataViewersComparator.MAX_DEPTH)];
Label sortByLabel = new Label(prioritiesArea, SWT.NULL);
sortByLabel.setText(STDataViewersMessages.sortDialog_label);
GridData data = new GridData();
data.horizontalSpan = 3;
sortByLabel.setLayoutData(data);
for (int i = 0; i < priorityCombos.length; i++) {
final int index = i;
Label numberLabel = new Label(prioritiesArea, SWT.NULL);
numberLabel.setText(NLS.bind(STDataViewersMessages.sortDialog_columnLabel, i + 1));
priorityCombos[i] = new Combo(prioritiesArea, SWT.READ_ONLY);
priorityCombos[i].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Composite directionGroup = new Composite(prioritiesArea, SWT.NONE);
directionGroup.setLayout(new GridLayout(2, false));
ascendingButtons[i] = new Button(directionGroup, SWT.RADIO);
ascendingButtons[i].setText(getAscendingText(i));
ascendingButtons[i].addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
markDirty();
}
});
descendingButtons[i] = new Button(directionGroup, SWT.RADIO);
descendingButtons[i].setText(getDescendingText(i));
descendingButtons[i].addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
markDirty();
}
});
if (i < priorityCombos.length - 1) {
priorityCombos[i].addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
List<String> allItems = new ArrayList<>(Arrays.asList(priorityCombos[index].getItems()));
computeSelectionItems(index, allItems);
markDirty();
}
private void computeSelectionItems(int index, List<String> allItems) {
// if not after the last
if (index < priorityCombos.length) {
// target combo
Combo priorityCombo = priorityCombos[index];
// target combo's "old selection" (current selection)
String oldSelection = priorityCombo.getItem(priorityCombo.getSelectionIndex());
// setting new items list
priorityCombo.setItems(allItems.toArray(new String[allItems.size()]));
if (allItems.contains(oldSelection)) {
// old selection can be kept.
String newSelection = oldSelection;
priorityCombo.select(allItems.indexOf(oldSelection));
allItems.remove(newSelection);
} else {
// old selection has been removed by another combo.
// selecting a new element (the first) in the items list.
String newSelection = allItems.get(0);
priorityCombo.select(0);
allItems.remove(newSelection);
}
computeSelectionItems(index + 1, allItems);
}
}
});
} else {
priorityCombos[i].addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
markDirty();
}
});
}
}
// set widget's values from sorter data
// (combos and radio buttons)
updateUIFromSorter();
}
/**
* Get the descending label for the Descending field at i. Use the index to determine the mnemonic.
*
* @param index
* @return String
*/
private String getDescendingText(int index) {
switch (index) {
case 1:
return STDataViewersMessages.sortDirectionDescending_text2;
case 2:
return STDataViewersMessages.sortDirectionDescending_text3;
case 3:
return STDataViewersMessages.sortDirectionDescending_text4;
default:
return STDataViewersMessages.sortDirectionDescending_text;
}
}
/**
* Get the ascending label for the Ascending field at i. Use the index to determine the mnemonic.
*
* @param index
* @return String
*/
private String getAscendingText(int index) {
switch (index) {
case 1:
return STDataViewersMessages.sortDirectionAscending_text2;
case 2:
return STDataViewersMessages.sortDirectionAscending_text3;
case 3:
return STDataViewersMessages.sortDirectionAscending_text4;
default:
return STDataViewersMessages.sortDirectionAscending_text;
}
}
/**
* Create the restore defaults button.
*
* @param parent
*/
private void createRestoreDefaultsButton(Composite parent) {
Button defaultsButton = new Button(parent, SWT.PUSH);
defaultsButton.setText(STDataViewersMessages.restoreDefaults_text);
setButtonSize(defaultsButton, new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.FILL_HORIZONTAL));
defaultsButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
restoreDefaults();
markDirty();
}
});
}
private void createSeparatorLine(Composite parent) {
Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER));
}
private void restoreDefaults() {
updateUI(null, null);
}
private void updateUIFromSorter() {
updateUI(sorter.getPriorities(), sorter.getDirections());
}
private void updateUI(int[] priorities, int[] directions) {
Item[] columns = sorter.getColumns();
List<String> allItems = new ArrayList<>();
List<Integer> allDirections = new ArrayList<>();
for (int i = 0; i < columns.length; i++) {
if (priorities == null || directions == null) {
allItems.add(columns[i].getText());
ISTDataViewersField field = (ISTDataViewersField) columns[i].getData();
allDirections.add(field.getDefaultDirection());
} else {
allItems.add(columns[priorities[i]].getText());
allDirections.add(directions[priorities[i]]);
}
}
for (int i = 0; i < priorityCombos.length; i++) {
priorityCombos[i].removeAll();
priorityCombos[i].setItems(allItems.toArray(new String[allItems.size()]));
priorityCombos[i].select(0);
allItems.remove(0);
ascendingButtons[i].setSelection(allDirections.get(0) == STDataViewersComparator.ASCENDING);
descendingButtons[i].setSelection(allDirections.get(0) == STDataViewersComparator.DESCENDING);
allDirections.remove(0);
}
}
@Override
public int open() {
dirty = false;
return super.open();
}
@Override
protected void okPressed() {
if (isDirty()) {
outerfor: for (int i = priorityCombos.length - 1; i >= 0; i--) {
Combo combo = priorityCombos[i];
int index = combo.getSelectionIndex();
String item = combo.getItem(index);
Item[] columns = sorter.getColumns();
for (Item column : columns) {
if (item.equals(column.getText())) {
ISTDataViewersField field = (ISTDataViewersField) column.getData();
sorter.setTopPriority(column, field);
int direction = STDataViewersComparator.ASCENDING;
if (descendingButtons[i].getSelection()) {
direction = STDataViewersComparator.DESCENDING;
}
sorter.setTopPriorityDirection(direction);
continue outerfor;
}
}
sorter.resetState();
return;
}
}
super.okPressed();
}
/**
* @return boolean
*/
public boolean isDirty() {
return dirty;
}
/**
* Sets the dirty flag to true.
*/
public void markDirty() {
dirty = true;
}
/**
* Set the layout data of the button to a GridData with appropriate heights and widths.
*
* @param button
*/
private void setButtonSize(Button button, GridData buttonData) {
button.setFont(button.getParent().getFont());
int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
buttonData.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
button.setLayoutData(buttonData);
}
/**
* Return the sorter for the receiver.
*
* @return TableSorter
*/
public STDataViewersComparator getSorter() {
return new STDataViewersComparator(sorter);
}
}