private void enableControls(final boolean canBeEnabled) {

    final boolean isLoading = OfflineLoadManager.isLoading();
    final boolean isPartSelected = _partViewer.getSelection().isEmpty() == false;

    _comboTargetZoom.setEnabled(canBeEnabled && isLoading == false);
    _comboMapProvider.setEnabled(canBeEnabled);

    _btnDownload.setEnabled(canBeEnabled && isLoading == false);
    _btnStop.setEnabled(canBeEnabled && isLoading);

    _btnRefreshParts.setEnabled(canBeEnabled && isLoading == false);
    _btnDeleteAll.setEnabled(canBeEnabled && isLoading == false);
    _btnDeletePart.setEnabled(canBeEnabled && isLoading == false && isPartSelected);
  }
  private void loadOfflineImages() {

    if (OfflineLoadManager.isLoading()) {
      return;
    }

    final int selectedZoomLevel = _targetZoomLevels[_comboTargetZoom.getSelectionIndex()];

    final int tileSize = _selectedMp.getTileSize();

    final int worldStartX = _offlineWorldStart.x;
    final int worldStartY = _offlineWorldStart.y;
    final int worldEndX = _offlineWorldEnd.x;
    final int worldEndY = _offlineWorldEnd.y;

    double worldX1 = Math.min(worldStartX, worldEndX);
    double worldX2 = Math.max(worldStartX, worldEndX);
    double worldY1 = Math.min(worldStartY, worldEndY);
    double worldY2 = Math.max(worldStartY, worldEndY);

    for (int zoomLevel = _validMapZoomLevel; zoomLevel <= selectedZoomLevel; zoomLevel++) {

      final int maxMapTileSize = _selectedMp.getMapTileSize(zoomLevel).width;

      final int areaPixelWidth = (int) (worldX2 - worldX1);
      final int areaPixelHeight = (int) (worldY2 - worldY1);

      final int numTileWidth = (int) Math.ceil((double) areaPixelWidth / (double) tileSize);
      final int numTileHeight = (int) Math.ceil((double) areaPixelHeight / (double) tileSize);

      int tilePosMinX = (int) Math.floor(worldX1 / tileSize);
      int tilePosMinY = (int) Math.floor(worldY1 / tileSize);
      int tilePosMaxX = tilePosMinX + numTileWidth;
      int tilePosMaxY = tilePosMinY + numTileHeight;

      // ensure tiles are within the map
      tilePosMinX = Math.max(0, tilePosMinX);
      tilePosMinY = Math.max(0, tilePosMinY);
      tilePosMaxX = Math.min(tilePosMaxX, maxMapTileSize);
      tilePosMaxY = Math.min(tilePosMaxY, maxMapTileSize);

      for (int tilePosX = tilePosMinX; tilePosX <= tilePosMaxX; tilePosX++) {
        for (int tilePosY = tilePosMinY; tilePosY <= tilePosMaxY; tilePosY++) {

          // create offline tile
          final Tile offlineTile = new Tile(_selectedMp, zoomLevel, tilePosX, tilePosY, null);
          offlineTile.setBoundingBoxEPSG4326();
          _selectedMp.doPostCreation(offlineTile);

          _offlineManager.addOfflineTile(_selectedMp, offlineTile);
        }
      }

      // set next zoom level, zoom into the map
      worldX1 *= 2;
      worldX2 *= 2;
      worldY1 *= 2;
      worldY2 *= 2;
    }

    // initialize progress bar
    _maxQueue = MP.getTileWaitingQueue().size();
    _progbarQueue.setMaximum(_maxQueue);
  }
  private void getOfflineImageState() {

    if (OfflineLoadManager.isLoading()) {
      return;
    }

    enableControls(false);

    getOfflineMapProviders();

    BusyIndicator.showWhile(
        _display,
        new Runnable() {
          @Override
          public void run() {

            final int selectedZoomLevel = _targetZoomLevels[_comboTargetZoom.getSelectionIndex()];

            final int tileSize = _selectedMp.getTileSize();

            final int worldStartX = _offlineWorldStart.x;
            final int worldStartY = _offlineWorldStart.y;
            final int worldEndX = _offlineWorldEnd.x;
            final int worldEndY = _offlineWorldEnd.y;

            for (final PartMP partMp : _partMapProvider) {

              final MP offlineMp = partMp.partMp;

              double worldX1 = Math.min(worldStartX, worldEndX);
              double worldX2 = Math.max(worldStartX, worldEndX);
              double worldY1 = Math.min(worldStartY, worldEndY);
              double worldY2 = Math.max(worldStartY, worldEndY);

              for (int zoomLevel = _validMapZoomLevel;
                  zoomLevel <= selectedZoomLevel;
                  zoomLevel++) {

                final int maxMapTileSize = offlineMp.getMapTileSize(zoomLevel).width;

                final int areaPixelWidth = (int) (worldX2 - worldX1);
                final int areaPixelHeight = (int) (worldY2 - worldY1);

                final int numTileWidth =
                    (int) Math.ceil((double) areaPixelWidth / (double) tileSize);
                final int numTileHeight =
                    (int) Math.ceil((double) areaPixelHeight / (double) tileSize);

                int tilePosMinX = (int) Math.floor(worldX1 / tileSize);
                int tilePosMinY = (int) Math.floor(worldY1 / tileSize);
                int tilePosMaxX = tilePosMinX + numTileWidth;
                int tilePosMaxY = tilePosMinY + numTileHeight;

                // ensure tiles are within the map
                tilePosMinX = Math.max(0, tilePosMinX);
                tilePosMinY = Math.max(0, tilePosMinY);
                tilePosMaxX = Math.min(tilePosMaxX, maxMapTileSize);
                tilePosMaxY = Math.min(tilePosMaxY, maxMapTileSize);

                for (int tilePosX = tilePosMinX; tilePosX <= tilePosMaxX; tilePosX++) {
                  for (int tilePosY = tilePosMinY; tilePosY <= tilePosMaxY; tilePosY++) {

                    // create offline tile
                    final Tile offlineTile =
                        new Tile(offlineMp, zoomLevel, tilePosX, tilePosY, null);
                    offlineTile.setBoundingBoxEPSG4326();
                    offlineMp.doPostCreation(offlineTile);

                    final boolean isAvailable =
                        _offlineManager.isOfflineImageAvailable(offlineMp, offlineTile);

                    if (isAvailable) {
                      partMp.existingImages++;
                    } else {
                      partMp.missingImages++;
                    }
                  }
                }

                // zoom into the map
                worldX1 *= 2;
                worldX2 *= 2;
                worldY1 *= 2;
                worldY2 *= 2;
              }
            }
          }
        });

    // update part viewer
    _partViewer.setInput(new Object());

    // deselect all
    _partViewer.setSelection(null);

    //		// reset queue
    //		_txtQueue.setText(UI.EMPTY_STRING);

    enableControls(true);
  }
  private void deleteOfflineImages(final MP selectedPartMp) {

    if (OfflineLoadManager.isLoading()) {
      return;
    }

    enableControls(false);

    final int selectedZoomLevel = _targetZoomLevels[_comboTargetZoom.getSelectionIndex()];

    final int tileSize = _selectedMp.getTileSize();

    final int worldStartX = _offlineWorldStart.x;
    final int worldStartY = _offlineWorldStart.y;
    final int worldEndX = _offlineWorldEnd.x;
    final int worldEndY = _offlineWorldEnd.y;

    for (final PartMP partMp : _partMapProvider) {

      final MP offlineMp = partMp.partMp;

      /*
       * check if only one part should be deleted, all will be deleted when the selectedPartMP
       * is null
       */
      //			if (selectedPartMp != null && offlineMp != selectedPartMp) {
      if (selectedPartMp != null) {

        // mp is set --> only 1 mp will be deleted

        if (_mpProfile == null) {

          if (selectedPartMp != offlineMp) {
            // delete only the selected mp offline images
            continue;
          }
        } else {

          // a mp profile is available in the mp list

          if (_mpProfile == offlineMp) {

            // delete also the mp profile offline images !!!

          } else {

            if (selectedPartMp != offlineMp) {
              continue;
            }
          }
        }
      }

      double worldX1 = Math.min(worldStartX, worldEndX);
      double worldX2 = Math.max(worldStartX, worldEndX);
      double worldY1 = Math.min(worldStartY, worldEndY);
      double worldY2 = Math.max(worldStartY, worldEndY);

      for (int zoomLevel = _validMapZoomLevel; zoomLevel <= selectedZoomLevel; zoomLevel++) {

        final int maxMapTileSize = _selectedMp.getMapTileSize(zoomLevel).width;

        final int areaPixelWidth = (int) (worldX2 - worldX1);
        final int areaPixelHeight = (int) (worldY2 - worldY1);

        final int numTileWidth = (int) Math.ceil((double) areaPixelWidth / (double) tileSize);
        final int numTileHeight = (int) Math.ceil((double) areaPixelHeight / (double) tileSize);

        int tilePosMinX = (int) Math.floor(worldX1 / tileSize);
        int tilePosMinY = (int) Math.floor(worldY1 / tileSize);
        int tilePosMaxX = tilePosMinX + numTileWidth;
        int tilePosMaxY = tilePosMinY + numTileHeight;

        // ensure tiles are within the map
        tilePosMinX = Math.max(0, tilePosMinX);
        tilePosMinY = Math.max(0, tilePosMinY);
        tilePosMaxX = Math.min(tilePosMaxX, maxMapTileSize);
        tilePosMaxY = Math.min(tilePosMaxY, maxMapTileSize);

        for (int tilePosX = tilePosMinX; tilePosX <= tilePosMaxX; tilePosX++) {
          for (int tilePosY = tilePosMinY; tilePosY <= tilePosMaxY; tilePosY++) {

            // create offline tile
            final Tile offlineTile = new Tile(offlineMp, zoomLevel, tilePosX, tilePosY, null);
            offlineTile.setBoundingBoxEPSG4326();
            offlineMp.doPostCreation(offlineTile);

            _offlineManager.deleteOfflineImage(offlineMp, offlineTile);
          }
        }

        // set next zoom level, zoom into the map
        worldX1 *= 2;
        worldX2 *= 2;
        worldY1 *= 2;
        worldY2 *= 2;
      }
    }

    getOfflineImageState();

    // reset states
    tileEvent(TileEventId.TILE_RESET_QUEUES, null);
  }