Commit | Line | Data |
---|---|---|
4bcc4ed6 | 1 | /******************************************************************************* |
60ae41e1 | 2 | * Copyright (c) 2013, 2014 Ericsson |
4bcc4ed6 BH |
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 | * Bernd Hufmann - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
2bdf0193 | 13 | package org.eclipse.tracecompass.tmf.ui.viewers.xycharts; |
4bcc4ed6 | 14 | |
a9ad9bdc | 15 | import org.eclipse.swt.SWT; |
4bcc4ed6 BH |
16 | import org.eclipse.swt.events.MouseEvent; |
17 | import org.eclipse.swt.events.MouseWheelListener; | |
18 | import org.swtchart.IAxis; | |
a9ad9bdc | 19 | import org.swtchart.Range; |
4bcc4ed6 BH |
20 | |
21 | /** | |
60f47dc3 MK |
22 | * Class for providing zooming and scrolling based on mouse wheel. For zooming, |
23 | * it centers the zoom on mouse position. For scrolling, it will move the zoom | |
24 | * window to another position while maintaining the window size. It also | |
25 | * notifies the viewer about a change of range. | |
4bcc4ed6 BH |
26 | * |
27 | * @author Bernd Hufmann | |
4bcc4ed6 BH |
28 | */ |
29 | public class TmfMouseWheelZoomProvider extends TmfBaseProvider implements MouseWheelListener { | |
30 | ||
31 | // ------------------------------------------------------------------------ | |
32 | // Constants | |
33 | // ------------------------------------------------------------------------ | |
574f43ad MK |
34 | private static final double ZOOM_FACTOR = 0.8; |
35 | private static final long MIN_WINDOW_SIZE = 1; | |
4bcc4ed6 BH |
36 | |
37 | // ------------------------------------------------------------------------ | |
38 | // Constructors | |
39 | // ------------------------------------------------------------------------ | |
40 | /** | |
41 | * Standard constructor. | |
42 | * | |
43 | * @param tmfChartViewer | |
44 | * The parent histogram object | |
45 | */ | |
46 | public TmfMouseWheelZoomProvider(ITmfChartTimeProvider tmfChartViewer) { | |
47 | super(tmfChartViewer); | |
48 | register(); | |
49 | } | |
50 | ||
51 | // ------------------------------------------------------------------------ | |
52 | // TmfBaseProvider | |
53 | // ------------------------------------------------------------------------ | |
54 | @Override | |
55 | public void register() { | |
56 | getChart().getPlotArea().addMouseWheelListener(this); | |
57 | } | |
58 | ||
59 | @Override | |
60 | public void deregister() { | |
61 | if ((getChartViewer().getControl() != null) && !getChartViewer().getControl().isDisposed()) { | |
62 | getChart().getPlotArea().removeMouseWheelListener(this); | |
63 | } | |
64 | } | |
65 | ||
66 | @Override | |
67 | public void refresh() { | |
68 | // nothing to do | |
69 | } | |
70 | ||
71 | // ------------------------------------------------------------------------ | |
72 | // MouseWheelListener | |
73 | // ------------------------------------------------------------------------ | |
74 | @Override | |
75 | public synchronized void mouseScrolled(MouseEvent event) { | |
76 | ITmfChartTimeProvider viewer = getChartViewer(); | |
77 | ||
a9ad9bdc | 78 | final int count = event.count; |
60f47dc3 MK |
79 | if (count != 0) { |
80 | if ((event.stateMask & SWT.CTRL) != 0) { | |
81 | final int x = event.x; | |
82 | zoom(viewer, count, x); | |
83 | } else if ((event.stateMask & SWT.SHIFT) != 0) { | |
84 | scroll(viewer, count); | |
85 | } | |
4bcc4ed6 | 86 | } |
a9ad9bdc | 87 | } |
4bcc4ed6 | 88 | |
60f47dc3 MK |
89 | private void scroll(ITmfChartTimeProvider viewer, int count) { |
90 | IAxis xAxis = getChart().getAxisSet().getXAxis(0); | |
91 | ||
92 | long windowStartTime = viewer.getWindowStartTime(); | |
93 | long windowsEndTime = viewer.getWindowEndTime(); | |
94 | ||
95 | long startTime = viewer.getStartTime(); | |
96 | long endTime = viewer.getEndTime(); | |
97 | ||
98 | long range = windowsEndTime - windowStartTime; | |
99 | if (range <= 0) { | |
100 | return; | |
101 | } | |
102 | long increment = Math.max(1, range / 2); | |
103 | if (count > 0) { | |
104 | windowStartTime = Math.max(windowStartTime - increment, startTime); | |
105 | windowsEndTime = windowStartTime + range; | |
106 | } else { | |
107 | windowsEndTime = Math.min(windowsEndTime + increment, endTime); | |
108 | windowStartTime = windowsEndTime - range; | |
109 | } | |
110 | viewer.updateWindow(windowStartTime, windowsEndTime); | |
111 | xAxis.setRange(new Range(windowStartTime - viewer.getTimeOffset(), windowsEndTime - viewer.getTimeOffset())); | |
112 | } | |
113 | ||
a9ad9bdc | 114 | private void zoom(ITmfChartTimeProvider viewer, final int count, final int x) { |
4bcc4ed6 | 115 | // Compute the new time range |
a9ad9bdc MK |
116 | long newDuration = viewer.getWindowDuration(); |
117 | if (newDuration == 0 || count == 0) { | |
118 | return; | |
119 | } | |
4bcc4ed6 | 120 | double ratio = 1.0; |
a9ad9bdc | 121 | if (count > 0) { |
4bcc4ed6 | 122 | ratio = ZOOM_FACTOR; |
a9ad9bdc | 123 | newDuration = Math.round(ZOOM_FACTOR * newDuration); |
4bcc4ed6 BH |
124 | } else { |
125 | ratio = 1.0 / ZOOM_FACTOR; | |
a9ad9bdc | 126 | newDuration = (long) Math.ceil(newDuration * ratio); |
4bcc4ed6 BH |
127 | } |
128 | newDuration = Math.max(MIN_WINDOW_SIZE, newDuration); | |
129 | ||
60f47dc3 MK |
130 | // Center the zoom on mouse position, distribute new duration and adjust |
131 | // for boundaries. | |
4bcc4ed6 | 132 | IAxis xAxis = getChart().getAxisSet().getXAxis(0); |
a9ad9bdc | 133 | long timeAtXPos = limitXDataCoordinate(xAxis.getDataCoordinate(x)) + viewer.getTimeOffset(); |
4bcc4ed6 BH |
134 | // Note: ratio = newDuration/oldDuration |
135 | long newWindowStartTime = timeAtXPos - Math.round(ratio * (timeAtXPos - viewer.getWindowStartTime())); | |
136 | long newWindowEndTime = validateWindowEndTime(newWindowStartTime, newWindowStartTime + newDuration); | |
137 | newWindowStartTime = validateWindowStartTime(newWindowStartTime); | |
138 | viewer.updateWindow(newWindowStartTime, newWindowEndTime); | |
a9ad9bdc | 139 | xAxis.setRange(new Range(newWindowStartTime - viewer.getTimeOffset(), |
60f47dc3 | 140 | newWindowEndTime - viewer.getTimeOffset())); |
4bcc4ed6 BH |
141 | } |
142 | ||
143 | // ------------------------------------------------------------------------ | |
144 | // Helper methods | |
145 | // ------------------------------------------------------------------------ | |
146 | private long validateWindowStartTime(long start) { | |
147 | ITmfChartTimeProvider viewer = getChartViewer(); | |
148 | long realStart = start; | |
149 | ||
150 | long startTime = viewer.getStartTime(); | |
151 | long endTime = viewer.getEndTime(); | |
152 | ||
153 | if (realStart < startTime) { | |
154 | realStart = startTime; | |
155 | } | |
156 | if (realStart > endTime) { | |
157 | realStart = endTime; | |
158 | } | |
159 | return realStart; | |
160 | } | |
161 | ||
162 | private long validateWindowEndTime(long start, long end) { | |
163 | ITmfChartTimeProvider viewer = getChartViewer(); | |
164 | long realEnd = end; | |
165 | long endTime = viewer.getEndTime(); | |
166 | ||
167 | if (realEnd > endTime) { | |
168 | realEnd = endTime; | |
169 | } | |
170 | if (realEnd < start + MIN_WINDOW_SIZE) { | |
171 | realEnd = start + MIN_WINDOW_SIZE; | |
172 | } | |
173 | return realEnd; | |
174 | } | |
175 | } |