001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.gwt.client.ui; 029 030import org.opencms.gwt.client.I_CmsDescendantResizeHandler; 031import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle; 032import org.opencms.gwt.client.util.CmsDebugLog; 033import org.opencms.gwt.client.util.CmsFocusedScrollingHandler; 034 035import com.google.gwt.dom.client.Element; 036import com.google.gwt.dom.client.Style.Unit; 037import com.google.gwt.event.dom.client.MouseDownEvent; 038import com.google.gwt.event.dom.client.MouseDownHandler; 039import com.google.gwt.event.dom.client.ScrollEvent; 040import com.google.gwt.event.dom.client.ScrollHandler; 041import com.google.gwt.event.logical.shared.HasResizeHandlers; 042import com.google.gwt.event.logical.shared.ResizeEvent; 043import com.google.gwt.event.logical.shared.ResizeHandler; 044import com.google.gwt.event.shared.HandlerRegistration; 045import com.google.gwt.user.client.DOM; 046import com.google.gwt.user.client.Event; 047import com.google.gwt.user.client.Event.NativePreviewEvent; 048import com.google.gwt.user.client.Event.NativePreviewHandler; 049import com.google.gwt.user.client.ui.ScrollPanel; 050import com.google.gwt.user.client.ui.Widget; 051 052/** 053 * Scroll panel implementation allowing focused scrolling.<p> 054 */ 055public class CmsScrollPanel extends ScrollPanel implements HasResizeHandlers, I_CmsDescendantResizeHandler { 056 057 /**Inner class for the resize button. */ 058 protected class ResizeButton extends CmsPushButton { 059 060 /** 061 * Default constructor.<p> 062 */ 063 public ResizeButton() { 064 065 super(); 066 setStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().resizeButton()); 067 068 } 069 070 /** 071 * @see com.google.gwt.user.client.ui.CustomButton#onAttach() 072 */ 073 @Override 074 protected void onAttach() { 075 076 super.onAttach(); 077 } 078 079 /** 080 * @see com.google.gwt.user.client.ui.CustomButton#onDetach() 081 */ 082 @Override 083 protected void onDetach() { 084 085 super.onDetach(); 086 } 087 } 088 089 /** 090 * Drag and drop event preview handler.<p> 091 * 092 * To be used while dragging.<p> 093 */ 094 protected class ResizeEventPreviewHandler implements NativePreviewHandler { 095 096 /** 097 * @see com.google.gwt.user.client.Event.NativePreviewHandler#onPreviewNativeEvent(com.google.gwt.user.client.Event.NativePreviewEvent) 098 */ 099 public void onPreviewNativeEvent(NativePreviewEvent event) { 100 101 Event nativeEvent = Event.as(event.getNativeEvent()); 102 switch (DOM.eventGetType(nativeEvent)) { 103 case Event.ONMOUSEMOVE: 104 // dragging 105 setNewHeight(nativeEvent); 106 onResizeDescendant(); 107 event.cancel(); 108 break; 109 case Event.ONMOUSEUP: 110 m_previewHandlerRegistration.removeHandler(); 111 m_previewHandlerRegistration = null; 112 break; 113 case Event.ONKEYDOWN: 114 break; 115 case Event.ONMOUSEWHEEL: 116 //onMouseWheelScroll(nativeEvent); 117 break; 118 default: 119 // do nothing 120 } 121 122 nativeEvent.preventDefault(); 123 nativeEvent.stopPropagation(); 124 125 } 126 127 } 128 129 /** The preview handler registration. */ 130 protected HandlerRegistration m_previewHandlerRegistration; 131 132 /** The start Y coordination. */ 133 private int m_clientY; 134 135 /** The default height. */ 136 private double m_defaultHeight = -1; 137 138 /** The prevent outer scrolling handler. */ 139 private CmsFocusedScrollingHandler m_focusedScrollingHandler; 140 141 /** The scroll handler registration. */ 142 private HandlerRegistration m_handlerRegistration; 143 144 /** Saves if the scrolling panel has the resize button. */ 145 private boolean m_isResize; 146 147 /** The start height. */ 148 private double m_oldheight; 149 150 /** The button to resize the scrolling panel. */ 151 private ResizeButton m_resize; 152 153 /** 154 * Constructor.<p> 155 * 156 * @see com.google.gwt.user.client.ui.ScrollPanel#ScrollPanel() 157 */ 158 public CmsScrollPanel() { 159 160 m_resize = new ResizeButton(); 161 162 } 163 164 /** 165 * Constructor to be used by {@link org.opencms.gwt.client.ui.CmsScrollPanelImpl}.<p> 166 * 167 * @param root the root element of the widget 168 * @param scrollabel the scrollable element of the widget 169 * @param container the container element of the widget 170 */ 171 protected CmsScrollPanel(Element root, Element scrollabel, Element container) { 172 173 super(root, scrollabel, container); 174 m_resize = new ResizeButton(); 175 176 } 177 178 /** 179 * @see com.google.gwt.event.logical.shared.HasResizeHandlers#addResizeHandler(com.google.gwt.event.logical.shared.ResizeHandler) 180 */ 181 public HandlerRegistration addResizeHandler(ResizeHandler handler) { 182 183 return addHandler(handler, ResizeEvent.getType()); 184 } 185 186 /** 187 * Enables or disables the focused scrolling feature.<p> 188 * Focused scrolling is enabled by default.<p> 189 * 190 * @param enable <code>true</code> to enable the focused scrolling feature 191 */ 192 public void enableFocusedScrolling(boolean enable) { 193 194 if (enable) { 195 if (m_handlerRegistration == null) { 196 m_handlerRegistration = addScrollHandler(new ScrollHandler() { 197 198 public void onScroll(ScrollEvent event) { 199 200 ensureFocusedScrolling(); 201 } 202 }); 203 } 204 } else if (m_handlerRegistration != null) { 205 m_handlerRegistration.removeHandler(); 206 m_handlerRegistration = null; 207 } 208 } 209 210 /** 211 * @see org.opencms.gwt.client.I_CmsDescendantResizeHandler#onResizeDescendant() 212 */ 213 public void onResizeDescendant() { 214 215 // not needed 216 } 217 218 /** 219 * @see com.google.gwt.user.client.ui.SimplePanel#remove(com.google.gwt.user.client.ui.Widget) 220 */ 221 @Override 222 public boolean remove(Widget w) { 223 224 if (w == m_resize) { 225 try { 226 orphan(m_resize); 227 } finally { 228 getElement().removeChild(m_resize.getElement()); 229 } 230 return true; 231 } else { 232 return super.remove(w); 233 } 234 } 235 236 /** 237 * Sets the default height of the scrolling panel. 238 * 239 * @param height the default height 240 */ 241 public void setDefaultHeight(double height) { 242 243 m_defaultHeight = height; 244 } 245 246 /** 247 * Sets the scrollpanel resizeable.<p> 248 * 249 * @param resize true if the scrollpanel should be resizeable. 250 */ 251 public void setResizable(boolean resize) { 252 253 if (resize != m_isResize) { 254 if (resize) { 255 getElement().appendChild(m_resize.getElement()); 256 adopt(m_resize); 257 m_resize.addMouseDownHandler(new MouseDownHandler() { 258 259 public void onMouseDown(MouseDownEvent event) { 260 261 setStartParameters(event); 262 CmsDebugLog.getInstance().printLine("Registering preview handler"); 263 if (m_previewHandlerRegistration != null) { 264 m_previewHandlerRegistration.removeHandler(); 265 } 266 m_previewHandlerRegistration = Event.addNativePreviewHandler(new ResizeEventPreviewHandler()); 267 } 268 }); 269 } else { 270 m_resize.removeFromParent(); 271 } 272 m_isResize = resize; 273 } 274 } 275 276 /** 277 * Ensures the focused scrolling event preview handler is registered.<p> 278 */ 279 protected void ensureFocusedScrolling() { 280 281 if (m_focusedScrollingHandler == null) { 282 m_focusedScrollingHandler = CmsFocusedScrollingHandler.installFocusedScrollingHandler(this); 283 } else if (!m_focusedScrollingHandler.isRegistered()) { 284 m_focusedScrollingHandler.register(); 285 } 286 } 287 288 /** 289 * @see com.google.gwt.user.client.ui.ScrollPanel#onAttach() 290 */ 291 @Override 292 protected void onAttach() { 293 294 super.onAttach(); 295 if (m_isResize) { 296 m_resize.onAttach(); 297 } 298 299 } 300 301 /** 302 * @see com.google.gwt.user.client.ui.ScrollPanel#onDetach() 303 */ 304 @Override 305 protected void onDetach() { 306 307 super.onDetach(); 308 if (m_isResize) { 309 m_resize.onDetach(); 310 } 311 } 312 313 /** 314 * Executed on mouse move while dragging.<p> 315 * 316 * @param event the event 317 */ 318 protected void setNewHeight(Event event) { 319 320 double newheight = m_oldheight + (event.getClientY() - m_clientY); 321 if (m_defaultHeight != -1) { 322 if (newheight < m_defaultHeight) { 323 newheight = m_defaultHeight; 324 } 325 } 326 ResizeEvent.fire(this, getOffsetWidth(), (int)newheight); 327 getElement().getStyle().setHeight(newheight, Unit.PX); 328 } 329 330 /** 331 * Sets the start parameters of the resize event.<p> 332 * 333 * @param event the mouse event 334 */ 335 protected void setStartParameters(MouseDownEvent event) { 336 337 m_oldheight = Double.parseDouble(getElement().getStyle().getHeight().replace("px", "")); 338 m_clientY = event.getClientY(); 339 } 340 341}