001package votorola.s.gwt.stage.talk; // Copyright 2012, Michael Allan. 2013 Christian Weilbach. 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.diff.DiffLookJS; 008import votorola.a.diff.DiffLook; 009import votorola.a.web.gwt.*; 010import votorola.g.hold.*; 011import votorola.g.web.gwt.*; 012import votorola.g.web.gwt.event.*; 013import votorola.s.gwt.stage.*; 014import votorola.s.gwt.stage.light.*; 015 016 017/** A talk view implemented as an HTML image. 018 */ 019final class TalkV extends Image 020{ 021 022 /** Constructs a PollV. 023 * 024 * @param spool the spool for the release of associated holds. When unwound it 025 * releases the holds of the view and thereby disables it. 026 */ 027 TalkV( final Spool spool ) 028 { 029 addStyleName("talkV"); 030 sensor = new Sensor( spool ); 031 imager = new Imager( spool ); 032 new Stager(); 033 } 034 035 private final Imager imager; 036 037 private final static String selectedLoc = App.getServletContextLocation() + "/stage/talk/selected.png"; 038 private final static String cuedLoc = App.getServletContextLocation() + "/stage/talk/cued.png"; 039 private final static String normalLoc = App.getServletContextLocation() + "/stage/talk/normal.png"; 040 041 static 042 { 043 prefetch( selectedLoc ); 044 prefetch( cuedLoc ); 045 prefetch( normalLoc ); 046 } 047 048 // ------------------------------------------------------------------------------------ 049 050 051 /** The difference-message on which this view is modelled, or null if none is modelled. 052 * 053 * @see #setMsg(DiffMessageJS) 054 */ 055 DiffMessageJS getMsg() { return msg; } 056 057 058 private DiffMessageJS msg = null; 059 060 061 /** Sets the difference-message on which this view is modelled. 062 * 063 * @see #getMsg() 064 */ 065 void setMsg( final DiffMessageJS msgNew ) 066 { 067 if( msgNew == null ) 068 { 069 if( msg == null ) return; // very common, nothing to do 070 071 msg = null; 072 } 073 else 074 { 075 msg = msgNew; 076 } 077 078 enabler.reEnable(); 079 imager.reImage(); 080 sensor.relight(); 081 } 082 083 084 // ==================================================================================== 085 086 087 private final class Imager implements MouseOutHandler, MouseOverHandler, PropertyChangeHandler 088 { 089 090 Imager( Spool _spool ) 091 { 092 spool = _spool; 093 addMouseOutHandler( Imager.this ); // no need to unregister, registry does not outlive the handler 094 addMouseOverHandler( Imager.this ); // " 095 spool.add( new Hold() 096 { 097 final HandlerRegistration hR = GWTX.i().bus().addHandlerToSource( 098 PropertyChange.TYPE, /*source*/Stage.i(), Imager.this ); 099 public void release() { hR.removeHandler(); } 100 }); 101 reImage(); 102 } 103 104 private final Spool spool; 105 106 boolean isCued; 107 108 109 private void reImage() 110 { 111 if(isStaged()) { 112 setUrl( selectedLoc ); 113 } else if(isCued) { 114 setUrl( cuedLoc ); 115 } else { 116 setUrl( normalLoc ); 117 } 118 } 119 120 121 // - M o u s e - O u t - H a n d l e r -------------------------------------------- 122 123 124 public void onMouseOut( MouseOutEvent _e ) 125 { 126 isCued = false; 127 reImage(); 128 } 129 130 131 // - M o u s e - O v e r - H a n d l e r ------------------------------------------ 132 133 134 public void onMouseOver( MouseOverEvent _e ) 135 { 136 isCued = true; 137 reImage(); 138 } 139 140 // - P r o p e r t y - C h a n g e - H a n d l e r -------------------------------- 141 142 143 public final void onPropertyChange( final PropertyChange e ) 144 { 145 if( ( "message".equals(e.propertyName()) 146 || "difference".equals(e.propertyName()) ) 147 && !spool.isUnwinding() ) 148 reImage(); 149 } 150 151 } 152 153 154 // ==================================================================================== 155 156 157 /** A lighting sensor for a poll view. 158 */ 159 final class Sensor extends Sensor1 implements MouseOutHandler, MouseOverHandler 160 { 161 162 private Sensor( final Spool spool ) 163 { 164 Stage.i().lightBank().addSensor( Sensor.this ); 165 spool.add( new Hold() 166 { 167 public void release() { Stage.i().lightBank().removeSensor( Sensor.this ); } 168 }); 169 addMouseOutHandler( Sensor.this ); // no need to unregister, registry does not outlive the handler 170 addMouseOverHandler( Sensor.this ); // " 171 } 172 173 174 private void relight() { changed(); } 175 176 177 /** The talk view associated with this lighting sensor. 178 */ 179 TalkV view() { return TalkV.this; } 180 181 182 // - M o u s e - O u t - H a n d l e r -------------------------------------------- 183 184 185 public void onMouseOut( MouseOutEvent _e ) { 186 out(); 187 } 188 189 190 // - M o u s e - O v e r - H a n d l e r ------------------------------------------ 191 192 193 public void onMouseOver( MouseOverEvent _e ) { 194 over(); 195 } 196 197 } 198 199 200 201//// P r i v a t e /////////////////////////////////////////////////////////////////////// 202 203 204 private final Enabler enabler = new Enabler(); 205 206 207 208 private final Sensor sensor; 209 210 211 // ==================================================================================== 212 213 214 private final class Enabler 215 { 216 217 Enabler() { setVisible( false ); } 218 219 220 private boolean isEnabled; 221 222 223 void reEnable() 224 { 225 final boolean toEnable = msg != null; 226 if( toEnable ) 227 { 228 if( !isEnabled ) 229 { 230 isEnabled = true; 231 setVisible( true ); 232 } 233 } 234 else if( isEnabled ) 235 { 236 isEnabled = false; 237 setVisible( false ); 238 } 239 } 240 241 } 242 243 244 245 // ==================================================================================== 246 247 248 private final class Stager implements ClickHandler 249 { 250 251 Stager() { addClickHandler( Stager.this ); } // no need to unregister, registry does not outlive this listener 252 253 private final Stage stage = Stage.i(); 254 255 256 public void onClick( ClickEvent _e ) 257 { 258 Message newMsg = msg.message(); 259 DiffLookJS newDiff = msg.difference(); 260 if( isStaged() ) { 261 newMsg = null; 262 newDiff = null; 263 } 264 stage.setMessage( newMsg ); 265 stage.setDifference( newDiff ); 266 } 267 268 } 269 270 private boolean isStaged() { 271 if( msg == null ) { 272 return false; 273 } 274 275 final Message msgS = Stage.i().getMessage(); 276 final DiffLook diffS = Stage.i().getDifference(); 277 278 return MessageJS.EQUATOR.equals(msg.message(), msgS) 279 && DiffLookJS.EQUATOR.equals(msg.difference(), diffS); 280 } 281 282 283}