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.model.*; public class ParentTaskContextMenu extends ContextMenu { public ParentTaskContextMenu() { } public void initMenus(IProject project, ITask task) { this.getItems().clear(); Menu assignDependencyTask = new Menu("Assign Predecessor"); this.getItems().addAll(assignDependencyTask); //заполняем меню this.setOnShowing(event -> 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()) { IDependentTask parentDependentTask = new DependentTask(); parentDependentTask.setTask(parentTask); parentDependentTask.setDependenceType(TaskDependencyType.FINISHSTART); task.addParentTask(parentDependentTask); IDependentTask childTask = new DependentTask(); childTask.setTask(task); parentTask.addChildTask(childTask); } else { task.getParentTasks().removeIf(parentDependentTask -> parentDependentTask.getTask().equals(parentTask)); parentTask.getChildTasks().removeIf(childTask -> childTask.getTask().equals(task)); } }); 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)); }); } } }