bug 411266: Allow context menus on all FormFields 
https://bugs.eclipse.org/bugs/show_bug.cgi?id=411266
Swt & RAP

Change-Id: Ic62739eb6a007277bf672b98ee035919eacd5806
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 417d248..4cf969e 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
@@ -11,7 +11,7 @@
 package org.eclipse.scout.rt.ui.rap.form.fields.filechooserfield;
 
 import org.eclipse.scout.rt.client.ui.form.fields.filechooserfield.IFileChooserField;
-import org.eclipse.scout.rt.ui.rap.ext.IDropDownFileUploadForPatch;
+import org.eclipse.scout.rt.ui.rap.ext.DropDownFileUpload;
 import org.eclipse.scout.rt.ui.rap.form.fields.IRwtScoutFormField;
 import org.eclipse.swt.widgets.ProgressBar;
 
@@ -20,7 +20,7 @@
   String VARIANT_FILECHOOSER = "filechooserfield_file";
   String VARIANT_DISABLED_SUFFIX = "-disabled";
 
-  IDropDownFileUploadForPatch getUiBrowseButton();
+  DropDownFileUpload getUiBrowseButton();
 
   ProgressBar getUiProgressBar();
 
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 abde997..e6e14fd 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
@@ -11,9 +11,6 @@
 package org.eclipse.scout.rt.ui.rap.form.fields.filechooserfield;
 
 import java.io.File;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.rap.addons.fileupload.DiskFileUploadReceiver;
@@ -31,14 +28,13 @@
 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.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.ext.IDropDownFileUploadForPatch;
-import org.eclipse.scout.rt.ui.rap.ext.MenuAdapterEx;
+import org.eclipse.scout.rt.ui.rap.action.menu.RwtContextMenuMarkerComposite;
+import org.eclipse.scout.rt.ui.rap.action.menu.RwtScoutContextMenu;
+import org.eclipse.scout.rt.ui.rap.ext.DropDownFileUpload;
 import org.eclipse.scout.rt.ui.rap.ext.StatusLabelEx;
 import org.eclipse.scout.rt.ui.rap.ext.StyledTextEx;
 import org.eclipse.scout.rt.ui.rap.ext.custom.StyledText;
@@ -50,7 +46,6 @@
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.FocusAdapter;
 import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.MenuEvent;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.events.SelectionAdapter;
@@ -62,23 +57,22 @@
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.swt.widgets.ProgressBar;
 
 public class RwtScoutFileUploadField extends RwtScoutValueFieldComposite<IFileChooserField> implements IRwtScoutFileUploadField {
   private static final IScoutLogger LOG = ScoutLogManager.getLogger(RwtScoutFileUploadField.class);
 
   private Composite m_fileContainer;
-  private IDropDownFileUploadForPatch m_browseButton;
+  private DropDownFileUpload m_browseButton;
   private ProgressBar m_progressBar;
-  private Menu m_contextMenu;
   private TextFieldEditableSupport m_editableSupport;
 
   private FileUploadHandler m_handler;
   private P_FileUploadListener m_uploadListener;
   private File m_uploadedFile = null;
 
+  private RwtContextMenuMarkerComposite m_markerComposite;
+
   private String m_originalVariant = "";
 
   public RwtScoutFileUploadField() {
@@ -94,7 +88,9 @@
     m_fileContainer = getUiEnvironment().getFormToolkit().createComposite(container, SWT.BORDER);
     m_fileContainer.setData(RWT.CUSTOM_VARIANT, VARIANT_FILECHOOSER);
 
-    StyledText textField = new StyledTextEx(m_fileContainer, SWT.SINGLE | getUiEnvironment().getFormToolkit().getOrientation()) {
+    m_markerComposite = new RwtContextMenuMarkerComposite(m_fileContainer, getUiEnvironment(), SWT.NONE);
+    getUiEnvironment().getFormToolkit().adapt(m_markerComposite);
+    StyledText textField = new StyledTextEx(m_markerComposite, SWT.SINGLE | getUiEnvironment().getFormToolkit().getOrientation()) {
       private static final long serialVersionUID = 1L;
 
       @Override
@@ -120,10 +116,7 @@
     createBrowseButton();
 
     // prevent the button from grabbing focus
-    m_fileContainer.setTabList(new Control[]{textField});
-
-    // context menu
-    createContextMenu(getUiBrowseButton());
+    m_fileContainer.setTabList(new Control[]{m_markerComposite});
 
     // layout
     container.setLayout(new LogicalGridLayout(1, 0));
@@ -132,19 +125,10 @@
     m_fileContainer.setLayout(new FormLayout());
 
     final FormData textLayoutData = new FormData(SWT.DEFAULT, SWT.DEFAULT);
-    textLayoutData.right = new FormAttachment(100, -20);
     textLayoutData.left = new FormAttachment(0, 0);
-    textLayoutData.bottom = new FormAttachment(textField, -1, SWT.BOTTOM);
-    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);
+    textLayoutData.right = new FormAttachment(100, -20);
+    textLayoutData.bottom = new FormAttachment(m_markerComposite, -1, SWT.BOTTOM);
+    m_markerComposite.setLayoutData(textLayoutData);
   }
 
   private void createBrowseButton() {
@@ -186,14 +170,14 @@
     });
 
     final FormData buttonLayoutData = new FormData(SWT.DEFAULT, SWT.DEFAULT);
-    buttonLayoutData.left = new FormAttachment(getUiField(), 0, SWT.RIGHT);
+    buttonLayoutData.left = new FormAttachment(m_markerComposite, 0, SWT.RIGHT);
     buttonLayoutData.bottom = new FormAttachment((Control) getUiBrowseButton(), 0, SWT.BOTTOM);
     buttonLayoutData.height = 20;
     buttonLayoutData.width = 20;
     getUiBrowseButton().setLayoutData(buttonLayoutData);
 
     setEnabledFromScout(getScoutObject().isEnabled());
-    m_browseButton.setDropdownEnabled(calculateDropDownButtonEnabled());
+//    m_browseButton.setDropdownEnabled(calculateDropDownButtonEnabled());
     m_fileContainer.layout();
   }
 
