Subversion Repositories public

Rev

Rev 89 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 89 Rev 91
1
/*
1
/*
2
 * TaskTableModel.java - implementation of tracked tasks table model
2
 * TaskTableModel.java - implementation of tracked tasks table model
3
 *
3
 *
4
 * Copyright (c) 2006, 2007, 2008 Lukas Jelinek, http://www.aiken.cz
4
 * Copyright (c) 2006, 2007, 2008 Lukas Jelinek, http://www.aiken.cz
5
 *
5
 *
6
 * ==========================================================================
6
 * ==========================================================================
7
 *
7
 *
8
 * This program is free software; you can redistribute it and/or modify
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License Version 2 as
9
 * it under the terms of the GNU General Public License Version 2 as
10
 * published by the Free Software Foundation.
10
 * published by the Free Software Foundation.
11
 *
11
 *
12
 * This program is distributed in the hope that it will be useful,
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
15
 * GNU General Public License for more details.
16
 *
16
 *
17
 * You should have received a copy of the GNU General Public License
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 *
20
 *
21
 * ==========================================================================
21
 * ==========================================================================
22
 */
22
 */
23
23
24
package cz.aiken.util.lwtt;
24
package cz.aiken.util.lwtt;
25
25
26
import javax.swing.*;
26
import javax.swing.*;
27
import javax.swing.table.*;
27
import javax.swing.table.*;
28
import java.util.*;
28
import java.util.*;
29
import java.io.*;
29
import java.io.*;
30
import java.awt.event.*;
30
import java.awt.event.*;
31
import java.math.*;
31
import java.math.*;
32
import java.text.*;
32
import java.text.*;
33
33
34
/**
34
/**
35
 * This class represents the task table model.
35
 * This class represents the task table model.
36
 * @author luk
36
 * @author luk
37
 */
37
 */
38
public class TaskTableModel extends AbstractTableModel implements ActionListener {
38
public class TaskTableModel extends AbstractTableModel implements ActionListener {
39
   
39
   
40
    private ArrayList<Task> tasks = new ArrayList<Task>();
40
    private ArrayList<Task> tasks = new ArrayList<Task>();
41
    private javax.swing.Timer timer = new javax.swing.Timer(300000, this);
41
    private javax.swing.Timer timer = new javax.swing.Timer(300000, this);
42
   
42
   
43
    private MessageFormat timeFormat = new MessageFormat("{0,number}:{1,number,00}");
43
    private MessageFormat timeFormat = new MessageFormat("{0,number}:{1,number,00}");
44
   
44
   
45
    private TaskFrame taskFrame = null;
45
    private TaskFrame taskFrame = null;
46
   
46
   
47
    /**
47
    /**
48
     * Creates a new instance of TaskTableModel
48
     * Creates a new instance of TaskTableModel
49
     * @param tf task frame instance
49
     * @param tf task frame instance
50
     */
50
     */
51
    public TaskTableModel(TaskFrame tf) {
51
    public TaskTableModel(TaskFrame tf) {
52
        taskFrame = tf;
52
        taskFrame = tf;
53
        loadFromFile();
53
        loadFromFile();
54
        timer.start();
54
        timer.start();
55
    }
55
    }
56
56
57
    /**
57
    /**
58
     * Returns the value at the given coordinates.
58
     * Returns the value at the given coordinates.
59
     * @param rowIndex row index
59
     * @param rowIndex row index
60
     * @param columnIndex column index
60
     * @param columnIndex column index
61
     * @return appropriate cell value; if the arguments are invalid
61
     * @return appropriate cell value; if the arguments are invalid
62
     * it returns <CODE>null</CODE>
62
     * it returns <CODE>null</CODE>
63
     */
63
     */
64
    public Object getValueAt(int rowIndex, int columnIndex) {
64
    public Object getValueAt(int rowIndex, int columnIndex) {
65
        switch (columnIndex) {
65
        switch (columnIndex) {
66
            case 0:
66
            case 0:
67
                return tasks.get(rowIndex).getName();
67
                return tasks.get(rowIndex).getName();
68
            case 1:
68
            case 1:
69
                long mins = tasks.get(rowIndex).getConsumption() / 60000;
69
                long mins = tasks.get(rowIndex).getConsumption() / 60000;
70
                BigDecimal hm[] = new BigDecimal((int) mins).divideAndRemainder(new BigDecimal(60));
70
                BigDecimal hm[] = new BigDecimal((int) mins).divideAndRemainder(new BigDecimal(60));
71
                return timeFormat.format(hm);
71
                return timeFormat.format(hm);
72
            default: return null;
72
            default: return null;
73
        }
73
        }
74
    }
74
    }
75
75
76
    /**
76
    /**
77
     * Returns the row count.
77
     * Returns the row count.
78
     * @return row count
78
     * @return row count
79
     */
79
     */
80
    public int getRowCount() {
80
    public int getRowCount() {
81
        return tasks.size();
81
        return tasks.size();
82
    }
82
    }
83
83
84
    /**
84
    /**
85
     * Returns the column count (currently 2).
85
     * Returns the column count (currently 2).
86
     * @return column count
86
     * @return column count
87
     */
87
     */
88
    public int getColumnCount() {
88
    public int getColumnCount() {
89
        return 2;
89
        return 2;
90
    }
90
    }
91
91
92
    /**
92
    /**
93
     * Sets a new value of the given cell. If at least one of the
93
     * Sets a new value of the given cell. If at least one of the
94
     * coordinates is invalid it does nothing.
94
     * coordinates is invalid it does nothing.
95
     * @param aValue new value
95
     * @param aValue new value
96
     * @param rowIndex row index
96
     * @param rowIndex row index
97
     * @param columnIndex column index
97
     * @param columnIndex column index
98
     */
98
     */
99
    @Override
99
    @Override
100
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
100
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
101
        switch (columnIndex) {
101
        switch (columnIndex) {
102
            case 0: tasks.get(rowIndex).setName((String) aValue);
102
            case 0: tasks.get(rowIndex).setName((String) aValue);
103
                break;
103
                break;
104
        }
104
        }
105
    }
105
    }
