/* * ----------------------------------------------------------------------- * File: $HeadURL: http://keith-laptop/svn/krs/LanguageTest/trunk/org.thanlwinsoft.languagetest/src/org/thanlwinsoft/languagetest/eclipse/editors/LanguageTable.java $ * Revision $LastChangedRevision: 1388 $ * Last Modified: $LastChangedDate: 2009-01-31 19:32:00 +0700 (Sat, 31 Jan 2009) $ * Last Change by: $LastChangedBy: keith $ * ----------------------------------------------------------------------- * Copyright (C) 2007 Keith Stribley <devel@thanlwinsoft.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * ----------------------------------------------------------------------- */ package org.thanlwinsoft.languagetest.eclipse.editors; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.math.BigDecimal; import org.apache.xmlbeans.XmlObject; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.CheckboxCellEditor; import org.eclipse.jface.viewers.ICellEditorValidator; import org.eclipse.jface.viewers.ICellModifier; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.ITreeSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.swt.widgets.TreeItem; import org.thanlwinsoft.languagetest.MessageUtil; import org.thanlwinsoft.languagetest.eclipse.LanguageTestPlugin; import org.thanlwinsoft.languagetest.eclipse.workspace.WorkspaceLanguageManager; import org.thanlwinsoft.languagetest.language.test.UniversalLanguage; import org.thanlwinsoft.schemas.languagetest.module.LangType; /** * @author keith * */ public class LanguageTable extends Composite { //private final static int LANG_DEPTH = 5; private TreeViewer tableViewer = null; private HashMap<String, LangType> availableTypes = null;// String, LangType private HashMap<String, XmlObject> inUseTypes = null;// String, LangType private HashSet<ModifyListener> modifyListeners = null; private final int LANG_NAME_COL = 0; private final int IN_USE_COL = 1; private final int LANG_FONT_COL = 2; private final int FONT_SIZE_COL = 3; private final String LANG_NAME = "Lang"; private final String IN_USE = "InUse"; private final String LANG_FONT = "Font"; private final String FONT_SIZE = "FontSize"; private boolean dirty = false; private LanguageLabelProvider labelProvider = null; private LanguageContentProvider contentProvider = null; private UniversalLanguage [] languages = null; //private IEditorPart editor = null; /** * @param parent * @param style */ public LanguageTable(Composite parent, int style) { super(parent, style); modifyListeners = new HashSet<ModifyListener>(); this.setLayout(new FillLayout()); availableTypes = new HashMap<String, LangType>(); inUseTypes = new HashMap<String, XmlObject>(); tableViewer = new TreeViewer(this, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION); labelProvider = new LanguageLabelProvider(); contentProvider = new LanguageContentProvider(); tableViewer.setContentProvider(contentProvider); tableViewer.setLabelProvider(labelProvider); LanguageCellModifier modifier = new LanguageCellModifier(); tableViewer.setCellModifier(modifier); tableViewer.getTree().setHeaderVisible(true); tableViewer.getTree().setSize(SWT.DEFAULT, 200); TreeColumn col = new TreeColumn(tableViewer.getTree(), SWT.LEFT); col.setResizable(true); col.setWidth(200); col.setText(MessageUtil.getString("Language")); col = new TreeColumn(tableViewer.getTree(), SWT.LEFT); col.setResizable(true); col.setWidth(100); col.setText(MessageUtil.getString("LangEnabled")); col = new TreeColumn(tableViewer.getTree(), SWT.LEFT); col.setResizable(true); col.setWidth(100); col.setText(MessageUtil.getString("Font")); col = new TreeColumn(tableViewer.getTree(), SWT.LEFT); col.setResizable(true); col.setWidth(100); col.setText(MessageUtil.getString("FontSize")); CellEditor[] editors = new CellEditor[] { null, new CheckboxCellEditor(tableViewer.getTree(), SWT.NONE), new FontCellEditor(tableViewer.getTree(), SWT.NONE), new TextCellEditor(tableViewer.getTree()) }; String [] columnProperties = new String [] { LANG_NAME, IN_USE, LANG_FONT, FONT_SIZE }; tableViewer.setColumnProperties(columnProperties); tableViewer.setCellEditors(editors); for (int i = 0; i < editors.length; i++) { if (editors[i] != null) editors[i].setValidator(modifier); } } /* (non-Javadoc) * @see org.eclipse.swt.widgets.Control#addFocusListener(org.eclipse.swt.events.FocusListener) */ public void addFocusListener(FocusListener listener) { tableViewer.getTree().addFocusListener(listener); super.addFocusListener(listener); } /* (non-Javadoc) * @see org.eclipse.swt.widgets.Control#removeFocusListener(org.eclipse.swt.events.FocusListener) */ public void removeFocusListener(FocusListener listener) { tableViewer.getTree().removeFocusListener(listener); super.removeFocusListener(listener); } public void addModifyListener(ModifyListener ml) { modifyListeners.add(ml); } public void removeModifyListener(ModifyListener ml) { modifyListeners.remove(ml); } /** * Set the project languages * The project languages are defined in the root of the project tree. * @param array of languages * */ public void setProjectLangs(LangType [] langs) { languages = new UniversalLanguage[langs.length]; availableTypes.clear(); for (int i = 0; i < langs.length; i++) { availableTypes.put(langs[i].getLang(), langs[i]); languages[i] = new UniversalLanguage(langs[i].getLang()); } contentProvider.setLanguages(languages); tableViewer.setInput(languages); tableViewer.getTree().setData(languages); tableViewer.expandAll(); tableViewer.refresh(); } /** * Set the project languages * The project languages are defined in the root of the project tree. * @param array of languages */ public void setProjectLangs(HashMap<String, LangType> langs) { languages = new UniversalLanguage[langs.size()]; Object [] langKeys = langs.keySet().toArray(); for (int i = 0; i < languages.length; i++) { languages[i] = new UniversalLanguage(langKeys[i].toString()); } availableTypes.clear(); availableTypes = langs; if (languages != null && languages.length > 0) { contentProvider.setLanguages(languages); tableViewer.setInput(languages); tableViewer.getTree().setData(languages); tableViewer.expandAll(); tableViewer.refresh(); } } /** set the module languages that are defined in the module file * * @param langs */ public void setModuleLangs(LangType [] langs) { inUseTypes.clear(); for (int i = 0; i < langs.length; i++) { inUseTypes.put(langs[i].getLang(), langs[i]); } tableViewer.refresh(); tableViewer.expandAll(); dirty = false; } /** Set the module languages that are defined in the module file * Keys are String language codes, Values are LangType * @param langs */ public void setModuleLangs(HashMap<String, XmlObject> langs) { inUseTypes.clear(); inUseTypes = langs; tableViewer.refresh(); tableViewer.expandAll(); dirty = false; } public LangType [] getModuleLangs() { LangType [] array = new LangType[inUseTypes.size()]; return inUseTypes.values().toArray(array); } public LangType [] getProjectLangs() { LangType [] array = new LangType[availableTypes.size()]; return availableTypes.values().toArray(array); } public void saveProjectLangs(IProject project, IProgressMonitor monitor, boolean notInUseOnly) { Iterator<String> it = availableTypes.keySet().iterator(); while (it.hasNext()) { String key = it.next().toString(); if (notInUseOnly && inUseTypes.containsKey(key)) continue; LangType lt = availableTypes.get(key); WorkspaceLanguageManager.addLanguage(project, lt, monitor); } } public LangType getSelectedLang() { ITreeSelection s = (ITreeSelection)tableViewer.getSelection(); if (s.getFirstElement() instanceof UniversalLanguage) { UniversalLanguage ul = (UniversalLanguage)s.getFirstElement(); return availableTypes.get(ul.getCode()); } return null; } /** Provides the labels for the columns in the language table * * @author keith * */ protected class LanguageLabelProvider extends LabelProvider implements ITableLabelProvider { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) */ public Image getColumnImage(Object element, int columnIndex) { return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) */ public String getColumnText(Object element, int columnIndex) { UniversalLanguage ul = null; if (element instanceof UniversalLanguage) { ul = (UniversalLanguage)element; } else if (element instanceof String[]) { String[] langProps = (String[])element; ul = new UniversalLanguage(langProps); if (columnIndex > 0) return null; } else if (element instanceof String) { ul = new UniversalLanguage(element.toString()); if (columnIndex > 0) return null; } if (ul != null) { LangType lt = availableTypes.get(ul.getCode()); boolean inUse = false; if (lt != null && inUseTypes.containsKey(ul.getCode())) { // use the module font, not the project font lt = (LangType)inUseTypes.get(ul.getCode()); inUse = true; } switch (columnIndex) { case LANG_NAME_COL: return ul.getDescription(); case IN_USE_COL: if (inUse) return MessageUtil.getString("yes"); else if (lt != null) return MessageUtil.getString("no"); return ""; case LANG_FONT_COL: if (lt != null) { return lt.getFont(); } return ""; case FONT_SIZE_COL: if (lt != null) { return lt.getFontSize().toString(); } return ""; } } return null; } } /** Provides the content for a Language Table. * A UniversalLanguage is used one per column. The top level tree objects * are raw language IDs. Scripts and sub classifications are the children. * @author keith * */ public class LanguageContentProvider implements ITreeContentProvider { private UniversalLanguage [] langs = null; protected boolean useTree = false; public LanguageContentProvider() { } public void setLanguages(UniversalLanguage [] langs) { this.langs = langs; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) */ public Object[] getChildren(Object parentElement) { HashSet<UniversalLanguage> set = new HashSet<UniversalLanguage>(); if (parentElement instanceof String[]) { String [] nodeArray = (String[])parentElement; if (nodeArray.length > 1) return null; for (int i = 0; i < langs.length; i++) { String [] langArray = langs[i].toArray(); if (equalsToDepth(nodeArray.length, nodeArray, langArray)) { //String [] child = subArray(nodeArray.length + 1, langArray); UniversalLanguage child = langs[i]; set.add(child); } } } else if (parentElement instanceof String) { for (int i = 0; i < langs.length; i++) { if (langs[i].getLanguageCode().equals(parentElement.toString())) set.add(langs[i]); } } //else System.out.println(parentElement.getClass()); return set.toArray(); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) */ public Object getParent(Object element) { if (element instanceof UniversalLanguage) { UniversalLanguage ul = (UniversalLanguage)element; return new String[] { ul.getLanguageCode() }; } if (element instanceof String[]) { String [] child = (String[])element; String [] parent = subArray(child.length - 1, child); return parent; } return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) */ public boolean hasChildren(Object element) { if (element instanceof String[]) { String [] nodeArray = (String[])element; if (nodeArray.length == 1) return true; // for (int i = 0; i < langs.length; i++) // { // if (equalsToDepth(nodeArray.length, nodeArray, // langs[i].toArray())) return true; // } } //else System.out.println(element.getClass()); return false; } protected boolean equalsToDepth(int depth, String[] a, String [] b) { if (a.length < depth || b.length < depth) return false; for (int i = 0; i < depth; i++) { if (a[i].equals(b[i]) == false) return false; } return true; } protected String[] subArray(int depth, String[] a) { if (depth < 0) return null; String [] subArray = new String[depth]; if (a.length < depth) return null; for (int i = 0; i < depth; i++) { subArray[i] = a[i]; } return subArray; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ public Object[] getElements(Object inputElement) { if (inputElement instanceof String[]) { return (Object[])inputElement; } if (inputElement instanceof UniversalLanguage []) { UniversalLanguage [] uls = (UniversalLanguage[])inputElement; if (useTree == false) { return uls; } HashSet<String> langSet = new HashSet<String>(uls.length); for (int i = 0; i < uls.length; i++) { if (!langSet.contains(uls[i].getLanguageCode())) langSet.add(uls[i].getLanguageCode()); } String [] elements = new String[langSet.size()]; Iterator<String> ils = langSet.iterator(); int i = 0; while (ils.hasNext()) elements[i++] = ils.next().toString(); return elements; } return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { } /* (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } } /** Modifier for the language cells. This modifies the entries associated * with a specific UniversalLanguage. * @author keith * */ public class LanguageCellModifier implements ICellModifier, ICellEditorValidator { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object, java.lang.String) */ public boolean canModify(Object element, String property) { if (element instanceof UniversalLanguage) { if (property.equals(IN_USE) || property.equals(LANG_FONT) || property.equals(FONT_SIZE)) return true; } return false; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object, java.lang.String) */ public Object getValue(Object element, String property) { UniversalLanguage ul = null; if (element instanceof TableItem) { TableItem ti = ((TableItem)element); if (ti.getData() instanceof UniversalLanguage) { ul = (UniversalLanguage)ti.getData(); } } else if (element instanceof UniversalLanguage) { ul = (UniversalLanguage)element; } if (ul != null) { if (property.equals(IN_USE)) return (inUseTypes.containsKey(ul.getCode()))? Boolean.TRUE : Boolean.FALSE; if (property.equals(LANG_FONT)) return labelProvider.getColumnText(ul, LANG_FONT_COL); if (property.equals(FONT_SIZE)) return labelProvider.getColumnText(ul, FONT_SIZE_COL); } return null; } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object, java.lang.String, java.lang.Object) */ public void modify(Object element, String property, Object value) { if (element instanceof TreeItem) { TreeItem ti = (TreeItem)element; if (ti.getData() instanceof UniversalLanguage) { UniversalLanguage ul = (UniversalLanguage)ti.getData(); LangType lt = availableTypes.get(ul.getCode()); if (property.equals(LANG_FONT)) { if (!lt.getFont().equals(value)) { lt.setFont(value.toString()); if (inUseTypes.containsKey(ul.getCode())) { lt = (LangType)inUseTypes.get(ul.getCode()); lt.setFont(value.toString()); } setDirty(true); tableViewer.refresh(ul, true); } } else if (property.equals(FONT_SIZE)) { try { float size = Float.parseFloat(value.toString()); BigDecimal bdSize = BigDecimal.valueOf(size); if (!lt.getFontSize().equals(bdSize)) { lt.setFontSize(bdSize); if (inUseTypes.containsKey(ul.getCode())) { lt = (LangType)inUseTypes.get(ul.getCode()); lt.setFontSize(bdSize); } setDirty(true); tableViewer.refresh(ul, true); } } catch (NumberFormatException e) { LanguageTestPlugin.log(IStatus.WARNING, e.getLocalizedMessage(),e); } } else if (property.equals(IN_USE)) { if (((Boolean)value).booleanValue()) { if (!inUseTypes.containsKey(ul.getCode())) { LangType lang = availableTypes.get(ul.getCode()); inUseTypes.put(ul.getCode(), lang.copy()); } } else { inUseTypes.remove(ul.getCode()); } setDirty(true); tableViewer.refresh(ul, true); } } } } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ICellEditorValidator#isValid(java.lang.Object) */ public String isValid(Object value) { // null means valid return null; } } public boolean isDirty() { return dirty; } protected void setDirty(boolean dirtyNow) { if (dirtyNow) { Iterator<ModifyListener> i = modifyListeners.iterator(); while (i.hasNext()) { ModifyListener ml = i.next(); Event e = new Event(); e.widget = tableViewer.getTree(); ModifyEvent me = new ModifyEvent(e); ml.modifyText(me); } } dirty = dirtyNow; } }