/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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 * * Contributors: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.editor; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.IProgressMonitor; import org.jboss.tools.common.editor.form.RightFormContainer; import org.jboss.tools.common.editor.form.SampleErrorForm; import org.jboss.tools.common.editor.form.SampleTreeForm; import org.jboss.tools.common.model.util.ModelFeatureFactory; import org.jboss.tools.common.model.util.XModelTreeListenerSWTASync; import org.eclipse.jface.action.IAction; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Image; 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.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPropertyListener; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.jboss.tools.common.meta.action.XActionItem; import org.jboss.tools.common.meta.action.XActionList; import org.jboss.tools.common.model.XFilteredTreeConstraint; import org.jboss.tools.common.model.XModel; import org.jboss.tools.common.model.XModelObject; import org.jboss.tools.common.model.event.XModelTreeEvent; import org.jboss.tools.common.model.event.XModelTreeListener; import org.jboss.tools.common.model.filesystems.FileSystemsHelper; import org.jboss.tools.common.model.ui.ModelUIPlugin; import org.jboss.tools.common.model.ui.forms.DefaultFormFactory; import org.jboss.tools.common.model.ui.forms.FormFactory; import org.jboss.tools.common.model.ui.forms.IFormFactory; import org.jboss.tools.common.model.ui.forms.LayouredFormFactory; import org.jboss.tools.common.model.ui.forms.XModelObjectFormFactory; import org.jboss.tools.common.model.ui.forms.DefaultFormContainer; import org.jboss.tools.common.model.ui.forms.DefaultFormPage; import org.jboss.tools.common.model.ui.forms.IForm; import org.jboss.tools.common.model.ui.forms.MementoDOM; import org.jboss.tools.common.model.ui.forms.SplitFormContainer; import org.jboss.tools.common.model.ui.resources.ResourceLayoutManager; import org.jboss.tools.common.model.ui.texteditors.TextActionHelper; import org.jboss.tools.common.model.ui.widgets.IWidgetSettings; public class TreeFormPage extends DefaultFormPage implements ITextEditor, ITextOperationTarget, ISelectionChangedListener { private SelectionNotifier selectionNotifier; private XModelObject installedObject; private XModel model; private boolean errorMode; private Map<String,IAction> actions = new HashMap<String,IAction>(); private ArrayList<String> actionMapping = new ArrayList<String>(); private IEditorSite site; private IEditorInput input; private DefaultFormContainer mainContainer; private SplitFormContainer splitContainer; private SampleTreeForm treeForm; private SampleErrorForm errorForm; private RightFormContainer rightFormContainer; private XModelTreeListenerSWTASync modelListener = new XModelTreeListenerSWTASync(new XMTL()); public TreeFormPage() { GridLayout layout = new GridLayout(); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 10; layout.marginWidth = 10; selectionNotifier = new SelectionNotifier(); selectionNotifier.addSelectionChangedListener(this); this.setSelectionProvider(selectionNotifier); errorForm = new SampleErrorForm(); errorForm.setVisible(Boolean.FALSE.booleanValue()); errorForm.setLayout(layout); treeForm = new SampleTreeForm(this); treeForm.setSelectionNotifier(selectionNotifier); rightFormContainer = new RightFormContainer(); rightFormContainer.setSelectionChangedListener(selectionNotifier); layout = new GridLayout(); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 5; layout.marginWidth = 5; splitContainer = new SplitFormContainer(treeForm, rightFormContainer); splitContainer.setLayout(layout); splitContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); mainContainer = new DefaultFormContainer(); mainContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); mainContainer.addForm(errorForm); mainContainer.addForm(splitContainer); this.form = mainContainer; } public void addErrorSelectionListener(ErrorSelectionListener listener) { errorForm.addErrorSelectionListener(listener); } public void addFilter(XFilteredTreeConstraint filter) { treeForm.addFilter(filter); } public void initialize(Object model) { this.installedObject = (XModelObject)model; this.model = installedObject.getModel(); treeForm.initialize(model); // add model listener } public Control createFormControl(Composite parent, IWidgetSettings settings) { final XModel m = model; m.addModelTreeListener(modelListener); Control c = super.createFormControl(parent, settings); c.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { m.removeModelTreeListener(modelListener); } }); return c; } public void update() { if(control == null || control.isDisposed()) return; if (treeForm!=null) treeForm.update(); if (rightFormContainer!=null) rightFormContainer.update(); } public ISelectionProvider getSelectionProvider() { return selectionNotifier; } private void printActionList(String level, XActionList actionList) { if(!ModelUIPlugin.getDefault().isDebugging()) return; String actionListName = actionList.getName(); String actionListDisplayName = actionList.getDisplayName(); String actionListPath = actionList.getPath(); XActionItem[] items = actionList.getActionItems(); for (int i=0;i<items.length;++i) { if (items[i] instanceof XActionList) { printActionList(level+" ", (XActionList)items[i]); //$NON-NLS-1$ } else { String actionItemName = items[i].getName(); String actionItemDisplayName = items[i].getDisplayName(); String actionItemPath = items[i].getPath(); } } } private MementoDOM memento; private XModelObject selection = null; private XModelObject nextSelection = null; boolean updateLater = true; // ISelectionChangedListener public void selectionChanged(SelectionChangedEvent event) { if(event.getSelection() instanceof ITextSelection) return; final XModelObject xmo = getModelObject(event.getSelection()); if(nextSelection == xmo) return; nextSelection = xmo; saveForm(); if(!updateLater) { updateSelection(xmo); } else { Display.getDefault().asyncExec(new Runnable() { public void run() { updateSelection(xmo); } }); } } void saveForm() { // store form into memento if (rightFormContainer.size()>0) { if (memento!=null) { Iterator i = rightFormContainer.iterator(); while (i.hasNext()) { IForm iForm = (IForm)i.next(); IMemento formMemento = memento.getChild(iForm.getHeadingText()); if (formMemento==null) formMemento = memento.createChild(iForm.getHeadingText()); iForm.store(formMemento); } } } } public void updateSelection(XModelObject xmo) { if(xmo != nextSelection) return; if(selection == nextSelection) return; selection = nextSelection; if (xmo!=null && xmo.getModelEntity()!=null) printActionList("", xmo.getModelEntity().getActionList()); //$NON-NLS-1$ IForm form = (xmo == null) ? null : getFormFactory(xmo).getForm(); rightFormContainer.clear(); if(form != null) { form.initialize(xmo); // load form from memento if (memento!=null) { IMemento formMementro = memento.getChild(form.getHeadingText()); if (formMementro==null) formMementro = memento.createChild(form.getHeadingText()); form.load(formMementro); } if(rightFormContainer.getControl() == null || rightFormContainer.getControl().isDisposed()) { return; } rightFormContainer.addForm(form); form.setParent(rightFormContainer); if(checkFocus()) { setFocus(); } } } boolean checkFocus() { Control c = Display.getDefault().getFocusControl(); if(c == null) { return true; } return false; } private IFormFactory getFormFactory(XModelObject selected) { if(selected == null) return null; XModelObjectFormFactory formFactory = null; String formFactoryClassName = selected.getModelEntity().getProperty("formFactory"); //$NON-NLS-1$ if(formFactoryClassName != null) { if("%Default%".equals(formFactoryClassName)) { //$NON-NLS-1$ return new LayouredFormFactory(selected); } Class cls = ModelFeatureFactory.getInstance().getFeatureClass(formFactoryClassName); if(cls == null) return new FormFactory(selected); try { Constructor c = cls.getConstructor(new Class[]{XModelObject.class}); formFactory = (XModelObjectFormFactory)c.newInstance(new Object[]{selected}); } catch (InstantiationException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (SecurityException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (NoSuchMethodException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (IllegalArgumentException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (IllegalAccessException e) { ModelUIPlugin.getPluginLog().logError(e); } catch (InvocationTargetException e) { ModelUIPlugin.getPluginLog().logError(e); } return formFactory == null ? new FormFactory(selected) : formFactory; } else { formFactory = new DefaultFormFactory(selected); } return formFactory; } private XModelObject getModelObject(ISelection selection) { if(!(selection instanceof IStructuredSelection) || selection.isEmpty()) return null; IStructuredSelection s = (IStructuredSelection)selection; Object o = s.getFirstElement(); return (o instanceof XModelObject) ? (XModelObject)o : null; } class XMTL implements XModelTreeListener { public void nodeChanged(XModelTreeEvent event) { XModelObject o = event.getModelObject(); String p1 = "" + installedObject.getPath() + "/"; //$NON-NLS-1$ //$NON-NLS-2$ String p2 = "" + o.getPath() + "/"; //$NON-NLS-1$ //$NON-NLS-2$ if(p2.startsWith(p1)) { update(); } } public void structureChanged(XModelTreeEvent event) { XModelObject o = event.getModelObject(); String p1 = "" + installedObject.getPath() + "/"; //$NON-NLS-1$ //$NON-NLS-2$ String p2 = "" + o.getPath() + "/"; //$NON-NLS-1$ //$NON-NLS-2$ if(p2.startsWith(p1)) { update(); } } } public boolean isErrorMode() { return errorMode; } public void setErrorMode(boolean b) { errorMode = b; if (this.installedObject!=null) doErrorMode(); mainContainer.setEnabled(!b); } private void doErrorMode() { if (isErrorMode()) { // show error page errorForm.initialize(getErrors()); errorForm.setVisible(Boolean.TRUE.booleanValue()); } else { // hide error page //errorForm.initialize(this.installedObject.get("errors")); errorForm.setVisible(Boolean.FALSE.booleanValue()); } } private String getErrors() { XModelObject f = FileSystemsHelper.getFile(installedObject); if(f == null) { f = installedObject; } return f.get("errors"); //$NON-NLS-1$ } public IDocumentProvider getDocumentProvider() { return null; } public void close(boolean save) { store(); } public boolean isEditable() { return false; } public void doRevertToSaved() { } public void setAction(String actionID, IAction action) { actions.put(actionID, action); } public IAction getAction(String id) { return (IAction)actions.get(id); } public void setActionActivationCode(String actionId, char activationCharacter, int activationKeyCode, int activationStateMask) { } public void removeActionActivationCode(String actionId) { } public boolean showsHighlightRangeOnly() { return false; } public void showHighlightRangeOnly(boolean showHighlightRangeOnly) { } public void setHighlightRange(int offset, int length, boolean moveCursor) { } public IRegion getHighlightRange() { return null; } public void resetHighlightRange() {} public void selectAndReveal(int offset, int length) {} public IEditorInput getEditorInput() { return input; } public IEditorSite getEditorSite() { return site; } public void gotoMarker(IMarker marker) { } public void init(IEditorSite site, IEditorInput input) throws PartInitException { this.site = site; this.input = input; if (input instanceof IFileEditorInput) { memento = new MementoDOM(ResourceLayoutManager.getDefault().getLayoutElement(getFile(), "TreeFormPage")); //$NON-NLS-1$ } } public void addPropertyListener(IPropertyListener listener) { } public void createPartControl(Composite parent) { super.createControl(parent); createActions(); } public IWorkbenchPartSite getSite() { return site; } public Image getTitleImage() { return null; } public String getTitleToolTip() { return null; } public void removePropertyListener(IPropertyListener listener) { } public void setFocus() { if(treeForm != null && treeForm.getControl() != null && !treeForm.getControl().isDisposed()) { treeForm.setFocus(); } else { if(control != null && !control.isDisposed()) control.setFocus(); } } public Object getAdapter(Class adapter) { if (ITextOperationTarget.class.equals(adapter)) return this; return null; } private IFile getFile() { return (input instanceof IFileEditorInput) ? ((IFileEditorInput)input).getFile() : null; } private void store() { IFile file = getFile(); if(file == null) return; ResourceLayoutManager.getDefault().store(file); } public void doSave(IProgressMonitor monitor) { store(); } public void doSaveAs() { store(); } public boolean isDirty() { return false; } public boolean isSaveAsAllowed() { return false; } public boolean isSaveOnCloseNeeded() { return false; } public boolean canDoOperation(int operation) { // Collection actions = this.actions.values(); // Iterator i = actions.iterator(); // IAction action; // while (i.hasNext()) { // action = (IAction)i.next(); // } return true; } public void doOperation(int operation) { if (operation>actionMapping.size()) { ModelUIPlugin.getPluginLog().logError(new IllegalArgumentException("Can not find global action with index: "+operation)); //$NON-NLS-1$ } else { String globalAction = (String)actionMapping.get(operation); this.doGlobalAction(globalAction); } } protected void createActions() { actionMapping.add(null); actionMapping.add(ITextOperationTarget.UNDO, ActionFactory.UNDO.getId()); actionMapping.add(ITextOperationTarget.REDO, ActionFactory.REDO.getId()); actionMapping.add(ITextOperationTarget.CUT, ActionFactory.CUT.getId()); actionMapping.add(ITextOperationTarget.COPY, ActionFactory.COPY.getId()); actionMapping.add(ITextOperationTarget.PASTE, ActionFactory.PASTE.getId()); actionMapping.add(ITextOperationTarget.DELETE, ActionFactory.DELETE.getId()); actionMapping.add(ITextOperationTarget.SELECT_ALL, ActionFactory.SELECT_ALL.getId()); actionMapping.add(ITextOperationTarget.SHIFT_RIGHT, ITextEditorActionConstants.SHIFT_RIGHT); actionMapping.add(ITextOperationTarget.SHIFT_LEFT, ITextEditorActionConstants.SHIFT_LEFT); actionMapping.add(ITextOperationTarget.PRINT, ActionFactory.PRINT.getId()); TextActionHelper.addCutAction(this); TextActionHelper.addCopyAction(this); TextActionHelper.addPasteAction(this); TextActionHelper.addDeleteAction(this); } public void doGlobalAction(String action) { if(errorForm != null && errorForm.isVisible() && errorForm.doGlobalAction(action)) { return; } if(treeForm.doGlobalAction(action)) { return; } if(mainContainer.doGlobalAction(action)) { // TODO // refresh } } }