001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.ui.cpu;
042:
043: import org.netbeans.lib.profiler.ui.charts.ChartModelListener;
044: import org.netbeans.lib.profiler.ui.charts.PieChart;
045: import org.netbeans.lib.profiler.ui.charts.PieChartModel;
046: import org.netbeans.lib.profiler.ui.components.HTMLTextArea;
047: import org.netbeans.lib.profiler.ui.components.SnippetPanel;
048: import java.awt.BorderLayout;
049: import java.awt.Color;
050: import java.awt.Component;
051: import java.awt.Cursor;
052: import java.awt.Dimension;
053: import java.awt.FlowLayout;
054: import java.awt.Font;
055: import java.awt.GridBagConstraints;
056: import java.awt.GridBagLayout;
057: import java.awt.Insets;
058: import java.awt.KeyboardFocusManager;
059: import java.awt.Rectangle;
060: import java.awt.event.FocusEvent;
061: import java.awt.event.FocusListener;
062: import java.awt.event.KeyAdapter;
063: import java.awt.event.KeyEvent;
064: import java.awt.event.MouseAdapter;
065: import java.awt.event.MouseEvent;
066: import java.awt.event.MouseListener;
067: import java.awt.event.MouseMotionAdapter;
068: import java.util.ArrayList;
069: import java.util.ResourceBundle;
070: import java.util.Vector;
071: import javax.swing.BorderFactory;
072: import javax.swing.Icon;
073: import javax.swing.JComponent;
074: import javax.swing.JLabel;
075: import javax.swing.JPanel;
076: import javax.swing.JScrollPane;
077: import javax.swing.Scrollable;
078: import javax.swing.SwingConstants;
079: import javax.swing.UIManager;
080: import org.netbeans.lib.profiler.ui.UIUtils;
081:
082: /**
083: *
084: * @author Jiri Sedlacek
085: */
086: public class StatisticsPanel extends JPanel {
087: //~ Inner Interfaces ---------------------------------------------------------------------------------------------------------
088:
089: public static interface Listener {
090: //~ Methods --------------------------------------------------------------------------------------------------------------
091:
092: public void itemClicked(int itemIndex);
093: }
094:
095: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
096:
097: private class ChartItemPresenter {
098: //~ Instance fields ------------------------------------------------------------------------------------------------------
099:
100: public JLabel valueLabel = new JLabel(""); // NOI18N
101: public JPanel filler = new JPanel(new FlowLayout(0, 0,
102: FlowLayout.LEADING));
103: public KeyboardAwareLabel nameLabel; // NOI18N
104: private ColorIcon colorIcon = new ColorIcon(UIUtils
105: .getProfilerResultsBackground());
106: private PieChartModel model;
107: private int index;
108:
109: //~ Constructors ---------------------------------------------------------------------------------------------------------
110:
111: public ChartItemPresenter(PieChart pieChart, int index) {
112: this .model = pieChart.getModel();
113: this .index = index;
114:
115: initComponents();
116: refresh();
117: }
118:
119: //~ Methods --------------------------------------------------------------------------------------------------------------
120:
121: public void refresh() {
122: double percentage = model.getItemValueRel(index);
123:
124: if (percentage == 0d) {
125: nameLabel.setVisible(false);
126: valueLabel.setVisible(false);
127: } else {
128: colorIcon.setColor(model.getItemColor(index));
129: nameLabel.setIcon(colorIcon);
130: nameLabel.setText(model.getItemName(index));
131: valueLabel.setText(getRelValue(percentage));
132:
133: nameLabel.setVisible(true);
134: valueLabel.setVisible(true);
135: }
136: }
137:
138: private String getRelValue(double value) {
139: int percent = (int) Math.floor(value * 100);
140: int permille = (int) Math.round(value * 1000)
141: - (10 * percent);
142:
143: return percent + "." + permille + "%"; // NOI18N
144: }
145:
146: private void initComponents() {
147: filler.setOpaque(false);
148: nameLabel = new KeyboardAwareLabel(new Runnable() {
149: public void run() {
150: for (int i = 0; i < listeners.size(); i++) {
151: ((Listener) listeners.get(i))
152: .itemClicked(index);
153: }
154: }
155: });
156:
157: valueLabel.setOpaque(false);
158: valueLabel.setHorizontalAlignment(SwingConstants.TRAILING);
159: }
160: }
161:
162: private class ChartPanel extends JPanel {
163: //~ Constructors ---------------------------------------------------------------------------------------------------------
164:
165: public ChartPanel(PieChart pieChart) {
166: initComponents(pieChart);
167: }
168:
169: //~ Methods --------------------------------------------------------------------------------------------------------------
170:
171: private void initComponents(final PieChart pieChart) {
172: pieChart.setBackground(UIUtils
173: .getProfilerResultsBackground());
174:
175: pieChart.addMouseListener(new MouseAdapter() {
176: @Override
177: public void mouseClicked(MouseEvent e) {
178: int clickedItem = pieChart.getItemIndexAt(e.getX(),
179: e.getY());
180:
181: for (int i = 0; i < listeners.size(); i++) {
182: ((Listener) listeners.get(i))
183: .itemClicked(clickedItem);
184: }
185: }
186:
187: @Override
188: public void mouseExited(MouseEvent e) {
189: pieChart.resetFocusedItem();
190: }
191: });
192: pieChart.addMouseMotionListener(new MouseMotionAdapter() {
193: @Override
194: public void mouseMoved(MouseEvent e) {
195: int focusedItem = pieChart.getItemIndexAt(e.getX(),
196: e.getY());
197:
198: if ((focusedItem != -1)
199: && pieChart.getModel().isSelectable(
200: focusedItem)) {
201: pieChart
202: .setCursor(Cursor
203: .getPredefinedCursor(Cursor.HAND_CURSOR));
204: } else {
205: pieChart.setCursor(Cursor.getDefaultCursor());
206: }
207:
208: pieChart.setFocusedItem(focusedItem);
209: }
210: });
211:
212: setOpaque(false);
213: setBorder(BorderFactory.createEmptyBorder(8, 5, 8, 5));
214: setPreferredSize(new Dimension(240, 220));
215: setMinimumSize(new Dimension(50, 220));
216:
217: setLayout(new BorderLayout());
218: add(pieChart, BorderLayout.CENTER);
219: }
220: }
221:
222: private class ColorIcon implements Icon {
223: //~ Static fields/initializers -------------------------------------------------------------------------------------------
224:
225: public static final int ICON_SIZE = 9;
226:
227: //~ Instance fields ------------------------------------------------------------------------------------------------------
228:
229: protected Color color;
230: protected int height;
231: protected int width;
232:
233: //~ Constructors ---------------------------------------------------------------------------------------------------------
234:
235: public ColorIcon(Color color) {
236: this (ICON_SIZE, ICON_SIZE, color);
237: }
238:
239: public ColorIcon(int width, int height, Color color) {
240: this .width = width;
241: this .height = height;
242: setColor(color);
243: }
244:
245: //~ Methods --------------------------------------------------------------------------------------------------------------
246:
247: public void setColor(Color color) {
248: this .color = color;
249: }
250:
251: public Color getColor() {
252: return color;
253: }
254:
255: public int getIconHeight() {
256: return height;
257: }
258:
259: public int getIconWidth() {
260: return width;
261: }
262:
263: public void paintIcon(java.awt.Component c,
264: java.awt.Graphics g, int x, int y) {
265: g.setColor(color);
266: g.fillRect(x, y, width, height);
267: g.setColor(Color.BLACK);
268: g.drawRect(x, y, width - 1, height - 1);
269: }
270: }
271:
272: private class Container extends JPanel implements Scrollable {
273: //~ Constructors ---------------------------------------------------------------------------------------------------------
274:
275: public Container() {
276: setLayout(new BorderLayout());
277: setOpaque(true);
278: setBackground(UIUtils.getProfilerResultsBackground());
279: }
280:
281: //~ Methods --------------------------------------------------------------------------------------------------------------
282:
283: public Dimension getPreferredScrollableViewportSize() {
284: return new Dimension(250, 500);
285: }
286:
287: public int getScrollableBlockIncrement(Rectangle visibleRect,
288: int orientation, int direction) {
289: return 50;
290: }
291:
292: public boolean getScrollableTracksViewportHeight() {
293: return false;
294: }
295:
296: public boolean getScrollableTracksViewportWidth() {
297: return true;
298: }
299:
300: public int getScrollableUnitIncrement(Rectangle visibleRect,
301: int orientation, int direction) {
302: return 10;
303: }
304: }
305:
306: private class KeyboardAwareLabel extends JLabel {
307: //~ Instance fields ------------------------------------------------------------------------------------------------------
308:
309: private String originalText;
310: private boolean isMouseOver;
311:
312: //~ Constructors ---------------------------------------------------------------------------------------------------------
313:
314: public KeyboardAwareLabel(final Runnable actionPerformer) {
315: super ();
316:
317: setOpaque(false);
318: setFocusable(true);
319:
320: addFocusListener(new FocusListener() {
321: public void focusGained(FocusEvent e) {
322: updateText();
323: }
324:
325: public void focusLost(FocusEvent e) {
326: updateText();
327: }
328: });
329:
330: addMouseListener(new MouseAdapter() {
331: public void mouseClicked(MouseEvent e) {
332: requestFocusInWindow();
333: actionPerformer.run();
334: }
335:
336: public void mouseEntered(MouseEvent e) {
337: isMouseOver = true;
338: updateText();
339: setCursor(Cursor
340: .getPredefinedCursor(Cursor.HAND_CURSOR));
341: }
342:
343: public void mouseExited(MouseEvent e) {
344: isMouseOver = false;
345: updateText();
346: setCursor(Cursor.getDefaultCursor());
347: }
348: });
349:
350: addKeyListener(new KeyAdapter() {
351: public void keyPressed(KeyEvent e) {
352: if (e.getKeyCode() == KeyEvent.VK_SPACE) {
353: actionPerformer.run();
354: }
355: }
356: });
357: }
358:
359: //~ Methods --------------------------------------------------------------------------------------------------------------
360:
361: public void setText(String value) {
362: this .originalText = value;
363: updateText();
364: }
365:
366: private void updateText() {
367: setForeground(isFocusOwner() ? Color.RED : UIManager
368: .getColor("Label.foreground")); // NOI18N
369:
370: if (isMouseOver) {
371: super .setText("<html><nobr><u>" + originalText + ":"
372: + "</u></nobr></html>"); // NOI18N
373: } else {
374: super .setText("<html><nobr>" + originalText + ":"
375: + "</nobr></html>"); // NOI18N
376: }
377: }
378: }
379:
380: private class NavPanel extends JPanel {
381: //~ Instance fields ------------------------------------------------------------------------------------------------------
382:
383: private final Color backgroundColor = new Color(248, 248, 248);
384: private final Color focusedBackgroundColor = new Color(230,
385: 230, 230);
386: private final MouseListener focusGrabber = new MouseAdapter() {
387: public void mouseClicked(MouseEvent e) {
388: requestFocusInWindow();
389: }
390: };
391:
392: //~ Constructors ---------------------------------------------------------------------------------------------------------
393:
394: public NavPanel(HTMLTextArea navArea) {
395: initComponents(navArea);
396: }
397:
398: //~ Methods --------------------------------------------------------------------------------------------------------------
399:
400: private void initComponents(HTMLTextArea navArea) {
401: setBackground(backgroundColor);
402: setBorder(BorderFactory.createCompoundBorder(BorderFactory
403: .createMatteBorder(1, 0, 1, 0, new Color(214, 223,
404: 247)), BorderFactory.createEmptyBorder(4,
405: 0, 4, 0)));
406:
407: navArea.setHighlighter(null);
408: navArea.setShowPopup(false);
409: navArea.setBorder(BorderFactory.createEmptyBorder());
410: navArea.setOpaque(false);
411: navArea.setFocusable(false);
412:
413: GridBagConstraints constraints;
414: setLayout(new GridBagLayout());
415:
416: JLabel scopeLabel = new JLabel(SCOPE_LABEL_TEXT);
417: scopeLabel.setFont(UIManager.getFont("Label.font")
418: .deriveFont(Font.BOLD)); //NOI18N
419: scopeLabel.setOpaque(false);
420:
421: constraints = new GridBagConstraints();
422: constraints.gridx = 0;
423: constraints.gridy = 0;
424: constraints.anchor = GridBagConstraints.NORTHWEST;
425: constraints.fill = GridBagConstraints.NONE;
426: constraints.insets = new Insets(1, 5, 1, 5);
427: add(scopeLabel, constraints);
428:
429: constraints = new GridBagConstraints();
430: constraints.gridx = 1;
431: constraints.gridy = 0;
432: constraints.weightx = 1;
433: constraints.weighty = 1;
434: constraints.anchor = GridBagConstraints.NORTHWEST;
435: constraints.fill = GridBagConstraints.BOTH;
436: constraints.insets = new Insets(1, 0, 1, 5);
437: add(navArea, constraints);
438:
439: setFocusable(true);
440: addFocusListener(new FocusListener() {
441: public void focusGained(FocusEvent e) {
442: setBackground(focusedBackgroundColor);
443: }
444:
445: public void focusLost(FocusEvent e) {
446: setBackground(backgroundColor);
447: }
448: });
449:
450: addKeyListener(new KeyAdapter() {
451: public void keyPressed(KeyEvent e) {
452: if (e.getKeyCode() == KeyEvent.VK_SPACE) {
453: navigationBackPerformer.run();
454: }
455: }
456: });
457:
458: addMouseListener(focusGrabber);
459: scopeLabel.addMouseListener(focusGrabber);
460: navArea.addMouseListener(focusGrabber);
461: }
462: }
463:
464: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
465:
466: // -----
467: // I18N String constants
468: private static final ResourceBundle messages = ResourceBundle
469: .getBundle("org.netbeans.lib.profiler.ui.cpu.Bundle"); // NOI18N
470: private static final String SCOPE_LABEL_TEXT = messages
471: .getString("StatisticsPanel_ScopeLabelText"); // NOI18N
472: // -----
473:
474: //~ Instance fields ----------------------------------------------------------------------------------------------------------
475:
476: private SnippetPanel.Padding snippetsBottomFiller;
477: private ArrayList itemPresenters = new ArrayList();
478: private ArrayList snippets = new ArrayList();
479:
480: // --- Declarations ----------------------------------------------------------
481: private JPanel container;
482: private JPanel noSnippetsBottomFiller;
483: private NavPanel navPanel;
484: private PieChart pieChart;
485: private Runnable navigationBackPerformer;
486: private Vector listeners = new Vector();
487:
488: //~ Constructors -------------------------------------------------------------------------------------------------------------
489:
490: // --- Constructors ----------------------------------------------------------
491: public StatisticsPanel(HTMLTextArea navArea, PieChart pieChart,
492: Runnable navigationBackPerformer) {
493: this .pieChart = pieChart;
494: this .navigationBackPerformer = navigationBackPerformer;
495:
496: initComponents(navArea, pieChart);
497:
498: pieChart.getModel().addChartModelListener(
499: new ChartModelListener() {
500: public void chartDataChanged() {
501: updateItemPresenters();
502: }
503: });
504: }
505:
506: //~ Methods ------------------------------------------------------------------------------------------------------------------
507:
508: // --- Listener stuff --------------------------------------------------------
509: public void addListener(Listener listener) {
510: if (!listeners.contains(listener)) {
511: listeners.add(listener);
512: }
513: }
514:
515: // --- Public interface ------------------------------------------------------
516: public void addSnippet(JComponent component) {
517: SnippetPanel snippet = new SnippetPanel(component.getName(),
518: component);
519: snippet.setOpaque(false);
520: snippets.add(snippet);
521: updateSnippets();
522: }
523:
524: public void removeListener(Listener listener) {
525: listeners.remove(listener);
526: }
527:
528: public void removeSnippet(JComponent component) {
529: for (int i = 0; i < snippets.size(); i++) {
530: if (((SnippetPanel) snippets.get(i)).getContent() == component) {
531: snippets.remove(i);
532:
533: break;
534: }
535: }
536:
537: updateSnippets();
538: }
539:
540: private void initComponents(HTMLTextArea navArea, PieChart pieChart) {
541: noSnippetsBottomFiller = new JPanel(new FlowLayout(0, 0,
542: FlowLayout.LEADING));
543: noSnippetsBottomFiller.setOpaque(false);
544: snippetsBottomFiller = new SnippetPanel.Padding();
545:
546: container = new Container();
547:
548: GridBagConstraints constraints;
549: container.setLayout(new GridBagLayout());
550:
551: navPanel = new NavPanel(navArea);
552: constraints = new GridBagConstraints();
553: constraints.gridx = 0;
554: constraints.gridy = 0;
555: constraints.gridwidth = GridBagConstraints.REMAINDER;
556: constraints.anchor = GridBagConstraints.NORTHWEST;
557: constraints.fill = GridBagConstraints.HORIZONTAL;
558: constraints.insets = new Insets(0, 0, 0, 0);
559: container.add(navPanel, constraints);
560:
561: constraints = new GridBagConstraints();
562: constraints.gridx = 0;
563: constraints.gridy = 1;
564: constraints.weightx = 1;
565: constraints.gridwidth = GridBagConstraints.REMAINDER;
566: constraints.anchor = GridBagConstraints.NORTHWEST;
567: constraints.fill = GridBagConstraints.HORIZONTAL;
568: constraints.insets = new Insets(5, 0, 5, 0);
569: container.add(new ChartPanel(pieChart), constraints);
570:
571: updateItemPresenters();
572:
573: JScrollPane contentsScrollPane = new JScrollPane(container,
574: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
575: JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
576: contentsScrollPane.setBorder(BorderFactory.createEmptyBorder());
577: contentsScrollPane.getViewport().setOpaque(true);
578: contentsScrollPane.getViewport().setBackground(
579: UIUtils.getProfilerResultsBackground());
580:
581: setLayout(new BorderLayout());
582: add(contentsScrollPane, BorderLayout.CENTER);
583: }
584:
585: private void refreshItemPresenters() {
586: for (int i = 0; i < itemPresenters.size(); i++) {
587: ((ChartItemPresenter) itemPresenters.get(i)).refresh();
588: }
589: }
590:
591: // --- Private implementation ------------------------------------------------
592: private void repopulateItemPresenters() {
593: for (int i = 0; i < itemPresenters.size(); i++) {
594: ChartItemPresenter itemPresenter = (ChartItemPresenter) itemPresenters
595: .get(i);
596: container.remove(itemPresenter.nameLabel);
597: container.remove(itemPresenter.valueLabel);
598: container.remove(itemPresenter.filler);
599: }
600:
601: itemPresenters.clear();
602:
603: GridBagConstraints constraints;
604: ChartItemPresenter itemPresenter;
605:
606: // JPanel filler;
607: for (int i = 0; i < pieChart.getModel().getItemCount(); i++) {
608: itemPresenter = new ChartItemPresenter(pieChart, i);
609: itemPresenters.add(itemPresenter);
610:
611: int bottomInset = (i == (pieChart.getModel().getItemCount() - 1)) ? 16
612: : 6;
613:
614: constraints = new GridBagConstraints();
615: constraints.gridx = 0;
616: constraints.gridy = 2 + i;
617: constraints.anchor = GridBagConstraints.NORTHWEST;
618: constraints.fill = GridBagConstraints.NONE;
619: constraints.insets = new Insets(0, 15, bottomInset, 8);
620: container.add(itemPresenter.nameLabel, constraints);
621:
622: constraints = new GridBagConstraints();
623: constraints.gridx = 1;
624: constraints.gridy = 2 + i;
625: constraints.anchor = GridBagConstraints.NORTHEAST;
626: constraints.fill = GridBagConstraints.NONE;
627: constraints.insets = new Insets(0, 22, bottomInset, 0);
628: container.add(itemPresenter.valueLabel, constraints);
629:
630: constraints = new GridBagConstraints();
631: constraints.gridx = 2;
632: constraints.gridy = 2 + i;
633: constraints.anchor = GridBagConstraints.NORTHEAST;
634: constraints.fill = GridBagConstraints.HORIZONTAL;
635: constraints.insets = new Insets(0, 0, bottomInset, 8);
636: container.add(itemPresenter.filler, constraints);
637: }
638:
639: container.revalidate();
640: }
641:
642: private void updateItemPresenters() {
643: if (pieChart.getModel().getItemCount() != itemPresenters.size()) {
644: repopulateItemPresenters();
645: updateSnippets();
646: } else {
647: refreshItemPresenters();
648: }
649:
650: Component focusOwner = KeyboardFocusManager
651: .getCurrentKeyboardFocusManager().getFocusOwner();
652:
653: if ((focusOwner != null) && !focusOwner.isShowing()) {
654: navPanel.requestFocusInWindow();
655: }
656: }
657:
658: private void updateSnippets() {
659: for (int i = 0; i < snippets.size(); i++) {
660: container.remove((JComponent) snippets.get(i));
661: }
662:
663: container.remove(snippetsBottomFiller);
664: container.remove(noSnippetsBottomFiller);
665:
666: GridBagConstraints constraints;
667:
668: // SnippetPanel snippet;
669: for (int i = 0; i < snippets.size(); i++) {
670: constraints = new GridBagConstraints();
671: constraints.gridx = 0;
672: constraints.gridy = 2 + itemPresenters.size() + i + 1;
673: constraints.gridwidth = GridBagConstraints.REMAINDER;
674: constraints.anchor = GridBagConstraints.NORTHWEST;
675: constraints.fill = GridBagConstraints.HORIZONTAL;
676: constraints.insets = new Insets(0, 0, 0, 0);
677: container.add((JComponent) snippets.get(i), constraints);
678: }
679:
680: if (snippets.size() == 0) {
681: constraints = new GridBagConstraints();
682: constraints.gridx = 0;
683: constraints.gridy = 2 + itemPresenters.size() + 1;
684: constraints.weighty = 1;
685: constraints.gridwidth = GridBagConstraints.REMAINDER;
686: constraints.anchor = GridBagConstraints.NORTHWEST;
687: constraints.fill = GridBagConstraints.BOTH;
688: constraints.insets = new Insets(0, 0, 0, 0);
689: container.add(noSnippetsBottomFiller, constraints);
690: } else {
691: constraints = new GridBagConstraints();
692: constraints.gridx = 0;
693: constraints.gridy = 2 + itemPresenters.size()
694: + snippets.size() + 1;
695: constraints.weighty = 1;
696: constraints.gridwidth = GridBagConstraints.REMAINDER;
697: constraints.anchor = GridBagConstraints.NORTHWEST;
698: constraints.fill = GridBagConstraints.BOTH;
699: constraints.insets = new Insets(0, 0, 0, 0);
700: container.add(snippetsBottomFiller, constraints);
701: }
702:
703: container.revalidate();
704: }
705: }
|