package com.mobilesorcery.sdk.ui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
/**
* Adds validation info to a certain control.
* @author mattias
*
* TODO: Should we start using Eclipse's databinding instead?
*/
public class FieldValidationHelper {
private final HashMap<Control, ControlDecoration> decorations = new HashMap<Control, ControlDecoration>();
private Set<Control> previousControls = new HashSet<Control>();
private final HashMap<TabItem, IMessageProvider> messagesPerTab = new HashMap<TabItem, IMessageProvider>();
public FieldValidationHelper() {
}
public void setMessage(ValidationMessageProvider provider) {
for (TabItem tab : messagesPerTab.keySet()) {
messagesPerTab.put(tab, DefaultMessageProvider.EMPTY);
}
HashSet<Control> resetControls = new HashSet<Control>(previousControls);
for (Control control : provider.getControls()) {
IMessageProvider message = provider.getMessage(control);
if (message != null) {
setMessage(control, message);
resetControls.remove(control);
}
}
for (Control control : resetControls) {
setMessage(control, DefaultMessageProvider.EMPTY);
}
for (TabItem tab : messagesPerTab.keySet()) {
IMessageProvider tabMessage = messagesPerTab.get(tab);
tab.setImage(getImage(tabMessage == null ? IMessageProvider.NONE : tabMessage.getMessageType(), true));
}
previousControls = provider.getControls();
}
private void setMessage(Control control, IMessageProvider message) {
TabItem tab = guessTabAncestor(control);
if (tab != null) {
IMessageProvider tabMessage = messagesPerTab.get(tab);
if (ValidationMessageProvider.compare(message, tabMessage) > 0) {
messagesPerTab.put(tab, message);
}
}
ControlDecoration decoration = initDecoration(control);
if (decoration != null) {
decoration.setDescriptionText(message.getMessage());
Image image = getImage(message.getMessageType(), false);
if (image == null) {
decoration.hide();
} else {
decoration.show();
decoration.setImage(image);
}
}
}
private Label guessLabel(Control control) {
Control[] siblings = control.getParent().getChildren();
Label currentLabel = null;
for (int i = 0; i < siblings.length; i++) {
Control sibling = siblings[i];
if (sibling instanceof Label) {
currentLabel = (Label) sibling;
}
if (sibling == control) {
break;
}
}
return currentLabel;
}
private TabItem guessTabAncestor(Control control) {
TabFolder folder = null;
boolean found = false;
Composite current = control.getParent();
Control tabControl = control;
while (!found) {
tabControl = current;
current = current.getParent();
if (current == null || current instanceof TabFolder) {
folder = (TabFolder) current;
found = true;
}
}
if (folder != null) {
TabItem[] tabItems = folder.getItems();
for (TabItem tabItem : tabItems) {
if (tabControl == tabItem.getControl()) {
return tabItem;
}
}
}
return null;
}
private Image getImage(int messageType, boolean onlyNoninformative) {
String id = null;
switch (messageType) {
case IMessageProvider.ERROR:
id = FieldDecorationRegistry.DEC_ERROR;
break;
case IMessageProvider.WARNING:
id = FieldDecorationRegistry.DEC_WARNING;
break;
case IMessageProvider.INFORMATION:
id = onlyNoninformative ? null : FieldDecorationRegistry.DEC_INFORMATION;
break;
}
return id == null ? null : FieldDecorationRegistry.getDefault()
.getFieldDecoration(id).getImage();
}
private ControlDecoration initDecoration(Control validatedControl) {
ControlDecoration decoration = decorations.get(validatedControl);
if (decoration == null) {
decoration = new ControlDecoration(validatedControl, SWT.LEFT | SWT.CENTER);
decorations.put(validatedControl, decoration);
}
return decoration;
}
}