Source code: com/port80/eclipse/jdt/history/EditorHistory.java
1 package com.port80.eclipse.jdt.history;
2
3 import org.eclipse.core.resources.IFile;
4 import org.eclipse.jdt.core.IJavaElement;
5 import org.eclipse.jdt.core.IType;
6 import org.eclipse.jface.action.Action;
7 import org.eclipse.jface.action.ActionContributionItem;
8 import org.eclipse.jface.action.IToolBarManager;
9 import org.eclipse.jface.preference.IPreferenceStore;
10 import org.eclipse.ui.IEditorInput;
11 import org.eclipse.ui.IEditorPart;
12 import org.eclipse.ui.IMemento;
13 import org.eclipse.ui.IPartListener;
14 import org.eclipse.ui.IWorkbenchPage;
15 import org.eclipse.ui.IWorkbenchPart;
16 import org.eclipse.ui.IWorkbenchWindow;
17 import org.eclipse.ui.internal.CoolBarContributionItem;
18 import org.eclipse.ui.internal.CoolBarManager;
19 import org.eclipse.ui.internal.Workbench;
20 import org.eclipse.ui.internal.WorkbenchWindow;
21 import org.eclipse.ui.part.FileEditorInput;
22
23 import com.port80.eclipse.jdt.IConstants;
24 import com.port80.eclipse.jdt.JdtPlugin;
25 import com.port80.eclipse.jdt.Util;
26 import com.port80.eclipse.jdt.util.JavaUtil;
27 import com.port80.eclipse.jdt.util.PersistentItem;
28 import com.port80.eclipse.util.IHistoryListener;
29 import com.port80.eclipse.util.NavigateHistory;
30 import com.port80.eclipse.util.UtilPluginImages;
31
32 /**
33 * EditorHistory maintain the history of files visited by the editor and provide a forward/backward/goto
34 * actions to navigate through the list.
35 *
36 * @author chrisl
37 */
38 public class EditorHistory implements IHistoryListener {
39
40 ////////////////////////////////////////////////////////////////////////
41
42 private static final String NAME = "EditorHistory";
43 private static final String ID = "Blacksun.EditorHistory";
44 private static final boolean DEBUG = true;
45
46 // private static final int VISITED_SIZE = 32;
47 // private static final int HISTORY_SIZE = 8;
48 // private static final int VISITED_MENU_LENGTH = 32;
49 // private static final int HISTORY_MENU_LENGTH = 8;
50
51 ////////////////////////////////////////////////////////////////////////
52
53 private IPreferenceStore fPreferences;
54 private NavigateHistory fHistory;
55 private IPartListener fPartListener;
56
57 private Action fActionForward;
58 private Action fActionBackward;
59 private GotoVisitedAction fActionGoto;
60 private ActionContributionItem fItemForward;
61 private ActionContributionItem fItemBackward;
62 private ActionContributionItem fItemGoto;
63
64 ////////////////////////////////////////////////////////////////////////
65
66 public EditorHistory(IPreferenceStore prefs) {
67 int historysize = prefs.getInt(IConstants.PREF_EDITOR_HISTORY_SIZE);
68 int visitedsize = prefs.getInt(IConstants.PREF_EDITOR_HISTORY_VISITED_SIZE);
69 fHistory = new NavigateHistory(historysize, visitedsize);
70 fHistory.addHistoryListener(this);
71 createActions();
72 }
73
74 public void initPrefs() {
75 if (DEBUG)
76 System.err.println(NAME + ".initPrefs()");
77 }
78
79 public void initActions() {
80 if (fPartListener == null) {
81 hookPartListener();
82 hookHistoryActions();
83 // } else {
84 // unhookPartListener();
85 // unhookHistoryActions();
86 }
87 initPrefs();
88 }
89
90 public void startup() {
91 }
92
93 public void shutdown() {
94 // No need to remove the property listener, since this is shutdown at the same time as
95 // the plugin and the preference store would have been gone by then.
96 }
97
98 ////////////////////////////////////////////////////////////////////////
99
100 public boolean restoreState(IMemento memento) {
101 IMemento[] children = memento.getChildren("Items");
102 if (children == null)
103 return true;
104 if (DEBUG)
105 System.err.println(NAME + ".restoreState(): number of items=" + children.length);
106 PersistentItem[] items = new PersistentItem[children.length];
107 for (int i = 0; i < children.length; ++i) {
108 IMemento m = children[i];
109 items[i] = PersistentItem.restore(m);
110 }
111 for (int i = 0; i < items.length; ++i) {
112 if (items[i] != null)
113 fHistory.updateVisited(items[i]);
114 else if (DEBUG)
115 System.err.println(NAME + ".restoreState(): Failed to restore item at index=" + i);
116 }
117 return true;
118 }
119
120 public void saveState(IMemento memento) {
121 PersistentItem item;
122 Object[] aa = fHistory.getVisited();
123 if (aa != null && aa.length > 0) {
124 IMemento visited = memento.createChild("Visited");
125 int count = 0;
126 for (int i = 0; i < aa.length; ++i) {
127 if (!(aa[i] instanceof PersistentItem)) {
128 JdtPlugin.log(
129 JdtPlugin.getString("ExpectedPersistentItemObjects")
130 + ": object="
131 + aa[i]);
132 continue;
133 }
134 item = (PersistentItem) aa[i];
135 ++count;
136 IMemento m = visited.createChild("Items");
137 item.saveState(m);
138 }
139 visited.putInteger("Size", count);
140 if (DEBUG)
141 System.err.println(NAME + ".saveState(): vsize=" + count);
142 }
143 }
144
145 ////////////////////////////////////////////////////////////////////////
146
147 protected void createActions() {
148 String str_backward = JdtPlugin.getString("Backward");
149 String str_forward = JdtPlugin.getString("Foward");
150 String str_gotovisited = JdtPlugin.getString("GotoVisited");
151 fActionBackward = new Action() {
152 public void run() {
153 getHistory().goBack();
154 }
155 };
156 fActionBackward.setText(str_backward);
157 fActionBackward.setToolTipText(str_backward);
158 fActionBackward.setEnabled(false);
159 UtilPluginImages.setToolImageDescriptors(fActionBackward, UtilPluginImages.IMG_BACKWARD);
160 fItemBackward = new ActionContributionItem(fActionBackward);
161 //
162 fActionForward = new Action() {
163 public void run() {
164 getHistory().goForward();
165 }
166 };
167 fActionForward.setText(str_forward);
168 fActionForward.setToolTipText(str_forward);
169 fActionForward.setEnabled(false);
170 UtilPluginImages.setToolImageDescriptors(fActionForward, UtilPluginImages.IMG_FORWARD);
171 fItemForward = new ActionContributionItem(fActionForward);
172 //
173 fActionGoto = new GotoVisitedAction();
174 fActionGoto.setText(str_gotovisited);
175 fActionGoto.setToolTipText(str_gotovisited);
176 UtilPluginImages.setToolImageDescriptors(fActionGoto, UtilPluginImages.IMG_GOTO);
177 fActionGoto.setMenuCreator(fActionGoto);
178 fItemGoto = new ActionContributionItem(fActionGoto);
179 }
180
181 /** Added history navigation actions to Workbench ToolBar and hookup listeners.*/
182 protected void hookHistoryActions() {
183 //
184 if (DEBUG)
185 System.err.println(NAME + ".hookHistoryActions()");
186 //
187 // Add navigation bar to window toolbars.
188 Workbench workbench = (Workbench) JdtPlugin.getDefault().getWorkbench();
189 WorkbenchWindow window = (WorkbenchWindow) workbench.getActiveWorkbenchWindow();
190 // For 2.0.2
191 //IToolBarManager manager = window.getToolsManager();
192 // For 2.1.0
193 IToolBarManager manager = window.getCoolBarManager();
194 CoolBarContributionItem coolbar = new CoolBarContributionItem((CoolBarManager) manager, ID);
195 IToolBarManager m = coolbar.getToolBarManager();
196 m.add(fItemBackward);
197 m.add(fItemForward);
198 m.add(fItemGoto);
199 manager.add(coolbar);
200 manager.update(true);
201 /*This do not work, only work with getActiveWorkbenchWindow().
202 IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
203 for (int i = 0; i < windows.length; ++i) {
204 WorkbenchWindow window = (WorkbenchWindow) windows[i];
205 CoolBarManager manager = (CoolBarManager) window.getCoolBarManager();
206 CoolBarContributionItem coolbar = new CoolBarContributionItem(manager, ID);
207 // 'manager' is indeed a CoolBarManager and do not accept add(IAction) or
208 // appendToGroup(String,IAction) directly, only accept CoolBars (a CoolBarContributionItem).
209 // So add a CoolBar first.
210 IToolBarManager m = coolbar.getToolBarManager();
211 m.add(fItemBackward);
212 m.add(fItemForward);
213 m.add(fItemGoto);
214 manager.add(coolbar);
215 manager.update(true);
216 }
217 */
218 }
219
220 /** Added history navigation actions to Workbench ToolBar and hookup listeners.*/
221 protected void unhookHistoryActions() {
222 //
223 getHistory().removeHistoryListener(this);
224 //
225 // Add navigation bar to window toolbars.
226 Workbench workbench = (Workbench) JdtPlugin.getDefault().getWorkbench();
227 IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
228 for (int i = 0; i < windows.length; ++i) {
229 WorkbenchWindow window = (WorkbenchWindow) windows[i];
230 //CoolBarManager manager = (CoolBarManager) window.getCoolBarManager();
231 //CoolBarContributionItem coolbar = (CoolBarContributionItem) manager.find(ID);
232 IToolBarManager manager = window.getCoolBarManager();
233 CoolBarContributionItem coolbar = new CoolBarContributionItem((CoolBarManager) manager, ID);
234 if (DEBUG)
235 System.err.println(
236 NAME + ".unhookHistoryActions(): manager=" + manager + ", coolbar=" + coolbar);
237 //FIXME: Don't work (as of 2.1.0-M4-gtk).
238 // These cannot remove the coolbar from the WorkbenchWindow toolbar.
239 if (coolbar != null) {
240 coolbar.getToolBarManager().removeAll();
241 manager.remove(coolbar);
242 }
243 manager.update(true);
244 }
245 }
246
247 // PartListener methods /////////////////////////////////////////
248 //
249
250 /** Listen to any part activation and update the method view if an editor part is activated. */
251 protected void hookPartListener() {
252 fPartListener = new IPartListener() {
253 public void partActivated(IWorkbenchPart part) {
254 editorActivation(part);
255 }
256 public void partBroughtToTop(IWorkbenchPart part) {
257 }
258 public void partClosed(IWorkbenchPart part) {
259 }
260 public void partDeactivated(IWorkbenchPart part) {
261 }
262 public void partOpened(IWorkbenchPart part) {
263 }
264 };
265 Workbench workbench = (Workbench) JdtPlugin.getDefault().getWorkbench();
266 WorkbenchWindow window = (WorkbenchWindow) workbench.getActiveWorkbenchWindow();
267 IWorkbenchPage[] pages = window.getPages();
268 for (int p = 0; p < pages.length; ++p) {
269 pages[p].addPartListener(fPartListener);
270 if (DEBUG)
271 System.err.println(NAME + ".hookPartListener(): " + pages[p]);
272 }
273 //This do not work, only work with getActiveWorkbenchWindow().
274 // IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
275 // for (int i = 0; i < windows.length; ++i) {
276 // IWorkbenchPage[] pages = windows[i].getPages();
277 // for (int p = 0; p < pages.length; ++p) {
278 // pages[p].addPartListener(fPartListener);
279 // if (DEBUG)
280 // System.err.println(NAME + ".hookPartListener(): " + pages[p]);
281 // }
282 // }
283 IEditorPart part = JdtPlugin.getActiveWorkbenchWindow().getActivePage().getActiveEditor();
284 if (part != null)
285 editorActivation(part);
286 }
287
288 protected void unhookPartListener() {
289 if (fPartListener == null)
290 return;
291 Workbench workbench = (Workbench) JdtPlugin.getDefault().getWorkbench();
292 IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
293 for (int i = 0; i < windows.length; ++i) {
294 IWorkbenchPage[] pages = windows[i].getPages();
295 for (int p = 0; p < pages.length; ++p) {
296 pages[p].removePartListener(fPartListener);
297 }
298 }
299 fPartListener = null;
300 }
301
302 ////////////////////////////////////////////////////////////////////////
303
304 /**
305 * Select the IResources for the activated editor if it exists in the WorkingSetModel.
306 * Otherwise, do nothing.
307 * //FIXME: For now, this only works for IJavaElement.
308 */
309 void editorActivation(IWorkbenchPart part) {
310 // Workbench is not always ready to add toolbar actions when plugin startup,
311 // so we have to do it here.
312 IJavaElement element = JavaUtil.getSelectedElementFromEditor(part);
313 if (element != null) {
314 //while(type.getDeclaringType()!=null) type=type.getDeclaringType();
315 IType type = Util.findJavaType(element);
316 if (type != null) {
317 getHistory().add(PersistentItem.create(type));
318 return;
319 }
320 }
321 // Non-java files.
322 if (!(part instanceof IEditorPart))
323 return;
324 IEditorInput input = ((IEditorPart) part).getEditorInput();
325 if (!(input instanceof FileEditorInput))
326 return;
327 IFile file = ((FileEditorInput) input).getFile();
328 getHistory().add(PersistentItem.create(file));
329 }
330
331 ////////////////////////////////////////////////////////////////////////
332
333 // /**
334 // * Add actions to jump to a visited item in the NavigateHistory.
335 // */
336 // public void fillHistoryMenuItems(IMenuManager manager) {
337 // Map map = new HashMap();
338 // String sortkey;
339 // PersistentItem item;
340 // NavigateHistory history = getHistory();
341 // int size = history.visitedSize();
342 // int start;
343 // //
344 // // History.
345 // //
346 // int pos = history.historyPos();
347 // size = history.historySize();
348 // start = Math.max(0, size - HISTORY_MENU_LENGTH);
349 // for (int i = start; i < history.historySize(); ++i) {
350 // Object a = history.getHistory(i);
351 // if (!(a instanceof PersistentItem))
352 // continue;
353 // item = (PersistentItem) a;
354 // Action action = new Action() {
355 // public void run() {
356 // try {
357 // int n = Integer.parseInt(getId());
358 // getHistory().gotoHistory(n);
359 // } catch (Exception e) {
360 // }
361 // }
362 // };
363 // action.setId("" + i);
364 // String text = item.getName();
365 // //action.setText("&" + i + ((i == pos) ? "->" : " ") + text);
366 // action.setText(((i == pos) ? "->" : "- ") + text);
367 // manager.add(action);
368 // }
369 // manager.add(new Separator());
370 // //
371 // // Visited.
372 // //
373 // start = Math.max(0, size - VISITED_MENU_LENGTH);
374 // for (int i = start; i < size; ++i) {
375 // Object a = history.getVisited(i);
376 // if (a instanceof PersistentItem) {
377 // item = (PersistentItem) a;
378 // Action action = new Action() {
379 // public void run() {
380 // try {
381 // int n = Integer.parseInt(getId());
382 // getHistory().gotoVisited(n);
383 // } catch (Exception e) {
384 // }
385 // }
386 // };
387 // action.setId("" + i);
388 // String text = item.getName();
389 // sortkey = text + item.toString();
390 // action.setText(((i == size - 1) ? "->" : "- ") + text);
391 // map.put(sortkey, action);
392 // }
393 // }
394 // Object[] sorted = map.keySet().toArray();
395 // Arrays.sort(sorted);
396 // for (int i = 0; i < sorted.length; ++i)
397 // manager.add((Action) map.get(sorted[i]));
398 // }
399
400 // IHistoryListener ////////////////////////////////////////////////////
401 //
402 public void gotoObject(Object a) {
403 if (!(a instanceof PersistentItem))
404 return;
405 Util.editItem((PersistentItem) a);
406 }
407
408 public void updateHistoryStatus(boolean backwardok, boolean forwardok, Object prev, Object next) {
409 if (fActionBackward != null) {
410 fActionBackward.setEnabled(backwardok);
411 if (backwardok && prev != null && prev instanceof PersistentItem) {
412 fActionBackward.setToolTipText("Prev: " + ((PersistentItem) prev).getName());
413 }
414 }
415 if (fActionForward != null) {
416 fActionForward.setEnabled(forwardok);
417 if (forwardok && next != null && next instanceof PersistentItem) {
418 fActionForward.setToolTipText("Next: " + ((PersistentItem) next).getName());
419 }
420 }
421 }
422
423 ////////////////////////////////////////////////////////////////////////
424
425 public NavigateHistory getHistory() {
426 return fHistory;
427 }
428
429 ////////////////////////////////////////////////////////////////////////
430
431 }