events - How to get selected items from a SWT Table using RxJava? -


i have table , button , want emit event itemsselected selected items of table when button clicked.

the button should not know table , should remain stream of clicks. solution discarded:

 final etable table = ...  publishsubject<itemselected> selected = publishsubject.create();  button.addselectionlistener(new selectionlistener(){        @override       public void widgetselected(selectionevent e) {         (tableitem item : table.getselection()) {          selected.onnext(new itemselected(item));          }        }      }); 

i prefer way compose click stream of button item selection stream of table in order keep loose coupling between 2 elements.

because table allows multiple selection must first scan items selected in order emit event items. like:

public static class itemsselected<t> {      final list<t> items = new arraylist<t>();    }    public abstract static class itemselection<t> {      public abstract void apply(itemsselected<t> selection);   }    public static class itemunselected<t> extends itemselection<t> {      final t item;      public itemunselected(t item) {       this.item = item;     }      public void apply(itemsselected<t> selection) {       selection.items.remove(item);     }    }    public static class itemselected<t> extends itemselection<t> {      final t item;      public itemselected(t item) {       this.item = item;     }      public void apply(itemsselected<t> selection) {       selection.items.add(item);     }    }    public static class observabletable<t> extends table {      private publishsubject<itemselection<t>> clicks = publishsubject.create();      public observable<itemsselected<t>> selection = clicks.scan(new itemsselected<t>(),         new func2<itemsselected<t>, itemselection<t>, itemsselected<t>>() {            @override           public itemsselected<t> call(itemsselected<t> t1, itemselection<t> t2) {             // breaking events immutability             t2.apply(t1);             return t1;           }          });      public observabletable(composite parent, int style) {       super(parent, style);       this.addselectionlistener(new selectionlistener() {          @suppresswarnings("unchecked")         @override         public void widgetselected(selectionevent e) {           if (((tableitem) e.item).getchecked())             clicks.onnext(new itemselected<t>((t) e.item.getdata()));           else             clicks.onnext(new itemunselected<t>((t) e.item.getdata()));         }          @override         public void widgetdefaultselected(selectionevent e) {          }       });     }    } 

then, must combine table.selection stream button.clicks stream in selectionforaction stream. idea when buttonclick emitted, selectionforaction emitted if , if itemselected emitted.

-------s1--u1-----s2---s3--------- table.clicks            (scan) -------(1)--()---(2)---(2,3)------ table.selection  ----o----------o-------------o---- button.clicks               (?) -----------------------------(2,3) selectionforaction 

so, wich operation should use?

  • zip: doesn't work because if click button , later select item, should not nothing, zip emit event.
  • join: end "solution" using join doesn't seem one. somethinkg like:

table.selection.join(button.clicks, new func1<itemsselected,observable<long>>() {    @override   public observable<long> call(itemsselected t) {     // doesn't seem idea     return observable.timer(1, timeunit.days);   }  }, new func1<clickevent, observable<long>>() {    @override   public observable<long> call(clickevent t) {     // makes clickevent dropped if there no previous itemsselected event emitted     return observable.timer(1, timeunit.milliseconds);   }  }, new func2<itemsselected, clickevent, selectionforaction>() {    @override   public selectionforactioncall(itemsselected t1, clickevent t2) {     return new selectionforaction(t1.items);   }  }); 

any idea?

i've found operator needed achieve join behaviour large time unit (days in example) , small 1 (milliseconds).

with variant of sample takes observable sampler emit event after event of b emitted. enter image description here

in example click acts sampler , stream selection emits events i'm interested in. (this requires ignore last event being emitted when stream completes).

another possible solution use buffer(boundary): enter image description here

the clicks stream act boundary , avoid scan operator because list of items selected created buffer operator. solution not considering unselection.

so, sample i've achieved original goal, however, i'm not happy way handle items unselection , final list of items selected. in case need maintain state of items selected in order perform operation on of them when clickevent occurs.

i subscribe items selection/unselection , maintain list of items selected i'll have lost possibility of compose clicks observable selection observable.

with scan maintain state , keep composability of observables, representing list of current selection event seems little forced, in fact represents new issue: if select x items , click button, event selection being emitted expected, if neither items unselected nor new 1 selected , click again button, nothing happens. so, seems selection doesn't fit event.


Comments