blob: b50f20ba7fa58a143ac4837f373317258a6f664d [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2020 Draeger, Auriga
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.tracecompass.incubator.internal.tmf.ui.multiview.ui.view.xychart;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.tracecompass.incubator.internal.tmf.ui.multiview.ui.view.IMultiViewer;
import org.eclipse.tracecompass.incubator.internal.tmf.ui.multiview.ui.view.MultiView;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal;
import org.eclipse.tracecompass.tmf.ui.viewers.ILegendImageProvider;
import org.eclipse.tracecompass.tmf.ui.viewers.TmfTimeViewer;
import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer;
import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractSelectTreeViewer;
import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfXYChartViewer;
import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.XYChartLegendImageProvider;
import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfCommonXAxisChartViewer;
import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfFilteredXYChartViewer;
import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfXYChartSettings;
import org.eclipse.tracecompass.tmf.ui.views.ManyEntriesSelectedDialogPreCheckedListener;
import org.eclipse.tracecompass.tmf.ui.views.TmfChartView;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.TriStateFilteredCheckboxTree;
/**
* The viewer corresponding to the {@link TmfChartView} to be used with the
* {@link MultiView}.
*
* @author Ivan Grinenko
*
*/
public class ChartMultiViewer extends TmfTimeViewer implements IMultiViewer {
private static final int[] DEFAULT_WEIGHTS = {1, 3};
private final SashForm fSashForm;
private final TreeViewer fLeftViewer;
/** The TMF XY Chart reference */
private final TmfXYChartViewer fChartViewer;
/** A composite that allows us to add margins */
private final Composite fXYViewerContainer;
/**
* Constructor.
*
* @param parent
* parent for the viewer
* @param leftViewerProviderId
* provider ID for the left viewer
* @param chartProviderId
* provider ID for the chart
*/
public ChartMultiViewer(Composite parent, String leftViewerProviderId, String chartProviderId) {
super(parent);
fSashForm = new SashForm(parent, SWT.NONE);
fLeftViewer = new TreeViewer(fSashForm, leftViewerProviderId);
fXYViewerContainer = new Composite(fSashForm, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
fXYViewerContainer.setLayout(layout);
fChartViewer = new TmfFilteredXYChartViewer(fXYViewerContainer, new TmfXYChartSettings("", "", "", 1), chartProviderId); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
fChartViewer.setTimeAxisVisible(false);
fChartViewer.setSendTimeAlignSignals(true);
fChartViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
fChartViewer.getSwtChart().getAxisSet().getXAxis(0).getTick().setVisible(false);
fChartViewer.getControl().addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
// Sashes in a SashForm are being created on layout so add the
// drag listener here
for (Control control : fSashForm.getChildren()) {
if (control instanceof Sash) {
control.removePaintListener(this);
control.addListener(SWT.Selection, event -> TmfSignalManager.dispatchSignal(
new TmfTimeViewAlignmentSignal(fSashForm, getTimeViewAlignmentInfo())));
// There should be only one sash
break;
}
}
}
});
fSashForm.setWeights(DEFAULT_WEIGHTS);
coupleSelectViewer();
}
@Override
public Control getControl() {
return fSashForm;
}
@Override
public void dispose() {
super.dispose();
fLeftViewer.dispose();
fSashForm.dispose();
}
@Override
public void refresh() {
fLeftViewer.refresh();
fChartViewer.refresh();
}
@Override
public void loadTrace(ITmfTrace trace) {
super.loadTrace(trace);
fLeftViewer.loadTrace(trace);
fChartViewer.loadTrace(trace);
}
@Override
public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
if (fChartViewer == null) {
return null;
}
return new TmfTimeViewAlignmentInfo(fChartViewer.getControl().getShell(), fSashForm.toDisplay(0, 0), getTimeAxisOffset());
}
@Override
public int getAvailableWidth(int requestedOffset) {
if (fChartViewer == null) {
return 0;
}
int pointAreaWidth = fChartViewer.getPointAreaWidth();
int curTimeAxisOffset = getTimeAxisOffset();
if (pointAreaWidth <= 0) {
pointAreaWidth = fSashForm.getBounds().width - curTimeAxisOffset;
}
int endOffset = curTimeAxisOffset + pointAreaWidth;
GridLayout layout = (GridLayout) fXYViewerContainer.getLayout();
int endOffsetWithoutMargin = endOffset + layout.marginRight;
int availableWidth = endOffsetWithoutMargin - requestedOffset;
availableWidth = Math.min(fSashForm.getBounds().width, Math.max(0, availableWidth));
return availableWidth;
}
@Override
public void performAlign(int offset, int width) {
int total = fSashForm.getBounds().width;
int plotAreaOffset = fChartViewer.getPointAreaOffset();
int width1 = Math.max(0, offset - plotAreaOffset - fSashForm.getSashWidth());
int width2 = Math.max(0, total - width1 - fSashForm.getSashWidth());
if (width1 >= 0 && width2 > 0 || width1 > 0 && width2 >= 0) {
fSashForm.setWeights(new int[] { width1, width2 });
fSashForm.layout();
}
Composite composite = fXYViewerContainer;
GridLayout layout = (GridLayout) composite.getLayout();
int timeAxisWidth = getAvailableWidth(offset);
int marginSize = timeAxisWidth - width;
layout.marginRight = Math.max(0, marginSize);
composite.layout();
}
/**
* Sets status line manager for the chart viewer.
*
* @param statusLineManager
* status line manager for the chart viewer
*/
public void setStatusLineManager(IStatusLineManager statusLineManager) {
fChartViewer.setStatusLineManager(statusLineManager);
}
/**
* Returns the TMF XY chart viewer implementation.
*
* @return the TMF XY chart viewer {@link TmfXYChartViewer}
*/
public TmfXYChartViewer getChartViewer() {
return fChartViewer;
}
/**
* Returns the left TMF viewer implementation.
*
* @return the left TMF viewer {@link TmfViewer}
*/
public TmfViewer getLeftChildViewer() {
return fLeftViewer;
}
/**
* Method to couple {@link AbstractSelectTreeViewer} and
* {@link TmfFilteredXYChartViewer} so that they use the same legend and
* that the chart listens to selected items in the tree
*/
private void coupleSelectViewer() {
TmfViewer tree = fLeftViewer;
TmfXYChartViewer chart = fChartViewer;
if (tree instanceof AbstractSelectTreeViewer && chart instanceof TmfFilteredXYChartViewer) {
ILegendImageProvider legendImageProvider = new XYChartLegendImageProvider((TmfCommonXAxisChartViewer) chart);
AbstractSelectTreeViewer selectTree = (AbstractSelectTreeViewer) tree;
selectTree.setTreeListener((TmfFilteredXYChartViewer) chart);
selectTree.setLegendImageProvider(legendImageProvider);
TriStateFilteredCheckboxTree checkboxTree = selectTree.getTriStateFilteredCheckboxTree();
checkboxTree.addPreCheckStateListener(new ManyEntriesSelectedDialogPreCheckedListener(checkboxTree));
}
}
private int getTimeAxisOffset() {
return fSashForm.getChildren()[0].getSize().x + fSashForm.getSashWidth() + fChartViewer.getPointAreaOffset();
}
}