001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.client.tide.collections.javafx;
022    
023    import java.util.ArrayList;
024    import java.util.Collection;
025    import java.util.List;
026    
027    import javax.annotation.PreDestroy;
028    
029    import javafx.beans.InvalidationListener;
030    import javafx.collections.FXCollections;
031    import javafx.collections.ListChangeListener;
032    import javafx.collections.ObservableList;
033    
034    import org.granite.client.tide.collections.AbstractPagedCollection;
035    import org.granite.client.tide.server.TideRpcEvent;
036    import org.granite.client.util.javafx.ListListenerHelper;
037    import org.granite.client.util.javafx.ListenerHelper;
038    
039    /**
040     * @author William DRAI
041     */
042    public abstract class PagedCollection<E> extends AbstractPagedCollection<E> implements ObservableList<E> {
043            
044        private List<E> internalWrappedList = new ArrayList<E>();
045        protected ObservableList<E> wrappedList;
046        
047        private ListenerHelper<PageChangeListener<E>> pageChangeHelper = new ListenerHelper<PageChangeListener<E>>(PageChangeListener.class);
048        
049        
050        @Override
051        protected List<E> getInternalWrappedList() {
052            return internalWrappedList;
053        }
054        
055        @Override
056        protected List<E> getWrappedList() {
057            return wrappedList;
058        }
059            
060    
061            public PagedCollection() {
062                    super();
063                    
064                    wrappedList = FXCollections.observableList(internalWrappedList);
065                    wrappedList.addListener(new WrappedListListChangeListener());
066            }
067            
068            
069            @Override
070            public boolean setAll(Collection<? extends E> coll) {
071                    if (!initializing)
072                            return fullRefresh();
073                    return false;
074            }
075            
076            
077            @Override
078            @PreDestroy
079            public void clear() {
080                    helper.clear();
081                    pageChangeHelper.clear();
082                    super.clear();
083            }
084            
085            
086            private ListListenerHelper<E> helper = new ListListenerHelper<E>();
087            
088            public void addListener(ListChangeListener<? super E> listener) {
089                    helper.addListener(listener);
090        }
091    
092            public void removeListener(ListChangeListener<? super E> listener) {
093                    helper.removeListener(listener);
094        }
095            
096            public void addListener(InvalidationListener listener) {
097                    helper.addListener(listener);
098        }
099    
100            public void removeListener(InvalidationListener listener) {
101                    helper.removeListener(listener);
102        }
103            
104            public void addListener(PageChangeListener<E> listener) {
105                    pageChangeHelper.addListener(listener);
106            }
107            
108            public void removeListener(PageChangeListener<E> listener) {
109                    pageChangeHelper.removeListener(listener);
110            }
111            
112            public void firePageChange(TideRpcEvent event) {
113                    fireItemsUpdated(0, this.last-this.first);
114                    pageChangeHelper.fireEvent(this, event);
115            }
116            
117            
118            public class WrappedListListChangeListener implements ListChangeListener<E> {             
119                @Override
120                public void onChanged(ListChangeListener.Change<? extends E> change) {
121                    ListChangeWrapper wrappedChange = new ListChangeWrapper(wrappedList, change);
122                    helper.fireValueChangedEvent(wrappedChange);
123                }
124            }
125            
126            public void fireItemsUpdated(final int from, final int to) {
127                    ListChangeListener.Change<E> change = new ListChangeListener.Change<E>(wrappedList) {
128                            @Override
129                            public int getFrom() {
130                                    return first+from;
131                            }
132    
133                            @Override
134                            public int getTo() {
135                                    return first+to;
136                            }
137                            
138                            @Override
139                            public boolean wasUpdated() {
140                                    return true;
141                            }
142                            
143                            @Override
144                            protected int[] getPermutation() {
145                                    return EMPTY_PERMUTATION;
146                            }
147    
148                            @Override
149                            public List<E> getRemoved() {
150                                    return null;
151                            }
152    
153                            @Override
154                            public boolean next() {
155                                    return false;
156                            }
157    
158                            @Override
159                            public void reset() {
160                            }                       
161                    };
162                    helper.fireValueChangedEvent(change);
163            }
164    
165        private static final int[] EMPTY_PERMUTATION = new int[0];
166        
167            public class ListChangeWrapper extends ListChangeListener.Change<E> {            
168                private final ListChangeListener.Change<? extends E> wrappedChange;
169                
170                public ListChangeWrapper(ObservableList<E> list, ListChangeListener.Change<? extends E> wrappedChange) {
171                    super(list);
172                    this.wrappedChange = wrappedChange;
173                }
174    
175                @Override
176                    public int getAddedSize() {
177                            return wrappedChange.getAddedSize();
178                    }
179    
180                    @SuppressWarnings("unchecked")
181                    @Override
182                    public List<E> getAddedSubList() {
183                            return (List<E>)wrappedChange.getAddedSubList();
184                    }
185    
186                    @Override
187                    public int getRemovedSize() {
188                            return wrappedChange.getRemovedSize();
189                    }
190    
191                    @Override
192                    public boolean wasAdded() {
193                            return wrappedChange.wasAdded();
194                    }
195    
196                    @Override
197                    public boolean wasPermutated() {
198                            return wrappedChange.wasPermutated();
199                    }
200    
201                    @Override
202                    public boolean wasRemoved() {
203                            return wrappedChange.wasRemoved();
204                    }
205    
206                    @Override
207                    public boolean wasReplaced() {
208                            return wrappedChange.wasReplaced();
209                    }
210    
211                    @Override
212                    public boolean wasUpdated() {
213                            return wrappedChange.wasUpdated();
214                    }
215    
216                    @Override
217                public int getFrom() {
218                            int from = wrappedChange.getFrom();
219                    return from+first;
220                }
221    
222                @Override
223                public int getTo() {
224                    int to = wrappedChange.getTo();
225                    return to+first;
226                }
227    
228                @Override
229                protected int[] getPermutation() {
230                    return EMPTY_PERMUTATION;
231                }
232    
233                @Override
234                public int getPermutation(int num) {
235                    return wrappedChange.getPermutation(num);
236                }
237    
238                @SuppressWarnings("unchecked")
239                    @Override
240                public List<E> getRemoved() {
241                    return (List<E>)wrappedChange.getRemoved();
242                }
243    
244                @Override
245                public boolean next() {
246                    return wrappedChange.next();
247                }
248    
249                @Override
250                public void reset() {
251                    wrappedChange.reset();
252                }        
253            }
254            
255            
256            @Override
257            public Object[] toArray() {
258                    return wrappedList.toArray();
259            }
260    
261            @Override
262            public <T> T[] toArray(T[] a) {
263                    return wrappedList.toArray(a);
264            }
265    
266            @Override
267            public boolean add(E e) {
268                    throw new UnsupportedOperationException();
269            }
270    
271            @Override
272            public void add(int index, E element) {
273                    throw new UnsupportedOperationException();
274            }
275    
276            @Override
277            public boolean addAll(Collection<? extends E> c) {
278                    throw new UnsupportedOperationException();
279            }
280    
281            @Override
282            public boolean addAll(int index, Collection<? extends E> c) {
283                    throw new UnsupportedOperationException();
284            }
285    
286            @Override
287            public boolean addAll(E... arg0) {
288                    throw new UnsupportedOperationException();
289            }
290            
291            @Override
292            public boolean remove(Object o) {
293                    throw new UnsupportedOperationException();
294            }
295    
296            @Override
297            public E remove(int index) {
298                    throw new UnsupportedOperationException();
299            }
300    
301            @Override
302            public boolean removeAll(Collection<?> c) {
303                    throw new UnsupportedOperationException();
304            }
305    
306            @Override
307            public void remove(int arg0, int arg1) {
308                    throw new UnsupportedOperationException();
309            }
310    
311            @Override
312            public boolean removeAll(E... arg0) {
313                    throw new UnsupportedOperationException();
314            }
315    
316            @Override
317            public boolean retainAll(E... arg0) {
318                    throw new UnsupportedOperationException();
319            }
320    
321            @Override
322            public boolean setAll(E... arg0) {
323                    throw new UnsupportedOperationException();
324            }
325    
326            @Override
327            public boolean retainAll(Collection<?> c) {
328                    throw new UnsupportedOperationException();
329            }
330    
331            @Override
332            public E set(int index, E element) {
333                    throw new UnsupportedOperationException();
334            }
335    
336            @Override
337            public List<E> subList(int fromIndex, int toIndex) {
338                    throw new UnsupportedOperationException();
339            }
340    }