/******************************************************************************* * Copyright (c) 2016 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * 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(); } }