OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 21 | Rev 26 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 21 Rev 25
Line 24... Line 24...
24
import org.openconcerto.ui.component.text.DocumentComponent;
24
import org.openconcerto.ui.component.text.DocumentComponent;
25
import org.openconcerto.ui.component.text.TextComponent;
25
import org.openconcerto.ui.component.text.TextComponent;
26
import org.openconcerto.ui.valuewrapper.ValueChangeSupport;
26
import org.openconcerto.ui.valuewrapper.ValueChangeSupport;
27
import org.openconcerto.ui.valuewrapper.ValueWrapper;
27
import org.openconcerto.ui.valuewrapper.ValueWrapper;
28
import org.openconcerto.utils.CollectionUtils;
28
import org.openconcerto.utils.CollectionUtils;
-
 
29
import org.openconcerto.utils.CompareUtils;
29
import org.openconcerto.utils.cc.ITransformer;
30
import org.openconcerto.utils.cc.ITransformer;
-
 
31
import org.openconcerto.utils.cc.IdentityHashSet;
30
import org.openconcerto.utils.checks.ValidListener;
32
import org.openconcerto.utils.checks.ValidListener;
31
import org.openconcerto.utils.checks.ValidState;
33
import org.openconcerto.utils.checks.ValidState;
32
import org.openconcerto.utils.model.DefaultIMutableListModel;
34
import org.openconcerto.utils.model.DefaultIMutableListModel;
33
import org.openconcerto.utils.model.IListModel;
35
import org.openconcerto.utils.model.IListModel;
34
import org.openconcerto.utils.model.IMutableListModel;
36
import org.openconcerto.utils.model.IMutableListModel;
35
import org.openconcerto.utils.model.ListComboBoxModel;
37
import org.openconcerto.utils.model.ListComboBoxModel;
-
 
38
import org.openconcerto.utils.model.Reloadable;
36
import org.openconcerto.utils.text.SimpleDocumentListener;
39
import org.openconcerto.utils.text.SimpleDocumentListener;
37
 
40
 
38
import java.awt.Color;
41
import java.awt.Color;
39
import java.awt.Component;
42
import java.awt.Component;
40
import java.awt.Container;
43
import java.awt.Container;
Line 62... Line 65...
62
import java.awt.image.ColorConvertOp;
65
import java.awt.image.ColorConvertOp;
63
import java.beans.PropertyChangeListener;
66
import java.beans.PropertyChangeListener;
64
import java.util.ArrayList;
67
import java.util.ArrayList;
65
import java.util.Collection;
68
import java.util.Collection;
66
import java.util.HashMap;
69
import java.util.HashMap;
-
 
70
import java.util.HashSet;
67
import java.util.List;
71
import java.util.List;
68
import java.util.Map;
72
import java.util.Map;
69
 
73
 
70
import javax.swing.Action;
74
import javax.swing.Action;
71
import javax.swing.Icon;
75
import javax.swing.Icon;
Line 406... Line 410...
406
        }
410
        }
407
    }
411
    }
408
 
412
 
409
    /**
413
    /**
410
     * Returns the actions added at the end of the list of items. The name of the action will be
414
     * Returns the actions added at the end of the list of items. The name of the action will be
411
     * displayed and its actionPerformed() invoked when choosed.
415
     * displayed and its actionPerformed() invoked when chosen.
412
     * 
416
     * 
413
     * @return the list of actions
417
     * @return the list of actions
414
     */
418
     */
415
    public final List<Action> getActions() {
419
    public final List<Action> getActions() {
416
        return this.actions;
420
        return this.actions;
Line 434... Line 438...
434
 
438
 
435
        if (this.getMode() == ComboLockedMode.UNLOCKED) {
439
        if (this.getMode() == ComboLockedMode.UNLOCKED) {
436
            if (!(acache instanceof IMutableListModel))
440
            if (!(acache instanceof IMutableListModel))
437
                throw new IllegalArgumentException(this + " is unlocked but " + acache + " is not mutable");
441
                throw new IllegalArgumentException(this + " is unlocked but " + acache + " is not mutable");
438
            final IMutableListModel<T> mutable = (IMutableListModel<T>) acache;
442
            final IMutableListModel<T> mutable = (IMutableListModel<T>) acache;
-
 
443
            final boolean isReloadable = mutable instanceof Reloadable;
-
 
444
            final Reloadable rel = isReloadable ? (Reloadable) mutable : null;
439
            new MutableListComboPopupListener(new MutableListCombo() {
445
            new MutableListComboPopupListener(new MutableListCombo() {
440
                public ComboLockedMode getMode() {
446
                public ComboLockedMode getMode() {
441
                    return ISearchableCombo.this.getMode();
447
                    return ISearchableCombo.this.getMode();
442
                }
448
                }
443
 
449
 
Line 452... Line 458...
452
                }
458
                }
453
 
459
 
454
                public void removeCurrentText() {
460
                public void removeCurrentText() {
455
                    mutable.removeElement(getValue());
461
                    mutable.removeElement(getValue());
456
                }
462
                }
-
 
463
 
-
 
464
                @Override
-
 
465
                public boolean canReload() {
-
 
466
                    return isReloadable;
-
 
467
                }
-
 
468
 
-
 
469
                @Override
-
 
470
                public void reload() {
-
 
471
                    rel.reload();
-
 
472
                }
457
            }).listen();
473
            }).listen();
458
        }
474
        }
