comparison org.eclipse.ui.forms/src/org/eclipse/ui/forms/DetailsPart.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children dbfb303e8fb0
comparison
equal deleted inserted replaced
11:43904fec5dca 12:bc29606a740c
1 /*******************************************************************************
2 * Copyright (c) 2000, 2006 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.ui.forms.DetailsPart;
14
15 import org.eclipse.ui.forms.IFormPart;
16 import org.eclipse.ui.forms.IPartSelectionListener;
17 import org.eclipse.ui.forms.IManagedForm;
18 import org.eclipse.ui.forms.IDetailsPageProvider;
19 import org.eclipse.ui.forms.IDetailsPage;
20
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.custom.BusyIndicator;
23 import org.eclipse.swt.widgets.Composite;
24 import org.eclipse.swt.widgets.Control;
25 import org.eclipse.jface.viewers.ISelection;
26 import org.eclipse.jface.viewers.IStructuredSelection;
27 import org.eclipse.ui.forms.widgets.ScrolledPageBook;
28
29 import java.lang.all;
30 import java.util.Enumeration;
31 import java.util.Iterator;
32 import java.util.Set;
33
34 /**
35 * This managed form part handles the 'details' portion of the
36 * 'master/details' block. It has a page book that manages pages
37 * of details registered for the current selection.
38 * <p>By default, details part accepts any number of pages.
39 * If dynamic page provider is registered, this number may
40 * be excessive. To avoid running out of steam (by creating
41 * a large number of pages with widgets on each), maximum
42 * number of pages can be set to some reasonable value (e.g. 10).
43 * When this number is reached, old pages (those created first)
44 * will be removed and disposed as new ones are added. If
45 * the disposed pages are needed again after that, they
46 * will be created again.
47 *
48 * @since 3.0
49 */
50 public final class DetailsPart : IFormPart, IPartSelectionListener {
51 private IManagedForm managedForm;
52 private ScrolledPageBook pageBook;
53 private IFormPart masterPart;
54 private IStructuredSelection currentSelection;
55 private Hashtable pages;
56 private IDetailsPageProvider pageProvider;
57 private int pageLimit=Integer.MAX_VALUE;
58
59 private static class PageBag {
60 private static int counter;
61 private int ticket;
62 private IDetailsPage page;
63 private bool fixed;
64
65 public this(IDetailsPage page, bool fixed) {
66 this.page= page;
67 this.fixed = fixed;
68 this.ticket = ++counter;
69 }
70 public int getTicket() {
71 return ticket;
72 }
73 public IDetailsPage getPage() {
74 return page;
75 }
76 public void dispose() {
77 page.dispose();
78 page=null;
79 }
80 public bool isDisposed() {
81 return page is null;
82 }
83 public bool isFixed() {
84 return fixed;
85 }
86 public static int getCurrentTicket() {
87 return counter;
88 }
89 }
90 /**
91 * Creates a details part by wrapping the provided page book.
92 * @param mform the parent form
93 * @param pageBook the page book to wrap
94 */
95 public this(IManagedForm mform, ScrolledPageBook pageBook) {
96 this.pageBook = pageBook;
97 pages = new Hashtable();
98 initialize(mform);
99 }
100 /**
101 * Creates a new details part in the provided form by creating
102 * the page book.
103 * @param mform the parent form
104 * @param parent the composite to create the page book in
105 * @param style the style for the page book
106 */
107 public this(IManagedForm mform, Composite parent, int style) {
108 this(mform, mform.getToolkit().createPageBook(parent, style|SWT.V_SCROLL|SWT.H_SCROLL));
109 }
110 /**
111 * Registers the details page to be used for all the objects of
112 * the provided object class.
113 * @param objectClass an object of type 'java.lang.Class' to be used
114 * as a key for the provided page
115 * @param page the page to show for objects of the provided object class
116 */
117 public void registerPage(Object objectClass, IDetailsPage page) {
118 registerPage(objectClass, page, true);
119 }
120
121 private void registerPage(Object objectClass, IDetailsPage page, bool fixed) {
122 pages.put(objectClass, new PageBag(page, fixed));
123 page.initialize(managedForm);
124 }
125 /**
126 * Sets the dynamic page provider. The dynamic provider can return
127 * different pages for objects of the same class based on their state.
128 * @param provider the provider to use
129 */
130 public void setPageProvider(IDetailsPageProvider provider) {
131 this.pageProvider = provider;
132 }
133 /**
134 * Commits the part by committing the current page.
135 * @param onSave <code>true</code> if commit is requested as a result
136 * of the 'save' action, <code>false</code> otherwise.
137 */
138 public void commit(bool onSave) {
139 IDetailsPage page = getCurrentPage();
140 if (page !is null)
141 page.commit(onSave);
142 }
143 /**
144 * Returns the current page visible in the part.
145 * @return the current page
146 */
147 public IDetailsPage getCurrentPage() {
148 Control control = pageBook.getCurrentPage();
149 if (control !is null) {
150 Object data = control.getData();
151 if (null !is cast(IDetailsPage)data )
152 return cast(IDetailsPage) data;
153 }
154 return null;
155 }
156 /*
157 * (non-Javadoc)
158 *
159 * @see org.eclipse.ui.forms.IFormPart#dispose()
160 */
161 public void dispose() {
162 for (Enumeration enm = pages.elements(); enm.hasMoreElements();) {
163 PageBag pageBag = cast(PageBag) enm.nextElement();
164 pageBag.dispose();
165 }
166 }
167 /*
168 * (non-Javadoc)
169 *
170 * @see org.eclipse.ui.forms.IFormPart#initialize(org.eclipse.ui.forms.IManagedForm)
171 */
172 public void initialize(IManagedForm form) {
173 this.managedForm = form;
174 }
175 /**
176 * Tests if the currently visible page is dirty.
177 * @return <code>true</code> if the page is dirty, <code>false</code> otherwise.
178 */
179 public bool isDirty() {
180 IDetailsPage page = getCurrentPage();
181 if (page !is null)
182 return page.isDirty();
183 return false;
184 }
185 /**
186 * Tests if the currently visible page is stale and needs refreshing.
187 * @return <code>true</code> if the page is stale, <code>false</code> otherwise.
188 */
189 public bool isStale() {
190 IDetailsPage page = getCurrentPage();
191 if (page !is null)
192 return page.isStale();
193 return false;
194 }
195
196 /**
197 * Refreshes the current page.
198 */
199 public void refresh() {
200 IDetailsPage page = getCurrentPage();
201 if (page !is null)
202 page.refresh();
203 }
204 /**
205 * Sets the focus to the currently visible page.
206 */
207 public void setFocus() {
208 IDetailsPage page = getCurrentPage();
209 if (page !is null)
210 page.setFocus();
211 }
212 /*
213 * (non-Javadoc)
214 *
215 * @see org.eclipse.ui.forms.IFormPart#setFormInput(java.lang.Object)
216 */
217 public bool setFormInput(Object input) {
218 return false;
219 }
220 /*
221 * (non-Javadoc)
222 *
223 * @see org.eclipse.ui.forms.IPartSelectionListener#selectionChanged(org.eclipse.ui.forms.IFormPart,
224 * org.eclipse.jface.viewers.ISelection)
225 */
226 public void selectionChanged(IFormPart part, ISelection selection) {
227 this.masterPart = part;
228 if (currentSelection !is null) {
229 }
230 if (null !is cast(IStructuredSelection)selection )
231 currentSelection = cast(IStructuredSelection) selection;
232 else
233 currentSelection = null;
234 update();
235 }
236 private void update() {
237 Object key = null;
238 if (currentSelection !is null) {
239 for (Iterator iter = currentSelection.iterator(); iter.hasNext();) {
240 Object obj = iter.next();
241 if (key is null)
242 key = getKey(obj);
243 else if (getKey(obj).opEquals(key) is false) {
244 key = null;
245 break;
246 }
247 }
248 }
249 showPage(key);
250 }
251 private Object getKey(Object object) {
252 if (pageProvider !is null) {
253 Object key = pageProvider.getPageKey(object);
254 if (key !is null)
255 return key;
256 }
257 return object.classinfo;
258 }
259 private void showPage( Object key) {
260 checkLimit();
261 final IDetailsPage oldPage = getCurrentPage();
262 if (key !is null) {
263 PageBag pageBag = cast(PageBag)pages.get(key);
264 IDetailsPage page = pageBag !is null?pageBag.getPage():null;
265 if (page is null) {
266 // try to get the page dynamically from the provider
267 if (pageProvider !is null) {
268 page = pageProvider.getPage(key);
269 if (page !is null) {
270 registerPage(key, page, false);
271 }
272 }
273 }
274 if (page !is null) {
275 BusyIndicator.showWhile(pageBook.getDisplay(), dgRunnable( (IDetailsPage fpage,Object key,IDetailsPage oldPage) {
276 if (!pageBook.hasPage(key)) {
277 Composite parent = pageBook.createPage(key);
278 fpage.createContents(parent);
279 parent.setData(cast(Object)fpage);
280 }
281 //commit the current page
282 if (oldPage !is null && oldPage.isDirty())
283 oldPage.commit(false);
284 //refresh the new page
285 if (fpage.isStale())
286 fpage.refresh();
287 fpage.selectionChanged(masterPart, currentSelection);
288 pageBook.showPage(key);
289 }, page, key, oldPage));
290 return;
291 }
292 }
293 // If we are switching from an old page to nothing,
294 // don't loose data
295 if (oldPage !is null && oldPage.isDirty())
296 oldPage.commit(false);
297 pageBook.showEmptyPage();
298 }
299 private void checkLimit() {
300 if (pages.size() <= getPageLimit()) return;
301 // overflow
302 int currentTicket = PageBag.getCurrentTicket();
303 int cutoffTicket = currentTicket - getPageLimit();
304 for (Enumeration enm=pages.keys(); enm.hasMoreElements();) {
305 Object key = enm.nextElement();
306 PageBag pageBag = cast(PageBag)pages.get(key);
307 if (pageBag.getTicket()<=cutoffTicket) {
308 // candidate - see if it is active and not fixed
309 if (!pageBag.isFixed() && !(cast(Object)pageBag.getPage()).opEquals(cast(Object)getCurrentPage())) {
310 // drop it
311 pageBag.dispose();
312 pages.remove(key);
313 pageBook.removePage(key, false);
314 }
315 }
316 }
317 }
318 /**
319 * Returns the maximum number of pages that should be
320 * maintained in this part. When an attempt is made to
321 * add more pages, old pages are removed and disposed
322 * based on the order of creation (the oldest pages
323 * are removed). The exception is made for the
324 * page that should otherwise be disposed but is
325 * currently active.
326 * @return maximum number of pages for this part
327 */
328 public int getPageLimit() {
329 return pageLimit;
330 }
331 /**
332 * Sets the page limit for this part.
333 * @see #getPageLimit()
334 * @param pageLimit the maximum number of pages that
335 * should be maintained in this part.
336 */
337 public void setPageLimit(int pageLimit) {
338 this.pageLimit = pageLimit;
339 checkLimit();
340 }
341 }