View Javadoc
1   package org.argeo.connect.ui.parts;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.argeo.cms.ui.eclipse.forms.FormToolkit;
7   import org.argeo.cms.ui.eclipse.forms.IFormPart;
8   import org.argeo.cms.ui.eclipse.forms.IManagedForm;
9   import org.argeo.cms.ui.eclipse.forms.IPartSelectionListener;
10  import org.eclipse.jface.viewers.ISelection;
11  import org.eclipse.swt.custom.ScrolledComposite;
12  import org.eclipse.swt.widgets.Composite;
13  import org.eclipse.swt.widgets.Display;
14  //import org.eclipse.ui.forms.IFormPart;
15  //import org.eclipse.ui.forms.IManagedForm;
16  //import org.eclipse.ui.forms.IMessageManager;
17  //import org.eclipse.ui.forms.IPartSelectionListener;
18  //import org.eclipse.ui.forms.widgets.FormToolkit;
19  //import org.eclipse.ui.forms.widgets.ScrolledForm;
20  
21  /**
22   * Implementation of the IManagedForm that relies on a Form rather than on a
23   * scroll form in order to workaround scrolling issues in complex layouts,
24   * especially when tables with many lines are displayed.
25   */
26  public class CompositeManagedForm implements IManagedForm {
27  
28  	private Object input;
29  
30  	private Object container;
31  
32  	private FormToolkit toolkit;
33  
34  	private boolean initialized = false;
35  
36  	private List<IFormPart> parts = new ArrayList<IFormPart>();
37  
38  	private Composite composite;
39  
40  	/**
41  	 * Creates a managed form that will use the provided toolkit
42  	 * 
43  	 * @param toolkit
44  	 */
45  	public CompositeManagedForm(Composite composite, FormToolkit toolkit) {
46  		this.composite = composite;
47  		this.toolkit = toolkit;
48  	}
49  
50  	@Override
51  	public void addPart(IFormPart part) {
52  		parts.add(part);
53  	}
54  
55  	@Override
56  	public void removePart(IFormPart part) {
57  		parts.remove(part);
58  	}
59  
60  	@Override
61  	public IFormPart[] getParts() {
62  		return parts.toArray(new IFormPart[parts.size()]);
63  	}
64  
65  	@Override
66  	public FormToolkit getToolkit() {
67  		return toolkit;
68  	}
69  
70  	
71  	
72  //	public ScrolledForm getForm() {
73  //		throw new UnsupportedOperationException(
74  //				"Unsupported method: we use a Form rather than a ScrolledForm");
75  //	}
76  //
77  //	@Override
78  //	public IMessageManager getMessageManager() {
79  //		throw new UnsupportedOperationException(
80  //				"Unsupported method: we use a Form rather than a ScrolledForm");
81  //	}
82  
83  	@Override
84  	public ScrolledComposite getForm() {
85  		throw new UnsupportedOperationException();
86  	}
87  
88  	/** Here is the magic */
89  	@Override
90  	public void reflow(boolean changed) {
91  		composite.layout(changed);
92  	}
93  
94  	@Override
95  	public void fireSelectionChanged(IFormPart part, ISelection selection) {
96  		for (IFormPart currpart : parts) {
97  			if (part.equals(currpart))
98  				continue;
99  			if (currpart instanceof IPartSelectionListener) {
100 				((IPartSelectionListener) currpart).selectionChanged(part,
101 						selection);
102 			}
103 		}
104 	}
105 
106 	@Override
107 	public void initialize() {
108 		if (initialized)
109 			return;
110 		for (IFormPart part : parts) {
111 			part.initialize(this);
112 		}
113 		initialized = true;
114 	}
115 
116 	/**
117 	 * Disposes all the parts in this form.
118 	 */
119 	public void dispose() {
120 		for (int i = 0; i < parts.size(); i++) {
121 			IFormPart part = (IFormPart) parts.get(i);
122 			part.dispose();
123 		}
124 		// toolkit is always provided
125 		// if (ownsToolkit) {
126 		// toolkit.dispose();
127 		// }
128 	}
129 
130 	@Override
131 	public void refresh() {
132 		Thread t = Thread.currentThread();
133 		Display display = composite.getDisplay();
134 		Thread dt = display.getThread();
135 		if (t.equals(dt))
136 			doRefresh();
137 		else {
138 			display.asyncExec(new Runnable() {
139 				public void run() {
140 					doRefresh();
141 				}
142 			});
143 		}
144 	}
145 
146 	private void doRefresh() {
147 		int nrefreshed = 0;
148 		for (IFormPart part : parts) {
149 			if (part.isStale()) {
150 				part.refresh();
151 				nrefreshed++;
152 			}
153 		}
154 		if (nrefreshed > 0)
155 			reflow(true);
156 	}
157 
158 	@Override
159 	public void commit(boolean onSave) {
160 		for (IFormPart part : parts) {
161 			if (part.isDirty())
162 				part.commit(onSave);
163 		}
164 	}
165 
166 	@Override
167 	public boolean setInput(Object input) {
168 		boolean pageResult = false;
169 
170 		this.input = input;
171 		for (IFormPart part : parts) {
172 			boolean result = part.setFormInput(input);
173 			if (result)
174 				pageResult = true;
175 		}
176 		return pageResult;
177 	}
178 
179 	@Override
180 	public Object getInput() {
181 		return input;
182 	}
183 
184 	/**
185 	 * Transfers the focus to the first form part.
186 	 */
187 	public void setFocus() {
188 		if (parts.size() > 0) {
189 			IFormPart part = (IFormPart) parts.get(0);
190 			part.setFocus();
191 		}
192 	}
193 
194 	@Override
195 	public boolean isDirty() {
196 		for (IFormPart part : parts) {
197 			if (part.isDirty())
198 				return true;
199 		}
200 		return false;
201 	}
202 
203 	@Override
204 	public boolean isStale() {
205 		for (IFormPart part : parts) {
206 			if (part.isStale())
207 				return true;
208 		}
209 		return false;
210 	}
211 
212 	/**
213 	 * Overwrite to call the corresponding fireproperty change on the correct
214 	 * workbench part
215 	 */
216 	@Override
217 	public void dirtyStateChanged() {
218 	}
219 
220 	@Override
221 	public void staleStateChanged() {
222 		// // TODO enhance stale state management: workaround to refresh active
223 		// // part when stale state change
224 		// for (IFormPart part : parts) {
225 		// if (part.isStale()) {
226 		// part.refresh();
227 		// }
228 		// }
229 	}
230 
231 	@Override
232 	public Object getContainer() {
233 		return container;
234 	}
235 
236 	@Override
237 	public void setContainer(Object container) {
238 		this.container = container;
239 	}
240 }