/* * 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.device.ViewNode; import com.android.hierarchyviewerlib.device.ViewNode.Property; import com.android.hierarchyviewerlib.models.TreeViewModel; import com.android.hierarchyviewerlib.models.TreeViewModel.ITreeChangeListener; 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.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; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import java.util.ArrayList; public class PropertyViewer extends Composite implements ITreeChangeListener { private TreeViewModel mModel; private TreeViewer mTreeViewer; private Tree mTree; private DrawableViewNode mSelectedNode; private Font mSmallFont; private class ContentProvider implements ITreeContentProvider, ITableLabelProvider { public Object[] getChildren(Object parentElement) { synchronized (PropertyViewer.this) { if (mSelectedNode != null && parentElement instanceof String) { String category = (String) parentElement; ArrayList<Property> returnValue = new ArrayList<Property>(); for (Property property : mSelectedNode.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 (mSelectedNode != null && element instanceof Property) { if (mSelectedNode.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 (mSelectedNode != null && element instanceof String) { String category = (String) element; for (String name : mSelectedNode.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 (mSelectedNode != null && inputElement instanceof TreeViewModel) { if (mSelectedNode.viewNode.categories.size() == 0) { return mSelectedNode.viewNode.properties .toArray(new Property[mSelectedNode.viewNode.properties.size()]); } else { return mSelectedNode.viewNode.categories .toArray(new String[mSelectedNode.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 (mSelectedNode != 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()); mTreeViewer = new TreeViewer(this, SWT.NONE); mTree = mTreeViewer.getTree(); mTree.setLinesVisible(true); mTree.setHeaderVisible(true); TreeColumn propertyColumn = new TreeColumn(mTree, SWT.NONE); propertyColumn.setText("Property"); TreeColumn valueColumn = new TreeColumn(mTree, SWT.NONE); valueColumn.setText("Value"); mModel = TreeViewModel.getModel(); ContentProvider contentProvider = new ContentProvider(); mTreeViewer.setContentProvider(contentProvider); mTreeViewer.setLabelProvider(contentProvider); mTreeViewer.setInput(mModel); mModel.addTreeChangeListener(this); loadResources(); addDisposeListener(mDisposeListener); mTree.setFont(mSmallFont); new TreeColumnResizer(this, propertyColumn, valueColumn); addControlListener(mControlListener); treeChanged(); } 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()); } mSmallFont = new Font(Display.getDefault(), newFontData); } private DisposeListener mDisposeListener = new DisposeListener() { public void widgetDisposed(DisposeEvent e) { mModel.removeTreeChangeListener(PropertyViewer.this); mSmallFont.dispose(); } }; // If the window gets too small, hide the data, otherwise SWT throws an // ERROR. private ControlListener mControlListener = new ControlAdapter() { private boolean noInput = false; private boolean noHeader = false; @Override public void controlResized(ControlEvent e) { if (getBounds().height <= 20) { mTree.setHeaderVisible(false); noHeader = true; } else if (noHeader) { mTree.setHeaderVisible(true); noHeader = false; } if (getBounds().height <= 38) { mTreeViewer.setInput(null); noInput = true; } else if (noInput) { mTreeViewer.setInput(mModel); noInput = false; } } }; public void selectionChanged() { synchronized (this) { mSelectedNode = mModel.getSelection(); } doRefresh(); } public void treeChanged() { synchronized (this) { mSelectedNode = mModel.getSelection(); } doRefresh(); } public void viewportChanged() { // pass } public void zoomChanged() { // pass } private void doRefresh() { Display.getDefault().syncExec(new Runnable() { public void run() { mTreeViewer.refresh(); } }); } }