@Override
  public void run(boolean fork, boolean cancelable, final IRunnableWithProgress request)
      throws InvocationTargetException, InterruptedException {
    if (headless && Display.getCurrent() == null) {
      PlatformGIS.run(request);
      return;
    }

    if (getProgressMonitor() instanceof ProgressMonitorPart) {
      ProgressMonitorPart part = (ProgressMonitorPart) getProgressMonitor();
      if (Display.getCurrent() != null) part.setVisible(true);

      try {
        setEnablement(buttonBar, false);
        if (fork) {
          PlatformGIS.run(request, part);
        } else {
          PlatformGIS.runBlockingOperation(request, part);
        }
      } finally {
        setEnablement(buttonBar, true);
        if (Display.getCurrent() != null && !part.isDisposed()) part.setVisible(false);
      }
    } else {
      if (fork) {
        PlatformGIS.run(request);
      } else {
        PlatformGIS.runBlockingOperation(request, ProgressManager.instance().get());
      }
    }
  }
  /**
   * Runs the dialog in headless mode. The dialog will run headless while the workflow can run.
   *
   * @param monitor
   * @param true if the workflow ran and completed correctly. False if it failed or the user
   *     cancelled (because user interaction was required)
   */
  public boolean runHeadless(IProgressMonitor monitor) {
    try {
      this.headless = true;
      int ticks = getWorkflowWizard().getWorkflow().getStates().length * 10;
      monitor.beginTask(Messages.WorkflowWizardDialog_importTask, ticks);
      // we must ensure that the contents of the dialog (shell) have been
      // creates, needed for wizard pages
      if (getShell() == null) {
        // do in ui thread
        PlatformGIS.syncInDisplayThread(
            new Runnable() {
              public void run() {
                create();
              }
            });
      }

      Workflow pipe = getWizard().getWorkflow();
      pipe.run(new SubProgressMonitor(monitor, ticks));
      final boolean[] result = new boolean[] {true};
      if (!pipe.isFinished()) {
        // show the page corresponding to the current state
        final IWizardPage page = getWizard().getPage(pipe.getCurrentState());
        if (page != null) {
          // ensure the page has a state if it is a DataPipelinePage
          if (page instanceof WorkflowWizardPage) {
            WorkflowWizardPage dpPage = (WorkflowWizardPage) page;
            if (dpPage.getState() == null) dpPage.setState(pipe.getCurrentState());
          }

          PlatformGIS.syncInDisplayThread(
              new Runnable() {
                public void run() {
                  headless = false;
                  showPage(page);
                  if (open() == Window.CANCEL) {
                    result[0] = false;
                  }
                };
              });
        }
      }

      this.headless = false;
      return result[0];
    } finally {
      monitor.done();
    }
  }
  /** Performs the initialization of the workflow. */
  protected void initWorkflow() {
    // start the workflow
    // TODO: This can potentially freeze up the ui if the fist state
    // does alot of work in the #init(IProgressMonitor) method. Perhaps
    // it should be made part of the contract of the dialog that the pipe
    // already be started before open is called.
    final Workflow pipe = getWizard().getWorkflow();
    final IRunnableWithProgress runnable =
        new IRunnableWithProgress() {
          public void run(IProgressMonitor monitor)
              throws InvocationTargetException, InterruptedException {
            if (!pipe.started) pipe.start(monitor);
          }
        };

    if (Display.getCurrent() != null) {
      try {
        runnable.run(ProgressManager.instance().get());
      } catch (Exception e) {
        throw (RuntimeException) new RuntimeException().initCause(e);
      }
    } else {
      PlatformGIS.syncInDisplayThread(
          new Runnable() {
            public void run() {
              try {
                PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(false, false, runnable);
              } catch (Throwable e) {
                throw new RuntimeException(e);
              }
            }
          });
    }
  }
  private static Collection<String> extractEPSG(
      final IMap map, final CoordinateReferenceSystem crs) {

    if (CRS.equalsIgnoreMetadata(crs, DefaultGeographicCRS.WGS84)) {
      return Collections.singleton(EPSG_4326);
    }
    final Collection<String> codes = new HashSet<String>();
    codes.addAll(CRSUtil.extractAuthorityCodes(crs));

    final String DONT_FIND = "DONT_FIND";
    boolean search = map.getBlackboard().get(EPSG_CODE) != DONT_FIND;
    if (codes.isEmpty() && search) {
      PlatformGIS.syncInDisplayThread(
          new Runnable() {
            public void run() {
              Shell shell = Display.getCurrent().getActiveShell();

              ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
              try {
                dialog.run(
                    false,
                    true,
                    new IRunnableWithProgress() {

                      public void run(IProgressMonitor monitor)
                          throws InvocationTargetException, InterruptedException {
                        CoordinateReferenceSystem found = CRSUtil.findEPSGCode(crs, monitor);
                        if (found == null) {
                          return;
                        }

                        ViewportModel model = (ViewportModel) map.getViewportModel();
                        model.eSetDeliver(false);
                        try {
                          model.setCRS(found);
                          codes.addAll(CRSUtil.extractAuthorityCodes(found));
                        } finally {
                          model.eSetDeliver(true);
                        }
                      }
                    });
              } catch (InvocationTargetException e) {
                WMSPlugin.log("Error tracking down EPSG Code", e);
                dontFind(map, DONT_FIND);
              } catch (InterruptedException e) {
                WMSPlugin.log("Error tracking down EPSG Code", e);
                dontFind(map, DONT_FIND);
              }
              dontFind(map, DONT_FIND);
            }
          });
    }

    return codes;
  }
  public static void showWhile(
      final ViewportPane pane, final Display display, final Runnable runnable) {

    PlatformGIS.syncInDisplayThread(
        new Runnable() {
          public void run() {
            pane.setCursor(display.getSystemCursor(SWT.CURSOR_WAIT));
            org.eclipse.swt.custom.BusyIndicator.showWhile(display, runnable);
            pane.setCursor(null);
          }
        });
  }
  public void backward(State current, State next) {
    if (headless) return;

    // move the wizard to the previous page
    PlatformGIS.syncInDisplayThread(
        new Runnable() {

          public void run() {
            backPressedSuper();
          }
        });
  }
 public void finished(State last) {
   if (headless) {
     // signal to the wizard that we are finished
     getWizard().performFinish();
   } else {
     Runnable runnable =
         new Runnable() {
           public void run() {
             finishPressedSuper();
           }
         };
     PlatformGIS.asyncInDisplayThread(runnable, true);
   }
 }
  public void run(IAction action) {

    IRunnableWithProgress operation =
        new IRunnableWithProgress() {

          public void run(final IProgressMonitor pm)
              throws InvocationTargetException, InterruptedException {
            Display.getDefault()
                .syncExec(
                    new Runnable() {
                      public void run() {

                        final List<?> toList = selection.toList();
                        Envelope bounds = null;
                        try {
                          pm.beginTask("Set active region to maps bounds...", toList.size());

                          try {
                            JGrassRegion currentRegion = null;
                            JGrassMapEnvironment grassMapEnvironment = null;

                            for (Object object : toList) {
                              if (object instanceof JGrassMapGeoResource) {
                                JGrassMapGeoResource mr = (JGrassMapGeoResource) object;
                                JGrassRegion fileWindow = mr.getFileWindow();
                                if (currentRegion == null) {
                                  currentRegion = mr.getActiveWindow();
                                  grassMapEnvironment = mr.getjGrassMapEnvironment();
                                }

                                Envelope envelope = fileWindow.getEnvelope();
                                if (bounds == null) {
                                  bounds = envelope;
                                } else {
                                  bounds.expandToInclude(envelope);
                                }
                              }
                              pm.worked(1);
                            }

                            String code = null;
                            try {
                              CoordinateReferenceSystem jGrassCrs =
                                  grassMapEnvironment.getCoordinateReferenceSystem();
                              try {
                                Integer epsg = CRS.lookupEpsgCode(jGrassCrs, true);
                                code = "EPSG:" + epsg;
                              } catch (Exception e) {
                                // try non epsg
                                code = CRS.lookupIdentifier(jGrassCrs, true);
                              }
                            } catch (Exception e) {
                              e.printStackTrace();
                            }

                            JGrassRegion newActiveRegion =
                                JGrassRegion.adaptActiveRegionToEnvelope(bounds, currentRegion);
                            File windFile = grassMapEnvironment.getWIND();
                            JGrassRegion.writeWINDToMapset(windFile.getParent(), newActiveRegion);

                            IMap activeMap = ApplicationGIS.getActiveMap();
                            IBlackboard blackboard = activeMap.getBlackboard();
                            ActiveRegionStyle style =
                                (ActiveRegionStyle) blackboard.get(ActiveregionStyleContent.ID);
                            if (style == null) {
                              style = ActiveregionStyleContent.createDefault();
                            }
                            style.north = (float) newActiveRegion.getNorth();
                            style.south = (float) newActiveRegion.getSouth();
                            style.east = (float) newActiveRegion.getEast();
                            style.west = (float) newActiveRegion.getWest();
                            style.rows = newActiveRegion.getRows();
                            style.cols = newActiveRegion.getCols();
                            style.windPath = windFile.getAbsolutePath();
                            style.crsString = code;

                            blackboard.put(ActiveregionStyleContent.ID, style);

                            ILayer activeRegionMapGraphic =
                                JGrassPlugin.getDefault().getActiveRegionMapGraphic();
                            activeRegionMapGraphic.refresh(null);

                          } catch (IOException e) {
                            e.printStackTrace();
                            String message =
                                "Problems occurred while setting the new active region.";
                            ExceptionDetailsDialog.openError(
                                "Information", message, IStatus.ERROR, JGrassPlugin.PLUGIN_ID, e);
                          }
                        } finally {
                          pm.done();
                        }
                      }
                    });
          }
        };

    PlatformGIS.runInProgressDialog("Set active region...", true, operation, true);
  }
  public void run(IAction action) {

    IRunnableWithProgress operation =
        new IRunnableWithProgress() {
          public void run(final IProgressMonitor pm)
              throws InvocationTargetException, InterruptedException {
            Display.getDefault()
                .syncExec(
                    new Runnable() {
                      public void run() {
                        final Shell shell = PlatformUI.getWorkbench().getDisplay().getActiveShell();

                        final Object object = selection.getFirstElement();
                        try {
                          pm.beginTask("Collecting stats...", IProgressMonitor.UNKNOWN);
                          StringBuilder regionString = new StringBuilder();
                          GridCoverage2D geodata = null;
                          if (object instanceof AbstractRasterGeoResource) {
                            AbstractRasterGeoResource rGeo = (AbstractRasterGeoResource) object;
                            AbstractGridCoverage2DReader gridCoverage2DReader =
                                rGeo.resolve(AbstractGridCoverage2DReader.class, pm);
                            geodata = ((GridCoverage2D) gridCoverage2DReader.read(null));
                            geodata = geodata.view(ViewType.GEOPHYSICS);

                            Envelope envelope = geodata.getEnvelope();
                            DirectPosition lowerCorner = envelope.getLowerCorner();
                            double[] westSouth = lowerCorner.getCoordinate();
                            DirectPosition upperCorner = envelope.getUpperCorner();
                            double[] eastNorth = upperCorner.getCoordinate();
                            GridGeometry2D gridGeometry = geodata.getGridGeometry();
                            GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
                            int rows = gridRange.height;
                            int cols = gridRange.width;

                            AffineTransform gridToCRS =
                                (AffineTransform) gridGeometry.getGridToCRS();
                            double we_res = XAffineTransform.getScaleX0(gridToCRS);
                            double ns_res = XAffineTransform.getScaleY0(gridToCRS);
                            double north = eastNorth[1];
                            double south = westSouth[1];
                            double east = eastNorth[0];
                            double west = westSouth[0];
                            regionString.append("region:\nwest=");
                            regionString.append(west);
                            regionString.append("\neast=");
                            regionString.append(east);
                            regionString.append("\nsouth=");
                            regionString.append(south);
                            regionString.append("\nnorth=");
                            regionString.append(north);
                            regionString.append("\nwe_res=");
                            regionString.append(we_res);
                            regionString.append("\nns_res=");
                            regionString.append(ns_res);
                            regionString.append("\nrows=");
                            regionString.append(rows);
                            regionString.append("\ncols=");
                            regionString.append(cols);

                          } else if (object instanceof JGrassMapGeoResource) {
                            JGrassMapGeoResource mr = (JGrassMapGeoResource) object;
                            File mapFile = mr.getMapFile();
                            JGrassMapEnvironment mapEnvironment = new JGrassMapEnvironment(mapFile);
                            JGrassRegion jGrassRegion = mapEnvironment.getActiveRegion();

                            int cols = jGrassRegion.getCols();
                            int rows = jGrassRegion.getRows();
                            double north = jGrassRegion.getNorth();
                            double south = jGrassRegion.getSouth();
                            double east = jGrassRegion.getEast();
                            double west = jGrassRegion.getWest();
                            double we_res = jGrassRegion.getWEResolution();
                            double ns_res = jGrassRegion.getNSResolution();
                            regionString.append("region:\nwest=");
                            regionString.append(west);
                            regionString.append("\neast=");
                            regionString.append(east);
                            regionString.append("\nsouth=");
                            regionString.append(south);
                            regionString.append("\nnorth=");
                            regionString.append(north);
                            regionString.append("\nwe_res=");
                            regionString.append(we_res);
                            regionString.append("\nns_res=");
                            regionString.append(ns_res);
                            regionString.append("\nrows=");
                            regionString.append(rows);
                            regionString.append("\ncols=");
                            regionString.append(cols);

                            GeneralParameterValue[] readParams =
                                createGridGeometryGeneralParameter(
                                    cols,
                                    rows,
                                    north,
                                    south,
                                    east,
                                    west,
                                    mapEnvironment.getCoordinateReferenceSystem());
                            AbstractGridFormat format =
                                (AbstractGridFormat)
                                    new GrassCoverageFormatFactory().createFormat();
                            AbstractGridCoverage2DReader reader =
                                format.getReader(mapEnvironment.getCELL());
                            geodata = ((GridCoverage2D) reader.read(readParams));
                            geodata = geodata.view(ViewType.GEOPHYSICS);
                          } else {
                            MessageDialog.openInformation(
                                shell, "WARNING", "Unable to read format");
                            return;
                          }

                          GridGeometry2D gridGeometry = geodata.getGridGeometry();
                          GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
                          int rows = gridRange.height;
                          int cols = gridRange.width;
                          AffineTransform gridToCRS = (AffineTransform) gridGeometry.getGridToCRS();
                          double xRes = XAffineTransform.getScaleX0(gridToCRS);
                          double yRes = XAffineTransform.getScaleY0(gridToCRS);

                          RandomIter inputIter =
                              RandomIterFactory.create(geodata.getRenderedImage(), null);
                          /*
                           * calculate mean, max and min
                           */
                          double mean = 0.0;

                          double[] minMaxMeans =
                              new double[] {Double.MAX_VALUE, Double.MIN_VALUE, 0, 0, 0};
                          int validCells = 0;
                          for (int y = 0; y < rows; y++) {
                            for (int x = 0; x < cols; x++) {
                              double value = inputIter.getSampleDouble(x, y, 0);
                              if (!Double.isNaN(value) && (int) value != -9999) {
                                if (value < minMaxMeans[0]) minMaxMeans[0] = value;
                                if (value > minMaxMeans[1]) minMaxMeans[1] = value;
                                mean = mean + value;
                                validCells++;
                              }
                            }
                          }

                          mean = mean / (double) validCells;

                          minMaxMeans[2] = mean;
                          minMaxMeans[3] = validCells;
                          minMaxMeans[4] = validCells * xRes * yRes;

                          /*
                           * print out some system out
                           */
                          StringBuilder sb = new StringBuilder();
                          sb.append("Summary for the map:\n");
                          sb.append("\n");
                          sb.append("range: " + minMaxMeans[0] + " - " + minMaxMeans[1] + "\n");
                          sb.append("mean: " + minMaxMeans[2] + "\n");
                          sb.append("active cells: " + minMaxMeans[3] + "\n");
                          sb.append(
                              "active area (assuming metric resolution): " + minMaxMeans[4] + "\n");
                          sb.append(regionString.toString() + "\n");
                          sb.append(
                              "data crs: "
                                  + geodata.getCoordinateReferenceSystem().getName().toString());

                          MessageDialog.openInformation(shell, "Summary", sb.toString());

                        } catch (Exception e) {
                          String message = "An error occurred while exporting the maps.";
                          ExceptionDetailsDialog.openError(
                              "ERROR", message, IStatus.ERROR, JGrassPlugin.PLUGIN_ID, e);
                        } finally {
                          pm.done();
                        }
                      }
                    });
          }
        };

    PlatformGIS.runInProgressDialog("Calculating map summery...", true, operation, true);
  }