[IDEMPIERE-184] Zk6: Port KeyListener component to Zk6

This commit is contained in:
Elaine Tan 2012-04-17 16:37:42 +08:00
parent d9ed7e2aaa
commit 76572f5bd6
10 changed files with 399 additions and 65 deletions

View File

@ -22,9 +22,20 @@ Copyright (C) 2007 Ashley G Ramdass (ADempiere WebUI).
<version-uid>3.5</version-uid> <version-uid>3.5</version-uid>
</version> </version>
<component>
<component-name>keylistener</component-name>
<component-class>org.zkforge.keylistener.Keylistener</component-class>
<widget-class>zkforge.KeyListener</widget-class>
<mold>
<mold-name>default</mold-name>
<mold-uri>mold/key-listener.js</mold-uri>
</mold>
</component>
<javascript src="/js/calc.js" charset="UTF-8"/> <javascript src="/js/calc.js" charset="UTF-8"/>
<javascript src="/js/layout.js" charset="UTF-8"/> <javascript src="/js/layout.js" charset="UTF-8"/>
<javascript src="/js/report.js" charset="UTF-8"/> <javascript src="/js/report.js" charset="UTF-8"/>
<javascript src="/js/persist-min.js" charset="UTF-8"/> <javascript src="/js/persist-min.js" charset="UTF-8"/>
<javascript src="/js/token.js" charset="UTF-8"/> <javascript src="/js/token.js" charset="UTF-8"/>
</language> </language>

View File

@ -40,7 +40,7 @@ import org.compiere.model.MQuery;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Msg; import org.compiere.util.Msg;
//import org.zkforge.keylistener.Keylistener; import org.zkforge.keylistener.Keylistener;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlBasedComponent; import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Event;
@ -52,8 +52,8 @@ import org.zkoss.zul.Center;
import org.zkoss.zul.East; import org.zkoss.zul.East;
import org.zkoss.zul.North; import org.zkoss.zul.North;
import org.zkoss.zul.South; import org.zkoss.zul.South;
import org.zkoss.zul.West;
import org.zkoss.zul.Tab; import org.zkoss.zul.Tab;
import org.zkoss.zul.West;
/** /**
* *
@ -78,7 +78,7 @@ public class ADWindowPanel extends AbstractADWindowPanel
private East east; private East east;
// private Keylistener keyListener; private Keylistener keyListener;
public ADWindowPanel(Properties ctx, int windowNo) public ADWindowPanel(Properties ctx, int windowNo)
{ {
@ -186,19 +186,14 @@ public class ADWindowPanel extends AbstractADWindowPanel
} }
if (!isEmbedded()) { if (!isEmbedded()) {
// if (keyListener != null) if (keyListener != null)
// keyListener.detach(); keyListener.detach();
// keyListener = new Keylistener(); keyListener = new Keylistener();
// statusBar.appendChild(keyListener); statusBar.appendChild(keyListener);
// keyListener.setCtrlKeys("#f1#f2#f3#f4#f5#f6#f7#f8#f9#f10#f11#f12^f^i^n^s^d@#left@#right@#up@#down@#pgup@#pgdn@p^p@z@x#enter"); keyListener.setCtrlKeys("#f1#f2#f3#f4#f5#f6#f7#f8#f9#f10#f11#f12^f^i^n^s^d@#left@#right@#up@#down@#pgup@#pgdn@p^p@z@x#enter");
// keyListener.addEventListener(Events.ON_CTRL_KEY, toolbar); keyListener.addEventListener(Events.ON_CTRL_KEY, toolbar);
// keyListener.addEventListener(Events.ON_OK, this); keyListener.addEventListener(Events.ON_CTRL_KEY, this);
// keyListener.setAutoBlur(false); keyListener.setAutoBlur(false);
//FIXME: only work when focus is at input element
contentArea.setCtrlKeys("#f1#f2#f3#f4#f5#f6#f7#f8#f9#f10#f11#f12^f^i^n^s^d@#left@#right@#up@#down@#pgup@#pgdn@p^p@z@x");
contentArea.addEventListener(Events.ON_CTRL_KEY, toolbar);
contentArea.addEventListener(Events.ON_OK, this);
} }
layout.setAttribute(ITabOnSelectHandler.ATTRIBUTE_KEY, new ITabOnSelectHandler() { layout.setAttribute(ITabOnSelectHandler.ATTRIBUTE_KEY, new ITabOnSelectHandler() {
@ -249,7 +244,6 @@ public class ADWindowPanel extends AbstractADWindowPanel
* @see EventListener#onEvent(Event) * @see EventListener#onEvent(Event)
*/ */
public void onEvent(Event event) { public void onEvent(Event event) {
//FIXME: not working for zk6
if (Events.ON_CTRL_KEY.equals(event.getName())) { if (Events.ON_CTRL_KEY.equals(event.getName())) {
KeyEvent keyEvent = (KeyEvent) event; KeyEvent keyEvent = (KeyEvent) event;
//enter == 13 //enter == 13
@ -261,13 +255,6 @@ public class ADWindowPanel extends AbstractADWindowPanel
} }
} }
} }
} else if (Events.ON_OK.equals(event.getName())) {
IADTabpanel panel = adTab.getSelectedTabpanel();
if (panel != null) {
if (panel.onEnterKey()) {
event.stopPropagation();
}
}
} else { } else {
super.onEvent(event); super.onEvent(event);
} }

