Skip to content

Commit e8bd5b3

Browse files
committed
#19 Open executions in the tab of the main window
1 parent 9ae1538 commit e8bd5b3

File tree

6 files changed

+78
-100
lines changed

6 files changed

+78
-100
lines changed

src/main/java/com/github/introfog/gitwave/controller/main/DirectoryTabController.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ public boolean isValid() {
4242
LOGGER.warn("Directory '{}' is empty, running git command was skipped.", directory.getText());
4343
DialogFactory.createErrorAlert("Invalid directory", "Directory can't be empty.");
4444
return false;
45+
} else {
46+
File directoryToRunIn = new File(directory.getText());
47+
if (!directoryToRunIn.exists() || !directoryToRunIn.isDirectory()) {
48+
DialogFactory.createInfoAlert("Invalid directory",
49+
"Specified directory either doesn't exist or isn't a directory.");
50+
return false;
51+
}
4552
}
4653
return true;
4754
}

src/main/java/com/github/introfog/gitwave/controller/main/ExecutionController.java

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,51 @@
1616

1717
package com.github.introfog.gitwave.controller.main;
1818

19-
import com.github.introfog.gitwave.controller.BaseController;
20-
import com.github.introfog.gitwave.model.StageFactory;
21-
import com.github.introfog.gitwave.model.StageFactory.FxmlStageHolder;
22-
19+
import java.util.Map;
2320
import javafx.application.Platform;
24-
import javafx.fxml.FXML;
21+
import javafx.geometry.Insets;
22+
import javafx.scene.control.Tab;
23+
import javafx.scene.control.TabPane;
2524
import javafx.scene.input.KeyCode;
25+
import org.fxmisc.flowless.VirtualizedScrollPane;
2626
import org.fxmisc.richtext.InlineCssTextArea;
2727

