Home | History | Annotate | Download | only in ui
      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 {
     70         @Override
     71         public Object[] getChildren(Object parentElement) {
     72             if (parentElement instanceof IDevice && mDoTreeViewStuff) {
     73                 Window[] list = mModel.getWindows((IDevice) parentElement);
     74                 if (list != null) {
     75                     return list;
     76                 }
     77             }
     78             return new Object[0];
     79         }
     80 
     81         @Override
     82         public Object getParent(Object element) {
     83             if (element instanceof Window) {
     84                 return ((Window) element).getDevice();
     85             }
     86             return null;
     87         }
     88 
     89         @Override
     90         public boolean hasChildren(Object element) {
     91             if (element instanceof IDevice && mDoTreeViewStuff) {
     92                 Window[] list = mModel.getWindows((IDevice) element);
     93                 if (list != null) {
     94                     return list.length != 0;
     95                 }
     96             }
     97             return false;
     98         }
     99 
    100         @Override
    101         public Object[] getElements(Object inputElement) {
    102             if (inputElement instanceof DeviceSelectionModel) {
    103                 return mModel.getDevices();
    104             }
    105             return new Object[0];
    106         }
    107 
    108         @Override
    109         public void dispose() {
    110             // pass
    111         }
    112 
    113         @Override
    114         public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
    115             // pass
    116         }
    117 
    118         @Override
    119         public Image getImage(Object element) {
    120             if (element instanceof IDevice) {
    121                 if (((IDevice) element).isEmulator()) {
    122                     return mEmulatorImage;
    123                 }
    124                 return mDeviceImage;
    125             }
    126             return null;
    127         }
    128 
    129         @Override
    130         public String getText(Object element) {
    131             if (element instanceof IDevice) {
    132                 return ((IDevice) element).toString();
    133             } else if (element instanceof Window) {
    134                 return ((Window) element).getTitle();
    135             }
    136             return null;
    137         }
    138 
    139         @Override
    140         public Font getFont(Object element) {
    141             if (element instanceof Window) {
    142                 int focusedWindow = mModel.getFocusedWindow(((Window) element).getDevice());
    143                 if (focusedWindow == ((Window) element).getHashCode()) {
    144                     return mBoldFont;
    145                 }
    146             }
    147             return null;
    148         }
    149 
    150         @Override
    151         public void addListener(ILabelProviderListener listener) {
    152             // pass
    153         }
    154 
    155         @Override
    156         public boolean isLabelProperty(Object element, String property) {
    157             // pass
    158             return false;
    159         }
    160 
    161         @Override
    162         public void removeListener(ILabelProviderListener listener) {
    163             // pass
    164         }
    165     }
    166 
    167     public DeviceSelector(Composite parent, boolean doTreeViewStuff, boolean doPixelPerfectStuff) {
    168         super(parent, SWT.NONE);
    169         this.mDoTreeViewStuff = doTreeViewStuff;
    170         this.mDoPixelPerfectStuff = doPixelPerfectStuff;
    171         setLayout(new FillLayout());
    172         mTreeViewer = new TreeViewer(this, SWT.SINGLE);
    173         mTreeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
    174 
    175         mTree = mTreeViewer.getTree();
    176         mTree.setLinesVisible(true);
    177         mTree.addSelectionListener(this);
    178 
    179         addDisposeListener(mDisposeListener);
    180 
    181         loadResources();
    182 
    183         mModel = DeviceSelectionModel.getModel();
    184         ContentProvider contentProvider = new ContentProvider();
    185         mTreeViewer.setContentProvider(contentProvider);
    186         mTreeViewer.setLabelProvider(contentProvider);
    187         mModel.addWindowChangeListener(this);
    188         mTreeViewer.setInput(mModel);
    189 
    190         addControlListener(mControlListener);
    191     }
    192 
    193     public void loadResources() {
    194         Display display = Display.getDefault();
    195         Font systemFont = display.getSystemFont();
    196         FontData[] fontData = systemFont.getFontData();
    197         FontData[] newFontData = new FontData[fontData.length];
    198         for (int i = 0; i < fontData.length; i++) {
    199             newFontData[i] =
    200                     new FontData(fontData[i].getName(), fontData[i].getHeight(), fontData[i]
    201                             .getStyle()
    202                             | SWT.BOLD);
    203         }
    204         mBoldFont = new Font(Display.getDefault(), newFontData);
    205 
    206         ImageLoader loader = ImageLoader.getDdmUiLibLoader();
    207         mDeviceImage =
    208                 loader.loadImage(display, "device.png", ICON_WIDTH, ICON_WIDTH, display //$NON-NLS-1$
    209                         .getSystemColor(SWT.COLOR_RED));
    210 
    211         mEmulatorImage =
    212                 loader.loadImage(display, "emulator.png", ICON_WIDTH, ICON_WIDTH, display //$NON-NLS-1$
    213                         .getSystemColor(SWT.COLOR_BLUE));
    214     }
    215 
    216     private DisposeListener mDisposeListener = new DisposeListener() {
    217         @Override
    218         public void widgetDisposed(DisposeEvent e) {
    219             mModel.removeWindowChangeListener(DeviceSelector.this);
    220             mBoldFont.dispose();
    221         }
    222     };
    223 
    224     // If the window gets too small, hide the data, otherwise SWT throws an
    225     // ERROR.
    226 
    227     private ControlListener mControlListener = new ControlAdapter() {
    228         private boolean noInput = false;
    229 
    230         @Override
    231         public void controlResized(ControlEvent e) {
    232             if (getBounds().height <= 38) {
    233                 mTreeViewer.setInput(null);
    234                 noInput = true;
    235             } else if (noInput) {
    236                 mTreeViewer.setInput(mModel);
    237                 noInput = false;
    238             }
    239         }
    240     };
    241 
    242     @Override
    243     public boolean setFocus() {
    244         return mTree.setFocus();
    245     }
    246 
    247     public void setMode(boolean doTreeViewStuff, boolean doPixelPerfectStuff) {
    248         if (this.mDoTreeViewStuff != doTreeViewStuff
    249                 || this.mDoPixelPerfectStuff != doPixelPerfectStuff) {
    250             final boolean expandAll = !this.mDoTreeViewStuff && doTreeViewStuff;
    251             this.mDoTreeViewStuff = doTreeViewStuff;
    252             this.mDoPixelPerfectStuff = doPixelPerfectStuff;
    253             Display.getDefault().syncExec(new Runnable() {
    254                 @Override
    255                 public void run() {
    256                     mTreeViewer.refresh();
    257                     if (expandAll) {
    258                         mTreeViewer.expandAll();
    259                     }
    260                 }
    261             });
    262         }
    263     }
    264 
    265     @Override
    266     public void deviceConnected(final IDevice device) {
    267         Display.getDefault().syncExec(new Runnable() {
    268             @Override
    269             public void run() {
    270                 mTreeViewer.refresh();
    271                 mTreeViewer.setExpandedState(device, true);
    272             }
    273         });
    274     }
    275 
    276     @Override
    277     public void deviceChanged(final IDevice device) {
    278         Display.getDefault().syncExec(new Runnable() {
    279             @Override
    280             public void run() {
    281                 TreeSelection selection = (TreeSelection) mTreeViewer.getSelection();
    282                 mTreeViewer.refresh(device);
    283                 if (selection.getFirstElement() instanceof Window
    284                         && ((Window) selection.getFirstElement()).getDevice() == device) {
    285                     mTreeViewer.setSelection(selection, true);
    286                 }
    287             }
    288         });
    289     }
    290 
    291     @Override
    292     public void deviceDisconnected(final IDevice device) {
    293         Display.getDefault().syncExec(new Runnable() {
    294             @Override
    295             public void run() {
    296                 mTreeViewer.refresh();
    297             }
    298         });
    299     }
    300 
    301     @Override
    302     public void focusChanged(final IDevice device) {
    303         Display.getDefault().syncExec(new Runnable() {
    304             @Override
    305             public void run() {
    306                 TreeSelection selection = (TreeSelection) mTreeViewer.getSelection();
    307                 mTreeViewer.refresh(device);
    308                 if (selection.getFirstElement() instanceof Window
    309                         && ((Window) selection.getFirstElement()).getDevice() == device) {
    310                     mTreeViewer.setSelection(selection, true);
    311                 }
    312             }
    313         });
    314     }
    315 
    316     @Override
    317     public void selectionChanged(IDevice device, Window window) {
    318         // pass
    319     }
    320 
    321     @Override
    322     public void widgetDefaultSelected(SelectionEvent e) {
    323         Object selection = ((TreeItem) e.item).getData();
    324         if (selection instanceof IDevice && mDoPixelPerfectStuff) {
    325             HierarchyViewerDirector.getDirector().loadPixelPerfectData((IDevice) selection);
    326         } else if (selection instanceof Window && mDoTreeViewStuff) {
    327             HierarchyViewerDirector.getDirector().loadViewTreeData((Window) selection);
    328         }
    329     }
    330 
    331     @Override
    332     public void widgetSelected(SelectionEvent e) {
    333         Object selection = ((TreeItem) e.item).getData();
    334         if (selection instanceof IDevice) {
    335             mModel.setSelection((IDevice) selection, null);
    336         } else if (selection instanceof Window) {
    337             mModel.setSelection(((Window) selection).getDevice(), (Window) selection);
    338         }
    339     }
    340 }
    341