/** * */ package org.csstudio.sds.ui.internal.preferences; import java.util.List; import org.csstudio.sds.cursorservice.AbstractCursor; import org.csstudio.sds.cursorservice.CursorService; import org.csstudio.sds.cursorservice.CursorSettings; import org.csstudio.sds.cursorservice.CursorState; import org.csstudio.sds.cursorservice.ICursorService; import org.csstudio.sds.cursorservice.RuleDescriptor; import org.csstudio.sds.ui.cursors.internal.CursorHelper; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; 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.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.TypedListener; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; /** * Preference page for the mouse cursor preferences. * * @author Joerg Rathlev */ public final class MouseCursorPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { /** * The <code>CursorService</code>. */ private final ICursorService _service; /** * The combo for selecting the cursor selection rule. */ private Combo _ruleCombo; /** * The cursor selection rules. */ private final RuleDescriptor[] _rules; /** * The available cursors. */ private final AbstractCursor[] _cursors; /** * References to the cursor states of the currently selected rule. */ private final CursorState[] _cursorStates; /** * The names of the cursors. */ private final String[] _cursorNames; /** * The labels for the cursor graphics combos. */ private CLabel[] _cursorLabels; /** * The combos for selecting the cursor graphics. */ private Combo[] _cursorCombos; /** * The cursor settings. This preference page uses a local copy of the preferences which is * written back to the <code>CursorService</code> when the settings are applied. */ private final CursorSettings _settings; /** * Label which explains the cursor selection. */ private Label _explainLabel; /** * Updates the available cursor selection combos when the selected cursor selection rule * changes. */ private class RuleSelectionListener extends SelectionAdapter { /** * Updates the available cursor selection combos based on the selected cursor selection * rule. * * @param e * the selection event. */ @Override public void widgetSelected(final SelectionEvent e) { if (e.widget == _ruleCombo) { updateCursorCombos(); } } } /** * Listener for cursor selection events which updates the label for previewing the cursor. */ private final class CursorSelectionListener extends SelectionAdapter { /** * The index of the label and combo. */ private final int _index; /** * Creates a new cursor selection listener. * * @param index * the index of the label and combo for which this listener is a listener. */ private CursorSelectionListener(final int index) { _index = index; } /** * Applies the selected cursor to the label. * * @param e * the selection event. */ @Override public void widgetSelected(final SelectionEvent e) { if (e.widget instanceof Combo) { final Combo combo = (Combo) e.widget; final int i = combo.getSelectionIndex(); final AbstractCursor cursor = _cursors[i]; _settings.setCursor(selectedRule(), _cursorStates[_index], cursor); CursorHelper.applyCursor(_cursorLabels[_index], cursor.getIdentifier()); } } } /** * Creates the preference page. */ public MouseCursorPreferencePage() { setDescription("Set up the mouse cursors that are used in running displays."); _service = CursorService.getInstance(); final List<RuleDescriptor> rules = _service.availableRules(); _rules = rules.toArray(new RuleDescriptor[rules.size()]); final List<AbstractCursor> cursors = _service.availableCursors(); _cursors = cursors.toArray(new AbstractCursor[cursors.size()]); _cursorNames = new String[_cursors.length]; for (int i = 0; i < _cursors.length; i++) { _cursorNames[i] = _cursors[i].getTitle(); } _cursorStates = new CursorState[ICursorService.MAX_CURSOR_STATES]; _settings = _service.getPreferences(); } /** * {@inheritDoc} */ @Override protected Control createContents(final Composite parent) { final Composite contents = new Composite(parent, SWT.NONE); final GridLayout layout = new GridLayout(2, false); layout.marginWidth = 0; layout.marginHeight = 0; contents.setLayout(layout); createRuleSelectionCombo(contents); // horizontal separator final Label label = new Label(contents, SWT.SEPARATOR | SWT.HORIZONTAL); label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false, 2, 1)); _explainLabel = new Label(contents, SWT.WRAP); final GridData gd = new GridData(SWT.FILL, SWT.BEGINNING, false, false, 2, 1); // Using a small widthHint to prevent the label from sizing up the // preference page. The label automatically expands to the full width // of the columns regardless of this hint, but the hint prevents the // label from being used to calculate the columns' width. gd.widthHint = 200; _explainLabel.setLayoutData(gd); _explainLabel.setText("The cursor selection rule applies cursors to " + "widgets in the states listed below. Select the cursor graphic to be used " + "for each state. To preview a cursor, hover your mouse over " + "the label."); createCursorSelectionCombos(contents); _ruleCombo.addSelectionListener(new RuleSelectionListener()); updateCursorCombos(); return contents; } /** * Creates the combo boxes for selecting the cursor graphics. * * @param parent * the parent control. */ private void createCursorSelectionCombos(final Composite parent) { _cursorLabels = new CLabel[ICursorService.MAX_CURSOR_STATES]; _cursorCombos = new Combo[ICursorService.MAX_CURSOR_STATES]; for (int i = 0; i < ICursorService.MAX_CURSOR_STATES; i++) { // For the cursor labels, a CLabel is used because it automatically // shortens the text if it is too long and displays the full text // in a tooltip if the text was shortened. _cursorLabels[i] = new CLabel(parent, SWT.NONE); _cursorLabels[i].setVisible(false); final GridData gd = new GridData(SWT.FILL, SWT.CENTER, false, false); gd.widthHint = 150; _cursorLabels[i].setLayoutData(gd); _cursorCombos[i] = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY); _cursorCombos[i].setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false)); _cursorCombos[i].setVisible(false); _cursorCombos[i].setItems(_cursorNames); _cursorCombos[i].select(0); _cursorCombos[i].addSelectionListener(new CursorSelectionListener(i)); } } /** * Creates the combo box for choosing the cursor selection rule. * * @param parent * the parent control. */ private void createRuleSelectionCombo(final Composite parent) { final Label label = new Label(parent, SWT.NONE); label.setText("Cursor selection rule:"); _ruleCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY); _ruleCombo.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); for (final RuleDescriptor rule : _rules) { _ruleCombo.add(rule.getDescription()); } // get the currently chosen rule and select it final RuleDescriptor currentRule = _service.getPreferredRule(); for (int i = 0, n = _rules.length; i < n; i++) { if (_rules[i].equals(currentRule)) { _ruleCombo.select(i); break; } } } /** * {@inheritDoc} */ @Override public boolean performOk() { final RuleDescriptor configuredRule = _rules[_ruleCombo.getSelectionIndex()]; _service.setPreferredRule(configuredRule); _service.setPreferences(_settings); return true; } /** * Returns the currently selected rule. * * @return the currently selected rule. */ private RuleDescriptor selectedRule() { final int index = _ruleCombo.getSelectionIndex(); return _rules[index]; } /** * {@inheritDoc} */ @Override public void init(final IWorkbench workbench) { // nothing to do } /** * Updates the visibilty and the selected cursors based on the currently selected cursor * selection rule. */ private void updateCursorCombos() { final RuleDescriptor rule = selectedRule(); final List<CursorState> cursorStates = rule.cursorStates(); _explainLabel.setEnabled(cursorStates.size() > 0); for (int i = 0; i < ICursorService.MAX_CURSOR_STATES; i++) { if (i < cursorStates.size()) { _cursorStates[i] = cursorStates.get(i); _cursorLabels[i].setText(_cursorStates[i].getName() + ":"); _cursorLabels[i].setVisible(true); _cursorCombos[i].setVisible(true); AbstractCursor cursor = _settings.getCursor(rule, _cursorStates[i]); if (cursor == null) { cursor = ICursorService.SYSTEM_DEFAULT_CURSOR; } for (int j = 0; j < ICursorService.MAX_CURSOR_STATES; j++) { if (cursor.equals(_cursors[j])) { _cursorCombos[i].select(j); final Listener[] listeners = _cursorCombos[i].getListeners(SWT.Selection); // FIXME HR: Geht das nicht eleganter? Das hab ich gemacht damit die // Courser nach der Initialisierung angezeigt werden. // Das .select l�st nicht den Selection Listener aus. if (listeners != null && listeners.length > 0) { final Listener listener = listeners[0]; listener.handleEvent(new Event()); final TypedListener tl = (TypedListener) listener; final CursorSelectionListener csl = (CursorSelectionListener) tl .getEventListener(); final Event e = new Event(); e.widget = _cursorCombos[i]; final SelectionEvent e2 = new SelectionEvent(e); e2.widget = _cursorCombos[i]; csl.widgetSelected(e2); } break; } } } else { _cursorStates[i] = null; // prevent stale references _cursorLabels[i].setVisible(false); _cursorCombos[i].setVisible(false); } } } }