#778 Updates Icon Manager to JavaFX. Resolves issue with displaying custom icons in alias editor. (#796)

Co-authored-by: Denny <denny@denny-desktop>
This commit is contained in:
Denny Sheirer
2020-05-06 08:08:05 +00:00
committed by GitHub
parent 2aff9ee817
commit 2723926f83
36 changed files with 1129 additions and 1051 deletions

View File

@@ -27,15 +27,17 @@ import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.controller.channel.map.ChannelMap;
import io.github.dsheirer.controller.channel.map.ChannelRange;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.gui.icon.IconManager;
import io.github.dsheirer.gui.icon.ViewIconManagerRequest;
import io.github.dsheirer.gui.playlist.PlaylistEditor;
import io.github.dsheirer.gui.playlist.PlaylistEditorRequest;
import io.github.dsheirer.gui.playlist.ViewPlaylistRequest;
import io.github.dsheirer.gui.playlist.channelMap.ChannelMapEditor;
import io.github.dsheirer.gui.playlist.channelMap.ChannelMapEditorViewRequest;
import io.github.dsheirer.gui.playlist.channelMap.ViewChannelMapEditorRequest;
import io.github.dsheirer.gui.preference.PreferenceEditorType;
import io.github.dsheirer.gui.preference.UserPreferenceEditorViewRequest;
import io.github.dsheirer.gui.preference.UserPreferencesEditor;
import io.github.dsheirer.icon.IconManager;
import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
import io.github.dsheirer.icon.IconModel;
import io.github.dsheirer.module.log.EventLogManager;
import io.github.dsheirer.playlist.PlaylistManager;
import io.github.dsheirer.preference.UserPreferences;
@@ -61,20 +63,24 @@ public class JavaFxWindowManager extends Application
private final static Logger mLog = LoggerFactory.getLogger(JavaFxWindowManager.class);
public static final String CHANNEL_MAP_EDITOR = "channelmap";
public static final String ICON_MANAGER = "iconmanager";
public static final String PLAYLIST_EDITOR = "playlist";
public static final String USER_PREFERENCES_EDITOR = "preferences";
public static final String STAGE_MONITOR_KEY_CHANNEL_MAP_EDITOR = "channel.map";
public static final String STAGE_MONITOR_KEY_ICON_MANAGER_EDITOR = "icon.manager";
public static final String STAGE_MONITOR_KEY_PLAYLIST_EDITOR = "playlist";
public static final String STAGE_MONITOR_KEY_USER_PREFERENCES_EDITOR = "user.preferences";
private JFXPanel mJFXPanel;
private PlaylistManager mPlaylistManager;
private ChannelMapEditor mChannelMapEditor;
private IconManager mIconManager;
private PlaylistEditor mPlaylistEditor;
private PlaylistManager mPlaylistManager;
private UserPreferences mUserPreferences;
private UserPreferencesEditor mUserPreferencesEditor;
private Stage mChannelMapStage;
private Stage mIconManagerStage;
private Stage mPlaylistStage;
private Stage mUserPreferencesStage;
@@ -101,7 +107,7 @@ public class JavaFxWindowManager extends Application
SourceManager sourceManager = new SourceManager(tunerModel, new SettingsManager(tunerConfigurationModel),
mUserPreferences);
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
mPlaylistManager = new PlaylistManager(mUserPreferences, sourceManager, aliasModel, eventLogManager, new IconManager());
mPlaylistManager = new PlaylistManager(mUserPreferences, sourceManager, aliasModel, eventLogManager, new IconModel());
mPlaylistManager.init();
setup();
}
@@ -151,6 +157,16 @@ public class JavaFxWindowManager extends Application
*/
public void shutdown()
{
if(mChannelMapStage != null)
{
mUserPreferences.getJavaFxPreferences().unmonitor(mChannelMapStage);
}
if(mIconManagerStage != null)
{
mUserPreferences.getJavaFxPreferences().unmonitor(mIconManagerStage);
}
if(mPlaylistStage != null)
{
mUserPreferences.getJavaFxPreferences().unmonitor(mPlaylistStage);
@@ -161,12 +177,32 @@ public class JavaFxWindowManager extends Application
mUserPreferences.getJavaFxPreferences().unmonitor(mUserPreferencesStage);
}
if(mChannelMapStage != null)
Platform.exit();
}
public Stage getIconManagerStage()
{
if(mIconManagerStage == null)
{
mUserPreferences.getJavaFxPreferences().unmonitor(mChannelMapStage);
createJFXPanel();
Scene scene = new Scene(getIconManager(), 500, 500);
mIconManagerStage = new Stage();
mIconManagerStage.setTitle("sdrtrunk - Icon Manager");
mIconManagerStage.setScene(scene);
mUserPreferences.getJavaFxPreferences().monitor(mIconManagerStage, STAGE_MONITOR_KEY_ICON_MANAGER_EDITOR);
}
Platform.exit();
return mIconManagerStage;
}
public IconManager getIconManager()
{
if(mIconManager == null)
{
mIconManager = new IconManager(mPlaylistManager.getIconModel());
}
return mIconManager;
}
/**
@@ -256,7 +292,7 @@ public class JavaFxWindowManager extends Application
* Processes a user preferences editor request
*/
@Subscribe
public void process(final UserPreferenceEditorViewRequest request)
public void process(final ViewUserPreferenceEditorRequest request)
{
execute(() -> {
getUserPreferencesStage().show();
@@ -297,11 +333,22 @@ public class JavaFxWindowManager extends Application
return mChannelMapStage;
}
@Subscribe
public void process(final ViewIconManagerRequest request)
{
mLog.debug("Processing view request");
execute(() -> {
getIconManagerStage().show();
getIconManagerStage().requestFocus();
getIconManagerStage().toFront();
});
}
/**
* Process a channel map editor request
*/
@Subscribe
public void process(final ChannelMapEditorViewRequest request)
public void process(final ViewChannelMapEditorRequest request)
{
execute(() -> {
getChannelMapStage().show();
@@ -344,7 +391,11 @@ public class JavaFxWindowManager extends Application
channelMap2.addRange(new ChannelRange(400,499,480000000, 25000));
mPlaylistManager.getChannelMapModel().addChannelMap(channelMap2);
valid = true;
process(new ChannelMapEditorViewRequest());
process(new ViewChannelMapEditorRequest());
break;
case ICON_MANAGER:
valid = true;
process(new ViewIconManagerRequest());
break;
case PLAYLIST_EDITOR:
valid = true;
@@ -352,7 +403,7 @@ public class JavaFxWindowManager extends Application
break;
case USER_PREFERENCES_EDITOR:
valid = true;
process(new UserPreferenceEditorViewRequest(PreferenceEditorType.DEFAULT));
process(new ViewUserPreferenceEditorRequest(PreferenceEditorType.DEFAULT));
break;
default:
break;
@@ -364,8 +415,8 @@ public class JavaFxWindowManager extends Application
{
StringBuilder sb = new StringBuilder();
sb.append("An argument is required to launch JavaFX windows from this window manager. " +
"Valid options are:\n\tplaylist\tPlaylist Editor\n\tpreferences\tUser Preferences Editor\n\tchannelmap\t" +
"Channel Map Editor\n");
"Valid options are:\n\tchannelmap\tChannel Map Editor\n\ticonmanager\tIcon Manager\n\tplaylist\tPlaylist Editor\n" +
"\tpreferences\tUser Preferences Editor\n");
sb.append("Supplied Argument(s): ").append(parameters.getRaw());
mLog.error(sb.toString());

View File

@@ -0,0 +1,30 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.gui;
/**
* Base class for all JavaFX window view and show requests
*/
public abstract class JavaFxWindowRequest
{
public JavaFxWindowRequest()
{
}
}

View File

@@ -30,9 +30,10 @@ import io.github.dsheirer.controller.channel.Channel;
import io.github.dsheirer.controller.channel.ChannelAutoStartFrame;
import io.github.dsheirer.controller.channel.ChannelSelectionManager;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.gui.icon.ViewIconManagerRequest;
import io.github.dsheirer.gui.playlist.ViewPlaylistRequest;
import io.github.dsheirer.gui.preference.UserPreferenceEditorViewRequest;
import io.github.dsheirer.icon.IconManager;
import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
import io.github.dsheirer.icon.IconModel;
import io.github.dsheirer.log.ApplicationLog;
import io.github.dsheirer.map.MapService;
import io.github.dsheirer.module.log.EventLogManager;
@@ -106,7 +107,7 @@ public class SDRTrunk implements Listener<TunerEvent>
private AudioStreamingManager mAudioStreamingManager;
private BroadcastStatusPanel mBroadcastStatusPanel;
private ControllerPanel mControllerPanel;
private IconManager mIconManager = new IconManager();
private IconModel mIconModel = new IconModel();
private PlaylistManager mPlaylistManager;
private SourceManager mSourceManager;
private SettingsManager mSettingsManager;
@@ -166,7 +167,7 @@ public class SDRTrunk implements Listener<TunerEvent>
AliasModel aliasModel = new AliasModel();
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
mPlaylistManager = new PlaylistManager(mUserPreferences, mSourceManager, aliasModel, eventLogManager, mIconManager);
mPlaylistManager = new PlaylistManager(mUserPreferences, mSourceManager, aliasModel, eventLogManager, mIconModel);
mJavaFxWindowManager = new JavaFxWindowManager(mUserPreferences, mPlaylistManager);
new ChannelSelectionManager(mPlaylistManager.getChannelModel());
@@ -183,10 +184,10 @@ public class SDRTrunk implements Listener<TunerEvent>
mPlaylistManager.getChannelProcessingManager().addAudioSegmentListener(mAudioRecordingManager);
mPlaylistManager.getChannelProcessingManager().addAudioSegmentListener(mAudioStreamingManager);
MapService mapService = new MapService(mIconManager);
MapService mapService = new MapService(mIconModel);
mPlaylistManager.getChannelProcessingManager().addDecodeEventListener(mapService);
mControllerPanel = new ControllerPanel(mPlaylistManager, audioPlaybackManager, mIconManager, mapService,
mControllerPanel = new ControllerPanel(mPlaylistManager, audioPlaybackManager, mIconModel, mapService,
mSettingsManager, mSourceManager, mUserPreferences);
mSpectralPanel = new SpectralDisplayPanel(mPlaylistManager, mSettingsManager, tunerModel);
@@ -331,11 +332,11 @@ public class SDRTrunk implements Listener<TunerEvent>
viewMenu.add(viewPlaylistItem);
JMenuItem preferencesItem = new JMenuItem("User Preferences");
preferencesItem.addActionListener(e -> MyEventBus.getEventBus().post(new UserPreferenceEditorViewRequest()));
preferencesItem.addActionListener(e -> MyEventBus.getEventBus().post(new ViewUserPreferenceEditorRequest()));
viewMenu.add(preferencesItem);
JMenuItem settingsMenu = new JMenuItem("Icon Manager");
settingsMenu.addActionListener(arg0 -> mIconManager.showEditor(mMainGui));
settingsMenu.addActionListener(arg0 -> MyEventBus.getEventBus().post(new ViewIconManagerRequest()));
viewMenu.add(settingsMenu);
JMenuItem logFilesMenu = new JMenuItem("Logs & Recordings");

View File

@@ -0,0 +1,574 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.gui.icon;
import io.github.dsheirer.gui.playlist.Editor;
import io.github.dsheirer.icon.Icon;
import io.github.dsheirer.icon.IconModel;
import javafx.beans.binding.Bindings;
import javafx.collections.transformation.SortedList;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Accordion;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* GUI manager/editor for standard and custom icons used in sdrtrunk
*/
public class IconManager extends Editor<Icon>
{
private static final Logger mLog = LoggerFactory.getLogger(IconManager.class);
private IconModel mIconModel;
private TableView<Icon> mIconTableView;
private Button mAddButton;
private Button mEditButton;
private Button mDeleteButton;
private Button mSetAsDefaultButton;
private SortedList<Icon> mIconSortedList;
private GridPane mEditorPane;
private Button mSaveButton;
private Button mCancelButton;
private Button mFileButton;
private TextField mFilePathTextField;
private TextField mNameTextField;
private TitledPane mContentTitledPane;
private TitledPane mEditorTitledPane;
private Accordion mAccordion;
/**
* Constructs an instance
*/
public IconManager(IconModel iconModel)
{
mIconModel = iconModel;
getChildren().addAll(getAccordion());
}
private Accordion getAccordion()
{
if(mAccordion == null)
{
mAccordion = new Accordion();
mAccordion.getPanes().addAll(getContentTitledPane(), getEditorTitledPane());
mAccordion.setExpandedPane(getContentTitledPane());
}
return mAccordion;
}
private TitledPane getContentTitledPane()
{
if(mContentTitledPane == null)
{
mContentTitledPane = new TitledPane();
mContentTitledPane.setCollapsible(false);
VBox buttonsBox = new VBox();
buttonsBox.setSpacing(10);
buttonsBox.setPadding(new Insets(10,10,10,10));
buttonsBox.getChildren().addAll(getAddButton(), getEditButton(), getDeleteButton(), getSetAsDefaultButton());
HBox.setHgrow(getIconTableView(), Priority.ALWAYS);
HBox contentBox = new HBox();
contentBox.setPadding(new Insets(0,0,0,0));
contentBox.getChildren().addAll(getIconTableView(), buttonsBox);
mContentTitledPane.setContent(contentBox);
}
return mContentTitledPane;
}
private TitledPane getEditorTitledPane()
{
if(mEditorTitledPane == null)
{
mEditorTitledPane = new TitledPane();
mEditorTitledPane.setDisable(true);
mEditorTitledPane.setExpanded(false);
mEditorTitledPane.setContent(getEditorPane());
}
return mEditorTitledPane;
}
private SortedList<Icon> getIconSortedList()
{
if(mIconSortedList == null)
{
mIconSortedList = new SortedList<>(mIconModel.iconsProperty(), (o1, o2) -> {
if(o1.getName() == null && o2.getName() == null)
{
return 0;
}
if(o1.getName() == null)
{
return -1;
}
if(o2.getName() == null)
{
return 1;
}
return o1.getName().compareTo(o2.getName());
});
}
return mIconSortedList;
}
private TableView<Icon> getIconTableView()
{
if(mIconTableView == null)
{
mIconTableView = new TableView<>(getIconSortedList());
TableColumn<Icon,String> iconColumn = new TableColumn("Icon");
iconColumn.setCellValueFactory(new PropertyValueFactory<>("path"));
iconColumn.setCellFactory(new IconTableCellFactory());
TableColumn<Icon,String> nameColumn = new TableColumn<>("Name");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
TableColumn<Icon,Boolean> typeColumn = new TableColumn<>("Type");
typeColumn.setPrefWidth(100);
typeColumn.setCellValueFactory(new PropertyValueFactory<>("defaultIcon"));
typeColumn.setCellFactory(param -> {
TableCell tableCell = new TableCell<Icon,Boolean>()
{
@Override
protected void updateItem(Boolean item, boolean empty)
{
Icon icon = getTableRow() != null ? getTableRow().getItem() : null;
if(icon != null)
{
if(icon.getDefaultIcon())
{
setText("Default");
}
else if(icon.getStandardIcon())
{
setText("Standard");
}
else
{
setText("Custom");
}
}
else
{
setText(null);
}
}
};
return tableCell;
});
mIconTableView.getColumns().addAll(typeColumn, iconColumn, nameColumn);
mIconTableView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
getDeleteButton().setDisable(newValue == null || newValue.getDefaultIcon() || newValue.getStandardIcon());
getEditButton().setDisable(newValue == null || newValue.getDefaultIcon() || newValue.getStandardIcon());
getSetAsDefaultButton().setDisable(newValue == null || newValue.getDefaultIcon());
});
}
return mIconTableView;
}
private void showEditor(boolean show)
{
if(show)
{
getEditorTitledPane().setText("Add or Edit an Icon");
getEditorTitledPane().setDisable(false);
getContentTitledPane().setCollapsible(true);
getAccordion().setExpandedPane(getEditorTitledPane());
getEditorTitledPane().setCollapsible(false);
getContentTitledPane().setDisable(true);
}
else
{
getEditorTitledPane().setText(null);
getContentTitledPane().setDisable(false);
getEditorTitledPane().setCollapsible(true);
getAccordion().setExpandedPane(getContentTitledPane());
getContentTitledPane().setCollapsible(false);
getEditorTitledPane().setDisable(true);
}
}
private Button getAddButton()
{
if(mAddButton == null)
{
mAddButton = new Button("Add");
mAddButton.setMaxWidth(Double.MAX_VALUE);
mAddButton.disableProperty().bind(getEditorPane().visibleProperty());
mAddButton.setOnAction(event -> {
setItem(null);
showEditor(true);
});
}
return mAddButton;
}
private Button getEditButton()
{
if(mEditButton == null)
{
mEditButton = new Button("Edit");
mEditButton.setDisable(true);
mEditButton.setMaxWidth(Double.MAX_VALUE);
mEditButton.setOnAction(event -> {
Icon selected = getIconTableView().getSelectionModel().getSelectedItem();
if(selected != null && !selected.standardIconProperty().get())
{
setItem(selected);
showEditor(true);
}
});
}
return mEditButton;
}
private Button getDeleteButton()
{
if(mDeleteButton == null)
{
mDeleteButton = new Button("Delete");
mDeleteButton.setDisable(true);
mDeleteButton.setMaxWidth(Double.MAX_VALUE);
mDeleteButton.setOnAction(event -> {
Icon selected = getIconTableView().getSelectionModel().getSelectedItem();
if(selected != null)
{
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "Delete alias: " +
selected.getName() + "?", ButtonType.YES, ButtonType.NO);
alert.setTitle("Delete Alias");
alert.setHeaderText("Deleting Alias");
alert.showAndWait().ifPresent(buttonType -> {
if(buttonType == ButtonType.YES)
{
mIconModel.removeIcon(selected);
}
});
}
});
}
return mDeleteButton;
}
private Button getSetAsDefaultButton()
{
if(mSetAsDefaultButton == null)
{
mSetAsDefaultButton = new Button("Set As Default");
mSetAsDefaultButton.setDisable(true);
mSetAsDefaultButton.setMaxWidth(Double.MAX_VALUE);
mSetAsDefaultButton.setOnAction(event -> {
Icon selected = getIconTableView().getSelectionModel().getSelectedItem();
if(selected != null)
{
mIconModel.setDefaultIcon(selected);
}
});
}
return mSetAsDefaultButton;
}
@Override
public void save()
{
String name = getNameTextField().getText();
String path = getFilePathTextField().getText();
if(name == null || name.isEmpty())
{
Alert alert = new Alert(Alert.AlertType.ERROR, "Please assign a name for the icon", ButtonType.OK);
alert.setHeaderText("Name is required");
alert.setTitle("Save Icon");
alert.showAndWait();
return;
}
if(path == null || path.isEmpty() || !Files.exists(Path.of(path)))
{
Alert alert = new Alert(Alert.AlertType.ERROR, "Please select a picture file for the icon", ButtonType.OK);
alert.setHeaderText("File is required");
alert.setTitle("Save Icon");
alert.showAndWait();
return;
}
if(getItem() != null)
{
getItem().setName(name);
getItem().setPath(path);
}
else
{
Icon icon = new Icon();
icon.setName(name);
icon.setPath(path);
mIconModel.addIcon(icon);
}
showEditor(false);
modifiedProperty().set(false);
}
@Override
public void dispose()
{
}
@Override
public void setItem(Icon item)
{
super.setItem(item);
if(item != null)
{
getNameTextField().setText(item.getName());
getFilePathTextField().setText(item.getPath());
}
else
{
getNameTextField().setText(null);
getFilePathTextField().setText(null);
}
modifiedProperty().set(false);
}
private GridPane getEditorPane()
{
if(mEditorPane == null)
{
mEditorPane = new GridPane();
mEditorPane.setPadding(new Insets(10,10,10,10));
mEditorPane.setHgap(10);
mEditorPane.setVgap(10);
int row = 0;
Label nameLabel = new Label("Name");
GridPane.setConstraints(nameLabel, 0, row);
GridPane.setHalignment(nameLabel, HPos.RIGHT);
mEditorPane.getChildren().add(nameLabel);
GridPane.setConstraints(getNameTextField(), 1, row);
GridPane.setHgrow(getNameTextField(), Priority.ALWAYS);
mEditorPane.getChildren().add(getNameTextField());
GridPane.setConstraints(getSaveButton(), 2, row);
mEditorPane.getChildren().add(getSaveButton());
GridPane.setConstraints(getFileButton(), 0, ++row);
mEditorPane.getChildren().add(getFileButton());
GridPane.setHgrow(getFilePathTextField(), Priority.ALWAYS);
GridPane.setConstraints(getFilePathTextField(), 1, row);
mEditorPane.getChildren().add(getFilePathTextField());
GridPane.setConstraints(getCancelButton(), 2, row);
mEditorPane.getChildren().add(getCancelButton());
}
return mEditorPane;
}
private TextField getFilePathTextField()
{
if(mFilePathTextField == null)
{
mFilePathTextField = new TextField();
}
return mFilePathTextField;
}
private Button getFileButton()
{
if(mFileButton == null)
{
mFileButton = new Button("File");
mFileButton.setMaxWidth(Double.MAX_VALUE);
mFileButton.setOnAction(event -> {
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("Picture Files", "*.png", "*.tif", "*.tiff",
"*.gif", "*.jpg", "*.jpeg"),
new FileChooser.ExtensionFilter("All Files (*.*)", "*.*"));
if(getFilePathTextField().getText() != null)
{
try
{
Path path = Path.of(getFilePathTextField().getText());
if(path.toFile().exists())
{
fileChooser.setInitialDirectory(path.getParent().toFile());
fileChooser.setInitialFileName(path.getFileName().toString());
}
}
catch(Exception e)
{
mLog.error("Error assigning file text to file chooser");
}
}
File selected = fileChooser.showOpenDialog(getFileButton().getScene().getWindow());
if(selected != null)
{
getFilePathTextField().setText(selected.getAbsolutePath());
}
});
}
return mFileButton;
}
private TextField getNameTextField()
{
if(mNameTextField == null)
{
mNameTextField = new TextField();
}
return mNameTextField;
}
private Button getSaveButton()
{
if(mSaveButton == null)
{
mSaveButton = new Button("Save");
mSaveButton.setMaxWidth(Double.MAX_VALUE);
mSaveButton.setOnAction(event -> save());
mSaveButton.disableProperty().bind(Bindings.or(Bindings.isNull(getNameTextField().textProperty()),
Bindings.isNull(getFilePathTextField().textProperty())));
}
return mSaveButton;
}
private Button getCancelButton()
{
if(mCancelButton == null)
{
mCancelButton = new Button("Cancel");
mCancelButton.setMaxWidth(Double.MAX_VALUE);
mCancelButton.setOnAction(event -> showEditor(false));
}
return mCancelButton;
}
public class IconTableCellFactory implements Callback<TableColumn<Icon, String>, TableCell<Icon, String>>
{
@Override
public TableCell<Icon, String> call(TableColumn<Icon, String> param)
{
TableCell<Icon,String> tableCell = new TableCell<>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
setAlignment(Pos.CENTER);
if(empty)
{
setGraphic(null);
}
else
{
if(getTableRow() != null)
{
Icon icon = getTableRow().getItem();
if(icon != null)
{
try
{
if(icon.getPath().startsWith("images"))
{
Image image = new Image(icon.getPath(), 0, 16, true, true);
setGraphic(new ImageView(image));
}
else
{
Path path = Path.of(icon.getPath());
Image image = new Image(path.toUri().toString(), 0, 16, true, true);
setGraphic(new ImageView(image));
}
}
catch(Exception e)
{
mLog.error("Error loading image: " + (icon != null ? icon.getPath() : "null"), e);
}
}
else
{
setGraphic(null);
}
}
}
}
};
return tableCell;
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2020 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.gui.icon;
import io.github.dsheirer.gui.JavaFxWindowRequest;
/**
* Request to view/show the Icon Manager
*/
public class ViewIconManagerRequest extends JavaFxWindowRequest
{
public ViewIconManagerRequest()
{
}
}

View File

@@ -23,6 +23,7 @@
package io.github.dsheirer.gui.playlist;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.gui.icon.ViewIconManagerRequest;
import io.github.dsheirer.gui.playlist.alias.AliasEditor;
import io.github.dsheirer.gui.playlist.alias.AliasTabRequest;
import io.github.dsheirer.gui.playlist.channel.ChannelEditor;
@@ -31,7 +32,7 @@ import io.github.dsheirer.gui.playlist.manager.PlaylistManagerEditor;
import io.github.dsheirer.gui.playlist.radioreference.RadioReferenceEditor;
import io.github.dsheirer.gui.playlist.streaming.StreamingEditor;
import io.github.dsheirer.gui.preference.PreferenceEditorType;
import io.github.dsheirer.gui.preference.UserPreferenceEditorViewRequest;
import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
import io.github.dsheirer.playlist.PlaylistManager;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.util.ThreadPool;
@@ -147,11 +148,18 @@ public class PlaylistEditor extends BorderPane
Menu viewMenu = new Menu("_View");
viewMenu.setAccelerator(new KeyCodeCombination(KeyCode.V, KeyCombination.ALT_ANY));
MenuItem iconManagerItem = new MenuItem("_Icon Manager");
iconManagerItem.setAccelerator(new KeyCodeCombination(KeyCode.I, KeyCombination.ALT_ANY));
iconManagerItem.setOnAction(event -> MyEventBus.getEventBus().post(new ViewIconManagerRequest()));
viewMenu.getItems().add(iconManagerItem);
MenuItem userPreferenceItem = new MenuItem("_User Preferences");
userPreferenceItem.setAccelerator(new KeyCodeCombination(KeyCode.U, KeyCombination.ALT_ANY));
userPreferenceItem.setOnAction(event -> MyEventBus.getEventBus()
.post(new UserPreferenceEditorViewRequest(PreferenceEditorType.TALKGROUP_FORMAT)));
.post(new ViewUserPreferenceEditorRequest(PreferenceEditorType.TALKGROUP_FORMAT)));
viewMenu.getItems().add(userPreferenceItem);
mMenuBar.getMenus().add(viewMenu);
Menu screenShot = new Menu("_Screenshot");

View File

@@ -23,7 +23,7 @@ import io.github.dsheirer.alias.AliasModel;
import io.github.dsheirer.audio.broadcast.BroadcastModel;
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
import io.github.dsheirer.gui.JavaFxWindowManager;
import io.github.dsheirer.icon.IconManager;
import io.github.dsheirer.icon.IconModel;
import io.github.dsheirer.module.log.EventLogManager;
import io.github.dsheirer.playlist.PlaylistManager;
import io.github.dsheirer.preference.UserPreferences;
@@ -50,14 +50,14 @@ public class PlaylistEditorApplication extends Application
public PlaylistEditorApplication()
{
AliasModel aliasModel = new AliasModel();
BroadcastModel broadcastModel = new BroadcastModel(aliasModel, new IconManager(), mUserPreferences);
BroadcastModel broadcastModel = new BroadcastModel(aliasModel, new IconModel(), mUserPreferences);
ChannelMapModel channelMapModel = new ChannelMapModel();
TunerConfigurationModel tunerConfigurationModel = new TunerConfigurationModel();
TunerModel tunerModel = new TunerModel(tunerConfigurationModel);
SourceManager sourceManager = new SourceManager(tunerModel, new SettingsManager(tunerConfigurationModel),
mUserPreferences);
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
mPlaylistManager = new PlaylistManager(mUserPreferences, sourceManager, aliasModel, eventLogManager, new IconManager());
mPlaylistManager = new PlaylistManager(mUserPreferences, sourceManager, aliasModel, eventLogManager, new IconModel());
mPlaylistManager.init();
mJavaFxWindowManager = new JavaFxWindowManager(mUserPreferences, mPlaylistManager);

View File

@@ -19,10 +19,12 @@
package io.github.dsheirer.gui.playlist;
import io.github.dsheirer.gui.JavaFxWindowRequest;
/**
* Request to view a facet of the playlist editor
*/
public abstract class PlaylistEditorRequest
public abstract class PlaylistEditorRequest extends JavaFxWindowRequest
{
public enum TabName {ALIAS, CHANNEL, PLAYLIST, RADIOREFERENCE, STREAM}

View File

@@ -777,7 +777,7 @@ public class AliasConfigurationEditor extends SplitPane
if(alias != null)
{
Icon icon = mPlaylistManager.getIconManager().getModel().getIcon(alias.getIconName());
Icon icon = mPlaylistManager.getIconModel().getIcon(alias.getIconName());
try
{

View File

@@ -103,6 +103,7 @@ import org.controlsfx.control.ToggleSwitch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -249,7 +250,7 @@ public class AliasItemEditor extends Editor<Alias>
String iconName = alias.getIconName();
if(iconName != null)
{
icon = mPlaylistManager.getIconManager().getModel().getIcon(iconName);
icon = mPlaylistManager.getIconModel().getIcon(iconName);
}
getIconNodeComboBox().getSelectionModel().select(icon);
@@ -1040,7 +1041,7 @@ public class AliasItemEditor extends Editor<Alias>
mIconNodeComboBox = new ComboBox<>();
mIconNodeComboBox.setMaxWidth(Double.MAX_VALUE);
mIconNodeComboBox.setDisable(true);
mIconNodeComboBox.getItems().addAll(mPlaylistManager.getIconManager().getIcons());
mIconNodeComboBox.setItems(mPlaylistManager.getIconModel().iconsProperty());
mIconNodeComboBox.setCellFactory(new IconCellFactory());
mIconNodeComboBox.getSelectionModel().selectedItemProperty()
.addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
@@ -1573,17 +1574,24 @@ public class AliasItemEditor extends Editor<Alias>
String path = item.getPath();
if(path.startsWith("images"))
try
{
try
if(path.startsWith("images"))
{
Image image = new Image(path, 0, 20, true, true);
setGraphic(new ImageView(image));
}
catch(Exception e)
else
{
Path filePath = Path.of(path);
Image image = new Image(filePath.toUri().toString(), 0, 16, true, true);
setGraphic(new ImageView(image));
}
}
catch(Exception e)
{
mLog.error("Error loading icon for [" + item.getName() + "] path [" + item.getPath() + "]");
}
}
}

View File

@@ -24,7 +24,7 @@ package io.github.dsheirer.gui.playlist.channel;
import io.github.dsheirer.controller.channel.map.ChannelMap;
import io.github.dsheirer.eventbus.MyEventBus;
import io.github.dsheirer.gui.playlist.channelMap.ChannelMapEditorViewRequest;
import io.github.dsheirer.gui.playlist.channelMap.ViewChannelMapEditorRequest;
import io.github.dsheirer.gui.playlist.eventlog.EventLogConfigurationEditor;
import io.github.dsheirer.gui.playlist.record.RecordConfigurationEditor;
import io.github.dsheirer.gui.playlist.source.FrequencyEditor;
@@ -271,7 +271,7 @@ public class MPT1327ConfigurationEditor extends ChannelConfigurationEditor
channelMapName = getChannelMapComboBox().getSelectionModel().getSelectedItem().getName();
}
MyEventBus.getEventBus().post(new ChannelMapEditorViewRequest(channelMapName));
MyEventBus.getEventBus().post(new ViewChannelMapEditorRequest(channelMapName));
}
});
}

