forked from JanZmyslowski/SouRCE
-
Notifications
You must be signed in to change notification settings - Fork 0
Improving detaching tabs #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
eatpasta02
wants to merge
6
commits into
recruitment-2026
Choose a base branch
from
improving-detaching-tabs
base: recruitment-2026
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
ad5cb3d
new file: src/main/java/pl/edu/pwr/pwrinspace/poliwrocket/Controlle…
eatpasta02 3c0d5b0
new file: src/main/java/pl/edu/pwr/pwrinspace/poliwrocket/Controlle…
eatpasta02 b1ef184
drobne poprawki przy wygladzie(usuniecie dodawania tla na Gauge), usu…
eatpasta02 559ed83
deleting mistakenly added line
eatpasta02 6b56dd3
final small changes
eatpasta02 ec6ccee
modified: src/main/java/pl/edu/pwr/pwrinspace/poliwrocket/Contr…
eatpasta02 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
src/main/java/pl/edu/pwr/pwrinspace/poliwrocket/Controller/DetachedTabController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package pl.edu.pwr.pwrinspace.poliwrocket.Controller; | ||
|
|
||
| import javafx.beans.InvalidationListener; | ||
| import javafx.beans.Observable; | ||
| import javafx.fxml.FXML; | ||
| import javafx.scene.Node; | ||
| import javafx.scene.control.TabPane; | ||
| import javafx.scene.transform.Scale; | ||
| import javafx.stage.Stage; | ||
|
|
||
| public class DetachedTabController implements InvalidationListener { | ||
|
|
||
| @FXML | ||
| private TabPane detachedTabPane; | ||
|
|
||
| private Stage myStage; | ||
|
|
||
| private static final double initWidth = 1550.4; | ||
| private static final double initHeight = 838.4; | ||
|
|
||
| public TabPane getTabPane() { | ||
| return this.detachedTabPane; | ||
| } | ||
|
|
||
| public void setStage(Stage stage) { | ||
| this.myStage = stage; | ||
|
|
||
| stage.widthProperty().addListener(this); | ||
| stage.heightProperty().addListener(this); | ||
| } | ||
|
|
||
| @Override | ||
| public void invalidated(Observable observable) { | ||
| if (myStage.widthProperty().equals(observable) || myStage.heightProperty().equals(observable)) { | ||
| scaleContent(myStage.getWidth() / initWidth, myStage.getHeight() / initHeight); | ||
| } | ||
| } | ||
|
|
||
| private void scaleContent(double scaleX, double scaleY) { | ||
| if (detachedTabPane != null) { | ||
| if(!detachedTabPane.getTransforms().isEmpty()) { | ||
| detachedTabPane.getTransforms().clear(); | ||
| } | ||
| detachedTabPane.getTransforms().add(new Scale(scaleX, scaleY, 0, 0)); | ||
| } | ||
| } | ||
|
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,15 @@ | ||
| package pl.edu.pwr.pwrinspace.poliwrocket.Controller; | ||
|
|
||
| import com.interactivemesh.jfx.importer.ModelImporter; | ||
| import com.interactivemesh.jfx.importer.tds.TdsModelImporter; | ||
| import com.jfoenix.controls.JFXTextArea; | ||
| import eu.hansolo.medusa.Gauge; | ||
| import eu.hansolo.tilesfx.Tile; | ||
| import javafx.application.Platform; | ||
| import javafx.beans.InvalidationListener; | ||
| import javafx.beans.Observable; | ||
| import javafx.fxml.FXML; | ||
| import javafx.fxml.FXMLLoader; | ||
| import javafx.scene.*; | ||
| import javafx.scene.control.TabPane; | ||
| import javafx.scene.control.*; | ||
| import javafx.scene.image.Image; | ||
| import javafx.scene.image.ImageView; | ||
| import javafx.scene.layout.AnchorPane; | ||
|
|
@@ -21,9 +21,11 @@ | |
| import pl.edu.pwr.pwrinspace.poliwrocket.Model.MessageParser.IMessageParser; | ||
| import pl.edu.pwr.pwrinspace.poliwrocket.Model.SerialPort.ISerialPortManager; | ||
| import pl.edu.pwr.pwrinspace.poliwrocket.Thred.UI.UIThreadManager; | ||
| import pl.edu.pwr.pwrinspace.poliwrocket.Provider.DetachedWindowsProvider; | ||
|
|
||
| import java.io.IOException; | ||
| import java.lang.reflect.Field; | ||
| import java.net.URL; | ||
| import java.util.*; | ||
| import java.util.stream.Collectors; | ||
|
|
||
|
|
@@ -32,6 +34,12 @@ public class MainController extends BasicController implements InvalidationListe | |
| private static final double initWidth = 1550.4; | ||
| private static final double initHeight = 838.4; | ||
|
|
||
| private static final Color white = Color.WHITE ; | ||
| private static final Color bgDark = Color.rgb(11, 66, 116, 0.7); | ||
|
|
||
| private static final Color black = Color.BLACK; | ||
| private static final Color fgDark = Color.rgb(245, 245, 247); | ||
|
|
||
| @FXML | ||
| private SubScene CANIndicatorsScene; | ||
|
|
||
|
|
@@ -199,7 +207,6 @@ public SubScene getMapScene() { | |
| return mapScene; | ||
| } | ||
|
|
||
|
|
||
| public void initSubScenes(Collection<FXMLLoader> fxmlLoaders) { | ||
| try { | ||
| HashMap<String, Field> fields = new HashMap<>(); | ||
|
|
@@ -230,6 +237,8 @@ protected void initialize() { | |
| addNodesForAppScalingPurpose(); | ||
| setAppImages(); | ||
| setup3DModel(); | ||
|
|
||
| setupDetachedWindowsProvider(); | ||
| } | ||
|
|
||
| private void setAppImages() { | ||
|
|
@@ -328,6 +337,36 @@ public void invalidated(Observable observable) { | |
| } else { | ||
| outGoing.setStyle(""); | ||
| } | ||
|
|
||
| boolean isLight = ((Configuration) observable).isLightMode(); | ||
| URL cssURL = getClass().getResource(isLight ? "/Views/constantsLight.css" : "/Views/constants.css"); | ||
|
|
||
| if (cssURL == null) { | ||
| System.err.println("ERROR: css not found"); | ||
| return; | ||
| } | ||
|
|
||
| String cssPath = cssURL.toExternalForm(); | ||
|
|
||
| nodes.forEach(node -> { | ||
| applyStyleToNode(node, cssPath, isLight); | ||
| }); | ||
|
|
||
| for (Field field : this.getClass().getDeclaredFields()) { | ||
| if (field.getName().endsWith("Scene")) { | ||
| try { | ||
| field.setAccessible(true); | ||
| Object value = field.get(this); | ||
| if (value instanceof SubScene) { | ||
| SubScene ss = (SubScene) value; | ||
| applyStyleToNode(ss, cssPath, isLight); | ||
| findAndStyleTiles(ss.getRoot(), isLight); | ||
| } | ||
| } catch (IllegalAccessException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
| } | ||
| } else if(primaryStage.heightProperty().equals(observable) || primaryStage.widthProperty().equals(observable)) { | ||
| scaleSubScenes(primaryStage.widthProperty().doubleValue()/initWidth,primaryStage.heightProperty().doubleValue()/initHeight); | ||
| } | ||
|
|
@@ -342,11 +381,136 @@ private void scaleSubScenes(double scaleX, double scaleY) { | |
| if(!scene.getTransforms().isEmpty()) { | ||
| scene.getTransforms().clear(); | ||
| } | ||
|
|
||
| scene.getTransforms().add(new Scale(scaleX,scaleY)); | ||
| scene.setLayoutX(nodesInitPositions.get(scene).getValue0() * scaleX); | ||
| scene.setLayoutY(nodesInitPositions.get(scene).getValue1() * scaleY); | ||
| }); | ||
| } | ||
|
|
||
| private void setupDetachedWindowsProvider() { | ||
| if (tabPane != null) { | ||
| DetachedWindowsProvider.addActiveTabPane(tabPane); | ||
| } | ||
| for(int i = 0; i < Objects.requireNonNull(tabPane).getTabs().size(); i++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Można to wciągnąc pod pierwszego ifa, który właśnie sprawdza czy tabPane nie jest nullem i na koniec dodać else jakiś z informacja o tym, ze tabPane jest nullem |
||
| Tab tab = tabPane.getTabs().get(i); | ||
| tab.setUserData(i); | ||
| configureTabContextMenu(tab); | ||
| } | ||
| } | ||
|
|
||
| private void configureTabContextMenu(Tab tab){ | ||
| ContextMenu contextMenu = new ContextMenu(); | ||
|
|
||
| MenuItem newWindowItem = new MenuItem("Detach to a new window"); | ||
| newWindowItem.setOnAction(e -> detachTabToNewWindow(tab)); | ||
| contextMenu.getItems().add(newWindowItem); | ||
|
|
||
| Menu moveMenu = new Menu("Move to: "); | ||
|
|
||
| contextMenu.setOnShowing(e ->{ | ||
| moveMenu.getItems().clear(); | ||
| for(TabPane tabPane: DetachedWindowsProvider.getActiveTabPanes()){ | ||
| if(tabPane == tab.getTabPane()){ | ||
| continue; | ||
| } | ||
| String title = ((Stage) tabPane.getScene().getWindow()).getTitle(); | ||
| MenuItem item = new MenuItem(title); | ||
| item.setOnAction(ev-> { | ||
| DetachedWindowsProvider.transferTabPane(tab, tabPane); | ||
| configureTabContextMenu(tab); | ||
| }); | ||
| moveMenu.getItems().add(item); | ||
| } | ||
| }); | ||
| contextMenu.getItems().add(moveMenu); | ||
| tab.setContextMenu(contextMenu); | ||
| } | ||
|
|
||
| private void detachTabToNewWindow(Tab tab) { | ||
| tab.setUserData(tabPane.getTabs().indexOf(tab)); | ||
|
|
||
| try { | ||
| FXMLLoader loader = new FXMLLoader(getClass().getResource("/Views/DetachedTabView.fxml")); | ||
| Parent root = loader.load(); | ||
| DetachedTabController detachedController = loader.getController(); | ||
|
|
||
| Stage stage = new Stage(); | ||
| stage.setScene(new Scene(root, initWidth, initHeight)); | ||
| detachedController.setStage(stage); | ||
|
|
||
| TabPane newTabPane = detachedController.getTabPane(); | ||
| DetachedWindowsProvider.addActiveTabPane(newTabPane); | ||
| DetachedWindowsProvider.transferTabPane(tab, newTabPane); | ||
|
|
||
| String tabTitle = tab.getText(); | ||
| stage.setTitle("SouRCE - " + tabTitle); | ||
|
|
||
| stage.setOnCloseRequest(e -> { | ||
| DetachedWindowsProvider.removeActiveTabPane(newTabPane); | ||
|
|
||
| List<Tab> tabsToReturn = new ArrayList<>(newTabPane.getTabs()); | ||
| tabsToReturn.sort(Comparator.comparingInt(t -> (int) t.getUserData())); | ||
| for (Tab t : tabsToReturn) { | ||
| DetachedWindowsProvider.transferTabPane(t, this.tabPane); | ||
| configureTabContextMenu(t); | ||
| } | ||
| }); | ||
| stage.show(); | ||
| } catch (IOException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
|
|
||
| private void applyStyleToNode(Node node, String cssPath, boolean isLight) { | ||
| if (node instanceof Parent) { | ||
| Parent p = (Parent) node; | ||
| p.getStylesheets().clear(); | ||
| p.getStylesheets().add(cssPath); | ||
| } else if (node instanceof SubScene) { | ||
| SubScene ss = (SubScene) node; | ||
| if (ss.getRoot() != null) { | ||
| ss.getRoot().getStylesheets().clear(); | ||
| ss.getRoot().getStylesheets().add(cssPath); | ||
| findAndStyleTiles(ss.getRoot(), isLight); | ||
| }else{ | ||
| System.out.println("Error: Scene root cannot be null when applying styles"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void findAndStyleTiles(Parent root, boolean isLight) { | ||
| Color bg = isLight ? white : bgDark; | ||
| Color fg = isLight ? black : fgDark; | ||
| for (Node n : root.getChildrenUnmodifiable()) { | ||
| if (n instanceof Tile) { | ||
| Tile tile = (Tile) n; | ||
| applyTileStyle(tile, bg, fg); | ||
| }else if (n instanceof Gauge) { | ||
| Gauge gauge = (Gauge) n; | ||
| applyGaugeStyle(gauge, fg); | ||
| }if (n.getClass().getName().startsWith("pl.edu.pwr") && | ||
| !(n instanceof Tile || n instanceof Gauge || n instanceof Parent)) { | ||
| System.out.println("Unpredicted node ignored for styling:: " + n.getClass().getSimpleName()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void applyTileStyle(Tile tile, Color bg, Color fg) { | ||
| tile.setBackgroundColor(bg); | ||
| tile.setForegroundBaseColor(fg); | ||
| tile.setTitleColor(fg); | ||
| tile.setTextColor(fg); | ||
| tile.setValueColor(fg); | ||
| tile.setUnitColor(fg); | ||
| tile.setBarColor(fg); | ||
| } | ||
|
|
||
| private void applyGaugeStyle(Gauge gauge, Color fg) { | ||
| gauge.setBarColor(fg); | ||
| gauge.setValueColor(fg); | ||
| gauge.setTitleColor(fg); | ||
| gauge.setUnitColor(fg); | ||
| gauge.setTickLabelColor(fg); | ||
| gauge.setNeedleColor(fg); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,4 +60,4 @@ protected TextChannel getChannel(@NotNull MessageReceivedEvent event) { | |
| } | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mamy już 2 miejsca, w ktorych pojawiaja się te wartości. Można zrobić wspólne miejsce do jej przechowywania