View File

@ -0,0 +1,195 @@
package org.zkforge.keylistener;
import java.io.IOException;
import org.zkoss.lang.Objects;
import org.zkoss.mesg.MCommon;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.sys.ContentRenderer;
/**
* Keylistener component. See Window for specification of ctrlKey format.
*
* @author boha
*
*/
public class Keylistener extends HtmlBasedComponent {
private String _ctrlKeys;
private String _jsCtrlKeys;
private boolean _autoBlur = true;
/**
* Auto generated serial UID
*/
private static final long serialVersionUID = 4611014738053691844L;
/**
* Is auto blur active
*
* @return the autoBlur
*/
public boolean isAutoBlur() {
return _autoBlur;
}
/**
* Set auto blur. If auto blur is set focus will be moved to keylistener
* component before onCtrlKey event is triggered. This is used to force any
* pending onChange events to be triggered first.
*
* @param autoBlur
* the autoBlur to set
*/
public void setAutoBlur(boolean autoBlur) {
this._autoBlur = autoBlur;
smartUpdate("autoblur", _autoBlur);
}
/**
* Get control keys
*
* @return the ctrlKeys
*/
public String getCtrlKeys() {
return _ctrlKeys;
}
/**
* Set control keys to listen for
*
* @param ctrlKeys
* the ctrlKeys to set
*/
public void setCtrlKeys(String ctrlKeys) {
if (ctrlKeys != null && ctrlKeys.length() == 0)
ctrlKeys = null;
if (!Objects.equals(this._ctrlKeys, ctrlKeys)) {
parseCtrlKeys(ctrlKeys);
smartUpdate("ctrlKeys", _jsCtrlKeys);
}
}
@Override
protected void renderProperties(ContentRenderer renderer)
throws IOException {
super.renderProperties(renderer);
render(renderer, "ctrlKeys", _jsCtrlKeys);
render(renderer, "autoblur", _autoBlur);
}
private void parseCtrlKeys(String keys) throws UiException {
if (keys == null || keys.length() == 0) {
_ctrlKeys = _jsCtrlKeys = null;
return;
}
final StringBuffer sbctl = new StringBuffer(), sbsft = new StringBuffer(), sbalt = new StringBuffer(), sbext = new StringBuffer();
StringBuffer sbcur = null;
for (int j = 0, len = keys.length(); j < len; ++j) {
char cc = keys.charAt(j);
switch (cc) {
case '^':
case '$':
case '@':
if (sbcur != null)
throw new WrongValueException(
"Combination of Shift, Alt and Ctrl not supported: "
+ keys);
sbcur = cc == '^' ? sbctl : cc == '@' ? sbalt : sbsft;
break;
case '#': {
int k = j + 1;
for (; k < len; ++k) {
final char c2 = (char) keys.charAt(k);
if ((c2 > 'Z' || c2 < 'A') && (c2 > 'z' || c2 < 'a')
&& (c2 > '9' || c2 < '0'))
break;
}
if (k == j + 1)
throw new WrongValueException(MCommon.UNEXPECTED_CHARACTER,
new Object[] { new Character(cc), keys });
final String s = keys.substring(j + 1, k).toLowerCase();
if ("pgup".equals(s))
cc = 'A';
else if ("pgdn".equals(s))
cc = 'B';
else if ("end".equals(s))
cc = 'C';
else if ("home".equals(s))
cc = 'D';
else if ("left".equals(s))
cc = 'E';
else if ("up".equals(s))
cc = 'F';
else if ("right".equals(s))
cc = 'G';
else if ("down".equals(s))
cc = 'H';
else if ("ins".equals(s))
cc = 'I';
else if ("del".equals(s))
cc = 'J';
else if ("enter".equals(s))
cc = 'K';
else if (s.length() > 1 && s.charAt(0) == 'f') {
final int v;
try {
v = Integer.parseInt(s.substring(1));
} catch (Throwable ex) {
throw new WrongValueException("Unknown #" + s + " in "
+ keys);
}
if (v == 0 || v > 12)
throw new WrongValueException(
"Unsupported function key: #f" + v);
cc = (char) ('O' + v); // 'P': F1, 'Q': F2... 'Z': F12
} else
throw new WrongValueException("Unknown #" + s + " in "
+ keys);
if (sbcur == null)
sbext.append(cc);
else {
sbcur.append(cc);
sbcur = null;
}
j = k - 1;
}
break;
default:
if (sbcur == null
|| ((cc > 'Z' || cc < 'A') && (cc > 'z' || cc < 'a') && (cc > '9' || cc < '0')))
throw new WrongValueException(MCommon.UNEXPECTED_CHARACTER,
new Object[] { new Character(cc), keys });
if (sbcur == sbsft)
throw new WrongValueException("$" + cc + " not supported: "
+ keys);
if (cc <= 'Z' && cc >= 'A')
cc = (char) (cc + ('a' - 'A')); // to lower case
sbcur.append(cc);
sbcur = null;
break;
}
}
_jsCtrlKeys = new StringBuffer().append('^').append(sbctl).append(';')
.append('@').append(sbalt).append(';').append('$')
.append(sbsft).append(';').append('#').append(sbext)
.append(';').toString();
_ctrlKeys = keys;
}
/* (non-Javadoc)
* @see org.zkoss.zk.ui.AbstractComponent#isChildable()
*/
public boolean isChildable() {
return false;
}
}

