1 12 13 package org.eclipse.ui.views.properties; 14 15 import java.util.ArrayList ; 16 import java.util.Arrays ; 17 import java.util.HashMap ; 18 import java.util.List ; 19 import java.util.Map ; 20 21 import org.eclipse.core.commands.common.EventManager; 22 import org.eclipse.jface.viewers.CellEditor; 23 import org.eclipse.jface.viewers.ICellEditorListener; 24 import org.eclipse.jface.viewers.ILabelProvider; 25 import org.eclipse.swt.graphics.Image; 26 import org.eclipse.swt.widgets.Composite; 27 import org.eclipse.ui.internal.views.ViewsPlugin; 28 29 48 public class PropertySheetEntry extends EventManager implements 49 IPropertySheetEntry { 50 51 56 private Object [] values = new Object [0]; 57 58 61 private Map sources = new HashMap (0); 62 63 68 private Object editValue; 69 70 private PropertySheetEntry parent; 71 72 private IPropertySourceProvider propertySourceProvider; 73 74 private IPropertyDescriptor descriptor; 75 76 private CellEditor editor; 77 78 private String errorText; 79 80 private PropertySheetEntry[] childEntries = null; 81 82 86 private ICellEditorListener cellEditorListener = new ICellEditorListener() { 87 public void editorValueChanged(boolean oldValidState, 88 boolean newValidState) { 89 if (!newValidState) { 90 setErrorText(editor.getErrorMessage()); 92 } else { 93 setErrorText(null); 95 } 96 } 97 98 public void cancelEditor() { 99 setErrorText(null); 100 } 101 102 public void applyEditorValue() { 103 PropertySheetEntry.this.applyEditorValue(); 104 } 105 }; 106 107 110 public void addPropertySheetEntryListener( 111 IPropertySheetEntryListener listener) { 112 addListenerObject(listener); 113 } 114 115 118 public void applyEditorValue() { 119 if (editor == null) { 120 return; 121 } 122 123 if (!editor.isValueValid()) { 125 setErrorText(editor.getErrorMessage()); 126 return; 127 } 128 129 setErrorText(null); 130 131 Object newValue = editor.getValue(); 133 boolean changed = false; 134 if (values.length > 1) { 135 changed = true; 136 } else if (editValue == null) { 137 if (newValue != null) { 138 changed = true; 139 } 140 } else if (!editValue.equals(newValue)) { 141 changed = true; 142 } 143 144 if (changed) { 146 setValue(newValue); 147 } 148 } 149 150 156 private List computeMergedPropertyDescriptors() { 157 if (values.length == 0) { 158 return new ArrayList (0); 159 } 160 161 IPropertySource firstSource = getPropertySource(values[0]); 162 if (firstSource == null) { 163 return new ArrayList (0); 164 } 165 166 if (values.length == 1) { 167 return Arrays.asList(firstSource.getPropertyDescriptors()); 168 } 169 170 Map [] propertyDescriptorMaps = new Map [values.length]; 172 for (int i = 0; i < values.length; i++) { 173 Object object = values[i]; 174 IPropertySource source = getPropertySource(object); 175 if (source == null) { 176 return new ArrayList (0); 179 } 180 propertyDescriptorMaps[i] = computePropertyDescriptorsFor(source); 182 } 183 184 Map intersection = propertyDescriptorMaps[0]; 186 for (int i = 1; i < propertyDescriptorMaps.length; i++) { 187 Object [] ids = intersection.keySet().toArray(); 189 for (int j = 0; j < ids.length; j++) { 190 Object object = propertyDescriptorMaps[i].get(ids[j]); 191 if (object == null || 192 !((IPropertyDescriptor) intersection.get(ids[j])) 195 .isCompatibleWith((IPropertyDescriptor) object)) { 196 intersection.remove(ids[j]); 197 } 198 } 199 } 200 201 ArrayList result = new ArrayList (intersection.size()); 204 IPropertyDescriptor[] firstDescs = firstSource.getPropertyDescriptors(); 205 for (int i = 0; i < firstDescs.length; i++) { 206 IPropertyDescriptor desc = firstDescs[i]; 207 if (intersection.containsKey(desc.getId())) { 208 result.add(desc); 209 } 210 } 211 return result; 212 } 213 214 222 private Map computePropertyDescriptorsFor(IPropertySource source) { 223 IPropertyDescriptor[] descriptors = source.getPropertyDescriptors(); 224 Map result = new HashMap (descriptors.length * 2 + 1); 225 for (int i = 0; i < descriptors.length; i++) { 226 result.put(descriptors[i].getId(), descriptors[i]); 227 } 228 return result; 229 } 230 231 234 private void createChildEntries() { 235 List descriptors = computeMergedPropertyDescriptors(); 237 238 PropertySheetEntry[] newEntries = new PropertySheetEntry[descriptors 240 .size()]; 241 for (int i = 0; i < descriptors.size(); i++) { 242 IPropertyDescriptor d = (IPropertyDescriptor) descriptors.get(i); 243 PropertySheetEntry entry = createChildEntry(); 245 entry.setDescriptor(d); 246 entry.setParent(this); 247 entry.setPropertySourceProvider(propertySourceProvider); 248 entry.refreshValues(); 249 newEntries[i] = entry; 250 } 251 childEntries = newEntries; 253 } 254 255 266 protected PropertySheetEntry createChildEntry() { 267 return new PropertySheetEntry(); 268 } 269 270 273 public void dispose() { 274 if (editor != null) { 275 editor.dispose(); 276 editor = null; 277 } 278 PropertySheetEntry[] entriesToDispose = childEntries; 280 childEntries = null; 281 if (entriesToDispose != null) { 282 for (int i = 0; i < entriesToDispose.length; i++) { 283 if (entriesToDispose[i] != null) { 287 entriesToDispose[i].dispose(); 288 } 289 } 290 } 291 } 292 293 297 private void fireChildEntriesChanged() { 298 Object [] array = getListeners(); 299 for (int i = 0; i < array.length; i++) { 300 IPropertySheetEntryListener listener = (IPropertySheetEntryListener) array[i]; 301 listener.childEntriesChanged(this); 302 } 303 } 304 305 309 private void fireErrorMessageChanged() { 310 Object [] array = getListeners(); 311 for (int i = 0; i < array.length; i++) { 312 IPropertySheetEntryListener listener = (IPropertySheetEntryListener) array[i]; 313 listener.errorMessageChanged(this); 314 } 315 } 316 317 321 private void fireValueChanged() { 322 Object [] array = getListeners(); 323 for (int i = 0; i < array.length; i++) { 324 IPropertySheetEntryListener listener = (IPropertySheetEntryListener) array[i]; 325 listener.valueChanged(this); 326 } 327 } 328 329 332 public String getCategory() { 333 return descriptor.getCategory(); 334 } 335 336 339 public IPropertySheetEntry[] getChildEntries() { 340 if (childEntries == null) { 341 createChildEntries(); 342 } 343 return childEntries; 344 } 345 346 349 public String getDescription() { 350 return descriptor.getDescription(); 351 } 352 353 359 protected IPropertyDescriptor getDescriptor() { 360 return descriptor; 361 } 362 363 366 public String getDisplayName() { 367 return descriptor.getDisplayName(); 368 } 369 370 375 public CellEditor getEditor(Composite parent) { 376 377 if (editor == null) { 378 editor = descriptor.createPropertyEditor(parent); 379 if (editor != null) { 380 editor.addListener(cellEditorListener); 381 } 382 } 383 if (editor != null) { 384 editor.setValue(editValue); 385 setErrorText(editor.getErrorMessage()); 386 } 387 return editor; 388 } 389 390 397 protected Object getEditValue(int index) { 398 Object value = values[index]; 399 IPropertySource source = getPropertySource(value); 400 if (source != null) { 401 value = source.getEditableValue(); 402 } 403 return value; 404 } 405 406 409 public String getErrorText() { 410 return errorText; 411 } 412 413 416 public String getFilters()[] { 417 return descriptor.getFilterFlags(); 418 } 419 420 423 public Object getHelpContextIds() { 424 return descriptor.getHelpContextIds(); 425 } 426 427 430 public Image getImage() { 431 ILabelProvider provider = descriptor.getLabelProvider(); 432 if (provider == null) { 433 return null; 434 } 435 return provider.getImage(editValue); 436 } 437 438 444 protected PropertySheetEntry getParent() { 445 return parent; 446 } 447 448 457 protected IPropertySource getPropertySource(Object object) { 458 if (sources.containsKey(object)) 459 return (IPropertySource) sources.get(object); 460 461 IPropertySource result = null; 462 IPropertySourceProvider provider = propertySourceProvider; 463 464 if (provider == null && object != null) { 465 provider = (IPropertySourceProvider) ViewsPlugin.getAdapter(object, 466 IPropertySourceProvider.class, false); 467 } 468 469 if (provider != null) { 470 result = provider.getPropertySource(object); 471 } else { 472 result = (IPropertySource)ViewsPlugin.getAdapter(object, IPropertySource.class, false); 473 } 474 475 sources.put(object, result); 476 return result; 477 } 478 479 482 public String getValueAsString() { 483 if (editValue == null) { 484 return ""; } 486 ILabelProvider provider = descriptor.getLabelProvider(); 487 if (provider == null) { 488 return editValue.toString(); 489 } 490 String text = provider.getText(editValue); 491 if (text == null) { 492 return ""; } 494 return text; 495 } 496 497 503 public Object [] getValues() { 504 return values; 505 } 506 507 510 public boolean hasChildEntries() { 511 if (childEntries != null && childEntries.length > 0) { 512 return true; 513 } 514 return computeMergedPropertyDescriptors().size() > 0; 516 } 517 518 523 private void refreshChildEntries() { 524 if (childEntries == null) { 525 return; 527 } 528 529 List descriptors = computeMergedPropertyDescriptors(); 531 532 Map entryCache = new HashMap (childEntries.length * 2 + 1); 534 for (int i = 0; i < childEntries.length; i++) { 535 PropertySheetEntry childEntry = childEntries[i]; 536 if (childEntry != null) { 537 entryCache.put(childEntry.getDescriptor().getId(), childEntry); 538 } 539 } 540 541 List entriesToDispose = new ArrayList (Arrays.asList(childEntries)); 543 544 this.childEntries = null; 546 547 PropertySheetEntry[] newEntries = new PropertySheetEntry[descriptors 549 .size()]; 550 boolean entriesChanged = descriptors.size() != entryCache.size(); 551 for (int i = 0; i < descriptors.size(); i++) { 552 IPropertyDescriptor d = (IPropertyDescriptor) descriptors.get(i); 553 PropertySheetEntry entry = (PropertySheetEntry) entryCache.get(d 555 .getId()); 556 if (entry != null) { 557 entry.setDescriptor(d); 559 entriesToDispose.remove(entry); 560 } else { 561 entry = createChildEntry(); 563 entry.setDescriptor(d); 564 entry.setParent(this); 565 entry.setPropertySourceProvider(propertySourceProvider); 566 entriesChanged = true; 567 } 568 entry.refreshValues(); 569 newEntries[i] = entry; 570 } 571 572 this.childEntries = newEntries; 574 575 if (entriesChanged) { 576 fireChildEntriesChanged(); 577 } 578 579 for (int i = 0; i < entriesToDispose.size(); i++) { 581 ((IPropertySheetEntry) entriesToDispose.get(i)).dispose(); 582 } 583 } 584 585 590 protected void refreshFromRoot() { 591 if (parent == null) { 592 refreshChildEntries(); 593 } else { 594 parent.refreshFromRoot(); 595 } 596 } 597 598 602 private void refreshValues() { 603 Object [] currentSources = parent.getValues(); 605 606 Object [] newValues = new Object [currentSources.length]; 608 for (int i = 0; i < currentSources.length; i++) { 609 IPropertySource source = parent 610 .getPropertySource(currentSources[i]); 611 newValues[i] = source.getPropertyValue(descriptor.getId()); 612 } 613 614 setValues(newValues); 616 } 617 618 621 public void removePropertySheetEntryListener( 622 IPropertySheetEntryListener listener) { 623 removeListenerObject(listener); 624 } 625 626 629 public void resetPropertyValue() { 630 if (parent == null) { 631 return; 633 } 634 635 boolean change = false; 637 Object [] objects = parent.getValues(); 638 for (int i = 0; i < objects.length; i++) { 639 IPropertySource source = getPropertySource(objects[i]); 640 if (source.isPropertySet(descriptor.getId())) { 641 if (source instanceof IPropertySource2) { 643 IPropertySource2 extendedSource = (IPropertySource2) source; 644 if (!extendedSource 646 .isPropertyResettable(descriptor.getId())) { 647 continue; 648 } 649 } 650 source.resetPropertyValue(descriptor.getId()); 651 change = true; 652 } 653 } 654 if (change) { 655 refreshFromRoot(); 656 } 657 } 658 659 664 private void setDescriptor(IPropertyDescriptor newDescriptor) { 665 if (descriptor != newDescriptor && editor != null) { 668 editor.dispose(); 669 editor = null; 670 } 671 descriptor = newDescriptor; 672 } 673 674 678 private void setErrorText(String newErrorText) { 679 errorText = newErrorText; 680 fireErrorMessageChanged(); 682 } 683 684 689 private void setParent(PropertySheetEntry propertySheetEntry) { 690 parent = propertySheetEntry; 691 } 692 693 701 public void setPropertySourceProvider(IPropertySourceProvider provider) { 702 propertySourceProvider = provider; 703 } 704 705 716 private void setValue(Object newValue) { 717 for (int i = 0; i < values.length; i++) { 719 values[i] = newValue; 720 } 721 722 parent.valueChanged(this); 724 725 refreshFromRoot(); 727 } 728 729 741 public void setValues(Object [] objects) { 742 values = objects; 743 sources = new HashMap (values.length * 2 + 1); 744 745 if (values.length == 0) { 746 editValue = null; 747 } else { 748 Object newValue = values[0]; 750 751 IPropertySource source = getPropertySource(newValue); 753 if (source != null) { 754 newValue = source.getEditableValue(); 755 } 756 editValue = newValue; 757 } 758 759 refreshChildEntries(); 761 762 fireValueChanged(); 764 } 765 766 779 protected void valueChanged(PropertySheetEntry child) { 780 for (int i = 0; i < values.length; i++) { 781 IPropertySource source = getPropertySource(values[i]); 782 source.setPropertyValue(child.getDescriptor().getId(), child 783 .getEditValue(i)); 784 } 785 786 if (parent != null) { 788 parent.valueChanged(this); 789 } 790 } 791 } 792 | Popular Tags |