1010import javafx .application .Platform ;
1111import javafx .fxml .FXML ;
1212import javafx .fxml .FXMLLoader ;
13+ import javafx .scene .Node ;
1314import javafx .scene .Parent ;
1415import javafx .scene .Scene ;
1516import javafx .scene .control .*;
3839public final class MainWindowController implements IAudioTimer , TrayIconListener {
3940
4041 @ FXML
41- private GridPane grpControls ;
42+ private TitledPane pneOther ;
43+ @ FXML
44+ private TitledPane pneRadioFrequencyStatic ;
45+ @ FXML
46+ private TitledPane pneAudiences ;
47+ @ FXML
48+ private TitledPane pneOffice ;
49+ @ FXML
50+ private TitledPane pneNature ;
51+ @ FXML
52+ private Button btnClearSearch ;
53+ @ FXML
54+ private TextField txtSearch ;
55+ @ FXML
56+ private GridPane grpOther ;
57+ @ FXML
58+ private GridPane grpRadioFrequencyStatic ;
59+ @ FXML
60+ private GridPane grpAudiences ;
61+ @ FXML
62+ private GridPane grpOffice ;
63+ @ FXML
64+ private GridPane grpNature ;
4265 @ FXML
4366 private CheckMenuItem mniTimerEnabled ;
4467 @ FXML
@@ -139,7 +162,7 @@ public void setControllers(final SettingsController settingsController, final Up
139162 * @param visible True if the media buttons should be visible, otherwise false
140163 */
141164 public void loadMediaButtonVisibility (final boolean visible ) {
142- getAllSoundPanes (grpControls ).forEach (s -> s .setMediaButton (visible ));
165+ getAllSoundPanes ().forEach (s -> s .setMediaButton (visible ));
143166 }
144167
145168 /**
@@ -201,20 +224,37 @@ private void checkForUpdates(final boolean showNoUpdates, final boolean showErro
201224 }
202225 }
203226
227+ /**
228+ * Get all {@link SoundPane} objects
229+ *
230+ * @return The {@link List} of {@link SoundPane} objects
231+ */
232+ private List <SoundPane > getAllSoundPanes () {
233+ final List <SoundPane > elements = new ArrayList <>();
234+
235+ elements .addAll (getSoundPanes (grpOther ));
236+ elements .addAll (getSoundPanes (grpRadioFrequencyStatic ));
237+ elements .addAll (getSoundPanes (grpAudiences ));
238+ elements .addAll (getSoundPanes (grpOffice ));
239+ elements .addAll (getSoundPanes (grpNature ));
240+
241+ return elements ;
242+ }
243+
204244 /**
205245 * Get all {@link SoundPane} objects from a {@link GridPane} object
206246 *
207247 * @param parent The {@link GridPane} object
208248 * @return The {@link List} of {@link SoundPane} objects inside the given {@link GridPane} object
209249 */
210- private List <SoundPane > getAllSoundPanes (final GridPane parent ) {
250+ private List <SoundPane > getSoundPanes (final GridPane parent ) {
211251 if (parent == null )
212252 throw new NullPointerException ("GridPane cannot be null!" );
213253
214254 final List <SoundPane > elements = new ArrayList <>();
215255 parent .getChildren ().forEach (e -> {
216256 if (e instanceof GridPane p )
217- elements .addAll (getAllSoundPanes (p ));
257+ elements .addAll (getSoundPanes (p ));
218258 if (e instanceof SoundPane s )
219259 elements .add (s );
220260 });
@@ -271,13 +311,112 @@ private void initialize() {
271311 cancelTimer ();
272312 }
273313 });
314+
315+ txtSearch .textProperty ().addListener ((_ , _ , newValue ) -> {
316+ if (newValue == null || newValue .isBlank ()) {
317+ Platform .runLater (() -> {
318+ getAllSoundPanes ().forEach (e -> {
319+ e .setVisible (true );
320+ e .setManaged (true );
321+ });
322+ btnClearSearch .setVisible (false );
323+ btnClearSearch .setManaged (false );
324+
325+ pneNature .setExpanded (true );
326+ pneNature .setVisible (true );
327+ pneNature .setManaged (true );
328+
329+ pneOffice .setExpanded (false );
330+ pneOffice .setVisible (true );
331+ pneOffice .setManaged (true );
332+
333+ pneAudiences .setExpanded (false );
334+ pneAudiences .setVisible (true );
335+ pneAudiences .setManaged (true );
336+
337+ pneRadioFrequencyStatic .setExpanded (false );
338+ pneRadioFrequencyStatic .setVisible (true );
339+ pneRadioFrequencyStatic .setManaged (true );
340+
341+ pneOther .setExpanded (false );
342+ pneOther .setVisible (true );
343+ pneOther .setManaged (true );
344+ });
345+ return ;
346+ }
347+ Platform .runLater (() -> {
348+ getAllSoundPanes ()
349+ .forEach (e -> {
350+ e .setVisible (e .getName ().toLowerCase ().contains (newValue .trim ().toLowerCase ()));
351+ e .setManaged (e .isVisible ());
352+ });
353+
354+ // Check if there are still active sound panes on pneNature
355+ getSoundPanes (grpNature ).stream ().filter (Node ::isVisible ).findFirst ().ifPresentOrElse (e -> {
356+ pneNature .setExpanded (true );
357+ pneNature .setVisible (true );
358+ pneNature .setManaged (true );
359+ }, () -> {
360+ pneNature .setExpanded (false );
361+ pneNature .setVisible (false );
362+ pneNature .setManaged (false );
363+ });
364+
365+ // Check if there are still active sound panes on pneOffice
366+ getSoundPanes (grpOffice ).stream ().filter (Node ::isVisible ).findFirst ().ifPresentOrElse (e -> {
367+ pneOffice .setExpanded (true );
368+ pneOffice .setVisible (true );
369+ pneOffice .setManaged (true );
370+ }, () -> {
371+ pneOffice .setExpanded (false );
372+ pneOffice .setVisible (false );
373+ pneOffice .setManaged (false );
374+ });
375+
376+ // Check if there are still active sound panes on pneAudiences
377+ getSoundPanes (grpAudiences ).stream ().filter (Node ::isVisible ).findFirst ().ifPresentOrElse (e -> {
378+ pneAudiences .setExpanded (true );
379+ pneAudiences .setVisible (true );
380+ pneAudiences .setManaged (true );
381+ }, () -> {
382+ pneAudiences .setExpanded (false );
383+ pneAudiences .setVisible (false );
384+ pneAudiences .setManaged (false );
385+ });
386+
387+ // Check if there are still active sound panes on pneRadioFrequencyStatic
388+ getSoundPanes (grpRadioFrequencyStatic ).stream ().filter (Node ::isVisible ).findFirst ().ifPresentOrElse (e -> {
389+ pneRadioFrequencyStatic .setExpanded (true );
390+ pneRadioFrequencyStatic .setVisible (true );
391+ pneRadioFrequencyStatic .setManaged (true );
392+ }, () -> {
393+ pneRadioFrequencyStatic .setExpanded (false );
394+ pneRadioFrequencyStatic .setVisible (false );
395+ pneRadioFrequencyStatic .setManaged (false );
396+ });
397+
398+ // Check if there are still active sound panes on pneOther
399+ getSoundPanes (grpOther ).stream ().filter (Node ::isVisible ).findFirst ().ifPresentOrElse (e -> {
400+ pneOther .setExpanded (true );
401+ pneOther .setVisible (true );
402+ pneOther .setManaged (true );
403+ }, () -> {
404+ pneOther .setExpanded (false );
405+ pneOther .setVisible (false );
406+ pneOther .setManaged (false );
407+ });
408+
409+ btnClearSearch .setVisible (true );
410+ btnClearSearch .setManaged (true );
411+ });
412+ });
274413 }
275414
276415 /**
277416 * Hide the current stage
278417 */
279418 private void hideShowStage () {
280- final Stage stage = (Stage ) grpControls .getScene ().getWindow ();
419+ final Stage stage = (Stage ) grpNature .getScene ().getWindow ();
281420 if (stage .isShowing ()) {
282421 stage .hide ();
283422 } else {
@@ -320,14 +459,14 @@ private void openSoundPreset(final String path) {
320459 final Path filePath = Path .of (path );
321460 final String actual = Files .readString (filePath );
322461
323- if (actual == null || actual .isEmpty ())
324- throw new IllegalArgumentException ("Sound preset cannot be null or empty!" );
462+ if (actual .isEmpty ())
463+ throw new IllegalArgumentException ("Sound preset cannot be empty!" );
325464
326465 final TypeReference <HashMap <String , Double >> typeRef = new TypeReference <>() {
327466 };
328467
329468 final Map <String , Double > mediaVolumes = objectMapper .readValue (actual , typeRef );
330- final List <SoundPane > soundPanes = getAllSoundPanes (grpControls );
469+ final List <SoundPane > soundPanes = getAllSoundPanes ();
331470
332471 mediaVolumes .forEach ((key , value ) -> soundPanes .stream ().filter (e -> e .getMediaKey ().equals (key )).forEach (e -> e .getSlider ().setValue (value )));
333472 } catch (final IOException ex ) {
@@ -356,7 +495,7 @@ private void saveSoundPresetAction() {
356495 }
357496
358497 final Map <String , Double > mediaVolumes = new HashMap <>();
359- getAllSoundPanes (grpControls ).forEach (e -> mediaVolumes .put (e .getMediaKey (), e .getSlider ().getValue ()));
498+ getAllSoundPanes ().forEach (e -> mediaVolumes .put (e .getMediaKey (), e .getSlider ().getValue ()));
360499
361500 try {
362501 objectMapper .writeValue (new File (filePath ), mediaVolumes );
@@ -376,7 +515,7 @@ private void saveSoundPresetAction() {
376515 private void playPauseAction () {
377516 logger .info ("Play / pause all media" );
378517 try {
379- for (final SoundPane soundPane : getAllSoundPanes (grpControls )) {
518+ for (final SoundPane soundPane : getAllSoundPanes ()) {
380519 soundPane .playPause ();
381520 }
382521 } catch (final MediaPlayerException ex ) {
@@ -391,7 +530,7 @@ private void playPauseAction() {
391530 @ FXML
392531 private void resetAction () {
393532 logger .info ("Resetting all audio sliders" );
394- getAllSoundPanes (grpControls ).forEach (e -> e .getSlider ().setValue (0 ));
533+ getAllSoundPanes ().forEach (e -> e .getSlider ().setValue (0 ));
395534 }
396535
397536 /**
@@ -530,13 +669,21 @@ private void updateAction() {
530669 checkForUpdates (true , true );
531670 }
532671
672+ /**
673+ * Method that is called when the search field should be cleared
674+ */
675+ @ FXML
676+ private void clearSearchAction () {
677+ txtSearch .clear ();
678+ }
679+
533680 /**
534681 * Method that is called when the {@link Timer} object has fired
535682 */
536683 @ Override
537684 public void fired () {
538685 cancelTimer ();
539- getAllSoundPanes (grpControls ).forEach (SoundPane ::pause );
686+ getAllSoundPanes ().forEach (SoundPane ::pause );
540687
541688 if (Boolean .parseBoolean (settingsController .getProperties ().getProperty ("timerComputerShutdown" , "false" ))) {
542689 final String command = switch (platformName .toLowerCase ()) {
@@ -707,7 +854,7 @@ public void setAudioBalance(final double audioBalance) {
707854 throw new IllegalArgumentException ("Balance must be between -1.0 and 1.0!" );
708855
709856 logger .info ("Setting the audio balance to {}" , audioBalance );
710- getAllSoundPanes (grpControls ).forEach (s -> s .setBalance (audioBalance ));
857+ getAllSoundPanes ().forEach (s -> s .setBalance (audioBalance ));
711858 }
712859
713860 /**
0 commit comments