Permalink
Browse files

Ch. 10, Mediators

  • Loading branch information...
1 parent a685385 commit 51fddefedb565eef47d4cad92d62809833b7d9e8 @bostond committed Mar 5, 2012
View
191 src/main/java/app/mediator/moveATub/MoveATub.java
@@ -0,0 +1,191 @@
+package app.mediator.moveATub;
+
+/*
+ * Copyright (c) 2001, 2005. Steven J. Metsker.
+ *
+ * Steve Metsker makes no representations or warranties about
+ * the fitness of this software for any particular purpose,
+ * including the implied warranty of merchantability.
+ *
+ * Please use this software as you wish with the sole
+ * restriction that you may not claim that you wrote it.
+ */
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.*;
+import java.util.List;
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import com.oozinoz.ui.SwingFacade;
+import com.oozinoz.ui.UI;
+
+/**
+ * This class is partially refactored, with a method for each control. The
+ * next step will be to create a mediator class, factoring the action logic
+ * out of this class.
+ */
+public class MoveATub extends JPanel implements ListSelectionListener, ActionListener {
+ private static Hashtable tubMachine;
+
+ private List boxes;
+ private JList boxList;
+
+ private JList tubList;
+ private Object selectedTub;
+
+ private JList machineList;
+ private Object selectedMachine;
+
+ private JButton assignButton;
+
+ private UI ui = UI.NORMAL;
+
+ public static void main(String[] args) {
+ JFrame frame = SwingFacade.launch(new MoveATub(), "Move a Tub");
+ frame.setSize(600, 250);
+ frame.validate();
+ }
+
+ public MoveATub() {
+ super(new GridLayout(1, 4));
+ setFont(ui.getFont());
+
+ this.add(labeledPanel("From Machine...", boxList()));
+ this.add(labeledPanel("Move Tub...", tubList()));
+ this.add(labeledPanel("To Machine...", machineList()));
+ this.add(buttonPanel(assignButton()));
+ }
+
+ private Component buttonPanel(JButton button) {
+ JPanel result = new JPanel(new GridLayout(3, 1));
+ result.add(new JLabel(" "));
+
+ JPanel innerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ innerPanel.add(button);
+ result.add(innerPanel);
+
+ result.add(new JLabel(" "));
+ return result;
+ }
+
+ private Component labeledPanel(String label, JList list) {
+ JPanel result = new JPanel(new BorderLayout());
+ result.add(new JLabel(label), BorderLayout.NORTH);
+ result.add(new JScrollPane(list), BorderLayout.CENTER);
+
+ int borderWidth = 15;
+ result.setBorder(BorderFactory.createEmptyBorder(borderWidth, borderWidth, borderWidth, borderWidth));
+
+ return result;
+ }
+
+ // This is a temporary approach that has hard-coded literals
+ private List boxes() {
+ if (boxes == null) {
+ boxes = new ArrayList();
+ boxes.add("Mixer-2201");
+ boxes.add("Mixer-2202");
+ boxes.add("Fuser-2101");
+ boxes.add("StarPress-2401");
+ boxes.add("StarPress-2402");
+ boxes.add("Assembler-2301");
+ }
+ return boxes;
+ }
+
+ private JList boxList() {
+ if (boxList == null) {
+ boxList = ui.createList(boxes().toArray());
+ boxList.addListSelectionListener(this);
+ }
+ return boxList;
+ }
+
+ private JList machineList() {
+ if (machineList == null) {
+ machineList = ui.createList(boxes().toArray());
+ machineList.addListSelectionListener(this);
+ }
+ return machineList;
+ }
+
+ private JList tubList() {
+ if (tubList == null) {
+ tubList = ui.createList(new String[] {});
+ tubList.addListSelectionListener(this);
+ }
+ return tubList;
+ }
+
+ private JButton assignButton() {
+ if (assignButton == null) {
+ assignButton = new JButton("Do it!");
+ assignButton.setEnabled(false);
+ assignButton.addActionListener(this);
+ }
+ return assignButton;
+ }
+
+ private static Hashtable tubMachine() {
+ if (tubMachine == null) {
+ tubMachine = new Hashtable();
+ tubMachine.put("T502", "Mixer-2201");
+ tubMachine.put("T503", "Mixer-2201");
+ tubMachine.put("T504", "Mixer-2201");
+ tubMachine.put("T101", "StarPress-2402");
+ tubMachine.put("T102", "StarPress-2402");
+ }
+ return tubMachine;
+ }
+
+ private static List tubNames(String machineName) {
+ ArrayList result = new ArrayList();
+
+ Enumeration iter = tubMachine().keys();
+ while (iter.hasMoreElements()) {
+ String key = iter.nextElement().toString();
+ String value = tubMachine().get(key).toString();
+ if (value.equals(machineName)) result.add(key);
+ }
+
+ return result;
+ }
+
+ private void updateTubList(String machineName) {
+ List tubs = tubNames(machineName);
+ tubList().setListData(tubs.toArray());
+ }
+
+ public void valueChanged(ListSelectionEvent e) {
+ JList sender = (JList) e.getSource();
+
+ if (!sender.isSelectionEmpty()) {
+ if (sender.equals(boxList()))
+ updateTubList(sender.getSelectedValue().toString());
+
+ if (sender.equals(machineList()))
+ selectedMachine = sender.getSelectedValue();
+
+ if (sender.equals(tubList()))
+ selectedTub = sender.getSelectedValue();
+ }
+
+ assignButton().setEnabled(
+ !tubList().isSelectionEmpty() && !machineList().isSelectionEmpty());
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (selectedMachine == null || selectedTub == null) return;
+ String tubName = selectedTub.toString();
+ String fromMachineName = (String) tubMachine().get(tubName);
+ String toMachineName = selectedMachine.toString();
+ tubMachine().put(tubName, toMachineName);
+ updateTubList(fromMachineName);
+ assignButton().setEnabled(false);
+ }
+}
View
111 src/main/java/app/mediator/moveATub2/MoveATub2.java
@@ -0,0 +1,111 @@
+package app.mediator.moveATub2;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import com.oozinoz.ui.SwingFacade;
+import com.oozinoz.ui.UI;
+
+/**
+ * Refactored from MoveATub. Challenges 10.1 and 10.2 we exercised on what would
+ * change, but didn't ask for an implementation.
+ * @author bostond
+ *
+ */
+
+public class MoveATub2 extends JPanel {
+
+ private static final long serialVersionUID = 8462238486128857207L;
+
+ private JButton assignButton;
+
+ private JList boxList;
+ private JList tubList;
+ private JList machineList;
+
+ private UI ui = UI.NORMAL;
+
+ private NameBase data = new NameBase();
+ private MoveATubMediator mediator;
+
+ public static void main(String[] args) {
+ JFrame frame = SwingFacade.launch(new MoveATub2(), "Move a Tub2");
+ frame.setSize(600, 250);
+ frame.validate();
+ }
+
+ public MoveATub2() {
+ super(new GridLayout(1, 4));
+ setFont(ui.getFont());
+
+ this.mediator = new MoveATubMediator(this, data);
+
+ this.add(labeledPanel("From Machine...", boxList()));
+ this.add(labeledPanel("Move Tub...", tubList()));
+ this.add(labeledPanel("To Machine...", machineList()));
+ this.add(buttonPanel(assignButton()));
+ }
+
+ private Component buttonPanel(JButton button) {
+ JPanel result = new JPanel(new GridLayout(3, 1));
+ result.add(new JLabel(" "));
+
+ JPanel innerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ innerPanel.add(button);
+ result.add(innerPanel);
+
+ result.add(new JLabel(" "));
+ return result;
+ }
+
+ private Component labeledPanel(String label, JList list) {
+ JPanel result = new JPanel(new BorderLayout());
+ result.add(new JLabel(label), BorderLayout.NORTH);
+ result.add(new JScrollPane(list), BorderLayout.CENTER);
+
+ int borderWidth = 15;
+ result.setBorder(BorderFactory.createEmptyBorder(borderWidth, borderWidth, borderWidth, borderWidth));
+
+ return result;
+ }
+
+ public JButton assignButton() {
+ if (assignButton == null) {
+ assignButton = new JButton("Do it!");
+ assignButton.setEnabled(false);
+ }
+ return assignButton;
+ }
+
+ public JList boxList() {
+ if (boxList == null) {
+ boxList = ui.createList(data.boxes());
+ }
+ return boxList;
+ }
+
+ public JList machineList() {
+ if (machineList == null) {
+ machineList = ui.createList(data.boxes());
+ }
+ return machineList;
+ }
+
+ public JList tubList() {
+ if (tubList == null) {
+ tubList = ui.createList(new String[] {});
+ }
+ return tubList;
+ }
+
+}
View
100 src/main/java/app/mediator/moveATub2/MoveATubMediator.java
@@ -0,0 +1,100 @@
+package app.mediator.moveATub2;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JList;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+/**
+ * Refactored from MoveATub. Challenges 10.1 and 10.2 we exercised on what would
+ * change, but didn't ask for an implementation.
+ * @author bostond
+ *
+ */
+
+public class MoveATubMediator implements ActionListener, ListSelectionListener {
+
+ private MoveATub2 gui =null;
+ private NameBase data = null;
+
+ private Object selectedMachine = null;
+ private Object selectedTub = null;
+
+
+
+ public MoveATubMediator(MoveATub2 gui, NameBase data) {
+ this.gui = gui;
+
+ gui.assignButton().addActionListener(this);
+ gui.boxList().addListSelectionListener(this);
+ gui.machineList().addListSelectionListener(this);
+ gui.tubList().addListSelectionListener(this);
+
+ this.data = data;
+ }
+
+ /**
+ * Upon notification of UI change: if the list changed is the
+ * source machine list, update the tub list with the selected machine's
+ * tubs, and set the selected machine value; if the list selected is the tub list,
+ * set the selected tub value; if the list is the destination machine
+ * list, update the selected destination machine value
+ */
+ public void valueChanged(ListSelectionEvent e) {
+ JList sender = (JList) e.getSource();
+
+ if (!sender.isSelectionEmpty()) {
+ if (sender.equals(gui.boxList())) {
+ updateTubList(sender.getSelectedValue().toString());
+ updateMachineList(sender.getSelectedValue().toString()); // don't include the source machine in the destination machine list
+ }
+
+ if (sender.equals(gui.machineList()))
+ selectedMachine = sender.getSelectedValue();
+
+ if (sender.equals(gui.tubList()))
+ selectedTub = sender.getSelectedValue();
+ }
+
+ gui.assignButton().setEnabled(
+ !gui.tubList().isSelectionEmpty() && !gui.machineList().isSelectionEmpty());
+ }
+
+ /**
+ * Make selected changes - move tub across machines, then update GUI to
+ * reflect that the tub is now gone from the selected machine, then
+ * disable move button.
+ */
+ public void actionPerformed(ActionEvent e) {
+ if (selectedMachine == null || selectedTub == null) return;
+ String tubName = selectedTub.toString();
+ String fromMachineName = data.getMachineContaining(tubName);
+ String toMachineName = selectedMachine.toString();
+ data.put(tubName, toMachineName);
+
+ updateTubList(fromMachineName);
+
+ gui.assignButton().setEnabled(false);
+ }
+
+ public void updateTubList(String machinename) {
+ gui.tubList().setListData(data.tubNames(machinename));
+ }
+
+ public void updateMachineList(String machinename) {
+ Object[] targets = data.boxes();
+ Object[] selectableBoxes = new Object[targets.length - 1];
+ int position = 0;
+ for (Object o : targets) {
+ if (! o.equals(machinename)) {
+ selectableBoxes[position++] = o;
+ }
+ }
+ gui.machineList().setListData(selectableBoxes);
+ }
+
+
+
+}
View
79 src/main/java/app/mediator/moveATub2/NameBase.java
@@ -0,0 +1,79 @@
+package app.mediator.moveATub2;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Refactored from MoveATub. Challenges 10.1 and 10.2 we exercised on what would
+ * change, but didn't ask for an implementation.
+ * @author bostond
+ *
+ */
+
+public class NameBase {
+ private List boxes;
+
+ protected Map<String, String> tubToMachine = null;
+
+ public NameBase() {
+
+ tubToMachine = new LinkedHashMap<String, String>();
+
+ tubToMachine.put("T502", "Mixer-2201");
+ tubToMachine.put("T503", "Mixer-2201");
+ tubToMachine.put("T504", "Mixer-2201");
+ tubToMachine.put("T101", "StarPress-2402");
+ tubToMachine.put("T102", "StarPress-2402");
+
+ }
+
+ public Object[] boxes()
+ {
+ if (boxes == null)
+ {
+ boxes = new ArrayList();
+ boxes.add("Mixer-2201");
+ boxes.add("Mixer-2202");
+ boxes.add("Fuser-2101");
+ boxes.add("StarPress-2401");
+ boxes.add("StarPress-2402");
+ boxes.add("Assembler-2301");
+ }
+ return boxes.toArray();
+ }
+
+ public Object[] tubNames(String machineName) {
+ Set<String> set = new LinkedHashSet<String>();
+ Iterator<Map.Entry<String, String>> i = tubToMachine.entrySet().iterator();
+
+ while (i.hasNext()) {
+ Map.Entry<String, String> e = i.next();
+ if (e.getValue().equals(machineName)) {
+ set.add(e.getKey());
+ }
+ }
+
+ return set.toArray();
+
+ }
+
+ public String getMachineContaining(String tubName) {
+ return tubToMachine.get(tubName);
+ }
+
+
+ public void put(String tubName, String toMachineName) {
+ tubToMachine.put(tubName, toMachineName);
+ }
+
+
+
+
+
+
+}
View
78 src/main/java/com/oozinoz/machine/Tub.java
@@ -0,0 +1,78 @@
+package com.oozinoz.machine;
+
+/*
+ * Copyright (c) 2001, 2005. Steven J. Metsker.
+ *
+ * Steve Metsker makes no representations or warranties about
+ * the fitness of this software for any particular purpose,
+ * including the implied warranty of merchantability.
+ *
+ * Please use this software as you wish with the sole
+ * restriction that you may not claim that you wrote it.
+ */
+
+/**
+* A tub is a standard, rubber container that contains
+* about four liters of a chemical. This class is a minimal
+* model that helps show how to manage a one-to-many
+* relation in an object model.
+*/
+public class Tub {
+ private String id;
+
+ private TubMediator mediator = null;
+
+ /**
+ * Create a tub with the given id and managed by the given
+ * mediator.
+ * @param id the identity of this machine
+ */
+ public Tub(String id, TubMediator mediator) {
+ this.id = id;
+ this.mediator = mediator;
+ }
+
+ /**
+ * Use a mediator to control getting and setting the location
+ * of this tub. This prevents a tub from ever being modeled as
+ * being on two machines at once.
+ */
+ public Machine getLocation() {
+ return mediator.getMachine(this);
+ }
+
+ public void setLocation(Machine value) {
+ mediator.set(this, value);
+ }
+
+ /**
+ * @return a textual representation of this tub.
+ */
+ public String toString() {
+ return id;
+ }
+
+ /**
+ * @return a unique id for this tub.
+ */
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ /**
+ * @return true if, according to business rules, this
+ * component and the supplied object refer to the same
+ * thing.
+ * @param o The candidate to compare to
+ */
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+
+ if (obj.getClass() != Tub.class)
+ return false;
+
+ Tub that = (Tub) obj;
+ return id.equals(that.id);
+ }
+}
View
44 src/main/java/com/oozinoz/machine/TubMediator.java
@@ -0,0 +1,44 @@
+package com.oozinoz.machine;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Challenge 10.4 (+class, + getMachine(), + setMachine())
+ * @author bostond
+ *
+ */
+
+public class TubMediator {
+
+ protected Map<Tub, Machine> tubToMachine = new HashMap<Tub, Machine>();
+
+ public Machine getMachine(Tub t) {
+ return tubToMachine.get(t);
+ }
+
+ public Set<Tub> getTubs(Machine m) {
+
+ Set<Tub> set = new HashSet<Tub>();
+ Iterator<Map.Entry<Tub, Machine>> i = tubToMachine.entrySet().iterator();
+
+ while (i.hasNext()) {
+ Map.Entry<Tub, Machine> e = i.next();
+ if (e.getValue().equals(m)) {
+ set.add(e.getKey());
+ }
+ }
+
+ return set;
+
+ }
+
+ public void set(Tub t, Machine m) {
+ tubToMachine.put(t, m);
+ }
+
+
+}
View
133 src/main/java/com/oozinoz/ui/UI.java
@@ -0,0 +1,133 @@
+package com.oozinoz.ui;
+
+/*
+ * Copyright (c) 2001, 2005. Steven J. Metsker.
+ *
+ * Steve Metsker makes no representations or warranties about
+ * the fitness of this software for any particular purpose,
+ * including the implied warranty of merchantability.
+ *
+ * Please use this software as you wish with the sole
+ * restriction that you may not claim that you wrote it.
+ */
+
+import java.awt.*;
+
+import javax.swing.*;
+import javax.swing.border.BevelBorder;
+import javax.swing.border.TitledBorder;
+
+/**
+ * User interface utilities.
+ */
+
+public class UI {
+ protected Font font = new Font("Book Antiqua", Font.PLAIN, 18);
+
+ public static final int STANDARD_PAD = 10;
+
+ public static final UI NORMAL = new UI();
+
+ /**
+ * @return a standard font that subclasses can override
+ */
+ public Font getFont() {
+ return font;
+ }
+
+ /**
+ * @return a standard padding amount that subclasses can override
+ */
+ public int getPad() {
+ return STANDARD_PAD;
+ }
+
+ /**
+ * @return a standard button
+ */
+ public JButton createButton() {
+ JButton button = new JButton();
+ button.setSize(128, 128);
+ button.setFont(getFont());
+ button.setVerticalTextPosition(SwingConstants.BOTTOM);
+ button.setHorizontalTextPosition(SwingConstants.CENTER);
+ return button;
+ }
+
+ /**
+ * @return a standard OK! (or affirmation) button
+ */
+ public JButton createButtonOk() {
+ JButton button = createButton();
+ button.setIcon(getIcon("images/rocket-large.gif"));
+ button.setText("Ok!");
+ return button;
+ }
+
+ /**
+ * @return a standard Cancel! (or negation) button
+ */
+ public JButton createButtonCancel() {
+ JButton button = createButton();
+ button.setIcon(getIcon("images/rocket-large-down.gif"));
+ button.setText("Cancel!");
+ return button;
+ }
+
+ /**
+ * @return a panel with a standard amount of padding around any controls
+ */
+ public JPanel createPaddedPanel() {
+ JPanel panel = new JPanel();
+ panel.setBorder(
+ BorderFactory.createEmptyBorder(getPad(), getPad(), getPad(), getPad()));
+ return panel;
+ }
+
+ /**
+ * @return a panel with a standard amount of padding around any particular
+ * control
+ * @param c
+ * the control
+ */
+ public JPanel createPaddedPanel(Component c) {
+ JPanel panel = createPaddedPanel();
+ panel.add(c);
+ return panel;
+ }
+
+ public static Icon getIcon(String imageName) {
+ return new ImageIcon(imageName);
+ }
+
+ public JList createList(Object[] contents) {
+ JList result = new JList(contents);
+ result.setFont(getFont());
+ result.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ return result;
+ }
+
+ /**
+ * @return a titled border with the given title.
+ */
+ public TitledBorder createTitledBorder(String title) {
+ TitledBorder border = BorderFactory.createTitledBorder(
+ BorderFactory.createBevelBorder(BevelBorder.RAISED),
+ title,
+ TitledBorder.LEFT,
+ TitledBorder.TOP);
+ border.setTitleColor(Color.black);
+ border.setTitleFont(getFont());
+ return border;
+ }
+
+ /**
+ * @return a new panel that wraps a titled border around a given panel.
+ */
+ public JPanel createTitledPanel(String title, JPanel in) {
+ JPanel out = new JPanel();
+ out.add(in);
+ out.setBorder(createTitledBorder(title));
+ return out;
+ }
+}

0 comments on commit 51fddef

Please sign in to comment.