package example;
//-*- mode:java; encoding:utf-8 -*-
// vim:set fileencoding=utf-8:
//@homepage@
import java.awt.*;
import java.awt.event.FocusEvent;
import java.util.Objects;
import javax.swing.*;

public final class MainPanel extends JPanel {
    private MainPanel() {
        super(new BorderLayout());
        JPanel p = new JPanel(new GridLayout(4, 1, 5, 5));
        setBorder(BorderFactory.createEmptyBorder(5, 20, 5, 20));
        p.add(new JLabel("Default JComboBox"));
        p.add(new JComboBox<>(new String[] {"Google", "Yahoo!", "Bing"}));
        p.add(new JLabel("SearchBar JComboBox"));

        DefaultComboBoxModel<SearchEngine> model = new SearchEngineComboBoxModel<>();
        model.addElement(new SearchEngine("Google", "http://www.google.com/", new ImageIcon(getClass().getResource("google.png"))));
        model.addElement(new SearchEngine("Yahoo!", "http://www.yahoo.com/", new ImageIcon(getClass().getResource("yahoo.png"))));
        model.addElement(new SearchEngine("Bing", "http://www.bing.com/", new ImageIcon(getClass().getResource("bing.png"))));

        JComboBox<SearchEngine> combo = new JSearchBar(model);
        combo.getEditor().setItem("java swing");

//         JComboBox combo = new JComboBox(model);
//         combo.setUI(new BasicSearchBarComboBoxUI());
//         EventQueue.invokeLater(new Runnable() {
//             @Override public void run() {
//                 SearchEngine se = combo.getItemAt(0);
//                 JButton arrowButton = (JButton) combo.getComponent(0);
//                 arrowButton.setIcon(se.favicon);
//                 combo.getEditor().setItem("java swing");
//             }
//         });

        p.add(combo);
        // p.add(new SearchBarComboBox(makeModel()));
        add(p, BorderLayout.NORTH);
        setPreferredSize(new Dimension(320, 240));
    }
    public static void main(String... args) {
        EventQueue.invokeLater(new Runnable() {
            @Override public void run() {
                createAndShowGUI();
            }
        });
    }
    public static void createAndShowGUI() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            UIManager.put("example.SearchBarComboBox", "SearchBarComboBoxUI");
            UIManager.put("SearchBarComboBoxUI", "example.BasicSearchBarComboBoxUI");
        } catch (ClassNotFoundException | InstantiationException
               | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            ex.printStackTrace();
        }
        JFrame frame = new JFrame("@title@");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().add(new MainPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

class SearchEngine {
    public final String name;
    public final String url;
    public final ImageIcon favicon;
    protected SearchEngine(String name, String url, ImageIcon icon) {
        this.name = name;
        this.url = url;
        this.favicon = icon;
    }
    @Override public String toString() {
        return name;
    }
}

class SearchEngineComboBoxModel<E extends SearchEngine> extends DefaultComboBoxModel<E> {
    @Override public void setSelectedItem(Object anObject) {
        // System.out.println("model: " + anObject);
    }
}

class JSearchBar extends JComboBox<SearchEngine> {
    private static final String UI_CLASS_ID = "SearchBarComboBoxUI";
    @Override public String getUIClassID() {
        return UI_CLASS_ID;
    }
    @Override public SearchBarComboBoxUI getUI() {
        return (SearchBarComboBoxUI) ui;
    }
//     @Override public void setUI(SearchBarComboBoxUI newUI) {
//         super.setUI(newUI);
//     }
    @Override public void updateUI() {
        super.updateUI();
        if (Objects.nonNull(UIManager.get(getUIClassID()))) {
            setUI((SearchBarComboBoxUI) UIManager.getUI(this));
        } else {
            setUI(new BasicSearchBarComboBoxUI());
        }
        UIManager.put("ComboBox.font", getFont()); // XXX: ???
        JButton arrowButton = (JButton) getComponent(0);
        SearchEngine se = getItemAt(0);
        if (Objects.nonNull(se)) {
            arrowButton.setIcon(se.favicon);
        }
//         ListCellRenderer renderer = getRenderer();
//         if (renderer instanceof Component) {
//             SwingUtilities.updateComponentTreeUI((Component) renderer);
//         }
    }
//     protected JSearchBar() {
//         super();
//         setModel(new DefaultComboBoxModel<>());
//         init();
//     }
    protected JSearchBar(ComboBoxModel<SearchEngine> model) {
        super(model);
        // setModel(model);
        // init();
    }
    protected JSearchBar(SearchEngine... items) {
        super(items);
        // setModel(new DefaultComboBoxModel<>(items));
        // init();
    }
//     protected JSearchBar(Vector<?> items) {
//         super();
//         setModel(new DefaultComboBoxModel(items));
//         init();
//     }
//     private void init() {
//         installAncestorListener();
//         // setUIProperty("opaque", true);
//         updateUI();
//     }
    @Override protected void processFocusEvent(FocusEvent e) {
        System.out.println("processFocusEvent");
    }
}

@@ -1130,16 +1130,18 @@
 earchBar
+%3C%3E
 (model);
@@ -3383,16 +3383,18 @@
 earchBar
+%3CE
  extends
@@ -3394,26 +3394,16 @@
 extends 
-JComboBox%3C
 SearchEn
@@ -3407,16 +3407,37 @@
 hEngine%3E
+ extends JComboBox%3CE%3E
  %7B%0A    p
@@ -4327,16 +4327,38 @@
 Renderer
+%3C? super SearchEngine%3E
  rendere
@@ -4684,36 +4684,25 @@
 mboBoxModel%3C
-SearchEngine
+E
 %3E model) %7B%0A 
@@ -4771,24 +4771,27 @@
 it();%0A    %7D%0A
+// 
     protecte
@@ -4803,28 +4803,17 @@
 archBar(
-SearchEngine
+E
 ... item
@@ -4813,24 +4813,27 @@
 .. items) %7B%0A
+// 
         supe
@@ -4842,16 +4842,19 @@
 items);%0A
+// 
         
@@ -4897,24 +4897,27 @@
 %3C%3E(items));%0A
+// 
         // i
@@ -4915,32 +4915,35 @@
      // init();%0A
+// 
     %7D%0A//     pro

use bounded type parameter instead of actual type parameter