< prev index next >

application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/JfrPropertySheet.java

Print this page




  19  * the distribution.
  20  * 
  21  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
  22  * endorse or promote products derived from this software without specific prior written permission.
  23  * 
  24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  26  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  31  * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 package org.openjdk.jmc.flightrecorder.ui;
  34 
  35 import java.text.MessageFormat;
  36 import java.util.ArrayList;
  37 import java.util.Arrays;
  38 import java.util.Collection;

  39 import java.util.Comparator;
  40 import java.util.HashSet;
  41 import java.util.Iterator;
  42 import java.util.LinkedList;
  43 import java.util.List;
  44 import java.util.Objects;
  45 import java.util.Set;
  46 import java.util.concurrent.CompletableFuture;
  47 import java.util.function.Consumer;
  48 import java.util.function.Function;
  49 import java.util.function.Predicate;
  50 import java.util.logging.Level;
  51 import java.util.stream.Collectors;
  52 import java.util.stream.Stream;
  53 


  54 import org.eclipse.jface.viewers.ArrayContentProvider;
  55 import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
  56 import org.eclipse.jface.viewers.ISelection;
  57 import org.eclipse.jface.viewers.IStructuredSelection;
  58 import org.eclipse.jface.viewers.TableViewer;
  59 import org.eclipse.osgi.util.NLS;
  60 import org.eclipse.swt.SWT;
  61 import org.eclipse.swt.graphics.Image;
  62 import org.eclipse.swt.widgets.Composite;
  63 import org.eclipse.swt.widgets.Control;
  64 import org.eclipse.swt.widgets.Display;
  65 import org.eclipse.ui.IWorkbenchPart;
  66 import org.eclipse.ui.PlatformUI;
  67 import org.eclipse.ui.part.Page;
  68 import org.eclipse.ui.views.properties.IPropertySheetPage;
  69 import org.openjdk.jmc.common.IDescribable;
  70 import org.openjdk.jmc.common.IDisplayable;
  71 import org.openjdk.jmc.common.IState;
  72 import org.openjdk.jmc.common.collection.IteratorToolkit;
  73 import org.openjdk.jmc.common.item.Aggregators;
  74 import org.openjdk.jmc.common.item.IAttribute;
  75 import org.openjdk.jmc.common.item.IItem;
  76 import org.openjdk.jmc.common.item.IItemCollection;
  77 import org.openjdk.jmc.common.item.IItemFilter;
  78 import org.openjdk.jmc.common.item.IItemIterable;
  79 import org.openjdk.jmc.common.item.IMemberAccessor;
  80 import org.openjdk.jmc.common.item.IType;
  81 import org.openjdk.jmc.common.unit.ContentType;
  82 import org.openjdk.jmc.common.unit.IQuantity;
  83 import org.openjdk.jmc.common.unit.IRange;
  84 import org.openjdk.jmc.common.unit.KindOfQuantity;
  85 import org.openjdk.jmc.common.unit.QuantitiesToolkit;
  86 import org.openjdk.jmc.common.unit.QuantityRange;
  87 import org.openjdk.jmc.common.unit.RangeContentType;
  88 import org.openjdk.jmc.common.unit.UnitLookup;
  89 import org.openjdk.jmc.common.util.TypeHandling;
  90 import org.openjdk.jmc.flightrecorder.JfrAttributes;
  91 import org.openjdk.jmc.flightrecorder.ui.common.DataPageToolkit;

  92 import org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages;
  93 import org.openjdk.jmc.flightrecorder.ui.preferences.PreferenceKeys;
  94 import org.openjdk.jmc.flightrecorder.ui.selection.FlavoredSelectionBase;
  95 import org.openjdk.jmc.flightrecorder.ui.selection.IFilterFlavor;
  96 import org.openjdk.jmc.flightrecorder.ui.selection.IFlavoredSelection;
  97 import org.openjdk.jmc.flightrecorder.ui.selection.IItemStreamFlavor;
  98 import org.openjdk.jmc.flightrecorder.ui.selection.IPropertyFlavor;
  99 import org.openjdk.jmc.flightrecorder.ui.selection.ItemBackedSelection;
 100 import org.openjdk.jmc.ui.TypeAppearance;
 101 import org.openjdk.jmc.ui.UIPlugin;
 102 import org.openjdk.jmc.ui.accessibility.FocusTracker;
 103 import org.openjdk.jmc.ui.column.ColumnBuilder;
 104 import org.openjdk.jmc.ui.column.ColumnManager;
 105 import org.openjdk.jmc.ui.column.ColumnMenusFactory;
 106 import org.openjdk.jmc.ui.column.IColumn;
 107 import org.openjdk.jmc.ui.column.TableSettings;
 108 import org.openjdk.jmc.ui.column.TableSettings.ColumnSettings;
 109 import org.openjdk.jmc.ui.common.util.AdapterUtil;
 110 import org.openjdk.jmc.ui.handlers.ActionToolkit;
 111 import org.openjdk.jmc.ui.handlers.MCContextMenuManager;
 112 import org.openjdk.jmc.ui.misc.DisplayToolkit;
 113 import org.openjdk.jmc.ui.misc.TypedLabelProvider;
 114 
 115 // FIXME: fields - units - filters - icons etc. should be handled more properly
 116 public class JfrPropertySheet extends Page implements IPropertySheetPage {
 117 


 118         private static final String HELP_CONTEXT_ID = FlightRecorderUI.PLUGIN_ID + ".JfrPropertiesView"; //$NON-NLS-1$
 119         private static final Object TOO_MANY_VALUES = new Object();
 120         private static final PropertySheetRow CALCULATING = new PropertySheetRow(null, null);
 121 
 122         private static class PropertySheetRowSelection extends FlavoredSelectionBase {
 123 
 124                 private final PropertySheetRow row;
 125 
 126                 PropertySheetRowSelection(PropertySheetRow row) {
 127                         super(MessageFormat.format(Messages.JFR_PROPERTIES_PROPERTY_SELECTION, row.attribute.getName()));
 128                         this.row = row;
 129                 }
 130 
 131                 @Override
 132                 public Stream<IItemStreamFlavor> getFlavors(
 133                         IItemFilter dstFilter, IItemCollection items, List<IAttribute<?>> dstAttributes) {
 134                         /*
 135                          * FIXME: Is this the desired behavior? Discuss and change if necessary.
 136                          * 
 137                          * This most likely need more thought and discussion, but the implemented order of
 138                          * flavors is currently:
 139                          * 
 140                          * For chart selections:
 141                          * 


 281                                 @Override
 282                                 protected Image getImageTyped(PropertySheetRow p) {
 283                                         if (p.attribute != null) {
 284                                                 Image icon = TypeAppearance.getImage(p.attribute.getContentType().getIdentifier());
 285                                                 return icon == null ? UIPlugin.getDefault().getImage(UIPlugin.ICON_PROPERTY_OBJECT) : icon;
 286                                         }
 287                                         return null;
 288                                 };
 289                         }).build();
 290 
 291         private static final IColumn VALUE_COLUMN = new ColumnBuilder(Messages.JFR_PROPERTY_SHEET_VALUE, "value", //$NON-NLS-1$
 292                         new TypedLabelProvider<PropertySheetRow>(PropertySheetRow.class) {
 293                                 @Override
 294                                 protected String getTextTyped(PropertySheetRow p) {
 295                                         Object value = p.getValue();
 296                                         if (p == CALCULATING) {
 297                                                 return Messages.JFR_PROPERTIES_CALCULATING;
 298                                         } else if (value == TOO_MANY_VALUES) {
 299                                                 return Messages.JFR_PROPERTIES_TOO_MANY_VALUES;
 300                                         }

 301                                         return getValueString(value);
 302                                 };
 303 
 304                                 // FIXME: Merge with TypeHandling.getValueString

 305                                 private String getValueString(Object value) {
 306                                         if (value instanceof IItemCollection) {
 307                                                 return itemCollectionDescription((IItemCollection) value);
 308                                         } else if (value instanceof IDescribable) {
 309                                                 return ((IDescribable) value).getName();
 310                                         } else if (value instanceof IDescribable[] && ((IDescribable[]) value).length > 0) {
 311                                                 IDescribable[] values = ((IDescribable[]) value);
 312                                                 return "[" + values[0].getName() + " ... " //$NON-NLS-1$ //$NON-NLS-2$
 313                                                                 + values[values.length - 1].getName() + "]"; //$NON-NLS-1$
 314                                         } else if (value instanceof Object[]) {
 315 
 316                                                 return limitedDeepToString((Object[]) value, this::getValueString);
 317                                         } else if (value instanceof Collection) {




 318                                                 return limitedDeepToString(((Collection<?>) value).toArray(), this::getValueString);
 319                                         }
 320                                         return TypeHandling.getValueString(value);
 321                                 }
 322 
 323                                 @Override
 324                                 protected String getToolTipTextTyped(PropertySheetRow p) {
 325                                         Object value = p.getValue();
 326                                         if (value instanceof IQuantity) {
 327                                                 return TypeHandling.getNumericString(((IQuantity) value).numberValue());
 328                                         }
 329                                         return JfrPropertySheet.getVerboseString(value);
 330                                 };
 331 
 332                         }).build();
 333 












 334         private static String limitedDeepToString(Object[] array, Function<Object, String> valueToStringProvider) {
 335                 return limitedDeepToString(array, new StringBuilder(), true, valueToStringProvider);
 336         }
 337 
 338         private static String limitedDeepToString(
 339                 Object[] array, StringBuilder builder, boolean isRootArray, Function<Object, String> valueToStringProvider) {
 340                 int maxCharacters = FlightRecorderUI.getDefault().getPreferenceStore()
 341                                 .getInt(PreferenceKeys.PROPERTY_MAXIMUM_PROPERTIES_ARRAY_STRING_SIZE);
 342                 int omitted = 0;
 343                 builder.append('[');
 344                 for (int i = 0; i < array.length; i++) {
 345                         Object element = array[i];
 346                         if (element != null && element.getClass().isArray()) {
 347                                 limitedDeepToString((Object[]) element, builder, false, valueToStringProvider);
 348                         } else {
 349                                 builder.append(valueToStringProvider.apply(element));
 350                         }
 351                         if ((i < (array.length - 1)) && builder.length() < maxCharacters) {
 352                                 builder.append(',');
 353                                 builder.append(' ');


 426                 viewer = new TableViewer(parent, SWT.MULTI | SWT.FULL_SELECTION);
 427                 viewer.setContentProvider(ArrayContentProvider.getInstance());
 428                 // FIXME: Should we keep a state for the properties view?
 429                 ColumnManager manager = ColumnManager.build(viewer,
 430                                 Arrays.asList(FIELD_COLUMN, VALUE_COLUMN, VERBOSE_VALUE_COLUMN), getTableSettings(null));
 431                 MCContextMenuManager mm = MCContextMenuManager.create(viewer.getControl());
 432                 ColumnMenusFactory.addDefaultMenus(manager, mm);
 433                 Function<Consumer<IFlavoredSelection>, Function<List<PropertySheetRow>, Runnable>> actionProvider = flavorConsumer -> selected -> {
 434                         if (selected.size() == 1 && selected.get(0).value != TOO_MANY_VALUES) {
 435                                 if (selected.get(0).attribute != null) {
 436                                         return () -> flavorConsumer.accept(new PropertySheetRowSelection(selected.get(0)));
 437                                 } else if (selected.get(0).value instanceof IItemCollection) {
 438                                         IItemCollection items = (IItemCollection) selected.get(0).value;
 439                                         String selectionName = itemCollectionDescription(items);
 440                                         return () -> flavorConsumer.accept(new ItemBackedSelection(items, selectionName));
 441                                 }
 442                         }
 443                         return null;
 444                 };
 445                 // FIXME: Break out to other place where these actions are added to menus



 446                 mm.appendToGroup(MCContextMenuManager.GROUP_EDIT,
 447                                 ActionToolkit.forListSelection(viewer, Messages.STORE_SELECTION_ACTION, false,
 448                                                 actionProvider.apply(controller.getSelectionStore()::addSelection)));
 449                 mm.appendToGroup(MCContextMenuManager.GROUP_EDIT,
 450                                 ActionToolkit.forListSelection(viewer, Messages.STORE_AND_ACTIVATE_SELECTION_ACTION, false,
 451                                                 actionProvider.apply(controller.getSelectionStore()::addAndSetAsCurrentSelection)));
 452                 ColumnViewerToolTipSupport.enableFor(viewer);
 453                 PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), HELP_CONTEXT_ID);
 454 
 455                 if (UIPlugin.getDefault().getAccessibilityMode()) {
 456                         FocusTracker.enableFocusTracking(viewer.getTable());
 457                 }
 458         }
 459 
 460         private static TableSettings getTableSettings(IState state) {
 461                 if (state == null) {
 462                         return new TableSettings(null,
 463                                         Arrays.asList(new ColumnSettings(FIELD_COLUMN.getId(), false, 120, null),
 464                                                         new ColumnSettings(VALUE_COLUMN.getId(), false, 120, null),
 465                                                         new ColumnSettings(VERBOSE_VALUE_COLUMN.getId(), true, 400, null)));




  19  * the distribution.
  20  * 
  21  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
  22  * endorse or promote products derived from this software without specific prior written permission.
  23  * 
  24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  26  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  31  * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 package org.openjdk.jmc.flightrecorder.ui;
  34 
  35 import java.text.MessageFormat;
  36 import java.util.ArrayList;
  37 import java.util.Arrays;
  38 import java.util.Collection;
  39 import java.util.Collections;
  40 import java.util.Comparator;
  41 import java.util.HashSet;
  42 import java.util.Iterator;
  43 import java.util.LinkedList;
  44 import java.util.List;
  45 import java.util.Objects;
  46 import java.util.Set;
  47 import java.util.concurrent.CompletableFuture;
  48 import java.util.function.Consumer;
  49 import java.util.function.Function;
  50 import java.util.function.Predicate;
  51 import java.util.logging.Level;
  52 import java.util.stream.Collectors;
  53 import java.util.stream.Stream;
  54 
  55 import org.eclipse.jface.action.IAction;
  56 import org.eclipse.jface.resource.ImageDescriptor;
  57 import org.eclipse.jface.viewers.ArrayContentProvider;
  58 import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
  59 import org.eclipse.jface.viewers.ISelection;
  60 import org.eclipse.jface.viewers.IStructuredSelection;
  61 import org.eclipse.jface.viewers.TableViewer;
  62 import org.eclipse.osgi.util.NLS;
  63 import org.eclipse.swt.SWT;
  64 import org.eclipse.swt.graphics.Image;
  65 import org.eclipse.swt.widgets.Composite;
  66 import org.eclipse.swt.widgets.Control;
  67 import org.eclipse.swt.widgets.Display;
  68 import org.eclipse.ui.IWorkbenchPart;
  69 import org.eclipse.ui.PlatformUI;
  70 import org.eclipse.ui.part.Page;
  71 import org.eclipse.ui.views.properties.IPropertySheetPage;
  72 import org.openjdk.jmc.common.IDescribable;
  73 import org.openjdk.jmc.common.IDisplayable;
  74 import org.openjdk.jmc.common.IState;
  75 import org.openjdk.jmc.common.collection.IteratorToolkit;
  76 import org.openjdk.jmc.common.item.Aggregators;
  77 import org.openjdk.jmc.common.item.IAttribute;
  78 import org.openjdk.jmc.common.item.IItem;
  79 import org.openjdk.jmc.common.item.IItemCollection;
  80 import org.openjdk.jmc.common.item.IItemFilter;
  81 import org.openjdk.jmc.common.item.IItemIterable;
  82 import org.openjdk.jmc.common.item.IMemberAccessor;
  83 import org.openjdk.jmc.common.item.IType;
  84 import org.openjdk.jmc.common.unit.ContentType;
  85 import org.openjdk.jmc.common.unit.IQuantity;
  86 import org.openjdk.jmc.common.unit.IRange;
  87 import org.openjdk.jmc.common.unit.KindOfQuantity;
  88 import org.openjdk.jmc.common.unit.QuantitiesToolkit;
  89 import org.openjdk.jmc.common.unit.QuantityRange;
  90 import org.openjdk.jmc.common.unit.RangeContentType;
  91 import org.openjdk.jmc.common.unit.UnitLookup;
  92 import org.openjdk.jmc.common.util.TypeHandling;
  93 import org.openjdk.jmc.flightrecorder.JfrAttributes;
  94 import org.openjdk.jmc.flightrecorder.ui.common.DataPageToolkit;
  95 import org.openjdk.jmc.flightrecorder.ui.common.ImageConstants;
  96 import org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages;
  97 import org.openjdk.jmc.flightrecorder.ui.preferences.PreferenceKeys;
  98 import org.openjdk.jmc.flightrecorder.ui.selection.FlavoredSelectionBase;
  99 import org.openjdk.jmc.flightrecorder.ui.selection.IFilterFlavor;
 100 import org.openjdk.jmc.flightrecorder.ui.selection.IFlavoredSelection;
 101 import org.openjdk.jmc.flightrecorder.ui.selection.IItemStreamFlavor;
 102 import org.openjdk.jmc.flightrecorder.ui.selection.IPropertyFlavor;
 103 import org.openjdk.jmc.flightrecorder.ui.selection.ItemBackedSelection;
 104 import org.openjdk.jmc.ui.TypeAppearance;
 105 import org.openjdk.jmc.ui.UIPlugin;
 106 import org.openjdk.jmc.ui.accessibility.FocusTracker;
 107 import org.openjdk.jmc.ui.column.ColumnBuilder;
 108 import org.openjdk.jmc.ui.column.ColumnManager;
 109 import org.openjdk.jmc.ui.column.ColumnMenusFactory;
 110 import org.openjdk.jmc.ui.column.IColumn;
 111 import org.openjdk.jmc.ui.column.TableSettings;
 112 import org.openjdk.jmc.ui.column.TableSettings.ColumnSettings;
 113 import org.openjdk.jmc.ui.common.util.AdapterUtil;
 114 import org.openjdk.jmc.ui.handlers.ActionToolkit;
 115 import org.openjdk.jmc.ui.handlers.MCContextMenuManager;
 116 import org.openjdk.jmc.ui.misc.DisplayToolkit;
 117 import org.openjdk.jmc.ui.misc.TypedLabelProvider;
 118 
 119 // FIXME: fields - units - filters - icons etc. should be handled more properly
 120 public class JfrPropertySheet extends Page implements IPropertySheetPage {
 121 
 122         private static final ImageDescriptor NEW_PAGE_ICON = FlightRecorderUI.getDefault()
 123                         .getMCImageDescriptor(ImageConstants.ICON_NEW_PAGE);
 124         private static final String HELP_CONTEXT_ID = FlightRecorderUI.PLUGIN_ID + ".JfrPropertiesView"; //$NON-NLS-1$
 125         private static final Object TOO_MANY_VALUES = new Object();
 126         private static final PropertySheetRow CALCULATING = new PropertySheetRow(null, null);
 127         private static Set<IType<?>> selectedTypes = Collections.emptySet();
 128         private static class PropertySheetRowSelection extends FlavoredSelectionBase {
 129 
 130                 private final PropertySheetRow row;
 131 
 132                 PropertySheetRowSelection(PropertySheetRow row) {
 133                         super(MessageFormat.format(Messages.JFR_PROPERTIES_PROPERTY_SELECTION, row.attribute.getName()));
 134                         this.row = row;
 135                 }
 136 
 137                 @Override
 138                 public Stream<IItemStreamFlavor> getFlavors(
 139                         IItemFilter dstFilter, IItemCollection items, List<IAttribute<?>> dstAttributes) {
 140                         /*
 141                          * FIXME: Is this the desired behavior? Discuss and change if necessary.
 142                          * 
 143                          * This most likely need more thought and discussion, but the implemented order of
 144                          * flavors is currently:
 145                          * 
 146                          * For chart selections:
 147                          * 


 287                                 @Override
 288                                 protected Image getImageTyped(PropertySheetRow p) {
 289                                         if (p.attribute != null) {
 290                                                 Image icon = TypeAppearance.getImage(p.attribute.getContentType().getIdentifier());
 291                                                 return icon == null ? UIPlugin.getDefault().getImage(UIPlugin.ICON_PROPERTY_OBJECT) : icon;
 292                                         }
 293                                         return null;
 294                                 };
 295                         }).build();
 296 
 297         private static final IColumn VALUE_COLUMN = new ColumnBuilder(Messages.JFR_PROPERTY_SHEET_VALUE, "value", //$NON-NLS-1$
 298                         new TypedLabelProvider<PropertySheetRow>(PropertySheetRow.class) {
 299                                 @Override
 300                                 protected String getTextTyped(PropertySheetRow p) {
 301                                         Object value = p.getValue();
 302                                         if (p == CALCULATING) {
 303                                                 return Messages.JFR_PROPERTIES_CALCULATING;
 304                                         } else if (value == TOO_MANY_VALUES) {
 305                                                 return Messages.JFR_PROPERTIES_TOO_MANY_VALUES;
 306                                         }
 307                                         updateSelectedTypes(value);
 308                                         return getValueString(value);
 309                                 };
 310 
 311                                 // FIXME: Merge with TypeHandling.getValueString
 312                                 @SuppressWarnings("unchecked")
 313                                 private String getValueString(Object value) {
 314                                         if (value instanceof IItemCollection) {
 315                                                 return itemCollectionDescription((IItemCollection) value);
 316                                         } else if (value instanceof IDescribable) {
 317                                                 return ((IDescribable) value).getName();
 318                                         } else if (value instanceof IDescribable[] && ((IDescribable[]) value).length > 0) {
 319                                                 IDescribable[] values = ((IDescribable[]) value);
 320                                                 return "[" + values[0].getName() + " ... " //$NON-NLS-1$ //$NON-NLS-2$
 321                                                                 + values[values.length - 1].getName() + "]"; //$NON-NLS-1$
 322                                         } else if (value instanceof Object[]) {
 323 
 324                                                 return limitedDeepToString((Object[]) value, this::getValueString);
 325                                         } else if (value instanceof Collection<?>) {
 326                                                 System.out.println(value);
 327                                                 selectedTypes = new HashSet<IType<?>>((Collection<IType<?>>) value)
 328                                                         .stream().collect(Collectors.toSet());
 329 
 330                                                 return limitedDeepToString(((Collection<?>) value).toArray(), this::getValueString);
 331                                         }
 332                                         return TypeHandling.getValueString(value);
 333                                 }
 334 
 335                                 @Override
 336                                 protected String getToolTipTextTyped(PropertySheetRow p) {
 337                                         Object value = p.getValue();
 338                                         if (value instanceof IQuantity) {
 339                                                 return TypeHandling.getNumericString(((IQuantity) value).numberValue());
 340                                         }
 341                                         return JfrPropertySheet.getVerboseString(value);
 342                                 };
 343 
 344                         }).build();
 345         
 346         private static void updateSelectedTypes(Object value) {
 347                 if (value instanceof IType<?>) {
 348                         selectedTypes = new HashSet<IType<?>>();
 349                         selectedTypes.add((IType<?>) value);
 350                 }
 351                 else if (value instanceof Collection<?>) {
 352                         selectedTypes = new HashSet<IType<?>>((Collection<IType<?>>) value)
 353                                         .stream().collect(Collectors.toSet());
 354                 }
 355                 
 356         }
 357         
 358         private static String limitedDeepToString(Object[] array, Function<Object, String> valueToStringProvider) {
 359                 return limitedDeepToString(array, new StringBuilder(), true, valueToStringProvider);
 360         }
 361 
 362         private static String limitedDeepToString(
 363                 Object[] array, StringBuilder builder, boolean isRootArray, Function<Object, String> valueToStringProvider) {
 364                 int maxCharacters = FlightRecorderUI.getDefault().getPreferenceStore()
 365                                 .getInt(PreferenceKeys.PROPERTY_MAXIMUM_PROPERTIES_ARRAY_STRING_SIZE);
 366                 int omitted = 0;
 367                 builder.append('[');
 368                 for (int i = 0; i < array.length; i++) {
 369                         Object element = array[i];
 370                         if (element != null && element.getClass().isArray()) {
 371                                 limitedDeepToString((Object[]) element, builder, false, valueToStringProvider);
 372                         } else {
 373                                 builder.append(valueToStringProvider.apply(element));
 374                         }
 375                         if ((i < (array.length - 1)) && builder.length() < maxCharacters) {
 376                                 builder.append(',');
 377                                 builder.append(' ');


 450                 viewer = new TableViewer(parent, SWT.MULTI | SWT.FULL_SELECTION);
 451                 viewer.setContentProvider(ArrayContentProvider.getInstance());
 452                 // FIXME: Should we keep a state for the properties view?
 453                 ColumnManager manager = ColumnManager.build(viewer,
 454                                 Arrays.asList(FIELD_COLUMN, VALUE_COLUMN, VERBOSE_VALUE_COLUMN), getTableSettings(null));
 455                 MCContextMenuManager mm = MCContextMenuManager.create(viewer.getControl());
 456                 ColumnMenusFactory.addDefaultMenus(manager, mm);
 457                 Function<Consumer<IFlavoredSelection>, Function<List<PropertySheetRow>, Runnable>> actionProvider = flavorConsumer -> selected -> {
 458                         if (selected.size() == 1 && selected.get(0).value != TOO_MANY_VALUES) {
 459                                 if (selected.get(0).attribute != null) {
 460                                         return () -> flavorConsumer.accept(new PropertySheetRowSelection(selected.get(0)));
 461                                 } else if (selected.get(0).value instanceof IItemCollection) {
 462                                         IItemCollection items = (IItemCollection) selected.get(0).value;
 463                                         String selectionName = itemCollectionDescription(items);
 464                                         return () -> flavorConsumer.accept(new ItemBackedSelection(items, selectionName));
 465                                 }
 466                         }
 467                         return null;
 468                 };
 469                 // FIXME: Break out to other place where these actions are added to menus
 470                 IAction addPageAction = ActionToolkit.action(() -> DataPageToolkit.addPage(selectedTypes),
 471                                 Messages.EventBrowserPage_NEW_PAGE_USING_TYPES_ACTION, NEW_PAGE_ICON);
 472                 mm.appendToGroup(MCContextMenuManager.GROUP_NEW, addPageAction);
 473                 mm.appendToGroup(MCContextMenuManager.GROUP_EDIT,
 474                                 ActionToolkit.forListSelection(viewer, Messages.STORE_SELECTION_ACTION, false,
 475                                                 actionProvider.apply(controller.getSelectionStore()::addSelection)));
 476                 mm.appendToGroup(MCContextMenuManager.GROUP_EDIT,
 477                                 ActionToolkit.forListSelection(viewer, Messages.STORE_AND_ACTIVATE_SELECTION_ACTION, false,
 478                                                 actionProvider.apply(controller.getSelectionStore()::addAndSetAsCurrentSelection)));
 479                 ColumnViewerToolTipSupport.enableFor(viewer);
 480                 PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), HELP_CONTEXT_ID);
 481 
 482                 if (UIPlugin.getDefault().getAccessibilityMode()) {
 483                         FocusTracker.enableFocusTracking(viewer.getTable());
 484                 }
 485         }
 486 
 487         private static TableSettings getTableSettings(IState state) {
 488                 if (state == null) {
 489                         return new TableSettings(null,
 490                                         Arrays.asList(new ColumnSettings(FIELD_COLUMN.getId(), false, 120, null),
 491                                                         new ColumnSettings(VALUE_COLUMN.getId(), false, 120, null),
 492                                                         new ColumnSettings(VERBOSE_VALUE_COLUMN.getId(), true, 400, null)));


< prev index next >