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
17package com.android.hierarchyviewerlib.ui;
18
19import com.android.ddmuilib.ImageLoader;
20import com.android.hierarchyviewerlib.device.ViewNode;
21import com.android.hierarchyviewerlib.models.PixelPerfectModel;
22import com.android.hierarchyviewerlib.models.PixelPerfectModel.IImageChangeListener;
23
24import org.eclipse.jface.viewers.ILabelProvider;
25import org.eclipse.jface.viewers.ILabelProviderListener;
26import org.eclipse.jface.viewers.ITreeContentProvider;
27import org.eclipse.jface.viewers.TreeSelection;
28import org.eclipse.jface.viewers.TreeViewer;
29import org.eclipse.jface.viewers.Viewer;
30import org.eclipse.swt.SWT;
31import org.eclipse.swt.events.DisposeEvent;
32import org.eclipse.swt.events.DisposeListener;
33import org.eclipse.swt.events.SelectionEvent;
34import org.eclipse.swt.events.SelectionListener;
35import org.eclipse.swt.graphics.Image;
36import org.eclipse.swt.layout.FillLayout;
37import org.eclipse.swt.widgets.Composite;
38import org.eclipse.swt.widgets.Display;
39import org.eclipse.swt.widgets.Tree;
40
41import java.util.List;
42
43public class PixelPerfectTree extends Composite implements IImageChangeListener, SelectionListener {
44
45    private TreeViewer mTreeViewer;
46
47    private Tree mTree;
48
49    private PixelPerfectModel mModel;
50
51    private Image mFolderImage;
52
53    private Image mFileImage;
54
55    private class ContentProvider implements ITreeContentProvider, ILabelProvider {
56        @Override
57        public Object[] getChildren(Object element) {
58            if (element instanceof ViewNode) {
59                List<ViewNode> children = ((ViewNode) element).children;
60                return children.toArray(new ViewNode[children.size()]);
61            }
62            return null;
63        }
64
65        @Override
66        public Object getParent(Object element) {
67            if (element instanceof ViewNode) {
68                return ((ViewNode) element).parent;
69            }
70            return null;
71        }
72
73        @Override
74        public boolean hasChildren(Object element) {
75            if (element instanceof ViewNode) {
76                return ((ViewNode) element).children.size() != 0;
77            }
78            return false;
79        }
80
81        @Override
82        public Object[] getElements(Object element) {
83            if (element instanceof PixelPerfectModel) {
84                ViewNode viewNode = ((PixelPerfectModel) element).getViewNode();
85                if (viewNode == null) {
86                    return new Object[0];
87                }
88                return new Object[] {
89                    viewNode
90                };
91            }
92            return new Object[0];
93        }
94
95        @Override
96        public void dispose() {
97            // pass
98        }
99
100        @Override
101        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
102            // pass
103        }
104
105        @Override
106        public Image getImage(Object element) {
107            if (element instanceof ViewNode) {
108                if (hasChildren(element)) {
109                    return mFolderImage;
110                }
111                return mFileImage;
112            }
113            return null;
114        }
115
116        @Override
117        public String getText(Object element) {
118            if (element instanceof ViewNode) {
119                return ((ViewNode) element).name;
120            }
121            return null;
122        }
123
124        @Override
125        public void addListener(ILabelProviderListener listener) {
126            // pass
127        }
128
129        @Override
130        public boolean isLabelProperty(Object element, String property) {
131            // pass
132            return false;
133        }
134
135        @Override
136        public void removeListener(ILabelProviderListener listener) {
137            // pass
138        }
139    }
140
141    public PixelPerfectTree(Composite parent) {
142        super(parent, SWT.NONE);
143        setLayout(new FillLayout());
144        mTreeViewer = new TreeViewer(this, SWT.SINGLE);
145        mTreeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
146
147        mTree = mTreeViewer.getTree();
148        mTree.addSelectionListener(this);
149
150        loadResources();
151
152        addDisposeListener(mDisposeListener);
153
154        mModel = PixelPerfectModel.getModel();
155        ContentProvider contentProvider = new ContentProvider();
156        mTreeViewer.setContentProvider(contentProvider);
157        mTreeViewer.setLabelProvider(contentProvider);
158        mTreeViewer.setInput(mModel);
159        mModel.addImageChangeListener(this);
160
161    }
162
163    private void loadResources() {
164        ImageLoader loader = ImageLoader.getDdmUiLibLoader();
165        mFileImage = loader.loadImage("file.png", Display.getDefault());
166        mFolderImage = loader.loadImage("folder.png", Display.getDefault());
167    }
168
169    private DisposeListener mDisposeListener = new DisposeListener() {
170        @Override
171        public void widgetDisposed(DisposeEvent e) {
172            mModel.removeImageChangeListener(PixelPerfectTree.this);
173        }
174    };
175
176    @Override
177    public boolean setFocus() {
178        return mTree.setFocus();
179    }
180
181    @Override
182    public void imageLoaded() {
183        Display.getDefault().syncExec(new Runnable() {
184            @Override
185            public void run() {
186                mTreeViewer.refresh();
187                mTreeViewer.expandAll();
188            }
189        });
190    }
191
192    @Override
193    public void imageChanged() {
194        // pass
195    }
196
197    @Override
198    public void crosshairMoved() {
199        // pass
200    }
201
202    @Override
203    public void selectionChanged() {
204        // pass
205    }
206
207    @Override
208    public void treeChanged() {
209        imageLoaded();
210    }
211
212    @Override
213    public void widgetDefaultSelected(SelectionEvent e) {
214        // pass
215    }
216
217    @Override
218    public void widgetSelected(SelectionEvent e) {
219        // To combat phantom selection...
220        if (((TreeSelection) mTreeViewer.getSelection()).isEmpty()) {
221            mModel.setSelected(null);
222        } else {
223            mModel.setSelected((ViewNode) e.item.getData());
224        }
225    }
226
227    @Override
228    public void zoomChanged() {
229        // pass
230    }
231
232    @Override
233    public void overlayChanged() {
234        // pass
235    }
236
237    @Override
238    public void overlayTransparencyChanged() {
239        // pass
240    }
241}
242