diff --git a/migration/i9/oracle/202202241400_IDEMPIERE-5188.sql b/migration/i9/oracle/202202241400_IDEMPIERE-5188.sql new file mode 100644 index 0000000000..bff94c0590 --- /dev/null +++ b/migration/i9/oracle/202202241400_IDEMPIERE-5188.sql @@ -0,0 +1,19 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-5188 +-- Feb 24, 2022, 1:54:35 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Select a color',0,0,'Y',TO_DATE('2022-02-24 13:54:34','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2022-02-24 13:54:34','YYYY-MM-DD HH24:MI:SS'),100,200726,'ColorFieldPlaceholder','D','7d428fc1-2826-4e2e-8626-1347ddcd9423') +; + +-- Feb 24, 2022, 1:55:09 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Erase',0,0,'Y',TO_DATE('2022-02-24 13:55:09','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2022-02-24 13:55:09','YYYY-MM-DD HH24:MI:SS'),100,200727,'Erase','D','cb0bcecb-2e6a-44d5-97cd-1fbc37ee1a80') +; + +-- IDEMPIERE-5188 +-- Feb 24, 2022, 1:58:06 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Color Picker',0,0,'Y',TO_DATE('2022-02-24 13:58:05','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2022-02-24 13:58:05','YYYY-MM-DD HH24:MI:SS'),100,200728,'ColorPicker','D','ecdf19df-e3e7-42d1-905e-5496b273fefb') +; + +SELECT register_migration_script('202202241400_IDEMPIERE-5188.sql') FROM dual +; diff --git a/migration/i9/postgresql/202202241400_IDEMPIERE-5188.sql b/migration/i9/postgresql/202202241400_IDEMPIERE-5188.sql new file mode 100644 index 0000000000..6bc0d27a66 --- /dev/null +++ b/migration/i9/postgresql/202202241400_IDEMPIERE-5188.sql @@ -0,0 +1,18 @@ + + + +-- IDEMPIERE-5188 +-- Feb 24, 2022, 1:54:35 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Select a color',0,0,'Y',TO_TIMESTAMP('2022-02-24 13:54:34','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-02-24 13:54:34','YYYY-MM-DD HH24:MI:SS'),100,200726,'ColorFieldPlaceholder','D','7d428fc1-2826-4e2e-8626-1347ddcd9423') +; + +-- Feb 24, 2022, 1:55:09 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Erase',0,0,'Y',TO_TIMESTAMP('2022-02-24 13:55:09','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-02-24 13:55:09','YYYY-MM-DD HH24:MI:SS'),100,200727,'Erase','D','cb0bcecb-2e6a-44d5-97cd-1fbc37ee1a80') +; + +-- Feb 24, 2022, 1:58:06 PM CET +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','Color Picker',0,0,'Y',TO_TIMESTAMP('2022-02-24 13:58:05','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-02-24 13:58:05','YYYY-MM-DD HH24:MI:SS'),100,200728,'ColorPicker','D','ecdf19df-e3e7-42d1-905e-5496b273fefb') +; + +SELECT register_migration_script('202202241400_IDEMPIERE-5188.sql') FROM dual +; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java index d62d1de7b9..63e3a2beaf 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java @@ -858,14 +858,17 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer label.addEventListener(Events.ON_CLICK, new ZoomListener((IZoomableEditor) editor)); } - popupMenu.addContextElement(label); - if (editor.getComponent() instanceof XulElement) - { - popupMenu.addContextElement((XulElement) editor.getComponent()); - } - } + popupMenu.addContextElement(label); + } } popupMenu.addSuggestion(field); + if(!ClientInfo.isMobile()) + { + if (editor.getComponent() instanceof XulElement) + { + popupMenu.addContextElement((XulElement) editor.getComponent()); + } + } } } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WColorEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WColorEditor.java new file mode 100644 index 0000000000..3ef72e5171 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WColorEditor.java @@ -0,0 +1,263 @@ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + * * + * Contributors: * + * - Nicolas Micoud (TGI) * + * - Low Heng Sin * + **********************************************************************/ + +package org.adempiere.webui.editor; + + +import java.util.logging.Level; + +import org.adempiere.webui.component.EditorBox; +import org.adempiere.webui.component.Textbox; +import org.adempiere.webui.event.ContextMenuEvent; +import org.adempiere.webui.event.ContextMenuListener; +import org.adempiere.webui.event.ValueChangeEvent; +import org.adempiere.webui.theme.ThemeManager; +import org.compiere.model.GridField; +import org.compiere.util.CLogger; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.compiere.util.Util; +import org.zkoss.zk.au.out.AuScript; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.util.Clients; +import org.zkoss.zul.Menuitem; + +/** + * + * @author Nicolas Micoud (TGI) + * + */ +public class WColorEditor extends WEditor implements ContextMenuListener +{ + private static final CLogger log = CLogger.getCLogger(WColorEditor.class); + private static final String[] LISTENER_EVENTS = {Events.ON_CLICK}; + public static final String COLOR_PICKER_EVENT = "COLOR_PICKER"; + + private String oldValue; + + private String placeHolder; + + private Textbox colorbox; + + /** + * + * @param gridField + */ + public WColorEditor(GridField gridField) + { + this(gridField, false, null); + } + + /** + * + * @param gridField + * @param tableEditor + * @param editorConfiguration + */ + public WColorEditor(GridField gridField, boolean tableEditor, IEditorConfiguration editorConfiguration) + { + super(new EditorBox(), gridField, tableEditor, editorConfiguration); + + init(); + + if (ThemeManager.isUseFontIconForImage()) + getComponent().getButton().setIconSclass("z-icon-pencil"); + else + getComponent().setButtonImage(ThemeManager.getThemeResource("images/ColorPicker16.png")); + + if (gridField != null) + placeHolder = gridField.getPlaceholder(); + if (Util.isEmpty(placeHolder, true)) + placeHolder = Msg.getMsg(Env.getCtx(), "ColorFieldPlaceholder"); + getComponent().getTextbox().setPlaceholder(placeHolder); + getComponent().getTextbox().setReadonly(true); + + colorbox = new Textbox(); + colorbox.setClientAttribute("type", "color"); + colorbox.setStyle("position:absolute;top:0;left:0;height:0px !important;width:0px !important;" + + "border:none !important;margin:0 !important;padding:0 !important;visibility:hidden;"); + getComponent().appendChild(colorbox); + + colorbox.addEventListener(Events.ON_CHANGE, e -> { + processNewValue(colorbox.getValue()); + }); + } + + private void init() + { + if (log.isLoggable(Level.INFO)) log.info("Initializing component"); + + popupMenu = new WEditorPopupMenu(false, false, isShowPreference()); + addColorEditorMenu(popupMenu); + addChangeLogMenu(popupMenu); + } + + protected void addColorEditorMenu(WEditorPopupMenu popupMenu) { + Menuitem editor = new Menuitem(); + editor.setAttribute("EVENT", WEditorPopupMenu.RESET_EVENT); + editor.setLabel(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Erase")).intern()); + if (ThemeManager.isUseFontIconForImage()) + editor.setIconSclass("z-icon-eraser"); + else + editor.setImage(ThemeManager.getThemeResource("images/Erase16.png")); + editor.addEventListener(Events.ON_CLICK, popupMenu); + popupMenu.appendChild(editor); + + editor = new Menuitem(); + editor.setAttribute("EVENT", COLOR_PICKER_EVENT); + editor.setLabel(Msg.getMsg(Env.getCtx(), "ColorPicker")); + if (ThemeManager.isUseFontIconForImage()) + editor.setIconSclass("z-icon-pencil"); + else + editor.setImage(ThemeManager.getThemeResource("images/ColorPicker16.png")); + editor.addEventListener(Events.ON_CLICK, popupMenu); + popupMenu.appendChild(editor); + } + + public void onMenu(ContextMenuEvent evt) + { + if (WEditorPopupMenu.RESET_EVENT.equals(evt.getContextEvent())) + { + processNewValue(null); + colorbox.setValue(oldValue); + + } + else if (COLOR_PICKER_EVENT.equals(evt.getContextEvent())) + { + openColorPicker(); + } + } + + @Override + public EditorBox getComponent() + { + return (EditorBox) component; + } + + @Override + public void setValue(Object value) + { + if (value == null) + { + oldValue = null; + getComponent().setText(""); + } + else + { + oldValue = String.valueOf(value); + getComponent().setText(oldValue); + } + colorbox.setValue(oldValue); + + fillTextbox(); + } + + private void fillTextbox() { + String style="background-color: transparent !important;"; + if (!Util.isEmpty(oldValue, true)) + style = "background: linear-gradient(to right, rgba(255,0,0,0) 50%, " + + oldValue + " 50%) !important;"; + String script = "jq('#"+getComponent().getTextbox().getUuid()+"').attr('style','"+style+"');"; + if (Executions.getCurrent() != null) + Clients.response(new AuScript(script)); + else if (getComponent().getDesktop() != null) + Executions.schedule(getComponent().getDesktop(), e -> Clients.response(new AuScript(script)), new Event("onFillTextBox")); + } + + @Override + public Object getValue() + { + return getComponent().getText(); + } + + @Override + public String getDisplay() + { + return getComponent().getText(); + } + + @Override + public boolean isReadWrite() { + return getComponent().getButton().isEnabled(); + } + + @Override + public void setReadWrite(boolean readWrite) { + getComponent().getButton().setEnabled(readWrite); + } + + public void onEvent(Event event) + { + if (Events.ON_CLICK.equalsIgnoreCase(event.getName())) + { + openColorPicker(); + } + else + { + return; + } + } + + public void openColorPicker() { // TODO color picker is opening at upper left ; better to open it at center of screen + String uid = colorbox.getUuid(); + String script = "var wgt = zk.Widget.$('#"+uid+"');wgt.$n().click();"; + Clients.response(new AuScript(script)); + } + + protected void processNewValue(String newValue) { + if (oldValue != null && newValue != null && oldValue.equals(newValue)) { + return; + } + if (oldValue == null && newValue == null) { + return; + } + ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), oldValue, newValue); + fireValueChange(changeEvent); + oldValue = getComponent().getTextbox().getValue(); + } + + public String[] getEvents() + { + return LISTENER_EVENTS; + } + + @Override + public void setTableEditor(boolean b) { + super.setTableEditor(b); + getComponent().setTableEditorMode(b); + } + + @Override + public String getDisplayTextForGridView(Object value) { + if (value == null) { + return ""; + } else { + return (String)value; + } + } +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WEditorPopupMenu.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WEditorPopupMenu.java index 1faa853330..2f95bf5e77 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WEditorPopupMenu.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WEditorPopupMenu.java @@ -62,6 +62,7 @@ public class WEditorPopupMenu extends Menupopup implements EventListener public static final String SHOWLOCATION_EVENT = "SHOW_LOCATION"; public static final String CHANGE_LOG_EVENT = "CHANGE_LOG"; public static final String EDITOR_EVENT = "EDITOR"; + public static final String RESET_EVENT = "RESET"; private boolean newEnabled = true; private boolean updateEnabled = true; // Elaine 2009/02/16 - update record diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java index 6b05bbb8ae..efbbbed6d8 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java @@ -21,6 +21,7 @@ import org.adempiere.webui.editor.WButtonEditor; import org.adempiere.webui.editor.WChartEditor; import org.adempiere.webui.editor.WChosenboxListEditor; import org.adempiere.webui.editor.WChosenboxSearchEditor; +import org.adempiere.webui.editor.WColorEditor; import org.adempiere.webui.editor.WDashboardContentEditor; import org.adempiere.webui.editor.WDateEditor; import org.adempiere.webui.editor.WDatetimeEditor; @@ -80,8 +81,7 @@ public class DefaultEditorFactory implements IEditorFactory { } /** String (clear/password) */ - if (displayType == DisplayType.String - || displayType == DisplayType.PrinterName || displayType == DisplayType.Color + if (displayType == DisplayType.String || displayType == DisplayType.PrinterName || displayType == DisplayType.Text || displayType == DisplayType.TextLong || displayType == DisplayType.Memo) { @@ -96,10 +96,12 @@ public class DefaultEditorFactory implements IEditorFactory { else editor = new WStringEditor(gridField, tableEditor, editorConfiguration); } - //enable html5 color input type - if (displayType == DisplayType.Color) - ((WStringEditor)editor).getComponent().setClientAttribute("type", "color"); } + /** Color */ + else if (displayType == DisplayType.Color) { + editor = new WColorEditor(gridField, tableEditor, editorConfiguration); + } + /** File */ else if (displayType == DisplayType.FileName) { diff --git a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/ColorPicker16.png b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/ColorPicker16.png new file mode 100644 index 0000000000..660e28aaf3 Binary files /dev/null and b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/ColorPicker16.png differ diff --git a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/ColorPicker24.png b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/ColorPicker24.png new file mode 100644 index 0000000000..f5e8cfb253 Binary files /dev/null and b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/ColorPicker24.png differ diff --git a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/Erase16.png b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/Erase16.png new file mode 100644 index 0000000000..f69ad0d91d Binary files /dev/null and b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/Erase16.png differ diff --git a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/Erase24.png b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/Erase24.png new file mode 100644 index 0000000000..12507eb8ee Binary files /dev/null and b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/images/Erase24.png differ