Source code: org/eclipse/ui/internal/EditorSashContainer.java
1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.ui.internal;
12
13
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.Map;
18
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.core.runtime.MultiStatus;
21 import org.eclipse.core.runtime.Status;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.dnd.DND;
24 import org.eclipse.swt.dnd.DropTarget;
25 import org.eclipse.swt.widgets.Composite;
26 import org.eclipse.swt.widgets.Control;
27 import org.eclipse.ui.IMemento;
28 import org.eclipse.ui.PlatformUI;
29 import org.eclipse.ui.internal.presentations.PresentationSerializer;
30 import org.eclipse.ui.presentations.StackPresentation;
31
32 /**
33 * Represents the area set aside for editor workbooks.
34 * This container only accepts EditorStack and PartSash
35 * as layout parts.
36 *
37 * Note no views are allowed within this container.
38 */
39 public class EditorSashContainer extends PartSashContainer {
40
41 private static final String DEFAULT_WORKBOOK_ID = "DefaultEditorWorkbook";//$NON-NLS-1$
42 private ArrayList editorWorkbooks = new ArrayList(3);
43 private EditorStack activeEditorWorkbook;
44 private DropTarget dropTarget;
45 private WorkbenchPage page;
46
47 public EditorSashContainer(String editorId, WorkbenchPage page) {
48 super(editorId,page);
49
50 //this.partDropListener = listener;
51 this.page = page;
52 createDefaultWorkbook();
53 }
54 /**
55 * Add an editor to the active workbook.
56 */
57 public void addEditor(EditorPane pane) {
58 EditorStack workbook = getActiveWorkbook();
59 workbook.add(pane);
60 }
61 /**
62 * Notification that a child layout part has been
63 * added to the container. Subclasses may override
64 * this method to perform any container specific
65 * work.
66 */
67 protected void childAdded(LayoutPart child) {
68 if (child instanceof EditorStack)
69 editorWorkbooks.add(child);
70 }
71 /**
72 * Notification that a child layout part has been
73 * removed from the container. Subclasses may override
74 * this method to perform any container specific
75 * work.
76 */
77 protected void childRemoved(LayoutPart child) {
78 if (child instanceof EditorStack) {
79 editorWorkbooks.remove(child);
80 if (activeEditorWorkbook == child)
81 setActiveWorkbook(null, false);
82 }
83 }
84 protected EditorStack createDefaultWorkbook() {
85 EditorStack newWorkbook = EditorStack.newEditorWorkbook(this, page);
86 newWorkbook.setID(DEFAULT_WORKBOOK_ID);
87 add(newWorkbook);
88 return newWorkbook;
89 }
90 /**
91 * Subclasses override this method to specify
92 * the composite to use to parent all children
93 * layout parts it contains.
94 */
95 protected Composite createParent(Composite parentWidget) {
96 return new Composite(parentWidget, SWT.NONE);
97 }
98 /**
99 * Dispose of the editor area.
100 */
101 public void dispose() {
102 // Free editor workbooks.
103 Iterator iter = editorWorkbooks.iterator();
104 while (iter.hasNext()) {
105 EditorStack wb = (EditorStack)iter.next();
106 wb.dispose();
107 }
108 editorWorkbooks.clear();
109
110 // Free rest.
111 super.dispose();
112 }
113 /**
114 * Subclasses override this method to dispose
115 * of any swt resources created during createParent.
116 */
117 protected void disposeParent() {
118 this.parent.dispose();
119 }
120 /**
121 * Return the editor workbook which is active.
122 */
123 public EditorStack getActiveWorkbook() {
124 if (activeEditorWorkbook == null) {
125 if (editorWorkbooks.size() < 1)
126 setActiveWorkbook(createDefaultWorkbook(), false);
127 else
128 setActiveWorkbook((EditorStack)editorWorkbooks.get(0), false);
129 }
130
131 return activeEditorWorkbook;
132 }
133 /**
134 * Return the editor workbook id which is active.
135 */
136 public String getActiveWorkbookID() {
137 return getActiveWorkbook().getID();
138 }
139 /**
140 * Return the all the editor workbooks.
141 */
142 public ArrayList getEditorWorkbooks() {
143 return (ArrayList)editorWorkbooks.clone();
144 }
145 /**
146 * Return the all the editor workbooks.
147 */
148 public int getEditorWorkbookCount() {
149 return editorWorkbooks.size();
150 }
151 /**
152 * Return true is the workbook specified
153 * is the active one.
154 */
155 protected boolean isActiveWorkbook(EditorStack workbook) {
156 return activeEditorWorkbook == workbook;
157 }
158 /**
159 * Find the sashs around the specified part.
160 */
161 public void findSashes(LayoutPart pane,PartPane.Sashes sashes) {
162 //Find the sashes around the current editor and
163 //then the sashes around the editor area.
164 super.findSashes(pane,sashes);
165
166 ILayoutContainer container = getContainer();
167 if (container != null) {
168 container.findSashes(this,sashes);
169 }
170 }
171 /**
172 * Remove all the editors
173 */
174 public void removeAllEditors() {
175 EditorStack currentWorkbook = getActiveWorkbook();
176
177 // Iterate over a copy so the original can be modified.
178 Iterator workbooks = ((ArrayList)editorWorkbooks.clone()).iterator();
179 while (workbooks.hasNext()) {
180 EditorStack workbook = (EditorStack)workbooks.next();
181 workbook.removeAll();
182 if (workbook != currentWorkbook) {
183 remove(workbook);
184 workbook.dispose();
185 }
186 }
187 }
188 /**
189 * Remove an editor from its' workbook.
190 */
191 public void removeEditor(EditorPane pane) {
192 EditorStack workbook = pane.getWorkbook();
193 if (workbook == null)
194 return;
195 workbook.remove(pane);
196
197 // remove the editor workbook if empty
198 if (workbook.getItemCount() < 1 /* && editorWorkbooks.size() > 1*/) {
199 remove(workbook);
200 workbook.dispose();
201 }
202 }
203 /**
204 * @see IPersistablePart
205 */
206 public IStatus restoreState(IMemento memento) {
207 MultiStatus result = new MultiStatus(
208 PlatformUI.PLUGIN_ID,IStatus.OK,
209 WorkbenchMessages.getString("RootLayoutContainer.problemsRestoringPerspective"),null); //$NON-NLS-1$
210
211 // Remove the default editor workbook that is
212 // initialy created with the editor area.
213 if (children != null) {
214 EditorStack defaultWorkbook = null;
215 for (int i = 0; i < children.size(); i++) {
216 LayoutPart child = (LayoutPart)children.get(i);
217 if (child.getID() == DEFAULT_WORKBOOK_ID) {
218 defaultWorkbook = (EditorStack)child;
219 if (defaultWorkbook.getItemCount() > 0)
220 defaultWorkbook = null;
221 }
222 }
223 if (defaultWorkbook != null)
224 remove(defaultWorkbook);
225 }
226
227 // Restore the relationship/layout
228 IMemento [] infos = memento.getChildren(IWorkbenchConstants.TAG_INFO);
229 Map mapIDtoPart = new HashMap(infos.length);
230
231 for (int i = 0; i < infos.length; i ++) {
232 // Get the info details.
233 IMemento childMem = infos[i];
234 String partID = childMem.getString(IWorkbenchConstants.TAG_PART);
235 String relativeID = childMem.getString(IWorkbenchConstants.TAG_RELATIVE);
236 int relationship = 0;
237 int left = 0, right = 0;
238 float ratio = 0.5f;
239 if (relativeID != null) {
240 relationship = childMem.getInteger(IWorkbenchConstants.TAG_RELATIONSHIP).intValue();
241 Float ratioFloat = childMem.getFloat(IWorkbenchConstants.TAG_RATIO);
242 Integer leftInt = childMem.getInteger(IWorkbenchConstants.TAG_RATIO_LEFT);
243 Integer rightInt = childMem.getInteger(IWorkbenchConstants.TAG_RATIO_RIGHT);
244 if (leftInt != null && rightInt != null) {
245 left = leftInt.intValue();
246 right = rightInt.intValue();
247 } else if (ratioFloat != null) {
248 ratio = ratioFloat.floatValue();
249 }
250 }
251
252 // Create the part.
253 EditorStack workbook = EditorStack.newEditorWorkbook(this, page);
254 workbook.setID(partID);
255 // 1FUN70C: ITPUI:WIN - Shouldn't set Container when not active
256 workbook.setContainer(this);
257
258 IMemento workbookMemento = childMem.getChild(IWorkbenchConstants.TAG_FOLDER);
259 if (workbookMemento != null) {
260 result.add(workbook.restoreState(workbookMemento));
261 }
262
263 // Add the part to the layout
264 if (relativeID == null) {
265 add(workbook);
266 } else {
267 LayoutPart refPart = (LayoutPart)mapIDtoPart.get(relativeID);
268 if (refPart != null) {
269 //$TODO pass in left and right
270 if (left == 0 || right == 0)
271 add(workbook, relationship, ratio, refPart);
272 else
273 add(workbook, relationship, left, right, refPart);
274 } else {
275 WorkbenchPlugin.log("Unable to find part for ID: " + relativeID);//$NON-NLS-1$
276 }
277 }
278 mapIDtoPart.put(partID, workbook);
279 }
280 return result;
281 }
282 /**
283 * @see IPersistablePart
284 */
285 public IStatus saveState(IMemento memento) {
286 RelationshipInfo[] relationships = computeRelation();
287 MultiStatus result = new MultiStatus(
288 PlatformUI.PLUGIN_ID,IStatus.OK,
289 WorkbenchMessages.getString("RootLayoutContainer.problemsSavingPerspective"),null); //$NON-NLS-1$
290
291 for (int i = 0; i < relationships.length; i ++) {
292 // Save the relationship info ..
293 // private LayoutPart part;
294 // private int relationship;
295 // private float ratio;
296 // private LayoutPart relative;
297 RelationshipInfo info = relationships[i];
298 IMemento childMem = memento.createChild(IWorkbenchConstants.TAG_INFO);
299 childMem.putString(IWorkbenchConstants.TAG_PART, info.part.getID());
300
301 EditorStack stack = (EditorStack) info.part;
302 if (stack != null) {
303 IMemento folderMem = childMem.createChild(IWorkbenchConstants.TAG_FOLDER);
304 result.add(stack.saveState(folderMem));
305 }
306
307 if (info.relative != null) {
308 childMem.putString(IWorkbenchConstants.TAG_RELATIVE, info.relative.getID());
309 childMem.putInteger(IWorkbenchConstants.TAG_RELATIONSHIP, info.relationship);
310 childMem.putInteger(IWorkbenchConstants.TAG_RATIO_LEFT, info.left);
311 childMem.putInteger(IWorkbenchConstants.TAG_RATIO_RIGHT, info.right);
312 // Note: "ratio" is not used in newer versions of Eclipse, which use "left"
313 // and "right" (above) instead
314 childMem.putFloat(IWorkbenchConstants.TAG_RATIO, info.getRatio());
315 }
316 }
317 return result;
318 }
319 /**
320 * Set the editor workbook which is active.
321 */
322 public void setActiveWorkbook(EditorStack newWorkbook, boolean hasFocus) {
323 if (newWorkbook != null) {
324 if (newWorkbook.isDisposed())
325 return;
326 if (!editorWorkbooks.contains(newWorkbook))
327 return;
328 }
329 EditorStack oldWorkbook = activeEditorWorkbook;
330 activeEditorWorkbook = newWorkbook;
331
332 if (oldWorkbook != null && oldWorkbook != newWorkbook) {
333 oldWorkbook.setActive(StackPresentation.AS_INACTIVE);
334 }
335
336 if (newWorkbook != null) {
337 if (hasFocus) {
338 newWorkbook.setActive(StackPresentation.AS_ACTIVE_FOCUS);
339 } else {
340 newWorkbook.setActive(StackPresentation.AS_ACTIVE_NOFOCUS);
341 }
342 }
343
344 updateTabList();
345 }
346 /**
347 * Set the editor workbook which is active.
348 */
349 public void setActiveWorkbookFromID(String id) {
350 for (int i = 0; i < editorWorkbooks.size(); i++) {
351 EditorStack workbook = (EditorStack) editorWorkbooks.get(i);
352 if (workbook.getID().equals(id))
353 setActiveWorkbook(workbook, false);
354 }
355 }
356
357 /**
358 * Updates the editor area's tab list to include the active
359 * editor and its tab.
360 */
361 public void updateTabList() {
362 Composite parent = getParent();
363 if (parent != null) { // parent may be null on startup
364 EditorStack wb = getActiveWorkbook();
365 if (wb == null) {
366 parent.setTabList(new Control[0]);
367 }
368 else {
369 parent.setTabList(wb.getTabList());
370 }
371 }
372 }
373
374
375 /**
376 * @see org.eclipse.ui.internal.LayoutPart#createControl(org.eclipse.swt.widgets.Composite)
377 */
378 public void createControl(Composite parent) {
379 super.createControl(parent);
380
381 //let the user drop files/editor input on the editor area
382 addDropSupport();
383 }
384 private void addDropSupport() {
385 if (dropTarget == null) {
386 WorkbenchWindowConfigurer winConfigurer = ((WorkbenchWindow) page.getWorkbenchWindow()).getWindowConfigurer();
387
388 dropTarget = new DropTarget(getControl(), DND.DROP_DEFAULT | DND.DROP_COPY);
389 dropTarget.setTransfer(winConfigurer.getTransfers());
390 if (winConfigurer.getDropTargetListener() != null) {
391 dropTarget.addDropListener(winConfigurer.getDropTargetListener());
392 }
393 }
394 }
395
396 /* package */ DropTarget getDropTarget() {
397 return dropTarget;
398 }
399 /**
400 * @see org.eclipse.ui.internal.LayoutPart#getImportance()
401 */
402 public boolean isCompressible() {
403 //Added for bug 19524
404 return true;
405 }
406 /* (non-Javadoc)
407 * @see org.eclipse.ui.internal.ILayoutContainer#allowsAutoFocus()
408 */
409 public boolean allowsAutoFocus() {
410 return true;
411 }
412
413 /* (non-Javadoc)
414 * @see org.eclipse.ui.internal.PartSashContainer#isStackType(org.eclipse.ui.internal.LayoutPart)
415 */
416 public boolean isStackType(LayoutPart toTest) {
417 return (toTest instanceof EditorStack);
418 }
419 /* (non-Javadoc)
420 * @see org.eclipse.ui.internal.PartSashContainer#isPaneType(org.eclipse.ui.internal.LayoutPart)
421 */
422 public boolean isPaneType(LayoutPart toTest) {
423 return (toTest instanceof EditorPane);
424 }
425 /* (non-Javadoc)
426 * @see org.eclipse.ui.internal.PartSashContainer#createStack(org.eclipse.ui.internal.LayoutPart)
427 */
428 protected PartStack createStack() {
429 EditorStack newWorkbook = EditorStack.newEditorWorkbook(this, page);
430
431 return newWorkbook;
432 }
433 /* (non-Javadoc)
434 * @see org.eclipse.ui.internal.PartSashContainer#setVisiblePart(org.eclipse.ui.internal.ILayoutContainer, org.eclipse.ui.internal.LayoutPart)
435 */
436 protected void setVisiblePart(ILayoutContainer container, LayoutPart visiblePart) {
437 EditorStack refPart = (EditorStack)container;
438
439 refPart.becomeActiveWorkbook(true);
440 refPart.setVisibleEditor((EditorPane)visiblePart);
441 }
442 /* (non-Javadoc)
443 * @see org.eclipse.ui.internal.PartSashContainer#getVisiblePart(org.eclipse.ui.internal.ILayoutContainer)
444 */
445 protected LayoutPart getVisiblePart(ILayoutContainer container) {
446 EditorStack refPart = (EditorStack)container;
447
448 return refPart.getVisibleEditor();
449 }
450
451 /**
452 * Restore the presentation state. Loop over the workbooks, create the appropriate serializer and pass to the presentation.
453 *
454 * @param areaMem the memento containing presentation
455 * @return the restoration status
456 */
457 public IStatus restorePresentationState(IMemento areaMem) {
458 for (Iterator i = getEditorWorkbooks().iterator(); i.hasNext();) {
459 EditorStack workbook = (EditorStack) i.next();
460 IMemento memento = workbook.getSavedPresentationState();
461 if (memento == null)
462 continue;
463 PresentationSerializer serializer = new PresentationSerializer(workbook.getPresentableParts());
464 workbook.getPresentation().restoreState(serializer, memento);
465 }
466 return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
467 }
468 }