001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.gui.sequence; 020 021import icy.file.FileUtil; 022import icy.gui.component.button.IcyButton; 023import icy.gui.frame.GenericFrame; 024import icy.gui.main.ActiveSequenceListener; 025import icy.main.Icy; 026import icy.math.UnitUtil; 027import icy.math.UnitUtil.UnitPrefix; 028import icy.resource.ResourceUtil; 029import icy.resource.icon.IcyIcon; 030import icy.sequence.Sequence; 031import icy.sequence.SequenceEvent; 032import icy.system.IcyExceptionHandler; 033import icy.system.SystemUtil; 034import icy.system.thread.ThreadUtil; 035import icy.util.EventUtil; 036import icy.util.StringUtil; 037 038import java.awt.Dimension; 039import java.awt.GridBagConstraints; 040import java.awt.GridBagLayout; 041import java.awt.Insets; 042import java.awt.event.ActionEvent; 043import java.awt.event.ActionListener; 044import java.awt.event.MouseAdapter; 045import java.awt.event.MouseEvent; 046import java.io.IOException; 047 048import javax.swing.JLabel; 049import javax.swing.JPanel; 050import javax.swing.JTextField; 051 052/** 053 * @author Stephane 054 */ 055public class SequenceInfosPanel extends JPanel implements ActiveSequenceListener 056{ 057 /** 058 * 059 */ 060 private static final long serialVersionUID = -6123324347914804260L; 061 062 // GUI 063 private JLabel dimensionLabel; 064 private JLabel resXLabel; 065 private JLabel resYLabel; 066 private JLabel resZLabel; 067 private JLabel resTLabel; 068 private JLabel sizeLabel; 069 private JLabel channelLabel; 070 071 private IcyButton editBtn; 072 private IcyButton detailBtn; 073 074 private JLabel pathLabel; 075 JTextField pathField; 076 private JTextField nameField; 077 078 // internals 079 private final Runnable infosRefresher; 080 081 public SequenceInfosPanel() 082 { 083 super(); 084 085 initialize(); 086 087 editBtn.addActionListener(new ActionListener() 088 { 089 @Override 090 public void actionPerformed(ActionEvent e) 091 { 092 // it should be the current focused sequence 093 final Sequence seq = Icy.getMainInterface().getActiveSequence(); 094 095 if (seq != null) 096 new SequencePropertiesDialog(seq); 097 } 098 }); 099 100 detailBtn.addActionListener(new ActionListener() 101 { 102 @Override 103 public void actionPerformed(ActionEvent e) 104 { 105 // it should be the current focused sequence 106 final Sequence seq = Icy.getMainInterface().getActiveSequence(); 107 108 if (seq != null) 109 { 110 final GenericFrame g = new GenericFrame(seq.getName() + " - Metadata", new SequenceMetadataPanel( 111 seq)); 112 113 g.addToDesktopPane(); 114 g.center(); 115 g.requestFocus(); 116 } 117 } 118 }); 119 120 infosRefresher = new Runnable() 121 { 122 @Override 123 public void run() 124 { 125 ThreadUtil.invokeNow(new Runnable() 126 { 127 @Override 128 public void run() 129 { 130 updateInfosInternal(Icy.getMainInterface().getActiveSequence()); 131 } 132 }); 133 } 134 }; 135 136 updateInfosInternal(null); 137 } 138 139 public void initialize() 140 { 141 GridBagLayout gridBagLayout = new GridBagLayout(); 142 gridBagLayout.columnWidths = new int[] {0, 40, 40, 40, 0}; 143 gridBagLayout.rowHeights = new int[] {18, 0, 18, 18, 18, 18, 18, 18, 0}; 144 gridBagLayout.columnWeights = new double[] {0.0, 1.0, 1.0, 1.0, Double.MIN_VALUE}; 145 gridBagLayout.rowWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; 146 setLayout(gridBagLayout); 147 148 JLabel lbl_name = new JLabel("Name"); 149 lbl_name.setToolTipText("Sequence name"); 150 GridBagConstraints gbc_lbl_name = new GridBagConstraints(); 151 gbc_lbl_name.anchor = GridBagConstraints.WEST; 152 gbc_lbl_name.fill = GridBagConstraints.VERTICAL; 153 gbc_lbl_name.insets = new Insets(0, 0, 5, 5); 154 gbc_lbl_name.gridx = 0; 155 gbc_lbl_name.gridy = 0; 156 add(lbl_name, gbc_lbl_name); 157 158 nameField = new JTextField() 159 { 160 @Override 161 public Dimension getPreferredSize() 162 { 163 final Dimension result = super.getPreferredSize(); 164 // prevent enlarging panel 165 result.width = 100; 166 return result; 167 } 168 }; 169 nameField.setOpaque(false); 170 nameField.setBorder(null); 171 nameField.setEditable(false); 172 173 GridBagConstraints gbc_scrollPane = new GridBagConstraints(); 174 gbc_scrollPane.fill = GridBagConstraints.BOTH; 175 gbc_scrollPane.gridwidth = 3; 176 gbc_scrollPane.insets = new Insets(0, 0, 5, 0); 177 gbc_scrollPane.gridx = 1; 178 gbc_scrollPane.gridy = 0; 179 add(nameField, gbc_scrollPane); 180 181 pathLabel = new JLabel("Path"); 182 pathLabel.setToolTipText("Sequence file path"); 183 GridBagConstraints gbc_pathLabel = new GridBagConstraints(); 184 gbc_pathLabel.fill = GridBagConstraints.VERTICAL; 185 gbc_pathLabel.anchor = GridBagConstraints.WEST; 186 gbc_pathLabel.insets = new Insets(0, 0, 5, 5); 187 gbc_pathLabel.gridx = 0; 188 gbc_pathLabel.gridy = 1; 189 add(pathLabel, gbc_pathLabel); 190 191 pathField = new JTextField() 192 { 193 @Override 194 public Dimension getPreferredSize() 195 { 196 final Dimension result = super.getPreferredSize(); 197 // prevent enlarging panel 198 result.width = 100; 199 return result; 200 } 201 }; 202 pathField.setOpaque(false); 203 pathField.setBorder(null); 204 pathField.setEditable(false); 205 pathField.addMouseListener(new MouseAdapter() 206 { 207 @Override 208 public void mouseClicked(MouseEvent e) 209 { 210 if (e.isConsumed()) 211 return; 212 213 if (EventUtil.isLeftMouseButton(e) && (e.getClickCount() == 2)) 214 { 215 try 216 { 217 SystemUtil.openFolder(FileUtil.getDirectory(pathField.getText())); 218 } 219 catch (IOException e1) 220 { 221 IcyExceptionHandler.showErrorMessage(e1, false, false); 222 } 223 224 e.consume(); 225 } 226 } 227 }); 228 229 GridBagConstraints gbc_scrollPane_1 = new GridBagConstraints(); 230 gbc_scrollPane_1.fill = GridBagConstraints.BOTH; 231 gbc_scrollPane_1.gridwidth = 3; 232 gbc_scrollPane_1.insets = new Insets(0, 0, 5, 5); 233 gbc_scrollPane_1.gridx = 1; 234 gbc_scrollPane_1.gridy = 1; 235 add(pathField, gbc_scrollPane_1); 236 237 JLabel lbl_dim = new JLabel("Dimension"); 238 lbl_dim.setToolTipText("Size of X, Y, Z and T dimension"); 239 GridBagConstraints gbc_lbl_dim = new GridBagConstraints(); 240 gbc_lbl_dim.anchor = GridBagConstraints.WEST; 241 gbc_lbl_dim.fill = GridBagConstraints.VERTICAL; 242 gbc_lbl_dim.insets = new Insets(0, 0, 5, 5); 243 gbc_lbl_dim.gridx = 0; 244 gbc_lbl_dim.gridy = 2; 245 add(lbl_dim, gbc_lbl_dim); 246 247 dimensionLabel = new JLabel(); 248 dimensionLabel.setText("---"); 249 GridBagConstraints gbc_dimensionLabel = new GridBagConstraints(); 250 gbc_dimensionLabel.anchor = GridBagConstraints.WEST; 251 gbc_dimensionLabel.gridwidth = 3; 252 gbc_dimensionLabel.fill = GridBagConstraints.VERTICAL; 253 gbc_dimensionLabel.insets = new Insets(0, 0, 5, 0); 254 gbc_dimensionLabel.gridx = 1; 255 gbc_dimensionLabel.gridy = 2; 256 add(dimensionLabel, gbc_dimensionLabel); 257 258 JLabel lbl_channel = new JLabel("Channel"); 259 lbl_channel.setToolTipText("Number of channel - data type"); 260 GridBagConstraints gbc_lbl_channel = new GridBagConstraints(); 261 gbc_lbl_channel.anchor = GridBagConstraints.WEST; 262 gbc_lbl_channel.fill = GridBagConstraints.VERTICAL; 263 gbc_lbl_channel.insets = new Insets(0, 0, 5, 5); 264 gbc_lbl_channel.gridx = 0; 265 gbc_lbl_channel.gridy = 3; 266 add(lbl_channel, gbc_lbl_channel); 267 268 channelLabel = new JLabel(); 269 channelLabel.setText("---"); 270 GridBagConstraints gbc_channelLabel = new GridBagConstraints(); 271 gbc_channelLabel.anchor = GridBagConstraints.WEST; 272 gbc_channelLabel.gridwidth = 3; 273 gbc_channelLabel.fill = GridBagConstraints.VERTICAL; 274 gbc_channelLabel.insets = new Insets(0, 0, 5, 0); 275 gbc_channelLabel.gridx = 1; 276 gbc_channelLabel.gridy = 3; 277 add(channelLabel, gbc_channelLabel); 278 279 JLabel lbl_size = new JLabel("Size"); 280 lbl_size.setToolTipText("Size"); 281 GridBagConstraints gbc_lbl_size = new GridBagConstraints(); 282 gbc_lbl_size.anchor = GridBagConstraints.WEST; 283 gbc_lbl_size.fill = GridBagConstraints.VERTICAL; 284 gbc_lbl_size.insets = new Insets(0, 0, 5, 5); 285 gbc_lbl_size.gridx = 0; 286 gbc_lbl_size.gridy = 4; 287 add(lbl_size, gbc_lbl_size); 288 289 sizeLabel = new JLabel(); 290 sizeLabel.setText("---"); 291 GridBagConstraints gbc_sizeLabel = new GridBagConstraints(); 292 gbc_sizeLabel.anchor = GridBagConstraints.WEST; 293 gbc_sizeLabel.gridwidth = 3; 294 gbc_sizeLabel.fill = GridBagConstraints.VERTICAL; 295 gbc_sizeLabel.insets = new Insets(0, 0, 5, 0); 296 gbc_sizeLabel.gridx = 1; 297 gbc_sizeLabel.gridy = 4; 298 add(sizeLabel, gbc_sizeLabel); 299 300 JLabel lbl_psx = new JLabel("Pixel size"); 301 lbl_psx.setToolTipText("Pixel size for X, Y, Z dimension"); 302 GridBagConstraints gbc_lbl_psx = new GridBagConstraints(); 303 gbc_lbl_psx.anchor = GridBagConstraints.WEST; 304 gbc_lbl_psx.fill = GridBagConstraints.VERTICAL; 305 gbc_lbl_psx.insets = new Insets(0, 0, 5, 5); 306 gbc_lbl_psx.gridx = 0; 307 gbc_lbl_psx.gridy = 5; 308 add(lbl_psx, gbc_lbl_psx); 309 310 resXLabel = new JLabel(); 311 resXLabel.setText("---"); 312 GridBagConstraints gbc_resXLabel = new GridBagConstraints(); 313 gbc_resXLabel.anchor = GridBagConstraints.WEST; 314 gbc_resXLabel.fill = GridBagConstraints.VERTICAL; 315 gbc_resXLabel.insets = new Insets(0, 0, 5, 5); 316 gbc_resXLabel.gridx = 1; 317 gbc_resXLabel.gridy = 5; 318 add(resXLabel, gbc_resXLabel); 319 320 resYLabel = new JLabel(); 321 resYLabel.setText("---"); 322 GridBagConstraints gbc_resYLabel = new GridBagConstraints(); 323 gbc_resYLabel.anchor = GridBagConstraints.WEST; 324 gbc_resYLabel.fill = GridBagConstraints.VERTICAL; 325 gbc_resYLabel.insets = new Insets(0, 0, 5, 5); 326 gbc_resYLabel.gridx = 2; 327 gbc_resYLabel.gridy = 5; 328 add(resYLabel, gbc_resYLabel); 329 330 resZLabel = new JLabel(); 331 resZLabel.setText("---"); 332 GridBagConstraints gbc_resZLabel = new GridBagConstraints(); 333 gbc_resZLabel.anchor = GridBagConstraints.WEST; 334 gbc_resZLabel.fill = GridBagConstraints.VERTICAL; 335 gbc_resZLabel.insets = new Insets(0, 0, 5, 0); 336 gbc_resZLabel.gridx = 3; 337 gbc_resZLabel.gridy = 5; 338 add(resZLabel, gbc_resZLabel); 339 340 JLabel lbl_time = new JLabel("Time interval"); 341 lbl_time.setToolTipText("Time Interval"); 342 GridBagConstraints gbc_lbl_time = new GridBagConstraints(); 343 gbc_lbl_time.anchor = GridBagConstraints.WEST; 344 gbc_lbl_time.fill = GridBagConstraints.VERTICAL; 345 gbc_lbl_time.insets = new Insets(0, 0, 5, 5); 346 gbc_lbl_time.gridx = 0; 347 gbc_lbl_time.gridy = 6; 348 add(lbl_time, gbc_lbl_time); 349 350 resTLabel = new JLabel(); 351 resTLabel.setText("---"); 352 GridBagConstraints gbc_resTLabel = new GridBagConstraints(); 353 gbc_resTLabel.anchor = GridBagConstraints.WEST; 354 gbc_resTLabel.gridwidth = 3; 355 gbc_resTLabel.fill = GridBagConstraints.VERTICAL; 356 gbc_resTLabel.insets = new Insets(0, 0, 5, 0); 357 gbc_resTLabel.gridx = 1; 358 gbc_resTLabel.gridy = 6; 359 add(resTLabel, gbc_resTLabel); 360 361 editBtn = new IcyButton("Edit", new IcyIcon(ResourceUtil.ICON_DOCEDIT)); 362 editBtn.setToolTipText("Edit sequence properties"); 363 364 GridBagConstraints gbc_editBtn = new GridBagConstraints(); 365 gbc_editBtn.gridwidth = 2; 366 gbc_editBtn.fill = GridBagConstraints.BOTH; 367 gbc_editBtn.insets = new Insets(0, 0, 0, 5); 368 gbc_editBtn.gridx = 0; 369 gbc_editBtn.gridy = 7; 370 add(editBtn, gbc_editBtn); 371 372 detailBtn = new IcyButton("Show metadata", new IcyIcon(ResourceUtil.ICON_PROPERTIES)); 373 detailBtn.setText("Metadata"); 374 detailBtn.setToolTipText("Show all associated metadata informations"); 375 376 GridBagConstraints gbc_detailBtn = new GridBagConstraints(); 377 gbc_detailBtn.gridwidth = 2; 378 gbc_detailBtn.fill = GridBagConstraints.BOTH; 379 gbc_detailBtn.gridx = 2; 380 gbc_detailBtn.gridy = 7; 381 add(detailBtn, gbc_detailBtn); 382 } 383 384 public void updateInfos() 385 { 386 ThreadUtil.runSingle(infosRefresher); 387 } 388 389 public void updateInfosInternal(Sequence sequence) 390 { 391 if (sequence != null) 392 { 393 final int sizeX = sequence.getSizeX(); 394 final int sizeY = sequence.getSizeY(); 395 final int sizeZ = sequence.getSizeZ(); 396 final int sizeT = sequence.getSizeT(); 397 final int sizeC = sequence.getSizeC(); 398 399 final double pxSizeX = sequence.getPixelSizeX(); 400 final double pxSizeY = sequence.getPixelSizeY(); 401 final double pxSizeZ = sequence.getPixelSizeZ(); 402 403 final String path = sequence.getFilename(); 404 405 nameField.setText(sequence.getName()); 406 // path 407 if (StringUtil.isEmpty(path)) 408 { 409 pathLabel.setVisible(false); 410 pathField.setVisible(false); 411 } 412 else 413 { 414 pathLabel.setVisible(true); 415 pathField.setVisible(true); 416 pathField.setText(path); 417 } 418 dimensionLabel.setText(sizeX + " x " + sizeY + " x " + sizeZ + " x " + sizeT); 419 channelLabel.setText(sizeC + " - " + sequence.getDataType_().toLongString()); 420 sizeLabel.setText(UnitUtil.getBytesString((double) sizeX * (double) sizeY * sizeZ * sizeT * sizeC 421 * sequence.getDataType_().getSize())); 422 resXLabel.setText(UnitUtil.getBestUnitInMeters(pxSizeX, 2, UnitPrefix.MICRO)); 423 resYLabel.setText(UnitUtil.getBestUnitInMeters(pxSizeY, 2, UnitPrefix.MICRO)); 424 resZLabel.setText(UnitUtil.getBestUnitInMeters(pxSizeZ, 2, UnitPrefix.MICRO)); 425 resTLabel.setText(UnitUtil.displayTimeAsStringWithUnits(sequence.getTimeInterval() * 1000d, false)); 426 427 nameField.setToolTipText(sequence.getName()); 428 pathField.setToolTipText(path + " (double click to see file location)"); 429 dimensionLabel.setToolTipText("Size X : " + sizeX + " Size Y : " + sizeY + " Size Z : " + sizeZ 430 + " Size T : " + sizeT); 431 if (sizeC > 1) 432 channelLabel.setToolTipText(sizeC + " channels - " + sequence.getDataType_()); 433 else 434 channelLabel.setToolTipText(sizeC + " channel - " + sequence.getDataType_()); 435 sizeLabel.setToolTipText(sizeLabel.getText()); 436 437 resXLabel.setToolTipText("X pixel resolution: " + resXLabel.getText()); 438 resYLabel.setToolTipText("Y pixel resolution: " + resYLabel.getText()); 439 resZLabel.setToolTipText("Z pixel resolution: " + resZLabel.getText()); 440 resTLabel.setToolTipText("T time resolution: " + resTLabel.getText()); 441 442 editBtn.setEnabled(true); 443 detailBtn.setEnabled(true); 444 } 445 else 446 { 447 pathLabel.setVisible(false); 448 pathField.setVisible(false); 449 450 nameField.setText("-"); 451 dimensionLabel.setText("-"); 452 channelLabel.setText("-"); 453 sizeLabel.setText("-"); 454 resXLabel.setText("-"); 455 resYLabel.setText("-"); 456 resZLabel.setText("-"); 457 resTLabel.setText("-"); 458 459 nameField.setToolTipText(""); 460 dimensionLabel.setToolTipText(""); 461 channelLabel.setToolTipText(""); 462 sizeLabel.setToolTipText(""); 463 resXLabel.setToolTipText("X pixel resolution"); 464 resYLabel.setToolTipText("Y pixel resolution"); 465 resZLabel.setToolTipText("Z pixel resolution"); 466 resTLabel.setToolTipText("T time resolution"); 467 468 editBtn.setEnabled(false); 469 detailBtn.setEnabled(false); 470 } 471 472 revalidate(); 473 } 474 475 @Override 476 public void sequenceActivated(Sequence sequence) 477 { 478 updateInfos(); 479 } 480 481 @Override 482 public void sequenceDeactivated(Sequence sequence) 483 { 484 // nothing to do here 485 } 486 487 @Override 488 public void activeSequenceChanged(SequenceEvent event) 489 { 490 switch (event.getSourceType()) 491 { 492 case SEQUENCE_DATA: 493 case SEQUENCE_TYPE: 494 case SEQUENCE_META: 495 updateInfos(); 496 break; 497 } 498 } 499}