Example usage for java.awt Dimension getWidth

List of usage examples for java.awt Dimension getWidth

Introduction

In this page you can find the example usage for java.awt Dimension getWidth.

Prototype

public double getWidth() 

Source Link

Usage

From source file:net.sf.jasperreports.view.JasperViewer.java

/** This method is called from within the constructor to
 * initialize the form./*from   www. ja va2 s .c  o  m*/
 * WARNING: Do NOT modify this code. The content of this method is
 * always regenerated by the Form Editor.
 */
private void initComponents() {//GEN-BEGIN:initComponents
    pnlMain = new javax.swing.JPanel();

    setTitle("JasperViewer");
    setIconImage(
            new javax.swing.ImageIcon(getClass().getResource("/net/sf/jasperreports/view/images/jricon.GIF"))
                    .getImage());
    addWindowListener(new java.awt.event.WindowAdapter() {
        @Override
        public void windowClosing(java.awt.event.WindowEvent evt) {
            exitForm();
        }
    });

    pnlMain.setLayout(new java.awt.BorderLayout());

    getContentPane().add(pnlMain, java.awt.BorderLayout.CENTER);

    pack();

    Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
    java.awt.Dimension screenSize = toolkit.getScreenSize();
    int screenResolution = toolkit.getScreenResolution();
    float zoom = ((float) screenResolution) / net.sf.jasperreports.swing.JRViewerPanel.REPORT_RESOLUTION;

    int height = (int) (550 * zoom);
    if (height > screenSize.getHeight()) {
        height = (int) screenSize.getHeight();
    }
    int width = (int) (750 * zoom);
    if (width > screenSize.getWidth()) {
        width = (int) screenSize.getWidth();
    }

    java.awt.Dimension dimension = new java.awt.Dimension(width, height);
    setSize(dimension);
    setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2);
}

From source file:org.jamwiki.parser.image.ImageUtil.java

/**
 * Given a virtualWiki and WikiFIle that correspond to an existing image,
 * return the WikiImage object.  In addition, if the image metadata specifies
 * a max width or max height greater than zero then a resized version of the
 * image may be created./* w ww  . ja v  a 2  s.c om*/
 *
 * @param wikiFile Given a WikiFile object, use it to initialize a
 *  WikiImage object.
 * @param imageMetadata The maximum width or height for the initialized
 *  WikiImage object.  Setting this value to 0 or less will cause the
 *  value to be ignored.
 * @param fileVersion The specific file version.  If this parameter is
 *  <code>null</code> then the current version is used.
 * @return An initialized WikiImage object.
 * @throws IOException Thrown if an error occurs while initializing the
 *  WikiImage object.
 */
private static WikiImage initializeWikiImage(WikiFile wikiFile, ImageMetadata imageMetadata,
        WikiFileVersion fileVersion) throws DataAccessException, IOException {
    if (wikiFile == null) {
        throw new IllegalArgumentException("wikiFile may not be null");
    }
    WikiImage wikiImage = new WikiImage(wikiFile);
    if (fileVersion != null) {
        wikiImage.setFileSize(fileVersion.getFileSize());
        wikiImage.setMimeType(fileVersion.getMimeType());
        wikiImage.setUrl(fileVersion.getUrl());
    }
    // get the size of the original (unresized) image
    Dimension originalDimensions = ImageUtil.retrieveFromCache(wikiImage);
    if (originalDimensions == null) {
        if (isImagesOnFS()) {
            File file = ImageUtil.buildAbsoluteFile(wikiImage.getUrl());
            originalDimensions = ImageProcessor.retrieveImageDimensions(file);
        } else if (fileVersion != null) {
            originalDimensions = ImageProcessor.retrieveImageDimensions(wikiImage.getFileId(),
                    fileVersion.getFileVersionId(), 0);
        } else {
            originalDimensions = ImageProcessor.retrieveImageDimensions(wikiImage.getFileId(), -1, 0);
        }
        if (originalDimensions == null) {
            logger.info("Unable to determine dimensions for image: " + wikiImage.getUrl());
            return null;
        }
        addToCache(wikiImage, originalDimensions);
    }
    if (!imageMetadata.getAllowEnlarge() && imageMetadata.getMaxWidth() > originalDimensions.getWidth()
            && imageMetadata.getMaxHeight() > originalDimensions.getHeight()) {
        imageMetadata.setMaxWidth((int) originalDimensions.getWidth());
        imageMetadata.setMaxHeight((int) originalDimensions.getHeight());
    }
    // determine the width & height of scaled image (if needed)
    Dimension scaledDimensions = calculateScaledDimensions(originalDimensions, imageMetadata.getMaxWidth(),
            imageMetadata.getMaxHeight());
    wikiImage.setWidth((int) scaledDimensions.getWidth());
    wikiImage.setHeight((int) scaledDimensions.getHeight());
    // return an appropriate WikiImage object with URL to the scaled image, proper width, and proper height
    Dimension incrementalDimensions = calculateIncrementalDimensions(wikiImage, originalDimensions,
            scaledDimensions, fileVersion);
    if (isImagesOnFS()) {
        String url = buildImagePath(wikiImage.getUrl(), (int) originalDimensions.getWidth(),
                (int) incrementalDimensions.getWidth());
        wikiImage.setUrl(url);
    } else {
        Integer resized = incrementalDimensions.width != originalDimensions.width ? incrementalDimensions.width
                : null;
        Integer fileVersionId = (fileVersion != null) ? fileVersion.getFileVersionId() : null;
        String url = buildDatabaseRelativeUrl(wikiImage.getFileId(), fileVersionId, resized,
                wikiImage.getUrl());
        wikiImage.setUrl(url);
    }
    return wikiImage;
}

