Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.swing / org.gvsig.tools.swing.impl / src / main / java / org / gvsig / tools / swing / impl / dynobject / set / DefaultJDynObjectSetComponent.java @ 306

History | View | Annotate | Download (15.3 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.tools.swing.impl.dynobject.set;
23

    
24
import static org.gvsig.tools.dynobject.DynObjectSet.Notification.EDITION_STATUS_CHANGE;
25

    
26
import java.awt.BorderLayout;
27
import java.awt.event.ActionEvent;
28

    
29
import javax.swing.AbstractAction;
30
import javax.swing.Action;
31
import javax.swing.Box;
32
import javax.swing.Icon;
33
import javax.swing.JComponent;
34
import javax.swing.JLabel;
35
import javax.swing.JOptionPane;
36
import javax.swing.JPanel;
37
import javax.swing.JToolBar;
38

    
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41

    
42
import org.gvsig.tools.ToolsLocator;
43
import org.gvsig.tools.dynobject.DynObject;
44
import org.gvsig.tools.dynobject.DynObjectSet;
45
import org.gvsig.tools.dynobject.DynObjectSet.Notification;
46
import org.gvsig.tools.exception.BaseException;
47
import org.gvsig.tools.i18n.I18nManager;
48
import org.gvsig.tools.observer.Observable;
49
import org.gvsig.tools.observer.Observer;
50
import org.gvsig.tools.service.Manager;
51
import org.gvsig.tools.swing.api.ToolsSwingLocator;
52
import org.gvsig.tools.swing.api.dynobject.DynObjectSwingManager;
53
import org.gvsig.tools.swing.api.dynobject.JDynObjectComponent;
54
import org.gvsig.tools.swing.api.dynobject.set.JDynObjectSetComponent;
55

    
56
/**
57
 * Default {@link JDynObjectSetComponent} implementation using a
58
 * {@link DynObjectSetModel}.
59
 * 
60
 * @author gvSIG Team
61
 * @version $Id$
62
 */
63
public class DefaultJDynObjectSetComponent extends JPanel implements
64
    JDynObjectSetComponent, Observer {
65

    
66
    private static final long serialVersionUID = -741238766386344850L;
67

    
68
    private static final Logger LOG = LoggerFactory
69
        .getLogger(DefaultJDynObjectSetComponent.class);
70

    
71
    private final DynObjectSetModel model;
72
    private final DynObjectSwingManager manager;
73
    private final I18nManager i18nManager = ToolsLocator.getI18nManager();
74

    
75
    private AbstractEnableAction firstAction;
76
    private AbstractEnableAction previousAction;
77

    
78
    private JLabel pageCountLabel;
79

    
80
    private AbstractEnableAction nextAction;
81

    
82
    private AbstractEnableAction lastAction;
83

    
84
    private AbstractEnableAction saveAction;
85

    
86
    private AbstractEnableAction deleteAction;
87

    
88
    private JDynObjectComponent component;
89

    
90
    private final boolean writable;
91

    
92
    /**
93
     * Creates a new {@link DefaultJDynObjectSetComponent}.
94
     * 
95
     * @param set
96
     *            to render
97
     * @param manager
98
     *            which manages this component
99
     * @throws BaseException
100
     *             if there is an error creating the component
101
     */
102
    public DefaultJDynObjectSetComponent(DynObjectSet set,
103
        DynObjectSwingManager manager) throws BaseException {
104
        this(set, manager, false);
105
    }
106

    
107
    /**
108
     * Creates a new {@link DefaultJDynObjectSetComponent}.
109
     * 
110
     * @param set
111
     *            to render
112
     * @param manager
113
     *            which manages this component
114
     * @param isDoubleBuffered
115
     *            a boolean, true for double-buffering, which uses additional
116
     *            memory space to achieve fast, flicker-free updates
117
     * @throws BaseException
118
     *             if there is an error creating the component
119
     */
120
    public DefaultJDynObjectSetComponent(DynObjectSet set,
121
        DynObjectSwingManager manager, boolean writable) throws BaseException {
122
        super(new BorderLayout());
123
        this.writable = writable;
124
        this.model = new DynObjectSetModel(set);
125
        model.addObserver(this);
126
        set.addObserver(this);
127
        this.manager = manager;
128
        initializeGUI();
129
    }
130

    
131
    /**
132
     * Initializes the GUI.
133
     */
134
    private void initializeGUI() {
135
        addDynObjectViewer();
136
        addDynObjectPagerAndButtons();
137
    }
138

    
139
    private void addDynObjectPagerAndButtons() {
140
        JToolBar toolBar = new JToolBar();
141
        toolBar.setRollover(true);
142
        toolBar.setFloatable(false);
143

    
144
        // Add horizontal glues to center the buttons
145
        toolBar.add(Box.createHorizontalGlue());
146
        toolBar.add(getFirstAction());
147
        toolBar.add(getPreviousAction());
148
        toolBar.addSeparator();
149
        toolBar.add(getPageCount());
150
        toolBar.addSeparator();
151
        toolBar.add(getNextAction());
152
        toolBar.add(getLastAction());
153
        toolBar.add(Box.createHorizontalGlue());
154
        if (writable) {
155
            toolBar.add(getSaveAction());
156
            toolBar.add(getDeleteAction());
157
        }
158

    
159
        add(toolBar, BorderLayout.SOUTH);
160
    }
161

    
162
    @SuppressWarnings("serial")
163
    private Action getFirstAction() {
164
        if (firstAction == null) {
165
            // TODO: replace the button text with an Icon
166
            firstAction = new AbstractEnableAction("<<", null) {
167

    
168
                public void actionPerformed(ActionEvent e) {
169
                    goFirst();
170
                }
171

    
172
                public boolean isEnabled() {
173
                    return model.hasPrevious();
174
                };
175
            };
176
            firstAction.putValue(Action.SHORT_DESCRIPTION,
177
                getTranslation("Go to the first value"));
178
            firstAction.checkEnabled();
179
        }
180
        return firstAction;
181
    }
182

    
183
    @SuppressWarnings("serial")
184
    private Action getPreviousAction() {
185
        if (previousAction == null) {
186
            // TODO: replace the button text with an Icon
187
            previousAction = new AbstractEnableAction("<", null) {
188

    
189
                public void actionPerformed(ActionEvent e) {
190
                    goPrevious();
191
                }
192

    
193
                public boolean isEnabled() {
194
                    return model.hasPrevious();
195
                };
196
            };
197
            previousAction.checkEnabled();
198
            previousAction.putValue(Action.SHORT_DESCRIPTION,
199
                getTranslation("Go to the previous value"));
200
        }
201
        return previousAction;
202
    }
203

    
204
    private JLabel getPageCount() {
205
        if (pageCountLabel == null) {
206
            pageCountLabel = new JLabel();
207
            updatePageCountLabel();
208
        }
209
        return pageCountLabel;
210
    }
211

    
212
    /**
213
     * 
214
     */
215
    private void updatePageCountLabel() {
216
        StringBuffer buffer = new StringBuffer();
217
        buffer.append(model.getCurrentPosition() + 1).append('/')
218
            .append(model.getSize());
219
        pageCountLabel.setText(buffer.toString());
220
    }
221

    
222
    @SuppressWarnings("serial")
223
    private Action getNextAction() {
224
        if (nextAction == null) {
225
            // TODO: replace the button text with an Icon
226
            nextAction = new AbstractEnableAction(">", null) {
227

    
228
                public void actionPerformed(ActionEvent e) {
229
                    goNext();
230
                }
231

    
232
                public boolean isEnabled() {
233
                    return model.hasNext();
234
                };
235
            };
236
            nextAction.checkEnabled();
237
            nextAction.putValue(Action.SHORT_DESCRIPTION,
238
                getTranslation("Go to the following value"));
239
        }
240
        return nextAction;
241
    }
242

    
243
    @SuppressWarnings("serial")
244
    private Action getLastAction() {
245
        if (lastAction == null) {
246
            // TODO: replace the button text with an Icon
247
            lastAction = new AbstractEnableAction(">>", null) {
248

    
249
                public void actionPerformed(ActionEvent e) {
250
                    goLast();
251
                }
252

    
253
                public boolean isEnabled() {
254
                    return model.hasNext();
255
                };
256

    
257
            };
258
            lastAction.checkEnabled();
259
            lastAction.putValue(Action.SHORT_DESCRIPTION,
260
                getTranslation("Go to the last value"));
261
        }
262
        return lastAction;
263
    }
264

    
265
    @SuppressWarnings("serial")
266
    private Action getSaveAction() {
267
        if (saveAction == null) {
268
            // TODO: replace the button text with an Icon
269
            saveAction = new AbstractEnableAction("Save", null) {
270

    
271
                public void actionPerformed(ActionEvent e) {
272
                    updateCurrentDynObject();
273
                }
274

    
275
                public boolean isEnabled() {
276
                    return model.getDynObjectSet().isUpdateEnabled();
277
                };
278

    
279
            };
280
            saveAction.checkEnabled();
281
            saveAction.putValue(Action.SHORT_DESCRIPTION,
282
                getTranslation("Save changes"));
283
        }
284
        return saveAction;
285
    }
286

    
287
    @SuppressWarnings("serial")
288
    private Action getDeleteAction() {
289
        if (deleteAction == null) {
290
            // TODO: replace the button text with an Icon
291
            deleteAction = new AbstractEnableAction("Delete", null) {
292

    
293
                public void actionPerformed(ActionEvent e) {
294
                    deleteCurrentDynObject();
295
                }
296

    
297
                public boolean isEnabled() {
298
                    return model.getDynObjectSet().isDeleteEnabled();
299
                };
300

    
301
            };
302
            deleteAction.checkEnabled();
303
            deleteAction.putValue(Action.SHORT_DESCRIPTION,
304
                getTranslation("Delete current element"));
305
        }
306
        return deleteAction;
307
    }
308

    
309
    private void addDynObjectViewer() {
310
        try {
311
            DynObject dynObject = model.getCurrentDynObject();
312
            if (dynObject != null) {
313
                component =
314
                    ToolsSwingLocator.getDynObjectSwingManager()
315
                        .createJDynObjectComponent(dynObject, writable);
316

    
317
                add(component.asJComponent(), BorderLayout.CENTER);
318
            }
319
        } catch (BaseException e) {
320
            LOG.error(
321
                "Error creating the component to view the current DynObject in"
322
                    + " position: " + model.getCurrentPosition(), e);
323
        }
324

    
325
    }
326

    
327
    public Manager getManager() {
328
        return manager;
329
    }
330

    
331
    public JComponent asJComponent() {
332
        return this;
333
    }
334

    
335
    public DynObjectSet getDynObjectSet() {
336
        return model.getDynObjectSet();
337
    }
338

    
339
    public void update(Observable observable, Object notification) {
340
        // The current position has changed, reload UI.
341
        if (model == observable) {
342
            reload();
343
        }
344

    
345
        // If the edition status has changed, update the save & delete buttons
346
        else
347
            if (writable
348
                && model.getDynObjectSet() == observable
349
                && EDITION_STATUS_CHANGE.equals(((Notification) notification)
350
                    .getType())) {
351
                updateEditButtons();
352
                // Update UI
353
                revalidate();
354
                repaint();
355
            }
356
    }
357

    
358
    /**
359
     * Reloads everything.
360
     */
361
    private void reload() {
362
        // Reload everything.
363
        updateDynObjectPager();
364
        updateDynObjectViewer();
365
        if (writable) {
366
            updateEditButtons();
367
        }
368

    
369
        // Update UI
370
        revalidate();
371
        repaint();
372
    }
373

    
374
    /**
375
     * Updates the status of the {@link DynObject} viewer when the model changes
376
     * the current DynObject.
377
     */
378
    private void updateDynObjectViewer() {
379
        if (component != null) {
380
            remove(component.asJComponent());
381
        }
382
        addDynObjectViewer();
383
    }
384

    
385
    /**
386
     * Updates the status of the tool bar when the model changes the current
387
     * DynObject.
388
     */
389
    private void updateDynObjectPager() {
390
        firstAction.checkEnabled();
391
        previousAction.checkEnabled();
392
        nextAction.checkEnabled();
393
        lastAction.checkEnabled();
394

    
395
        StringBuffer buffer = new StringBuffer();
396
        long size = model.getSize();
397
        if (size <= 0) {
398
            buffer.append("0/0");
399
        } else {
400
            buffer.append(model.getCurrentPosition() + 1).append('/')
401
                .append(model.getSize());
402
        }
403
        pageCountLabel.setText(buffer.toString());
404
    }
405

    
406
    /**
407
         * 
408
         */
409
    private void updateEditButtons() {
410
        LOG.debug("Updating save & update buttons active status");
411
        if (saveAction != null) {
412
            saveAction.checkEnabled();
413
        }
414
        if (deleteAction != null) {
415
            deleteAction.checkEnabled();
416
        }
417
    }
418

    
419
    private void updateCurrentDynObject() {
420
        try {
421
            component.saveStatus();
422
            model.getDynObjectSet().update(component.getDynObject());
423
        } catch (BaseException ex) {
424
            LOG.error("Error updating the current DynObject in " + "position: "
425
                + model.getCurrentPosition(), ex);
426
        }
427
    }
428

    
429
    private void deleteCurrentDynObject() {
430
        if (JOptionPane.YES_OPTION == JOptionPane
431
            .showConfirmDialog(
432
                this,
433
                getTranslation("Are you sure you want to delete the current element?"),
434
                getTranslation("Delete confirmation"),
435
                JOptionPane.YES_NO_OPTION)) {
436

    
437
            try {
438
                model.getDynObjectSet().delete(component.getDynObject());
439
                reload();
440
            } catch (BaseException ex) {
441
                LOG.error("Error deleting the current DynObject in "
442
                    + "position: " + model.getCurrentPosition(), ex);
443
            }
444
        }
445
    }
446

    
447
    /**
448
     * Utility Action extension which adds a new checkEnabled() method to set
449
     * enabled or not depending on the isEnabled() method implementation. That
450
     * will only work as expected if the isEnabled() method implementation is
451
     * changed.
452
     * 
453
     * @author gvSIG Team
454
     * @version $Id$
455
     */
456
    @SuppressWarnings("serial")
457
    private static abstract class AbstractEnableAction extends AbstractAction {
458

    
459
        /**
460
         * @see AbstractAction#AbstractAction(String, Icon).
461
         */
462
        public AbstractEnableAction(String name, Icon icon) {
463
            super(name, icon);
464
        }
465

    
466
        /**
467
         * Checks if the action must be enabled
468
         */
469
        public void checkEnabled() {
470
            setEnabled(isEnabled());
471
        }
472

    
473
    }
474

    
475
    public void dispose() {
476
        model.deleteObserver(this);
477
        model.getDynObjectSet().deleteObserver(this);
478
    }
479

    
480
    private String getTranslation(String msg) {
481
        // return i18nManager.getTranslation("Tools.Swing.".concat(msg));
482
        return i18nManager.getTranslation(msg);
483
    }
484

    
485
    private void goFirst() {
486
        if (!isCurrentModified()) {
487
            model.first();
488
        }
489
    }
490

    
491
    private void goPrevious() {
492
        if (!isCurrentModified()) {
493
            model.previous();
494
        }
495
    }
496

    
497
    private void goNext() {
498
        if (!isCurrentModified()) {
499
            model.next();
500
        }
501
    }
502

    
503
    private void goLast() {
504
        if (!isCurrentModified()) {
505
            model.last();
506
        }
507
    }
508

    
509
    private boolean isCurrentModified() {
510
        if (component != null) {
511
            // TODO: check if the component has not saved changes
512
            // component.
513
        }
514
        return false;
515
    }
516
}