blob: 5228ed48270ec3bcbce4ca7eb804515dda8ea4da [file] [log] [blame]
/**
********************************************************************************
* 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();
}
}
}