public boolean handleChange(Object oldValue, Object newValue, IFigure figure) {
        IPV oldPV = pvMap.get(pvNamePropID);
        if (oldPV != null) {
          oldPV.stop();
          oldPV.removeListener(pvListenerMap.get(pvNamePropID));
        }
        pvMap.remove(pvNamePropID);
        String newPVName = ((String) newValue).trim();
        if (newPVName.length() <= 0) return false;
        try {
          lastWriteAccess = null;
          IPV newPV = BOYPVFactory.createPV(newPVName, isAllValuesBuffered);
          WidgetPVListener pvListener = new WidgetPVListener(pvNamePropID);
          newPV.addListener(pvListener);
          pvMap.put(pvNamePropID, newPV);
          pvListenerMap.put(pvNamePropID, pvListener);

          newPV.start();
        } catch (Exception e) {
          OPIBuilderPlugin.getLogger()
              .log(
                  Level.WARNING,
                  "Unable to connect to PV:"
                      + //$NON-NLS-1$
                      newPVName,
                  e);
        }

        return false;
      }
 public void doActivate() {
   if (editpart.getExecutionMode() == ExecutionMode.RUN_MODE) {
     pvMap.clear();
     final Map<StringProperty, PVValueProperty> pvPropertyMap =
         editpart.getWidgetModel().getPVMap();
     for (final StringProperty sp : pvPropertyMap.keySet()) {
       if (sp.getPropertyValue() == null
           || ((String) sp.getPropertyValue()).trim().length() <= 0) {
         continue;
       }
       try {
         IPV pv = BOYPVFactory.createPV((String) sp.getPropertyValue(), isAllValuesBuffered);
         pvMap.put(sp.getPropertyID(), pv);
         WidgetPVListener pvListener = new WidgetPVListener(sp.getPropertyID());
         pv.addListener(pvListener);
         pvListenerMap.put(sp.getPropertyID(), pvListener);
       } catch (Exception e) {
         OPIBuilderPlugin.getLogger()
             .log(
                 Level.WARNING,
                 "Unable to connect to PV:" + (String) sp.getPropertyValue(),
                 e); //$NON-NLS-1$
       }
     }
   }
 }
 @SuppressWarnings("deprecation")
 public void run(IAction action) {
   try {
     if (window == null) window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
     final IWorkbenchPage page = window.getActivePage();
     page.showView(IPageLayout.ID_RES_NAV);
   } catch (WorkbenchException e) {
     final String message = NLS.bind("Failed to open navigator. \n{0}", e.getMessage());
     MessageDialog.openError(null, "Error", message);
     OPIBuilderPlugin.getLogger().log(Level.WARNING, message, e);
   }
 }
 /** Start all PVs. This should be called as the last step in editpart.activate(). */
 public void startPVs() {
   // the pv should be started at the last minute
   for (String pvPropId : pvMap.keySet()) {
     IPV pv = pvMap.get(pvPropId);
     try {
       pv.start();
     } catch (Exception e) {
       OPIBuilderPlugin.getLogger()
           .log(Level.WARNING, "Unable to connect to PV:" + pv.getName(), e); // $NON-NLS-1$
     }
   }
 }
