CheckboxTreeviewer previously set checked elements after reload - eclipse-rcp

I have used JFace CheckboxTreeviewer and added ICheckStateListener to get result of checked elements.
Code is as follows
private HashSet<Object> checkElement=new HashSet<Object>();
checkboxTreeViewer.addCheckStateListener(new ICheckStateListener() {
#Override
public void checkStateChanged(CheckStateChangedEvent event) {
String childNode=null;
String rootNode=null;
Object changed = event.getElement();
if(changed instanceof ChildFacetNodeVo){
checkElement.add(changed);
ChildFacetNodeVo childFacetNodeVo=(ChildFacetNodeVo)changed;
childNode=childFacetNodeVo.getLabelFacet();
rootNode=childFacetNodeVo.getParent();
//here to get a new result after element checked and put new result to checkboxtreeviewer
List<RootFacetNodeVo> facetNodeVos=createFacetFilter(rootNode,childNode);
if(facetNodeVos!=null){
checkboxTreeViewer.setInput(facetNodeVos);
checkboxTreeViewer.expandToLevel(3);
checkboxTreeViewer.setCheckedElements(checkElement.toArray());
}
}
}
});
Now what i need is when i checked the new element the previously checked element should not get unchecked.
when i set new input in CheckboxTreeviewer nothing is visible.
So how do i set prevously checked element in CheckboxTreeviewer.
for example
p1
-----A1 - previous checked
-----A2
-----A3
-----A4
-----A5
p1
-----A6
-----A7
-----A8 - previous checked
-----A8
-----A9
p1
-----A10
-----A11

If you call setCheckedElements you must include everything that should be checked in the array you specify.
You appear to be creating a new set of objects to go in the tree so you will have to work out which of these new items needs to be checked.
You can call checkboxTreeViewer.getCheckedElements() to get the old checked elements (do this before setting the new input). This should help you work out which of the new elements need to be checked.

Related

Added row moves to last position once filter is removed

In NatTable I am adding a row in filtered table. After removing the filter, the newly added row moves to last position in the table.
But I want to it to stay in the same position, that is next to the row which I added when the table is filtered.
I am currently using the RowInsertCommand. I don't want to add row via model or list which used to populated the table. I want to achieve only via NatTable commands. Is it possible?
It is always hard to follow the explanations and the issue without example code. But I assume you simply copied code from the NatTable examples, so I will explain your issue based on that.
First, the RowInsertCommand has several constructors. If you are using a constructor without a rowIndex or rowPositionparameter, the new object will ALWAYS be added at the end of the list.
When using the filter functionality in NatTable with GlazedLists, the list that is wrapped in the body DataLayer is the FilterList. If you are operating on the FilterList for calculating the rowIndex where the new object should be added and have the FilterList as base list in the RowInsertCommandHandler, the place where the new object is added is transformed between the FilterList and the base EventList, which might not be the desired result.
To solve this you need to create the RowInsertCommandHandler by using the base EventList.
EventList<T> eventList = GlazedLists.eventList(values);
TransformedList<T, T> rowObjectsGlazedList = GlazedLists.threadSafeList(eventList);
SortedList<T> sortedList = new SortedList<>(rowObjectsGlazedList, null);
this.filterList = new FilterList<>(sortedList);
this.baseList = eventList;
bodyDataLayer.registerCommandHandler(new RowInsertCommandHandler<>(this.baseList));
The action that performs the add operation then of course needs to calculate the index based on the base EventList. The following code is part of the SelectionAdapter of an IMenuItemProvider:
int rowPosition = MenuItemProviders.getNatEventData(event).getRowPosition();
int rowIndex = natTable.getRowIndexByPosition(rowPosition);
Object relative = bodyLayerStack.filterList.get(rowIndex);
int baseIndex = bodyLayerStack.baseList.indexOf(relative);
Object newObject = new ...;
natTable.doCommand(new RowInsertCommand<>(baseIndex + 1, newObject));

