Class JComboBox<E>

All Implemented Interfaces:
ActionListener, ImageObserver, ItemSelectable, MenuContainer, Serializable, EventListener, Accessible, ListDataListener, FieldReconciler.Reconcilable

Emulator for JComboBox, rendered by SJComboBox (SD_sjcombobox). R_leaf_peer_lockdown-locked-down: JComboBox is a leaf in the public javax.swing.* hierarchy, so the protected (Component peer) ctor is omitted and the root public ctor hard-codes the surrogate.

The event engine is the JDK's, and it lives here, as it does in the JDK: this combo is its model's ListDataListener, and contentsChanged(ListDataEvent) / intervalAdded(ListDataEvent) / intervalRemoved(ListDataEvent) fire the ItemEvent pair and the ActionEvent. So a worker filling the model hears the events on the worker, and every getter reads the model or a Swing-side field, never the peer. The surrogate listens to the same model and renders it. It keeps its own listener lists for stage-3 code, which this emulator does not subscribe to. A browser pick reaches the model through the surrogate and comes back here as a model event. isPopupVisible() is the one piece of state the browser also changes: setPopupVisible(boolean) writes it and fires the popup events itself, and a user's click reaches it through the surrogate's SJComboBox.addOpenedChangeListener(ComponentEventListener). The ListCellRenderer carve-out (D_jcombobox) is documented on setRenderer(ListCellRenderer).