Beispiel #5
0
 /**
  * Render a new OPI in the same shell. The file path changes but the macros remain the same. Is
  * this correct?
  */
 @Override
 public void setOPIInput(IEditorInput input) throws PartInitException {
   try {
     if (input instanceof IFileEditorInput) {
       this.path = ((IFileEditorInput) input).getFile().getFullPath();
     } else if (input instanceof RunnerInput) {
       this.path = ((RunnerInput) input).getPath();
     }
     displayModel = createDisplayModel();
     setTitle();
     resizeToContents();
   } catch (Exception e) {
     OPIBuilderPlugin.getLogger().log(Level.WARNING, "Failed to replace OPIShell contents.", e);
   }
 }
  @Override
  public void activate() {
    if (!isActive()) {
      super.activate();
      initFigure(getFigure());

      // add listener to all properties.
      for (String id : getWidgetModel().getAllPropertyIDs()) {

        AbstractWidgetProperty property = getWidgetModel().getProperty(id);
        if (property != null) {
          WidgetPropertyChangeListener listener = new WidgetPropertyChangeListener(this, property);
          property.addPropertyChangeListener(listener);
          propertyListenerMap.put(id, listener);

          property.setExecutionMode(executionMode);
          property.setWidgetModel(getWidgetModel());
        }
      }
      registerBasePropertyChangeHandlers();
      registerPropertyChangeHandlers();

      if (executionMode == ExecutionMode.RUN_MODE) {
        // hook open display action
        Set<String> allPropIds = getWidgetModel().getAllPropertyIDs();
        if (allPropIds.contains(AbstractWidgetModel.PROP_ACTIONS)
            && allPropIds.contains(AbstractWidgetModel.PROP_ENABLED)) {
          hookMouseClickAction();
        }

        // script and rules execution
        ScriptsInput scriptsInput = getWidgetModel().getScriptsInput();
        scriptDataList = new ArrayList<ScriptData>(scriptsInput.getScriptList());
        for (RuleData rd : getWidgetModel().getRulesInput().getRuleDataList()) {
          scriptDataList.add(rd.convertToScriptData());
        }
        for (final ScriptData scriptData : scriptDataList) {
          final IPV[] pvArray = new IPV[scriptData.getPVList().size()];
          int i = 0;
          for (PVTuple pvTuple : scriptData.getPVList()) {
            String pvName = pvTuple.pvName;
            if (pvMap.containsKey(pvName)) {
              pvArray[i] = pvMap.get(pvName);
            } else {
              try {
                IPV pv = BOYPVFactory.createPV(pvName, false, 2);
                pvMap.put(pvName, pv);
                addToConnectionHandler(pvName, pv);
                pvArray[i] = pv;
              } catch (Exception e) {
                String message =
                    NLS.bind(
                        "Unable to connect to PV: {0}! \n"
                            + "This may cause error when executing the script.",
                        pvName);
                OPIBuilderPlugin.getLogger().log(Level.WARNING, message, e);
                ConsoleService.getInstance().writeError(message);
                pvArray[i] = null;
              }
            }
            i++;
          }

          ScriptService.getInstance()
              .registerScript(scriptData, AbstractBaseEditPart.this, pvArray);

          UIBundlingThread.getInstance()
              .addRunnable(
                  new Runnable() {
                    @Override
                    public void run() {
                      if (!isActive()) {
                        // already deactivated
                        return;
                      }
                      hasStartedPVs = true;
                      for (IPV pv : pvArray)
                        if (pv != null && !pv.isStarted())
                          try {
                            pv.start();
                          } catch (Exception e) {
                            OPIBuilderPlugin.getLogger()
                                .log(
                                    Level.WARNING,
                                    "Unable to start PV " + pv.getName(),
                                    e); //$NON-NLS-1$
                          }
                    }
                  });
        }
      }
      doActivate();
    }

    // Rap specified code
    displayDisposeListener =
        new Runnable() {

          @Override
          public void run() {
            deactivate();
          }
        };
    SingleSourceHelper.rapActivateBaseEditPart(this);
  }
Beispiel #7
0
/**
 * An OPIShell is a CS-Studio OPI presented in an SWT shell, which allows more free integration with
 * the host operating system. In most ways it behaves like an OPIView.
 *
 * <p>All OPIShells are maintained in a static set within this class. To maintain a cache of all
 * shells, construction is limited to a static method. The private constructor means that this class
 * cannot be extended.
 *
 * <p>In order for the OPIShell to be integrated with Eclipse functionality, in particular the
 * right-click context menu, it needs to be registered against an existing IViewPart.
 *
 * @author Will Rogers, Matthew Furseman
 */
public final class OPIShell implements IOPIRuntime {

  // Estimates for the size of a window border, for how much
  // bigger to make a shell than the size of its contents.
  private static final int WINDOW_BORDER_X = 30;
  private static final int WINDOW_BORDER_Y = 30;

  private static Logger log = OPIBuilderPlugin.getLogger();
  public static final String OPI_SHELLS_CHANGED_ID = "org.csstudio.opibuilder.opiShellsChanged";
  // Cache of open OPI shells in order of opening.
  private static final Set<OPIShell> openShells = new LinkedHashSet<OPIShell>();
  // The view against which the context menu is registered.
  private IViewPart view;

  // Variables that do not change for any shell.
  private final Image icon;
  private final Shell shell;
  private final ActionRegistry actionRegistry;
  private final GraphicalViewer viewer;
  // Variables that change if OPI input is changed.
  private DisplayModel displayModel;
  private IPath path;
  // macrosInput should not be null.  If there are no macros it should
  // be an empty MacrosInput object.
  private MacrosInput macrosInput;

