Skip to content

Commit

Permalink
Added suggestions list view
Browse files Browse the repository at this point in the history
Major refactoring, exception handling and improved logging
  • Loading branch information
st4s1k committed Apr 1, 2022
1 parent 569f4ef commit bc360ce
Show file tree
Hide file tree
Showing 46 changed files with 2,282 additions and 883 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/.idea/
/LeagueTeamComp.iml
/out/
/logs/
25 changes: 13 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,7 @@
<artifactId>javafx-fxml</artifactId>
<version>${javafx-fxml.version}</version>
</dependency>
<!-- Misc -->
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>${controlsfx.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
Expand All @@ -67,6 +56,18 @@
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- Misc -->
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>${controlsfx.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down
105 changes: 67 additions & 38 deletions src/main/java/com/st4s1k/leagueteamcomp/LeagueTeamCompApplication.java
Original file line number Diff line number Diff line change
@@ -1,99 +1,128 @@
package com.st4s1k.leagueteamcomp;

import com.google.gson.Gson;
import com.st4s1k.leagueteamcomp.controller.LTCExceptionController;
import com.st4s1k.leagueteamcomp.controller.LeagueTeamCompController;
import com.st4s1k.leagueteamcomp.model.champion.Champions;
import com.st4s1k.leagueteamcomp.exceptions.LTCException;
import com.st4s1k.leagueteamcomp.model.champion.ChampionsDTO;
import com.st4s1k.leagueteamcomp.repository.ChampionRepository;
import com.st4s1k.leagueteamcomp.utils.ResizeHelper;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.text.MessageFormat;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.stream.DoubleStream;

import static com.st4s1k.leagueteamcomp.utils.Resources.*;
import static java.net.http.HttpResponse.BodyHandlers;
import static java.util.Objects.requireNonNull;

@Slf4j
public class LeagueTeamCompApplication extends Application {

/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Resource path constants *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */

public static final String ICON_FILE_PATH = "icon.png";
public static final String FXML_FILE_PATH = "ltc-view.fxml";
public static final String APP_BUNDLE_PATH = "com.st4s1k.leagueteamcomp.ltc";
public static final String FXML_BUNDLE_PATH = "com.st4s1k.leagueteamcomp.ltc-view";

/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Window constants *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */

private static final String WINDOW_TITLE = "League of Legends Team Composition Tool";
private static final int WINDOW_WIDTH = 800;
private static final int WINDOW_HEIGHT = 600;
private static final boolean WINDOW_IS_RESIZABLE = false;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Resource bundles *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */

private final ResourceBundle ltcProperties = ResourceBundle.getBundle(APP_BUNDLE_PATH);
private final ResourceBundle ltcViewProperties = ResourceBundle.getBundle(FXML_BUNDLE_PATH);

public static void main(String[] args) {
launch();
}

@Override
@SneakyThrows
public void start(Stage stage) {
ChampionRepository.init(getChampionsFromUrl());
FXMLLoader loader = new FXMLLoader(getClass().getResource(FXML_FILE_PATH), ltcViewProperties);
Thread.setDefaultUncaughtExceptionHandler(LeagueTeamCompApplication::showError);
getChampionsFromUrl();
FXMLLoader loader = new FXMLLoader(getClass().getResource(FXML_FILE_PATH), LTC_VIEW_PROPERTIES);
Parent root = loader.load();
LeagueTeamCompController controller = loader.getController();
controller.setStageAndSetupListeners(stage);
controller.setCloseButtonAction(() -> closeProgram(stage, controller));
controller.setCloseButtonAction(() -> closeProgram(stage, controller));
controller.setMinimizeButtonAction(() -> stage.setIconified(true));
Scene scene = new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT);
stage.initStyle(StageStyle.TRANSPARENT);
scene.setFill(Color.TRANSPARENT);
stage.setScene(scene);
stage.getIcons().add(new Image(requireNonNull(getClass().getResourceAsStream(ICON_FILE_PATH))));
stage.setTitle(WINDOW_TITLE);
stage.setResizable(WINDOW_IS_RESIZABLE);
stage.initStyle(StageStyle.UNDECORATED);
stage.show();
}

@SneakyThrows
private CompletableFuture<Champions> getChampionsFromUrl() {
private void getChampionsFromUrl() {
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(ltcProperties.getString("champions-url")))
.uri(new URI(CHAMPIONS_URL))
.build();
return HttpClient.newHttpClient()
HttpClient.newHttpClient()
.sendAsync(request, BodyHandlers.ofString())
.thenApply(this::getChampions);
.thenApply(this::getChampions)
.thenAccept(ChampionRepository::init);
}

private Champions getChampions(HttpResponse<String> response) {
private ChampionsDTO getChampions(HttpResponse<String> response) {
String json = MessageFormat.format("'{'\"champions\":{0}'}'", response.body());
Champions champions = new Gson().fromJson(json, Champions.class);
ChampionsDTO champions = new Gson().fromJson(json, ChampionsDTO.class);
champions.getChampions().values()
.forEach(champion -> champion.setImage(new Image(champion.getIconUrl(), true)));
return champions;
}

private static void showError(Thread t, Throwable e) {
log.error("***Default exception handler***");
if (Platform.isFxApplicationThread()) {
showErrorDialog(e);
} else {
log.error("An unexpected error occurred in " + t);
}
}

@SneakyThrows
private static void showErrorDialog(Throwable e) {
StringWriter errorMsg = new StringWriter();
e.printStackTrace(new PrintWriter(errorMsg));
Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
FXMLLoader loader = new FXMLLoader(LeagueTeamCompApplication.class.getResource("ltc-exception.fxml"));
Region root = loader.load();
LTCExceptionController controller = loader.getController();
controller.setStageAndSetupListeners(dialog);
int sceneWidth = 600;
int sceneHeight = 400;
if (e instanceof LTCException ltcException) {
sceneWidth = 300;
sceneHeight = 150;
controller.setErrorText(ltcException.getMessage());
} else {
controller.setErrorText(errorMsg.toString());
}
Scene scene = new Scene(root, sceneWidth, sceneHeight);
scene.setFill(Color.TRANSPARENT);
dialog.initStyle(StageStyle.TRANSPARENT);
dialog.setScene(scene);
dialog.setMinHeight(sceneHeight);
dialog.setMinWidth(sceneWidth);
Insets padding = root.getPadding();
double border = DoubleStream.of(padding.getTop(), padding.getRight(), padding.getBottom(), padding.getLeft())
.min().orElse(4);
ResizeHelper.addResizeListener(dialog, border);
dialog.show();
}

private void closeProgram(Stage stage, LeagueTeamCompController controller) {
log.info("Closing application...");
controller.stop();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.st4s1k.leagueteamcomp.controller;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ResourceBundle;

public class LTCExceptionController implements Initializable {

private static double xOffset = 0;
private static double yOffset = 0;

@FXML
private Button minimizeButton;
@FXML
private Button closeButton;
@FXML
private Button okButton;
@FXML
private TextArea errorMessage;
@FXML
private HBox windowTitleBar;

@Override
public void initialize(URL location, ResourceBundle resources) {
errorMessage.setEditable(false);
}

public void setStageAndSetupListeners(Stage stage) {
windowTitleBar.setOnMousePressed(event -> {
xOffset = stage.getX() - event.getScreenX();
yOffset = stage.getY() - event.getScreenY();
});
windowTitleBar.setOnMouseDragged(event -> {
stage.setX(event.getScreenX() + xOffset);
stage.setY(event.getScreenY() + yOffset);
});
windowTitleBar.setOnMouseClicked(event -> {
if (event.getButton().equals(MouseButton.PRIMARY)) {
if (event.getClickCount() == 2) {
stage.setMaximized(!stage.isMaximized());
}
}
});
okButton.setOnAction(event -> stage.close());
closeButton.setOnAction(actionEvent -> stage.close());
minimizeButton.setOnAction(actionEvent -> stage.setIconified(true));
}

public void setErrorText(String text) {
errorMessage.setText(text);
}
}
Loading

0 comments on commit bc360ce

Please sign in to comment.