Skip to content

Commit

Permalink
Added basic contect menu support. A partial solution to #3.
Browse files Browse the repository at this point in the history
Currently supports marking a station as a favourite and removing a station using a context menu. The context menu appears when the user right clicks on a station entry in a tableview.
Thanks to the ModelAdapters event functionality, all GUI components are notified of any changes made to the model via context menu actions.
When a station is marked as favourite it appears on the favourite station table instantly.
When a station is removed from the model it is removed from all tables immediately.
Still need to create an FXML view to display station details before #3 can be marked complete.
  • Loading branch information
lemon-codes committed Feb 8, 2021
1 parent 078f0b1 commit 633234c
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 16 deletions.
9 changes: 4 additions & 5 deletions .netradio-stations.csv
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"BITRATE","FAVOURITE","ID","LASTPLAYED","NAMES","PLAYCOUNT","URI"
"-1","false","2","","BBC Radio 1","15","http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p"
"-1","true","0","","Clyde1(mp3)","98","http://stream-al.planetradio.co.uk/clyde1.mp3"
"-1","false","1","","Capital FM","58","http://media-ice.musicradio.com/Capital"
"-1","false","2","","BBC Radio 1","17","http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p"
"-1","false","3","","StartFM","14","http://eteris.startfm.lt/startfm.ogg"
"-1","true","7","","Clyde1(aac)","9","http://stream-al.planetradio.co.uk/clyde1.aac"
"-1","false","6","","test2","0","http://test.test2"
"-1","false","1","","Capital FM","55","http://media-ice.musicradio.com/Capital"
"-1","true","0","","Clyde1(mp3)","97","http://stream-al.planetradio.co.uk/clyde1.mp3"
"-1","false","3","","StartFM","13","http://eteris.startfm.lt/startfm.ogg"
"-1","false","4","","FreeDesktop","2","https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm"
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ public class StationExplorerController implements Initializable, ModelEventHandl
public void initialize(URL url, ResourceBundle resourceBundle) {
model.subscribeToModelEvents(this);
// fill tables with station data from the model
updateAllTableValues();

}

