diff --git a/migration/i6.2z/oracle/201910081000_IDEMPIERE-4060.sql b/migration/i6.2z/oracle/201910081000_IDEMPIERE-4060.sql
new file mode 100644
index 0000000000..c2ea19585d
--- /dev/null
+++ b/migration/i6.2z/oracle/201910081000_IDEMPIERE-4060.sql
@@ -0,0 +1,75 @@
+SET SQLBLANKLINES ON
+SET DEFINE OFF
+
+-- IDEMPIERE-4060 Implement change scheduler state at scheduler window
+-- Oct 7, 2019, 5:15:42 PM MYT
+INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,Help,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (214058,0,'System Element','System Element enables the central maintenance of column description and help.','The System Element allows for the central maintenance of help, descriptions and terminology for a database column.',102,'AD_Element_ID',22,'N','N','N','N','N',0,'N',30,0,0,'Y',TO_DATE('2019-10-07 17:15:41','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-10-07 17:15:41','YYYY-MM-DD HH24:MI:SS'),100,106,'Y','N','D','N','N','N','Y','403c387b-fc05-48d3-8bfa-4bff1d84ebe0','Y',0,'N','N','N','N')
+;
+
+-- Oct 7, 2019, 5:15:52 PM MYT
+UPDATE AD_Column SET FKConstraintName='ADElement_ADReference', FKConstraintType='N',Updated=TO_DATE('2019-10-07 17:15:52','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=214058
+;
+
+-- Oct 7, 2019, 5:15:52 PM MYT
+ALTER TABLE AD_Reference ADD AD_Element_ID NUMBER(10) DEFAULT NULL
+;
+
+-- Oct 7, 2019, 5:15:52 PM MYT
+ALTER TABLE AD_Reference ADD CONSTRAINT ADElement_ADReference FOREIGN KEY (AD_Element_ID) REFERENCES ad_element(ad_element_id) DEFERRABLE INITIALLY DEFERRED
+;
+
+-- Oct 7, 2019, 5:18:40 PM MYT
+INSERT INTO AD_Val_Rule (AD_Val_Rule_ID,Name,Type,Code,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,AD_Val_Rule_UU) VALUES (200137,'AD_Reference of AD_Element','S','(AD_Reference.AD_Element_ID IS NULL OR AD_Reference.AD_Element_ID=@AD_Element_ID:0@)',0,0,'Y',TO_DATE('2019-10-07 17:18:39','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-10-07 17:18:39','YYYY-MM-DD HH24:MI:SS'),100,'D','30490e6b-25df-44ed-b12f-1f0c9858a9c4')
+;
+
+-- Oct 7, 2019, 5:21:29 PM MYT
+UPDATE AD_Field SET SeqNo=120, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, SeqNoGrid=120, IsToolbarButton=NULL,Updated=TO_DATE('2019-10-07 17:21:29','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=54400
+;
+
+-- Oct 7, 2019, 5:21:38 PM MYT
+UPDATE AD_Field SET SeqNo=110, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, SeqNoGrid=110, IsToolbarButton=NULL,Updated=TO_DATE('2019-10-07 17:21:38','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=314
+;
+
+-- Oct 7, 2019, 5:23:39 PM MYT
+INSERT INTO AD_Field (AD_Field_ID,Name,Description,Help,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLogic,DisplayLength,SeqNo,SortNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan,NumLines,IsQuickEntry,IsDefaultFocus,IsAdvancedField) VALUES (206184,'System Element','System Element enables the central maintenance of column description and help.','The System Element allows for the central maintenance of help, descriptions and terminology for a database column.',102,214058,'Y','@ValidationType@=''D''',0,100,0,'N','N','N','N',0,0,'Y',TO_DATE('2019-10-07 17:23:38','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-10-07 17:23:38','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','1f1ae42b-f779-4b83-bdcd-7c562f93821e','Y',100,4,2,1,'N','N','N')
+;
+
+-- Oct 7, 2019, 5:25:33 PM MYT
+UPDATE AD_Column SET AD_Val_Rule_ID=200137,Updated=TO_DATE('2019-10-07 17:25:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=226
+;
+
+-- Oct 7, 2019, 5:26:02 PM MYT
+UPDATE AD_Column SET AD_Val_Rule_ID=200137,Updated=TO_DATE('2019-10-07 17:26:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=15011
+;
+
+-- Oct 7, 2019, 5:26:28 PM MYT
+UPDATE AD_Column SET AD_Val_Rule_ID=200137,Updated=TO_DATE('2019-10-07 17:26:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2827
+;
+
+-- Oct 7, 2019, 5:26:54 PM MYT
+UPDATE AD_Column SET AD_Val_Rule_ID=200137,Updated=TO_DATE('2019-10-07 17:26:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=200959
+;
+
+-- Oct 7, 2019, 5:30:43 PM MYT
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203368,0,0,'Y',TO_DATE('2019-10-07 17:30:42','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-10-07 17:30:42','YYYY-MM-DD HH24:MI:SS'),100,'SchedulerState','Scheduler State','State of this scheduler record (not scheduled, started or stopped)','Scheduler State','D','e266c453-619a-4ac8-bf2c-a3826cf5e3ea')
+;
+
+-- Oct 7, 2019, 5:34:10 PM MYT
+INSERT INTO AD_Reference (AD_Reference_ID,Name,Description,ValidationType,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,IsOrderByValue,AD_Reference_UU,AD_Element_ID) VALUES (200173,'Scheduler State','View and change the state of a scheduler','D',0,0,'Y',TO_DATE('2019-10-07 17:34:09','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-10-07 17:34:09','YYYY-MM-DD HH24:MI:SS'),100,'D','N','6b31c7a3-12ee-40d6-ae12-e5d16dc854b4',203368)
+;
+
+-- Oct 7, 2019, 5:37:01 PM MYT
+INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,ColumnSQL,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (214059,0,'Scheduler State','State of this scheduler record (not scheduled, started or stopped)',688,'SchedulerState',10,'N','N','N','N','N',0,'N',200173,0,0,'Y',TO_DATE('2019-10-07 17:37:00','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-10-07 17:37:00','YYYY-MM-DD HH24:MI:SS'),100,203368,'N','N','D','N','N','AD_Scheduler_ID','N','N','43da28ea-8c13-4c0a-a61c-c6a27311a986','N',0,'N','N','N','N')
+;
+
+-- Oct 7, 2019, 5:38:37 PM MYT
+INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,SortNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan,NumLines,IsQuickEntry,IsDefaultFocus,IsAdvancedField) VALUES (206185,'Scheduler State','State of this scheduler record (not scheduled, started or stopped)',589,214059,'Y',0,150,0,'N','N','N','N',0,0,'Y',TO_DATE('2019-10-07 17:38:36','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2019-10-07 17:38:36','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','4f57d49d-c334-44e8-98bc-a725007e5032','Y',160,1,2,1,'N','N','N')
+;
+
+-- IDEMPIERE-4060 Implement change scheduler state at scheduler window
+-- Oct 7, 2019, 9:54:33 PM MYT
+UPDATE AD_ToolBarButton SET IsActive='N',Updated=TO_DATE('2019-10-07 21:54:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_ToolBarButton_ID=200099
+;
+
+SELECT register_migration_script('201910081000_IDEMPIERE-4060.sql') FROM dual
+;
diff --git a/migration/i6.2z/postgresql/201910081000_IDEMPIERE-4060.sql b/migration/i6.2z/postgresql/201910081000_IDEMPIERE-4060.sql
new file mode 100644
index 0000000000..8123374a00
--- /dev/null
+++ b/migration/i6.2z/postgresql/201910081000_IDEMPIERE-4060.sql
@@ -0,0 +1,72 @@
+-- IDEMPIERE-4060 Implement change scheduler state at scheduler window
+-- Oct 7, 2019, 5:15:42 PM MYT
+INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,Help,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (214058,0,'System Element','System Element enables the central maintenance of column description and help.','The System Element allows for the central maintenance of help, descriptions and terminology for a database column.',102,'AD_Element_ID',22,'N','N','N','N','N',0,'N',30,0,0,'Y',TO_TIMESTAMP('2019-10-07 17:15:41','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-10-07 17:15:41','YYYY-MM-DD HH24:MI:SS'),100,106,'Y','N','D','N','N','N','Y','403c387b-fc05-48d3-8bfa-4bff1d84ebe0','Y',0,'N','N','N','N')
+;
+
+-- Oct 7, 2019, 5:15:52 PM MYT
+UPDATE AD_Column SET FKConstraintName='ADElement_ADReference', FKConstraintType='N',Updated=TO_TIMESTAMP('2019-10-07 17:15:52','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=214058
+;
+
+-- Oct 7, 2019, 5:15:52 PM MYT
+ALTER TABLE AD_Reference ADD COLUMN AD_Element_ID NUMERIC(10) DEFAULT NULL
+;
+
+-- Oct 7, 2019, 5:15:52 PM MYT
+ALTER TABLE AD_Reference ADD CONSTRAINT ADElement_ADReference FOREIGN KEY (AD_Element_ID) REFERENCES ad_element(ad_element_id) DEFERRABLE INITIALLY DEFERRED
+;
+
+-- Oct 7, 2019, 5:18:40 PM MYT
+INSERT INTO AD_Val_Rule (AD_Val_Rule_ID,Name,Type,Code,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,AD_Val_Rule_UU) VALUES (200137,'AD_Reference of AD_Element','S','(AD_Reference.AD_Element_ID IS NULL OR AD_Reference.AD_Element_ID=@AD_Element_ID:0@)',0,0,'Y',TO_TIMESTAMP('2019-10-07 17:18:39','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-10-07 17:18:39','YYYY-MM-DD HH24:MI:SS'),100,'D','30490e6b-25df-44ed-b12f-1f0c9858a9c4')
+;
+
+-- Oct 7, 2019, 5:21:29 PM MYT
+UPDATE AD_Field SET SeqNo=120, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, SeqNoGrid=120, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2019-10-07 17:21:29','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=54400
+;
+
+-- Oct 7, 2019, 5:21:38 PM MYT
+UPDATE AD_Field SET SeqNo=110, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, SeqNoGrid=110, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2019-10-07 17:21:38','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=314
+;
+
+-- Oct 7, 2019, 5:23:39 PM MYT
+INSERT INTO AD_Field (AD_Field_ID,Name,Description,Help,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLogic,DisplayLength,SeqNo,SortNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan,NumLines,IsQuickEntry,IsDefaultFocus,IsAdvancedField) VALUES (206184,'System Element','System Element enables the central maintenance of column description and help.','The System Element allows for the central maintenance of help, descriptions and terminology for a database column.',102,214058,'Y','@ValidationType@=''D''',0,100,0,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2019-10-07 17:23:38','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-10-07 17:23:38','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','1f1ae42b-f779-4b83-bdcd-7c562f93821e','Y',100,4,2,1,'N','N','N')
+;
+
+-- Oct 7, 2019, 5:25:33 PM MYT
+UPDATE AD_Column SET AD_Val_Rule_ID=200137,Updated=TO_TIMESTAMP('2019-10-07 17:25:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=226
+;
+
+-- Oct 7, 2019, 5:26:02 PM MYT
+UPDATE AD_Column SET AD_Val_Rule_ID=200137,Updated=TO_TIMESTAMP('2019-10-07 17:26:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=15011
+;
+
+-- Oct 7, 2019, 5:26:28 PM MYT
+UPDATE AD_Column SET AD_Val_Rule_ID=200137,Updated=TO_TIMESTAMP('2019-10-07 17:26:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=2827
+;
+
+-- Oct 7, 2019, 5:26:54 PM MYT
+UPDATE AD_Column SET AD_Val_Rule_ID=200137,Updated=TO_TIMESTAMP('2019-10-07 17:26:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=200959
+;
+
+-- Oct 7, 2019, 5:30:43 PM MYT
+INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203368,0,0,'Y',TO_TIMESTAMP('2019-10-07 17:30:42','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-10-07 17:30:42','YYYY-MM-DD HH24:MI:SS'),100,'SchedulerState','Scheduler State','State of this scheduler record (not scheduled, started or stopped)','Scheduler State','D','e266c453-619a-4ac8-bf2c-a3826cf5e3ea')
+;
+
+-- Oct 7, 2019, 5:34:10 PM MYT
+INSERT INTO AD_Reference (AD_Reference_ID,Name,Description,ValidationType,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,IsOrderByValue,AD_Reference_UU,AD_Element_ID) VALUES (200173,'Scheduler State','View and change the state of a scheduler','D',0,0,'Y',TO_TIMESTAMP('2019-10-07 17:34:09','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-10-07 17:34:09','YYYY-MM-DD HH24:MI:SS'),100,'D','N','6b31c7a3-12ee-40d6-ae12-e5d16dc854b4',203368)
+;
+
+-- Oct 7, 2019, 5:37:01 PM MYT
+INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,ColumnSQL,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (214059,0,'Scheduler State','State of this scheduler record (not scheduled, started or stopped)',688,'SchedulerState',10,'N','N','N','N','N',0,'N',200173,0,0,'Y',TO_TIMESTAMP('2019-10-07 17:37:00','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-10-07 17:37:00','YYYY-MM-DD HH24:MI:SS'),100,203368,'N','N','D','N','N','AD_Scheduler_ID','N','N','43da28ea-8c13-4c0a-a61c-c6a27311a986','N',0,'N','N','N','N')
+;
+
+-- Oct 7, 2019, 5:38:37 PM MYT
+INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,SortNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan,NumLines,IsQuickEntry,IsDefaultFocus,IsAdvancedField) VALUES (206185,'Scheduler State','State of this scheduler record (not scheduled, started or stopped)',589,214059,'Y',0,150,0,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2019-10-07 17:38:36','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2019-10-07 17:38:36','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','4f57d49d-c334-44e8-98bc-a725007e5032','Y',160,1,2,1,'N','N','N')
+;
+
+-- IDEMPIERE-4060 Implement change scheduler state at scheduler window
+-- Oct 7, 2019, 9:54:33 PM MYT
+UPDATE AD_ToolBarButton SET IsActive='N',Updated=TO_TIMESTAMP('2019-10-07 21:54:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_ToolBarButton_ID=200099
+;
+
+SELECT register_migration_script('201910081000_IDEMPIERE-4060.sql') FROM dual
+;
diff --git a/org.adempiere.ui.zk/OSGI-INF/org.adempiere.webui.scheduler.SchedulerStateEditorFactory.xml b/org.adempiere.ui.zk/OSGI-INF/org.adempiere.webui.scheduler.SchedulerStateEditorFactory.xml
new file mode 100644
index 0000000000..ab2229a746
--- /dev/null
+++ b/org.adempiere.ui.zk/OSGI-INF/org.adempiere.webui.scheduler.SchedulerStateEditorFactory.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java
index 2b512bee95..1249bbd40d 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java
@@ -2193,7 +2193,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
});
}
- private void onSave(final boolean onSaveEvent, final boolean onNavigationEvent, final Callback callback) {
+ public void onSave(final boolean onSaveEvent, final boolean onNavigationEvent, final Callback callback) {
final Callback postCallback = new Callback() {
@Override
public void onCallback(Boolean result) {
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/scheduler/SchedulerStateEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/scheduler/SchedulerStateEditor.java
new file mode 100644
index 0000000000..501fbd4b74
--- /dev/null
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/scheduler/SchedulerStateEditor.java
@@ -0,0 +1,337 @@
+/**********************************************************************
+* 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: *
+* - Trek Global Corporation *
+* - Heng Sin Low *
+**********************************************************************/
+package org.adempiere.webui.scheduler;
+
+import org.adempiere.base.IServiceHolder;
+import org.adempiere.base.Service;
+import org.adempiere.util.Callback;
+import org.adempiere.webui.adwindow.ADWindow;
+import org.adempiere.webui.component.Button;
+import org.adempiere.webui.editor.WEditor;
+import org.adempiere.webui.window.FDialog;
+import org.compiere.model.GridField;
+import org.compiere.model.MScheduler;
+import org.compiere.model.StateChangeEvent;
+import org.compiere.model.StateChangeListener;
+import org.compiere.server.AdempiereServerMgr;
+import org.compiere.server.IServerManager;
+import org.compiere.util.Env;
+import org.compiere.util.Msg;
+import org.idempiere.distributed.IClusterService;
+import org.idempiere.server.cluster.ClusterServerMgr;
+import org.zkoss.zk.ui.event.Event;
+import org.zkoss.zk.ui.event.Events;
+import org.zkoss.zk.ui.util.Clients;
+
+/**
+ * @author hengsin
+ *
+ */
+public class SchedulerStateEditor extends WEditor {
+
+ private static final String ON_START_SCHEDULER_EVENT = "onStartScheduler";
+ private static final String ON_STOP_SCHEDULER_EVENT = "onStopScheduler";
+ private static final String ON_ADD_SCHEDULER_EVENT = "onAddScheduler";
+
+ private int schedulerState;
+
+ public SchedulerStateEditor(GridField gridField)
+ {
+ this(gridField, -1);
+ }
+
+ public SchedulerStateEditor(GridField gridField, int rowIndex) {
+ super(new Button(), gridField, rowIndex);
+ Button btn = getComponent();
+
+ btn.addEventListener(ON_START_SCHEDULER_EVENT, evt -> {
+ int id = getAD_Scheduler_ID();
+ if (id > 0) {
+ MScheduler model = new MScheduler(Env.getCtx(), id, null);
+ IServerManager serverMgr = getServerMgr();
+ if (serverMgr != null) {
+ String error = serverMgr.start(model.getServerID());
+ if (error == null) {
+ FDialog.info(0, null, "SchedulerStartSuccess");
+ } else {
+ FDialog.error(0, "SchedulerStartFail", error);
+ }
+ getComponent().setLabel(getDisplay());
+ }
+ Clients.clearBusy();
+ }
+ });
+
+ btn.addEventListener(ON_STOP_SCHEDULER_EVENT, evt -> {
+ int id = getAD_Scheduler_ID();
+ if (id > 0) {
+ MScheduler model = new MScheduler(Env.getCtx(), id, null);
+ IServerManager serverMgr = getServerMgr();
+ if (serverMgr != null) {
+ String error = serverMgr.stop(model.getServerID());
+ if (error == null) {
+ FDialog.info(0, null, "SchedulerStopSuccess");
+ } else {
+ FDialog.error(0, "SchedulerStopFail", error);
+ }
+ getComponent().setLabel(getDisplay());
+ }
+ Clients.clearBusy();
+ }
+ });
+
+ btn.addEventListener(ON_ADD_SCHEDULER_EVENT, evt -> {
+ int id = getAD_Scheduler_ID();
+ if (id > 0) {
+ MScheduler model = new MScheduler(Env.getCtx(), id, null);
+ IServerManager serverMgr = getServerMgr();
+ if (serverMgr != null) {
+ String error = serverMgr.addScheduler(model);
+ if (error == null) {
+ FDialog.info(0, null, "SchedulerAddAndStartSuccess");
+ } else {
+ FDialog.error(0, "SchedulerAddAndStartFail", error);
+ }
+ getComponent().setLabel(getDisplay());
+ }
+ Clients.clearBusy();
+ }
+ });
+
+ getComponent().addEventListener(Events.ON_CLICK, this);
+ getComponent().setLabel(getDisplay());
+ if (gridField.getGridTab() != null) {
+ gridField.getGridTab().addStateChangeListener(new StateChangeListener() {
+ @Override
+ public void stateChange(StateChangeEvent event) {
+ if (event.getEventType() == StateChangeEvent.DATA_SAVE || event.getEventType() == StateChangeEvent.DATA_IGNORE) {
+ getComponent().setLabel(getDisplay());
+ }
+ }
+ });
+ }
+ }
+
+ private int getAD_Scheduler_ID() {
+ return gridTab.getRecord_ID();
+ }
+
+ /**
+ * @see org.zkoss.zk.ui.event.EventListener#onEvent(org.zkoss.zk.ui.event.Event)
+ */
+ @Override
+ public void onEvent(Event event) throws Exception {
+ if (event.getName().equals(Events.ON_CLICK)) {
+ if (schedulerState == AdempiereServerMgr.SERVER_STATE_NOT_SCHEDULE) {
+ ADWindow adwindow = ADWindow.findADWindow(getComponent());
+ if (adwindow != null) {
+ if (gridTab.isNew() || gridTab.needSave(false, false)) {
+ adwindow.getADWindowContent().onSave(true, false, new Callback() {
+ @Override
+ public void onCallback(Boolean result) {
+ if (result) {
+ int id = getAD_Scheduler_ID();
+ if (id <= 0)
+ return;
+ schedule();
+ }
+ }
+ });
+ } else {
+ schedule();
+ }
+ }
+ } else if (schedulerState == AdempiereServerMgr.SERVER_STATE_STARTED) {
+ ADWindow adwindow = ADWindow.findADWindow(getComponent());
+ if (adwindow != null) {
+ if (gridTab.isNew() || gridTab.needSave(false, false)) {
+ adwindow.getADWindowContent().onSave(true, false, new Callback() {
+ @Override
+ public void onCallback(Boolean result) {
+ if (result)
+ stop();
+ }
+ });
+ } else {
+ stop();
+ }
+ }
+ } else if (schedulerState == AdempiereServerMgr.SERVER_STATE_STOPPED) {
+ ADWindow adwindow = ADWindow.findADWindow(getComponent());
+ if (adwindow != null) {
+ if (gridTab.isNew() || gridTab.needSave(false, false)) {
+ adwindow.getADWindowContent().onSave(true, false, new Callback() {
+ @Override
+ public void onCallback(Boolean result) {
+ if (result)
+ start();
+ }
+ });
+ } else {
+ start();
+ }
+ }
+ } else {
+ FDialog.error(0, "CantReadCurrentSchedulerState");
+ }
+ }
+
+ }
+
+ private void schedule() {
+ int id = getAD_Scheduler_ID();
+ if (id <= 0)
+ return;
+
+ FDialog.ask(0, null, "SchedulerAddAndStartPrompt", new Callback() {
+ @Override
+ public void onCallback(Boolean result) {
+ if (result) {
+ Clients.showBusy(Msg.getMsg(Env.getCtx(), "Processing"));
+ Events.echoEvent(ON_ADD_SCHEDULER_EVENT, getComponent(), null);
+ }
+ }
+ });
+ }
+
+
+
+ private void stop() {
+ int id = getAD_Scheduler_ID();
+ if (id <= 0)
+ return;
+
+ FDialog.ask(0, null, "SchedulerStopPrompt", new Callback() {
+ @Override
+ public void onCallback(Boolean result) {
+ if (result) {
+ Clients.showBusy(Msg.getMsg(Env.getCtx(), "Processing"));
+ Events.echoEvent(ON_STOP_SCHEDULER_EVENT, getComponent(), null);
+ }
+
+ }
+ });
+ }
+
+ private void start() {
+ int id = getAD_Scheduler_ID();
+ if (id <= 0)
+ return;
+
+ FDialog.ask(0, null, "SchedulerStartPrompt", new Callback() {
+ @Override
+ public void onCallback(Boolean result) {
+ if (result) {
+ Clients.showBusy(Msg.getMsg(Env.getCtx(), "Processing"));
+ Events.echoEvent(ON_START_SCHEDULER_EVENT, getComponent(), null);
+ }
+ }
+ });
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.webui.editor.WEditor#setReadWrite(boolean)
+ */
+ @Override
+ public void setReadWrite(boolean readWrite) {
+ GridField descriptionField = gridTab.getField("Description");
+ if (descriptionField != null)
+ getComponent().setEnabled(descriptionField.isEditable(true));
+ else
+ getComponent().setEnabled(readWrite);
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.webui.editor.WEditor#isReadWrite()
+ */
+ @Override
+ public boolean isReadWrite() {
+ return getComponent().isEnabled();
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.webui.editor.WEditor#setValue(java.lang.Object)
+ */
+ @Override
+ public void setValue(Object value) {
+ getComponent().setLabel(getDisplay());
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.webui.editor.WEditor#getValue()
+ */
+ @Override
+ public Object getValue() {
+ return getAD_Scheduler_ID();
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.webui.editor.WEditor#getDisplay()
+ */
+ @Override
+ public String getDisplay() {
+ schedulerState=0;
+ MScheduler scheduler = new MScheduler(Env.getCtx(), getAD_Scheduler_ID(), null);
+ IServerManager serverMgr = getServerMgr();
+ schedulerState = serverMgr.getServerStatus(scheduler.getServerID());
+ String label = null;
+ if (schedulerState == IServerManager.SERVER_STATE_NOT_SCHEDULE)
+ label = Msg.getMsg(Env.getCtx(), "SchedulerNotSchedule");
+ else if (schedulerState == IServerManager.SERVER_STATE_STARTED)
+ label = Msg.getMsg(Env.getCtx(), "SchedulerStarted");
+ else if (schedulerState == IServerManager.SERVER_STATE_STOPPED)
+ label = Msg.getMsg(Env.getCtx(), "SchedulerStopped");
+ else
+ label = "-";
+
+ return label;
+ }
+
+ @Override
+ public Button getComponent() {
+ return (Button) component;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.webui.editor.WEditor#isSearchable()
+ */
+ @Override
+ public boolean isSearchable() {
+ return false;
+ }
+
+ private IServerManager getServerMgr() {
+ IServerManager serverMgr = null;
+ IServiceHolder holder = Service.locator().locate(IClusterService.class);
+ IClusterService service = holder != null ? holder.getService() : null;
+ if (service != null)
+ serverMgr = ClusterServerMgr.getInstance();
+ else
+ serverMgr = AdempiereServerMgr.get(false);
+ return serverMgr;
+ }
+}
+
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/scheduler/SchedulerStateEditorFactory.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/scheduler/SchedulerStateEditorFactory.java
new file mode 100644
index 0000000000..0c05419d8c
--- /dev/null
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/scheduler/SchedulerStateEditorFactory.java
@@ -0,0 +1,58 @@
+/**********************************************************************
+* 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: *
+* - Trek Global Corporation *
+* - Heng Sin Low *
+**********************************************************************/
+package org.adempiere.webui.scheduler;
+
+import org.adempiere.webui.editor.WEditor;
+import org.adempiere.webui.factory.IEditorFactory;
+import org.compiere.model.GridField;
+import org.compiere.model.GridTab;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * @author hengsin
+ *
+ */
+@Component(name = "org.adempiere.webui.scheduler.SchedulerStateEditorFactory", service = {IEditorFactory.class},
+ property = {"service.ranking:Integer=1"})
+public class SchedulerStateEditorFactory implements IEditorFactory {
+
+ private final static int SCHEDULER_STATE_AD_REFERENCE_ID = 200173;
+
+ /**
+ * default constructor
+ */
+ public SchedulerStateEditorFactory() {
+ }
+
+ @Override
+ public WEditor getEditor(GridTab gridTab, GridField gridField, boolean tableEditor) {
+ if (gridField != null && gridField.getDisplayType() == SCHEDULER_STATE_AD_REFERENCE_ID) {
+ return new SchedulerStateEditor(gridField);
+ }
+ return null;
+ }
+
+}