release 0.8.0 #12
|
@ -165,8 +165,8 @@ public class MainWindowController {
|
|||
@FXML private ScrollPane posterModeScrollPane;
|
||||
@FXML private FlowPane posterModeFlowPane;
|
||||
|
||||
// FilmDetailView
|
||||
@FXML private FilmDetailView filmDetailViewController;
|
||||
@FXML private SeriesDetailView seriesDetailViewController;
|
||||
|
||||
private static MainWindowController instance = null;
|
||||
private DBController dbController;
|
||||
|
@ -264,12 +264,6 @@ public class MainWindowController {
|
|||
|
||||
setLocalUI();
|
||||
applyColor();
|
||||
|
||||
// BoxBlur boxBlur = new BoxBlur();
|
||||
// boxBlur.setWidth(9);
|
||||
// boxBlur.setHeight(7);
|
||||
// boxBlur.setIterations(3);
|
||||
// posterModeFlowPane.setEffect(boxBlur);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -421,7 +415,7 @@ public class MainWindowController {
|
|||
}
|
||||
}
|
||||
|
||||
if ((dbController.getCached(getCurrentStreamUrl()).isAfter(lastValidCache) || getCurrentStreamUrl().contains("_rootNode"))
|
||||
if ((dbController.getCacheDate(getCurrentStreamUrl()).isAfter(lastValidCache) || getCurrentStreamUrl().contains("_rootNode"))
|
||||
&& dbController.searchCacheByURL(getCurrentStreamUrl())) {
|
||||
LOGGER.info("loading from cache: " + getCurrentTitle());
|
||||
setSelectedFilmInfo(dbController.readCache(getCurrentStreamUrl()));
|
||||
|
@ -795,6 +789,7 @@ public class MainWindowController {
|
|||
}
|
||||
|
||||
filmDetailViewController.updateGUILocal();
|
||||
seriesDetailViewController.updateGUILocal();
|
||||
|
||||
aboutBtn.setText(XMLController.getLocalBundle().getString("info"));
|
||||
settingsBtn.setText(XMLController.getLocalBundle().getString("settings"));
|
||||
|
@ -960,8 +955,10 @@ public class MainWindowController {
|
|||
filmDetailViewController.setFilm(element.getStreamURL());
|
||||
filmDetailViewController.showPane();
|
||||
} else {
|
||||
filmDetailViewController.setFilm(element.getStreamURL());
|
||||
filmDetailViewController.showPane();
|
||||
// filmDetailViewController.setFilm(element.getStreamURL());
|
||||
// filmDetailViewController.showPane();
|
||||
seriesDetailViewController.setSeries(element.getStreamURL());
|
||||
seriesDetailViewController.showPane();
|
||||
}
|
||||
|
||||
System.out.println("selected: " + element.getStreamURL());
|
||||
|
|
|
@ -1,10 +1,216 @@
|
|||
package kellerkinder.HomeFlix.application;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.util.Duration;
|
||||
import kellerkinder.HomeFlix.controller.DBController;
|
||||
import kellerkinder.HomeFlix.controller.XMLController;
|
||||
import kellerkinder.HomeFlix.datatypes.SeriresDVEpisode;
|
||||
|
||||
public class SeriesDetailView {
|
||||
|
||||
@FXML private AnchorPane seriesDVPane;
|
||||
@FXML private ScrollPane scrollPaneEpisodes;
|
||||
|
||||
@FXML private HBox hBoxEpisodes;
|
||||
|
||||
@FXML private Label lblTitle;
|
||||
@FXML private Label lblYear;
|
||||
@FXML private Label lblScore;
|
||||
|
||||
@FXML private Label lblCrew;
|
||||
@FXML private Label lblDirectors;
|
||||
@FXML private Label lblDirectorsInfo;
|
||||
@FXML private Label lblWriters;
|
||||
@FXML private Label lblWritersInfo;
|
||||
@FXML private Label lblActors;
|
||||
@FXML private Label lblActorsInfo;
|
||||
|
||||
@FXML private JFXButton btnWishlist;
|
||||
@FXML private JFXButton btnFavourite;
|
||||
@FXML private JFXButton btnHide;
|
||||
@FXML private JFXButton btnPlay;
|
||||
@FXML private JFXButton btnDirectory;
|
||||
|
||||
@FXML private ImageView wishlistIcon;
|
||||
@FXML private ImageView favoriteIcon;
|
||||
@FXML private ImageView imgPoster;
|
||||
|
||||
@FXML private Text textPlot;
|
||||
|
||||
@FXML private ChoiceBox<String> cbSeason;
|
||||
|
||||
private DBController dbController;
|
||||
private static final Logger LOGGER = LogManager.getLogger(SeriesDetailView.class.getName());
|
||||
private String currentStreamURL;
|
||||
|
||||
public void initialize() {
|
||||
dbController = DBController.getInstance();
|
||||
seriesDVPane.setStyle("-fx-background-color: rgba(89,89,89,0.9);");
|
||||
scrollPaneEpisodes.setStyle("-fx-background-color: transparent;");
|
||||
scrollPaneEpisodes.setHbarPolicy(ScrollBarPolicy.ALWAYS);
|
||||
|
||||
cbSeason.getSelectionModel().selectedIndexProperty().addListener((e, oldValue, newValue) -> {
|
||||
addEpisodes(newValue.intValue() + 1);
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void btnWishlistAction() {
|
||||
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void btnFavouriteAction() {
|
||||
dbController.toggleFavoriteState(currentStreamURL);
|
||||
|
||||
// update the favorite icon
|
||||
if(dbController.getFavoriteState(currentStreamURL) == 1) {
|
||||
favoriteIcon.setImage(new Image("icons/baseline_favorite_black_48dp.png"));
|
||||
} else {
|
||||
favoriteIcon.setImage(new Image("icons/baseline_favorite_border_black_48dp.png"));
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void btnHideAction() {
|
||||
hidePane();
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void btnPlayAction() {
|
||||
// playFilm(); // TODO
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void btnDirectoryAction() {
|
||||
File dest = new File(currentStreamURL).getParentFile();
|
||||
|
||||
if (!System.getProperty("os.name").contains("Linux")) {
|
||||
try {
|
||||
Desktop.getDesktop().open(dest);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set the cached data of a series to the SeriesDetailView
|
||||
* @param streamURL URL of the series root directory
|
||||
*/
|
||||
public void setSeries(String streamURL) {
|
||||
currentStreamURL = streamURL;
|
||||
String[] cacheInfo = dbController.readCache(streamURL); // get the cache data from the database
|
||||
|
||||
// add the cache data to the GUI
|
||||
lblTitle.setText(cacheInfo[0]);
|
||||
lblYear.setText("(" + cacheInfo[1] + ")");
|
||||
lblScore.setText(XMLController.getLocalBundle().getString("score") + ": " + cacheInfo[15] + "%");
|
||||
|
||||
textPlot.setText(cacheInfo[11]);
|
||||
|
||||
lblDirectors.setText(cacheInfo[8]);
|
||||
lblWriters.setText(cacheInfo[9]);
|
||||
lblActors.setText(cacheInfo[10]);
|
||||
|
||||
try {
|
||||
imgPoster.setImage(new Image(new File(cacheInfo[20]).toURI().toString()));
|
||||
} catch (Exception e) {
|
||||
imgPoster.setImage(new Image("icons/Homeflix_Poster.png"));
|
||||
LOGGER.error("No Poster found, useing default.");
|
||||
}
|
||||
|
||||
// set the favorite correct icon
|
||||
if(dbController.getFavoriteState(streamURL) == 1) {
|
||||
favoriteIcon.setImage(new Image("icons/baseline_favorite_black_48dp.png"));
|
||||
} else {
|
||||
favoriteIcon.setImage(new Image("icons/baseline_favorite_border_black_48dp.png"));
|
||||
}
|
||||
|
||||
// add all seasons to the ChoiceBox
|
||||
ObservableList<String> seasons = FXCollections.observableArrayList();
|
||||
for (int i = 1; i <= new File(currentStreamURL).listFiles().length; i++) {
|
||||
seasons.add("Season " + i);
|
||||
}
|
||||
cbSeason.getItems().clear();
|
||||
cbSeason.setItems(seasons);
|
||||
cbSeason.getSelectionModel().select(0);
|
||||
|
||||
// add all episodes for season 1
|
||||
addEpisodes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* update the text of all static GUI elements of FilmDeatilView
|
||||
*/
|
||||
public void updateGUILocal() {
|
||||
lblCrew.setText(XMLController.getLocalBundle().getString("crew"));
|
||||
lblDirectorsInfo.setText(XMLController.getLocalBundle().getString("directors"));
|
||||
lblWritersInfo.setText(XMLController.getLocalBundle().getString("writers"));
|
||||
lblActorsInfo.setText(XMLController.getLocalBundle().getString("actors"));
|
||||
}
|
||||
|
||||
/**
|
||||
* show the FilmDVpane
|
||||
*/
|
||||
public void showPane() {
|
||||
seriesDVPane.setVisible(true);
|
||||
FadeTransition fadeIn = new FadeTransition(Duration.millis(300), seriesDVPane);
|
||||
fadeIn.setFromValue(0.3);
|
||||
fadeIn.setToValue(1.0);
|
||||
fadeIn.play();
|
||||
}
|
||||
|
||||
/**
|
||||
* hide the FilmDVpane
|
||||
*/
|
||||
private void hidePane() {
|
||||
FadeTransition fadeOut = new FadeTransition(Duration.millis(200), seriesDVPane);
|
||||
fadeOut.setFromValue(1.0);
|
||||
fadeOut.setToValue(0.3);
|
||||
fadeOut.play();
|
||||
|
||||
seriesDVPane.setVisible(false);
|
||||
|
||||
MainWindowController.getInstance().disableBlur(); // disable blur
|
||||
}
|
||||
|
||||
/**
|
||||
* add all episodes of one season to the ScrollPane
|
||||
* @param season the season to add
|
||||
*/
|
||||
private void addEpisodes(int season) {
|
||||
hBoxEpisodes.getChildren().clear();
|
||||
for (String[] episodePoster : dbController.getEpisodes(new File(currentStreamURL).getName(), season)) {
|
||||
Image poster;
|
||||
try {
|
||||
poster = new Image(episodePoster[2].length() > 0 ? new File(episodePoster[2]).toURI().toString() : "icons/Homeflix_Poster.png");
|
||||
} catch (Exception e) {
|
||||
poster = new Image("icons/Homeflix_Poster.png");
|
||||
}
|
||||
hBoxEpisodes.getChildren().add(new SeriresDVEpisode(episodePoster[0], episodePoster[1], poster));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -452,7 +452,7 @@ public class DBController {
|
|||
* get the cached date for the film
|
||||
* @param streamUrl URL of the film
|
||||
*/
|
||||
public LocalDate getCached(String streamUrl) {
|
||||
public LocalDate getCacheDate(String streamUrl) {
|
||||
LocalDate cacheDate = LocalDate.now().minusDays(31);
|
||||
try {
|
||||
PreparedStatement ps = connection.prepareStatement("SELECT cached FROM films WHERE streamUrl = ?");
|
||||
|
@ -651,6 +651,34 @@ public class DBController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return the cache data for all episodes of a series season
|
||||
* @param title the title of the series
|
||||
* @param season the season you want
|
||||
* @return a ArrayList of cache data (String Array [21])
|
||||
*/
|
||||
public ArrayList<String[]> getEpisodes(String title, int season) {
|
||||
ArrayList<String[]> episodePosters =new ArrayList<>();
|
||||
try {
|
||||
// try to get a all episode of one season
|
||||
PreparedStatement ps = connection.prepareStatement("SELECT streamUrl, episode FROM films WHERE title = ? AND season = ?");
|
||||
ps.setString(1, title);
|
||||
ps.setString(2, Integer.toString(season));
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
// for each episode load cache data
|
||||
while (rs.next()) {
|
||||
String[] cacheData = readCache(rs.getString("streamUrl"));
|
||||
String[] ret = {rs.getString("streamUrl"), rs.getString("episode"), cacheData[20]};
|
||||
episodePosters.add(ret);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
LOGGER.error("Ups! error while getting episodes of a season!", e);
|
||||
}
|
||||
|
||||
return episodePosters;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the next episode of a series
|
||||
* @param title title of the film
|
||||
|
@ -662,7 +690,7 @@ public class DBController {
|
|||
|
||||
try {
|
||||
// try to get a new episode of the current season
|
||||
PreparedStatement ps = connection.prepareStatement("SELECT * FROM films WHERE title = ? AND season = ? AND episode = ?");
|
||||
PreparedStatement ps = connection.prepareStatement("SELECT * FROM films WHERE title = ? AND season = ? AND episode = ?");
|
||||
ps.setString(1, title);
|
||||
ps.setString(2, Integer.toString(season));
|
||||
ps.setString(3, Integer.toString(episode + 1));
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package kellerkinder.HomeFlix.datatypes;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import kellerkinder.HomeFlix.player.Player;
|
||||
|
||||
public class SeriresDVEpisode extends AnchorPane {
|
||||
|
||||
private String streamURL;
|
||||
private Label label = new Label();
|
||||
private ImageView imageView = new ImageView();
|
||||
|
||||
public SeriresDVEpisode() {
|
||||
super.getChildren().addAll(imageView, label);
|
||||
super.prefWidth(200);
|
||||
super.prefHeight(112);
|
||||
|
||||
|
||||
imageView.setPreserveRatio(true);
|
||||
imageView.setFitHeight(112);
|
||||
|
||||
label.setStyle("-fx-text-fill: #ffffff; -fx-font-size: 14pt ; -fx-font-weight: bold;");
|
||||
super.setTopAnchor(label, 3.0);
|
||||
super.setLeftAnchor(label, 7.0);
|
||||
}
|
||||
|
||||
public SeriresDVEpisode(String streamURL, String episode, Image poster) {
|
||||
this();
|
||||
|
||||
this.streamURL = streamURL;
|
||||
|
||||
label.setText(episode);
|
||||
imageView.setImage(poster);
|
||||
imageView.addEventHandler(MouseEvent.MOUSE_PRESSED, (e) -> {
|
||||
// Always play with the integrated Player TODO
|
||||
new Player(streamURL);
|
||||
});
|
||||
}
|
||||
|
||||
public String getStreamURL() {
|
||||
return streamURL;
|
||||
}
|
||||
|
||||
public Label getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public ImageView getImageView() {
|
||||
return imageView;
|
||||
}
|
||||
|
||||
public void setStreamURL(String streamURL) {
|
||||
this.streamURL = streamURL;
|
||||
}
|
||||
|
||||
public void setLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public void setImageView(ImageView imageView) {
|
||||
this.imageView = imageView;
|
||||
}
|
||||
|
||||
}
|
|
@ -39,6 +39,8 @@ public class Player {
|
|||
private AnchorPane pane;
|
||||
private Scene scene;
|
||||
|
||||
// TODO move the players choose logic to a separate static class
|
||||
|
||||
/**
|
||||
* generate a new PlayerWindow
|
||||
* @param currentTableFilm the currently selected film
|
||||
|
|
|
@ -188,3 +188,7 @@
|
|||
.scroll-pane .corner {
|
||||
-fx-background-insets: 0;
|
||||
}
|
||||
|
||||
.scroll-pane > .viewport {
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
</content>
|
||||
</ScrollPane>
|
||||
<fx:include fx:id="filmDetailView" source="FilmDetailView.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="32.0" />
|
||||
<fx:include fx:id="seriesDetailView" source="SeriesDetailView.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="32.0" />
|
||||
<ScrollPane fx:id="settingsScrollPane" fitToHeight="true" fitToWidth="true" prefHeight="568.0" prefWidth="800.0" style="-fx-background: white;" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="150.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="32.0">
|
||||
<content>
|
||||
<AnchorPane fx:id="settingsAnchorPane" style="-fx-background-color: white;">
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<?import javafx.scene.text.Text?>
|
||||
<?import javafx.scene.text.TextFlow?>
|
||||
|
||||
<AnchorPane fx:id="seriesDVPane" prefHeight="568.0" prefWidth="1130.0" style="-fx-background-color: #595959;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="kellerkinder.HomeFlix.application.SeriesDetailView">
|
||||
<AnchorPane fx:id="seriesDVPane" prefHeight="568.0" prefWidth="1130.0" style="-fx-background-color: #595959;" visible="false" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="kellerkinder.HomeFlix.application.SeriesDetailView">
|
||||
<children>
|
||||
<HBox layoutX="22.0" layoutY="21.0" prefWidth="808.0" spacing="10.0" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="22.0">
|
||||
<children>
|
||||
|
@ -118,66 +118,17 @@
|
|||
</VBox>
|
||||
</children>
|
||||
</HBox>
|
||||
<ChoiceBox layoutX="22.0" layoutY="523.0" prefHeight="25.0" prefWidth="168.0" AnchorPane.leftAnchor="22.0" AnchorPane.topAnchor="523.0" />
|
||||
<ScrollPane layoutX="22.0" layoutY="398.0" prefHeight="145.0" prefWidth="798.0" style="-fx-background: transparent;" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="370.0">
|
||||
<ScrollPane fx:id="scrollPaneEpisodes" layoutX="22.0" layoutY="398.0" prefHeight="135.0" style="-fx-background-color: #595959;" AnchorPane.leftAnchor="22.0" AnchorPane.rightAnchor="310.0" AnchorPane.topAnchor="370.0">
|
||||
<content>
|
||||
<HBox spacing="10.0">
|
||||
<children>
|
||||
<VBox>
|
||||
<children>
|
||||
<ImageView fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../icons/2QjWeU6mfvx6sWF2z9CLb4kdRnR.jpg" />
|
||||
</image>
|
||||
</ImageView>
|
||||
<Label text="Label" />
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox>
|
||||
<children>
|
||||
<ImageView fitWidth="200.0" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../icons/2QjWeU6mfvx6sWF2z9CLb4kdRnR.jpg" />
|
||||
</image>
|
||||
</ImageView>
|
||||
<Label text="Label" />
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox>
|
||||
<children>
|
||||
<ImageView fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../icons/2QjWeU6mfvx6sWF2z9CLb4kdRnR.jpg" />
|
||||
</image>
|
||||
</ImageView>
|
||||
<Label text="Label" />
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox>
|
||||
<children>
|
||||
<ImageView fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../icons/2QjWeU6mfvx6sWF2z9CLb4kdRnR.jpg" />
|
||||
</image>
|
||||
</ImageView>
|
||||
<Label text="Label" />
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox>
|
||||
<children>
|
||||
<ImageView fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../icons/2QjWeU6mfvx6sWF2z9CLb4kdRnR.jpg" />
|
||||
</image>
|
||||
</ImageView>
|
||||
<Label text="Label" />
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
<HBox fx:id="hBoxEpisodes" maxHeight="-Infinity" minHeight="-Infinity" prefHeight="117.0" spacing="10.0">
|
||||
<padding>
|
||||
<Insets left="10.0" right="10.0" top="5.0" />
|
||||
</padding>
|
||||
</HBox>
|
||||
</content>
|
||||
</ScrollPane>
|
||||
<JFXButton fx:id="btnHide" contentDisplay="GRAPHIC_ONLY" layoutX="532.0" layoutY="520.0" maxHeight="-Infinity" minWidth="-Infinity" onAction="#btnHideAction" prefHeight="32.0" style="-fx-background-color: transparent;" text="Hide" AnchorPane.bottomAnchor="16.0" AnchorPane.leftAnchor="532.0" AnchorPane.rightAnchor="532.0">
|
||||
<ChoiceBox fx:id="cbSeason" layoutX="22.0" layoutY="523.0" prefHeight="25.0" prefWidth="168.0" AnchorPane.leftAnchor="22.0" AnchorPane.topAnchor="515.0" />
|
||||
<JFXButton fx:id="btnHide" contentDisplay="GRAPHIC_ONLY" layoutX="532.0" layoutY="520.0" maxHeight="-Infinity" minWidth="-Infinity" onAction="#btnHideAction" prefHeight="32.0" style="-fx-background-color: transparent;" text="Hide" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="530.0" AnchorPane.rightAnchor="530.0">
|
||||
<graphic>
|
||||
<ImageView pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue