@Override public String getColumnName(int column) { switch (column) { case 0: return I18N.getString("EditTokenDialog.msg.speech.colID"); case 1: return I18N.getString("EditTokenDialog.msg.speech.colSpeechText"); } return ""; }
@Override public String getColumnName(int column) { switch (column) { case 0: return I18N.getString("EditTokenDialog.msg.generic.colKey"); case 1: return I18N.getString("EditTokenDialog.msg.generic.colValue"); } return ""; }
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(); } }
/** * 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); } } }
public void showDialog(Token token) { dialog = new GenericDialog( I18N.getString("EditTokenDialog.msg.title"), TabletopTool.getFrame(), this) { private static final long serialVersionUID = 5439449816096482201L; @Override public void closeDialog() { // TODO: I don't like this. There should really be a AbeilleDialog class that does this unbind(); super.closeDialog(); } }; bind(token); getRootPane().setDefaultButton(getOKButton()); dialog.showDialog(); }
// // 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); } } }
/** * 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); } }
/** * 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; }