blob: 28c92206d7c8da41d94d281dda65d6f365db361d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.tools.jconsole.inspector;
27
28import javax.swing.*;
29import javax.swing.event.*;
30import javax.swing.table.*;
31import javax.swing.tree.*;
32import javax.swing.border.*;
33import java.awt.BorderLayout;
34import java.awt.GridLayout;
35import java.awt.FlowLayout;
36import java.awt.Component;
37import java.awt.EventQueue;
38import java.awt.Color;
39import java.awt.Font;
40import java.awt.Rectangle;
41import java.awt.event.*;
42import java.awt.Insets;
43import java.awt.Dimension;
44import java.awt.GridBagConstraints;
45import java.awt.GridBagLayout;
46import java.util.*;
47import java.io.*;
48import java.lang.reflect.Array;
49
50import javax.management.*;
51import javax.management.openmbean.*;
52
53import sun.tools.jconsole.BorderedComponent;
54import sun.tools.jconsole.JConsole;
55import sun.tools.jconsole.LabeledComponent;
56import sun.tools.jconsole.Resources;
57import sun.tools.jconsole.VariableGridLayout;
58
59@SuppressWarnings("serial")
60public class XOpenTypeViewer extends JPanel implements ActionListener {
61 JButton prev, incr, decr, tabularPrev, tabularNext;
62 JLabel compositeLabel, tabularLabel;
63 JScrollPane container;
64 XOpenTypeData current;
65 XOpenTypeDataListener listener = new XOpenTypeDataListener();
66
67 private static final String compositeNavigationSingle =
68 Resources.getText("MBeansTab.compositeNavigationSingle");
69 private static final String tabularNavigationSingle =
70 Resources.getText("MBeansTab.tabularNavigationSingle");
71
72 private static TableCellEditor editor =
73 new Utils.ReadOnlyTableCellEditor(new JTextField());
74
75 class XOpenTypeDataListener extends MouseAdapter {
76 XOpenTypeDataListener() {
77 }
78
79 public void mousePressed(MouseEvent e) {
80 if(e.getButton() == MouseEvent.BUTTON1) {
81 if(e.getClickCount() >= 2) {
82 XOpenTypeData elem = getSelectedViewedOpenType();
83 if(elem != null) {
84 try {
85 elem.viewed(XOpenTypeViewer.this);
86 }catch(Exception ex) {
87 //Nothing to change, the element
88 //can't be displayed
89 }
90 }
91 }
92 }
93 }
94
95 private XOpenTypeData getSelectedViewedOpenType() {
96 int row = XOpenTypeViewer.this.current.getSelectedRow();
97 int col = XOpenTypeViewer.this.current.getSelectedColumn();
98 Object elem =
99 XOpenTypeViewer.this.current.getModel().getValueAt(row, col);
100 if(elem instanceof XOpenTypeData)
101 return (XOpenTypeData) elem;
102 else
103 return null;
104 }
105 }
106
107 static interface Navigatable {
108 public void incrElement();
109 public void decrElement();
110 public boolean canDecrement();
111 public boolean canIncrement();
112 public int getElementCount();
113 public int getSelectedElementIndex();
114 }
115
116 static interface XViewedTabularData extends Navigatable {
117 }
118
119 static interface XViewedArrayData extends Navigatable {
120 }
121
122 static abstract class XOpenTypeData extends JTable {
123 XOpenTypeData parent;
124 private Color defaultColor;
125 protected int col1Width = -1;
126 protected int col2Width = -1;
127 private boolean init;
128 private Font normalFont, boldFont;
129 protected XOpenTypeData(XOpenTypeData parent) {
130 this.parent = parent;
131 }
132
133 public XOpenTypeData getViewedParent() {
134 return parent;
135 }
136
137 public String getToolTip(int row, int col) {
138 if(col == 1) {
139 Object value = getModel().getValueAt(row, col);
140 if (value != null) {
141 if(isClickableElement(value))
142 return Resources.getText("Double click to visualize")
143 + ". " + value.toString();
144 else
145 return value.toString();
146 }
147 }
148 return null;
149 }
150
151 public TableCellRenderer getCellRenderer(int row, int column) {
152 DefaultTableCellRenderer tcr =
153 (DefaultTableCellRenderer)super.getCellRenderer(row,column);
154 tcr.setToolTipText(getToolTip(row,column));
155 return tcr;
156 }
157
158 public void renderKey(String key, Component comp) {
159 comp.setFont(normalFont);
160 }
161
162 public Component prepareRenderer(TableCellRenderer renderer,
163 int row, int column) {
164 Component comp = super.prepareRenderer(renderer, row, column);
165
166 if (normalFont == null) {
167 normalFont = comp.getFont();
168 boldFont = normalFont.deriveFont(Font.BOLD);
169 }
170
171 Object o = ((DefaultTableModel) getModel()).getValueAt(row, column);
172 if (column == 0) {
173 String key = o.toString();
174 renderKey(key, comp);
175 } else {
176 if (isClickableElement(o)) {
177 comp.setFont(boldFont);
178 } else {
179 comp.setFont(normalFont);
180 }
181 }
182
183 return comp;
184 }
185
186 protected boolean isClickableElement(Object obj) {
187 if (obj instanceof XOpenTypeData) {
188 if (obj instanceof Navigatable) {
189 return (((Navigatable) obj).getElementCount() != 0);
190 } else {
191 return (obj instanceof XCompositeData);
192 }
193 }
194 return false;
195 }
196
197 protected void updateColumnWidth() {
198 if (!init) {
199 TableColumnModel colModel = getColumnModel();
200 if (col2Width == -1) {
201 col1Width = col1Width * 7;
202 if (col1Width <
203 getPreferredScrollableViewportSize().getWidth()) {
204 col1Width = (int)
205 getPreferredScrollableViewportSize().getWidth();
206 }
207 colModel.getColumn(0).setPreferredWidth(col1Width);
208 init = true;
209 return;
210 }
211 col1Width = (col1Width * 7) + 7;
212 col1Width = Math.max(col1Width, 70);
213 col2Width = (col2Width * 7) + 7;
214 if (col1Width + col2Width <
215 getPreferredScrollableViewportSize().getWidth()) {
216 col2Width = (int)
217 getPreferredScrollableViewportSize().getWidth() -
218 col1Width;
219 }
220 colModel.getColumn(0).setPreferredWidth(col1Width);
221 colModel.getColumn(1).setPreferredWidth(col2Width);
222 init = true;
223 }
224 }
225
226 public abstract void viewed(XOpenTypeViewer viewer) throws Exception;
227
228 protected void initTable(String[] columnNames) {
229 setRowSelectionAllowed(false);
230 setColumnSelectionAllowed(false);
231 getTableHeader().setReorderingAllowed(false);
232 ((DefaultTableModel) getModel()).setColumnIdentifiers(columnNames);
233 for (Enumeration<TableColumn> e = getColumnModel().getColumns();
234 e.hasMoreElements();) {
235 TableColumn tc = e.nextElement();
236 tc.setCellEditor(editor);
237 }
238 addKeyListener(new Utils.CopyKeyAdapter());
239 setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
240 setPreferredScrollableViewportSize(new Dimension(350, 200));
241 }
242
243 protected void emptyTable() {
244 invalidate();
245 while (getModel().getRowCount()>0)
246 ((DefaultTableModel) getModel()).removeRow(0);
247 validate();
248 }
249
250 public void setValueAt(Object value, int row, int col) {
251 }
252 }
253
254 static class TabularDataComparator implements Comparator<CompositeData> {
255
256 private final List<String> indexNames;
257
258 public TabularDataComparator(TabularType type) {
259 indexNames = type.getIndexNames();
260 }
261
262 @SuppressWarnings("unchecked")
263 public int compare(CompositeData o1, CompositeData o2) {
264 for (String key : indexNames) {
265 Object c1 = o1.get(key);
266 Object c2 = o2.get(key);
267 if (c1 instanceof Comparable && c2 instanceof Comparable) {
268 int result = ((Comparable) c1).compareTo(c2);
269 if (result != 0)
270 return result;
271 }
272 }
273 return 0;
274 }
275 }
276
277 static class XTabularData extends XCompositeData
278 implements XViewedTabularData {
279
280 final TabularData tabular;
281 final TabularType type;
282 int currentIndex = 0;
283 final Object[] elements;
284 final int size;
285 private Font normalFont, italicFont;
286
287 @SuppressWarnings("unchecked")
288 public XTabularData(XOpenTypeData parent, TabularData tabular) {
289 super(parent, accessFirstElement(tabular));
290 this.tabular = tabular;
291 type = tabular.getTabularType();
292 size = tabular.values().size();
293 if (size > 0) {
294 // Order tabular data elements using index names
295 List<CompositeData> data = new ArrayList<CompositeData>(
296 (Collection<CompositeData>) tabular.values());
297 Collections.sort(data, new TabularDataComparator(type));
298 elements = data.toArray();
299 loadCompositeData((CompositeData) elements[0]);
300 } else {
301 elements = new Object[0];
302 }
303 }
304
305 private static CompositeData accessFirstElement(TabularData tabular) {
306 if(tabular.values().size() == 0) return null;
307 return (CompositeData) tabular.values().toArray()[0];
308 }
309
310 public void renderKey(String key, Component comp) {
311 if (normalFont == null) {
312 normalFont = comp.getFont();
313 italicFont = normalFont.deriveFont(Font.ITALIC);
314 }
315 for(Object k : type.getIndexNames()) {
316 if(key.equals(k))
317 comp.setFont(italicFont);
318 }
319 }
320
321 public int getElementCount() {
322 return size;
323 }
324
325 public int getSelectedElementIndex() {
326 return currentIndex;
327 }
328
329 public void incrElement() {
330 currentIndex++;
331 loadCompositeData((CompositeData)elements[currentIndex]);
332 }
333
334 public void decrElement() {
335 currentIndex--;
336 loadCompositeData((CompositeData)elements[currentIndex]);
337 }
338
339 public boolean canDecrement() {
340 if(currentIndex == 0)
341 return false;
342 else
343 return true;
344 }
345
346 public boolean canIncrement(){
347 if(size == 0 ||
348 currentIndex == size -1)
349 return false;
350 else
351 return true;
352 }
353
354 public String toString() {
355 return type == null ? "" : type.getDescription();
356 }
357 }
358
359 static class XCompositeData extends XOpenTypeData {
360 protected final String[] columnNames = {
361 Resources.getText("Name"), Resources.getText("Value")
362 };
363 CompositeData composite;
364
365 public XCompositeData() {
366 super(null);
367 initTable(columnNames);
368 }
369
370 //In sync with array, no init table.
371 public XCompositeData(XOpenTypeData parent) {
372 super(parent);
373 }
374
375 public XCompositeData(XOpenTypeData parent,
376 CompositeData composite) {
377 super(parent);
378 initTable(columnNames);
379 if(composite != null) {
380 this.composite = composite;
381 loadCompositeData(composite);
382 }
383 }
384
385 public void viewed(XOpenTypeViewer viewer) throws Exception {
386 viewer.setOpenType(this);
387 updateColumnWidth();
388 }
389
390 public String toString() {
391 return composite == null ? "" :
392 composite.getCompositeType().getTypeName();
393 }
394
395 protected Object formatKey(String key) {
396 return key;
397 }
398
399 private void load(CompositeData data) {
400 CompositeType type = data.getCompositeType();
401 Set keys = type.keySet();
402 Iterator it = keys.iterator();
403 Object[] rowData = new Object[2];
404 while (it.hasNext()) {
405 String key = (String) it.next();
406 Object val = data.get(key);
407 rowData[0] = formatKey(key);
408 if (val == null) {
409 rowData[1] = "";
410 } else {
411 OpenType openType = type.getType(key);
412 if (openType instanceof CompositeType) {
413 rowData[1] =
414 new XCompositeData(this, (CompositeData) val);
415 } else if (openType instanceof ArrayType) {
416 rowData[1] =
417 new XArrayData(this, (ArrayType) openType, val);
418 } else if (openType instanceof SimpleType) {
419 rowData[1] = val;
420 } else if (openType instanceof TabularType) {
421 rowData[1] = new XTabularData(this, (TabularData) val);
422 }
423 }
424 // Update column width
425 String str = null;
426 if (rowData[0] != null) {
427 str = rowData[0].toString();
428 if (str.length() > col1Width) {
429 col1Width = str.length();
430 }
431 }
432 if (rowData[1] != null) {
433 str = rowData[1].toString();
434 if (str.length() > col2Width) {
435 col2Width = str.length();
436 }
437 }
438 ((DefaultTableModel) getModel()).addRow(rowData);
439 }
440 }
441
442 protected void loadCompositeData(CompositeData data) {
443 composite = data;
444 emptyTable();
445 load(data);
446 DefaultTableModel tableModel = (DefaultTableModel) getModel();
447 tableModel.newDataAvailable(new TableModelEvent(tableModel));
448 }
449 }
450
451 static class XArrayData extends XCompositeData
452 implements XViewedArrayData {
453
454 private int dimension;
455 private int size;
456 private OpenType elemType;
457 private Object val;
458 private boolean isCompositeType;
459 private boolean isTabularType;
460 private int currentIndex;
461 private CompositeData[] elements;
462 private final String[] arrayColumns = {Resources.getText("Value")};
463 private Font normalFont, boldFont;
464
465 XArrayData(XOpenTypeData parent, ArrayType type, Object val) {
466 this(parent, type.getDimension(), type.getElementOpenType(), val);
467 }
468
469 XArrayData(XOpenTypeData parent, int dimension,
470 OpenType elemType, Object val) {
471 super(parent);
472 this.dimension = dimension;
473 this.elemType = elemType;
474 this.val = val;
475 String[] columns = null;
476
477 if (dimension > 1) return;
478
479 isCompositeType = (elemType instanceof CompositeType);
480 isTabularType = (elemType instanceof TabularType);
481 columns = isCompositeType ? columnNames : arrayColumns;
482
483 initTable(columns);
484 loadArray();
485 }
486
487 public void viewed(XOpenTypeViewer viewer) throws Exception {
488 if (size == 0)
489 throw new Exception(Resources.getText("Empty array"));
490 if (dimension > 1)
491 throw new Exception(Resources.getText("Dimension is not " +
492 "supported:") +
493 dimension);
494 super.viewed(viewer);
495 }
496
497 public int getElementCount() {
498 return size;
499 }
500
501 public int getSelectedElementIndex() {
502 return currentIndex;
503 }
504
505 public void renderKey(String key, Component comp) {
506 if (normalFont == null) {
507 normalFont = comp.getFont();
508 boldFont = normalFont.deriveFont(Font.BOLD);
509 }
510 if (isTabularType) {
511 comp.setFont(boldFont);
512 }
513 }
514
515 public void incrElement() {
516 currentIndex++;
517 loadCompositeData(elements[currentIndex]);
518 }
519
520 public void decrElement() {
521 currentIndex--;
522 loadCompositeData(elements[currentIndex]);
523 }
524
525 public boolean canDecrement() {
526 if (isCompositeType && currentIndex > 0) {
527 return true;
528 }
529 return false;
530 }
531
532 public boolean canIncrement() {
533 if (isCompositeType && currentIndex < size - 1) {
534 return true;
535 }
536 return false;
537 }
538
539 private void loadArray() {
540 if (isCompositeType) {
541 elements = (CompositeData[]) val;
542 size = elements.length;
543 if (size != 0) {
544 loadCompositeData(elements[0]);
545 }
546 } else {
547 load();
548 }
549 }
550
551 private void load() {
552 Object[] rowData = new Object[1];
553 size = Array.getLength(val);
554 for (int i = 0; i < size; i++) {
555 rowData[0] = isTabularType ?
556 new XTabularData(this, (TabularData) Array.get(val, i)) :
557 Array.get(val, i);
558 String str = rowData[0].toString();
559 if (str.length() > col1Width) {
560 col1Width = str.length();
561 }
562 ((DefaultTableModel) getModel()).addRow(rowData);
563 }
564 }
565
566 public String toString() {
567 if (dimension > 1) {
568 return Resources.getText("Dimension is not supported:") +
569 dimension;
570 } else {
571 return elemType.getTypeName() + "[" + size + "]";
572 }
573 }
574 }
575
576 /**
577 * The supplied value is viewable iff:
578 * - it's a CompositeData/TabularData, or
579 * - it's a non-empty array of CompositeData/TabularData, or
580 * - it's a non-empty Collection of CompositeData/TabularData.
581 */
582 public static boolean isViewableValue(Object value) {
583 // Check for CompositeData/TabularData
584 //
585 if (value instanceof CompositeData || value instanceof TabularData) {
586 return true;
587 }
588 // Check for non-empty array of CompositeData/TabularData
589 //
590 if (value instanceof CompositeData[] || value instanceof TabularData[]) {
591 return Array.getLength(value) > 0;
592 }
593 // Check for non-empty Collection of CompositeData/TabularData
594 //
595 if (value instanceof Collection) {
596 Collection<?> c = (Collection<?>) value;
597 if (c.isEmpty()) {
598 // Empty Collections are not viewable
599 //
600 return false;
601 } else {
602 // Only Collections of CompositeData/TabularData are viewable
603 //
604 return Utils.isUniformCollection(c, CompositeData.class) ||
605 Utils.isUniformCollection(c, TabularData.class);
606 }
607 }
608 return false;
609 }
610
611 public static Component loadOpenType(Object value) {
612 Component comp = null;
613 if(isViewableValue(value)) {
614 XOpenTypeViewer open =
615 new XOpenTypeViewer(value);
616 comp = open;
617 }
618 return comp;
619 }
620
621 private XOpenTypeViewer(Object value) {
622 XOpenTypeData comp = null;
623 if (value instanceof CompositeData) {
624 comp = new XCompositeData(null, (CompositeData) value);
625 } else if (value instanceof TabularData) {
626 comp = new XTabularData(null, (TabularData) value);
627 } else if (value instanceof CompositeData[]) {
628 CompositeData cda[] = (CompositeData[]) value;
629 CompositeType ct = cda[0].getCompositeType();
630 comp = new XArrayData(null, 1, ct, cda);
631 } else if (value instanceof TabularData[]) {
632 TabularData tda[] = (TabularData[]) value;
633 TabularType tt = tda[0].getTabularType();
634 comp = new XArrayData(null, 1, tt, tda);
635 } else if (value instanceof Collection) {
636 // At this point we know 'value' is a uniform collection, either
637 // Collection<CompositeData> or Collection<TabularData>, because
638 // isViewableValue() has been called before calling the private
639 // XOpenTypeViewer() constructor.
640 //
641 Object e = ((Collection<?>) value).iterator().next();
642 if (e instanceof CompositeData) {
643 Collection<?> cdc = (Collection<?>) value;
644 CompositeData cda[] = cdc.toArray(new CompositeData[0]);
645 CompositeType ct = cda[0].getCompositeType();
646 comp = new XArrayData(null, 1, ct, cda);
647 } else if (e instanceof TabularData) {
648 Collection<?> tdc = (Collection<?>) value;
649 TabularData tda[] = tdc.toArray(new TabularData[0]);
650 TabularType tt = tda[0].getTabularType();
651 comp = new XArrayData(null, 1, tt, tda);
652 }
653 }
654 setupDisplay(comp);
655 try {
656 comp.viewed(this);
657 } catch (Exception e) {
658 // Nothing to change, the element can't be displayed
659 if (JConsole.isDebug()) {
660 System.out.println("Exception viewing openType : " + e);
661 e.printStackTrace();
662 }
663 }
664 }
665
666 void setOpenType(XOpenTypeData data) {
667 if (current != null) {
668 current.removeMouseListener(listener);
669 }
670
671 current = data;
672
673 // Enable/Disable the previous (<<) button
674 if (current.getViewedParent() == null) {
675 prev.setEnabled(false);
676 } else {
677 prev.setEnabled(true);
678 }
679
680 // Set the listener to handle double-click mouse events
681 current.addMouseListener(listener);
682
683 // Enable/Disable the tabular buttons
684 if (!(data instanceof XViewedTabularData)) {
685 tabularPrev.setEnabled(false);
686 tabularNext.setEnabled(false);
687 tabularLabel.setText(tabularNavigationSingle);
688 tabularLabel.setEnabled(false);
689 } else {
690 XViewedTabularData tabular = (XViewedTabularData) data;
691 tabularNext.setEnabled(tabular.canIncrement());
692 tabularPrev.setEnabled(tabular.canDecrement());
693 boolean hasMoreThanOneElement =
694 tabular.canIncrement() || tabular.canDecrement();
695 if (hasMoreThanOneElement) {
696 tabularLabel.setText(
697 Resources.getText("MBeansTab.tabularNavigationMultiple",
698 String.format("%d", tabular.getSelectedElementIndex() + 1),
699 String.format("%d", tabular.getElementCount())));
700 } else {
701 tabularLabel.setText(tabularNavigationSingle);
702 }
703 tabularLabel.setEnabled(hasMoreThanOneElement);
704 }
705
706 // Enable/Disable the composite buttons
707 if (!(data instanceof XViewedArrayData)) {
708 incr.setEnabled(false);
709 decr.setEnabled(false);
710 compositeLabel.setText(compositeNavigationSingle);
711 compositeLabel.setEnabled(false);
712 } else {
713 XViewedArrayData array = (XViewedArrayData) data;
714 incr.setEnabled(array.canIncrement());
715 decr.setEnabled(array.canDecrement());
716 boolean hasMoreThanOneElement =
717 array.canIncrement() || array.canDecrement();
718 if (hasMoreThanOneElement) {
719 compositeLabel.setText(
720 Resources.getText("MBeansTab.compositeNavigationMultiple",
721 String.format("%d", array.getSelectedElementIndex() + 1),
722 String.format("%d", array.getElementCount())));
723 } else {
724 compositeLabel.setText(compositeNavigationSingle);
725 }
726 compositeLabel.setEnabled(hasMoreThanOneElement);
727 }
728
729 container.invalidate();
730 container.setViewportView(current);
731 container.validate();
732 }
733
734 public void actionPerformed(ActionEvent event) {
735 if (event.getSource() instanceof JButton) {
736 JButton b = (JButton) event.getSource();
737 if (b == prev) {
738 XOpenTypeData parent = current.getViewedParent();
739 try {
740 parent.viewed(this);
741 } catch (Exception e) {
742 //Nothing to change, the element can't be displayed
743 }
744 } else if (b == incr) {
745 ((XViewedArrayData) current).incrElement();
746 try {
747 current.viewed(this);
748 } catch (Exception e) {
749 //Nothing to change, the element can't be displayed
750 }
751 } else if (b == decr) {
752 ((XViewedArrayData) current).decrElement();
753 try {
754 current.viewed(this);
755 } catch (Exception e) {
756 //Nothing to change, the element can't be displayed
757 }
758 } else if (b == tabularNext) {
759 ((XViewedTabularData) current).incrElement();
760 try {
761 current.viewed(this);
762 } catch (Exception e) {
763 //Nothing to change, the element can't be displayed
764 }
765 } else if (b == tabularPrev) {
766 ((XViewedTabularData) current).decrElement();
767 try {
768 current.viewed(this);
769 } catch (Exception e) {
770 //Nothing to change, the element can't be displayed
771 }
772 }
773 }
774 }
775
776 private void setupDisplay(XOpenTypeData data) {
777 setBackground(Color.white);
778 container =
779 new JScrollPane(data,
780 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
781 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
782
783 JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
784 tabularPrev = new JButton(Resources.getText("<"));
785 tabularNext = new JButton(Resources.getText(">"));
786 JPanel tabularButtons = new JPanel(new FlowLayout(FlowLayout.LEFT));
787 tabularButtons.add(tabularPrev);
788 tabularPrev.addActionListener(this);
789 tabularLabel = new JLabel(tabularNavigationSingle);
790 tabularLabel.setEnabled(false);
791 tabularButtons.add(tabularLabel);
792 tabularButtons.add(tabularNext);
793 tabularNext.addActionListener(this);
794 tabularButtons.setBackground(Color.white);
795
796 prev = new JButton(Resources.getText("<<"));
797 prev.addActionListener(this);
798 buttons.add(prev);
799
800 incr = new JButton(Resources.getText(">"));
801 incr.addActionListener(this);
802 decr = new JButton(Resources.getText("<"));
803 decr.addActionListener(this);
804
805 JPanel array = new JPanel();
806 array.setBackground(Color.white);
807 array.add(decr);
808 compositeLabel = new JLabel(compositeNavigationSingle);
809 compositeLabel.setEnabled(false);
810 array.add(compositeLabel);
811 array.add(incr);
812
813 buttons.add(array);
814 setLayout(new BorderLayout());
815 buttons.setBackground(Color.white);
816
817 JPanel navigationPanel = new JPanel(new BorderLayout());
818 navigationPanel.setBackground(Color.white);
819 navigationPanel.add(tabularButtons, BorderLayout.NORTH);
820 navigationPanel.add(buttons, BorderLayout.WEST);
821 add(navigationPanel, BorderLayout.NORTH);
822
823 add(container, BorderLayout.CENTER);
824 Dimension d = new Dimension((int)container.getPreferredSize().
825 getWidth() + 20,
826 (int)container.getPreferredSize().
827 getHeight() + 20);
828 setPreferredSize(d);
829 }
830}