/******************************************************************************
* Product: Posterita Ajax UI *
* Copyright (C) 2007 Posterita Ltd. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius *
* or via info@posterita.org or http://www.posterita.org/ *
*****************************************************************************/
package org.adempiere.webui.component;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.event.ToolbarListener;
import org.adempiere.webui.session.SessionManager;
import org.compiere.model.MRole;
import org.compiere.util.CLogger;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.KeyEvent;
import org.zkoss.zul.Space;
/**
*
* @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a>
* @date Feb 25, 2007
* @version $Revision: 0.10 $
*
* @author Cristina Ghita, www.arhipac.ro
* <li>FR [ 2076330 ] Add new methods in CWindowToolbar class
*/
public class CWindowToolbar extends FToolbar implements EventListener
{
/**
*
*/
private static final long serialVersionUID = -8259762910508209764L;
private static final String TOOLBAR_BUTTON_STYLE = "background-color: transparent; display:inline-block; margin-left: 1px; margin-right: 1px; width: 26px; height: 24px;";
private static final String EMBEDDED_TOOLBAR_BUTTON_STYLE = "background-color: transparent; display:inline-block; margin-left: 1px; margin-right: 1px; width: 20px; height: 18px;";
private static CLogger log = CLogger.getCLogger(CWindowToolbar.class);
private ToolBarButton btnIgnore;
private ToolBarButton btnHelp, btnNew, btnCopy, btnDelete, btnDeleteSelection, btnSave;
private ToolBarButton btnRefresh, btnFind, btnLock, btnAttachment;
private ToolBarButton btnGridToggle;
private ToolBarButton btnHistoryRecords, btnParentRecord, btnDetailRecord;
private ToolBarButton btnFirst, btnPrevious, btnNext, btnLast;
private ToolBarButton btnReport, btnArchive, btnPrint;
private ToolBarButton btnZoomAcross, btnActiveWorkflows, btnRequests, btnProductInfo;
private ToolBarButton btnChat;
private HashMap<String, ToolBarButton> buttons = new HashMap<String, ToolBarButton>();
// private ToolBarButton btnExit;
private ArrayList<ToolbarListener> listeners = new ArrayList<ToolbarListener>();
private Event event;
private Map<Integer, ToolBarButton> keyMap = new HashMap<Integer, ToolBarButton>();
private Map<Integer, ToolBarButton> altKeyMap = new HashMap<Integer, ToolBarButton>();
private Map<Integer, ToolBarButton> ctrlKeyMap = new HashMap<Integer, ToolBarButton>();
private boolean embedded;
// Elaine 2008/12/04
/** Show Personal Lock */
public boolean isPersonalLock = MRole.getDefault().isPersonalLock();
private boolean isAllowProductInfo = MRole.getDefault().isAllow_Info_Product();
private int windowNo = 0;
private long prevKeyEventTime = 0;
private KeyEvent prevKeyEvent;
/** Last Modifier of Action Event */
// public int lastModifiers;
//
public CWindowToolbar()
{
this(false);
}
public CWindowToolbar(boolean embedded)
{
this.embedded = embedded;
init();
}
private void init()
{
LayoutUtils.addSclass("adwindow-toolbar", this);
btnIgnore = createButton("Ignore", "Ignore", "Ignore");
addSeparator();
btnHelp = createButton("Help", "Help","Help");
btnNew = createButton("New", "New", "New");
btnCopy = createButton("Copy", "Copy", "Copy");
btnDelete = createButton("Delete", "Delete", "Delete");
btnDeleteSelection = createButton("DeleteSelection", "DeleteSelection", "DeleteSelection");
btnSave = createButton("Save", "Save", "Save");
addSeparator();
btnRefresh = createButton("Refresh", "Refresh", "Refresh");
btnFind = createButton("Find", "Find", "Find");
btnAttachment = createButton("Attachment", "Attachment", "Attachment");
btnChat = createButton("Chat", "Chat", "Chat");
btnGridToggle = createButton("Toggle", "Multi", "Multi");
btnHistoryRecords = createButton("HistoryRecords", "HistoryX", "History");
addSeparator();
btnParentRecord = createButton("ParentRecord", "Parent", "Parent");
btnDetailRecord = createButton("DetailRecord", "Detail", "Detail");
btnFirst = createButton("First", "First", "First");
btnPrevious = createButton("Previous", "Previous", "Previous");
btnNext = createButton("Next", "Next", "Next");
btnLast = createButton("Last", "Last", "Last");
addSeparator();
btnReport = createButton("Report", "Report", "Report");
btnArchive = createButton("Archive", "Archive", "Archive");
btnPrint = createButton("Print", "Print", "Print");
addSeparator();
btnLock = createButton("Lock", "Lock", "Lock"); // Elaine 2008/12/04
btnLock.setVisible(isPersonalLock);
btnZoomAcross = createButton("ZoomAcross", "ZoomAcross", "ZoomAcross");
btnActiveWorkflows = createButton("ActiveWorkflows", "WorkFlow", "WorkFlow");
btnRequests = createButton("Requests", "Request", "Request");
btnProductInfo = createButton("ProductInfo", "Product", "InfoProduct");
btnProductInfo.setVisible(isAllowProductInfo);
// Help and Exit should always be enabled
btnHelp.setDisabled(false);
btnGridToggle.setDisabled(false);
btnZoomAcross.setDisabled(false);
btnActiveWorkflows.setDisabled(false); // Elaine 2008/07/17
btnRequests.setDisabled(false); // Elaine 2008/07/22
btnProductInfo.setDisabled(!isAllowProductInfo); // Elaine 2008/07/22
btnArchive.setDisabled(false); // Elaine 2008/07/28
btnLock.setDisabled(!isPersonalLock); // Elaine 2008/12/04
configureKeyMap();
if (embedded)
{
btnParentRecord.setVisible(false);
btnDetailRecord.setVisible(false);
btnActiveWorkflows.setVisible(false);
btnHistoryRecords.setVisible(false);
btnProductInfo.setVisible(false);
setAlign("end");
setWidth("100%");
setStyle("background: transparent none; ");
}
else
{
setWidth("100%");
}
}
private ToolBarButton createButton(String name, String image, String tooltip)
{
ToolBarButton btn = new ToolBarButton("");
btn.setName("btn"+name);
btn.setImage("/images/"+image + (embedded ? "16.png" : "24.png"));
btn.setTooltiptext(Msg.getMsg(Env.getCtx(),tooltip));
if (embedded)
{
btn.setStyle(EMBEDDED_TOOLBAR_BUTTON_STYLE);
btn.setSclass("embedded-toolbar-button");
}
else
{
btn.setStyle(TOOLBAR_BUTTON_STYLE);
btn.setSclass("toolbar-button");
}
buttons.put(name, btn);
this.appendChild(btn);
//make toolbar button last to receive focus
btn.setTabindex(0);
btn.addEventListener(Events.ON_CLICK, this);
btn.setDisabled(true);
return btn;
}
public ToolBarButton getButton(String name)
{
return buttons.get(name);
}
/** VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
public static final int VK_A = 0x41;
public static final int VK_B = 0x42;
public static final int VK_C = 0x43;
public static final int VK_D = 0x44;
public static final int VK_E = 0x45;
public static final int VK_F = 0x46;
public static final int VK_G = 0x47;
public static final int VK_H = 0x48;
public static final int VK_I = 0x49;
public static final int VK_J = 0x4A;
public static final int VK_K = 0x4B;
public static final int VK_L = 0x4C;
public static final int VK_M = 0x4D;
public static final int VK_N = 0x4E;
public static final int VK_O = 0x4F;
public static final int VK_P = 0x50;
public static final int VK_Q = 0x51;
public static final int VK_R = 0x52;
public static final int VK_S = 0x53;
public static final int VK_T = 0x54;
public static final int VK_U = 0x55;
public static final int VK_V = 0x56;
public static final int VK_W = 0x57;
public static final int VK_X = 0x58;
public static final int VK_Y = 0x59;
public static final int VK_Z = 0x5A;
private void configureKeyMap()
{
keyMap.put(KeyEvent.F1, btnHelp);
keyMap.put(KeyEvent.F2, btnNew);
keyMap.put(KeyEvent.F3, btnDelete);
keyMap.put(KeyEvent.F4, btnSave);
keyMap.put(KeyEvent.F5, btnRefresh);
keyMap.put(KeyEvent.F6, btnFind);
keyMap.put(KeyEvent.F7, btnAttachment);
keyMap.put(KeyEvent.F8, btnGridToggle);
keyMap.put(KeyEvent.F9, btnHistoryRecords);
keyMap.put(KeyEvent.F11, btnReport);
keyMap.put(KeyEvent.F12, btnPrint);
altKeyMap.put(KeyEvent.LEFT, btnParentRecord);
altKeyMap.put(KeyEvent.RIGHT, btnDetailRecord);
altKeyMap.put(KeyEvent.UP, btnPrevious);
altKeyMap.put(KeyEvent.DOWN, btnNext);
altKeyMap.put(KeyEvent.PAGE_UP, btnFirst);
altKeyMap.put(KeyEvent.PAGE_DOWN, btnLast);
altKeyMap.put(VK_P, btnReport);
altKeyMap.put(VK_Z, btnIgnore);
ctrlKeyMap.put(VK_I, btnProductInfo);
ctrlKeyMap.put(VK_P, btnPrint);
ctrlKeyMap.put(VK_N, btnNew);
ctrlKeyMap.put(VK_S, btnSave);
ctrlKeyMap.put(VK_D, btnDelete);
ctrlKeyMap.put(VK_F, btnFind);
}
protected void addSeparator()
{
Space s = new Space();
if (embedded)
s.setSpacing("3px");
else
s.setSpacing("6px");
s.setOrient("vertical");
this.appendChild(s);
}
public void addListener(ToolbarListener toolbarListener)
{
listeners.add(toolbarListener);
}
public void removeListener(ToolbarListener toolbarListener)
{
listeners.remove(toolbarListener);
}
public void onEvent(Event event)
{
String eventName = event.getName();
if(eventName.equals(Events.ON_CLICK))
{
if(event.getTarget() instanceof ToolBarButton)
{
doOnClick(event);
}
} else if (eventName.equals(Events.ON_CTRL_KEY))
{
KeyEvent keyEvent = (KeyEvent) event;
if (isRealVisible()) {
//filter same key event that is too close
//firefox fire key event twice when grid is visible
long time = System.currentTimeMillis();
if (prevKeyEvent != null && prevKeyEventTime > 0 &&
prevKeyEvent.getKeyCode() == keyEvent.getKeyCode() &&
prevKeyEvent.getTarget() == keyEvent.getTarget() &&
prevKeyEvent.isAltKey() == keyEvent.isAltKey() &&
prevKeyEvent.isCtrlKey() == keyEvent.isCtrlKey() &&
prevKeyEvent.isShiftKey() == keyEvent.isShiftKey()) {
if ((time - prevKeyEventTime) <= 300) {
return;
}
}
this.onCtrlKeyEvent(keyEvent);
}
}
}
private void doOnClick(Event event) {
this.event = event;
ToolBarButton cComponent = (ToolBarButton) event.getTarget();
String compName = cComponent.getName();
String methodName = "on" + compName.substring(3);
Iterator<ToolbarListener> listenerIter = listeners.iterator();
while(listenerIter.hasNext())
{
try
{
ToolbarListener tListener = listenerIter.next();
Method method = tListener.getClass().getMethod(methodName, (Class[]) null);
method.invoke(tListener, (Object[]) null);
}
catch(SecurityException e)
{
log.log(Level.SEVERE, "Could not invoke Toolbar listener method: " + methodName + "()", e);
}
catch(NoSuchMethodException e)
{
log.log(Level.SEVERE, "Could not invoke Toolbar listener method: " + methodName + "()", e);
}
catch(IllegalArgumentException e)
{
log.log(Level.SEVERE, "Could not invoke Toolbar listener method: " + methodName + "()", e);
}
catch(IllegalAccessException e)
{
log.log(Level.SEVERE, "Could not invoke Toolbar listener method: " + methodName + "()", e);
}
catch(InvocationTargetException e)
{
log.log(Level.SEVERE, "Could not invoke Toolbar listener method: " + methodName + "()", e);
}
}
this.event = null;
}
public void enableHistoryRecords(boolean enabled)
{
this.btnHistoryRecords.setDisabled(!enabled);
}
public void enableNavigation(boolean enabled)
{
this.btnFirst.setDisabled(!enabled);
this.btnPrevious.setDisabled(!enabled);
this.btnNext.setDisabled(!enabled);
this.btnLast.setDisabled(!enabled);
}
public void enableTabNavigation(boolean enabled)
{
enableTabNavigation(enabled, enabled);
}
public void enableTabNavigation(boolean enableParent, boolean enableDetail)
{
this.btnParentRecord.setDisabled(!enableParent);
this.btnDetailRecord.setDisabled(!enableDetail);
}
public void enableFirstNavigation(boolean enabled)
{
this.btnFirst.setDisabled(!enabled);
this.btnPrevious.setDisabled(!enabled);
}
public void enableLastNavigation(boolean enabled)
{
this.btnLast.setDisabled(!enabled);
this.btnNext.setDisabled(!enabled);
}
public void enabledNew(boolean enabled)
{
this.btnNew.setDisabled(!enabled);
}
/* public void enableEdit(boolean enabled)
{
this.btnEdit.setEnabled(enabled);
}*/
public void enableRefresh(boolean enabled)
{
this.btnRefresh.setDisabled(!enabled);
}
public void enableSave(boolean enabled)
{
this.btnSave.setDisabled(!enabled);
}
public boolean isSaveEnable() {
return !btnSave.isDisabled();
}
// public void enableExit(boolean enabled)
// {
// this.btnExit.setDisabled(!enabled);
// }
public void enableDelete(boolean enabled)
{
this.btnDelete.setDisabled(!enabled);
}
// Elaine 2008/12/01
public void enableDeleteSelection(boolean enabled)
{
this.btnDeleteSelection.setDisabled(!enabled);
}
//
public void enableChanges(boolean enabled)
{
this.btnNew.setDisabled(!enabled);
this.btnCopy.setDisabled(!enabled);
}
public void enableIgnore(boolean enabled)
{
this.btnIgnore.setDisabled(!enabled);
}
public void enableNew(boolean enabled)
{
this.btnNew.setDisabled(!enabled);
}
public void enableAttachment(boolean enabled)
{
this.btnAttachment.setDisabled(!enabled);
}
public void enableChat(boolean enabled)
{
this.btnChat.setDisabled(!enabled);
}
public void enablePrint(boolean enabled)
{
this.btnPrint.setDisabled(!enabled);
}
public void enableReport(boolean enabled)
{
this.btnReport.setDisabled(!enabled);
}
public void enableCopy(boolean enabled)
{
this.btnCopy.setDisabled(!enabled);
}
public void enableFind(boolean enabled)
{
this.btnFind.setDisabled(!enabled);
}
public void enableGridToggle(boolean enabled)
{
btnGridToggle.setDisabled(!enabled);
}
public void lock(boolean locked)
{
this.btnLock.setPressed(locked);
String imgURL = "/images/"+ (this.btnLock.isPressed() ? "LockX" : "Lock") + (embedded ? "16.png" : "24.png");
this.btnLock.setImage(imgURL);
}
public Event getEvent()
{
return event;
}
private void onCtrlKeyEvent(KeyEvent keyEvent) {
ToolBarButton btn = null;
if (keyEvent.isAltKey() && !keyEvent.isCtrlKey() && !keyEvent.isShiftKey())
{
if (keyEvent.getKeyCode() == VK_X)
{
if (windowNo > 0)
{
prevKeyEventTime = System.currentTimeMillis();
prevKeyEvent = keyEvent;
keyEvent.stopPropagation();
SessionManager.getAppDesktop().closeWindow(windowNo);
}
}
else
{
btn = altKeyMap.get(keyEvent.getKeyCode());
}
}
else if (!keyEvent.isAltKey() && keyEvent.isCtrlKey() && !keyEvent.isShiftKey())
btn = ctrlKeyMap.get(keyEvent.getKeyCode());
else if (!keyEvent.isAltKey() && !keyEvent.isCtrlKey() && !keyEvent.isShiftKey())
btn = keyMap.get(keyEvent.getKeyCode());
if (btn != null) {
prevKeyEventTime = System.currentTimeMillis();
prevKeyEvent = keyEvent;
keyEvent.stopPropagation();
if (!btn.isDisabled() && btn.isVisible()) {
Events.sendEvent(btn, new Event(Events.ON_CLICK, btn));
}
}
}
private boolean isRealVisible() {
if (!isVisible())
return false;
Component parent = this.getParent();
while (parent != null) {
if (!parent.isVisible())
return false;
parent = parent.getParent();
}
return true;
}
/**
*
* @param visible
*/
public void setVisibleAll(boolean visible)
{
for (ToolBarButton btn : buttons.values())
{
btn.setVisible(visible);
}
}
/**
*
* @param buttonName
* @param visible
*/
public void setVisible(String buttonName, boolean visible)
{
ToolBarButton btn = buttons.get(buttonName);
if (btn != null)
{
btn.setVisible(visible);
}
}
/**
*
* @param windowNo
*/
public void setWindowNo(int windowNo) {
this.windowNo = windowNo;
}
}