106
106
107
    /**
107
    /**
108
     * Returns the name of the given column.
108
     * Returns the name of the given column.
109
     * @param column column index
109
     * @param column column index
110
     * @return column name; if the index is invalid it returns an empty
110
     * @return column name; if the index is invalid it returns an empty
111
     * string
111
     * string
112
     */
112
     */
113
    @Override
113
    @Override
114
    public String getColumnName(int column) {
114
    public String getColumnName(int column) {
115
        switch (column) {
115
        switch (column) {
116
            case 0: return "Task name";
116
            case 0: return "Task name";
117
            case 1: return "Time consumption [h:min]";
117
            case 1: return "Time consumption [h:min]";
118
            default: return "";
118
            default: return "";
119
        }
119
        }
120
    }
120
    }
121
121
122
    /**
122
    /**
123
     * Returns the class of the given column.
123
     * Returns the class of the given column.
124
     * @param columnIndex column index
124
     * @param columnIndex column index
125
     * @return appropriate class object; if the column index is invalid
125
     * @return appropriate class object; if the column index is invalid
126
     * it returns <CODE>Void.class</CODE>.
126
     * it returns <CODE>Void.class</CODE>.
127
     */
127
     */
128
    @Override
128
    @Override
129
    public Class<?> getColumnClass(int columnIndex) {
129
    public Class<?> getColumnClass(int columnIndex) {
130
        switch (columnIndex) {
130
        switch (columnIndex) {
131
            case 0: return String.class;
131
            case 0: return String.class;
132
            case 1: return StringBuffer.class;
132
            case 1: return StringBuffer.class;
133
            default: return Void.class;
133
            default: return Void.class;
134
        }
134
        }
135
    }
135
    }
136
136
137
    /**
137
    /**
138
     * Checks whether the given cell is editable.
138
     * Checks whether the given cell is editable.
139
     * @param rowIndex row index
139
     * @param rowIndex row index
140
     * @param columnIndex column index
140
     * @param columnIndex column index
141
     * @return <CODE>true</CODE> for the first column (index 0),
141
     * @return <CODE>true</CODE> for the first column (index 0),
142
     * <CODE>false</CODE> otherwise
142
     * <CODE>false</CODE> otherwise
143
     */
143
     */
144
    @Override
144
    @Override
145
    public boolean isCellEditable(int rowIndex, int columnIndex) {
145
    public boolean isCellEditable(int rowIndex, int columnIndex) {
146
        return columnIndex == 0;
146
        return columnIndex == 0;
147
    }
147
    }
148
   
148
   
149
    /**
149
    /**
150
     * Creates a new task.
150
     * Creates a new task.
151
     */
151
     */