/**
* Fills tables with up to date station data from the model
*/
private void updateAllTableValues() {
allStationsTable.getItems().setAll(stationToStationData(model.getAllStations()));
favouriteStationsTable.getItems().setAll(stationToStationData(getFavouriteStations()));
mostPlayedStationsTable.getItems().setAll(stationToStationData(getMostPlayedStations()));
Expand Down Expand Up @@ -116,16 +124,25 @@ public void searchStations(ActionEvent actionEvent) {
stationTabs.getSelectionModel().select(searchResultTab);
}


/**
* Handle events in the model triggered when other components in the UI
* alter the models state.
* @param event an event in the model
*/
@Override
public void handleEvent(ModelAdapter.ModelEvent event) {
// TODO: consider handling events
switch(event) {
case PLAYBACK_STARTED -> {}
case PLAYBACK_STOPPED -> {}
case STATION_CHANGED -> {}
case STATION_ADDED -> updateAllTableValues();
case STATION_REMOVED -> updateAllTableValues();
case STATION_EDITED -> updateAllTableValues();
case SEARCH_RESULTS_READY -> {}
case TAG_UPDATE -> {}
case VOLUME_CHANGED -> {}
case SHUTDOWN -> {}
}
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import codes.lemon.netradio.model.Station;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
Expand Down Expand Up @@ -52,21 +53,36 @@ public void initialize(URL url, ResourceBundle resourceBundle) {
* @param mouseEvent a mouse click on a station
*/
public void stationClicked(MouseEvent mouseEvent) {
List<StationData> stationList = tableView.getItems();
if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
if (mouseEvent.getClickCount() == 2) {
List<TablePosition> rows = tableView.getSelectionModel().getSelectedCells();
assert(rows.size() == 1) : "rows.size()>1. multiple rows cannot be clicked at once";
for (TablePosition row : rows) {
int rowIndex = row.getRow();
StationData clickedStation = stationList.get(rowIndex);
StationData clickedStation = getStationSelected();
if (clickedStation != null) {
model.setStation(clickedStation.getStationIdAsInt());
model.play();
}
}
}
}

/**
* Returns the StationData instance representing the station selected in the table.
* Returns null if no station is selected.
* @return the station selected in the table, else null if none selected.
*/
private StationData getStationSelected() {
List<StationData> stationDataList = tableView.getItems();
List<TablePosition> rows = tableView.getSelectionModel().getSelectedCells();
if (rows.size() == 1) {
int rowIndex = rows.get(0).getRow();
return stationDataList.get(rowIndex);
}
else {
// no station selected
assert(rows.size() == 0) : "rows.size() > 1. multiple rows cannot be clicked at once";
return null;
}
}


/**
* TODO: handle events
Expand All @@ -89,19 +105,73 @@ public void handleEvent(ModelAdapter.ModelEvent event) {
}
}

/**
* Set the stations who's values are displayed in the tableview.
* @param stations list of stations to display
*/
public void setStationsOnDisplay(List<Station> stations) {
Objects.requireNonNull(stations);
List<StationData> tableEntries = stationToStationData(stations);
tableView.getItems().setAll(tableEntries);
}

private List<StationData> stationToStationData(List<Station> stations) {
/**
* Convert Station instances from the model to StationData instances that can be processed
* by JavaFX property value providers.
* StationData and Station instances have a 1 to 1 relationship.
* @param stations list of Station instances
* @return list of StationData instances with the same values as the Station instances
*/
private static List<StationData> stationToStationData(List<Station> stations) {
assert(stations != null) : "stations cannot be null";
List<StationData> convertedStations = new ArrayList<>();
for (Station s : stations) {
convertedStations.add(new StationData(s.getStationID(), s.getStationName(), s.getURI()));
}
return convertedStations;
}

/**
* Get the station instance from the model corresponding to the provided
* StationData instance.
* @param stationData a StationData instance representing a Station from the model
* @return Station instance from the model
*/
private Station getStationFromModel(StationData stationData) {
assert(stationData != null) : "stationData cannot be null";
return model.getStation(stationData.getStationIdAsInt());
}

/**
* Mark selected station as a favourite in the model.
* If the station is already a favourite, it's favourite status is removed.
* @param actionEvent
*/
public void toggleFavouriteStatus(ActionEvent actionEvent) {
StationData selectedStationData = getStationSelected();
if (selectedStationData != null) {
Station selectedStation = getStationFromModel(selectedStationData);
model.setStationFavouriteStatus(selectedStation.getStationID(), !selectedStation.isFavourite());
}
}

/**
* Show all details available from the model about the selected station.
* @param actionEvent
*/
public void showDetails(ActionEvent actionEvent) {
// TODO: construct fxml view to display station details
}

/**
* Remove the selected station from the model
* @param actionEvent
*/
public void removeStation(ActionEvent actionEvent) {
StationData selectedStationData = getStationSelected();
if (selectedStationData != null) {
model.removeStation(selectedStationData.getStationIdAsInt());
}
}
}

14 changes: 14 additions & 0 deletions src/main/resources/codes/lemon/netradio/view/stationTable.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

<!-- Default table view. A table with columns station ID, station name and the uri. -->
<!-- The controller for this view fills the table with details of all stations stored in the model -->
<?import javafx.scene.control.ContextMenu?>
<?import javafx.scene.control.MenuItem?>
<TableView fx:id="tableView" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
fx:controller="codes.lemon.netradio.controller.StationTableController"
prefHeight="200.0" prefWidth="Infinity" maxWidth="Infinity" onMouseClicked="#stationClicked">
Expand All @@ -16,4 +18,16 @@
<sortOrder>
<fx:reference source="idColumn"/>
</sortOrder>

<!-- context menu which is shown when a user right clicks on a station -->
<contextMenu>
<ContextMenu fx:id="contextMenu">
<items>
<MenuItem text="Favourite" onAction="#toggleFavouriteStatus"/>
<MenuItem text="Details" onAction="#showDetails"/>
<MenuItem text="Remove" onAction="#removeStation"/>
</items>
</ContextMenu>

</contextMenu>
</TableView>
14 changes: 14 additions & 0 deletions target/classes/codes/lemon/netradio/view/stationTable.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

<!-- Default table view. A table with columns station ID, station name and the uri. -->
<!-- The controller for this view fills the table with details of all stations stored in the model -->
<?import javafx.scene.control.ContextMenu?>
<?import javafx.scene.control.MenuItem?>
<TableView fx:id="tableView" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
fx:controller="codes.lemon.netradio.controller.StationTableController"
prefHeight="200.0" prefWidth="Infinity" maxWidth="Infinity" onMouseClicked="#stationClicked">
Expand All @@ -16,4 +18,16 @@
<sortOrder>
<fx:reference source="idColumn"/>
</sortOrder>

<!-- context menu which is shown when a user right clicks on a station -->
<contextMenu>
<ContextMenu fx:id="contextMenu">
<items>
<MenuItem text="Favourite" onAction="#toggleFavouriteStatus"/>
<MenuItem text="Details" onAction="#showDetails"/>
<MenuItem text="Remove" onAction="#removeStation"/>
</items>
</ContextMenu>

</contextMenu>
</TableView>

0 comments on commit 633234c

Please sign in to comment.