/**
* 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);
}
}