1. import com.google.gwt.dom.client.Style.Unit;
  2. import com.google.gwt.event.dom.client.ClickEvent;
  3. import com.google.gwt.event.dom.client.ClickHandler;
  4. import com.google.gwt.event.logical.shared.ValueChangeEvent;
  5. import com.google.gwt.event.logical.shared.ValueChangeHandler;
  6. import com.google.gwt.event.shared.HandlerRegistration;
  7. import com.google.gwt.user.client.ui.FlowPanel;
  8. import com.google.gwt.user.client.ui.FocusPanel;
  9. import com.google.gwt.user.client.ui.FocusWidget;
  10. import com.google.gwt.user.client.ui.HasValue;
  11. import com.google.gwt.user.client.ui.VerticalPanel;
  12. import com.google.gwt.user.client.ui.Widget;
  13. import java.util.ArrayList;
  14. import java.util.HashMap;
  15. import java.util.List;
  16. public class ComboBox<T extends Widget> extends FocusWidget implements
  17. HasValue<T> {
  18. private final List<T> items;
  19. private int selectedIndex = -1;
  20. private final FlowPanel display;
  21. private final PopupPanel popup;
  22. private final VerticalPanel popupListPanel;
  23. private final HashMap<T, FocusPanel> itemToWrapperMap;
  24. public ComboBox() {
  25. items = new ArrayList<T>();
  26. display = new FlowPanel();
  27. popup = new PopupPanel();
  28. popup.getElement().getStyle().setBorderWidth(1, Unit.PX);
  29. popup.getElement().getStyle().setPadding(0, Unit.PX);
  30. popup.setAutoHideEnabled(true);
  31. /*
  32. * Can only be used if you copied PopupPanel source and changed
  33. * visibility
  34. */
  35. // popup.setAnimationType(AnimationType.ROLL_DOWN);
  36. popupListPanel = new VerticalPanel();
  37. popup.add(popupListPanel);
  38. itemToWrapperMap = new HashMap<T, FocusPanel>();
  39. setElement(display.getElement());
  40. addClickHandler(new ClickHandler() {
  41. @Override
  42. public void onClick(final ClickEvent event) {
  43. if (!popup.isShowing()) {
  44. popup.setAnimationEnabled(true);
  45. popup.showRelativeTo(display);
  46. }
  47. }
  48. });
  49. }
  50. public List<T> getItems() {
  51. return items.subList(0, items.size() - 1);
  52. }
  53. public int indexOf(final T item) {
  54. return items.indexOf(item);
  55. }
  56. public int getItemCount() {
  57. return items.size();
  58. }
  59. public T getItem(final int index) {
  60. return items.get(index);
  61. }
  62. public void addItem(final T item) {
  63. items.add(item);
  64. if (selectedIndex == -1) {
  65. setSelectedIndex(items.indexOf(item));
  66. } else {
  67. addPopupItem(item);
  68. }
  69. }
  70. public void removeItem(final T item) {
  71. final int indexOf = items.indexOf(item);
  72. if (indexOf != -1) {
  73. items.remove(item);
  74. removePopupItem(item);
  75. if (indexOf == selectedIndex) {
  76. display.remove(item);
  77. }
  78. }
  79. }
  80. private void addPopupItem(final T item) {
  81. final FocusPanel itemWrapper = new FocusPanel();
  82. itemWrapper.add(item);
  83. itemWrapper.addClickHandler(new ClickHandler() {
  84. @Override
  85. public void onClick(final ClickEvent event) {
  86. popup.setAnimationEnabled(false);
  87. popup.hide();
  88. setValue(item);
  89. }
  90. });
  91. itemToWrapperMap.put(item, itemWrapper);
  92. // Relayout popupPanel (sorted by add order)
  93. popupListPanel.clear();
  94. for (final T i : items) {
  95. final FocusPanel w = itemToWrapperMap.get(i);
  96. if (w != null) {
  97. popupListPanel.add(w);
  98. }
  99. }
  100. }
  101. private void removePopupItem(final T item) {
  102. final FocusPanel itemWrapper = itemToWrapperMap.remove(item);
  103. if (itemWrapper != null) {
  104. popupListPanel.remove(itemWrapper);
  105. }
  106. }
  107. public boolean setSelectedIndex(final int index) {
  108. final T item = items.get(index);
  109. if (item != null) {
  110. final T previous = getSelectedItem();
  111. removePopupItem(item);
  112. if (previous != null) {
  113. previous.removeFromParent();
  114. addPopupItem(previous);
  115. }
  116. selectedIndex = index;
  117. display.add(item);
  118. return true;
  119. }
  120. return false;
  121. }
  122. public void clear() {
  123. // Intentional copy (getItems() creates subList)
  124. for (final T item : getItems()) {
  125. removePopupItem(item);
  126. removeItem(item);
  127. }
  128. }
  129. public T getSelectedItem() {
  130. return getValue();
  131. }
  132. @Override
  133. public HandlerRegistration addValueChangeHandler(
  134. final ValueChangeHandler<T> handler) {
  135. return addHandler(handler, ValueChangeEvent.getType());
  136. }
  137. @Override
  138. public T getValue() {
  139. if (selectedIndex != -1) {
  140. return items.get(selectedIndex);
  141. }
  142. return null;
  143. }
  144. @Override
  145. public void setValue(final T value) {
  146. setValue(value, true);
  147. }
  148. @Override
  149. public void setValue(final T value, final boolean fireEvents) {
  150. if (setSelectedIndex(items.indexOf(value))) {
  151. if (fireEvents) {
  152. fireEvent(new ValueChangeEvent<T>(value) {
  153. });
  154. }
  155. }
  156. }
  157. }

GWT ComboBox for any kind of Widget