001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.acacia.client.widgets; 029 030import org.opencms.acacia.client.css.I_CmsLayoutBundle; 031 032import com.google.gwt.core.client.JavaScriptObject; 033import com.google.gwt.core.client.Scheduler; 034import com.google.gwt.core.client.Scheduler.ScheduledCommand; 035import com.google.gwt.dom.client.Element; 036import com.google.gwt.dom.client.Style.Position; 037import com.google.gwt.event.dom.client.BlurEvent; 038import com.google.gwt.event.dom.client.BlurHandler; 039import com.google.gwt.event.dom.client.ChangeEvent; 040import com.google.gwt.event.dom.client.ChangeHandler; 041import com.google.gwt.event.dom.client.KeyCodes; 042import com.google.gwt.event.dom.client.KeyDownEvent; 043import com.google.gwt.event.dom.client.KeyDownHandler; 044import com.google.gwt.event.logical.shared.ValueChangeEvent; 045import com.google.gwt.event.logical.shared.ValueChangeHandler; 046import com.google.gwt.event.shared.HandlerRegistration; 047import com.google.gwt.user.client.DOM; 048import com.google.gwt.user.client.ui.RootPanel; 049import com.google.gwt.user.client.ui.TextArea; 050 051/** 052 * The string edit widget.<p> 053 */ 054public class CmsStringWidget extends A_CmsEditWidget { 055 056 /** The value to know if the user want to paste something. */ 057 protected boolean m_paste; 058 059 /** Indicating if the widget is active. */ 060 private boolean m_active; 061 062 /** The value changed handler initialized flag. */ 063 private boolean m_valueChangeHandlerInitialized; 064 065 /** 066 * Constructor.<p> 067 */ 068 public CmsStringWidget() { 069 070 this(DOM.createDiv()); 071 } 072 073 /** 074 * Constructor wrapping a specific DOM element.<p> 075 * 076 * @param element the element to wrap 077 */ 078 public CmsStringWidget(Element element) { 079 080 super(element); 081 init(); 082 } 083 084 /** 085 * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler) 086 */ 087 @Override 088 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) { 089 090 // Initialization code 091 if (!m_valueChangeHandlerInitialized) { 092 m_valueChangeHandlerInitialized = true; 093 addDomHandler(new KeyDownHandler() { 094 095 /** The text selection range. */ 096 protected JavaScriptObject m_range; 097 098 /** The Element of this widget. */ 099 protected com.google.gwt.dom.client.Element m_element; 100 101 /** Helper text area to store the text that should be pasted. */ 102 protected TextArea m_helpfield; 103 104 public void onKeyDown(KeyDownEvent event) { 105 106 // check if something was pasted to the field 107 if (event.isShiftKeyDown() || event.isControlKeyDown()) { 108 int charCode = event.getNativeEvent().getCharCode(); 109 if ((charCode == 'v') || (charCode == 45)) { 110 m_helpfield = new TextArea(); 111 m_helpfield.getElement().getStyle().setPosition(Position.FIXED); 112 m_range = getSelection(); 113 m_element = event.getRelativeElement(); 114 m_element.setAttribute("contentEditable", "false"); 115 RootPanel.get().add(m_helpfield); 116 m_helpfield.setFocus(true); 117 } 118 } 119 // prevent adding line breaks 120 if (KeyCodes.KEY_ENTER == event.getNativeEvent().getKeyCode()) { 121 event.preventDefault(); 122 event.stopPropagation(); 123 } 124 125 // schedule the change event, so the key press can take effect 126 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 127 128 public void execute() { 129 130 if (m_range != null) { 131 String pasteValue = m_helpfield.getText(); 132 m_helpfield.removeFromParent(); 133 m_element.setAttribute("contentEditable", "true"); 134 setFocus(true); 135 setSelection(m_range, pasteValue); 136 m_range = null; 137 138 } 139 fireValueChange(false); 140 } 141 }); 142 } 143 144 }, KeyDownEvent.getType()); 145 146 addDomHandler(new ChangeHandler() { 147 148 public void onChange(ChangeEvent event) { 149 150 fireValueChange(false); 151 152 } 153 }, ChangeEvent.getType()); 154 addDomHandler(new BlurHandler() { 155 156 public void onBlur(BlurEvent event) { 157 158 fireValueChange(false); 159 } 160 }, BlurEvent.getType()); 161 } 162 return addHandler(handler, ValueChangeEvent.getType()); 163 } 164 165 /** 166 * @see com.google.gwt.user.client.ui.HasValue#getValue() 167 */ 168 @Override 169 public String getValue() { 170 171 return getElement().getInnerText(); 172 } 173 174 /** 175 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#isActive() 176 */ 177 public boolean isActive() { 178 179 return m_active; 180 } 181 182 /** 183 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setActive(boolean) 184 */ 185 public void setActive(boolean active) { 186 187 if (m_active == active) { 188 return; 189 } 190 m_active = active; 191 if (m_active) { 192 getElement().setAttribute("contentEditable", "true"); 193 getElement().removeClassName(I_CmsLayoutBundle.INSTANCE.form().inActive()); 194 getElement().focus(); 195 fireValueChange(true); 196 } else { 197 getElement().setAttribute("contentEditable", "false"); 198 getElement().addClassName(I_CmsLayoutBundle.INSTANCE.form().inActive()); 199 } 200 } 201 202 /** 203 * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setName(java.lang.String) 204 */ 205 public void setName(String name) { 206 207 // nothing to do 208 209 } 210 211 /** 212 * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object) 213 */ 214 public void setValue(String value) { 215 216 setValue(value, true); 217 } 218 219 /** 220 * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object, boolean) 221 */ 222 public void setValue(String value, boolean fireEvents) { 223 224 getElement().setInnerText(value); 225 if (fireEvents) { 226 fireValueChange(false); 227 } 228 } 229 230 /** 231 * Returns the actual range of the courser.<p> 232 * 233 * @return the actual range of the courser 234 */ 235 protected native JavaScriptObject getSelection() 236 /*-{ 237 var range, sel; 238 sel = $wnd.rangy.getSelection(); 239 range = null; 240 if (sel.rangeCount > 0) { 241 range = sel.getRangeAt(0); 242 } else { 243 range = rangy.createRange(); 244 } 245 return range; 246 }-*/; 247 248 /** 249 * Includes the new text into the text block.<p> 250 * @param range the range where the text should be included 251 * @param text the text that should be included 252 */ 253 protected native void setSelection(JavaScriptObject range, String text) 254 /*-{ 255 var sel; 256 range.deleteContents(); 257 var textNode = $wnd.document.createTextNode(text) 258 range.insertNode(textNode); 259 sel = $wnd.rangy.getSelection(); 260 range.setStart(textNode, textNode.length); 261 range.setEnd(textNode, textNode.length); 262 sel.removeAllRanges(); 263 sel.setSingleRange(range); 264 }-*/; 265 266 /** 267 * Initializes the widget.<p> 268 */ 269 private void init() { 270 271 getElement().setAttribute("contentEditable", "true"); 272 addStyleName(I_CmsLayoutBundle.INSTANCE.form().input()); 273 m_active = true; 274 } 275}