Project

General

Profile

Download (21.1 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
 * Copyright (C) 2015 EDIT
4
 * European Distributed Institute of Taxonomy
5
 * http://www.e-taxonomy.eu
6
 *
7
 * The contents of this file are subject to the Mozilla Public License Version 1.1
8
 * See LICENSE.TXT at the top of this package for the full license terms.
9
 */
10
package eu.etaxonomy.cdm.vaadin.component;
11

    
12
import java.sql.SQLException;
13
import java.util.ArrayList;
14
import java.util.List;
15

    
16
import org.apache.log4j.Logger;
17

    
18
import com.vaadin.annotations.AutoGenerated;
19
import com.vaadin.data.Item;
20
import com.vaadin.data.Property;
21
import com.vaadin.data.Property.ValueChangeEvent;
22
import com.vaadin.data.Property.ValueChangeListener;
23
import com.vaadin.data.util.IndexedContainer;
24
import com.vaadin.data.util.sqlcontainer.RowId;
25
import com.vaadin.event.Action;
26
import com.vaadin.event.FieldEvents;
27
import com.vaadin.event.FieldEvents.TextChangeEvent;
28
import com.vaadin.event.LayoutEvents.LayoutClickEvent;
29
import com.vaadin.event.LayoutEvents.LayoutClickListener;
30
import com.vaadin.server.FontAwesome;
31
import com.vaadin.ui.Alignment;
32
import com.vaadin.ui.Button;
33
import com.vaadin.ui.Button.ClickEvent;
34
import com.vaadin.ui.CheckBox;
35
import com.vaadin.ui.ComboBox;
36
import com.vaadin.ui.Component;
37
import com.vaadin.ui.CustomComponent;
38
import com.vaadin.ui.GridLayout;
39
import com.vaadin.ui.HorizontalLayout;
40
import com.vaadin.ui.Label;
41
import com.vaadin.ui.Notification;
42
import com.vaadin.ui.Notification.Type;
43
import com.vaadin.ui.Table;
44
import com.vaadin.ui.Table.ColumnHeaderMode;
45
import com.vaadin.ui.TextField;
46
import com.vaadin.ui.Tree.ExpandEvent;
47
import com.vaadin.ui.Tree.ExpandListener;
48
import com.vaadin.ui.TreeTable;
49
import com.vaadin.ui.VerticalLayout;
50

    
51
import eu.etaxonomy.cdm.vaadin.container.LeafNodeTaxonContainer;
52
import eu.etaxonomy.cdm.vaadin.view.IStatusComposite;
53

    
54
/**
55
 * @author cmathew
56
 * @date 11 Mar 2015
57
 *
58
 */
59
public class StatusComposite extends CustomComponent implements IStatusComposite {
60

    
61
    /*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
62

    
63
    @AutoGenerated
64
    private GridLayout mainLayout;
65
    @AutoGenerated
66
    private Label inViewLabel;
67
    @AutoGenerated
68
    private TreeTable taxaTreeTable;
69
    @AutoGenerated
70
    private HorizontalLayout searchHorizontalLayout;
71
    @AutoGenerated
72
    private Button clearSearchButton;
73
    @AutoGenerated
74
    private TextField searchTextField;
75
    @AutoGenerated
76
    private HorizontalLayout addRemovehorizontalLayout;
77
    @AutoGenerated
78
    private Button removeButton;
79
    @AutoGenerated
80
    private ComboBox addComboBox;
81
    @AutoGenerated
82
    private VerticalLayout filterVerticalLayout;
83
    @AutoGenerated
84
    private Table filterTable;
85
    @AutoGenerated
86
    private Label filterLabel;
87
    @AutoGenerated
88
    private ComboBox classificationComboBox;
89
    private static final Logger logger = Logger.getLogger(StatusComposite.class);
90
    private StatusComponentListener listener;
91

    
92
    private static final String SELECT_FILTER = "Select filter ...";
93
    private static final String SELECT_CLASSIFICATION = "Select classification ...";
94
    private static final String ADD_TAXON_SYNONYM = "Add ...";
95
    private static final String PROPERTY_FILTER_ID = "filter";
96
    private static final String PROPERTY_SELECTED_ID = "selected";
97

    
98
    private static final String FILTER_NOT_RESOLVED = "not resolved";
99
    private static final String FILTER_UNPLACED = "unplaced";
100
    private static final String FILTER_UNFINISHED = "unfinished";
101
    private static final String FILTER_UNPUBLISHED = "unpublished";
102

    
103

    
104
    private static final String FILTER_TAXA_INPUT = "Filter Taxa ...";
105
    private static final String IN_VIEW_PREFIX = "in view : ";
106

    
107
    /**
108
     * The constructor should first build the main layout, set the
109
     * composition root and then do any custom initialization.
110
     *
111
     * The constructor will not be automatically regenerated by the
112
     * visual editor.
113
     */
114
    public StatusComposite() {
115
        buildMainLayout();
116
        setCompositionRoot(mainLayout);
117

    
118
        searchHorizontalLayout.addLayoutClickListener(new LayoutClickListener() {
119

    
120
            @Override
121
            public void layoutClick(LayoutClickEvent event) {
122
                if (event.getChildComponent() == searchTextField && searchTextField.getValue().equals(FILTER_TAXA_INPUT)) {
123
                   searchTextField.setValue("");
124
                }
125
            }
126
        });
127
        addUIListeners();
128
        initAddComboBox();
129
        initSearchTextField();
130
        initClearSearchButton();
131
        setEnabledAll(false);
132
    }
133

    
134
    public void init() {
135
        initClassificationComboBox();
136

    
137
    }
138

    
139
    public void setEnabledAll(boolean enable) {
140
        filterLabel.setEnabled(enable);
141
        filterTable.setEnabled(enable);
142
        taxaTreeTable.setEnabled(enable);
143
        addComboBox.setEnabled(enable);
144
        removeButton.setEnabled(enable);
145
        searchTextField.setEnabled(enable);
146
        clearSearchButton.setEnabled(enable);
147
    }
148

    
149
    private void initTaxaTable(int classificationId) {
150

    
151
        taxaTreeTable.setSelectable(true);
152
        taxaTreeTable.setImmediate(false);
153

    
154
        if(listener != null) {
155
            List<String> columnIds = new ArrayList<String>();
156
            columnIds.add(LeafNodeTaxonContainer.NAME_ID);
157
            taxaTreeTable.setColumnExpandRatio(LeafNodeTaxonContainer.NAME_ID, 1);
158
            columnIds.add(LeafNodeTaxonContainer.PB_ID);
159
            taxaTreeTable.setColumnWidth(LeafNodeTaxonContainer.PB_ID, 25);
160

    
161
            ValueChangeListener pbListener = new ValueChangeListener() {
162
                @Override
163
                public void valueChange(ValueChangeEvent event) {
164
                    boolean value = (Boolean) event.getProperty().getValue();
165
                    Notification.show("Changing Published Flag", "Implement me", Type.WARNING_MESSAGE);
166
                }
167

    
168
            };
169
            taxaTreeTable.addGeneratedColumn(LeafNodeTaxonContainer.PB_ID, new BooleanCheckBoxGenerator(pbListener));
170
            try {
171
                taxaTreeTable.setContainerDataSource(listener.loadTaxa(classificationId), columnIds);
172
            } catch (SQLException e) {
173
              //TODO : throw up warning dialog
174
                e.printStackTrace();
175
            }
176

    
177
            taxaTreeTable.addExpandListener(new ExpandListener() {
178

    
179
                @Override
180
                public void nodeExpand(ExpandEvent event) {
181
                    //listener.addChildren(event.getItemId());
182
                }
183

    
184
            });
185

    
186
            taxaTreeTable.setCellStyleGenerator(new Table.CellStyleGenerator() {
187

    
188
                @Override
189
                public String getStyle(Table source, Object itemId, Object propertyId) {
190
                    Property hasSynProperty = source.getItem(itemId).getItemProperty(LeafNodeTaxonContainer.HAS_SYN_ID);
191
                    if(hasSynProperty == null) {
192
                        // this is a synonym
193
                        return "synonym";
194
                    }
195
                    return null;
196
                }
197
            });
198

    
199
            // NOTE : Not really sure why we need to refresh the container here.
200
            // in the case of 'Table' this is not required
201
            listener.refresh();
202
            updateInViewLabel();
203
        }
204

    
205

    
206
        final Action changeAcceptedTaxonToSynonymAction = new Action("Change Accepted Taxon To Synonym");
207

    
208

    
209
        taxaTreeTable.addActionHandler(new Action.Handler() {
210
            @Override
211
            public Action[] getActions(final Object target, final Object sender) {
212
                    return new Action[] { changeAcceptedTaxonToSynonymAction };
213
            }
214

    
215
            @Override
216
            public void handleAction(final Action action, final Object sender,
217
                    final Object target) {
218
                Notification.show("action for Change Accepted Taxon To Synonym", "Implement me", Type.WARNING_MESSAGE);
219
            }
220
        });
221

    
222
    }
223

    
224
    private void initClassificationComboBox() {
225

    
226
        classificationComboBox.setNewItemsAllowed(false);
227
        classificationComboBox.setNullSelectionAllowed(false);
228
        classificationComboBox.setImmediate(true);
229
        classificationComboBox.setItemCaptionPropertyId("titleCache");
230
        classificationComboBox.setInputPrompt(SELECT_CLASSIFICATION);
231
        if(listener != null) {
232
            try {
233
                classificationComboBox.setContainerDataSource(listener.loadClassifications());
234
            } catch (SQLException e) {
235
                //TODO : throw up warning dialog
236
                e.printStackTrace();
237
            }
238
        }
239
    }
240

    
241

    
242

    
243
    private void initFilterTable() {
244
        filterTable.setNullSelectionAllowed(false);
245
        final IndexedContainer container = new IndexedContainer();
246
        container.addContainerProperty("filter", String.class, "");
247
        container.addContainerProperty("selected", Boolean.class, "");
248

    
249
        Item item = container.addItem(FILTER_NOT_RESOLVED);
250
        item.getItemProperty(PROPERTY_FILTER_ID).setValue(FILTER_NOT_RESOLVED);
251
        item.getItemProperty(PROPERTY_SELECTED_ID).setValue(false);
252

    
253
        item = container.addItem(FILTER_UNPLACED);
254
        item.getItemProperty(PROPERTY_FILTER_ID).setValue(FILTER_UNPLACED);
255
        item.getItemProperty(PROPERTY_SELECTED_ID).setValue(false);
256

    
257
        item = container.addItem(FILTER_UNFINISHED);
258
        item.getItemProperty(PROPERTY_FILTER_ID).setValue(FILTER_UNFINISHED);
259
        item.getItemProperty(PROPERTY_SELECTED_ID).setValue(false);
260

    
261
        item = container.addItem(FILTER_UNPUBLISHED);
262
        item.getItemProperty(PROPERTY_FILTER_ID).setValue(FILTER_UNPUBLISHED);
263
        item.getItemProperty(PROPERTY_SELECTED_ID).setValue(false);
264

    
265

    
266
        filterTable.setContainerDataSource(container);
267
        filterTable.setColumnHeaderMode(ColumnHeaderMode.HIDDEN);
268

    
269

    
270
        ValueChangeListener selectedListener = new ValueChangeListener() {
271

    
272
            private static final long serialVersionUID = -5551250788805117454L;
273

    
274
            @Override
275
            public void valueChange(ValueChangeEvent event) {
276
                boolean value = (Boolean) event.getProperty().getValue();
277
                String selectedFilter = (String)filterTable.getItem(((CheckBox)event.getProperty()).getData()).getItemProperty(PROPERTY_FILTER_ID).getValue();
278
                if(selectedFilter != null) {
279
                    if(value) {
280
                        if(selectedFilter.equals(FILTER_UNPLACED)) {
281
                            listener.setUnplacedFilter();
282
                        }
283
                        if(selectedFilter.equals(FILTER_UNPUBLISHED)) {
284
                            listener.setUnpublishedFilter();
285
                        }
286
                    } else {
287
                        if(selectedFilter.equals(FILTER_UNPLACED)) {
288
                            listener.removeUnplacedFilter();
289
                        }
290
                        if(selectedFilter.equals(FILTER_UNPUBLISHED)) {
291
                            listener.removeUnpublishedFilter();
292
                        }
293
                    }
294
                    updateInViewLabel();
295
                }
296
            }
297

    
298
        };
299
        filterTable.addGeneratedColumn(PROPERTY_SELECTED_ID, new BooleanCheckBoxGenerator(selectedListener));
300

    
301
    }
302

    
303
    private void updateInViewLabel() {
304
        inViewLabel.setValue(IN_VIEW_PREFIX + String.valueOf(listener.getCurrentNoOfTaxa()) + " / " + String.valueOf(listener.getTotalNoOfTaxa()) + " taxa");
305
    }
306

    
307
    private void initSearchTextField() {
308
        searchTextField.setInputPrompt(FILTER_TAXA_INPUT);
309
    }
310

    
311

    
312
    private void initAddComboBox() {
313
        addComboBox.setNullSelectionAllowed(false);
314
        addComboBox.setImmediate(true);
315
        addComboBox.addItem(ADD_TAXON_SYNONYM);
316
        addComboBox.addItem("New Accepted Taxon");
317
        addComboBox.addItem("New Synonym");
318
        addComboBox.setValue(ADD_TAXON_SYNONYM);
319

    
320
    }
321

    
322
    private void initClearSearchButton() {
323
        //ThemeResource resource = new ThemeResource("icons/32/cancel.png");
324
        clearSearchButton.setIcon(FontAwesome.REFRESH);
325
        clearSearchButton.setCaption("");
326
    }
327

    
328
    private void addUIListeners() {
329
        addClassificationComboBoxListener();
330
        addAddComboBoxListener();
331
        addSearchTextFieldListener();
332
        addClearSearchButtonListener();
333
    }
334

    
335
    private void addClassificationComboBoxListener() {
336

    
337
        classificationComboBox.addValueChangeListener(new Property.ValueChangeListener() {
338

    
339
            private static final long serialVersionUID = 4196786323147791606L;
340

    
341
            @Override
342
            public void valueChange(ValueChangeEvent event) {
343
                if (classificationComboBox.getValue() != null) {
344
                    Object selected = classificationComboBox.getValue();
345
                    logger.info("selected : " + selected);
346
                    int classificationId = (Integer)((RowId)selected).getId()[0];
347
                    initTaxaTable(classificationId);
348
                    initFilterTable();
349
                    setEnabledAll(true);
350
                }
351
            }
352
        });
353
    }
354

    
355

    
356
    private void addAddComboBoxListener() {
357
        addComboBox.addValueChangeListener(new Property.ValueChangeListener() {
358

    
359
            private static final long serialVersionUID = -6235423275051269517L;
360

    
361
            @Override
362
            public void valueChange(ValueChangeEvent event) {
363
                if (addComboBox.getValue() != null) {
364
                    String selected = (String)addComboBox.getValue();
365
                    if(!selected.equals(ADD_TAXON_SYNONYM)) {
366
                        Notification.show(selected, "Implement me", Type.WARNING_MESSAGE);
367
                        addComboBox.setValue(ADD_TAXON_SYNONYM);
368
                    }
369
                }
370
            }
371
        });
372
    }
373

    
374
    private void addSearchTextFieldListener() {
375
        searchTextField.addTextChangeListener(new FieldEvents.TextChangeListener() {
376

    
377
            private static final long serialVersionUID = -7376538870420619534L;
378

    
379
            @Override
380
            public void textChange(TextChangeEvent event) {
381
               listener.setNameFilter(event.getText());
382
               updateInViewLabel();
383
            }
384

    
385
        });
386

    
387
    }
388

    
389
    private void addClearSearchButtonListener() {
390
        clearSearchButton.addClickListener(new Button.ClickListener() {
391

    
392
            @Override
393
            public void buttonClick(ClickEvent event) {
394
               listener.removeNameFilter();
395
               searchTextField.setValue(FILTER_TAXA_INPUT);
396
               updateInViewLabel();
397
            }
398

    
399
        });
400
    }
401

    
402

    
403

    
404
    /* (non-Javadoc)
405
     * @see eu.etaxonomy.cdm.vaadin.view.IStatusComponent#setListener(eu.etaxonomy.cdm.vaadin.view.IStatusComponent.StatusComponentListener)
406
     */
407
    @Override
408
    public void setListener(StatusComponentListener listener) {
409
        this.listener = listener;
410
    }
411

    
412

    
413
    class BooleanCheckBoxGenerator implements Table.ColumnGenerator {
414

    
415
        private final ValueChangeListener listener;
416

    
417
        public BooleanCheckBoxGenerator(ValueChangeListener listener) {
418
            this.listener = listener;
419
        }
420

    
421
        /**
422
         * Generates the cell containing an open image when boolean is true
423
         */
424
        @Override
425
        public Component generateCell(Table source, Object itemId, Object columnId) {
426
            if(source.getItem(itemId) != null) {
427
                Property prop = source.getItem(itemId).getItemProperty(columnId);
428
                if(prop == null) {
429
                    return null;
430
                }
431
                CheckBox cb = new CheckBox(null, prop);
432
                cb.addValueChangeListener(listener);
433
                cb.setData(itemId);
434
                return cb;
435
            } else {
436
                return null;
437
            }
438

    
439
        }
440
    }
441

    
442

    
443
    @AutoGenerated
444
    private GridLayout buildMainLayout() {
445
        // common part: create layout
446
        mainLayout = new GridLayout();
447
        mainLayout.setImmediate(false);
448
        mainLayout.setWidth("340px");
449
        mainLayout.setHeight("840px");
450
        mainLayout.setMargin(true);
451
        mainLayout.setSpacing(true);
452
        mainLayout.setRows(6);
453

    
454
        // top-level component properties
455
        setWidth("340px");
456
        setHeight("840px");
457

    
458
        // classificationComboBox
459
        classificationComboBox = new ComboBox();
460
        classificationComboBox.setImmediate(false);
461
        classificationComboBox.setWidth("100.0%");
462
        classificationComboBox.setHeight("-1px");
463
        mainLayout.addComponent(classificationComboBox, 0, 0);
464

    
465
        // filterVerticalLayout
466
        filterVerticalLayout = buildFilterVerticalLayout();
467
        mainLayout.addComponent(filterVerticalLayout, 0, 1);
468
        mainLayout.setComponentAlignment(filterVerticalLayout, new Alignment(20));
469

    
470
        // addRemovehorizontalLayout
471
        addRemovehorizontalLayout = buildAddRemovehorizontalLayout();
472
        mainLayout.addComponent(addRemovehorizontalLayout, 0, 2);
473
        mainLayout.setComponentAlignment(addRemovehorizontalLayout, new Alignment(48));
474

    
475
        // searchHorizontalLayout
476
        searchHorizontalLayout = buildSearchHorizontalLayout();
477
        mainLayout.addComponent(searchHorizontalLayout, 0, 3);
478
        mainLayout.setComponentAlignment(searchHorizontalLayout, new Alignment(48));
479

    
480
        // taxaTreeTable
481
        taxaTreeTable = new TreeTable();
482
        taxaTreeTable.setImmediate(false);
483
        taxaTreeTable.setWidth("100.0%");
484
        taxaTreeTable.setHeight("534px");
485
        mainLayout.addComponent(taxaTreeTable, 0, 4);
486
        mainLayout.setComponentAlignment(taxaTreeTable, new Alignment(20));
487

    
488
        // inViewLabel
489
        inViewLabel = new Label();
490
        inViewLabel.setImmediate(false);
491
        inViewLabel.setWidth("100.0%");
492
        inViewLabel.setHeight("-1px");
493
        inViewLabel.setValue("in view : ");
494
        mainLayout.addComponent(inViewLabel, 0, 5);
495

    
496
        return mainLayout;
497
    }
498

    
499
    @AutoGenerated
500
    private VerticalLayout buildFilterVerticalLayout() {
501
        // common part: create layout
502
        filterVerticalLayout = new VerticalLayout();
503
        filterVerticalLayout.setImmediate(false);
504
        filterVerticalLayout.setWidth("100.0%");
505
        filterVerticalLayout.setHeight("-1px");
506
        filterVerticalLayout.setMargin(false);
507

    
508
        // filterLabel
509
        filterLabel = new Label();
510
        filterLabel.setImmediate(false);
511
        filterLabel.setWidth("100.0%");
512
        filterLabel.setHeight("-1px");
513
        filterLabel.setValue("Filter by :");
514
        filterVerticalLayout.addComponent(filterLabel);
515

    
516
        // filterTable
517
        filterTable = new Table();
518
        filterTable.setImmediate(false);
519
        filterTable.setWidth("100.0%");
520
        filterTable.setHeight("86px");
521
        filterVerticalLayout.addComponent(filterTable);
522
        filterVerticalLayout.setComponentAlignment(filterTable, new Alignment(48));
523

    
524
        return filterVerticalLayout;
525
    }
526

    
527
    @AutoGenerated
528
    private HorizontalLayout buildAddRemovehorizontalLayout() {
529
        // common part: create layout
530
        addRemovehorizontalLayout = new HorizontalLayout();
531
        addRemovehorizontalLayout.setImmediate(false);
532
        addRemovehorizontalLayout.setWidth("100.0%");
533
        addRemovehorizontalLayout.setHeight("-1px");
534
        addRemovehorizontalLayout.setMargin(false);
535
        addRemovehorizontalLayout.setSpacing(true);
536

    
537
        // addComboBox
538
        addComboBox = new ComboBox();
539
        addComboBox.setImmediate(false);
540
        addComboBox.setWidth("100.0%");
541
        addComboBox.setHeight("-1px");
542
        addRemovehorizontalLayout.addComponent(addComboBox);
543
        addRemovehorizontalLayout.setExpandRatio(addComboBox, 3.0f);
544

    
545
        // removeButton
546
        removeButton = new Button();
547
        removeButton.setCaption("Remove");
548
        removeButton.setImmediate(true);
549
        removeButton.setWidth("100.0%");
550
        removeButton.setHeight("-1px");
551
        addRemovehorizontalLayout.addComponent(removeButton);
552
        addRemovehorizontalLayout.setExpandRatio(removeButton, 2.0f);
553

    
554
        return addRemovehorizontalLayout;
555
    }
556

    
557
    @AutoGenerated
558
    private HorizontalLayout buildSearchHorizontalLayout() {
559
        // common part: create layout
560
        searchHorizontalLayout = new HorizontalLayout();
561
        searchHorizontalLayout.setImmediate(false);
562
        searchHorizontalLayout.setWidth("100.0%");
563
        searchHorizontalLayout.setHeight("-1px");
564
        searchHorizontalLayout.setMargin(false);
565
        searchHorizontalLayout.setSpacing(true);
566

    
567
        // searchTextField
568
        searchTextField = new TextField();
569
        searchTextField.setImmediate(false);
570
        searchTextField.setWidth("100.0%");
571
        searchTextField.setHeight("-1px");
572
        searchHorizontalLayout.addComponent(searchTextField);
573
        searchHorizontalLayout.setExpandRatio(searchTextField, 4.0f);
574
        searchHorizontalLayout.setComponentAlignment(searchTextField, new Alignment(48));
575

    
576
        // clearSearchButton
577
        clearSearchButton = new Button();
578
        clearSearchButton.setCaption("Button");
579
        clearSearchButton.setImmediate(true);
580
        clearSearchButton.setWidth("100.0%");
581
        clearSearchButton.setHeight("-1px");
582
        searchHorizontalLayout.addComponent(clearSearchButton);
583
        searchHorizontalLayout.setExpandRatio(clearSearchButton, 1.0f);
584
        searchHorizontalLayout.setComponentAlignment(clearSearchButton, new Alignment(48));
585

    
586
        return searchHorizontalLayout;
587
    }
588

    
589
}
(2-2/2)