Skip to content

Commit

Permalink
task assigning: Use button and allow the user to move tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
ge0ffrey committed Apr 28, 2016
1 parent bd1d27e commit 894aab3
Show file tree
Hide file tree
Showing 8 changed files with 13,911 additions and 28 deletions.
1,530 changes: 1,530 additions & 0 deletions optaplanner-examples/data/taskassigning/unsolved/100tasks-5employees.xml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

10,716 changes: 10,716 additions & 0 deletions optaplanner-examples/data/taskassigning/unsolved/500tasks-20employees.xml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Expand Up @@ -24,12 +24,13 @@
import org.optaplanner.core.api.domain.variable.CustomShadowVariable; import org.optaplanner.core.api.domain.variable.CustomShadowVariable;
import org.optaplanner.core.api.domain.variable.PlanningVariable; import org.optaplanner.core.api.domain.variable.PlanningVariable;
import org.optaplanner.core.api.domain.variable.PlanningVariableGraphType; import org.optaplanner.core.api.domain.variable.PlanningVariableGraphType;
import org.optaplanner.examples.common.swingui.components.Labeled;
import org.optaplanner.examples.taskassigning.domain.solver.MovableTaskSelectionFilter; import org.optaplanner.examples.taskassigning.domain.solver.MovableTaskSelectionFilter;
import org.optaplanner.examples.taskassigning.domain.solver.StartTimeUpdatingVariableListener; import org.optaplanner.examples.taskassigning.domain.solver.StartTimeUpdatingVariableListener;


@PlanningEntity(movableEntitySelectionFilter = MovableTaskSelectionFilter.class) @PlanningEntity(movableEntitySelectionFilter = MovableTaskSelectionFilter.class)
@XStreamAlias("MsTask") @XStreamAlias("MsTask")
public class Task extends TaskOrEmployee { public class Task extends TaskOrEmployee implements Labeled {


private TaskType taskType; private TaskType taskType;
private int indexInTaskType; private int indexInTaskType;
Expand Down
Expand Up @@ -103,8 +103,8 @@ public class TaskAssigningGenerator extends LoggingMain {
"Research"); "Research");
private static final StringDataGenerator customerNameGenerator = StringDataGenerator.build1kCompanyNames(); private static final StringDataGenerator customerNameGenerator = StringDataGenerator.build1kCompanyNames();
private static final StringDataGenerator employeeNameGenerator = StringDataGenerator.build10kFullNames(); private static final StringDataGenerator employeeNameGenerator = StringDataGenerator.build10kFullNames();
public static final int BASE_DURATION_MINIMUM = 20; public static final int BASE_DURATION_MINIMUM = 30;
public static final int BASE_DURATION_MAXIMUM = 120; public static final int BASE_DURATION_MAXIMUM = 90;
public static final int BASE_DURATION_AVERAGE = BASE_DURATION_MINIMUM + BASE_DURATION_MAXIMUM / 2; public static final int BASE_DURATION_AVERAGE = BASE_DURATION_MINIMUM + BASE_DURATION_MAXIMUM / 2;
private static final int SKILL_SET_SIZE_MINIMUM = 2; private static final int SKILL_SET_SIZE_MINIMUM = 2;
private static final int SKILL_SET_SIZE_MAXIMUM = 4; private static final int SKILL_SET_SIZE_MAXIMUM = 4;
Expand All @@ -127,7 +127,7 @@ public void generate() {
writeTaskAssigningSolution(50, 5); writeTaskAssigningSolution(50, 5);
writeTaskAssigningSolution(100, 5); writeTaskAssigningSolution(100, 5);
writeTaskAssigningSolution(500, 20); writeTaskAssigningSolution(500, 20);
writeTaskAssigningSolution(1000, 20); // For more tasks, switch to BendableLongScore to avoid overflow in the score.
} }


