Import views plugins
[deliverable/tracecompass.git] / tmf / org.lttng.scope.tmf2.views.ui / src / org / lttng / scope / tmf2 / views / ui / timeline / widgets / timegraph / toolbar / modelconfig / ModelConfigDialog.java
1 /*
2 * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com>
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
10 package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.toolbar.modelconfig;
11
12 import java.util.Arrays;
13 import java.util.List;
14 import java.util.stream.Collectors;
15
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.lttng.scope.tmf2.views.core.config.ConfigOption;
18 import org.lttng.scope.tmf2.views.core.timegraph.model.provider.states.ITimeGraphModelStateProvider;
19 import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition;
20 import org.lttng.scope.tmf2.views.core.timegraph.model.render.LineThickness;
21 import org.lttng.scope.tmf2.views.core.timegraph.model.render.StateDefinition;
22 import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.MultiStateInterval;
23 import org.lttng.scope.tmf2.views.ui.jfx.CountingGridPane;
24 import org.lttng.scope.tmf2.views.ui.jfx.JfxColorFactory;
25 import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.StateRectangle;
26 import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.TimeGraphWidget;
27
28 import javafx.beans.property.ReadOnlyProperty;
29 import javafx.event.ActionEvent;
30 import javafx.scene.Node;
31 import javafx.scene.control.ButtonBar.ButtonData;
32 import javafx.scene.control.ButtonType;
33 import javafx.scene.control.ColorPicker;
34 import javafx.scene.control.Dialog;
35 import javafx.scene.control.Label;
36 import javafx.scene.control.MenuButton;
37 import javafx.scene.control.RadioMenuItem;
38 import javafx.scene.control.ToggleGroup;
39 import javafx.scene.paint.Color;
40 import javafx.scene.paint.Paint;
41 import javafx.scene.shape.Rectangle;
42 import javafx.scene.text.Text;
43
44 class ModelConfigDialog extends Dialog<@Nullable Void> {
45
46 private static final double H_GAP = 10;
47
48 public ModelConfigDialog(TimeGraphWidget widget) {
49 setTitle(Messages.modelConfigDialogTitle);
50 setHeaderText(Messages.modelConfigDialogHeader);
51
52 ButtonType resetToDefaultButtonType = new ButtonType(Messages.modelConfigDialogResetDefaultsButton, ButtonData.LEFT);
53 getDialogPane().getButtonTypes().addAll(resetToDefaultButtonType, ButtonType.CLOSE);
54
55 // TODO Allow configuring arrow, etc. providers too (different tabs?)
56 ITimeGraphModelStateProvider stateProvider = widget.getControl().getModelRenderProvider().getStateProvider();
57 List<ColorDefControl> stateControls = stateProvider.getStateDefinitions().stream()
58 .map(stateDef -> new ColorDefControl(widget, stateDef))
59 .collect(Collectors.toList());
60
61 /* Setup the GridPane which will be the contents of the dialog */
62 CountingGridPane grid = new CountingGridPane();
63 grid.setHgap(H_GAP);
64 /* Header row */
65 grid.appendRow(new Text(Messages.modelConfigDialogRowHeaderState),
66 new Text(Messages.modelConfigDialogRowHeaderColor),
67 new Text(Messages.modelConfigDialogRowHeaderLineThickness));
68
69 stateControls.forEach(setter -> grid.appendRow(setter.getNodes()));
70
71 /* Add an "empty row", then the control for multi-state intervals */
72 LineThicknessMenuButton multiStateThicknessButton = new LineThicknessMenuButton(widget,
73 MultiStateInterval.MULTI_STATE_THICKNESS_OPTION,
74 widget.getDebugOptions().multiStatePaint);
75 grid.appendRow(new Text("")); //$NON-NLS-1$
76 grid.appendRow(new Label("Multi-states"), new Text(), multiStateThicknessButton);
77
78 getDialogPane().setContent(grid);
79
80 /*
81 * We do not set the dialog's 'resultConverter', there is nothing
82 * special to do on close (all changes are immediately valid).
83 */
84
85 /* Define how to "Reset Defaults" button works */
86 getDialogPane().lookupButton(resetToDefaultButtonType).addEventFilter(ActionEvent.ACTION, e -> {
87 /*
88 * This button should not close the dialog. Consuming the event here
89 * will prevent the dialog from closing.
90 */
91 e.consume();
92
93 stateControls.forEach(sc -> {
94 sc.getOptions().forEach(ConfigOption::resetToDefault);
95 sc.load();
96 });
97 multiStateThicknessButton.getOption().resetToDefault();
98 multiStateThicknessButton.load();
99
100 repaintAllRectangles(widget);
101 });
102
103 }
104
105 // TODO Repaint the rectangles of the whole Timeline view, not just 1 widget
106 private static void repaintAllRectangles(TimeGraphWidget widget) {
107 widget.getRenderedStateRectangles().forEach(StateRectangle::updatePaint);
108 }
109
110 private static class ColorDefControl {
111
112 private final TimeGraphWidget fWidget;
113 private final StateDefinition fStateDef;
114
115 private final Label fLabel;
116 private final ColorPicker fColorPicker;
117 private final LineThicknessMenuButton fLineThicknessButton;
118
119 /**
120 * Constructor
121 *
122 * TODO Use a "PaintPicker" dialog instead, so a full Paint object can
123 * be configured from the UI. There is apparently one in SceneBuilder.
124 */
125 public ColorDefControl(TimeGraphWidget widget, StateDefinition stateDef) {
126 fWidget = widget;
127 fStateDef = stateDef;
128
129 fLabel = new Label(stateDef.getName());
130 fColorPicker = new ColorPicker();
131 fColorPicker.getStyleClass().add(ColorPicker.STYLE_CLASS_BUTTON);
132 fLineThicknessButton = new LineThicknessMenuButton(widget, stateDef.getLineThickness(), fColorPicker.valueProperty());
133 load();
134
135 /*
136 * Whenever a new color is selected in the UI, update the
137 * corresponding model color.
138 */
139 fColorPicker.setOnAction(e -> {
140 Color color = fColorPicker.getValue();
141 if (color == null) {
142 return;
143 }
144 ColorDefinition colorDef = JfxColorFactory.colorToColorDef(color);
145 fStateDef.getColor().set(colorDef);
146
147 repaintAllRectangles(widget);
148 });
149
150 }
151
152 public Node[] getNodes() {
153 return new Node[] { fLabel, fColorPicker, fLineThicknessButton };
154 }
155
156 public Iterable<ConfigOption<?>> getOptions() {
157 return Arrays.asList(fStateDef.getColor(), fStateDef.getLineThickness());
158 }
159
160 public void load() {
161 Color color = JfxColorFactory.getColorFromDef(fStateDef.getColor().get());
162 fColorPicker.setValue(color);
163
164 fLineThicknessButton.load();
165 }
166 }
167
168 private static class LineThicknessMenuButton extends MenuButton {
169
170 private static final double RECTANGLE_WIDTH = 30;
171
172 private final ConfigOption<LineThickness> fOption;
173 private final ReadOnlyProperty<? extends Paint> fColorSource;
174
175 public LineThicknessMenuButton(TimeGraphWidget widget,
176 ConfigOption<LineThickness> option,
177 ReadOnlyProperty<? extends Paint> colorSource) {
178 fOption = option;
179 fColorSource = colorSource;
180
181 ToggleGroup tg = new ToggleGroup();
182 List<LineThicknessMenuButtonItem> items = Arrays.stream(LineThickness.values())
183 .map(lt -> {
184 LineThicknessMenuButtonItem rmi = new LineThicknessMenuButtonItem(lt);
185 rmi.setGraphic(getRectangleForThickness(lt));
186 rmi.setToggleGroup(tg);
187
188 LineThickness currentThickness = option.get();
189 rmi.setSelected(lt == currentThickness);
190
191 rmi.setOnAction(e -> {
192 option.set(lt);
193 LineThicknessMenuButton.this.setGraphic(getRectangleForThickness(lt));
194 repaintAllRectangles(widget);
195 });
196 return rmi;
197 })
198 .collect(Collectors.toList());
199
200 /* Initial value shown in the button */
201 setGraphic(getRectangleForThickness(option.get()));
202 getItems().addAll(items);
203 }
204
205 private Rectangle getRectangleForThickness(LineThickness lt) {
206 Rectangle rectangle = new Rectangle(RECTANGLE_WIDTH, StateRectangle.getHeightFromThickness(lt));
207 rectangle.fillProperty().bind(fColorSource);
208 return rectangle;
209 }
210
211 public ConfigOption<LineThickness> getOption() {
212 return fOption;
213 }
214
215 public void load() {
216 LineThickness lt = fOption.get();
217 setGraphic(getRectangleForThickness(lt));
218 getItems().stream()
219 .map(item -> (LineThicknessMenuButtonItem) item)
220 .filter(item -> item.getLineThickness() == lt)
221 .findFirst().get().setSelected(true);
222 }
223 }
224
225 private static class LineThicknessMenuButtonItem extends RadioMenuItem {
226
227 private final LineThickness fLineThickness;
228
229 public LineThicknessMenuButtonItem(LineThickness lt) {
230 fLineThickness = lt;
231 }
232
233 public LineThickness getLineThickness() {
234 return fLineThickness;
235 }
236 }
237
238 }
This page took 0.035715 seconds and 5 git commands to generate.