You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PackingTable.java 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (c) 2006-2014 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package com.dmdirc.addons.ui_swing.components;
  23. import java.awt.Graphics;
  24. import javax.swing.JScrollPane;
  25. import javax.swing.JTable;
  26. import javax.swing.table.DefaultTableModel;
  27. import javax.swing.table.TableColumn;
  28. import javax.swing.table.TableColumnModel;
  29. import javax.swing.table.TableModel;
  30. import net.miginfocom.layout.PlatformDefaults;
  31. /**
  32. * Creates a new table that automatically sizes its columns to the size of its data.
  33. */
  34. public class PackingTable extends JTable {
  35. /**
  36. * A version number for this class. It should be changed whenever the class structure is changed
  37. * (or anything else that would prevent serialized objects being unserialized with the new
  38. * class).
  39. */
  40. private static final long serialVersionUID = 1;
  41. /** Scrollpane. */
  42. private final JScrollPane scrollPane;
  43. /** Should the last column fit text (true), or fit viewport (false). */
  44. private boolean lastColumnFit;
  45. /** Border padding. */
  46. private final int padding = (int) PlatformDefaults.getUnitValueX("related").
  47. getValue();
  48. /**
  49. * Creates a new packing table.
  50. *
  51. * @param rows Row data
  52. * @param cols Column data
  53. * @param scrollPane Scrollpane parent
  54. */
  55. public PackingTable(final Object[][] rows, final Object[] cols,
  56. final JScrollPane scrollPane) {
  57. this(new DefaultTableModel(rows, cols), scrollPane, true);
  58. }
  59. /**
  60. * Creates a new packing table.
  61. *
  62. * @param rows Row data
  63. * @param cols Column data
  64. * @param scrollPane Scrollpane parent
  65. * @param lastColumnFit Should the last column fit text (true), or fit viewport (false).
  66. */
  67. public PackingTable(final Object[][] rows, final Object[] cols,
  68. final JScrollPane scrollPane, final boolean lastColumnFit) {
  69. this(new DefaultTableModel(rows, cols), scrollPane,
  70. lastColumnFit);
  71. }
  72. /**
  73. * Creates a new packing table.
  74. *
  75. * @param tableModel Table data model
  76. * @param scrollPane Scrollpane parent
  77. */
  78. public PackingTable(final TableModel tableModel,
  79. final JScrollPane scrollPane) {
  80. this(tableModel, scrollPane, true);
  81. }
  82. /**
  83. * Creates a new packing table.
  84. *
  85. * @param tableModel Table data model
  86. * @param scrollPane Scrollpane parent
  87. * @param lastColumnFit Should the last column fit text (true), or fit viewport (false).
  88. */
  89. public PackingTable(final TableModel tableModel,
  90. final JScrollPane scrollPane, final boolean lastColumnFit) {
  91. super(tableModel);
  92. this.scrollPane = scrollPane;
  93. this.lastColumnFit = lastColumnFit;
  94. super.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
  95. super.getTableHeader().setResizingAllowed(false);
  96. super.getTableHeader().setReorderingAllowed(false);
  97. super.setDragEnabled(false);
  98. }
  99. /** {@inheritDoc} */
  100. @Override
  101. public void setAutoResizeMode(final int mode) {
  102. //Ignore
  103. }
  104. /** {@inheritDoc} */
  105. @Override
  106. public final boolean getScrollableTracksViewportHeight() {
  107. return getPreferredSize().height < getParent().getHeight();
  108. }
  109. /** {@inheritDoc} */
  110. @Override
  111. public final void paint(final Graphics g) {
  112. packColumns();
  113. super.paint(g);
  114. }
  115. /** Packs the columns to their width. */
  116. public final void packColumns() {
  117. if (!isShowing()) {
  118. return;
  119. }
  120. if (getColumnCount() == 0) {
  121. return;
  122. }
  123. final TableColumnModel myColumnModel = getTableHeader()
  124. .getColumnModel();
  125. final int numCols = myColumnModel.getColumnCount();
  126. final int totalSize = (int) (scrollPane.getViewportBorderBounds().width * 0.99);
  127. final int[] widths = new int[numCols];
  128. int widthsTotal = 0;
  129. int checkNumCols = numCols;
  130. if (!lastColumnFit) {
  131. checkNumCols--;
  132. }
  133. for (int i = 0; i < checkNumCols; i++) { //NOPMD I'm not copying
  134. widths[i] = getWidth(i);
  135. widthsTotal += widths[i];
  136. }
  137. final int extra = totalSize - widthsTotal;
  138. if (extra > 0) {
  139. widths[numCols - 1] += extra;
  140. }
  141. for (int i = 0; i < numCols; i++) {
  142. final TableColumn col = myColumnModel.getColumn(i);
  143. col.setPreferredWidth(widths[i]);
  144. }
  145. }
  146. /**
  147. * Returns the width of a column.
  148. *
  149. * @param col Column to retrieve width for
  150. *
  151. * @return Width of the specified column
  152. */
  153. private int getWidth(final int col) {
  154. if (getColumnCount() == 0) {
  155. return 0;
  156. }
  157. if (getColumnCount() <= col) {
  158. return 0;
  159. }
  160. final TableColumn column = getColumnModel().getColumn(col);
  161. int width = (int) getTableHeader().getDefaultRenderer().
  162. getTableCellRendererComponent(this, column.getIdentifier(),
  163. false, false, -1, col).getPreferredSize().getWidth();
  164. if (getRowCount() == 0) {
  165. return width + padding;
  166. }
  167. for (int row = 0; row < getRowCount(); row++) {
  168. if (getCellRenderer(row, col) != null) {
  169. width = Math.max(width, (int) getCellRenderer(row, col).
  170. getTableCellRendererComponent(this, getValueAt(row,
  171. col), false, false, row, col).getPreferredSize().
  172. getWidth());
  173. }
  174. }
  175. return width + padding;
  176. }
  177. }