/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2009 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** 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.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.ui.internal.dialogs;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.rssowl.core.Owl;
import org.rssowl.core.persist.ILabel;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.ICategoryDAO;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.Pair;
import org.rssowl.core.util.StringUtils;
import org.rssowl.ui.internal.Controller;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.util.ContentAssistAdapter;
import org.rssowl.ui.internal.util.JobRunner;
import org.rssowl.ui.internal.util.LayoutUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* A Dialog to assign Labels to a selection of News.
*
* @author bpasero
*/
public class AssignLabelsDialog extends Dialog {
private Text fLabelsInput;
private final Set<INews> fNews;
private Set<ILabel> fExistingLabels;
private ResourceManager fResources = new LocalResourceManager(JFaceResources.getResources());
private HashSet<String> fExistingLabelNames;
private Label fInfoImg;
private Label fInfoText;
/**
* @param parentShell
* @param news
*/
public AssignLabelsDialog(Shell parentShell, Set<INews> news) {
super(parentShell);
fNews = news;
fExistingLabels = CoreUtils.loadSortedLabels();
fExistingLabelNames = new HashSet<String>(fExistingLabels.size());
for (ILabel label : fExistingLabels) {
fExistingLabelNames.add(label.getName().toLowerCase());
}
}
/*
* @see org.eclipse.jface.dialogs.Dialog#okPressed()
*/
@Override
protected void okPressed() {
String labelsValue = fLabelsInput.getText();
String[] labelsValueSplit = labelsValue.split(","); //$NON-NLS-1$
/* Remove All Labels first */
for (INews news : fNews) {
Set<ILabel> newsLabels = news.getLabels();
for (ILabel newsLabel : newsLabels) {
news.removeLabel(newsLabel);
}
}
/* Assign New Labels */
if (labelsValueSplit.length > 0) {
/* For each typed Label */
for (String labelValue : labelsValueSplit) {
ILabel label = null;
labelValue = labelValue.trim();
if (labelValue.length() == 0)
continue;
/* Check if Label exists */
for (ILabel existingLabel : fExistingLabels) {
if (existingLabel.getName().toLowerCase().equals(labelValue.toLowerCase())) {
label = existingLabel;
break;
}
}
/* Create new Label if necessary */
if (label == null) {
ILabel newLabel = Owl.getModelFactory().createLabel(null, labelValue);
newLabel.setColor(OwlUI.toString(new RGB(0, 0, 0)));
newLabel.setOrder(fExistingLabels.size());
DynamicDAO.save(newLabel);
fExistingLabels.add(newLabel);
label = newLabel;
}
/* Add Label to all News */
for (INews news : fNews) {
news.addLabel(label);
}
}
}
/* Mark Saved Search Service as in need for a quick Update */
Controller.getDefault().getSavedSearchService().forceQuickUpdate();
/* Save News */
DynamicDAO.saveAll(fNews);
super.okPressed();
}
/*
* @see org.eclipse.jface.dialogs.Dialog#close()
*/
@Override
public boolean close() {
fResources.dispose();
return super.close();
}
/*
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createDialogArea(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(LayoutUtils.createGridLayout(2, 10, 10, 5, 6, false));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
/* Name */
Label nameLabel = new Label(composite, SWT.NONE);
nameLabel.setText(Messages.AssignLabelsDialog_LABELS);
fLabelsInput = new Text(composite, SWT.BORDER | SWT.SINGLE);
fLabelsInput.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
fLabelsInput.setText(getLabelsValue());
fLabelsInput.setSelection(fLabelsInput.getText().length());
fLabelsInput.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
onModifyName();
}
});
/* Add auto-complete for Labels taken from existing Categories */
ContentAssistAdapter adapter = new ContentAssistAdapter(fLabelsInput, ',', true);
/* Labels */
final List<String> labelNames = new ArrayList<String>(fExistingLabels.size());
for (ILabel label : fExistingLabels) {
labelNames.add(label.getName());
}
final Pair<SimpleContentProposalProvider, ContentProposalAdapter> pair = OwlUI.hookAutoComplete(fLabelsInput, adapter, labelNames, true, false);
pair.getSecond().setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_INSERT);
/* Load proposals in the Background */
JobRunner.runDelayedInBackgroundThread(new Runnable() {
public void run() {
if (!fLabelsInput.isDisposed()) {
Set<String> values = new TreeSet<String>(new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);
}
});
/* Categories */
Set<String> categoryNames = DynamicDAO.getDAO(ICategoryDAO.class).loadAllNames();
categoryNames = StringUtils.replaceAll(categoryNames, ",", " "); // Comma not allowed for Labels //$NON-NLS-1$ //$NON-NLS-2$
values.addAll(categoryNames);
/* Labels */
values.addAll(labelNames);
/* Apply Proposals */
if (!fLabelsInput.isDisposed())
OwlUI.applyAutoCompleteProposals(values, pair.getFirst(), pair.getSecond());
}
}
});
/* Info Container */
Composite infoContainer = new Composite(composite, SWT.None);
infoContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
infoContainer.setLayout(LayoutUtils.createGridLayout(2, 0, 0));
((GridLayout) infoContainer.getLayout()).marginTop = 15;
fInfoImg = new Label(infoContainer, SWT.NONE);
fInfoImg.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
fInfoText = new Label(infoContainer, SWT.WRAP);
fInfoText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
showInfo();
applyDialogFont(composite);
return composite;
}
private String getLabelsValue() {
/* Sort by Sort Key to respect order */
Set<ILabel> labels = new TreeSet<ILabel>(new Comparator<ILabel>() {
public int compare(ILabel l1, ILabel l2) {
if (l1.equals(l2))
return 0;
return l1.getOrder() < l2.getOrder() ? -1 : 1;
}
});
for (INews news : fNews) {
Set<ILabel> newsLabels = news.getLabels();
labels.addAll(newsLabels);
}
StringBuilder str = new StringBuilder();
for (ILabel label : labels) {
str.append(label.getName()).append(", "); //$NON-NLS-1$
}
return str.toString();
}
private void showWarning(String msg) {
fInfoText.setText(msg);
fInfoImg.setImage(OwlUI.getImage(fResources, "icons/obj16/warning.gif")); //$NON-NLS-1$
fInfoImg.getParent().layout();
}
private void showInfo() {
fInfoText.setText(Messages.AssignLabelsDialog_SEPARATE_LABELS);
fInfoImg.setImage(OwlUI.getImage(fResources, "icons/obj16/info.gif")); //$NON-NLS-1$
fInfoImg.getParent().layout();
}
private void onModifyName() {
int newLabelCounter = 0;
String labelsValue = fLabelsInput.getText();
String[] labelsValueSplit = labelsValue.split(","); //$NON-NLS-1$
Set<String> handledNewLabels = new HashSet<String>(1);
for (String labelValue : labelsValueSplit) {
labelValue = labelValue.trim().toLowerCase();
if (labelValue.length() > 0 && !handledNewLabels.contains(labelValue) && !fExistingLabelNames.contains(labelValue)) {
newLabelCounter++;
handledNewLabels.add(labelValue.toLowerCase());
}
}
if (newLabelCounter == 0)
showInfo();
else if (newLabelCounter == 1)
showWarning(Messages.AssignLabelsDialog_NEW_LABEL_CREATE);
else
showWarning(NLS.bind(Messages.AssignLabelsDialog_N_LABEL_CREATE, newLabelCounter));
}
/*
* @see org.eclipse.jface.dialogs.Dialog#createButtonBar(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createButtonBar(Composite parent) {
/* Spacer */
new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
return super.createButtonBar(parent);
}
/*
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(Messages.AssignLabelsDialog_ASSIGN_LABELS);
}
/*
* @see org.eclipse.jface.dialogs.Dialog#initializeBounds()
*/
@Override
protected void initializeBounds() {
super.initializeBounds();
Shell shell = getShell();
/* Minimum Size */
int minWidth = convertHorizontalDLUsToPixels(OwlUI.MIN_DIALOG_WIDTH_DLU);
int minHeight = shell.computeSize(minWidth, SWT.DEFAULT).y;
/* Required Size */
Point requiredSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
shell.setSize(Math.max(minWidth, requiredSize.x), Math.max(minHeight, requiredSize.y));
LayoutUtils.positionShell(shell);
}
}