See Also:
  • Field Details

    • actionCommand

      protected String actionCommand
    • renderer

      protected ListCellRenderer<? super E> renderer
    • dataModel

      protected ComboBoxModel<E> dataModel
    • isEditable

      protected boolean isEditable
    • maximumRowCount

      protected int maximumRowCount
    • selectedItemReminder

      protected Object selectedItemReminder
    • editor

      protected Object editor
    • lightWeightPopupEnabled

      protected boolean lightWeightPopupEnabled
    • keySelectionManager

      protected JComboBox.KeySelectionManager keySelectionManager
  • Constructor Details

    • JComboBox

      public JComboBox()
    • JComboBox

      public JComboBox(ComboBoxModel<E> aModel)
    • JComboBox

      public JComboBox(E[] items)
    • JComboBox

      public JComboBox(Vector<E> items)
  • Method Details

    • reconcileFields

      public final void reconcileFields()
      D_field_write_reconcile repair hook — see JSlider.reconcileFields().
      Specified by:
      reconcileFields in interface FieldReconciler.Reconcilable
    • setSelectedItem

      public void setSelectedItem(Object anObject)
      Selects anObject, rejecting one the model does not contain unless the combo box is editable, and fires the ActionEvent once whether or not the selection changed, as the JDK does. On a match, the model's own element is selected, so an equals-but-not-== argument does not displace it.

      The JDK also hands a matched item to getEditor().setItem; the editor here is inert (see setEditor(Object)), so that step is the declined effect.

    • getSelectedItem

      public Object getSelectedItem()
    • getSelectedIndex

      public int getSelectedIndex()
    • setSelectedIndex

      public void setSelectedIndex(int anIndex)
    • getSelectedObjects

      public Object[] getSelectedObjects()
      Specified by:
      getSelectedObjects in interface ItemSelectable
    • addItem

      public void addItem(E item)
    • insertItemAt

      public void insertItemAt(E item, int index)
    • removeItem

      public void removeItem(Object anObject)
    • removeItemAt

      public void removeItemAt(int anIndex)
    • removeAllItems

      public void removeAllItems()
      The JDK also clears an editable combo's editor; the editor here is inert (see setEditor(Object)), so that step is the declined effect.
    • getItemAt

      public E getItemAt(int index)
    • getItemCount

      public int getItemCount()
    • getModel

      public ComboBoxModel<E> getModel()
    • setModel

      public void setModel(ComboBoxModel<E> aModel)
    • isEditable

      public boolean isEditable()
    • setEditable

      public void setEditable(boolean aFlag)
    • isPopupVisible

      public boolean isPopupVisible()
      Whether the dropdown is open, whether the program or the user opened it.
    • setPopupVisible

      public void setPopupVisible(boolean v)
      Open or close the dropdown. Opening fires popupMenuWillBecomeVisible every time, even on an open dropdown; closing fires popupMenuWillBecomeInvisible only when it was open. Both fire before the state changes.

      The notifications are the Basic L&F's, which every stock L&F inherits: BasicComboPopup.show() fires unconditionally and then asks for getLocationOnScreen(), whose getLocationOnScreen_NoTreeLock throws unless peer != null && isShowing() (message reproduced verbatim), while hide() reaches JPopupMenu.setVisible(false), which returns early on a hidden popup. The hide path never asks for a location, so setPopupVisible(false) stays silent on a combo box that was never shown.

      Throws:
      IllegalComponentStateException - on an opening call for a combo box that is not showing, after popupMenuWillBecomeVisible has fired — the same failure a real JComboBox produces for the same call, per R_match_swing_errors' match-Swing's-error-handling clause.
    • showPopup

      public void showPopup()
    • hidePopup

      public void hidePopup()
    • getMaximumRowCount

      public int getMaximumRowCount()
    • setMaximumRowCount

      public void setMaximumRowCount(int count)
    • addItemListener

      public void addItemListener(ItemListener aListener)
      Specified by:
      addItemListener in interface ItemSelectable
    • removeItemListener

      public void removeItemListener(ItemListener aListener)
      Specified by:
      removeItemListener in interface ItemSelectable
    • getItemListeners

      public ItemListener[] getItemListeners()
    • fireItemStateChanged

      protected void fireItemStateChanged(ItemEvent e)
    • selectedItemChanged

      protected void selectedItemChanged()
      Fires the ItemEvent pair for a selection change: DESELECTED on the old item and SELECTED on the new one, each only when non-null.
    • addActionListener

      public void addActionListener(ActionListener l)
    • removeActionListener

      public void removeActionListener(ActionListener l)
    • getActionListeners

      public ActionListener[] getActionListeners()
    • setActionCommand

      public void setActionCommand(String aCommand)
    • getActionCommand

      public String getActionCommand()
    • fireActionEvent

      protected void fireActionEvent()
      Notifies the ActionListeners last to first, as the JDK does; a listener re-entering it fires nothing.

      The JDK copies the modifiers of EventQueue.getCurrentEvent(); no AWT event is being dispatched here, so they are 0.

    • actionPerformed

      public void actionPerformed(ActionEvent e)
      JDK JComboBox implements ActionListener so it can register itself as the editor's ActionListener for editable combo boxes. The default body fires the combo's own ActionEvent — which is what happens here too.
      Specified by:
      actionPerformed in interface ActionListener
    • addPopupMenuListener

      public void addPopupMenuListener(PopupMenuListener l)
    • removePopupMenuListener

      public void removePopupMenuListener(PopupMenuListener l)
    • getPopupMenuListeners

      public PopupMenuListener[] getPopupMenuListeners()
    • firePopupMenuWillBecomeVisible

      public void firePopupMenuWillBecomeVisible()
    • firePopupMenuWillBecomeInvisible

      public void firePopupMenuWillBecomeInvisible()
    • firePopupMenuCanceled

      public void firePopupMenuCanceled()
      Never reached by SB-Emulators itself; see installOpenedSync(SJComboBox).
    • contentsChanged

      public void contentsChanged(ListDataEvent e)
      The model's selection or contents changed: the ItemEvent pair, then the ActionEvent unless setSelectedItem(Object) is firing it.
      Specified by:
      contentsChanged in interface ListDataListener
    • intervalAdded

      public void intervalAdded(ListDataEvent e)
      An added element can change the selection (a first element becomes selected); no ActionEvent.
      Specified by:
      intervalAdded in interface ListDataListener
    • intervalRemoved

      public void intervalRemoved(ListDataEvent e)
      Specified by:
      intervalRemoved in interface ListDataListener
    • getRenderer

      public ListCellRenderer<? super E> getRenderer()
    • setRenderer

      public void setRenderer(ListCellRenderer<? super E> r)
      Install a JDK-shaped ListCellRenderer on this combo. The bridge wraps the renderer in a Vaadin ComponentRenderer that, per item, calls renderer.getListCellRendererComponent(null, item, index, false, false) and snapshots the resulting emulator component's rendered state into a fresh Vaadin Span before returning it. The snapshot is required because the JDK renderer pattern is mutate-and-return-self: the same JLabel instance is reconfigured and returned on every call. Vaadin's ComponentRenderer requires a fresh Component per item — adopting the same DOM node into multiple positions silently fails on all but the last (only the last assignment "wins"; earlier rows render empty).

      The snapshot covers:

      • Text (always) — read from JLabel.getText() and applied to the fresh Span.
      • Icon (ImageIcon only — Path 1 per D_icon_rendering) — read from JLabel.getIcon() and bridged to a Vaadin Image child via the existing com.vaadin.swingbridge.surrogates.util.Icons.imageIconToVaadinImage. Other Icon impls drop with a WARN (Path 2/3 deferred).

      Limitation: renderer must be JLabel-shaped. DefaultListCellRenderer + subclasses (the typical migration pattern) work directly. Renderers that return a JPanel or other deeper component tree fall back to a Span with String.valueOf(value) and emit a WARN — the JDK mutate-and-return-self contract doesn't generalise to fresh-per-call without per-renderer snapshot logic, and we don't ship one for arbitrary subtrees. R_match_swing_errors sub-bucket (a) gap.

      The list argument is always null, isSelected and cellHasFocus always false — Vaadin's render pipeline doesn't surface those at render time and our combo box doesn't model a JList yet (D_jcombobox). index is reconstructed by scanning the model for the item — O(n) per render, accepted for typical CRUD-shape dropdowns.

    • getAction

      public Action getAction()
    • setAction

      public void setAction(Action a)
    • configurePropertiesFromAction

      protected void configurePropertiesFromAction(Action a)
    • createActionPropertyChangeListener

      protected PropertyChangeListener createActionPropertyChangeListener(Action a)
    • getEditor

      public Object getEditor()
    • setEditor

      public void setEditor(Object anEditor)
      Stores the editor and fires "editor"; the editor is inert. A Vaadin ComboBox renders its own input, so there is no slot to host a ComboBoxEditor's component and no ActionListener rewiring to do — the declined effect. State and notification are owed regardless (R_decline_effect_only, D_owed_events).
    • configureEditor

      public void configureEditor(Object anEditor, Object anItem)
    • getKeySelectionManager

      public JComboBox.KeySelectionManager getKeySelectionManager()
      Returns:
      null unless setKeySelectionManager(JComboBox.KeySelectionManager) installed one, as in the JDK
    • setKeySelectionManager

      public void setKeySelectionManager(JComboBox.KeySelectionManager aManager)
      Stored but never consulted: the JDK reaches a manager only through selectWithKeyChar, which its L&F calls on a keystroke, and here type-to-select is the browser's own — a vaadin-combo-box filters on typing and no keystroke reaches the server as a char. So an installed manager is state whose effect is the browser's, and the WARN says so.
    • isLightWeightPopupEnabled

      public boolean isLightWeightPopupEnabled()
      Returns:
      what setLightWeightPopupEnabled(boolean) stored; Swing's default is true
    • setLightWeightPopupEnabled

      public void setLightWeightPopupEnabled(boolean aFlag)
      Stores the flag and fires "lightWeightPopupEnabled". The distinction it draws — a lightweight in-hierarchy popup vs. a heavyweight native window — has no browser counterpart at all; the overlay is what it is. State and notification are owed regardless (R_decline_effect_only, D_owed_events).
    • getPrototypeDisplayValue

      public E getPrototypeDisplayValue()
    • setPrototypeDisplayValue

      public void setPrototypeDisplayValue(E prototypeDisplayValue)
      Stores the prototype and fires "prototypeDisplayValue"; no sizing happens. The prototype exists to let Swing size the popup from one value instead of measuring every row — a pixel-measurement concern with no counterpart here (R_layouts_close_enough). State and notification are owed regardless (R_decline_effect_only, D_owed_events).
    • selectWithKeyChar

      public boolean selectWithKeyChar(char keyChar)
    • getUIClassID

      public String getUIClassID()
      Overrides:
      getUIClassID in class JComponent
    • updateUI

      public void updateUI()
      Overrides:
      updateUI in class JComponent
    • getUI

      public ComboBoxUI getUI()
      Overrides:
      getUI in class JComponent
    • setUI

      public void setUI(ComboBoxUI ui)
    • getAccessibleContext

      public AccessibleContext getAccessibleContext()
      Specified by:
      getAccessibleContext in interface Accessible
      Overrides:
      getAccessibleContext in class Component