From source file:RasterTest.java

public void updateRenderRaster() {
    // takes the Depth Raster and updates the Render Raster
    // containing the image based on the depth values stored in
    // the Depth Raster.

    // create a temporary BufferedImage for the depth components
    BufferedImage tempBufferedImage = new BufferedImage(m_DepthRaster.getDepthComponent().getWidth(),
            m_DepthRaster.getDepthComponent().getHeight(), BufferedImage.TYPE_INT_RGB);

    // allocate an array of ints to store the depth components from the
    // Depth Raster
    if (m_DepthData == null)
        m_DepthData = new int[m_DepthRaster.getDepthComponent().getWidth()
                * m_DepthRaster.getDepthComponent().getHeight()];

    // copy the depth values from the Raster into the int array
    ((DepthComponentInt) m_DepthRaster.getDepthComponent()).getDepthData(m_DepthData);

    // assign the depth values to the temporary image, the integer depths
    // will be//from  ww  w  .  j ava2  s  .c  o m
    // interpreted as integer rgb values.
    tempBufferedImage.setRGB(0, 0, m_DepthRaster.getDepthComponent().getWidth(),
            m_DepthRaster.getDepthComponent().getHeight(), m_DepthData, 0,
            m_DepthRaster.getDepthComponent().getWidth());

    // get a graphics device for the image
    Graphics g = tempBufferedImage.getGraphics();
    Dimension size = new Dimension();
    m_RenderRaster.getSize(size);

    // because the Depth Raster is a different size to the Render Raster,
    // i.e. the Depth Raster is canvas width by canvas height and the Render
    // Raster
    // is of aritrary size, we rescale the image here.
    g.drawImage(tempBufferedImage, 0, 0, (int) size.getWidth(), (int) size.getHeight(), null);

    // finally, assign the scaled image to the RenderRaster
    m_RenderRaster.setImage(new ImageComponent2D(BufferedImage.TYPE_INT_RGB, tempBufferedImage));
}

From source file:net.chaosserver.timelord.swingui.Timelord.java

/**
 * Saves the size of the current frame into preferences.
 *//*www  .ja  v  a2s .com*/
protected void saveFrameSize() {
    if (applicationFrame != null) {
        Dimension windowSize = applicationFrame.getSize();

        Preferences preferences = Preferences.userNodeForPackage(this.getClass());
        preferences.putDouble(FRAME_WIDTH, windowSize.getWidth());
        preferences.putDouble(FRAME_HEIGHT, windowSize.getHeight());
    }
}

From source file:shuffle.fwk.service.roster.EditRosterService.java

