1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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.ide.eclipse.adt.internal.editors.layout.gle2;
18 
19 import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
20 import com.android.ide.eclipse.adt.internal.editors.layout.gre.RulesEngine;
21 
22 import org.eclipse.core.runtime.ListenerList;
23 import org.eclipse.jface.util.SafeRunnable;
24 import org.eclipse.jface.viewers.IPostSelectionProvider;
25 import org.eclipse.jface.viewers.ISelection;
26 import org.eclipse.jface.viewers.ISelectionChangedListener;
27 import org.eclipse.jface.viewers.ISelectionProvider;
28 import org.eclipse.jface.viewers.SelectionChangedEvent;
29 import org.eclipse.jface.viewers.TreePath;
30 import org.eclipse.jface.viewers.TreeSelection;
31 import org.eclipse.jface.viewers.Viewer;
32 import org.eclipse.swt.widgets.Composite;
33 import org.eclipse.swt.widgets.Control;
34 
35 
36 /**
37  * JFace {@link Viewer} wrapper around {@link LayoutCanvas}.
38  * <p/>
39  * The viewer is owned by {@link GraphicalEditorPart}.
40  * <p/>
41  * The viewer is an {@link ISelectionProvider} instance and is set as the
42  * site's main {@link ISelectionProvider} by the editor part. Consequently
43  * canvas' selection changes are broadcasted to anyone listening, which includes
44  * the part itself as well as the associated outline and property sheet pages.
45  */
46 class LayoutCanvasViewer extends Viewer implements IPostSelectionProvider {
47 
48     private LayoutCanvas mCanvas;
49     private final LayoutEditorDelegate mEditorDelegate;
50 
LayoutCanvasViewer(LayoutEditorDelegate editorDelegate, RulesEngine rulesEngine, Composite parent, int style)51     public LayoutCanvasViewer(LayoutEditorDelegate editorDelegate,
52             RulesEngine rulesEngine,
53             Composite parent,
54             int style) {
55         mEditorDelegate = editorDelegate;
56         mCanvas = new LayoutCanvas(editorDelegate, rulesEngine, parent, style);
57 
58         mCanvas.getSelectionManager().addSelectionChangedListener(mSelectionListener);
59     }
60 
61     private ISelectionChangedListener mSelectionListener = new ISelectionChangedListener() {
62         @Override
63         public void selectionChanged(SelectionChangedEvent event) {
64             fireSelectionChanged(event);
65             firePostSelectionChanged(event);
66         }
67     };
68 
69     @Override
getControl()70     public Control getControl() {
71         return mCanvas;
72     }
73 
74     /**
75      * Returns the underlying {@link LayoutCanvas}.
76      * This is the same control as returned by {@link #getControl()} but clients
77      * have it already casted in the right type.
78      * <p/>
79      * This can never be null.
80      * @return The underlying {@link LayoutCanvas}.
81      */
getCanvas()82     public LayoutCanvas getCanvas() {
83         return mCanvas;
84     }
85 
86     /**
87      * Returns the current layout editor's input.
88      */
89     @Override
getInput()90     public Object getInput() {
91         return mEditorDelegate.getEditor().getEditorInput();
92     }
93 
94     /**
95      * Unused. We don't support switching the input.
96      */
97     @Override
setInput(Object input)98     public void setInput(Object input) {
99     }
100 
101     /**
102      * Returns a new {@link TreeSelection} where each {@link TreePath} item
103      * is a {@link CanvasViewInfo}.
104      */
105     @Override
getSelection()106     public ISelection getSelection() {
107         return mCanvas.getSelectionManager().getSelection();
108     }
109 
110     /**
111      * Sets a new selection. <code>reveal</code> is ignored right now.
112      * <p/>
113      * The selection can be null, which is interpreted as an empty selection.
114      */
115     @Override
setSelection(ISelection selection, boolean reveal)116     public void setSelection(ISelection selection, boolean reveal) {
117         if (mEditorDelegate.getEditor().getIgnoreXmlUpdate()) {
118             return;
119         }
120         mCanvas.getSelectionManager().setSelection(selection);
121     }
122 
123     /** Unused. Refreshing is done solely by the owning {@link LayoutEditorDelegate}. */
124     @Override
refresh()125     public void refresh() {
126         // ignore
127     }
128 
dispose()129     public void dispose() {
130         if (mSelectionListener != null) {
131             mCanvas.getSelectionManager().removeSelectionChangedListener(mSelectionListener);
132         }
133         if (mCanvas != null) {
134             mCanvas.dispose();
135             mCanvas = null;
136         }
137     }
138 
139     // ---- Implements IPostSelectionProvider ----
140 
141     private ListenerList mPostChangedListeners = new ListenerList();
142 
143     @Override
addPostSelectionChangedListener(ISelectionChangedListener listener)144     public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
145         mPostChangedListeners.add(listener);
146     }
147 
148     @Override
removePostSelectionChangedListener(ISelectionChangedListener listener)149     public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
150         mPostChangedListeners.remove(listener);
151     }
152 
firePostSelectionChanged(final SelectionChangedEvent event)153     protected void firePostSelectionChanged(final SelectionChangedEvent event) {
154         Object[] listeners = mPostChangedListeners.getListeners();
155         for (int i = 0; i < listeners.length; i++) {
156             final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
157             SafeRunnable.run(new SafeRunnable() {
158                 @Override
159                 public void run() {
160                     l.selectionChanged(event);
161                 }
162             });
163         }
164     }
165 }
166