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