| 1 28 package net.sf.jasperreports.view; 29 30 import java.awt.BasicStroke ; 31 import java.awt.Color ; 32 import java.awt.Container ; 33 import java.awt.Cursor ; 34 import java.awt.Dimension ; 35 import java.awt.Graphics2D ; 36 import java.awt.Image ; 37 import java.awt.Point ; 38 import java.awt.RenderingHints ; 39 import java.awt.Shape ; 40 import java.awt.Stroke ; 41 import java.awt.Toolkit ; 42 import java.awt.font.TextAttribute ; 43 import java.awt.geom.AffineTransform ; 44 import java.awt.image.BufferedImage ; 45 import java.io.InputStream ; 46 import java.util.Collection ; 47 import java.util.HashMap ; 48 import java.util.Iterator ; 49 import java.util.List ; 50 import java.util.Map ; 51 52 import javax.swing.DefaultComboBoxModel ; 53 import javax.swing.ImageIcon ; 54 import javax.swing.JOptionPane ; 55 import javax.swing.JViewport ; 56 57 import net.sf.jasperreports.crosstabs.JRCellContents; 58 import net.sf.jasperreports.crosstabs.JRCrosstab; 59 import net.sf.jasperreports.crosstabs.JRCrosstabCell; 60 import net.sf.jasperreports.crosstabs.JRCrosstabColumnGroup; 61 import net.sf.jasperreports.crosstabs.JRCrosstabRowGroup; 62 import net.sf.jasperreports.crosstabs.fill.calculation.BucketDefinition; 63 import net.sf.jasperreports.engine.JRAlignment; 64 import net.sf.jasperreports.engine.JRBand; 65 import net.sf.jasperreports.engine.JRBox; 66 import net.sf.jasperreports.engine.JRBreak; 67 import net.sf.jasperreports.engine.JRChart; 68 import net.sf.jasperreports.engine.JRChild; 69 import net.sf.jasperreports.engine.JRElement; 70 import net.sf.jasperreports.engine.JRElementGroup; 71 import net.sf.jasperreports.engine.JREllipse; 72 import net.sf.jasperreports.engine.JRException; 73 import net.sf.jasperreports.engine.JRExpression; 74 import net.sf.jasperreports.engine.JRExpressionChunk; 75 import net.sf.jasperreports.engine.JRFrame; 76 import net.sf.jasperreports.engine.JRGraphicElement; 77 import net.sf.jasperreports.engine.JRGroup; 78 import net.sf.jasperreports.engine.JRImage; 79 import net.sf.jasperreports.engine.JRLine; 80 import net.sf.jasperreports.engine.JRRectangle; 81 import net.sf.jasperreports.engine.JRReport; 82 import net.sf.jasperreports.engine.JRStaticText; 83 import net.sf.jasperreports.engine.JRSubreport; 84 import net.sf.jasperreports.engine.JRTextElement; 85 import net.sf.jasperreports.engine.JRTextField; 86 import net.sf.jasperreports.engine.JasperCompileManager; 87 import net.sf.jasperreports.engine.base.JRBaseBox; 88 import net.sf.jasperreports.engine.design.JRDesignFrame; 89 import net.sf.jasperreports.engine.design.JasperDesign; 90 import net.sf.jasperreports.engine.export.TextRenderer; 91 import net.sf.jasperreports.engine.fill.TextMeasurer; 92 import net.sf.jasperreports.engine.util.JRFontUtil; 93 import net.sf.jasperreports.engine.util.JRGraphEnvInitializer; 94 import net.sf.jasperreports.engine.util.JRImageLoader; 95 import net.sf.jasperreports.engine.util.JRLoader; 96 import net.sf.jasperreports.engine.util.JRStyledText; 97 import net.sf.jasperreports.engine.util.JRStyledTextParser; 98 import net.sf.jasperreports.engine.xml.JRXmlLoader; 99 100 import org.xml.sax.SAXException ; 101 102 103 107 public class JRDesignViewer extends javax.swing.JPanel  108 { 109 110 111 114 private static final int TYPE_FILE_NAME = 1; 115 private static final int TYPE_INPUT_STREAM = 2; 116 private static final int TYPE_JASPER_DESIGN = 3; 117 118 private static final int zooms[] = {50, 75, 100, 125, 150, 175, 200, 250}; 119 120 private int type = TYPE_FILE_NAME; 121 private boolean isXML = false; 122 private String reportFileName = null; 123 private JRReport report = null; 124 private float zoom = 1f; 125 126 129 private int screenResolution = JRViewer.REPORT_RESOLUTION; 130 131 134 private float realZoom = 0f; 135 136 private int offsetY = 0; 137 private int upColumns = 0; 138 private int downColumns = 0; 139 140 private int downX = 0; 141 private int downY = 0; 142 143 protected JRStyledTextParser styledTextParser = new JRStyledTextParser(); 144 protected TextRenderer textRenderer = TextRenderer.getInstance(); 145 146 147 148 public JRDesignViewer(String fileName, boolean isXML) throws JRException 149 { 150 JRGraphEnvInitializer.initializeGraphEnv(); 151 152 setScreenDetails(); 153 154 initComponents(); 155 156 this.loadReport(fileName, isXML); 157 this.cmbZoom.setSelectedIndex(2); } 159 160 161 162 public JRDesignViewer(InputStream is, boolean isXML) throws JRException 163 { 164 JRGraphEnvInitializer.initializeGraphEnv(); 165 166 setScreenDetails(); 167 168 initComponents(); 169 170 this.loadReport(is, isXML); 171 this.cmbZoom.setSelectedIndex(2); } 173 174 175 176 public JRDesignViewer(JRReport report) throws JRException 177 { 178 JRGraphEnvInitializer.initializeGraphEnv(); 179 180 setScreenDetails(); 181 182 initComponents(); 183 184 this.loadReport(report); 185 this.cmbZoom.setSelectedIndex(2); } 187 188 189 private void setScreenDetails() 190 { 191 screenResolution = Toolkit.getDefaultToolkit().getScreenResolution(); 192 setZoom(1f); 193 } 194 195 196 201 private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; 203 204 tlbToolBar = new javax.swing.JPanel (); 205 btnReload = new javax.swing.JButton (); 206 pnlSep01 = new javax.swing.JPanel (); 207 pnlSep02 = new javax.swing.JPanel (); 208 btnZoomIn = new javax.swing.JButton (); 209 btnZoomOut = new javax.swing.JButton (); 210 cmbZoom = new javax.swing.JComboBox (); 211 DefaultComboBoxModel model = new DefaultComboBoxModel (); 212 for(int i = 0; i < zooms.length; i++) 213 { 214 model.addElement("" + zooms[i] + "%"); 215 } 216 cmbZoom.setModel(model); 217 218 pnlMain = new javax.swing.JPanel (); 219 scrollPane = new javax.swing.JScrollPane (); 220 scrollPane.getHorizontalScrollBar().setUnitIncrement(5); 221 scrollPane.getVerticalScrollBar().setUnitIncrement(5); 222 223 pnlInScroll = new javax.swing.JPanel (); 224 pnlPage = new javax.swing.JPanel (); 225 jPanel4 = new javax.swing.JPanel (); 226 jPanel5 = new javax.swing.JPanel (); 227 jPanel6 = new javax.swing.JPanel (); 228 jPanel7 = new javax.swing.JPanel (); 229 jPanel8 = new javax.swing.JPanel (); 230 jLabel1 = new javax.swing.JLabel (); 231 jPanel9 = new javax.swing.JPanel (); 232 lblPage = new javax.swing.JLabel (); 233 234 setLayout(new java.awt.BorderLayout ()); 235 236 tlbToolBar.setLayout(new java.awt.FlowLayout (java.awt.FlowLayout.LEFT, 0, 2)); 237 238 btnReload.setIcon(new javax.swing.ImageIcon (getClass().getResource("/net/sf/jasperreports/view/images/reload.GIF"))); 239 btnReload.setText("Reload"); 240 btnReload.setToolTipText("Reload Document"); 241 btnReload.setMargin(new java.awt.Insets (2, 2, 2, 2)); 242 btnReload.setMaximumSize(new java.awt.Dimension (80, 23)); 243 btnReload.setMinimumSize(new java.awt.Dimension (80, 23)); 244 btnReload.setPreferredSize(new java.awt.Dimension (80, 23)); 245 btnReload.addActionListener(new java.awt.event.ActionListener () { 246 public void actionPerformed(java.awt.event.ActionEvent evt) { 247 btnReloadActionPerformed(); 248 } 249 }); 250 251 tlbToolBar.add(btnReload); 252 253 pnlSep01.setMaximumSize(new java.awt.Dimension (10, 10)); 254 tlbToolBar.add(pnlSep01); 255 256 pnlSep02.setMaximumSize(new java.awt.Dimension (10, 10)); 257 tlbToolBar.add(pnlSep02); 258 259 btnZoomIn.setIcon(new javax.swing.ImageIcon (getClass().getResource("/net/sf/jasperreports/view/images/zoomin.GIF"))); 260 btnZoomIn.setToolTipText("Zoom In"); 261 btnZoomIn.setMargin(new java.awt.Insets (2, 2, 2, 2)); 262 btnZoomIn.setMaximumSize(new java.awt.Dimension (23, 23)); 263 btnZoomIn.setMinimumSize(new java.awt.Dimension (23, 23)); 264 btnZoomIn.setPreferredSize(new java.awt.Dimension (23, 23)); 265 btnZoomIn.addActionListener(new java.awt.event.ActionListener () { 266 public void actionPerformed(java.awt.event.ActionEvent evt) { 267 btnZoomInActionPerformed(); 268 } 269 }); 270 271 tlbToolBar.add(btnZoomIn); 272 273 btnZoomOut.setIcon(new javax.swing.ImageIcon (getClass().getResource("/net/sf/jasperreports/view/images/zoomout.GIF"))); 274 btnZoomOut.setToolTipText("Zoom Out"); 275 btnZoomOut.setMargin(new java.awt.Insets (2, 2, 2, 2)); 276 btnZoomOut.setMaximumSize(new java.awt.Dimension (23, 23)); 277 btnZoomOut.setMinimumSize(new java.awt.Dimension (23, 23)); 278 btnZoomOut.setPreferredSize(new java.awt.Dimension (23, 23)); 279 btnZoomOut.addActionListener(new java.awt.event.ActionListener () { 280 public void actionPerformed(java.awt.event.ActionEvent evt) { 281 btnZoomOutActionPerformed(); 282 } 283 }); 284 285 tlbToolBar.add(btnZoomOut); 286 287 cmbZoom.setToolTipText("Zoom Ratio"); 288 cmbZoom.setMaximumSize(new java.awt.Dimension (80, 23)); 289 cmbZoom.setMinimumSize(new java.awt.Dimension (80, 23)); 290 cmbZoom.setPreferredSize(new java.awt.Dimension (80, 23)); 291 cmbZoom.addActionListener(new java.awt.event.ActionListener () { 292 public void actionPerformed(java.awt.event.ActionEvent evt) { 293 cmbZoomActionPerformed(); 294 } 295 }); 296 297 tlbToolBar.add(cmbZoom); 298 299 add(tlbToolBar, java.awt.BorderLayout.NORTH); 300 301 pnlMain.setLayout(new java.awt.BorderLayout ()); 302 303 pnlInScroll.setLayout(new java.awt.GridBagLayout ()); 304 305 pnlPage.setLayout(new java.awt.BorderLayout ()); 306 307 pnlPage.setMinimumSize(new java.awt.Dimension (100, 100)); 308 pnlPage.setPreferredSize(new java.awt.Dimension (100, 100)); 309 jPanel4.setLayout(new java.awt.GridBagLayout ()); 310 311 jPanel4.setMinimumSize(new java.awt.Dimension (100, 120)); 312 jPanel4.setPreferredSize(new java.awt.Dimension (100, 120)); 313 jPanel5.setBackground(java.awt.Color.gray); 314 jPanel5.setMinimumSize(new java.awt.Dimension (5, 5)); 315 jPanel5.setPreferredSize(new java.awt.Dimension (5, 5)); 316 gridBagConstraints = new java.awt.GridBagConstraints (); 317 gridBagConstraints.gridx = 2; 318 gridBagConstraints.gridy = 1; 319 gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; 320 jPanel4.add(jPanel5, gridBagConstraints); 321 322 jPanel6.setMinimumSize(new java.awt.Dimension (5, 5)); 323 jPanel6.setPreferredSize(new java.awt.Dimension (5, 5)); 324 gridBagConstraints = new java.awt.GridBagConstraints (); 325 gridBagConstraints.gridx = 0; 326 gridBagConstraints.gridy = 2; 327 jPanel4.add(jPanel6, gridBagConstraints); 328 329 jPanel7.setBackground(java.awt.Color.gray); 330 jPanel7.setMinimumSize(new java.awt.Dimension (5, 5)); 331 jPanel7.setPreferredSize(new java.awt.Dimension (5, 5)); 332 gridBagConstraints = new java.awt.GridBagConstraints (); 333 gridBagConstraints.gridx = 1; 334 gridBagConstraints.gridy = 2; 335 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 336 jPanel4.add(jPanel7, gridBagConstraints); 337 338 jPanel8.setBackground(java.awt.Color.gray); 339 jPanel8.setMinimumSize(new java.awt.Dimension (5, 5)); 340 jPanel8.setPreferredSize(new java.awt.Dimension (5, 5)); 341 jLabel1.setText("jLabel1"); 342 jPanel8.add(jLabel1); 343 344 gridBagConstraints = new java.awt.GridBagConstraints (); 345 gridBagConstraints.gridx = 2; 346 gridBagConstraints.gridy = 2; 347 jPanel4.add(jPanel8, gridBagConstraints); 348 349 jPanel9.setMinimumSize(new java.awt.Dimension (5, 5)); 350 jPanel9.setPreferredSize(new java.awt.Dimension (5, 5)); 351 gridBagConstraints = new java.awt.GridBagConstraints (); 352 gridBagConstraints.gridx = 2; 353 gridBagConstraints.gridy = 0; 354 jPanel4.add(jPanel9, gridBagConstraints); 355 356 lblPage.setBackground(java.awt.Color.white); 357 lblPage.setBorder(new javax.swing.border.LineBorder (new java.awt.Color (0, 0, 0))); 358 lblPage.setOpaque(true); 359 lblPage.addMouseListener(new java.awt.event.MouseAdapter () { 360 public void mousePressed(java.awt.event.MouseEvent evt) { 361 lblPageMousePressed(evt); 362 } 363 public void mouseReleased(java.awt.event.MouseEvent evt) { 364 lblPageMouseReleased(); 365 } 366 }); 367 368 lblPage.addMouseMotionListener(new java.awt.event.MouseMotionAdapter () { 369 public void mouseDragged(java.awt.event.MouseEvent evt) { 370 lblPageMouseDragged(evt); 371 } 372 }); 373 374 gridBagConstraints = new java.awt.GridBagConstraints (); 375 gridBagConstraints.gridx = 0; 376 gridBagConstraints.gridy = 0; 377 gridBagConstraints.gridwidth = 2; 378 gridBagConstraints.gridheight = 2; 379 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 380 gridBagConstraints.weightx = 1.0; 381 gridBagConstraints.weighty = 1.0; 382 jPanel4.add(lblPage, gridBagConstraints); 383 384 pnlPage.add(jPanel4, java.awt.BorderLayout.CENTER); 385 386 gridBagConstraints = new java.awt.GridBagConstraints (); 387 gridBagConstraints.insets = new java.awt.Insets (5, 5, 5, 5); 388 pnlInScroll.add(pnlPage, gridBagConstraints); 389 390 scrollPane.setViewportView(pnlInScroll); 391 392 pnlMain.add(scrollPane, java.awt.BorderLayout.CENTER); 393 394 add(pnlMain, java.awt.BorderLayout.CENTER); 395 396 } 398 void btnReloadActionPerformed() { if (this.type == TYPE_FILE_NAME) 402 { 403 try 404 { 405 this.loadReport(this.reportFileName, this.isXML); 406 this.refreshDesign(); 408 } 409 catch (JRException e) 410 { 411 e.printStackTrace(); 412 JOptionPane.showMessageDialog(this, "Error loading report design. See console for details."); 413 } 414 } 415 } 417 void btnZoomInActionPerformed() { int index = this.cmbZoom.getSelectedIndex(); 421 if (index < this.cmbZoom.getModel().getSize() - 1) 422 { 423 this.cmbZoom.setSelectedIndex(index + 1); 424 } 425 } 427 void btnZoomOutActionPerformed() { int index = this.cmbZoom.getSelectedIndex(); 431 if (index > 0) 432 { 433 this.cmbZoom.setSelectedIndex(index - 1); 434 } 435 } 437 void lblPageMousePressed(java.awt.event.MouseEvent evt) { this.lblPage.setCursor(new Cursor (Cursor.MOVE_CURSOR)); 441 442 this.downX = evt.getX(); 443 this.downY = evt.getY(); 444 } 446 void lblPageMouseReleased() { this.lblPage.setCursor(new Cursor (Cursor.DEFAULT_CURSOR)); 450 } 452 void lblPageMouseDragged(java.awt.event.MouseEvent evt) { Container container = pnlInScroll.getParent(); 456 if (container instanceof JViewport ) 457 { 458 JViewport viewport = (JViewport ) container; 459 Point point = viewport.getViewPosition(); 460 int newX = point.x - (evt.getX() - downX); 461 int newY = point.y - (evt.getY() - downY); 462 463 int maxX = pnlInScroll.getWidth() - viewport.getWidth(); 464 int maxY = pnlInScroll.getHeight() - viewport.getHeight(); 465 466 if (newX < 0) 467 { 468 newX = 0; 469 } 470 if (newX > maxX) 471 { 472 newX = maxX; 473 } 474 if (newY < 0) 475 { 476 newY = 0; 477 } 478 if (newY > maxY) 479 { 480 newY = maxY; 481 } 482 483 viewport.setViewPosition(new Point (newX, newY)); 484 } 485 } 487 void cmbZoomActionPerformed() { int index = this.cmbZoom.getSelectedIndex(); 491 setZoom(zooms[index] / 100f); 492 this.btnZoomIn.setEnabled( (index < this.cmbZoom.getModel().getSize() - 1) ); 493 this.btnZoomOut.setEnabled( (index > 0) ); 494 this.refreshDesign(); 495 } 497 498 private void setZoom(float zoom) 499 { 500 this.zoom = zoom; 501 this.realZoom = this.zoom * screenResolution / JRViewer.REPORT_RESOLUTION; 502 } 503 504 505 507 private void verifyDesign(JasperDesign jasperDesign) throws JRException 508 { 509 510 Collection brokenRules = JasperCompileManager.verifyDesign(jasperDesign); 511 if (brokenRules != null && brokenRules.size() > 0) 512 { 513 StringBuffer sbuffer = new StringBuffer (); 514 sbuffer.append("Report definition not valid : "); 515 int i = 1; 516 for(Iterator it = brokenRules.iterator(); it.hasNext(); i++) 517 { 518 sbuffer.append("\n\t " + i + ". " + (String )it.next()); 519 } 520 521 throw new JRException(sbuffer.toString()); 522 } 523 } 524 525 526 528 private void loadReport(String fileName, boolean isXmlReport) throws JRException 529 { 530 if (isXmlReport) 531 { 532 JasperDesign jasperDesign = JRXmlLoader.load(fileName); 533 setReport(jasperDesign); 534 } 535 else 536 { 537 setReport((JRReport) JRLoader.loadObject(fileName)); 538 } 539 this.type = TYPE_FILE_NAME; 540 this.isXML = isXmlReport; 541 this.reportFileName = fileName; 542 this.setOffsetY(); 543 this.btnReload.setEnabled(true); 544 } 545 546 547 549 private void loadReport(InputStream is, boolean isXmlReport) throws JRException 550 { 551 if (isXmlReport) 552 { 553 JasperDesign jasperDesign = JRXmlLoader.load(is); 554 setReport(jasperDesign); 555 } 556 else 557 { 558 setReport((JRReport) JRLoader.loadObject(is)); 559 } 560 this.type = TYPE_INPUT_STREAM; 561 this.isXML = isXmlReport; 562 this.setOffsetY(); 563 this.btnReload.setEnabled(false); 564 } 565 566 567 569 private void loadReport(JRReport rep) throws JRException 570 { 571 setReport(rep); 572 this.type = TYPE_JASPER_DESIGN; 573 this.isXML = false; 574 this.setOffsetY(); 575 this.btnReload.setEnabled(false); 576 } 577 578 private void setReport(JRReport report) throws JRException 579 { 580 if (report instanceof JasperDesign) 581 { 582 verifyDesign((JasperDesign) report); 583 } 584 585 this.report = report; 586 } 587 588 589 592 public void setOffsetY() 593 { 594 offsetY = report.getTopMargin(); 595 offsetY += (report.getTitle() != null ? report.getTitle().getHeight() : 0); 596 offsetY += (report.getPageHeader() != null ? report.getPageHeader().getHeight() : 0); 597 upColumns = offsetY; 598 offsetY += (report.getColumnHeader() != null ? report.getColumnHeader().getHeight() : 0); 599 600 JRGroup group = null; 601 JRGroup[] groups = report.getGroups(); 602 if (groups != null && groups.length > 0) 603 { 604 for(int i = 0; i < groups.length; i++) 605 { 606 group = groups[i]; 607 608 offsetY += (group.getGroupHeader() != null ? group.getGroupHeader().getHeight() : 0); 609 } 610 } 611 612 offsetY += (report.getDetail() != null ? report.getDetail().getHeight() : 0); 613 614 if (groups != null && groups.length > 0) 615 { 616 for(int i = groups.length - 1; i >= 0; i--) 617 { 618 group = groups[i]; 619 620 offsetY += (group.getGroupFooter() != null ? group.getGroupFooter().getHeight() : 0); 621 } 622 } 623 624 offsetY += (report.getColumnFooter() != null ? report.getColumnFooter().getHeight() : 0); 625 downColumns = offsetY; 626 offsetY += (report.getPageFooter() != null ? report.getPageFooter().getHeight() : 0); 627 offsetY += (report.getLastPageFooter() != null ? report.getLastPageFooter().getHeight() : 0); 628 offsetY += (report.getSummary() != null ? report.getSummary().getHeight() : 0); 629 offsetY += report.getBottomMargin(); 630 } 631 632 633 635 private void refreshDesign() 636 { 637 Image image = null; 638 ImageIcon imageIcon = null; 639 640 Dimension dim = new Dimension ( 641 (int)(report.getPageWidth() * realZoom) + 8, (int)(offsetY * realZoom) + 8 643 ); 644 this.pnlPage.setMaximumSize(dim); 645 this.pnlPage.setMinimumSize(dim); 646 this.pnlPage.setPreferredSize(dim); 647 648 try 649 { 650 image = this.printDesignToImage(); 651 imageIcon = new ImageIcon (image); 652 } 653 catch(Exception e) 654 { 655 e.printStackTrace(); 656 } 657 658 this.lblPage.setIcon(imageIcon); 659 } 660 661 662 664 private Image printDesignToImage() 665 { 666 Image designImage = new BufferedImage ( 667 (int)(report.getPageWidth() * realZoom) + 1, 668 (int)(offsetY * realZoom) + 1, 669 BufferedImage.TYPE_INT_RGB 670 ); 671 Graphics2D grx = (Graphics2D )designImage.getGraphics(); 672 673 grx.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 674 grx.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 675 grx.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 676 677 AffineTransform atrans = new AffineTransform (); 678 atrans.scale(realZoom, realZoom); 679 grx.transform(atrans); 680 681 printDesign(grx); 682 683 grx.dispose(); 684 685 return designImage; 686 } 687 688 689 691 private void printDesign(Graphics2D grx) 692 { 693 Stroke dashedStroke = 694 new BasicStroke ( 695 1f / realZoom, 696 BasicStroke.CAP_BUTT, 697 BasicStroke.JOIN_BEVEL, 698 0f, 699 new float[]{5f, 3f}, 700 0f 701 ); 702 Color dashedColor = new Color (170, 170, 255); 703 704 grx.setColor(Color.white); 705 grx.fillRect( 706 0, 707 0, 708 report.getPageWidth() + 1, 709 offsetY + 1 710 ); 711 712 grx.setStroke(dashedStroke); 713 grx.setColor(dashedColor); 714 grx.drawLine( 715 report.getLeftMargin(), 716 0, 717 report.getLeftMargin(), 718 offsetY + 1 719 ); 720 grx.drawLine( 721 (report.getPageWidth() - report.getRightMargin()), 722 0, 723 (report.getPageWidth() - report.getRightMargin()), 724 offsetY + 1 725 ); 726 grx.drawLine( 727 (report.getLeftMargin() + report.getColumnWidth()), 728 upColumns, 729 (report.getLeftMargin() + report.getColumnWidth()), 730 downColumns 731 ); 732 grx.drawLine( 733 (report.getLeftMargin() + report.getColumnWidth() + report.getColumnSpacing()), 734 upColumns, 735 (report.getLeftMargin() + report.getColumnWidth() + report.getColumnSpacing()), 736 downColumns 737 ); 738 739 740 grx.translate( 741 report.getLeftMargin(), 742 report.getTopMargin() 743 ); 744 745 grx.setStroke(dashedStroke); 746 grx.setColor(dashedColor); 747 grx.drawLine( 748 &nb
|