From 7e87e711974d258d8a3d780a4abc8f9c6c005bba Mon Sep 17 00:00:00 2001 From: Konstantin Lopyrev Date: Wed, 11 Aug 2010 12:45:59 -0700 Subject: Adding property and profile viewers + misc Change-Id: I04b7e6045047d303b3434dc64662ffeb36c48c24 --- .../hierarchyviewerlib/device/DeviceBridge.java | 21 +- .../hierarchyviewerlib/device/ViewNode.java | 73 +++++-- .../hierarchyviewerlib/models/TreeViewModel.java | 27 +++ .../hierarchyvieweruilib/DeviceSelector.java | 6 - .../android/hierarchyvieweruilib/PixelPerfect.java | 8 +- .../hierarchyvieweruilib/PixelPerfectTree.java | 4 - .../hierarchyvieweruilib/ProfileViewer.java | 179 ++++++++++++++++ .../hierarchyvieweruilib/PropertyViewer.java | 232 +++++++++++++++++++++ .../com/android/hierarchyvieweruilib/TreeView.java | 30 ++- .../hierarchyvieweruilib/TreeViewOverview.java | 26 ++- .../util/TreeColumnResizer.java | 92 ++++++++ 11 files changed, 656 insertions(+), 42 deletions(-) create mode 100644 hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/ProfileViewer.java create mode 100644 hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PropertyViewer.java create mode 100644 hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/util/TreeColumnResizer.java (limited to 'hierarchyviewer2/libs') 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 c9244d2..af3f9f1 100644 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java +++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/DeviceBridge.java @@ -440,7 +440,15 @@ public class DeviceBridge { connection = new DeviceConnection(window.getDevice()); connection.sendCommand("PROFILE " + window.encode() + " " + viewNode.toString()); BufferedReader in = connection.getInputStream(); - return loadProfileDataRecursive(viewNode, in); + int protocol; + synchronized (viewServerInfo) { + protocol = viewServerInfo.get(window.getDevice()).protocolVersion; + } + if (protocol < 3) { + return loadProfileData(viewNode, in); + } else { + return loadProfileDataRecursive(viewNode, in); + } } catch (IOException e) { Log.e(TAG, "Unable to load profiling data for window " + window.getTitle() + " on device " + window.getDevice()); @@ -452,8 +460,7 @@ public class DeviceBridge { return false; } - private static boolean loadProfileDataRecursive(ViewNode node, BufferedReader in) - throws IOException { + private static boolean loadProfileData(ViewNode node, BufferedReader in) throws IOException { String line; if ((line = in.readLine()) == null || line.equalsIgnoreCase("-1 -1 -1") || line.equalsIgnoreCase("DONE.")) { @@ -463,6 +470,14 @@ public class DeviceBridge { node.measureTime = (Long.parseLong(data[0]) / 1000.0) / 1000.0; node.layoutTime = (Long.parseLong(data[1]) / 1000.0) / 1000.0; node.drawTime = (Long.parseLong(data[2]) / 1000.0) / 1000.0; + return true; + } + + private static boolean loadProfileDataRecursive(ViewNode node, BufferedReader in) + throws IOException { + if (!loadProfileData(node, in)) { + return false; + } for (int i = 0; i < node.children.size(); i++) { if (!loadProfileDataRecursive(node.children.get(i), in)) { return false; 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 2e22b56..2dd9b61 100644 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewNode.java +++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/device/ViewNode.java @@ -22,8 +22,12 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; public class ViewNode { + public static final String MISCELLANIOUS = "miscellaneous"; + public String id; public String name; @@ -82,6 +86,8 @@ public class ViewNode { public double drawTime; + public Set categories = new TreeSet(); + public ViewNode(ViewNode parent, String data) { this.parent = parent; index = this.parent == null ? 0 : this.parent.children.size(); @@ -130,28 +136,61 @@ public class ViewNode { id = namedProperties.get("mID").value; - left = getInt("mLeft", 0); - top = getInt("mTop", 0); - width = getInt("getWidth()", 0); - height = getInt("getHeight()", 0); - scrollX = getInt("mScrollX", 0); - scrollY = getInt("mScrollY", 0); - paddingLeft = getInt("mPaddingLeft", 0); - paddingRight = getInt("mPaddingRight", 0); - paddingTop = getInt("mPaddingTop", 0); - paddingBottom = getInt("mPaddingBottom", 0); - marginLeft = getInt("layout_leftMargin", Integer.MIN_VALUE); - marginRight = getInt("layout_rightMargin", Integer.MIN_VALUE); - marginTop = getInt("layout_topMargin", Integer.MIN_VALUE); - marginBottom = getInt("layout_bottomMargin", Integer.MIN_VALUE); - baseline = getInt("getBaseline()", 0); - willNotDraw = getBoolean("willNotDraw()", false); - hasFocus = getBoolean("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("measurement:getWidth()", 0); + height = namedProperties.containsKey("getHeight()") ? + getInt("getHeight()", 0) : getInt("measurement: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:leftMargin", Integer.MIN_VALUE); + marginRight = namedProperties.containsKey("layout_rightMargin") ? + getInt("layout_rightMargin", Integer.MIN_VALUE) : + getInt("layout:rightMargin", Integer.MIN_VALUE); + marginTop = namedProperties.containsKey("layout_topMargin") ? + getInt("layout_topMargin", Integer.MIN_VALUE) : + getInt("layout:topMargin", Integer.MIN_VALUE); + marginBottom = namedProperties.containsKey("layout_bottomMargin") ? + getInt("layout_bottomMargin", Integer.MIN_VALUE) : + getInt("layout:bottomMargin", Integer.MIN_VALUE); + baseline = namedProperties.containsKey("getBaseline()") ? + getInt("getBaseline()", 0) : + getInt("measurement: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()) { + int index = name.indexOf(':'); + if(index != -1) { + categories.add(name.substring(0, index)); + } + } + if(categories.size() != 0) { + categories.add(MISCELLANIOUS); + } } private boolean getBoolean(String name, boolean defaultValue) { 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 890b88c..f6279df 100644 --- a/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/TreeViewModel.java +++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/com/android/hierarchyviewerlib/models/TreeViewModel.java @@ -33,6 +33,8 @@ public class TreeViewModel { private DrawableViewNode tree; + private DrawableViewNode selectedNode; + private Rectangle viewport; private double zoom; @@ -48,10 +50,18 @@ public class TreeViewModel { tree.placeRoot(); viewport = null; zoom = 1; + selectedNode = null; } notifyTreeChanged(); } + public void setSelection(DrawableViewNode selectedNode) { + synchronized (this) { + this.selectedNode = selectedNode; + } + notifySelectionChanged(); + } + public void setViewport(Rectangle viewport) { synchronized (this) { this.viewport = viewport; @@ -113,9 +123,17 @@ public class TreeViewModel { } } + public DrawableViewNode getSelection() { + synchronized (this) { + return selectedNode; + } + } + public static interface TreeChangeListener { public void treeChanged(); + public void selectionChanged(); + public void viewportChanged(); public void zoomChanged(); @@ -142,6 +160,15 @@ public class TreeViewModel { } } + public void notifySelectionChanged() { + TreeChangeListener[] listeners = getTreeChangeListenerList(); + if (listeners != null) { + for (int i = 0; i < listeners.length; i++) { + listeners[i].selectionChanged(); + } + } + } + public void notifyViewportChanged() { TreeChangeListener[] listeners = getTreeChangeListenerList(); if (listeners != null) { diff --git a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/DeviceSelector.java b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/DeviceSelector.java index 4add510..49eb418 100644 --- a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/DeviceSelector.java +++ b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/DeviceSelector.java @@ -42,7 +42,6 @@ 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 org.eclipse.swt.widgets.TreeItem; public class DeviceSelector extends Composite implements WindowChangeListener, SelectionListener { @@ -153,10 +152,6 @@ public class DeviceSelector extends Composite implements WindowChangeListener, S treeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS); tree = treeViewer.getTree(); - TreeColumn col = new TreeColumn(tree, SWT.LEFT); - col.setText("Name"); - col.pack(); - tree.setHeaderVisible(true); tree.setLinesVisible(true); tree.addSelectionListener(this); @@ -170,7 +165,6 @@ public class DeviceSelector extends Composite implements WindowChangeListener, S treeViewer.setLabelProvider(contentProvider); treeViewer.setInput(model); model.addWindowChangeListener(this); - } public void loadResources() { diff --git a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PixelPerfect.java b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PixelPerfect.java index 5336ec3..8165c0b 100644 --- a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PixelPerfect.java +++ b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PixelPerfect.java @@ -165,10 +165,10 @@ public class PixelPerfect extends ScrolledComposite implements ImageChangeListen int nodeTop = selectedNode.top; int nodeWidth = selectedNode.width; int nodeHeight = selectedNode.height; - int nodeMarginLeft = Math.abs(selectedNode.marginLeft); - int nodeMarginTop = Math.abs(selectedNode.marginTop); - int nodeMarginRight = Math.abs(selectedNode.marginRight); - int nodeMarginBottom = Math.abs(selectedNode.marginBottom); + int nodeMarginLeft = selectedNode.marginLeft; + int nodeMarginTop = selectedNode.marginTop; + int nodeMarginRight = selectedNode.marginRight; + int nodeMarginBottom = selectedNode.marginBottom; int nodePadLeft = selectedNode.paddingLeft; int nodePadTop = selectedNode.paddingTop; int nodePadRight = selectedNode.paddingRight; diff --git a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PixelPerfectTree.java b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PixelPerfectTree.java index 30a7b9e..2c30857 100644 --- a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PixelPerfectTree.java +++ b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PixelPerfectTree.java @@ -136,10 +136,6 @@ public class PixelPerfectTree extends Composite implements ImageChangeListener, treeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS); tree = treeViewer.getTree(); - TreeColumn col = new TreeColumn(tree, SWT.LEFT); - col.setText("Name"); - col.pack(); - tree.setHeaderVisible(true); tree.addSelectionListener(this); loadResources(); diff --git a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/ProfileViewer.java b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/ProfileViewer.java new file mode 100644 index 0000000..400318c --- /dev/null +++ b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/ProfileViewer.java @@ -0,0 +1,179 @@ +/* + * 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.hierarchyvieweruilib; + +import com.android.hierarchyviewerlib.ComponentRegistry; +import com.android.hierarchyviewerlib.models.TreeViewModel; +import com.android.hierarchyviewerlib.models.TreeViewModel.TreeChangeListener; +import com.android.hierarchyviewerlib.scene.DrawableViewNode; +import com.android.hierarchyvieweruilib.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")) { + return formatter.format(selectedNode.viewNode.measureTime); + } else if (((String) element).equals("layout")) { + return formatter.format(selectedNode.viewNode.layoutTime); + } else { + 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/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PropertyViewer.java b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PropertyViewer.java new file mode 100644 index 0000000..da4997b --- /dev/null +++ b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/PropertyViewer.java @@ -0,0 +1,232 @@ +/* + * 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.hierarchyvieweruilib; + +import com.android.hierarchyviewerlib.ComponentRegistry; +import com.android.hierarchyviewerlib.device.ViewNode; +import com.android.hierarchyviewerlib.device.ViewNode.Property; +import com.android.hierarchyviewerlib.models.TreeViewModel; +import com.android.hierarchyviewerlib.models.TreeViewModel.TreeChangeListener; +import com.android.hierarchyviewerlib.scene.DrawableViewNode; +import com.android.hierarchyvieweruilib.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.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; + +import java.util.ArrayList; + +public class PropertyViewer 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 (PropertyViewer.this) { + if (selectedNode != null && parentElement instanceof String) { + String category = (String) parentElement; + ArrayList returnValue = new ArrayList(); + for (Property property : selectedNode.viewNode.properties) { + if (category.equals(ViewNode.MISCELLANIOUS)) { + if (property.name.indexOf(':') == -1) { + returnValue.add(property); + } + } else { + if (property.name.startsWith(((String) parentElement) + ":")) { + returnValue.add(property); + } + } + } + return returnValue.toArray(new Property[returnValue.size()]); + } + return new Object[0]; + } + } + + public Object getParent(Object element) { + synchronized (PropertyViewer.this) { + if (selectedNode != null && element instanceof Property) { + if (selectedNode.viewNode.categories.size() == 0) { + return null; + } + String name = ((Property) element).name; + int index = name.indexOf(':'); + if (index == -1) { + return ViewNode.MISCELLANIOUS; + } + return name.substring(0, index); + } + return null; + } + } + + public boolean hasChildren(Object element) { + synchronized (PropertyViewer.this) { + if (selectedNode != null && element instanceof String) { + String category = (String) element; + for (String name : selectedNode.viewNode.namedProperties.keySet()) { + if (category.equals(ViewNode.MISCELLANIOUS)) { + if (name.indexOf(':') == -1) { + return true; + } + } else { + if (name.startsWith(((String) element) + ":")) { + return true; + } + } + } + } + return false; + } + } + + public Object[] getElements(Object inputElement) { + synchronized (PropertyViewer.this) { + if (selectedNode != null && inputElement instanceof TreeViewModel) { + if (selectedNode.viewNode.categories.size() == 0) { + return selectedNode.viewNode.properties + .toArray(new Property[selectedNode.viewNode.properties.size()]); + } else { + return selectedNode.viewNode.categories + .toArray(new String[selectedNode.viewNode.categories.size()]); + } + } + 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 (PropertyViewer.this) { + if (selectedNode != null) { + if (element instanceof String && column == 0) { + String category = (String) element; + return Character.toUpperCase(category.charAt(0)) + category.substring(1); + } else if (element instanceof Property) { + if (column == 0) { + String returnValue = ((Property) element).name; + int index = returnValue.indexOf(':'); + if (index != -1) { + return returnValue.substring(index + 1); + } + return returnValue; + } else if (column == 1) { + return ((Property) element).value; + } + } + } + return ""; + } + } + + public void addListener(ILabelProviderListener listener) { + // pass + } + + public boolean isLabelProperty(Object element, String property) { + // pass + return false; + } + + public void removeListener(ILabelProviderListener listener) { + // pass + } + } + + public PropertyViewer(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 propertyColumn = new TreeColumn(tree, SWT.NONE); + propertyColumn.setText("Property"); + TreeColumn valueColumn = new TreeColumn(tree, SWT.NONE); + valueColumn.setText("Value"); + + model = ComponentRegistry.getTreeViewModel(); + ContentProvider contentProvider = new ContentProvider(); + treeViewer.setContentProvider(contentProvider); + treeViewer.setLabelProvider(contentProvider); + treeViewer.setInput(model); + model.addTreeChangeListener(this); + + new TreeColumnResizer(this, propertyColumn, valueColumn); + } + + + 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/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/TreeView.java b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/TreeView.java index 2bf4012..f5d7ae0 100644 --- a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/TreeView.java +++ b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/TreeView.java @@ -46,6 +46,8 @@ public class TreeView extends Canvas implements TreeChangeListener { private DrawableViewNode tree; + private DrawableViewNode selectedNode; + private Rectangle viewport; private Transform transform; @@ -112,10 +114,15 @@ public class TreeView extends Canvas implements TreeChangeListener { } public void mouseDown(MouseEvent e) { + boolean selectionChanged = false; synchronized (this) { if (tree != null && viewport != null) { Point pt = transformPoint(e.x, e.y); draggedNode = tree.getSelected(pt.x, pt.y); + if (draggedNode != null && draggedNode != selectedNode) { + selectedNode = draggedNode; + selectionChanged = true; + } if (draggedNode == tree) { draggedNode = null; } @@ -126,6 +133,9 @@ public class TreeView extends Canvas implements TreeChangeListener { } } } + if (selectionChanged) { + model.setSelection(selectedNode); + } } public void mouseUp(MouseEvent e) { @@ -260,15 +270,21 @@ public class TreeView extends Canvas implements TreeChangeListener { 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)); paintRecursive(e.gc, tree); } } } }; - static void paintRecursive(GC gc, DrawableViewNode node) { - gc.drawRectangle(node.left, (int) Math.round(node.top), DrawableViewNode.NODE_WIDTH, - DrawableViewNode.NODE_HEIGHT); + private void paintRecursive(GC gc, DrawableViewNode node) { + if (selectedNode == node) { + gc.fillRectangle(node.left, (int) Math.round(node.top), DrawableViewNode.NODE_WIDTH, + DrawableViewNode.NODE_HEIGHT); + } else { + gc.drawRectangle(node.left, (int) Math.round(node.top), DrawableViewNode.NODE_WIDTH, + DrawableViewNode.NODE_HEIGHT); + } int N = node.children.size(); for (int i = 0; i < N; i++) { DrawableViewNode child = node.children.get(i); @@ -290,6 +306,7 @@ public class TreeView extends Canvas implements TreeChangeListener { public void treeChanged() { synchronized (this) { tree = model.getTree(); + selectedNode = model.getSelection(); if (tree == null) { viewport = null; } else { @@ -334,4 +351,11 @@ public class TreeView extends Canvas implements TreeChangeListener { public void zoomChanged() { viewportChanged(); } + + public void selectionChanged() { + synchronized (this) { + selectedNode = model.getSelection(); + } + doRedraw(); + } } diff --git a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/TreeViewOverview.java b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/TreeViewOverview.java index d299717..feed1af 100644 --- a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/TreeViewOverview.java +++ b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/TreeViewOverview.java @@ -31,6 +31,7 @@ import org.eclipse.swt.events.MouseListener; 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.Transform; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; @@ -179,13 +180,12 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener { private PaintListener paintListener = new PaintListener() { public void paintControl(PaintEvent e) { if (tree != null && viewport != null) { - e.gc.setTransform(transform); e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE)); - e.gc.fillRectangle((int) bounds.x, (int) bounds.y, (int) Math.ceil(bounds.width), - (int) Math.ceil(bounds.height)); - TreeView.paintRecursive(e.gc, tree); + e.gc.fillRectangle(0, 0, getBounds().width, getBounds().height); + e.gc.setTransform(transform); + paintRecursive(e.gc, tree); - e.gc.setAlpha(100); + e.gc.setAlpha(80); e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY)); e.gc.fillRectangle((int) viewport.x, (int) viewport.y, (int) Math .ceil(viewport.width), (int) Math.ceil(viewport.height)); @@ -199,6 +199,19 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener { } }; + private void paintRecursive(GC gc, DrawableViewNode node) { + gc.drawRectangle(node.left, (int) Math.round(node.top), DrawableViewNode.NODE_WIDTH, + DrawableViewNode.NODE_HEIGHT); + int N = node.children.size(); + for (int i = 0; i < N; i++) { + DrawableViewNode child = node.children.get(i); + paintRecursive(gc, child); + gc.drawLine(node.left + DrawableViewNode.NODE_WIDTH, (int) Math.round(node.top) + + DrawableViewNode.NODE_HEIGHT / 2, child.left, (int) Math.round(child.top) + + DrawableViewNode.NODE_HEIGHT / 2); + } + } + private void doRedraw() { Display.getDefault().syncExec(new Runnable() { public void run() { @@ -270,4 +283,7 @@ public class TreeViewOverview extends Canvas implements TreeChangeListener { viewportChanged(); } + public void selectionChanged() { + // pass + } } diff --git a/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/util/TreeColumnResizer.java b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/util/TreeColumnResizer.java new file mode 100644 index 0000000..09851c3 --- /dev/null +++ b/hierarchyviewer2/libs/hierarchyvieweruilib/src/com/android/hierarchyvieweruilib/util/TreeColumnResizer.java @@ -0,0 +1,92 @@ +/* + * 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.hierarchyvieweruilib.util; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.TreeColumn; + +public class TreeColumnResizer { + + private TreeColumn column1; + private TreeColumn column2; + + private Composite control; + private int column1Width; + private int column2Width; + public TreeColumnResizer(Composite control, TreeColumn column1, TreeColumn column2) { + this.control = control; + this.column1 = column1; + this.column2 = column2; + control.addListener(SWT.Resize, resizeListener); + column1.addListener(SWT.Resize, column1ResizeListener); + column2.setResizable(false); + } + + private Listener resizeListener = new Listener() { + public void handleEvent(Event e) { + if (column1Width == 0 && column2Width == 0) { + column1Width = (control.getBounds().width - 18) / 2; + column2Width = (control.getBounds().width - 18) / 2; + } else { + int dif = control.getBounds().width - 18 - (column1Width + column2Width); + int columnDif = Math.abs(column1Width - column2Width); + int mainColumnChange = Math.min(Math.abs(dif), columnDif); + int left = Math.max(0, Math.abs(dif) - columnDif); + if (dif < 0) { + if (column1Width > column2Width) { + column1Width -= mainColumnChange; + } else { + column2Width -= mainColumnChange; + } + column1Width -= left / 2; + column2Width -= left - left / 2; + } else { + if (column1Width > column2Width) { + column2Width += mainColumnChange; + } else { + column1Width += mainColumnChange; + } + column1Width += left / 2; + column2Width += left - left / 2; + } + } + column1.removeListener(SWT.Resize, column1ResizeListener); + column1.setWidth(column1Width); + column2.setWidth(column2Width); + column1.addListener(SWT.Resize, column1ResizeListener); + } + }; + + private Listener column1ResizeListener = new Listener() { + public void handleEvent(Event e) { + int widthDif = column1Width - column1.getWidth(); + column1Width -= widthDif; + column2Width += widthDif; + if (column2Width < 0) { + column1Width += column2Width; + column2Width = 0; + column1.removeListener(SWT.Resize, this); + column1.setWidth(column1Width); + column1.addListener(SWT.Resize, this); + } + column2.setWidth(column2Width); + } + }; +} -- cgit v1.1