001package votorola.s.gwt.scene.dum; // Copyright 2010, 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.web.bindery.event.shared.HandlerRegistration;
004import com.google.gwt.user.client.ui.*;
005import com.google.gwt.view.client.SelectionChangeEvent;
006import java.util.Arrays;
007import votorola.a.web.gwt.*;
008import votorola.s.gwt.scene.*;
009import votorola.s.gwt.scene.feed.*;
010import votorola.s.gwt.stage.poll.*;
011import votorola.g.hold.*;
012import votorola.g.web.gwt.*;
013
014
015/** A view of a dummy scene rendered as a cubic grid collapsed to a planar grid.  Thus only
016  * the lateral x and y positions are visible, as though the point of view was along the
017  * z-axis (e.g. top down) where depth is imperceptible.
018  *
019  *     @see <a href='http://reluk.ca/y/vw/xf/#c=DDum'>Live example of a DummySceneV
020  *       (right)</a>
021  */
022public final class DummySceneV extends Grid
023{
024
025
026    /** Constructs a DummySceneV.
027      */
028    public DummySceneV( DummyScene _scene )
029    {
030        super( SIZE, SIZE );
031        scene = _scene;
032        addStyleName( "dum-DummySceneV" );
033        addStyleName( "plain" );
034    }
035
036
037
038   // - W i d g e t ----------------------------------------------------------------------
039
040
041    protected @Override void onLoad()
042    {
043        spool = new Spool1();
044        new Scoper();
045        new Spotlighter();
046
047        super.onLoad();
048    }
049
050
051
052    protected @Override void onUnload()
053    {
054        super.onUnload();
055
056        spool.unwind();
057        spool = null; // single use
058    }
059
060
061
062//// P r i v a t e ///////////////////////////////////////////////////////////////////////
063
064
065    /** @param ii the array in which to store row and column indeces, in that order.
066      * @return the same ii array, or a newly constructed one if it was null.
067      */
068    private static int[] calculateCellIndeces( final DummyScene.MappedPoll poll, int[] ii )
069    {
070        if( ii == null ) ii = new int[2];
071
072        final float x = poll.x();
073        final float y = 1 - poll.y(); // reflected, so origin at bottom
074        ii[0] = (int)(y * SIZE); // row
075        ii[1] = (int)(x * SIZE); // col
076        return ii;
077    }
078
079
080    private final DummyScene scene;
081
082
083
084    private static final int SIZE = 40; // the larger, the slower to layout
085
086
087
088    private Spool spool;
089
090
091
092   // ====================================================================================
093
094
095    private final class Scoper implements ScopeChangeHandler
096    {
097
098        Scoper()
099        {
100            spool.add( new Hold()
101            {
102                final HandlerRegistration hR = scene.scoping().addHandler( Scoper.this );
103                public void release() { hR.removeHandler(); }
104            });
105            rescope(); // init state
106        }
107
108
109        public void onScopeChange( final ScopeChangeEvent e ) { rescope(); }
110
111
112        private void rescope()
113        {
114            final HTMLTable.CellFormatter f = getCellFormatter();
115            int row = 0;
116            int col;
117            for( ; row < SIZE; ++row )
118            {
119                col = 0;
120                for( ; col < SIZE; ++col )
121                {
122                    f.removeStyleName( row, col, "multi" );
123                    f.removeStyleName( row, col, "p" );
124                }
125            }
126
127            final int[] ii = new int[2];
128            for( final DummyScene.MappedPoll poll: scene.polls().values() )
129            {
130                if( !scene.inScope( poll )) continue;
131
132                calculateCellIndeces( poll, ii );
133                row = ii[0];
134                col = ii[1];
135                final String allNames = f.getStyleName( row, col );
136                if( ElementX.hasClassName( allNames, "p" )) f.addStyleName( row, col, "multi" );
137                else f.addStyleName( row, col, "p" );
138            }
139        }
140    }
141
142
143
144   // ====================================================================================
145
146
147    private final class Spotlighter implements ScopeChangeHandler, SelectionChangeEvent.Handler
148    {
149
150        Spotlighter()
151        {
152            spool.add( new Hold()
153            {
154                final HandlerRegistration hR = scene.scoping().addHandler( Spotlighter.this );
155                public void release() { hR.removeHandler(); }
156            });
157            spool.add( new Hold()
158            {
159                final HandlerRegistration hR =
160                  Scenes.i().biteSelection().addSelectionChangeHandler( Spotlighter.this );
161                public void release() { hR.removeHandler(); }
162            });
163            respotlight(); // init state
164        }
165
166
167        private int[] iiLast;
168
169
170        public void onScopeChange( final ScopeChangeEvent e ) { respotlight(); }
171
172
173        public void onSelectionChange( SelectionChangeEvent e ) { respotlight(); }
174
175
176        private void respotlight()
177        {
178            int[] ii = null; // thus far
179            final BiteJS bite = Scenes.i().biteSelection().getSelectedObject();
180            if( bite != null )
181            {
182                final PollJS poll = bite.poll();
183                if( poll != null )
184                {
185                    final String pollName = poll.name();
186                    if( pollName != null )
187                    {
188                        final DummyScene.MappedPoll pollM = scene.polls().get( pollName );
189                        if( pollM != null && scene.inScope( pollM ))
190                        {
191                            ii = calculateCellIndeces( pollM, ii );
192                        }
193                    }
194                }
195            }
196
197            if( Arrays.equals( ii, iiLast )) return;
198
199            final HTMLTable.CellFormatter f = getCellFormatter();
200            if( iiLast != null ) f.removeStyleName( iiLast[0], iiLast[1], "spotlighted"  );
201
202            iiLast = ii;
203            if( ii != null ) f.addStyleName( ii[0], ii[1], "spotlighted"  );
204        }
205    }
206
207
208}