99
1010import javax .swing .undo .UndoManager ;
1111
12- import javafx .application .Platform ;
1312import javafx .beans .binding .Bindings ;
1413import javafx .beans .binding .BooleanBinding ;
1514import javafx .beans .property .BooleanProperty ;
1615import javafx .beans .property .SimpleBooleanProperty ;
1716import javafx .collections .ListChangeListener ;
18- import javafx .collections .ObservableList ;
17+ import javafx .collections .SetChangeListener ;
1918import javafx .css .PseudoClass ;
2019import javafx .event .Event ;
2120import javafx .geometry .Insets ;
5554import org .jabref .gui .keyboard .KeyBindingRepository ;
5655import org .jabref .gui .search .rules .describer .SearchDescribers ;
5756import org .jabref .gui .util .BindingsHelper ;
58- import org .jabref .gui .util .IconValidationDecorator ;
5957import org .jabref .gui .util .OptionalObjectProperty ;
6058import org .jabref .gui .util .TooltipTextUtil ;
6159import org .jabref .gui .util .UiTaskExecutor ;
6664import org .jabref .preferences .PreferencesService ;
6765import org .jabref .preferences .SearchPreferences ;
6866
69- import de .saxsys .mvvmfx .utils .validation .FunctionBasedValidator ;
70- import de .saxsys .mvvmfx .utils .validation .ValidationMessage ;
71- import de .saxsys .mvvmfx .utils .validation .Validator ;
72- import de .saxsys .mvvmfx .utils .validation .visualization .ControlsFxVisualizer ;
7367import impl .org .controlsfx .skin .AutoCompletePopup ;
7468import org .controlsfx .control .textfield .AutoCompletionBinding ;
7569import org .controlsfx .control .textfield .CustomTextField ;
@@ -99,7 +93,6 @@ public class GlobalSearchBar extends HBox {
9993
10094 private final StateManager stateManager ;
10195 private final PreferencesService preferencesService ;
102- private final Validator regexValidator ;
10396 private final UndoManager undoManager ;
10497 private final LibraryTabContainer tabContainer ;
10598
@@ -145,32 +138,22 @@ public GlobalSearchBar(LibraryTabContainer tabContainer,
145138
146139 searchField .addEventFilter (KeyEvent .KEY_PRESSED , event -> {
147140 if (keyBindingRepository .matches (event , KeyBinding .CLEAR_SEARCH )) {
148- // Clear search and select first entry, if available
149141 searchField .clear ();
150142 if (searchType == SearchType .NORMAL_SEARCH ) {
151- tabContainer .getCurrentLibraryTab ().getMainTable ().getSelectionModel (). selectFirst ();
143+ tabContainer .getCurrentLibraryTab ().getMainTable ().requestFocus ();
152144 }
153145 event .consume ();
154146 }
155147 });
156148
157- searchField .setContextMenu (SearchFieldRightClickMenu .create (
158- stateManager ,
159- searchField ,
160- tabContainer ,
161- undoManager ));
162-
163- ObservableList <String > search = stateManager .getWholeSearchHistory ();
164- search .addListener ((ListChangeListener .Change <? extends String > change ) ->
165- searchField .setContextMenu (SearchFieldRightClickMenu .create (
166- stateManager ,
167- searchField ,
168- tabContainer ,
169- undoManager ))
170- );
171-
172149 ClipBoardManager .addX11Support (searchField );
173150
151+ searchField .setContextMenu (SearchFieldRightClickMenu .create (stateManager , searchField ));
152+ stateManager .getWholeSearchHistory ().addListener ((ListChangeListener .Change <? extends String > change ) -> {
153+ searchField .getContextMenu ().getItems ().removeLast ();
154+ searchField .getContextMenu ().getItems ().add (SearchFieldRightClickMenu .createSearchFromHistorySubMenu (stateManager , searchField ));
155+ });
156+
174157 regularExpressionButton = IconTheme .JabRefIcons .REG_EX .asToggleButton ();
175158 caseSensitiveButton = IconTheme .JabRefIcons .CASE_SENSITIVE .asToggleButton ();
176159 fulltextButton = IconTheme .JabRefIcons .FULLTEXT .asToggleButton ();
@@ -184,8 +167,7 @@ public GlobalSearchBar(LibraryTabContainer tabContainer,
184167 .or (caseSensitiveButton .focusedProperty ())
185168 .or (fulltextButton .focusedProperty ())
186169 .or (keepSearchString .focusedProperty ())
187- .or (searchField .textProperty ()
188- .isNotEmpty ());
170+ .or (searchField .textProperty ().isNotEmpty ());
189171
190172 regularExpressionButton .visibleProperty ().unbind ();
191173 regularExpressionButton .visibleProperty ().bind (focusedOrActive );
@@ -205,18 +187,10 @@ public GlobalSearchBar(LibraryTabContainer tabContainer,
205187
206188 modifierButtons .setAlignment (Pos .CENTER );
207189 searchField .setRight (new HBox (searchField .getRight (), modifierButtons ));
208- searchField .getStyleClass ().add ("search-field " );
190+ searchField .getStyleClass ().add ("global- search-bar " );
209191 searchField .setMinWidth (100 );
210192 HBox .setHgrow (searchField , Priority .ALWAYS );
211193
212- regexValidator = new FunctionBasedValidator <>(
213- searchField .textProperty (),
214- query -> !(regularExpressionButton .isSelected () && !validRegex ()),
215- ValidationMessage .error (Localization .lang ("Invalid regular expression" )));
216- ControlsFxVisualizer visualizer = new ControlsFxVisualizer ();
217- visualizer .setDecoration (new IconValidationDecorator (Pos .CENTER_LEFT ));
218- Platform .runLater (() -> visualizer .initVisualization (regexValidator .getValidationStatus (), searchField ));
219-
220194 if (searchType == SearchType .NORMAL_SEARCH ) {
221195 this .getChildren ().addAll (searchField , openGlobalSearchButton , currentResults );
222196 } else {
@@ -261,52 +235,64 @@ private void initSearchModifierButtons() {
261235 regularExpressionButton .setSelected (searchPreferences .isRegularExpression ());
262236 regularExpressionButton .setTooltip (new Tooltip (Localization .lang ("regular expression" )));
263237 initSearchModifierButton (regularExpressionButton );
264- regularExpressionButton .setOnAction ( event -> {
265- searchPreferences .setSearchFlag (SearchRules .SearchFlags .REGULAR_EXPRESSION , regularExpressionButton . isSelected () );
238+ regularExpressionButton .selectedProperty (). addListener (( obs , oldVal , newVal ) -> {
239+ searchPreferences .setSearchFlag (SearchRules .SearchFlags .REGULAR_EXPRESSION , newVal );
266240 updateSearchQuery ();
267241 });
268242
269243 caseSensitiveButton .setSelected (searchPreferences .isCaseSensitive ());
270244 caseSensitiveButton .setTooltip (new Tooltip (Localization .lang ("Case sensitive" )));
271245 initSearchModifierButton (caseSensitiveButton );
272- caseSensitiveButton .setOnAction ( event -> {
273- searchPreferences .setSearchFlag (SearchRules .SearchFlags .CASE_SENSITIVE , caseSensitiveButton . isSelected () );
246+ caseSensitiveButton .selectedProperty (). addListener (( obs , oldVal , newVal ) -> {
247+ searchPreferences .setSearchFlag (SearchRules .SearchFlags .CASE_SENSITIVE , newVal );
274248 updateSearchQuery ();
275249 });
276250
277251 fulltextButton .setSelected (searchPreferences .isFulltext ());
278252 fulltextButton .setTooltip (new Tooltip (Localization .lang ("Fulltext search" )));
279253 initSearchModifierButton (fulltextButton );
280- fulltextButton .setOnAction ( event -> {
281- searchPreferences .setSearchFlag (SearchRules .SearchFlags .FULLTEXT , fulltextButton . isSelected () );
254+ fulltextButton .selectedProperty (). addListener (( obs , oldVal , newVal ) -> {
255+ searchPreferences .setSearchFlag (SearchRules .SearchFlags .FULLTEXT , newVal );
282256 updateSearchQuery ();
283257 });
284258
285259 keepSearchString .setSelected (searchPreferences .shouldKeepSearchString ());
286260 keepSearchString .setTooltip (new Tooltip (Localization .lang ("Keep search string across libraries" )));
287261 initSearchModifierButton (keepSearchString );
288- keepSearchString .setOnAction ( evt -> {
289- searchPreferences .setSearchFlag (SearchRules .SearchFlags .KEEP_SEARCH_STRING , keepSearchString . isSelected () );
262+ keepSearchString .selectedProperty (). addListener (( obs , oldVal , newVal ) -> {
263+ searchPreferences .setSearchFlag (SearchRules .SearchFlags .KEEP_SEARCH_STRING , newVal );
290264 updateSearchQuery ();
291265 });
292266
293267 openGlobalSearchButton .disableProperty ().bindBidirectional (globalSearchActive );
294268 openGlobalSearchButton .setTooltip (new Tooltip (Localization .lang ("Search across libraries in a new window" )));
295269 initSearchModifierButton (openGlobalSearchButton );
296- openGlobalSearchButton .setOnAction (evt -> {
297- globalSearchActive .setValue (true );
298- if (globalSearchResultDialog == null ) {
299- globalSearchResultDialog = new GlobalSearchResultDialog (undoManager , tabContainer );
300- }
301- stateManager .activeGlobalSearchQueryProperty ().setValue (searchQueryProperty .get ());
302- updateSearchQuery ();
303- dialogService .showCustomDialogAndWait (globalSearchResultDialog );
304- globalSearchActive .setValue (false );
270+ openGlobalSearchButton .setOnAction (evt -> openGlobalSearchDialog ());
271+
272+ searchPreferences .getObservableSearchFlags ().addListener ((SetChangeListener .Change <? extends SearchRules .SearchFlags > change ) -> {
273+ regularExpressionButton .setSelected (searchPreferences .isRegularExpression ());
274+ caseSensitiveButton .setSelected (searchPreferences .isCaseSensitive ());
275+ fulltextButton .setSelected (searchPreferences .isFulltext ());
276+ keepSearchString .setSelected (searchPreferences .shouldKeepSearchString ());
305277 });
306278 }
307279
280+ public void openGlobalSearchDialog () {
281+ if (globalSearchActive .get ()) {
282+ return ;
283+ }
284+ globalSearchActive .setValue (true );
285+ if (globalSearchResultDialog == null ) {
286+ globalSearchResultDialog = new GlobalSearchResultDialog (undoManager , tabContainer );
287+ }
288+ stateManager .activeGlobalSearchQueryProperty ().setValue (searchQueryProperty .get ());
289+ updateSearchQuery ();
290+ dialogService .showCustomDialogAndWait (globalSearchResultDialog );
291+ globalSearchActive .setValue (false );
292+ }
293+
308294 private void initSearchModifierButton (ButtonBase searchButton ) {
309- searchButton .setCursor (Cursor .DEFAULT );
295+ searchButton .setCursor (Cursor .HAND );
310296 searchButton .setMinHeight (28 );
311297 searchButton .setMaxHeight (28 );
312298 searchButton .setMinWidth (28 );
@@ -319,7 +305,8 @@ private void initSearchModifierButton(ButtonBase searchButton) {
319305 /**
320306 * Focuses the search field if it is not focused.
321307 */
322- public void focus () {
308+ @ Override
309+ public void requestFocus () {
323310 if (!searchField .isFocused ()) {
324311 searchField .requestFocus ();
325312 }
@@ -339,7 +326,7 @@ public void updateSearchQuery() {
339326 }
340327
341328 // Invalid regular expression
342- if (! regexValidator . getValidationStatus (). isValid ()) {
329+ if (regularExpressionButton . isSelected () && ! validRegex ()) {
343330 currentResults .setText (Localization .lang ("Invalid regular expression" ));
344331 return ;
345332 }
0 commit comments