Commit | Line | Data |
---|---|---|
0a08e17d PT |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 Ericsson | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * Patrick Tasse - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.tracecompass.tmf.ui.viewers.events; | |
14 | ||
15 | import org.eclipse.swt.SWT; | |
16 | import org.eclipse.swt.custom.CLabel; | |
17 | import org.eclipse.swt.events.ControlAdapter; | |
18 | import org.eclipse.swt.events.ControlEvent; | |
19 | import org.eclipse.swt.events.MouseAdapter; | |
20 | import org.eclipse.swt.events.MouseEvent; | |
21 | import org.eclipse.swt.graphics.Color; | |
22 | import org.eclipse.swt.graphics.Image; | |
23 | import org.eclipse.swt.graphics.Point; | |
24 | import org.eclipse.swt.graphics.RGB; | |
25 | import org.eclipse.swt.graphics.Rectangle; | |
26 | import org.eclipse.swt.layout.RowLayout; | |
27 | import org.eclipse.swt.widgets.Composite; | |
28 | import org.eclipse.swt.widgets.Control; | |
29 | import org.eclipse.tracecompass.internal.tmf.ui.Activator; | |
30 | import org.eclipse.tracecompass.tmf.core.filter.ITmfFilter; | |
31 | import org.eclipse.tracecompass.tmf.core.filter.model.ITmfFilterTreeNode; | |
32 | import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterNode; | |
33 | import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterRootNode; | |
34 | ||
35 | /** | |
36 | * Header bar for the events table. | |
37 | * | |
38 | * @since 2.0 | |
39 | */ | |
40 | public class TmfEventsTableHeader extends Composite { | |
41 | ||
42 | private static final Image COLLAPSED = Activator.getDefault().getImageFromPath("icons/ovr16/collapsed_ovr.gif"); //$NON-NLS-1$ | |
43 | private static final Image EXPANDED = Activator.getDefault().getImageFromPath("icons/ovr16/expanded_ovr.gif"); //$NON-NLS-1$ | |
44 | private static final Image DELETE = Activator.getDefault().getImageFromPath("icons/elcl16/delete_button.gif"); //$NON-NLS-1$ | |
45 | private static final Image DELETE_SMALL = Activator.getDefault().getImageFromPath("icons/ovr16/delete_ovr.gif"); //$NON-NLS-1$ | |
46 | private static final int DEFAULT_MARGIN = 3; | |
47 | private static final int COLLAPSED_IMAGE_MARGIN = 2; | |
48 | private static final int COLLAPSED_RIGHT_MARGIN = 32; | |
49 | private static final RGB LABEL_BACKGROUND = new RGB(255, 255, 192); | |
50 | private static final String TOOLTIP_KEY = "toolTip"; //$NON-NLS-1$ | |
51 | ||
52 | /** | |
53 | * Interface for header bar call-backs. | |
54 | */ | |
55 | public interface IEventsTableHeaderListener { | |
56 | /** | |
57 | * A filter has been selected. | |
58 | * | |
59 | * @param filter | |
60 | * the selected filter | |
61 | */ | |
62 | void filterSelected(ITmfFilter filter); | |
63 | ||
64 | /** | |
65 | * A filter has been removed. | |
66 | * | |
67 | * @param filter | |
68 | * the removed filter | |
69 | */ | |
70 | void filterRemoved(ITmfFilter filter); | |
71 | } | |
72 | ||
73 | private final IEventsTableHeaderListener fListener; | |
74 | private final RowLayout fLayout; | |
75 | private final Color fLabelBackground; | |
76 | private boolean fCollapsed = false; | |
77 | ||
78 | /** | |
79 | * Constructor | |
80 | * | |
81 | * @param parent | |
82 | * the parent composite | |
83 | * @param style | |
84 | * the style of widget to construct | |
85 | * @param listener | |
86 | * the listener to the header bar events | |
87 | */ | |
88 | public TmfEventsTableHeader(Composite parent, int style, IEventsTableHeaderListener listener) { | |
89 | super(parent, style); | |
90 | fListener = listener; | |
91 | fLayout = new RowLayout(); | |
92 | fLayout.marginTop = 0; | |
93 | fLayout.marginBottom = 0; | |
94 | fLayout.marginLeft = EXPANDED.getBounds().width; | |
95 | setLayout(fLayout); | |
96 | fLabelBackground = new Color(getDisplay(), LABEL_BACKGROUND); | |
97 | getParent().addControlListener(new ControlAdapter() { | |
98 | @Override | |
99 | public void controlResized(ControlEvent e) { | |
100 | getParent().layout(); | |
101 | } | |
102 | }); | |
103 | addPaintListener(e -> { | |
104 | if (fCollapsed) { | |
105 | e.gc.drawImage(COLLAPSED, 0, 0); | |
106 | } else { | |
107 | e.gc.drawImage(EXPANDED, 0, 0); | |
108 | } | |
109 | }); | |
110 | addMouseListener(new MouseAdapter() { | |
111 | @Override | |
112 | public void mouseDown(MouseEvent e) { | |
113 | toggle(); | |
114 | } | |
115 | }); | |
116 | } | |
117 | ||
118 | @Override | |
119 | public void dispose() { | |
120 | super.dispose(); | |
121 | fLabelBackground.dispose(); | |
122 | } | |
123 | ||
124 | @Override | |
125 | public Point computeSize(int wHint, int hHint, boolean changed) { | |
126 | int height = fCollapsed && getChildren().length > 0 ? EXPANDED.getBounds().height : hHint; | |
127 | return super.computeSize(getParent().getSize().x, height, changed); | |
128 | } | |
129 | ||
130 | /** | |
131 | * Add a filter to the header. | |
132 | * | |
133 | * @param filter | |
134 | * the filter to add | |
135 | */ | |
136 | public void addFilter(ITmfFilter filter) { | |
137 | if (filter instanceof TmfFilterRootNode) { | |
138 | TmfFilterRootNode parentFilter = (TmfFilterRootNode) filter; | |
139 | for (ITmfFilterTreeNode childFilter : parentFilter.getChildren()) { | |
140 | addNewFilter(childFilter); | |
141 | } | |
142 | } else { | |
143 | addNewFilter(filter); | |
144 | } | |
145 | fLayout.marginTop = 1; | |
146 | fLayout.marginBottom = 1; | |
147 | getParent().layout(true, true); | |
148 | } | |
149 | ||
150 | /** | |
151 | * Remove a filter from the header. | |
152 | * | |
153 | * @param filter | |
154 | * the filter to remove | |
155 | */ | |
156 | public void removeFilter(ITmfFilter filter) { | |
157 | for (Control control : getChildren()) { | |
158 | if (filter.equals(control.getData())) { | |
159 | control.dispose(); | |
160 | break; | |
161 | } | |
162 | } | |
163 | if (getChildren().length == 0) { | |
164 | fLayout.marginTop = 0; | |
165 | fLayout.marginBottom = 0; | |
166 | } | |
167 | getParent().layout(true, true); | |
168 | } | |
169 | ||
170 | /** | |
171 | * Clear all filters in the header. | |
172 | */ | |
173 | public void clearFilters() { | |
174 | for (Control control : getChildren()) { | |
175 | control.dispose(); | |
176 | } | |
177 | fLayout.marginTop = 0; | |
178 | fLayout.marginBottom = 0; | |
179 | getParent().layout(true, true); | |
180 | } | |
181 | ||
182 | private void addNewFilter(ITmfFilter filter) { | |
183 | CLabel label = new CLabel(this, SWT.SHADOW_OUT); | |
184 | label.setBackground(fLabelBackground); | |
185 | String text; | |
186 | if (filter instanceof TmfFilterNode) { | |
187 | text = ((TmfFilterNode) filter).getFilterName(); | |
188 | label.setData(TOOLTIP_KEY, filter.toString()); | |
189 | } else { | |
190 | text = filter.toString(); | |
191 | } | |
192 | if (fCollapsed) { | |
193 | label.setToolTipText(text); | |
194 | label.setTopMargin(0); | |
195 | label.setBottomMargin(0); | |
196 | label.setRightMargin(COLLAPSED_RIGHT_MARGIN); | |
197 | } else { | |
198 | label.setImage(DELETE); | |
199 | label.setText(text); | |
200 | label.setToolTipText((String) label.getData(TOOLTIP_KEY)); | |
201 | } | |
202 | label.setData(filter); | |
203 | label.addMouseListener(new MouseAdapter() { | |
204 | @Override | |
205 | public void mouseDown(MouseEvent e) { | |
206 | Rectangle bounds; | |
207 | if (fCollapsed) { | |
208 | bounds = new Rectangle(0, 0, 2 * COLLAPSED_IMAGE_MARGIN + DELETE_SMALL.getBounds().width, label.getBounds().height); | |
209 | } else { | |
210 | bounds = DELETE.getBounds(); | |
211 | bounds.x += label.getLeftMargin(); | |
212 | bounds.y = (label.getSize().y - bounds.height) / 2; | |
213 | } | |
214 | if (bounds.contains(e.x, e.y)) { | |
215 | fListener.filterRemoved((ITmfFilter) label.getData()); | |
216 | } else { | |
217 | fListener.filterSelected((ITmfFilter) label.getData()); | |
218 | getParent().layout(true, true); | |
219 | } | |
220 | } | |
221 | }); | |
222 | label.addPaintListener(e -> { | |
223 | if (fCollapsed) { | |
224 | e.gc.drawImage(DELETE_SMALL, COLLAPSED_IMAGE_MARGIN, COLLAPSED_IMAGE_MARGIN); | |
225 | } | |
226 | }); | |
227 | } | |
228 | ||
229 | private void toggle() { | |
230 | fCollapsed = !fCollapsed; | |
231 | for (Control child : getChildren()) { | |
232 | if (child instanceof CLabel) { | |
233 | CLabel label = (CLabel) child; | |
234 | if (fCollapsed) { | |
235 | label.setImage(null); | |
236 | label.setToolTipText(label.getText()); | |
237 | label.setText(null); | |
238 | label.setMargins(DEFAULT_MARGIN, 0, COLLAPSED_RIGHT_MARGIN, 0); | |
239 | } else { | |
240 | label.setImage(DELETE); | |
241 | label.setText(label.getToolTipText()); | |
242 | label.setToolTipText((String) label.getData(TOOLTIP_KEY)); | |
243 | label.setMargins(DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN); | |
244 | } | |
245 | } | |
246 | } | |
247 | getParent().layout(); | |
248 | } | |
249 | } |