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.internal.quickaccess;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.Iterator;
015: import java.util.LinkedList;
016: import java.util.List;
017: import java.util.Map;
018:
019: import org.eclipse.core.commands.Command;
020: import org.eclipse.core.runtime.Assert;
021: import org.eclipse.jface.bindings.TriggerSequence;
022: import org.eclipse.jface.bindings.keys.KeySequence;
023: import org.eclipse.jface.bindings.keys.SWTKeySupport;
024: import org.eclipse.jface.dialogs.Dialog;
025: import org.eclipse.jface.dialogs.IDialogSettings;
026: import org.eclipse.jface.dialogs.PopupDialog;
027: import org.eclipse.jface.layout.GridDataFactory;
028: import org.eclipse.jface.layout.GridLayoutFactory;
029: import org.eclipse.jface.layout.TableColumnLayout;
030: import org.eclipse.jface.resource.FontDescriptor;
031: import org.eclipse.jface.resource.ImageDescriptor;
032: import org.eclipse.jface.resource.JFaceResources;
033: import org.eclipse.jface.resource.LocalResourceManager;
034: import org.eclipse.jface.viewers.ColumnWeightData;
035: import org.eclipse.jface.window.DefaultToolTip;
036: import org.eclipse.jface.window.ToolTip;
037: import org.eclipse.osgi.util.NLS;
038: import org.eclipse.swt.SWT;
039: import org.eclipse.swt.custom.BusyIndicator;
040: import org.eclipse.swt.events.ControlAdapter;
041: import org.eclipse.swt.events.ControlEvent;
042: import org.eclipse.swt.events.KeyAdapter;
043: import org.eclipse.swt.events.KeyEvent;
044: import org.eclipse.swt.events.KeyListener;
045: import org.eclipse.swt.events.ModifyEvent;
046: import org.eclipse.swt.events.ModifyListener;
047: import org.eclipse.swt.events.MouseAdapter;
048: import org.eclipse.swt.events.MouseEvent;
049: import org.eclipse.swt.events.SelectionEvent;
050: import org.eclipse.swt.events.SelectionListener;
051: import org.eclipse.swt.graphics.Color;
052: import org.eclipse.swt.graphics.Font;
053: import org.eclipse.swt.graphics.FontMetrics;
054: import org.eclipse.swt.graphics.GC;
055: import org.eclipse.swt.graphics.Point;
056: import org.eclipse.swt.graphics.Rectangle;
057: import org.eclipse.swt.graphics.TextLayout;
058: import org.eclipse.swt.graphics.TextStyle;
059: import org.eclipse.swt.widgets.Composite;
060: import org.eclipse.swt.widgets.Control;
061: import org.eclipse.swt.widgets.Event;
062: import org.eclipse.swt.widgets.Listener;
063: import org.eclipse.swt.widgets.Shell;
064: import org.eclipse.swt.widgets.Table;
065: import org.eclipse.swt.widgets.TableColumn;
066: import org.eclipse.swt.widgets.TableItem;
067: import org.eclipse.swt.widgets.Text;
068: import org.eclipse.ui.IWorkbenchPage;
069: import org.eclipse.ui.IWorkbenchWindow;
070: import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
071: import org.eclipse.ui.internal.WorkbenchImages;
072: import org.eclipse.ui.internal.WorkbenchPlugin;
073: import org.eclipse.ui.internal.progress.ProgressManagerUtil;
074: import org.eclipse.ui.keys.IBindingService;
075: import org.eclipse.ui.themes.ColorUtil;
076:
077: /**
078: * @since 3.3
079: *
080: */
081: public class QuickAccessDialog extends PopupDialog {
082: private static final int INITIAL_COUNT_PER_PROVIDER = 5;
083: private static final int MAX_COUNT_TOTAL = 20;
084:
085: private Text filterText;
086:
087: private QuickAccessProvider[] providers;
088: private IWorkbenchWindow window;
089:
090: private Table table;
091:
092: private LocalResourceManager resourceManager = new LocalResourceManager(
093: JFaceResources.getResources());
094:
095: private static final String TEXT_ARRAY = "textArray"; //$NON-NLS-1$
096: private static final String TEXT_ENTRIES = "textEntries"; //$NON-NLS-1$
097: private static final String ORDERED_PROVIDERS = "orderedProviders"; //$NON-NLS-1$
098: private static final String ORDERED_ELEMENTS = "orderedElements"; //$NON-NLS-1$
099: static final int MAXIMUM_NUMBER_OF_ELEMENTS = 60;
100: static final int MAXIMUM_NUMBER_OF_TEXT_ENTRIES_PER_ELEMENT = 3;
101:
102: protected String rememberedText;
103:
104: protected Map textMap = new HashMap();
105:
106: protected Map elementMap = new HashMap();
107:
108: private LinkedList previousPicksList = new LinkedList();
109:
110: protected Map providerMap;
111: // private Font italicsFont;
112: private Color grayColor;
113: private TextLayout textLayout;
114: private TriggerSequence[] invokingCommandKeySequences;
115: private Command invokingCommand;
116: private KeyAdapter keyAdapter;
117: private boolean showAllMatches = false;
118: protected boolean resized = false;
119:
120: /**
121: * @param parent
122: */
123: QuickAccessDialog(IWorkbenchWindow window,
124: final Command invokingCommand) {
125: super (
126: ProgressManagerUtil.getDefaultParent(),
127: SWT.RESIZE,
128: true,
129: true,
130: true,
131: true,
132: null,
133: QuickAccessMessages.QuickAccess_StartTypingToFindMatches);
134:
135: this .window = window;
136: BusyIndicator.showWhile(window.getShell() == null ? null
137: : window.getShell().getDisplay(), new Runnable() {
138: public void run() {
139: QuickAccessDialog.this .providers = new QuickAccessProvider[] {
140: new PreviousPicksProvider(),
141: new EditorProvider(), new ViewProvider(),
142: new PerspectiveProvider(),
143: new CommandProvider(), new ActionProvider(),
144: new WizardProvider(), new PreferenceProvider(),
145: new PropertiesProvider() };
146: providerMap = new HashMap();
147: for (int i = 0; i < providers.length; i++) {
148: providerMap.put(providers[i].getId(), providers[i]);
149: }
150: restoreDialog();
151: QuickAccessDialog.this .invokingCommand = invokingCommand;
152: if (QuickAccessDialog.this .invokingCommand != null
153: && !QuickAccessDialog.this .invokingCommand
154: .isDefined()) {
155: QuickAccessDialog.this .invokingCommand = null;
156: } else {
157: // Pre-fetch key sequence - do not change because scope will
158: // change later.
159: getInvokingCommandKeySequences();
160: }
161: // create early
162: create();
163: }
164: });
165: // Ugly hack to avoid bug 184045. If this gets fixed, replace the
166: // following code with a call to refresh("").
167: getShell().getDisplay().asyncExec(new Runnable() {
168: public void run() {
169: final Shell shell = getShell();
170: if (shell != null && !shell.isDisposed()) {
171: Point size = shell.getSize();
172: shell.setSize(size.x, size.y + 1);
173: }
174: }
175: });
176: }
177:
178: protected Control createTitleControl(Composite parent) {
179: filterText = new Text(parent, SWT.NONE);
180:
181: GC gc = new GC(parent);
182: gc.setFont(parent.getFont());
183: FontMetrics fontMetrics = gc.getFontMetrics();
184: gc.dispose();
185:
186: GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
187: .grab(true, false).hint(
188: SWT.DEFAULT,
189: Dialog.convertHeightInCharsToPixels(
190: fontMetrics, 1)).applyTo(filterText);
191:
192: filterText.addKeyListener(getKeyAdapter());
193: filterText.addKeyListener(new KeyListener() {
194: public void keyPressed(KeyEvent e) {
195: if (e.keyCode == 0x0D) {
196: handleSelection();
197: return;
198: } else if (e.keyCode == SWT.ARROW_DOWN) {
199: int index = table.getSelectionIndex();
200: if (index != -1 && table.getItemCount() > index + 1) {
201: table.setSelection(index + 1);
202: }
203: table.setFocus();
204: } else if (e.keyCode == SWT.ARROW_UP) {
205: int index = table.getSelectionIndex();
206: if (index != -1 && index >= 1) {
207: table.setSelection(index - 1);
208: table.setFocus();
209: }
210: } else if (e.character == 0x1B) // ESC
211: close();
212: }
213:
214: public void keyReleased(KeyEvent e) {
215: // do nothing
216: }
217: });
218: filterText.addModifyListener(new ModifyListener() {
219: public void modifyText(ModifyEvent e) {
220: String text = ((Text) e.widget).getText().toLowerCase();
221: refresh(text);
222: }
223: });
224:
225: return filterText;
226: }
227:
228: /*
229: * (non-Javadoc)
230: *
231: * @see org.eclipse.jface.dialogs.PopupDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
232: */
233: protected Control createDialogArea(Composite parent) {
234: Composite composite = (Composite) super
235: .createDialogArea(parent);
236: boolean isWin32 = "win32".equals(SWT.getPlatform()); //$NON-NLS-1$
237: GridLayoutFactory.fillDefaults().extendedMargins(
238: isWin32 ? 0 : 3, 3, 2, 2).applyTo(composite);
239: Composite tableComposite = new Composite(composite, SWT.NONE);
240: GridDataFactory.fillDefaults().grab(true, true).applyTo(
241: tableComposite);
242: TableColumnLayout tableColumnLayout = new TableColumnLayout();
243: tableComposite.setLayout(tableColumnLayout);
244: table = new Table(tableComposite, SWT.SINGLE
245: | SWT.FULL_SELECTION);
246: textLayout = new TextLayout(table.getDisplay());
247: textLayout.setOrientation(getDefaultOrientation());
248: Font boldFont = resourceManager.createFont(FontDescriptor
249: .createFrom(table.getFont()).setStyle(SWT.BOLD));
250: textLayout.setFont(table.getFont());
251: textLayout
252: .setText(QuickAccessMessages.QuickAccess_AvailableCategories);
253: int maxProviderWidth = (int) (textLayout.getBounds().width * 1.1);
254: textLayout.setFont(boldFont);
255: for (int i = 0; i < providers.length; i++) {
256: QuickAccessProvider provider = providers[i];
257: textLayout.setText(provider.getName());
258: int width = (int) (textLayout.getBounds().width * 1.1);
259: if (width > maxProviderWidth) {
260: maxProviderWidth = width;
261: }
262: }
263: tableColumnLayout.setColumnData(
264: new TableColumn(table, SWT.NONE), new ColumnWeightData(
265: 0, maxProviderWidth));
266: tableColumnLayout.setColumnData(
267: new TableColumn(table, SWT.NONE), new ColumnWeightData(
268: 100, 100));
269: table.getShell().addControlListener(new ControlAdapter() {
270: public void controlResized(ControlEvent e) {
271: if (!showAllMatches) {
272: if (!resized) {
273: resized = true;
274: e.display.timerExec(100, new Runnable() {
275: public void run() {
276: if (getShell() != null
277: && !getShell().isDisposed()) {
278: refresh(filterText.getText()
279: .toLowerCase());
280: }
281: resized = false;
282: }
283: });
284: }
285: }
286: }
287: });
288:
289: new DefaultToolTip(table, ToolTip.NO_RECREATE, false) {
290: private QuickAccessEntry getEntry(Event event) {
291: TableItem item = table.getItem(new Point(event.x,
292: event.y));
293: if (item != null) {
294: return (QuickAccessEntry) item.getData();
295: }
296: return null;
297: }
298:
299: protected String getText(Event event) {
300: QuickAccessEntry entry = getEntry(event);
301: if (entry != null) {
302: return entry.element.getLabel();
303: }
304: return null;
305: }
306:
307: protected boolean shouldCreateToolTip(Event event) {
308: table.setToolTipText(""); //$NON-NLS-1$
309: return getEntry(event) != null
310: && super .shouldCreateToolTip(event);
311: }
312:
313: protected Object getToolTipArea(Event event) {
314: return getEntry(event);
315: }
316: }.activate();
317:
318: table.addKeyListener(getKeyAdapter());
319: table.addKeyListener(new KeyListener() {
320: public void keyPressed(KeyEvent e) {
321: if (e.keyCode == SWT.ARROW_UP
322: && table.getSelectionIndex() == 0) {
323: filterText.setFocus();
324: } else if (e.character == SWT.ESC) {
325: close();
326: }
327: }
328:
329: public void keyReleased(KeyEvent e) {
330: // do nothing
331: }
332: });
333: table.addMouseListener(new MouseAdapter() {
334: public void mouseUp(MouseEvent e) {
335:
336: if (table.getSelectionCount() < 1)
337: return;
338:
339: if (e.button != 1)
340: return;
341:
342: if (table.equals(e.getSource())) {
343: Object o = table.getItem(new Point(e.x, e.y));
344: TableItem selection = table.getSelection()[0];
345: if (selection.equals(o))
346: handleSelection();
347: }
348: }
349: });
350:
351: table.addSelectionListener(new SelectionListener() {
352: public void widgetSelected(SelectionEvent e) {
353: // do nothing
354: }
355:
356: public void widgetDefaultSelected(SelectionEvent e) {
357: handleSelection();
358: }
359: });
360:
361: // italicsFont = resourceManager.createFont(FontDescriptor.createFrom(
362: // table.getFont()).setStyle(SWT.ITALIC));
363: grayColor = resourceManager.createColor(ColorUtil.blend(table
364: .getBackground().getRGB(), table.getForeground()
365: .getRGB()));
366: final TextStyle boldStyle = new TextStyle(boldFont, null, null);
367: Listener listener = new Listener() {
368: public void handleEvent(Event event) {
369: QuickAccessEntry entry = (QuickAccessEntry) event.item
370: .getData();
371: if (entry != null) {
372: switch (event.type) {
373: case SWT.MeasureItem:
374: entry.measure(event, textLayout,
375: resourceManager, boldStyle);
376: break;
377: case SWT.PaintItem:
378: entry.paint(event, textLayout, resourceManager,
379: boldStyle, grayColor);
380: break;
381: case SWT.EraseItem:
382: entry.erase(event);
383: break;
384: }
385: }
386: }
387: };
388: table.addListener(SWT.MeasureItem, listener);
389: table.addListener(SWT.EraseItem, listener);
390: table.addListener(SWT.PaintItem, listener);
391:
392: return composite;
393: }
394:
395: /**
396: *
397: */
398: private int computeNumberOfItems() {
399: int height = table.getClientArea().height;
400: int lineWidth = table.getLinesVisible() ? table
401: .getGridLineWidth() : 0;
402: return (height - lineWidth)
403: / (table.getItemHeight() + lineWidth);
404: }
405:
406: /**
407: *
408: */
409: private void refresh(String filter) {
410: int numItems = computeNumberOfItems();
411:
412: // perfect match, to be selected in the table if not null
413: QuickAccessElement perfectMatch = (QuickAccessElement) elementMap
414: .get(filter);
415:
416: List[] entries = computeMatchingEntries(filter, perfectMatch,
417: numItems);
418:
419: int selectionIndex = refreshTable(perfectMatch, entries);
420:
421: if (table.getItemCount() > 0) {
422: table.setSelection(selectionIndex);
423: } else if (filter.length() == 0) {
424: {
425: TableItem item = new TableItem(table, SWT.NONE);
426: item
427: .setText(
428: 0,
429: QuickAccessMessages.QuickAccess_AvailableCategories);
430: item.setForeground(0, grayColor);
431: }
432: for (int i = 0; i < providers.length; i++) {
433: QuickAccessProvider provider = providers[i];
434: TableItem item = new TableItem(table, SWT.NONE);
435: item.setText(1, provider.getName());
436: item.setForeground(1, grayColor);
437: }
438: }
439:
440: if (filter.length() == 0) {
441: setInfoText(QuickAccessMessages.QuickAccess_StartTypingToFindMatches);
442: } else {
443: TriggerSequence[] sequences = getInvokingCommandKeySequences();
444: if (showAllMatches || sequences == null
445: || sequences.length == 0) {
446: setInfoText(""); //$NON-NLS-1$
447: } else {
448: setInfoText(NLS
449: .bind(
450: QuickAccessMessages.QuickAccess_PressKeyToShowAllMatches,
451: sequences[0].format()));
452: }
453: }
454: }
455:
456: final protected TriggerSequence[] getInvokingCommandKeySequences() {
457: if (invokingCommandKeySequences == null) {
458: if (invokingCommand != null) {
459: IBindingService bindingService = (IBindingService) window
460: .getWorkbench().getAdapter(
461: IBindingService.class);
462: invokingCommandKeySequences = bindingService
463: .getActiveBindingsFor(invokingCommand.getId());
464: }
465: }
466: return invokingCommandKeySequences;
467: }
468:
469: private KeyAdapter getKeyAdapter() {
470: if (keyAdapter == null) {
471: keyAdapter = new KeyAdapter() {
472: public void keyPressed(KeyEvent e) {
473: int accelerator = SWTKeySupport
474: .convertEventToUnmodifiedAccelerator(e);
475: KeySequence keySequence = KeySequence
476: .getInstance(SWTKeySupport
477: .convertAcceleratorToKeyStroke(accelerator));
478: TriggerSequence[] sequences = getInvokingCommandKeySequences();
479: if (sequences == null)
480: return;
481: for (int i = 0; i < sequences.length; i++) {
482: if (sequences[i].equals(keySequence)) {
483: e.doit = false;
484: toggleShowAllMatches();
485: return;
486: }
487: }
488: }
489: };
490: }
491: return keyAdapter;
492: }
493:
494: private void toggleShowAllMatches() {
495: showAllMatches = !showAllMatches;
496: refresh(filterText.getText().toLowerCase());
497: }
498:
499: private int refreshTable(QuickAccessElement perfectMatch,
500: List[] entries) {
501: if (table.getItemCount() > entries.length
502: && table.getItemCount() - entries.length > 20) {
503: table.removeAll();
504: }
505: TableItem[] items = table.getItems();
506: int selectionIndex = -1;
507: int index = 0;
508: for (int i = 0; i < providers.length; i++) {
509: if (entries[i] != null) {
510: boolean firstEntry = true;
511: for (Iterator it = entries[i].iterator(); it.hasNext();) {
512: QuickAccessEntry entry = (QuickAccessEntry) it
513: .next();
514: entry.firstInCategory = firstEntry;
515: firstEntry = false;
516: if (!it.hasNext()) {
517: entry.lastInCategory = true;
518: }
519: TableItem item;
520: if (index < items.length) {
521: item = items[index];
522: table.clear(index);
523: } else {
524: item = new TableItem(table, SWT.NONE);
525: }
526: if (perfectMatch == entry.element
527: && selectionIndex == -1) {
528: selectionIndex = index;
529: }
530: item.setData(entry);
531: item.setText(0, entry.provider.getName());
532: item.setText(1, entry.element.getLabel());
533: if (SWT.getPlatform().equals("wpf")) { //$NON-NLS-1$
534: item.setImage(1, entry.getImage(entry.element,
535: resourceManager));
536: }
537: index++;
538: }
539: }
540: }
541: if (index < items.length) {
542: table.remove(index, items.length - 1);
543: }
544: if (selectionIndex == -1) {
545: selectionIndex = 0;
546: }
547: return selectionIndex;
548: }
549:
550: private List[] computeMatchingEntries(String filter,
551: QuickAccessElement perfectMatch, int maxCount) {
552: // collect matches in an array of lists
553: List[] entries = new ArrayList[providers.length];
554: int[] indexPerProvider = new int[providers.length];
555: int countPerProvider = Math.min(maxCount / 4,
556: INITIAL_COUNT_PER_PROVIDER);
557: int countTotal = 0;
558: boolean perfectMatchAdded = true;
559: if (perfectMatch != null) {
560: // reserve one entry for the perfect match
561: maxCount--;
562: perfectMatchAdded = false;
563: }
564: boolean done;
565: do {
566: // will be set to false if we find a provider with remaining
567: // elements
568: done = true;
569: for (int i = 0; i < providers.length
570: && (showAllMatches || countTotal < maxCount); i++) {
571: if (entries[i] == null) {
572: entries[i] = new ArrayList();
573: indexPerProvider[i] = 0;
574: }
575: int count = 0;
576: QuickAccessProvider provider = providers[i];
577: if (filter.length() > 0
578: || provider instanceof PreviousPicksProvider
579: || showAllMatches) {
580: QuickAccessElement[] elements = provider
581: .getElementsSorted();
582: int j = indexPerProvider[i];
583: while (j < elements.length
584: && (showAllMatches || (count < countPerProvider && countTotal < maxCount))) {
585: QuickAccessElement element = elements[j];
586: QuickAccessEntry entry;
587: if (filter.length() == 0) {
588: if (i == 0 || showAllMatches) {
589: entry = new QuickAccessEntry(element,
590: provider, new int[0][0],
591: new int[0][0]);
592: } else {
593: entry = null;
594: }
595: } else {
596: entry = element.match(filter, provider);
597: }
598: if (entry != null) {
599: entries[i].add(entry);
600: count++;
601: countTotal++;
602: if (i == 0 && entry.element == perfectMatch) {
603: perfectMatchAdded = true;
604: maxCount = MAX_COUNT_TOTAL;
605: }
606: }
607: j++;
608: }
609: indexPerProvider[i] = j;
610: if (j < elements.length) {
611: done = false;
612: }
613: }
614: }
615: // from now on, add one element per provider
616: countPerProvider = 1;
617: } while ((showAllMatches || countTotal < maxCount) && !done);
618: if (!perfectMatchAdded) {
619: QuickAccessEntry entry = perfectMatch.match(filter,
620: providers[0]);
621: if (entry != null) {
622: if (entries[0] == null) {
623: entries[0] = new ArrayList();
624: indexPerProvider[0] = 0;
625: }
626: entries[0].add(entry);
627: }
628: }
629: return entries;
630: }
631:
632: protected Control getFocusControl() {
633: return filterText;
634: }
635:
636: public boolean close() {
637: storeDialog(getDialogSettings());
638: if (textLayout != null && !textLayout.isDisposed()) {
639: textLayout.dispose();
640: }
641: if (resourceManager != null) {
642: resourceManager.dispose();
643: resourceManager = null;
644: }
645: return super .close();
646: }
647:
648: protected Point getInitialSize() {
649: if (!getPersistBounds()) {
650: return new Point(350, 420);
651: }
652: return super .getInitialSize();
653: }
654:
655: protected Point getInitialLocation(Point initialSize) {
656: if (!getPersistBounds()) {
657: Point size = new Point(400, 400);
658: Rectangle parentBounds = getParentShell().getBounds();
659: int x = parentBounds.x + parentBounds.width / 2 - size.x
660: / 2;
661: int y = parentBounds.y + parentBounds.height / 2 - size.y
662: / 2;
663: return new Point(x, y);
664: }
665: return super .getInitialLocation(initialSize);
666: }
667:
668: protected IDialogSettings getDialogSettings() {
669: final IDialogSettings workbenchDialogSettings = WorkbenchPlugin
670: .getDefault().getDialogSettings();
671: IDialogSettings result = workbenchDialogSettings
672: .getSection(getId());
673: if (result == null) {
674: result = workbenchDialogSettings.addNewSection(getId());
675: }
676: return result;
677: }
678:
679: protected String getId() {
680: return "org.eclipse.ui.internal.QuickAccess"; //$NON-NLS-1$
681: }
682:
683: private void storeDialog(IDialogSettings dialogSettings) {
684: String[] orderedElements = new String[previousPicksList.size()];
685: String[] orderedProviders = new String[previousPicksList.size()];
686: String[] textEntries = new String[previousPicksList.size()];
687: ArrayList arrayList = new ArrayList();
688: for (int i = 0; i < orderedElements.length; i++) {
689: QuickAccessElement quickAccessElement = (QuickAccessElement) previousPicksList
690: .get(i);
691: ArrayList elementText = (ArrayList) textMap
692: .get(quickAccessElement);
693: Assert.isNotNull(elementText);
694: orderedElements[i] = quickAccessElement.getId();
695: orderedProviders[i] = quickAccessElement.getProvider()
696: .getId();
697: arrayList.addAll(elementText);
698: textEntries[i] = elementText.size() + ""; //$NON-NLS-1$
699: }
700: String[] textArray = (String[]) arrayList
701: .toArray(new String[arrayList.size()]);
702: dialogSettings.put(ORDERED_ELEMENTS, orderedElements);
703: dialogSettings.put(ORDERED_PROVIDERS, orderedProviders);
704: dialogSettings.put(TEXT_ENTRIES, textEntries);
705: dialogSettings.put(TEXT_ARRAY, textArray);
706: }
707:
708: private void restoreDialog() {
709: IDialogSettings dialogSettings = getDialogSettings();
710: if (dialogSettings != null) {
711: String[] orderedElements = dialogSettings
712: .getArray(ORDERED_ELEMENTS);
713: String[] orderedProviders = dialogSettings
714: .getArray(ORDERED_PROVIDERS);
715: String[] textEntries = dialogSettings
716: .getArray(TEXT_ENTRIES);
717: String[] textArray = dialogSettings.getArray(TEXT_ARRAY);
718: elementMap = new HashMap();
719: textMap = new HashMap();
720: previousPicksList = new LinkedList();
721: if (orderedElements != null && orderedProviders != null
722: && textEntries != null && textArray != null) {
723: int arrayIndex = 0;
724: for (int i = 0; i < orderedElements.length; i++) {
725: QuickAccessProvider quickAccessProvider = (QuickAccessProvider) providerMap
726: .get(orderedProviders[i]);
727: int numTexts = Integer.parseInt(textEntries[i]);
728: if (quickAccessProvider != null) {
729: QuickAccessElement quickAccessElement = quickAccessProvider
730: .getElementForId(orderedElements[i]);
731: if (quickAccessElement != null) {
732: ArrayList arrayList = new ArrayList();
733: for (int j = arrayIndex; j < arrayIndex
734: + numTexts; j++) {
735: String text = textArray[j];
736: // text length can be zero for old workspaces, see bug 190006
737: if (text.length() > 0) {
738: arrayList.add(text);
739: elementMap.put(text,
740: quickAccessElement);
741: }
742: }
743: textMap.put(quickAccessElement, arrayList);
744: previousPicksList.add(quickAccessElement);
745: }
746: }
747: arrayIndex += numTexts;
748: }
749: }
750: }
751: }
752:
753: protected void handleElementSelected(String text,
754: Object selectedElement) {
755: IWorkbenchPage activePage = window.getActivePage();
756: if (activePage != null) {
757: if (selectedElement instanceof QuickAccessElement) {
758: addPreviousPick(text, selectedElement);
759: storeDialog(getDialogSettings());
760: QuickAccessElement element = (QuickAccessElement) selectedElement;
761: element.execute();
762: }
763: }
764: }
765:
766: /**
767: * @param element
768: */
769: private void addPreviousPick(String text, Object element) {
770: // previousPicksList:
771: // Remove element from previousPicksList so there are no duplicates
772: // If list is max size, remove last(oldest) element
773: // Remove entries for removed element from elementMap and textMap
774: // Add element to front of previousPicksList
775: previousPicksList.remove(element);
776: if (previousPicksList.size() == MAXIMUM_NUMBER_OF_ELEMENTS) {
777: Object removedElement = previousPicksList.removeLast();
778: ArrayList removedList = (ArrayList) textMap
779: .remove(removedElement);
780: for (int i = 0; i < removedList.size(); i++) {
781: elementMap.remove(removedList.get(i));
782: }
783: }
784: previousPicksList.addFirst(element);
785:
786: // textMap:
787: // Get list of strings for element from textMap
788: // Create new list for element if there isn't one and put
789: // element->textList in textMap
790: // Remove rememberedText from list
791: // If list is max size, remove first(oldest) string
792: // Remove text from elementMap
793: // Add rememberedText to list of strings for element in textMap
794: ArrayList textList = (ArrayList) textMap.get(element);
795: if (textList == null) {
796: textList = new ArrayList();
797: textMap.put(element, textList);
798: }
799:
800: textList.remove(text);
801: if (textList.size() == MAXIMUM_NUMBER_OF_TEXT_ENTRIES_PER_ELEMENT) {
802: Object removedText = textList.remove(0);
803: elementMap.remove(removedText);
804: }
805:
806: if (text.length() > 0) {
807: textList.add(text);
808:
809: // elementMap:
810: // Put rememberedText->element in elementMap
811: // If it replaced a different element update textMap and
812: // PreviousPicksList
813: Object replacedElement = elementMap.put(text, element);
814: if (replacedElement != null
815: && !replacedElement.equals(element)) {
816: textList = (ArrayList) textMap.get(replacedElement);
817: if (textList != null) {
818: textList.remove(text);
819: if (textList.isEmpty()) {
820: textMap.remove(replacedElement);
821: previousPicksList.remove(replacedElement);
822: }
823: }
824: }
825: }
826: }
827:
828: /**
829: *
830: */
831: private void handleSelection() {
832: QuickAccessElement selectedElement = null;
833: String text = filterText.getText().toLowerCase();
834: if (table.getSelectionCount() == 1) {
835: QuickAccessEntry entry = (QuickAccessEntry) table
836: .getSelection()[0].getData();
837: selectedElement = entry == null ? null : entry.element;
838: }
839: close();
840: if (selectedElement != null) {
841: handleElementSelected(text, selectedElement);
842: }
843: }
844:
845: private class PreviousPicksProvider extends QuickAccessProvider {
846:
847: public QuickAccessElement getElementForId(String id) {
848: return null;
849: }
850:
851: public QuickAccessElement[] getElements() {
852: return (QuickAccessElement[]) previousPicksList
853: .toArray(new QuickAccessElement[previousPicksList
854: .size()]);
855: }
856:
857: public QuickAccessElement[] getElementsSorted() {
858: return getElements();
859: }
860:
861: public String getId() {
862: return "org.eclipse.ui.previousPicks"; //$NON-NLS-1$
863: }
864:
865: public ImageDescriptor getImageDescriptor() {
866: return WorkbenchImages
867: .getImageDescriptor(IWorkbenchGraphicConstants.IMG_OBJ_NODE);
868: }
869:
870: public String getName() {
871: return QuickAccessMessages.QuickAccess_Previous;
872: }
873: }
874:
875: }
|