package ru.khasang.cachoeira.viewcontroller;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.WeakInvalidationListener;
import javafx.beans.property.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.WeakChangeListener;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.WeakListChangeListener;
import javafx.scene.control.*;
import javafx.stage.WindowEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.khasang.cachoeira.commands.CommandExecutor;
import ru.khasang.cachoeira.commands.project.*;
import ru.khasang.cachoeira.data.DataService;
import ru.khasang.cachoeira.model.*;
import ru.khasang.cachoeira.properties.ISettingsManager;
import ru.khasang.cachoeira.properties.RecentProjectsController;
import ru.khasang.cachoeira.properties.SettingsManager;
import ru.khasang.cachoeira.viewcontroller.contextmenus.ColumnContextMenu;
import ru.khasang.cachoeira.viewcontroller.draganddrop.ResourceTableDragAndDrop;
import ru.khasang.cachoeira.viewcontroller.draganddrop.TaskTableDragAndDrop;
import ru.khasang.cachoeira.viewcontroller.mainwindowcontrollers.buttonsbar.ButtonsBoxController;
import ru.khasang.cachoeira.viewcontroller.mainwindowcontrollers.MenuBarController;
import ru.khasang.cachoeira.viewcontroller.mainwindowcontrollers.buttonsbar.ResourceButtonsBoxController;
import ru.khasang.cachoeira.viewcontroller.mainwindowcontrollers.buttonsbar.TaskButtonsBoxController;
import ru.khasang.cachoeira.viewcontroller.mainwindowcontrollers.propertiesmodules.*;
import ru.khasang.cachoeira.viewcontroller.rowfactories.ResourceTreeTableViewRowFactory;
import ru.khasang.cachoeira.viewcontroller.rowfactories.TaskTreeTableViewRowFactory;
import ru.khasang.cachoeira.view.IView;
import ru.khasang.cachoeira.view.mainwindow.MainWindowView;
import ru.khasang.cachoeira.view.mainwindow.diagram.ResourcePane;
import ru.khasang.cachoeira.view.mainwindow.diagram.TaskPane;
import ru.khasang.cachoeira.view.mainwindow.diagram.buttonbox.AbstractButtonsBox;
import ru.khasang.cachoeira.view.mainwindow.diagram.buttonbox.ResourcesButtonBox;
import ru.khasang.cachoeira.view.mainwindow.diagram.buttonbox.TasksButtonBox;
import ru.khasang.cachoeira.view.mainwindow.diagram.ganttplan.AbstractGanttPlan;
import ru.khasang.cachoeira.view.mainwindow.diagram.ganttplan.ResourceGanttPlan;
import ru.khasang.cachoeira.view.mainwindow.diagram.ganttplan.TaskGanttPlan;
import ru.khasang.cachoeira.view.mainwindow.diagram.tables.AbstractTableView;
import ru.khasang.cachoeira.view.mainwindow.diagram.tables.ResourceTableView;
import ru.khasang.cachoeira.view.mainwindow.diagram.tables.TaskTableView;
import ru.khasang.cachoeira.view.mainwindow.menubar.AbstractMenuBar;
import ru.khasang.cachoeira.view.mainwindow.menubar.MainMenuBar;
import ru.khasang.cachoeira.view.mainwindow.properties.AbstractPropertiesSidePanel;
import ru.khasang.cachoeira.view.mainwindow.properties.modules.*;
import ru.khasang.cachoeira.view.mainwindow.properties.PropertiesSidePanel;
import ru.khasang.cachoeira.view.mainwindow.properties.panes.ProjectPropertiesTab;
import ru.khasang.cachoeira.view.mainwindow.properties.panes.ResourcePropertiesTab;
import ru.khasang.cachoeira.view.mainwindow.properties.panes.TaskPropertiesTab;
import java.io.File;
public class MainWindowController {
private static final Logger LOGGER = LoggerFactory.getLogger(MainWindowController.class.getName());
private File projectFile;
private final IProject project;
private final CommandExecutor commandExecutor;
private final IView view;
private ObjectProperty<ITask> selectedTask = new SimpleObjectProperty<>(this, "selectedTask", null);
private ObjectProperty<IResource> selectedResource = new SimpleObjectProperty<>(this, "selectedResource", null);
private IntegerProperty zoomMultiplier = new SimpleIntegerProperty(this, "zoomMultiplier", 70);
private DoubleProperty ganttHorizontalScrollValue = new SimpleDoubleProperty(this, "ganttHorizontalScrollValue", 0);
private DoubleProperty taskVerticalScrollValue = new SimpleDoubleProperty(this, "taskVerticalScrollValue", 0);
private DoubleProperty resourceVerticalScrollValue = new SimpleDoubleProperty(this, "resourceVerticalScrollValue", 0);
private DoubleProperty taskHorizontalScrollValue = new SimpleDoubleProperty(this, "taskHorizontalScrollValue", 0);
private DoubleProperty resourceHorizontalScrollValue = new SimpleDoubleProperty(this, "resourceHorizontalScrollValue", 0);
private DoubleProperty splitPaneDividerValue = new SimpleDoubleProperty(this, "splitPaneDividerValue", 0.15);
private DoubleProperty widthOfWindow = new SimpleDoubleProperty(this, "widthOfWindow", 1280);
private DoubleProperty heightOfWindow = new SimpleDoubleProperty(this, "heightOfWindow", 720);
private BooleanProperty isMaximized = new SimpleBooleanProperty(this, "isMaximized", false);
private AbstractMenuBar menuBar;
private SplitPane taskSplitPane;
private SplitPane resourceSplitPane;
private AbstractTableView<ITask> taskTableView;
private AbstractTableView<IResource> resourceTableView;
private AbstractGanttPlan taskGanttPlan;
private AbstractGanttPlan resourceGanttPlan;
private AbstractPropertiesSidePanel sidePanel;
private ProjectInformation projectInformation;
private TaskInformation taskInformation;
private TaskAssignedResources taskAssignedResources;
private TaskDependencies taskDependencies;
private ResourceInformation resourceInformation;
private ResourceAssignedTasks resourceAssignedTasks;
private AbstractButtonsBox tasksButtonsBox;
private AbstractButtonsBox resourcesButtonBox;
@SuppressWarnings("FieldCanBeLocal")
private ListChangeListener<ITask> taskListChangeListener;
@SuppressWarnings("FieldCanBeLocal")
private ListChangeListener<IResource> resourceListChangeListener;
@SuppressWarnings("FieldCanBeLocal")
private InvalidationListener projectDateListener;
@SuppressWarnings("FieldCanBeLocal")
private ChangeListener<TreeItem<ITask>> taskChangeListener;
@SuppressWarnings("FieldCanBeLocal")
private ChangeListener<TreeItem<IResource>> resourceChangeListener;
@SuppressWarnings("FieldCanBeLocal")
private ListChangeListener<TreeItem<ITask>> taskTreeItemsChangeListener;
@SuppressWarnings("FieldCanBeLocal")
private ListChangeListener<TreeItem<IResource>> resourceTreeItemsChangeListener;
public MainWindowController(File projectFile, IProject project, CommandExecutor commandExecutor) {
this.projectFile = projectFile;
this.project = project;
this.commandExecutor = commandExecutor;
view = createMainWindow();
projectDateListener = this::projectDateObserver;
project.startDateProperty().addListener(new WeakInvalidationListener(projectDateListener));
project.finishDateProperty().addListener(new WeakInvalidationListener(projectDateListener));
}
private void projectDateObserver(Observable observable) {
taskGanttPlan.getObjectsLayer().refreshPlan();
resourceGanttPlan.getObjectsLayer().refreshPlan();
}
public void launch() {
view.createView();
MenuBarController menuBarController = new MenuBarController(menuBar, this);
menuBarController.attachMenuBarEvents();
ButtonsBoxController taskButtonsBoxController = new TaskButtonsBoxController(tasksButtonsBox, this);
taskButtonsBoxController.attachButtonsEvents();
ButtonsBoxController resourceButtonsBoxController = new ResourceButtonsBoxController(resourcesButtonBox, this);
resourceButtonsBoxController.attachButtonsEvents();
ModuleController projectInformationModuleController = new ProjectInformationModuleController(projectInformation, this);
projectInformationModuleController.initModule();
ModuleController taskInformationModuleController = new TaskInformationModuleController(taskInformation, this);
taskInformationModuleController.initModule();
TaskAssignedResourcesModuleController taskAssignedResourcesModuleController = new TaskAssignedResourcesModuleController(taskAssignedResources, this);
taskAssignedResourcesModuleController.initModule();
TaskDependenciesModuleController taskDependenciesModuleController = new TaskDependenciesModuleController(taskDependencies, this);
taskDependenciesModuleController.initModule();
ModuleController resourceInformationModuleController = new ResourceInformationModuleController(resourceInformation, this);
resourceInformationModuleController.initModule();
ResourceAssignedTasksModuleController resourceAssignedTasksModuleController = new ResourceAssignedTasksModuleController(resourceAssignedTasks, this);
resourceAssignedTasksModuleController.initModule();
this.attachGanttPlanEvents();
this.attachContextMenus();
view.getStage().setOnCloseRequest(event -> {
this.saveProperties();
this.saveProject(event);
});
LOGGER.debug("Launched.");
}
private void saveProperties() {
ISettingsManager settingsManager = SettingsManager.getInstance();
settingsManager.writeUIValues(
splitPaneDividerValue.get(),
zoomMultiplier.getValue(),
view.getStage().getWidth(),
view.getStage().getHeight(),
view.getStage().isMaximized());
settingsManager.writeRecentProjects(RecentProjectsController.getInstance().getRecentProjects());
}
private void saveProject(WindowEvent event) {
//минимум JDK 8u40
if (commandExecutor.isChanged()) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Cachoeira");
alert.setHeaderText("Вы хотите сохранить изменения в " + project.getName() + "?");
ButtonType saveProjectButtonType = new ButtonType("Сохранить");
ButtonType doNotSaveProjectButtonType = new ButtonType("Не сохранять");
ButtonType cancelButtonType = new ButtonType("Отмена", ButtonBar.ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(saveProjectButtonType, doNotSaveProjectButtonType, cancelButtonType);
alert.showAndWait().ifPresent(response -> {
if (response == saveProjectButtonType) {
DataService.getInstance().saveProject(projectFile, project);
view.getStage().close();
} else if (response == doNotSaveProjectButtonType) {
view.getStage().close();
} else {
if (event != null) {
event.consume();
}
}
});
} else {
view.getStage().close();
}
}
private void attachGanttPlanEvents() {
taskSplitPane.getDividers().get(0).positionProperty().bindBidirectional(splitPaneDividerValue);
resourceSplitPane.getDividers().get(0).positionProperty().bindBidirectional(splitPaneDividerValue);
}
private void attachContextMenus() {
// Контекстное меню для выбора нужных столбцов
ColumnContextMenu columnContextMenuTask = new ColumnContextMenu(taskTableView);
columnContextMenuTask.setOnShowing(event -> columnContextMenuTask.updateContextMenuColumnTTV(taskTableView));
taskTableView.getColumns().forEach(column -> column.setContextMenu(columnContextMenuTask));
// Контекстное меню для таблицы
ContextMenu taskTableMenu = new ContextMenu();
MenuItem addNewTask = new MenuItem("Новая задача");
addNewTask.setOnAction(event -> commandExecutor.execute(new AddTaskToProjectCommand(project, new Task())));
taskTableMenu.getItems().addAll(addNewTask); //заполняем меню
taskTableView.setContextMenu(taskTableMenu);
ColumnContextMenu columnContextMenuResource = new ColumnContextMenu(resourceTableView);
columnContextMenuResource.setOnShowing(event -> columnContextMenuResource.updateContextMenuColumnTTV(resourceTableView));
resourceTableView.getColumns().forEach(column -> column.setContextMenu(columnContextMenuResource));
// Контекстное меню для таблицы
ContextMenu resourceTableMenu = new ContextMenu();
MenuItem addNewResource = new MenuItem("Новый ресурс");
addNewResource.setOnAction(event -> commandExecutor.execute(new AddResourceToProjectCommand(project, new Resource())));
resourceTableMenu.getItems().addAll(addNewResource); //заполняем меню
resourceTableView.setContextMenu(resourceTableMenu);
}
private MainWindowView createMainWindow() {
// Выгружаем настройки программы из файлов
if (SettingsManager.getInstance().getUIValueByKey("ZoomValue") != null) {
zoomMultiplier.setValue(Double.valueOf(SettingsManager.getInstance().getUIValueByKey("ZoomValue")).intValue());
}
if (SettingsManager.getInstance().getUIValueByKey("DiagramDividerValue") != null) {
splitPaneDividerValue.setValue(Double.valueOf(SettingsManager.getInstance().getUIValueByKey("DiagramDividerValue")));
}
if (SettingsManager.getInstance().getUIValueByKey("WidthOfWindow") != null) {
widthOfWindow.setValue(Double.valueOf(SettingsManager.getInstance().getUIValueByKey("WidthOfWindow")));
}
if (SettingsManager.getInstance().getUIValueByKey("HeightOfWindow") != null) {
heightOfWindow.setValue(Double.valueOf(SettingsManager.getInstance().getUIValueByKey("HeightOfWindow")));
}
isMaximized.setValue(isMaximized());
taskGanttPlan = new TaskGanttPlan(this);
resourceGanttPlan = new ResourceGanttPlan(this);
menuBar = new MainMenuBar();
sidePanel = new PropertiesSidePanel(new ProjectPropertiesTab(), new TaskPropertiesTab(), new ResourcePropertiesTab());
projectInformation = (ProjectInformation) createPropertiesModule(new ProjectInformation());
sidePanel.getProjectPropertiesTab().addNewPropertiesTitledModule(projectInformation, "Information");
taskInformation = (TaskInformation) createPropertiesModule(new TaskInformation());
sidePanel.getTaskPropertiesTab().addNewPropertiesTitledModule(taskInformation, "Information");
taskAssignedResources = (TaskAssignedResources) createPropertiesModule(new TaskAssignedResources());
sidePanel.getTaskPropertiesTab().addNewPropertiesTitledModule(taskAssignedResources, "Assigned Resources");
taskDependencies = (TaskDependencies) createPropertiesModule(new TaskDependencies());
sidePanel.getTaskPropertiesTab().addNewPropertiesTitledModule(taskDependencies, "Dependencies");
resourceInformation = (ResourceInformation) createPropertiesModule(new ResourceInformation());
sidePanel.getResourcePropertiesTab().addNewPropertiesTitledModule(resourceInformation, "Information");
resourceAssignedTasks = (ResourceAssignedTasks) createPropertiesModule(new ResourceAssignedTasks());
sidePanel.getResourcePropertiesTab().addNewPropertiesTitledModule(resourceAssignedTasks, "Assigned Tasks");
tasksButtonsBox = new TasksButtonBox();
resourcesButtonBox = new ResourcesButtonBox();
taskSplitPane = new SplitPane();
resourceSplitPane = new SplitPane();
return new MainWindowView(
this,
project,
menuBar,
sidePanel,
new TaskPane(
this,
createTaskTable(
taskHorizontalScrollValueProperty(),
taskVerticalScrollValueProperty()),
taskGanttPlan,
tasksButtonsBox,
taskSplitPane),
new ResourcePane(
this,
createResourceTable(
resourceHorizontalScrollValueProperty(),
resourceVerticalScrollValueProperty()),
resourceGanttPlan,
resourcesButtonBox,
resourceSplitPane));
}
private boolean isMaximized() {
return SettingsManager.getInstance().getUIValueByKey("MaximizedWindow") != null &&
SettingsManager.getInstance().getUIValueByKey("MaximizedWindow").equals("1");
}
private IModule createPropertiesModule(IModule module) {
module.createPane();
return module;
}
private AbstractTableView<ITask> createTaskTable(DoubleProperty horizontalScrollValue,
DoubleProperty verticalScrollValue) {
taskTableView = new TaskTableView<>(horizontalScrollValue, verticalScrollValue);
taskTableView.setRoot(new TreeItem<>(new Task()));
taskTableView.setRowFactory(new TaskTreeTableViewRowFactory(this, new TaskTableDragAndDrop(this)));
taskTableView.setRowFactory(new TaskTreeTableViewRowFactory(this, new TaskTableDragAndDrop(this)));
taskListChangeListener = this::taskChangeListenerHandler;
project.getTaskList().addListener(new WeakListChangeListener<>(taskListChangeListener));
taskChangeListener = this::refreshSelectedTask;
taskTableView.getSelectionModel().selectedItemProperty().addListener(new WeakChangeListener<>(taskChangeListener));
taskTreeItemsChangeListener = this::setSelectedTaskNull;
taskTableView.getRoot().getChildren().addListener(new WeakListChangeListener<>(taskTreeItemsChangeListener));
return taskTableView;
}
private void setSelectedTaskNull(ListChangeListener.Change<? extends TreeItem<ITask>> change) {
while (change.next()) {
if (change.getList().isEmpty()) {
selectedTask.setValue(null);
}
}
}
private void refreshSelectedTask(ObservableValue<? extends TreeItem<ITask>> observableValue,
TreeItem<ITask> oldTaskTreeItem,
TreeItem<ITask> newTaskTreeItem) {
if (newTaskTreeItem != null) {
selectedTask.setValue(newTaskTreeItem.getValue());
}
}
private AbstractTableView<IResource> createResourceTable(DoubleProperty horizontalScrollValue,
DoubleProperty verticalScrollValue) {
resourceTableView = new ResourceTableView<>(horizontalScrollValue, verticalScrollValue);
resourceTableView.setRoot(new TreeItem<>(new Resource()));
resourceTableView.setRowFactory(new ResourceTreeTableViewRowFactory(this, new ResourceTableDragAndDrop(this)));
resourceListChangeListener = this::resourceChangeListenerHandler;
project.getResourceList().addListener(new WeakListChangeListener<>(resourceListChangeListener));
resourceChangeListener = this::refreshSelectedResource;
resourceTableView.getSelectionModel().selectedItemProperty().addListener(new WeakChangeListener<>(resourceChangeListener));
resourceTreeItemsChangeListener = this::setSelectedResourceNull;
resourceTableView.getRoot().getChildren().addListener(new WeakListChangeListener<>(resourceTreeItemsChangeListener));
return resourceTableView;
}
private void setSelectedResourceNull(ListChangeListener.Change<? extends TreeItem<IResource>> change) {
while (change.next()) {
if (change.getList().isEmpty()) {
selectedResource.setValue(null);
}
}
}
private void refreshSelectedResource(ObservableValue<? extends TreeItem<IResource>> observableValue,
TreeItem<IResource> oldResourceTreeItem,
TreeItem<IResource> newResourceTreeItem) {
if (newResourceTreeItem != null) {
selectedResource.setValue(newResourceTreeItem.getValue());
}
}
private void resourceChangeListenerHandler(ListChangeListener.Change<? extends IResource> change) {
// При добавлении или удалении элемента из модели обновляем таблицу задач
while (change.next()) {
// Добавляем
if (change.wasAdded()) {
change.getAddedSubList().forEach(resource -> {
// Получаем индекс задачи
int indexOfTask = project.getResourceList().indexOf(resource);
// Создаем элемент таблицы и присваиваем ему нашу задачу
TreeItem<IResource> resourceTreeItem = new TreeItem<>(resource);
// Добавляем элемент в таблицу на нужную строку (indexOfTask)
resourceTableView.getRoot().getChildren().add(indexOfTask, resourceTreeItem); //обязательно нужен индекс элемента, иначе драгндроп не будет работать
// Выделяем добавленный элемент в таблице
resourceTableView.getSelectionModel().select(resourceTreeItem);
});
}
// Удаляем
if (change.wasRemoved()) {
change.getRemoved().forEach(resource -> {
// Сначала удаляем из таблицы...
removeTreeItem(resource, resourceTableView.getRoot().getChildren());
});
}
}
}
private void taskChangeListenerHandler(ListChangeListener.Change<? extends ITask> change) {
// При добавлении или удалении элемента из модели обновляем таблицу задач
while (change.next()) {
// Добавляем
if (change.wasAdded()) {
change.getAddedSubList().forEach(task -> {
// Получаем индекс задачи
int indexOfTask = project.getTaskList().indexOf(task);
// Создаем элемент таблицы и присваиваем ему нашу задачу
TreeItem<ITask> taskTreeItem = new TreeItem<>(task);
// Добавляем элемент в таблицу на нужную строку (indexOfTask)
taskTableView.getRoot().getChildren().add(indexOfTask, taskTreeItem); //обязательно нужен индекс элемента, иначе драгндроп не будет работать
// Выделяем добавленный элемент в таблице
taskTableView.getSelectionModel().select(taskTreeItem);
// Добавляем задачу на диаграмму
taskGanttPlan.getObjectsLayer().addTaskBar(task, null);
});
}
// Удаляем
if (change.wasRemoved()) {
change.getRemoved().forEach(task -> {
// Сначала удаляем из таблицы...
removeTreeItem(task, taskTableView.getRoot().getChildren());
// ...а теперь с диаграммы
taskGanttPlan.getObjectsLayer().removeTaskBar(task);
taskGanttPlan.getSelectedObjectLayer().removeBackgroundTaskBar(task);
});
}
}
}
public <T> void removeTreeItem(T object, ObservableList<TreeItem<T>> itemList) {
itemList.removeIf(item -> item.getValue().equals(object));
}
public void refreshInformation() {
// При загрузке проверяем наличие задач
for (ITask task : project.getTaskList()) {
TreeItem<ITask> treeItem = new TreeItem<>(task);
taskTableView.getRoot().getChildren().add(treeItem);
taskTableView.getSelectionModel().select(treeItem);
}
for (IResource resource : project.getResourceList()) {
TreeItem<IResource> treeItem = new TreeItem<>(resource);
resourceTableView.getRoot().getChildren().add(treeItem);
resourceTableView.getSelectionModel().select(treeItem);
}
taskGanttPlan.getObjectsLayer().refreshPlan();
taskGanttPlan.getRelationsLayer().refreshRelationsDiagram(this);
resourceGanttPlan.getObjectsLayer().refreshPlan();
}
public IProject getProject() {
return project;
}
public IView getView() {
return view;
}
public int getZoomMultiplier() {
return zoomMultiplier.get();
}
public IntegerProperty zoomMultiplierProperty() {
return zoomMultiplier;
}
public double getGanttHorizontalScrollValue() {
return ganttHorizontalScrollValue.get();
}
public DoubleProperty ganttHorizontalScrollValueProperty() {
return ganttHorizontalScrollValue;
}
public double getTaskVerticalScrollValue() {
return taskVerticalScrollValue.get();
}
public DoubleProperty taskVerticalScrollValueProperty() {
return taskVerticalScrollValue;
}
public double getResourceVerticalScrollValue() {
return resourceVerticalScrollValue.get();
}
public DoubleProperty resourceVerticalScrollValueProperty() {
return resourceVerticalScrollValue;
}
public double getTaskHorizontalScrollValue() {
return taskHorizontalScrollValue.get();
}
public DoubleProperty taskHorizontalScrollValueProperty() {
return taskHorizontalScrollValue;
}
public double getResourceHorizontalScrollValue() {
return resourceHorizontalScrollValue.get();
}
public DoubleProperty resourceHorizontalScrollValueProperty() {
return resourceHorizontalScrollValue;
}
public double getSplitPaneDividerValue() {
return splitPaneDividerValue.get();
}
public DoubleProperty splitPaneDividerValueProperty() {
return splitPaneDividerValue;
}
public double getWidthOfWindow() {
return widthOfWindow.get();
}
public DoubleProperty widthOfWindowProperty() {
return widthOfWindow;
}
public double getHeightOfWindow() {
return heightOfWindow.get();
}
public DoubleProperty heightOfWindowProperty() {
return heightOfWindow;
}
public boolean getIsMaximized() {
return isMaximized.get();
}
public BooleanProperty isMaximizedProperty() {
return isMaximized;
}
public AbstractTableView<ITask> getTaskTableView() {
return taskTableView;
}
public AbstractTableView<IResource> getResourceTableView() {
return resourceTableView;
}
public AbstractGanttPlan getTaskGanttPlan() {
return taskGanttPlan;
}
public AbstractGanttPlan getResourceGanttPlan() {
return resourceGanttPlan;
}
public File getProjectFile() {
return projectFile;
}
public void setProjectFile(File projectFile) {
this.projectFile = projectFile;
}
public ITask getSelectedTask() {
return selectedTask.get();
}
public ObjectProperty<ITask> selectedTaskProperty() {
return selectedTask;
}
public IResource getSelectedResource() {
return selectedResource.get();
}
public ObjectProperty<IResource> selectedResourceProperty() {
return selectedResource;
}
public CommandExecutor getCommandExecutor() {
return commandExecutor;
}
public AbstractPropertiesSidePanel getSidePanel() {
return sidePanel;
}
}