Esempio n. 1
0
  public Tool createTool(Class<? extends Tool> toolClass) {
    Tool tool;
    try {
      Constructor<? extends Tool> constructor = toolClass.getDeclaredConstructor(new Class[] {});
      tool = constructor.newInstance(new Object[] {});
      //			tool = constructor.newInstance((Object) null);

      buttonGroup.add(tool);
      toolMap.put(toolClass, tool);
      tool.setToolbox(this);
      return tool;
    } catch (InstantiationException e) {
      TabletopTool.showError(
          I18N.getText("msg.error.toolCannotInstantiate", toolClass.getName()), e);
    } catch (IllegalAccessException e) {
      TabletopTool.showError(
          I18N.getText("msg.error.toolNeedPublicConstructor", toolClass.getName()), e);
    } catch (NoSuchMethodException nsme) {
      TabletopTool.showError(
          I18N.getText("msg.error.toolNeedValidConstructor", toolClass.getName()), nsme);
    } catch (InvocationTargetException ite) {
      TabletopTool.showError(
          I18N.getText("msg.error.toolConstructorFailed", toolClass.getName()), ite);
    }
    return null;
  }
  private void exportButtonAction() {
    // This block is to allow preservation of existing dialog behavior:
    // Neither button is set when the dialog first appears, so we have to
    // make sure the user picks one. Presumably this is to force the user
    // to pay attention to this choice and not just accept a default.
    if (!(ExportRadioButtons.VIEW_GM.isChecked() || ExportRadioButtons.VIEW_PLAYER.isChecked())) {
      TabletopTool.showError(I18N.getString("dialog.screenshot.error.mustSelectView"), null);
      return;
    }

    // LOCATION
    // TODO: Show a progress dialog
    // TODO: Make this less fragile
    switch (formPanel.getTabbedPane("tabs").getSelectedIndex()) {
      case 0:
        File file = new File(formPanel.getText("locationTextField"));

        // PNG only supported for now
        if (!file.getName().toLowerCase().endsWith(".png")) {
          file = new File(file.getAbsolutePath() + ".png");
        }

        exportLocation = new LocalLocation(file);
        break;
      case 1:
        String username = formPanel.getText("username");
        String password = formPanel.getText("password");
        String host = formPanel.getText("host");
        String path = formPanel.getText("path");

        // PNG only supported for now
        if (!path.toLowerCase().endsWith(".png")) {
          path += ".png";
        }

        exportLocation = new FTPLocation(username, password, host, path);
        break;
    }

    try {
      screenCapture();
    } catch (Exception ex) {
      TabletopTool.showError(I18N.getString("dialog.screenshot.error.failedExportingImage"), ex);
    } finally {
      dispose();
    }
  }
  /**
   * This is the top-level screen-capture routine. It sends the resulting PNG image to the location
   * previously selected by the user. TODO: It currently calls {@link
   * TabletopTool.takeMapScreenShot()} for "normal" screenshots, but that's just until this code is
   * considered stable enough.
   *
   * @throws Exception
   */
  public void screenCapture() throws Exception {

    BufferedImage screenCap = null;

    TabletopTool.getFrame()
        .setStatusMessage(I18N.getString("dialog.screenshot.msg.GeneratingScreenshot"));
    ExportRadioButtons type = ExportRadioButtons.getType();
    try {
      switch (type) {
        case TYPE_CURRENT_VIEW:
          // This uses the original screenshot code: I didn't want to touch it, so I need
          // to pass it the same parameter it took before.
          Player.Role role =
              ExportRadioButtons.VIEW_GM.isChecked() ? Player.Role.GM : Player.Role.PLAYER;
          screenCap = TabletopTool.takeMapScreenShot(new PlayerView(role));
          // since old screenshot code doesn't throw exceptions, look for null
          if (screenCap == null) {
            throw new Exception(I18N.getString("dialog.screenshot.error.failedImageGeneration"));
          }
          break;
        case TYPE_ENTIRE_MAP:
          screenCap = entireMapScreenShotWithLayers();
          break;
        default:
          throw new Exception(I18N.getString("dialog.screenshot.error.invalidDialogSettings"));
      }
      TabletopTool.getFrame()
          .setStatusMessage(I18N.getString("dialog.screenshot.msg.screenshotStreaming"));
      try (ByteArrayOutputStream imageOut = new ByteArrayOutputStream()) {
        ImageIO.write(screenCap, "png", imageOut);
        screenCap = null; // Free up the memory as soon as possible

        TabletopTool.getFrame()
            .setStatusMessage(I18N.getString("dialog.screenshot.msg.screenshotSaving"));
        exportLocation.putContent(
            new BufferedInputStream(new ByteArrayInputStream(imageOut.toByteArray())));
      }

      TabletopTool.getFrame()
          .setStatusMessage(I18N.getString("dialog.screenshot.msg.screenshotSaved"));
    } catch (OutOfMemoryError e) {
      TabletopTool.showError("Out Of Memory", e);
    } catch (Exception ex) {
      TabletopTool.showError("screenCapture()", ex);
    }
  }
 /**
  * Stores the form this is attached to, so we don't have to store duplicate data locally (like
  * selected and enabled). Also perform some error checking, since we _are_ duplicating the
  * description of the form itself (like what buttons it has).
  *
  * @param form The FormPanel this dialog is part of.
  */
 public static void setForm(FormPanel form) {
   ExportLayers.form = form;
   for (ExportLayers button : ExportLayers.values()) {
     try {
       if (form.getButton(button.toString()) == null) {
         throw new Exception("Export Dialog has a mis-matched enum: " + button.toString());
       }
     } catch (Exception ex) {
       TabletopTool.showError(
           I18N.getString("dialog.screenshot.layer.button.uiImplementationError"), ex);
     }
   }
 }
    //
    // SetForm stores the form this is attached to
    //
    public static void setForm(FormPanel form) {
      ExportRadioButtons.form = form;

      for (ExportRadioButtons button : ExportRadioButtons.values()) {
        try {
          if (form.getRadioButton(button.toString()) == null) {
            throw new Exception("Export Dialog has a mis-matched enum: " + button.toString());
          }
          button.addActionListener(
              new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent evt) {
                  enforceButtonRules();
                }
              });
        } catch (Exception ex) {
          TabletopTool.showError(
              I18N.getString("dialog.screenshot.radio.button.uiImplementationError"), ex);
        }
      }
    }
  @Override
  public boolean commit() {
    Token token = getModel();

    if (getNameField().getText().equals("")) {
      TabletopTool.showError("msg.error.emptyTokenName");
      return false;
    }
    if (getSpeechTable().isEditing()) {
      getSpeechTable().getCellEditor().stopCellEditing();
    }
    if (getPropertyTable().isEditing()) {
      getPropertyTable().getCellEditor().stopCellEditing();
    }
    // Commit the changes to the token properties
    if (!super.commit()) {
      return false;
    }
    // SIZE
    token.setSnapToScale(getSizeCombo().getSelectedIndex() != 0);
    if (getSizeCombo().getSelectedIndex() > 0) {
      Grid grid = TabletopTool.getFrame().getCurrentZoneRenderer().getZone().getGrid();
      token.setFootprint(grid, (TokenFootprint) getSizeCombo().getSelectedItem());
    }
    // Other
    token.setPropertyType((String) getPropertyTypeCombo().getSelectedItem());
    token.setSightType((String) getSightTypeCombo().getSelectedItem());

    // Get the states
    Component[] stateComponents = getStatesPanel().getComponents();
    Component barPanel = null;
    for (int j = 0; j < stateComponents.length; j++) {
      if ("bar".equals(stateComponents[j].getName())) {
        barPanel = stateComponents[j];
        continue;
      }
      Component[] components = ((Container) stateComponents[j]).getComponents();
      for (int i = 0; i < components.length; i++) {
        JCheckBox cb = (JCheckBox) components[i];
        String state = cb.getText();
        token.setState(state, cb.isSelected());
      }
    } // endfor

    // BARS
    if (barPanel != null) {
      Component[] bars = ((Container) barPanel).getComponents();
      for (int i = 0; i < bars.length; i += 2) {
        JCheckBox cb = (JCheckBox) ((Container) bars[i]).getComponent(1);
        JSlider bar = (JSlider) bars[i + 1];
        Float value = cb.isSelected() ? null : new Float(bar.getValue() / 100f);
        token.setBar(bar.getName(), value);
      }
    }
    // Ownership
    // If the token is owned by all and we are a player don't alter the ownership list.
    if (TabletopTool.getPlayer().isGM() || !token.isOwnedByAll()) {
      token.clearAllOwners();

      for (int i = 0; i < getOwnerList().getModel().getSize(); i++) {
        DefaultSelectable selectable =
            (DefaultSelectable) getOwnerList().getModel().getElementAt(i);
        if (selectable.isSelected()) {
          token.addOwner((String) selectable.getObject());
        }
      }
      // If we are not a GM and the only non GM owner make sure we can't
      // take our selves off of the owners list
      if (!TabletopTool.getPlayer().isGM()) {
        boolean hasPlayer = false;
        Set<String> owners = token.getOwners();
        if (owners != null) {
          Iterator<Player> playerIter = TabletopTool.getPlayerList().iterator();
          while (playerIter.hasNext()) {
            Player pl = playerIter.next();
            if (!pl.isGM() && owners.contains(pl.getName())) {
              hasPlayer = true;
            }
          }
        }
        if (!hasPlayer) {
          token.addOwner(TabletopTool.getPlayer().getName());
        }
      }
    }
    // SHAPE
    token.setShape((Token.TokenShape) getShapeCombo().getSelectedItem());

    // Macros
    token.setSpeechMap(((KeyValueTableModel) getSpeechTable().getModel()).getMap());

    // Properties
    ((TokenPropertyTableModel) getPropertyTable().getModel()).applyTo(token);

    // Charsheet
    if (getCharSheetPanel().getImageId() != null) {
      T3Util.uploadAsset(AssetManager.getAsset(getCharSheetPanel().getImageId()));
    }
    token.setCharsheetImage(getCharSheetPanel().getImageId());

    // IMAGE
    if (!token.getImageAssetId().equals(getTokenIconPanel().getImageId())) {
      BufferedImage image = ImageManager.getImageAndWait(getTokenIconPanel().getImageId());
      T3Util.uploadAsset(AssetManager.getAsset(getTokenIconPanel().getImageId()));
      token.setImageAsset(null, getTokenIconPanel().getImageId()); // Default image for now
      token.setWidth(image.getWidth(null));
      token.setHeight(image.getHeight(null));
    }
    // PORTRAIT
    if (getPortraitPanel().getImageId() != null) {
      // Make sure the server has the image
      if (!TabletopTool.getCampaign().containsAsset(getPortraitPanel().getImageId())) {
        TabletopTool.serverCommand()
            .putAsset(AssetManager.getAsset(getPortraitPanel().getImageId()));
      }
    }
    token.setPortraitImage(getPortraitPanel().getImageId());

    // LAYOUT
    token.setSizeScale(getTokenLayoutPanel().getSizeScale());
    token.setAnchor(getTokenLayoutPanel().getAnchorX(), getTokenLayoutPanel().getAnchorY());

    // OTHER
    tokenSaved = true;

    // Character Sheet
    //		Map<String, Object> properties = controller.getData();
    //		for (String prop : token.getPropertyNames())
    //			token.setProperty(prop, properties.get(prop));

    // Update UI
    TabletopTool.getFrame().updateTokenTree();
    TabletopTool.getFrame().resetTokenPanels();

    return true;
  }
  /**
   * Finds the extents of the map, then takes a 'screenshot' of that area. If the user is the GM,
   * the extents include every object and everything that has any area, such as 'fog' and
   * 'visibility' objects.
   *
   * <p>If a background tiling texture is used, the image is aligned to it, so that it can be used
   * on re-import as a new base map image.
   *
   * <p>If the user is a player (or GM posing as a player), the extents only go as far as the
   * revealed fog-of-war.
   *
   * @return the image to be saved
   */
  private static BufferedImage takeEntireMapScreenShot() throws Exception, OutOfMemoryError {
    final ZoneRenderer renderer = TabletopTool.getFrame().getCurrentZoneRenderer();
    if (renderer == null) {
      throw (new Exception("renderer = NULL"));
    }

    boolean viewAsPlayer = ExportRadioButtons.VIEW_PLAYER.isChecked();

    //
    // First, figure out the 'extents' of the canvas
    //   This will be later modified by the fog (for players),
    //   and by the tiling texture (for re-importing)
    //
    final PlayerView view = new PlayerView(viewAsPlayer ? Player.Role.PLAYER : Player.Role.GM);
    Rectangle extents = renderer.zoneExtents(view);
    try {
      // Clip to what the players know about (if applicable).
      // This keeps the player from exporting the map to learn which
      // direction has more 'stuff' in it.

      if (viewAsPlayer) {
        Rectangle fogE = renderer.fogExtents();
        // TabletopTool.showError(fogE.x + " " + fogE.y + " " + fogE.width + " " + fogE.height);
        if ((fogE.width < 0) || (fogE.height < 0)) {
          TabletopTool.showError(
              I18N.getString(
                  "dialog.screenshot.error.negativeFogExtents")); // Image is not clipped to show
          // only fog-revealed areas!"));
        } else {
          extents = extents.intersection(fogE);
        }
      }
    } catch (Exception ex) {
      throw (new Exception(I18N.getString("dialog.screenshot.error.noArea"), ex));
    }
    if ((extents == null) || (extents.width == 0) || (extents.height == 0)) {
      throw (new Exception(I18N.getString("dialog.screenshot.error.noArea")));
    }

    // If output includes the tiling 'board' texture, move the upper-left corner
    // to an integer multiple of the background tile (so it matches up on import).
    // We don't need to move the lower-right corner because it doesn't matter for
    // aligning on importing.

    boolean drawBoard = ExportLayers.LAYER_BOARD.isChecked();
    if (drawBoard) {
      DrawablePaint paint = renderer.getZone().getBackgroundPaint();
      DrawableTexturePaint dummy = new DrawableTexturePaint();
      Integer tileX = 0, tileY = 0;

      if (paint.getClass() == dummy.getClass()) {
        Image bgTexture = ImageManager.getImage(((DrawableTexturePaint) paint).getAsset().getId());
        tileX = bgTexture.getWidth(null);
        tileY = bgTexture.getHeight(null);
        Integer x = ((int) Math.floor((float) extents.x / tileX)) * tileX;
        Integer y = ((int) Math.floor((float) extents.y / tileY)) * tileY;
        extents.width = extents.width + (extents.x - x);
        extents.height = extents.height + (extents.y - y);
        extents.x = x;
        extents.y = y;
      }
    }

    // Save the original state of the renderer to restore later.
    // Create a place to put the image, and
    // set up the renderer to encompass the whole extents of the map.

    Rectangle origBounds = renderer.getBounds();
    Scale origScale = renderer.getZoneScale();
    Dimension origSize = renderer.getSize();

    BufferedImage image = null;
    try {
      image = new BufferedImage(extents.width, extents.height, Transparency.OPAQUE);
    } catch (OutOfMemoryError me) {
      throw new OutOfMemoryError("image size = " + extents.width + " x " + extents.height);
    } catch (Exception e) {
      throw new Exception("image size = " + extents.width + " x " + extents.height, e);
    }

    final Graphics2D g = image.createGraphics();
    g.setClip(0, 0, extents.width, extents.height);
    Scale s = new Scale();
    s.setOffset(-extents.x, -extents.y);

    // Finally, draw the image.
    // Copied this thread concept from the original screenshot code in TabletopTool.
    //  Have to do this on the EDT so that there aren't any odd side effects
    //  of rendering using a renderer that's on screen.

    try {
      renderer.setZoneScale(s);
      renderer.setBounds(extents);
      renderer.setSize(extents.getSize());
      if (!EventQueue.isDispatchThread()) {
        EventQueue.invokeAndWait(
            new Runnable() {
              @Override
              public void run() {
                renderer.renderZone(g, view);
              }
            });
      } else {
        renderer.renderZone(g, view);
      }
      return image;
    } catch (OutOfMemoryError me) {
      throw new OutOfMemoryError("image size = " + extents.width + " x " + extents.height);
    } catch (InterruptedException ie) {
      TabletopTool.showError("While creating snapshot", ie);
    } catch (InvocationTargetException ite) {
      TabletopTool.showError("While creating snapshot", ite);
    } catch (Exception e) {
      throw new Exception("image size = " + extents.width + " x " + extents.height, e);
    } finally {
      g.dispose();
      // Restore original state
      renderer.setBounds(origBounds);
      renderer.setZoneScale(origScale);
      renderer.setSize(origSize);
    }
    // This is just to avoid the compiler error: it should be unreachable
    return null;
  }