| /** |
| ******************************************************************************** |
| * Copyright (c) 2015-2020 Eclipse APP4MC contributors. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| ******************************************************************************** |
| */ |
| |
| package org.eclipse.app4mc.atdb.metrics; |
| |
| import java.util.Arrays; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.stream.IntStream; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.nebula.widgets.nattable.NatTable; |
| import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration; |
| import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider; |
| import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer; |
| import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer; |
| import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer; |
| import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer; |
| import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer; |
| import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer; |
| import org.eclipse.nebula.widgets.nattable.group.performance.RowGroupExpandCollapseLayer; |
| import org.eclipse.nebula.widgets.nattable.group.performance.RowGroupHeaderLayer; |
| import org.eclipse.nebula.widgets.nattable.group.performance.config.DefaultRowGroupHeaderLayerConfiguration; |
| import org.eclipse.nebula.widgets.nattable.layer.DataLayer; |
| import org.eclipse.nebula.widgets.nattable.layer.SpanningDataLayer; |
| import org.eclipse.nebula.widgets.nattable.layer.cell.DataCell; |
| import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; |
| import org.eclipse.nebula.widgets.nattable.layer.cell.LayerCell; |
| import org.eclipse.nebula.widgets.nattable.layer.cell.TranslatedLayerCell; |
| import org.eclipse.nebula.widgets.nattable.layer.config.DefaultRowHeaderLayerConfiguration; |
| import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer; |
| import org.eclipse.nebula.widgets.nattable.style.theme.ModernNatTableThemeConfiguration; |
| import org.eclipse.nebula.widgets.nattable.ui.menu.HeaderMenuConfiguration; |
| import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.CTabFolder; |
| import org.eclipse.swt.custom.CTabItem; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IEditorSite; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.part.EditorPart; |
| import org.eclipse.ui.part.FileEditorInput; |
| |
| public class DBViewer extends EditorPart implements IEditorPart { |
| |
| private Map<String, DBResultRowDataProvider> view2ResultRowDataProvider = new LinkedHashMap<>(); |
| private CTabFolder cTabFolder = null; |
| |
| @Override |
| public void doSave(final IProgressMonitor monitor) { |
| // this is just a viewer for trace metrics, nothing can be changed |
| // so there is nothing to save |
| } |
| |
| @Override |
| public void doSaveAs() { |
| // this is just a viewer for trace metrics, nothing can be changed |
| // so there is nothing to save |
| } |
| |
| @Override |
| public boolean isDirty() { |
| // this is just a viewer for trace metrics, nothing can be changed |
| // so there is nothing to save, so it is never dirty |
| return false; |
| } |
| |
| @Override |
| public boolean isSaveAsAllowed() { |
| // this is just a viewer for trace metrics, nothing can be changed |
| // so there is nothing to save |
| return false; |
| } |
| |
| @Override |
| public void init(final IEditorSite site, final IEditorInput input) throws PartInitException { |
| setSite(site); |
| setInput(input); |
| setPartName(input.getName()); |
| if (input instanceof FileEditorInput) { |
| final FileEditorInput fei = (FileEditorInput) input; |
| final IFile dbFile = fei.getFile(); |
| try (final DatabaseAccess dbAccess = new DatabaseAccess(dbFile)){ |
| this.view2ResultRowDataProvider.put(Messages.DBViewer_processTimeMetricsTitle, |
| dbAccess.getProcessMetricValues(Arrays.asList("time"), true)); //$NON-NLS-1$ |
| this.view2ResultRowDataProvider.put(Messages.DBViewer_runnableTimeMetricsTitle, |
| dbAccess.getRunnableMetricValues(Arrays.asList("time"), true, true)); //$NON-NLS-1$ |
| this.view2ResultRowDataProvider.put(Messages.DBViewer_eventChainTimeMetricsTitle, |
| dbAccess.getEventChainMetricValues(Arrays.asList("time"))); |
| } |
| catch (final Exception e) { |
| MessageDialog.openError(site.getShell(), Messages.DBViewer_fileErrorTitle, |
| String.format(Messages.DBViewer_fileErrorMessage, fei.getName())); |
| } |
| } |
| } |
| |
| private static class RowHeaderConfiguration extends DefaultRowHeaderLayerConfiguration { |
| @Override |
| protected void addRowHeaderUIBindings() { |
| // We're suppressing the row resize bindings. |
| } |
| } |
| |
| |
| @Override |
| public void createPartControl(final Composite parent) { |
| this.cTabFolder = new CTabFolder(parent, SWT.BOTTOM | SWT.FLAT); |
| for(final Entry<String, DBResultRowDataProvider> entry:this.view2ResultRowDataProvider.entrySet()) { |
| final CTabItem item = new CTabItem(this.cTabFolder, SWT.NONE); |
| item.setText(entry.getKey()); |
| // Body layer stack |
| final DataLayer spanningDataLayer = new SpanningDataLayer(entry.getValue()); |
| final RowGroupExpandCollapseLayer rowExpandCollapseLayer = new RowGroupExpandCollapseLayer(spanningDataLayer) { |
| @Override |
| public ILayerCell getCellByPosition(int columnPosition, int rowPosition) { |
| // make it aware of spanning rows |
| int underlyingColumnPosition = localToUnderlyingColumnPosition(columnPosition); |
| int underlyingRowPosition = localToUnderlyingRowPosition(rowPosition); |
| if (underlyingColumnPosition < 0 || underlyingColumnPosition >= spanningDataLayer.getColumnCount() || |
| underlyingRowPosition < 0 || underlyingRowPosition >= spanningDataLayer.getRowCount()) { |
| return null; |
| } |
| DataCell dataCell = entry.getValue().getCellByPosition(underlyingColumnPosition, underlyingRowPosition); |
| final int dCRowPos = dataCell.getRowPosition(); |
| final int dCRowSp = dataCell.getRowSpan(); |
| // subtract hidden rows from row span |
| int actualRowSpan = dCRowSp - (int)IntStream.range(1, dCRowSp).filter(i -> isRowIndexHidden(dCRowPos + i)).count(); |
| dataCell = new DataCell(dataCell.getColumnPosition(), dCRowPos, dataCell.getColumnSpan(), actualRowSpan); |
| ILayerCell cell = new LayerCell(spanningDataLayer, underlyingColumnPosition, underlyingRowPosition, dataCell); |
| if (cell != null) { |
| cell = new TranslatedLayerCell(cell, this, |
| underlyingToLocalColumnPosition(this.underlyingLayer, cell.getOriginColumnPosition()), |
| underlyingToLocalRowPosition(this.underlyingLayer, cell.getOriginRowPosition()), |
| underlyingToLocalColumnPosition(this.underlyingLayer, cell.getColumnPosition()), |
| underlyingToLocalRowPosition(this.underlyingLayer, cell.getRowPosition())); |
| } |
| return cell; |
| } |
| }; |
| final SelectionLayer selectionLayer = new SelectionLayer(rowExpandCollapseLayer); |
| final ViewportLayer viewportLayer = new ViewportLayer(selectionLayer); |
| |
| // Column header |
| final DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(entry.getValue().getColumnHeaderDataProvider()); |
| final ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer); |
| |
| // Row header |
| final DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(entry.getValue().getRowHeaderDataProvider()); |
| final RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, viewportLayer, selectionLayer, false); |
| rowHeaderLayer.addConfiguration(new RowHeaderConfiguration()); |
| final RowGroupHeaderLayer rowGroupHeaderLayer = new RowGroupHeaderLayer(rowHeaderLayer, selectionLayer, false); |
| rowGroupHeaderLayer.addConfiguration(new DefaultRowGroupHeaderLayerConfiguration(true)); |
| rowGroupHeaderLayer.setColumnWidth(20); |
| |
| entry.getValue().initializeGroups(rowGroupHeaderLayer); |
| |
| // Corner header |
| final DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(entry.getValue().getColumnHeaderDataProvider(), |
| entry.getValue().getRowHeaderDataProvider()); |
| final CornerLayer cornerLayer = new CornerLayer(new DataLayer(cornerDataProvider), rowGroupHeaderLayer, columnHeaderLayer); |
| |
| final GridLayer gridLayer = new GridLayer(viewportLayer, columnHeaderLayer, rowGroupHeaderLayer, cornerLayer); |
| final NatTable natTable = new NatTable(this.cTabFolder, gridLayer, false); |
| natTable.addConfiguration(new DefaultNatTableStyleConfiguration()); |
| natTable.addConfiguration(new HeaderMenuConfiguration(natTable)); |
| natTable.configure(); |
| natTable.setTheme(new ModernNatTableThemeConfiguration()); |
| item.setControl(natTable); |
| } |
| } |
| |
| @Override |
| public void setFocus() { |
| if (this.cTabFolder != null) { |
| this.cTabFolder.forceFocus(); |
| } |
| } |
| } |