459
 
475
 
460
        addItemsFromCache(0, this.getCache().getSize() - 1);
476
        addItemsFromCache(0, this.getCache().getSize() - 1);
461
        this.getCache().addListDataListener(new ListDataListener() {
477
        this.getCache().addListDataListener(new ListDataListener() {
Line 495... Line 511...
495
    private void addItemsFromCache(final int index0, final int index1) {
511
    private void addItemsFromCache(final int index0, final int index1) {
496
        addItems(index0, getCache().getList().subList(index0, index1 + 1));
512
        addItems(index0, getCache().getList().subList(index0, index1 + 1));
497
    }
513
    }
498
 
514
 
499
    private void addItems(final int index, final Collection<T> originalItems) {
515
    private void addItems(final int index, final Collection<T> originalItems) {
-
 
516
        // selection cannot change
-
 
517
        assert SwingUtilities.isEventDispatchThread();
-
 
518
        final ISearchableComboItem<T> sel = getSelection();
-
 
519
        final T selOriginal = sel == null ? null : sel.getOriginal();
-
 
520
 
500
        final List<ISearchableComboItem<T>> toAdd = new ArrayList<ISearchableComboItem<T>>(originalItems.size());
521
        final List<ISearchableComboItem<T>> toAdd = new ArrayList<ISearchableComboItem<T>>(originalItems.size());
501
        for (final T originalItem : originalItems) {
522
        for (final T originalItem : originalItems) {
502
            final ISearchableComboItem<T> textSelectorItem = createItem(originalItem);
523
            final ISearchableComboItem<T> textSelectorItem;
-
 
524
            if (this.itemsByOriginalItem.containsKey(originalItem)) {
-
 
525
                // allow another item with the same original : add another item to our model, but
-
 
526
                // keep the first one in itemsByOriginalItem (this map is only used in setValue() to
-
 
527
                // quickly find the ISearchableComboItem)
-
 
528
                textSelectorItem = createItem(originalItem);
-
 
529
                // see ISearchableComboPopup.validateSelection()
-
 
530
                assert !textSelectorItem.equals(this.itemsByOriginalItem.get(originalItem)) : "Have to not be equal to be able to choose one or the other";
-
 
531
            } else {
-
 
532
                // reuse the selected value, otherwise the popup will select nothing
-
 
533
                if (sel != null && CompareUtils.equals(selOriginal, originalItem))
-
 
534
                    textSelectorItem = sel;
-
 
535
                else
-
 
536
                    textSelectorItem = createItem(originalItem);
503
            this.itemsByOriginalItem.put(originalItem, textSelectorItem);
537
                this.itemsByOriginalItem.put(originalItem, textSelectorItem);
-
 
538
            }
504
            toAdd.add(textSelectorItem);
539
            toAdd.add(textSelectorItem);
505
        }
540
        }
506
        // only 1 fire
541
        // only 1 fire
507
        this.getModel().addAll(index, toAdd);
542
        this.getModel().addAll(index, toAdd);
508
    }
543
    }
509
 
544
 
510
    private void rmItemsFromModel(final int index0, final int index1) {
545
    private void rmItemsFromModel(final int index0, final int index1) {
511
        getModel().removeElementsAt(index0, index1);
546
        getModel().removeElementsAt(index0, index1);
512
        // remove from our map
547
        // remove from our map
-
 
548
        // ATTN for ~35000 items, new HashSet() got us from 6000ms to 8ms !
513
        this.itemsByOriginalItem.keySet().retainAll(getCache().getList());
549
        this.itemsByOriginalItem.keySet().retainAll(new HashSet<T>(getCache().getList()));
514
    }
550
    }
515
 
551
 
516
    // conversion
552
    // conversion
517
 
553
 
518
    private ISearchableComboItem<T> createItem(final T originalItem) {
554
    private ISearchableComboItem<T> createItem(final T originalItem) {
Line 577... Line 613...
577
    }
613
    }
578
 
614
 
579
    // set
615
    // set
580
 
616
 
581
    public void resetValue() {
617
    public void resetValue() {
582
        this.setValue(null);
618
        this.setValue((T) null);
583
    }
619
    }
584
 
620
 
585
    public final void setValue(final T val) {
621
    public final void setValue(final T val) {
586
        this.setValue(val, true);
622
        this.setValue(val, true);
587
    }
623
    }
Line 601... Line 637...
601
        } else {
637
        } else {
602
            setSelectedItem(this.getCache().getElementAt(anIndex));
638
            setSelectedItem(this.getCache().getElementAt(anIndex));
603
        }
639
        }
604
    }
640
    }
