mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Added most sound functionality.
There is not background music and sound effects (button clicking, ocean noises, crashes for collisions). Can mute the sound and the music independently of each other from the main menu. #story[1249]
This commit is contained in:
@@ -15,6 +15,7 @@ import org.apache.commons.cli.ParseException;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import seng302.model.PolarTable;
|
import seng302.model.PolarTable;
|
||||||
|
import seng302.utilities.Sounds;
|
||||||
|
|
||||||
public class App extends Application {
|
public class App extends Application {
|
||||||
|
|
||||||
@@ -67,6 +68,7 @@ public class App extends Application {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws Exception {
|
public void start(Stage primaryStage) throws Exception {
|
||||||
|
Sounds.playMenuMusic();
|
||||||
Parent root = FXMLLoader.load(getClass().getResource("/views/StartScreenView.fxml"));
|
Parent root = FXMLLoader.load(getClass().getResource("/views/StartScreenView.fxml"));
|
||||||
primaryStage.setTitle("Party Parrots at Sea");
|
primaryStage.setTitle("Party Parrots at Sea");
|
||||||
Scene scene = new Scene(root, 1530, 960);
|
Scene scene = new Scene(root, 1530, 960);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import javafx.collections.FXCollections;
|
|||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import seng302.model.stream.parser.RaceStartData;
|
import seng302.model.stream.parser.RaceStartData;
|
||||||
import seng302.model.stream.parser.RaceStatusData;
|
import seng302.model.stream.parser.RaceStatusData;
|
||||||
|
import seng302.utilities.Sounds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for storing race data that does not relate to specific vessels or marks such as time or wind.
|
* Class for storing race data that does not relate to specific vessels or marks such as time or wind.
|
||||||
@@ -34,6 +35,7 @@ public class RaceState {
|
|||||||
private long serverSystemTime;
|
private long serverSystemTime;
|
||||||
private long expectedStartTime;
|
private long expectedStartTime;
|
||||||
private boolean isRaceStarted = false;
|
private boolean isRaceStarted = false;
|
||||||
|
private boolean gunFired = false;
|
||||||
long timeTillStart;
|
long timeTillStart;
|
||||||
private ObservableList<ClientYacht> playerPositions;
|
private ObservableList<ClientYacht> playerPositions;
|
||||||
private List<ClientYacht> collisions = new ArrayList<>();
|
private List<ClientYacht> collisions = new ArrayList<>();
|
||||||
@@ -64,6 +66,10 @@ public class RaceState {
|
|||||||
if (raceTime < 0) {
|
if (raceTime < 0) {
|
||||||
return "-" + DATE_TIME_FORMAT.format(-1 * (raceTime - 1000));
|
return "-" + DATE_TIME_FORMAT.format(-1 * (raceTime - 1000));
|
||||||
} else {
|
} else {
|
||||||
|
if (!gunFired) {
|
||||||
|
gunFired = true;
|
||||||
|
Sounds.playCapGunSound();
|
||||||
|
}
|
||||||
return DATE_TIME_FORMAT.format(serverSystemTime - expectedStartTime);
|
return DATE_TIME_FORMAT.format(serverSystemTime - expectedStartTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package seng302.utilities;
|
||||||
|
|
||||||
|
import javafx.scene.media.Media;
|
||||||
|
import javafx.scene.media.MediaPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static class for playing sounds throughout the program
|
||||||
|
*
|
||||||
|
* Created by kre39 on 28/08/17.
|
||||||
|
*/
|
||||||
|
public class Sounds {
|
||||||
|
|
||||||
|
private static MediaPlayer musicPlayer;
|
||||||
|
private static MediaPlayer soundEffect;
|
||||||
|
private static MediaPlayer soundPlayer;
|
||||||
|
|
||||||
|
private static boolean musicMuted = false;
|
||||||
|
private static boolean soundEffectsMuted = false;
|
||||||
|
|
||||||
|
|
||||||
|
public static void stopMusic() {
|
||||||
|
musicPlayer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void toggleMuteMusic() {
|
||||||
|
musicMuted = !musicMuted;
|
||||||
|
musicPlayer.setMute(musicMuted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void toggleMuteEffects() {
|
||||||
|
soundEffectsMuted = !soundEffectsMuted;
|
||||||
|
if (soundPlayer != null) {
|
||||||
|
soundPlayer.setMute(soundEffectsMuted);
|
||||||
|
}
|
||||||
|
if (soundEffect != null) {
|
||||||
|
soundEffect.setMute(soundEffectsMuted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isMusicMuted() {
|
||||||
|
return musicMuted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSoundEffectsMuted() {
|
||||||
|
return soundEffectsMuted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playRaceMusic() {
|
||||||
|
// Media menuMusic = new Media(Sounds.class.getClassLoader().getResource("sounds/Chill-house-music-loop-116-bpm.wav").toString());
|
||||||
|
Media raceMusic = new Media(Sounds.class.getClassLoader().getResource("sounds/Music-loop-120-bpm.mp3").toString());
|
||||||
|
musicPlayer = new MediaPlayer(raceMusic);
|
||||||
|
musicPlayer.setCycleCount(MediaPlayer.INDEFINITE);
|
||||||
|
musicPlayer.play();
|
||||||
|
raceMusic = new Media(Sounds.class.getClassLoader().getResource("sounds/Sounds-of-the-ocean.mp3").toString());
|
||||||
|
soundEffect = new MediaPlayer(raceMusic);
|
||||||
|
soundEffect.setCycleCount(MediaPlayer.INDEFINITE);
|
||||||
|
// soundEffect.setVolume(0.3);
|
||||||
|
soundEffect.play();
|
||||||
|
musicPlayer.setMute(musicMuted);
|
||||||
|
soundEffect.setMute(soundEffectsMuted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playMenuMusic() {
|
||||||
|
Media menuMusic = new Media(Sounds.class.getClassLoader().getResource("sounds/Elevator-music.mp3").toString());
|
||||||
|
musicPlayer = new MediaPlayer(menuMusic);
|
||||||
|
musicPlayer.setCycleCount(MediaPlayer.INDEFINITE);
|
||||||
|
musicPlayer.play();
|
||||||
|
musicPlayer.setMute(musicMuted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playButtonClick() {
|
||||||
|
Media buttonClick = new Media(Sounds.class.getClassLoader().getResource("sounds/Button-click-sound.mp3").toString());
|
||||||
|
soundPlayer = new MediaPlayer(buttonClick);
|
||||||
|
soundPlayer.play();
|
||||||
|
soundPlayer.setMute(soundEffectsMuted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playCapGunSound() {
|
||||||
|
Media gunSound = new Media(Sounds.class.getClassLoader().getResource("sounds/Gunshot-sound.mp3").toString());
|
||||||
|
soundPlayer = new MediaPlayer(gunSound);
|
||||||
|
soundPlayer.play();
|
||||||
|
soundPlayer.setMute(soundEffectsMuted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playCrashSound() {
|
||||||
|
Media crashSound = new Media(Sounds.class.getClassLoader().getResource("sounds/Large-metal-door-slam.mp3").toString());
|
||||||
|
soundPlayer = new MediaPlayer(crashSound);
|
||||||
|
soundPlayer.play();
|
||||||
|
soundPlayer.setMute(soundEffectsMuted);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import seng302.model.stream.parser.RaceStatusData;
|
|||||||
import seng302.model.stream.parser.YachtEventData;
|
import seng302.model.stream.parser.YachtEventData;
|
||||||
import seng302.model.stream.xml.parser.RaceXMLData;
|
import seng302.model.stream.xml.parser.RaceXMLData;
|
||||||
import seng302.model.stream.xml.parser.RegattaXMLData;
|
import seng302.model.stream.xml.parser.RegattaXMLData;
|
||||||
|
import seng302.utilities.Sounds;
|
||||||
import seng302.utilities.StreamParser;
|
import seng302.utilities.StreamParser;
|
||||||
import seng302.utilities.XMLParser;
|
import seng302.utilities.XMLParser;
|
||||||
import seng302.visualiser.controllers.FinishScreenViewController;
|
import seng302.visualiser.controllers.FinishScreenViewController;
|
||||||
@@ -421,6 +422,7 @@ public class GameClient {
|
|||||||
private void showCollisionAlert(YachtEventData yachtEventData) {
|
private void showCollisionAlert(YachtEventData yachtEventData) {
|
||||||
// 33 is the agreed code to show collision
|
// 33 is the agreed code to show collision
|
||||||
if (yachtEventData.getEventId() == 33) {
|
if (yachtEventData.getEventId() == 33) {
|
||||||
|
Sounds.playCrashSound();
|
||||||
raceState.storeCollision(
|
raceState.storeCollision(
|
||||||
allBoatsMap.get(
|
allBoatsMap.get(
|
||||||
yachtEventData.getSubjectId().intValue()
|
yachtEventData.getSubjectId().intValue()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import javafx.scene.control.TextField;
|
|||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import seng302.gameServer.messages.CustomizeRequestType;
|
import seng302.gameServer.messages.CustomizeRequestType;
|
||||||
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.ClientToServerThread;
|
import seng302.visualiser.ClientToServerThread;
|
||||||
|
|
||||||
public class CustomizationController {
|
public class CustomizationController {
|
||||||
@@ -34,7 +35,8 @@ public class CustomizationController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void submitCustomization() {
|
public void submitCustomization() {
|
||||||
System.out.println("Attempting to send");
|
Sounds.playButtonClick();
|
||||||
|
// System.out.println("Attempting to send");
|
||||||
socketThread.sendCustomizationRequest(CustomizeRequestType.NAME, nameField.getText().getBytes());
|
socketThread.sendCustomizationRequest(CustomizeRequestType.NAME, nameField.getText().getBytes());
|
||||||
// TODO: 16/08/17 ajm412: Turn colors into byte array.
|
// TODO: 16/08/17 ajm412: Turn colors into byte array.
|
||||||
Color color = boatColorPicker.getValue();
|
Color color = boatColorPicker.getValue();
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import seng302.gameServer.GameStages;
|
|||||||
import seng302.gameServer.GameState;
|
import seng302.gameServer.GameState;
|
||||||
import seng302.model.Colors;
|
import seng302.model.Colors;
|
||||||
import seng302.model.RaceState;
|
import seng302.model.RaceState;
|
||||||
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.ClientToServerThread;
|
import seng302.visualiser.ClientToServerThread;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,6 +154,7 @@ public class LobbyController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void customize() {
|
public void customize() {
|
||||||
|
Sounds.playButtonClick();
|
||||||
Parent root;
|
Parent root;
|
||||||
try {
|
try {
|
||||||
FXMLLoader fxmlLoader = new FXMLLoader(LobbyController.class.getResource("/views/customizeView.fxml"));
|
FXMLLoader fxmlLoader = new FXMLLoader(LobbyController.class.getResource("/views/customizeView.fxml"));
|
||||||
@@ -184,6 +186,7 @@ public class LobbyController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void leaveLobbyButtonPressed() {
|
public void leaveLobbyButtonPressed() {
|
||||||
|
Sounds.playButtonClick();
|
||||||
// TODO: 10/07/17 wmu16 - Finish function!
|
// TODO: 10/07/17 wmu16 - Finish function!
|
||||||
GameState.setCurrentStage(GameStages.CANCELLED);
|
GameState.setCurrentStage(GameStages.CANCELLED);
|
||||||
// TODO: 20/07/17 wmu16 - Implement some way of terminating the game
|
// TODO: 20/07/17 wmu16 - Implement some way of terminating the game
|
||||||
@@ -193,6 +196,7 @@ public class LobbyController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void readyButtonPressed() {
|
public void readyButtonPressed() {
|
||||||
|
Sounds.playButtonClick();
|
||||||
GameState.setCurrentStage(GameStages.PRE_RACE);
|
GameState.setCurrentStage(GameStages.PRE_RACE);
|
||||||
// Do countdown logic here
|
// Do countdown logic here
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import seng302.model.RaceState;
|
|||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Mark;
|
import seng302.model.mark.Mark;
|
||||||
import seng302.model.stream.xml.parser.RaceXMLData;
|
import seng302.model.stream.xml.parser.RaceXMLData;
|
||||||
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.GameView;
|
import seng302.visualiser.GameView;
|
||||||
import seng302.visualiser.controllers.annotations.Annotation;
|
import seng302.visualiser.controllers.annotations.Annotation;
|
||||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
|
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
|
||||||
@@ -91,6 +92,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
private ImportantAnnotationsState importantAnnotations;
|
private ImportantAnnotationsState importantAnnotations;
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
Sounds.stopMusic();
|
||||||
|
Sounds.playRaceMusic();
|
||||||
// Load a default important annotation state
|
// Load a default important annotation state
|
||||||
importantAnnotations = new ImportantAnnotationsState();
|
importantAnnotations = new ImportantAnnotationsState();
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,15 @@ import java.net.NetworkInterface;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.ToggleButton;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import seng302.gameServer.GameState;
|
import seng302.gameServer.GameState;
|
||||||
|
import seng302.utilities.Sounds;
|
||||||
import seng302.visualiser.GameClient;
|
import seng302.visualiser.GameClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,6 +23,10 @@ import seng302.visualiser.GameClient;
|
|||||||
*/
|
*/
|
||||||
public class StartScreenController implements Initializable {
|
public class StartScreenController implements Initializable {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ToggleButton muteMusicButton;
|
||||||
|
@FXML
|
||||||
|
private ToggleButton muteSoundsButton;
|
||||||
@FXML
|
@FXML
|
||||||
private TextField ipTextField;
|
private TextField ipTextField;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -32,6 +39,17 @@ public class StartScreenController implements Initializable {
|
|||||||
GameClient gameClient;
|
GameClient gameClient;
|
||||||
|
|
||||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||||
|
if (Sounds.isMusicMuted()) {
|
||||||
|
muteMusicButton.setText("UnMute Music");
|
||||||
|
} else {
|
||||||
|
muteMusicButton.setText("Mute Music");
|
||||||
|
}
|
||||||
|
if (Sounds.isSoundEffectsMuted()) {
|
||||||
|
muteSoundsButton.setText("UnMute Sounds");
|
||||||
|
} else {
|
||||||
|
muteSoundsButton.setText("Mute Sounds");
|
||||||
|
}
|
||||||
|
|
||||||
// gameClient = new GameClient(holder);
|
// gameClient = new GameClient(holder);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@@ -66,6 +84,7 @@ public class StartScreenController implements Initializable {
|
|||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
public void hostButtonPressed() {
|
public void hostButtonPressed() {
|
||||||
|
Sounds.playButtonClick();
|
||||||
// new GameState(getLocalHostIp());
|
// new GameState(getLocalHostIp());
|
||||||
gameClient = new GameClient(holder);
|
gameClient = new GameClient(holder);
|
||||||
gameClient.runAsHost(getLocalHostIp(), 4942);
|
gameClient.runAsHost(getLocalHostIp(), 4942);
|
||||||
@@ -104,6 +123,7 @@ public class StartScreenController implements Initializable {
|
|||||||
@FXML
|
@FXML
|
||||||
public void connectButtonPressed() {
|
public void connectButtonPressed() {
|
||||||
// TODO: 10/07/17 wmu16 - Finish function
|
// TODO: 10/07/17 wmu16 - Finish function
|
||||||
|
Sounds.playButtonClick();
|
||||||
gameClient = new GameClient(holder);
|
gameClient = new GameClient(holder);
|
||||||
gameClient.runAsClient(ipTextField.getText().trim().toLowerCase(), 4942);
|
gameClient.runAsClient(ipTextField.getText().trim().toLowerCase(), 4942);
|
||||||
|
|
||||||
@@ -165,4 +185,24 @@ public class StartScreenController implements Initializable {
|
|||||||
// ClientState.setHostIp(ipAddress);
|
// ClientState.setHostIp(ipAddress);
|
||||||
return ipAddress;
|
return ipAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void toggleMusic(ActionEvent actionEvent) {
|
||||||
|
Sounds.toggleMuteMusic();
|
||||||
|
Sounds.playButtonClick();
|
||||||
|
if (Sounds.isMusicMuted()) {
|
||||||
|
muteMusicButton.setText("UnMute Music");
|
||||||
|
} else {
|
||||||
|
muteMusicButton.setText("Mute Music");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleSounds(ActionEvent actionEvent) {
|
||||||
|
Sounds.toggleMuteEffects();
|
||||||
|
Sounds.playButtonClick();
|
||||||
|
if (Sounds.isSoundEffectsMuted()) {
|
||||||
|
muteSoundsButton.setText("UnMute Sounds");
|
||||||
|
} else {
|
||||||
|
muteSoundsButton.setText("Mute Sounds");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -20,9 +20,7 @@
|
|||||||
<children>
|
<children>
|
||||||
<GridPane fx:id="startScreen2" layoutX="365.0" layoutY="285.0" nodeOrientation="LEFT_TO_RIGHT" prefWidth="800.0" style="-fx-background-color: #2C2c36;">
|
<GridPane fx:id="startScreen2" layoutX="365.0" layoutY="285.0" nodeOrientation="LEFT_TO_RIGHT" prefWidth="800.0" style="-fx-background-color: #2C2c36;">
|
||||||
<children>
|
<children>
|
||||||
<Label alignment="CENTER" text="Party Parrots at Sea" textFill="WHITE"
|
<Label alignment="CENTER" text="Party Parrots at Sea" textFill="WHITE" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
|
||||||
GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="1"
|
|
||||||
GridPane.valignment="BOTTOM">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="40.0" />
|
<Font size="40.0" />
|
||||||
</font>
|
</font>
|
||||||
@@ -51,6 +49,27 @@
|
|||||||
<Insets left="5.0" right="5.0" />
|
<Insets left="5.0" right="5.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</TextField>
|
</TextField>
|
||||||
|
<GridPane GridPane.columnSpan="2" GridPane.rowIndex="5">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<ToggleButton fx:id="muteMusicButton" mnemonicParsing="false" onAction="#toggleMusic" prefWidth="130.0" text="Mute Music" GridPane.halignment="RIGHT">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="5.0" right="5.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton fx:id="muteSoundsButton" mnemonicParsing="false" onAction="#toggleSounds" prefWidth="130.0" text="Mute Sounds" GridPane.columnIndex="1">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="5.0" right="5.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</ToggleButton>
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="442.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="442.0" />
|
||||||
|
|||||||
Reference in New Issue
Block a user