• 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             public void run() {
71                 synchronized (PixelPerfectModel.this) {
72                     PixelPerfectModel.this.mDevice = device;
73                     PixelPerfectModel.this.mImage = image;
74                     PixelPerfectModel.this.mViewNode = viewNode;
75                     if (image != null) {
76                         PixelPerfectModel.this.mCrosshairLocation =
77                                 new Point(image.getBounds().width / 2, image.getBounds().height / 2);
78                     } else {
79                         PixelPerfectModel.this.mCrosshairLocation = null;
80                     }
81                     mOverlayImage = null;
82                     PixelPerfectModel.this.mSelectedNode = null;
83                     mZoom = DEFAULT_ZOOM;
84                 }
85             }
86         });
87         notifyImageLoaded();
88         if (toDispose != null) {
89             Display.getDefault().syncExec(new Runnable() {
90                 public void run() {
91                     toDispose.dispose();
92                 }
93             });
94         }
95         if (toDispose2 != null) {
96             Display.getDefault().syncExec(new Runnable() {
97                 public void run() {
98                     toDispose2.dispose();
99                 }
100             });
101         }
102 
103     }
104 
setCrosshairLocation(int x, int y)105     public void setCrosshairLocation(int x, int y) {
106         synchronized (this) {
107             mCrosshairLocation = new Point(x, y);
108         }
109         notifyCrosshairMoved();
110     }
111 
setSelected(ViewNode selected)112     public void setSelected(ViewNode selected) {
113         synchronized (this) {
114             this.mSelectedNode = selected;
115         }
116         notifySelectionChanged();
117     }
118 
setTree(final ViewNode viewNode)119     public void setTree(final ViewNode viewNode) {
120         Display.getDefault().syncExec(new Runnable() {
121             public void run() {
122                 synchronized (PixelPerfectModel.this) {
123                     PixelPerfectModel.this.mViewNode = viewNode;
124                     PixelPerfectModel.this.mSelectedNode = null;
125                 }
126             }
127         });
128         notifyTreeChanged();
129     }
130 
setImage(final Image image)131     public void setImage(final Image image) {
132         final Image toDispose = this.mImage;
133         Display.getDefault().syncExec(new Runnable() {
134             public void run() {
135                 synchronized (PixelPerfectModel.this) {
136                     PixelPerfectModel.this.mImage = image;
137                 }
138             }
139         });
140         notifyImageChanged();
141         if (toDispose != null) {
142             Display.getDefault().syncExec(new Runnable() {
143                 public void run() {
144                     toDispose.dispose();
145                 }
146             });
147         }
148     }
149 
setZoom(int newZoom)150     public void setZoom(int newZoom) {
151         synchronized (this) {
152             if (newZoom < MIN_ZOOM) {
153                 newZoom = MIN_ZOOM;
154             }
155             if (newZoom > MAX_ZOOM) {
156                 newZoom = MAX_ZOOM;
157             }
158             mZoom = newZoom;
159         }
160         notifyZoomChanged();
161     }
162 
setOverlayImage(final Image overlayImage)163     public void setOverlayImage(final Image overlayImage) {
164         final Image toDispose = this.mOverlayImage;
165         Display.getDefault().syncExec(new Runnable() {
166             public void run() {
167                 synchronized (PixelPerfectModel.this) {
168                     PixelPerfectModel.this.mOverlayImage = overlayImage;
169                 }
170             }
171         });
172         notifyOverlayChanged();
173         if (toDispose != null) {
174             Display.getDefault().syncExec(new Runnable() {
175                 public void run() {
176                     toDispose.dispose();
177                 }
178             });
179         }
180     }
181 
setOverlayTransparency(double value)182     public void setOverlayTransparency(double value) {
183         synchronized (this) {
184             value = Math.max(value, 0);
185             value = Math.min(value, 1);
186             mOverlayTransparency = value;
187         }
188         notifyOverlayTransparencyChanged();
189     }
190 
getViewNode()191     public ViewNode getViewNode() {
192         synchronized (this) {
193             return mViewNode;
194         }
195     }
196 
getCrosshairLocation()197     public Point getCrosshairLocation() {
198         synchronized (this) {
199             return mCrosshairLocation;
200         }
201     }
202 
getImage()203     public Image getImage() {
204         synchronized (this) {
205             return mImage;
206         }
207     }
208 
getSelected()209     public ViewNode getSelected() {
210         synchronized (this) {
211             return mSelectedNode;
212         }
213     }
214 
getDevice()215     public IDevice getDevice() {
216         synchronized (this) {
217             return mDevice;
218         }
219     }
220 
getZoom()221     public int getZoom() {
222         synchronized (this) {
223             return mZoom;
224         }
225     }
226 
getOverlayImage()227     public Image getOverlayImage() {
228         synchronized (this) {
229             return mOverlayImage;
230         }
231     }
232 
getOverlayTransparency()233     public double getOverlayTransparency() {
234         synchronized (this) {
235             return mOverlayTransparency;
236         }
237     }
238 
239     public static interface IImageChangeListener {
imageLoaded()240         public void imageLoaded();
241 
imageChanged()242         public void imageChanged();
243 
crosshairMoved()244         public void crosshairMoved();
245 
selectionChanged()246         public void selectionChanged();
247 
treeChanged()248         public void treeChanged();
249 
zoomChanged()250         public void zoomChanged();
251 
overlayChanged()252         public void overlayChanged();
253 
overlayTransparencyChanged()254         public void overlayTransparencyChanged();
255     }
256 
getImageChangeListenerList()257     private IImageChangeListener[] getImageChangeListenerList() {
258         IImageChangeListener[] listeners = null;
259         synchronized (mImageChangeListeners) {
260             if (mImageChangeListeners.size() == 0) {
261                 return null;
262             }
263             listeners =
264                     mImageChangeListeners.toArray(new IImageChangeListener[mImageChangeListeners
265                             .size()]);
266         }
267         return listeners;
268     }
269 
notifyImageLoaded()270     public void notifyImageLoaded() {
271         IImageChangeListener[] listeners = getImageChangeListenerList();
272         if (listeners != null) {
273             for (int i = 0; i < listeners.length; i++) {
274                 listeners[i].imageLoaded();
275             }
276         }
277     }
278 
notifyImageChanged()279     public void notifyImageChanged() {
280         IImageChangeListener[] listeners = getImageChangeListenerList();
281         if (listeners != null) {
282             for (int i = 0; i < listeners.length; i++) {
283                 listeners[i].imageChanged();
284             }
285         }
286     }
287 
notifyCrosshairMoved()288     public void notifyCrosshairMoved() {
289         IImageChangeListener[] listeners = getImageChangeListenerList();
290         if (listeners != null) {
291             for (int i = 0; i < listeners.length; i++) {
292                 listeners[i].crosshairMoved();
293             }
294         }
295     }
296 
notifySelectionChanged()297     public void notifySelectionChanged() {
298         IImageChangeListener[] listeners = getImageChangeListenerList();
299         if (listeners != null) {
300             for (int i = 0; i < listeners.length; i++) {
301                 listeners[i].selectionChanged();
302             }
303         }
304     }
305 
notifyTreeChanged()306     public void notifyTreeChanged() {
307         IImageChangeListener[] listeners = getImageChangeListenerList();
308         if (listeners != null) {
309             for (int i = 0; i < listeners.length; i++) {
310                 listeners[i].treeChanged();
311             }
312         }
313     }
314 
notifyZoomChanged()315     public void notifyZoomChanged() {
316         IImageChangeListener[] listeners = getImageChangeListenerList();
317         if (listeners != null) {
318             for (int i = 0; i < listeners.length; i++) {
319                 listeners[i].zoomChanged();
320             }
321         }
322     }
323 
notifyOverlayChanged()324     public void notifyOverlayChanged() {
325         IImageChangeListener[] listeners = getImageChangeListenerList();
326         if (listeners != null) {
327             for (int i = 0; i < listeners.length; i++) {
328                 listeners[i].overlayChanged();
329             }
330         }
331     }
332 
notifyOverlayTransparencyChanged()333     public void notifyOverlayTransparencyChanged() {
334         IImageChangeListener[] listeners = getImageChangeListenerList();
335         if (listeners != null) {
336             for (int i = 0; i < listeners.length; i++) {
337                 listeners[i].overlayTransparencyChanged();
338             }
339         }
340     }
341 
addImageChangeListener(IImageChangeListener listener)342     public void addImageChangeListener(IImageChangeListener listener) {
343         synchronized (mImageChangeListeners) {
344             mImageChangeListeners.add(listener);
345         }
346     }
347 
removeImageChangeListener(IImageChangeListener listener)348     public void removeImageChangeListener(IImageChangeListener listener) {
349         synchronized (mImageChangeListeners) {
350             mImageChangeListeners.remove(listener);
351         }
352     }
353 }
354