  // Private constructor means you can't open an OPIShell without adding
  // it to the cache.
  private OPIShell(Display display, IPath path, MacrosInput macrosInput) throws Exception {
    this.path = path;
    this.macrosInput = macrosInput;
    icon =
        OPIBuilderPlugin.imageDescriptorFromPlugin(
                OPIBuilderPlugin.PLUGIN_ID, "icons/OPIRunner.png")
            .createImage(display);

    shell = new Shell(display);
    shell.setImage(icon);
    displayModel = new DisplayModel(path);
    displayModel.setOpiRuntime(this);
    actionRegistry = new ActionRegistry();

    viewer = new GraphicalViewerImpl();
    viewer.createControl(shell);
    viewer.setEditPartFactory(new WidgetEditPartFactory(ExecutionMode.RUN_MODE));
    viewer.setRootEditPart(
        new ScalableFreeformRootEditPart() {
          @Override
          public DragTracker getDragTracker(Request req) {
            return new DragEditPartsTracker(this);
          }

          @Override
          public boolean isSelectable() {
            return false;
          }
        });

    EditDomain editDomain =
        new EditDomain() {
          @Override
          public void loadDefaultTool() {
            setActiveTool(new RuntimePatchedSelectionTool());
          }
        };
    editDomain.addViewer(viewer);

    displayModel = createDisplayModel();
    setTitle();

    shell.setLayout(new FillLayout());
    shell.addShellListener(
        new ShellListener() {
          private boolean firstRun = true;

          public void shellIconified(ShellEvent e) {}

          public void shellDeiconified(ShellEvent e) {}

          public void shellDeactivated(ShellEvent e) {}

          public void shellClosed(ShellEvent e) {
            // Remove this shell from the cache.
            openShells.remove(OPIShell.this);
            sendUpdateCommand();
          }

          public void shellActivated(ShellEvent e) {
            if (firstRun) {
              // Resize the shell after it's open, so we can take into account different window
              // borders.
              // Do this only the first time it's activated.
              resizeToContents();
              shell.setFocus();
              firstRun = false;
            }
          }
        });
    shell.addDisposeListener(
        new DisposeListener() {

          @Override
          public void widgetDisposed(DisposeEvent e) {
            if (!icon.isDisposed()) icon.dispose();
          }
        });
    /*
     * Don't open the Shell here, as it causes SWT to think the window is on top when it really isn't.
     * Wait until the window is open, then call shell.setFocus() in the activated listener.
     *
     * Make some attempt at sizing the shell, sometimes a shell is not given focus and the shellActivated
     * listener callback doesn't resize the window. It's better to have something a little too large as the
     * default. Related to Eclipse bug 96700.
     */
    shell.setSize(
        displayModel.getSize().width + WINDOW_BORDER_X,
        displayModel.getSize().height + WINDOW_BORDER_Y);
    shell.setVisible(true);
  }

  /**
   * In order for the right-click menu to work, this shell must be registered with a view. Register
   * the context menu against the view. Make the view the default.
   *
   * @param view
   */
  public void registerWithView(IViewPart view) {
    this.view = view;
    actionRegistry.registerAction(new RefreshOPIAction(this));
    SingleSourceHelper.registerRCPRuntimeActions(actionRegistry, this);
    OPIRunnerContextMenuProvider contextMenuProvider =
        new OPIRunnerContextMenuProvider(viewer, this);
    getSite().registerContextMenu(contextMenuProvider, viewer);
    viewer.setContextMenu(contextMenuProvider);
  }

  public MacrosInput getMacrosInput() {
    return macrosInput;
  }

  public IPath getPath() {
    return path;
  }

  public void raiseToTop() {
    shell.forceFocus();
    shell.forceActive();
    shell.setFocus();
    shell.setActive();
  }

  @Override
  public boolean equals(Object o) {
    boolean equal = false;
    if (o instanceof OPIShell) {
      OPIShell opiShell = (OPIShell) o;
      equal = opiShell.getMacrosInput().equals(this.getMacrosInput());
      equal &= opiShell.getPath().equals(this.path);
    }
    return equal;
  }

  public void close() {
    shell.close();
    dispose();
  }

  private DisplayModel createDisplayModel() throws Exception {
    displayModel = new DisplayModel(path);
    XMLUtil.fillDisplayModelFromInputStream(ResourceUtil.pathToInputStream(path), displayModel);
    if (macrosInput != null) {
      macrosInput = macrosInput.getCopy();
      macrosInput.getMacrosMap().putAll(displayModel.getMacrosInput().getMacrosMap());
      displayModel.setPropertyValue(AbstractContainerModel.PROP_MACROS, macrosInput);
    }
    viewer.setContents(displayModel);
    displayModel.setViewer(viewer);
    displayModel.setOpiRuntime(this);
    return displayModel;
  }

  private void setTitle() {
    if (displayModel.getName() != null && displayModel.getName().trim().length() > 0) {
      shell.setText(displayModel.getName());
    } else { // If the name doesn't exist, use the OPI path
      shell.setText(path.toString());
    }
  }

  private void resizeToContents() {
    int frameX = shell.getSize().x - shell.getClientArea().width;
    int frameY = shell.getSize().y - shell.getClientArea().height;
    shell.setSize(displayModel.getSize().width + frameX, displayModel.getSize().height + frameY);
  }

  /**
   * *********************************************************** Static helper methods to manage
   * open shells. ***********************************************************
   */