View File

@ -0,0 +1,11 @@
package org.zkforge.keylistener;
/**
* Version
* @author Bobo H<EFBFBD>ggstr<EFBFBD>m
*/
public class Version {
public static final String UID = "1.0.1";
}

View File

@ -0,0 +1,128 @@
/* keylistener.js
{{IS_NOTE
Purpose:
zkforge.KeyListener
Description:
Keylistener component for ZK.
}}IS_NOTE
Copyright 2007 by Easit AB. All rights reserved.
{{IS_RIGHT
This program is distributed under GPL Version 2.0 in the hope that
it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/
zk.$package('zkforge');
zkforge.KeyListener = zk.$extends(zul.Widget, {
_ctrlKeys: null,
_autoBlur: true,
getCtrlKeys: function() {
return this._ctrlKeys;
},
setCtrlKeys: function(ctrlKeys) {
if(this._ctrlKeys != ctrlKeys) {
this._ctrlKeys = ctrlKeys;
}
},
getAutoBlur: function() {
return this._autoBlur;
},
setAutoBlur: function(autoBlur) {
if(this._autoBlur != autoBlur) {
this._autoBlur = autoBlur;
}
},
bind_: function (desktop, skipper, after) {
this.$supers('bind_', arguments);
var self = this;
jq(document).ready(function () {
jq(document).keydown(function (evt) {
self.keyDown(evt);
});
});
},
keyDown: function(evt) {
if (!evt) evt = window.event;
var keycode = evt.keyCode, zkcode; //zkcode used to search z.ctkeys
switch (keycode) {
case 13: //ENTER
zkcode = 'K';
break;
case 27: //ESC
break;
case 16: //Shift
case 17: //Ctrl
case 18: //Alt
return true;
case 44: //Ins
case 45: //Del
zkcode = keycode == 44 ? 'I': 'J';
break;
default:
if (keycode >= 33 && keycode <= 40) { //PgUp, PgDn, End, Home, L, U, R, D
zkcode = String.fromCharCode('A'.charCodeAt(0) + (keycode - 33));
//A~H: PgUp, ...
break;
} else if (keycode >= 112 && keycode <= 123) { //F1: 112, F12: 123
zkcode = String.fromCharCode('P'.charCodeAt(0) + (keycode - 112));
//M~Z: F1~F12
break;
} else if (evt.ctrlKey || evt.altKey) {
zkcode = String.fromCharCode(keycode).toLowerCase();
break;
}
return true;
}
// If keyboard command is registered for this component, send request
if(this.inCtrlKeys(evt, zkcode, this._ctrlKeys) ) {
// If autoblur is specified, set focus to keylistener to trigger onBlur for focused component
if(this._autoBlur == true){
this.tabIndex = 32000;
this.focus();
this.tabIndex = 0;
}
zAu.send(new zk.Event(zk.Widget.$(this), 'onCtrlKey', {keyCode: keycode, ctrlKey: evt.ctrlKey, shiftKey: evt.shiftKey, altKey: evt.altKey}, {toServer: true}));
// Do not send request directly, otherwise onChange events won't be fired correctly in IE
//setTimeout(function () {
// zAu.send(new zk.Event(zk.Widget.$(this), 'onCtrlKey', {keyCode: keycode, ctrlKey: evt.ctrlKey, shiftKey: evt.shiftKey, altKey: evt.altKey}, {toServer: true}), 38);
//}, 10);
evt.stop();
// Special handling for IE that Event.stop doesn't support
if (document.all && window.event && !evt.preventDefault) {
evt.keyCode = 0;
}
return false;
}
return true;
},
inCtrlKeys: function(evt, zkcode, keys) {
if (keys) {
//format: ctl+k;alt+k;shft+k;k
var cc = evt.ctrlKey ? '^': evt.altKey ? '@': evt.shiftKey ? '$': '#';
var j = keys.indexOf(cc), k = keys.indexOf(';', j + 1);
if (j >=0 && k >= 0) {
keys = keys.substring(j + 1, k);
return keys.indexOf(zkcode) >= 0;
}
}
return false;
}
});

View File

@ -0,0 +1,3 @@
function (out) {
out.push('<div style="position:absolute; bottom:0; right:0; width:0px; height:0px; z-index:-100;" ', this.domAttrs_(), '>', '</div>');
}

View File

@ -0,0 +1,3 @@
<package name="zkforge" language="xul/html" depends="zul">
<widget name="KeyListener"/>
</package>

View File

@ -20,7 +20,7 @@
<!-- change to false to use compress js which is much smaller --> <!-- change to false to use compress js which is much smaller -->
<client-config> <client-config>
<debug-js>false</debug-js> <debug-js>true</debug-js>
<processing-prompt-delay>500</processing-prompt-delay> <processing-prompt-delay>500</processing-prompt-delay>
</client-config> </client-config>

View File

@ -15,7 +15,6 @@
<classpathentry exported="true" kind="lib" path="lib/junit.jar"/> <classpathentry exported="true" kind="lib" path="lib/junit.jar"/>
<classpathentry exported="true" kind="lib" path="lib/jxl.jar"/> <classpathentry exported="true" kind="lib" path="lib/jxl.jar"/>
<classpathentry exported="true" kind="lib" path="lib/jython.jar"/> <classpathentry exported="true" kind="lib" path="lib/jython.jar"/>
<classpathentry exported="true" kind="lib" path="lib/keylistener.jar"/>
<classpathentry exported="true" kind="lib" path="lib/mvel.jar"/> <classpathentry exported="true" kind="lib" path="lib/mvel.jar"/>
<classpathentry exported="true" kind="lib" path="lib/ognl.jar"/> <classpathentry exported="true" kind="lib" path="lib/ognl.jar"/>
<classpathentry exported="true" kind="lib" path="lib/timelinez.jar"/> <classpathentry exported="true" kind="lib" path="lib/timelinez.jar"/>

View File

@ -524,7 +524,6 @@ Export-Package: Lib,
org.zkforge.ckez, org.zkforge.ckez,
org.zkforge.json.simple, org.zkforge.json.simple,
org.zkforge.json.simple.parser, org.zkforge.json.simple.parser,
org.zkforge.keylistener,
org.zkforge.timeline, org.zkforge.timeline,
org.zkforge.timeline.data, org.zkforge.timeline.data,
org.zkforge.timeline.decorator, org.zkforge.timeline.decorator,
@ -880,8 +879,6 @@ Export-Package: Lib,
web.js.zk.wgt, web.js.zk.wgt,
web.js.zk.xml, web.js.zk.xml,
web.js.zk.zuml, web.js.zk.zuml,
web.js.zkforge,
web.js.zkforge.mold,
web.js.zul, web.js.zul,
web.js.zul.box, web.js.zul.box,
web.js.zul.box.css, web.js.zul.box.css,