import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; import javafx.util.Callback; import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.MouseEvent; import javafx.scene.paint.Color; import javafx.scene.layout.*; import javafx.stage.*; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.control.cell.ProgressBarTableCell; import javafx.event.*; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.layout.GridPane; import javafx.stage.Stage; import javafx.application.Platform; import java.awt.Desktop; import java.awt.Toolkit; import java.awt.datatransfer.DataFlavor; public class Main extends Application { public static String tempFolderPath = System.getProperty("user.home")+File.separator + ".downloadPlusPlus" + File.separator + "segments"; static{ Logger.enableDebug(); Logger.enableLog(); File toTemp = new File(tempFolderPath); if(!toTemp.isDirectory()) toTemp.mkdirs(); } private Button addbtn,playPausebtn,stopbtn; private static TableView<DownloadUnit> table = new TableView<DownloadUnit>(); private String windowTitle = "Download++"; private int width = 1000, height = 650; @SuppressWarnings({"rawtypes"}) private TableColumn fileNameCol, sizeCol, statusCol, transferRateCol, percentageCol, progressCol, resumeCapCol, downloadedCol; private static final ObservableList<DownloadUnit> downloadList = FXCollections.observableArrayList(); private static final HashMap<Long, DownloadUnit> idToDunit = new HashMap<Long, DownloadUnit>(); private static final HashMap<Long, Downloader> idToDownloader = new HashMap<Long, Downloader>(); private static volatile long uid = 0; //private boolean paused = false; public static SplitPane infoPane = new SplitPane(); public static GridPane gridPane = new GridPane(); static Label fileNameLabel = new Label(); static Label sizeLabel = new Label(); static Label statusLabel = new Label(); static Label fileTypeLabel = new Label(); static Label filePathLabel = new Label(); final static VBox topContainer = new VBox(); public static void main(String[] args) { Platform.setImplicitExit(false); launch(args); } @Override public void start(Stage stage) throws Exception { initGUI(stage); initToolbarHandlers(); if(table != null) table.addEventHandler(MouseEvent.MOUSE_CLICKED, new TableClickHandler()); stage.show(); stage.setOnCloseRequest(new EventHandler<WindowEvent>() { public void handle(WindowEvent we) { for(Map.Entry<Long, Downloader> dwnld: idToDownloader.entrySet()){ dwnld.getValue().pauseDownload(true); } } }); loadDownloadState(); } private void loadDownloadState(){ new Thread(){ @SuppressWarnings({ "unchecked", "rawtypes" }) public void run(){ try{ for(final File file: (new File(JSON.dumpPath)).listFiles()){ if(!file.isDirectory()){ String ext = file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf("."), file.getAbsolutePath().length()); if(ext.equals(".data")){ DownloadUnit dUnit = JSON.loadDumpDownload(file.getAbsolutePath()); idToDunit.put(dUnit.getUID(), dUnit); Downloader dwnld = new Downloader(dUnit); idToDownloader.put(dUnit.getUID(), dwnld); downloadList.add(dUnit); if(dUnit.statusEnum != DownloadUnit.Status.COMPLETED){ dUnit.statusEnum = DownloadUnit.Status.RESUMED; dwnld.start(); } if(uid>dUnit.getUID()) uid = dUnit.getUID(); file.delete(); } } } uid++; fileNameCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("filename")); sizeCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("size")); statusCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("status")); transferRateCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("transferRate")); resumeCapCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("resumeCap")); downloadedCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("downloaded")); percentageCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("percentage")); resumeCapCol.setCellFactory(new Callback<TableColumn, TableCell>() { public TableCell call(TableColumn param) { return new TableCell<DownloadUnit, String>() { @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (!isEmpty()) { if(item.contains("Yes")) this.setTextFill(Color.GREEN); else if(item.contains("No")) this.setTextFill(Color.RED); setText(item); } else setText(null); } }; } }); }catch(Exception e){ Logger.log(Logger.Status.ERR_LOAD, "Error restoring state: "+e.getMessage()); } } }.start(); } @SuppressWarnings({ "rawtypes", "unchecked" }) private void initGUI(Stage stage){ BorderPane root = new BorderPane(); stage.setTitle(windowTitle); Scene scene = new Scene(root,width,height); stage.setMinWidth(width); stage.setMinHeight(height); stage.setScene(scene); stage.sizeToScene(); ToolBar toolBar = new ToolBar(); //Creates our tool-bar to hold the buttons topContainer.getChildren().addAll(toolBar); root.setTop(topContainer); addbtn = new Button(); playPausebtn = new Button(); stopbtn = new Button(); /*** Toolbar ***/ Image playimage = new Image(getClass().getResourceAsStream("images/add.png")); addbtn.setGraphic(new ImageView(playimage)); Image pauseimage = new Image(getClass().getResourceAsStream("images/pause.png")); playPausebtn.setGraphic(new ImageView(pauseimage)); Image stopimage = new Image(getClass().getResourceAsStream("images/stop.png")); stopbtn.setGraphic(new ImageView(stopimage)); toolBar.getItems().addAll(addbtn,playPausebtn,stopbtn); toolBar.getStylesheets().add("css/downloadboxStyle.css"); //list of downloads table.setEditable(true); /*** Information Table ***/ fileNameCol = new TableColumn("File Name"); fileNameCol.setPrefWidth(120); sizeCol = new TableColumn("Size"); sizeCol.setPrefWidth(100); resumeCapCol = new TableColumn("Resumable"); resumeCapCol.setPrefWidth(100); statusCol = new TableColumn("Status"); statusCol.setPrefWidth(100); transferRateCol = new TableColumn("Transfer Rate"); transferRateCol.setPrefWidth(100); downloadedCol = new TableColumn("Downloaded"); downloadedCol.setPrefWidth(120); percentageCol = new TableColumn("Percentage"); percentageCol.setPrefWidth(120); progressCol = new TableColumn("Progress"); progressCol.setPrefWidth(200); progressCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit, Double>("progress")); progressCol.setCellFactory(ProgressBarTableCell.<DownloadUnit> forTableColumn()); table.getColumns().addAll(fileNameCol, sizeCol, downloadedCol, percentageCol, progressCol, transferRateCol, resumeCapCol, statusCol); table.setItems(downloadList); topContainer.getChildren().addAll(table); stage.setScene(scene); } private void initToolbarHandlers(){ addbtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { final Stage popup = new Stage(); popup.initModality(Modality.APPLICATION_MODAL); popup.setTitle("Enter URL(s) to download"); popup.setResizable(false); BorderPane popupRoot = new BorderPane(); Scene scene = new Scene(popupRoot,650,200); popup.setScene(scene); GridPane grid = new GridPane(); grid.setPadding(new Insets(10, 10, 10, 10)); grid.setVgap(5); grid.setHgap(5); scene.setRoot(grid); final TextArea addURL = new TextArea(); final TextField saveAs = new TextField(); addURL.setPromptText("Add Url"); addURL.setPrefColumnCount(45); addURL.setPrefHeight(175); GridPane.setConstraints(addURL, 0, 0); String clipboardContent=null; try { clipboardContent = (String) Toolkit.getDefaultToolkit() .getSystemClipboard().getData(DataFlavor.stringFlavor); } catch (Exception e) { Logger.log(Logger.Status.ERR_CLIPBOARD, e.getMessage()); } if (Pattern.compile("((mailto\\:|(news|(ht|f)tp(s?))\\://){1}\\S+)").matcher(clipboardContent).find()) { addURL.setText(clipboardContent); } saveAs.setText(System.getProperty("user.home")+File.separator+"Downloads"); saveAs.setPrefColumnCount(20); GridPane.setConstraints(saveAs, 0, 1); grid.getChildren().addAll(addURL, saveAs); Button okbtn = new Button("OK"); okbtn.setPrefWidth(100); GridPane.setConstraints(okbtn, 1, 0); Button cancelbtn = new Button("Cancel"); cancelbtn.setPrefWidth(100); cancelbtn.setCancelButton(true); GridPane.setConstraints(cancelbtn, 1, 1); Button browsebtn = new Button("Browse"); browsebtn.setPrefWidth(100); GridPane.setConstraints(browsebtn, 0, 2); final Label label = new Label(); GridPane.setConstraints(label, 0, 3); GridPane.setColumnSpan(label, 1); grid.getChildren().addAll(okbtn,cancelbtn,browsebtn,label); // event when "OK" is clicked okbtn.setOnAction(new EventHandler<ActionEvent>() { @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void handle(ActionEvent e) { Boolean URLvalid = (Pattern.compile("((mailto\\:|(news|(ht|f)tp(s?))\\://){1}\\S+)").matcher(addURL.getText()).find()); if ((addURL.getText() != null && !addURL.getText().isEmpty()) && URLvalid){ popup.close(); String[] batchList = (addURL.getText().split("\n")); for(int i=0; i<batchList.length; ++i){ final int index = i; new Thread(){ public void run(){ uid++; DownloadUnit dUnit = new DownloadUnit(batchList[index]); dUnit.setProperty(DownloadUnit.TableField.FOLDER, (String)saveAs.getText()); dUnit.setUID(uid); idToDunit.put(uid, dUnit); Downloader dwnld = new Downloader(dUnit); Logger.debug(dUnit.getUID()+""); idToDownloader.put(uid, dwnld); downloadList.add(dUnit); dwnld.start(); } }.start(); } fileNameCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("filename")); sizeCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("size")); statusCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("status")); transferRateCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("transferRate")); resumeCapCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("resumeCap")); downloadedCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("downloaded")); percentageCol.setCellValueFactory(new PropertyValueFactory<DownloadUnit,String>("percentage")); resumeCapCol.setCellFactory(new Callback<TableColumn, TableCell>() { public TableCell call(TableColumn param) { return new TableCell<DownloadUnit, String>() { @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (!isEmpty()) { if(item.contains("Yes")) this.setTextFill(Color.GREEN); else if(item.contains("No")) this.setTextFill(Color.RED); setText(item); } else setText(null); } }; } }); } else label.setText("Please enter a URL"); } }); browsebtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { DirectoryChooser dc = new DirectoryChooser(); dc.setTitle("Browse Directory"); File file = dc.showDialog(null); if(file!=null) saveAs.setText(file.getPath()); } }); cancelbtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { popup.close(); } }); popup.show(); } }); playPausebtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { DownloadUnit selected = (DownloadUnit)table.getSelectionModel().getSelectedItem(); //function/java file is called that contain the functionality for pause/stop if(selected != null) { if (selected.getProperty(DownloadUnit.TableField.STATUS)=="Downloading") { //change button images Image playimage = new Image(getClass().getResourceAsStream("images/play.png")); playPausebtn.setGraphic(new ImageView(playimage)); idToDownloader.get(selected.getUID()).pauseDownload(); } else if (selected.getProperty(DownloadUnit.TableField.STATUS)=="Paused") { idToDownloader.remove(selected.getUID()); selected.statusEnum = DownloadUnit.Status.RESUMED; Downloader dwnld = new Downloader(selected); idToDownloader.put(selected.getUID(), dwnld); dwnld.start(); selected.setProperty(DownloadUnit.TableField.STATUS,"Downloading"); //change button image Image pauseimage = new Image(getClass().getResourceAsStream("images/pause.png")); playPausebtn.setGraphic(new ImageView(pauseimage)); } } } }); stopbtn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { DownloadUnit selected = (DownloadUnit)table.getSelectionModel().getSelectedItem(); fileNameLabel.setText(""); sizeLabel.setText(""); statusLabel.setText(""); fileTypeLabel.setText(""); filePathLabel.setText(""); if(selected != null) { infoPane.getItems().removeAll(gridPane); gridPane.getChildren().removeAll(fileNameLabel,sizeLabel,statusLabel,fileTypeLabel,filePathLabel); topContainer.getChildren().remove(infoPane); /* destroy object and related temporary dependencies */ Downloader removed = idToDownloader.get(selected.getUID()); removed.destroyDownload(); idToDownloader.remove(selected.getUID()); idToDunit.remove(selected.getUID()); downloadList.remove(selected); } } }); } class TableClickHandler implements EventHandler<MouseEvent>{ @SuppressWarnings("rawtypes") @Override public void handle(MouseEvent event) { TableView tab = (TableView)event.getSource(); DownloadUnit selected = (DownloadUnit)tab.getSelectionModel().getSelectedItem(); if (selected != null && event.getClickCount()>1 && selected.getProperty(DownloadUnit.TableField.STATUS)=="Completed") { if (Desktop.isDesktopSupported()) { try { Desktop.getDesktop().open(new File((String)selected.getProperty(DownloadUnit.TableField.FOLDER))); } catch (IOException e) { e.printStackTrace(); } } } else if (event.getClickCount() == 1 && selected != null){ if (selected.getProperty(DownloadUnit.TableField.STATUS)=="Downloading") { Image pauseimage = new Image(getClass().getResourceAsStream("images/pause.png")); playPausebtn.setGraphic(new ImageView(pauseimage)); } else if (selected.getProperty(DownloadUnit.TableField.STATUS)=="Paused") { Image playimage = new Image(getClass().getResourceAsStream("images/play.png")); playPausebtn.setGraphic(new ImageView(playimage)); } infoPane.getItems().removeAll(gridPane); gridPane.getChildren().removeAll(fileNameLabel, sizeLabel, statusLabel, fileTypeLabel, filePathLabel); topContainer.getChildren().remove(infoPane); if(selected!=null){ fileNameLabel.setText("File Name: "+(String)selected.getProperty(DownloadUnit.TableField.FILENAME)); sizeLabel.setText("File Size: "+(String)selected.getProperty(DownloadUnit.TableField.SIZE)); statusLabel.setText("Status: "+(String)selected.getProperty(DownloadUnit.TableField.STATUS)); fileTypeLabel.setText("File Type: "+(String)selected.getProperty(DownloadUnit.TableField.TYPE)); filePathLabel.setText("File Location: "+(String)selected.getProperty(DownloadUnit.TableField.FOLDER)); } GridPane.setConstraints(fileNameLabel, 0, 0); GridPane.setConstraints(sizeLabel, 0, 1); GridPane.setConstraints(statusLabel, 0, 2); GridPane.setConstraints(fileTypeLabel, 0, 3); GridPane.setConstraints(filePathLabel, 0, 4); gridPane.getChildren().addAll(fileNameLabel, sizeLabel, statusLabel, fileTypeLabel,filePathLabel); infoPane.getItems().add(gridPane); topContainer.getChildren().add(infoPane); } } } }