    rev 48858 : Work in progress for JDK-6303622
    Use generic in Swing components like JComboBox
    1. Added generic return type and parameter type for JComboBox.
    2. Modified JList related classes as well.
    3. Reverted the changes made to "getSelectedValues" as suggested by Joe.
    4. Modified files that were failing on Linux and Mac as well.

       1 /*
       2  * Copyright (c) 2004, 2013, 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.  Oracle designates this
       8  * particular file as subject to the "Classpath" exception as provided
       9  * by Oracle in the LICENSE file that accompanied this code.
      10  *
      11  * This code is distributed in the hope that it will be useful, but WITHOUT
      12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  * version 2 for more details (a copy is included in the LICENSE file that
      15  * accompanied this code).
      16  *
      17  * You should have received a copy of the GNU General Public License version
      18  * 2 along with this work; if not, write to the Free Software Foundation,
      19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
      20  *
      21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
      22  * or visit www.oracle.com if you need additional information or have any
      23  * questions.
      24  */
      25
      26 package sun.tools.jconsole;
      27
      28 import java.awt.*;
      29 import java.awt.event.*;
      30 import java.io.*;
      31 import java.lang.management.*;
      32 import java.lang.reflect.*;
      33 import java.util.*;
      34 import java.util.concurrent.*;
      35
      36 import javax.accessibility.*;
      37 import javax.management.*;
      38 import javax.management.openmbean.CompositeData;
      39 import javax.swing.*;
      40 import javax.swing.border.*;
      41
      42
      43 import static sun.tools.jconsole.Formatter.*;
      44 import static sun.tools.jconsole.Utilities.*;
      45
      46 @SuppressWarnings("serial")
      47 class MemoryTab extends Tab implements ActionListener, ItemListener {
      48     JComboBox<Plotter> plotterChoice;
      49     TimeComboBox timeComboBox;
      50     JButton gcButton;
      51
      52     PlotterPanel plotterPanel;
      53     JPanel bottomPanel;
      54     HTMLPane details;
      55     PoolChart poolChart;
      56
      57     ArrayList<Plotter> plotterList;
      58     Plotter heapPlotter, nonHeapPlotter;
      59
      60     private MemoryOverviewPanel overviewPanel;
      61
      62     private static final String usedKey        = "used";
      63     private static final String committedKey   = "committed";
      64     private static final String maxKey         = "max";
      65     private static final String thresholdKey   = "threshold";
      66     private static final Color  usedColor      = Plotter.defaultColor;
      67     private static final Color  committedColor = null;
      68     private static final Color  maxColor       = null;
      69     private static final Color  thresholdColor = Color.red;
      70
      71     /*
      72       Hierarchy of panels and layouts for this tab:
      73
      74         MemoryTab (BorderLayout)
      75
      76             North:  topPanel (BorderLayout)
      77
      78                         Center: controlPanel (FlowLayout)
      79                                     plotterChoice, timeComboBox
      80
      81                         East:   topRightPanel (FlowLayout)
      82                                     gcButton
      83
      84             Center: plotterPanel
      85
      86                         Center: plotter
      87
      88             South:  bottomPanel (BorderLayout)
      89
      90                         Center: details
      91                         East:   poolChart
      92     */
      93
      94
      95     public static String getTabName() {
      96         return Messages.MEMORY;
      97     }
      98
      99     public MemoryTab(VMPanel vmPanel) {
     100         super(vmPanel, getTabName());
     101
     102         setLayout(new BorderLayout(0, 0));
     103         setBorder(new EmptyBorder(4, 4, 3, 4));
     104
     105         JPanel topPanel     = new JPanel(new BorderLayout());
     106                plotterPanel = new PlotterPanel(null);
     107                bottomPanel  = new JPanel(new BorderLayout());
     108
     109         add(topPanel,     BorderLayout.NORTH);
     110         add(plotterPanel, BorderLayout.CENTER);
     111
     112         JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 20, 5));
     113         topPanel.add(controlPanel, BorderLayout.CENTER);
     114
     115         // Plotter choice
     116         plotterChoice = new JComboBox<Plotter>();
     117         plotterChoice.addItemListener(this);
     118         controlPanel.add(new LabeledComponent(Messages.CHART_COLON,
     119                                               Resources.getMnemonicInt(Messages.CHART_COLON),
     120                                               plotterChoice));
     121
     122         // Range control
     123         timeComboBox = new TimeComboBox();
     124         controlPanel.add(new LabeledComponent(Messages.TIME_RANGE_COLON,
     125                                               Resources.getMnemonicInt(Messages.TIME_RANGE_COLON),
     126                                               timeComboBox));
     127
     128         gcButton = new JButton(Messages.PERFORM_GC);
     129         gcButton.setMnemonic(Resources.getMnemonicInt(Messages.PERFORM_GC));
     130         gcButton.addActionListener(this);
     131         gcButton.setToolTipText(Messages.PERFORM_GC_TOOLTIP);
     132         JPanel topRightPanel = new JPanel();
     133         topRightPanel.setBorder(new EmptyBorder(0, 65-8, 0, 70));
     134         topRightPanel.add(gcButton);
     135         topPanel.add(topRightPanel, BorderLayout.AFTER_LINE_ENDS);
     136
     137         bottomPanel.setBorder(new CompoundBorder(new TitledBorder(Messages.DETAILS),
     138                                                   new EmptyBorder(10, 10, 10, 10)));
     139
     140         details = new HTMLPane();
     141         setAccessibleName(details, Messages.DETAILS);
     142         bottomPanel.add(new JScrollPane(details), BorderLayout.CENTER);
     143
     144         poolChart = new PoolChart();
     145         bottomPanel.add(poolChart, BorderLayout.AFTER_LINE_ENDS);
     146     }
     147
     148
     149     private void createPlotters() throws IOException {
     150         plotterList = new ArrayList<Plotter>();
     151
     152         ProxyClient proxyClient = vmPanel.getProxyClient();
     153
     154         heapPlotter = new Plotter(Plotter.Unit.BYTES) {
     155             public String toString() {
     156                 return Messages.HEAP_MEMORY_USAGE;
     157             }
     158         };
     159         proxyClient.addWeakPropertyChangeListener(heapPlotter);
     160
     161         nonHeapPlotter = new Plotter(Plotter.Unit.BYTES) {
     162             public String toString() {
     163                 return Messages.NON_HEAP_MEMORY_USAGE;
     164             }
     165         };
     166
     167         setAccessibleName(heapPlotter,
     168                           Messages.MEMORY_TAB_HEAP_PLOTTER_ACCESSIBLE_NAME);
     169         setAccessibleName(nonHeapPlotter,
     170                           Messages.MEMORY_TAB_NON_HEAP_PLOTTER_ACCESSIBLE_NAME);
     171
     172         proxyClient.addWeakPropertyChangeListener(nonHeapPlotter);
     173
     174         heapPlotter.createSequence(usedKey,         Messages.USED,      usedColor,      true);
     175         heapPlotter.createSequence(committedKey,    Messages.COMMITTED, committedColor, false);
     176         heapPlotter.createSequence(maxKey,          Messages.MAX,       maxColor,       false);
     177
     178         nonHeapPlotter.createSequence(usedKey,      Messages.USED,      usedColor,      true);
     179         nonHeapPlotter.createSequence(committedKey, Messages.COMMITTED, committedColor, false);
     180         nonHeapPlotter.createSequence(maxKey,       Messages.MAX,       maxColor,       false);
     181
     182         plotterList.add(heapPlotter);
     183         plotterList.add(nonHeapPlotter);
     184
     185         // Now add memory pools
     186         Map<ObjectName, MBeanInfo> mBeanMap = proxyClient.getMBeans("java.lang");
     187         Set<ObjectName> keys = mBeanMap.keySet();
     188         ObjectName[] objectNames = keys.toArray(new ObjectName[keys.size()]);
     189         ArrayList<PoolPlotter> nonHeapPlotters = new ArrayList<PoolPlotter>(2);
     190         for (ObjectName objectName : objectNames) {
     191             String type = objectName.getKeyProperty("type");
     192             if (type.equals("MemoryPool")) {
     193                 String name = Resources.format(Messages.MEMORY_POOL_LABEL,
     194                                                objectName.getKeyProperty("name"));
     195                 // Heap or non-heap?
     196                 boolean isHeap = false;
     197                 AttributeList al =
     198                     proxyClient.getAttributes(objectName,
     199                                               new String[] { "Type" });
     200                 if (al.size() > 0) {
     201                     isHeap = MemoryType.HEAP.name().equals(((Attribute)al.get(0)).getValue());
     202                 }
     203                 PoolPlotter poolPlotter = new PoolPlotter(objectName, name, isHeap);
     204                 proxyClient.addWeakPropertyChangeListener(poolPlotter);
     205
     206                 poolPlotter.createSequence(usedKey,      Messages.USED,      usedColor,      true);
     207                 poolPlotter.createSequence(committedKey, Messages.COMMITTED, committedColor, false);
     208                 poolPlotter.createSequence(maxKey,       Messages.MAX,       maxColor,       false);
     209                 poolPlotter.createSequence(thresholdKey, Messages.THRESHOLD, thresholdColor, false);
     210                 poolPlotter.setUseDashedTransitions(thresholdKey, true);
     211
     212                 if (isHeap) {
     213                     plotterList.add(poolPlotter);
     214                 } else {
     215                     // Will be added to plotterList below
     216                     nonHeapPlotters.add(poolPlotter);
     217                 }
     218             }
     219         }
     220         // Add non-heap plotters last
     221         for (PoolPlotter poolPlotter : nonHeapPlotters) {
     222             plotterList.add(poolPlotter);
     223         }
     224     }
     225
     226
     227     public void itemStateChanged(ItemEvent ev) {
     228         if (ev.getStateChange() == ItemEvent.SELECTED) {
     229             Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
     230             plotterPanel.setPlotter(plotter);
     231             plotterPanel.repaint();
     232         }
     233     }
     234
     235     public void gc() {
     236         new Thread("MemoryPanel.gc") {
     237             public void run() {
     238                 ProxyClient proxyClient = vmPanel.getProxyClient();
     239                 try {
     240                     proxyClient.getMemoryMXBean().gc();
     241                 } catch (UndeclaredThrowableException e) {
     242                     proxyClient.markAsDead();
     243                 } catch (IOException e) {
     244                     // Ignore
     245                 }
     246             }
     247         }.start();
     248     }
     249
     250     public SwingWorker<?, ?> newSwingWorker() {
     251         return new SwingWorker<Boolean, Object>() {
     252             private long[] used, committed, max, threshold;
     253             private long timeStamp;
     254             private String detailsStr;
     255             private boolean initialRun = false;
     256
     257             public Boolean doInBackground() {
     258                 ProxyClient proxyClient = vmPanel.getProxyClient();
     259
     260                 if (plotterList == null) {
     261                     try {
     262                         createPlotters();
     263                     } catch (UndeclaredThrowableException e) {
     264                         proxyClient.markAsDead();
     265                         return false;
     266                     } catch (final IOException ex) {
     267                         return false;
     268                     }
     269                     initialRun = true;
     270                 }
     271
     272                 int n = plotterList.size();
     273                 used      = new long[n];
     274                 committed = new long[n];
     275                 max       = new long[n];
     276                 threshold = new long[n];
     277                 timeStamp = System.currentTimeMillis();
     278
     279                 for (int i = 0; i < n; i++) {
     280                     Plotter plotter = plotterList.get(i);
     281                     MemoryUsage mu = null;
     282                     used[i] = -1L;
     283                     threshold[i] = -1L;
     284
     285                     try {
     286                         if (plotter instanceof PoolPlotter) {
     287                             PoolPlotter poolPlotter = (PoolPlotter)plotter;
     288                             ObjectName objectName = poolPlotter.objectName;
     289                             AttributeList al =
     290                                 proxyClient.getAttributes(objectName,
     291                                                           new String[] { "Usage", "UsageThreshold" });
     292                             if (al.size() > 0) {
     293                                 CompositeData cd = (CompositeData)((Attribute)al.get(0)).getValue();
     294                                 mu = MemoryUsage.from(cd);
     295
     296                                 if (al.size() > 1) {
     297                                     threshold[i] = (Long)((Attribute)al.get(1)).getValue();
     298                                 }
     299                             }
     300                         } else if (plotter == heapPlotter) {
     301                             mu = proxyClient.getMemoryMXBean().getHeapMemoryUsage();
     302                         } else if (plotter == nonHeapPlotter) {
     303                             mu = proxyClient.getMemoryMXBean().getNonHeapMemoryUsage();
     304                         }
     305                     } catch (UndeclaredThrowableException e) {
     306                         proxyClient.markAsDead();
     307                         return false;
     308                     } catch (IOException ex) {
     309                         // Skip this plotter
     310                     }
     311
     312                     if (mu != null) {
     313                         used[i]      = mu.getUsed();
     314                         committed[i] = mu.getCommitted();
     315                         max[i]       = mu.getMax();
     316                     }
     317                 }
     318                 detailsStr = formatDetails();
     319
     320                 return true;
     321             }
     322
     323             protected void done() {
     324                 try {
     325                     if (!get()) {
     326                         return;
     327                     }
     328                 } catch (InterruptedException ex) {
     329                     return;
     330                 } catch (ExecutionException ex) {
     331                     if (JConsole.isDebug()) {
     332                         ex.printStackTrace();
     333                     }
     334                     return;
     335                 }
     336
     337                 if (initialRun) {
     338                     // Add Memory Pools
     339                     for (Plotter p : plotterList) {
     340                         plotterChoice.addItem(p);
     341                         timeComboBox.addPlotter(p);
     342                     }
     343                     add(bottomPanel,  BorderLayout.SOUTH);
     344                 }
     345
     346
     347                 int n = plotterList.size();
     348                 int poolCount = 0;
     349
     350                 for (int i = 0; i < n; i++) {
     351                     Plotter plotter = plotterList.get(i);
     352                     if (used[i] >= 0L) {
     353                         if (plotter instanceof PoolPlotter) {
     354                             plotter.addValues(timeStamp, used[i], committed[i], max[i], threshold[i]);
     355                             if (threshold[i] > 0L) {
     356                                 plotter.setIsPlotted(thresholdKey, true);
     357                             }
     358                             poolChart.setValue(poolCount++, (PoolPlotter)plotter,
     359                                                used[i], threshold[i], max[i]);
     360                         } else {
     361                             plotter.addValues(timeStamp, used[i], committed[i], max[i]);
     362                         }
     363
     364                         if (plotter == heapPlotter && overviewPanel != null) {
     365                             overviewPanel.getPlotter().addValues(timeStamp, used[i]);
     366                             overviewPanel.updateMemoryInfo(used[i], committed[i], max[i]);
     367                         }
     368                     }
     369                 }
     370                 details.setText(detailsStr);
     371             }
     372         };
     373     }
     374
     375     private String formatDetails() {
     376         ProxyClient proxyClient = vmPanel.getProxyClient();
     377         if (proxyClient.isDead()) {
     378             return "";
     379         }
     380
     381         String text = "<table cellspacing=0 cellpadding=0>";
     382
     383         Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
     384         if (plotter == null) {
     385             return "";
     386         }
     387
     388         //long time = plotter.getLastTimeStamp();
     389         long time = System.currentTimeMillis();
     390         String timeStamp = formatDateTime(time);
     391         text += newRow(Messages.TIME, timeStamp);
     392
     393         long used = plotter.getLastValue(usedKey);
     394         long committed = plotter.getLastValue(committedKey);
     395         long max = plotter.getLastValue(maxKey);
     396         long threshold = plotter.getLastValue(thresholdKey);
     397
     398         text += newRow(Messages.USED, formatKBytes(used));
     399         if (committed > 0L) {
     400             text += newRow(Messages.COMMITTED, formatKBytes(committed));
     401         }
     402         if (max > 0L) {
     403             text += newRow(Messages.MAX, formatKBytes(max));
     404         }
     405         if (threshold > 0L) {
     406             text += newRow(Messages.USAGE_THRESHOLD, formatKBytes(threshold));
     407         }
     408
     409         try {
     410             Collection<GarbageCollectorMXBean> garbageCollectors =
     411                 proxyClient.getGarbageCollectorMXBeans();
     412
     413             boolean descPrinted = false;
     414             for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) {
     415                 String gcName = garbageCollectorMBean.getName();
     416                 long gcCount = garbageCollectorMBean.getCollectionCount();
     417                 long gcTime = garbageCollectorMBean.getCollectionTime();
     418                 String str = Resources.format(Messages.GC_TIME_DETAILS, justify(formatTime(gcTime), 14),
     419                                               gcName,
     420                                               String.format("%,d",gcCount));
     421                 if (!descPrinted) {
     422                     text += newRow(Messages.GC_TIME, str);
     423                     descPrinted = true;
     424                 } else {
     425                     text += newRow(null, str);
     426                 }
     427            }
     428         } catch (IOException e) {
     429         }
     430
     431         return text;
     432     }
     433
     434     public void actionPerformed(ActionEvent ev) {
     435         Object src = ev.getSource();
     436         if (src == gcButton) {
     437             gc();
     438         }
     439     }
     440
     441     private class PoolPlotter extends Plotter {
     442         ObjectName objectName;
     443         String name;
     444         boolean isHeap;
     445         long value, threshold, max;
     446         int barX;
     447
     448         public PoolPlotter(ObjectName objectName, String name, boolean isHeap) {
     449             super(Plotter.Unit.BYTES);
     450
     451             this.objectName = objectName;
     452             this.name       = name;
     453             this.isHeap     = isHeap;
     454
     455             setAccessibleName(this,
     456                               Resources.format(Messages.MEMORY_TAB_POOL_PLOTTER_ACCESSIBLE_NAME,
     457                                                name));
     458         }
     459
     460
     461         public String toString() {
     462             return name;
     463         }
     464     }
     465
     466     private class PoolChart extends BorderedComponent
     467                             implements Accessible, MouseListener {
     468         final int height       = 150;
     469         final int leftMargin   =  50;
     470         final int rightMargin  =  23;
     471         final int bottomMargin =  35;
     472         final int barWidth     =  22;
     473         final int barGap       =   3;
     474         final int groupGap     =   8;
     475         final int barHeight    = height * 2 / 3;
     476
     477         final Color greenBar           = new Color(100, 255, 100);
     478         final Color greenBarBackground = new Color(210, 255, 210);
     479         final Color redBarBackground   = new Color(255, 210, 210);
     480
     481         Font smallFont = null;
     482
     483         ArrayList<PoolPlotter> poolPlotters = new ArrayList<PoolPlotter>(5);
     484
     485         int nHeapPools    = 0;
     486         int nNonHeapPools = 0;
     487         Rectangle heapRect    = new Rectangle(leftMargin,            height - bottomMargin + 6, barWidth, 20);
     488         Rectangle nonHeapRect = new Rectangle(leftMargin + groupGap, height - bottomMargin + 6, barWidth, 20);
     489
     490         public PoolChart() {
     491             super(null, null);
     492
     493             setFocusable(true);
     494             addMouseListener(this);
     495             ToolTipManager.sharedInstance().registerComponent(this);
     496         }
     497
     498         public void setValue(int poolIndex, PoolPlotter poolPlotter,
     499                              long value, long threshold, long max) {
     500             poolPlotter.value = value;
     501             poolPlotter.threshold = threshold;
     502             poolPlotter.max = max;
     503
     504             if (poolIndex == poolPlotters.size()) {
     505                 poolPlotters.add(poolPlotter);
     506                 if (poolPlotter.isHeap) {
     507                     poolPlotter.barX = nHeapPools * (barWidth + barGap);
     508                     nHeapPools++;
     509                     heapRect.width = nHeapPools * barWidth + (nHeapPools - 1) * barGap;
     510                     nonHeapRect.x  = leftMargin + heapRect.width + groupGap;
     511                 } else {
     512                     poolPlotter.barX = nonHeapRect.x - leftMargin + nNonHeapPools * (barWidth + barGap);
     513                     nNonHeapPools++;
     514                     nonHeapRect.width = nNonHeapPools * barWidth + (nNonHeapPools - 1) * barGap;
     515                 }
     516             } else {
     517                 poolPlotters.set(poolIndex, poolPlotter);
     518             }
     519             repaint();
     520         }
     521
     522         private void paintPoolBar(Graphics g, PoolPlotter poolPlotter) {
     523             Rectangle barRect = getBarRect(poolPlotter);
     524             g.setColor(Color.gray);
     525             g.drawRect(barRect.x, barRect.y, barRect.width, barRect.height);
     526
     527             long value = poolPlotter.value;
     528             long max   = poolPlotter.max;
     529             if (max > 0L) {
     530                 g.translate(barRect.x, barRect.y);
     531
     532                 // Paint green background
     533                 g.setColor(greenBarBackground);
     534                 g.fillRect(1, 1, barRect.width - 1, barRect.height - 1);
     535
     536                 int greenHeight = (int)(value * barRect.height / max);
     537                 long threshold = poolPlotter.threshold;
     538                 if (threshold > 0L) {
     539                     int redHeight = (int)(threshold * barRect.height / max);
     540
     541                     // Paint red background
     542                     g.setColor(redBarBackground);
     543                     g.fillRect(1, 1, barRect.width - 1, barRect.height - redHeight);
     544
     545                     if (value > threshold) {
     546                         // Over threshold, paint red bar
     547                         g.setColor(thresholdColor);
     548                         g.fillRect(1, barRect.height - greenHeight,
     549                                    barRect.width - 1, greenHeight - redHeight);
     550                         greenHeight = redHeight;
     551                     }
     552                 }
     553
     554                 // Paint green bar
     555                 g.setColor(greenBar);
     556                 g.fillRect(1, barRect.height - greenHeight,
     557                            barRect.width - 1, greenHeight);
     558
     559                 g.translate(-barRect.x, -barRect.y);
     560             }
     561         }
     562
     563         public void paintComponent(Graphics g) {
     564             super.paintComponent(g);
     565
     566             if (poolPlotters.size() == 0) {
     567                 return;
     568             }
     569
     570             if (smallFont == null) {
     571                 smallFont = g.getFont().deriveFont(9.0F);
     572             }
     573
     574             // Paint background for chart area
     575             g.setColor(getBackground());
     576             Rectangle r = g.getClipBounds();
     577             g.fillRect(r.x, r.y, r.width, r.height);
     578
     579             g.setFont(smallFont);
     580             FontMetrics fm = g.getFontMetrics();
     581             int fontDescent = fm.getDescent();
     582
     583             // Paint percentage axis
     584             g.setColor(getForeground());
     585             for (int pc : new int[] { 0, 25, 50, 75, 100 }) {
     586                 String str = pc + "% --";
     587                 g.drawString(str,
     588                              leftMargin - fm.stringWidth(str) - 4,
     589                              height - bottomMargin - (pc * barHeight / 100) + fontDescent + 1);
     590             }
     591
     592             for (PoolPlotter poolPlotter : poolPlotters) {
     593                 paintPoolBar(g, poolPlotter);
     594             }
     595
     596             g.setColor(Color.gray);
     597             g.drawRect(heapRect.x,    heapRect.y,    heapRect.width,    heapRect.height);
     598             g.drawRect(nonHeapRect.x, nonHeapRect.y, nonHeapRect.width, nonHeapRect.height);
     599
     600             Color heapColor    = greenBar;
     601             Color nonHeapColor = greenBar;
     602
     603
     604             for (PoolPlotter poolPlotter : poolPlotters) {
     605                 if (poolPlotter.threshold > 0L && poolPlotter.value > poolPlotter.threshold) {
     606                     if (poolPlotter.isHeap) {
     607                         heapColor = thresholdColor;
     608                     } else {
     609                         nonHeapColor = thresholdColor;
     610                     }
     611                 }
     612             }
     613             g.setColor(heapColor);
     614             g.fillRect(heapRect.x + 1,    heapRect.y + 1,    heapRect.width - 1,    heapRect.height - 1);
     615             g.setColor(nonHeapColor);
     616             g.fillRect(nonHeapRect.x + 1, nonHeapRect.y + 1, nonHeapRect.width - 1, nonHeapRect.height - 1);
     617
     618             String str = Messages.HEAP;
     619             int stringWidth = fm.stringWidth(str);
     620             int x = heapRect.x + (heapRect.width - stringWidth) / 2;
     621             int y = heapRect.y + heapRect.height - 6;
     622             g.setColor(Color.white);
     623             g.drawString(str, x-1, y-1);
     624             g.drawString(str, x+1, y-1);
     625             g.drawString(str, x-1, y+1);
     626             g.drawString(str, x+1, y+1);
     627             g.setColor(Color.black);
     628             g.drawString(str, x, y);
     629
     630             str = Messages.NON_HEAP;
     631             stringWidth = fm.stringWidth(str);
     632             x = nonHeapRect.x + (nonHeapRect.width - stringWidth) / 2;
     633             y = nonHeapRect.y + nonHeapRect.height - 6;
     634             g.setColor(Color.white);
     635             g.drawString(str, x-1, y-1);
     636             g.drawString(str, x+1, y-1);
     637             g.drawString(str, x-1, y+1);
     638             g.drawString(str, x+1, y+1);
     639             g.setColor(Color.black);
     640             g.drawString(str, x, y);
     641
     642             // Highlight current plotter
     643             g.setColor(Color.blue);
     644             r = null;
     645             Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
     646             if (plotter == heapPlotter) {
     647                 r = heapRect;
     648             } else if (plotter == nonHeapPlotter) {
     649                 r = nonHeapRect;
     650             } else if (plotter instanceof PoolPlotter) {
     651                 r = getBarRect((PoolPlotter)plotter);
     652             }
     653             if (r != null) {
     654                 g.drawRect(r.x - 1, r.y - 1, r.width + 2, r.height + 2);
     655             }
     656         }
     657
     658         private Rectangle getBarRect(PoolPlotter poolPlotter) {
     659             return new Rectangle(leftMargin + poolPlotter.barX,
     660                                  height - bottomMargin - barHeight,
     661                                  barWidth, barHeight);
     662         }
     663
     664         public Dimension getPreferredSize() {
     665             return new Dimension(nonHeapRect.x + nonHeapRect.width + rightMargin,
     666                                  height);
     667         }
     668
     669         public void mouseClicked(MouseEvent e) {
     670             requestFocusInWindow();
     671             Plotter plotter = getPlotter(e);
     672
     673             if (plotter != null && plotter != plotterChoice.getSelectedItem()) {
     674                 plotterChoice.setSelectedItem(plotter);
     675                 repaint();
     676             }
     677         }
     678
     679         public String getToolTipText(MouseEvent e) {
     680             Plotter plotter = getPlotter(e);
     681
     682             return (plotter != null) ? plotter.toString() : null;
     683         }
     684
     685         private Plotter getPlotter(MouseEvent e) {
     686             Point p = e.getPoint();
     687             Plotter plotter = null;
     688
     689             if (heapRect.contains(p)) {
     690                 plotter = heapPlotter;
     691             } else if (nonHeapRect.contains(p)) {
     692                 plotter = nonHeapPlotter;
     693             } else {
     694                 for (PoolPlotter poolPlotter : poolPlotters) {
     695                     if (getBarRect(poolPlotter).contains(p)) {
     696                         plotter = poolPlotter;
     697                         break;
     698                     }
     699                 }
     700             }
     701             return plotter;
     702         }
     703
     704         public void mousePressed(MouseEvent e) {}
     705         public void mouseReleased(MouseEvent e) {}
     706         public void mouseEntered(MouseEvent e) {}
     707         public void mouseExited(MouseEvent e) {}
     708
     709
     710         public AccessibleContext getAccessibleContext() {
     711             if (accessibleContext == null) {
     712                 accessibleContext = new AccessiblePoolChart();
     713             }
     714             return accessibleContext;
     715         }
     716
     717         protected class AccessiblePoolChart extends AccessibleJPanel {
     718             public String getAccessibleName() {
     719                 String name = Messages.MEMORY_TAB_POOL_CHART_ACCESSIBLE_NAME;
     720
     721                 String keyValueList = "";
     722                 for (PoolPlotter poolPlotter : poolPlotters) {
     723                     String value = (poolPlotter.value * 100 / poolPlotter.max) + "%";
     724                     // Assume format string ends with newline
     725                     keyValueList +=
     726                         Resources.format(Messages.PLOTTER_ACCESSIBLE_NAME_KEY_AND_VALUE,
     727                                          poolPlotter.toString(), value);
     728                     if (poolPlotter.threshold > 0L) {
     729                         String threshold =
     730                             (poolPlotter.threshold * 100 / poolPlotter.max) + "%";
     731                         if (poolPlotter.value > poolPlotter.threshold) {
     732                             keyValueList +=
     733                                Resources.format(Messages.MEMORY_TAB_POOL_CHART_ABOVE_THRESHOLD,
     734                                                 threshold);
     735                         } else {
     736                             keyValueList +=
     737                                     Resources.format(Messages.MEMORY_TAB_POOL_CHART_BELOW_THRESHOLD,
     738                                                      threshold);
     739                         }
     740                     }
     741                 }
     742
     743                 return name + "\n" + keyValueList + ".";
     744             }
     745         }
     746     }
     747
     748
     749     OverviewPanel[] getOverviewPanels() {
     750         if (overviewPanel == null) {
     751             overviewPanel = new MemoryOverviewPanel();
     752         }
     753         return new OverviewPanel[] { overviewPanel };
     754     }
     755
     756     private static class MemoryOverviewPanel extends OverviewPanel {
     757         MemoryOverviewPanel() {
     758             super(Messages.HEAP_MEMORY_USAGE, usedKey, Messages.USED, Plotter.Unit.BYTES);
     759         }
     760
     761         private void updateMemoryInfo(long used, long committed, long max) {
     762             getInfoLabel().setText(Resources.format(Messages.MEMORY_TAB_INFO_LABEL_FORMAT,
     763                                                     formatBytes(used, true),
     764                                                     formatBytes(committed, true),
     765                                                     formatBytes(max, true)));
     766         }
     767     }
     768 }
    --- EOF ---