Add or remove item in datagrid does not trigger WhenAnyPropertyChanged

I am using dynamic data with reactiveui,
` _propList.Connect()
.WhenAnyPropertyChanged()
.Subscribe(t =>
{
}`
the code will be trigger if I just edit any item in the grid. However, when I try to add or remove an item, it is not triggered.
In my view model I have something like this
private SourceList<Decision> _myList { get; set; } = new SourceList<Decision>();
private readonly IObservableCollection<Decision> _targetCollection = new ObservableCollectionExtended<Decision>();
public IObservableCollection<Decision> TargetCollection => _targetCollection;
in my view, I simply
this.OneWayBind(VM, vm => vm.TargetCollection, v => v.DataGrid1.DataSource);
If I remove or Add item in the grid, and press Save
_myList.Count() didn't change, but
_TargetCollection.Count() will increase or decrease by number of items I delete
In my ViewModel
OKCmd = ReactiveCommand.Create(() =>
{
//// _myList.Connect()
////.Subscribe(t =>
//// {
//// ;
//// }
//// );
t.Items.count() and it is the initial load items, but I couldn't seem to know what items have been added or removed. Am I missing something.
Of course, I can keep track of what items are added or removed in the UI, but I am hoping I don't have to do that.
Thanks.
To help me answer your question, I need to better understand what you are trying to achieve but first I will explain what the default behaviour of DD is.
If you want add / remove events you need _propList.Connect().Subscribe(changes => ...). These are the collection changes and you will receive all collection change events including the initial load, but no inline changes.
By default, no property changes are wire in. This is because to monitor property changes is expensive and is opt in only. Also WhenAnyPropertyChanged() never tiggers for the initial load. This is because the item is already loaded and no properties have changed between Connect being called and the property changed observable being subscribed to.
Following on from 2, you will never receive a property changed when an item is removed from the underlying source. This is because when an item it removed, any inline subscriptions are disposed of. Otherwise there would be memory leaks.
Another option for monitoring inline changes is to make use of 'MergeMany' which allows you to craft any observable on a specific item, and in your case you can create an observable to return the initial value as well as as subsequent changes.
It is possible using standard rx to listen to collection changes and inline changes in a single observable, which you would have to compose yourself. For example
var myCollectionChanges = _propList.Connect();
var myPropertyChanges = _propList.Connect().WhenAnyPropertyChanged();
var allMyChanges = myCollectionChanges.Select(_ => Unit.Default)
.Merge(myPropertyChanges.Select(_ => Unit.Default));
In the this example, I have used Select(_ => Unit.Default) to enable the merge operator as it requires the same signature. However what signature is returned is up to you, the key point being that the signatures must match.

EF6 - Adding new associated child not populating Navigation Properties

I have the following code which adds members to a parent group. The issue I'm running into is that the LAST member added to the PCSGroupMembers collection will not load it's navigation properties on demand. I have a set of 3 I've tried adding in various orders... the first 2 always work, the last one won't load the nav properties.
In the case below, you'll see 6 members total. The last 3 are the ones I just added in this request are the SAME IDS as the first 3 (unique key is groupid, memberid, startdate), so I know for sure there isn't an issue with a "bad FK" or similar. The first two of the new members are building out their nav properties, but that last one never does. Doesn't matter if I'm adding 2, 3, 4, etc. Last one never populates.
What seems REALLY odd to me is the PcsGroupID is an empty Guid on that last one even though it got added to the group via group.PcsGroupMembers.add(pcsMember) in the code below.
Edit: If you see the block labeled Hack, however, the real final member now has it's Nav properties. The faked temp member is then removed from the collection (and context) and everything magically works. So....WAT?
Code to add new members
//expire all existing members ([0..2] in this example)
group.PCSGroupMembers
.Where(m => m.EndDate == null)
.ToList().ForEach(m => {
m.EndDate = DateTime.Now.Date;
});
//add new members from request ([3..5] in this example)
foreach (PcsGroupMemberAddViewModel member in requestViewModel.Members) {
PCSGroupMember pcsMember = db.PCSGroupMembers.Create();
pcsMember.PCSSplitID = Guid.NewGuid();
pcsMember.ProjectProtocolID = member.ProjectProtocolID;
pcsMember.SplitAmount = member.Split;
pcsMember.IsPrimary = member.IsPrimary;
pcsMember.StartDate = DateTime.Now.Date;
group.PCSGroupMembers.Add(pcsMember);
}
Second to last (index 4)
Last Child (index 5)
Hack
var tempmember = db.PCSGroupMembers.Create();
//this Add seems to trigger the previous 'real' item to load it's Nav properties.... ???
group.PCSGroupMembers.Add(tempmember);
group.PCSGroupMembers.Remove(tempmember); //remove from collection
db.PCSGroupMembers.Remove(tempmember); //remove from context

Richfaces 4 dynamic select options when user type

I am using rich faces select component.
I want dynamic values when user manually type some thing in the select component.
<rich:select enableManualInput="true" defaultLabel="start typing for select" value="#{supplierSearchBean.userInput}">
<a4j:ajax event="keyup" execute="#this" listener="#{supplierSearchBean.userInputChange}"/>
<f:selectItems value="#{supplierSearchBean.selectOptions}" />
</rich:select>
Java code as follows
public void userInputChange(ActionEvent ae){
Map map = ae.getComponent().getAttributes();
System.out.println(map.toString());
}
public void setUserInput(String userInput) {
System.out.println("userINput = " + userInput);
this.userInput = userInput;
}
Here i found 2 issues
1st: setUserINput always print empty string when user type value
2nd: listener method never get call.
any help ?
The problem is most probably that there is no selected value while the user types, and this component restricts the allowed values to the specified select items. A partial input is thus not valid and cannot be bound to your bean.
I think you could get the expected behavior if you use a rich:autocomplete instead. However, if you want to restrict the allowed values, maybe you can keep your rich:select and listen for the selectitem event.
Override getItems function in richfaces-utils.js file in richfaces-core-impl-4.0.0.Final.jar under richfaces-core-impl-4.0.0.Final\META-INF\resources folder.
Change the condition of pushing items to be
if(p != -1)
instead of
if(p == 0)
This should fix the issue.

How to conditionally change a ListGridField's required attribute in SmartGWT?

I've been trying to achieve similar functionality on ListGrid that already exists for FormItems: com.smartgwt.client.widgets.form.validator.RequiredIfValidator.
I want to set a column required based on a value of another column.
Ie. we got ListGridFields A = "Need more coffee? If not, why?" and B for answering the question. B is not required until A has a certain value.
ListGrid grid = new ListGrid();
// Boolean
ListGridField questionA = new ListGridField("questionA", "Need more coffee?");
questionA.setRequired(true);
// String
ListGridField reason = new ListGridField("reason", "Reason");
reason.setRequired(false); // should become true when A is not checked.
grid.setFields(questionA, reason);
I tried using the same validator for the ListGridField and got the validator to fire, but it does not change the field's required attribute, no matter what gets returned from the RequiredIfFunction's execute() method.
Is there a neat way to deal with this?
Although it makes sense, the other answer for this question, equivalent to myConditionalValidatedField.setRequired(myCheckBox.getValueAsBoolean()) in my example code, didn't work for me. I fixed the problem doing the following:
RequiredIfValidator validator = new RequiredIfValidator();
validator.setExpression(new RequiredIfFunction() {
#Override
public boolean execute(FormItem formItem, Object value) {
return myCheckBox.getValueAsBoolean();
}
});
validator.setErrorMessage("Required field if 'myCheckBox' is checked");
myConditionalValidatedField.setValidators(validator);
Hope ot helps!