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;
011:
012: import org.eclipse.core.runtime.IPath;
013: import org.eclipse.core.runtime.Path;
014: import org.eclipse.core.runtime.SafeRunner;
015: import org.eclipse.jface.action.ContributionItem;
016: import org.eclipse.jface.action.IMenuListener;
017: import org.eclipse.jface.action.IMenuManager;
018: import org.eclipse.jface.action.MenuManager;
019: import org.eclipse.jface.dialogs.MessageDialog;
020: import org.eclipse.jface.util.SafeRunnable;
021: import org.eclipse.osgi.util.NLS;
022: import org.eclipse.osgi.util.TextProcessor;
023: import org.eclipse.swt.SWT;
024: import org.eclipse.swt.events.SelectionAdapter;
025: import org.eclipse.swt.events.SelectionEvent;
026: import org.eclipse.swt.widgets.Menu;
027: import org.eclipse.swt.widgets.MenuItem;
028: import org.eclipse.ui.IEditorDescriptor;
029: import org.eclipse.ui.IEditorInput;
030: import org.eclipse.ui.IWorkbenchPage;
031: import org.eclipse.ui.IWorkbenchWindow;
032: import org.eclipse.ui.PartInitException;
033:
034: /**
035: * A dynamic menu item which supports to switch to other Windows.
036: */
037: public class ReopenEditorMenu extends ContributionItem {
038: private IWorkbenchWindow window;
039:
040: private EditorHistory history;
041:
042: private boolean showSeparator;
043:
044: private boolean dirty = true;
045:
046: private IMenuListener menuListener = new IMenuListener() {
047: public void menuAboutToShow(IMenuManager manager) {
048: manager.markDirty();
049: dirty = true;
050: }
051: };
052:
053: // the maximum length for a file name; must be >= 4
054: private static final int MAX_TEXT_LENGTH = 40;
055:
056: // only assign mnemonic to the first nine items
057: private static final int MAX_MNEMONIC_SIZE = 9;
058:
059: /**
060: * Create a new instance.
061: * @param window the window on which the menu is to be created
062: * @param id menu's id
063: * @param showSeparator whether or not to show a separator
064: */
065: public ReopenEditorMenu(IWorkbenchWindow window, String id,
066: boolean showSeparator) {
067: super (id);
068: this .window = window;
069: this .showSeparator = showSeparator;
070: history = ((Workbench) window.getWorkbench())
071: .getEditorHistory();
072: }
073:
074: /**
075: * Returns the text for a history item. This may be truncated to fit
076: * within the MAX_TEXT_LENGTH.
077: */
078: private String calcText(int index, EditorHistoryItem item) {
079: StringBuffer sb = new StringBuffer();
080:
081: int mnemonic = index + 1;
082: sb.append(mnemonic);
083: if (mnemonic <= MAX_MNEMONIC_SIZE) {
084: sb.insert(sb.length() - (mnemonic + "").length(), '&'); //$NON-NLS-1$
085: }
086: sb.append(" "); //$NON-NLS-1$
087:
088: // IMPORTANT: avoid accessing the item's input since
089: // this can require activating plugins.
090: // Instead, ask the item for the info, which can
091: // consult its memento if it is not restored yet.
092: String fileName = item.getName();
093: String pathName = item.getToolTipText();
094: if (pathName.equals(fileName)) {
095: // tool tip text isn't necessarily a path;
096: // sometimes it's the same as name, so it shouldn't be treated as a path then
097: pathName = ""; //$NON-NLS-1$
098: }
099: IPath path = new Path(pathName);
100: // if last segment in path is the fileName, remove it
101: if (path.segmentCount() > 1
102: && path.segment(path.segmentCount() - 1).equals(
103: fileName)) {
104: path = path.removeLastSegments(1);
105: pathName = path.toString();
106: }
107:
108: if ((fileName.length() + pathName.length()) <= (MAX_TEXT_LENGTH - 4)) {
109: // entire item name fits within maximum length
110: sb.append(fileName);
111: if (pathName.length() > 0) {
112: sb.append(" ["); //$NON-NLS-1$
113: sb.append(pathName);
114: sb.append("]"); //$NON-NLS-1$
115: }
116: } else {
117: // need to shorten the item name
118: int length = fileName.length();
119: if (length > MAX_TEXT_LENGTH) {
120: // file name does not fit within length, truncate it
121: sb.append(fileName.substring(0, MAX_TEXT_LENGTH - 3));
122: sb.append("..."); //$NON-NLS-1$
123: } else if (length > MAX_TEXT_LENGTH - 7) {
124: sb.append(fileName);
125: } else {
126: sb.append(fileName);
127: int segmentCount = path.segmentCount();
128: if (segmentCount > 0) {
129: length += 7; // 7 chars are taken for " [...]"
130:
131: sb.append(" ["); //$NON-NLS-1$
132:
133: // Add first n segments that fit
134: int i = 0;
135: while (i < segmentCount && length < MAX_TEXT_LENGTH) {
136: String segment = path.segment(i);
137: if (length + segment.length() < MAX_TEXT_LENGTH) {
138: sb.append(segment);
139: sb.append(IPath.SEPARATOR);
140: length += segment.length() + 1;
141: i++;
142: } else if (i == 0) {
143: // append at least part of the first segment
144: sb.append(segment.substring(0,
145: MAX_TEXT_LENGTH - length));
146: length = MAX_TEXT_LENGTH;
147: break;
148: } else {
149: break;
150: }
151: }
152:
153: sb.append("..."); //$NON-NLS-1$
154:
155: i = segmentCount - 1;
156: // Add last n segments that fit
157: while (i > 0 && length < MAX_TEXT_LENGTH) {
158: String segment = path.segment(i);
159: if (length + segment.length() < MAX_TEXT_LENGTH) {
160: sb.append(IPath.SEPARATOR);
161: sb.append(segment);
162: length += segment.length() + 1;
163: i--;
164: } else {
165: break;
166: }
167: }
168:
169: sb.append("]"); //$NON-NLS-1$
170: }
171: }
172: }
173: return TextProcessor.process(sb.toString(), TextProcessor
174: .getDefaultDelimiters()
175: + "[]");//$NON-NLS-1$
176: }
177:
178: /**
179: * Fills the given menu with
180: * menu items for all windows.
181: */
182: public void fill(final Menu menu, int index) {
183: if (window.getActivePage() == null
184: || window.getActivePage().getPerspective() == null) {
185: return;
186: }
187:
188: if (getParent() instanceof MenuManager) {
189: ((MenuManager) getParent()).addMenuListener(menuListener);
190: }
191:
192: int itemsToShow = WorkbenchPlugin.getDefault()
193: .getPreferenceStore().getInt(
194: IPreferenceConstants.RECENT_FILES);
195: if (itemsToShow == 0) {
196: return;
197: }
198:
199: // Get items.
200: EditorHistoryItem[] historyItems = history.getItems();
201:
202: int n = Math.min(itemsToShow, historyItems.length);
203: if (n <= 0) {
204: return;
205: }
206:
207: if (showSeparator) {
208: new MenuItem(menu, SWT.SEPARATOR, index);
209: ++index;
210: }
211:
212: final int menuIndex[] = new int[] { index };
213:
214: for (int i = 0; i < n; i++) {
215: final EditorHistoryItem item = historyItems[i];
216: final int historyIndex = i;
217: SafeRunner.run(new SafeRunnable() {
218: public void run() throws Exception {
219: String text = calcText(historyIndex, item);
220: MenuItem mi = new MenuItem(menu, SWT.PUSH,
221: menuIndex[0]);
222: ++menuIndex[0];
223: mi.setText(text);
224: mi.addSelectionListener(new SelectionAdapter() {
225: public void widgetSelected(SelectionEvent e) {
226: open(item);
227: }
228: });
229: }
230:
231: public void handleException(Throwable e) {
232: // just skip the item if there's an error,
233: // e.g. in the calculation of the shortened name
234: WorkbenchPlugin.log(getClass(), "fill", e); //$NON-NLS-1$
235: }
236: });
237: }
238: dirty = false;
239: }
240:
241: /**
242: * Overridden to always return true and force dynamic menu building.
243: */
244: public boolean isDirty() {
245: return dirty;
246: }
247:
248: /**
249: * Overridden to always return true and force dynamic menu building.
250: */
251: public boolean isDynamic() {
252: return true;
253: }
254:
255: /**
256: * Reopens the editor for the given history item.
257: */
258: private void open(EditorHistoryItem item) {
259: IWorkbenchPage page = window.getActivePage();
260: if (page != null) {
261: try {
262: String itemName = item.getName();
263: if (!item.isRestored()) {
264: item.restoreState();
265: }
266: IEditorInput input = item.getInput();
267: IEditorDescriptor desc = item.getDescriptor();
268: if (input == null || desc == null) {
269: String title = WorkbenchMessages.OpenRecent_errorTitle;
270: String msg = NLS.bind(
271: WorkbenchMessages.OpenRecent_unableToOpen,
272: itemName);
273: MessageDialog.openWarning(window.getShell(), title,
274: msg);
275: history.remove(item);
276: } else {
277: page.openEditor(input, desc.getId());
278: }
279: } catch (PartInitException e2) {
280: String title = WorkbenchMessages.OpenRecent_errorTitle;
281: MessageDialog.openWarning(window.getShell(), title, e2
282: .getMessage());
283: history.remove(item);
284: }
285: }
286: }
287:
288: }
|