/*
* Copyright (C) 2015-2017 PÂRIS Quentin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.phoenicis.javafx.views.mainwindow.containers;
import javafx.collections.FXCollections;
import javafx.scene.control.*;
import javafx.util.StringConverter;
import org.phoenicis.containers.dto.WinePrefixContainerDTO;
import org.phoenicis.containers.wine.parameters.*;
import org.phoenicis.engines.EnginesSource;
import org.phoenicis.engines.dto.EngineVersionDTO;
import org.phoenicis.javafx.views.common.ColumnConstraintsWithPercentage;
import org.phoenicis.javafx.views.common.TextWithStyle;
import com.sun.javafx.collections.ImmutableObservableList;
import com.sun.javafx.collections.ObservableListWrapper;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.text.Text;
import org.phoenicis.javafx.views.common.ThemeManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import static org.phoenicis.configuration.localisation.Localisation.translate;
public class WinePrefixContainerPanel extends AbstractContainerPanel<WinePrefixContainerDTO> {
private static final String CAPTION_TITLE_CSS_CLASS = "captionTitle";
private static final String CONFIGURATION_PANE_CSS_CLASS = "containerConfigurationPane";
private static final String TITLE_CSS_CLASS = "title";
private final List<Node> lockableElements = new ArrayList<>();
private Consumer<WinePrefixContainerDTO> onWineCfg = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onRegedit = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onWineboot = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onWinebootRepair = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onWineConsole = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onTaskMgr = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onKillProcess = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onUninstaller = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onOpenTerminalInWinePrefix = winePrefix -> {
};
private Consumer<WinePrefixContainerDTO> onDeletePrefix = winePrefix -> {
};
private BiConsumer<WinePrefixContainerDTO, RegistryParameter> onChangeSetting = (winePrefix, value) -> {
};
public WinePrefixContainerPanel(WinePrefixContainerDTO containerEntity, ThemeManager themeManager,
List<EngineVersionDTO> engineVersions) {
super(containerEntity, themeManager, engineVersions);
this.getTabs().add(drawDisplayTab(containerEntity));
this.getTabs().add(drawInputTab(containerEntity));
this.getTabs().add(drawWineToolsTab(containerEntity));
this.getTabs().add(drawToolsTab(containerEntity));
}
public void setOnDeletePrefix(Consumer<WinePrefixContainerDTO> onDeletePrefix) {
this.onDeletePrefix = onDeletePrefix;
}
@Override
Tab drawInformationTab(WinePrefixContainerDTO container, List<EngineVersionDTO> engineVersions) {
final Tab informationTab = new Tab(translate("Information"));
final VBox informationPane = new VBox();
final Text title = new TextWithStyle(translate("Information"), TITLE_CSS_CLASS);
informationPane.getStyleClass().add(CONFIGURATION_PANE_CSS_CLASS);
informationPane.getChildren().add(title);
final GridPane informationContentPane = new GridPane();
informationContentPane.getStyleClass().add("grid");
informationContentPane.add(new TextWithStyle(translate("Name:"), CAPTION_TITLE_CSS_CLASS), 0, 0);
Label name = new Label(container.getName());
name.setWrapText(true);
informationContentPane.add(name, 1, 0);
informationContentPane.add(new TextWithStyle(translate("Path:"), CAPTION_TITLE_CSS_CLASS), 0, 1);
Label path = new Label(container.getPath());
path.setWrapText(true);
informationContentPane.add(path, 1, 1);
informationContentPane.add(new TextWithStyle(translate("Wine version:"), CAPTION_TITLE_CSS_CLASS), 0, 2);
Label version = new Label(container.getVersion());
version.setWrapText(true);
informationContentPane.add(version, 1, 2);
informationContentPane.add(new TextWithStyle(translate("Wine architecture:"), CAPTION_TITLE_CSS_CLASS), 0, 3);
Label architecture = new Label(container.getArchitecture());
architecture.setWrapText(true);
informationContentPane.add(architecture, 1, 3);
informationContentPane.add(new TextWithStyle(translate("Wine distribution:"), CAPTION_TITLE_CSS_CLASS), 0, 4);
Label distribution = new Label(container.getDistribution());
distribution.setWrapText(true);
informationContentPane.add(distribution, 1, 4);
Region spacer = new Region();
spacer.setPrefHeight(20);
VBox.setVgrow(spacer, Priority.NEVER);
ComboBox<EngineVersionDTO> changeEngineComboBox = new ComboBox<EngineVersionDTO>(
FXCollections.observableList(engineVersions));
changeEngineComboBox.setConverter(new StringConverter<EngineVersionDTO>() {
@Override
public String toString(EngineVersionDTO object) {
return object.getVersion();
}
@Override
public EngineVersionDTO fromString(String string) {
return engineVersions.stream().filter(engineVersion -> engineVersion.getVersion().equals(string))
.findFirst().get();
}
});
changeEngineComboBox.getSelectionModel().select(engineVersions.stream()
.filter(engineVersion -> engineVersion.getVersion().equals(container.getVersion())).findFirst().get());
Button deleteButton = new Button("Delete container");
deleteButton.setOnMouseClicked(event -> this.deletePrefix(container));
informationPane.getChildren().addAll(informationContentPane, spacer, changeEngineComboBox, deleteButton);
informationTab.setContent(informationPane);
informationTab.setClosable(false);
return informationTab;
}
private void deletePrefix(WinePrefixContainerDTO winePrefix) {
this.onDeletePrefix.accept(winePrefix);
}
private Tab drawDisplayTab(WinePrefixContainerDTO winePrefixContainerDTO) {
final Tab displayTab = new Tab(translate("Display"));
final VBox displayPane = new VBox();
final Text title = new TextWithStyle(translate("Display settings"), TITLE_CSS_CLASS);
displayPane.getStyleClass().add(CONFIGURATION_PANE_CSS_CLASS);
displayPane.getChildren().add(title);
final GridPane displayContentPane = new GridPane();
displayContentPane.getStyleClass().add("grid");
final ComboBox<UseGLSL> glslComboBox = new ComboBox<>();
glslComboBox.setMaxWidth(Double.MAX_VALUE);
glslComboBox.setValue(winePrefixContainerDTO.getUseGlslValue());
glslComboBox.valueProperty()
.addListener((observable, oldValue, newValue) -> this.changeSetting(winePrefixContainerDTO, newValue));
addItems(glslComboBox, UseGLSL.class);
displayContentPane.add(new TextWithStyle(translate("GLSL support"), CAPTION_TITLE_CSS_CLASS), 0, 0);
displayContentPane.add(glslComboBox, 1, 0);
final ComboBox<DirectDrawRenderer> directDrawRendererComboBox = new ComboBox<>();
directDrawRendererComboBox.setMaxWidth(Double.MAX_VALUE);
directDrawRendererComboBox.setValue(winePrefixContainerDTO.getDirectDrawRenderer());
directDrawRendererComboBox.valueProperty()
.addListener((observable, oldValue, newValue) -> this.changeSetting(winePrefixContainerDTO, newValue));
addItems(directDrawRendererComboBox, DirectDrawRenderer.class);
displayContentPane.add(new TextWithStyle(translate("Direct Draw Renderer"), CAPTION_TITLE_CSS_CLASS), 0, 1);
displayContentPane.add(directDrawRendererComboBox, 1, 1);
final ComboBox<VideoMemorySize> videoMemorySizeComboBox = new ComboBox<>();
videoMemorySizeComboBox.setMaxWidth(Double.MAX_VALUE);
videoMemorySizeComboBox.setValue(winePrefixContainerDTO.getVideoMemorySize());
videoMemorySizeComboBox.valueProperty()
.addListener((observable, oldValue, newValue) -> this.changeSetting(winePrefixContainerDTO, newValue));
addItemsVideoMemorySize(videoMemorySizeComboBox);
displayContentPane.add(new TextWithStyle(translate("Video memory size"), CAPTION_TITLE_CSS_CLASS), 0, 2);
displayContentPane.add(videoMemorySizeComboBox, 1, 2);
final ComboBox<OffscreenRenderingMode> offscreenRenderingModeComboBox = new ComboBox<>();
offscreenRenderingModeComboBox.setMaxWidth(Double.MAX_VALUE);
offscreenRenderingModeComboBox.setValue(winePrefixContainerDTO.getOffscreenRenderingMode());
offscreenRenderingModeComboBox.valueProperty()
.addListener((observable, oldValue, newValue) -> this.changeSetting(winePrefixContainerDTO, newValue));
addItems(offscreenRenderingModeComboBox, OffscreenRenderingMode.class);
displayContentPane.add(new TextWithStyle(translate("Offscreen rendering mode"), CAPTION_TITLE_CSS_CLASS), 0, 3);
displayContentPane.add(offscreenRenderingModeComboBox, 1, 3);
final ComboBox<RenderTargetModeLock> renderTargetModeLockComboBox = new ComboBox<>();
renderTargetModeLockComboBox.setMaxWidth(Double.MAX_VALUE);
renderTargetModeLockComboBox.setValue(winePrefixContainerDTO.getRenderTargetModeLock());
renderTargetModeLockComboBox.valueProperty()
.addListener((observable, oldValue, newValue) -> this.changeSetting(winePrefixContainerDTO, newValue));
addItems(renderTargetModeLockComboBox, RenderTargetModeLock.class);
displayContentPane.add(new TextWithStyle(translate("Render target lock mode"), CAPTION_TITLE_CSS_CLASS), 0, 4);
displayContentPane.add(renderTargetModeLockComboBox, 1, 4);
final ComboBox<Multisampling> multisamplingComboBox = new ComboBox<>();
multisamplingComboBox.setMaxWidth(Double.MAX_VALUE);
multisamplingComboBox.setValue(winePrefixContainerDTO.getMultisampling());
multisamplingComboBox.valueProperty()
.addListener((observable, oldValue, newValue) -> this.changeSetting(winePrefixContainerDTO, newValue));
addItems(multisamplingComboBox, Multisampling.class);
displayContentPane.add(new TextWithStyle(translate("Multisampling"), CAPTION_TITLE_CSS_CLASS), 0, 5);
displayContentPane.add(multisamplingComboBox, 1, 5);
final ComboBox<StrictDrawOrdering> strictDrawOrderingComboBox = new ComboBox<>();
strictDrawOrderingComboBox.setMaxWidth(Double.MAX_VALUE);
strictDrawOrderingComboBox.setValue(winePrefixContainerDTO.getStrictDrawOrdering());
strictDrawOrderingComboBox.valueProperty()
.addListener((observable, oldValue, newValue) -> this.changeSetting(winePrefixContainerDTO, newValue));
addItems(strictDrawOrderingComboBox, StrictDrawOrdering.class);
displayContentPane.add(new TextWithStyle(translate("Strict Draw Ordering"), CAPTION_TITLE_CSS_CLASS), 0, 6);
displayContentPane.add(strictDrawOrderingComboBox, 1, 6);
final ComboBox<AlwaysOffscreen> alwaysOffscreenComboBox = new ComboBox<>();
alwaysOffscreenComboBox.setMaxWidth(Double.MAX_VALUE);
alwaysOffscreenComboBox.setValue(winePrefixContainerDTO.getAlwaysOffscreen());
alwaysOffscreenComboBox.valueProperty()
.addListener((observable, oldValue, newValue) -> this.changeSetting(winePrefixContainerDTO, newValue));
addItems(alwaysOffscreenComboBox, AlwaysOffscreen.class);
displayContentPane.add(new TextWithStyle(translate("Always Offscreen"), CAPTION_TITLE_CSS_CLASS), 0, 7);
displayContentPane.add(alwaysOffscreenComboBox, 1, 7);
Region spacer = new Region();
GridPane.setHgrow(spacer, Priority.ALWAYS);
displayContentPane.add(spacer, 2, 0);
displayPane.getChildren().addAll(displayContentPane);
displayTab.setContent(displayPane);
displayTab.setClosable(false);
lockableElements.addAll(Arrays.asList(glslComboBox, directDrawRendererComboBox, offscreenRenderingModeComboBox,
renderTargetModeLockComboBox, multisamplingComboBox, strictDrawOrderingComboBox,
alwaysOffscreenComboBox, videoMemorySizeComboBox));
return displayTab;
}
private void changeSetting(WinePrefixContainerDTO winePrefixContainerDTO, RegistryParameter newValue) {
onChangeSetting.accept(winePrefixContainerDTO, newValue);
lockAll();
}
private Tab drawInputTab(WinePrefixContainerDTO containerEntity) {
final Tab inputTab = new Tab(translate("Input"));
final VBox inputPane = new VBox();
final Text title = new TextWithStyle(translate("Input settings"), TITLE_CSS_CLASS);
inputPane.getStyleClass().add(CONFIGURATION_PANE_CSS_CLASS);
inputPane.getChildren().add(title);
final GridPane inputContentPane = new GridPane();
inputContentPane.getStyleClass().add("grid");
final ComboBox<MouseWarpOverride> mouseWarpOverrideComboBox = new ComboBox<>();
mouseWarpOverrideComboBox.setValue(containerEntity.getMouseWarpOverride());
addItems(mouseWarpOverrideComboBox, MouseWarpOverride.class);
inputContentPane.add(new TextWithStyle(translate("Mouse Warp Override"), CAPTION_TITLE_CSS_CLASS), 0, 0);
inputContentPane.add(mouseWarpOverrideComboBox, 1, 0);
inputContentPane.getColumnConstraints().addAll(new ColumnConstraintsWithPercentage(30),
new ColumnConstraintsWithPercentage(70));
inputPane.getChildren().addAll(inputContentPane);
inputTab.setContent(inputPane);
inputTab.setClosable(false);
lockableElements.add(mouseWarpOverrideComboBox);
return inputTab;
}
private Tab drawWineToolsTab(WinePrefixContainerDTO containerEntity) {
final Tab toolsTab = new Tab(translate("Wine tools"));
final VBox toolsPane = new VBox();
final Text title = new TextWithStyle(translate("Wine tools"), TITLE_CSS_CLASS);
toolsPane.getStyleClass().add(CONFIGURATION_PANE_CSS_CLASS);
toolsPane.getChildren().add(title);
final GridPane toolsContentPane = new GridPane();
toolsContentPane.getStyleClass().add("grid");
toolsContentPane.add(
wineToolButton(translate("Configure Wine"), "winecfg.png", e -> this.onWineCfg.accept(containerEntity)),
0, 0);
toolsContentPane.add(wineToolCaption(translate("Configure Wine")), 0, 1);
toolsContentPane.add(wineToolButton(translate("Registry Editor"), "regedit.png",
e -> this.onRegedit.accept(containerEntity)), 1, 0);
toolsContentPane.add(wineToolCaption(translate("Registry Editor")), 1, 1);
toolsContentPane.add(wineToolButton(translate("Windows reboot"), "rebootPrefix.png",
e -> this.onWineboot.accept(containerEntity)), 2, 0);
toolsContentPane.add(wineToolCaption(translate("Windows reboot")), 2, 1);
toolsContentPane.add(wineToolButton(translate("Repair virtual drive"), "repair.png",
e -> this.onWinebootRepair.accept(containerEntity)), 3, 0);
toolsContentPane.add(wineToolCaption(translate("Repair virtual drive")), 3, 1);
toolsContentPane.add(
wineToolButton(translate("Command prompt"), "cmd.png", e -> this.onWineConsole.accept(containerEntity)),
0, 3);
toolsContentPane.add(wineToolCaption(translate("Command prompt")), 0, 4);
toolsContentPane.add(
wineToolButton(translate("Task manager"), "taskmgr.png", e -> this.onTaskMgr.accept(containerEntity)),
1, 3);
toolsContentPane.add(wineToolCaption(translate("Task manager")), 1, 4);
toolsContentPane.add(wineToolButton(translate("Kill processes"), "killProcesses.png",
e -> this.onKillProcess.accept(containerEntity), false), 2, 3);
toolsContentPane.add(wineToolCaption(translate("Kill processes")), 2, 4);
toolsContentPane.add(wineToolButton(translate("Wine uninstaller"), "uninstaller.png",
e -> this.onUninstaller.accept(containerEntity)), 3, 3);
toolsContentPane.add(wineToolCaption(translate("Wine uninstaller")), 3, 4);
toolsPane.getChildren().addAll(toolsContentPane);
toolsContentPane.getColumnConstraints().addAll(new ColumnConstraintsWithPercentage(25),
new ColumnConstraintsWithPercentage(25), new ColumnConstraintsWithPercentage(25),
new ColumnConstraintsWithPercentage(25));
toolsTab.setContent(toolsPane);
toolsTab.setClosable(false);
return toolsTab;
}
private Tab drawToolsTab(WinePrefixContainerDTO containerEntity) {
final Tab toolsTab = new Tab(translate("Tools"));
final VBox toolsPane = new VBox();
final Text title = new TextWithStyle(translate("Tools"), TITLE_CSS_CLASS);
toolsPane.getStyleClass().add(CONFIGURATION_PANE_CSS_CLASS);
toolsPane.getChildren().add(title);
final GridPane toolsContentPane = new GridPane();
toolsContentPane.getStyleClass().add("grid");
toolsContentPane.add(wineToolButton(translate("Open a terminal"), "cmd.png",
e -> this.onOpenTerminalInWinePrefix.accept(containerEntity)), 0, 0);
toolsContentPane.add(wineToolCaption(translate("Open a terminal")), 0, 1);
toolsPane.getChildren().addAll(toolsContentPane);
toolsContentPane.getColumnConstraints().addAll(new ColumnConstraintsWithPercentage(25),
new ColumnConstraintsWithPercentage(25), new ColumnConstraintsWithPercentage(25),
new ColumnConstraintsWithPercentage(25));
toolsTab.setContent(toolsPane);
toolsTab.setClosable(false);
return toolsTab;
}
private Text wineToolCaption(String caption) {
final Text text = new TextWithStyle(caption, "wineToolCaption");
GridPane.setHalignment(text, HPos.CENTER);
GridPane.setValignment(text, VPos.CENTER);
lockableElements.add(text);
return text;
}
private Button wineToolButton(String caption, String icon, EventHandler<? super MouseEvent> eventHandler) {
return wineToolButton(caption, icon, eventHandler, true);
}
private Button wineToolButton(String caption, String icon, EventHandler<? super MouseEvent> eventHandler,
boolean lockable) {
final Button button = new Button(caption);
button.getStyleClass().add("wineToolButton");
final String iconResource = "icons/mainwindow/containers/" + icon;
button.setStyle("-fx-background-image: url('" + themeManager.getResourceUrl(iconResource) + "');");
button.setOnMouseClicked(event -> {
lockAll();
eventHandler.handle(event);
});
if (lockable) {
lockableElements.add(button);
}
GridPane.setHalignment(button, HPos.CENTER);
return button;
}
public void unlockAll() {
for (Node element : lockableElements) {
element.setDisable(false);
}
}
private void lockAll() {
for (Node element : lockableElements) {
element.setDisable(true);
}
}
private void addItemsVideoMemorySize(ComboBox<VideoMemorySize> videoMemorySizeComboBox) {
videoMemorySizeComboBox.setItems(new ImmutableObservableList<>(VideoMemorySize.possibleValues()));
}
private <T extends Enum> void addItems(ComboBox<T> comboBox, Class<T> clazz) {
final List<T> possibleValues = new ArrayList<>(EnumSet.allOf(clazz));
final ObservableList<T> possibleValuesObservable = new ObservableListWrapper<>(possibleValues);
comboBox.setItems(possibleValuesObservable);
}
public void setOnWineCfg(Consumer<WinePrefixContainerDTO> onWineCfg) {
this.onWineCfg = onWineCfg;
}
public void setOnRegedit(Consumer<WinePrefixContainerDTO> onRegedit) {
this.onRegedit = onRegedit;
}
public void setOnWineboot(Consumer<WinePrefixContainerDTO> onWineboot) {
this.onWineboot = onWineboot;
}
public void setOnWinebootRepair(Consumer<WinePrefixContainerDTO> onWinebootRepair) {
this.onWinebootRepair = onWinebootRepair;
}
public void setOnWineConsole(Consumer<WinePrefixContainerDTO> onWineconsole) {
this.onWineConsole = onWineconsole;
}
public void setOnTaskMgr(Consumer<WinePrefixContainerDTO> onTaskMgr) {
this.onTaskMgr = onTaskMgr;
}
public void setOnUninstaller(Consumer<WinePrefixContainerDTO> onUninstaller) {
this.onUninstaller = onUninstaller;
}
public void setOnKillProcess(Consumer<WinePrefixContainerDTO> onKillProcess) {
this.onKillProcess = onKillProcess;
}
public void setOnOpenTerminalInWinePrefix(Consumer<WinePrefixContainerDTO> onOpenTerminalInWinePrefix) {
this.onOpenTerminalInWinePrefix = onOpenTerminalInWinePrefix;
}
public void setOnChangeSetting(BiConsumer<WinePrefixContainerDTO, RegistryParameter> onChangeSetting) {
this.onChangeSetting = onChangeSetting;
}
}