OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Compare Revisions

Regard whitespace Rev 24 → Rev 25

/trunk/OpenConcerto/src/org/openconcerto/ui/component/combo/ISearchableComboPopup.java
13,8 → 13,6
package org.openconcerto.ui.component.combo;
 
import org.openconcerto.utils.model.SimpleListDataListener;
 
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
36,7 → 34,6
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.ListDataEvent;
 
public class ISearchableComboPopup<T> extends JPopupMenu {
 
53,26 → 50,7
uiInit();
// Listeners
this.list.addMouseMotionListener(new ListMouseMotionHandler());
// JList always displays visibleRowCount even when fewer items exists
// so if we put a high number we get a big blank popup
// instead listen to model change to adjust row count
this.getListModel().addListDataListener(new SimpleListDataListener() {
@Override
public void contentsChanged(ListDataEvent e) {
// ATTN row count always gets back to zero when the contents change (because of
// removeAll())
final int rowCount = Math.min(getListModel().getSize(), 30);
// checking if rowCount changes doesn't work (one reason is probably that we're
// called before Swing and so setVisible displays an empty list)
ISearchableComboPopup.this.list.setVisibleRowCount(rowCount);
if (rowCount > 0 && isVisible()) {
// since "visible row count" is not dynamic
setVisible(false);
setVisible(true);
}
}
});
}
 