605
 
641
 
606
    private final void setValue(final T val, final boolean valid) {
642
    private final boolean setValid(final boolean valid) {
607
        log("entering " + this.getClass().getSimpleName() + ".setValue " + val + " valid: " + valid);
-
 
608
        final boolean invalidChange = this.invalidEdit != !valid;
643
        final boolean invalidChange = this.invalidEdit != !valid;
609
        if (invalidChange) {
644
        if (invalidChange) {
610
            this.invalidEdit = !valid;
645
            this.invalidEdit = !valid;
611
            this.text.setForeground(this.invalidEdit ? Color.GRAY : Color.BLACK);
646
            this.text.setForeground(this.invalidEdit ? Color.GRAY : Color.BLACK);
612
        }
647
        }
-
 
648
        return invalidChange;
-
 
649
    }
613
 
650
 
-
 
651
    private final void setValue(final T val, final boolean valid) {
-
 
652
        log("entering " + this.getClass().getSimpleName() + ".setValue " + val + " valid: " + valid);
-
 
653
        final boolean invalidChange = this.setValid(valid);
-
 
654
 
614
        if (this.getValue() != val) {
655
        if (!CompareUtils.equals(this.getValue(), val)) {
615
            log("this.getValue() != val :" + this.getValue());
656
            log("this.getValue() != val :" + this.getValue());
616
            if (val == null)
657
            if (val == null)
617
                this.setSelection(null);
658
                this.setSelection(null);
618
            else if (this.itemsByOriginalItem.containsKey(val)) {
659
            else if (this.itemsByOriginalItem.containsKey(val)) {
619
                this.setSelection(this.itemsByOriginalItem.get(val));
660
                this.setSelection(this.itemsByOriginalItem.get(val));
Line 632... Line 673...
632
            // so the text must be changed, and listeners notified
673
            // so the text must be changed, and listeners notified
633
            this.selectionChanged();
674
            this.selectionChanged();
634
        }
675
        }
635
    }
676
    }
636
 
677
 
-
 
678
    // perhaps try to factor with the other setValue()
-
 
679
    final void setValue(final ISearchableComboItem<T> val) {
-
 
680
        log("entering " + this.getClass().getSimpleName() + ".setValue(ISearchableComboItem) " + val);
-
 
681
        assert new IdentityHashSet<ISearchableComboItem<T>>(this.getModelValues()).contains(val) : "Item not in model, perhaps use setValue(T)";
-
 
682
        // valid since val is in our model
-
 
683
        final boolean invalidChange = this.setValid(true);
-
 
684
 
-
 
685
        if (!CompareUtils.equals(this.getSelection(), val)) {
-
 
686
            this.setSelection(val);
-
 
687
        } else if (invalidChange) {
-
 
688
            log("this.getSelection() == val and invalidChange");
-
 
689
            // since val hasn't changed the model won't fire and thus our selectionChanged()
-
 
690
            // will not be called, but it has to since invalidEdit did change
-
 
691
            // so the text must be changed, and listeners notified
-
 
692
            this.selectionChanged();
-
 
693
        }
-
 
694
    }
-
 
695
 
637
    private final void setSelection(final ISearchableComboItem<T> val) {
696
    private final void setSelection(final ISearchableComboItem<T> val) {
638
        log("entering " + this.getClass().getSimpleName() + ".setSelection " + val);
697
        log("entering " + this.getClass().getSimpleName() + ".setSelection " + val);
639
        this.getModel().setSelectedItem(val);
698
        this.getModel().setSelectedItem(val);
640
    }
699
    }
641
 
700
 
Line 785... Line 844...
785
    /**
844
    /**
786
     * Set the row count on the current text editor if possible. Otherwise create a new text editor
845
     * Set the row count on the current text editor if possible. Otherwise create a new text editor
787
     * with the desired rows.
846
     * with the desired rows.
788
     * 
847
     * 
789
     * @param rows the new row count.
848
     * @param rows the new row count.
790
     * @param textArea <code>true</code> if the editor should be a text area (ie can have more than
849
     * @param textArea <code>true</code> if the editor should be a text area (i.e. can have more
791
     *        one line), <code>null</code> to retain the current editor, ignored if
850
     *        than one line), <code>null</code> to retain the current editor, ignored if
792
     *        <code>rows</code> >= 2.
851
     *        <code>rows</code> >= 2.
793
     */
852
     */
794
    public final void setRows(int rows, final Boolean textArea) {
853
    public final void setRows(int rows, final Boolean textArea) {
795
        JTextComponent newText = null;
854
        JTextComponent newText = null;
796
        if (this.text instanceof JTextArea) {
855
        if (this.text instanceof JTextArea) {