001    /*
002     * Copyright 2007 Mat Gessel <mat.gessel@gmail.com>
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package asquare.gwt.tk.client.ui;
017    
018    import java.util.List;
019    
020    import asquare.gwt.tk.client.ui.behavior.Controller;
021    import asquare.gwt.tk.client.ui.behavior.ControllerSupport;
022    import asquare.gwt.tk.client.ui.behavior.ControllerSupportDelegate;
023    import asquare.gwt.tk.client.util.DomUtil;
024    
025    import com.google.gwt.core.client.GWT;
026    import com.google.gwt.user.client.DOM;
027    import com.google.gwt.user.client.Event;
028    import com.google.gwt.user.client.ui.PopupPanel;
029    import com.google.gwt.user.client.ui.Widget;
030    
031    /**
032     * Adds controller support to popup panels. 
033     */
034    public class CPopupPanel extends PopupPanel implements ControllerSupport
035    {
036            private final ControllerSupportDelegate m_controllerSupport = new ControllerSupportDelegate(this);
037            private final EventPreviewDelegate m_eventPreview = (EventPreviewDelegate) GWT.create(EventPreviewDelegate.class);
038            
039            /**
040             * Creates a popup panel with auto hide disabled. 
041             */
042            public CPopupPanel()
043            {
044                    this(false);
045            }
046            
047            /**
048             * Creates a popup panel. 
049             * @param autoHide true to hide the popup when the user clicks outside of it
050             */
051            public CPopupPanel(boolean autoHide)
052            {
053                    super(autoHide);
054                    setControllers(createControllers());
055            }
056            
057            /**
058             * A factory method which gives a subclass the opportunity to override default 
059             * controller creation.
060             * 
061             * @return a List with 0 or more controllers, or <code>null</code>
062             */
063            protected List createControllers()
064            {
065                    return null;
066            }
067            
068            /*
069             * (non-Javadoc)
070             * @see asquare.gwt.tk.client.ui.behavior.ControllerSupport#addController(asquare.gwt.tk.client.ui.behavior.Controller)
071             */
072            public Widget addController(Controller controller)
073            {
074                    return m_controllerSupport.addController(controller);
075            }
076            
077            /*
078             * (non-Javadoc)
079             * @see asquare.gwt.tk.client.ui.behavior.ControllerSupport#getController(java.lang.Class)
080             */
081            public Controller getController(Class id)
082            {
083                    return m_controllerSupport.getController(id);
084            }
085            
086            /*
087             * (non-Javadoc)
088             * @see asquare.gwt.tk.client.ui.behavior.ControllerSupport#removeController(asquare.gwt.tk.client.ui.behavior.Controller)
089             */
090            public Widget removeController(Controller controller)
091            {
092                    return m_controllerSupport.removeController(controller);
093            }
094            
095            /*
096             * (non-Javadoc)
097             * @see asquare.gwt.tk.client.ui.behavior.ControllerSupport#setControllers(java.util.List)
098             */
099            public void setControllers(List controllers)
100            {
101                    m_controllerSupport.setControllers(controllers);
102            }
103            
104            /*
105             * (non-Javadoc)
106             * @see com.google.gwt.user.client.ui.UIObject#sinkEvents(int)
107             */
108            public void sinkEvents(int eventBits)
109            {
110                    m_controllerSupport.sinkEvents(eventBits);
111            }
112            
113            /*
114             * (non-Javadoc)
115             * @see com.google.gwt.user.client.ui.UIObject#unsinkEvents(int)
116             */
117            public void unsinkEvents(int eventBits)
118            {
119                    m_controllerSupport.unsinkEvents(eventBits);
120            }
121            
122            /*
123             * (non-Javadoc)
124             * @see com.google.gwt.user.client.ui.Panel#onAttach()
125             */
126            protected void onAttach()
127            {
128                    if (isAttached())
129                            return;
130                    
131                    m_controllerSupport.onAttach();
132                    super.onAttach();
133            }
134            
135            /*
136             * (non-Javadoc)
137             * @see com.google.gwt.user.client.ui.Panel#onDetach()
138             */
139            protected void onDetach()
140            {
141                    if(! isAttached())
142                            return;
143                    
144                    super.onDetach();
145                    m_controllerSupport.onDetach();
146            }
147            
148            /*
149             * (non-Javadoc)
150             * @see com.google.gwt.user.client.ui.PopupPanel#onEventPreview(com.google.gwt.user.client.Event)
151             */
152            public boolean onEventPreview(Event event)
153            {
154                    return m_eventPreview.onEventPreview(event, super.onEventPreview(event));
155            }
156            
157            /*
158             * (non-Javadoc)
159             * @see com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user.client.Event)
160             */
161            public void onBrowserEvent(Event event)
162            {
163                    m_controllerSupport.onBrowserEvent(event);
164            }
165            
166            /**
167             * This class basically exists to deal with the Firefox/scroll bug. 
168             */
169            static class EventPreviewDelegate
170            {
171                    public boolean onEventPreview(Event event, boolean superResult)
172                    {
173                            return superResult;
174                    }
175            }
176            
177            static class EventPreviewDelegateFF extends EventPreviewDelegate
178            {
179                    public boolean onEventPreview(Event event, boolean superResult)
180                    {
181                            if (DomUtil.isWin() && (DOM.eventGetType(event) & Event.MOUSEEVENTS) != 0)
182                            {
183                                    /*
184                                     * The client area is bounded by the scroll bars. If a mouse
185                                     * event is outside the client area it must be targeted to a
186                                     * scroll bar. Override default behavior to allow these events.
187                                     */
188                                    int clientX = DOM.eventGetClientX(event);
189                                    int clientY = DOM.eventGetClientY(event);
190                                    if (clientX > DomUtil.getViewportWidth() || clientY > DomUtil.getViewportHeight())
191                                    {
192                                            return true;
193                                    }
194                            }
195                            return super.onEventPreview(event, superResult);
196                    }
197            }
198    }