152
    public void addNewTask() {
152
    public void addNewTask() {
153
        Task t = new Task();
153
        Task t = new Task();
154
        t.setActionListener(this);
154
        t.setActionListener(this);
155
        tasks.add(t);
155
        tasks.add(t);
156
       
156
       
157
        int row = tasks.size()-1;
157
        int row = tasks.size()-1;
158
        fireTableRowsInserted(row, row);
158
        fireTableRowsInserted(row, row);
159
    }
159
    }
160
   
160
   
161
    /**
161
    /**
162
     * Removes the given tasks.
162
     * Removes the given tasks.
163
     * @param start start index
163
     * @param start start index
164
     * @param end end index (including)
164
     * @param end end index (including)
165
     */
165
     */
166
    public void removeTasks(int start, int end) {
166
    public void removeTasks(int start, int end) {
167
        for (int i=end; i>=start; i--) {
167
        for (int i=end; i>=start; i--) {
168
            Task t = tasks.remove(i);
168
            Task t = tasks.remove(i);
169
            t.stop();
169
            t.stop();
170
            t.setActionListener(null);
170
            t.setActionListener(null);
171
        }
171
        }
172
       
172
       
173
        fireTableRowsDeleted(start, end);
173
        fireTableRowsDeleted(start, end);
174
    }
174
    }
175
   
175
   
176
    /**
176
    /**
177
     * Starts the given tasks.
177
     * Starts the given tasks.
178
     * @param start start index
178
     * @param start start index
179
     * @param end end index (including)
179
     * @param end end index (including)
180
     */
180
     */
181
    public void startTasks(int start, int end) {
181
    public void startTasks(int start, int end) {
182
        for (int i=start; i<=end; i++) {
182
        for (int i=start; i<=end; i++) {
183
            Task t = tasks.get(i);
183
            Task t = tasks.get(i);
184
            t.start();
184
            t.start();
185
            fireTableCellUpdated(i, 1);
185
            fireTableCellUpdated(i, 1);
186
        }        
186
        }        
187
    }
187
    }
188
   
188
   
189
    /**
189
    /**
190
     * Stops the given tasks.
190
     * Stops the given tasks.
191
     * @param start start index
191
     * @param start start index
192
     * @param end end index (including)
192
     * @param end end index (including)
193
     */
193
     */
194
    public void stopTasks(int start, int end) {
194
    public void stopTasks(int start, int end) {
195
        for (int i=start; i<=end; i++) {
195
        for (int i=start; i<=end; i++) {
196
            Task t = tasks.get(i);
196
            Task t = tasks.get(i);
197
            t.stop();
197
            t.stop();
198
            fireTableCellUpdated(i, 1);
198
            fireTableCellUpdated(i, 1);
199
        }
199
        }
200
    }
200
    }
201
   
201
   
202
    /**
202
    /**
203
     * Stops all tasks.
203
     * Stops all tasks.
204
     */
204
     */
205
    public void stopAllTasks() {
205
    public void stopAllTasks() {
206
        Iterator<Task> it = tasks.iterator();
206
        Iterator<Task> it = tasks.iterator();
207
        while (it.hasNext()) {
207
        while (it.hasNext()) {
208
            it.next().stop();
208
            it.next().stop();
209
        }
209
        }
210
       
210
       
211
        fireTableDataChanged();
211
        fireTableDataChanged();
212
    }
212
    }
213
   
213
   
214
    /**
214
    /**
215
     * Resets the given tasks.
215
     * Resets the given tasks.
216
     * @param start index of the first resetted task
216
     * @param start index of the first resetted task
217
     * @param end index of the first NOT resetted task (the first task beyond the interval)
217
     * @param end index of the first NOT resetted task (the first task beyond the interval)
218
     */
218
     */
219
    public void resetTasks(int start, int end) {
219
    public void resetTasks(int start, int end) {
220
        for (int i=start; i<=end; i++) {
220
        for (int i=start; i<=end; i++) {
221
            Task t = tasks.get(i);
221
            Task t = tasks.get(i);
222
            t.setConsumption(0);
222
            t.setConsumption(0);
223
            fireTableCellUpdated(i, 1);
223
            fireTableCellUpdated(i, 1);
224
        }
224
        }
225
    }
225
    }
226
   
226
   
227
    /**
227
    /**
228
     * Destroys the timer controlling automatic data saving.
228
     * Destroys the timer controlling automatic data saving.
229
     */
229
     */
230
    public void cancelAutoSave() {
230
    public void cancelAutoSave() {
231
        timer.stop();
231
        timer.stop();
232
    }
232
    }
233
   
233
   
