blob: 5c7ac55b67db3d3cbdf09662ac8d1b520842124b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Ericsson
*
* 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
*
* Contributors:
* Patrick Tasse - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.tmf.ui.viewers.events;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
import org.eclipse.tracecompass.tmf.core.filter.ITmfFilter;
import org.eclipse.tracecompass.tmf.core.filter.model.ITmfFilterTreeNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterRootNode;
/**
* Header bar for the events table.
*
* @since 2.0
*/
public class TmfEventsTableHeader extends Composite {
private static final Image COLLAPSED = Activator.getDefault().getImageFromPath("icons/ovr16/collapsed_ovr.gif"); //$NON-NLS-1$
private static final Image EXPANDED = Activator.getDefault().getImageFromPath("icons/ovr16/expanded_ovr.gif"); //$NON-NLS-1$
private static final Image DELETE = Activator.getDefault().getImageFromPath("icons/elcl16/delete_button.gif"); //$NON-NLS-1$
private static final Image DELETE_SMALL = Activator.getDefault().getImageFromPath("icons/ovr16/delete_ovr.gif"); //$NON-NLS-1$
private static final int DEFAULT_MARGIN = 3;
private static final int COLLAPSED_IMAGE_MARGIN = 2;
private static final int COLLAPSED_RIGHT_MARGIN = 32;
private static final RGB LABEL_BACKGROUND = new RGB(255, 255, 192);
private static final String TOOLTIP_KEY = "toolTip"; //$NON-NLS-1$
/**
* Interface for header bar call-backs.
*/
public interface IEventsTableHeaderListener {
/**
* A filter has been selected.
*
* @param filter
* the selected filter
*/
void filterSelected(ITmfFilter filter);
/**
* A filter has been removed.
*
* @param filter
* the removed filter
*/
void filterRemoved(ITmfFilter filter);
}
private final IEventsTableHeaderListener fListener;
private final RowLayout fLayout;
private final Color fLabelBackground;
private boolean fCollapsed = false;
/**
* Constructor
*
* @param parent
* the parent composite
* @param style
* the style of widget to construct
* @param listener
* the listener to the header bar events
*/
public TmfEventsTableHeader(Composite parent, int style, IEventsTableHeaderListener listener) {
super(parent, style);
fListener = listener;
fLayout = new RowLayout();
fLayout.marginTop = 0;
fLayout.marginBottom = 0;
fLayout.marginLeft = EXPANDED.getBounds().width;
setLayout(fLayout);
fLabelBackground = new Color(getDisplay(), LABEL_BACKGROUND);
getParent().addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
getParent().layout();
}
});
addPaintListener(e -> {
if (fCollapsed) {
e.gc.drawImage(COLLAPSED, 0, 0);
} else {
e.gc.drawImage(EXPANDED, 0, 0);
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
toggle();
}
});
addDisposeListener((e) -> {
fLabelBackground.dispose();
});
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
int height = fCollapsed && getChildren().length > 0 ? EXPANDED.getBounds().height : hHint;
return super.computeSize(getParent().getSize().x, height, changed);
}
/**
* Add a filter to the header.
*
* @param filter
* the filter to add
*/
public void addFilter(ITmfFilter filter) {
if (filter instanceof TmfFilterRootNode) {
TmfFilterRootNode parentFilter = (TmfFilterRootNode) filter;
for (ITmfFilterTreeNode childFilter : parentFilter.getChildren()) {
addNewFilter(childFilter);
}
} else {
addNewFilter(filter);
}
fLayout.marginTop = 1;
fLayout.marginBottom = 1;
getParent().layout(true, true);
}
/**
* Remove a filter from the header.
*
* @param filter
* the filter to remove
*/
public void removeFilter(ITmfFilter filter) {
for (Control control : getChildren()) {
if (filter.equals(control.getData())) {
control.dispose();
break;
}
}
if (getChildren().length == 0) {
fLayout.marginTop = 0;
fLayout.marginBottom = 0;
}
getParent().layout(true, true);
}
/**
* Clear all filters in the header.
*/
public void clearFilters() {
for (Control control : getChildren()) {
control.dispose();
}
fLayout.marginTop = 0;
fLayout.marginBottom = 0;
getParent().layout(true, true);
}
private void addNewFilter(ITmfFilter filter) {
CLabel label = new CLabel(this, SWT.SHADOW_OUT);
label.setBackground(fLabelBackground);
String text;
if (filter instanceof TmfFilterNode) {
text = ((TmfFilterNode) filter).getFilterName();
label.setData(TOOLTIP_KEY, filter.toString());
} else {
text = filter.toString();
}
if (fCollapsed) {
label.setToolTipText(text);
label.setTopMargin(0);
label.setBottomMargin(0);
label.setRightMargin(COLLAPSED_RIGHT_MARGIN);
} else {
label.setImage(DELETE);
label.setText(text);
label.setToolTipText((String) label.getData(TOOLTIP_KEY));
}
label.setData(filter);
label.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
Rectangle bounds;
if (fCollapsed) {
bounds = new Rectangle(0, 0, 2 * COLLAPSED_IMAGE_MARGIN + DELETE_SMALL.getBounds().width, label.getBounds().height);
} else {
bounds = DELETE.getBounds();
bounds.x += label.getLeftMargin();
bounds.y = (label.getSize().y - bounds.height) / 2;
}
if (bounds.contains(e.x, e.y)) {
fListener.filterRemoved((ITmfFilter) label.getData());
} else {
fListener.filterSelected((ITmfFilter) label.getData());
getParent().layout(true, true);
}
}
});
label.addPaintListener(e -> {
if (fCollapsed) {
e.gc.drawImage(DELETE_SMALL, COLLAPSED_IMAGE_MARGIN, COLLAPSED_IMAGE_MARGIN);
}
});
}
private void toggle() {
fCollapsed = !fCollapsed;
for (Control child : getChildren()) {
if (child instanceof CLabel) {
CLabel label = (CLabel) child;
if (fCollapsed) {
label.setImage(null);
label.setToolTipText(label.getText());
label.setText(null);
label.setMargins(DEFAULT_MARGIN, 0, COLLAPSED_RIGHT_MARGIN, 0);
} else {
label.setImage(DELETE);
label.setText(label.getToolTipText());
label.setToolTipText((String) label.getData(TOOLTIP_KEY));
label.setMargins(DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN);
}
}
}
getParent().layout();
}
}