1 /******************************************************************************* 2 * Copyright (c) 2005, 2016 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Wind River Systems - added saving and restoring properties 14 *******************************************************************************/ 15 package org.eclipse.debug.internal.ui.viewers.model.provisional; 16 17 import java.util.HashMap; 18 import java.util.Map; 19 import java.util.Map.Entry; 20 import java.util.Set; 21 22 import org.eclipse.core.runtime.ListenerList; 23 import org.eclipse.core.runtime.SafeRunner; 24 import org.eclipse.jface.util.IPropertyChangeListener; 25 import org.eclipse.jface.util.PropertyChangeEvent; 26 import org.eclipse.jface.util.SafeRunnable; 27 import org.eclipse.ui.IElementFactory; 28 import org.eclipse.ui.IMemento; 29 import org.eclipse.ui.IPersistableElement; 30 import org.eclipse.ui.IWorkbenchPart; 31 import org.eclipse.ui.IWorkbenchWindow; 32 import org.eclipse.ui.PlatformUI; 33 34 /** 35 * Presentation context. 36 * <p> 37 * Clients may instantiate and subclass this class. 38 * </p> 39 * @since 3.2 40 */ 41 public class PresentationContext implements IPresentationContext { 42 43 private static final String PRESENTATION_CONTEXT_PROPERTIES = "PRESENTATION_CONTEXT_PROPERTIES"; //$NON-NLS-1$ 44 private static final String BOOLEAN = "BOOLEAN"; //$NON-NLS-1$ 45 private static final String STRING = "STRING"; //$NON-NLS-1$ 46 private static final String INTEGER = "INTEGER"; //$NON-NLS-1$ 47 private static final String PERSISTABLE = "PERSISTABLE"; //$NON-NLS-1$ 48 49 final private String fId; 50 final private ListenerList<IPropertyChangeListener> fListeners = new ListenerList<>(); 51 final private Map<String, Object> fProperties = new HashMap<>(); 52 private IWorkbenchWindow fWindow; 53 private IWorkbenchPart fPart; 54 55 /** 56 * Constructs a presentation context for the given id. 57 * 58 * @param id presentation context id 59 */ PresentationContext(String id)60 public PresentationContext(String id) { 61 this (id, null, null); 62 } 63 64 /** 65 * Constructs a presentation context for the given id and window. 66 * 67 * @param id presentation context id 68 * @param window presentation context window, may be <code>null</code> 69 */ PresentationContext(String id, IWorkbenchWindow window)70 public PresentationContext(String id, IWorkbenchWindow window) { 71 this (id, window, null); 72 } 73 74 /** 75 * Constructs a presentation context for the given id and part. 76 * The presentation context window is derived from the part. 77 * 78 * @param id presentation context id 79 * @param part presentation context part, may be <code>null</code> 80 */ PresentationContext(String id, IWorkbenchPart part)81 public PresentationContext(String id, IWorkbenchPart part) { 82 this (id, part == null ? null : part.getSite().getWorkbenchWindow(), part); 83 } 84 85 /** 86 * Constructs a presentation context for the given id and part. 87 * The presentation context id and window are derived from the part. 88 * 89 * @param part presentation context part, can NOT be <code>null</code> 90 */ PresentationContext(IWorkbenchPart part)91 public PresentationContext(IWorkbenchPart part) { 92 this (part.getSite().getId(), part.getSite().getWorkbenchWindow(), part); 93 } 94 PresentationContext(String id, IWorkbenchWindow window, IWorkbenchPart part)95 private PresentationContext(String id, IWorkbenchWindow window, IWorkbenchPart part) { 96 fId = id; 97 fWindow = window; 98 fPart = part; 99 } 100 101 @Override getColumns()102 public String[] getColumns() { 103 return (String[]) getProperty(IPresentationContext.PROPERTY_COLUMNS); 104 } 105 106 /** 107 * Fires a property change event to all registered listeners 108 * 109 * @param property property name 110 * @param oldValue old value or <code>null</code> 111 * @param newValue new value or <code>null</code> 112 */ firePropertyChange(String property, Object oldValue, Object newValue)113 protected void firePropertyChange(String property, Object oldValue, Object newValue) { 114 if (!fListeners.isEmpty()) { 115 final PropertyChangeEvent event = new PropertyChangeEvent(this, property, oldValue, newValue); 116 for (IPropertyChangeListener iPropertyChangeListener : fListeners) { 117 final IPropertyChangeListener listener = iPropertyChangeListener; 118 SafeRunner.run(new SafeRunnable() { 119 @Override 120 public void run() throws Exception { 121 listener.propertyChange(event); 122 } 123 }); 124 } 125 } 126 } 127 128 /** 129 * Sets the visible column ids. 130 * 131 * @param ids column identifiers 132 */ setColumns(String[] ids)133 public void setColumns(String[] ids) { 134 setProperty(IPresentationContext.PROPERTY_COLUMNS, ids); 135 } 136 137 @Override dispose()138 public void dispose() { 139 fProperties.clear(); 140 setProperty(PROPERTY_DISPOSED, Boolean.TRUE); 141 fListeners.clear(); 142 // Free the reference to fWindow (Bug 321658). 143 fWindow = null; 144 fPart = null; 145 } 146 147 @Override addPropertyChangeListener(IPropertyChangeListener listener)148 public void addPropertyChangeListener(IPropertyChangeListener listener) { 149 fListeners.add(listener); 150 } 151 152 @Override removePropertyChangeListener(IPropertyChangeListener listener)153 public void removePropertyChangeListener(IPropertyChangeListener listener) { 154 fListeners.remove(listener); 155 } 156 157 @Override getId()158 public String getId() { 159 return fId; 160 } 161 162 @Override getProperty(String property)163 public Object getProperty(String property) { 164 synchronized (fProperties) { 165 return fProperties.get(property); 166 } 167 } 168 169 @Override setProperty(String property, Object value)170 public void setProperty(String property, Object value) { 171 Object oldValue = null; 172 boolean propertySet = false; 173 synchronized (fProperties) { 174 oldValue = fProperties.get(property); 175 if (!isEqual(oldValue, value)) { 176 propertySet = true; 177 fProperties.put(property, value); 178 } 179 } 180 181 if (propertySet) { 182 firePropertyChange(property, oldValue, value); 183 } 184 } 185 186 /** 187 * Restores the presentation context properties from the given memento. 188 * @param memento Memento to restore from. 189 */ initProperties(IMemento memento)190 public void initProperties(IMemento memento) { 191 IMemento presentationMemento = null; 192 193 for (IMemento childMemento : memento.getChildren(PRESENTATION_CONTEXT_PROPERTIES)) { 194 if (getId().equals(childMemento.getID())) { 195 presentationMemento = childMemento; 196 break; 197 } 198 } 199 200 if (presentationMemento != null) { 201 for (IMemento stringProperty : presentationMemento.getChildren(STRING)) { 202 fProperties.put(stringProperty.getID(), stringProperty.getString(STRING)); 203 } 204 205 for (IMemento integerMemento : presentationMemento.getChildren(INTEGER)) { 206 fProperties.put(integerMemento.getID(), integerMemento.getInteger(INTEGER)); 207 } 208 209 for (IMemento booleanMemento : presentationMemento.getChildren(BOOLEAN)) { 210 fProperties.put(booleanMemento.getID(), booleanMemento.getBoolean(BOOLEAN)); 211 } 212 213 for (IMemento persistableMemento : presentationMemento.getChildren(PERSISTABLE)) { 214 String factoryID = persistableMemento.getString(PERSISTABLE); 215 if (factoryID != null) { 216 IElementFactory factory = PlatformUI.getWorkbench().getElementFactory(factoryID); 217 if (factory != null) { 218 Object element = factory.createElement(persistableMemento); 219 if (element != null) { 220 fProperties.put(persistableMemento.getID(), element); 221 } 222 } 223 } 224 } 225 } 226 } 227 228 /** 229 * Saves the current presentation context properties to the given memento. 230 * @param memento Memento to save to. 231 */ saveProperites(IMemento memento)232 public void saveProperites(IMemento memento) { 233 if (fProperties.isEmpty()) { 234 return; 235 } 236 IMemento properties = memento.createChild(PRESENTATION_CONTEXT_PROPERTIES, getId()); 237 for (Entry<String, Object> entry : fProperties.entrySet()) { 238 if (entry.getValue() instanceof String) { 239 IMemento value = properties.createChild(STRING, entry.getKey()); 240 value.putString(STRING, (String)entry.getValue()); 241 } else if (entry.getValue() instanceof Integer) { 242 IMemento value = properties.createChild(INTEGER, entry.getKey()); 243 value.putInteger(INTEGER, ((Integer)entry.getValue()).intValue()); 244 } else if (entry.getValue() instanceof Boolean) { 245 IMemento value = properties.createChild(BOOLEAN, entry.getKey()); 246 value.putBoolean(BOOLEAN, ((Boolean)entry.getValue()).booleanValue()); 247 } else if (entry.getValue() instanceof IPersistableElement) { 248 IPersistableElement persistable = (IPersistableElement)entry.getValue(); 249 IMemento value = properties.createChild(PERSISTABLE, entry.getKey()); 250 value.putString(PERSISTABLE, persistable.getFactoryId()); 251 persistable.saveState(value); 252 } 253 } 254 } 255 isEqual(Object a, Object b)256 private boolean isEqual(Object a, Object b) { 257 if (a == null) { 258 return b == null; 259 } 260 return a.equals(b); 261 } 262 263 @Override getProperties()264 public String[] getProperties() { 265 synchronized (fProperties) { 266 Set<String> keys = fProperties.keySet(); 267 return keys.toArray(new String[keys.size()]); 268 } 269 } 270 271 @Override getPart()272 public IWorkbenchPart getPart() { 273 return fPart; 274 } 275 276 @Override getWindow()277 public IWorkbenchWindow getWindow() { 278 return fWindow; 279 } 280 281 282 } 283