package ru.khasang.cachoeira.viewcontroller.contextmenus; import javafx.collections.ObservableList; import javafx.scene.control.CheckMenuItem; import javafx.scene.control.ContextMenu; import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; import ru.khasang.cachoeira.commands.project.RemoveTaskFromProjectCommand; import ru.khasang.cachoeira.commands.task.*; import ru.khasang.cachoeira.model.*; import ru.khasang.cachoeira.viewcontroller.MainWindowController; /** * Класс описывает контекстное меню всплывающее при нажатии правой кнопкой на задаче. */ public class TaskContextMenu extends ContextMenu { private final IProject project; private final ITask task; private final MainWindowController controller; public TaskContextMenu(IProject project, ITask task, MainWindowController controller) { this.project = project; this.task = task; this.controller = controller; } public void initMenus() { this.getItems().clear(); Menu assignResourceMenu = new Menu("Assign Resource"); Menu assignDependencyTask = new Menu("Assign Predecessor"); MenuItem removeTaskMenuItem = new MenuItem("Remove Task"); removeTaskMenuItem.setOnAction(event -> controller.getCommandExecutor().execute(new RemoveTaskFromProjectCommand(project, task))); this.getItems().addAll(assignResourceMenu, assignDependencyTask, removeTaskMenuItem); //заполняем меню this.setOnShowing(event -> { refreshResourceMenu(assignResourceMenu.getItems(), task, project.getResourceList()); refreshDependencyTaskMenu(assignDependencyTask.getItems(), task, project.getTaskList()); }); } private void refreshDependencyTaskMenu(ObservableList<MenuItem> menuItemsList, ITask task, ObservableList<ITask> taskList) { menuItemsList.clear(); taskList.stream() .filter(parentTask -> !parentTask.equals(task)) // Убираем возможность присвоить предшественником саму себя .forEach(parentTask -> { CheckMenuItem checkMenuItem = new CheckMenuItem(parentTask.getName()); // Расставляем галочки на нужных пунктах task.getParentTasks() .stream() .filter(dependentTask -> parentTask.equals(dependentTask.getTask()) && !checkMenuItem.isSelected()) .forEach(dependentTask -> checkMenuItem.setSelected(true)); // Вешаем ивент при нажатии на каком-либо пункте меню checkMenuItem.setOnAction(event -> { if (checkMenuItem.isSelected()) { controller.getCommandExecutor().execute(new AddParentTaskToTaskCommand(task, new DependentTask(parentTask, TaskDependencyType.FINISHSTART))); controller.getCommandExecutor().execute(new AddChildTaskToTaskCommand(parentTask, new DependentTask(task, null))); } else { task.getParentTasks().stream() .filter(dependentTask -> dependentTask.getTask().equals(parentTask)) .findFirst() .ifPresent(dependentTask -> controller.getCommandExecutor().execute(new RemoveParentTaskFromTaskCommand(task, dependentTask))); parentTask.getChildTasks().stream() .filter(dependentTask -> dependentTask.getTask().equals(task)) .findFirst() .ifPresent(dependentTask -> controller.getCommandExecutor().execute(new RemoveChildTaskFromTaskCommand(parentTask, dependentTask))); } }); menuItemsList.add(checkMenuItem); }); // Отключаем те задачи, которые уже находятся в списке последователей (childTasks), // чтобы нельзя было сделать закольцованность (например Задача 2 начинается после // Задачи 1, а Задача 1, после Задачи 2) setDisableSelectionChildTasks(task, menuItemsList); } /** * Рекурсивный метод который отключает возможность сделать предшественником задачу, если она уже находится * в списке наследников (или в списках наследников наследников). * Например, есть последовательность Задача 1 -> Задача 2 -> Задача 3. * Нажав правой кнопкой на Задаче 1 мы не сможем сделать предшественником ни Задачу 2, ни Задачу 3 (до тех пор пока * не уберем предшественником Задачу 1 у Задачи 2). * * @param task Задача на которую нажали правой кнопкой. * @param menuItems Список меню с задачами. */ private void setDisableSelectionChildTasks(ITask task, ObservableList<MenuItem> menuItems) { if (!task.getChildTasks().isEmpty()) { task.getChildTasks() .stream() .forEach(childTask -> { setDisableSelectionChildTasks(childTask.getTask(), menuItems); menuItems .stream() .filter(menuItem -> menuItem.getText().equals(childTask.getTask().getName())) .forEach(menuItem -> menuItem.setDisable(true)); }); } } private void refreshResourceMenu(ObservableList<MenuItem> menuItemList, ITask task, ObservableList<IResource> resourceList) { menuItemList.clear(); for (IResource resource : resourceList) { //берем список всех ресурсов CheckMenuItem checkMenuItem = new CheckMenuItem(resource.getName()); //создаем элемент меню для каждого ресурса task.getResourceList() .stream() .filter(resourceOfTask -> resource.equals(resourceOfTask) && !checkMenuItem.isSelected()) .forEach(resourceOfTask -> checkMenuItem.setSelected(true)); checkMenuItem.setOnAction(event -> { if (checkMenuItem.isSelected()) { controller.getCommandExecutor().execute(new AddResourceToTaskCommand(task, resource)); } else { controller.getCommandExecutor().execute(new RemoveResourceFromTaskCommand(task, resource)); } }); menuItemList.add(checkMenuItem); } } }