  /** This is the only way to create an OPIShell */
  public static void openOPIShell(IPath path, MacrosInput macrosInput) {
    if (macrosInput == null) {
      macrosInput = new MacrosInput(new LinkedHashMap<String, String>(), false);
    }
    boolean alreadyOpen = false;
    for (OPIShell opiShell : openShells) {
      if (opiShell.getPath().equals(path) && opiShell.getMacrosInput().equals(macrosInput)) {
        opiShell.raiseToTop();
        alreadyOpen = true;
      }
    }
    if (!alreadyOpen) {
      OPIShell os = null;
      try {
        os = new OPIShell(Display.getCurrent(), path, macrosInput);
        openShells.add(os);
        sendUpdateCommand();
      } catch (Exception e) {
        if (os != null) {
          os.dispose();
        }
        log.log(Level.WARNING, "Failed to create new OPIShell.", e);
      }
    }
  }

  /**
   * Close all open OPIShells. Use getAllShells() for a copy of the set, to avoid removing items
   * during iteration.
   */
  public static void closeAll() {
    for (OPIShell s : getAllShells()) {
      s.close();
    }
  }

  /** Show all open OPIShells. */
  public static void showAll() {
    for (OPIShell s : getAllShells()) {
      s.raiseToTop();
    }
  }

  /**
   * Search the cache of open OPIShells to find a match for the input Shell object.
   *
   * <p>Return associated OPIShell or Null if none found
   */
  public static OPIShell getOPIShellForShell(final Shell target) {
    OPIShell foundShell = null;
    if (target != null) {
      for (OPIShell os : openShells) {
        if (os.shell == target) {
          foundShell = os;
          break;
        }
      }
    }
    return foundShell;
  }

  /**
   * Return a copy of the set of open shells. Returning the same instance may lead to problems when
   * closing shells.
   *
   * @return a copy of the set of open shells.
   */
  public static Set<OPIShell> getAllShells() {
    return new LinkedHashSet<OPIShell>(openShells);
  }

  /** Alert whoever is listening that a new OPIShell has been created. */
  private static void sendUpdateCommand() {
    IServiceLocator serviceLocator = PlatformUI.getWorkbench();
    ICommandService commandService =
        (ICommandService) serviceLocator.getService(ICommandService.class);
    try {
      Command command = commandService.getCommand(OPI_SHELLS_CHANGED_ID);
      command.executeWithChecks(new ExecutionEvent());
    } catch (ExecutionException
        | NotHandledException
        | NotEnabledException
        | NotDefinedException e) {
      log.log(Level.WARNING, "Failed to send OPI shells changed command", e);
    }
  }

  /**
   * ****************************************** Partial implementation of IOPIRuntime
   * ******************************************
   */
  @Override
  public void addPropertyListener(IPropertyListener listener) {
    throw new NotImplementedException();
  }

  @Override
  public void createPartControl(Composite parent) {
    throw new NotImplementedException();
  }

  @Override
  public void dispose() {
    shell.dispose();
    actionRegistry.dispose();
  }

  @Override
  public IWorkbenchPartSite getSite() {
    if (view != null) {
      return view.getSite();
    } else {
      return null;
    }
  }

  @Override
  public String getTitle() {
    return shell.getText();
  }

  @Override
  public Image getTitleImage() {
    throw new NotImplementedException();
  }

  @Override
  public String getTitleToolTip() {
    return shell.getToolTipText();
  }

  @Override
  public void removePropertyListener(IPropertyListener listener) {
    throw new NotImplementedException();
  }

  @Override
  public void setFocus() {
    throw new NotImplementedException();
  }

  @SuppressWarnings("rawtypes")
  @Override
  public Object getAdapter(Class adapter) {
    if (adapter == ActionRegistry.class) return this.actionRegistry;
    if (adapter == GraphicalViewer.class) return this.viewer;
    return null;
  }

  @Override
  public void setWorkbenchPartName(String name) {
    throw new NotImplementedException();
  }

  /**
   * Render a new OPI in the same shell. The file path changes but the macros remain the same. Is
   * this correct?
   */
  @Override
  public void setOPIInput(IEditorInput input) throws PartInitException {
    try {
      if (input instanceof IFileEditorInput) {
        this.path = ((IFileEditorInput) input).getFile().getFullPath();
      } else if (input instanceof RunnerInput) {
        this.path = ((RunnerInput) input).getPath();
      }
      displayModel = createDisplayModel();
      setTitle();
      resizeToContents();
    } catch (Exception e) {
      OPIBuilderPlugin.getLogger().log(Level.WARNING, "Failed to replace OPIShell contents.", e);
    }
  }

  @Override
  public IEditorInput getOPIInput() {
    IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(displayModel.getOpiFilePath());
    return new FileEditorInput(file);
  }

  @Override
  public DisplayModel getDisplayModel() {
    return displayModel;
  }

  @Override
  public int hashCode() {
    return Objects.hash(OPIShell.class, macrosInput, path);
  }
}