28-
public class ExecutionController extends BaseController {
29-
@FXML
30-
private InlineCssTextArea canvas;
31-
28+
public class ExecutionController {
3229
private boolean wasClosed = false;
3330
private boolean isExecutionFinished = false;
31+
private final InlineCssTextArea canvas;
32+
private final Tab tab;
33+
private final TabPane tabPane;
34+
private final Map<Tab, ExecutionController> executionTabs;
35+
36+
public ExecutionController(TabPane tabPane, Map<Tab, ExecutionController> executionTabs) {
37+
canvas = new InlineCssTextArea("Searching git repositories...");
38+
canvas.setEditable(false);
39+
canvas.setFocusTraversable(false);
40+
canvas.setPadding(new Insets(10, 2, 2, 2));
41+
canvas.setStyle("-fx-font-family: verdana; -fx-font-size: 12;");
42+
43+
VirtualizedScrollPane<InlineCssTextArea> scrollPane = new VirtualizedScrollPane<>(canvas);
44+
45+
tab = new Tab("Execution " + tabPane.getTabs().size());
46+
tab.setContent(scrollPane);
3447

35-
@Override
36-
public void initialize(FxmlStageHolder fxmlStageHolder) {
37-
super.initialize(fxmlStageHolder);
38-
fxmlStageHolder.getStage().setOnCloseRequest(event -> {
39-
beforeStageClose();
48+
tabPane.getTabs().add(tab);
49+
tabPane.getSelectionModel().select(tab);
50+
canvas.requestFocus();
51+
52+
this.executionTabs = executionTabs;
53+
this.tabPane = tabPane;
54+
executionTabs.put(tab, this);
55+
56+
tab.setOnCloseRequest(event -> {
57+
close();
4058
});
4159
canvas.setOnKeyPressed(event -> {
4260
if (event.getCode() == KeyCode.ESCAPE || event.getCode() == KeyCode.ENTER) {
4361
if (isExecutionFinished) {
44-
closeStage();
45-
}
46-
}
47-
});
48-
fxmlStageHolder.getScene().setOnKeyPressed(event -> {
49-
if (event.getCode() == KeyCode.ESCAPE || event.getCode() == KeyCode.ENTER) {
50-
if (isExecutionFinished) {
51-
closeStage();
62+
tabPane.getTabs().remove(tab);
63+
close();
5264
}
5365
}
5466
});
@@ -82,10 +94,15 @@ public boolean wasClosed() {
8294
return wasClosed;
8395
}
8496

85-
@Override
86-
protected void closeStage() {
87-
beforeStageClose();
88-
super.closeStage();
97+
public void close() {
98+
wasClosed = true;
99+
executionTabs.remove(tab);
100+
if (!tabPane.getTabs().isEmpty()) {
101+
Tab previousTab = tabPane.getTabs().get(tabPane.getTabs().size() - 1);
102+
if (executionTabs.get(previousTab) != null) {
103+
executionTabs.get(previousTab).canvas.requestFocus();
104+
}
105+
}
89106
}
90107

91108
private void commonWritingPart(String line, String style) {
@@ -95,9 +112,4 @@ private void commonWritingPart(String line, String style) {
95112
canvas.requestFollowCaret();
96113
});
97114
}
98-
99-
private void beforeStageClose() {
100-
wasClosed = true;
101-
StageFactory.unregisterExecutingController(this);
102-
}
103115
}

src/main/java/com/github/introfog/gitwave/controller/main/MainController.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,23 @@
2020
import com.github.introfog.gitwave.model.AppConfig;
2121
import com.github.introfog.gitwave.model.AppConstants;
2222
import com.github.introfog.gitwave.model.CommandExecutor;
23-
import com.github.introfog.gitwave.model.DialogFactory;
24-
import com.github.introfog.gitwave.model.StageFactory;
2523
import com.github.introfog.gitwave.model.StageFactory.FxmlStageHolder;
2624
import com.github.introfog.gitwave.model.dto.ParameterDto;
2725

2826
import java.io.File;
27+
import java.util.ArrayList;
28+
import java.util.HashMap;
2929
import java.util.List;
30+
import java.util.Map;
3031
import javafx.concurrent.Task;
3132
import javafx.fxml.FXML;
3233
import javafx.scene.control.Button;
3334
import javafx.scene.control.Label;
3435
import javafx.scene.control.Menu;
3536
import javafx.scene.control.MenuItem;
3637
import javafx.scene.control.SeparatorMenuItem;
38+
import javafx.scene.control.Tab;
39+
import javafx.scene.control.TabPane;
3740
import javafx.scene.control.TableView;
3841
import javafx.scene.control.TextField;
3942
import javafx.stage.Stage;
@@ -65,6 +68,10 @@ public class MainController extends BaseController {
6568
@FXML
6669
private SeparatorMenuItem updateMenuItemSeparator;
6770

71+
@FXML
72+
private TabPane executionTabPage;
73+
private final Map<Tab, ExecutionController> executionTabs = new HashMap<>();
74+
6875
@Override
6976
public void initialize(FxmlStageHolder fxmlStageHolder) {
7077
super.initialize(fxmlStageHolder);
@@ -73,9 +80,10 @@ public void initialize(FxmlStageHolder fxmlStageHolder) {
7380
event.consume();
7481

7582
AppConfig.getInstance().closeApp();
76-
for (ExecutionController executionController : StageFactory.getExecutingControllers()) {
77-
executionController.getStage().close();
83+
for (ExecutionController controller: new ArrayList<>(executionTabs.values())) {
84+
controller.close();
7885
}
86+
executionTabPage.getTabs().clear();
7987
primaryStage.close();
8088
});
8189

@@ -113,23 +121,16 @@ protected void runCommand() {
113121
&& commandTabController.isValid() && parametersTabController.isValid()) {
114122

115123
File directoryToRunIn = new File(directoryTabController.getDirectory());
116-
if (!directoryToRunIn.exists() || !directoryToRunIn.isDirectory()) {
117-
DialogFactory.createInfoAlert("Invalid directory",
118-
"Specified directory either doesn't exist or isn't a directory.");
119-
return;
120-
}
121124
AppConfig.getInstance().setLastRunFolder(directoryToRunIn.getAbsolutePath());
122125

123-
final FxmlStageHolder executionWindow = StageFactory.createNoneModalExecutionWindow();
124-
executionWindow.getStage().show();
125-
ExecutionController executionController = executionWindow.getFxmlLoader().getController();
126126

127+
ExecutionController controller = new ExecutionController(executionTabPage, executionTabs);
127128
new Thread(new Task<>() {
128129
@Override
129130
protected Void call() {
130131
final List<File> repositoriesToRunCommand = CommandExecutor.searchGitRepositories(directoryToRunIn);
131132

132-
CommandExecutor.executeCommand(repositoriesToRunCommand, executionController,
133+
CommandExecutor.executeCommand(repositoriesToRunCommand, controller,
133134
commandTabController.getCommandWithParameters());
134135
return null;
135136
}

src/main/java/com/github/introfog/gitwave/model/StageFactory.java

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,9 @@
1919
import com.github.introfog.gitwave.GitWaveLauncher;
2020
import com.github.introfog.gitwave.controller.BaseController;
2121
import com.github.introfog.gitwave.controller.EditController;
22-
import com.github.introfog.gitwave.controller.main.ExecutionController;
2322
import com.github.introfog.gitwave.model.dto.CommandDto;
2423

2524
import java.io.IOException;
26-
import java.util.HashSet;
27-
import java.util.Set;
2825
import javafx.fxml.FXMLLoader;
2926
import javafx.scene.Scene;
3027
import javafx.scene.image.Image;
@@ -36,36 +33,10 @@
3633
public final class StageFactory {
3734
private static final Logger LOGGER = LoggerFactory.getLogger(StageFactory.class);
3835

39-
private static final Set<ExecutionController> executingControllers = new HashSet<>();
40-
4136
private StageFactory() {
4237
// private constructor
4338
}
4439

45-
public static void registerExecutionController(ExecutionController executionController) {
46-
executingControllers.add(executionController);
47-
}
48-
49-
public static void unregisterExecutingController(ExecutionController executionController) {
50-
executingControllers.remove(executionController);
51-
}
52-
53-
public static Set<ExecutionController> getExecutingControllers() {
54-
return executingControllers;
55-
}
56-
57-
public static FxmlStageHolder createNoneModalExecutionWindow() {
58-
FxmlStageHolder holder = StageFactory.createNoneModalStage("view/execution.fxml", "Command execution result");
59-
holder.getStage().setMinWidth(200);
60-
holder.getStage().setMinHeight(200);
61-
int alreadyOpenedExecutors = getExecutingControllers().size();
62-
int shift = 20;
63-
holder.getStage().setX(100 + (alreadyOpenedExecutors * shift));
64-
holder.getStage().setY(100 + (alreadyOpenedExecutors * shift));
65-
registerExecutionController(holder.getFxmlLoader().getController());
66-
return holder;
67-
}
68-
6940
public static FxmlStageHolder createModalExploreWindow() {
7041
FxmlStageHolder holder = StageFactory.createModalStage("view/explorer.fxml", "Command explorer");
7142
holder.getStage().setMinWidth(400);
@@ -111,7 +82,7 @@ public static FxmlStageHolder createModalUpdateWindow() {
11182
public static FxmlStageHolder createPrimaryExecuteWindow(Stage stage) {
11283
final FxmlStageHolder holder = creteStage("view/main.fxml", "GitWave", stage);
11384
holder.getStage().setMinWidth(400);
114-
holder.getStage().setMinHeight(340);
85+
holder.getStage().setMinHeight(500);
11586
return holder;
11687
}
11788

src/main/resources/com/github/introfog/gitwave/view/execution.fxml

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/main/resources/com/github/introfog/gitwave/view/main.fxml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22

3+
<?import javafx.geometry.Insets?>
34
<?import javafx.scene.control.Button?>
45
<?import javafx.scene.control.Hyperlink?>
56
<?import javafx.scene.control.Label?>
@@ -18,16 +19,17 @@
1819
<?import javafx.scene.layout.GridPane?>
1920
<?import javafx.scene.layout.RowConstraints?>
2021
<?import javafx.scene.text.Font?>
21-
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="450.0" style="-fx-font-family: verdana; -fx-font-size: 12;" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.github.introfog.gitwave.controller.main.MainController">
22+
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" style="-fx-font-family: verdana; -fx-font-size: 12;" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.github.introfog.gitwave.controller.main.MainController">
2223
<children>
2324
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
2425
<columnConstraints>
2526
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
2627
</columnConstraints>
2728
<rowConstraints>
2829
<RowConstraints maxHeight="25.0" minHeight="25.0" prefHeight="25.0" vgrow="NEVER" />
29-
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
30-
<RowConstraints maxHeight="63.0" minHeight="63.0" prefHeight="63.0" vgrow="NEVER" />
30+
<RowConstraints maxHeight="212.0" minHeight="212.0" prefHeight="212.0" vgrow="SOMETIMES" />
31+
<RowConstraints maxHeight="40.0" minHeight="40.0" prefHeight="40.0" vgrow="NEVER" />
32+
<RowConstraints minHeight="63.0" vgrow="NEVER" />
3133
</rowConstraints>
3234
<children>
3335
<MenuBar prefHeight="25.0" prefWidth="450.0" GridPane.vgrow="NEVER">
@@ -122,17 +124,23 @@
122124
</TabPane>
123125
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2" GridPane.vgrow="NEVER">
124126
<children>
125-
<Button layoutX="386.0" layoutY="36.0" mnemonicParsing="false" onAction="#runCommand" text="4. Run" AnchorPane.bottomAnchor="20.0" AnchorPane.rightAnchor="20.0">
127+
<Separator layoutY="17.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
128+
<Button layoutX="386.0" layoutY="36.0" mnemonicParsing="false" onAction="#runCommand" text="4. Run" AnchorPane.bottomAnchor="9.0" AnchorPane.rightAnchor="20.0">
126129
<font>
127130
<Font name="Verdana" size="12.0" />
128131
</font></Button>
129132
<Hyperlink focusTraversable="false" layoutY="25.0" onAction="#foundIssue" text="Found an issue?" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0">
130133
<font>
131134
<Font name="Verdana" size="12.0" />
132135
</font></Hyperlink>
133-
<Separator layoutY="17.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
136+
<Separator prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
134137
</children>
135138
</AnchorPane>
139+
<TabPane fx:id="executionTabPage" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="ALL_TABS" GridPane.hgrow="ALWAYS" GridPane.rowIndex="3" GridPane.vgrow="ALWAYS">
140+
<GridPane.margin>
141+
<Insets bottom="20.0" left="20.0" right="20.0" />
142+
</GridPane.margin>
143+
</TabPane>
136144
</children>
137145
</GridPane>
138146
</children>

0 commit comments

Comments
 (0)