1 /*
2  * This file is part of Arduino.
3  *
4  * Copyright 2015 Arduino LLC (http://www.arduino.cc/)
5  *
6  * Arduino is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  */
29 
30 package cc.arduino.contributions.ui;
31 
32 import javax.swing.*;
33 import javax.swing.event.DocumentEvent;
34 import javax.swing.event.DocumentListener;
35 import java.awt.*;
36 import java.awt.event.FocusEvent;
37 import java.awt.event.FocusListener;
38 
39 @SuppressWarnings("serial")
40 public class FilterJTextField extends JTextField {
41   private final String filterHint;
42 
43   private boolean showingHint;
44 
FilterJTextField(String hint)45   public FilterJTextField(String hint) {
46     super(hint);
47     filterHint = hint;
48 
49     showingHint = true;
50     updateStyle();
51 
52     addFocusListener(new FocusListener() {
53       public void focusLost(FocusEvent focusEvent) {
54         if (getText().isEmpty()) {
55           showingHint = true;
56         }
57         updateStyle();
58       }
59 
60       public void focusGained(FocusEvent focusEvent) {
61         if (showingHint) {
62           showingHint = false;
63           setText("");
64         }
65         updateStyle();
66       }
67     });
68 
69     getDocument().addDocumentListener(new DocumentListener() {
70       public void removeUpdate(DocumentEvent e) {
71         applyFilter();
72       }
73 
74       public void insertUpdate(DocumentEvent e) {
75         applyFilter();
76       }
77 
78       public void changedUpdate(DocumentEvent e) {
79         applyFilter();
80       }
81     });
82   }
83 
84   private String lastFilter = "";
85 
applyFilter()86   private void applyFilter() {
87     String filter = showingHint ? "" : getText();
88     filter = filter.toLowerCase();
89 
90     // Replace anything but 0-9, a-z, or : with a space
91     filter = filter.replaceAll("[^\\x30-\\x39^\\x61-\\x7a^\\x3a]", " ");
92 
93     // Fire event only if the filter is changed
94     if (filter.equals(lastFilter))
95       return;
96 
97     lastFilter = filter;
98     onFilter(filter.split(" "));
99   }
100 
onFilter(String[] strings)101   protected void onFilter(String[] strings) {
102     // Empty
103   }
104 
updateStyle()105   private void updateStyle() {
106     if (showingHint) {
107       setText(filterHint);
108       setForeground(Color.gray);
109       setFont(getFont().deriveFont(Font.ITALIC));
110     } else {
111       setForeground(UIManager.getColor("TextField.foreground"));
112       setFont(getFont().deriveFont(Font.PLAIN));
113     }
114   }
115 }
116