001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.editor.schema;
011:
012: import java.util.Arrays;
013: import java.util.Iterator;
014:
015: import org.eclipse.core.runtime.Path;
016: import org.eclipse.jface.action.Action;
017: import org.eclipse.jface.action.IMenuManager;
018: import org.eclipse.jface.action.MenuManager;
019: import org.eclipse.jface.action.Separator;
020: import org.eclipse.jface.action.ToolBarManager;
021: import org.eclipse.jface.dialogs.MessageDialog;
022: import org.eclipse.jface.viewers.ISelection;
023: import org.eclipse.jface.viewers.IStructuredSelection;
024: import org.eclipse.jface.viewers.ITreeContentProvider;
025: import org.eclipse.jface.viewers.StructuredSelection;
026: import org.eclipse.jface.viewers.TreeViewer;
027: import org.eclipse.osgi.util.NLS;
028: import org.eclipse.pde.core.IModelChangedEvent;
029: import org.eclipse.pde.internal.core.ICoreConstants;
030: import org.eclipse.pde.internal.core.ischema.ISchema;
031: import org.eclipse.pde.internal.core.ischema.ISchemaAttribute;
032: import org.eclipse.pde.internal.core.ischema.ISchemaComplexType;
033: import org.eclipse.pde.internal.core.ischema.ISchemaCompositor;
034: import org.eclipse.pde.internal.core.ischema.ISchemaElement;
035: import org.eclipse.pde.internal.core.ischema.ISchemaInclude;
036: import org.eclipse.pde.internal.core.ischema.ISchemaObject;
037: import org.eclipse.pde.internal.core.ischema.ISchemaObjectReference;
038: import org.eclipse.pde.internal.core.ischema.ISchemaRootElement;
039: import org.eclipse.pde.internal.core.ischema.ISchemaSimpleType;
040: import org.eclipse.pde.internal.core.ischema.ISchemaType;
041: import org.eclipse.pde.internal.core.schema.Schema;
042: import org.eclipse.pde.internal.core.schema.SchemaAttribute;
043: import org.eclipse.pde.internal.core.schema.SchemaCompositor;
044: import org.eclipse.pde.internal.core.schema.SchemaElement;
045: import org.eclipse.pde.internal.core.schema.SchemaElementReference;
046: import org.eclipse.pde.internal.core.schema.SchemaRootElement;
047: import org.eclipse.pde.internal.ui.PDEPlugin;
048: import org.eclipse.pde.internal.ui.PDEUIMessages;
049: import org.eclipse.pde.internal.ui.editor.ModelDataTransfer;
050: import org.eclipse.pde.internal.ui.editor.PDEFormPage;
051: import org.eclipse.pde.internal.ui.editor.TreeSection;
052: import org.eclipse.pde.internal.ui.editor.actions.CollapseAction;
053: import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
054: import org.eclipse.pde.internal.ui.parts.TreePart;
055: import org.eclipse.swt.SWT;
056: import org.eclipse.swt.dnd.Clipboard;
057: import org.eclipse.swt.dnd.DND;
058: import org.eclipse.swt.dnd.TextTransfer;
059: import org.eclipse.swt.dnd.Transfer;
060: import org.eclipse.swt.events.DisposeEvent;
061: import org.eclipse.swt.events.DisposeListener;
062: import org.eclipse.swt.graphics.Cursor;
063: import org.eclipse.swt.widgets.Composite;
064: import org.eclipse.swt.widgets.Display;
065: import org.eclipse.swt.widgets.ToolBar;
066: import org.eclipse.ui.actions.ActionFactory;
067: import org.eclipse.ui.forms.widgets.FormToolkit;
068: import org.eclipse.ui.forms.widgets.Section;
069:
070: public class ElementSection extends TreeSection {
071: private TreeViewer fTreeViewer;
072: private Schema fSchema;
073: private NewElementAction fNewElementAction = new NewElementAction();
074: private NewAttributeAction fNewAttributeAction = new NewAttributeAction();
075: private Clipboard fClipboard;
076: private SchemaRearranger fRearranger;
077: private CollapseAction fCollapseAction;
078:
079: class ContentProvider extends DefaultContentProvider implements
080: ITreeContentProvider {
081: public Object[] getElements(Object object) {
082: if (object instanceof Schema) {
083: Schema schema = (Schema) object;
084: return schema.getElements();
085: }
086: return new Object[0];
087: }
088:
089: public Object[] getChildren(Object parent) {
090: Object[] children = new Object[0];
091: if (parent instanceof ISchemaElement) {
092: Object[] types = new Object[0];
093: Object[] attributes = ((ISchemaElement) parent)
094: .getAttributes();
095: ISchemaType type = ((ISchemaElement) parent).getType();
096: if (type instanceof ISchemaComplexType) {
097: Object compositor = ((ISchemaComplexType) type)
098: .getCompositor();
099: if (compositor != null)
100: types = new Object[] { compositor };
101: }
102: children = new Object[types.length + attributes.length];
103: System.arraycopy(types, 0, children, 0, types.length);
104: System.arraycopy(attributes, 0, children, types.length,
105: attributes.length);
106: } else if (parent instanceof ISchemaCompositor) {
107: children = ((ISchemaCompositor) parent).getChildren();
108: }
109: return children;
110: }
111:
112: public Object getParent(Object child) {
113: if (child instanceof ISchemaObject)
114: return ((ISchemaObject) child).getParent();
115: return null;
116: }
117:
118: public boolean hasChildren(Object parent) {
119: if (parent instanceof ISchemaAttribute
120: || parent instanceof ISchemaObjectReference)
121: return false;
122: return getChildren(parent).length > 0;
123: }
124: }
125:
126: public ElementSection(PDEFormPage page, Composite parent) {
127: super (page, parent, Section.DESCRIPTION, new String[] {
128: PDEUIMessages.SchemaEditor_ElementSection_newElement,
129: PDEUIMessages.SchemaEditor_ElementSection_newAttribute,
130: PDEUIMessages.SchemaEditor_ElementSection_newChoice,
131: PDEUIMessages.SchemaEditor_ElementSection_newSequence,
132: PDEUIMessages.SchemaEditor_ElementSection_remove });
133: getSection().setText(
134: PDEUIMessages.SchemaEditor_ElementSection_title);
135: getSection().setDescription(
136: PDEUIMessages.SchemaEditor_ElementSection_desc);
137: }
138:
139: public void createClient(Section section, FormToolkit toolkit) {
140: Composite container = createClientContainer(section, 2, toolkit);
141: createTree(container, toolkit);
142: toolkit.paintBordersFor(container);
143: section.setClient(container);
144: initialize();
145: createSectionToolbar(section, toolkit);
146: }
147:
148: /**
149: * @param section
150: * @param toolkit
151: */
152: private void createSectionToolbar(Section section,
153: FormToolkit toolkit) {
154:
155: ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
156: ToolBar toolbar = toolBarManager.createControl(section);
157: final Cursor handCursor = new Cursor(Display.getCurrent(),
158: SWT.CURSOR_HAND);
159: toolbar.setCursor(handCursor);
160: // Cursor needs to be explicitly disposed
161: toolbar.addDisposeListener(new DisposeListener() {
162: public void widgetDisposed(DisposeEvent e) {
163: if ((handCursor != null)
164: && (handCursor.isDisposed() == false)) {
165: handCursor.dispose();
166: }
167: }
168: });
169: // Add collapse action to the tool bar
170: fCollapseAction = new CollapseAction(fTreeViewer,
171: PDEUIMessages.ExtensionsPage_collapseAll);
172: toolBarManager.add(fCollapseAction);
173:
174: toolBarManager.update(true);
175:
176: section.setTextClient(toolbar);
177: }
178:
179: private void createTree(Composite container, FormToolkit toolkit) {
180: TreePart treePart = getTreePart();
181: createViewerPartControl(container, SWT.MULTI, 2, toolkit);
182: fTreeViewer = treePart.getTreeViewer();
183: fTreeViewer.setContentProvider(new ContentProvider());
184: fTreeViewer.setLabelProvider(PDEPlugin.getDefault()
185: .getLabelProvider());
186: PDEPlugin.getDefault().getLabelProvider().connect(this );
187: initDragAndDrop();
188: }
189:
190: protected void initDragAndDrop() {
191: fClipboard = new Clipboard(fTreeViewer.getControl()
192: .getDisplay());
193: int ops = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
194: Transfer[] transfers = new Transfer[] {
195: ModelDataTransfer.getInstance(),
196: TextTransfer.getInstance() };
197: ElementSectionDragAdapter dragAdapter = new ElementSectionDragAdapter(
198: fTreeViewer);
199: fTreeViewer.addDragSupport(ops, transfers, dragAdapter);
200: fTreeViewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers,
201: new ElementSectionDropAdapter(dragAdapter, this ));
202: }
203:
204: protected TreeViewer getTreeViewer() {
205: return fTreeViewer;
206: }
207:
208: public void refresh() {
209: fTreeViewer.refresh();
210: super .refresh();
211:
212: if (fTreeViewer.getSelection().isEmpty()
213: && fSchema.getElementCount() > 0) {
214: fTreeViewer.setSelection(new StructuredSelection(fSchema
215: .getElements()[0]));
216: }
217: }
218:
219: protected void buttonSelected(int index) {
220: switch (index) {
221: case 0:
222: handleNewElement();
223: break;
224: case 1:
225: handleNewAttribute();
226: break;
227: case 2:
228: addCompositor(ISchemaCompositor.CHOICE);
229: break;
230: case 3:
231: addCompositor(ISchemaCompositor.SEQUENCE);
232: break;
233: case 4:
234: final ISelection selection = fTreeViewer.getSelection();
235: handleDelete((IStructuredSelection) selection);
236: break;
237: }
238: }
239:
240: private void addCompositor(int kind) {
241: Object selection = ((IStructuredSelection) fTreeViewer
242: .getSelection()).getFirstElement();
243: ISchemaElement sourceElement = null;
244: Object current = selection;
245: while (current instanceof ISchemaCompositor)
246: current = ((ISchemaCompositor) current).getParent();
247: if (current instanceof ISchemaElement)
248: sourceElement = (ISchemaElement) current;
249: if (sourceElement != null)
250: new NewCompositorAction(sourceElement, selection, kind)
251: .run();
252: }
253:
254: public void dispose() {
255: if (fClipboard != null) {
256: fClipboard.dispose();
257: fClipboard = null;
258: }
259: PDEPlugin.getDefault().getLabelProvider().disconnect(this );
260: super .dispose();
261: }
262:
263: public boolean doGlobalAction(String actionId) {
264: boolean cut = actionId.equals(ActionFactory.CUT.getId());
265: if (cut || actionId.equals(ActionFactory.DELETE.getId())) {
266: // Get the current selection
267: IStructuredSelection sel = (IStructuredSelection) fTreeViewer
268: .getSelection();
269: // Get the first selected object
270: Object selectedObject = sel.getFirstElement();
271: // Ensure we have a selection
272: if (selectedObject == null) {
273: return true;
274: }
275: handleDelete(sel);
276: // if cutting delete here and let the editor transfer
277: // the selection to the clipboard
278: return !cut;
279: }
280: if (actionId.equals(ActionFactory.PASTE.getId())) {
281: doPaste();
282: return true;
283: }
284: return false;
285: }
286:
287: public boolean setFormInput(Object object) {
288: if (object instanceof ISchemaElement
289: || object instanceof ISchemaAttribute
290: || object instanceof ISchemaCompositor) {
291: fTreeViewer.setSelection(new StructuredSelection(object),
292: true);
293:
294: ISelection selection = fTreeViewer.getSelection();
295: if (selection != null && !selection.isEmpty())
296: return true;
297: if (object instanceof ISchemaElement) {
298: ISchemaElement found = fSchema
299: .findElement(((ISchemaElement) object)
300: .getName());
301: if (found != null)
302: fTreeViewer.setSelection(new StructuredSelection(
303: found), true);
304: return found != null;
305: }
306: }
307: return false;
308: }
309:
310: protected void fillContextMenu(IMenuManager manager) {
311: final ISelection selection = fTreeViewer.getSelection();
312: final Object object = ((IStructuredSelection) selection)
313: .getFirstElement();
314:
315: MenuManager submenu = new MenuManager(
316: PDEUIMessages.Menus_new_label);
317: if (object == null) {
318: fNewElementAction.setSchema(fSchema);
319: fNewElementAction.setEnabled(fSchema.isEditable());
320: submenu.add(fNewElementAction);
321: }
322: if (object != null) {
323: ISchemaElement element = null;
324: if (object instanceof SchemaElement)
325: element = (SchemaElement) object;
326: else if (object instanceof SchemaAttribute)
327: element = (SchemaElement) ((SchemaAttribute) object)
328: .getParent();
329:
330: if (element != null
331: && !(element instanceof ISchemaRootElement)
332: && !(element instanceof ISchemaObjectReference)) { //$NON-NLS-1$
333: fNewAttributeAction.setElement((SchemaElement) element);
334: fNewAttributeAction.setEnabled(fSchema.isEditable());
335: submenu.add(fNewAttributeAction);
336: }
337: }
338: if (object instanceof SchemaElement
339: || object instanceof SchemaCompositor) {
340: ISchemaElement sourceElement = null;
341: ISchemaObject schemaObject = (ISchemaObject) object;
342: while (schemaObject != null) {
343: if (schemaObject instanceof ISchemaElement) {
344: sourceElement = (ISchemaElement) schemaObject;
345: break;
346: }
347: schemaObject = schemaObject.getParent();
348: }
349: if (sourceElement != null) {
350: if (object instanceof SchemaCompositor
351: || sourceElement.getType() instanceof ISchemaSimpleType
352: || ((ISchemaComplexType) sourceElement
353: .getType()).getCompositor() == null) {
354: if (submenu.getItems().length > 0)
355: submenu.add(new Separator());
356: submenu.add(new NewCompositorAction(sourceElement,
357: object, ISchemaCompositor.CHOICE));
358: submenu.add(new NewCompositorAction(sourceElement,
359: object, ISchemaCompositor.SEQUENCE));
360: }
361: if (object instanceof SchemaCompositor) {
362: boolean seperatorAdded = false;
363: ISchemaElement[] elements = sourceElement
364: .getSchema().getResolvedElements();
365: Arrays.sort(elements);
366: for (int i = 0; i < elements.length; i++) {
367: if (!(elements[i] instanceof SchemaRootElement)) {
368: if (!seperatorAdded) {
369: submenu.add(new Separator());
370: seperatorAdded = true;
371: }
372: submenu
373: .add(new NewReferenceAction(
374: sourceElement, object,
375: elements[i]));
376: }
377: }
378: }
379: }
380: }
381: manager.add(submenu);
382: if (object != null) {
383: if (!(object instanceof ISchemaRootElement)) { //$NON-NLS-1$
384: if (manager.getItems().length > 0)
385: manager.add(new Separator());
386: if (!(object instanceof ISchemaAttribute && ((ISchemaAttribute) object)
387: .getParent() instanceof ISchemaRootElement)) {
388: Action deleteAction = new Action() {
389: public void run() {
390: handleDelete((IStructuredSelection) selection);
391: }
392: };
393: deleteAction
394: .setText(PDEUIMessages.Actions_delete_label);
395: deleteAction.setEnabled(fSchema.isEditable());
396: manager.add(deleteAction);
397: }
398: }
399: }
400: getPage().getPDEEditor().getContributor()
401: .contextMenuAboutToShow(manager);
402: manager.add(new Separator());
403: }
404:
405: private void handleDelete(IStructuredSelection selection) {
406: IStructuredSelection nextSelection = null;
407: Object selectionSource = null;
408: for (Iterator iter = selection.iterator(); iter.hasNext();) {
409: Object this Object = iter.next();
410: // Do the delete and generate a new selection in one of the following cases:
411: // 1. No selection has been generated
412: // 2. This object is higher up in the hierarchy than the previous
413: // object used to generate the selection
414: // 3. The object selected for deletion is currently set as the next selection
415: IStructuredSelection result = handleDelete(this Object,
416: nextSelection == null
417: || schemaObjectHigherThan(this Object,
418: selectionSource)
419: || nextSelection.getFirstElement().equals(
420: this Object));
421: if (result != null) {
422: nextSelection = result;
423: selectionSource = this Object;
424: }
425: }
426: if (nextSelection != null)
427: getTreeViewer().setSelection(nextSelection);
428: }
429:
430: private IStructuredSelection handleDelete(Object object,
431: boolean generateSelection) {
432: IStructuredSelection newSelection = null;
433: if (object instanceof ISchemaRootElement) {
434: // Semantic rule: The root "extension" element of a schema
435: // cannot be removed
436:
437: // Produce audible beep
438: Display.getCurrent().beep();
439: } else if (object instanceof SchemaElementReference) {
440: newSelection = handleReferenceDelete(
441: (SchemaElementReference) object, generateSelection);
442: } else if (object instanceof ISchemaElement) {
443: newSelection = handleElementDelete((ISchemaElement) object,
444: generateSelection);
445: } else if (object instanceof ISchemaAttribute) {
446: ISchemaAttribute att = (ISchemaAttribute) object;
447: if (!(att.getParent() instanceof ISchemaRootElement)) {
448: newSelection = handleAttributeDelete(att,
449: generateSelection);
450: } else {
451: // Semantic rule: Attributes of the root "extension" element
452: // of a schema cannot be removed
453:
454: // Produce audible beep
455: Display.getCurrent().beep();
456: }
457: } else if (object instanceof ISchemaCompositor) {
458: newSelection = handleCompositorDelete(
459: (ISchemaCompositor) object, generateSelection);
460: }
461: return newSelection;
462: }
463:
464: private IStructuredSelection handleReferenceDelete(
465: SchemaElementReference ref, boolean generateSelection) {
466: IStructuredSelection newSelection = null;
467: if (generateSelection) {
468: SchemaCompositor parent = (SchemaCompositor) ref
469: .getParent();
470: ISchemaObject[] children = parent.getChildren();
471: int index = getNewSelectionIndex(getArrayIndex(children,
472: ref), children.length);
473: if (index == -1)
474: newSelection = new StructuredSelection(parent);
475: else
476: newSelection = new StructuredSelection(children[index]);
477: }
478: fRearranger.deleteReference(ref);
479: return newSelection;
480: }
481:
482: private IStructuredSelection handleElementDelete(
483: ISchemaElement element, boolean generateSelection) {
484: IStructuredSelection newSelection = null;
485: if (generateSelection) {
486: ISchema parent = element.getSchema();
487: ISchemaElement[] children = parent.getElements();
488: int index = getNewSelectionIndex(getArrayIndex(children,
489: element), children.length);
490: if (index != -1)
491: newSelection = new StructuredSelection(children[index]);
492: }
493: fRearranger.deleteElement(element);
494: return newSelection;
495: }
496:
497: private IStructuredSelection handleAttributeDelete(
498: ISchemaAttribute att, boolean generateSelection) {
499: IStructuredSelection newSelection = null;
500: if (generateSelection) {
501: ISchemaElement parent = (ISchemaElement) att.getParent();
502: ISchemaAttribute[] children = parent.getAttributes();
503: int index = getNewSelectionIndex(getArrayIndex(children,
504: att), children.length);
505: if (index == -1) {
506: ISchemaType type = parent.getType();
507: if (type instanceof ISchemaComplexType) {
508: ISchemaCompositor comp = ((ISchemaComplexType) type)
509: .getCompositor();
510: if (comp != null)
511: newSelection = new StructuredSelection(comp);
512: else
513: newSelection = new StructuredSelection(parent);
514: }
515: } else
516: newSelection = new StructuredSelection(children[index]);
517: }
518: fRearranger.deleteAttribute(att);
519: return newSelection;
520: }
521:
522: private IStructuredSelection handleCompositorDelete(
523: ISchemaCompositor comp, boolean generateSelection) {
524: IStructuredSelection newSelection = null;
525: if (generateSelection) {
526: ISchemaObject parent = comp.getParent();
527: if (parent instanceof ISchemaElement) {
528: ISchemaElement element = (ISchemaElement) parent;
529: ISchemaAttribute[] attributes = element.getAttributes();
530: if (attributes.length > 0)
531: newSelection = new StructuredSelection(
532: attributes[0]);
533: else
534: newSelection = new StructuredSelection(element);
535: } else {
536: ISchemaCompositor parentComp = (ISchemaCompositor) parent;
537: ISchemaObject[] children = parentComp.getChildren();
538: int index = getNewSelectionIndex(getArrayIndex(
539: children, comp), children.length);
540: if (index == -1)
541: newSelection = new StructuredSelection(parent);
542: else
543: newSelection = new StructuredSelection(
544: children[index]);
545: }
546: }
547: fRearranger.deleteCompositor(comp);
548: return newSelection;
549: }
550:
551: // returns true if object a is a SchemaObject higher in the hierarchy than object b
552: // returns false if b is higher or they are equal
553: private boolean schemaObjectHigherThan(Object a, Object b) {
554: if (!(b instanceof ISchemaObject))
555: return true;
556: if (!(a instanceof ISchemaObject))
557: return false;
558: return (computeNestLevel((ISchemaObject) a) < computeNestLevel((ISchemaObject) b));
559: }
560:
561: // determines how deeply nested an ISchemaObject is
562: // returns 0 if this is an element, 1 if it's a direct child, etc.
563: private int computeNestLevel(ISchemaObject o) {
564: int result = 0;
565: while ((o instanceof SchemaElementReference)
566: || !(o instanceof ISchemaElement)) {
567: o = o.getParent();
568: result++;
569: }
570: return result;
571: }
572:
573: private void handleNewAttribute() {
574: Object object = ((IStructuredSelection) fTreeViewer
575: .getSelection()).getFirstElement();
576: if (object != null) {
577: SchemaElement element = null;
578: if (object instanceof SchemaElement)
579: element = (SchemaElement) object;
580: else if (object instanceof SchemaAttribute)
581: element = (SchemaElement) ((SchemaAttribute) object)
582: .getParent();
583:
584: if (element != null
585: && !(element instanceof ISchemaRootElement)) { //$NON-NLS-1$
586: fNewAttributeAction.setElement(element);
587: fNewAttributeAction.run();
588: }
589: }
590: }
591:
592: private void handleNewElement() {
593: fNewElementAction.setSchema(fSchema);
594: fNewElementAction.run();
595: }
596:
597: public void initialize() {
598: this .fSchema = (Schema) getPage().getModel();
599: fRearranger = new SchemaRearranger(fSchema);
600: fTreeViewer.setInput(fSchema);
601: boolean isEditable = fSchema.isEditable();
602: getTreePart().setButtonEnabled(0, isEditable);
603: getTreePart().setButtonEnabled(1, false);
604: getTreePart().setButtonEnabled(2, isEditable);
605: getTreePart().setButtonEnabled(3, isEditable);
606: getTreePart().setButtonEnabled(4, isEditable);
607: }
608:
609: public void handleModelChanged(IModelChangedEvent e) {
610: if (e.getChangedProperty() != null
611: && e.getChangedProperty().equals(
612: ISchemaObject.P_DESCRIPTION))
613: return;
614: if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
615: handleModelEventWorldChanged(e);
616: return;
617: }
618: Object[] objects = e.getChangedObjects();
619: for (int i = 0; i < objects.length; i++) {
620: Object obj = objects[0];
621: if (obj instanceof SchemaElementReference) {
622: fTreeViewer.refresh(((SchemaElementReference) obj)
623: .getCompositor());
624: if (e.getChangeType() == IModelChangedEvent.INSERT)
625: fTreeViewer.setSelection(new StructuredSelection(
626: obj), true);
627: } else if (obj instanceof ISchemaElement
628: || obj instanceof ISchemaAttribute) {
629: if (e.getChangeType() == IModelChangedEvent.CHANGE) {
630: String changeProp = e.getChangedProperty();
631: if (changeProp != null
632: && (changeProp.equals(ISchemaObject.P_NAME) || changeProp
633: .equals(SchemaAttribute.P_KIND)))
634: fTreeViewer.update(obj, null);
635: Object typeCheck = e.getNewValue();
636: if (typeCheck instanceof ISchemaComplexType
637: && changeProp.equals(SchemaElement.P_TYPE)
638: && obj instanceof ISchemaElement) {
639: fTreeViewer.refresh(typeCheck);
640: fTreeViewer.setSelection(
641: new StructuredSelection(typeCheck),
642: true);
643: } else {
644: fTreeViewer.refresh(obj);
645: }
646: } else if (e.getChangeType() == IModelChangedEvent.INSERT) {
647: ISchemaObject sobj = (ISchemaObject) obj;
648: ISchemaObject parent = sobj.getParent();
649: fTreeViewer.refresh(parent);
650: fTreeViewer.setSelection(new StructuredSelection(
651: obj), true);
652: } else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
653: fTreeViewer.remove(obj);
654: // the new selection is handled by the handleDelete method for cuts and deletes,
655: // for moves it is handled by the subsequent insert
656: }
657: } else if (obj instanceof ISchemaCompositor
658: || obj instanceof ISchemaObjectReference) {
659: final ISchemaObject sobj = (ISchemaObject) obj;
660: ISchemaObject parent = sobj.getParent();
661: if (e.getChangeType() == IModelChangedEvent.CHANGE) {
662: fTreeViewer.refresh(sobj);
663: } else if (e.getChangeType() == IModelChangedEvent.INSERT) {
664: fTreeViewer.add(parent, sobj);
665: fTreeViewer.getTree().getDisplay().asyncExec(
666: new Runnable() {
667: public void run() {
668: fTreeViewer.setSelection(
669: new StructuredSelection(
670: sobj), true);
671: }
672: });
673: } else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
674: fTreeViewer.remove(sobj);
675: // the new selection is handled by the handleDelete method for cuts and deletes,
676: // for moves it is handled by the subsequent insert
677: }
678: } else if (obj instanceof ISchemaComplexType) {
679: // first compositor added/removed
680: ISchemaCompositor comp = ((ISchemaComplexType) obj)
681: .getCompositor();
682: fTreeViewer.refresh(comp);
683: if (comp != null)
684: fTreeViewer.refresh(comp.getParent());
685:
686: if (e.getChangeType() == IModelChangedEvent.INSERT
687: || e.getChangeType() == IModelChangedEvent.CHANGE) {
688: ISchemaComplexType type = (ISchemaComplexType) obj;
689: final ISchemaCompositor compositor = type
690: .getCompositor();
691: if (compositor != null) {
692: fTreeViewer.getTree().getDisplay().asyncExec(
693: new Runnable() {
694: public void run() {
695: fTreeViewer
696: .setSelection(
697: new StructuredSelection(
698: compositor),
699: true);
700: }
701: });
702: }
703: }
704: } else if (obj instanceof ISchema) {
705: if (!ISchemaObject.P_NAME
706: .equals(e.getChangedProperty()))
707: fTreeViewer.refresh();
708: }
709: }
710: }
711:
712: /**
713: * @param event
714: */
715: private void handleModelEventWorldChanged(IModelChangedEvent event) {
716: // Note: Cannot use event. There are no changed objects within it
717: // This method acts like a refresh
718: initialize();
719: // TODO: MP: REVERT: LOW: Update initialize with this once Bug #171897 is fixed
720: ISchemaElement root = fSchema.getSchema().findElement(
721: ICoreConstants.EXTENSION_NAME);
722: // Ensure the root element is present
723: if (root == null) {
724: return;
725: }
726: // Select the root extension element
727: fTreeViewer.setSelection(new StructuredSelection(root), true);
728: // Collapse tree to the first level
729: fTreeViewer.expandToLevel(1);
730: }
731:
732: protected void selectionChanged(IStructuredSelection selection) {
733: // getPage().getManagedForm().fireSelectionChanged(this, selection);
734: getPage().getPDEEditor().setSelection(selection);
735: updateButtons();
736: }
737:
738: /* (non-Javadoc)
739: * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#setFocus()
740: */
741: public void setFocus() {
742: if (fTreeViewer != null) {
743: fTreeViewer.getTree().setFocus();
744: getPage().getPDEEditor().setSelection(
745: fTreeViewer.getSelection());
746: }
747: }
748:
749: private void updateButtons() {
750: if (!fSchema.isEditable())
751: return;
752: IStructuredSelection selection = (IStructuredSelection) fTreeViewer
753: .getSelection();
754: ISchemaObject sobject = (ISchemaObject) selection
755: .getFirstElement();
756:
757: boolean canAddAttribute = false;
758: if (sobject instanceof ISchemaElement) {
759: if (!(sobject instanceof ISchemaRootElement)
760: && !(sobject instanceof ISchemaObjectReference))
761: canAddAttribute = true;
762: } else if (sobject instanceof ISchemaAttribute) {
763: ISchemaElement element = (ISchemaElement) (sobject
764: .getParent());
765: if (!(element instanceof ISchemaRootElement))
766: canAddAttribute = true;
767: }
768: getTreePart().setButtonEnabled(1, canAddAttribute);
769:
770: boolean canAddCompositor = false;
771: if (sobject instanceof ISchemaCompositor
772: || (sobject instanceof ISchemaElement
773: && !(sobject instanceof SchemaElementReference) && (((ISchemaElement) sobject)
774: .getType() instanceof ISchemaSimpleType || ((ISchemaComplexType) ((ISchemaElement) sobject)
775: .getType()).getCompositor() == null)))
776: canAddCompositor = true;
777: getTreePart().setButtonEnabled(2, canAddCompositor);
778: getTreePart().setButtonEnabled(3, canAddCompositor);
779:
780: boolean canRemove = false;
781: for (Iterator iter = selection.iterator(); iter.hasNext();) {
782: sobject = (ISchemaObject) iter.next();
783: if (sobject != null
784: && !(sobject instanceof ISchemaRootElement)
785: && !(sobject instanceof ISchemaAttribute && sobject
786: .getParent() instanceof ISchemaRootElement)) {
787: canRemove = true;
788: break;
789: }
790: }
791: getTreePart().setButtonEnabled(4, canRemove);
792: }
793:
794: private ISchemaObject getSibling(Object target, Object object) {
795: if (target instanceof ISchemaElement
796: && object instanceof ISchemaElement)
797: return (ISchemaElement) target;
798: if (target instanceof ISchemaAttribute
799: && object instanceof ISchemaAttribute)
800: return (ISchemaAttribute) target;
801: if (target instanceof SchemaElementReference
802: && object instanceof ISchemaElement)
803: return (SchemaElementReference) target;
804: return null;
805: }
806:
807: private ISchemaObject getRealTarget(Object target, Object object) {
808: if (object instanceof ISchemaElement
809: || object instanceof ISchemaObjectReference) {
810: if (target instanceof SchemaElementReference)
811: return ((SchemaElementReference) target)
812: .getCompositor();
813: if (target instanceof ISchemaCompositor)
814: return (ISchemaCompositor) target;
815: if (object instanceof ISchemaElement)
816: return fSchema;
817: }
818: if (object instanceof ISchemaAttribute) {
819: if (target instanceof ISchemaAttribute) {
820: // add it to the parent of the selected attribute
821: return ((ISchemaAttribute) target).getParent();
822: }
823: if (target instanceof ISchemaElement)
824: return (ISchemaElement) target;
825: }
826: if (object instanceof ISchemaCompositor) {
827: if (target instanceof SchemaElementReference)
828: return ((SchemaElementReference) target)
829: .getCompositor();
830: if (target instanceof ISchemaElement)
831: return (ISchemaElement) target;
832: if (target instanceof ISchemaCompositor)
833: return (ISchemaCompositor) target;
834: }
835: return null;
836: }
837:
838: protected boolean canPaste(Object target, Object[] objects) {
839: for (int i = 0; i < objects.length; i++) {
840: Object obj = objects[i];
841: if (obj instanceof ISchemaAttribute
842: && target instanceof ISchemaAttribute) {
843: continue;
844: } else if (obj instanceof ISchemaObjectReference
845: && target instanceof ISchemaCompositor) {
846: continue;
847: } else if (target instanceof ISchemaElement
848: && !(target instanceof ISchemaObjectReference)
849: && !(obj instanceof ISchemaRootElement)) {
850: continue;
851: }
852: return false;
853: }
854: return true;
855: }
856:
857: protected void handleDoubleClick(IStructuredSelection selection) {
858: super .handleDoubleClick(selection);
859: Object object = selection.getFirstElement();
860: if (object instanceof SchemaElementReference) {
861: ISchemaElement element = ((SchemaElementReference) object)
862: .getReferencedElement();
863: if (element == null) {
864: String name = ((SchemaElementReference) object)
865: .getName();
866: MessageDialog
867: .openWarning(
868: getPage().getSite().getShell(),
869: PDEUIMessages.ElementSection_missingRefElement,
870: NLS
871: .bind(
872: PDEUIMessages.SchemaIncludesSection_missingWarningMessage,
873: name));
874: return;
875: }
876: ISchema schema = element.getSchema();
877: if (schema.equals(fSchema))
878: fireSelection(new StructuredSelection(element));
879: else {
880: ISchemaInclude[] includes = fSchema.getIncludes();
881: for (int i = 0; i < includes.length; i++) {
882: if (includes[i].getIncludedSchema().equals(schema)) {
883: String location = includes[i].getLocation();
884: SchemaEditor.openToElement(new Path(location),
885: element);
886: break;
887: }
888: }
889: }
890: }
891: }
892:
893: protected void fireSelection(ISelection selection) {
894: if (selection == null)
895: selection = fTreeViewer.getSelection();
896: fTreeViewer.setSelection(selection);
897: }
898:
899: protected void doPaste(Object target, Object[] objects) {
900: handleOp(target, objects, DND.DROP_COPY);
901: }
902:
903: public void handleOp(Object currentTarget, Object[] objects,
904: int currentOperation) {
905: for (int i = 0; i < objects.length; i++) {
906: if (!(objects[i] instanceof ISchemaObject))
907: continue;
908: ISchemaObject object = (ISchemaObject) objects[i];
909: ISchemaObject realTarget = getRealTarget(currentTarget,
910: object);
911: ISchemaObject sibling = getSibling(currentTarget, object);
912: if (realTarget == null)
913: continue;
914: switch (currentOperation) {
915: case DND.DROP_COPY:
916: doPaste(realTarget, sibling, object);
917: break;
918: case DND.DROP_MOVE:
919: doMove(realTarget, sibling, object);
920: break;
921: case DND.DROP_LINK:
922: doLink(realTarget, sibling, object);
923: break;
924: }
925: }
926: }
927:
928: private void doLink(ISchemaObject realTarget,
929: ISchemaObject sibling, ISchemaObject object) {
930: if (realTarget instanceof ISchemaCompositor
931: && object instanceof ISchemaElement) {
932: fRearranger.linkReference((ISchemaCompositor) realTarget,
933: (ISchemaElement) object, sibling);
934: }
935: }
936:
937: private void doMove(ISchemaObject realTarget,
938: ISchemaObject sibling, ISchemaObject object) {
939: if (object instanceof ISchemaCompositor) {
940: fRearranger.moveCompositor(realTarget,
941: (ISchemaCompositor) object);
942: } else if (object instanceof SchemaElementReference) {
943: fRearranger.moveReference((SchemaElementReference) object,
944: (ISchemaCompositor) realTarget, sibling);
945: } else if (object instanceof ISchemaElement) {
946: fRearranger.moveElement(realTarget,
947: (ISchemaElement) object, sibling);
948: } else if (object instanceof ISchemaAttribute) {
949: fRearranger
950: .moveAttribute(
951: (ISchemaElement) realTarget,
952: (ISchemaAttribute) object,
953: sibling != null ? (ISchemaAttribute) sibling
954: : null);
955: }
956: }
957:
958: private void doPaste(ISchemaObject realTarget,
959: ISchemaObject sibling, ISchemaObject object) {
960: if (object instanceof ISchemaCompositor) {
961: fRearranger.pasteCompositor(realTarget,
962: (ISchemaCompositor) object, sibling);
963: } else if (object instanceof SchemaElementReference) {
964: fRearranger.pasteReference(realTarget,
965: (SchemaElementReference) object, sibling);
966: } else if (object instanceof ISchemaElement) {
967: fRearranger.pasteElement((ISchemaElement) object, sibling);
968: } else if (object instanceof ISchemaAttribute) {
969: fRearranger.pasteAttribute((ISchemaElement) realTarget,
970: (ISchemaAttribute) object, sibling);
971: }
972: }
973: }
|