001package votorola.s.gwt.stage.poll; // Copyright 2012, 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.event.dom.client.*; 004import com.google.gwt.user.client.ui.*; 005import com.google.web.bindery.event.shared.HandlerRegistration; 006import votorola.a.count.*; 007import votorola.a.web.gwt.*; 008import votorola.g.hold.*; 009import votorola.g.web.gwt.*; 010import votorola.g.web.gwt.event.*; 011import votorola.s.gwt.stage.*; 012import votorola.s.gwt.stage.light.*; 013 014 015/** A poll view implemented as an HTML image. 016 */ 017final class PollV extends Image 018{ 019 020 021 /** Constructs a PollV. 022 * 023 * @param spool the spool for the release of associated holds. When unwound it 024 * releases the holds of the view and thereby disables it. 025 */ 026 PollV( final Spool spool ) 027 { 028 imager = new Imager( spool ); 029 sensor = new Sensor( spool ); 030 new Stager(); 031 } 032 033 034 035 static 036 { 037 final String loc = App.i().staticContextLocation(); 038 prefetch( loc, "Issue" ); 039 prefetch( src( loc, "IssueStaged" )); 040 041 prefetch( loc, "Norm" ); 042 prefetch( loc, "Law" ); 043 prefetch( loc, "Plan" ); 044 prefetch( loc, "Policy" ); 045 046 prefetch( loc, "Office" ); 047 prefetch( loc, "Assembly seat" ); 048 prefetch( loc, "Executive office" ); 049 } 050 051 052 053 // ------------------------------------------------------------------------------------ 054 055 056 /** The poll on which this view is modelled, or null if none is modelled. 057 * 058 * @see #setPoll(Poll) 059 */ 060 Poll getPoll() { return poll; } 061 062 063 private Poll poll; 064 065 066 /** Sets the poll on which this view is modelled. 067 * 068 * @see #getPoll() 069 */ 070 void setPoll( final Poll pollNew ) 071 { 072 if( pollNew == null ) 073 { 074 if( poll == null ) return; // very common, nothing to do 075 076 poll = null; 077 pollNameLeft = ""; 078 pollNameRight = ""; 079 } 080 else 081 { 082 poll = pollNew; 083 final String name = poll.name(); 084 int c = name.lastIndexOf( '/' ); 085 if( c == -1 ) 086 { 087 pollNameLeft = ""; 088 pollNameRight = name; 089 } 090 else 091 { 092 ++c; 093 pollNameLeft = name.substring( 0, c ); 094 pollNameRight = name.substring( c ); 095 } 096 } 097 enabler.reEnable(); 098 imager.reImage(); 099 sensor.relight(); 100 } 101 102 103 104 /** The left portion of the poll name extending to the final slash character '/' 105 * inclusive, or the empty string if there is no slash character or no poll. 106 */ 107 String pollNameLeft() { return pollNameLeft; } 108 109 110 String pollNameLeft = ""; 111 112 113 114 /** The right portion of the poll name immediately following the left, or the empty 115 * string if there is no poll. 116 */ 117 String pollNameRight() { return pollNameRight; } 118 119 120 String pollNameRight = ""; 121 122 123 124 // ==================================================================================== 125 126 127 /** A lighting sensor for a poll view. 128 */ 129 final class Sensor extends Sensor1 implements MouseOutHandler, MouseOverHandler 130 { 131 132 private Sensor( final Spool spool ) 133 { 134 Stage.i().lightBank().addSensor( Sensor.this ); 135 spool.add( new Hold() 136 { 137 public void release() { Stage.i().lightBank().removeSensor( Sensor.this ); } 138 }); 139 addMouseOutHandler( Sensor.this ); // no need to unregister, registry does not outlive the handler 140 addMouseOverHandler( Sensor.this ); // " 141 } 142 143 144 private void relight() { changed(); } 145 146 147 /** The poll view associated with this lighting sensor. 148 */ 149 PollV view() { return PollV.this; } 150 151 152 // - M o u s e - O u t - H a n d l e r -------------------------------------------- 153 154 155 public void onMouseOut( MouseOutEvent _e ) { out(); } 156 157 158 // - M o u s e - O v e r - H a n d l e r ------------------------------------------ 159 160 161 public void onMouseOver( MouseOverEvent _e ) { over(); } 162 163 } 164 165 166 167//// P r i v a t e /////////////////////////////////////////////////////////////////////// 168 169 170 private final Enabler enabler = new Enabler(); 171 172 173 174 private final Imager imager; 175 176 177 178 private final Sensor sensor; 179 180 181 182 private static void prefetch( final String staticContextLocation, final String issueType ) 183 { 184 prefetch( src( staticContextLocation, issueType )); 185 prefetch( src( staticContextLocation, issueType + "Stub" )); 186 } 187 188 189 190 private static String src( final String staticContextLocation, String issueType ) 191 { 192 issueType = issueType.replace( ' ', '_' ); 193 return staticContextLocation + "/stage/poll/i" + issueType + ".png"; 194 } 195 196 197 198 // ==================================================================================== 199 200 201 private final class Enabler 202 { 203 204 Enabler() { setVisible( false ); } 205 206 207 private boolean isEnabled; 208 209 210 void reEnable() 211 { 212 final boolean toEnable = poll != null; 213 if( toEnable ) 214 { 215 if( !isEnabled ) 216 { 217 isEnabled = true; 218 setVisible( true ); 219 } 220 } 221 else if( isEnabled ) 222 { 223 isEnabled = false; 224 setVisible( false ); 225 } 226 } 227 228 } 229 230 231 232 // ==================================================================================== 233 234 235 private final class Imager implements MouseOutHandler, MouseOverHandler, PropertyChangeHandler 236 { 237 238 Imager( Spool _spool ) 239 { 240 spool = _spool; 241 addMouseOutHandler( Imager.this ); // no need to unregister, registry does not outlive the handler 242 addMouseOverHandler( Imager.this ); // " 243 spool.add( new Hold() 244 { 245 final HandlerRegistration hR = GWTX.i().bus().addHandlerToSource( 246 PropertyChange.TYPE, /*source*/Stage.i(), Imager.this ); 247 public void release() { hR.removeHandler(); } 248 }); 249 reImage(); 250 } 251 252 253 boolean isCued; 254 255 256 private void reImage() 257 { 258 if( poll == null ) return; 259 260 final String issueType = poll.issueType(); 261 final String suffix; 262 if( issueType.equals( "Issue" )) 263 { 264 if( poll.name().equals(Stage.i().getPollName()) ) suffix = "Staged"; // extra bright 265 else if( isCued ) suffix = ""; 266 else suffix = "Stub"; 267 } 268 else 269 { 270 if( isCued || poll.name().equals(Stage.i().getPollName()) ) suffix = ""; 271 else suffix = "Stub"; 272 } 273 setUrl( src( App.i().staticContextLocation(), issueType + suffix )); 274 } 275 276 277 private final Spool spool; 278 279 280 // - M o u s e - O u t - H a n d l e r -------------------------------------------- 281 282 283 public void onMouseOut( MouseOutEvent _e ) 284 { 285 isCued = false; 286 reImage(); 287 } 288 289 290 // - M o u s e - O v e r - H a n d l e r ------------------------------------------ 291 292 293 public void onMouseOver( MouseOverEvent _e ) 294 { 295 isCued = true; 296 reImage(); 297 } 298 299 300 // - P r o p e r t y - C h a n g e - H a n d l e r -------------------------------- 301 302 303 public final void onPropertyChange( final PropertyChange e ) 304 { 305 if( "pollName".equals(e.propertyName()) && !spool.isUnwinding() ) reImage(); 306 } 307 308 } 309 310 311 312 // ==================================================================================== 313 314 315 private final class Stager implements ClickHandler 316 { 317 318 Stager() { addClickHandler( Stager.this ); } // no need to unregister, registry does not outlive this listener 319 320 321 public void onClick( ClickEvent _e ) 322 { 323 if( poll == null ) return; // though likely impossible 324 325 final Stage stage = Stage.i(); 326 final String nameS = stage.getPollName(); 327 String name = poll.name(); 328 if( name.equals( nameS )) name = null; // unstage 329 stage.setPollName( name ); 330 } 331 332 } 333 334 335}