private void writeTaskAssigningSolution(int taskListSize, int employeeListSize) { private void writeTaskAssigningSolution(int taskListSize, int employeeListSize) {
Expand Down
Expand Up @@ -68,7 +68,7 @@ public TaskAssigningPanel() {
setLayout(new BorderLayout()); setLayout(new BorderLayout());
JPanel headerPanel = createHeaderPanel(); JPanel headerPanel = createHeaderPanel();
add(headerPanel, BorderLayout.NORTH); add(headerPanel, BorderLayout.NORTH);
taskOverviewPanel = new TaskOverviewPanel(); taskOverviewPanel = new TaskOverviewPanel(this);
add(new JScrollPane(taskOverviewPanel), BorderLayout.CENTER); add(new JScrollPane(taskOverviewPanel), BorderLayout.CENTER);
} }


Expand Down
Expand Up @@ -20,35 +20,48 @@
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JViewport; import javax.swing.JViewport;
import javax.swing.Scrollable; import javax.swing.Scrollable;
import javax.swing.SwingConstants; import javax.swing.SwingConstants;


import org.optaplanner.examples.common.swingui.SolutionPanel; import org.optaplanner.examples.common.swingui.SolutionPanel;
import org.optaplanner.examples.common.swingui.components.LabeledComboBoxRenderer;
import org.optaplanner.examples.pas.domain.Bed;
import org.optaplanner.examples.pas.domain.BedDesignation;
import org.optaplanner.examples.pas.domain.Patient;
import org.optaplanner.examples.taskassigning.domain.Employee; import org.optaplanner.examples.taskassigning.domain.Employee;
import org.optaplanner.examples.taskassigning.domain.Skill; import org.optaplanner.examples.taskassigning.domain.Skill;
import org.optaplanner.examples.taskassigning.domain.Task; import org.optaplanner.examples.taskassigning.domain.Task;
import org.optaplanner.examples.taskassigning.domain.TaskAssigningSolution; import org.optaplanner.examples.taskassigning.domain.TaskAssigningSolution;
import org.optaplanner.examples.taskassigning.domain.TaskOrEmployee;
import org.optaplanner.swing.impl.SwingUtils;
import org.optaplanner.swing.impl.TangoColorFactory; import org.optaplanner.swing.impl.TangoColorFactory;


public class TaskOverviewPanel extends JPanel implements Scrollable { public class TaskOverviewPanel extends JPanel implements Scrollable {


public static final int HEADER_ROW_HEIGHT = 40; public static final int HEADER_ROW_HEIGHT = 50;
public static final int HEADER_COLUMN_WIDTH = 150; public static final int HEADER_COLUMN_WIDTH = 150;
public static final int ROW_HEIGHT = 40; public static final int ROW_HEIGHT = 50;
public static final int TIME_COLUMN_WIDTH = 60; public static final int TIME_COLUMN_WIDTH = 60;


private final TaskAssigningPanel taskAssigningPanel;
private final ImageIcon[] affinityIcons; private final ImageIcon[] affinityIcons;
private final ImageIcon[] priorityIcons; private final ImageIcon[] priorityIcons;


Expand All @@ -57,7 +70,8 @@ public class TaskOverviewPanel extends JPanel implements Scrollable {


private int consumedDuration = 0; private int consumedDuration = 0;


public TaskOverviewPanel() { public TaskOverviewPanel(TaskAssigningPanel taskAssigningPanel) {
this.taskAssigningPanel = taskAssigningPanel;
affinityIcons = new ImageIcon[] { affinityIcons = new ImageIcon[] {
new ImageIcon(getClass().getResource("affinityNone.png")), new ImageIcon(getClass().getResource("affinityNone.png")),
new ImageIcon(getClass().getResource("affinityLow.png")), new ImageIcon(getClass().getResource("affinityLow.png")),
Expand Down Expand Up @@ -94,8 +108,7 @@ public void resetPanel(TaskAssigningSolution taskAssigningSolution) {
int panelWidth = HEADER_COLUMN_WIDTH; int panelWidth = HEADER_COLUMN_WIDTH;
int unassignedIndex = employeeList.size(); int unassignedIndex = employeeList.size();
for (Task task : taskAssigningSolution.getTaskList()) { for (Task task : taskAssigningSolution.getTaskList()) {
TaskPanel taskPanel = new TaskPanel(task); JButton taskButton = createTaskButton(task);
taskPanel.setToolTipText(task.getToolText());
int x; int x;
int y; int y;
if (task.getEmployee() != null) { if (task.getEmployee() != null) {
Expand All @@ -106,11 +119,11 @@ public void resetPanel(TaskAssigningSolution taskAssigningSolution) {
y = HEADER_ROW_HEIGHT + unassignedIndex * ROW_HEIGHT; y = HEADER_ROW_HEIGHT + unassignedIndex * ROW_HEIGHT;
unassignedIndex++; unassignedIndex++;
} }
if (x + taskPanel.getWidth() > panelWidth) { if (x + taskButton.getWidth() > panelWidth) {
panelWidth = x + taskPanel.getWidth(); panelWidth = x + taskButton.getWidth();
} }
taskPanel.setLocation(x, y); taskButton.setLocation(x, y);
add(taskPanel); add(taskButton);
} }
for (int x = HEADER_COLUMN_WIDTH; x < panelWidth; x += TIME_COLUMN_WIDTH) { for (int x = HEADER_COLUMN_WIDTH; x < panelWidth; x += TIME_COLUMN_WIDTH) {
// Start at 8:00 // Start at 8:00
Expand Down Expand Up @@ -148,24 +161,46 @@ protected void paintComponent(Graphics g) {
g.fillRect(lineX, 0, getWidth(), getHeight()); g.fillRect(lineX, 0, getWidth(), getHeight());
} }


private class TaskPanel extends JPanel { private JButton createTaskButton(Task task) {
JButton taskButton = SwingUtils.makeSmallButton(new JButton(new TaskAction(task)));
taskButton.setBackground(task.isLocked() ? TangoColorFactory.ALUMINIUM_3 : TangoColorFactory.ALUMINIUM_1);
taskButton.setHorizontalTextPosition(SwingConstants.CENTER);
taskButton.setVerticalTextPosition(SwingConstants.TOP);
taskButton.setSize(task.getDuration(), ROW_HEIGHT);
return taskButton;
}

private class TaskAction extends AbstractAction {


private final Task task; private final Task task;


public TaskPanel(Task task) { public TaskAction(Task task) {
super(task.getCode(), new TaskOrEmployeeIcon(task));
this.task = task; this.task = task;
setLayout(null); // Tooltip
setBackground(task.isLocked() ? TangoColorFactory.ALUMINIUM_3 : TangoColorFactory.ALUMINIUM_1); putValue(SHORT_DESCRIPTION, task.getToolText());
setSize(task.getDuration(), ROW_HEIGHT); }
JLabel codeLabel = new JLabel(task.getCode(), SwingConstants.CENTER);
codeLabel.setLocation(0, 0); @Override
codeLabel.setSize(task.getDuration(), ROW_HEIGHT / 2); public void actionPerformed(ActionEvent e) {
add(codeLabel); JPanel listFieldsPanel = new JPanel(new GridLayout(2, 1));
JLabel iconLabel = new JLabel(new TaskOrEmployeeIcon(task), SwingConstants.CENTER); List<TaskOrEmployee> taskOrEmployeeList = new ArrayList<>();
iconLabel.setLocation(0, ROW_HEIGHT / 2); taskOrEmployeeList.addAll(taskAssigningPanel.getSolution().getEmployeeList());
iconLabel.setSize(task.getDuration(), ROW_HEIGHT / 2); taskOrEmployeeList.addAll(taskAssigningPanel.getSolution().getTaskList());
add(iconLabel); // Add 1 to array size to add null, which makes the entity unassigned
setBorder(BorderFactory.createLineBorder(Color.BLACK)); JComboBox TaskOrEmployeeListField = new JComboBox(
taskOrEmployeeList.toArray(new Object[taskOrEmployeeList.size() + 1]));
LabeledComboBoxRenderer.applyToComboBox(TaskOrEmployeeListField);
TaskOrEmployeeListField.setSelectedItem(task.getPreviousTaskOrEmployee());
listFieldsPanel.add(TaskOrEmployeeListField);
int result = JOptionPane.showConfirmDialog(TaskOverviewPanel.this.getRootPane(),
listFieldsPanel, "Select previous task or employee for " + task.getLabel(),
JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
TaskOrEmployee toTaskOrEmployee = (TaskOrEmployee) TaskOrEmployeeListField.getSelectedItem();
taskAssigningPanel.getSolutionBusiness().doChangeMove(task, "previousTaskOrEmployee", toTaskOrEmployee);
taskAssigningPanel.getSolverAndPersistenceFrame().resetScreen();
}
} }


} }
Expand Down

0 comments on commit 894aab3

Please sign in to comment.