001package votorola.s.gwt.scene.dum; // Copyright 2010-2011, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE. 002 003import com.google.gwt.core.client.*; 004import com.google.gwt.user.cellview.client.*; 005import com.google.gwt.user.client.*; 006import com.google.gwt.user.client.rpc.AsyncCallback; 007import java.util.ArrayList; 008import java.util.List; 009import votorola.a.web.gwt.*; 010import votorola.s.gwt.scene.*; 011import votorola.s.gwt.scene.feed.*; 012import votorola.g.hold.*; 013import votorola.g.web.gwt.*; 014 015 016/** A feed for dummy bites. 017 */ 018public final class DummyFeed extends Feed implements Hold 019{ 020 021 022 /** Constructs a DummyFeed. Call {@linkplain #release release}() when done with it. 023 */ 024 public DummyFeed() 025 { 026 super( new ArrayList<BiteJS>( /*initial capacity*/LIST_MAX_SIZE )); 027 028 new Ticker(); 029 } 030 031 032 033 // ```````````````````````````````````````````````````````````````````````````````````` 034 // init for early use 035 036 037 private final Spool spool = new Spool1(); 038 039 040 041 // - H o l d -------------------------------------------------------------------------- 042 043 044 public void release() { spool.unwind(); } 045 046 047 048//// P r i v a t e /////////////////////////////////////////////////////////////////////// 049 050 051 private static void addTrim( final List<BiteJS> list, final BiteJS bite, final int maxSize ) 052 { 053 while( list.size() >= maxSize ) list.remove( maxSize - 1 ); 054 list.add( 0, bite ); 055 } 056 057 058 059 private static final int LIST_MAX_SIZE = 200; 060 061 062 063 private static final int LISTU_MAX_SIZE = LIST_MAX_SIZE * 100; 064 065 066 067 private static final String REQUEST_LOC = App.getServletContextLocation() + "/xfDum?form=json"; 068 // callback parameter added automatically by JsonpRequestBuilder 069 070 071 072 private final UnScoper scoper = new UnScoper( LIST_MAX_SIZE, new ArrayList<BiteJS>(), spool ); 073 074 075 076 // ==================================================================================== 077 078 079 private final class Ticker extends Timer implements AsyncCallback<JsArray<BiteJS>> 080 { 081 082 Ticker() 083 { 084 spool.add( new Hold() { public void release() { cancel(); }}); 085 run(); // tick eagerly 086 scheduleRepeating( 5000/*ms*/ ); 087 } 088 089 090 JsArray<BiteJS> biteBuffer // received from server, not yet displayed in feed list 091 = JavaScriptObject.createArray().cast(); 092 093 094 boolean isResponsePending; 095 096 097 boolean isScrapingBottom; 098 099 100 public void onFailure( final Throwable x ) 101 { 102 if( spool.isUnwinding() ) return; 103 104 final boolean toRetry = Window.confirm( "Feed request failed: " + x 105 + ". Ready to retry." ); 106 if( toRetry ) isResponsePending = false; 107 else cancel(); 108 } 109 110 111 public void onSuccess( final JsArray<BiteJS> moreBites ) 112 { 113 if( spool.isUnwinding() ) return; 114 115 if( biteBuffer.length() > 0 ) 116 { 117 assert false; 118 return; 119 } 120 121 biteBuffer = moreBites; 122 isResponsePending = false; 123 124 if( isScrapingBottom ) run(); 125 } 126 127 128 public void run() 129 { 130 if( spool.isUnwinding() ) return; // though probably impossible, as ticker would be cancelled 131 132 final int bN = biteBuffer.length(); 133 isScrapingBottom = bN <= 0; 134 if( !isScrapingBottom ) 135 { 136 final BiteJS bite = biteBuffer.shift(); 137 addTrim( scoper.unList(), bite, LISTU_MAX_SIZE ); 138 if( Scenes.i().scene().inScope( bite )) 139 { 140 addTrim( getList(), bite, LIST_MAX_SIZE ); 141 } 142 } 143 144 if( bN <= 1/*just emptied or was empty*/ && !isResponsePending ) 145 { 146 App.i().jsonp().requestObject( REQUEST_LOC, Ticker.this ); 147 isResponsePending = true; 148 } 149 } 150 151 152 } 153 154 155 156}