1// BEGIN LICENSE BLOCK 2// Version: CMPL 1.1 3// 4// The contents of this file are subject to the Cisco-style Mozilla Public 5// License Version 1.1 (the "License"); you may not use this file except 6// in compliance with the License. You may obtain a copy of the License 7// at www.eclipse-clp.org/license. 8// 9// Software distributed under the License is distributed on an "AS IS" 10// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11// the License for the specific language governing rights and limitations 12// under the License. 13// 14// The Original Code is The ECLiPSe Constraint Logic Programming System. 15// The Initial Developer of the Original Code is Cisco Systems, Inc. 16// Portions created by the Initial Developer are 17// Copyright (C) 2006 Cisco Systems, Inc. All Rights Reserved. 18// 19// Contributor(s): 20// 21// END LICENSE BLOCK 22 23package com.parctechnologies.eclipse.visualisation; 24 25import com.parctechnologies.eclipse.*; 26 27import java.awt.Rectangle; 28import java.awt.Shape; 29import java.awt.geom.*; 30import java.awt.Color; 31import java.awt.Component; 32import java.util.*; 33import java.awt.event.ActionEvent; 34import javax.swing.*; 35import javax.swing.table.*; 36import att.grappa.*; 37 38 39/** 40 * Meta-viewlet type used to treat many other viewlet types as one. 41 * 42 * <p> The multi-viewlet data holds both the original ViewletData and 43 * the original ViewletTye. 44 * */ 45public class MultiViewletType implements ViewletType, ViewletFactory { 46 private SymRef symRef; 47 48 private TableCellRenderer tableCellRenderer; 49 50 /** The actual types which this meta-type wraps */ 51 private Collection viewletTypeCollection; 52 53 public MultiViewletType(Collection viewletTypeCollection) { 54 this.viewletTypeCollection = new LinkedList(); 55 for(Iterator it = viewletTypeCollection.iterator(); it.hasNext();) { 56 addViewletType((ViewletType)it.next()); 57 } 58 } 59 60 public void addViewletType(ViewletType viewletType) { 61 viewletTypeCollection.add(viewletType); 62 } 63 64 public Collection getViewletTypeCollection() { 65 return viewletTypeCollection; 66 } 67 68 /* ViewletFactory methods */ 69 public boolean canBuildFrom(ElementType elementType) 70 { 71 return(true); 72 } 73 74 public ViewletData build() 75 { 76 // by default build the first type in the list 77 ViewletType type = (ViewletType)viewletTypeCollection.iterator().next(); 78 ViewletData subData = ((ViewletFactory)type).build(); 79 return new Data(type, subData); 80 } 81 82 public String getDescription() 83 { 84 return("Multi viewlet"); 85 } 86 87 public void setSymRef(SymRef symRef) 88 { 89 this.symRef = symRef; 90 for(Iterator it = viewletTypeCollection.iterator(); it.hasNext();) { 91 ViewletType viewletType = (ViewletType) it.next(); 92 viewletType.setSymRef(new SymRef(viewletType, 93 this.getSymRef(), 94 viewletType.getClass().getName())); 95 } 96 97 } 98 public SymRef getSymRef() 99 { 100 return(symRef); 101 } 102 103 104 105 /* ViewletType methods */ 106 public synchronized TableCellRenderer getTableCellRenderer() { 107 if (tableCellRenderer == null) { 108 tableCellRenderer = new CellRenderer(); 109 } 110 return tableCellRenderer; 111 } 112 113 synchronized Class getCustomRendererClass() { 114// if (customRenderer == null) { 115// customRenderer = new CustRenderer(); 116// } 117// return customRenderer; 118 return com.parctechnologies.eclipse.visualisation.viewers.CustRenderer.class; 119 } 120 121 public void customizeElement(ViewletDataStore store, 122 java.util.List index, 123 Element element) { 124 Data data = (Data)(store.getViewletDataAt(index)); 125 if (DebuggingSupport.logMessages) { 126 DebuggingSupport.logMessage(this,"MultiViewletType customizeElement called with data="+data+" element="+element); 127 } 128 ViewletData realData = data.getViewletData(); 129 ViewletType realType = data.getViewletType(); 130 if (DebuggingSupport.logMessages) { 131 DebuggingSupport.logMessage(this,"MultiViewletType customizeElement called with data="+data+" element="+element); 132 DebuggingSupport.logMessage(this,"MultiViewletType customizeElement called with realData="+realData+" realType="+realType); 133 } 134 // pass the customization on to the actual type of this element 135 MultiViewletDataStore multiStore=(MultiViewletDataStore)store; 136 data.getViewletType().customizeElement(multiStore.getViewletDataStore(data.getViewletType()), index, element); 137 } 138 139 private Map rangeToTypeRangeMap(ViewletDataStore store, 140 ViewletRange range) { 141 Iterator indexListIterator = range.iterator(); 142 java.util.List currentIndex; 143 Map typeRangeMap = new HashMap(); 144 while(indexListIterator.hasNext()) { 145 currentIndex = (java.util.List) indexListIterator.next(); 146 Data data = (Data) store.getViewletDataAt(currentIndex); 147 ViewletType type = data.getViewletType(); 148 ViewletRange typeRange = (ViewletRange) typeRangeMap.get(type); 149 if (typeRange == null) { 150 typeRange = new ViewletRangeCollection(); 151 typeRangeMap.put(type, typeRange); 152 } 153 typeRange.add(currentIndex); 154 } 155 if (DebuggingSupport.logMessages) { 156 DebuggingSupport.logMessage(this, 157 "Range="+range+ 158 "Range to type map="+typeRangeMap); 159 } 160 return typeRangeMap; 161 } 162 163 164 public BatchGoal collectPreBuildGoal(Viewer viewer, 165 ViewletDataStore store, 166 ViewletRange range) 167 { 168 BatchGoal result = new BatchGoal(); 169 Map typeRangeMap = rangeToTypeRangeMap(store, range); 170 // now collect together all the type specific batch goals 171 for(Iterator it = viewletTypeCollection.iterator(); it.hasNext(); ) { 172 ViewletType type = (ViewletType) it.next(); 173 ViewletRange typeRange = (ViewletRange) typeRangeMap.get(type); 174 ViewletDataStore typeStore = ((MultiViewletDataStore)store).getViewletDataStore(type); 175 if (typeRange == null) { 176 typeRange = new ViewletRangeCollection(); 177 } 178 result.add(type.collectPreBuildGoal(viewer, typeStore, typeRange)); 179 } 180 return result; 181 } 182 183 public void startBuild(Viewer viewer, 184 ViewletDataStore store, 185 ViewletRange range, 186 List results) { 187 Map typeRangeMap = rangeToTypeRangeMap(store, range); 188 Iterator resultIt = results.iterator(); 189 // now collect together all the type specific batch goals 190 for(Iterator it = viewletTypeCollection.iterator(); it.hasNext(); ) { 191 ViewletType type = (ViewletType) it.next(); 192 ViewletRange typeRange = (ViewletRange) typeRangeMap.get(type); 193 ViewletDataStore typeStore = ((MultiViewletDataStore)store).getViewletDataStore(type); 194 List typeResult = (List) resultIt.next(); 195 if (typeRange == null) { 196 typeRange = new ViewletRangeCollection(); 197 } 198 type.startBuild(viewer, typeStore, typeRange, typeResult); 199 } 200 } 201 202 203 public void stopBuild() 204 {} 205 206 public BatchGoal collectPreUpdateGoal(Viewer viewer, 207 ViewletDataStore store, 208 ViewletRange range, 209 UpdateEvent updateEvent) 210 { 211 BatchGoal result = new BatchGoal(); 212 Map typeRangeMap = rangeToTypeRangeMap(store, range); 213 // now collect together all the type specific batch goals 214 for(Iterator it = viewletTypeCollection.iterator(); it.hasNext(); ) { 215 ViewletType type = (ViewletType) it.next(); 216 ViewletRange typeRange = (ViewletRange) typeRangeMap.get(type); 217 ViewletDataStore typeStore = ((MultiViewletDataStore)store).getViewletDataStore(type); 218 if (typeRange == null) { 219 typeRange = new ViewletRangeCollection(); 220 } 221 result.add(type.collectPreUpdateGoal(viewer, typeStore, typeRange, updateEvent)); 222 } 223 if (DebuggingSupport.logMessages) { 224 DebuggingSupport.logMessage(this,"Pre-update goals="+result); 225 } 226 return result; 227 } 228 229 public void startUpdate(Viewer viewer, 230 ViewletDataStore store, 231 ViewletRange range, 232 List results, 233 UpdateEvent updateEvent) 234 { 235 if (DebuggingSupport.logMessages) { 236 DebuggingSupport.logMessage(this,"start-update results="+results); 237 } 238 Map typeRangeMap = rangeToTypeRangeMap(store, range); 239 Iterator resultIt = results.iterator(); 240 // now collect together all the type specific batch goals 241 for(Iterator it = viewletTypeCollection.iterator(); it.hasNext(); ) { 242 ViewletType type = (ViewletType) it.next(); 243 ViewletRange typeRange = (ViewletRange) typeRangeMap.get(type); 244 ViewletDataStore typeStore = ((MultiViewletDataStore)store).getViewletDataStore(type); 245 List typeResult = (List) resultIt.next(); 246 if (typeRange == null) { 247 typeRange = new ViewletRangeCollection(); 248 } 249 type.startUpdate(viewer, typeStore, typeRange, typeResult, updateEvent); 250 } 251 } 252 253 public void stopUpdate(Viewer viewer, 254 ViewletDataStore store, 255 ViewletRange range) 256 { 257 // unsure why this is parameterised. 258 //setUpdating("no"); 259 //setUpdating(viewer, range, Data.UPDATING_NOT); 260 } 261 262 263 264 265 266 /* 267 * Data is a viewlet which can monitor elements of any type. It is 268 * responsible for: 269 * <ul> 270 * <li> Maintaining a record of the text representation of the term. 271 * </ul> 272 */ 273 public static class Data extends ViewletDataImpl 274 { 275 private ViewletType viewletType; 276 private ViewletData viewletData; 277 278 public Data(ViewletType viewletType, ViewletData viewletData) 279 { 280 super(); 281 this.viewletType = viewletType; 282 this.viewletData = viewletData; 283 } 284 285 public void setViewletData(ViewletData viewletData) { 286 this.viewletData = viewletData; 287 } 288 289 public ViewletData getViewletData() { 290 return viewletData; 291 } 292 293 public void setViewletType(ViewletType viewletType) { 294 this.viewletType = viewletType; 295 } 296 297 public ViewletType getViewletType() { 298 return viewletType; 299 } 300 301 public boolean getHoldsOnUpdates() { 302 return viewletData.getHoldsOnUpdates(); 303 } 304 305 public void setHoldsOnUpdates(boolean newValue) { 306 viewletData.setHoldsOnUpdates(newValue); 307 } 308 309 public String toString() { 310 return viewletData.toString(); 311 } 312 } 313 314 315 /** 316 * Return a collection of actions which can be applied to viewlets 317 * in this table 318 */ 319 public Collection getActions(ViewletDataStore store, 320 ViewletRange range) { 321 Collection ll = new LinkedList(); 322 //ll.add(new ChangeTypeAction(viewletTypeCollection, store, range)); 323 for(Iterator it = viewletTypeCollection.iterator(); it.hasNext();) { 324 ViewletType type = (ViewletType) it.next(); 325 ViewletDataStore typeStore = 326 ((MultiViewletDataStore)store).getViewletDataStore(type); 327 // filter the range to only those indices which are applicable to 328 ViewletRange typeRange = typeStore.createRange(range); 329 ll.addAll(type.getActions(typeStore, typeRange )); 330 } 331 // now combine any duplicated actions in the list by combining 332 // them into a single MultiAction 333 Map nameMultiActionMap = new TreeMap(); 334 for(Iterator it = ll.iterator(); it.hasNext(); ) { 335 Action action = (Action)it.next(); 336 String name = (String)action.getValue(Action.NAME); 337 MultiAction multiAction = (MultiAction)nameMultiActionMap.get(name); 338 if (multiAction == null) { 339 multiAction = 340 new MultiAction(name, 341 (Icon)action.getValue(Action.SMALL_ICON)); 342 nameMultiActionMap.put(name, multiAction); 343 } 344 multiAction.actions.add(action); 345 } 346 return nameMultiActionMap.values(); 347 } 348 349 protected class MultiAction extends AbstractAction { 350 /** Holds the type specific sub-actions */ 351 Collection actions; 352 353 public MultiAction(String name, Icon icon) { 354 super(name); 355 putValue(Action.SMALL_ICON, icon); 356 actions = new LinkedList(); 357 } 358 359 /** 360 * Perform all the sub-actions contained within 361 */ 362 public void actionPerformed(ActionEvent event) { 363 for(Iterator it = actions.iterator(); it.hasNext(); ) { 364 Action action = (Action)it.next(); 365 action.actionPerformed(event); 366 } 367 } 368 } 369 370 protected class ChangeTypeAction extends ViewletAction { 371 protected ViewletDataStore viewletDataStore; 372 protected ViewletRange viewletRange; 373 protected Collection viewletTypeCollection; 374 375 public ChangeTypeAction(Collection viewletTypeCollection, 376 ViewletDataStore store, 377 ViewletRange range) { 378 super("Change type"); 379 putValue(Action.NAME, "Change type"); 380 putValue(Action.LONG_DESCRIPTION, 381 "Change the type of viewlet at this location"); 382 putValue(Action.SHORT_DESCRIPTION, 383 "Change type of viewlet"); 384 //putValue(Action.SMALL_ICON, new FadeIcon(20, 20)); 385 this.viewletTypeCollection = viewletTypeCollection; 386 this.viewletRange = range; 387 this.viewletDataStore = store; 388 // temporariy disable 389 setEnabled(false); 390 } 391 392 public void actionPerformed() { 393 // do nothing for now 394 } 395 } 396 397 /** 398 * The default text cell render 399 */ 400 private class CellRenderer extends DefaultTableCellRenderer { 401 402 public CellRenderer() { 403 super(); 404 } 405 406 public Component getTableCellRendererComponent(JTable table, 407 Object value, 408 boolean isSelected, 409 boolean hasFocus, 410 int row, 411 int column) { 412 // pass the request up to the correct viewlet type 413 Data data = (Data)value; 414 return 415 data.getViewletType().getTableCellRenderer(). 416 getTableCellRendererComponent(table, 417 data.getViewletData(), 418 isSelected, 419 hasFocus, 420 row, 421 column); 422 } 423 } 424 425} 426 427