1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * The contents of this file are subject to the terms of either the Universal Permissive License 7 * v 1.0 as shown at http://oss.oracle.com/licenses/upl 8 * 9 * or the following license: 10 * 11 * Redistribution and use in source and binary forms, with or without modification, are permitted 12 * provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 15 * and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 18 * conditions and the following disclaimer in the documentation and/or other materials provided with 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.pages; 34 35 import java.awt.Color; 36 import java.util.ArrayList; 37 import java.util.Arrays; 38 import java.util.List; 39 40 import org.eclipse.jface.resource.ImageDescriptor; 41 import org.eclipse.osgi.util.NLS; 42 import org.eclipse.swt.SWT; 43 import org.eclipse.swt.custom.CTabFolder; 44 import org.eclipse.swt.custom.CTabItem; 45 import org.eclipse.swt.custom.SashForm; 46 import org.eclipse.swt.events.SelectionAdapter; 47 import org.eclipse.swt.events.SelectionEvent; 48 import org.eclipse.swt.widgets.Composite; 49 import org.eclipse.ui.forms.widgets.Form; 50 import org.eclipse.ui.forms.widgets.FormToolkit; 51 import org.openjdk.jmc.common.IState; 52 import org.openjdk.jmc.common.IWritableState; 53 import org.openjdk.jmc.common.item.IItem; 54 import org.openjdk.jmc.common.item.IItemCollection; 55 import org.openjdk.jmc.common.item.IItemFilter; 56 import org.openjdk.jmc.common.item.ItemFilters; 57 import org.openjdk.jmc.common.unit.IQuantity; 58 import org.openjdk.jmc.common.unit.IRange; 59 import org.openjdk.jmc.common.unit.UnitLookup; 60 import org.openjdk.jmc.common.util.ColorToolkit; 61 import org.openjdk.jmc.flightrecorder.JfrAttributes; 62 import org.openjdk.jmc.flightrecorder.jdk.JdkAggregators; 63 import org.openjdk.jmc.flightrecorder.jdk.JdkAttributes; 64 import org.openjdk.jmc.flightrecorder.jdk.JdkFilters; 65 import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs; 66 import org.openjdk.jmc.flightrecorder.rules.util.JfrRuleTopics; 67 import org.openjdk.jmc.flightrecorder.ui.FlightRecorderUI; 68 import org.openjdk.jmc.flightrecorder.ui.IDataPageFactory; 69 import org.openjdk.jmc.flightrecorder.ui.IDisplayablePage; 70 import org.openjdk.jmc.flightrecorder.ui.IPageContainer; 71 import org.openjdk.jmc.flightrecorder.ui.IPageDefinition; 72 import org.openjdk.jmc.flightrecorder.ui.IPageUI; 73 import org.openjdk.jmc.flightrecorder.ui.ItemCollectionToolkit; 74 import org.openjdk.jmc.flightrecorder.ui.StreamModel; 75 import org.openjdk.jmc.flightrecorder.ui.common.AbstractDataPage; 76 import org.openjdk.jmc.flightrecorder.ui.common.DataPageToolkit; 77 import org.openjdk.jmc.flightrecorder.ui.common.FilterComponent; 78 import org.openjdk.jmc.flightrecorder.ui.common.FlavorSelector; 79 import org.openjdk.jmc.flightrecorder.ui.common.FlavorSelector.FlavorSelectorState; 80 import org.openjdk.jmc.flightrecorder.ui.common.ImageConstants; 81 import org.openjdk.jmc.flightrecorder.ui.common.ItemHistogram; 82 import org.openjdk.jmc.flightrecorder.ui.common.ItemHistogram.HistogramSelection; 83 import org.openjdk.jmc.flightrecorder.ui.common.ItemHistogram.ItemHistogramBuilder; 84 import org.openjdk.jmc.flightrecorder.ui.common.ItemList; 85 import org.openjdk.jmc.flightrecorder.ui.common.ItemList.ItemListBuilder; 86 import org.openjdk.jmc.flightrecorder.ui.common.TypeLabelProvider; 87 import org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages; 88 import org.openjdk.jmc.flightrecorder.ui.selection.SelectionStoreActionToolkit; 89 import org.openjdk.jmc.ui.charts.IXDataRenderer; 90 import org.openjdk.jmc.ui.charts.RendererToolkit; 91 import org.openjdk.jmc.ui.charts.XYChart; 92 import org.openjdk.jmc.ui.column.ColumnManager.SelectionState; 93 import org.openjdk.jmc.ui.column.ColumnMenusFactory; 94 import org.openjdk.jmc.ui.column.TableSettings; 95 import org.openjdk.jmc.ui.column.TableSettings.ColumnSettings; 96 import org.openjdk.jmc.ui.handlers.MCContextMenuManager; 97 import org.openjdk.jmc.ui.misc.ChartCanvas; 98 import org.openjdk.jmc.ui.misc.PersistableSashForm; 99 100 public class FileIOPage extends AbstractDataPage { 101 public static class FileIOPageFactory implements IDataPageFactory { 102 103 @Override 104 public String getName(IState state) { 105 return Messages.FileIOPage_PAGE_NAME; 106 } 107 108 @Override 109 public ImageDescriptor getImageDescriptor(IState state) { 110 return FlightRecorderUI.getDefault().getMCImageDescriptor(ImageConstants.PAGE_IO); 111 } 112 113 @Override 114 public String[] getTopics(IState state) { 115 return new String[] {JfrRuleTopics.FILE_IO_TOPIC}; 116 } 117 118 @Override 119 public IDisplayablePage createPage(IPageDefinition dpd, StreamModel items, IPageContainer editor) { 120 return new FileIOPage(dpd, items, editor); 121 } 122 123 } 124 125 private static final Color WRITE_COLOR = TypeLabelProvider.getColor(JdkTypeIDs.FILE_WRITE); 126 private static final Color READ_COLOR = TypeLabelProvider.getColor(JdkTypeIDs.FILE_READ); 127 private static final Color WRITE_ALPHA_COLOR = ColorToolkit.withAlpha(WRITE_COLOR, 80); 128 private static final Color READ_ALPHA_COLOR = ColorToolkit.withAlpha(READ_COLOR, 80); 129 private static final IItemFilter TABLE_ITEMS = ItemFilters.type(JdkTypeIDs.FILE_READ, JdkTypeIDs.FILE_WRITE); 130 private static final String TOTAL_TIME = "totalTime"; //$NON-NLS-1$ 131 private static final String MAX_TIME = "maxTime"; //$NON-NLS-1$ 132 private static final String AVG_TIME = "avgTime"; //$NON-NLS-1$ 133 private static final String STDDEV_TIME = "stddevTime"; //$NON-NLS-1$ 134 private static final String READ_COUNT = "readCount"; //$NON-NLS-1$ 135 private static final String WRITE_COUNT = "writeCount"; //$NON-NLS-1$ 136 private static final String READ_SIZE = "readSize"; //$NON-NLS-1$ 137 private static final String WRITE_SIZE = "writeSize"; //$NON-NLS-1$ 138 private static final String READ_EOF = "endOfFile"; //$NON-NLS-1$ 139 140 private static final ItemHistogramBuilder HISTOGRAM = new ItemHistogramBuilder(); 141 private static final ItemListBuilder LIST = new ItemListBuilder(); 142 143 static { 144 HISTOGRAM.addCountColumn(); 145 HISTOGRAM.addColumn(TOTAL_TIME, JdkAggregators.TOTAL_IO_TIME); 146 HISTOGRAM.addColumn(MAX_TIME, JdkAggregators.MAX_IO_TIME); 147 HISTOGRAM.addColumn(AVG_TIME, JdkAggregators.AVG_IO_TIME); 148 HISTOGRAM.addColumn(STDDEV_TIME, JdkAggregators.STDDEV_IO_TIME); 149 HISTOGRAM.addColumn(READ_COUNT, JdkAggregators.FILE_READ_COUNT); 150 HISTOGRAM.addColumn(WRITE_COUNT, JdkAggregators.FILE_WRITE_COUNT); 151 HISTOGRAM.addColumn(READ_SIZE, JdkAggregators.FILE_READ_SIZE); 152 HISTOGRAM.addColumn(WRITE_SIZE, JdkAggregators.FILE_WRITE_SIZE); 153 LIST.addColumn(JdkAttributes.IO_PATH); 154 LIST.addColumn(JfrAttributes.START_TIME); 155 LIST.addColumn(JfrAttributes.END_TIME); 156 LIST.addColumn(JfrAttributes.DURATION); 157 LIST.addColumn(JdkAttributes.IO_FILE_BYTES_READ); 158 LIST.addColumn(JdkAttributes.IO_FILE_BYTES_WRITTEN); 159 LIST.addColumn(JfrAttributes.EVENT_THREAD); 160 LIST.addColumn(JdkAttributes.IO_FILE_READ_EOF); 161 } 162 163 private class IOPageUi implements IPageUI { 164 private static final String FILE_IO_TABLE = "fileIoTable"; //$NON-NLS-1$ 165 private static final String FILE_IO_LIST = "fileIoList"; //$NON-NLS-1$ 166 private static final String SASH_ELEMENT = "sash"; //$NON-NLS-1$ 167 private static final String LIST_ELEMENT = "eventList"; //$NON-NLS-1$ 168 private static final String TABLE_ELEMENT = "table"; //$NON-NLS-1$ 169 170 private final ChartCanvas timelineCanvas; 171 private final ChartCanvas durationCanvas; 172 private XYChart timelineChart; 173 private IRange<IQuantity> timeRange; 174 private IItemCollection selectionItems; 175 private final ItemList itemList; 176 private final ItemHistogram table; 177 private final SashForm sash; 178 private final IPageContainer pageContainer; 179 private FilterComponent tableFilter; 180 private FilterComponent itemListFilter; 181 private FlavorSelector flavorSelector; 182 183 IOPageUi(Composite parent, FormToolkit toolkit, IPageContainer pageContainer, IState state) { 184 this.pageContainer = pageContainer; 185 Form form = DataPageToolkit.createForm(parent, toolkit, getName(), getIcon()); 186 sash = new SashForm(form.getBody(), SWT.VERTICAL); 187 toolkit.adapt(sash); 188 189 addResultActions(form); 190 191 table = HISTOGRAM.buildWithoutBorder(sash, JdkAttributes.IO_PATH, 192 getTableSettings(state.getChild(TABLE_ELEMENT))); 193 MCContextMenuManager mm = MCContextMenuManager.create(table.getManager().getViewer().getControl()); 194 ColumnMenusFactory.addDefaultMenus(table.getManager(), mm); 195 SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), table, 196 Messages.FileIOPage_HISTOGRAM_SELECTION, mm); 197 table.getManager().getViewer().addSelectionChangedListener(e -> updateDetails()); 198 table.getManager().getViewer() 199 .addSelectionChangedListener(e -> pageContainer.showSelection(table.getSelection().getItems())); 200 tableFilter = FilterComponent.createFilterComponent(table, FileIOPage.this.tableFilter, 201 getDataSource().getItems().apply(TABLE_ITEMS), pageContainer.getSelectionStore()::getSelections, 202 this::onTableFilterChange); 203 mm.add(tableFilter.getShowFilterAction()); 204 mm.add(tableFilter.getShowSearchAction()); 205 206 CTabFolder tabFolder = new CTabFolder(sash, SWT.NONE); 207 toolkit.adapt(tabFolder); 208 CTabItem t1 = new CTabItem(tabFolder, SWT.NONE); 209 t1.setToolTipText(Messages.IO_PAGE_TIMELINE_DESCRIPTION); 210 timelineCanvas = new ChartCanvas(tabFolder); 211 t1.setText(Messages.PAGES_TIMELINE); 212 t1.setControl(timelineCanvas); 213 DataPageToolkit.createChartTimestampTooltip(timelineCanvas); 214 215 CTabItem t2 = new CTabItem(tabFolder, SWT.NONE); 216 t2.setToolTipText(Messages.IO_PAGE_DURATIONS_DESCRIPTION); 217 durationCanvas = new ChartCanvas(tabFolder); 218 t2.setText(Messages.PAGES_DURATIONS); 219 t2.setControl(durationCanvas); 220 DataPageToolkit.createChartTooltip(durationCanvas); 221 222 CTabItem t3 = new CTabItem(tabFolder, SWT.NONE); 223 t3.setToolTipText(Messages.IO_PAGE_EVENT_LOG_DESCRIPTION); 224 itemList = LIST.buildWithoutBorder(tabFolder, getTableSettings(state.getChild(LIST_ELEMENT))); 225 MCContextMenuManager itemListMm = MCContextMenuManager 226 .create(itemList.getManager().getViewer().getControl()); 227 ColumnMenusFactory.addDefaultMenus(itemList.getManager(), itemListMm); 228 SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), itemList, 229 Messages.FileIOPage_LOG_SELECTION, itemListMm); 230 itemList.getManager().getViewer().addSelectionChangedListener( 231 e -> pageContainer.showSelection(ItemCollectionToolkit.build(itemList.getSelection().get()))); 232 t3.setText(Messages.PAGES_EVENT_LOG); 233 itemListFilter = FilterComponent.createFilterComponent(itemList, FileIOPage.this.itemListFilter, 234 getDataSource().getItems().apply(TABLE_ITEMS), pageContainer.getSelectionStore()::getSelections, 235 this::onListFilterChange); 236 itemListMm.add(itemListFilter.getShowFilterAction()); 237 itemListMm.add(itemListFilter.getShowSearchAction()); 238 t3.setControl(itemListFilter.getComponent()); 239 240 tableFilter.loadState(state.getChild(FILE_IO_TABLE)); 241 itemListFilter.loadState(state.getChild(FILE_IO_LIST)); 242 243 tabFolder.setSelection(tabFolderIndex); 244 tabFolder.addSelectionListener(new SelectionAdapter() { 245 @Override 246 public void widgetSelected(SelectionEvent e) { 247 tabFolderIndex = ((CTabFolder) e.getSource()).getSelectionIndex(); 248 } 249 }); 250 251 timelineChart = createTimelineChart(pageContainer); 252 hookUpTimeLineChart(); 253 PersistableSashForm.loadState(sash, state.getChild(SASH_ELEMENT)); 254 255 flavorSelector = FlavorSelector.itemsWithTimerange(form, TABLE_ITEMS, getDataSource().getItems(), 256 pageContainer, this::onInputSelected, this::onShowFlavor, flavorSelectorState); 257 258 table.getManager().setSelectionState(tableSelection); 259 itemList.getManager().setSelectionState(itemListSelection); 260 } 261 262 private XYChart createTimelineChart(IPageContainer pageContainer) { 263 XYChart timelineChart = new XYChart(pageContainer.getRecordingRange(), RendererToolkit.empty(), 180); 264 timelineChart.setVisibleRange(timelineRange.getStart(), timelineRange.getEnd()); 265 timelineChart.addVisibleRangeListener(range -> timelineRange = range); 266 return timelineChart; 267 } 268 269 private void onTableFilterChange(IItemFilter filter) { 270 tableFilter.filterChangeHelper(filter, table, getDataSource().getItems().apply(TABLE_ITEMS)); 271 itemListFilter.notifyListener(); 272 FileIOPage.this.tableFilter = filter; 273 } 274 275 private void onListFilterChange(IItemFilter filter) { 276 itemListFilter.filterChangeHelper(filter, itemList, getDataSource().getItems().apply(TABLE_ITEMS)); 277 FileIOPage.this.itemListFilter = filter; 278 } 279 280 @Override 281 public void saveTo(IWritableState writableState) { 282 PersistableSashForm.saveState(sash, writableState.createChild(SASH_ELEMENT)); 283 table.getManager().getSettings().saveState(writableState.createChild(TABLE_ELEMENT)); 284 tableFilter.saveState(writableState.createChild(FILE_IO_TABLE)); 285 itemList.getManager().getSettings().saveState(writableState.createChild(LIST_ELEMENT)); 286 itemListFilter.saveState(writableState.createChild(FILE_IO_LIST)); 287 288 saveToLocal(); 289 } 290 291 private void saveToLocal() { 292 tableSelection = table.getManager().getSelectionState(); 293 itemListSelection = itemList.getManager().getSelectionState(); 294 flavorSelectorState = flavorSelector.getFlavorSelectorState(); 295 } 296 297 private void onShowFlavor(Boolean show) { 298 IRange<IQuantity> range = show ? timeRange : pageContainer.getRecordingRange(); 299 timelineChart.setVisibleRange(range.getStart(), range.getEnd()); 300 hookUpTimeLineChart(); 301 } 302 303 private void hookUpTimeLineChart() { 304 DataPageToolkit.setChart(timelineCanvas, timelineChart, pageContainer::showSelection); 305 SelectionStoreActionToolkit.addSelectionStoreRangeActions(pageContainer.getSelectionStore(), timelineChart, 306 JfrAttributes.LIFETIME, Messages.FileIOPage_TIMELINE_SELECTION, timelineCanvas.getContextMenu()); 307 } 308 309 private void onInputSelected(IItemCollection items, IRange<IQuantity> timeRange) { 310 this.selectionItems = items; 311 this.timeRange = timeRange; 312 updateDetails(); 313 } 314 315 private void updateDetails() { 316 IItemCollection items = selectionItems != null ? selectionItems.apply(TABLE_ITEMS) 317 : getDataSource().getItems().apply(TABLE_ITEMS); 318 table.show(items); 319 HistogramSelection histogramSelection = table.getSelection(); 320 IItemCollection selectedItems = histogramSelection.getRowCount() == 0 ? items 321 : histogramSelection.getItems(); 322 323 String pathCount = pathCount(histogramSelection.getRowCount()); 324 List<IXDataRenderer> timelineRows = new ArrayList<>(); 325 List<IXDataRenderer> durationRows = new ArrayList<>(); 326 IItemCollection readItems = selectedItems.apply(JdkFilters.FILE_READ); 327 if (readItems.hasItems()) { 328 timelineRows.add(DataPageToolkit.buildSizeRow(Messages.FileIOPage_ROW_FILE_READ + pathCount, 329 JdkAggregators.FILE_READ_SIZE.getDescription(), readItems, JdkAggregators.FILE_READ_SIZE, 330 READ_COLOR, FileIOPage::getColor)); 331 durationRows.add(DataPageToolkit.buildDurationHistogram(Messages.FileIOPage_ROW_FILE_READ + pathCount, 332 JdkAggregators.FILE_READ_COUNT.getDescription(), readItems, JdkAggregators.FILE_READ_COUNT, 333 READ_COLOR)); 334 } 335 IItemCollection writeItems = selectedItems.apply(JdkFilters.FILE_WRITE); 336 if (writeItems.hasItems()) { 337 timelineRows.add(DataPageToolkit.buildSizeRow(Messages.FileIOPage_ROW_FILE_WRITE + pathCount, 338 JdkAggregators.FILE_WRITE_SIZE.getDescription(), writeItems, JdkAggregators.FILE_WRITE_SIZE, 339 WRITE_COLOR, FileIOPage::getColor)); 340 durationRows.add(DataPageToolkit.buildDurationHistogram(Messages.FileIOPage_ROW_FILE_WRITE + pathCount, 341 JdkAggregators.FILE_WRITE_COUNT.getDescription(), writeItems, JdkAggregators.FILE_WRITE_COUNT, 342 WRITE_COLOR)); 343 } 344 // ItemRow[] pathRows = selection.getSelectedRows(FileIOPage::buildPathLane).toArray(ItemRow[]::new); 345 346 timelineCanvas.replaceRenderer(RendererToolkit.uniformRows(timelineRows)); 347 348 IXDataRenderer durationRoot = RendererToolkit.uniformRows(durationRows); 349 // FIXME: X-auto-range should be done properly 350 IQuantity max = selectedItems.getAggregate(JdkAggregators.LONGEST_EVENT); 351 // FIXME: Workaround to make max value included 352 max = max == null ? UnitLookup.MILLISECOND.quantity(20) : max.add(UnitLookup.MILLISECOND.quantity(20)); 353 XYChart durationChart = new XYChart(UnitLookup.MILLISECOND.quantity(0), max, durationRoot, 180); 354 DataPageToolkit.setChart(durationCanvas, durationChart, JfrAttributes.DURATION, 355 selection -> pageContainer.showSelection(selection)); 356 durationChart.setVisibleRange(durationRange.getStart(), durationRange.getEnd()); 357 durationChart.addVisibleRangeListener(range -> durationRange = range); 358 durationCanvas.setChart(durationChart); 359 SelectionStoreActionToolkit.addSelectionStoreActions(pageContainer.getSelectionStore(), durationChart, 360 JfrAttributes.DURATION, Messages.FileIOPage_DURATION_SELECTION, durationCanvas.getContextMenu()); 361 itemList.show(selectedItems); 362 } 363 } 364 365 private static TableSettings getTableSettings(IState state) { 366 if (state == null) { 367 return new TableSettings(TOTAL_TIME, Arrays.asList( 368 new ColumnSettings(ItemHistogram.KEY_COL_ID, false, 500, null), 369 new ColumnSettings(TOTAL_TIME, true, 120, false), new ColumnSettings(MAX_TIME, false, 120, false), 370 new ColumnSettings(AVG_TIME, false, 120, false), new ColumnSettings(STDDEV_TIME, false, 120, false), 371 new ColumnSettings(READ_COUNT, false, 120, false), 372 new ColumnSettings(WRITE_COUNT, false, 120, false), 373 new ColumnSettings(READ_SIZE, false, 120, false), new ColumnSettings(WRITE_SIZE, false, 120, false), 374 new ColumnSettings(READ_EOF, false, 80, false))); 375 } else { 376 return new TableSettings(state); 377 } 378 } 379 380 @Override 381 public IPageUI display(Composite parent, FormToolkit toolkit, IPageContainer pageContainer, IState state) { 382 return new IOPageUi(parent, toolkit, pageContainer, state); 383 } 384 385 private SelectionState tableSelection; 386 private SelectionState itemListSelection; 387 private IItemFilter tableFilter = null; 388 private IItemFilter itemListFilter = null; 389 private int tabFolderIndex = 0; 390 private IRange<IQuantity> timelineRange; 391 private IRange<IQuantity> durationRange; 392 public FlavorSelectorState flavorSelectorState; 393 394 public FileIOPage(IPageDefinition dpd, StreamModel items, IPageContainer editor) { 395 super(dpd, items, editor); 396 timelineRange = editor.getRecordingRange(); 397 durationRange = editor.getRecordingRange(); 398 } 399 400 // private static ItemRow buildPathLane(Object path, Supplier<Stream<ItemStream>> pathItems) { 401 // String pathName = String.valueOf(path); 402 // pathName = pathName.length() > 26 ? pathName.substring(0, 23) + "..." : pathName; //$NON-NLS-1$ 403 // return new ItemRow(pathName, buildSpanRenderer(pathItems), pathItems); 404 // } 405 406 private static Color getColor(IItem item) { 407 return JdkTypeIDs.FILE_READ.equals(item.getType().getIdentifier()) ? READ_ALPHA_COLOR : WRITE_ALPHA_COLOR; 408 } 409 410 @Override 411 public IItemFilter getDefaultSelectionFilter() { 412 return TABLE_ITEMS; 413 } 414 415 private static String pathCount(int count) { 416 switch (count) { 417 case 0: 418 return ""; //$NON-NLS-1$ 419 case 1: 420 return " (" + Messages.FileIOPage_SELECTED_PATH + ")"; //$NON-NLS-1$ //$NON-NLS-2$ 421 default: 422 return " (" + NLS.bind(Messages.FileIOPage_SELECTED_PATHS, count) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ 423 } 424 } 425 }