1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.hierarchyviewerlib.ui; 18 19 import com.android.ddmlib.IDevice; 20 import com.android.ddmuilib.ImageLoader; 21 import com.android.hierarchyviewerlib.HierarchyViewerDirector; 22 import com.android.hierarchyviewerlib.device.Window; 23 import com.android.hierarchyviewerlib.models.DeviceSelectionModel; 24 import com.android.hierarchyviewerlib.models.DeviceSelectionModel.IWindowChangeListener; 25 26 import org.eclipse.jface.viewers.IFontProvider; 27 import org.eclipse.jface.viewers.ILabelProvider; 28 import org.eclipse.jface.viewers.ILabelProviderListener; 29 import org.eclipse.jface.viewers.ITreeContentProvider; 30 import org.eclipse.jface.viewers.TreeSelection; 31 import org.eclipse.jface.viewers.TreeViewer; 32 import org.eclipse.jface.viewers.Viewer; 33 import org.eclipse.swt.SWT; 34 import org.eclipse.swt.events.ControlAdapter; 35 import org.eclipse.swt.events.ControlEvent; 36 import org.eclipse.swt.events.ControlListener; 37 import org.eclipse.swt.events.DisposeEvent; 38 import org.eclipse.swt.events.DisposeListener; 39 import org.eclipse.swt.events.SelectionEvent; 40 import org.eclipse.swt.events.SelectionListener; 41 import org.eclipse.swt.graphics.Font; 42 import org.eclipse.swt.graphics.FontData; 43 import org.eclipse.swt.graphics.Image; 44 import org.eclipse.swt.layout.FillLayout; 45 import org.eclipse.swt.widgets.Composite; 46 import org.eclipse.swt.widgets.Display; 47 import org.eclipse.swt.widgets.Tree; 48 import org.eclipse.swt.widgets.TreeItem; 49 50 public class DeviceSelector extends Composite implements IWindowChangeListener, SelectionListener { 51 private TreeViewer mTreeViewer; 52 53 private Tree mTree; 54 55 private DeviceSelectionModel mModel; 56 57 private Font mBoldFont; 58 59 private Image mDeviceImage; 60 61 private Image mEmulatorImage; 62 63 private final static int ICON_WIDTH = 16; 64 65 private boolean mDoTreeViewStuff; 66 67 private boolean mDoPixelPerfectStuff; 68 69 private class ContentProvider implements ITreeContentProvider, ILabelProvider, IFontProvider { getChildren(Object parentElement)70 public Object[] getChildren(Object parentElement) { 71 if (parentElement instanceof IDevice && mDoTreeViewStuff) { 72 Window[] list = mModel.getWindows((IDevice) parentElement); 73 if (list != null) { 74 return list; 75 } 76 } 77 return new Object[0]; 78 } 79 getParent(Object element)80 public Object getParent(Object element) { 81 if (element instanceof Window) { 82 return ((Window) element).getDevice(); 83 } 84 return null; 85 } 86 hasChildren(Object element)87 public boolean hasChildren(Object element) { 88 if (element instanceof IDevice && mDoTreeViewStuff) { 89 Window[] list = mModel.getWindows((IDevice) element); 90 if (list != null) { 91 return list.length != 0; 92 } 93 } 94 return false; 95 } 96 getElements(Object inputElement)97 public Object[] getElements(Object inputElement) { 98 if (inputElement instanceof DeviceSelectionModel) { 99 return mModel.getDevices(); 100 } 101 return new Object[0]; 102 } 103 dispose()104 public void dispose() { 105 // pass 106 } 107 inputChanged(Viewer viewer, Object oldInput, Object newInput)108 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 109 // pass 110 } 111 getImage(Object element)112 public Image getImage(Object element) { 113 if (element instanceof IDevice) { 114 if (((IDevice) element).isEmulator()) { 115 return mEmulatorImage; 116 } 117 return mDeviceImage; 118 } 119 return null; 120 } 121 getText(Object element)122 public String getText(Object element) { 123 if (element instanceof IDevice) { 124 return ((IDevice) element).toString(); 125 } else if (element instanceof Window) { 126 return ((Window) element).getTitle(); 127 } 128 return null; 129 } 130 getFont(Object element)131 public Font getFont(Object element) { 132 if (element instanceof Window) { 133 int focusedWindow = mModel.getFocusedWindow(((Window) element).getDevice()); 134 if (focusedWindow == ((Window) element).getHashCode()) { 135 return mBoldFont; 136 } 137 } 138 return null; 139 } 140 addListener(ILabelProviderListener listener)141 public void addListener(ILabelProviderListener listener) { 142 // pass 143 } 144 isLabelProperty(Object element, String property)145 public boolean isLabelProperty(Object element, String property) { 146 // pass 147 return false; 148 } 149 removeListener(ILabelProviderListener listener)150 public void removeListener(ILabelProviderListener listener) { 151 // pass 152 } 153 } 154 DeviceSelector(Composite parent, boolean doTreeViewStuff, boolean doPixelPerfectStuff)155 public DeviceSelector(Composite parent, boolean doTreeViewStuff, boolean doPixelPerfectStuff) { 156 super(parent, SWT.NONE); 157 this.mDoTreeViewStuff = doTreeViewStuff; 158 this.mDoPixelPerfectStuff = doPixelPerfectStuff; 159 setLayout(new FillLayout()); 160 mTreeViewer = new TreeViewer(this, SWT.SINGLE); 161 mTreeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS); 162 163 mTree = mTreeViewer.getTree(); 164 mTree.setLinesVisible(true); 165 mTree.addSelectionListener(this); 166 167 addDisposeListener(mDisposeListener); 168 169 loadResources(); 170 171 mModel = DeviceSelectionModel.getModel(); 172 ContentProvider contentProvider = new ContentProvider(); 173 mTreeViewer.setContentProvider(contentProvider); 174 mTreeViewer.setLabelProvider(contentProvider); 175 mModel.addWindowChangeListener(this); 176 mTreeViewer.setInput(mModel); 177 178 addControlListener(mControlListener); 179 } 180 loadResources()181 public void loadResources() { 182 Display display = Display.getDefault(); 183 Font systemFont = display.getSystemFont(); 184 FontData[] fontData = systemFont.getFontData(); 185 FontData[] newFontData = new FontData[fontData.length]; 186 for (int i = 0; i < fontData.length; i++) { 187 newFontData[i] = 188 new FontData(fontData[i].getName(), fontData[i].getHeight(), fontData[i] 189 .getStyle() 190 | SWT.BOLD); 191 } 192 mBoldFont = new Font(Display.getDefault(), newFontData); 193 194 ImageLoader loader = ImageLoader.getDdmUiLibLoader(); 195 mDeviceImage = 196 loader.loadImage(display, "device.png", ICON_WIDTH, ICON_WIDTH, display //$NON-NLS-1$ 197 .getSystemColor(SWT.COLOR_RED)); 198 199 mEmulatorImage = 200 loader.loadImage(display, "emulator.png", ICON_WIDTH, ICON_WIDTH, display //$NON-NLS-1$ 201 .getSystemColor(SWT.COLOR_BLUE)); 202 } 203 204 private DisposeListener mDisposeListener = new DisposeListener() { 205 public void widgetDisposed(DisposeEvent e) { 206 mModel.removeWindowChangeListener(DeviceSelector.this); 207 mBoldFont.dispose(); 208 } 209 }; 210 211 // If the window gets too small, hide the data, otherwise SWT throws an 212 // ERROR. 213 214 private ControlListener mControlListener = new ControlAdapter() { 215 private boolean noInput = false; 216 217 @Override 218 public void controlResized(ControlEvent e) { 219 if (getBounds().height <= 38) { 220 mTreeViewer.setInput(null); 221 noInput = true; 222 } else if (noInput) { 223 mTreeViewer.setInput(mModel); 224 noInput = false; 225 } 226 } 227 }; 228 229 @Override setFocus()230 public boolean setFocus() { 231 return mTree.setFocus(); 232 } 233 setMode(boolean doTreeViewStuff, boolean doPixelPerfectStuff)234 public void setMode(boolean doTreeViewStuff, boolean doPixelPerfectStuff) { 235 if (this.mDoTreeViewStuff != doTreeViewStuff 236 || this.mDoPixelPerfectStuff != doPixelPerfectStuff) { 237 final boolean expandAll = !this.mDoTreeViewStuff && doTreeViewStuff; 238 this.mDoTreeViewStuff = doTreeViewStuff; 239 this.mDoPixelPerfectStuff = doPixelPerfectStuff; 240 Display.getDefault().syncExec(new Runnable() { 241 public void run() { 242 mTreeViewer.refresh(); 243 if (expandAll) { 244 mTreeViewer.expandAll(); 245 } 246 } 247 }); 248 } 249 } 250 deviceConnected(final IDevice device)251 public void deviceConnected(final IDevice device) { 252 Display.getDefault().syncExec(new Runnable() { 253 public void run() { 254 mTreeViewer.refresh(); 255 mTreeViewer.setExpandedState(device, true); 256 } 257 }); 258 } 259 deviceChanged(final IDevice device)260 public void deviceChanged(final IDevice device) { 261 Display.getDefault().syncExec(new Runnable() { 262 public void run() { 263 TreeSelection selection = (TreeSelection) mTreeViewer.getSelection(); 264 mTreeViewer.refresh(device); 265 if (selection.getFirstElement() instanceof Window 266 && ((Window) selection.getFirstElement()).getDevice() == device) { 267 mTreeViewer.setSelection(selection, true); 268 } 269 } 270 }); 271 } 272 deviceDisconnected(final IDevice device)273 public void deviceDisconnected(final IDevice device) { 274 Display.getDefault().syncExec(new Runnable() { 275 public void run() { 276 mTreeViewer.refresh(); 277 } 278 }); 279 } 280 focusChanged(final IDevice device)281 public void focusChanged(final IDevice device) { 282 Display.getDefault().syncExec(new Runnable() { 283 public void run() { 284 TreeSelection selection = (TreeSelection) mTreeViewer.getSelection(); 285 mTreeViewer.refresh(device); 286 if (selection.getFirstElement() instanceof Window 287 && ((Window) selection.getFirstElement()).getDevice() == device) { 288 mTreeViewer.setSelection(selection, true); 289 } 290 } 291 }); 292 } 293 selectionChanged(IDevice device, Window window)294 public void selectionChanged(IDevice device, Window window) { 295 // pass 296 } 297 widgetDefaultSelected(SelectionEvent e)298 public void widgetDefaultSelected(SelectionEvent e) { 299 Object selection = ((TreeItem) e.item).getData(); 300 if (selection instanceof IDevice && mDoPixelPerfectStuff) { 301 HierarchyViewerDirector.getDirector().loadPixelPerfectData((IDevice) selection); 302 } else if (selection instanceof Window && mDoTreeViewStuff) { 303 HierarchyViewerDirector.getDirector().loadViewTreeData((Window) selection); 304 } 305 } 306 widgetSelected(SelectionEvent e)307 public void widgetSelected(SelectionEvent e) { 308 Object selection = ((TreeItem) e.item).getData(); 309 if (selection instanceof IDevice) { 310 mModel.setSelection((IDevice) selection, null); 311 } else if (selection instanceof Window) { 312 mModel.setSelection(((Window) selection).getDevice(), (Window) selection); 313 } 314 } 315 } 316