234
    /**
234
    /**
235
     * Returns the absolute path to the directory where LWTT data should be
235
     * Returns the absolute path to the directory where LWTT data should be
236
     * saved.
236
     * saved.
237
     * @return directory path
237
     * @return directory path
238
     */
238
     */
239
    public static File getDir() {
239
    public static File getDir() {
240
        Properties sys = System.getProperties();
240
        Properties sys = System.getProperties();
241
        return new File(sys.getProperty("user.home"), ".lwtt");
241
        return new File(sys.getProperty("user.home"), ".lwtt");
242
    }
242
    }
243
   
243
   
244
    /**
244
    /**
245
     * Returns the absolute path to the file where LWTT data should be
245
     * Returns the absolute path to the file where LWTT data should be
246
     * saved.
246
     * saved.
247
     * @return absolute file path
247
     * @return absolute file path
248
     */
248
     */
249
    public static File getPath() {
249
    public static File getPath() {
250
        return new File(getDir(), "data.xml");
250
        return new File(getDir(), "data.xml");
251
    }
251
    }
252
   
252
   
253
    /**
253
    /**
254
     * Checks whether the given task is running.
254
     * Checks whether the given task is running.
255
     * @param index task index
255
     * @param index task index
256
     * @return <CODE>true</CODE> for running task,
256
     * @return <CODE>true</CODE> for running task,
257
     * <CODE>false</CODE> otherwise
257
     * <CODE>false</CODE> otherwise
258
     */
258
     */
259
    public boolean isRunning(int index) {
259
    public boolean isRunning(int index) {
260
        return tasks.get(index).isRunning();
260
        return tasks.get(index).isRunning();
261
    }
261
    }
262
   
262
   
263
    /**
263
    /**
264
     * Loads application's data from the file.
264
     * Loads application's data from the file.
265
     */
265
     */
266
    public synchronized void loadFromFile() {
266
    public synchronized void loadFromFile() {
267
        tasks.clear();
267
        tasks.clear();
268
       
268
       
269
        File file = getPath();
269
        File file = getPath();
270
        if (!file.exists())
270
        if (!file.exists()) {
-
 
271
            Properties props = new Properties();
-
 
272
            taskFrame.setStartSettings(props);
271
            return;
273
            return;
-
 
274
        }
272
       
275
       
273
        try {
276
        try {
274
            FileInputStream is = new FileInputStream(file);
277
            FileInputStream is = new FileInputStream(file);
275
            Properties props = new Properties();
278
            Properties props = new Properties();
276
            props.loadFromXML(is);
279
            props.loadFromXML(is);
277
            is.close();
280
            is.close();
278
           
281
           
279
            taskFrame.setStartSettings(props);
282
            taskFrame.setStartSettings(props);
280
           
283
           
281
            Iterator<Object> it = props.keySet().iterator();
284
            Iterator<Object> it = props.keySet().iterator();
282
            while (it.hasNext()) {
285
            while (it.hasNext()) {
283
                String key = (String) it.next();
286
                String key = (String) it.next();
284
                if (key.endsWith(".name")) {
287
                if (key.endsWith(".name")) {
285
                    String ids = key.substring(0, key.length() - 5);
288
                    String ids = key.substring(0, key.length() - 5);
286
                    String name = props.getProperty(ids + ".name");
289
                    String name = props.getProperty(ids + ".name");
287
                    String cons = props.getProperty(ids + ".consumption");
290
                    String cons = props.getProperty(ids + ".consumption");
288
                    try {
291
                    try {
289
                        int id = Integer.parseInt(ids);
292
                        int id = Integer.parseInt(ids);
290
                        long cn = Long.parseLong(cons);
293
                        long cn = Long.parseLong(cons);
291
                        Task t = new Task(id, name, cn);
294
                        Task t = new Task(id, name, cn);
292
                        t.setActionListener(this);
295
                        t.setActionListener(this);
293
                        tasks.add(t);
296
                        tasks.add(t);
294
                    } catch (NumberFormatException e) {
297
                    } catch (NumberFormatException e) {
295
                        JOptionPane.showMessageDialog(null, "Cannot load data from file (bad format).", "Error", JOptionPane.ERROR_MESSAGE);
298
                        JOptionPane.showMessageDialog(null, "Cannot load data from file (bad format).", "Error", JOptionPane.ERROR_MESSAGE);
296
                    }                    
299
                    }                    
297
                }
300
                }
298
            }
301
            }
299
           
302
           
300
            Collections.sort(tasks);
303
            Collections.sort(tasks);
301
           
304
           
302
            fireTableDataChanged();
305
            fireTableDataChanged();
303
           
306
           
304
        } catch (Exception e) {
307
        } catch (Exception e) {
305
            e.printStackTrace();
308
            e.printStackTrace();
306
        }
309
        }
307
    }
310
    }
