Bug 427546 - SmartField Menu Button (Arrow) is enabled initialy also whitout any Menus defined

https://bugs.eclipse.org/bugs/show_bug.cgi?id=427546

Add property change listener on actions.
Enable handle drop down when enabling scout field.

Change-Id: I925ff2f85de6f460bb54e1aeb8bff8205cdb64e3
Reviewed-on: https://git.eclipse.org/r/23210
Reviewed-by: Matthias Villiger <mvi@bsiag.com>
Reviewed-by: Ken Lee <kle@bsiag.com>
IP-Clean: Ken Lee <kle@bsiag.com>
Tested-by: Ken Lee <kle@bsiag.com>
diff --git a/org.eclipse.scout.rt.ui.rap.incubator.filechooser/src/org/eclipse/scout/rt/ui/rap/form/fields/filechooserfield/IRwtScoutFileUploadField.java b/org.eclipse.scout.rt.ui.rap.incubator.filechooser/src/org/eclipse/scout/rt/ui/rap/form/fields/filechooserfield/IRwtScoutFileUploadField.java
index 6b15db9..417d248 100644
--- a/org.eclipse.scout.rt.ui.rap.incubator.filechooser/src/org/eclipse/scout/rt/ui/rap/form/fields/filechooserfield/IRwtScoutFileUploadField.java
+++ b/org.eclipse.scout.rt.ui.rap.incubator.filechooser/src/org/eclipse/scout/rt/ui/rap/form/fields/filechooserfield/IRwtScoutFileUploadField.java
@@ -17,7 +17,7 @@
 
 public interface IRwtScoutFileUploadField extends IRwtScoutFormField<IFileChooserField> {
 
-  String VARIANT_FILECHOOSER = "filechooserfield";
+  String VARIANT_FILECHOOSER = "filechooserfield_file";
   String VARIANT_DISABLED_SUFFIX = "-disabled";
 
   IDropDownFileUploadForPatch getUiBrowseButton();
diff --git a/org.eclipse.scout.rt.ui.rap.incubator.filechooser/src/org/eclipse/scout/rt/ui/rap/form/fields/filechooserfield/RwtScoutFileUploadField.java b/org.eclipse.scout.rt.ui.rap.incubator.filechooser/src/org/eclipse/scout/rt/ui/rap/form/fields/filechooserfield/RwtScoutFileUploadField.java
index d0e4a91..c56a1c8 100644
--- a/org.eclipse.scout.rt.ui.rap.incubator.filechooser/src/org/eclipse/scout/rt/ui/rap/form/fields/filechooserfield/RwtScoutFileUploadField.java
+++ b/org.eclipse.scout.rt.ui.rap.incubator.filechooser/src/org/eclipse/scout/rt/ui/rap/form/fields/filechooserfield/RwtScoutFileUploadField.java
@@ -10,11 +10,14 @@
  *******************************************************************************/
 package org.eclipse.scout.rt.ui.rap.form.fields.filechooserfield;
 
+import java.beans.PropertyChangeEvent;
 import java.io.File;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.service.ServerPushSession;
 import org.eclipse.rap.rwt.supplemental.fileupload.DiskFileUploadReceiver;
 import org.eclipse.rap.rwt.supplemental.fileupload.FileUploadEvent;
 import org.eclipse.rap.rwt.supplemental.fileupload.FileUploadHandler;
@@ -28,12 +31,14 @@
 import org.eclipse.scout.commons.job.JobEx;
 import org.eclipse.scout.commons.logger.IScoutLogger;
 import org.eclipse.scout.commons.logger.ScoutLogManager;
+import org.eclipse.scout.rt.client.ui.action.IAction;
 import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
 import org.eclipse.scout.rt.client.ui.form.fields.IFormField;
 import org.eclipse.scout.rt.client.ui.form.fields.ScoutFieldStatus;
 import org.eclipse.scout.rt.client.ui.form.fields.filechooserfield.IFileChooserField;
 import org.eclipse.scout.rt.ui.rap.LogicalGridLayout;
 import org.eclipse.scout.rt.ui.rap.RwtMenuUtility;
+import org.eclipse.scout.rt.ui.rap.action.AbstractRwtScoutActionPropertyChangeListener;
 import org.eclipse.scout.rt.ui.rap.ext.IDropDownFileUploadForPatch;
 import org.eclipse.scout.rt.ui.rap.ext.MenuAdapterEx;
 import org.eclipse.scout.rt.ui.rap.ext.StatusLabelEx;
@@ -73,8 +78,9 @@
   private TextFieldEditableSupport m_editableSupport;
 
   private FileUploadHandler m_handler;
-  private FileUploadListener m_uploadListener;
+  private P_FileUploadListener m_uploadListener;
   private File m_uploadedFile = null;
+  private P_ScoutActionPropertyChangeListener m_scoutActionPropertyListener;
 
   private String m_originalVariant = "";
 
@@ -114,16 +120,13 @@
     setUiLabel(label);
     setUiField(textField);
 
-    createProgressBar();
     createBrowseButton();
 
     // prevent the button from grabbing focus
     m_fileContainer.setTabList(new Control[]{textField});
 
     // context menu
-    m_contextMenu = new Menu(getUiBrowseButton().getShell(), SWT.POP_UP);
-    m_contextMenu.addMenuListener(new P_ContextMenuListener());
-    getUiBrowseButton().setMenu(m_contextMenu);
+    createContextMenu(getUiBrowseButton());
 
     // layout
     container.setLayout(new LogicalGridLayout(1, 0));
@@ -138,6 +141,15 @@
     textField.setLayoutData(textLayoutData);
   }
 