View File

@@ -802,7 +802,7 @@ public class ChannelMapEditor extends SplitPane
/**
* Processes a request to show/edit a channel map
*/
public void process(ChannelMapEditorViewRequest request)
public void process(ViewChannelMapEditorRequest request)
{
String channelMapName = request.getChannelMapName();

View File

@@ -19,10 +19,12 @@
package io.github.dsheirer.gui.playlist.channelMap;
import io.github.dsheirer.gui.JavaFxWindowRequest;
/**
* Request to show the channel map editor
*/
public class ChannelMapEditorViewRequest
public class ViewChannelMapEditorRequest extends JavaFxWindowRequest
{
private String mChannelMapName;
@@ -30,7 +32,7 @@ public class ChannelMapEditorViewRequest
* Constructs an instance
* @param channelMapName to select once the editor is showing.
*/
public ChannelMapEditorViewRequest(String channelMapName)
public ViewChannelMapEditorRequest(String channelMapName)
{
mChannelMapName = channelMapName;
}
@@ -38,7 +40,7 @@ public class ChannelMapEditorViewRequest
/**
* Constructs an instance.
*/
public ChannelMapEditorViewRequest()
public ViewChannelMapEditorRequest()
{
}

View File

@@ -45,8 +45,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.ListIterator;
import java.util.Map;
/**
@@ -94,7 +92,7 @@ public class UserPreferencesEditor extends BorderPane
/**
* Shows the editor specified in the request by scrolling the editor view tree to the selected item.
*/
public void process(UserPreferenceEditorViewRequest request)
public void process(ViewUserPreferenceEditorRequest request)
{
if(request.getPreferenceType() != null)
{

View File

@@ -16,10 +16,12 @@
package io.github.dsheirer.gui.preference;
import io.github.dsheirer.gui.JavaFxWindowRequest;
/**
* Request to launch the preferences editor and scroll to a specific editor view
*/
public class UserPreferenceEditorViewRequest
public class ViewUserPreferenceEditorRequest extends JavaFxWindowRequest
{
private PreferenceEditorType mPreferenceType;
@@ -27,7 +29,7 @@ public class UserPreferenceEditorViewRequest
* Request to show the preference editor and focus the specified editor type control
* @param preferenceEditorType to focus
*/
public UserPreferenceEditorViewRequest(PreferenceEditorType preferenceEditorType)
public ViewUserPreferenceEditorRequest(PreferenceEditorType preferenceEditorType)
{
mPreferenceType = preferenceEditorType;
}
@@ -35,7 +37,7 @@ public class UserPreferenceEditorViewRequest
/**
* Request to simply show the preference editor without focusing any of the components
*/
public UserPreferenceEditorViewRequest()
public ViewUserPreferenceEditorRequest()
{
}