1 | /** |
2 | * Copyright 2005-2011 Steve McDuff d-duff@users.sourceforge.net |
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 | package org.deduced.viewer.web.shared; |
17 | |
18 | import java.util.List; |
19 | |
20 | import com.google.gwt.user.client.ui.CellPanel; |
21 | import com.google.gwt.user.client.ui.HorizontalPanel; |
22 | import com.google.gwt.user.client.ui.Label; |
23 | import com.google.gwt.user.client.ui.VerticalPanel; |
24 | import com.google.gwt.user.client.ui.Widget; |
25 | |
26 | /** |
27 | * FlowPanel Model. This model will always contain a horizontal panel as a host |
28 | * to the Flow panel. This is done so that when the Flow panel implementation |
29 | * changes between horizontal and vertical, the correct widget can be rebuilt |
30 | * without notifying the parent tree to add the newly rebuilt widget. |
31 | * |
32 | * @author Steve McDuff |
33 | * |
34 | */ |
35 | @SuppressWarnings("deprecation") |
36 | public class FlowPanelModel extends CellPanelModel |
37 | { |
38 | |
39 | /** |
40 | * serialVersionUID |
41 | */ |
42 | private static final long serialVersionUID = 4758807191823727214L; |
43 | |
44 | /** |
45 | * is the Flow panel vertical or horizontal |
46 | */ |
47 | private boolean vertical; |
48 | |
49 | /** |
50 | * the child widget list |
51 | */ |
52 | private OrderedListModel<OrderedWidgetModel> orderedComponentList; |
53 | |
54 | /** |
55 | * the horizontal alignment |
56 | */ |
57 | private String horizontalAlignment; |
58 | |
59 | /** |
60 | * the vertical alignment |
61 | */ |
62 | private String verticalAlignment; |
63 | |
64 | /** |
65 | * FlowPanelModel constructor |
66 | */ |
67 | public FlowPanelModel() |
68 | { |
69 | |
70 | } |
71 | |
72 | /** |
73 | * set Ordered Component List |
74 | * |
75 | * @param newWidgetList the new component list |
76 | */ |
77 | public void setOrderedComponentList( |
78 | OrderedListModel<OrderedWidgetModel> newWidgetList) |
79 | { |
80 | orderedComponentList = newWidgetList; |
81 | } |
82 | |
83 | /** |
84 | * (non-JSDoc) |
85 | * |
86 | * @see org.deduced.viewer.web.shared.UserInterfaceModel#deleteChildModels() |
87 | */ |
88 | @Override |
89 | protected void deleteChildModels() |
90 | { |
91 | setOrderedComponentList(updateModel(null, getOrderedComponentList(), |
92 | this)); |
93 | super.deleteChildModels(); |
94 | } |
95 | |
96 | /** |
97 | * update Ordered Component List |
98 | * |
99 | * @param newWidgetList the new component list |
100 | */ |
101 | public void updateOrderedComponentList( |
102 | OrderedListModel<OrderedWidgetModel> newWidgetList) |
103 | { |
104 | setOrderedComponentList(updateModel(newWidgetList, |
105 | getOrderedComponentList(), this)); |
106 | synchronizeWithUI(); |
107 | } |
108 | |
109 | /** |
110 | * synchronize Child Widget List |
111 | */ |
112 | private void synchronizeChildWidgetList() |
113 | { |
114 | if (!isUISynchronized()) |
115 | { |
116 | rebuildPanel(); |
117 | } |
118 | } |
119 | |
120 | /** |
121 | * check if the UI is synchronized with the model |
122 | * |
123 | * @return true if the UI is synchronized |
124 | */ |
125 | private boolean isUISynchronized() |
126 | { |
127 | boolean isUISynchronized = true; |
128 | CellPanel cellPanel = getCellPanel(); |
129 | boolean currentIsVertical = false; |
130 | |
131 | currentIsVertical = cellPanel instanceof VerticalPanel; |
132 | |
133 | if (isVertical() != currentIsVertical) |
134 | { |
135 | isUISynchronized = false; |
136 | } |
137 | |
138 | else |
139 | { |
140 | OrderedListModel<OrderedWidgetModel> currentOrderedComponentList = |
141 | getOrderedComponentList(); |
142 | int widgetCount = cellPanel.getWidgetCount(); |
143 | |
144 | if (currentOrderedComponentList == null) |
145 | { |
146 | isUISynchronized = widgetCount == 0; |
147 | } |
148 | else |
149 | { |
150 | List<OrderedWidgetModel> widgetContainerList = |
151 | currentOrderedComponentList.getList(); |
152 | |
153 | isUISynchronized = |
154 | areWidgetsSynchronized(cellPanel, widgetContainerList); |
155 | } |
156 | } |
157 | return isUISynchronized; |
158 | } |
159 | |
160 | /** |
161 | * |
162 | * are Widgets Synchronized |
163 | * |
164 | * @param cellPanel a cell panel containing a list of widgets |
165 | * @param widgetContainerList a model containing a list of widget models |
166 | * @return true if the cell panel contains the same content in the same |
167 | * order as the widget container list. |
168 | */ |
169 | public static boolean areWidgetsSynchronized( |
170 | CellPanel cellPanel, List<OrderedWidgetModel> widgetContainerList) |
171 | { |
172 | boolean isUISynchronized = true; |
173 | |
174 | int expectedWidgetCount = widgetContainerList.size(); |
175 | int widgetCount = cellPanel.getWidgetCount(); |
176 | |
177 | if (widgetCount == expectedWidgetCount) |
178 | { |
179 | for (int i = 0; i < widgetCount; i++) |
180 | { |
181 | Widget currentWidget = cellPanel.getWidget(i); |
182 | OrderedWidgetModel orderedWidgetModel = |
183 | widgetContainerList.get(i); |
184 | WidgetModel widgetModel = orderedWidgetModel.getWidget(); |
185 | |
186 | if (widgetModel != null) |
187 | { |
188 | Widget expectedWidget = widgetModel.getWidget(); |
189 | |
190 | if (currentWidget != expectedWidget) |
191 | { |
192 | isUISynchronized = false; |
193 | break; |
194 | } |
195 | } |
196 | } |
197 | } |
198 | else |
199 | { |
200 | isUISynchronized = false; |
201 | } |
202 | |
203 | return isUISynchronized; |
204 | } |
205 | |
206 | /** |
207 | * rebuild the Panel |
208 | */ |
209 | private void rebuildPanel() |
210 | { |
211 | CellPanel cellPanel = getCellPanel(); |
212 | boolean currentIsVertical = false; |
213 | |
214 | currentIsVertical = cellPanel instanceof VerticalPanel; |
215 | |
216 | boolean finalIsVertical = isVertical(); |
217 | |
218 | boolean isUIObjectUpdateRequired = finalIsVertical != currentIsVertical; |
219 | if (isUIObjectUpdateRequired) |
220 | { |
221 | cellPanel = rebuildFlow(); |
222 | setUIObject(cellPanel); |
223 | } |
224 | |
225 | cellPanel.clear(); |
226 | |
227 | OrderedListModel<OrderedWidgetModel> currentComponentList = |
228 | getOrderedComponentList(); |
229 | if (currentComponentList != null) |
230 | { |
231 | List<OrderedWidgetModel> widgetContainerList = |
232 | currentComponentList.getList(); |
233 | |
234 | for (OrderedWidgetModel orderedWidgetModel : widgetContainerList) |
235 | { |
236 | WidgetModel widgetModel = orderedWidgetModel.getWidget(); |
237 | Widget addWidget = null; |
238 | if (widgetModel != null) |
239 | { |
240 | addWidget = widgetModel.getWidget(); |
241 | } |
242 | |
243 | if (addWidget == null) |
244 | { |
245 | addWidget = new Label(); |
246 | addWidget.setVisible(false); |
247 | } |
248 | cellPanel.add(addWidget); |
249 | } |
250 | } |
251 | |
252 | if (isUIObjectUpdateRequired) |
253 | { |
254 | notifyParentThatModelChanged(); |
255 | } |
256 | } |
257 | |
258 | /** |
259 | * (non-JSDoc) |
260 | * |
261 | * @see org.deduced.viewer.web.shared.CellPanelModel#propertyChanged(org.deduced.viewer.web.shared.ChangeEvent) |
262 | */ |
263 | @SuppressWarnings("unchecked") |
264 | @Override |
265 | public void propertyChanged( |
266 | ChangeEvent event) |
267 | { |
268 | if (isEventNameEqual(event, "horizontal alignment")) |
269 | { |
270 | setHorizontalAlignment((String) event.getSerializableValue()); |
271 | synchronizeWithUI(); |
272 | } |
273 | else if (isEventNameEqual(event, "vertical alignment")) |
274 | { |
275 | setVerticalAlignment((String) event.getSerializableValue()); |
276 | synchronizeWithUI(); |
277 | } |
278 | else if (isEventNameEqual(event, "ordered component list")) |
279 | { |
280 | OrderedListModel<OrderedWidgetModel> updatedList = |
281 | (OrderedListModel<OrderedWidgetModel>) event |
282 | .getSerializableValue(); |
283 | updateOrderedComponentList(updatedList); |
284 | } |
285 | else if (isEventNameEqual(event, "vertical")) |
286 | { |
287 | setVertical(((Boolean) event.getSerializableValue()).booleanValue()); |
288 | synchronizeWithUI(); |
289 | } |
290 | else |
291 | { |
292 | super.propertyChanged(event); |
293 | } |
294 | } |
295 | |
296 | /** |
297 | * @param setHorizontalAlignment the horizontalAlignment to set |
298 | */ |
299 | public void setHorizontalAlignment( |
300 | String setHorizontalAlignment) |
301 | { |
302 | horizontalAlignment = setHorizontalAlignment; |
303 | } |
304 | |
305 | /** |
306 | * @return the horizontalAlignment |
307 | */ |
308 | public String getHorizontalAlignment() |
309 | { |
310 | return horizontalAlignment; |
311 | } |
312 | |
313 | /** |
314 | * @param setVerticalAlignment the verticalAlignment to set |
315 | */ |
316 | public void setVerticalAlignment( |
317 | String setVerticalAlignment) |
318 | { |
319 | verticalAlignment = setVerticalAlignment; |
320 | } |
321 | |
322 | /** |
323 | * @return the verticalAlignment |
324 | */ |
325 | public String getVerticalAlignment() |
326 | { |
327 | return verticalAlignment; |
328 | } |
329 | |
330 | /** |
331 | * @return the orderedComponentList |
332 | */ |
333 | public OrderedListModel<OrderedWidgetModel> getOrderedComponentList() |
334 | { |
335 | return orderedComponentList; |
336 | } |
337 | |
338 | /** |
339 | * (non-JSDoc) |
340 | * |
341 | * @see org.deduced.viewer.web.shared.Model#registerChildModels() |
342 | */ |
343 | @Override |
344 | protected void registerChildModels() |
345 | { |
346 | registerChildModel(getOrderedComponentList(), this); |
347 | |
348 | // super register |
349 | super.registerChildModels(); |
350 | } |
351 | |
352 | /** |
353 | * (non-JSDoc) |
354 | * |
355 | * @see org.deduced.viewer.web.shared.WidgetModel#createUIObject() |
356 | */ |
357 | @Override |
358 | public CellPanel createUIObject() |
359 | { |
360 | return rebuildFlow(); |
361 | } |
362 | |
363 | /** |
364 | * force a rebuild of the Flow panel |
365 | * |
366 | * @return the new Flow panel in use |
367 | */ |
368 | private CellPanel rebuildFlow() |
369 | { |
370 | CellPanel cellPanel = null; |
371 | if (isVertical()) |
372 | { |
373 | cellPanel = new VerticalPanel(); |
374 | } |
375 | else |
376 | { |
377 | cellPanel = new HorizontalPanel(); |
378 | } |
379 | return cellPanel; |
380 | } |
381 | |
382 | /** |
383 | * (non-JSDoc) |
384 | * |
385 | * @see org.deduced.viewer.web.shared.UserInterfaceModel#internalSynchronizeWithUI() |
386 | */ |
387 | @Override |
388 | public void internalSynchronizeWithUI() |
389 | { |
390 | synchronizeChildWidgetList(); |
391 | |
392 | CellPanel cellPanel = getCellPanel(); |
393 | |
394 | if (isVertical()) |
395 | { |
396 | VerticalPanel verticalPanel = (VerticalPanel) cellPanel; |
397 | |
398 | verticalPanel |
399 | .setVerticalAlignment(getVerticalAlignment(getVerticalAlignment())); |
400 | verticalPanel |
401 | .setHorizontalAlignment(getHorizontalAlignment(getHorizontalAlignment())); |
402 | } |
403 | else |
404 | { |
405 | HorizontalPanel horizontalPanel = (HorizontalPanel) cellPanel; |
406 | |
407 | horizontalPanel |
408 | .setVerticalAlignment(getVerticalAlignment(getVerticalAlignment())); |
409 | horizontalPanel |
410 | .setHorizontalAlignment(getHorizontalAlignment(getHorizontalAlignment())); |
411 | } |
412 | |
413 | super.internalSynchronizeWithUI(); |
414 | } |
415 | |
416 | /** |
417 | * @param setVertical the vertical to set |
418 | */ |
419 | public void setVertical( |
420 | boolean setVertical) |
421 | { |
422 | vertical = setVertical; |
423 | } |
424 | |
425 | /** |
426 | * @return the vertical |
427 | */ |
428 | public boolean isVertical() |
429 | { |
430 | return vertical; |
431 | } |
432 | |
433 | } |