private ISearchableCombo<T> getCombo() {
return this.text;
98,6 → 76,7
final JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
comp.setFont(getCombo().getFont());
if (value instanceof Action) {
comp.setFont(comp.getFont().deriveFont(Font.ITALIC));
comp.setText((String) ((Action) value).getValue(Action.NAME));
comp.setIcon(null);
} else {
207,7 → 186,9
// if no selection, don't change the combo
if (sel != null) {
if (sel instanceof ISearchableComboItem) {
this.getCombo().setValue(((ISearchableComboItem<T>) sel).getOriginal());
// don't call setValue() with sel.getOriginal() to handle list with the same item
// multiple times.
this.getCombo().setValue((ISearchableComboItem<T>) sel);
} else if (sel instanceof Action) {
((Action) sel).actionPerformed(new ActionEvent(this.getCombo(), ActionEvent.ACTION_PERFORMED, this.getCombo().getName()));
} else
217,6 → 198,24
}
 
public void open() {
// JList always displays visibleRowCount even when fewer items exists
// so if we put a high number we get a big blank popup
// handle this in open() and not with a SimpleListDataListener since :
// 1. open() is called only once whereas add is called multiple times in
// ISearchableCombo.setMatchingCompletions().
// 2. open() is always called when the list is modified.
final int size = getListModel().getSize();
// rowCount == 0 looks like a bug so show 3 empty rows
final int rowCount = size == 0 ? 3 : Math.min(size, 30);
if (this.list.getVisibleRowCount() != rowCount) {
// checking if rowCount changes doesn't work (one reason is probably that we're
// called before Swing and so setVisible displays an empty list)
this.list.setVisibleRowCount(rowCount);
if (this.isShowing()) {
// since "visible row count" is not dynamic
setVisible(false);
}
}
// si on est pas déjà affiché
// afficher même qd pas d'items : si l'user clique il faut qu'il voit la liste même vide
if (!this.isShowing())
/trunk/OpenConcerto/src/org/openconcerto/ui/component/combo/ISearchableCombo.java
26,7 → 26,9
import org.openconcerto.ui.valuewrapper.ValueChangeSupport;
import org.openconcerto.ui.valuewrapper.ValueWrapper;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.CompareUtils;
import org.openconcerto.utils.cc.ITransformer;
import org.openconcerto.utils.cc.IdentityHashSet;
import org.openconcerto.utils.checks.ValidListener;
import org.openconcerto.utils.checks.ValidState;
import org.openconcerto.utils.model.DefaultIMutableListModel;
33,6 → 35,7
import org.openconcerto.utils.model.IListModel;
import org.openconcerto.utils.model.IMutableListModel;
import org.openconcerto.utils.model.ListComboBoxModel;
import org.openconcerto.utils.model.Reloadable;
import org.openconcerto.utils.text.SimpleDocumentListener;
 
import java.awt.Color;
64,6 → 67,7
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
 
408,7 → 412,7
 
/**
* Returns the actions added at the end of the list of items. The name of the action will be
* displayed and its actionPerformed() invoked when choosed.
* displayed and its actionPerformed() invoked when chosen.
*
* @return the list of actions
*/
436,6 → 440,8
if (!(acache instanceof IMutableListModel))
throw new IllegalArgumentException(this + " is unlocked but " + acache + " is not mutable");
final IMutableListModel<T> mutable = (IMutableListModel<T>) acache;
final boolean isReloadable = mutable instanceof Reloadable;
final Reloadable rel = isReloadable ? (Reloadable) mutable : null;
new MutableListComboPopupListener(new MutableListCombo() {
public ComboLockedMode getMode() {
return ISearchableCombo.this.getMode();
454,6 → 460,16
public void removeCurrentText() {
mutable.removeElement(getValue());
}
 
@Override
public boolean canReload() {
return isReloadable;
}
 
@Override
public void reload() {
rel.reload();
}
}).listen();
}
 
497,10 → 513,29
}
 
private void addItems(final int index, final Collection<T> originalItems) {
// selection cannot change
assert SwingUtilities.isEventDispatchThread();
final ISearchableComboItem<T> sel = getSelection();
final T selOriginal = sel == null ? null : sel.getOriginal();
 
final List<ISearchableComboItem<T>> toAdd = new ArrayList<ISearchableComboItem<T>>(originalItems.size());
for (final T originalItem : originalItems) {
final ISearchableComboItem<T> textSelectorItem = createItem(originalItem);
final ISearchableComboItem<T> textSelectorItem;
if (this.itemsByOriginalItem.containsKey(originalItem)) {
// allow another item with the same original : add another item to our model, but
// keep the first one in itemsByOriginalItem (this map is only used in setValue() to
// quickly find the ISearchableComboItem)
textSelectorItem = createItem(originalItem);
// see ISearchableComboPopup.validateSelection()
assert !textSelectorItem.equals(this.itemsByOriginalItem.get(originalItem)) : "Have to not be equal to be able to choose one or the other";
} else {
// reuse the selected value, otherwise the popup will select nothing
if (sel != null && CompareUtils.equals(selOriginal, originalItem))
textSelectorItem = sel;
else
textSelectorItem = createItem(originalItem);
this.itemsByOriginalItem.put(originalItem, textSelectorItem);
}
toAdd.add(textSelectorItem);
}
// only 1 fire
510,7 → 545,8
private void rmItemsFromModel(final int index0, final int index1) {
getModel().removeElementsAt(index0, index1);
// remove from our map
this.itemsByOriginalItem.keySet().retainAll(getCache().getList());
// ATTN for ~35000 items, new HashSet() got us from 6000ms to 8ms !
this.itemsByOriginalItem.keySet().retainAll(new HashSet<T>(getCache().getList()));
}
 
// conversion
579,7 → 615,7
// set
 
public void resetValue() {
this.setValue(null);
this.setValue((T) null);
}
 
public final void setValue(final T val) {
603,15 → 639,20
}
}
 
private final void setValue(final T val, final boolean valid) {
log("entering " + this.getClass().getSimpleName() + ".setValue " + val + " valid: " + valid);
private final boolean setValid(final boolean valid) {
final boolean invalidChange = this.invalidEdit != !valid;
if (invalidChange) {
this.invalidEdit = !valid;
this.text.setForeground(this.invalidEdit ? Color.GRAY : Color.BLACK);
}
return invalidChange;
}
 
if (this.getValue() != val) {
private final void setValue(final T val, final boolean valid) {
log("entering " + this.getClass().getSimpleName() + ".setValue " + val + " valid: " + valid);
final boolean invalidChange = this.setValid(valid);
 
if (!CompareUtils.equals(this.getValue(), val)) {
log("this.getValue() != val :" + this.getValue());
if (val == null)
this.setSelection(null);
634,6 → 675,24
}
}
 
// perhaps try to factor with the other setValue()
final void setValue(final ISearchableComboItem<T> val) {
log("entering " + this.getClass().getSimpleName() + ".setValue(ISearchableComboItem) " + val);
assert new IdentityHashSet<ISearchableComboItem<T>>(this.getModelValues()).contains(val) : "Item not in model, perhaps use setValue(T)";
// valid since val is in our model
final boolean invalidChange = this.setValid(true);
 
if (!CompareUtils.equals(this.getSelection(), val)) {
this.setSelection(val);
} else if (invalidChange) {
log("this.getSelection() == val and invalidChange");
// since val hasn't changed the model won't fire and thus our selectionChanged()
// will not be called, but it has to since invalidEdit did change
// so the text must be changed, and listeners notified
this.selectionChanged();
}
}
 
private final void setSelection(final ISearchableComboItem<T> val) {
log("entering " + this.getClass().getSimpleName() + ".setSelection " + val);
this.getModel().setSelectedItem(val);
787,8 → 846,8
* with the desired rows.
*
* @param rows the new row count.
* @param textArea <code>true</code> if the editor should be a text area (ie can have more than
* one line), <code>null</code> to retain the current editor, ignored if
* @param textArea <code>true</code> if the editor should be a text area (i.e. can have more
* than one line), <code>null</code> to retain the current editor, ignored if
* <code>rows</code> >= 2.
*/
public final void setRows(int rows, final Boolean textArea) {