308
   
311
   
309
    /**
312
    /**
310
     * Saves application's data to the file.
313
     * Saves application's data to the file.
311
     */
314
     */
312
    public synchronized void saveToFile() {
315
    public synchronized void saveToFile() {
313
        File dir = getDir();
316
        File dir = getDir();
314
        if (!dir.exists()) {
317
        if (!dir.exists()) {
315
            if (!dir.mkdir()) {
318
            if (!dir.mkdir()) {
316
                JOptionPane.showMessageDialog(null, "Cannot save data to file (cannot create data directory).", "Error", JOptionPane.ERROR_MESSAGE);
319
                JOptionPane.showMessageDialog(null, "Cannot save data to file (cannot create data directory).", "Error", JOptionPane.ERROR_MESSAGE);
317
                return;
320
                return;
318
            }
321
            }
319
        }
322
        }
320
       
323
       
321
        Properties props = new Properties();
324
        Properties props = new Properties();
322
        props.setProperty("window.location.x", Integer.toString(taskFrame.getX()));
325
        props.setProperty("window.location.x", Integer.toString(taskFrame.getX()));
323
        props.setProperty("window.location.y", Integer.toString(taskFrame.getY()));
326
        props.setProperty("window.location.y", Integer.toString(taskFrame.getY()));
324
        props.setProperty("window.size.w", Integer.toString(taskFrame.getWidth()));
327
        props.setProperty("window.size.w", Integer.toString(taskFrame.getWidth()));
325
        props.setProperty("window.size.h", Integer.toString(taskFrame.getHeight()));
328
        props.setProperty("window.size.h", Integer.toString(taskFrame.getHeight()));
326
        for (int i=0; i<tasks.size(); i++) {
329
        for (int i=0; i<tasks.size(); i++) {
327
            Task t = tasks.get(i);
330
            Task t = tasks.get(i);
328
            String id = Integer.toString(t.getId());
331
            String id = Integer.toString(t.getId());
329
            props.setProperty(id + ".name", t.getName());
332
            props.setProperty(id + ".name", t.getName());
330
            props.setProperty(id + ".consumption", Long.toString(t.getConsumption()));
333
            props.setProperty(id + ".consumption", Long.toString(t.getConsumption()));
331
        }
334
        }
332
       
335
       
333
        try {
336
        try {
334
            FileOutputStream os = new FileOutputStream(getPath());
337
            FileOutputStream os = new FileOutputStream(getPath());
335
            props.storeToXML(os, "LWTT task data");
338
            props.storeToXML(os, "LWTT task data");
336
            os.close();
339
            os.close();
337
        } catch (IOException e) {
340
        } catch (IOException e) {
338
            JOptionPane.showMessageDialog(null, "Cannot save data to file (" + e.getLocalizedMessage() + ").", "Error", JOptionPane.ERROR_MESSAGE);
341
            JOptionPane.showMessageDialog(null, "Cannot save data to file (" + e.getLocalizedMessage() + ").", "Error", JOptionPane.ERROR_MESSAGE);
339
        }
342
        }
340
    }
343
    }
341
344
342
    /**
345
    /**
343
     * Processes an action event.
346
     * Processes an action event.
344
     *
347
     *
345
     * If the event has been generated by the auto-save timer it saves
348
     * If the event has been generated by the auto-save timer it saves
346
     * the data. Otherwise (a button action occurred) it updates
349
     * the data. Otherwise (a button action occurred) it updates
347
     * the appropriate table cell.
350
     * the appropriate table cell.
348
     * @param e action event
351
     * @param e action event
349
     */
352
     */
350
    public void actionPerformed(ActionEvent e) {
353
    public void actionPerformed(ActionEvent e) {
351
        Object src = e.getSource();
354
        Object src = e.getSource();
352
        if (src == timer) {
355
        if (src == timer) {
353
            saveToFile();
356
            saveToFile();
354
        }
357
        }
355
        else {
358
        else {
356
            int row = tasks.indexOf(src);
359
            int row = tasks.indexOf(src);
357
            fireTableCellUpdated(row, 1);
360
            fireTableCellUpdated(row, 1);
358
        }
361
        }
359
    }
362
    }
360
   
363
   
361
}
364
}
362
 
365