1
2
3
4 package ca.spaz.cron.ui;
5
6 import java.awt.BorderLayout;
7 import java.awt.event.*;
8 import java.util.*;
9
10 import javax.swing.*;
11 import javax.swing.event.*;
12
13 import ca.spaz.cron.database.*;
14 import ca.spaz.gui.DoubleField;
15
16 /***
17 * A measure widget displays the UI for choosing an amount of a food item, based
18 * on various Measures stored for the particular food being weighed.
19 *
20 * @author davidson
21 */
22 public class MeasureWidget extends JPanel implements ItemListener, ActionListener, KeyListener {
23
24 private Measure curMeasure = Measure.GRAM;
25
26
27 private JComboBox measures = new JComboBox();
28
29
30 private DoubleField multiplier = new DoubleField(0,8);
31
32
33 private Vector listeners = new Vector();
34
35
36 private boolean linked = false;
37
38 /***
39 * Construct a new measure widget
40 */
41 public MeasureWidget() {
42 multiplier.setRange(0,1000000);
43 multiplier.setValue(1);
44
45 measures.addItemListener(this);
46 multiplier.addActionListener(this);
47 multiplier.addKeyListener(this);
48
49 setLayout(new BorderLayout(4,4));
50 add(multiplier, BorderLayout.WEST);
51 add(measures, BorderLayout.CENTER);
52 }
53
54 /***
55 * Set the measure to display weights for a particular food.
56 */
57 public void setFood(Food f) {
58 measures.setModel(new DefaultComboBoxModel(f.getMeasures().toArray()));
59 curMeasure = Measure.GRAM;
60 fireChangeEvent();
61 }
62
63 /***
64 * Set the weight to display
65 * @param w the type of measure
66 * @param mult the multiplier for that measure
67 */
68 public void setMeasure(Measure w, double mult) {
69 measures.setSelectedItem(w);
70 multiplier.setValue(mult);
71 fireChangeEvent();
72 }
73
74 /***
75 * Update the widget after a weight change has occurred.
76 * Called when weight menu is changed or edited
77 */
78 public void updateMeasure() {
79 Measure w = getSelectedMeasure();
80 if (w != curMeasure) {
81
82
83 if (linked) {
84 double mult = w.getAmount();
85 if (curMeasure != null) {
86 double grams = curMeasure.getGrams() * multiplier.getValue();
87 mult = grams/w.getGrams();
88 }
89 multiplier.setValue(mult);
90 }
91 focus();
92 curMeasure = w;
93 }
94 fireChangeEvent();
95 }
96
97 /***
98 * Get the multiplier for the current weight and mult settings.
99 * @return a multiple of the standard nutrient value (x per 100g)
100 */
101 public double getMultiplier() {
102 return getGrams() / 100.0;
103 }
104
105 /***
106 * Get the number of grams in this measure
107 * @return the number of grams in this state
108 */
109 public double getGrams() {
110 Measure w = getSelectedMeasure();
111 if (w != null) {
112 return multiplier.getValue() * w.getGrams();
113 }
114 return 0;
115 }
116
117 public Measure getSelectedMeasure() {
118 return (Measure)measures.getSelectedItem();
119 }
120
121 /***
122 * Focus the component, selecting the text field and giving it
123 * keyboard focus.
124 */
125 public void focus() {
126 multiplier.requestFocus();
127 multiplier.selectAll();
128 }
129
130 public void addChangeListener(ChangeListener l) {
131 listeners.add(l);
132 }
133
134 public void addRemoveListener(ChangeListener l) {
135 listeners.remove(l);
136 }
137
138 public void fireChangeEvent() {
139 ChangeEvent ce = new ChangeEvent(this);
140 Iterator iter = listeners.iterator();
141 while (iter.hasNext()) {
142 ((ChangeListener)iter.next()).stateChanged(ce);
143 }
144 }
145
146 /***
147 * Called if the weight menu state is changed
148 */
149 public void itemStateChanged(ItemEvent e) {
150 updateMeasure();
151 }
152
153 /***
154 * Called when the text field is set
155 */
156 public void actionPerformed(ActionEvent arg0) {
157 fireChangeEvent();
158 }
159
160 public void keyTyped(KeyEvent arg0) {
161 }
162
163 public void keyPressed(KeyEvent arg0) {
164 }
165
166 /***
167 * Called when the text field is edited
168 */
169 public void keyReleased(KeyEvent arg0) {
170 fireChangeEvent();
171 }
172
173 /***
174 * If linked, changing a weight will update the multiplier
175 * to keep the grams constant. Otherwise, the multiplier is left unchanged.
176 *
177 * @return true if the multiplier is linked to the weight
178 */
179 public boolean isLinked() {
180 return linked;
181 }
182
183
184 /***
185 * If linked, changing a weight will update the multiplier
186 * to keep the grams constant. Otherwise, the multiplier
187 * is left unchanged.
188 */
189 public void setLinked(boolean linked) {
190 this.linked = linked;
191 }
192 }