Skip to content

Commit

Permalink
examples: improve combobox labels + enable moving dinner party guests
Browse files Browse the repository at this point in the history
  • Loading branch information
ge0ffrey committed Jan 27, 2015
1 parent 48f53eb commit 80bca5d
Show file tree
Hide file tree
Showing 28 changed files with 224 additions and 46 deletions.
Expand Up @@ -384,6 +384,15 @@ public String buildInvalidVariableNameExceptionMessage(String variableName) {


} }


public boolean hasAnyChainedGenuineVariables() {
for (GenuineVariableDescriptor variableDescriptor : effectiveGenuineVariableDescriptorMap.values()) {
if (!variableDescriptor.isChained()) {
return true;
}
}
return false;
}

// ************************************************************************ // ************************************************************************
// Extraction methods // Extraction methods
// ************************************************************************ // ************************************************************************
Expand Down
Expand Up @@ -18,9 +18,10 @@


import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import org.optaplanner.examples.common.domain.AbstractPersistable; import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.common.swingui.components.Labeled;


@XStreamAlias("CloudComputer") @XStreamAlias("CloudComputer")
public class CloudComputer extends AbstractPersistable { public class CloudComputer extends AbstractPersistable implements Labeled {


private int cpuPower; // in gigahertz private int cpuPower; // in gigahertz
private int memory; // in gigabyte RAM private int memory; // in gigabyte RAM
Expand Down
Expand Up @@ -45,6 +45,7 @@
import org.optaplanner.examples.cloudbalancing.domain.CloudComputer; import org.optaplanner.examples.cloudbalancing.domain.CloudComputer;
import org.optaplanner.examples.cloudbalancing.domain.CloudProcess; import org.optaplanner.examples.cloudbalancing.domain.CloudProcess;
import org.optaplanner.examples.common.swingui.SolutionPanel; import org.optaplanner.examples.common.swingui.SolutionPanel;
import org.optaplanner.examples.common.swingui.components.LabeledComboBoxRenderer;


public class CloudBalancingPanel extends SolutionPanel { public class CloudBalancingPanel extends SolutionPanel {


Expand Down Expand Up @@ -352,8 +353,11 @@ public CloudProcessAction(CloudProcess process) {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
JPanel listFieldsPanel = new JPanel(new GridLayout(1, 2)); JPanel listFieldsPanel = new JPanel(new GridLayout(1, 2));
listFieldsPanel.add(new JLabel("Computer:")); listFieldsPanel.add(new JLabel("Computer:"));
List<CloudComputer> periodList = getCloudBalance().getComputerList(); List<CloudComputer> computerList = getCloudBalance().getComputerList();
JComboBox computerListField = new JComboBox(periodList.toArray()); // Add 1 to array size to add null, which makes the entity unassigned
JComboBox<CloudComputer> computerListField = new JComboBox<CloudComputer>(
computerList.toArray(new CloudComputer[computerList.size() + 1]));
computerListField.setRenderer(new LabeledComboBoxRenderer());
computerListField.setSelectedItem(process.getComputer()); computerListField.setSelectedItem(process.getComputer());
listFieldsPanel.add(computerListField); listFieldsPanel.add(computerListField);
int result = JOptionPane.showConfirmDialog(CloudBalancingPanel.this.getRootPane(), listFieldsPanel, int result = JOptionPane.showConfirmDialog(CloudBalancingPanel.this.getRootPane(), listFieldsPanel,
Expand Down
Expand Up @@ -18,6 +18,7 @@


import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
Expand All @@ -29,10 +30,14 @@
import org.optaplanner.core.api.solver.Solver; import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.event.BestSolutionChangedEvent; import org.optaplanner.core.api.solver.event.BestSolutionChangedEvent;
import org.optaplanner.core.api.solver.event.SolverEventListener; import org.optaplanner.core.api.solver.event.SolverEventListener;
import org.optaplanner.core.impl.domain.entity.descriptor.EntityDescriptor;
import org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor;
import org.optaplanner.core.impl.domain.variable.descriptor.GenuineVariableDescriptor; import org.optaplanner.core.impl.domain.variable.descriptor.GenuineVariableDescriptor;
import org.optaplanner.core.impl.heuristic.move.Move; import org.optaplanner.core.impl.heuristic.move.Move;
import org.optaplanner.core.impl.heuristic.selector.move.generic.ChangeMove; import org.optaplanner.core.impl.heuristic.selector.move.generic.ChangeMove;
import org.optaplanner.core.impl.heuristic.selector.move.generic.SwapMove;
import org.optaplanner.core.impl.heuristic.selector.move.generic.chained.ChainedChangeMove; import org.optaplanner.core.impl.heuristic.selector.move.generic.chained.ChainedChangeMove;
import org.optaplanner.core.impl.heuristic.selector.move.generic.chained.ChainedSwapMove;
import org.optaplanner.core.impl.score.director.InnerScoreDirector; import org.optaplanner.core.impl.score.director.InnerScoreDirector;
import org.optaplanner.core.impl.score.director.ScoreDirector; import org.optaplanner.core.impl.score.director.ScoreDirector;
import org.optaplanner.core.impl.score.director.ScoreDirectorFactory; import org.optaplanner.core.impl.score.director.ScoreDirectorFactory;
Expand Down Expand Up @@ -302,8 +307,9 @@ public void terminateSolvingEarly() {
} }


public ChangeMove createChangeMove(Object entity, String variableName, Object toPlanningValue) { public ChangeMove createChangeMove(Object entity, String variableName, Object toPlanningValue) {
GenuineVariableDescriptor variableDescriptor = ((InnerScoreDirector) guiScoreDirector).getSolutionDescriptor() SolutionDescriptor solutionDescriptor = ((InnerScoreDirector) guiScoreDirector).getSolutionDescriptor();
.findGenuineVariableDescriptorOrFail(entity, variableName); GenuineVariableDescriptor variableDescriptor = solutionDescriptor.findGenuineVariableDescriptorOrFail(
entity, variableName);
if (variableDescriptor.isChained()) { if (variableDescriptor.isChained()) {
return new ChainedChangeMove(entity, variableDescriptor, toPlanningValue); return new ChainedChangeMove(entity, variableDescriptor, toPlanningValue);
} else { } else {
Expand All @@ -316,4 +322,20 @@ public void doChangeMove(Object entity, String variableName, Object toPlanningVa
doMove(move); doMove(move);
} }


public SwapMove createSwapMove(Object leftEntity, Object rightEntity) {
SolutionDescriptor solutionDescriptor = ((InnerScoreDirector) guiScoreDirector).getSolutionDescriptor();
EntityDescriptor entityDescriptor = solutionDescriptor.findEntityDescriptor(leftEntity.getClass());
Collection<GenuineVariableDescriptor> variableDescriptors = entityDescriptor.getGenuineVariableDescriptors();
if (entityDescriptor.hasAnyChainedGenuineVariables()) {
return new ChainedSwapMove(variableDescriptors, leftEntity, rightEntity);
} else {
return new SwapMove(variableDescriptors, leftEntity, rightEntity);
}
}

public void doSwapMove(Object leftEntity, Object rightEntity) {
SwapMove move = createSwapMove(leftEntity, rightEntity);
doMove(move);
}

} }
@@ -0,0 +1,26 @@
/*
* Copyright 2015 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.optaplanner.examples.common.swingui.components;

/**
* @see LabeledComboBoxRenderer
*/
public interface Labeled {

String getLabel();

}
@@ -0,0 +1,45 @@
/*
* Copyright 2015 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.optaplanner.examples.common.swingui.components;

import java.awt.Component;
import javax.swing.Icon;
import javax.swing.JList;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

/**
* Display the user-friendly {@link Labeled#getLabel()} instead of the developer-friendly {@link Object#toString()}.
*/
public class LabeledComboBoxRenderer extends BasicComboBoxRenderer {

@Override
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
setFont(list.getFont());

setText((value == null) ? "" : ((Labeled) value).getLabel());
return this;
}

}
Expand Up @@ -18,9 +18,10 @@


import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import org.optaplanner.examples.common.domain.AbstractPersistable; import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.common.swingui.components.Labeled;


@XStreamAlias("Period") @XStreamAlias("Period")
public class Period extends AbstractPersistable { public class Period extends AbstractPersistable implements Labeled {


private Day day; private Day day;
private Timeslot timeslot; private Timeslot timeslot;
Expand Down
Expand Up @@ -18,9 +18,10 @@


import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import org.optaplanner.examples.common.domain.AbstractPersistable; import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.common.swingui.components.Labeled;


@XStreamAlias("Room") @XStreamAlias("Room")
public class Room extends AbstractPersistable { public class Room extends AbstractPersistable implements Labeled {


private String code; private String code;
private int capacity; private int capacity;
Expand All @@ -47,7 +48,7 @@ public String getLabel() {


@Override @Override
public String toString() { public String toString() {
return code + " {C" + capacity + "}"; return code;
} }


} }
Expand Up @@ -38,6 +38,7 @@
import org.optaplanner.examples.common.swingui.CommonIcons; import org.optaplanner.examples.common.swingui.CommonIcons;
import org.optaplanner.examples.common.swingui.SolutionPanel; import org.optaplanner.examples.common.swingui.SolutionPanel;
import org.optaplanner.examples.common.swingui.TangoColorFactory; import org.optaplanner.examples.common.swingui.TangoColorFactory;
import org.optaplanner.examples.common.swingui.components.LabeledComboBoxRenderer;
import org.optaplanner.examples.common.swingui.timetable.TimeTablePanel; import org.optaplanner.examples.common.swingui.timetable.TimeTablePanel;
import org.optaplanner.examples.curriculumcourse.domain.CourseSchedule; import org.optaplanner.examples.curriculumcourse.domain.CourseSchedule;
import org.optaplanner.examples.curriculumcourse.domain.Curriculum; import org.optaplanner.examples.curriculumcourse.domain.Curriculum;
Expand Down Expand Up @@ -243,12 +244,18 @@ public void actionPerformed(ActionEvent e) {
JPanel listFieldsPanel = new JPanel(new GridLayout(3, 2)); JPanel listFieldsPanel = new JPanel(new GridLayout(3, 2));
listFieldsPanel.add(new JLabel("Period:")); listFieldsPanel.add(new JLabel("Period:"));
List<Period> periodList = getCourseSchedule().getPeriodList(); List<Period> periodList = getCourseSchedule().getPeriodList();
JComboBox periodListField = new JComboBox(periodList.toArray()); // Add 1 to array size to add null, which makes the entity unassigned
JComboBox<Period> periodListField = new JComboBox<Period>(
periodList.toArray(new Period[periodList.size() + 1]));
periodListField.setRenderer(new LabeledComboBoxRenderer());
periodListField.setSelectedItem(lecture.getPeriod()); periodListField.setSelectedItem(lecture.getPeriod());
listFieldsPanel.add(periodListField); listFieldsPanel.add(periodListField);
listFieldsPanel.add(new JLabel("Room:")); listFieldsPanel.add(new JLabel("Room:"));
List<Room> roomList = getCourseSchedule().getRoomList(); List<Room> roomList = getCourseSchedule().getRoomList();
JComboBox roomListField = new JComboBox(roomList.toArray()); // Add 1 to array size to add null, which makes the entity unassigned
JComboBox<Room> roomListField = new JComboBox<Room>(
roomList.toArray(new Room[roomList.size() + 1]));
roomListField.setRenderer(new LabeledComboBoxRenderer());
roomListField.setSelectedItem(lecture.getRoom()); roomListField.setSelectedItem(lecture.getRoom());
listFieldsPanel.add(roomListField); listFieldsPanel.add(roomListField);
listFieldsPanel.add(new JLabel("Locked:")); listFieldsPanel.add(new JLabel("Locked:"));
Expand Down
Expand Up @@ -71,6 +71,10 @@ public void setHobbyPracticianList(List<HobbyPractician> hobbyPracticianList) {
this.hobbyPracticianList = hobbyPracticianList; this.hobbyPracticianList = hobbyPracticianList;
} }


public String getLabel() {
return name;
}

@Override @Override
public String toString() { public String toString() {
return code + "(" + job + "," + gender.getCode() + ")"; return code + "(" + job + "," + gender.getCode() + ")";
Expand Down
Expand Up @@ -60,13 +60,18 @@ public void setRightSeat(Seat rightSeat) {
this.rightSeat = rightSeat; this.rightSeat = rightSeat;
} }


public Gender getRequiredGender() {
return (seatIndexInTable % 2 == 0) ? Gender.MALE : Gender.FEMALE;
}

public String getLabel() {
return "Table " + table.getTableIndex() + " seat " + seatIndexInTable;
}

@Override @Override
public String toString() { public String toString() {
return table + "." + seatIndexInTable; return table + "." + seatIndexInTable;
} }


public Gender getRequiredGender() {
return (seatIndexInTable % 2 == 0) ? Gender.MALE : Gender.FEMALE;
}


} }
Expand Up @@ -20,10 +20,11 @@
import org.optaplanner.core.api.domain.entity.PlanningEntity; import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.variable.PlanningVariable; import org.optaplanner.core.api.domain.variable.PlanningVariable;
import org.optaplanner.examples.common.domain.AbstractPersistable; import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.common.swingui.components.Labeled;


@PlanningEntity @PlanningEntity
@XStreamAlias("SeatDesignation") @XStreamAlias("SeatDesignation")
public class SeatDesignation extends AbstractPersistable { public class SeatDesignation extends AbstractPersistable implements Labeled {


private Guest guest; private Guest guest;
private Seat seat; private Seat seat;
Expand Down Expand Up @@ -91,6 +92,10 @@ public boolean isNeighborOf(SeatDesignation otherSeatDesignation) {
return seat.getLeftSeat() == otherSeatDesignation.seat || seat.getRightSeat() == otherSeatDesignation.seat; return seat.getLeftSeat() == otherSeatDesignation.seat || seat.getRightSeat() == otherSeatDesignation.seat;
} }


public String getLabel() {
return guest.getLabel();
}

@Override @Override
public String toString() { public String toString() {
return guest + " @ " + seat; return guest + " @ " + seat;
Expand Down
Expand Up @@ -39,6 +39,7 @@
import org.optaplanner.core.api.domain.solution.Solution; import org.optaplanner.core.api.domain.solution.Solution;
import org.optaplanner.examples.common.swingui.SolutionPanel; import org.optaplanner.examples.common.swingui.SolutionPanel;
import org.optaplanner.examples.common.swingui.TangoColorFactory; import org.optaplanner.examples.common.swingui.TangoColorFactory;
import org.optaplanner.examples.common.swingui.components.LabeledComboBoxRenderer;
import org.optaplanner.examples.dinnerparty.domain.DinnerParty; import org.optaplanner.examples.dinnerparty.domain.DinnerParty;
import org.optaplanner.examples.dinnerparty.domain.Gender; import org.optaplanner.examples.dinnerparty.domain.Gender;
import org.optaplanner.examples.dinnerparty.domain.Guest; import org.optaplanner.examples.dinnerparty.domain.Guest;
Expand Down Expand Up @@ -226,16 +227,19 @@ public SeatDesignationAction(SeatDesignation seatDesignation) {


public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
List<SeatDesignation> seatDesignationList = getDinnerParty().getSeatDesignationList(); List<SeatDesignation> seatDesignationList = getDinnerParty().getSeatDesignationList();
JComboBox seatDesignationListField = new JComboBox(seatDesignationList.toArray()); // Add 1 to array size to add null, which makes the entity unassigned
JComboBox<SeatDesignation> seatDesignationListField = new JComboBox<SeatDesignation>(
seatDesignationList.toArray(new SeatDesignation[seatDesignationList.size() + 1]));
seatDesignationListField.setRenderer(new LabeledComboBoxRenderer());
seatDesignationListField.setSelectedItem(seatDesignation); seatDesignationListField.setSelectedItem(seatDesignation);
int result = JOptionPane.showConfirmDialog(DinnerPartyPanel.this.getRootPane(), seatDesignationListField, int result = JOptionPane.showConfirmDialog(DinnerPartyPanel.this.getRootPane(), seatDesignationListField,
"Select seat designation to switch with", JOptionPane.OK_CANCEL_OPTION); "Select seat designation to switch with", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) { if (result == JOptionPane.OK_OPTION) {
SeatDesignation switchSeatDesignation = (SeatDesignation) seatDesignationListField.getSelectedItem(); SeatDesignation switchSeatDesignation = (SeatDesignation) seatDesignationListField.getSelectedItem();
// TODO FIXME if (seatDesignation != switchSeatDesignation) {
throw new UnsupportedOperationException(); solutionBusiness.doSwapMove(seatDesignation, switchSeatDesignation);
// solutionBusiness.doMove(new SwapMove(seatDesignation, switchSeatDesignation)); }
// solverAndPersistenceFrame.resetScreen(); solverAndPersistenceFrame.resetScreen();
} }
} }


Expand Down
Expand Up @@ -18,9 +18,10 @@


import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import org.optaplanner.examples.common.domain.AbstractPersistable; import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.common.swingui.components.Labeled;


@XStreamAlias("Period") @XStreamAlias("Period")
public class Period extends AbstractPersistable { public class Period extends AbstractPersistable implements Labeled {


private String startDateTimeString; private String startDateTimeString;
private int periodIndex; private int periodIndex;
Expand Down
Expand Up @@ -18,9 +18,10 @@


import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import org.optaplanner.examples.common.domain.AbstractPersistable; import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.common.swingui.components.Labeled;


@XStreamAlias("Room") @XStreamAlias("Room")
public class Room extends AbstractPersistable { public class Room extends AbstractPersistable implements Labeled {


private int capacity; private int capacity;
private int penalty; private int penalty;
Expand Down
Expand Up @@ -41,6 +41,7 @@
import org.optaplanner.examples.common.swingui.SolutionPanel; import org.optaplanner.examples.common.swingui.SolutionPanel;
import org.optaplanner.examples.common.swingui.SolverAndPersistenceFrame; import org.optaplanner.examples.common.swingui.SolverAndPersistenceFrame;
import org.optaplanner.examples.common.swingui.TangoColorFactory; import org.optaplanner.examples.common.swingui.TangoColorFactory;
import org.optaplanner.examples.common.swingui.components.LabeledComboBoxRenderer;
import org.optaplanner.examples.common.swingui.timetable.TimeTablePanel; import org.optaplanner.examples.common.swingui.timetable.TimeTablePanel;
import org.optaplanner.examples.examination.domain.Exam; import org.optaplanner.examples.examination.domain.Exam;
import org.optaplanner.examples.examination.domain.Examination; import org.optaplanner.examples.examination.domain.Examination;
Expand Down Expand Up @@ -236,12 +237,18 @@ public void actionPerformed(ActionEvent e) {
JPanel listFieldsPanel = new JPanel(new GridLayout(2, 2)); JPanel listFieldsPanel = new JPanel(new GridLayout(2, 2));
listFieldsPanel.add(new JLabel("Period:")); listFieldsPanel.add(new JLabel("Period:"));
List<Period> periodList = getExamination().getPeriodList(); List<Period> periodList = getExamination().getPeriodList();
JComboBox periodListField = new JComboBox(periodList.toArray()); // Add 1 to array size to add null, which makes the entity unassigned
JComboBox<Period> periodListField = new JComboBox<Period>(
periodList.toArray(new Period[periodList.size() + 1]));
periodListField.setRenderer(new LabeledComboBoxRenderer());
periodListField.setSelectedItem(exam.getPeriod()); periodListField.setSelectedItem(exam.getPeriod());
listFieldsPanel.add(periodListField); listFieldsPanel.add(periodListField);
listFieldsPanel.add(new JLabel("Room:")); listFieldsPanel.add(new JLabel("Room:"));
List<Room> roomList = getExamination().getRoomList(); List<Room> roomList = getExamination().getRoomList();
JComboBox roomListField = new JComboBox(roomList.toArray()); // Add 1 to array size to add null, which makes the entity unassigned
JComboBox<Room> roomListField = new JComboBox<Room>(
roomList.toArray(new Room[roomList.size() + 1]));
roomListField.setRenderer(new LabeledComboBoxRenderer());
roomListField.setSelectedItem(exam.getRoom()); roomListField.setSelectedItem(exam.getRoom());
listFieldsPanel.add(roomListField); listFieldsPanel.add(roomListField);
int result = JOptionPane.showConfirmDialog(ExaminationPanel.this.getRootPane(), listFieldsPanel, int result = JOptionPane.showConfirmDialog(ExaminationPanel.this.getRootPane(), listFieldsPanel,
Expand Down
Expand Up @@ -21,9 +21,10 @@


import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import org.optaplanner.examples.common.domain.AbstractPersistable; import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.common.swingui.components.Labeled;


@XStreamAlias("MrMachine") @XStreamAlias("MrMachine")
public class MrMachine extends AbstractPersistable { public class MrMachine extends AbstractPersistable implements Labeled {


private MrNeighborhood neighborhood; private MrNeighborhood neighborhood;
private MrLocation location; private MrLocation location;
Expand Down

0 comments on commit 80bca5d

Please sign in to comment.