/** * Copyright (c) 2009, 2010 Mark Feber, MulgaSoft * * 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.eclipse.org/legal/epl-v10.html * */ package com.mulgasoft.emacsplus.preferences; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.StringTokenizer; import org.eclipse.core.commands.Category; import org.eclipse.core.commands.common.NotDefinedException; import org.eclipse.jface.dialogs.StatusDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; 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.List; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; //import org.eclipse.ui.dialogs.FilteredList; // TODO: Change this & MListEditor to use FilteredList /** * @author Mark Feber - initial API and implementation */ public class CommandCategoryEditor extends EMPListEditor { ArrayList<Category> active = new ArrayList<Category>(); // The array of categories currently NOT set in this dialog ArrayList<Category> inactive = new ArrayList<Category>(); // When the chooser add dialogs, this holds the new ones ArrayList<Category> newOnes = null; /** * sub dialog title */ private String chooserLabel; /** * @param name * @param labelText * @param chooserLabel * @param parent */ CommandCategoryEditor(String name, String labelText, String chooserLabel, Composite parent) { super(name,labelText,parent); this.chooserLabel = chooserLabel; } @Override protected void doLoad() { super.doLoad(); selectionChanged(); } /** * @see org.eclipse.jface.preference.ListEditor#getNewInputObject() */ protected String getNewInputObject() { List myList = getListUnchecked(); CategoryDialog dialog = new CategoryDialog(getShell()); dialog.setTitle(chooserLabel); dialog.setCategories(inactive); dialog.open(); if (newOnes != null && myList != null) { for (int i = 0; i< newOnes.size(); i++) { myList.add(getLabel(newOnes.get(i))); } active.addAll(newOnes); inactive.removeAll(newOnes); newOnes = null; selectionChanged(); } return null; } @Override protected void selectionChanged() { checkCats(); setPresentsDefaultValue((active != null) ? checkDefaults(active) : false); super.selectionChanged(); } private Category[] defaultCats; private boolean checkDefaults(ArrayList<Category> compareCats) { boolean result = true; Category[] newArray = sortCats(compareCats); if (defaultCats == null) { defaultCats = sortCats(convertToCats(getPreferenceStore().getDefaultString(getPreferenceName()), getAllCategories())); } if (newArray.length == defaultCats.length) { for (int i = 0; i < newArray.length; i++) { if (newArray[i] != defaultCats[i]) { result = false; break; } } } else { result = false; } return result; } // TODO: Make our own version with FilteredList, so we can dump this crap // hack so we can use the list control as is private void checkCats(){ List myList = this.getListUnchecked(); if (myList != null) { String[] items = myList.getItems(); if (items.length != active.size()) { // a remove happened ArrayList<Category> moveCats = new ArrayList<Category>(); String[] catLabels = new String[active.size()]; for (int i = 0; i < active.size(); i++) { catLabels[i] = getLabel(active.get(i)); } for (int i = 0; i < catLabels.length; i++) { boolean ok = false; for (int j = 0; j < items.length; j++) { if (items[j].equals(catLabels[i])) { ok = true; break; } } if (!ok) { moveCats.add(active.get(i)); } } if (!moveCats.isEmpty()) { active.removeAll(moveCats); inactive.addAll(moveCats); } } } } /** * Cook up a label that is, hopefully, distinct and useful * @param cat * @return */ String getLabel(Category cat) { String result = null; try { String desc = cat.getDescription(); result= cat.getName() + DISPLAY_SEPARATOR + (desc != null ? desc : ""); //$NON-NLS-1$ } catch (NotDefinedException e) {} return result; } /** * @see org.eclipse.jface.preference.ListEditor#createList(java.lang.String[]) */ protected String createList(String[] items) { Category[] orderedCats = sortCats(active); StringBuilder result = new StringBuilder("");//$NON-NLS-1$ for (int i = 0; i < orderedCats.length; i++) { result.append(orderedCats[i].getId()); result.append(SEPARATOR); } return result.toString(); } /** * @param catIdList is a 'list' of category ids * * @see org.eclipse.jface.preference.ListEditor#parseString(java.lang.String) */ protected String[] parseString(String catIdList) { Category[] allCats = this.getAllCategories(); active = convertToCats(catIdList,allCats); inactive = new ArrayList<Category>(); for (int i=0; i< allCats.length; i++){ if (!active.contains(allCats[i])){ inactive.add(allCats[i]); } } String[] result = new String[active.size()]; for (int i=0; i< result.length; i++){ result[i] = getLabel(active.get(i)); } return result; } private ArrayList<Category> convertToCats(String idList, Category[] allCats){ ArrayList<Category> result; StringTokenizer st = new StringTokenizer(idList, SEPARATOR); result = new ArrayList<Category>(); while (st.hasMoreElements()) { String next = ((String) st.nextElement()).trim(); for (int i=0; i< allCats.length; i++){ if (allCats[i].getId().equals(next)){ result.add(allCats[i]); break; } } } return result; } /** * Receive the results of the add dialog * * @param cats */ void setOkCategories(ArrayList<Category> cats) { newOnes = cats; } Category[] sortCats(java.util.List<Category> sCats) { Category[] sCatsArray = sCats.toArray(new Category[0]); Arrays.sort(sCatsArray, new Comparator<Category>() { public int compare(Category o1, Category o2) { int result = 0; try { result = o1.getName().compareTo(o2.getName()); } catch (NotDefinedException e) {} return result; } }); return sCatsArray; } /** * Get all the currently defined categories * @return */ private Category[] getAllCategories() { return ((ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class)).getDefinedCategories(); } /** * A Category chooser dialog for adding unused categories to the category list * used to generate the executable command list * * @author Mark Feber - initial API and implementation */ private class CategoryDialog extends StatusDialog { List catList; // Array of categories from which to choose ArrayList<Category> categoryArray = null; public CategoryDialog(Shell parent) { super(parent); } /** * Return the selected categories on ok exit * * @see org.eclipse.jface.dialogs.Dialog#okPressed() */ protected void okPressed() { setOkCategories(this.getNewCategories()); super.okPressed(); } /** * @see org.eclipse.jface.dialogs.Dialog#isResizable() */ protected boolean isResizable() { return false; } /** * @see Dialog#createDialogArea(Composite) */ protected Control createDialogArea(Composite parent) { Composite result = new Composite(parent, SWT.NONE); result.setLayout(new GridLayout()); result.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); catList = new List(result, SWT.BORDER | SWT.MULTI ); catList.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); if (categoryArray != null){ for (int i=0; i< categoryArray.size(); i++){ catList.add(getLabel(categoryArray.get(i))); } catList.pack(true); catList.computeSize(SWT.DEFAULT, SWT.DEFAULT); catList.setVisible(true); } result.setVisible(true); catList.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { catList = null; } }); return result; } /** * Initialize our categories with cats * * @param cats */ void setCategories(ArrayList<Category> cats){ Category[] orderedCats = sortCats(cats); categoryArray = new ArrayList<Category>(); for (int i=0; i < orderedCats.length; i++){ categoryArray.add((Category)orderedCats[i]); } } /** * Get all the selected categories from the add dialog * @return */ ArrayList<Category> getNewCategories() { int[] selection = catList.getSelectionIndices(); ArrayList<Category> cats = new ArrayList<Category>(); for (int i = 0; i < selection.length; i++) { cats.add(categoryArray.get(selection[i])); } return cats; } } }