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.ui.texteditor.rulers;
011:
012: import java.net.URL;
013:
014: import org.eclipse.core.runtime.Assert;
015: import org.eclipse.core.runtime.CoreException;
016: import org.eclipse.core.runtime.IConfigurationElement;
017: import org.eclipse.core.runtime.ILog;
018: import org.eclipse.core.runtime.InvalidRegistryObjectException;
019: import org.eclipse.core.runtime.content.IContentType;
020:
021: import org.eclipse.jface.resource.ImageDescriptor;
022: import org.eclipse.ui.IEditorInput;
023: import org.eclipse.ui.IWorkbenchPartSite;
024: import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
025: import org.eclipse.ui.internal.texteditor.rulers.ExtensionPointHelper;
026: import org.eclipse.ui.internal.texteditor.rulers.RulerColumnMessages;
027: import org.eclipse.ui.internal.texteditor.rulers.RulerColumnPlacement;
028: import org.eclipse.ui.internal.texteditor.rulers.RulerColumnTarget;
029: import org.eclipse.ui.texteditor.IDocumentProvider;
030: import org.eclipse.ui.texteditor.IDocumentProviderExtension4;
031: import org.eclipse.ui.texteditor.ITextEditor;
032:
033: /**
034: * The description of an extension to the
035: * <code>org.eclipse.ui.workbench.texteditor.rulerColumns</code> extension point. Instances are
036: * immutable. Instances can be obtained from a {@link RulerColumnRegistry}.
037: *
038: * @since 3.3
039: */
040: public final class RulerColumnDescriptor {
041: /** The extension schema name of the class attribute. */
042: private static final String CLASS = "class"; //$NON-NLS-1$
043: /** The extension schema name of the id attribute. */
044: private static final String ID = "id"; //$NON-NLS-1$
045: /** The extension schema name of the optional name attribute. */
046: private static final String NAME = "name"; //$NON-NLS-1$
047: /** The extension schema name of the optional enabled attribute. */
048: private static final String ENABLED = "enabled"; //$NON-NLS-1$
049: /** The extension schema name of the optional icon attribute. */
050: private static final String ICON = "icon"; //$NON-NLS-1$
051: /** The extension schema name of the optional global attribute. */
052: private static final String GLOBAL = "global"; //$NON-NLS-1$
053: /** The extension schema name of the optional menu inclusion attribute. */
054: private static final String INCLUDE_IN_MENU = "includeInMenu"; //$NON-NLS-1$
055: /** The extension schema name of the targetEditor element. */
056: private static final String TARGET_EDITOR = "targetEditor"; //$NON-NLS-1$
057: /** The extension schema name of the targetContentType element. */
058: private static final String TARGET_CONTENT_TYPE = "targetContentType"; //$NON-NLS-1$
059: /** The extension schema name of the targetClass element. */
060: private static final String TARGET_CLASS = "targetClass"; //$NON-NLS-1$
061: /** The extension schema name of the placement element. */
062: private static final String PLACEMENT = "placement"; //$NON-NLS-1$
063:
064: /** The identifier of the extension. */
065: private final String fId;
066: /** The name of the extension, equal to the id if no name is given. */
067: private final String fName;
068: /** The icon descriptor. */
069: private final ImageDescriptor fIcon;
070: /** The configuration element of this extension. */
071: private final IConfigurationElement fElement;
072: /** The target specification of the ruler column contribution. */
073: private final RulerColumnTarget fTarget;
074: /** The placement specification of the ruler column contribution. */
075: private final RulerColumnPlacement fRulerColumnPlacement;
076: /** The default enablement setting of the ruler column contribution. */
077: private final boolean fDefaultEnablement;
078: /** The global setting of the ruler column contribution. */
079: private final boolean fIsGlobal;
080: /** The menu inclusion setting of the ruler column contribution. */
081: private final boolean fIncludeInMenu;
082:
083: /**
084: * Creates a new descriptor.
085: *
086: * @param element the configuration element to read
087: * @param registry the computer registry creating this descriptor
088: * @throws InvalidRegistryObjectException if the configuration element does not conform to the
089: * extension point spec
090: */
091: RulerColumnDescriptor(IConfigurationElement element,
092: RulerColumnRegistry registry)
093: throws InvalidRegistryObjectException {
094: Assert.isLegal(registry != null);
095: Assert.isLegal(element != null);
096: fElement = element;
097:
098: ILog log = TextEditorPlugin.getDefault().getLog();
099: ExtensionPointHelper helper = new ExtensionPointHelper(element,
100: log);
101:
102: fId = helper.getNonNullAttribute(ID);
103: fName = helper.getDefaultAttribute(NAME, fId);
104: helper.getNonNullAttribute(CLASS); // just check validity
105: URL iconURL = helper.getDefaultResourceURL(ICON, null);
106: fIcon = iconURL == null ? null : ImageDescriptor
107: .createFromURL(iconURL);
108: fDefaultEnablement = helper.getDefaultAttribute(ENABLED, true);
109: fIsGlobal = helper.getDefaultAttribute(GLOBAL, true);
110: fIncludeInMenu = helper.getDefaultAttribute(INCLUDE_IN_MENU,
111: true);
112:
113: IConfigurationElement[] targetEditors = element
114: .getChildren(TARGET_EDITOR);
115: IConfigurationElement[] targetContentTypes = element
116: .getChildren(TARGET_CONTENT_TYPE);
117: IConfigurationElement[] targetClasses = element
118: .getChildren(TARGET_CLASS);
119:
120: if (targetContentTypes.length + targetEditors.length
121: + targetClasses.length == 0) {
122: helper
123: .fail(RulerColumnMessages.RulerColumnDescriptor_missing_target_msg);
124: fTarget = null; // dummy
125: } else {
126: RulerColumnTarget combined = null;
127: for (int i = 0; i < targetEditors.length; i++) {
128: IConfigurationElement targetEditor = targetEditors[i];
129: RulerColumnTarget target = RulerColumnTarget
130: .createEditorIdTarget(new ExtensionPointHelper(
131: targetEditor, log)
132: .getNonNullAttribute(ID));
133: combined = RulerColumnTarget.createOrTarget(combined,
134: target);
135: }
136: for (int i = 0; i < targetContentTypes.length; i++) {
137: IConfigurationElement targetContentType = targetContentTypes[i];
138: RulerColumnTarget target = RulerColumnTarget
139: .createContentTypeTarget(new ExtensionPointHelper(
140: targetContentType, log)
141: .getNonNullAttribute(ID));
142: combined = RulerColumnTarget.createOrTarget(combined,
143: target);
144: }
145: for (int i = 0; i < targetClasses.length; i++) {
146: IConfigurationElement targetClass = targetClasses[i];
147: RulerColumnTarget target = RulerColumnTarget
148: .createClassTarget(new ExtensionPointHelper(
149: targetClass, log)
150: .getNonNullAttribute(CLASS));
151: combined = RulerColumnTarget.createOrTarget(combined,
152: target);
153: }
154: fTarget = combined;
155: }
156:
157: IConfigurationElement[] placements = element
158: .getChildren(PLACEMENT);
159: switch (placements.length) {
160: case 0:
161: fRulerColumnPlacement = new RulerColumnPlacement();
162: break;
163: case 1:
164: fRulerColumnPlacement = new RulerColumnPlacement(
165: placements[0]);
166: break;
167: default:
168: helper
169: .fail(RulerColumnMessages.RulerColumnDescriptor_invalid_placement_msg);
170: fRulerColumnPlacement = null; // dummy
171: break;
172: }
173:
174: Assert.isTrue(fTarget != null);
175: Assert.isTrue(fRulerColumnPlacement != null);
176: }
177:
178: /**
179: * Returns the identifier of the described extension.
180: *
181: * @return the identifier of the described extension
182: */
183: public String getId() {
184: return fId;
185: }
186:
187: /**
188: * Returns the name of the described extension.
189: *
190: * @return the name of the described extension
191: */
192: public String getName() {
193: return fName;
194: }
195:
196: /**
197: * Returns the image descriptor of the described extension, <code>null</code> if it does not
198: * have an image.
199: *
200: * @return the image descriptor of the described extension or <code>null</code> for no image
201: */
202: public ImageDescriptor getIcon() {
203: return fIcon;
204: }
205:
206: RulerColumnTarget getTarget() {
207: return fTarget;
208: }
209:
210: RulerColumnPlacement getPlacement() {
211: return fRulerColumnPlacement;
212: }
213:
214: /**
215: * Returns the default enablement of the described extension. Editors that support this
216: * contribution should typically enable the column by default.
217: *
218: * @return the default enablement of the described extension
219: */
220: public boolean getDefaultEnablement() {
221: return fDefaultEnablement;
222: }
223:
224: /**
225: * Returns the global property of the described extension. Changing the visibility of a column
226: * with the global property set to <code>true</code> should typically affect all matching
227: * editors. Changing the visibility of a column with the global property set to
228: * <code>false</code> should only affect the current editor.
229: *
230: * @return the global property of the described extension
231: */
232: public boolean isGlobal() {
233: return fIsGlobal;
234: }
235:
236: /**
237: * Returns the menu inclusion property of the described extension. A toggle menu entry should be
238: * inluded in the ruler context menu for columns with this property set to <code>true</code>.
239: *
240: * @return the menu inclusion property of the described extension
241: */
242: public boolean isIncludedInMenu() {
243: return fIncludeInMenu;
244: }
245:
246: /**
247: * Returns <code>true</code> if this contribution matches the passed editor, <code>false</code> if not.
248: *
249: * @param editor the editor to check
250: * @return <code>true</code> if this contribution targets the passed editor
251: */
252: public boolean matchesEditor(ITextEditor editor) {
253: Assert.isLegal(editor != null);
254: RulerColumnTarget target = getTarget();
255:
256: IWorkbenchPartSite site = editor.getSite();
257: if (site != null && target.matchesEditorId(site.getId()))
258: return true;
259:
260: if (target.matchesClass(editor.getClass()))
261: return true;
262:
263: IContentType contentType = getContentType(editor);
264: return contentType != null
265: && target.matchesContentType(contentType);
266:
267: }
268:
269: /**
270: * Creates a {@link IContributedRulerColumn} instance as described by the receiver. This may load the contributing plug-in.
271: *
272: * @param editor the editor that loads the contributed column
273: * @return the instantiated column
274: * @throws CoreException as thrown by {@link IConfigurationElement#createExecutableExtension(String)}
275: * @throws InvalidRegistryObjectException as thrown by {@link IConfigurationElement#createExecutableExtension(String)}
276: */
277: public IContributedRulerColumn createColumn(ITextEditor editor)
278: throws CoreException, InvalidRegistryObjectException {
279: Assert.isLegal(editor != null);
280: IContributedRulerColumn column = (IContributedRulerColumn) fElement
281: .createExecutableExtension(CLASS);
282: column.setDescriptor(this );
283: column.setEditor(editor);
284: column.columnCreated();
285: return column;
286: }
287:
288: /*
289: * @see java.lang.Object#toString()
290: * @since 3.3
291: */
292: public String toString() {
293: return "RulerColumnDescriptor[name=" + getName() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
294: }
295:
296: IConfigurationElement getConfigurationElement() {
297: return fElement;
298: }
299:
300: /*
301: * @see java.lang.Object#hashCode()
302: */
303: public int hashCode() {
304: final int prime = 31;
305: int result = 1;
306: result = prime * result + ((fId == null) ? 0 : fId.hashCode());
307: return result;
308: }
309:
310: /*
311: * @see java.lang.Object#equals(java.lang.Object)
312: */
313: public boolean equals(Object obj) {
314: if (this == obj)
315: return true;
316: if (obj == null)
317: return false;
318: if (getClass() != obj.getClass())
319: return false;
320: final RulerColumnDescriptor other = (RulerColumnDescriptor) obj;
321: if (fId == null) {
322: if (other.fId != null)
323: return false;
324: } else if (!fId.equals(other.fId))
325: return false;
326: return true;
327: }
328:
329: /**
330: * Returns the content type of the editor's input, <code>null</code> if the editor input or
331: * the document provider is <code>null</code> or the content type cannot be determined.
332: *
333: * @param editor the editor to get the content type from
334: * @return the content type of the editor's input, <code>null</code> if it cannot be
335: * determined
336: */
337: private IContentType getContentType(ITextEditor editor) {
338: IEditorInput input = editor.getEditorInput();
339: if (input == null)
340: return null;
341: IDocumentProvider provider = editor.getDocumentProvider();
342: if (provider instanceof IDocumentProviderExtension4) {
343: IDocumentProviderExtension4 ext = (IDocumentProviderExtension4) provider;
344: try {
345: return ext.getContentType(input);
346: } catch (CoreException x) {
347: // ignore and return null;
348: }
349: }
350: return null;
351: }
352:
353: String getContributor() {
354: try {
355: return fElement.getContributor().getName();
356: } catch (InvalidRegistryObjectException e) {
357: return "unknown"; //$NON-NLS-1$
358: }
359: }
360: }
|