• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.hierarchyviewerlib.models;
18 
19 import com.android.ddmlib.IDevice;
20 import com.android.hierarchyviewerlib.device.ViewNode;
21 
22 import org.eclipse.swt.graphics.Image;
23 import org.eclipse.swt.graphics.Point;
24 import org.eclipse.swt.widgets.Display;
25 
26 import java.util.ArrayList;
27 
28 public class PixelPerfectModel {
29 
30     public static final int MIN_ZOOM = 2;
31 
32     public static final int MAX_ZOOM = 24;
33 
34     public static final int DEFAULT_ZOOM = 8;
35 
36     public static final int DEFAULT_OVERLAY_TRANSPARENCY_PERCENTAGE = 50;
37 
38     private IDevice mDevice;
39 
40     private Image mImage;
41 
42     private Point mCrosshairLocation;
43 
44     private ViewNode mViewNode;
45 
46     private ViewNode mSelectedNode;
47 
48     private int mZoom;
49 
50     private final ArrayList<IImageChangeListener> mImageChangeListeners =
51             new ArrayList<IImageChangeListener>();
52 
53     private Image mOverlayImage;
54 
55     private double mOverlayTransparency = DEFAULT_OVERLAY_TRANSPARENCY_PERCENTAGE / 100.0;
56 
57     private static PixelPerfectModel sModel;
58 
getModel()59     public static PixelPerfectModel getModel() {
60         if (sModel == null) {
61             sModel = new PixelPerfectModel();
62         }
63         return sModel;
64     }
65 
setData(final IDevice device, final Image image, final ViewNode viewNode)66     public void setData(final IDevice device, final Image image, final ViewNode viewNode) {
67         final Image toDispose = this.mImage;
68         final Image toDispose2 = this.mOverlayImage;
69         Display.getDefault().syncExec(new Runnable() {
70             @Override
71             public void run() {
72                 synchronized (PixelPerfectModel.this) {
73                     PixelPerfectModel.this.mDevice = device;
74                     PixelPerfectModel.this.mImage = image;
75                     PixelPerfectModel.this.mViewNode = viewNode;
76                     if (image != null) {
77                         PixelPerfectModel.this.mCrosshairLocation =
78                                 new Point(image.getBounds().width / 2, image.getBounds().height / 2);
79                     } else {
80                         PixelPerfectModel.this.mCrosshairLocation = null;
81                     }
82                     mOverlayImage = null;
83                     PixelPerfectModel.this.mSelectedNode = null;
84                     mZoom = DEFAULT_ZOOM;
85                 }
86             }
87         });
88         notifyImageLoaded();
89         if (toDispose != null) {
90             Display.getDefault().syncExec(new Runnable() {
91                 @Override
92                 public void run() {
93                     toDispose.dispose();
94                 }
95             });
96         }
97         if (toDispose2 != null) {
98             Display.getDefault().syncExec(new Runnable() {
99                 @Override
100                 public void run() {
101                     toDispose2.dispose();
102                 }
103             });
104         }
105 
106     }
107 
setCrosshairLocation(int x, int y)108     public void setCrosshairLocation(int x, int y) {
109         synchronized (this) {
110             mCrosshairLocation = new Point(x, y);
111         }
112         notifyCrosshairMoved();
113     }
114 
setSelected(ViewNode selected)115     public void setSelected(ViewNode selected) {
116         synchronized (this) {
117             this.mSelectedNode = selected;
118         }
119         notifySelectionChanged();
120     }
121 
setTree(final ViewNode viewNode)122     public void setTree(final ViewNode viewNode) {
123         Display.getDefault().syncExec(new Runnable() {
124             @Override
125             public void run() {
126                 synchronized (PixelPerfectModel.this) {
127                     PixelPerfectModel.this.mViewNode = viewNode;
128                     PixelPerfectModel.this.mSelectedNode = null;
129                 }
130             }
131         });
132         notifyTreeChanged();
133     }
134 
setImage(final Image image)135     public void setImage(final Image image) {
136         final Image toDispose = this.mImage;
137         Display.getDefault().syncExec(new Runnable() {
138             @Override
139             public void run() {
140                 synchronized (PixelPerfectModel.this) {
141                     PixelPerfectModel.this.mImage = image;
142                 }
143             }
144         });
145         notifyImageChanged();
146         if (toDispose != null) {
147             Display.getDefault().syncExec(new Runnable() {
148                 @Override
149                 public void run() {
150                     toDispose.dispose();
151                 }
152             });
153         }
154     }
155 
setZoom(int newZoom)156     public void setZoom(int newZoom) {
157         synchronized (this) {
158             if (newZoom < MIN_ZOOM) {
159                 newZoom = MIN_ZOOM;
160             }
161             if (newZoom > MAX_ZOOM) {
162                 newZoom = MAX_ZOOM;
163             }
164             mZoom = newZoom;
165         }
166         notifyZoomChanged();
167     }
168 
setOverlayImage(final Image overlayImage)169     public void setOverlayImage(final Image overlayImage) {
170         final Image toDispose = this.mOverlayImage;
171         Display.getDefault().syncExec(new Runnable() {
172             @Override
173             public void run() {
174                 synchronized (PixelPerfectModel.this) {
175                     PixelPerfectModel.this.mOverlayImage = overlayImage;
176                 }
177             }
178         });
179         notifyOverlayChanged();
180         if (toDispose != null) {
181             Display.getDefault().syncExec(new Runnable() {
182                 @Override
183                 public void run() {
184                     toDispose.dispose();
185                 }
186             });
187         }
188     }
189 
setOverlayTransparency(double value)190     public void setOverlayTransparency(double value) {
191         synchronized (this) {
192             value = Math.max(value, 0);
193             value = Math.min(value, 1);
194             mOverlayTransparency = value;
195         }
196         notifyOverlayTransparencyChanged();
197     }
198 
getViewNode()199     public ViewNode getViewNode() {
200         synchronized (this) {
201             return mViewNode;
202         }
203     }
204 
getCrosshairLocation()205     public Point getCrosshairLocation() {
206         synchronized (this) {
207             return mCrosshairLocation;
208         }
209     }
210 
getImage()211     public Image getImage() {
212         synchronized (this) {
213             return mImage;
214         }
215     }
216 
getSelected()217     public ViewNode getSelected() {
218         synchronized (this) {
219             return mSelectedNode;
220         }
221     }
222 
getDevice()223     public IDevice getDevice() {
224         synchronized (this) {
225             return mDevice;
226         }
227     }
228 
getZoom()229     public int getZoom() {
230         synchronized (this) {
231             return mZoom;
232         }
233     }
234 
getOverlayImage()235     public Image getOverlayImage() {
236         synchronized (this) {
237             return mOverlayImage;
238         }
239     }
240 
getOverlayTransparency()241     public double getOverlayTransparency() {
242         synchronized (this) {
243             return mOverlayTransparency;
244         }
245     }
246 
247     public static interface IImageChangeListener {
imageLoaded()248         public void imageLoaded();
249 
imageChanged()250         public void imageChanged();
251 
crosshairMoved()252         public void crosshairMoved();
253 
selectionChanged()254         public void selectionChanged();
255 
treeChanged()256         public void treeChanged();
257 
zoomChanged()258         public void zoomChanged();
259 
overlayChanged()260         public void overlayChanged();
261 
overlayTransparencyChanged()262         public void overlayTransparencyChanged();
263     }
264 
getImageChangeListenerList()265     private IImageChangeListener[] getImageChangeListenerList() {
266         IImageChangeListener[] listeners = null;
267         synchronized (mImageChangeListeners) {
268             if (mImageChangeListeners.size() == 0) {
269                 return null;
270             }
271             listeners =
272                     mImageChangeListeners.toArray(new IImageChangeListener[mImageChangeListeners
273                             .size()]);
274         }
275         return listeners;
276     }
277 
notifyImageLoaded()278     public void notifyImageLoaded() {
279         IImageChangeListener[] listeners = getImageChangeListenerList();
280         if (listeners != null) {
281             for (int i = 0; i < listeners.length; i++) {
282                 listeners[i].imageLoaded();
283             }
284         }
285     }
286 
notifyImageChanged()287     public void notifyImageChanged() {
288         IImageChangeListener[] listeners = getImageChangeListenerList();
289         if (listeners != null) {
290             for (int i = 0; i < listeners.length; i++) {
291                 listeners[i].imageChanged();
292             }
293         }
294     }
295 
notifyCrosshairMoved()296     public void notifyCrosshairMoved() {
297         IImageChangeListener[] listeners = getImageChangeListenerList();
298         if (listeners != null) {
299             for (int i = 0; i < listeners.length; i++) {
300                 listeners[i].crosshairMoved();
301             }
302         }
303     }
304 
notifySelectionChanged()305     public void notifySelectionChanged() {
306         IImageChangeListener[] listeners = getImageChangeListenerList();
307         if (listeners != null) {
308             for (int i = 0; i < listeners.length; i++) {
309                 listeners[i].selectionChanged();
310             }
311         }
312     }
313 
notifyTreeChanged()314     public void notifyTreeChanged() {
315         IImageChangeListener[] listeners = getImageChangeListenerList();
316         if (listeners != null) {
317             for (int i = 0; i < listeners.length; i++) {
318                 listeners[i].treeChanged();
319             }
320         }
321     }
322 
notifyZoomChanged()323     public void notifyZoomChanged() {
324         IImageChangeListener[] listeners = getImageChangeListenerList();
325         if (listeners != null) {
326             for (int i = 0; i < listeners.length; i++) {
327                 listeners[i].zoomChanged();
328             }
329         }
330     }
331 
notifyOverlayChanged()332     public void notifyOverlayChanged() {
333         IImageChangeListener[] listeners = getImageChangeListenerList();
334         if (listeners != null) {
335             for (int i = 0; i < listeners.length; i++) {
336                 listeners[i].overlayChanged();
337             }
338         }
339     }
340 
notifyOverlayTransparencyChanged()341     public void notifyOverlayTransparencyChanged() {
342         IImageChangeListener[] listeners = getImageChangeListenerList();
343         if (listeners != null) {
344             for (int i = 0; i < listeners.length; i++) {
345                 listeners[i].overlayTransparencyChanged();
346             }
347         }
348     }
349 
addImageChangeListener(IImageChangeListener listener)350     public void addImageChangeListener(IImageChangeListener listener) {
351         synchronized (mImageChangeListeners) {
352             mImageChangeListeners.add(listener);
353         }
354     }
355 
removeImageChangeListener(IImageChangeListener listener)356     public void removeImageChangeListener(IImageChangeListener listener) {
357         synchronized (mImageChangeListeners) {
358             mImageChangeListeners.remove(listener);
359         }
360     }
361 }
362