Java tutorial
/* * Copyright (c) 2012 Diamond Light Source Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.dawnsci.common.widgets.breadcrumb; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Stack; import org.eclipse.swt.widgets.Item; import org.eclipse.swt.widgets.Widget; import org.eclipse.core.resources.IResource; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.internal.ui.viewsupport.ResourceToItemsMapper.IContentViewerAccessor; /** * Helper class for updating error markers and other decorators that work on resources. * Items are mapped to their element's underlying resource. * Method <code>resourceChanged</code> updates all items that are affected from the changed * elements. */ public class ResourceToItemsMapper { public static interface IContentViewerAccessor { public void doUpdateItem(Widget item); } private static final int NUMBER_LIST_REUSE = 10; // map from IResource to Item or List<Item> private HashMap<IResource, Object> fResourceToItem; private Stack<List<Item>> fReuseLists; private IContentViewerAccessor fContentViewerAccess; public ResourceToItemsMapper(IContentViewerAccessor viewer) { fResourceToItem = new HashMap<IResource, Object>(); fReuseLists = new Stack<List<Item>>(); fContentViewerAccess = viewer; } /** * Must be called from the UI thread. * @param changedResource Changed resource */ public void resourceChanged(IResource changedResource) { Object obj = fResourceToItem.get(changedResource); if (obj == null) { // not mapped } else if (obj instanceof Item) { updateItem((Item) obj); } else { // List of Items @SuppressWarnings("unchecked") List<Item> list = (List<Item>) obj; for (int k = 0; k < list.size(); k++) { updateItem(list.get(k)); } } } private void updateItem(Item item) { if (!item.isDisposed()) { fContentViewerAccess.doUpdateItem(item); } } /** * Adds a new item to the map. * @param element Element to map * @param item The item used for the element */ public void addToMap(Object element, Item item) { IResource resource = getCorrespondingResource(element); if (resource != null) { Object existingMapping = fResourceToItem.get(resource); if (existingMapping == null) { fResourceToItem.put(resource, item); } else if (existingMapping instanceof Item) { if (existingMapping != item) { List<Item> list = getNewList(); list.add((Item) existingMapping); list.add(item); fResourceToItem.put(resource, list); } } else { // List @SuppressWarnings("unchecked") List<Item> list = (List<Item>) existingMapping; if (!list.contains(item)) { list.add(item); } } } } /** * Removes an element from the map. * @param element The data element * @param item The table or tree item */ public void removeFromMap(Object element, Item item) { IResource resource = getCorrespondingResource(element); if (resource != null) { Object existingMapping = fResourceToItem.get(resource); if (existingMapping == null) { return; } else if (existingMapping instanceof Item) { fResourceToItem.remove(resource); } else { // List @SuppressWarnings("unchecked") List<Item> list = (List<Item>) existingMapping; list.remove(item); if (list.isEmpty()) { fResourceToItem.remove(list); releaseList(list); } } } } private List<Item> getNewList() { if (!fReuseLists.isEmpty()) { return fReuseLists.pop(); } return new ArrayList<Item>(2); } private void releaseList(List<Item> list) { if (fReuseLists.size() < NUMBER_LIST_REUSE) { fReuseLists.push(list); } } /** * Clears the map. */ public void clearMap() { fResourceToItem.clear(); } /** * Tests if the map is empty * @return Returns if there are mappings */ public boolean isEmpty() { return fResourceToItem.isEmpty(); } /** * Method that decides which elements can have error markers * Returns null if an element can not have error markers. * @param element The input element * @return Returns the corresponding resource or null */ private static IResource getCorrespondingResource(Object element) { if (element instanceof IJavaElement) { IJavaElement elem = (IJavaElement) element; IResource res = elem.getResource(); if (res == null) { ICompilationUnit cu = (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT); if (cu != null) { // elements in compilation units are mapped to the underlying resource of the original cu res = cu.getResource(); } } return res; } else if (element instanceof IResource) { return (IResource) element; } return null; } }