001package observer.gui;
002//[C] 2002 Sun Microsystems, Inc.---
003import java.awt.BorderLayout;
004import java.awt.Container;
005import java.awt.GridLayout;
006import java.awt.event.ActionEvent;
007import java.awt.event.ActionListener;
008import java.awt.event.WindowAdapter;
009import java.awt.event.WindowEvent;
010import java.util.List;
011import java.util.ArrayList;
012
013import javax.swing.BoxLayout;
014import javax.swing.JButton;
015import javax.swing.JComboBox;
016import javax.swing.JFrame;
017import javax.swing.JLabel;
018import javax.swing.JPanel;
019import javax.swing.JScrollPane;
020import javax.swing.JTextArea;
021import javax.swing.JTextField;
022
023public class RunObserverPattern {
024        public static void main(String[] arguments) {
025                System.out.println("Example for the Observer pattern");
026                System.out.println("This demonstration uses a central observable");
027                System.out.println(" object to send change notifications to several");
028                System.out.println(" JPanels in a GUI. Each JPanel is an Observer,");
029                System.out.println(" receiving notifcations when there has been some");
030                System.out.println(" change in the shared Task that is being edited.");
031                System.out.println();
032
033                System.out.println("Creating the ObserverGui");
034                ObserverGui application = new ObserverGui();
035                application.createGui();
036        }
037}
038
039class Task {
040        private String name = "";
041
042        private String notes = "";
043
044        private double timeRequired;
045
046        public Task() {
047        }
048
049        public Task(String newName, String newNotes, double newTimeRequired) {
050                name = newName;
051                notes = newNotes;
052                timeRequired = newTimeRequired;
053        }
054
055        public String getName() {
056                return name;
057        }
058
059        public String getNotes() {
060                return notes;
061        }
062
063        public double getTimeRequired() {
064                return timeRequired;
065        }
066
067        public void setName(String newName) {
068                name = newName;
069        }
070
071        public void setTimeRequired(double newTimeRequired) {
072                timeRequired = newTimeRequired;
073        }
074
075        public void setNotes(String newNotes) {
076                notes = newNotes;
077        }
078
079        public String toString() {
080                return name + " " + notes;
081        }
082}
083
084class TaskChangeObservable {
085        private List<TaskChangeObserver> observers = new ArrayList<TaskChangeObserver>();
086
087        public void addTaskChangeObserver(TaskChangeObserver observer) {
088                if (!observers.contains(observer)) {
089                        observers.add(observer);
090                }
091        }
092
093        public void removeTaskChangeObserver(TaskChangeObserver observer) {
094                observers.remove(observer);
095        }
096
097        public void selectTask(Task task) {
098                for (TaskChangeObserver o : observers) {
099                        o.taskSelected(task);
100                }
101        }
102
103        public void addTask(Task task) {
104                for (TaskChangeObserver o : observers) {
105                        o.taskSelected(task);
106                }
107        }
108
109        public void updateTask(Task task) {
110                for (TaskChangeObserver o : observers) {
111                        o.taskChanged(task);
112                }
113        }
114}
115
116interface TaskChangeObserver {
117        public void taskAdded(Task task);
118        public void taskChanged(Task task);
119        public void taskSelected(Task task);
120}
121
122@SuppressWarnings("serial")
123class TaskEditorPanel
124extends JPanel implements ActionListener, TaskChangeObserver
125{
126        private JPanel controlPanel, editPanel;
127
128        private JButton add, update, exit;
129
130        private JTextField taskName, taskNotes, taskTime;
131
132        private TaskChangeObservable notifier;
133
134        private Task editTask;
135
136        public TaskEditorPanel(TaskChangeObservable newNotifier) {
137                notifier = newNotifier;
138                createGui();
139        }
140
141        public void createGui() {
142                setLayout(new BorderLayout());
143                editPanel = new JPanel();
144                editPanel.setLayout(new GridLayout(3, 2));
145                taskName = new JTextField(20);
146                taskNotes = new JTextField(20);
147                taskTime = new JTextField(20);
148                editPanel.add(new JLabel("Task Name"));
149                editPanel.add(taskName);
150                editPanel.add(new JLabel("Task Notes"));
151                editPanel.add(taskNotes);
152                editPanel.add(new JLabel("Time Required"));
153                editPanel.add(taskTime);
154
155                controlPanel = new JPanel();
156                add = new JButton("Add Task");
157                update = new JButton("Update Task");
158                exit = new JButton("Exit");
159                controlPanel.add(add);
160                controlPanel.add(update);
161                controlPanel.add(exit);
162                add.addActionListener(this);
163                update.addActionListener(this);
164                exit.addActionListener(this);
165                add(controlPanel, BorderLayout.SOUTH);
166                add(editPanel, BorderLayout.CENTER);
167        }
168
169        public void setTaskChangeObservable(TaskChangeObservable newNotifier) {
170                notifier = newNotifier;
171        }
172
173        public void actionPerformed(ActionEvent event) {
174                Object source = event.getSource();
175                if (source == add) {
176                        double timeRequired = 0.0;
177                        try {
178                                timeRequired = Double.parseDouble(taskTime.getText());
179                        } catch (NumberFormatException exc) {
180                        }
181                        notifier.addTask(new Task(taskName.getText(), taskNotes.getText(),
182                                        timeRequired));
183                } else if (source == update) {
184                        editTask.setName(taskName.getText());
185                        editTask.setNotes(taskNotes.getText());
186                        try {
187                                editTask
188                                .setTimeRequired(Double.parseDouble(taskTime.getText()));
189                        } catch (NumberFormatException exc) {
190                        }
191                        notifier.updateTask(editTask);
192                } else if (source == exit) {
193                        System.exit(0);
194                }
195
196        }
197
198        public void taskAdded(Task task) {
199        }
200
201        public void taskChanged(Task task) {
202        }
203
204        public void taskSelected(Task task) {
205                editTask = task;
206                taskName.setText(task.getName());
207                taskNotes.setText(task.getNotes());
208                taskTime.setText("" + task.getTimeRequired());
209        }
210}
211
212@SuppressWarnings("serial")
213class TaskHistoryPanel extends JPanel implements TaskChangeObserver {
214        private JTextArea displayRegion;
215
216        public TaskHistoryPanel() {
217                createGui();
218        }
219
220        public void createGui() {
221                setLayout(new BorderLayout());
222                displayRegion = new JTextArea(10, 40);
223                displayRegion.setEditable(false);
224                add(new JScrollPane(displayRegion));
225        }
226
227        public void taskAdded(Task task) {
228                displayRegion.append("Created task " + task + "\n");
229        }
230
231        public void taskChanged(Task task) {
232                displayRegion.append("Updated task " + task + "\n");
233        }
234
235        public void taskSelected(Task task) {
236                displayRegion.append("Selected task " + task + "\n");
237        }
238}
239
240@SuppressWarnings("all")
241class TaskSelectorPanel
242extends JPanel implements ActionListener, TaskChangeObserver
243{
244        private JComboBox selector = new JComboBox();
245
246        private TaskChangeObservable notifier;
247
248        public TaskSelectorPanel(TaskChangeObservable newNotifier) {
249                notifier = newNotifier;
250                createGui();
251        }
252
253        public void createGui() {
254                selector = new JComboBox();
255                selector.addActionListener(this);
256                add(selector);
257        }
258
259        public void actionPerformed(ActionEvent evt) {
260                notifier.selectTask((Task) selector.getSelectedItem());
261        }
262
263        public void setTaskChangeObservable(TaskChangeObservable newNotifier) {
264                notifier = newNotifier;
265        }
266
267        public void taskAdded(Task task) {
268                selector.addItem(task);
269        }
270
271        public void taskChanged(Task task) {
272        }
273
274        public void taskSelected(Task task) {
275        }
276}
277
278class ObserverGui {
279        public void createGui() {
280                JFrame mainFrame = new JFrame("Observer Pattern Example");
281                Container content = mainFrame.getContentPane();
282                content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
283                TaskChangeObservable observable = new TaskChangeObservable();
284                TaskSelectorPanel select = new TaskSelectorPanel(observable);
285                TaskHistoryPanel history = new TaskHistoryPanel();
286                TaskEditorPanel edit = new TaskEditorPanel(observable);
287                observable.addTaskChangeObserver(select);
288                observable.addTaskChangeObserver(history);
289                observable.addTaskChangeObserver(edit);
290                observable.addTask(new Task());
291                content.add(select);
292                content.add(history);
293                content.add(edit);
294                mainFrame.addWindowListener(new WindowCloseManager());
295                mainFrame.pack();
296                mainFrame.setVisible(true);
297        }
298
299        private static class WindowCloseManager extends WindowAdapter {
300                public void windowClosing(WindowEvent evt) {
301                        System.exit(0);
302                }
303        }
304}