001package icy.gui.inspector; 002 003import icy.gui.component.AbstractRoisPanel.BaseColumnInfo; 004import icy.gui.component.button.IcyButton; 005import icy.preferences.XMLPreferences; 006import icy.resource.ResourceUtil; 007import icy.resource.icon.IcyIcon; 008import icy.roi.ROIDescriptor; 009import icy.roi.ROIUtil; 010 011import java.awt.BorderLayout; 012import java.awt.GridBagConstraints; 013import java.awt.GridBagLayout; 014import java.awt.Insets; 015import java.awt.event.ActionEvent; 016import java.awt.event.ActionListener; 017import java.util.ArrayList; 018import java.util.Collections; 019import java.util.List; 020import java.util.Set; 021 022import javax.swing.JLabel; 023import javax.swing.JPanel; 024import javax.swing.JScrollPane; 025import javax.swing.JSplitPane; 026import javax.swing.JTable; 027import javax.swing.ListSelectionModel; 028import javax.swing.table.AbstractTableModel; 029import javax.swing.table.TableColumn; 030import javax.swing.table.TableColumnModel; 031 032public class RoiSettingPanel extends JPanel implements ActionListener 033{ 034 // GUI 035 private JScrollPane scrollPaneView; 036 private JScrollPane scrollPaneExport; 037 private JTable tableView; 038 private JTable tableExport; 039 private JPanel panelExportTop; 040 private JLabel lblColumnSelectionFor; 041 private JLabel lblNewLabel; 042 private IcyButton upViewBtn; 043 private IcyButton downViewBtn; 044 private IcyButton upExportBtn; 045 private IcyButton downExportBtn; 046 047 // internals 048 List<BaseColumnInfo> idsView; 049 List<BaseColumnInfo> idsExport; 050 051 private AbstractTableModel viewModel; 052 private AbstractTableModel exportModel; 053 054 private final XMLPreferences prefView; 055 private final XMLPreferences prefExport; 056 057 /** 058 * Create the panel. 059 * 060 * @param exportPreferences 061 */ 062 public RoiSettingPanel(XMLPreferences viewPreferences, XMLPreferences exportPreferences) 063 { 064 super(); 065 066 prefView = viewPreferences; 067 prefExport = exportPreferences; 068 069 final Set<ROIDescriptor> descriptors = ROIUtil.getROIDescriptors().keySet(); 070 071 idsView = new ArrayList<BaseColumnInfo>(); 072 idsExport = new ArrayList<BaseColumnInfo>(); 073 074 // build view and export lists 075 for (ROIDescriptor descriptor : descriptors) 076 { 077 idsView.add(new BaseColumnInfo(descriptor, prefView, false)); 078 idsExport.add(new BaseColumnInfo(descriptor, prefExport, true)); 079 } 080 081 sortLists(); 082 083 initialize(); 084 085 viewModel = new AbstractTableModel() 086 { 087 @Override 088 public int getColumnCount() 089 { 090 return 2; 091 } 092 093 @Override 094 public Class<?> getColumnClass(int columnIndex) 095 { 096 switch (columnIndex) 097 { 098 case 0: 099 // name 100 return String.class; 101 102 case 1: 103 // visibility 104 return Boolean.class; 105 } 106 107 return String.class; 108 } 109 110 @Override 111 public String getColumnName(int column) 112 { 113 switch (column) 114 { 115 case 0: 116 return "Column name"; 117 118 case 1: 119 return "Visible"; 120 } 121 122 return ""; 123 } 124 125 @Override 126 public int getRowCount() 127 { 128 return idsView.size(); 129 } 130 131 @Override 132 public Object getValueAt(int rowIndex, int columnIndex) 133 { 134 switch (columnIndex) 135 { 136 case 0: 137 // name 138 return idsView.get(rowIndex).descriptor.getName(); 139 140 case 1: 141 // visibility 142 return Boolean.valueOf(idsView.get(rowIndex).visible); 143 } 144 145 return null; 146 } 147 148 @Override 149 public boolean isCellEditable(int rowIndex, int columnIndex) 150 { 151 return (columnIndex == 1); 152 } 153 154 @Override 155 public void setValueAt(Object aValue, int rowIndex, int columnIndex) 156 { 157 // visibility 158 if (columnIndex == 1) 159 idsView.get(rowIndex).visible = ((Boolean) aValue).booleanValue(); 160 } 161 }; 162 163 exportModel = new AbstractTableModel() 164 { 165 @Override 166 public int getColumnCount() 167 { 168 return 2; 169 } 170 171 @Override 172 public Class<?> getColumnClass(int columnIndex) 173 { 174 switch (columnIndex) 175 { 176 case 0: 177 // name 178 return String.class; 179 180 case 1: 181 // visibility 182 return Boolean.class; 183 } 184 185 return String.class; 186 } 187 188 @Override 189 public String getColumnName(int column) 190 { 191 switch (column) 192 { 193 case 0: 194 return "Column name"; 195 196 case 1: 197 return "Visible"; 198 } 199 200 return ""; 201 } 202 203 @Override 204 public int getRowCount() 205 { 206 return idsExport.size(); 207 } 208 209 @Override 210 public Object getValueAt(int rowIndex, int columnIndex) 211 { 212 switch (columnIndex) 213 { 214 case 0: 215 // name 216 return idsExport.get(rowIndex).descriptor.getName(); 217 218 case 1: 219 // visibility 220 return Boolean.valueOf(idsExport.get(rowIndex).visible); 221 } 222 223 return null; 224 } 225 226 @Override 227 public boolean isCellEditable(int rowIndex, int columnIndex) 228 { 229 return (columnIndex == 1); 230 } 231 232 @Override 233 public void setValueAt(Object aValue, int rowIndex, int columnIndex) 234 { 235 // visibility 236 if (columnIndex == 1) 237 idsExport.get(rowIndex).visible = ((Boolean) aValue).booleanValue(); 238 } 239 }; 240 241 TableColumnModel columnModel; 242 TableColumn column; 243 244 tableView.setModel(viewModel); 245 columnModel = tableView.getColumnModel(); 246 247 column = columnModel.getColumn(0); 248 column.setPreferredWidth(150); 249 column.setMinWidth(80); 250 column = columnModel.getColumn(1); 251 column.setResizable(false); 252 column.setPreferredWidth(50); 253 column.setMaxWidth(50); 254 column.setMinWidth(30); 255 256 tableExport.setModel(exportModel); 257 columnModel = tableExport.getColumnModel(); 258 259 column = columnModel.getColumn(0); 260 column.setPreferredWidth(150); 261 column.setMinWidth(80); 262 column = columnModel.getColumn(1); 263 column.setResizable(false); 264 column.setPreferredWidth(50); 265 column.setMaxWidth(50); 266 column.setMinWidth(30); 267 268 upViewBtn.addActionListener(this); 269 downViewBtn.addActionListener(this); 270 upExportBtn.addActionListener(this); 271 downExportBtn.addActionListener(this); 272 } 273 274 private void initialize() 275 { 276 setLayout(new BorderLayout(0, 0)); 277 278 JSplitPane splitPane = new JSplitPane(); 279 splitPane.setResizeWeight(0.5); 280 add(splitPane, BorderLayout.CENTER); 281 282 JPanel panelView = new JPanel(); 283 splitPane.setLeftComponent(panelView); 284 panelView.setLayout(new BorderLayout(0, 0)); 285 286 scrollPaneView = new JScrollPane(); 287 panelView.add(scrollPaneView, BorderLayout.CENTER); 288 289 tableView = new JTable(); 290 tableView.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 291 tableView.setRowSelectionAllowed(true); 292 scrollPaneView.setViewportView(tableView); 293 294 JPanel panelViewTop = new JPanel(); 295 panelView.add(panelViewTop, BorderLayout.NORTH); 296 GridBagLayout gbl_panelViewTop = new GridBagLayout(); 297 gbl_panelViewTop.columnWidths = new int[] {0, 0, 0, 0}; 298 gbl_panelViewTop.rowHeights = new int[] {14, 0}; 299 gbl_panelViewTop.columnWeights = new double[] {1.0, 0.0, 0.0, Double.MIN_VALUE}; 300 gbl_panelViewTop.rowWeights = new double[] {0.0, Double.MIN_VALUE}; 301 panelViewTop.setLayout(gbl_panelViewTop); 302 303 lblColumnSelectionFor = new JLabel("Columns to display"); 304 GridBagConstraints gbc_lblColumnSelectionFor = new GridBagConstraints(); 305 gbc_lblColumnSelectionFor.insets = new Insets(0, 0, 0, 5); 306 gbc_lblColumnSelectionFor.gridx = 0; 307 gbc_lblColumnSelectionFor.gridy = 0; 308 panelViewTop.add(lblColumnSelectionFor, gbc_lblColumnSelectionFor); 309 310 upViewBtn = new IcyButton(new IcyIcon(ResourceUtil.ICON_ARROW_UP)); 311 upViewBtn.setToolTipText("Change order of selected column(s)"); 312 upViewBtn.setFlat(true); 313 GridBagConstraints gbc_upViewBtn = new GridBagConstraints(); 314 gbc_upViewBtn.insets = new Insets(0, 0, 0, 5); 315 gbc_upViewBtn.gridx = 1; 316 gbc_upViewBtn.gridy = 0; 317 panelViewTop.add(upViewBtn, gbc_upViewBtn); 318 319 downViewBtn = new IcyButton(new IcyIcon(ResourceUtil.ICON_ARROW_DOWN)); 320 downViewBtn.setToolTipText("Change order of selected column(s)"); 321 downViewBtn.setFlat(true); 322 GridBagConstraints gbc_downViewBtn = new GridBagConstraints(); 323 gbc_downViewBtn.gridx = 2; 324 gbc_downViewBtn.gridy = 0; 325 panelViewTop.add(downViewBtn, gbc_downViewBtn); 326 327 JPanel panelExport = new JPanel(); 328 splitPane.setRightComponent(panelExport); 329 panelExport.setLayout(new BorderLayout(0, 0)); 330 331 scrollPaneExport = new JScrollPane(); 332 panelExport.add(scrollPaneExport, BorderLayout.CENTER); 333 334 tableExport = new JTable(); 335 tableExport.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 336 tableExport.setRowSelectionAllowed(true); 337 scrollPaneExport.setViewportView(tableExport); 338 339 panelExportTop = new JPanel(); 340 panelExport.add(panelExportTop, BorderLayout.NORTH); 341 GridBagLayout gbl_panelExportTop = new GridBagLayout(); 342 gbl_panelExportTop.columnWidths = new int[] {0, 0, 0, 0}; 343 gbl_panelExportTop.rowHeights = new int[] {14, 0}; 344 gbl_panelExportTop.columnWeights = new double[] {1.0, 0.0, 0.0, Double.MIN_VALUE}; 345 gbl_panelExportTop.rowWeights = new double[] {0.0, Double.MIN_VALUE}; 346 panelExportTop.setLayout(gbl_panelExportTop); 347 348 lblNewLabel = new JLabel("Columns to export (XLS or CSV)"); 349 GridBagConstraints gbc_lblNewLabel = new GridBagConstraints(); 350 gbc_lblNewLabel.insets = new Insets(0, 0, 0, 5); 351 gbc_lblNewLabel.gridx = 0; 352 gbc_lblNewLabel.gridy = 0; 353 panelExportTop.add(lblNewLabel, gbc_lblNewLabel); 354 355 upExportBtn = new IcyButton(new IcyIcon(ResourceUtil.ICON_ARROW_UP)); 356 upExportBtn.setToolTipText("Change order of selected column(s)"); 357 upExportBtn.setFlat(true); 358 GridBagConstraints gbc_upExportBtn = new GridBagConstraints(); 359 gbc_upExportBtn.insets = new Insets(0, 0, 0, 5); 360 gbc_upExportBtn.gridx = 1; 361 gbc_upExportBtn.gridy = 0; 362 panelExportTop.add(upExportBtn, gbc_upExportBtn); 363 364 downExportBtn = new IcyButton(new IcyIcon(ResourceUtil.ICON_ARROW_DOWN)); 365 downExportBtn.setToolTipText("Change order of selected column(s)"); 366 downExportBtn.setFlat(true); 367 GridBagConstraints gbc_downExportBtn = new GridBagConstraints(); 368 gbc_downExportBtn.gridx = 2; 369 gbc_downExportBtn.gridy = 0; 370 panelExportTop.add(downExportBtn, gbc_downExportBtn); 371 } 372 373 void fixOrders() 374 { 375 int order; 376 377 order = 0; 378 for (BaseColumnInfo columnInfo : idsView) 379 columnInfo.order = order++; 380 order = 0; 381 for (BaseColumnInfo columnInfo : idsExport) 382 columnInfo.order = order++; 383 } 384 385 /** 386 * Sort lists on their order 387 */ 388 void sortLists() 389 { 390 // sort tables 391 Collections.sort(idsView); 392 Collections.sort(idsExport); 393 // and fix orders 394 fixOrders(); 395 } 396 397 /** 398 * Save columns setting to preferences 399 */ 400 public void save() 401 { 402 sortLists(); 403 404 for (BaseColumnInfo columnInfo : idsView) 405 columnInfo.save(prefView); 406 for (BaseColumnInfo columnInfo : idsExport) 407 columnInfo.save(prefExport); 408 } 409 410 List<BaseColumnInfo> getSelected(JTable table, List<BaseColumnInfo> columnInfos) 411 { 412 final List<BaseColumnInfo> result = new ArrayList<BaseColumnInfo>(); 413 final int[] selected = table.getSelectedRows(); 414 415 for (int index : selected) 416 result.add(columnInfos.get(index)); 417 418 return result; 419 } 420 421 void restoreSelected(JTable table, List<BaseColumnInfo> columnInfos, List<BaseColumnInfo> selected) 422 { 423 final ListSelectionModel selectionModel = table.getSelectionModel(); 424 425 selectionModel.setValueIsAdjusting(true); 426 try 427 { 428 selectionModel.clearSelection(); 429 430 for (BaseColumnInfo bci : selected) 431 { 432 final int index = columnInfos.indexOf(bci); 433 if (index >= 0) 434 selectionModel.addSelectionInterval(index, index); 435 } 436 } 437 finally 438 { 439 selectionModel.setValueIsAdjusting(false); 440 } 441 } 442 443 @Override 444 public void actionPerformed(ActionEvent e) 445 { 446 final Object source = e.getSource(); 447 final JTable table; 448 final List<BaseColumnInfo> columnInfos; 449 final int v; 450 451 if ((source == upViewBtn) || (source == downViewBtn)) 452 { 453 table = tableView; 454 columnInfos = idsView; 455 } 456 else if ((source == upExportBtn) || (source == downExportBtn)) 457 { 458 table = tableExport; 459 columnInfos = idsExport; 460 } 461 else 462 { 463 table = null; 464 columnInfos = null; 465 } 466 467 if ((source == upViewBtn) || (source == upExportBtn)) 468 v = -1; 469 else if ((source == downViewBtn) || (source == downExportBtn)) 470 v = 1; 471 else 472 v = 0; 473 474 if ((table != null) && (columnInfos != null)) 475 { 476 final List<BaseColumnInfo> selected = getSelected(table, columnInfos); 477 478 // update order of selected area 479 for (BaseColumnInfo bci : selected) 480 bci.order = bci.order + v; 481 482 if (v == -1) 483 { 484 // change order of previous item 485 final int firstSelected = table.getSelectionModel().getMinSelectionIndex(); 486 if ((firstSelected != -1) && (firstSelected > 0)) 487 columnInfos.get(firstSelected - 1).order += table.getSelectedRowCount(); 488 } 489 else 490 { 491 // change order of next item 492 final int lastSelected = table.getSelectionModel().getMaxSelectionIndex(); 493 if ((lastSelected != -1) && (lastSelected < (columnInfos.size() - 1))) 494 columnInfos.get(lastSelected + 1).order -= table.getSelectedRowCount(); 495 } 496 497 // sort lists 498 sortLists(); 499 500 restoreSelected(table, columnInfos, selected); 501 // refresh table data 502 viewModel.fireTableRowsUpdated(0, idsView.size() - 1); 503 exportModel.fireTableRowsUpdated(0, idsExport.size() - 1); 504 } 505 } 506}