ComboBoxCellEditor events on linux, a follow up to the mac issue [message #1850576] |
Tue, 08 March 2022 14:52  |
Eclipse User |
|
|
|
Hey there,
This post is particularly aimed at providing some info to Dirk as he helped with a fix before on the Mac issue.
The fix for Mac https://git.eclipse.org/r/c/nattable/org.eclipse.nebula.widgets.nattable/+/180274 Works perfectly, thanks :).
However we had to add some new changes in order to make everything compatible with Linux. For some reason when using the ComboBoxCellEditor with NatCombo on Linux specifically in the single select checkbox mode, the selection of the cell to open the dropdown forces the selection listener to try to unselect the first item, this results in it flashing open and shut and stops the user from actually getting to the dropdown.
In order to fix it we implemented this change in our overridden selection listener.
// If trying to unselect, but the item was not selected before. do nothing
// This is a weird case that seems to appear on Linux specifically.
Boolean selectedBefore = AdvocateNatCombo.this.selectionStateMap.get(chosenItem.getText()).booleanValue();
if (AdvocateNatCombo.this.useCheckbox && selected && !selectedBefore) {
return;
}
The full code is below for the selection listener.
this.dropdownTable.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
// selected here seems to refer to the original state of the box
// i.e. this boolean is true if unselecting, false if selecting a new item
boolean selected = e.detail != SWT.CHECK;
boolean isCtrlPressed = (e.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL;
TableItem chosenItem = (TableItem) e.item;
// Given the ability to filter we need to find the item's
// table index which may not match the index in the itemList
int itemTableIndex = AdvocateNatCombo.this.dropdownTable.indexOf(chosenItem);
// If trying to unselect, but the item was not selected before. do nothing
// This is a weird case that seems to appear on Linux specifically.
Boolean selectedBefore = AdvocateNatCombo.this.selectionStateMap.get(chosenItem.getText()).booleanValue();
if (AdvocateNatCombo.this.useCheckbox && selected && !selectedBefore) {
return;
}
// This case handles check actions
if (!selected) {
if (!chosenItem.getChecked()) {
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.FALSE);
} else {
if (!AdvocateNatCombo.this.multiselect) {
for (String key : selectionStateMap.keySet()) {
AdvocateNatCombo.this.selectionStateMap.put(key, Boolean.FALSE);
}
}
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.TRUE);
}
} else if (!AdvocateNatCombo.this.useCheckbox) {
if (AdvocateNatCombo.this.multiselect && isCtrlPressed) {
boolean isSelected = AdvocateNatCombo.this.dropdownTable.isSelected(itemTableIndex);
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), isSelected);
} else {
// A single item was selected. Clear all previous state
for (String item : AdvocateNatCombo.this.itemList) {
AdvocateNatCombo.this.selectionStateMap.put(item, Boolean.FALSE);
}
// Set the state for the selected item
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.TRUE);
}
} else if (selected) {
if (!chosenItem.getChecked()) {
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.FALSE);
}
}
// Mouse up and Selection Events get fired the wrong way around on OSX
// This change makes sure that the Mouse up event gets fired again after the selection event
if (!AdvocateNatCombo.this.multiselect && AdvocateNatCombo.this.useCheckbox) {
Event event = new Event();
event.widget = AdvocateNatCombo.this;
event.display = AdvocateNatCombo.this.getDisplay();
event.type = SWT.MouseUp;
event.data = chosenItem;
AdvocateNatCombo.this.notifyListeners(SWT.MouseUp, event);
}
updateTextControl(false);
}
});
When investigating it appears that the SWT code specifically on linux is triggering this selection, I'm not sure if by design.
Just wanted to check if you had come across this issue or not and let you know the work around we added for it.
Cheers
Jonathan
|
|
|
Re: ComboBoxCellEditor events on linux, a follow up to the mac issue [message #1850586 is a reply to message #1850576] |
Wed, 09 March 2022 00:35  |
Eclipse User |
|
|
|
Hi,
thanks for reporting and showing what you have done. I have not seen this before, or at least can't remember it. Comparing your SelectionListener with the current one from the code base, I noticed a difference.
Your code:
if (!selected) {
if (!chosenItem.getChecked()) {
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.FALSE);
} else {
if (!AdvocateNatCombo.this.multiselect) {
for (String key : selectionStateMap.keySet()) {
AdvocateNatCombo.this.selectionStateMap.put(key, Boolean.FALSE);
}
}
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.TRUE);
}
} else if (!AdvocateNatCombo.this.useCheckbox) {
if (AdvocateNatCombo.this.multiselect && isCtrlPressed) {
boolean isSelected = AdvocateNatCombo.this.dropdownTable.isSelected(itemTableIndex);
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), isSelected);
} else {
// A single item was selected. Clear all previous state
for (String item : AdvocateNatCombo.this.itemList) {
AdvocateNatCombo.this.selectionStateMap.put(item, Boolean.FALSE);
}
// Set the state for the selected item
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.TRUE);
}
} else if (selected) {
if (!chosenItem.getChecked()) {
AdvocateNatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.FALSE);
}
}
NatTable code:
if (!selected) {
// handle checkbox interactions
if (!NatCombo.this.multiselect) {
// on single select first set all states to false
NatCombo.this.itemList.forEach(item -> NatCombo.this.selectionStateMap.put(item, Boolean.FALSE));
}
if (!chosenItem.getChecked()) {
NatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.FALSE);
} else {
NatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.TRUE);
}
} else {
// handle item interactions
if (!NatCombo.this.multiselect || (!NatCombo.this.useCheckbox && !isCtrlPressed)) {
// A single item was selected. Clear all previous state
NatCombo.this.itemList.forEach(item -> NatCombo.this.selectionStateMap.put(item, Boolean.FALSE));
// Set the state for the selected item
NatCombo.this.selectionStateMap.put(chosenItem.getText(), Boolean.TRUE);
} else if (NatCombo.this.multiselect && isCtrlPressed) {
boolean isSelected = NatCombo.this.dropdownTable.isSelected(itemTableIndex);
NatCombo.this.selectionStateMap.put(chosenItem.getText(), isSelected);
if (NatCombo.this.useCheckbox) {
chosenItem.setChecked(isSelected);
}
}
}
The if-clauses are different and also the handling differs then slightly. Could you try to update your SelectionListener to match the current implementation without your workaround if possible? I know that I checked and tested multiple scenarios to make everything work.
|
|
|
Powered by
FUDForum. Page generated in 0.02524 seconds