+  private void createContextMenu(IDropDownFileUploadForPatch uiBrowseButton) {
+    if (m_contextMenu != null && !m_contextMenu.isDisposed()) {
+      m_contextMenu.dispose();
+    }
+    m_contextMenu = new Menu(uiBrowseButton.getShell(), SWT.POP_UP);
+    m_contextMenu.addMenuListener(new P_ContextMenuListener());
+    uiBrowseButton.setMenu(m_contextMenu);
+  }
+
   private void createBrowseButton() {
     m_browseButton = getUiEnvironment().getFormToolkit().createDropDownFileUpload(m_fileContainer, SWT.DROP_DOWN);
     m_browseButton.setData(RWT.CUSTOM_VARIANT, VARIANT_FILECHOOSER);
@@ -184,6 +196,7 @@
     getUiBrowseButton().setLayoutData(buttonLayoutData);
 
     setEnabledFromScout(getScoutObject().isEnabled());
+    m_browseButton.setDropdownEnabled(calculateDropDownButtonEnabled());
     m_fileContainer.layout();
   }
 
@@ -264,16 +277,30 @@
   protected void attachScout() {
     super.attachScout();
     setFileIconIdFromScout(getScoutObject().getFileIconId());
-    getUiBrowseButton().setDropdownEnabled(getScoutObject().hasMenus());
+    getUiBrowseButton().setDropdownEnabled(calculateDropDownButtonEnabled());
     if (getScoutObject().isFolderMode()) {
       String msg = "IFileChooserField.isFolderMode() == true is not possible in RAP";
       LOG.error(msg);
       getUiLabel().setStatus(new ProcessingStatus(msg, IProcessingStatus.ERROR));
     }
+    if (m_scoutActionPropertyListener == null) {
+      m_scoutActionPropertyListener = new P_ScoutActionPropertyChangeListener();
+    }
+    m_scoutActionPropertyListener.attachToScoutMenus(getScoutObject().getMenus());
+  }
+
+  @Override
+  protected void detachScout() {
+    if (m_scoutActionPropertyListener != null) {
+      m_scoutActionPropertyListener.detachFromScoutMenus(getScoutObject().getMenus());
+      m_scoutActionPropertyListener = null;
+    }
+    super.detachScout();
   }
 
   @Override
   protected void setDisplayTextFromScout(String s) {
+    getUiBrowseButton().setDropdownEnabled(calculateDropDownButtonEnabled());
     if (s == null) {
       s = "";
     }
@@ -282,12 +309,31 @@
     getUiField().setCaretOffset(0);
   }
 
+  private boolean calculateDropDownButtonEnabled() {
+    final AtomicBoolean hasValidMenus = new AtomicBoolean(false);
+    Runnable t = new Runnable() {
+      @Override
+      public void run() {
+        hasValidMenus.set(getScoutObject().getUIFacade().hasValidMenusFromUI());
+      }
+    };
+    JobEx job = getUiEnvironment().invokeScoutLater(t, 1200);
+    try {
+      job.join(1200);
+    }
+    catch (InterruptedException ex) {
+      //nop
+    }
+    return hasValidMenus.get();
+  }
+
   @Override
   protected void setEnabledFromScout(boolean b) {
     super.setEnabledFromScout(b);
     getUiBrowseButton().setButtonEnabled(b);
     //textfield must be disabled. We can't upload the file from it for now.
     getUiField().setEnabled(false);
+    handleDropDownButtonEnabled();
 
     if (!StringUtility.hasText(m_originalVariant)) {
       m_originalVariant = (String) m_fileContainer.getData(RWT.CUSTOM_VARIANT);
@@ -361,7 +407,9 @@
     if (m_uploadListener == null) {
       m_uploadListener = new P_FileUploadListener();
     }
+    m_uploadListener.startUpload();
     m_handler.addUploadListener(m_uploadListener);
+    createProgressBar();
     getUiBrowseButton().submit(url);
   }
 
@@ -371,6 +419,7 @@
     }
     if (m_uploadListener != null) {
       m_handler.removeUploadListener(m_uploadListener);
+      m_uploadListener.cancelUpload();
       m_uploadListener = null;
     }
     m_handler.dispose();
