1
2
3
4 package de.desy.acop.video;
5
6 import java.awt.Dimension;
7 import java.awt.Point;
8 import java.awt.Rectangle;
9 import java.awt.Shape;
10 import java.awt.event.ComponentAdapter;
11 import java.awt.event.ComponentEvent;
12 import java.awt.event.MouseAdapter;
13 import java.awt.event.MouseEvent;
14 import java.awt.geom.GeneralPath;
15 import java.awt.geom.Line2D;
16 import java.awt.geom.Point2D;
17 import java.awt.geom.Rectangle2D;
18 import java.beans.PropertyChangeEvent;
19 import java.beans.PropertyChangeListener;
20 import java.beans.PropertyChangeSupport;
21
22 import javax.swing.JViewport;
23 import javax.swing.event.ChangeEvent;
24 import javax.swing.event.ChangeListener;
25
26 import de.desy.acop.video.analysis.AImage;
27 import de.desy.acop.video.analysis.ImageAnalysisEngine;
28 import de.desy.acop.video.displayer.ImageDisplayer;
29 import de.desy.acop.video.displayer.ImageZoom;
30 import de.desy.tine.types.IMAGE;
31 import de.desy.tine.types.IMAGE.FrameHeader;
32
33
34
35
36
37
38
39
40
41 public class DisplayerManager extends MouseAdapter {
42
43 public static final String PROPERTY_ON_SCREEN_ROI = "onScreenRoi";
44
45 private final ImageAnalysisEngine analysisEngine;
46 private final ImageDisplayer imageDisp;
47 private final SideProfileDisplayer horizontalDisp;
48 private final SideProfileDisplayer verticalDisp;
49
50 private PropertyChangeSupport pcSupport;
51
52 private ScaleHelper scaleHelper;
53 private ChangeListener viewPortListener;
54 private AImage aImage;
55
56 private Rectangle2D selectedRectangle;
57 private Rectangle2D thresholdRectangle;
58 private Rectangle2D draggingRectangle;
59 private Rectangle2D crossRect;
60 private Rectangle2D crossFitRect;
61 private Rectangle aoiRectangle;
62
63 private boolean dragStarted = false;
64 private Point2D p1 = null;
65 private Point2D p2 = null;
66 private Point2D viewPoint = new Point2D.Double();
67
68 private boolean canChangeSettings = false;
69
70 private boolean displayStatistics = true;
71
72 public DisplayerManager(ImageAnalysisEngine imageAnalysisEngine, ImageDisplayer imageDisplayer, SideProfileDisplayer horizontalDisplayer, SideProfileDisplayer verticalDisplayer) {
73 analysisEngine = imageAnalysisEngine;
74 imageDisp = imageDisplayer;
75 horizontalDisp = horizontalDisplayer;
76 verticalDisp = verticalDisplayer;
77
78 imageDisp.addMouseListener(this);
79 imageDisp.addMouseMotionListener(this);
80 imageDisp.addComponentListener(new ComponentAdapter() {
81 @Override
82 public void componentResized(ComponentEvent e) {
83 getScaleHelper().setComponentDimesnion(imageDisp.getSize());
84 }
85 });
86 imageDisp.addPropertyChangeListener(new PropertyChangeListener() {
87 @Override
88 public void propertyChange(PropertyChangeEvent evt) {
89 String name = evt.getPropertyName();
90 if (name == ImageDisplayer.PROPERTY_KEEP_ASPECT_RATIO) {
91 getScaleHelper().setKeepAspectRatio((Boolean) evt.getNewValue());
92 }
93 else if (name == ImageDisplayer.PROPERTY_AOI_ZOOM) {
94 getScaleHelper().setAoiZoom((Boolean) evt.getNewValue());
95 }
96 else if (name == ImageDisplayer.PROPERTY_IMAGE_ZOOM) {
97 getScaleHelper().setImageZoom((ImageZoom) evt.getNewValue());
98 }
99 }
100 });
101 }
102
103 public void setDisplayStatistics(boolean display) {
104 this.displayStatistics = display;
105 horizontalDisp.setDisplayStatistics(display);
106 verticalDisp.setDisplayStatistics(display);
107 }
108
109 public boolean isDisplayStatistics() {
110 return this.displayStatistics;
111 }
112
113 public void updateImageDisplayerSize(Dimension size) {
114 getScaleHelper().setComponentDimesnion(size);
115 }
116
117 public synchronized void updateAImage(AImage aImage) {
118 if (this.aImage == aImage) return;
119 boolean clean = true;
120 if (this.aImage != null && aImage != null) {
121 clean = this.aImage.getImageW() != aImage.getImageW() ||
122 this.aImage.getImageH() != aImage.getImageH();
123 }
124 this.aImage = aImage;
125 if (dragStarted && clean) {
126 p1 = null;
127 p2 = null;
128 dragStarted = false;
129 draggingRectangle = null;
130 horizontalDisp.clearRoi();
131 verticalDisp.clearRoi();
132 }
133 if (aImage == null) {
134 crossRect = null;
135 selectedRectangle = null;
136 getScaleHelper().setImageData(null, null);
137 imageDisp.resetForReceiving();
138 horizontalDisp.clearData();
139 verticalDisp.clearData();
140 return;
141 }
142
143 IMAGE im = aImage.getImage();
144 FrameHeader fh = im.getFrameHeader();
145 int offsetX = fh.xStart;
146 int offsetY = fh.yStart;
147 int sizeX = (fh.aoiWidth >= 0) ? fh.aoiWidth : fh.sourceWidth;
148 int sizeY = (fh.aoiHeight >= 0) ? fh.aoiHeight : fh.sourceHeight;
149
150 aoiRectangle = new Rectangle(offsetX, offsetY, sizeX, sizeY);
151 getScaleHelper().setImageData(new Dimension(fh.sourceWidth, fh.sourceHeight), aoiRectangle);
152
153 crossRect = new Rectangle2D.Double(aImage.getMeanX()-aImage.getStdX()/2, aImage.getMeanY()-aImage.getStdY()/2, aImage.getStdX(), aImage.getStdY());
154
155 selectedRectangle = new Rectangle2D.Double(aImage.getRoiX(), aImage.getRoiY(), aImage.getRoiW(), aImage.getRoiH());
156 if (aImage.isCalculateThreshold()) {
157 thresholdRectangle = new Rectangle2D.Double(aImage.getRoi2X(), aImage.getRoi2Y(), aImage.getRoi2W(), aImage.getRoi2H());
158 } else {
159 thresholdRectangle = null;
160 }
161
162 if (aImage.isPerformFit()) {
163 crossFitRect = new Rectangle2D.Double(aImage.getMeanXFit() - aImage.getStdXFit()/2, aImage.getMeanYFit()-aImage.getStdYFit()/2,aImage.getStdXFit(),aImage.getStdYFit());
164 } else {
165 crossFitRect = null;
166 }
167
168 imageDisp.updateValue(im);
169
170 adjustSideProfileAspectRatio(false);
171 horizontalDisp.setData(
172 aImage.getSideViewX(), aImage.getSideViewAmplitudeX(),
173 aImage.getMeanX(), aImage.getStdX(), aImage.getSideViewConstX(),
174 aImage.getAmplitudeXFit(), aImage.getMeanXFit(), aImage.getStdXFit(), aImage.getConstXFit(),
175 aImage.getSlopeXFit(),aImage.getRoiX(), aImage.getRoiW(), aImage.isPerformFit()
176 );
177 verticalDisp.setData(
178 aImage.getSideViewY(), aImage.getSideViewAmplitudeY(),
179 aImage.getMeanY(), aImage.getStdY(), aImage.getSideViewConstY(),
180 aImage.getAmplitudeYFit(), aImage.getMeanYFit(), aImage.getStdYFit(), aImage.getConstYFit(),
181 aImage.getSlopeYFit(),aImage.getRoiY(), aImage.getRoiH(), aImage.isPerformFit()
182 );
183 }
184
185 @Override
186 public void mouseClicked(MouseEvent e) {
187 if (e.getClickCount() == 2 && aImage != null) {
188 Rectangle r = getScaleHelper().getImageAoi();
189 if (canChangeSettings) analysisEngine.setRoi(0, 0, r.width, r.height);
190 else getPcSupport().firePropertyChange(PROPERTY_ON_SCREEN_ROI, null, r);
191 }
192 }
193
194 @Override
195 public void mouseDragged(MouseEvent e) {
196 if (dragStarted) {
197 p2 = transformPoint(e.getPoint(), e.getComponent().getSize());
198 horizontalDisp.setRoi(p1.getX()-viewPoint.getX(), p2.getX()-viewPoint.getX());
199 verticalDisp.setRoi(p1.getY()-viewPoint.getY(), p2.getY()-viewPoint.getY());
200
201 draggingRectangle = calculateRectangle();
202 imageDisp.repaint();
203 }
204 }
205
206 @Override
207 public void mousePressed(MouseEvent e) {
208 if (aImage == null) return;
209 if (e.getButton() == MouseEvent.BUTTON1) {
210 dragStarted = true;
211 p1 = transformPoint(e.getPoint(), e.getComponent().getSize());
212 }
213 }
214
215 @Override
216 public void mouseReleased(MouseEvent e) {
217 if (e.getButton() == MouseEvent.BUTTON1) {
218 if (dragStarted) {
219 if (p1 != null && p2 != null) {
220
221 Rectangle r = getScaleHelper().componentToImage(calculateRectangle());
222 Rectangle rect = getScaleHelper().getImageAoi();
223 r = new Rectangle(r.x + rect.x,r.y + rect.y,r.width,r.height);
224 if (canChangeSettings) {
225 horizontalDisp.clearRoi();
226 verticalDisp.clearRoi();
227 analysisEngine.setRoi(r.x, r.y, r.width, r.height);
228 }
229 else getPcSupport().firePropertyChange(PROPERTY_ON_SCREEN_ROI, null, r);
230 }
231 dragStarted = false;
232 p1 = null;
233 p2 = null;
234 draggingRectangle = null;
235 }
236 }
237 }
238
239 private Rectangle2D calculateRectangle() {
240 double x, y, w, h;
241 if (p1.getX() < p2.getX()) {
242 x = p1.getX();
243 w = p2.getX()-p1.getX();
244 } else {
245 x = p2.getX();
246 w = p1.getX()-p2.getX();
247 }
248 if (p1.getY() < p2.getY()) {
249 y = p1.getY();
250 h = p2.getY()-p1.getY();
251 } else {
252 y = p2.getY();
253 h = p1.getY()-p2.getY();
254 }
255 return new Rectangle2D.Double(x, y, w, h);
256 }
257
258 private synchronized Point2D transformPoint(Point p, Dimension dim) {
259 Rectangle2D r = getScaleHelper().getActiveRectangle();
260 r = getScaleHelper().imageToComponent(getScaleHelper().componentToImage(r));
261 double x = p.x, y = p.y;
262 if (p.x < r.getMinX()) x = r.getMinX();
263 else if (p.x > r.getMaxX()) x = r.getMaxX();
264 if (p.y < r.getMinY()) y = r.getMinY();
265 else if (p.y > r.getMaxY()) y = r.getMaxY();
266 p.setLocation(x, y);
267 return p;
268 }
269
270 public Rectangle2D getDraggingRectangle() {
271 return draggingRectangle;
272 }
273
274 public boolean isRoiSelected() {
275 return selectedRectangle != null;
276 }
277
278 public synchronized Rectangle2D getScaledSelectedRectangle() {
279 if (selectedRectangle == null) return null;
280 return getScaleHelper().imageToComponent(selectedRectangle);
281 }
282
283 public boolean isThresholdROISelected() {
284 return thresholdRectangle != null;
285 }
286
287 public synchronized Rectangle2D getScaledThresholdROIRectangle() {
288 if (thresholdRectangle == null) return null;
289 return getScaleHelper().imageToComponent(thresholdRectangle);
290 }
291
292 public boolean isCrossAvailable() {
293 return crossRect != null && displayStatistics;
294 }
295
296 public synchronized Shape getCross() {
297 if (crossRect == null) return null;
298 Rectangle2D r = getScaleHelper().imageToComponent(crossRect);
299 if (r == null) return null;
300 GeneralPath marker = new GeneralPath(new Line2D.Double(r.getCenterX()-r.getWidth()/2, r.getCenterY(), r.getCenterX()+r.getWidth()/2, r.getCenterY()));
301 marker.append(new Line2D.Double(r.getCenterX(), r.getCenterY()-r.getHeight()/2, r.getCenterX(), r.getCenterY()+r.getHeight()/2), false);
302 return marker;
303 }
304
305 public boolean isCrossFitAvailable() {
306 return crossFitRect != null;
307 }
308
309 public synchronized Shape getCrossFit() {
310 if (crossFitRect == null) return null;
311 Rectangle2D r = getScaleHelper().imageToComponent(crossFitRect);
312 if (r == null) return null;
313 GeneralPath marker = new GeneralPath(new Line2D.Double(r.getCenterX()-r.getWidth()/2, r.getCenterY(), r.getCenterX()+r.getWidth()/2, r.getCenterY()));
314 marker.append(new Line2D.Double(r.getCenterX(), r.getCenterY()-r.getHeight()/2, r.getCenterX(), r.getCenterY()+r.getHeight()/2), false);
315 return marker;
316 }
317
318 public ChangeListener getViewPortListener() {
319 if (viewPortListener == null) {
320 viewPortListener = new ChangeListener() {
321 @Override
322 public void stateChanged(ChangeEvent e) {
323 JViewport port = (JViewport) e.getSource();
324 Point p = port.getViewPosition();
325 if (p.getX() != viewPoint.getX() || p.getY() != viewPoint.getY()) {
326 viewPoint = p;
327 horizontalDisp.setCanvasStart(-viewPoint.getX());
328 verticalDisp.setCanvasStart(-viewPoint.getY());
329 }
330 }
331 };
332
333 }
334
335 return viewPortListener;
336 }
337
338 private synchronized ScaleHelper getScaleHelper() {
339 if (scaleHelper == null) {
340 scaleHelper = new ScaleHelper(imageDisp.isKeepAspectRatio(), imageDisp.isAOIZoom(), imageDisp.getImageZoom());
341 scaleHelper.addPropertyChangeListener(new PropertyChangeListener() {
342 @Override
343 public void propertyChange(PropertyChangeEvent evt) {
344 String name = evt.getPropertyName();
345 if (name == ScaleHelper.PROPERTY_COMPONENT_DIMENSION) {
346 adjustSideProfileAspectRatio(true);
347 }
348 else if (name == ScaleHelper.PROPERTY_ACTIVE_RECTANGLE) {
349 adjustSideProfileAspectRatio(true);
350 }
351 }
352 });
353 }
354 return scaleHelper;
355 }
356
357 private void adjustSideProfileAspectRatio(boolean repaintAtOnce) {
358 Rectangle2D image = getScaleHelper().getActiveRectangle();
359 if (image == null) return;
360 image = getScaleHelper().imageToComponent(getScaleHelper().componentToImage(image));
361
362
363 horizontalDisp.setCanvasSize(image.getX()-viewPoint.getX(), image.getWidth()+2, repaintAtOnce);
364 verticalDisp.setCanvasSize(image.getY()-viewPoint.getY(), image.getHeight()+2, repaintAtOnce);
365 }
366
367
368
369
370 public boolean isCanChangeSettings() {
371 return canChangeSettings;
372 }
373
374
375
376
377 public void setCanChangeSettings(boolean canChangeSettings) {
378 this.canChangeSettings = canChangeSettings;
379 }
380
381 private PropertyChangeSupport getPcSupport() {
382 if (pcSupport == null) {
383 pcSupport = new PropertyChangeSupport(this);
384 }
385 return pcSupport;
386 }
387
388
389
390
391
392
393 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
394 getPcSupport().addPropertyChangeListener(propertyName, listener);
395 }
396
397
398
399
400
401
402 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
403 getPcSupport().removePropertyChangeListener(propertyName, listener);
404 }
405
406
407
408
409
410 public void addPropertyChangeListener(PropertyChangeListener listener) {
411 getPcSupport().addPropertyChangeListener(listener);
412 }
413
414
415
416
417
418 public void removePropertyChangeListener(PropertyChangeListener listener) {
419 getPcSupport().removePropertyChangeListener(listener);
420 }
421
422 }