001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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.internal.ide.dialogs;
011:
012: import java.net.URI;
013:
014: import org.eclipse.core.filesystem.EFS;
015: import org.eclipse.core.filesystem.IFileSystem;
016: import org.eclipse.core.resources.IContainer;
017: import org.eclipse.core.resources.IFile;
018: import org.eclipse.core.resources.IProject;
019: import org.eclipse.core.resources.IResource;
020: import org.eclipse.core.resources.ResourceAttributes;
021: import org.eclipse.core.runtime.CoreException;
022: import org.eclipse.core.runtime.IPath;
023: import org.eclipse.core.runtime.content.IContentDescription;
024: import org.eclipse.jface.dialogs.ErrorDialog;
025: import org.eclipse.jface.preference.FieldEditor;
026: import org.eclipse.jface.util.IPropertyChangeListener;
027: import org.eclipse.jface.util.PropertyChangeEvent;
028: import org.eclipse.osgi.util.TextProcessor;
029: import org.eclipse.swt.SWT;
030: import org.eclipse.swt.graphics.Font;
031: import org.eclipse.swt.layout.GridData;
032: import org.eclipse.swt.layout.GridLayout;
033: import org.eclipse.swt.widgets.Button;
034: import org.eclipse.swt.widgets.Composite;
035: import org.eclipse.swt.widgets.Control;
036: import org.eclipse.swt.widgets.Label;
037: import org.eclipse.swt.widgets.Text;
038: import org.eclipse.ui.PlatformUI;
039: import org.eclipse.ui.dialogs.PropertyPage;
040: import org.eclipse.ui.ide.dialogs.ResourceEncodingFieldEditor;
041: import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
042: import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
043: import org.eclipse.ui.internal.ide.LineDelimiterEditor;
044:
045: /**
046: * The ResourceInfoPage is the page that shows the basic info about the
047: * resource.
048: */
049: public class ResourceInfoPage extends PropertyPage {
050:
051: private Button editableBox;
052:
053: private Button executableBox;
054:
055: private Button archiveBox;
056:
057: private Button derivedBox;
058:
059: private boolean previousReadOnlyValue;
060:
061: private boolean previousExecutableValue;
062:
063: private boolean previousArchiveValue;
064:
065: private boolean previousDerivedValue;
066:
067: private IContentDescription cachedContentDescription;
068:
069: private ResourceEncodingFieldEditor encodingEditor;
070:
071: private LineDelimiterEditor lineDelimiterEditor;
072:
073: private static String READ_ONLY = IDEWorkbenchMessages.ResourceInfo_readOnly;
074:
075: private static String EXECUTABLE = IDEWorkbenchMessages.ResourceInfo_executable;
076:
077: private static String ARCHIVE = IDEWorkbenchMessages.ResourceInfo_archive;
078:
079: private static String DERIVED = IDEWorkbenchMessages.ResourceInfo_derived;
080:
081: private static String TYPE_TITLE = IDEWorkbenchMessages.ResourceInfo_type;
082:
083: private static String LOCATION_TITLE = IDEWorkbenchMessages.ResourceInfo_location;
084:
085: private static String RESOLVED_LOCATION_TITLE = IDEWorkbenchMessages.ResourceInfo_resolvedLocation;
086:
087: private static String SIZE_TITLE = IDEWorkbenchMessages.ResourceInfo_size;
088:
089: private static String PATH_TITLE = IDEWorkbenchMessages.ResourceInfo_path;
090:
091: private static String TIMESTAMP_TITLE = IDEWorkbenchMessages.ResourceInfo_lastModified;
092:
093: private static String FILE_ENCODING_TITLE = IDEWorkbenchMessages.WorkbenchPreference_encoding;
094:
095: private static String CONTAINER_ENCODING_TITLE = IDEWorkbenchMessages.ResourceInfo_fileEncodingTitle;
096:
097: // Max value width in characters before wrapping
098: private static final int MAX_VALUE_WIDTH = 80;
099:
100: /**
101: * Create the group that shows the name, location, size and type.
102: *
103: * @param parent
104: * the composite the group will be created in
105: * @param resource
106: * the resource the information is being taken from.
107: * @return the composite for the group
108: */
109: private Composite createBasicInfoGroup(Composite parent,
110: IResource resource) {
111:
112: Font font = parent.getFont();
113:
114: Composite basicInfoComposite = new Composite(parent, SWT.NULL);
115: GridLayout layout = new GridLayout();
116: layout.numColumns = 2;
117: layout.marginWidth = 0;
118: layout.marginHeight = 0;
119: basicInfoComposite.setLayout(layout);
120: GridData data = new GridData();
121: data.verticalAlignment = GridData.FILL;
122: data.horizontalAlignment = GridData.FILL;
123: basicInfoComposite.setLayoutData(data);
124: basicInfoComposite.setFont(font);
125:
126: // The group for path
127: Label pathLabel = new Label(basicInfoComposite, SWT.NONE);
128: pathLabel.setText(PATH_TITLE);
129: GridData gd = new GridData();
130: gd.verticalAlignment = SWT.TOP;
131: pathLabel.setLayoutData(gd);
132: pathLabel.setFont(font);
133:
134: // path value label
135: Text pathValueText = new Text(basicInfoComposite, SWT.WRAP
136: | SWT.READ_ONLY);
137: String pathString = TextProcessor.process(resource
138: .getFullPath().toString());
139: pathValueText.setText(pathString);
140: gd = new GridData();
141: gd.widthHint = convertWidthInCharsToPixels(MAX_VALUE_WIDTH);
142: gd.grabExcessHorizontalSpace = true;
143: gd.horizontalAlignment = GridData.FILL;
144: pathValueText.setLayoutData(gd);
145: pathValueText.setFont(font);
146: pathValueText.setBackground(pathValueText.getDisplay()
147: .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
148:
149: // The group for types
150: Label typeTitle = new Label(basicInfoComposite, SWT.LEFT);
151: typeTitle.setText(TYPE_TITLE);
152: typeTitle.setFont(font);
153:
154: Text typeValue = new Text(basicInfoComposite, SWT.LEFT
155: | SWT.READ_ONLY);
156: typeValue.setText(IDEResourceInfoUtils.getTypeString(resource,
157: getContentDescription(resource)));
158: typeValue.setBackground(typeValue.getDisplay().getSystemColor(
159: SWT.COLOR_WIDGET_BACKGROUND));
160: typeValue.setFont(font);
161:
162: // The group for location
163: Label locationTitle = new Label(basicInfoComposite, SWT.LEFT);
164: locationTitle.setText(LOCATION_TITLE);
165: gd = new GridData();
166: gd.verticalAlignment = SWT.TOP;
167: locationTitle.setLayoutData(gd);
168: locationTitle.setFont(font);
169:
170: Text locationValue = new Text(basicInfoComposite, SWT.WRAP
171: | SWT.READ_ONLY);
172: String locationStr = TextProcessor.process(IDEResourceInfoUtils
173: .getLocationText(resource));
174: locationValue.setText(locationStr);
175: gd = new GridData();
176: gd.widthHint = convertWidthInCharsToPixels(MAX_VALUE_WIDTH);
177: gd.grabExcessHorizontalSpace = true;
178: gd.horizontalAlignment = GridData.FILL;
179: locationValue.setLayoutData(gd);
180: locationValue.setFont(font);
181: locationValue.setBackground(locationValue.getDisplay()
182: .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
183:
184: if (isPathVariable(resource)) {
185: Label resolvedLocationTitle = new Label(basicInfoComposite,
186: SWT.LEFT);
187: resolvedLocationTitle.setText(RESOLVED_LOCATION_TITLE);
188: gd = new GridData();
189: gd.verticalAlignment = SWT.TOP;
190: resolvedLocationTitle.setLayoutData(gd);
191: resolvedLocationTitle.setFont(font);
192:
193: Text resolvedLocationValue = new Text(basicInfoComposite,
194: SWT.WRAP | SWT.READ_ONLY);
195: resolvedLocationValue.setText(IDEResourceInfoUtils
196: .getResolvedLocationText(resource));
197: gd = new GridData();
198: gd.widthHint = convertWidthInCharsToPixels(MAX_VALUE_WIDTH);
199: gd.grabExcessHorizontalSpace = true;
200: gd.horizontalAlignment = GridData.FILL;
201: resolvedLocationValue.setLayoutData(gd);
202: resolvedLocationValue.setFont(font);
203: resolvedLocationValue.setBackground(resolvedLocationValue
204: .getDisplay().getSystemColor(
205: SWT.COLOR_WIDGET_BACKGROUND));
206: }
207: if (resource.getType() == IResource.FILE) {
208: // The group for size
209: Label sizeTitle = new Label(basicInfoComposite, SWT.LEFT);
210: sizeTitle.setText(SIZE_TITLE);
211: sizeTitle.setFont(font);
212:
213: Text sizeValue = new Text(basicInfoComposite, SWT.LEFT
214: | SWT.READ_ONLY);
215: sizeValue.setText(IDEResourceInfoUtils
216: .getSizeString(resource));
217: gd = new GridData();
218: gd.widthHint = convertWidthInCharsToPixels(MAX_VALUE_WIDTH);
219: gd.grabExcessHorizontalSpace = true;
220: gd.horizontalAlignment = GridData.FILL;
221: sizeValue.setLayoutData(gd);
222: sizeValue.setFont(font);
223: sizeValue.setBackground(sizeValue.getDisplay()
224: .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
225: }
226:
227: return basicInfoComposite;
228: }
229:
230: protected Control createContents(Composite parent) {
231:
232: PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
233: IIDEHelpContextIds.RESOURCE_INFO_PROPERTY_PAGE);
234:
235: // layout the page
236: IResource resource = (IResource) getElement().getAdapter(
237: IResource.class);
238:
239: if (resource == null) {
240: Label label = new Label(parent, SWT.NONE);
241: label
242: .setText(IDEWorkbenchMessages.ResourceInfoPage_noResource);
243: return label;
244: }
245:
246: if (resource.getType() != IResource.PROJECT) {
247: ResourceAttributes attrs = resource.getResourceAttributes();
248: if (attrs != null) {
249: previousReadOnlyValue = attrs.isReadOnly();
250: previousExecutableValue = attrs.isExecutable();
251: previousArchiveValue = attrs.isArchive();
252: } else {
253: previousReadOnlyValue = previousExecutableValue = previousArchiveValue = false;
254: }
255: previousDerivedValue = resource.isDerived();
256: }
257:
258: // top level group
259: Composite composite = new Composite(parent, SWT.NONE);
260: GridLayout layout = new GridLayout();
261: layout.marginWidth = 0;
262: layout.marginHeight = 0;
263: composite.setLayout(layout);
264: GridData data = new GridData(GridData.FILL);
265: data.grabExcessHorizontalSpace = true;
266: composite.setLayoutData(data);
267: composite.setFont(parent.getFont());
268:
269: createBasicInfoGroup(composite, resource);
270: createSeparator(composite);
271: createStateGroup(composite, resource);
272: new Label(composite, SWT.NONE); // a vertical spacer
273: encodingEditor = new ResourceEncodingFieldEditor(
274: getFieldEditorLabel(resource), composite, resource);
275: encodingEditor.setPage(this );
276: encodingEditor.load();
277:
278: encodingEditor
279: .setPropertyChangeListener(new IPropertyChangeListener() {
280: /*
281: * (non-Javadoc)
282: *
283: * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
284: */
285: public void propertyChange(PropertyChangeEvent event) {
286: if (event.getProperty().equals(
287: FieldEditor.IS_VALID)) {
288: setValid(encodingEditor.isValid());
289: }
290:
291: }
292: });
293:
294: if (resource.getType() == IResource.PROJECT) {
295: lineDelimiterEditor = new LineDelimiterEditor(composite,
296: resource.getProject());
297: lineDelimiterEditor.doLoad();
298: }
299:
300: //We can't save the preferences for close
301: if (resource.getType() == IResource.PROJECT
302: && !((IProject) resource).isOpen()) {
303: encodingEditor.setEnabled(false, composite);
304: lineDelimiterEditor.setEnabled(false);
305: }
306:
307: return composite;
308: }
309:
310: /**
311: * Return the label for the encoding field editor for the resource.
312: *
313: * @param resource -
314: * the resource to edit.
315: * @return String
316: */
317: private String getFieldEditorLabel(IResource resource) {
318: if (resource instanceof IContainer) {
319: return CONTAINER_ENCODING_TITLE;
320: }
321: return FILE_ENCODING_TITLE;
322: }
323:
324: /**
325: * Create the isEditable button and it's associated label as a child of
326: * parent using the editableValue of the receiver. The Composite will be the
327: * parent of the button.
328: *
329: * @param composite
330: * the parent of the button
331: */
332: private void createEditableButton(Composite composite) {
333:
334: this .editableBox = new Button(composite, SWT.CHECK | SWT.RIGHT);
335: this .editableBox.setAlignment(SWT.LEFT);
336: this .editableBox.setText(READ_ONLY);
337: this .editableBox.setSelection(this .previousReadOnlyValue);
338: this .editableBox.setFont(composite.getFont());
339: GridData data = new GridData();
340: data.horizontalSpan = 2;
341: this .editableBox.setLayoutData(data);
342: }
343:
344: /**
345: * Create the isExecutable button and it's associated label as a child of
346: * parent using the editableValue of the receiver. The Composite will be the
347: * parent of the button.
348: *
349: * @param composite
350: * the parent of the button
351: */
352: private void createExecutableButton(Composite composite) {
353:
354: this .executableBox = new Button(composite, SWT.CHECK
355: | SWT.RIGHT);
356: this .executableBox.setAlignment(SWT.LEFT);
357: this .executableBox.setText(EXECUTABLE);
358: this .executableBox.setSelection(this .previousExecutableValue);
359: this .executableBox.setFont(composite.getFont());
360: GridData data = new GridData();
361: data.horizontalSpan = 2;
362: this .executableBox.setLayoutData(data);
363: }
364:
365: /**
366: * Create the isArchive button and it's associated label as a child of
367: * parent using the editableValue of the receiver. The Composite will be the
368: * parent of the button.
369: *
370: * @param composite
371: * the parent of the button
372: */
373: private void createArchiveButton(Composite composite) {
374:
375: this .archiveBox = new Button(composite, SWT.CHECK | SWT.RIGHT);
376: this .archiveBox.setAlignment(SWT.LEFT);
377: this .archiveBox.setText(ARCHIVE);
378: this .archiveBox.setSelection(this .previousArchiveValue);
379: this .archiveBox.setFont(composite.getFont());
380: GridData data = new GridData();
381: data.horizontalSpan = 2;
382: this .archiveBox.setLayoutData(data);
383: }
384:
385: /**
386: * Create the derived button and it's associated label as a child of parent
387: * using the derived of the receiver. The Composite will be the parent of
388: * the button.
389: *
390: * @param composite
391: * the parent of the button
392: */
393: private void createDerivedButton(Composite composite) {
394:
395: this .derivedBox = new Button(composite, SWT.CHECK | SWT.RIGHT);
396: this .derivedBox.setAlignment(SWT.LEFT);
397: this .derivedBox.setText(DERIVED);
398: this .derivedBox.setSelection(this .previousDerivedValue);
399: this .derivedBox.setFont(composite.getFont());
400: GridData data = new GridData();
401: data.horizontalSpan = 2;
402: this .derivedBox.setLayoutData(data);
403: }
404:
405: /**
406: * Create a separator that goes across the entire page
407: *
408: * @param composite
409: * The parent of the seperator
410: */
411: private void createSeparator(Composite composite) {
412:
413: Label separator = new Label(composite, SWT.SEPARATOR
414: | SWT.HORIZONTAL);
415: GridData gridData = new GridData();
416: gridData.horizontalAlignment = GridData.FILL;
417: gridData.grabExcessHorizontalSpace = true;
418: separator.setLayoutData(gridData);
419: }
420:
421: /**
422: * Create the group that shows the read only state and the timestamp.
423: *
424: * @param parent
425: * the composite the group will be created in
426: * @param resource
427: * the resource the information is being taken from.
428: */
429: private void createStateGroup(Composite parent, IResource resource) {
430:
431: Font font = parent.getFont();
432:
433: Composite composite = new Composite(parent, SWT.NULL);
434: GridLayout layout = new GridLayout();
435: layout.numColumns = 2;
436: layout.marginWidth = 0;
437: layout.marginHeight = 0;
438: composite.setLayout(layout);
439: GridData data = new GridData();
440: data.horizontalAlignment = GridData.FILL;
441: composite.setLayoutData(data);
442: composite.setFont(font);
443:
444: Label timeStampLabel = new Label(composite, SWT.NONE);
445: timeStampLabel.setText(TIMESTAMP_TITLE);
446: timeStampLabel.setFont(font);
447:
448: // timeStamp value label
449: Text timeStampValue = new Text(composite, SWT.READ_ONLY);
450: timeStampValue.setText(IDEResourceInfoUtils
451: .getDateStringValue(resource));
452: timeStampValue.setFont(font);
453: timeStampValue.setBackground(timeStampValue.getDisplay()
454: .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
455: timeStampValue.setLayoutData(new GridData(
456: GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
457:
458: // Not relevant to projects
459: if (resource.getType() != IResource.PROJECT) {
460: URI location = resource.getLocationURI();
461: if (location != null && location.getScheme() != null) {
462: try {
463: IFileSystem fs = EFS.getFileSystem(location
464: .getScheme());
465: int attributes = fs.attributes();
466: if ((attributes & EFS.ATTRIBUTE_READ_ONLY) != 0) {
467: createEditableButton(composite);
468: }
469: if ((attributes & EFS.ATTRIBUTE_EXECUTABLE) != 0) {
470: createExecutableButton(composite);
471: }
472: if ((attributes & EFS.ATTRIBUTE_ARCHIVE) != 0) {
473: createArchiveButton(composite);
474: }
475: } catch (CoreException e) {
476: // ignore if we can't access the file system for this
477: // resource
478: }
479: }
480: createDerivedButton(composite);
481: // create warning for executable flag
482: if (executableBox != null
483: && resource.getType() == IResource.FOLDER) {
484: Composite noteComposite = createNoteComposite(font,
485: composite,
486: IDEWorkbenchMessages.Preference_note,
487: IDEWorkbenchMessages.ResourceInfo_exWarning);
488: GridData noteData = new GridData();
489: noteData.horizontalSpan = 2;
490: noteComposite.setLayoutData(noteData);
491: }
492: }
493: }
494:
495: private IContentDescription getContentDescription(IResource resource) {
496: if (resource.getType() != IResource.FILE) {
497: return null;
498: }
499:
500: if (cachedContentDescription == null) {
501: try {
502: cachedContentDescription = ((IFile) resource)
503: .getContentDescription();
504: } catch (CoreException e) {
505: // silently ignore
506: }
507: }
508: return cachedContentDescription;
509: }
510:
511: /**
512: * Returns whether the given resource is a linked resource bound to a path
513: * variable.
514: *
515: * @param resource
516: * resource to test
517: * @return boolean <code>true</code> the given resource is a linked
518: * resource bound to a path variable. <code>false</code> the given
519: * resource is either not a linked resource or it is not using a
520: * path variable.
521: */
522: private boolean isPathVariable(IResource resource) {
523: if (!resource.isLinked()) {
524: return false;
525: }
526:
527: IPath resolvedLocation = resource.getLocation();
528: if (resolvedLocation == null) {
529: // missing path variable
530: return true;
531: }
532: IPath rawLocation = resource.getRawLocation();
533: if (resolvedLocation.equals(rawLocation)) {
534: return false;
535: }
536:
537: return true;
538: }
539:
540: /**
541: * Reset the editableBox to the false.
542: */
543: protected void performDefaults() {
544:
545: IResource resource = (IResource) getElement().getAdapter(
546: IResource.class);
547:
548: if (resource == null)
549: return;
550:
551: // Nothing to update if we never made the box
552: if (this .editableBox != null) {
553: this .editableBox.setSelection(false);
554: }
555:
556: // Nothing to update if we never made the box
557: if (this .executableBox != null) {
558: this .executableBox.setSelection(false);
559: }
560:
561: // Nothing to update if we never made the box
562: if (this .derivedBox != null) {
563: this .derivedBox.setSelection(false);
564: }
565:
566: encodingEditor.loadDefault();
567:
568: if (lineDelimiterEditor != null) {
569: lineDelimiterEditor.loadDefault();
570: }
571:
572: }
573:
574: /**
575: * Apply the read only state and the encoding to the resource.
576: */
577: public boolean performOk() {
578:
579: IResource resource = (IResource) getElement().getAdapter(
580: IResource.class);
581:
582: if (resource == null)
583: return true;
584:
585: encodingEditor.store();
586:
587: if (lineDelimiterEditor != null) {
588: lineDelimiterEditor.store();
589: }
590:
591: try {
592: ResourceAttributes attrs = resource.getResourceAttributes();
593: if (attrs != null) {
594: boolean hasChange = false;
595: // Nothing to update if we never made the box
596: if (editableBox != null
597: && editableBox.getSelection() != previousReadOnlyValue) {
598: attrs.setReadOnly(editableBox.getSelection());
599: hasChange = true;
600: }
601: if (executableBox != null
602: && executableBox.getSelection() != previousExecutableValue) {
603: attrs.setExecutable(executableBox.getSelection());
604: hasChange = true;
605: }
606: if (archiveBox != null
607: && archiveBox.getSelection() != previousArchiveValue) {
608: attrs.setArchive(archiveBox.getSelection());
609: hasChange = true;
610: }
611: if (hasChange) {
612: resource.setResourceAttributes(attrs);
613: attrs = resource.getResourceAttributes();
614: if (attrs != null) {
615: previousReadOnlyValue = attrs.isReadOnly();
616: previousExecutableValue = attrs.isExecutable();
617: previousArchiveValue = attrs.isArchive();
618: if (editableBox != null) {
619: editableBox
620: .setSelection(attrs.isReadOnly());
621: }
622: if (executableBox != null) {
623: executableBox.setSelection(attrs
624: .isExecutable());
625: }
626: if (archiveBox != null) {
627: archiveBox.setSelection(attrs.isArchive());
628: }
629: }
630: }
631: }
632:
633: // Nothing to update if we never made the box
634: if (this .derivedBox != null) {
635: boolean localDerivedValue = derivedBox.getSelection();
636: if (previousDerivedValue != localDerivedValue) {
637: resource.setDerived(localDerivedValue);
638: boolean isDerived = resource.isDerived();
639: previousDerivedValue = isDerived;
640: derivedBox.setSelection(isDerived);
641: }
642: }
643: } catch (CoreException exception) {
644: ErrorDialog.openError(getShell(),
645: IDEWorkbenchMessages.InternalError, exception
646: .getLocalizedMessage(), exception
647: .getStatus());
648: return false;
649: }
650: return true;
651: }
652: }
|