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}