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 }