001: /*
002: *
003: * JMoney - A Personal Finance Manager
004: * Copyright (c) 2004 Nigel Westbury <westbury@users.sourceforge.net>
005: *
006: *
007: * This program is free software; you can redistribute it and/or modify
008: * it under the terms of the GNU General Public License as published by
009: * the Free Software Foundation; either version 2 of the License, or
010: * (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
020: *
021: */
022:
023: package net.sf.jmoney.model2;
024:
025: import java.util.Date;
026:
027: import net.sf.jmoney.JMoneyPlugin;
028: import net.sf.jmoney.VerySimpleDateFormat;
029: import net.sf.jmoney.fields.AccountControlFactory;
030: import net.sf.jmoney.fields.AmountControlFactory;
031: import net.sf.jmoney.fields.AmountEditor;
032: import net.sf.jmoney.fields.CurrencyControlFactory;
033: import net.sf.jmoney.fields.DateControlFactory;
034: import net.sf.jmoney.fields.TextControlFactory;
035:
036: import org.eclipse.swt.SWT;
037: import org.eclipse.swt.widgets.Composite;
038: import org.eclipse.swt.widgets.Control;
039: import org.eclipse.swt.widgets.Label;
040:
041: /**
042: * This class is a listener class to the net.sf.jmoney.fields
043: * extension point. It implements an extension.
044: * <P>
045: * This extension registers the Entry properties. By registering
046: * the properties, every one can know how to display, edit, and store
047: * the properties.
048: * <P>
049: * These properties are supported in the JMoney base code, so everyone
050: * including plug-ins will know about these properties. However, to
051: * follow the Eclipse paradigm (every one should be treated equal,
052: * including oneself), these are registered through the same extension
053: * point that plug-ins must also use to register their properties.
054: *
055: * @author Nigel Westbury
056: * @author Johann Gyger
057: */
058: public class EntryInfo implements IPropertySetInfo {
059:
060: /**
061: * Date format used for the creation timestamp.
062: */
063: private VerySimpleDateFormat dateFormat = new VerySimpleDateFormat(
064: JMoneyPlugin.getDefault().getDateFormat());
065:
066: // Listen to date format changes so we keep up to date
067: // Johann, 2005-07-02: Shouldn't this be done in the control?
068: /*
069: static {
070: JMoneyPlugin.getDefault().getPreferenceStore()
071: .addPropertyChangeListener(new IPropertyChangeListener() {
072: public void propertyChange(PropertyChangeEvent event) {
073: if (event.getProperty().equals("dateFormat")) {
074: fDateFormat = new VerySimpleDateFormat(JMoneyPlugin
075: .getDefault().getDateFormat());
076: }
077: }
078: });
079: }
080: */
081:
082: private static ExtendablePropertySet<Entry> propertySet = PropertySet
083: .addBaseFinalPropertySet(Entry.class, "Accounting Entry",
084: new IExtendableObjectConstructors<Entry>() {
085:
086: public Entry construct(IObjectKey objectKey,
087: ListKey parentKey) {
088: return new Entry(objectKey, parentKey);
089: }
090:
091: public Entry construct(IObjectKey objectKey,
092: ListKey parentKey, IValues values) {
093: return new Entry(
094: objectKey,
095: parentKey,
096: values.getScalarValue(EntryInfo
097: .getCheckAccessor()),
098: values
099: .getReferencedObjectKey(EntryInfo
100: .getAccountAccessor()),
101: values.getScalarValue(EntryInfo
102: .getValutaAccessor()),
103: values.getScalarValue(EntryInfo
104: .getMemoAccessor()),
105: values.getScalarValue(EntryInfo
106: .getAmountAccessor()),
107: values.getScalarValue(EntryInfo
108: .getCreationAccessor()),
109: values
110: .getReferencedObjectKey(EntryInfo
111: .getIncomeExpenseCurrencyAccessor()),
112: values);
113: }
114: });
115:
116: private static ScalarPropertyAccessor<String> checkAccessor = null;
117: private static ReferencePropertyAccessor<Account> accountAccessor = null;
118: private static ScalarPropertyAccessor<Date> valutaAccessor = null;
119: private static ScalarPropertyAccessor<String> memoAccessor = null;
120: private static ScalarPropertyAccessor<Long> amountAccessor = null;
121: private static ScalarPropertyAccessor<Long> creationAccessor = null;
122: private static ReferencePropertyAccessor<Currency> incomeExpenseCurrencyAccessor = null;
123:
124: public PropertySet registerProperties() {
125: IPropertyControlFactory<String> textControlFactory = new TextControlFactory();
126: IPropertyControlFactory<Date> dateControlFactory = new DateControlFactory();
127: IReferenceControlFactory<Entry, Account> accountControlFactory = new AccountControlFactory<Entry, Account>() {
128: public IObjectKey getObjectKey(Entry parentObject) {
129: return parentObject.accountKey;
130: }
131: };
132:
133: IPropertyControlFactory<Long> amountControlFactory = new AmountControlFactory() {
134: @Override
135: protected Commodity getCommodity(ExtendableObject object) {
136: // If not enough information has yet been set to determine
137: // the currency of the amount in this entry, return
138: // the default currency.
139: Commodity commodity = ((Entry) object).getCommodity();
140: if (commodity == null) {
141: commodity = ((Entry) object).getSession()
142: .getDefaultCurrency();
143: }
144: return commodity;
145: }
146:
147: public IPropertyControl createPropertyControl(
148: Composite parent,
149: ScalarPropertyAccessor<Long> propertyAccessor) {
150: final AmountEditor editor = new AmountEditor(parent,
151: propertyAccessor, this );
152:
153: // The format of the amount will change if either
154: // the account property of the entry changes or if
155: // the commodity property of the account changes.
156: editor.setListener(new SessionChangeAdapter() {
157: @Override
158: public void objectChanged(
159: ExtendableObject changedObject,
160: ScalarPropertyAccessor changedProperty,
161: Object oldValue, Object newValue) {
162: Entry entry = (Entry) editor.getObject();
163: if (entry == null) {
164: return;
165: }
166: // Has the account property changed?
167: if (changedObject.equals(entry)
168: && changedProperty == EntryInfo
169: .getAccountAccessor()) {
170: editor
171: .updateCommodity(entry
172: .getCommodity());
173: }
174: // Has the currency property of the account changed?
175: if (changedObject == entry.getAccount()
176: && changedProperty == CurrencyAccountInfo
177: .getCurrencyAccessor()) {
178: editor
179: .updateCommodity(entry
180: .getCommodity());
181: }
182: // If any property in the commodity object changed then
183: // the format of the amount might also change.
184: if (changedObject == entry.getCommodity()) {
185: editor
186: .updateCommodity(entry
187: .getCommodity());
188: }
189:
190: // TODO: All the above tests are still not complete.
191: // If the account for the entry can contain multiple
192: // commodities then the commodity may depend on properties
193: // in the entry object. We really need a special listener
194: // that listens for any changes that would affect the
195: // Entry.getCommodity() value.
196: }
197: });
198:
199: return editor;
200: }
201: };
202:
203: IPropertyControlFactory<Long> creationControlFactory = new PropertyControlFactory<Long>() {
204:
205: @Override
206: public String formatValueForTable(
207: ExtendableObject extendableObject,
208: ScalarPropertyAccessor<? extends Long> propertyAccessor) {
209: Long value = extendableObject
210: .getPropertyValue(propertyAccessor);
211: Date date = new Date(value);
212: date.setTime(value);
213: return dateFormat.format(date);
214: }
215:
216: @Override
217: public String formatValueForMessage(
218: ExtendableObject extendableObject,
219: ScalarPropertyAccessor<? extends Long> propertyAccessor) {
220: Long value = extendableObject
221: .getPropertyValue(propertyAccessor);
222: Date date = new Date(value);
223: date.setTime(value);
224: return dateFormat.format(date);
225: }
226:
227: public IPropertyControl createPropertyControl(
228: Composite parent,
229: final ScalarPropertyAccessor<Long> propertyAccessor) {
230: // This property is not editable
231: final Label control = new Label(parent, SWT.NONE);
232:
233: return new IPropertyControl() {
234: public Control getControl() {
235: return control;
236: }
237:
238: public void load(ExtendableObject object) {
239: control.setText(formatValueForTable(object,
240: propertyAccessor));
241: }
242:
243: public void save() {
244: // Not editable so nothing to do
245: }
246: };
247: }
248:
249: public Long getDefaultValue() {
250: return 0L;
251: }
252:
253: public boolean isEditable() {
254: return false;
255: }
256: };
257:
258: IReferenceControlFactory<Entry, Currency> currencyControlFactory = new CurrencyControlFactory<Entry>() {
259: public IObjectKey getObjectKey(Entry parentObject) {
260: return parentObject.incomeExpenseCurrencyKey;
261: }
262: };
263:
264: IPropertyDependency<Entry> onlyIfIncomeExpenseAccount = new IPropertyDependency<Entry>() {
265: public boolean isApplicable(Entry entry) {
266: return entry.getAccount() instanceof IncomeExpenseAccount;
267: }
268: };
269:
270: IPropertyDependency<Entry> onlyIfCurrencyAccount = new IPropertyDependency<Entry>() {
271: public boolean isApplicable(Entry entry) {
272: return entry.getAccount() instanceof CurrencyAccount;
273: }
274: };
275:
276: IPropertyDependency<Entry> onlyIfBankAccount = new IPropertyDependency<Entry>() {
277: public boolean isApplicable(Entry entry) {
278: return entry.getAccount() instanceof BankAccount;
279: }
280: };
281:
282: checkAccessor = propertySet.addProperty("check", JMoneyPlugin
283: .getResourceString("Entry.check"), String.class, 2, 50,
284: textControlFactory, onlyIfBankAccount);
285: accountAccessor = propertySet.addProperty("account",
286: JMoneyPlugin.getResourceString("Entry.category"),
287: Account.class, 2, 70, accountControlFactory, null);
288: valutaAccessor = propertySet.addProperty("valuta", JMoneyPlugin
289: .getResourceString("Entry.valuta"), Date.class, 0, 74,
290: dateControlFactory, onlyIfCurrencyAccount);
291: memoAccessor = propertySet.addProperty("memo", JMoneyPlugin
292: .getResourceString("Entry.memo"), String.class, 5, 100,
293: textControlFactory, null);
294: amountAccessor = propertySet.addProperty("amount", JMoneyPlugin
295: .getResourceString("Entry.amount"), Long.class, 2, 70,
296: amountControlFactory, null);
297: creationAccessor = propertySet.addProperty("creation",
298: JMoneyPlugin.getResourceString("Entry.creation"),
299: Long.class, 0, 70, creationControlFactory, null);
300: incomeExpenseCurrencyAccessor = propertySet.addProperty(
301: "incomeExpenseCurrency", JMoneyPlugin
302: .getResourceString("Entry.currency"),
303: Currency.class, 2, 70, currencyControlFactory,
304: onlyIfIncomeExpenseAccount);
305:
306: return propertySet;
307: }
308:
309: /**
310: * @return
311: */
312: public static ExtendablePropertySet<Entry> getPropertySet() {
313: return propertySet;
314: }
315:
316: /**
317: * @return
318: */
319: public static ScalarPropertyAccessor<String> getCheckAccessor() {
320: return checkAccessor;
321: }
322:
323: /**
324: * @return
325: */
326: public static ReferencePropertyAccessor<Account> getAccountAccessor() {
327: return accountAccessor;
328: }
329:
330: /**
331: * @return
332: */
333: public static ScalarPropertyAccessor<Date> getValutaAccessor() {
334: return valutaAccessor;
335: }
336:
337: /**
338: * @return
339: */
340: public static ScalarPropertyAccessor<String> getMemoAccessor() {
341: return memoAccessor;
342: }
343:
344: /**
345: * @return
346: */
347: public static ScalarPropertyAccessor<Long> getAmountAccessor() {
348: return amountAccessor;
349: }
350:
351: /**
352: * @return
353: */
354: public static ScalarPropertyAccessor<Long> getCreationAccessor() {
355: return creationAccessor;
356: }
357:
358: /**
359: * @return
360: */
361: public static ReferencePropertyAccessor<Currency> getIncomeExpenseCurrencyAccessor() {
362: return incomeExpenseCurrencyAccessor;
363: }
364: }
|