001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Brad Reynolds - bug 116920
011: * Brad Reynolds - bug 160000
012: *******************************************************************************/package org.eclipse.jface.tests.databinding.scenarios;
013:
014: import java.lang.reflect.InvocationTargetException;
015: import java.lang.reflect.Method;
016: import java.util.ArrayList;
017: import java.util.Arrays;
018: import java.util.List;
019: import java.util.Locale;
020:
021: import org.eclipse.core.databinding.beans.BeansObservables;
022: import org.eclipse.core.databinding.observable.Realm;
023: import org.eclipse.core.databinding.observable.list.IObservableList;
024: import org.eclipse.core.databinding.observable.list.WritableList;
025: import org.eclipse.core.databinding.observable.map.IObservableMap;
026: import org.eclipse.core.databinding.observable.value.IObservableValue;
027: import org.eclipse.jface.databinding.swt.SWTObservables;
028: import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
029: import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
030: import org.eclipse.jface.databinding.viewers.ViewersObservables;
031: import org.eclipse.jface.examples.databinding.model.Account;
032: import org.eclipse.jface.examples.databinding.model.Adventure;
033: import org.eclipse.jface.examples.databinding.model.Catalog;
034: import org.eclipse.jface.examples.databinding.model.Lodging;
035: import org.eclipse.jface.examples.databinding.model.SampleData;
036: import org.eclipse.jface.viewers.ComboViewer;
037: import org.eclipse.jface.viewers.ILabelProvider;
038: import org.eclipse.jface.viewers.IStructuredContentProvider;
039: import org.eclipse.jface.viewers.IStructuredSelection;
040: import org.eclipse.jface.viewers.LabelProvider;
041: import org.eclipse.jface.viewers.StructuredSelection;
042: import org.eclipse.swt.SWT;
043: import org.eclipse.swt.custom.CCombo;
044: import org.eclipse.swt.layout.FillLayout;
045: import org.eclipse.swt.widgets.Combo;
046:
047: public class ComboScenarios extends ScenariosTestCase {
048:
049: protected ComboViewer cviewer = null;
050:
051: protected Combo combo = null;
052:
053: protected Catalog catalog = null;
054:
055: ILabelProvider lodgingLabelProvider = new LabelProvider() {
056: public String getText(Object element) {
057: return ((Lodging) element).getName();
058: }
059: };
060:
061: ILabelProvider accountLabelProvider = new LabelProvider() {
062: public String getText(Object element) {
063: return ((Account) element).getCountry();
064: }
065: };
066:
067: protected void setUp() throws Exception {
068: super .setUp();
069: getComposite().setLayout(new FillLayout());
070:
071: combo = new Combo(getComposite(), SWT.READ_ONLY | SWT.DROP_DOWN);
072: cviewer = new ComboViewer(combo);
073:
074: catalog = SampleData.CATALOG_2005; // Lodging source
075: }
076:
077: protected void tearDown() throws Exception {
078: combo.dispose();
079: combo = null;
080: cviewer = null;
081: super .tearDown();
082: }
083:
084: protected Object getViewerSelection() {
085: return ((IStructuredSelection) cviewer.getSelection())
086: .getFirstElement();
087: }
088:
089: /**
090: * @return the ComboViewer's domain object list
091: */
092: protected List getViewerContent(ComboViewer cviewer) {
093: Object[] elements = ((IStructuredContentProvider) cviewer
094: .getContentProvider()).getElements(null);
095: if (elements != null)
096: return Arrays.asList(elements);
097: return null;
098: }
099:
100: /**
101: *
102: * @return the combo's items (String[]), which is the same thing as the
103: * Viewer's labels
104: *
105: */
106: protected List getComboContent() {
107: String[] elements = combo.getItems();
108: if (elements != null)
109: return Arrays.asList(elements);
110: return null;
111: }
112:
113: protected List getColumn(Object[] list, String feature) {
114: List result = new ArrayList();
115: if (list == null || list.length == 0)
116: return result;
117: String getterName = "get"
118: + feature.substring(0, 1).toUpperCase(Locale.ENGLISH)
119: + feature.substring(1);
120: try {
121: Method getter = list[0].getClass().getMethod(getterName,
122: new Class[0]);
123: try {
124: for (int i = 0; i < list.length; i++) {
125: result.add(getter.invoke(list[i], new Object[0]));
126: }
127: } catch (IllegalArgumentException e) {
128: } catch (IllegalAccessException e) {
129: } catch (InvocationTargetException e) {
130: }
131: } catch (SecurityException e) {
132: } catch (NoSuchMethodException e) {
133: }
134: return result;
135: }
136:
137: /**
138: * This test case deal with the 3rd scenario, using vanilla bindings: Ensure
139: * a valid content and selection are bounded correctly Bind a collection of
140: * Lodgings to a ComboViewer Bind the ComboViewer's selection to the
141: * defaultLodging of an Adventure
142: *
143: * This test does not deal with null values, empty content, changed content,
144: * property change of content elements, etc.
145: *
146: */
147: public void test_ROCombo_Scenario03_vanilla() {
148: IObservableList lodgings = BeansObservables.observeList(Realm
149: .getDefault(), catalog, "lodgings");
150: ObservableListContentProvider contentProvider = new ObservableListContentProvider();
151:
152: IObservableMap[] attributeMaps = BeansObservables.observeMaps(
153: contentProvider.getKnownElements(), Lodging.class,
154: new String[] { "name" });
155:
156: // Bind the ComboViewer's content to the available lodging
157: cviewer.setContentProvider(contentProvider);
158: cviewer.setLabelProvider(new ObservableMapLabelProvider(
159: attributeMaps));
160: cviewer.setInput(lodgings);
161:
162: Adventure skiAdventure = SampleData.WINTER_HOLIDAY; // selection will
163:
164: // Ensure that cv's content now has the catalog's lodgings
165: assertArrayEquals(catalog.getLodgings(), getViewerContent(
166: cviewer).toArray());
167:
168: // Ensure that the cv's labels are the same as the lodging descriptions
169: assertEquals(getColumn(catalog.getLodgings(), "name"),
170: getComboContent());
171:
172: getDbc().bindValue(
173: ViewersObservables.observeSingleSelection(cviewer),
174: BeansObservables.observeValue(skiAdventure,
175: "defaultLodging"), null, null);
176:
177: // Check to see that the initial selection is the currentDefault Lodging
178: assertEquals(getViewerSelection(), skiAdventure
179: .getDefaultLodging());
180:
181: // Change the selection of the ComboViewer to all possible lodgings, and
182: // verify that skiAdventure's default lodging was changed accordingly
183: for (int i = 0; i < catalog.getLodgings().length; i++) {
184: Object selection = catalog.getLodgings()[i];
185: cviewer.setSelection(new StructuredSelection(selection));
186: assertEquals(selection, skiAdventure.getDefaultLodging());
187: assertEquals(getViewerSelection(), skiAdventure
188: .getDefaultLodging());
189: }
190:
191: }
192:
193: /**
194: * This test case deal with the 3rd scenario, and focuses on the collection
195: * binding to the combo. It will bind a collection, add/remove/change
196: * elements in the collection, and change element's properties to ensure
197: * that the combo's labels were updated appropriatly.
198: *
199: * it also induce null values in properties, and elments.
200: *
201: * This test does not deal with the combo's selection.
202: */
203: public void test_ROCombo_Scenario03_collectionBindings() {
204: // column binding
205: // Bind the ComboViewer's content to the available lodging
206: IObservableList lodgings = BeansObservables.observeList(Realm
207: .getDefault(), catalog, "lodgings");
208: ObservableListContentProvider contentProvider = new ObservableListContentProvider();
209:
210: IObservableMap[] attributeMaps = BeansObservables.observeMaps(
211: contentProvider.getKnownElements(), Lodging.class,
212: new String[] { "name" });
213:
214: cviewer.setContentProvider(contentProvider);
215: cviewer.setLabelProvider(new ObservableMapLabelProvider(
216: attributeMaps));
217: cviewer.setInput(lodgings);
218:
219: // Ensure that cv's content now has the catalog's lodgings
220: assertArrayEquals(catalog.getLodgings(), getViewerContent(
221: cviewer).toArray());
222:
223: // Ensure that the cv's labels are the same as the lodging descriptions
224: assertEquals(getColumn(catalog.getLodgings(), "name"),
225: getComboContent());
226:
227: // Add a lodging in the middle (not supported by the model right now)
228: // Lodging lodging = SampleData.FACTORY.createLodging();
229: // lodging.setName("Middle Lodging");
230: // catalog.addLodging(lodging);
231: // assertEquals(getViewerContent(cviewer).get(2), lodging);
232:
233: // Add a lodging at the end
234: Lodging lodging = SampleData.FACTORY.createLodging();
235: lodging.setName("End Lodging");
236: catalog.addLodging(lodging);
237: int index = getComboContent().size() - 1;
238: assertEquals(getViewerContent(cviewer).get(index), lodging);
239:
240: // Delete the first Lodging
241: catalog.removeLodging(catalog.getLodgings()[0]);
242: // Ensure that the cv's labels are the same as the lodging descriptions
243: assertEquals(getColumn(catalog.getLodgings(), "name"),
244: getComboContent());
245:
246: // Delete middle Lodging
247: catalog.removeLodging(catalog.getLodgings()[2]);
248: // Ensure that the cv's labels are the same as the lodging descriptions
249: assertEquals(getColumn(catalog.getLodgings(), "name"),
250: getComboContent());
251:
252: // Change the names of all Lodging
253: for (int i = 0; i < catalog.getLodgings().length; i++) {
254: Lodging l = catalog.getLodgings()[i];
255: l.setName("Changed: " + l.getName());
256: }
257: spinEventLoop(0); // force Async. efforts
258: assertEquals(getColumn(catalog.getLodgings(), "name"),
259: getComboContent());
260:
261: // Set to null value
262: Lodging l = catalog.getLodgings()[0];
263: assertEquals(combo.getItem(0), l.getName());
264: l.setName(null);
265: assertEquals("", combo.getItem(0));
266:
267: // set to empty list
268: while (catalog.getLodgings().length > 0) {
269: catalog.removeLodging(catalog.getLodgings()[0]);
270: assertEquals(getColumn(catalog.getLodgings(), "name"),
271: getComboContent());
272: }
273: }
274:
275: /**
276: * This scenario tests a simple SWT combo with a set item list where the
277: * selection is bouded to a String property
278: */
279: // public void test_ROCombo_Scenario01() {
280: //
281: // // Read-Only Combo will not change its text property on a call to
282: // // setText()
283: //
284: // String[] items = new String[] { "FairyLand", "TuneLand", "NoWereLand",
285: // "TinkerLand", "DreamLand" };
286: // combo.setItems(items);
287: // Account account = catalog.getAccounts()[0];
288: //
289: // // simple Combo's selection bound to the Account's country property
290: // getDbc().bind(new Property(combo, SWTProperties.SELECTION),
291: // new Property(account, "country"), null);
292: //
293: // // Drive the combo selection
294: // int index = 3;
295: // combo.setText(items[index]); // this should drive the selection
296: // assertEquals(account.getCountry(), items[index]);
297: //
298: // // Set the country, and ensure selection is set property
299: // index = 1;
300: // account.setCountry(items[index]);
301: // assertEquals(index, combo.getSelectionIndex());
302: // assertEquals(combo.getText(), items[index]);
303: //
304: // index = combo.getSelectionIndex();
305: // String txt = combo.getText();
306: // // Set the country to something that is not in the Combo's list
307: // account.setCountry("FooBar");
308: // // Combo's selection will not Change
309: // assertEquals(combo.getSelectionIndex(), index);
310: // assertEquals(combo.getText(), txt);
311: //
312: // }
313: /**
314: * This scenario tests a simple SWT combo that is bound to a list of Country
315: * objects. The Country object's name property is listed in the Combo.
316: *
317: * The Combo's selection is bounded to the Country property of an Account.
318: */
319: // public void test_ROCombo_Scenario02_SWTCombo() {
320: //
321: // // Create a list of Strings for the countries
322: // IObservableList list = new WritableList();
323: // for (int i = 0; i < catalog.getAccounts().length; i++)
324: // list.add(catalog.getAccounts()[i].getCountry());
325: //
326: // // Bind the combo's content to that of the String based list
327: // getDbc().bind(combo, list, null);
328: // assertEquals(Arrays.asList(combo.getItems()), list);
329: //
330: // Account account = catalog.getAccounts()[0];
331: //
332: // // simple Combo's selection bound to the Account's country property
333: // getDbc().bind(new Property(combo, SWTProperties.SELECTION),
334: // new Property(account, "country"), null);
335: //
336: // // Drive the combo selection
337: // String selection = (String) list.get(2);
338: // combo.setText(selection); // this should drive the selection
339: // assertEquals(account.getCountry(), selection);
340: //
341: // }
342: /**
343: * This scenario tests a simple SWT combo that is bound to a list of Country
344: * objects. The Country object's name property is listed in the Combo.
345: *
346: * The Combo's selection is bounded to the Country property of an Account.
347: */
348: // public void test_ROCombo_Scenario02_ComboViewer() {
349: //
350: // // Account label provider will fill the combo with the country
351: // cviewer.setLabelProvider(accountLabelProvider);
352: // // Bind the ComboViewer's content to the available accounts
353: // getDbc().bind(
354: // cviewer,
355: // new ListModelDescription(new Property(catalog, "accounts"),
356: // "country"), null);
357: //
358: // // Ensure that cv's content now has the catalog's accounts
359: // assertArrayEquals(catalog.getAccounts(), getViewerContent(cviewer)
360: // .toArray());
361: // // Ensure that the cv's labels are the same as the account countries
362: // assertEquals(getColumn(catalog.getAccounts(), "country"),
363: // getComboContent());
364: //
365: // Account account = SampleData.FACTORY.createAccount();
366: //
367: // // Use the Viewers visual Combo (Strings) to set the account's country
368: // getDbc().bind(new Property(combo, SWTProperties.SELECTION),
369: // new Property(account, "country"), null);
370: //
371: // // Change the selection of the ComboViewer to all possible accounts, and
372: // // verify that the account's Country is being changed correctly.
373: // for (int i = 0; i < catalog.getAccounts().length; i++) {
374: // Account selection = catalog.getAccounts()[i];
375: // cviewer.setSelection(new StructuredSelection(selection));
376: // assertEquals(selection.getCountry(), account.getCountry());
377: // }
378: //
379: // }
380: /**
381: * This test ensure that multiple combos can be bound to the same deomain
382: * model
383: */
384: public void test_ROCombo_multipleBindings() {
385: Adventure skiAdventure = SampleData.WINTER_HOLIDAY; // for selection
386:
387: // Bind the ComboViewer's content to the available lodging
388: IObservableList lodgings = BeansObservables.observeList(Realm
389: .getDefault(), catalog, "lodgings");
390: ObservableListContentProvider contentProvider = new ObservableListContentProvider();
391:
392: IObservableMap[] attributeMaps = BeansObservables.observeMaps(
393: contentProvider.getKnownElements(), Lodging.class,
394: new String[] { "name" });
395:
396: cviewer.setContentProvider(contentProvider);
397: cviewer.setLabelProvider(new ObservableMapLabelProvider(
398: attributeMaps));
399: cviewer.setInput(lodgings);
400:
401: // Ensure that cv's content now has the catalog's lodgings
402: assertArrayEquals(catalog.getLodgings(), getViewerContent(
403: cviewer).toArray());
404:
405: // Ensure that the cv's labels are the same as the lodging descriptions
406: assertEquals(getColumn(catalog.getLodgings(), "name"),
407: getComboContent());
408:
409: ComboViewer otherViewer = new ComboViewer(getComposite(),
410: SWT.NONE);
411: lodgings = BeansObservables.observeList(Realm.getDefault(),
412: catalog, "lodgings");
413: contentProvider = new ObservableListContentProvider();
414:
415: attributeMaps = BeansObservables.observeMaps(contentProvider
416: .getKnownElements(), Lodging.class,
417: new String[] { "name" });
418:
419: otherViewer.setContentProvider(contentProvider);
420: otherViewer.setLabelProvider(new ObservableMapLabelProvider(
421: attributeMaps));
422: otherViewer.setInput(lodgings);
423:
424: // Ensure that cv's content now has the catalog's lodgings
425: assertArrayEquals(catalog.getLodgings(), getViewerContent(
426: otherViewer).toArray());
427:
428: // Bind both selections to the same thing
429: IObservableValue selection = ViewersObservables
430: .observeSingleSelection(cviewer);
431: getDbc().bindValue(
432: selection,
433: BeansObservables.observeValue(skiAdventure,
434: "defaultLodging"), null, null);
435:
436: IObservableValue otherSelection = ViewersObservables
437: .observeSingleSelection(otherViewer);
438: getDbc().bindValue(
439: otherSelection,
440: BeansObservables.observeValue(skiAdventure,
441: "defaultLodging"), null, null);
442:
443: Lodging lodging = catalog.getLodgings()[0];
444:
445: // Ensure that setting the selection is driven forward to the other
446: // combo
447: cviewer.setSelection(new StructuredSelection(lodging));
448: assertEquals(((IStructuredSelection) cviewer.getSelection())
449: .getFirstElement(), ((IStructuredSelection) otherViewer
450: .getSelection()).getFirstElement());
451:
452: // Change the list of one combo, and ensure it updates the other combo
453: catalog.removeLodging(lodging);
454: assertEquals(getViewerContent(cviewer),
455: getViewerContent(otherViewer));
456:
457: }
458:
459: /**
460: * This scenario tests a simple SWT CCombo that is bound to a list of
461: * Country objects. The Country object's name property is listed in the
462: * Combo.
463: *
464: * The Combo's selection is bounded to the Country property of an Account.
465: */
466: public void test_ROCombo_SWTCCombo() {
467:
468: // Create a list of Strings for the countries
469: IObservableList list = new WritableList();
470: for (int i = 0; i < catalog.getAccounts().length; i++)
471: list.add(catalog.getAccounts()[i].getCountry());
472:
473: CCombo ccombo = new CCombo(getComposite(), SWT.READ_ONLY
474: | SWT.DROP_DOWN);
475:
476: // Bind the combo's content to that of the String based list
477: getDbc().bindList(SWTObservables.observeItems(ccombo), list,
478: null, null);
479: assertEquals(Arrays.asList(ccombo.getItems()), list);
480:
481: Account account = catalog.getAccounts()[0];
482:
483: // simple Combo's selection bound to the Account's country property
484: IObservableValue comboSelection = SWTObservables
485: .observeSelection(ccombo);
486: getDbc().bindValue(comboSelection,
487: BeansObservables.observeValue(account, "country"),
488: null, null);
489:
490: // Drive the combo selection
491: String selection = (String) list.get(2);
492: ccombo.setText(selection); // this should drive the selection
493: assertEquals(account.getCountry(), selection);
494:
495: }
496:
497: /**
498: * This scenario tests a simple SWT CCombo that is bound to a list of
499: * Country objects. The Country object's name property is listed in the
500: * Combo.
501: *
502: * The Combo's selection is bounded to the Country property of an Account.
503: */
504: public void test_WCombo_SWTCCombo() {
505:
506: // Create a list of Strings for the countries
507: IObservableList list = new WritableList();
508: for (int i = 0; i < catalog.getAccounts().length; i++)
509: list.add(catalog.getAccounts()[i].getCountry());
510:
511: CCombo ccombo = new CCombo(getComposite(), SWT.READ_ONLY
512: | SWT.DROP_DOWN);
513:
514: // Bind the combo's content to that of the String based list
515: getDbc().bindList(SWTObservables.observeItems(ccombo), list,
516: null, null);
517: assertEquals(Arrays.asList(ccombo.getItems()), list);
518:
519: Account account = catalog.getAccounts()[0];
520:
521: // simple Combo's selection bound to the Account's country property
522: IObservableValue comboSelection = SWTObservables
523: .observeSelection(ccombo);
524: getDbc().bindValue(comboSelection,
525: BeansObservables.observeValue(account, "country"),
526: null, null);
527:
528: // Drive the combo selection
529: String selection = (String) list.get(2);
530: ccombo.setText(selection); // this should drive the selection
531: assertEquals(account.getCountry(), selection);
532:
533: selection = (String) list.get(1);
534: account.setCountry(selection);
535: assertEquals(selection, ccombo.getItem(ccombo
536: .getSelectionIndex()));
537: assertEquals(selection, ccombo.getText());
538:
539: selection = "country not in list";
540: account.setCountry(selection);
541: assertEquals(-1, ccombo.getSelectionIndex());
542: assertEquals(selection, ccombo.getText());
543: }
544:
545: /**
546: * This scenario tests a simple SWT CCombo that is bound to a list of
547: * Country objects. The Country object's name property is listed in the
548: * Combo.
549: *
550: * The Combo's selection is bounded to the Country property of an Account.
551: */
552: public void test_ROCombo_SWTList() {
553:
554: // Create a list of Strings for the countries
555: IObservableList list = new WritableList();
556: for (int i = 0; i < catalog.getAccounts().length; i++)
557: list.add(catalog.getAccounts()[i].getCountry());
558:
559: org.eclipse.swt.widgets.List swtlist = new org.eclipse.swt.widgets.List(
560: getComposite(), SWT.READ_ONLY | SWT.SINGLE);
561:
562: // Bind the combo's content to that of the String based list
563: getDbc().bindList(SWTObservables.observeItems(swtlist), list,
564: null, null);
565: assertEquals(Arrays.asList(swtlist.getItems()), list);
566:
567: Account account = catalog.getAccounts()[0];
568:
569: // simple Combo's selection bound to the Account's country property
570: IObservableValue listSelection = SWTObservables
571: .observeSelection(swtlist);
572: getDbc().bindValue(listSelection,
573: BeansObservables.observeValue(account, "country"),
574: null, null);
575:
576: String selection = (String) list.get(2);
577: swtlist.select(2); // this should drive the selection
578: swtlist.notifyListeners(SWT.Selection, null); // Force notification
579: assertEquals(account.getCountry(), selection);
580:
581: }
582:
583: }
|