@@ -380,8 +429,9 @@
 
     initializeFileUpload();
 
-    createProgressBar();
     createBrowseButton();
+    createContextMenu(getUiBrowseButton());
+
     return true;
   }
 
@@ -393,6 +443,17 @@
     }
   }
 
+  protected void handleScoutActionPropertyChange(String name, Object newValue) {
+    if (IAction.PROP_INHERIT_ACCESSIBILITY.equals(name) || IAction.PROP_EMPTY_SPACE.equals(name) ||
+        IAction.PROP_SINGLE_SELECTION.equals(name) || IAction.PROP_VISIBLE.equals(name)) {
+      handleDropDownButtonEnabled();
+    }
+  }
+
+  protected void handleDropDownButtonEnabled() {
+    getUiBrowseButton().setDropdownEnabled(calculateDropDownButtonEnabled());
+  }
+
   private class P_ContextMenuListener extends MenuAdapterEx {
 
     private static final long serialVersionUID = 1L;
@@ -455,14 +516,36 @@
 
   private class P_FileUploadListener implements FileUploadListener {
 
+    private final ServerPushSession m_pushSession;
+    private int m_oldPercentage = 0;
+
+    public P_FileUploadListener() {
+      m_pushSession = new ServerPushSession();
+    }
+
+    public void startUpload() {
+      m_pushSession.start();
+    }
+
+    public void cancelUpload() {
+      m_pushSession.stop();
+    }
+
+    private int getPercentage(FileUploadEvent uploadEvent) {
+      double bytesRead = uploadEvent.getBytesRead();
+      double contentLength = uploadEvent.getContentLength();
+      double fraction = bytesRead / contentLength;
+      return (int) Math.floor(fraction * 100);
+    }
+
     @Override
     public void uploadProgress(final FileUploadEvent uploadEvent) {
       getUiEnvironment().getDisplay().asyncExec(new Runnable() {
         @Override
         public void run() {
-          double fraction = uploadEvent.getBytesRead() / (double) uploadEvent.getContentLength();
-          int percent = (int) Math.floor(fraction * 100);
-          if (getUiProgressBar() != null && !getUiProgressBar().isDisposed()) {
+          int percent = getPercentage(uploadEvent);
+          if (percent != m_oldPercentage && getUiProgressBar() != null && !getUiProgressBar().isDisposed()) {
+            m_oldPercentage = percent;
             getUiProgressBar().setSelection(percent);
             getUiProgressBar().setToolTipText("Upload progress: " + percent + "%");
           }
@@ -486,14 +569,13 @@
       getUiEnvironment().getDisplay().asyncExec(new Runnable() {
         @Override
         public void run() {
-          int percent = 0;
           if (getUiProgressBar() != null && !getUiProgressBar().isDisposed()) {
-            getUiProgressBar().setSelection(percent);
-            getUiProgressBar().setToolTipText("");
+            getUiProgressBar().dispose();
           }
           m_handler.removeUploadListener(m_uploadListener);
         }
       });
+      m_pushSession.stop();
     }
 
     @Override
@@ -504,9 +586,37 @@
           if (getUiLabel() != null) {
             getUiLabel().setStatus(new ScoutFieldStatus(uploadEvent.getException().getMessage(), IStatus.ERROR));
           }
+          if (getUiProgressBar() != null && !getUiProgressBar().isDisposed()) {
+            getUiProgressBar().dispose();
+          }
           m_handler.removeUploadListener(m_uploadListener);
         }
       });
+      m_pushSession.stop();
     }
   }
+
+  private class P_ScoutActionPropertyChangeListener extends AbstractRwtScoutActionPropertyChangeListener {
+    @Override
+    public void propertyChange(final PropertyChangeEvent e) {
+      if (getUiEnvironment().getDisplay() != null && !getUiEnvironment().getDisplay().isDisposed()) {
+        Runnable t = new Runnable() {
+          @Override
+          public void run() {
+            if (!isUiDisposed()) {
+              try {
+                getUpdateUiFromScoutLock().acquire();
+                //
+                handleScoutActionPropertyChange(e.getPropertyName(), e.getNewValue());
+              }
+              finally {
+                getUpdateUiFromScoutLock().release();
+              }
+            }
+          }
+        };
+        getUiEnvironment().invokeUiLater(t);
+      }
+    }
+  } // end class P_ScoutActionPropertyChangeListener
 }