TextInputControlMatcherEditor.java
001 /*
002  * Copyright 2014-2016 the original author or authors.
003  *
004  * Licensed under the Apache License, Version 2.0 (the "License");
005  * you may not use this file except in compliance with the License.
006  * You may obtain a copy of the License at
007  *
008  *     http://www.apache.org/licenses/LICENSE-2.0
009  *
010  * Unless required by applicable law or agreed to in writing, software
011  * distributed under the License is distributed on an "AS IS" BASIS,
012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013  * See the License for the specific language governing permissions and
014  * limitations under the License.
015  */
016 package griffon.plugins.glazedlists.javafx.gui;
017 
018 import ca.odell.glazedlists.TextFilterator;
019 import ca.odell.glazedlists.matchers.TextMatcherEditor;
020 import javafx.beans.value.ChangeListener;
021 import javafx.beans.value.ObservableValue;
022 import javafx.event.EventHandler;
023 import javafx.scene.control.TextInputControl;
024 import javafx.scene.input.KeyCode;
025 import javafx.scene.input.KeyEvent;
026 
027 /**
028  @author Andres Almiray
029  @since 1.3.1
030  */
031 public class TextInputControlMatcherEditor<E> extends TextMatcherEditor<E> {
032     private final TextInputControl textInputControl;
033     private boolean live;
034     private final TextHandler textHandler = new TextHandler();
035 
036     public TextInputControlMatcherEditor(TextInputControl textInputControl, TextFilterator<? super E> textFilterator) {
037         this(textInputControl, textFilterator, true);
038     }
039 
040     public TextInputControlMatcherEditor(TextInputControl textInputControl, TextFilterator<? super E> textFilterator, boolean live) {
041         super(textFilterator);
042         this.textInputControl = textInputControl;
043         this.live = live;
044         registerListeners(live);
045         refilter();
046     }
047 
048     public boolean isLive() {
049         return live;
050     }
051 
052     public void setLive(boolean live) {
053         if (live == this.live) { return}
054         deregisterListeners(this.live);
055         this.live = live;
056         registerListeners(this.live);
057     }
058 
059     private void registerListeners(boolean live) {
060         if (live) {
061             textInputControl.textProperty().addListener(textHandler);
062         else {
063             EventHandler<? super KeyEvent> delegate = textInputControl.getOnKeyReleased();
064             KeyHandler keyHandler = new KeyHandler(delegate);
065             textInputControl.setOnKeyReleased(keyHandler);
066 
067         }
068     }
069 
070     private void deregisterListeners(boolean live) {
071         if (live) {
072             textInputControl.textProperty().removeListener(textHandler);
073         else {
074             EventHandler<? super KeyEvent> handler = textInputControl.getOnKeyReleased();
075             if (handler instanceof TextInputControlMatcherEditor.KeyHandler) {
076                 textInputControl.setOnKeyReleased(((TextInputControlMatcherEditor.KeyHandlerhandler).getDelegate());
077             }
078         }
079     }
080 
081     public void dispose() {
082         deregisterListeners(live);
083     }
084 
085     private void refilter() {
086         final int mode = getMode();
087         final String text = textInputControl.getText();
088         final String[] filters;
089 
090         // in CONTAINS mode we treat the string as whitespace delimited
091         if (mode == CONTAINS) { filters = text.split("[ \t]")}
092 
093         // in STARTS_WITH, REGULAR_EXPRESSION, or EXACT modes we use the string in its entirety
094         else if (mode == STARTS_WITH || mode == REGULAR_EXPRESSION || mode == EXACT) {
095             filters = new String[]{text};
096         else throw new IllegalStateException("Unknown mode: " + mode)}
097 
098         setFilterText(filters);
099     }
100 
101     private class TextHandler implements ChangeListener<String> {
102         @Override
103         public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
104             refilter();
105         }
106     }
107 
108     private class KeyHandler extends DelegatingKeyHandler {
109         public KeyHandler(EventHandler<? super KeyEvent> delegate) {
110             super(delegate);
111         }
112 
113         @Override
114         public void handle(KeyEvent event) {
115             if (event.getCode() == KeyCode.ENTER) {
116                 refilter();
117             }
118         }
119     }
120 
121     private static class DelegatingKeyHandler implements EventHandler<KeyEvent> {
122         private EventHandler<? super KeyEvent> delegate;
123 
124         public DelegatingKeyHandler() {
125 
126         }
127 
128         public DelegatingKeyHandler(EventHandler<? super KeyEvent> delegate) {
129             this.delegate = delegate;
130         }
131 
132         @Override
133         public void handle(KeyEvent event) {
134             delegate.handle(event);
135         }
136 
137         protected EventHandler<? super KeyEvent> getDelegate() {
138             return delegate;
139         }
140     }
141 }