@@ -213,6 +197,14 @@
   }
 
   @Override
+  protected void installContextMenu() {
+    RwtScoutContextMenu contextMenu = new RwtScoutContextMenu(getUiField().getShell(), getScoutObject().getContextMenu(), m_markerComposite, getUiEnvironment());
+    if (getUiBrowseButton() != null) {
+      getUiBrowseButton().setMenu(contextMenu.getUiMenu());
+    }
+  }
+
+  @Override
   public void disposeImpl() {
     if (m_uploadListener != null) {
       m_handler.removeUploadListener(m_uploadListener);
@@ -234,7 +226,7 @@
   }
 
   @Override
-  public IDropDownFileUploadForPatch getUiBrowseButton() {
+  public DropDownFileUpload getUiBrowseButton() {
     return m_browseButton;
   }
 
@@ -274,7 +266,6 @@
   protected void attachScout() {
     super.attachScout();
     setFileIconIdFromScout(getScoutObject().getFileIconId());
-    getUiBrowseButton().setDropdownEnabled(calculateDropDownButtonEnabled());
     if (getScoutObject().isFolderMode()) {
       String msg = "IFileChooserField.isFolderMode() == true is not possible in RAP";
       LOG.error(msg);
@@ -284,33 +275,16 @@
 
   @Override
   protected void setDisplayTextFromScout(String s) {
-    getUiBrowseButton().setDropdownEnabled(calculateDropDownButtonEnabled());
+//    getUiBrowseButton().setDropdownEnabled(calculateDropDownButtonEnabled());
     if (s == null) {
       s = "";
     }
     getUiField().setText(s);
+    System.out.println(getUiField().getText());
     super.handleUiFocusGained();
     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);
@@ -406,14 +380,21 @@
       m_uploadListener = null;
     }
     m_handler.dispose();
-    getUiBrowseButton().dispose();
-    getUiProgressBar().dispose();
+
+    DropDownFileUpload uiBrowseButton = getUiBrowseButton();
+    if (uiBrowseButton != null && !uiBrowseButton.isDisposed()) {
+      uiBrowseButton.dispose();
+    }
+
+    ProgressBar uiProgressBar = getUiProgressBar();
+    if (uiProgressBar != null && !uiProgressBar.isDisposed()) {
+      uiProgressBar.dispose();
+    }
     getUiField().setText("");
 
     initializeFileUpload();
 
     createBrowseButton();
-    createContextMenu(getUiBrowseButton());
 
     return true;
   }
@@ -426,66 +407,6 @@
     }
   }
 
-  private class P_ContextMenuListener extends MenuAdapterEx {
-
-    private static final long serialVersionUID = 1L;
-
-    public P_ContextMenuListener() {
-      super((Control) RwtScoutFileUploadField.this.getUiBrowseButton(), RwtScoutFileUploadField.this.getUiBrowseButton().getParent());
-    }
-
-    @Override
-    public void menuShown(MenuEvent e) {
-      super.menuShown(e);
-      /*
-       * Since the FileUpload widget does fire a MouseEvent when it is clicked on, we do not know if the right mouse button has been clicked or not.
-       * Therefore, a MenuDetect listener cannot be attached. The creation of the menu is done once after initialization.
-       * While handling the menuShown, the menu (event source) might already contain contributed Scout menus from the previous right mouse click. To
-       * avoid the menus being added several times, the menu items are removed first before the Scout menus are contributed.
-       */
-      Menu contextMenu = (Menu) e.getSource();
-      cleanUpMenuItems(contextMenu);
-
-      final AtomicReference<List<IMenu>> scoutMenusRef = new AtomicReference<List<IMenu>>();
-      Runnable t = new Runnable() {
-        @Override
-        public void run() {
-          List<IMenu> scoutMenus = getScoutObject().getUIFacade().firePopupFromUI();
-          scoutMenusRef.set(scoutMenus);
-        }
-      };
-      JobEx job = RwtScoutFileUploadField.this.getUiEnvironment().invokeScoutLater(t, 1200);
-      try {
-        job.join(1200);
-      }
-      catch (InterruptedException ex) {
-        //nop
-      }
-      // grab the actions out of the job, when the actions are providden within
-      // the scheduled time the popup will be handled.
-      if (scoutMenusRef.get() != null) {
-        RwtMenuUtility.fillContextMenu(scoutMenusRef.get(), RwtScoutFileUploadField.this.getUiEnvironment(), contextMenu);
-      }
-    }
-
-    protected void cleanUpMenuItems(Menu menu) {
-      for (MenuItem menuItem : menu.getItems()) {
-        disposeMenuItem(menuItem);
-      }
-    }
-
-    protected void disposeMenuItem(MenuItem item) {
-      Menu menu = item.getMenu();
-      if (menu != null) {
-        for (MenuItem childItem : menu.getItems()) {
-          disposeMenuItem(childItem);
-        }
-        menu.dispose();
-      }
-      item.dispose();
-    }
-  } // end class P_ContextMenuListener
-
   private class P_FileUploadListener implements FileUploadListener {
 
     private final ServerPushSession m_pushSession;