package org.eclipse.m2e.core.ui.internal.dialogs; import java.beans.Beans; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Control; import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator; public class InputHistory { /** the history limit */ protected static final int MAX_HISTORY = 10; /** dialog settings to store input history */ protected IDialogSettings dialogSettings; /** the Map of field ids to List of comboboxes that share the same history */ private Map<String, List<ControlWrapper>> comboMap; private List<String> privileged; public InputHistory(String sectionName) { this(sectionName, new String[0]); } public InputHistory(String sectionName, String[] privileged) { comboMap = new HashMap<String, List<ControlWrapper>>(); M2EUIPluginActivator plugin = M2EUIPluginActivator.getDefault(); if(plugin != null) { IDialogSettings pluginSettings = plugin.getDialogSettings(); dialogSettings = pluginSettings.getSection(sectionName); if(dialogSettings == null) { dialogSettings = pluginSettings.addNewSection(sectionName); pluginSettings.addSection(dialogSettings); } } assert privileged != null; this.privileged = Arrays.asList(privileged); } /** Loads the input history from the dialog settings. */ public void load() { if(Beans.isDesignTime()) { return; } for(Map.Entry<String, List<ControlWrapper>> e : comboMap.entrySet()) { String id = e.getKey(); Set<String> items = new LinkedHashSet<String>(); String[] itemsArr = dialogSettings.getArray(id); items.addAll(privileged); if(itemsArr != null) { items.addAll(Arrays.asList(itemsArr)); } for(ControlWrapper wrapper : e.getValue()) { if(!wrapper.isDisposed()) { wrapper.setItems(items.toArray(new String[0])); } } } } /** Saves the input history into the dialog settings. */ public void save() { if(Beans.isDesignTime()) { return; } for(Map.Entry<String, List<ControlWrapper>> e : comboMap.entrySet()) { String id = e.getKey(); Set<String> history = new LinkedHashSet<String>(MAX_HISTORY); for(ControlWrapper wrapper : e.getValue()) { wrapper.collect(); String lastValue = wrapper.text; if(lastValue != null && lastValue.trim().length() > 0) { history.add(lastValue); } } ControlWrapper wrapper = e.getValue().iterator().next(); String[] items = wrapper.items; if(items != null) { for(int j = 0; j < items.length && history.size() < MAX_HISTORY; j++ ) { // do not store the privileged items if they are not selected. // we eventually inject the same or different set next time if(!privileged.contains(items[j])) { history.add(items[j]); } } } dialogSettings.put(id, history.toArray(new String[history.size()])); } } /** Adds an input control to the list of fields to save. */ public void add(Control combo) { add(null, combo); } /** Adds an input control to the list of fields to save. */ public void add(String id, final Control combo) { if(combo != null) { if(id == null) { id = String.valueOf(combo.getData("name")); } List<ControlWrapper> combos = comboMap.get(id); if(combos == null) { combos = new ArrayList<ControlWrapper>(); comboMap.put(id, combos); } if(combo instanceof Combo) { combos.add(new ComboWrapper((Combo) combo)); } else if(combo instanceof CCombo) { combos.add(new CComboWrapper((CCombo) combo)); } } } abstract private class ControlWrapper { protected Control control; protected String text; protected String[] items; private boolean collected; protected ControlWrapper(Control control) { this.control = control; control.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { collect(); } }); } protected void collect() { if(!collected && !isDisposed()) { text = getText(); items = getItems(); } collected = true; } protected boolean isDisposed() { return control.isDisposed(); } abstract protected String getText(); abstract protected String[] getItems(); abstract protected void setItems(String[] items); } private class ComboWrapper extends ControlWrapper { private Combo combo; protected ComboWrapper(Combo combo) { super(combo); this.combo = combo; } protected String getText() { return combo.getText(); } protected String[] getItems() { return combo.getItems(); } protected void setItems(String[] items) { String value = combo.getText(); combo.setItems(items); if(value.length() > 0) { // setItems() clears the text input, so we need to restore it combo.setText(value); } else if(items.length > 0) { combo.setText(items[0]); } } } private class CComboWrapper extends ControlWrapper { private CCombo combo; protected CComboWrapper(CCombo combo) { super(combo); this.combo = combo; } protected String getText() { return combo.getText(); } protected String[] getItems() { try { return combo.getItems(); } catch(SWTException swtException) { //CCombo throws this if the list is disposed, but the combo itself is not disposed yet return new String[0]; } } protected void setItems(String[] items) { String value = combo.getText(); combo.setItems(items); if(value.length() > 0) { // setItems() clears the text input, so we need to restore it combo.setText(value); } } } }