package ru.khasang.cachoeira.view.mainwindow.diagram.ganttplan.objectslayer.taskbar; import javafx.animation.Timeline; import javafx.beans.InvalidationListener; import javafx.beans.WeakInvalidationListener; import javafx.beans.value.ChangeListener; import javafx.beans.value.WeakChangeListener; import javafx.collections.ListChangeListener; import javafx.collections.WeakListChangeListener; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import ru.khasang.cachoeira.model.IDependentTask; import ru.khasang.cachoeira.model.IResource; import ru.khasang.cachoeira.model.ITask; import ru.khasang.cachoeira.viewcontroller.MainWindowController; import java.time.LocalDate; public class TaskGanttPlanTaskBar extends TaskBar { @SuppressWarnings("FieldCanBeLocal") private ListChangeListener<ITask> taskListChangeListener; @SuppressWarnings("FieldCanBeLocal") private ChangeListener<LocalDate> startDateChangeListener; @SuppressWarnings("FieldCanBeLocal") private ChangeListener<LocalDate> finishDateChangeListener; @SuppressWarnings("FieldCanBeLocal") private ListChangeListener<IResource> resourceListChangeListener; @SuppressWarnings("FieldCanBeLocal") private InvalidationListener hoverListener; @SuppressWarnings("FieldCanBeLocal") private ListChangeListener<IDependentTask> dependentTaskListChangeListener; @SuppressWarnings("FieldCanBeLocal") private InvalidationListener zoomListener; public TaskGanttPlanTaskBar(MainWindowController controller) { this.controller = controller; } @Override public void initTaskRectangle(ITask task, IResource resource) { super.initTaskRectangle(task, resource); } @Override protected void setParameters(ITask task, IResource resource, Rectangle backgroundRectangle) { backgroundRectangle.setWidth(taskWidth( task.getStartDate(), task.getFinishDate(), controller.getZoomMultiplier())); backgroundRectangle.setLayoutY(6); this.setLayoutX(taskX( task.getStartDate(), controller.getProject().getStartDate(), controller.getZoomMultiplier())); this.setLayoutY(taskY(controller.getProject().getTaskList().indexOf(task))); } @Override protected double taskY(int rowIndex) { this.rowIndex = rowIndex; return (rowIndex * ROW_HEIGHT); } @Override protected void setListeners(ITask task, IResource resource, Rectangle backgroundRectangle, Rectangle donePercentRectangle) { taskListChangeListener = change -> { while (change.next()) { if (change.wasRemoved() || change.wasAdded()) { // Анимация при удалении и добавления элемента на диаграмме Timeline timeline = createTimelineAnimation( this.layoutYProperty(), taskY(controller.getProject().getTaskList().indexOf(task)), (rowIndex + 1) * 150); timeline.play(); } } }; startDateChangeListener = (observable, oldValue, newValue) -> { // ... если эти изменения произошли не спомощью мышки, то... if (!wasMovedByMouse) { // ... меняем положение метки на диаграмме... // Animation Timeline timeline = createTimelineAnimation( this.layoutXProperty(), taskX( task.getStartDate(), controller.getProject().getStartDate(), controller.getZoomMultiplier() ), 400 ); Timeline timeline1 = createTimelineAnimation( backgroundRectangle.widthProperty(), taskWidth( task.getStartDate(), task.getFinishDate(), controller.getZoomMultiplier() ), 400 ); timeline.play(); timeline1.play(); } }; finishDateChangeListener = (observable, oldValue, newValue) -> { if (!wasMovedByMouse) { // Animation Timeline timeline = createTimelineAnimation( backgroundRectangle.widthProperty(), taskWidth( task.getStartDate(), task.getFinishDate(), controller.getZoomMultiplier() ), 400 ); timeline.play(); } }; resourceListChangeListener = change -> { while (change.next()) { // Если добавился if (change.wasAdded()) { for (IResource res : change.getAddedSubList()) { controller.getResourceGanttPlan().getObjectsLayer().addTaskBar(task, res); } } // Если удалился if (change.wasRemoved()) { for (IResource res : change.getRemoved()) { controller.getResourceGanttPlan().getObjectsLayer().removeTaskBarByResource(task, res); } } } }; hoverListener = observable -> { if (this.isHover()) { backgroundRectangle.setFill(Color.valueOf("#03bdf4")); backgroundRectangle.setStroke(Color.valueOf("#03d1f4")); donePercentRectangle.setFill(Color.valueOf("#0395f4")); } else { backgroundRectangle.setFill(Color.valueOf("#03A9F4")); //цвет прямоугольника backgroundRectangle.setStroke(Color.valueOf("#03bdf4")); donePercentRectangle.setFill(Color.valueOf("#0381f4")); } }; dependentTaskListChangeListener = change -> { while (change.next()) { if (change.wasAdded()) { change.getAddedSubList().forEach(dependentTask -> controller.getTaskGanttPlan() .getRelationsLayer() .addRelation(dependentTask, controller.getSelectedTask(), controller)); } if (change.wasRemoved()) { change.getRemoved().forEach(dependentTask ->controller.getTaskGanttPlan() .getRelationsLayer().removeRelation(dependentTask.getTask(), this.task)); } } }; zoomListener = observable -> { this.setLayoutX(taskX(task.getStartDate(), controller.getProject().getStartDate(), controller.getZoomMultiplier())); backgroundRectangle.setWidth(taskWidth(task.getStartDate(), task.getFinishDate(), controller.getZoomMultiplier())); }; /* Следим за изменениями в списке задач, если произошло добавление или удаление элемента в списке, то пересчитываем индексы у элементов на диаграмме */ controller.getProject().getTaskList().addListener(new WeakListChangeListener<>(taskListChangeListener)); // Если начальная дата изменилась, то... task.startDateProperty().addListener(new WeakChangeListener<>(startDateChangeListener)); // Если конечная дата изменилась, то... task.finishDateProperty().addListener(new WeakChangeListener<>(finishDateChangeListener)); // Следим за списком ресурсов привязанных к данной задаче/ task.getResourceList().addListener(new WeakListChangeListener<>(resourceListChangeListener)); //подсветка при наведении // TODO: 15.01.2016 Сделать анимацию this.hoverProperty().addListener(hoverListener); controller.getSelectedTask().getParentTasks().addListener(new WeakListChangeListener<>(dependentTaskListChangeListener)); controller.zoomMultiplierProperty().addListener(new WeakInvalidationListener(zoomListener)); } }