aboutsummaryrefslogtreecommitdiffstats
path: root/hierarchyviewer2/libs
diff options
context:
space:
mode:
Diffstat (limited to 'hierarchyviewer2/libs')
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ComponentRegistry.java69
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/HierarchyViewerDirector.java407
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java125
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceConnection.java10
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewNode.java128
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/DeviceSelectionModel.java45
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/PixelPerfectModel.java77
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/TreeViewModel.java19
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/CaptureDisplay.java17
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/DeviceSelector.java34
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/LayoutViewer.java85
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfect.java61
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectLoupe.java62
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectPixelPanel.java190
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java7
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/ProfileViewer.java188
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PropertyViewer.java62
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeView.java201
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeViewOverview.java53
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/DrawableViewNode.java10
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/PsdFile.java508
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/TreeColumnResizer.java3
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about-small.jpgbin0 -> 467 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about.jpgbin0 -> 27144 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/auto-refresh.pngbin0 -> 541 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/capture-psd.pngbin0 -> 339 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view-selected.pngbin0 -> 254 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view.pngbin0 -> 228 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/display.pngbin0 -> 946 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/filtered.pngbin0 -> 9242 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/green.pngbin219 -> 302 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/inspect-screenshot.pngbin0 -> 412 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/invalidate.pngbin0 -> 391 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-all-views.pngbin0 -> 728 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-overlay.pngbin0 -> 549 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-view-hierarchy.pngbin0 -> 288 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/not-selected.pngbin0 -> 12468 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-black.pngbin0 -> 157 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-white.pngbin0 -> 158 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view-selected.pngbin0 -> 734 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view.pngbin0 -> 733 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/red.pngbin220 -> 383 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/refresh-windows.pngbin0 -> 872 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/request-layout.pngbin0 -> 223 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/save.pngbin0 -> 360 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered-small.pngbin0 -> 5182 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered.pngbin0 -> 9015 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-small.pngbin0 -> 12611 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected.pngbin0 -> 12159 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-overlay.pngbin0 -> 958 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view-selected.pngbin0 -> 276 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view.pngbin0 -> 281 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/yellow.pngbin221 -> 255 bytes
53 files changed, 1840 insertions, 521 deletions
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ComponentRegistry.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ComponentRegistry.java
deleted file mode 100644
index a50478e..0000000
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ComponentRegistry.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.hierarchyviewerlib;
-
-import com.android.hierarchyviewerlib.models.DeviceSelectionModel;
-import com.android.hierarchyviewerlib.models.PixelPerfectModel;
-import com.android.hierarchyviewerlib.models.TreeViewModel;
-
-/**
- * This is the central point for getting access to the various parts of the
- * Hierarchy Viewer. Components register themselves with the class using the
- * setters and can be accessed using the getters.
- */
-public class ComponentRegistry {
-
- private static HierarchyViewerDirector director;
-
- private static DeviceSelectionModel deviceSelectionModel;
-
- private static PixelPerfectModel pixelPerfectModel;
-
- private static TreeViewModel treeViewModel;
-
- public static HierarchyViewerDirector getDirector() {
- return director;
- }
-
- public static void setDirector(HierarchyViewerDirector director) {
- ComponentRegistry.director = director;
- }
-
- public static DeviceSelectionModel getDeviceSelectionModel() {
- return deviceSelectionModel;
- }
-
- public static void setDeviceSelectionModel(DeviceSelectionModel deviceSelectionModel) {
- ComponentRegistry.deviceSelectionModel = deviceSelectionModel;
- }
-
- public static void setPixelPerfectModel(PixelPerfectModel pixelPerfectModel) {
- ComponentRegistry.pixelPerfectModel = pixelPerfectModel;
- }
-
- public static PixelPerfectModel getPixelPerfectModel() {
- return pixelPerfectModel;
- }
-
- public static void setTreeViewModel(TreeViewModel treeViewModel) {
- ComponentRegistry.treeViewModel = treeViewModel;
- }
-
- public static TreeViewModel getTreeViewModel() {
- return treeViewModel;
- }
-}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/HierarchyViewerDirector.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/HierarchyViewerDirector.java
index 48a45dd..29b35f1 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/HierarchyViewerDirector.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/HierarchyViewerDirector.java
@@ -28,18 +28,28 @@ import com.android.hierarchyviewerlib.device.Window;
import com.android.hierarchyviewerlib.device.WindowUpdater;
import com.android.hierarchyviewerlib.device.DeviceBridge.ViewServerInfo;
import com.android.hierarchyviewerlib.device.WindowUpdater.IWindowChangeListener;
+import com.android.hierarchyviewerlib.models.DeviceSelectionModel;
+import com.android.hierarchyviewerlib.models.PixelPerfectModel;
+import com.android.hierarchyviewerlib.models.TreeViewModel;
import com.android.hierarchyviewerlib.ui.CaptureDisplay;
+import com.android.hierarchyviewerlib.ui.TreeView;
+import com.android.hierarchyviewerlib.ui.util.DrawableViewNode;
+import com.android.hierarchyviewerlib.ui.util.PsdFile;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.util.HashSet;
/**
* This is the class where most of the logic resides.
@@ -47,6 +57,8 @@ import java.io.IOException;
public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
IWindowChangeListener {
+ protected static HierarchyViewerDirector director;
+
public static final String TAG = "hierarchyviewer";
private int pixelPerfectRefreshesInProgress = 0;
@@ -57,6 +69,10 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
public abstract String getAdbLocation();
+ public static HierarchyViewerDirector getDirector() {
+ return director;
+ }
+
public void initDebugBridge() {
DeviceBridge.initDebugBridge(getAdbLocation());
}
@@ -80,23 +96,20 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
DeviceBridge.stopListenForDevices(this);
}
- public abstract void executeInBackground(Runnable task);
+ public abstract void executeInBackground(String taskName, Runnable task);
public void deviceConnected(final IDevice device) {
- if (device.isOnline()) {
- DeviceBridge.setupDeviceForward(device);
- if (!DeviceBridge.isViewServerRunning(device)) {
- if (!DeviceBridge.startViewServer(device)) {
- // Let's do something interesting here... Try again in 2
- // seconds.
- executeInBackground(new Runnable() {
- public void run() {
+ executeInBackground("Connecting device", new Runnable() {
+ public void run() {
+ if (device.isOnline()) {
+ DeviceBridge.setupDeviceForward(device);
+ if (!DeviceBridge.isViewServerRunning(device)) {
+ if (!DeviceBridge.startViewServer(device)) {
+ // Let's do something interesting here... Try again
+ // in 2 seconds.
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
- Log.e(TAG, "Unable to debug device " + device);
- DeviceBridge.removeDeviceForward(device);
- return;
}
if (!DeviceBridge.startViewServer(device)) {
Log.e(TAG, "Unable to debug device " + device);
@@ -104,46 +117,49 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
} else {
loadViewServerInfoAndWindows(device);
}
+ return;
}
- });
- return;
+ }
+ loadViewServerInfoAndWindows(device);
}
}
- loadViewServerInfoAndWindows(device);
- }
+ });
}
private void loadViewServerInfoAndWindows(final IDevice device) {
- executeInBackground(new Runnable() {
- public void run() {
- ViewServerInfo viewServerInfo = DeviceBridge.loadViewServerInfo(device);
- if (viewServerInfo == null) {
- return;
- }
- Window[] windows = DeviceBridge.loadWindows(device);
- ComponentRegistry.getDeviceSelectionModel().addDevice(device, windows);
- if (viewServerInfo.protocolVersion >= 3) {
- WindowUpdater.startListenForWindowChanges(HierarchyViewerDirector.this, device);
- focusChanged(device);
- }
- }
- });
- }
- public void deviceDisconnected(IDevice device) {
- ViewServerInfo viewServerInfo = DeviceBridge.getViewServerInfo(device);
+ ViewServerInfo viewServerInfo = DeviceBridge.loadViewServerInfo(device);
if (viewServerInfo == null) {
return;
}
+ Window[] windows = DeviceBridge.loadWindows(device);
+ DeviceSelectionModel.getModel().addDevice(device, windows);
if (viewServerInfo.protocolVersion >= 3) {
- WindowUpdater.stopListenForWindowChanges(this, device);
- }
- DeviceBridge.removeDeviceForward(device);
- DeviceBridge.removeViewServerInfo(device);
- ComponentRegistry.getDeviceSelectionModel().removeDevice(device);
- if (ComponentRegistry.getPixelPerfectModel().getDevice() == device) {
- ComponentRegistry.getPixelPerfectModel().setData(null, null, null);
+ WindowUpdater.startListenForWindowChanges(HierarchyViewerDirector.this, device);
+ focusChanged(device);
}
+
+ }
+
+ public void deviceDisconnected(final IDevice device) {
+ executeInBackground("Disconnecting device", new Runnable() {
+ public void run() {
+ ViewServerInfo viewServerInfo = DeviceBridge.getViewServerInfo(device);
+ if (viewServerInfo != null && viewServerInfo.protocolVersion >= 3) {
+ WindowUpdater.stopListenForWindowChanges(HierarchyViewerDirector.this, device);
+ }
+ DeviceBridge.removeDeviceForward(device);
+ DeviceBridge.removeViewServerInfo(device);
+ DeviceSelectionModel.getModel().removeDevice(device);
+ if (PixelPerfectModel.getModel().getDevice() == device) {
+ PixelPerfectModel.getModel().setData(null, null, null);
+ }
+ Window treeViewWindow = TreeViewModel.getModel().getWindow();
+ if (treeViewWindow != null && treeViewWindow.getDevice() == device) {
+ TreeViewModel.getModel().setData(null, null);
+ }
+ }
+ });
}
public void deviceChanged(IDevice device, int changeMask) {
@@ -153,48 +169,63 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
}
public void windowsChanged(final IDevice device) {
- executeInBackground(new Runnable() {
+ executeInBackground("Refreshing windows", new Runnable() {
public void run() {
Window[] windows = DeviceBridge.loadWindows(device);
- ComponentRegistry.getDeviceSelectionModel().updateDevice(device, windows);
+ DeviceSelectionModel.getModel().updateDevice(device, windows);
}
});
}
public void focusChanged(final IDevice device) {
- executeInBackground(new Runnable() {
+ executeInBackground("Updating focus", new Runnable() {
public void run() {
int focusedWindow = DeviceBridge.getFocusedWindow(device);
- ComponentRegistry.getDeviceSelectionModel().updateFocusedWindow(device,
- focusedWindow);
+ DeviceSelectionModel.getModel().updateFocusedWindow(device, focusedWindow);
}
});
+ }
- // Some interesting logic here. We don't want to refresh the pixel
- // perfect view 1000 times in a row if the focus keeps changing. We just
- // want it to refresh following the last focus change.
- boolean proceed = false;
- synchronized (this) {
- if (pixelPerfectRefreshesInProgress <= 1) {
- proceed = true;
- pixelPerfectRefreshesInProgress++;
+ public void refreshPixelPerfect() {
+ final IDevice device = PixelPerfectModel.getModel().getDevice();
+ if (device != null) {
+ // Some interesting logic here. We don't want to refresh the pixel
+ // perfect view 1000 times in a row if the focus keeps changing. We
+ // just
+ // want it to refresh following the last focus change.
+ boolean proceed = false;
+ synchronized (this) {
+ if (pixelPerfectRefreshesInProgress <= 1) {
+ proceed = true;
+ pixelPerfectRefreshesInProgress++;
+ }
}
- }
- if (proceed) {
- executeInBackground(new Runnable() {
- public void run() {
- if (ComponentRegistry.getDeviceSelectionModel().getFocusedWindow(device) != -1
- && device == ComponentRegistry.getPixelPerfectModel().getDevice()) {
- ViewNode viewNode =
- DeviceBridge.loadWindowData(Window.getFocusedWindow(device));
+ if (proceed) {
+ executeInBackground("Refreshing pixel perfect screenshot", new Runnable() {
+ public void run() {
Image screenshotImage = getScreenshotImage(device);
if (screenshotImage != null) {
- ComponentRegistry.getPixelPerfectModel().setFocusData(screenshotImage,
- viewNode);
+ PixelPerfectModel.getModel().setImage(screenshotImage);
+ }
+ synchronized (HierarchyViewerDirector.this) {
+ pixelPerfectRefreshesInProgress--;
}
}
- synchronized (HierarchyViewerDirector.this) {
- pixelPerfectRefreshesInProgress--;
+
+ });
+ }
+ }
+ }
+
+ public void refreshPixelPerfectTree() {
+ final IDevice device = PixelPerfectModel.getModel().getDevice();
+ if (device != null) {
+ executeInBackground("Refreshing pixel perfect tree", new Runnable() {
+ public void run() {
+ ViewNode viewNode =
+ DeviceBridge.loadWindowData(Window.getFocusedWindow(device));
+ if (viewNode != null) {
+ PixelPerfectModel.getModel().setTree(viewNode);
}
}
@@ -203,14 +234,15 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
}
public void loadPixelPerfectData(final IDevice device) {
- executeInBackground(new Runnable() {
+ executeInBackground("Loading pixel perfect data", new Runnable() {
public void run() {
Image screenshotImage = getScreenshotImage(device);
if (screenshotImage != null) {
ViewNode viewNode =
DeviceBridge.loadWindowData(Window.getFocusedWindow(device));
- ComponentRegistry.getPixelPerfectModel().setData(device, screenshotImage,
- viewNode);
+ if (viewNode != null) {
+ PixelPerfectModel.getModel().setData(device, screenshotImage, viewNode);
+ }
}
}
});
@@ -248,13 +280,14 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
}
public void loadViewTreeData(final Window window) {
- executeInBackground(new Runnable() {
+ executeInBackground("Loading view hierarchy", new Runnable() {
public void run() {
ViewNode viewNode = DeviceBridge.loadWindowData(window);
if (viewNode != null) {
DeviceBridge.loadProfileData(window, viewNode);
- ComponentRegistry.getTreeViewModel().setData(window, viewNode);
+ viewNode.setViewCount();
+ TreeViewModel.getModel().setData(window, viewNode);
}
}
});
@@ -270,11 +303,12 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
fileDialog.setFilterNames(new String[] {
"Image (*.jpg, *.jpeg, *.png, *.gif, *.bmp)"
});
+ fileDialog.setText("Choose an overlay image");
String fileName = fileDialog.open();
if (fileName != null) {
try {
Image image = new Image(Display.getDefault(), fileName);
- ComponentRegistry.getPixelPerfectModel().setOverlayImage(image);
+ PixelPerfectModel.getModel().setOverlayImage(image);
} catch (SWTException e) {
Log.e(TAG, "Unable to load image from " + fileName);
}
@@ -284,14 +318,14 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
}
public void showCapture(final Shell shell, final ViewNode viewNode) {
- executeInBackground(new Runnable() {
+ executeInBackground("Capturing node", new Runnable() {
public void run() {
final Image image = DeviceBridge.loadCapture(viewNode.window, viewNode);
if (image != null) {
viewNode.image = image;
// Force the layout viewer to redraw.
- ComponentRegistry.getTreeViewModel().notifySelectionChanged();
+ TreeViewModel.getModel().notifySelectionChanged();
Display.getDefault().asyncExec(new Runnable() {
public void run() {
@@ -302,4 +336,231 @@ public abstract class HierarchyViewerDirector implements IDeviceChangeListener,
}
});
}
+
+ public void showCapture(Shell shell) {
+ DrawableViewNode viewNode = TreeViewModel.getModel().getSelection();
+ if (viewNode != null) {
+ showCapture(shell, viewNode.viewNode);
+ }
+ }
+
+ public void refreshWindows() {
+ executeInBackground("Refreshing windows", new Runnable() {
+ public void run() {
+ IDevice[] devicesA = DeviceSelectionModel.getModel().getDevices();
+ IDevice[] devicesB = DeviceBridge.getDevices();
+ HashSet<IDevice> deviceSet = new HashSet<IDevice>();
+ for (int i = 0; i < devicesB.length; i++) {
+ deviceSet.add(devicesB[i]);
+ }
+ for (int i = 0; i < devicesA.length; i++) {
+ if (deviceSet.contains(devicesA[i])) {
+ windowsChanged(devicesA[i]);
+ deviceSet.remove(devicesA[i]);
+ } else {
+ deviceDisconnected(devicesA[i]);
+ }
+ }
+ for (IDevice device : deviceSet) {
+ deviceConnected(device);
+ }
+ }
+ });
+ }
+
+ public void loadViewHierarchy() {
+ Window window = DeviceSelectionModel.getModel().getSelectedWindow();
+ if (window != null) {
+ loadViewTreeData(window);
+ }
+ }
+
+ public void inspectScreenshot() {
+ IDevice device = DeviceSelectionModel.getModel().getSelectedDevice();
+ if (device != null) {
+ loadPixelPerfectData(device);
+ }
+ }
+
+ public void saveTreeView(final Shell shell) {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ final DrawableViewNode viewNode = TreeViewModel.getModel().getTree();
+ if (viewNode != null) {
+ FileDialog fileDialog = new FileDialog(shell, SWT.SAVE);
+ fileDialog.setFilterExtensions(new String[] {
+ "*.png"
+ });
+ fileDialog.setFilterNames(new String[] {
+ "Portable Network Graphics File (*.png)"
+ });
+ fileDialog.setText("Choose where to save the tree image");
+ final String fileName = fileDialog.open();
+ if (fileName != null) {
+ executeInBackground("Saving tree view", new Runnable() {
+ public void run() {
+ Image image = TreeView.paintToImage(viewNode);
+ ImageLoader imageLoader = new ImageLoader();
+ imageLoader.data = new ImageData[] {
+ image.getImageData()
+ };
+ String extensionedFileName = fileName;
+ if (!extensionedFileName.toLowerCase().endsWith(".png")) {
+ extensionedFileName += ".png";
+ }
+ try {
+ imageLoader.save(extensionedFileName, SWT.IMAGE_PNG);
+ } catch (SWTException e) {
+ Log.e(TAG, "Unable to save tree view as a PNG image at "
+ + fileName);
+ }
+ image.dispose();
+ }
+ });
+ }
+ }
+ }
+ });
+ }
+
+ public void savePixelPerfect(final Shell shell) {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ Image untouchableImage = PixelPerfectModel.getModel().getImage();
+ if (untouchableImage != null) {
+ final ImageData imageData = untouchableImage.getImageData();
+ FileDialog fileDialog = new FileDialog(shell, SWT.SAVE);
+ fileDialog.setFilterExtensions(new String[] {
+ "*.png"
+ });
+ fileDialog.setFilterNames(new String[] {
+ "Portable Network Graphics File (*.png)"
+ });
+ fileDialog.setText("Choose where to save the screenshot");
+ final String fileName = fileDialog.open();
+ if (fileName != null) {
+ executeInBackground("Saving pixel perfect", new Runnable() {
+ public void run() {
+ ImageLoader imageLoader = new ImageLoader();
+ imageLoader.data = new ImageData[] {
+ imageData
+ };
+ String extensionedFileName = fileName;
+ if (!extensionedFileName.toLowerCase().endsWith(".png")) {
+ extensionedFileName += ".png";
+ }
+ try {
+ imageLoader.save(extensionedFileName, SWT.IMAGE_PNG);
+ } catch (SWTException e) {
+ Log.e(TAG, "Unable to save tree view as a PNG image at "
+ + fileName);
+ }
+ }
+ });
+ }
+ }
+ }
+ });
+ }
+
+ public void capturePSD(final Shell shell) {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ final Window window = TreeViewModel.getModel().getWindow();
+ if (window != null) {
+ FileDialog fileDialog = new FileDialog(shell, SWT.SAVE);
+ fileDialog.setFilterExtensions(new String[] {
+ "*.psd"
+ });
+ fileDialog.setFilterNames(new String[] {
+ "Photoshop Document (*.psd)"
+ });
+ fileDialog.setText("Choose where to save the window layers");
+ final String fileName = fileDialog.open();
+ if (fileName != null) {
+ executeInBackground("Saving window layers", new Runnable() {
+ public void run() {
+ PsdFile psdFile = DeviceBridge.captureLayers(window);
+ if (psdFile != null) {
+ String extensionedFileName = fileName;
+ if (!extensionedFileName.toLowerCase().endsWith(".psd")) {
+ extensionedFileName += ".psd";
+ }
+ try {
+ psdFile.write(new FileOutputStream(extensionedFileName));
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "Unable to write to file " + fileName);
+ }
+ }
+ }
+ });
+ }
+ }
+ }
+ });
+ }
+
+ public void reloadViewHierarchy() {
+ Window window = TreeViewModel.getModel().getWindow();
+ if (window != null) {
+ loadViewTreeData(window);
+ }
+ }
+
+ public void invalidateCurrentNode() {
+ final DrawableViewNode selectedNode = TreeViewModel.getModel().getSelection();
+ if (selectedNode != null) {
+ executeInBackground("Invalidating view", new Runnable() {
+ public void run() {
+ DeviceBridge.invalidateView(selectedNode.viewNode);
+ }
+ });
+ }
+ }
+
+ public void relayoutCurrentNode() {
+ final DrawableViewNode selectedNode = TreeViewModel.getModel().getSelection();
+ if (selectedNode != null) {
+ executeInBackground("Request layout", new Runnable() {
+ public void run() {
+ DeviceBridge.requestLayout(selectedNode.viewNode);
+ }
+ });
+ }
+ }
+
+ public void loadAllViews() {
+ executeInBackground("Loading all views", new Runnable() {
+ public void run() {
+ DrawableViewNode tree = TreeViewModel.getModel().getTree();
+ if (tree != null) {
+ loadViewRecursive(tree.viewNode);
+ // Force the layout viewer to redraw.
+ TreeViewModel.getModel().notifySelectionChanged();
+ }
+ }
+ });
+ }
+
+ private void loadViewRecursive(ViewNode viewNode) {
+ Image image = DeviceBridge.loadCapture(viewNode.window, viewNode);
+ if (image == null) {
+ return;
+ }
+ viewNode.image = image;
+ final int N = viewNode.children.size();
+ for (int i = 0; i < N; i++) {
+ loadViewRecursive(viewNode.children.get(i));
+ }
+ }
+
+ public void filterNodes(String filterText) {
+ DrawableViewNode tree = TreeViewModel.getModel().getTree();
+ if (tree != null) {
+ tree.viewNode.filter(filterText);
+ // Force redraw
+ TreeViewModel.getModel().notifySelectionChanged();
+ }
+ }
+
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java
index 23c6f07..c2cb668 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java
@@ -23,17 +23,26 @@ import com.android.ddmlib.Log;
import com.android.ddmlib.MultiLineReceiver;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.TimeoutException;
+import com.android.hierarchyviewerlib.ui.util.PsdFile;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.image.BufferedImage;
+import java.io.BufferedInputStream;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.imageio.ImageIO;
+
/**
* A bridge to the device.
*/
@@ -120,7 +129,7 @@ public class DeviceBridge {
} catch (AdbCommandRejectedException e) {
Log.e(TAG, String.format("Adb rejected forward command for device %1$s: %2$s",
device, e.getMessage()));
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, String.format("Failed to create forward for device %1$s: %2$s",
device, e.getMessage()));
}
@@ -139,7 +148,7 @@ public class DeviceBridge {
Log.e(TAG, "Timeout removing port forwarding for " + device);
} catch (AdbCommandRejectedException e) {
// In this case, we want to fail silently.
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, String.format("Failed to remove forward for device %1$s: %2$s",
device, e.getMessage()));
}
@@ -354,7 +363,7 @@ public class DeviceBridge {
if (serverInfo.protocolVersion < 3) {
windows.add(Window.getFocusedWindow(device));
}
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, "Unable to load the window list from device " + device);
} finally {
if (connection != null) {
@@ -385,7 +394,7 @@ public class DeviceBridge {
return -1;
}
return (int) Long.parseLong(line.substring(0, line.indexOf(' ')), 16);
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, "Unable to get the focused window from device " + device);
} finally {
if (connection != null) {
@@ -425,8 +434,12 @@ public class DeviceBridge {
while (currentNode.parent != null) {
currentNode = currentNode.parent;
}
+ ViewServerInfo serverInfo = getViewServerInfo(window.getDevice());
+ if (serverInfo != null) {
+ currentNode.protocolVersion = serverInfo.protocolVersion;
+ }
return currentNode;
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, "Unable to load window data for window " + window.getTitle() + " on device "
+ window.getDevice());
} finally {
@@ -456,7 +469,7 @@ public class DeviceBridge {
}
return ret;
}
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, "Unable to load profiling data for window " + window.getTitle()
+ " on device " + window.getDevice());
} finally {
@@ -510,4 +523,104 @@ public class DeviceBridge {
return null;
}
+ public static PsdFile captureLayers(Window window) {
+ DeviceConnection connection = null;
+ DataInputStream in = null;
+
+ try {
+ connection = new DeviceConnection(window.getDevice());
+
+ connection.sendCommand("CAPTURE_LAYERS " + window.encode());
+
+ in =
+ new DataInputStream(new BufferedInputStream(connection.getSocket()
+ .getInputStream()));
+
+ int width = in.readInt();
+ int height = in.readInt();
+
+ PsdFile psd = new PsdFile(width, height);
+
+ while (readLayer(in, psd)) {
+ }
+
+ return psd;
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to capture layers for window " + window.getTitle() + " on device "
+ + window.getDevice());
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (Exception ex) {
+ }
+ }
+ connection.close();
+ }
+
+ return null;
+ }
+
+ private static boolean readLayer(DataInputStream in, PsdFile psd) {
+ try {
+ if (in.read() == 2) {
+ return false;
+ }
+ String name = in.readUTF();
+ boolean visible = in.read() == 1;
+ int x = in.readInt();
+ int y = in.readInt();
+ int dataSize = in.readInt();
+
+ byte[] data = new byte[dataSize];
+ int read = 0;
+ while (read < dataSize) {
+ read += in.read(data, read, dataSize - read);
+ }
+
+ ByteArrayInputStream arrayIn = new ByteArrayInputStream(data);
+ BufferedImage chunk = ImageIO.read(arrayIn);
+
+ // Ensure the image is in the right format
+ BufferedImage image =
+ new BufferedImage(chunk.getWidth(), chunk.getHeight(),
+ BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g = image.createGraphics();
+ g.drawImage(chunk, null, 0, 0);
+ g.dispose();
+
+ psd.addLayer(name, image, new Point(x, y), visible);
+
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public static void invalidateView(ViewNode viewNode) {
+ DeviceConnection connection = null;
+ try {
+ connection = new DeviceConnection(viewNode.window.getDevice());
+ connection.sendCommand("INVALIDATE " + viewNode.window.encode() + " " + viewNode);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to invalidate view " + viewNode + " in window " + viewNode.window
+ + " on device " + viewNode.window.getDevice());
+ } finally {
+ connection.close();
+ }
+ }
+
+ public static void requestLayout(ViewNode viewNode) {
+ DeviceConnection connection = null;
+ try {
+ connection = new DeviceConnection(viewNode.window.getDevice());
+ connection.sendCommand("REQUEST_LAYOUT " + viewNode.window.encode() + " " + viewNode);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to request layout for node " + viewNode + " in window "
+ + viewNode.window + " on device " + viewNode.window.getDevice());
+ } finally {
+ connection.close();
+ }
+ }
+
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceConnection.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceConnection.java
index 18b9619..3080cc1 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceConnection.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceConnection.java
@@ -42,8 +42,14 @@ public class DeviceConnection {
public DeviceConnection(IDevice device) throws IOException {
socketChannel = SocketChannel.open();
- socketChannel.connect(new InetSocketAddress("127.0.0.1", DeviceBridge
- .getDeviceLocalPort(device)));
+ int port = DeviceBridge.getDeviceLocalPort(device);
+
+ if (port == -1) {
+ throw new IOException();
+ }
+
+ socketChannel.connect(new InetSocketAddress("127.0.0.1", port));
+ socketChannel.socket().setSoTimeout(120000);
}
public BufferedReader getInputStream() throws IOException {
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewNode.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewNode.java
index 2872952..6457159 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewNode.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewNode.java
@@ -111,6 +111,12 @@ public class ViewNode {
public int imageReferences = 1;
+ public int viewCount;
+
+ public boolean filtered;
+
+ public int protocolVersion;
+
public ViewNode(Window window, ViewNode parent, String data) {
this.window = window;
this.parent = parent;
@@ -132,7 +138,7 @@ public class ViewNode {
public void dispose() {
final int N = children.size();
- for(int i = 0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
children.get(i).dispose();
}
dereferenceImage();
@@ -179,59 +185,68 @@ public class ViewNode {
id = namedProperties.get("mID").value;
- left = namedProperties.containsKey("mLeft") ?
- getInt("mLeft", 0) : getInt("layout:mLeft", 0);
- top = namedProperties.containsKey("mTop") ?
- getInt("mTop", 0) : getInt("layout:mTop", 0);
- width = namedProperties.containsKey("getWidth()") ?
- getInt("getWidth()", 0) : getInt("layout:getWidth()", 0);
- height = namedProperties.containsKey("getHeight()") ?
- getInt("getHeight()", 0) : getInt("layout:getHeight()", 0);
- scrollX = namedProperties.containsKey("mScrollX") ?
- getInt("mScrollX", 0) : getInt("scrolling:mScrollX", 0);
- scrollY = namedProperties.containsKey("mScrollY") ?
- getInt("mScrollY", 0) : getInt("scrolling:mScrollY", 0);
- paddingLeft = namedProperties.containsKey("mPaddingLeft") ?
- getInt("mPaddingLeft", 0) : getInt("padding:mPaddingLeft", 0);
- paddingRight = namedProperties.containsKey("mPaddingRight") ?
- getInt("mPaddingRight", 0) : getInt("padding:mPaddingRight", 0);
- paddingTop = namedProperties.containsKey("mPaddingTop") ?
- getInt("mPaddingTop", 0) : getInt("padding:mPaddingTop", 0);
- paddingBottom = namedProperties.containsKey("mPaddingBottom") ?
- getInt("mPaddingBottom", 0) : getInt("padding:mPaddingBottom", 0);
- marginLeft = namedProperties.containsKey("layout_leftMargin") ?
- getInt("layout_leftMargin", Integer.MIN_VALUE) :
- getInt("layout:layout_leftMargin", Integer.MIN_VALUE);
- marginRight = namedProperties.containsKey("layout_rightMargin") ?
- getInt("layout_rightMargin", Integer.MIN_VALUE) :
- getInt("layout:layout_rightMargin", Integer.MIN_VALUE);
- marginTop = namedProperties.containsKey("layout_topMargin") ?
- getInt("layout_topMargin", Integer.MIN_VALUE) :
- getInt("layout:layout_topMargin", Integer.MIN_VALUE);
- marginBottom = namedProperties.containsKey("layout_bottomMargin") ?
- getInt("layout_bottomMargin", Integer.MIN_VALUE) :
- getInt("layout:layout_bottomMargin", Integer.MIN_VALUE);
- baseline = namedProperties.containsKey("getBaseline()") ?
- getInt("getBaseline()", 0) :
- getInt("layout:getBaseline()", 0);
- willNotDraw = namedProperties.containsKey("willNotDraw()") ?
- getBoolean("willNotDraw()", false) :
- getBoolean("drawing:willNotDraw()", false);
- hasFocus = namedProperties.containsKey("hasFocus()") ?
- getBoolean("hasFocus()", false) :
- getBoolean("focus:hasFocus()", false);
+ left =
+ namedProperties.containsKey("mLeft") ? getInt("mLeft", 0) : getInt("layout:mLeft",
+ 0);
+ top = namedProperties.containsKey("mTop") ? getInt("mTop", 0) : getInt("layout:mTop", 0);
+ width =
+ namedProperties.containsKey("getWidth()") ? getInt("getWidth()", 0) : getInt(
+ "layout:getWidth()", 0);
+ height =
+ namedProperties.containsKey("getHeight()") ? getInt("getHeight()", 0) : getInt(
+ "layout:getHeight()", 0);
+ scrollX =
+ namedProperties.containsKey("mScrollX") ? getInt("mScrollX", 0) : getInt(
+ "scrolling:mScrollX", 0);
+ scrollY =
+ namedProperties.containsKey("mScrollY") ? getInt("mScrollY", 0) : getInt(
+ "scrolling:mScrollY", 0);
+ paddingLeft =
+ namedProperties.containsKey("mPaddingLeft") ? getInt("mPaddingLeft", 0) : getInt(
+ "padding:mPaddingLeft", 0);
+ paddingRight =
+ namedProperties.containsKey("mPaddingRight") ? getInt("mPaddingRight", 0) : getInt(
+ "padding:mPaddingRight", 0);
+ paddingTop =
+ namedProperties.containsKey("mPaddingTop") ? getInt("mPaddingTop", 0) : getInt(
+ "padding:mPaddingTop", 0);
+ paddingBottom =
+ namedProperties.containsKey("mPaddingBottom") ? getInt("mPaddingBottom", 0)
+ : getInt("padding:mPaddingBottom", 0);
+ marginLeft =
+ namedProperties.containsKey("layout_leftMargin") ? getInt("layout_leftMargin",
+ Integer.MIN_VALUE) : getInt("layout:layout_leftMargin", Integer.MIN_VALUE);
+ marginRight =
+ namedProperties.containsKey("layout_rightMargin") ? getInt("layout_rightMargin",
+ Integer.MIN_VALUE) : getInt("layout:layout_rightMargin", Integer.MIN_VALUE);
+ marginTop =
+ namedProperties.containsKey("layout_topMargin") ? getInt("layout_topMargin",
+ Integer.MIN_VALUE) : getInt("layout:layout_topMargin", Integer.MIN_VALUE);
+ marginBottom =
+ namedProperties.containsKey("layout_bottomMargin") ? getInt("layout_bottomMargin",
+ Integer.MIN_VALUE)
+ : getInt("layout:layout_bottomMargin", Integer.MIN_VALUE);
+ baseline =
+ namedProperties.containsKey("getBaseline()") ? getInt("getBaseline()", 0) : getInt(
+ "layout:getBaseline()", 0);
+ willNotDraw =
+ namedProperties.containsKey("willNotDraw()") ? getBoolean("willNotDraw()", false)
+ : getBoolean("drawing:willNotDraw()", false);
+ hasFocus =
+ namedProperties.containsKey("hasFocus()") ? getBoolean("hasFocus()", false)
+ : getBoolean("focus:hasFocus()", false);
hasMargins =
marginLeft != Integer.MIN_VALUE && marginRight != Integer.MIN_VALUE
&& marginTop != Integer.MIN_VALUE && marginBottom != Integer.MIN_VALUE;
- for(String name : namedProperties.keySet()) {
+ for (String name : namedProperties.keySet()) {
int index = name.indexOf(':');
- if(index != -1) {
+ if (index != -1) {
categories.add(name.substring(0, index));
}
}
- if(categories.size() != 0) {
+ if (categories.size() != 0) {
categories.add(MISCELLANIOUS);
}
}
@@ -278,6 +293,29 @@ public class ViewNode {
}
}
+ public void setViewCount() {
+ viewCount = 1;
+ final int N = children.size();
+ for (int i = 0; i < N; i++) {
+ ViewNode child = children.get(i);
+ child.setViewCount();
+ viewCount += child.viewCount;
+ }
+ }
+
+ public void filter(String text) {
+ int dotIndex = name.lastIndexOf('.');
+ String shortName = (dotIndex == -1) ? name : name.substring(dotIndex + 1);
+ filtered =
+ !text.equals("")
+ && (shortName.toLowerCase().contains(text.toLowerCase()) || (!id
+ .equals("NO_ID") && id.toLowerCase().contains(text.toLowerCase())));
+ final int N = children.size();
+ for (int i = 0; i < N; i++) {
+ children.get(i).filter(text);
+ }
+ }
+
private boolean getBoolean(String name, boolean defaultValue) {
Property p = namedProperties.get(name);
if (p != null) {
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/DeviceSelectionModel.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/DeviceSelectionModel.java
index 7c4f2f6..d8a9a4f 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/DeviceSelectionModel.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/DeviceSelectionModel.java
@@ -42,6 +42,15 @@ public class DeviceSelectionModel {
private Window selectedWindow;
+ private static DeviceSelectionModel model;
+
+ public static DeviceSelectionModel getModel() {
+ if (model == null) {
+ model = new DeviceSelectionModel();
+ }
+ return model;
+ }
+
public void addDevice(IDevice device, Window[] windows) {
synchronized (deviceMap) {
deviceMap.put(device, windows);
@@ -51,23 +60,31 @@ public class DeviceSelectionModel {
}
public void removeDevice(IDevice device) {
+ boolean selectionChanged = false;
synchronized (deviceMap) {
- deviceMap.remove(device);
deviceList.remove(device);
- focusedWindowHashes.remove(device);
- if (selectedDevice == device) {
- selectedDevice = null;
- selectedWindow = null;
+ if (!deviceList.contains(device)) {
+ deviceMap.remove(device);
+ focusedWindowHashes.remove(device);
+ if (selectedDevice == device) {
+ selectedDevice = null;
+ selectedWindow = null;
+ selectionChanged = true;
+ }
}
}
notifyDeviceDisconnected(device);
+ if (selectionChanged) {
+ notifySelectionChanged(selectedDevice, selectedWindow);
+ }
}
public void updateDevice(IDevice device, Window[] windows) {
+ boolean selectionChanged = false;
synchronized (deviceMap) {
deviceMap.put(device, windows);
// If the selected window no longer exists, we clear the selection.
- if (selectedDevice == device) {
+ if (selectedDevice == device && selectedWindow != null) {
boolean windowStillExists = false;
for (int i = 0; i < windows.length && !windowStillExists; i++) {
if (windows[i].equals(selectedWindow)) {
@@ -77,10 +94,14 @@ public class DeviceSelectionModel {
if (!windowStillExists) {
selectedDevice = null;
selectedWindow = null;
+ selectionChanged = true;
}
}
}
notifyDeviceChanged(device);
+ if (selectionChanged) {
+ notifySelectionChanged(selectedDevice, selectedWindow);
+ }
}
/*
@@ -113,6 +134,8 @@ public class DeviceSelectionModel {
public void deviceDisconnected(IDevice device);
public void focusChanged(IDevice device);
+
+ public void selectionChanged(IDevice device, Window window);
}
private WindowChangeListener[] getWindowChangeListenerList() {
@@ -164,6 +187,15 @@ public class DeviceSelectionModel {
}
}
+ private void notifySelectionChanged(IDevice device, Window window) {
+ WindowChangeListener[] listeners = getWindowChangeListenerList();
+ if (listeners != null) {
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].selectionChanged(device, window);
+ }
+ }
+ }
+
public void addWindowChangeListener(WindowChangeListener listener) {
synchronized (windowChangeListeners) {
windowChangeListeners.add(listener);
@@ -208,6 +240,7 @@ public class DeviceSelectionModel {
selectedDevice = device;
selectedWindow = window;
}
+ notifySelectionChanged(device, window);
}
public IDevice getSelectedDevice() {
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/PixelPerfectModel.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/PixelPerfectModel.java
index e8f8240..7702f49 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/PixelPerfectModel.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/PixelPerfectModel.java
@@ -17,7 +17,6 @@
package com.android.hierarchyviewerlib.models;
import com.android.ddmlib.IDevice;
-import com.android.ddmlib.RawImage;
import com.android.hierarchyviewerlib.device.ViewNode;
import org.eclipse.swt.graphics.Image;
@@ -32,7 +31,7 @@ public class PixelPerfectModel {
public static final int MAX_ZOOM = 24;
- private static final int DEFAULT_ZOOM = 8;
+ public static final int DEFAULT_ZOOM = 8;
private IDevice device;
@@ -53,14 +52,22 @@ public class PixelPerfectModel {
private double overlayTransparency = 0.5;
+ private static PixelPerfectModel model;
+
+ public static PixelPerfectModel getModel() {
+ if (model == null) {
+ model = new PixelPerfectModel();
+ }
+ return model;
+ }
+
public void setData(final IDevice device, final Image image, final ViewNode viewNode) {
+ final Image toDispose = this.image;
+ final Image toDispose2 = this.overlayImage;
Display.getDefault().syncExec(new Runnable() {
public void run() {
synchronized (PixelPerfectModel.this) {
PixelPerfectModel.this.device = device;
- if (PixelPerfectModel.this.image != null) {
- PixelPerfectModel.this.image.dispose();
- }
PixelPerfectModel.this.image = image;
PixelPerfectModel.this.viewNode = viewNode;
if (image != null) {
@@ -69,12 +76,28 @@ public class PixelPerfectModel {
} else {
PixelPerfectModel.this.crosshairLocation = null;
}
+ overlayImage = null;
PixelPerfectModel.this.selected = null;
zoom = DEFAULT_ZOOM;
}
}
});
notifyImageLoaded();
+ if (toDispose != null) {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ toDispose.dispose();
+ }
+ });
+ }
+ if (toDispose2 != null) {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ toDispose2.dispose();
+ }
+ });
+ }
+
}
public void setCrosshairLocation(int x, int y) {
@@ -91,20 +114,35 @@ public class PixelPerfectModel {
notifySelectionChanged();
}
- public void setFocusData(final Image image, final ViewNode viewNode) {
+ public void setTree(final ViewNode viewNode) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
synchronized (PixelPerfectModel.this) {
- if (PixelPerfectModel.this.image != null) {
- PixelPerfectModel.this.image.dispose();
- }
- PixelPerfectModel.this.image = image;
PixelPerfectModel.this.viewNode = viewNode;
PixelPerfectModel.this.selected = null;
}
}
});
- notifyFocusChanged();
+ notifyTreeChanged();
+ }
+
+ public void setImage(final Image image) {
+ final Image toDispose = this.image;
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ synchronized (PixelPerfectModel.this) {
+ PixelPerfectModel.this.image = image;
+ }
+ }
+ });
+ notifyImageChanged();
+ if (toDispose != null) {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ toDispose.dispose();
+ }
+ });
+ }
}
public void setZoom(int newZoom) {
@@ -121,17 +159,22 @@ public class PixelPerfectModel {
}
public void setOverlayImage(final Image overlayImage) {
+ final Image toDispose = this.overlayImage;
Display.getDefault().syncExec(new Runnable() {
public void run() {
synchronized (PixelPerfectModel.this) {
- if (PixelPerfectModel.this.overlayImage != null) {
- PixelPerfectModel.this.overlayImage.dispose();
- }
PixelPerfectModel.this.overlayImage = overlayImage;
}
}
});
notifyOverlayChanged();
+ if (toDispose != null) {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ toDispose.dispose();
+ }
+ });
+ }
}
public void setOverlayTransparency(double value) {
@@ -200,7 +243,7 @@ public class PixelPerfectModel {
public void selectionChanged();
- public void focusChanged();
+ public void treeChanged();
public void zoomChanged();
@@ -258,11 +301,11 @@ public class PixelPerfectModel {
}
}
- public void notifyFocusChanged() {
+ public void notifyTreeChanged() {
ImageChangeListener[] listeners = getImageChangeListenerList();
if (listeners != null) {
for (int i = 0; i < listeners.length; i++) {
- listeners[i].focusChanged();
+ listeners[i].treeChanged();
}
}
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/TreeViewModel.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/TreeViewModel.java
index c49ce95..ba0fa57 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/TreeViewModel.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/TreeViewModel.java
@@ -42,15 +42,28 @@ public class TreeViewModel {
private final ArrayList<TreeChangeListener> treeChangeListeners =
new ArrayList<TreeChangeListener>();
+ private static TreeViewModel model;
+
+ public static TreeViewModel getModel() {
+ if (model == null) {
+ model = new TreeViewModel();
+ }
+ return model;
+ }
+
public void setData(Window window, ViewNode viewNode) {
synchronized (this) {
if (tree != null) {
tree.viewNode.dispose();
}
this.window = window;
- tree = new DrawableViewNode(viewNode);
- tree.setLeft();
- tree.placeRoot();
+ if (viewNode == null) {
+ tree = null;
+ } else {
+ tree = new DrawableViewNode(viewNode);
+ tree.setLeft();
+ tree.placeRoot();
+ }
viewport = null;
zoom = 1;
selectedNode = null;
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/CaptureDisplay.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/CaptureDisplay.java
index 54a94fd..a17baac 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/CaptureDisplay.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/CaptureDisplay.java
@@ -35,8 +35,6 @@ import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
public class CaptureDisplay {
@@ -66,12 +64,7 @@ public class CaptureDisplay {
CaptureDisplay.image = image;
CaptureDisplay.viewNode = viewNode;
viewNode.referenceImage();
- int dotIndex = viewNode.name.lastIndexOf('.');
- if (dotIndex != -1) {
- shell.setText(viewNode.name.substring(dotIndex + 1));
- } else {
- shell.setText(viewNode.name);
- }
+ shell.setText(viewNode.name);
boolean shellVisible = shell.isVisible();
if (!shellVisible) {
@@ -82,7 +75,6 @@ public class CaptureDisplay {
shell.computeTrim(0, 0, Math.max(buttonBar.getBounds().width,
image.getBounds().width), buttonBar.getBounds().height
+ image.getBounds().height + 5);
- System.out.println(bounds);
shell.setSize(bounds.width, bounds.height);
if (!shellVisible) {
shell.setLocation(parentShell.getBounds().x
@@ -92,6 +84,8 @@ public class CaptureDisplay {
if (shellVisible) {
canvas.redraw();
}
+ // Odd bug in setting the size... Do it again.
+ shell.setSize(bounds.width, bounds.height);
}
private static void createShell() {
@@ -102,12 +96,14 @@ public class CaptureDisplay {
shell.setLayout(gridLayout);
buttonBar = new Composite(shell, SWT.NONE);
+ // buttonBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
rowLayout.pack = true;
rowLayout.center = true;
buttonBar.setLayout(rowLayout);
Composite buttons = new Composite(buttonBar, SWT.NONE);
buttons.setLayout(new FillLayout());
+ // buttons.setLayoutData(new RowData());
onWhite = new Button(buttons, SWT.TOGGLE);
onWhite.setText("On White");
@@ -118,11 +114,12 @@ public class CaptureDisplay {
onBlack.addSelectionListener(blackSelectionListener);
showExtras = new Button(buttonBar, SWT.CHECK);
+ // showExtras.setLayoutData(new RowData());
showExtras.setText("Show Extras");
showExtras.addSelectionListener(extrasSelectionListener);
canvas = new Canvas(shell, SWT.NONE);
- canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ canvas.setLayoutData(new GridData(GridData.FILL_BOTH));
canvas.addPaintListener(paintListener);
shell.addShellListener(shellListener);
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/DeviceSelector.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/DeviceSelector.java
index 5e7c606..2a11df1 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/DeviceSelector.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/DeviceSelector.java
@@ -18,7 +18,7 @@ package com.android.hierarchyviewerlib.ui;
import com.android.ddmlib.IDevice;
import com.android.ddmuilib.ImageLoader;
-import com.android.hierarchyviewerlib.ComponentRegistry;
+import com.android.hierarchyviewerlib.HierarchyViewerDirector;
import com.android.hierarchyviewerlib.device.Window;
import com.android.hierarchyviewerlib.models.DeviceSelectionModel;
import com.android.hierarchyviewerlib.models.DeviceSelectionModel.WindowChangeListener;
@@ -31,6 +31,9 @@ import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionEvent;
@@ -159,12 +162,14 @@ public class DeviceSelector extends Composite implements WindowChangeListener, S
loadResources();
- model = ComponentRegistry.getDeviceSelectionModel();
+ model = DeviceSelectionModel.getModel();
ContentProvider contentProvider = new ContentProvider();
treeViewer.setContentProvider(contentProvider);
treeViewer.setLabelProvider(contentProvider);
model.addWindowChangeListener(this);
treeViewer.setInput(model);
+
+ addControlListener(controlListener);
}
public void loadResources() {
@@ -197,6 +202,23 @@ public class DeviceSelector extends Composite implements WindowChangeListener, S
}
};
+ // HACK TO GET RID OF AN ERROR
+
+ private ControlListener controlListener = new ControlAdapter() {
+ private boolean noInput = false;
+
+ @Override
+ public void controlResized(ControlEvent e) {
+ if (getBounds().height <= 38) {
+ treeViewer.setInput(null);
+ noInput = true;
+ } else if (noInput) {
+ treeViewer.setInput(model);
+ noInput = false;
+ }
+ }
+ };
+
@Override
public boolean setFocus() {
return tree.setFocus();
@@ -245,13 +267,17 @@ public class DeviceSelector extends Composite implements WindowChangeListener, S
});
}
+ public void selectionChanged(IDevice device, Window window) {
+ // pass
+ }
+
public void widgetDefaultSelected(SelectionEvent e) {
// TODO: Double click to open view hierarchy
Object selection = ((TreeItem) e.item).getData();
if (selection instanceof IDevice) {
- ComponentRegistry.getDirector().loadPixelPerfectData((IDevice) selection);
+ HierarchyViewerDirector.getDirector().loadPixelPerfectData((IDevice) selection);
} else if (selection instanceof Window) {
- ComponentRegistry.getDirector().loadViewTreeData((Window) selection);
+ HierarchyViewerDirector.getDirector().loadViewTreeData((Window) selection);
}
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/LayoutViewer.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/LayoutViewer.java
index 917e96e..458bae6 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/LayoutViewer.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/LayoutViewer.java
@@ -16,7 +16,7 @@
package com.android.hierarchyviewerlib.ui;
-import com.android.hierarchyviewerlib.ComponentRegistry;
+import com.android.hierarchyviewerlib.HierarchyViewerDirector;
import com.android.hierarchyviewerlib.models.TreeViewModel;
import com.android.hierarchyviewerlib.models.TreeViewModel.TreeChangeListener;
import com.android.hierarchyviewerlib.ui.util.DrawableViewNode;
@@ -54,11 +54,13 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
private double scale;
- private boolean showExtras = true;
+ private boolean showExtras = false;
+
+ private boolean onBlack = true;
public LayoutViewer(Composite parent) {
super(parent, SWT.NONE);
- model = ComponentRegistry.getTreeViewModel();
+ model = TreeViewModel.getModel();
model.addTreeChangeListener(this);
addDisposeListener(disposeListener);
@@ -72,6 +74,16 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
public void setShowExtras(boolean show) {
showExtras = show;
+ doRedraw();
+ }
+
+ public void setOnBlack(boolean value) {
+ onBlack = value;
+ doRedraw();
+ }
+
+ public boolean getOnBlack() {
+ return onBlack;
}
private DisposeListener disposeListener = new DisposeListener() {
@@ -93,12 +105,12 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
public void mouseDoubleClick(MouseEvent e) {
if (selectedNode != null) {
- ComponentRegistry.getDirector().showCapture(getShell(), selectedNode.viewNode);
+ HierarchyViewerDirector.getDirector()
+ .showCapture(getShell(), selectedNode.viewNode);
}
}
public void mouseDown(MouseEvent e) {
- System.out.println("CLICK");
boolean selectionChanged = false;
DrawableViewNode newSelection = null;
synchronized (LayoutViewer.this) {
@@ -125,8 +137,8 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
}
};
- private DrawableViewNode updateSelection(DrawableViewNode node, float x, float y, int left, int top,
- int clipX, int clipY, int clipWidth, int clipHeight) {
+ private DrawableViewNode updateSelection(DrawableViewNode node, float x, float y, int left,
+ int top, int clipX, int clipY, int clipWidth, int clipHeight) {
if (!node.treeDrawn) {
return null;
}
@@ -145,10 +157,12 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
final int N = node.children.size();
for (int i = N - 1; i >= 0; i--) {
DrawableViewNode child = node.children.get(i);
- DrawableViewNode ret = updateSelection(child, x, y, left + child.viewNode.left - node.viewNode.scrollX,
- top + child.viewNode.top - node.viewNode.scrollY, clipX, clipY, clipWidth,
- clipHeight);
- if(ret != null) {
+ DrawableViewNode ret =
+ updateSelection(child, x, y,
+ left + child.viewNode.left - node.viewNode.scrollX, top
+ + child.viewNode.top - node.viewNode.scrollY, clipX, clipY,
+ clipWidth, clipHeight);
+ if (ret != null) {
return ret;
}
}
@@ -158,14 +172,23 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
private PaintListener paintListener = new PaintListener() {
public void paintControl(PaintEvent e) {
synchronized (LayoutViewer.this) {
- e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
+ if (onBlack) {
+ e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
+ } else {
+ e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
+ }
e.gc.fillRectangle(0, 0, getBounds().width, getBounds().height);
if (tree != null) {
- e.gc.setLineWidth((int) Math.ceil(0.2 / scale));
+ e.gc.setLineWidth((int) Math.ceil(0.3 / scale));
e.gc.setTransform(transform);
- e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
+ if (onBlack) {
+ e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
+ } else {
+ e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
+ }
Rectangle parentClipping = e.gc.getClipping();
- e.gc.setClipping(0, 0, tree.viewNode.width, tree.viewNode.height);
+ e.gc.setClipping(0, 0, tree.viewNode.width + (int) Math.ceil(0.3 / scale),
+ tree.viewNode.height + (int) Math.ceil(0.3 / scale));
paintRecursive(e.gc, tree, 0, 0, true);
if (selectedNode != null) {
@@ -191,25 +214,27 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
for (int i = 0; i < N; i++) {
e.gc.drawRectangle((int) (left - rightLeftDistances.get(i).x),
(int) (top - rightLeftDistances.get(i).y),
- currentNode.viewNode.width - (int) Math.ceil(0.2 / scale),
- currentNode.viewNode.height - (int) Math.ceil(0.2 / scale));
+ currentNode.viewNode.width, currentNode.viewNode.height);
currentNode = currentNode.parent;
}
if (showExtras && selectedNode.viewNode.image != null) {
e.gc.drawImage(selectedNode.viewNode.image, left, top);
- e.gc
- .setForeground(Display.getDefault().getSystemColor(
- SWT.COLOR_WHITE));
+ if (onBlack) {
+ e.gc.setForeground(Display.getDefault().getSystemColor(
+ SWT.COLOR_WHITE));
+ } else {
+ e.gc.setForeground(Display.getDefault().getSystemColor(
+ SWT.COLOR_BLACK));
+ }
paintRecursive(e.gc, selectedNode, left, top, true);
}
e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
e.gc.setLineWidth((int) Math.ceil(2 / scale));
- e.gc.drawRectangle(left, top, selectedNode.viewNode.width
- - (int) Math.ceil(2 / scale) + 1, selectedNode.viewNode.height
- - (int) Math.ceil(2 / scale) + 1);
+ e.gc.drawRectangle(left, top, selectedNode.viewNode.width,
+ selectedNode.viewNode.height);
}
}
}
@@ -227,9 +252,16 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
}
Rectangle parentClipping = gc.getClipping();
int x1 = Math.max(parentClipping.x, left);
- int x2 = Math.min(parentClipping.x + parentClipping.width, left + node.viewNode.width);
+ int x2 =
+ Math.min(parentClipping.x + parentClipping.width, left + node.viewNode.width
+ + (int) Math.ceil(0.3 / scale));
int y1 = Math.max(parentClipping.y, top);
- int y2 = Math.min(parentClipping.y + parentClipping.height, top + node.viewNode.height);
+ int y2 =
+ Math.min(parentClipping.y + parentClipping.height, top + node.viewNode.height
+ + (int) Math.ceil(0.3 / scale));
+ if (x2 <= x1 || y2 <= y1) {
+ return;
+ }
gc.setClipping(x1, y1, x2 - x1, y2 - y1);
final int N = node.children.size();
for (int i = 0; i < N; i++) {
@@ -238,8 +270,7 @@ public class LayoutViewer extends Canvas implements TreeChangeListener {
}
gc.setClipping(parentClipping);
if (!node.viewNode.willNotDraw) {
- gc.drawRectangle(left, top, node.viewNode.width - (int) Math.ceil(0.2 / scale),
- node.viewNode.height - (int) Math.ceil(0.2 / scale));
+ gc.drawRectangle(left, top, node.viewNode.width, node.viewNode.height);
}
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfect.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfect.java
index 1a2876b..05b9679 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfect.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfect.java
@@ -16,8 +16,6 @@
package com.android.hierarchyviewerlib.ui;
-import com.android.ddmlib.RawImage;
-import com.android.hierarchyviewerlib.ComponentRegistry;
import com.android.hierarchyviewerlib.device.ViewNode;
import com.android.hierarchyviewerlib.models.PixelPerfectModel;
import com.android.hierarchyviewerlib.models.PixelPerfectModel.ImageChangeListener;
@@ -26,6 +24,8 @@ import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
@@ -33,8 +33,6 @@ import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Canvas;
@@ -74,12 +72,13 @@ public class PixelPerfect extends ScrolledComposite implements ImageChangeListen
setContent(canvas);
setExpandHorizontal(true);
setExpandVertical(true);
- model = ComponentRegistry.getPixelPerfectModel();
+ model = PixelPerfectModel.getModel();
model.addImageChangeListener(this);
canvas.addPaintListener(paintListener);
canvas.addMouseListener(mouseListener);
canvas.addMouseMoveListener(mouseMoveListener);
+ canvas.addKeyListener(keyListener);
addDisposeListener(disposeListener);
@@ -92,9 +91,6 @@ public class PixelPerfect extends ScrolledComposite implements ImageChangeListen
private DisposeListener disposeListener = new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
model.removeImageChangeListener(PixelPerfect.this);
- if (image != null) {
- image.dispose();
- }
crosshairColor.dispose();
borderColor.dispose();
paddingColor.dispose();
@@ -147,6 +143,51 @@ public class PixelPerfect extends ScrolledComposite implements ImageChangeListen
model.setCrosshairLocation(e.x, e.y);
}
+ private KeyListener keyListener = new KeyListener() {
+
+ public void keyPressed(KeyEvent e) {
+ boolean crosshairMoved = false;
+ synchronized (PixelPerfect.this) {
+ if (image != null) {
+ switch (e.keyCode) {
+ case SWT.ARROW_UP:
+ if (crosshairLocation.y != 0) {
+ crosshairLocation.y--;
+ crosshairMoved = true;
+ }
+ break;
+ case SWT.ARROW_DOWN:
+ if (crosshairLocation.y != height - 1) {
+ crosshairLocation.y++;
+ crosshairMoved = true;
+ }
+ break;
+ case SWT.ARROW_LEFT:
+ if (crosshairLocation.x != 0) {
+ crosshairLocation.x--;
+ crosshairMoved = true;
+ }
+ break;
+ case SWT.ARROW_RIGHT:
+ if (crosshairLocation.x != width - 1) {
+ crosshairLocation.x++;
+ crosshairMoved = true;
+ }
+ break;
+ }
+ }
+ }
+ if (crosshairMoved) {
+ model.setCrosshairLocation(crosshairLocation.x, crosshairLocation.y);
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+ // pass
+ }
+
+ };
+
private PaintListener paintListener = new PaintListener() {
public void paintControl(PaintEvent e) {
synchronized (PixelPerfect.this) {
@@ -266,6 +307,7 @@ public class PixelPerfect extends ScrolledComposite implements ImageChangeListen
loadImage();
crosshairLocation = model.getCrosshairLocation();
selectedNode = model.getSelected();
+ overlayImage = model.getOverlayImage();
}
}
});
@@ -297,11 +339,10 @@ public class PixelPerfect extends ScrolledComposite implements ImageChangeListen
doRedraw();
}
- public void focusChanged() {
+ public void treeChanged() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
synchronized (this) {
- loadImage();
selectedNode = model.getSelected();
}
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectLoupe.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectLoupe.java
index 84ce08f..5497a3f 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectLoupe.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectLoupe.java
@@ -16,14 +16,14 @@
package com.android.hierarchyviewerlib.ui;
-import com.android.ddmlib.RawImage;
-import com.android.hierarchyviewerlib.ComponentRegistry;
import com.android.hierarchyviewerlib.models.PixelPerfectModel;
import com.android.hierarchyviewerlib.models.PixelPerfectModel.ImageChangeListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseWheelListener;
@@ -73,13 +73,14 @@ public class PixelPerfectLoupe extends Canvas implements ImageChangeListener {
public PixelPerfectLoupe(Composite parent) {
super(parent, SWT.NONE);
- model = ComponentRegistry.getPixelPerfectModel();
+ model = PixelPerfectModel.getModel();
model.addImageChangeListener(this);
addPaintListener(paintListener);
addMouseListener(mouseListener);
addMouseWheelListener(mouseWheelListener);
addDisposeListener(disposeListener);
+ addKeyListener(keyListener);
crosshairColor = new Color(Display.getDefault(), new RGB(255, 94, 254));
@@ -90,14 +91,12 @@ public class PixelPerfectLoupe extends Canvas implements ImageChangeListener {
synchronized (this) {
showOverlay = value;
}
+ doRedraw();
}
private DisposeListener disposeListener = new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
model.removeImageChangeListener(PixelPerfectLoupe.this);
- if (image != null) {
- image.dispose();
- }
crosshairColor.dispose();
transform.dispose();
if (grid != null) {
@@ -161,7 +160,53 @@ public class PixelPerfectLoupe extends Canvas implements ImageChangeListener {
}
}
+ private KeyListener keyListener = new KeyListener() {
+
+ public void keyPressed(KeyEvent e) {
+ boolean crosshairMoved = false;
+ synchronized (PixelPerfectLoupe.this) {
+ if (image != null) {
+ switch (e.keyCode) {
+ case SWT.ARROW_UP:
+ if (crosshairLocation.y != 0) {
+ crosshairLocation.y--;
+ crosshairMoved = true;
+ }
+ break;
+ case SWT.ARROW_DOWN:
+ if (crosshairLocation.y != height - 1) {
+ crosshairLocation.y++;
+ crosshairMoved = true;
+ }
+ break;
+ case SWT.ARROW_LEFT:
+ if (crosshairLocation.x != 0) {
+ crosshairLocation.x--;
+ crosshairMoved = true;
+ }
+ break;
+ case SWT.ARROW_RIGHT:
+ if (crosshairLocation.x != width - 1) {
+ crosshairLocation.x++;
+ crosshairMoved = true;
+ }
+ break;
+ }
+ }
+ }
+ if (crosshairMoved) {
+ model.setCrosshairLocation(crosshairLocation.x, crosshairLocation.y);
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+ // pass
+ }
+
+ };
+
private PaintListener paintListener = new PaintListener() {
+ @SuppressWarnings("deprecation")
public void paintControl(PaintEvent e) {
synchronized (PixelPerfectLoupe.this) {
e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
@@ -255,6 +300,7 @@ public class PixelPerfectLoupe extends Canvas implements ImageChangeListener {
loadImage();
crosshairLocation = model.getCrosshairLocation();
zoom = model.getZoom();
+ overlayImage = model.getOverlayImage();
}
}
});
@@ -283,8 +329,8 @@ public class PixelPerfectLoupe extends Canvas implements ImageChangeListener {
// pass
}
- public void focusChanged() {
- imageChanged();
+ public void treeChanged() {
+ // pass
}
public void zoomChanged() {
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectPixelPanel.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectPixelPanel.java
new file mode 100644
index 0000000..8fce603
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectPixelPanel.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.hierarchyviewerlib.ui;
+
+import com.android.hierarchyviewerlib.models.PixelPerfectModel;
+import com.android.hierarchyviewerlib.models.PixelPerfectModel.ImageChangeListener;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+public class PixelPerfectPixelPanel extends Canvas implements ImageChangeListener {
+ private PixelPerfectModel model;
+
+ private Image image;
+
+ private Image overlayImage;
+
+ private Point crosshairLocation;
+
+ public static final int PREFERRED_WIDTH = 180;
+
+ public static final int PREFERRED_HEIGHT = 52;
+
+ public PixelPerfectPixelPanel(Composite parent) {
+ super(parent, SWT.NONE);
+ model = PixelPerfectModel.getModel();
+ model.addImageChangeListener(this);
+
+ addPaintListener(paintListener);
+ addDisposeListener(disposeListener);
+ }
+
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ int height = PREFERRED_HEIGHT;
+ int width = (wHint == SWT.DEFAULT) ? PREFERRED_WIDTH : wHint;
+ return new Point(width, height);
+ }
+
+ private DisposeListener disposeListener = new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ model.removeImageChangeListener(PixelPerfectPixelPanel.this);
+ }
+ };
+
+ private PaintListener paintListener = new PaintListener() {
+ public void paintControl(PaintEvent e) {
+ synchronized (PixelPerfectPixelPanel.this) {
+ e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
+ e.gc.fillRectangle(0, 0, getBounds().width, getBounds().height);
+ if (image != null) {
+ RGB pixel =
+ image.getImageData().palette.getRGB(image.getImageData().getPixel(
+ crosshairLocation.x, crosshairLocation.y));
+ Color rgbColor = new Color(Display.getDefault(), pixel);
+ e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
+ e.gc.setBackground(rgbColor);
+ e.gc.drawRectangle(4, 4, 60, 30);
+ e.gc.fillRectangle(5, 5, 59, 29);
+ rgbColor.dispose();
+ e.gc.drawText("#"
+ + Integer
+ .toHexString(
+ (1 << 24) + (pixel.red << 16) + (pixel.green << 8)
+ + pixel.blue).substring(1), 4, 35, true);
+ e.gc.drawText("R:", 80, 4, true);
+ e.gc.drawText("G:", 80, 20, true);
+ e.gc.drawText("B:", 80, 35, true);
+ e.gc.drawText(Integer.toString(pixel.red), 97, 4, true);
+ e.gc.drawText(Integer.toString(pixel.green), 97, 20, true);
+ e.gc.drawText(Integer.toString(pixel.blue), 97, 35, true);
+ e.gc.drawText("X:", 132, 4, true);
+ e.gc.drawText("Y:", 132, 20, true);
+ e.gc.drawText(Integer.toString(crosshairLocation.x) + " px", 149, 4, true);
+ e.gc.drawText(Integer.toString(crosshairLocation.y) + " px", 149, 20, true);
+
+ if (overlayImage != null) {
+ int xInOverlay = crosshairLocation.x;
+ int yInOverlay =
+ crosshairLocation.y
+ - (image.getBounds().height - overlayImage.getBounds().height);
+ if (xInOverlay >= 0 && yInOverlay >= 0
+ && xInOverlay < overlayImage.getBounds().width
+ && yInOverlay < overlayImage.getBounds().height) {
+ pixel =
+ overlayImage.getImageData().palette.getRGB(overlayImage
+ .getImageData().getPixel(xInOverlay, yInOverlay));
+ rgbColor = new Color(Display.getDefault(), pixel);
+ e.gc
+ .setForeground(Display.getDefault().getSystemColor(
+ SWT.COLOR_WHITE));
+ e.gc.setBackground(rgbColor);
+ e.gc.drawRectangle(204, 4, 60, 30);
+ e.gc.fillRectangle(205, 5, 59, 29);
+ rgbColor.dispose();
+ e.gc.drawText("#"
+ + Integer.toHexString(
+ (1 << 24) + (pixel.red << 16) + (pixel.green << 8)
+ + pixel.blue).substring(1), 204, 35, true);
+ e.gc.drawText("R:", 280, 4, true);
+ e.gc.drawText("G:", 280, 20, true);
+ e.gc.drawText("B:", 280, 35, true);
+ e.gc.drawText(Integer.toString(pixel.red), 297, 4, true);
+ e.gc.drawText(Integer.toString(pixel.green), 297, 20, true);
+ e.gc.drawText(Integer.toString(pixel.blue), 297, 35, true);
+ }
+ }
+ }
+ }
+ }
+ };
+
+ private void doRedraw() {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ redraw();
+ }
+ });
+ }
+
+ public void crosshairMoved() {
+ synchronized (this) {
+ crosshairLocation = model.getCrosshairLocation();
+ }
+ doRedraw();
+ }
+
+ public void imageChanged() {
+ synchronized (this) {
+ image = model.getImage();
+ }
+ doRedraw();
+ }
+
+ public void imageLoaded() {
+ synchronized (this) {
+ image = model.getImage();
+ crosshairLocation = model.getCrosshairLocation();
+ overlayImage = model.getOverlayImage();
+ }
+ doRedraw();
+ }
+
+ public void overlayChanged() {
+ synchronized (this) {
+ overlayImage = model.getOverlayImage();
+ }
+ doRedraw();
+ }
+
+ public void overlayTransparencyChanged() {
+ // pass
+ }
+
+ public void selectionChanged() {
+ // pass
+ }
+
+ public void treeChanged() {
+ // pass
+ }
+
+ public void zoomChanged() {
+ // pass
+ }
+}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java
index 7df4d9d..80e4091 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PixelPerfectTree.java
@@ -17,7 +17,6 @@
package com.android.hierarchyviewerlib.ui;
import com.android.ddmuilib.ImageLoader;
-import com.android.hierarchyviewerlib.ComponentRegistry;
import com.android.hierarchyviewerlib.device.ViewNode;
import com.android.hierarchyviewerlib.models.PixelPerfectModel;
import com.android.hierarchyviewerlib.models.PixelPerfectModel.ImageChangeListener;
@@ -141,7 +140,7 @@ public class PixelPerfectTree extends Composite implements ImageChangeListener,
addDisposeListener(disposeListener);
- model = ComponentRegistry.getPixelPerfectModel();
+ model = PixelPerfectModel.getModel();
ContentProvider contentProvider = new ContentProvider();
treeViewer.setContentProvider(contentProvider);
treeViewer.setLabelProvider(contentProvider);
@@ -150,7 +149,7 @@ public class PixelPerfectTree extends Composite implements ImageChangeListener,
}
- public void loadResources() {
+ private void loadResources() {
ImageLoader loader = ImageLoader.getDdmUiLibLoader();
fileImage = loader.loadImage("file.png", Display.getDefault());
@@ -191,7 +190,7 @@ public class PixelPerfectTree extends Composite implements ImageChangeListener,
// pass
}
- public void focusChanged() {
+ public void treeChanged() {
imageLoaded();
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/ProfileViewer.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/ProfileViewer.java
deleted file mode 100644
index f83ba3d..0000000
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/ProfileViewer.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.hierarchyviewerlib.ui;
-
-import com.android.hierarchyviewerlib.ComponentRegistry;
-import com.android.hierarchyviewerlib.models.TreeViewModel;
-import com.android.hierarchyviewerlib.models.TreeViewModel.TreeChangeListener;
-import com.android.hierarchyviewerlib.ui.util.DrawableViewNode;
-import com.android.hierarchyviewerlib.ui.util.TreeColumnResizer;
-
-import org.eclipse.jface.viewers.ILabelProviderListener;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Tree;
-import org.eclipse.swt.widgets.TreeColumn;
-
-import java.text.DecimalFormat;
-
-public class ProfileViewer extends Composite implements TreeChangeListener {
- private TreeViewModel model;
-
- private TreeViewer treeViewer;
-
- private Tree tree;
-
- private DrawableViewNode selectedNode;
-
- private class ContentProvider implements ITreeContentProvider, ITableLabelProvider {
-
- public Object[] getChildren(Object parentElement) {
- synchronized (ProfileViewer.this) {
- return new Object[0];
- }
- }
-
- public Object getParent(Object element) {
- synchronized (ProfileViewer.this) {
- return new Object[0];
- }
- }
-
- public boolean hasChildren(Object element) {
- synchronized (ProfileViewer.this) {
- return false;
- }
- }
-
- public Object[] getElements(Object inputElement) {
- synchronized (ProfileViewer.this) {
- if (selectedNode != null && selectedNode.viewNode.measureTime != -1) {
- return new String[] {
- "measure", "layout", "draw"
- };
- }
- return new Object[0];
- }
- }
-
- public void dispose() {
- // pass
- }
-
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- // pass
- }
-
- public Image getColumnImage(Object element, int column) {
- return null;
- }
-
- public String getColumnText(Object element, int column) {
- synchronized (ProfileViewer.this) {
- if (selectedNode != null) {
- if (column == 0) {
- return (String) element;
- } else if (column == 1) {
- DecimalFormat formatter = new DecimalFormat("0.000");
- if(((String)element).equals("measure")) {
- if (selectedNode.viewNode.measureTime == -1) {
- return "unknown";
- }
- return formatter.format(selectedNode.viewNode.measureTime);
- } else if (((String) element).equals("layout")) {
- if (selectedNode.viewNode.layoutTime == -1) {
- return "unknown";
- }
- return formatter.format(selectedNode.viewNode.layoutTime);
- } else {
- if (selectedNode.viewNode.drawTime == -1) {
- return "unknown";
- }
- return formatter.format(selectedNode.viewNode.drawTime);
- }
- }
- }
- return "";
- }
- }
-
- public void addListener(ILabelProviderListener listener) {
- // pass
- }
-
- public boolean isLabelProperty(Object element, String property) {
- // pass
- return false;
- }
-
- public void removeListener(ILabelProviderListener listener) {
- // pass
- }
- }
-
- public ProfileViewer(Composite parent) {
- super(parent, SWT.NONE);
- setLayout(new FillLayout());
- treeViewer = new TreeViewer(this, SWT.NONE);
-
- tree = treeViewer.getTree();
- tree.setLinesVisible(true);
- tree.setHeaderVisible(true);
-
- TreeColumn operationColumn = new TreeColumn(tree, SWT.NONE);
- operationColumn.setText("Operation");
- TreeColumn durationColumn = new TreeColumn(tree, SWT.NONE);
- durationColumn.setText("Duration (ms)");
-
- model = ComponentRegistry.getTreeViewModel();
- ContentProvider contentProvider = new ContentProvider();
- treeViewer.setContentProvider(contentProvider);
- treeViewer.setLabelProvider(contentProvider);
- treeViewer.setInput(model);
- model.addTreeChangeListener(this);
-
- new TreeColumnResizer(this, operationColumn, durationColumn);
- }
-
- public void selectionChanged() {
- synchronized (this) {
- selectedNode = model.getSelection();
- }
- doRefresh();
- }
-
- public void treeChanged() {
- synchronized (this) {
- selectedNode = model.getSelection();
- }
- doRefresh();
- }
-
- public void viewportChanged() {
- // pass
- }
-
- public void zoomChanged() {
- // pass
- }
-
- private void doRefresh() {
- Display.getDefault().asyncExec(new Runnable() {
- public void run() {
- treeViewer.refresh();
- }
- });
- }
-}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PropertyViewer.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PropertyViewer.java
index d262d16..0b76909 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PropertyViewer.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/PropertyViewer.java
@@ -16,7 +16,6 @@
package com.android.hierarchyviewerlib.ui;
-import com.android.hierarchyviewerlib.ComponentRegistry;
import com.android.hierarchyviewerlib.device.ViewNode;
import com.android.hierarchyviewerlib.device.ViewNode.Property;
import com.android.hierarchyviewerlib.models.TreeViewModel;
@@ -30,6 +29,13 @@ import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
@@ -48,6 +54,8 @@ public class PropertyViewer extends Composite implements TreeChangeListener {
private DrawableViewNode selectedNode;
+ private Font smallFont;
+
private class ContentProvider implements ITreeContentProvider, ITableLabelProvider {
public Object[] getChildren(Object parentElement) {
@@ -187,16 +195,66 @@ public class PropertyViewer extends Composite implements TreeChangeListener {
TreeColumn valueColumn = new TreeColumn(tree, SWT.NONE);
valueColumn.setText("Value");
- model = ComponentRegistry.getTreeViewModel();
+ model = TreeViewModel.getModel();
ContentProvider contentProvider = new ContentProvider();
treeViewer.setContentProvider(contentProvider);
treeViewer.setLabelProvider(contentProvider);
treeViewer.setInput(model);
model.addTreeChangeListener(this);
+ loadResources();
+ addDisposeListener(disposeListener);
+
+ tree.setFont(smallFont);
+
new TreeColumnResizer(this, propertyColumn, valueColumn);
+
+ addControlListener(controlListener);
}
+ public void loadResources() {
+ Display display = Display.getDefault();
+ Font systemFont = display.getSystemFont();
+ FontData[] fontData = systemFont.getFontData();
+ FontData[] newFontData = new FontData[fontData.length];
+ for (int i = 0; i < fontData.length; i++) {
+ newFontData[i] = new FontData(fontData[i].getName(), 8, fontData[i].getStyle());
+ }
+ smallFont = new Font(Display.getDefault(), newFontData);
+ }
+
+ private DisposeListener disposeListener = new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ model.removeTreeChangeListener(PropertyViewer.this);
+ smallFont.dispose();
+ }
+ };
+
+ // HACK TO GET RID OF AN ERROR
+
+ private ControlListener controlListener = new ControlAdapter() {
+ private boolean noInput = false;
+
+ private boolean noHeader = false;
+
+ @Override
+ public void controlResized(ControlEvent e) {
+ if (getBounds().height <= 20) {
+ tree.setHeaderVisible(false);
+ noHeader = true;
+ } else if (noHeader) {
+ tree.setHeaderVisible(true);
+ noHeader = false;
+ }
+ if (getBounds().height <= 38) {
+ treeViewer.setInput(null);
+ noInput = true;
+ } else if (noInput) {
+ treeViewer.setInput(model);
+ noInput = false;
+ }
+ }
+ };
public void selectionChanged() {
synchronized (this) {
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeView.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeView.java
index abf5690..4dfdf19 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeView.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeView.java
@@ -17,7 +17,7 @@
package com.android.hierarchyviewerlib.ui;
import com.android.ddmuilib.ImageLoader;
-import com.android.hierarchyviewerlib.ComponentRegistry;
+import com.android.hierarchyviewerlib.HierarchyViewerDirector;
import com.android.hierarchyviewerlib.device.ViewNode.ProfileRating;
import com.android.hierarchyviewerlib.models.TreeViewModel;
import com.android.hierarchyviewerlib.models.TreeViewModel.TreeChangeListener;
@@ -36,6 +36,7 @@ import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseWheelListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Path;
@@ -46,6 +47,8 @@ import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
+import java.text.DecimalFormat;
+
public class TreeView extends Canvas implements TreeChangeListener {
private TreeViewModel model;
@@ -70,16 +73,24 @@ public class TreeView extends Canvas implements TreeChangeListener {
public static final float BEZIER_FRACTION = 0.35f;
- private Image redImage;
+ private static Image redImage;
+
+ private static Image yellowImage;
+
+ private static Image greenImage;
- private Image yellowImage;
+ private static Image notSelectedImage;
- private Image greenImage;
+ private static Image selectedImage;
+
+ private static Image filteredImage;
+
+ private static Image filteredSelectedImage;
public TreeView(Composite parent) {
super(parent, SWT.NONE);
- model = ComponentRegistry.getTreeViewModel();
+ model = TreeViewModel.getModel();
model.addTreeChangeListener(this);
addPaintListener(paintListener);
@@ -90,13 +101,22 @@ public class TreeView extends Canvas implements TreeChangeListener {
addDisposeListener(disposeListener);
addKeyListener(keyListener);
+ loadResources();
+
transform = new Transform(Display.getDefault());
inverse = new Transform(Display.getDefault());
+ }
+
+ private void loadResources() {
ImageLoader loader = ImageLoader.getLoader(this.getClass());
redImage = loader.loadImage("red.png", Display.getDefault());
yellowImage = loader.loadImage("yellow.png", Display.getDefault());
greenImage = loader.loadImage("green.png", Display.getDefault());
+ notSelectedImage = loader.loadImage("not-selected.png", Display.getDefault());
+ selectedImage = loader.loadImage("selected.png", Display.getDefault());
+ filteredImage = loader.loadImage("filtered.png", Display.getDefault());
+ filteredSelectedImage = loader.loadImage("selected-filtered.png", Display.getDefault());
}
private DisposeListener disposeListener = new DisposeListener() {
@@ -138,7 +158,7 @@ public class TreeView extends Canvas implements TreeChangeListener {
if (tree != null && viewport != null && selectedNode != null) {
switch (e.keyCode) {
case SWT.ARROW_LEFT:
- if(selectedNode.parent != null) {
+ if (selectedNode.parent != null) {
selectedNode = selectedNode.parent;
selectionChanged = true;
}
@@ -171,7 +191,7 @@ public class TreeView extends Canvas implements TreeChangeListener {
currentNode = selectedNode;
while (currentNode.parent != null
&& currentNode.viewNode.index + 1 == currentNode.parent.children
- .size()) {
+ .size()) {
levelsOut++;
currentNode = currentNode.parent;
}
@@ -193,7 +213,7 @@ public class TreeView extends Canvas implements TreeChangeListener {
DrawableViewNode rightNode = null;
double mostOverlap = 0;
final int N = selectedNode.children.size();
- for(int i = 0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
DrawableViewNode child = selectedNode.children.get(i);
DrawableViewNode topMostChild = child;
while (topMostChild.children.size() != 0) {
@@ -224,7 +244,7 @@ public class TreeView extends Canvas implements TreeChangeListener {
model.setSelection(selectedNode);
}
if (clickedNode != null) {
- ComponentRegistry.getDirector().showCapture(getShell(), clickedNode.viewNode);
+ HierarchyViewerDirector.getDirector().showCapture(getShell(), clickedNode.viewNode);
}
}
@@ -243,7 +263,7 @@ public class TreeView extends Canvas implements TreeChangeListener {
}
}
if (clickedNode != null) {
- ComponentRegistry.getDirector().showCapture(getShell(), clickedNode.viewNode);
+ HierarchyViewerDirector.getDirector().showCapture(getShell(), clickedNode.viewNode);
}
}
@@ -399,27 +419,115 @@ public class TreeView extends Canvas implements TreeChangeListener {
private PaintListener paintListener = new PaintListener() {
public void paintControl(PaintEvent e) {
synchronized (TreeView.this) {
- e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
+ e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
e.gc.fillRectangle(0, 0, getBounds().width, getBounds().height);
if (tree != null && viewport != null) {
e.gc.setTransform(transform);
- e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_GRAY));
+ e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
Path connectionPath = new Path(Display.getDefault());
- paintRecursive(e.gc, tree, connectionPath);
+ paintRecursive(e.gc, transform, tree, selectedNode, connectionPath);
e.gc.drawPath(connectionPath);
connectionPath.dispose();
+
+ Transform tempTransform = new Transform(Display.getDefault());
+ e.gc.setTransform(tempTransform);
+
+ e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_GRAY));
+ e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
+
+ // Draw the number of views.
+ String viewsString = Integer.toString(tree.viewNode.viewCount) + " view";
+ if (tree.viewNode.viewCount != 1) {
+ viewsString += 's';
+ }
+ org.eclipse.swt.graphics.Point stringExtent = e.gc.stringExtent(viewsString);
+
+ e.gc.fillRectangle(0, getBounds().height - stringExtent.y - 4,
+ stringExtent.x + 4, stringExtent.y + 4);
+
+ e.gc.drawText(viewsString, 2, getBounds().height - stringExtent.y - 2);
+
+ DrawableViewNode profiledNode =
+ (tree.viewNode.protocolVersion < 3) ? tree : selectedNode;
+
+ // Draw the profiling stuff
+ if (profiledNode != null && profiledNode.viewNode.measureTime != -1) {
+ DecimalFormat formatter = new DecimalFormat("0.000");
+ String measureString = "Measure:";
+ String measureTimeString =
+ formatter.format(profiledNode.viewNode.measureTime) + " ms";
+ String layoutString = "Layout:";
+ String layoutTimeString =
+ formatter.format(profiledNode.viewNode.layoutTime) + " ms";
+ String drawString = "Draw:";
+ String drawTimeString =
+ formatter.format(profiledNode.viewNode.drawTime) + " ms";
+
+ org.eclipse.swt.graphics.Point measureExtent =
+ e.gc.stringExtent(measureString);
+ org.eclipse.swt.graphics.Point measureTimeExtent =
+ e.gc.stringExtent(measureTimeString);
+ org.eclipse.swt.graphics.Point layoutExtent =
+ e.gc.stringExtent(layoutString);
+ org.eclipse.swt.graphics.Point layoutTimeExtent =
+ e.gc.stringExtent(layoutTimeString);
+ org.eclipse.swt.graphics.Point drawExtent = e.gc.stringExtent(drawString);
+ org.eclipse.swt.graphics.Point drawTimeExtent =
+ e.gc.stringExtent(drawTimeString);
+
+ int letterHeight = e.gc.getFontMetrics().getHeight();
+
+ int width =
+ Math.max(measureExtent.x, Math.max(layoutExtent.x, drawExtent.x))
+ + Math.max(measureTimeExtent.x, Math.max(
+ layoutTimeExtent.x, drawTimeExtent.x)) + 8;
+ int height = 3 * letterHeight + 8;
+
+ int x = getBounds().width - width;
+ int y = getBounds().height - height;
+
+ e.gc.fillRectangle(x, y, width, height);
+
+ x += 2;
+ y += 2;
+ e.gc.drawText(measureString, x, y);
+
+ y += letterHeight + 2;
+ e.gc.drawText(layoutString, x, y);
+
+ y += letterHeight + 2;
+ e.gc.drawText(drawString, x, y);
+
+ x = getBounds().width - measureTimeExtent.x - 2;
+ y = getBounds().height - height + 2;
+ e.gc.drawText(measureTimeString, x, y);
+
+ x = getBounds().width - layoutTimeExtent.x - 2;
+ y += letterHeight + 2;
+ e.gc.drawText(layoutTimeString, x, y);
+
+ x = getBounds().width - drawTimeExtent.x - 2;
+ y += letterHeight + 2;
+ e.gc.drawText(drawTimeString, x, y);
+
+ }
+ tempTransform.dispose();
+
}
}
}
};
- private void paintRecursive(GC gc, DrawableViewNode node, Path connectionPath) {
- if (selectedNode == node) {
- gc.fillRectangle(node.left, (int) Math.round(node.top), DrawableViewNode.NODE_WIDTH,
- DrawableViewNode.NODE_HEIGHT);
+ private static void paintRecursive(GC gc, Transform transform, DrawableViewNode node,
+ DrawableViewNode selectedNode, Path connectionPath) {
+ if (selectedNode == node && node.viewNode.filtered) {
+ gc.drawImage(filteredSelectedImage, node.left, (int) Math.round(node.top));
+ } else if (selectedNode == node) {
+ gc.drawImage(selectedImage, node.left, (int) Math.round(node.top));
+ } else if (node.viewNode.filtered) {
+ gc.drawImage(filteredImage, node.left, (int) Math.round(node.top));
} else {
- gc.drawRectangle(node.left, (int) Math.round(node.top), DrawableViewNode.NODE_WIDTH,
- DrawableViewNode.NODE_HEIGHT);
+ gc.drawImage(notSelectedImage, node.left, (int) Math.round(node.top));
}
int fontHeight = gc.getFontMetrics().getHeight();
@@ -434,7 +542,7 @@ public class TreeView extends Canvas implements TreeChangeListener {
}
double x = node.left + DrawableViewNode.CONTENT_LEFT_RIGHT_PADDING;
double y = node.top + DrawableViewNode.CONTENT_TOP_BOTTOM_PADDING;
- drawTextInArea(gc, name, x, y, contentWidth, fontHeight);
+ drawTextInArea(gc, transform, name, x, y, contentWidth, fontHeight);
y += fontHeight + DrawableViewNode.CONTENT_INTER_PADDING;
@@ -442,7 +550,7 @@ public class TreeView extends Canvas implements TreeChangeListener {
y += fontHeight + DrawableViewNode.CONTENT_INTER_PADDING;
if (!node.viewNode.id.equals("NO_ID")) {
- drawTextInArea(gc, node.viewNode.id, x, y, contentWidth, fontHeight);
+ drawTextInArea(gc, transform, node.viewNode.id, x, y, contentWidth, fontHeight);
}
if (node.viewNode.measureRating != ProfileRating.NONE) {
@@ -491,15 +599,16 @@ public class TreeView extends Canvas implements TreeChangeListener {
}
}
-
org.eclipse.swt.graphics.Point indexExtent =
gc.stringExtent(Integer.toString(node.viewNode.index));
- x = node.left+DrawableViewNode.NODE_WIDTH-DrawableViewNode.INDEX_PADDING-indexExtent.x;
- y = node.top+DrawableViewNode.NODE_HEIGHT-DrawableViewNode.INDEX_PADDING-indexExtent.y;
+ x =
+ node.left + DrawableViewNode.NODE_WIDTH - DrawableViewNode.INDEX_PADDING
+ - indexExtent.x;
+ y =
+ node.top + DrawableViewNode.NODE_HEIGHT - DrawableViewNode.INDEX_PADDING
+ - indexExtent.y;
gc.drawText(Integer.toString(node.viewNode.index), (int) x, (int) y, SWT.DRAW_TRANSPARENT);
-
-
int N = node.children.size();
if (N == 0) {
return;
@@ -507,7 +616,7 @@ public class TreeView extends Canvas implements TreeChangeListener {
float childSpacing = (1.0f * (DrawableViewNode.NODE_HEIGHT - 2 * LINE_PADDING)) / N;
for (int i = 0; i < N; i++) {
DrawableViewNode child = node.children.get(i);
- paintRecursive(gc, child, connectionPath);
+ paintRecursive(gc, transform, child, selectedNode, connectionPath);
float x1 = node.left + DrawableViewNode.NODE_WIDTH;
float y1 = (float) node.top + LINE_PADDING + childSpacing * i + childSpacing / 2;
float x2 = child.left;
@@ -521,7 +630,8 @@ public class TreeView extends Canvas implements TreeChangeListener {
}
}
- private void drawTextInArea(GC gc, String text, double x, double y, double width, double height) {
+ private static void drawTextInArea(GC gc, Transform transform, String text, double x, double y,
+ double width, double height) {
org.eclipse.swt.graphics.Point extent = gc.stringExtent(text);
if (extent.x > width) {
@@ -532,8 +642,8 @@ public class TreeView extends Canvas implements TreeChangeListener {
transform.scale((float) scale, (float) scale);
gc.setTransform(transform);
- x/=scale;
- y/=scale;
+ x /= scale;
+ y /= scale;
y += (extent.y / scale - extent.y) / 2;
gc.drawText(text, (int) x, (int) y, SWT.DRAW_TRANSPARENT);
@@ -547,6 +657,31 @@ public class TreeView extends Canvas implements TreeChangeListener {
}
+ public static Image paintToImage(DrawableViewNode tree) {
+ Image image =
+ new Image(Display.getDefault(), (int) Math.ceil(tree.bounds.width), (int) Math
+ .ceil(tree.bounds.height));
+
+ Transform transform = new Transform(Display.getDefault());
+ transform.identity();
+ transform.translate((float) -tree.bounds.x, (float) -tree.bounds.y);
+ Path connectionPath = new Path(Display.getDefault());
+ GC gc = new GC(image);
+ Color white = new Color(Display.getDefault(), 255, 255, 255);
+ Color black = new Color(Display.getDefault(), 0, 0, 0);
+ gc.setForeground(white);
+ gc.setBackground(black);
+ gc.fillRectangle(0, 0, image.getBounds().width, image.getBounds().height);
+ gc.setTransform(transform);
+ paintRecursive(gc, transform, tree, null, connectionPath);
+ gc.drawPath(connectionPath);
+ gc.dispose();
+ connectionPath.dispose();
+ white.dispose();
+ black.dispose();
+ return image;
+ }
+
private void doRedraw() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
@@ -565,9 +700,9 @@ public class TreeView extends Canvas implements TreeChangeListener {
viewport = null;
} else {
viewport =
- new Rectangle((tree.bounds.width - getBounds().width) / 2,
- (tree.bounds.height - getBounds().height) / 2,
- getBounds().width, getBounds().height);
+ new Rectangle(0, tree.top + DrawableViewNode.NODE_HEIGHT / 2
+ - getBounds().height / 2, getBounds().width,
+ getBounds().height);
}
}
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeViewOverview.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeViewOverview.java
index 83a2b0d..9a44694 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeViewOverview.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/TreeViewOverview.java
@@ -16,7 +16,7 @@
package com.android.hierarchyviewerlib.ui;
-import com.android.hierarchyviewerlib.ComponentRegistry;
+import com.android.ddmuilib.ImageLoader;
import com.android.hierarchyviewerlib.models.TreeViewModel;
import com.android.hierarchyviewerlib.models.TreeViewModel.TreeChangeListener;
import com.android.hierarchyviewerlib.ui.util.DrawableViewNode;
@@ -32,6 +32,7 @@ import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.Transform;
import org.eclipse.swt.widgets.Canvas;
@@ -58,12 +59,24 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener {
private boolean dragging = false;
+ private DrawableViewNode selectedNode;
+
+ private static Image notSelectedImage;
+
+ private static Image selectedImage;
+
+ private static Image filteredImage;
+
+ private static Image filteredSelectedImage;
+
public TreeViewOverview(Composite parent) {
super(parent, SWT.NONE);
- model = ComponentRegistry.getTreeViewModel();
+ model = TreeViewModel.getModel();
model.addTreeChangeListener(this);
+ loadResources();
+
addPaintListener(paintListener);
addMouseListener(mouseListener);
addMouseMoveListener(mouseMoveListener);
@@ -74,6 +87,15 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener {
inverse = new Transform(Display.getDefault());
}
+ private void loadResources() {
+ ImageLoader loader = ImageLoader.getLoader(this.getClass());
+ notSelectedImage = loader.loadImage("not-selected.png", Display.getDefault());
+ selectedImage = loader.loadImage("selected-small.png", Display.getDefault());
+ filteredImage = loader.loadImage("filtered.png", Display.getDefault());
+ filteredSelectedImage =
+ loader.loadImage("selected-filtered-small.png", Display.getDefault());
+ }
+
private DisposeListener disposeListener = new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
model.removeTreeChangeListener(TreeViewOverview.this);
@@ -182,21 +204,23 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener {
public void paintControl(PaintEvent e) {
synchronized (TreeViewOverview.this) {
if (tree != null && viewport != null) {
- e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
+ e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
+ e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
e.gc.fillRectangle(0, 0, getBounds().width, getBounds().height);
e.gc.setTransform(transform);
+ e.gc.setLineWidth((int) Math.ceil(0.7 / scale));
Path connectionPath = new Path(Display.getDefault());
paintRecursive(e.gc, tree, connectionPath);
e.gc.drawPath(connectionPath);
connectionPath.dispose();
- e.gc.setAlpha(80);
- e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY));
+ e.gc.setAlpha(50);
+ e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
e.gc.fillRectangle((int) viewport.x, (int) viewport.y, (int) Math
.ceil(viewport.width), (int) Math.ceil(viewport.height));
e.gc.setAlpha(255);
- e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK));
+ e.gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY));
e.gc.setLineWidth((int) Math.ceil(2 / scale));
e.gc.drawRectangle((int) viewport.x, (int) viewport.y, (int) Math
.ceil(viewport.width), (int) Math.ceil(viewport.height));
@@ -206,8 +230,15 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener {
};
private void paintRecursive(GC gc, DrawableViewNode node, Path connectionPath) {
- gc.drawRectangle(node.left, (int) Math.round(node.top), DrawableViewNode.NODE_WIDTH,
- DrawableViewNode.NODE_HEIGHT);
+ if (selectedNode == node && node.viewNode.filtered) {
+ gc.drawImage(filteredSelectedImage, node.left, (int) Math.round(node.top));
+ } else if (selectedNode == node) {
+ gc.drawImage(selectedImage, node.left, (int) Math.round(node.top));
+ } else if (node.viewNode.filtered) {
+ gc.drawImage(filteredImage, node.left, (int) Math.round(node.top));
+ } else {
+ gc.drawImage(notSelectedImage, node.left, (int) Math.round(node.top));
+ }
int N = node.children.size();
if (N == 0) {
return;
@@ -244,6 +275,7 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener {
public void run() {
synchronized (this) {
tree = model.getTree();
+ selectedNode = model.getSelection();
setBounds();
setTransform();
}
@@ -311,6 +343,9 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener {
}
public void selectionChanged() {
- // pass
+ synchronized (this) {
+ selectedNode = model.getSelection();
+ }
+ doRedraw();
}
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/DrawableViewNode.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/DrawableViewNode.java
index fccc3ba..0d64e86 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/DrawableViewNode.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/DrawableViewNode.java
@@ -25,17 +25,17 @@ public class DrawableViewNode {
public final ArrayList<DrawableViewNode> children = new ArrayList<DrawableViewNode>();
- public final static int NODE_HEIGHT = 110;
+ public final static int NODE_HEIGHT = 100;
- public final static int NODE_WIDTH = 170;
+ public final static int NODE_WIDTH = 180;
- public final static int CONTENT_LEFT_RIGHT_PADDING = 3;
+ public final static int CONTENT_LEFT_RIGHT_PADDING = 7;
- public final static int CONTENT_TOP_BOTTOM_PADDING = 7;
+ public final static int CONTENT_TOP_BOTTOM_PADDING = 8;
public final static int CONTENT_INTER_PADDING = 3;
- public final static int INDEX_PADDING = 5;
+ public final static int INDEX_PADDING = 7;
public final static int LEAF_NODE_SPACING = 9;
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/PsdFile.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/PsdFile.java
new file mode 100644
index 0000000..275ea36
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/PsdFile.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.hierarchyviewerlib.ui.util;
+
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.image.BufferedImage;
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Writes PSD file. Supports only 8 bits, RGB images with 4 channels.
+ */
+public class PsdFile {
+ private final Header mHeader;
+
+ private final ColorMode mColorMode;
+
+ private final ImageResources mImageResources;
+
+ private final LayersMasksInfo mLayersMasksInfo;
+
+ private final LayersInfo mLayersInfo;
+
+ private final BufferedImage mMergedImage;
+
+ private final Graphics2D mGraphics;
+
+ public PsdFile(int width, int height) {
+ mHeader = new Header(width, height);
+ mColorMode = new ColorMode();
+ mImageResources = new ImageResources();
+ mLayersMasksInfo = new LayersMasksInfo();
+ mLayersInfo = new LayersInfo();
+
+ mMergedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ mGraphics = mMergedImage.createGraphics();
+ }
+
+ public void addLayer(String name, BufferedImage image, Point offset) {
+ addLayer(name, image, offset, true);
+ }
+
+ public void addLayer(String name, BufferedImage image, Point offset, boolean visible) {
+ mLayersInfo.addLayer(name, image, offset, visible);
+ if (visible)
+ mGraphics.drawImage(image, null, offset.x, offset.y);
+ }
+
+ public void write(OutputStream stream) {
+ mLayersMasksInfo.setLayersInfo(mLayersInfo);
+
+ DataOutputStream out = new DataOutputStream(new BufferedOutputStream(stream));
+ try {
+ mHeader.write(out);
+ out.flush();
+
+ mColorMode.write(out);
+ mImageResources.write(out);
+ mLayersMasksInfo.write(out);
+ mLayersInfo.write(out);
+ out.flush();
+
+ mLayersInfo.writeImageData(out);
+ out.flush();
+
+ writeImage(mMergedImage, out, false);
+ out.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ out.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static void writeImage(BufferedImage image, DataOutputStream out, boolean split)
+ throws IOException {
+
+ if (!split)
+ out.writeShort(0);
+
+ int width = image.getWidth();
+ int height = image.getHeight();
+
+ final int length = width * height;
+ int[] pixels = new int[length];
+
+ image.getData().getDataElements(0, 0, width, height, pixels);
+
+ byte[] a = new byte[length];
+ byte[] r = new byte[length];
+ byte[] g = new byte[length];
+ byte[] b = new byte[length];
+
+ for (int i = 0; i < length; i++) {
+ final int pixel = pixels[i];
+ a[i] = (byte) ((pixel >> 24) & 0xFF);
+ r[i] = (byte) ((pixel >> 16) & 0xFF);
+ g[i] = (byte) ((pixel >> 8) & 0xFF);
+ b[i] = (byte) (pixel & 0xFF);
+ }
+
+ if (split)
+ out.writeShort(0);
+ if (split)
+ out.write(a);
+ if (split)
+ out.writeShort(0);
+ out.write(r);
+ if (split)
+ out.writeShort(0);
+ out.write(g);
+ if (split)
+ out.writeShort(0);
+ out.write(b);
+ if (!split)
+ out.write(a);
+ }
+
+ @SuppressWarnings( {
+ "UnusedDeclaration"
+ })
+ static class Header {
+ static final short MODE_BITMAP = 0;
+
+ static final short MODE_GRAYSCALE = 1;
+
+ static final short MODE_INDEXED = 2;
+
+ static final short MODE_RGB = 3;
+
+ static final short MODE_CMYK = 4;
+
+ static final short MODE_MULTI_CHANNEL = 7;
+
+ static final short MODE_DUOTONE = 8;
+
+ static final short MODE_LAB = 9;
+
+ final byte[] mSignature = "8BPS".getBytes();
+
+ final short mVersion = 1;
+
+ final byte[] mReserved = new byte[6];
+
+ final short mChannelCount = 4;
+
+ final int mHeight;
+
+ final int mWidth;
+
+ final short mDepth = 8;
+
+ final short mMode = MODE_RGB;
+
+ Header(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.write(mSignature);
+ out.writeShort(mVersion);
+ out.write(mReserved);
+ out.writeShort(mChannelCount);
+ out.writeInt(mHeight);
+ out.writeInt(mWidth);
+ out.writeShort(mDepth);
+ out.writeShort(mMode);
+ }
+ }
+
+ // Unused at the moment
+ @SuppressWarnings( {
+ "UnusedDeclaration"
+ })
+ static class ColorMode {
+ final int mLength = 0;
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeInt(mLength);
+ }
+ }
+
+ // Unused at the moment
+ @SuppressWarnings( {
+ "UnusedDeclaration"
+ })
+ static class ImageResources {
+ static final short RESOURCE_RESOLUTION_INFO = 0x03ED;
+
+ int mLength = 0;
+
+ final byte[] mSignature = "8BIM".getBytes();
+
+ final short mResourceId = RESOURCE_RESOLUTION_INFO;
+
+ final short mPad = 0;
+
+ final int mDataLength = 16;
+
+ final short mHorizontalDisplayUnit = 0x48; // 72 dpi
+
+ final int mHorizontalResolution = 1;
+
+ final short mWidthDisplayUnit = 1;
+
+ final short mVerticalDisplayUnit = 0x48; // 72 dpi
+
+ final int mVerticalResolution = 1;
+
+ final short mHeightDisplayUnit = 1;
+
+ ImageResources() {
+ mLength = mSignature.length;
+ mLength += 2;
+ mLength += 2;
+ mLength += 4;
+ mLength += 8;
+ mLength += 8;
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeInt(mLength);
+ out.write(mSignature);
+ out.writeShort(mResourceId);
+ out.writeShort(mPad);
+ out.writeInt(mDataLength);
+ out.writeShort(mHorizontalDisplayUnit);
+ out.writeInt(mHorizontalResolution);
+ out.writeShort(mWidthDisplayUnit);
+ out.writeShort(mVerticalDisplayUnit);
+ out.writeInt(mVerticalResolution);
+ out.writeShort(mHeightDisplayUnit);
+ }
+ }
+
+ @SuppressWarnings( {
+ "UnusedDeclaration"
+ })
+ static class LayersMasksInfo {
+ int mMiscLength;
+
+ int mLayerInfoLength;
+
+ void setLayersInfo(LayersInfo layersInfo) {
+ mLayerInfoLength = layersInfo.getLength();
+ // Round to the next multiple of 2
+ if ((mLayerInfoLength & 0x1) == 0x1)
+ mLayerInfoLength++;
+ mMiscLength = mLayerInfoLength + 8;
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeInt(mMiscLength);
+ out.writeInt(mLayerInfoLength);
+ }
+ }
+
+ @SuppressWarnings( {
+ "UnusedDeclaration"
+ })
+ static class LayersInfo {
+ final List<Layer> mLayers = new ArrayList<Layer>();
+
+ void addLayer(String name, BufferedImage image, Point offset, boolean visible) {
+ mLayers.add(new Layer(name, image, offset, visible));
+ }
+
+ int getLength() {
+ int length = 2;
+ for (Layer layer : mLayers) {
+ length += layer.getLength();
+ }
+ return length;
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeShort((short) -mLayers.size());
+ for (Layer layer : mLayers) {
+ layer.write(out);
+ }
+ }
+
+ void writeImageData(DataOutputStream out) throws IOException {
+ for (Layer layer : mLayers) {
+ layer.writeImageData(out);
+ }
+ // Global layer mask info length
+ out.writeInt(0);
+ }
+ }
+
+ @SuppressWarnings( {
+ "UnusedDeclaration"
+ })
+ static class Layer {
+ static final byte OPACITY_TRANSPARENT = 0x0;
+
+ static final byte OPACITY_OPAQUE = (byte) 0xFF;
+
+ static final byte CLIPPING_BASE = 0x0;
+
+ static final byte CLIPPING_NON_BASE = 0x1;
+
+ static final byte FLAG_TRANSPARENCY_PROTECTED = 0x1;
+
+ static final byte FLAG_INVISIBLE = 0x2;
+
+ final int mTop;
+
+ final int mLeft;
+
+ final int mBottom;
+
+ final int mRight;
+
+ final short mChannelCount = 4;
+
+ final Channel[] mChannelInfo = new Channel[mChannelCount];
+
+ final byte[] mBlendSignature = "8BIM".getBytes();
+
+ final byte[] mBlendMode = "norm".getBytes();
+
+ final byte mOpacity = OPACITY_OPAQUE;
+
+ final byte mClipping = CLIPPING_BASE;
+
+ byte mFlags = 0x0;
+
+ final byte mFiller = 0x0;
+
+ int mExtraSize = 4 + 4;
+
+ final int mMaskDataLength = 0;
+
+ final int mBlendRangeDataLength = 0;
+
+ final byte[] mName;
+
+ final byte[] mLayerExtraSignature = "8BIM".getBytes();
+
+ final byte[] mLayerExtraKey = "luni".getBytes();
+
+ int mLayerExtraLength;
+
+ final String mOriginalName;
+
+ private BufferedImage mImage;
+
+ Layer(String name, BufferedImage image, Point offset, boolean visible) {
+ final int height = image.getHeight();
+ final int width = image.getWidth();
+ final int length = width * height;
+
+ mChannelInfo[0] = new Channel(Channel.ID_ALPHA, length);
+ mChannelInfo[1] = new Channel(Channel.ID_RED, length);
+ mChannelInfo[2] = new Channel(Channel.ID_GREEN, length);
+ mChannelInfo[3] = new Channel(Channel.ID_BLUE, length);
+
+ mTop = offset.y;
+ mLeft = offset.x;
+ mBottom = offset.y + height;
+ mRight = offset.x + width;
+
+ mOriginalName = name;
+ byte[] data = name.getBytes();
+
+ try {
+ mLayerExtraLength = 4 + mOriginalName.getBytes("UTF-16").length;
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+
+ final byte[] nameData = new byte[data.length + 1];
+ nameData[0] = (byte) (data.length & 0xFF);
+ System.arraycopy(data, 0, nameData, 1, data.length);
+
+ // This could be done in the same pass as above
+ if (nameData.length % 4 != 0) {
+ data = new byte[nameData.length + 4 - (nameData.length % 4)];
+ System.arraycopy(nameData, 0, data, 0, nameData.length);
+ mName = data;
+ } else {
+ mName = nameData;
+ }
+ mExtraSize += mName.length;
+ mExtraSize +=
+ mLayerExtraLength + 4 + mLayerExtraKey.length + mLayerExtraSignature.length;
+
+ mImage = image;
+
+ if (!visible) {
+ mFlags |= FLAG_INVISIBLE;
+ }
+ }
+
+ int getLength() {
+ int length = 4 * 4 + 2;
+
+ for (Channel channel : mChannelInfo) {
+ length += channel.getLength();
+ }
+
+ length += mBlendSignature.length;
+ length += mBlendMode.length;
+ length += 4;
+ length += 4;
+ length += mExtraSize;
+
+ return length;
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeInt(mTop);
+ out.writeInt(mLeft);
+ out.writeInt(mBottom);
+ out.writeInt(mRight);
+
+ out.writeShort(mChannelCount);
+ for (Channel channel : mChannelInfo) {
+ channel.write(out);
+ }
+
+ out.write(mBlendSignature);
+ out.write(mBlendMode);
+
+ out.write(mOpacity);
+ out.write(mClipping);
+ out.write(mFlags);
+ out.write(mFiller);
+
+ out.writeInt(mExtraSize);
+ out.writeInt(mMaskDataLength);
+
+ out.writeInt(mBlendRangeDataLength);
+
+ out.write(mName);
+
+ out.write(mLayerExtraSignature);
+ out.write(mLayerExtraKey);
+ out.writeInt(mLayerExtraLength);
+ out.writeInt(mOriginalName.length() + 1);
+ out.write(mOriginalName.getBytes("UTF-16"));
+ }
+
+ void writeImageData(DataOutputStream out) throws IOException {
+ writeImage(mImage, out, true);
+ }
+ }
+
+ @SuppressWarnings( {
+ "UnusedDeclaration"
+ })
+ static class Channel {
+ static final short ID_RED = 0;
+
+ static final short ID_GREEN = 1;
+
+ static final short ID_BLUE = 2;
+
+ static final short ID_ALPHA = -1;
+
+ static final short ID_LAYER_MASK = -2;
+
+ final short mId;
+
+ final int mDataLength;
+
+ Channel(short id, int dataLength) {
+ mId = id;
+ mDataLength = dataLength + 2;
+ }
+
+ int getLength() {
+ return 2 + 4 + mDataLength;
+ }
+
+ void write(DataOutputStream out) throws IOException {
+ out.writeShort(mId);
+ out.writeInt(mDataLength);
+ }
+ }
+}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/TreeColumnResizer.java b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/TreeColumnResizer.java
index ad18540..6b20366 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/TreeColumnResizer.java
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/ui/util/TreeColumnResizer.java
@@ -25,10 +25,13 @@ import org.eclipse.swt.widgets.TreeColumn;
public class TreeColumnResizer {
private TreeColumn column1;
+
private TreeColumn column2;
private Composite control;
+
private int column1Width;
+
private int column2Width;
private final static int MIN_COLUMN1_WIDTH = 18;
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about-small.jpg b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about-small.jpg
new file mode 100644
index 0000000..72ecabc
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about-small.jpg
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about.jpg b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about.jpg
new file mode 100644
index 0000000..2183168
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about.jpg
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/auto-refresh.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/auto-refresh.png
new file mode 100644
index 0000000..240862f
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/auto-refresh.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/capture-psd.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/capture-psd.png
new file mode 100644
index 0000000..0f25426
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/capture-psd.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view-selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view-selected.png
new file mode 100644
index 0000000..fd107ed
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view-selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view.png
new file mode 100644
index 0000000..9a7eed4
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/display.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/display.png
new file mode 100644
index 0000000..a9de0ec
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/display.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/filtered.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/filtered.png
new file mode 100644
index 0000000..4fcab3f
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/filtered.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/green.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/green.png
index b52a342..800000d 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/green.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/green.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/inspect-screenshot.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/inspect-screenshot.png
new file mode 100644
index 0000000..6e51701
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/inspect-screenshot.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/invalidate.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/invalidate.png
new file mode 100644
index 0000000..ee75f69
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/invalidate.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-all-views.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-all-views.png
new file mode 100644
index 0000000..3329ec9
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-all-views.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-overlay.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-overlay.png
new file mode 100644
index 0000000..4817252
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-overlay.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-view-hierarchy.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-view-hierarchy.png
new file mode 100644
index 0000000..8f01dda
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-view-hierarchy.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/not-selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/not-selected.png
new file mode 100644
index 0000000..db6f13b
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/not-selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-black.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-black.png
new file mode 100644
index 0000000..cd88803
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-black.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-white.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-white.png
new file mode 100644
index 0000000..5f05662
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-white.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view-selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view-selected.png
new file mode 100644
index 0000000..1e44000
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view-selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view.png
new file mode 100644
index 0000000..ec51cec
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/red.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/red.png
index 338c2d9..a2ab855 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/red.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/red.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/refresh-windows.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/refresh-windows.png
new file mode 100644
index 0000000..8fddcae
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/refresh-windows.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/request-layout.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/request-layout.png
new file mode 100644
index 0000000..92a78c8
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/request-layout.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/save.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/save.png
new file mode 100644
index 0000000..2c0bab1
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/save.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered-small.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered-small.png
new file mode 100644
index 0000000..9ef6b34
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered-small.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered.png
new file mode 100644
index 0000000..1f59685
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-small.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-small.png
new file mode 100644
index 0000000..538e385
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-small.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected.png
new file mode 100644
index 0000000..5cd5c3f
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-overlay.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-overlay.png
new file mode 100644
index 0000000..e39e90a
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-overlay.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view-selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view-selected.png
new file mode 100644
index 0000000..175ad1f
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view-selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view.png
new file mode 100644
index 0000000..23aa424
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/yellow.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/yellow.png
index b6fadac..e9b5781 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/yellow.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/yellow.png
Binary files differ