/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2011, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.swing.dialog;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Toolkit;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import org.geotools.swing.testutils.GraphicsTestBase;
import org.geotools.swing.testutils.GraphicsTestRunner;
import org.geotools.swing.testutils.WindowActivatedListener;
import org.fest.swing.core.GenericTypeMatcher;
import org.fest.swing.fixture.JComboBoxFixture;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Tests for {@linkplain JFileImageChooser}.
* <p>
*
* This test class uses an {@linkplain ExecutorService} to launch the dialog which
* avoids a deadlock between the modal dialog and this class waiting for the dialog
* to show up on the event thread.
* <p>
*
* TODO: it would be good to test display of the "Confirm file name" dialog but
* I haven't worked out how to detect its appearance on the EDT reliably without
* blocking the test.
*
* @author Michael Bedward
* @since 8.0
* @source $URL$
* @version $Id$
*/
@RunWith(GraphicsTestRunner.class)
public class JFileImageChooserTest extends GraphicsTestBase<Dialog> {
private static final Class<? extends Component> DIALOG_CLASS = JFileImageChooser.class;
private static final ExecutorService executor = Executors.newSingleThreadExecutor();;
private static List<String> readerFileSuffixes;
private static List<String> writerFileSuffixes;
private WindowActivatedListener listener;
@BeforeClass
public static void setupOnce() {
readerFileSuffixes = Arrays.asList( ImageIO.getReaderFileSuffixes() );
writerFileSuffixes = Arrays.asList( ImageIO.getWriterFileSuffixes() );
}
@Before
public void setup() {
/*
* Note that we have to listen for a JDialog, rhther than a JFileImageChooser
* or JFileChooser, because this is what the underlying Swing file chooser
* creates and displays.
*/
listener = new WindowActivatedListener(JDialog.class);
Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.WINDOW_EVENT_MASK);
}
@After
public void cleanup() {
Toolkit.getDefaultToolkit().removeAWTEventListener(listener);
}
@Test
public void showOpenFileDialogHasOpenButton() throws Exception {
showOpenDialog(null, null);
// Can't use base class getButton method because JFileChooser has
// duplicate components
windowFixture.button(new GenericTypeMatcher<JButton>(JButton.class) {
@Override
protected boolean isMatching(JButton component) {
return component.isVisible() && "Open".equals(component.getText());
}
});
}
@Test
public void showSaveFileDialogHasSaveButton() throws Exception {
showSaveDialog(null, null);
// Can't use base class getButton method because JFileChooser has
// duplicate components
windowFixture.button(new GenericTypeMatcher<JButton>(JButton.class) {
@Override
protected boolean isMatching(JButton component) {
return component.isVisible() && "Save".equals(component.getText());
}
});
}
@Test
public void showOpenFileDisplaysSupportedFormats() throws Exception {
showOpenDialog(null, null);
JComboBoxFixture comboBox = getFileFormatComboBox();
final int N = comboBox.contents().length;
for (int i = 0; i < N; i++) {
JFileImageChooser.FormatFilter filter =
(JFileImageChooser.FormatFilter) comboBox.component().getItemAt(i);
String suffix = filter.getDefaultSuffix();
if (suffix.startsWith(".")) {
suffix = suffix.substring(1);
}
assertTrue("file suffix not a supported format: " + suffix,
readerFileSuffixes.contains(suffix));
}
}
@Test
public void showSaveFileDisplaysSupportedFormats() throws Exception {
showSaveDialog(null, null);
JComboBoxFixture comboBox = getFileFormatComboBox();
final int N = comboBox.contents().length;
for (int i = 0; i < N; i++) {
JFileImageChooser.FormatFilter filter =
(JFileImageChooser.FormatFilter) comboBox.component().getItemAt(i);
String suffix = filter.getDefaultSuffix();
if (suffix.startsWith(".")) {
suffix = suffix.substring(1);
}
assertTrue("file suffix not a supported format: " + suffix,
writerFileSuffixes.contains(suffix));
}
}
/**
* Calls {@linkplain JFileImageChooser#showOpenFile(java.awt.Component, java.io.File)}
* in a separate thread and confirms that the dialog is displayed.
*
* @param parent optional parent component
* @param workingDir optional initial working dir
*
* @return a future for the task being run in a separate thread
*/
private Future<File> showOpenDialog(final Component parent, final File workingDir)
throws Exception {
Future<File> future = executor.submit(
new Callable<File>() {
@Override
public File call() throws Exception {
return JFileImageChooser.showOpenFile(parent, workingDir);
}
});
assertComponentDisplayed(DIALOG_CLASS);
windowFixture = listener.getFixture(DISPLAY_TIMEOUT);
return future;
}
/**
* Calls {@linkplain JFileImageChooser#showSaveFile(java.awt.Component, java.io.File)}
* in a separate thread and confirms that the dialog is displayed.
*
* @param parent optional parent component
* @param workingDir optional initial working dir
*
* @return a future for the task being run in a separate thread
*/
private Future<File> showSaveDialog(final Component parent, final File workingDir)
throws Exception {
Future<File> future = executor.submit(
new Callable<File>() {
@Override
public File call() throws Exception {
return JFileImageChooser.showSaveFile(parent, workingDir);
}
});
assertComponentDisplayed(DIALOG_CLASS);
windowFixture = listener.getFixture(DISPLAY_TIMEOUT);
return future;
}
/**
* Gets the file format combo box.
*
* @return FEST fixture for the component
*/
private JComboBoxFixture getFileFormatComboBox() {
return windowFixture.comboBox(new GenericTypeMatcher<JComboBox>(JComboBox.class) {
@Override
protected boolean isMatching(JComboBox component) {
return component.getItemAt(0) instanceof JFileImageChooser.FormatFilter;
}
});
}
}