/* Copyright (C) 2009 Mobile Sorcery AB
This program is free software; you can redistribute it and/or modify it
under the terms of the Eclipse Public License v1.0.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for
more details.
You should have received a copy of the Eclipse Public License v1.0 along
with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html
*/
package com.mobilesorcery.sdk.profiles.ui;
import java.beans.PropertyChangeSupport;
import java.text.MessageFormat;
import java.util.Iterator;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
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.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import com.mobilesorcery.sdk.core.MoSyncProject;
import com.mobilesorcery.sdk.core.MoSyncTool;
import com.mobilesorcery.sdk.core.ProfileManager;
import com.mobilesorcery.sdk.profiles.ICompositeDeviceFilter;
import com.mobilesorcery.sdk.profiles.IDeviceFilter;
import com.mobilesorcery.sdk.profiles.IProfile;
import com.mobilesorcery.sdk.profiles.filter.ConstantFilter;
import com.mobilesorcery.sdk.profiles.filter.FeatureFilter;
import com.mobilesorcery.sdk.profiles.filter.ProfileFilter;
import com.mobilesorcery.sdk.profiles.ui.internal.ConstantFilterDialog;
import com.mobilesorcery.sdk.profiles.ui.internal.DeviceFilterDialog;
import com.mobilesorcery.sdk.profiles.ui.internal.FeatureFilterDialog;
import com.mobilesorcery.sdk.profiles.ui.internal.Messages;
import com.mobilesorcery.sdk.profiles.ui.internal.ProfileFilterDialog;
import com.mobilesorcery.sdk.profiles.ui.internal.SelectFilterTypeDialog;
public class DeviceFilterComposite extends Composite {
private ICompositeDeviceFilter filter;
private final TableViewer filterTable;
private final Button remove;
private final Button edit;
private final Button add;
PropertyChangeSupport listeners = new PropertyChangeSupport(this);
private final Label deviceCountLabel;
private MoSyncProject currentProject;
public DeviceFilterComposite(Composite parent, int style) {
super(parent, style);
GridLayout layout = new GridLayout(1, false);
layout.marginWidth = 0;
setLayout(layout);
Composite buttonRow = new Composite(this, SWT.NONE);
buttonRow.setLayout(new GridLayout(3, true));
add = new Button(buttonRow, SWT.PUSH);
add.setText(Messages.DeviceFilterComposite_Add);
constrainSize(add, 85, SWT.DEFAULT);
remove = new Button(buttonRow, SWT.PUSH);
remove.setText(Messages.DeviceFilterComposite_Remove);
constrainSize(remove, 85, SWT.DEFAULT);
edit = new Button(buttonRow, SWT.PUSH);
edit.setText(Messages.DeviceFilterComposite_Edit);
constrainSize(edit, 85, SWT.DEFAULT);
add.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
SelectFilterTypeDialog dialog = new SelectFilterTypeDialog(getShell());
int result = dialog.open();
if (result == IDialogConstants.OK_ID && dialog.getFilter() != null) {
filter.addFilter(dialog.getFilter());
updateUI(true);
}
}
});
edit.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
editSelectedFilter();
}
});
filterTable = new TableViewer(this);
filterTable.setContentProvider(new ArrayContentProvider());
filterTable.setLabelProvider(new LabelProvider());
filterTable.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
updateUI(false);
}
});
GridData filterTableData = new GridData(SWT.FILL, SWT.FILL, true, true);
filterTable.getControl().setLayoutData(filterTableData);
filterTable.getControl().addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent e) {
if (e.keyCode == SWT.DEL) {
removeSelectedFilters();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
});
remove.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
removeSelectedFilters();
}
});
deviceCountLabel = new Label(this, SWT.TRAIL);
deviceCountLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
updateUI(true);
}
protected void editSelectedFilter() {
IStructuredSelection selection = (IStructuredSelection) filterTable.getSelection();
Object element = selection.getFirstElement();
if (element instanceof IDeviceFilter) {
IDeviceFilter filter = (IDeviceFilter) element;
DeviceFilterDialog dialog = createDialogForFilter(filter);
if (DeviceFilterDialog.OK == dialog.open()) {
this.filter.update(filter);
updateUI(true);
updateDeviceCount();
}
}
}
private DeviceFilterDialog createDialogForFilter(IDeviceFilter filter) {
// TODO! Hard-coded?
DeviceFilterDialog dialog = null;
if (filter instanceof FeatureFilter) {
dialog = new FeatureFilterDialog(getShell());
} else if (filter instanceof ConstantFilter) {
dialog = new ConstantFilterDialog(getShell());
} else if (filter instanceof ProfileFilter) {
dialog = new ProfileFilterDialog(getShell());
} else {
return null;
}
dialog.setFilter(filter);
return dialog;
}
protected boolean isEditable(IDeviceFilter filter) {
return filter instanceof FeatureFilter ||
filter instanceof ConstantFilter ||
filter instanceof ProfileFilter;
}
protected void removeSelectedFilters() {
IStructuredSelection selection = (IStructuredSelection) filterTable.getSelection();
for (Iterator selected = selection.iterator(); selected.hasNext(); ) {
filter.removeFilter((IDeviceFilter)selected.next());
updateUI(true);
}
}
/**
* Will only set the filter if it is an <code>ICompositeDeviceFilter</code>,
* will ignore otherwise.
* @param currentProject
*/
public void setCurrentProject(MoSyncProject currentProject) {
this.filter = currentProject.getDeviceFilter();
this.currentProject = currentProject;
updateUI(true);
}
private void updateUI(final boolean updateCount) {
filterTable.getControl().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
boolean noFilters = filter == null || filter.getFilters().length == 0;
filterTable.setInput(noFilters ?
new String[] { Messages.DeviceFilterComposite_NoFilter } :
filter.getFilters());
remove.setEnabled(!noFilters);
IStructuredSelection selection = (IStructuredSelection) filterTable.getSelection();
edit.setEnabled(selection.size() == 1 &&
selection.getFirstElement() instanceof IDeviceFilter &&
isEditable((IDeviceFilter) selection.getFirstElement()) &&
!noFilters);
if (updateCount) {
updateDeviceCount();
}
}
});
}
private void updateDeviceCount() {
deviceCountLabel.setText(getDeviceCountText());
}
protected String getDeviceCountText() {
ProfileManager mgr = currentProject == null ?
MoSyncTool.getDefault().getProfileManager(MoSyncTool.LEGACY_PROFILE_TYPE) :
currentProject.getProfileManager();
int selected = mgr.getProfiles(filter).length;
int total = mgr.getProfiles().length;
return MessageFormat.format("{0} of {1} included", selected, total);
}
@Override
public void setEnabled(boolean enabled) {
filterTable.getControl().setEnabled(enabled);
add.setEnabled(enabled);
remove.setEnabled(enabled);
edit.setEnabled(enabled);
super.setEnabled(enabled);
}
/**
* <p>
* Utility method for setting the layout data of a control to have a certain
* size.
* </p>
* <p>
* <emph>Works only with GridLayouts</emph>
* </p>
*
* @param control
* the control
* @param hSize
* the horizontal size in pixels, or SWT.DEFAULT if unspecified
* @param vSize
* the vertical size in pixels, or SWT.DEFAULT if unspecified
*/
// TODO: Move somewhere else, and rewrite (because it's also in project X)
protected void constrainSize(Control control, int hSize, int vSize) {
if (control.getParent().getLayout() instanceof GridLayout) {
GridData data = (GridData) control.getLayoutData();
if (data == null) {
data = new GridData();
}
if (vSize != SWT.DEFAULT) {
data.heightHint = vSize;
}
if (hSize != SWT.DEFAULT) {
data.widthHint = hSize;
}
control.setLayoutData(data);
}
}
}