@SuppressWarnings("serial")
private Component makeCenterPanel() {
    rosterEntryPanel = new JPanel(new WrapLayout()) {
        // Fix to make it play nice with the scroll bar.
        @Override/*from w  w w  . j  a va  2s.  co  m*/
        public Dimension getPreferredSize() {
            Dimension d = super.getPreferredSize();
            d.width = (int) (d.getWidth() - 20);
            return d;
        }
    };
    final JScrollPane ret = new JScrollPane(rosterEntryPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    ret.addComponentListener(new ComponentAdapter() {
        @Override
        public void componentResized(ComponentEvent e) {
            ret.revalidate();
        }
    });
    ret.getVerticalScrollBar().setUnitIncrement(27);
    return ret;
}

From source file:fedora.client.Downloader.java

/**
 * Get data via HTTP as an InputStream, following redirects, and supplying
 * credentials if the host is the Fedora server.
 *//*from  w  w w  .ja  v a  2 s .c  o  m*/
public InputStream get(String url) throws IOException {
    GetMethod get = null;
    boolean ok = false;
    try {
        m_cManager.getParams().setConnectionTimeout(20000);
        HttpClient client = new HttpClient(m_cManager);
        client.getState().setCredentials(m_authScope, m_creds);
        client.getParams().setAuthenticationPreemptive(true); // don't bother with challenges
        int redirectCount = 0; // how many redirects did we follow
        int resultCode = 300; // not really, but enter the loop that way
        Dimension d = null;
        while (resultCode > 299 && resultCode < 400 && redirectCount < 25) {
            get = new GetMethod(url);
            get.setDoAuthentication(true);
            get.setFollowRedirects(true);
            if (Administrator.INSTANCE != null) {
                d = Administrator.PROGRESS.getSize();
                // if they're using Administrator, tell them we're downloading...
                Administrator.PROGRESS.setString("Downloading " + url + " . . .");
                Administrator.PROGRESS.setValue(100);
                Administrator.PROGRESS.paintImmediately(0, 0, (int) d.getWidth() - 1, (int) d.getHeight() - 1);
            }
            resultCode = client.executeMethod(get);
            if (resultCode > 299 && resultCode < 400) {
                redirectCount++;
                url = get.getResponseHeader("Location").getValue();
            }
        }
        if (resultCode != 200) {
            System.err.println(get.getResponseBodyAsString());
            throw new IOException(
                    "Server returned error: " + resultCode + " " + HttpStatus.getStatusText(resultCode));
        }
        ok = true;
        if (Administrator.INSTANCE != null) {
            // cache it to a file
            File tempFile = File.createTempFile("fedora-client-download-", null);
            tempFile.deleteOnExit();
            HashMap PARMS = new HashMap();
            PARMS.put("in", get.getResponseBodyAsStream());
            PARMS.put("out", new FileOutputStream(tempFile));
            // do the actual download in a safe thread
            SwingWorker worker = new SwingWorker(PARMS) {

                @Override
                public Object construct() {
                    try {
                        StreamUtility.pipeStream((InputStream) parms.get("in"), (OutputStream) parms.get("out"),
                                8192);
                    } catch (Exception e) {
                        thrownException = e;
                    }
                    return "";
                }
            };
            worker.start();
            // The following code will run in the (safe)
            // Swing event dispatcher thread.
            int ms = 200;
            while (!worker.done) {
                try {
                    Administrator.PROGRESS.setValue(ms);
                    Administrator.PROGRESS.paintImmediately(0, 0, (int) d.getWidth() - 1,
                            (int) d.getHeight() - 1);
                    Thread.sleep(100);
                    ms = ms + 100;
                    if (ms >= 2000) {
                        ms = 200;
                    }
                } catch (InterruptedException ie) {
                }
            }
            if (worker.thrownException != null) {
                throw worker.thrownException;
            }
            Administrator.PROGRESS.setValue(2000);
            Administrator.PROGRESS.paintImmediately(0, 0, (int) d.getWidth() - 1, (int) d.getHeight() - 1);
            try {
                Thread.sleep(100);
            } catch (InterruptedException ie) {
            }
            return new FileInputStream(tempFile);
        }
        return get.getResponseBodyAsStream();
    } catch (Exception e) {
        throw new IOException(e.getMessage());
    } finally {
        if (get != null && !ok) {
            get.releaseConnection();
        }
        if (Administrator.INSTANCE != null) {
            Administrator.PROGRESS.setValue(0);
            Administrator.PROGRESS.setString("");
        }
    }

}

From source file:SciTK.Plot.java

/** 
 * Constructor (automatic window sizing) 
 *///from  ww w. j a va 2s . com
public Plot() {
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    def_width = (int) (screenSize.getWidth() / 4);
    def_height = (int) (screenSize.getHeight() / 4);
    // for very wide screen resolutions (i.e. dual monitor setups)
    // the above creates funny results. Introduce a max aspect ratio:
    def_width = Math.min(def_width, 2 * def_height);
}

From source file:com.projity.dialog.assignment.AssignmentEntryPane.java

public void init() {
    if (project == null)
        return;//from  w w  w  .  ja v a2 s.  co m
    ResourcePool pool = project.getResourcePool();

    //      if (assignmentModel==null){
    pool.getResourceOutline().getHierarchy().removeHierarchyListener(this);
    pool.getResourceOutline().getHierarchy().addHierarchyListener(this);

    assignmentModel = NodeModelFactory.getInstance().replicate(pool.getResourceOutline(),
            new NodeFactoryTransformer());
    assignmentModel.getHierarchy().setNbEndVoidNodes(0); // don't allow blank lines
    //      }
    if (spreadSheet == null) {
        spreadSheet = new AssignmentSpreadSheet(resourceAssigner);
        spreadSheet.setSpreadSheetCategory(spreadsheetCategory); // for columns.  Must do first
        spreadSheet.setActions(new String[] {});

    }

    cache = NodeModelCacheFactory.getInstance().createDefaultCache(assignmentModel, pool,
            NodeModelCache.ASSIGNMENT_TYPE, "AssignmentEntry", transformerClosure);
    SpreadSheetFieldArray fields = getFields();
    spreadSheet.setCache(cache, fields, fields.getCellStyle(), fields.getActionList());

    // set widths of these columns explicitly
    if (!replace) { //TODO width should come from definition in xml, not hard coded here
        //         spreadSheet.getColumnModel().getColumn(REQUEST_DEMAND_TYPE_COLUMN).setPreferredWidth(50);
        spreadSheet.getColumnModel().getColumn(UNITS_COLUMN).setPreferredWidth(50);
    }

    JViewport viewport = createViewport();
    viewport.setView(spreadSheet);
    setViewport(viewport);

    setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    Dimension d = spreadSheet.getPreferredSize();
    Dimension enclosing = new Dimension();

    //big awful hack to remove
    GraphicConfiguration config = GraphicConfiguration.getInstance();
    int rowHeaderWidth = config.getRowHeaderWidth() + spreadSheet.getRowMargin() * 2; //should be rowHeader's one

    //      TableColumnModel tm=spreadSheet.getColumnModel();
    //      int w=tm.getTotalColumnWidth();

    enclosing.setSize(d.getWidth()/*+rowHeaderWidth*/, d.getHeight());
    viewport.setPreferredSize(enclosing);

    //setBorder(new EmptyBorder(0,0,0,0));
    updateTable();
}

From source file:org.martus.client.swingui.PureFxMainWindow.java

@Override
public void restoreWindowSizeAndState() {
    Dimension appDimension = getUiState().getCurrentAppDimension();
    Point appPosition = getUiState().getCurrentAppPosition();
    boolean showMaximized = getUiState().isCurrentAppMaximized();

    if (appDimension.getHeight() == 0 || appDimension.getWidth() == 0) {
        showMaximized = true;/*from   w w  w .j av  a  2s .  co  m*/
    } else {
        realStage.setWidth(appDimension.getWidth());
        realStage.setHeight(getNonFullScreenHeight(appDimension.getHeight()));
    }

    realStage.setX(appPosition.getX());
    realStage.setY(appPosition.getY());
    realStage.setMaximized(showMaximized);

    getUiState().setCurrentAppDimension(getMainWindowSize());
}

From source file:com.hp.autonomy.frontend.reports.powerpoint.PowerPointServiceImpl.java

/**
 * Internal implementation to add an image (a world map, though other image data is also fine) to a slide.
 *   Preserves the original image's aspect ratio, leaving blank space below and to the sides of the image.
 * @param slide the slide to add to./*from   ww w . j a  va  2  s. c om*/
 * @param anchor bounding rectangle to draw onto, in PowerPoint coordinates.
 * @param picture the picture data.
 * @param markers an array of markers to draw over the map.
 * @param polygons
 * @return the picture shape object added to the slide.
 */
private static XSLFPictureShape addMap(final XSLFSlide slide, final Rectangle2D.Double anchor,
        final XSLFPictureData picture, final Marker[] markers, final MapData.Polygon[] polygons) {
    double tgtW = anchor.getWidth(), tgtH = anchor.getHeight();

    final Dimension size = picture.getImageDimension();
    final double ratio = size.getWidth() / size.getHeight();

    if (ratio > tgtW / tgtH) {
        // source image is wider than target, clip fixed width variable height
        tgtH = tgtW / ratio;
    } else {
        tgtW = tgtH * ratio;
    }

    final XSLFPictureShape canvas = slide.createPicture(picture);
    // Vertically align top, horizontally-align center
    final double offsetX = anchor.getMinX() + 0.5 * (anchor.getWidth() - tgtW), offsetY = anchor.getMinY();
    canvas.setAnchor(new Rectangle2D.Double(offsetX, offsetY, tgtW, tgtH));

    if (polygons != null) {
        for (MapData.Polygon polygon : polygons) {
            final Color color = Color.decode(polygon.getColor());
            final double[][] shapes = polygon.getPoints();
            // The ESRI spec version 1.2.1 from http://www.opengeospatial.org/standards/sfa has section 6.1.11.1,
            //    which defines polygons as follows:
            /// A Polygon is a planar Surface defined by 1 exterior boundary and 0 or more interior boundaries.
            //    Each interior boundary defines a hole in the Polygon. A Triangle is a polygon with 3 distinct,
            //    non-collinear vertices and no interior boundary.
            /// The exterior boundary LinearRing defines the top? of the surface which is the side of the surface
            //    from which the exterior boundary appears to traverse the boundary in a counter clockwise direction.
            //    The interior LinearRings will have the opposite orientation, and appear as clockwise
            //    when viewed from the top?
            // so it's even-odd winding (whereas the Path2D default is non-zero-winding).
            final Path2D.Double path = new Path2D.Double(Path2D.WIND_EVEN_ODD);

            for (final double[] points : shapes) {
                for (int ii = 0; ii < points.length; ii += 2) {
                    final double x1 = offsetX + points[ii] * tgtW;
                    final double y1 = offsetY + points[ii + 1] * tgtH;
                    if (ii == 0) {
                        path.moveTo(x1, y1);
                    } else {
                        path.lineTo(x1, y1);
                    }
                }
                path.closePath();
            }

            final XSLFFreeformShape freeform = slide.createFreeform();
            freeform.setPath(path);
            freeform.setStrokeStyle(0.5);
            // There's a 0.5 alpha transparency on the stroke, and a 0.2 alpha transparency on the polygon fill.
            freeform.setLineColor(transparentColor(color, 128));
            freeform.setFillColor(transparentColor(color, 51));

            if (StringUtils.isNotEmpty(polygon.getText())) {
                final PackageRelationship rel = freeform.getSheet().getPackagePart().addRelationship(
                        slide.getPackagePart().getPartName(), TargetMode.INTERNAL,
                        XSLFRelation.SLIDE.getRelation());
                // We create a hyperlink which links back to this slide; so we get hover-over-detail-text on the polygon
                final CTHyperlink link = ((CTShape) freeform.getXmlObject()).getNvSpPr().getCNvPr()
                        .addNewHlinkClick();
                link.setTooltip(polygon.getText());
                link.setId(rel.getId());
                link.setAction("ppaction://hlinksldjump");
            }
        }
    }

    for (Marker marker : markers) {
        final Color color = Color.decode(marker.getColor());
        final double centerX = offsetX + marker.getX() * tgtW;
        final double centerY = offsetY + marker.getY() * tgtH;

        if (marker.isCluster()) {
            final XSLFGroupShape group = slide.createGroup();
            double halfMark = 10;
            double mark = halfMark * 2;
            double innerHalfMark = 7;
            double innerMark = innerHalfMark * 2;
            // align these so the middle is the latlng position
            final Rectangle2D.Double groupAnchor = new Rectangle2D.Double(centerX - halfMark,
                    centerY - halfMark, mark, mark);

            group.setAnchor(groupAnchor);
            group.setInteriorAnchor(groupAnchor);

            final XSLFAutoShape shape = group.createAutoShape();
            shape.setShapeType(ShapeType.ELLIPSE);
            final boolean fade = marker.isFade();
            // There's a 0.3 alpha transparency (255 * 0.3 is 76) when a marker is faded out
            final int FADE_ALPHA = 76;
            shape.setFillColor(transparentColor(color, fade ? 47 : 154));
            shape.setAnchor(groupAnchor);

            final XSLFAutoShape inner = group.createAutoShape();
            inner.setFillColor(fade ? transparentColor(color, FADE_ALPHA) : color);
            inner.setLineWidth(0.1);
            inner.setLineColor(new Color((int) (color.getRed() * 0.9), (int) (color.getGreen() * 0.9),
                    (int) (color.getBlue() * 0.9), fade ? FADE_ALPHA : 255));
            inner.setShapeType(ShapeType.ELLIPSE);
            inner.setHorizontalCentered(true);
            inner.setWordWrap(false);
            inner.setVerticalAlignment(VerticalAlignment.MIDDLE);
            inner.clearText();
            final XSLFTextParagraph para = inner.addNewTextParagraph();
            para.setTextAlign(TextParagraph.TextAlign.CENTER);
            final XSLFTextRun text = para.addNewTextRun();
            text.setFontSize(6.0);
            final Color fontColor = Color.decode(StringUtils.defaultString(marker.getFontColor(), "#000000"));
            text.setFontColor(fade ? transparentColor(fontColor, FADE_ALPHA) : fontColor);
            text.setText(marker.getText());
            inner.setAnchor(new Rectangle2D.Double(centerX - innerHalfMark, centerY - innerHalfMark, innerMark,
                    innerMark));
        } else {
            final XSLFGroupShape group = slide.createGroup();

            final XSLFFreeformShape shape = group.createFreeform();
            shape.setHorizontalCentered(true);
            shape.setWordWrap(false);

            shape.setVerticalAlignment(VerticalAlignment.BOTTOM);
            shape.setLineWidth(0.5);
            shape.setLineColor(color.darker());
            shape.setFillColor(transparentColor(color, 210));

            final double halfMark = 8, mark = halfMark * 2, extension = 0.85,
                    markerHeight = (0.5 + extension) * mark, angle = Math.asin(0.5 / extension) * 180 / Math.PI;

            // Set group position
            group.setAnchor(
                    new Rectangle2D.Double(centerX - halfMark, centerY - markerHeight, mark, markerHeight));
            group.setInteriorAnchor(new Rectangle2D.Double(0, 0, mark, markerHeight));

            // Draw a semicircle and a triangle to represent the marker, pointing at the precise x,y location
            final Path2D.Double path = new Path2D.Double();
            path.moveTo(halfMark, markerHeight);
            path.append(new Arc2D.Double(0, 0, mark, mark, -angle, 180 + angle + angle, Arc2D.OPEN), true);
            path.lineTo(halfMark, markerHeight);
            shape.setPath(path);
            shape.setAnchor(new Rectangle2D.Double(0, 0, mark, markerHeight));

            final XSLFAutoShape disc = group.createAutoShape();
            disc.setShapeType(ShapeType.DONUT);
            final double discRadius = 0.25 * mark;
            final double discDiameter = 2 * discRadius;
            disc.setAnchor(new Rectangle2D.Double(halfMark - discRadius, halfMark - discRadius, discDiameter,
                    discDiameter));
            disc.setFillColor(Color.WHITE);
            disc.setLineColor(Color.WHITE);

            if (StringUtils.isNotEmpty(marker.getText())) {
                final PackageRelationship rel = shape.getSheet().getPackagePart().addRelationship(
                        slide.getPackagePart().getPartName(), TargetMode.INTERNAL,
                        XSLFRelation.SLIDE.getRelation());
                // We create a hyperlink which links back to this slide; so we get hover-over-detail-text on the marker
                // Annoyingly, you can't put a link on the group, just on the individual shapes.
                for (XSLFShape clickable : group.getShapes()) {
                    final CTHyperlink link = ((CTShape) clickable.getXmlObject()).getNvSpPr().getCNvPr()
                            .addNewHlinkClick();
                    link.setTooltip(marker.getText());
                    link.setId(rel.getId());
                    link.setAction("ppaction://hlinksldjump");
                }
            }
        }
    }

    return canvas;
}