/** * Copyright 2015 GitFx * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package io.github.gitfx.controller; import io.github.gitfx.dialog.GitFxDialog; import io.github.gitfx.dialog.GitFxDialogResponse; import io.github.gitfx.GitFxApp; import io.github.gitfx.GitResourceBundle; import io.github.gitfx.data.GitRepoMetaData; import io.github.gitfx.data.ProjectData; import io.github.gitfx.data.RepositoryData; import io.github.gitfx.util.GitFXGsonUtil; import io.github.gitfx.util.WorkbenchUtil; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.ResourceBundle; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.fxml.FXML; //import javafx.event.EventHandler; //import javafx.event.Event; import javafx.fxml.Initializable; import javafx.scene.control.*; //import javafx.scene.effect.BlendMode; import javafx.scene.layout.AnchorPane; //import javafx.scene.layout.Background; //import javafx.scene.layout.Region; //import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.util.Pair; import org.eclipse.jgit.api.errors.GitAPIException; import com.jcabi.aspects.Loggable; //[LOG] import org.slf4j.Logger; //[LOG] import org.slf4j.LoggerFactory; import javafx.scene.layout.Pane; @Loggable public class GitFxController implements Initializable { // Logger logger = LoggerFactory.getLogger(GitFxApp.class.getName()); @FXML private Button gitclone; @FXML private Button gitsettings; @FXML private MenuItem gitSyncEverything; @FXML private Button gitinit; @FXML private Button gitopen; @FXML private MenuItem gitSpecific; @FXML private MenuButton gitsync; @FXML private TreeView<String> RepositoryTree; // Shouldn't we rename this name to repositoryTree @FXML private Accordion historyAccordion; @FXML private Label commits; @FXML private AnchorPane treeContainer; @FXML private AnchorPane historyContainer; @FXML private AnchorPane diffContainer; @FXML private TextArea diffArea; //[DOUBT] Shouldn't we either remove this or the duplicate declaration in the addProgressIndiactor() private ProgressIndicator pi; private GitFxDialog dialog; // Reference to the main application private GitFxApp gitFxApp; private ResourceBundle resourceBundle; /** * Reference to GitFxApp. * * @param gitFxApp]' */ public void setMainApp(GitFxApp gitFxApp) { this.gitFxApp = gitFxApp; resourceBundle = new GitResourceBundle().getBundle(); } @Override public void initialize(URL url, ResourceBundle rb) { Font.loadFont(GitFxController.class.getResource("/fonts/fontawesome-webfont.ttf").toExternalForm(), 12); //[CHANGE] I think we should use some common resource from where all these values are fetched... gitinit.setText('\uf04b' + ""); gitopen.setText('\uf07c' + ""); gitsettings.setText('\uf013' + ""); gitsync.setText('\uf021' + ""); gitclone.setText('\uf0c5' + ""); RepositoryTree.getSelectionModel().selectedItemProperty().addListener( (observable, oldValue, newValue) -> { TreeItem<String> selectedItem = (TreeItem<String>) newValue; if (selectedItem != null) { //[LOG] logger.debug("Selected Text" + selectedItem.getValue()); addProgressIndicator(historyContainer); if (!selectedItem.getValue().equals("github")) initializeHistoryAccordion(selectedItem.getValue()); } }); GitFXGsonUtil.checkRepoInformation(); initializeTree(); initializeHistoryAccordion(); } /* * Method which initializes the Repository Tree Panel * Possible clients calls from * 1) Applicaiton Initialize event * 2) Initialization of a New Repository */ private void initializeTree() { RepositoryData metaData = GitFXGsonUtil.getRepositoryMetaData(); if (metaData != null) { TreeItem<String> treeRoot = new TreeItem<>(metaData.getServerName()); treeRoot.setExpanded(true); List<ProjectData> projectData = metaData.getRepositories(); projectData.stream().forEach((project) -> { treeRoot.getChildren().add(new TreeItem<>(project.getProjectName())); }); RepositoryTree.setShowRoot(true); RepositoryTree.setRoot(treeRoot); } } //Method adds a progress indicator to a container of type Pane private void addProgressIndicator(Pane container) { ProgressIndicator pi = new ProgressIndicator(); container.getChildren().add(pi); pi.setLayoutX(container.getWidth() / 2 - 20); pi.setLayoutY(container.getHeight() / 2) ; //[LOG] logger.debug(String.valueOf(container.getWidth())); pi.setPrefSize(50, 50); delayProgressIndicator(pi); } //Method simulates a delay on the progress indicator private void delayProgressIndicator(ProgressIndicator pi) { new Thread(new Runnable() { @Override public void run() { try { pi.setVisible(true); Thread.sleep(500); } catch (InterruptedException exception) { //[LOG] logger.debug("Interruped Exception"+exception.getMessage()); } finally { Platform.runLater(new Runnable() { public void run() { pi.setVisible(false); } }); } } }).start(); } /* * By default load the first repository in the first server listed in tree */ private void initializeHistoryAccordion() { RepositoryData repoData = GitFXGsonUtil.getRepositoryMetaData(); //If application is loaded for the first time the metaData will be missing if (repoData != null) { GitRepoMetaData metaData = GitFXGsonUtil.getGitRepositoryMetaData(repoData.getFirstRepoPath()); initializeHistoryAccordion(metaData); } } /* * Given a projectName find the repoPath from the JSON and initialize the * History accordion accordingly */ private void initializeHistoryAccordion(String projectName) { RepositoryData repoData = GitFXGsonUtil.getRepositoryMetaData(); String repoPath = repoData.getRepoPath(projectName); GitRepoMetaData metaData = GitFXGsonUtil.getGitRepositoryMetaData(repoPath); //addProgressIndicator(); initializeHistoryAccordion(metaData); } /* * Given the GitRepoMetaData load the accordion with the repository * commit history */ private void initializeHistoryAccordion(GitRepoMetaData metaData) { ObservableList<TitledPane> panes = historyAccordion.getPanes(); historyAccordion.expandedPaneProperty().addListener(new ChangeListener<TitledPane>() { @Override public void changed(ObservableValue<? extends TitledPane> observable, TitledPane oldValue, TitledPane newValue) { if(newValue!=null) { try { //[LOG] logger.debug("Accordion expanded with oldvalue" + newValue.getId()); diffArea.setWrapText(true); diffArea.setText(metaData.getDiffBetweenCommits(Integer.parseInt(newValue.getId()))); }catch(GitAPIException | IOException ex){ //[LOG] logger.debug("Something went wrong in getting commit history"); } } } }); if (panes != null) { historyAccordion.getPanes().removeAll(panes); } if(metaData == null){ commits.setText("Empty Repository!"); } else{ ArrayList<String> list = metaData.getShortMessage(); ArrayList<ArrayList<String>> commitFiles = metaData.getCommitFiles(); TitledPane pane; int i = 0; for (String str : list) { ListView<String> changedFiles = new ListView<>(); changedFiles.autosize(); pane = new TitledPane(str, changedFiles); pane.setId(String.valueOf(i)); changedFiles.setItems(FXCollections.observableArrayList(commitFiles.get(i++))); changedFiles.maxHeight(Double.MAX_VALUE); //Specifying a height here as without height repo's with more commits //were not expanding to show commits pane.setMaxHeight(50); historyAccordion.getPanes().add(pane); } //Show number of commits on top of history accordion commits.setText(metaData.getCommitCount() + " commits"); } } @FXML public void onGitSettingsClicked(ActionEvent event) { } @FXML public void onGitCloneClicked(ActionEvent event) { dialog = new GitFxDialog(); Pair<String, String> clonedRepo = dialog.gitCloneDialog(resourceBundle.getString("cloneRepo"), resourceBundle.getString("cloneRepo"), null); if (dialog.getResponse() == GitFxDialogResponse.CLONE && clonedRepo != null) { //[LOG] logger.debug("Response Ok Repo Path"); String repoURL =clonedRepo.getKey(); String repoName=""; if(repoURL.contains(".git")) { repoName = repoURL.substring(repoURL.lastIndexOf("/")+1,repoURL.indexOf(".git")); } else { repoName = repoURL.substring(repoURL.lastIndexOf("/")+1); } String localPath = clonedRepo.getValue(); localPath = localPath +File.separator+repoName; //[LOG] logger.debug("Clone URL" + repoURL ); //[LOG] logger.debug("Local Path" + localPath); if(GitFXGsonUtil.cloneGitRepository(repoURL,localPath)) { GitRepoMetaData metaData = GitFXGsonUtil.getGitRepositoryMetaData(localPath); initializeHistoryAccordion(metaData); GitFXGsonUtil.saveRepositoryInformation("github", repoName,localPath); initializeTree(); } //[LOG] else{ //[LOG] logger.debug("Its not a Valid URL"); //[LOG] } } //[LOG] else { //[LOG] logger.debug("Response Cancel"); //[LOG] } } @FXML public void onGitOpenClicked(ActionEvent event) { dialog = new GitFxDialog(); String repoPath = dialog.gitOpenDialog(resourceBundle.getString("openRepo"), resourceBundle.getString("chooseRepo"), resourceBundle.getString("repo")); if (dialog.getResponse() == GitFxDialogResponse.OK) { //[LOG] logger.debug("Response Ok Repo Path" + repoPath); GitRepoMetaData metaData = GitFXGsonUtil.getGitRepositoryMetaData(repoPath); initializeHistoryAccordion(metaData); String repoName =repoPath.substring(repoPath.lastIndexOf(File.separator)+1); GitFXGsonUtil.saveRepositoryInformation("github", repoName, repoPath); initializeTree(); } //[LOG] else { //[LOG] logger.debug("Response Cancel"); //[LOG] } } @FXML public void onGitSyncClicked(ActionEvent event) { //[LOG] logger.debug("Sync particular repository"); } @FXML public void syncEveryThingClicked(ActionEvent event) { dialog = new GitFxDialog(); dialog.gitConfirmationDialog(resourceBundle.getString("sync"), resourceBundle.getString("syncAll"), resourceBundle.getString("syncAllDesc")); if (dialog.getResponse() == GitFxDialogResponse.OK) { //[LOG] logger.debug("Sync all clicked"); } //[LOG] else { //[LOG] logger.debug("Cancelled"); //[LOG] } } @FXML public void onGitInitClicked(ActionEvent event) { dialog = new GitFxDialog(); Pair<String, String> newRepo = dialog.gitInitDialog(resourceBundle.getString("initRepo"), resourceBundle.getString("initRepo"), null); if (dialog.getResponse() == GitFxDialogResponse.INITIALIZE && newRepo != null) { //[LOG] logger.debug("Git init clicked"); //[LOG] logger.debug("Project Name" + newRepo.getKey()); //[LOG] logger.debug("Local Path" + newRepo.getValue()); // [NOT USED] String path = WorkbenchUtil.getGitFxWorkbenchPath(); GitFXGsonUtil.saveRepositoryInformation("github", newRepo.getKey(), newRepo.getValue()); //Call a utility method to intitilize a repository initializeTree(); } //[LOG] else { //[LOG] logger.debug("Cancelled"); //[LOG] } } @FXML public void onGitParticularRepositoryClicked(ActionEvent event) { //[LOG] logger.debug("Git Particular Repository clicked"); dialog = new GitFxDialog(); RepositoryData metaData = GitFXGsonUtil.getRepositoryMetaData(); List<String> list = new ArrayList<>(); if(metaData!=null){ List<ProjectData> projectData = metaData.getRepositories(); projectData.stream().forEach(project -> list.add(project.getProjectName()) ); } dialog.gitFxInformationListDialog(resourceBundle.getString("syncRepo"), resourceBundle.getString("repo"),null,list); } }