1 /*
2  * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 package sun.jvm.hotspot.ui;
26 
27 import java.awt.*;
28 import java.awt.font.*;
29 import java.awt.geom.*;
30 import java.util.*;
31 
32 import sun.jvm.hotspot.debugger.*;
33 import sun.jvm.hotspot.utilities.*;
34 
35 /** This can be extended, along with AnnotatedMemoryPanel, to be an
36     arbitrarily complex mechanism, supporting user interaction,
37     etc. */
38 
39 public class Annotation {
40   private Interval interval;
41   private java.util.List<String> strings;
42   private java.util.List<Integer> heights;
43   private Color baseColor;
44   private int width;
45   private int height;
46   private int x;
47   private int y;
48 
49   /** The Annotation can handle the sense of lowAddress and
50       highAddress being swapped. */
Annotation(Address lowAddress, Address highAddress, String s)51   public Annotation(Address lowAddress,
52                     Address highAddress,
53                     String s) {
54     strings = new ArrayList<>();
55     heights = new ArrayList<>();
56     for (StringTokenizer tok = new StringTokenizer(s, "\n"); tok.hasMoreTokens(); ) {
57       strings.add(tok.nextToken());
58     }
59     if (AddressOps.lessThan(highAddress, lowAddress)) {
60       Address temp = lowAddress;
61       lowAddress = highAddress;
62       highAddress = temp;
63     }
64     interval = new Interval(lowAddress, highAddress);
65   }
66 
getInterval()67   public Interval getInterval() {
68     return interval;
69   }
70 
getLowAddress()71   public Address getLowAddress() {
72     return (Address) getInterval().getLowEndpoint();
73   }
74 
getHighAddress()75   public Address getHighAddress() {
76     return (Address) getInterval().getHighEndpoint();
77   }
78 
79   /** Draw the annotation at its current (x, y) position with its
80       current color */
draw(Graphics g)81   public void draw(Graphics g) {
82     g.setColor(baseColor);
83     int tmpY = y;
84     for (int i = 0; i < strings.size(); i++) {
85       String s = (String) strings.get(i);
86       Integer h = (Integer) heights.get(i);
87       g.drawString(s, x, tmpY);
88       tmpY += h.intValue();
89     }
90   }
91 
92   /** Sets the base color of this annotation. The annotation may
93       render sub-portions in a different color if desired. */
setColor(Color c)94   public void setColor(Color c) {
95     this.baseColor = c;
96   }
97 
98   /** Returns the base color of this annotation. */
getColor()99   public Color getColor() {
100     return baseColor;
101   }
102 
103   /** Computes width and height for this Annotation. Retrieve the
104       computed information using getWidth() and getHeight(). Separated
105       because the width and height only need to be recomputed if the
106       font changes. */
computeWidthAndHeight(Graphics g)107   public void computeWidthAndHeight(Graphics g) {
108     width = 0;
109     height = 0;
110     heights.clear();
111     for (Iterator iter = strings.iterator(); iter.hasNext(); ) {
112       String s = (String) iter.next();
113       Rectangle2D bounds = GraphicsUtilities.getStringBounds(s, g);
114       width  =  Math.max(width, (int) bounds.getWidth());
115       height += (int) bounds.getHeight();
116       heights.add((int) bounds.getHeight());
117     }
118   }
119 
getWidth()120   public int getWidth() {
121     return width;
122   }
123 
getHeight()124   public int getHeight() {
125     return height;
126   }
127 
128   /** Set the x and y position of this annotation */
setXAndY(int x, int y)129   public void setXAndY(int x, int y) {
130     this.x = x; this.y = y;
131   }
132 
setX(int x)133   public void setX(int x) {
134     this.x = x;
135   }
136 
getX()137   public int getX() {
138     return x;
139   }
140 
setY(int y)141   public void setY(int y) {
142     this.y = y;
143   }
144 
getY()145   public int getY() {
146     return y;
147   }
148 
getBounds()149   public Rectangle getBounds() {
150     return new Rectangle(x, y, width, height);
151   }
toString()152   public String toString() {
153     String result = "Annotation: lowAddr: " + getLowAddress() + " highAddr: " + getHighAddress() + " strings: "  + strings.size();
154     for (int i = 0; i < strings.size(); i++) {
155       result += "\n" + (String) strings.get(i);
156     }
157     return result;
158   }
159 }
160