View Javadoc

1   /*
2    * Created on Apr 2, 2005 by davidson
3    */
4   package ca.spaz.cron;
5   
6   import java.awt.BorderLayout;
7   import java.awt.event.*;
8   import java.io.*;
9   import java.util.*;
10  
11  import javax.swing.*;
12  
13  import org.apache.log4j.*;
14  
15  import ca.spaz.cron.database.Food;
16  import ca.spaz.cron.datasource.*;
17  import ca.spaz.cron.targets.TargetEditor;
18  import ca.spaz.cron.ui.*;
19  import ca.spaz.cron.user.NewUserWizard;
20  import ca.spaz.cron.user.impl.CRONUser;
21  import ca.spaz.gui.SpazMenuBar;
22  import ca.spaz.task.*;
23  import ca.spaz.util.*;
24  
25  import com.jgoodies.looks.plastic.Plastic3DLookAndFeel;
26  
27  /***
28   * The main app. This is more of a place holder class at the moment. I'm not yet
29   * decided how to structure the overall program, as I'm not yet sure of all the
30   * screens and components and how they'll interact. Right now, it's just
31   * handling the main JFrame of the app and providing some global access to data
32   * structures.
33   * <ul>
34   * <li>@TODO: Ensure good program architecture</li>
35   * <li>@TODO: Figure out using multiple databases</li>
36   * <li>@TODO: biomarker tracker (weight, temp, etc...)</li>
37   * <li>@TODO: XML format for import/export of food data</li>
38   * <li>@TODO: Manual / help</li>
39   * <li>@TODO: Recipie editor / meal planner / food search</li>
40   * <li>@TODO: Generate reports, ranged summaries, dietary suggestions</li>
41   * </ul>
42   * 
43   * @author davidson
44   */
45  public class CRONOMETER extends JFrame implements TaskListener {
46     
47     private static final class SplashScreenTask implements Task, ProgressListener {
48        int prog = 0;
49        private TaskListener tl;
50  
51        public int getTaskProgress() {
52           return prog;
53        }
54  
55        public void abortTask() {
56        }
57  
58        public boolean canAbortTask() {
59           return false;
60        }
61  
62        public String getTaskDescription() {
63           return "Starting CRON-O-METER...";
64        }
65  
66        public void run() {
67           Datasources.initialize(this);
68        }
69  
70        /* (non-Javadoc)
71         * @see ca.spaz.util.ProgressListener#progressStart()
72         */
73        public void progressStart() {
74           prog = 0;
75        }
76  
77        /* (non-Javadoc)
78         * @see ca.spaz.util.ProgressListener#progressFinish()
79         */
80        public void progressFinish() {
81           prog = 100;
82        }
83  
84        /* (non-Javadoc)
85         * @see ca.spaz.util.ProgressListener#progress(int)
86         */
87        public void progress(int percent) {
88           prog = percent;
89        }
90     }
91  
92     /***
93      * Logger for this class
94      */
95     private static final Logger logger = Logger.getLogger(CRONOMETER.class);
96  
97     private SearchPanel sp;
98  
99     private DailySummary ds;
100 
101    private SpazMenuBar menu;
102 
103    private JPanel mainPanel;
104 
105    private static boolean isLoggerConfigured = false;
106 
107    private static CRONOMETER instance;
108 
109    public static CRONOMETER getInstance() {
110       if (null == instance) {
111          instance = new CRONOMETER();
112       }
113       return instance;
114    }
115 
116    /***
117     * Constructor
118     */
119    public CRONOMETER() {
120       
121    }
122 
123    /***
124     * 
125     */
126    private void initGUI() {
127       setJMenuBar(getMenu());
128       ImageIcon icon = new ImageIcon(ImageFactory.getInstance().loadImage("/img/icon.png"));
129       setIconImage(icon.getImage());
130       setTitle("CRON-O-METER");
131       getContentPane().add(getMainPanel());
132       setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
133       addWindowListener(new WindowAdapter() {
134          /* (non-Javadoc)
135           * @see java.awt.event.WindowAdapter#windowClosing(java.awt.event.WindowEvent)
136           */
137          public void windowClosing(WindowEvent e) {
138             doQuit();
139          }
140       });
141       pack();
142       ToolBox.centerFrame(this);
143       if (((CRONUser)CRONUser.getUser()).firstRun()) {
144          ((CRONUser)CRONUser.getUser()).setFirstRun(false);
145          doNewUserWizard();
146       }
147    }
148 
149    /***
150     * @return
151     */
152    private JMenuBar getMenu() {
153       if (null == menu) {
154          menu = new SpazMenuBar(getClass().getResourceAsStream("menubar.xml"), this);
155       }
156       return menu;
157    }
158 
159    private JPanel getMainPanel() {
160       if (null == mainPanel) {
161          mainPanel = new JPanel(new BorderLayout(4, 4));
162          mainPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
163          JSplitPane jsplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
164                getSearchPanel(), getDailySummary());
165          jsplit.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
166          mainPanel.add(jsplit, BorderLayout.CENTER);
167       }
168       return mainPanel;
169    }
170 
171    public SearchPanel getSearchPanel() {
172       if (null == sp) {
173          sp = new SearchPanel(this);
174       }
175       return sp;
176    }
177 
178    public DailySummary getDailySummary() {
179       if (null == ds) {
180          ds = new DailySummary(this);
181       }
182       return ds;
183    }
184 
185    public void doCreateNewFood() {
186       Food f = Datasources.getInstance().getMutableDataSource().createNewFood();
187       FoodEditor.editFood(f);
188    }
189 
190    public void doEditTargets() {      
191       TargetEditor.editTargets();
192    }
193 
194    public void doNewUserWizard() {      
195       NewUserWizard.createNewUser(CRONUser.getUser());
196    }
197    
198    public void doQuit() {
199       Datasources.getInstance().closeAll();
200       System.exit(0);
201    }
202    
203    public void doUSDAImport() {
204       USDAImportDialog dlg = new USDAImportDialog(this);
205       dlg.setModal(true);
206       dlg.setVisible(true);
207    }
208 
209    /***
210     * @param args
211     */
212    public static void main(String[] args) {
213       configureLogger();
214       try {
215          UIManager.setLookAndFeel(new Plastic3DLookAndFeel());
216          // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
217       } catch (Exception e) {
218          logger.error("main() - Error configuring UI delegate", e);
219       }
220       
221       final CRONOMETER cron = CRONOMETER.getInstance();
222       SplashScreen scr = new SplashScreen(new SplashScreenTask());
223       scr.addTaskListener(cron);
224       scr.start();
225    }
226 
227    /***
228     * 
229     */
230    public static void configureLogger() {
231       if (!isLoggerConfigured) {
232          Properties p = new Properties();
233          InputStream psrc = CRONOMETER.class
234                .getResourceAsStream("/logger.properties");
235          try {
236             p.load(psrc);
237          } catch (IOException e1) {
238             e1.printStackTrace();
239          }
240          PropertyConfigurator.configure(p);
241          isLoggerConfigured = true;
242       }
243    }
244 
245    /* (non-Javadoc)
246     * @see ca.spaz.task.TaskListener#taskStarted(ca.spaz.task.Task)
247     */
248    public void taskStarted(Task t) {
249       // Nothing
250    }
251 
252    /* (non-Javadoc)
253     * @see ca.spaz.task.TaskListener#taskFinished(ca.spaz.task.Task)
254     */
255    public void taskFinished(Task t) {
256       SwingUtilities.invokeLater(new Runnable() {
257 
258          public void run() {
259             checkDataSources();
260             initGUI();
261             setVisible(true);
262          }});
263    }
264 
265    /***
266     * @todo Add a wizard page for each unavailable datasource.
267     * @todo Check the user for existence, as well.
268     * @todo Invoke the New User wizard (needs a better name) before firing the UI up
269     */
270    protected void checkDataSources() {
271       Set incomplete = new HashSet();
272       List sources = Datasources.getInstance().getDatasources(true);
273       for (Iterator iter = sources.iterator(); iter.hasNext();) {
274          IFoodDatasource ds = (IFoodDatasource) iter.next();
275          if (!ds.isAvailable()) {
276             incomplete.add(ds);
277          }
278       }
279       // Here
280       for (Iterator iter = incomplete.iterator(); iter.hasNext();) {
281          IFoodDatasource ds = (IFoodDatasource) iter.next();
282          logger.warn(ds.getName() + " is not functional");
283       }
284    }
285 
286    /* (non-Javadoc)
287     * @see ca.spaz.task.TaskListener#taskAborted(ca.spaz.task.Task)
288     */
289    public void taskAborted(Task t) {
290       logger.error("Startup tasks aborted unexpectedly.  Halting...");
291       System.exit(1);
292    }
293 
294 }