package org.marketcetera.photon.notification.preferences;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.FileFieldEditor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.RadioGroupFieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
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.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.marketcetera.core.notifications.INotification.Severity;
import org.marketcetera.photon.notification.NotificationPlugin;
import org.marketcetera.photon.notification.PlayWave;
import org.marketcetera.util.misc.ClassVersion;
/* $License$ */
/**
* Preferences page controlling behavior of desktop notifications.
*
* @author <a href="mailto:will@marketcetera.com">Will Horn</a>
* @version $Id: DesktopNotificationPreferencesPage.java 16154 2012-07-14 16:34:05Z colin $
* @since 0.8.0
*/
@ClassVersion("$Id: DesktopNotificationPreferencesPage.java 16154 2012-07-14 16:34:05Z colin $")//$NON-NLS-1$
public class DesktopNotificationPreferencesPage extends
FieldEditorPreferencePage implements IWorkbenchPreferencePage, Messages {
/**
* Labels and values for priority radio group
*/
private static final String[][] PRIORITY_NAMES_AND_VALUES = {
{
DESKTOP_NOTIFICATIONS_PARENTHETICAL_PATTERN
.getText(DESKTOP_NOTIFICATIONS_SEVERITY_LABEL_HIGH
.getText(), DESKTOP_NOTIFICATIONS_FEWEST
.getText()), Severity.HIGH.name() },
{ DESKTOP_NOTIFICATIONS_SEVERITY_LABEL_MEDIUM.getText(),
Severity.MEDIUM.name() },
{
DESKTOP_NOTIFICATIONS_PARENTHETICAL_PATTERN.getText(
DESKTOP_NOTIFICATIONS_SEVERITY_LABEL_LOW.getText(),
DESKTOP_NOTIFICATIONS_MOST.getText()),
Severity.LOW.name() } };
@Override
public void init(IWorkbench workbench) {
}
@Override
protected Control createContents(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
GridLayoutFactory.fillDefaults().applyTo(composite);
GridDataFactory.fillDefaults().applyTo(
createPriorityLevelEditor(composite));
GridDataFactory.fillDefaults().grab(true, false).applyTo(
createSoundGroup(composite));
initialize();
return composite;
}
/**
* Creates the priority level preference radio group.
*
* @param parent
* parent composite
* @return composite containing the priority level radio group
*/
private Composite createPriorityLevelEditor(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
RadioGroupFieldEditor notificationLevelEditor = new RadioGroupFieldEditor(
NotificationPreferences.PRIORITY,
DESKTOP_NOTIFICATIONS_PRIORITY.getText(), 1,
PRIORITY_NAMES_AND_VALUES, composite, true);
addField(notificationLevelEditor);
return composite;
}
/**
* Creates the sound preference area.
*
* @param parent
* parent composite
* @return sound preference area group
*/
private Group createSoundGroup(Composite parent) {
Font font = parent.getFont();
// the group
Group group = new Group(parent, SWT.NONE);
group.setFont(font);
GridLayoutFactory.swtDefaults().numColumns(2).applyTo(group);
group.setText(DESKTOP_NOTIFICATIONS_SOUNDS_GROUP.getText());
// description label
Label label = new Label(group, SWT.WRAP);
label.setText(DESKTOP_NOTIFICATIONS_SOUNDS_GROUP_DESCRIPTION.getText());
label.setFont(font);
GridDataFactory.swtDefaults().grab(true, false).span(2, 1).align(
SWT.FILL, SWT.CENTER).applyTo(label);
// table containing notification types
Table notificationTypeList = new Table(group, SWT.BORDER | SWT.H_SCROLL
| SWT.V_SCROLL);
notificationTypeList.setFont(parent.getFont());
GridDataFactory.swtDefaults().applyTo(notificationTypeList);
createTableItem(notificationTypeList,
DESKTOP_NOTIFICATIONS_SEVERITY_LABEL_HIGH.getText(),
Severity.HIGH);
createTableItem(notificationTypeList,
DESKTOP_NOTIFICATIONS_SEVERITY_LABEL_MEDIUM.getText(),
Severity.MEDIUM);
createTableItem(notificationTypeList,
DESKTOP_NOTIFICATIONS_SEVERITY_LABEL_LOW.getText(),
Severity.LOW);
// sound details section
final Composite soundDetails = new Composite(group, SWT.NONE);
GridDataFactory.fillDefaults().grab(true, false).applyTo(soundDetails);
final StackLayout layout = new StackLayout();
soundDetails.setLayout(layout);
final Composite empty = new Composite(soundDetails, SWT.NONE);
final Composite high = createSoundDetail(soundDetails, Severity.HIGH);
final Composite medium = createSoundDetail(soundDetails, Severity.MEDIUM);
final Composite low = createSoundDetail(soundDetails, Severity.LOW);
layout.topControl = empty;
notificationTypeList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Object data = e.item.getData();
if (data.equals(Severity.HIGH))
layout.topControl = high;
else if (data.equals(Severity.MEDIUM))
layout.topControl = medium;
else if (data.equals(Severity.LOW))
layout.topControl = low;
else
layout.topControl = empty;
soundDetails.layout();
}
});
return group;
}
/**
* Helper method to create a simple table item.
*
* @param table
* the parent table
* @param text
* the item text
* @param data
* the item data
*/
private void createTableItem(Table table, String text, Object data) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(text);
item.setData(data);
}
/**
* Helper method to create a "sound detail" group where sound preferences
* are configured for a given severity.
*
* @param parent
* the parent composite
* @param severity
* the notification severity
* @return the created composite
*/
private Composite createSoundDetail(Composite parent, Severity severity) {
Font font = parent.getFont();
// Grouping composite
final Composite composite = new Composite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().applyTo(composite);
GridDataFactory.fillDefaults().grab(true, false).applyTo(composite);
// Button controlling whether to play sound
final Button b = new Button(composite, SWT.NONE | SWT.CHECK);
b.setText(DESKTOP_NOTIFICATIONS_PLAY_SOUND_LABEL.getText());
b.setFont(font);
String clipPref = NotificationPreferences.SOUND_ENABLED_PREFIX
+ severity.name();
addField(new SimpleFieldEditor(clipPref) {
@Override
protected void doLoad() {
if (b != null)
b.setSelection(getPreferenceStore().getBoolean(
getPreferenceName()));
}
@Override
protected void doLoadDefault() {
if (b != null)
b.setSelection(getPreferenceStore().getDefaultBoolean(
getPreferenceName()));
}
@Override
protected void doStore() {
getPreferenceStore().setValue(getPreferenceName(),
b.getSelection());
}
});
// Sound file selection area
final Composite fileComposite = new Composite(composite, SWT.NONE);
fileComposite.setFont(font);
GridDataFactory.fillDefaults().grab(true, false).indent(20, 0).applyTo(
fileComposite);
GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(true).applyTo(
fileComposite);
final FileFieldEditor clipEditor = new SoundClipFieldEditor(
NotificationPreferences.SOUND_CLIP_PREFIX + severity.name(),
fileComposite);
addField(clipEditor);
// Enable/disable sound clip editor based on button selection
clipEditor.setEnabled(getPreferenceStore().getBoolean(clipPref),
fileComposite);
b.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
clipEditor.setEnabled(b.getSelection(), fileComposite);
}
});
return composite;
}
@Override
protected IPreferenceStore doGetPreferenceStore() {
return NotificationPlugin.getDefault().getPreferenceStore();
}
@Override
protected void createFieldEditors() {
// Do nothing, field editors are created in createContents
}
/**
* A FileFieldEditor with Test button that tries to play the selected file
* as a sound clip.
*
* @author <a href="mailto:will@marketcetera.com">Will Horn</a>
* @version $Id: DesktopNotificationPreferencesPage.java 16154 2012-07-14 16:34:05Z colin $
* @since 0.8.0
*/
@ClassVersion("$Id: DesktopNotificationPreferencesPage.java 16154 2012-07-14 16:34:05Z colin $")//$NON-NLS-1$
private static final class SoundClipFieldEditor extends FileFieldEditor {
/**
* Cache of text widget (created in superclass) holding file name
*/
private Text text;
/**
* Cache of button (created in superclass) which opens file selection
* dialog
*/
private Button browse;
/**
* Button to test selected sound clip
*/
private Button test;
/**
* Constructor.
*
*@param name
* the name of the preference this field editor works on
* @param parent
* the parent of the field editor's control
*/
private SoundClipFieldEditor(String name, Composite parent) {
super(name, "", true, parent); //$NON-NLS-1$
}
@Override
protected void createControl(Composite parent) {
setEmptyStringAllowed(false);
setValidateStrategy(VALIDATE_ON_KEY_STROKE);
text = getTextControl(parent);
GridDataFactory.fillDefaults().span(2, 1).grab(true, false)
.applyTo(text);
browse = getChangeControl(parent);
GridDataFactory.defaultsFor(browse).applyTo(browse);
test = new Button(parent, SWT.PUSH);
test.setFont(parent.getFont());
test.setText(DESKTOP_NOTIFICATIONS_TEST_BUTTON_LABEL.getText());
GridDataFactory.defaultsFor(test).applyTo(test);
test.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
String file = text.getText();
if (!file.isEmpty())
new PlayWave(file).start();
}
});
}
@Override
public void setEnabled(boolean enabled, Composite parent) {
if (text != null)
text.setEnabled(enabled);
if (browse != null)
browse.setEnabled(enabled);
if (test != null)
test.setEnabled(enabled);
}
@Override
protected boolean checkState() {
// Validation is too buggy to be useful so it is skipped
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=76127
return true;
}
}
/**
* Field editor without UI. Subclass must implement {@link #doLoad()},
* {@link #doLoadDefault()}, and {@link #doStore()} to work with custom UI.
*
* @author <a href="mailto:will@marketcetera.com">Will Horn</a>
* @version $Id: DesktopNotificationPreferencesPage.java 16154 2012-07-14 16:34:05Z colin $
* @since 0.8.0
*/
@ClassVersion("$Id: DesktopNotificationPreferencesPage.java 16154 2012-07-14 16:34:05Z colin $")//$NON-NLS-1$
private abstract class SimpleFieldEditor extends FieldEditor {
/**
* Constructor.
*
* @param name the preference name
*/
public SimpleFieldEditor(String name) {
super();
setPreferenceName(name);
}
@Override
protected void adjustForNumColumns(int numColumns) {
throw new UnsupportedOperationException();
}
@Override
protected void doFillIntoGrid(Composite parent, int numColumns) {
throw new UnsupportedOperationException();
}
@Override
public int getNumberOfControls() {
throw new UnsupportedOperationException();
}
}
}