Author: tchemit Date: 2013-11-24 23:44:33 +0100 (Sun, 24 Nov 2013) New Revision: 1379 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/1379 Log: initial import of ifremer shared application Added: application/trunk/LICENSE.txt application/trunk/README.txt application/trunk/application-swing/ application/trunk/application-swing/LICENSE.txt application/trunk/application-swing/README.txt application/trunk/application-swing/pom.xml application/trunk/application-swing/src/ application/trunk/application-swing/src/main/ application/trunk/application-swing/src/main/java/ application/trunk/application-swing/src/main/java/fr/ application/trunk/application-swing/src/main/java/fr/ifremer/ application/trunk/application-swing/src/main/java/fr/ifremer/shared/ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/AbstractApplicationUIHandler.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUI.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUIContext.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/AbstractApplicationAction.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionEngine.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionException.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionFactory.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionSwingWorker.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUI.css application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUI.jaxx application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUIHandler.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUIModel.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationUIAction.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationAction.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEngine.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEvent.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionListener.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/AbstractApplicationTableModel.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/AbstractSelectTableAction.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/ColumnIdentifier.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToNextEditableCellAction.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToNextEditableRowAction.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToPreviousEditableCellAction.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToPreviousEditableRowAction.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationColorHighlighter.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationErrorHelper.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationExceptionHandler.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationUIUtil.java application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/CloseableUI.java application/trunk/application-swing/src/main/resources/ application/trunk/application-swing/src/main/resources/i18n/ application/trunk/application-swing/src/main/resources/i18n/application-swing_en_GB.properties application/trunk/application-swing/src/main/resources/i18n/application-swing_fr_FR.properties application/trunk/application/ application/trunk/application/LICENSE.txt application/trunk/application/README.txt application/trunk/application/pom.xml application/trunk/application/src/ application/trunk/application/src/main/ application/trunk/application/src/main/java/ application/trunk/application/src/main/java/fr/ application/trunk/application/src/main/java/fr/ifremer/ application/trunk/application/src/main/java/fr/ifremer/shared/ application/trunk/application/src/main/java/fr/ifremer/shared/application/ application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationBusinessException.java application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationConfiguration.java application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationContext.java application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationDataUtil.java application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationIOUtil.java application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationTechnicalException.java application/trunk/application/src/main/java/fr/ifremer/shared/application/type/ application/trunk/application/src/main/java/fr/ifremer/shared/application/type/ApplicationProgressionModel.java application/trunk/application/src/main/java/fr/ifremer/shared/application/type/CoordinateEditorType.java application/trunk/application/src/main/java/fr/ifremer/shared/application/type/WeightUnit.java application/trunk/application/src/main/resources/ application/trunk/application/src/main/resources/i18n/ application/trunk/application/src/main/resources/i18n/application_en_GB.properties application/trunk/application/src/main/resources/i18n/application_fr_FR.properties application/trunk/pom.xml Modified: application/trunk/ Property changes on: application/trunk ___________________________________________________________________ Added: svn:ignore + target .idea *.ipr *.iws *.iml Property changes on: application/trunk/LICENSE.txt ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Property changes on: application/trunk/README.txt ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Property changes on: application/trunk/application ___________________________________________________________________ Added: svn:ignore + target .idea *.ipr *.iws *.iml Property changes on: application/trunk/application/LICENSE.txt ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Property changes on: application/trunk/application/README.txt ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/pom.xml =================================================================== --- application/trunk/application/pom.xml (rev 0) +++ application/trunk/application/pom.xml 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + Ifremer shared :: Application + %% + Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/gpl-3.0.html>. + #L% + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>fr.ifremer.shared</groupId> + <artifactId>shared-pom</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + + <artifactId>application</artifactId> + <name>Ifremer shared :: Application</name> + + <properties> + + </properties> + + <dependencies> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-decorator</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-config</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-csv</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + <scope>test</scope> + <classifier>tests</classifier> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + </dependency> + + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-vfs2</artifactId> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-common</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.struts.xwork</groupId> + <artifactId>xwork-core</artifactId> + </dependency> + + <!-- Logging --> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-jcl</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + </dependency> + + </dependencies> + + <build> + <plugins> + + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>i18n-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>parserValidation</goal> + <goal>gen</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + +</project> Property changes on: application/trunk/application/pom.xml ___________________________________________________________________ Added: svn:mime-type + text/xml Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationBusinessException.java =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationBusinessException.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationBusinessException.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,51 @@ +package fr.ifremer.shared.application; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Application business exception, a such exeception should be shown to + * user in application. + * + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationBusinessException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ApplicationBusinessException(String message) { + super(message); + } + + public ApplicationBusinessException(String message, Throwable cause) { + super(message, cause); + } + + public ApplicationBusinessException(Throwable cause) { + super(cause); + } +} Property changes on: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationBusinessException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationConfiguration.java =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationConfiguration.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationConfiguration.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,54 @@ +package fr.ifremer.shared.application; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.nuiton.config.ApplicationConfig; +import org.nuiton.util.Version; + +/** + * Created on 11/24/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public abstract class ApplicationConfiguration { + + /** + * Delegate application config. + */ + protected final ApplicationConfig applicationConfig; + + public abstract String getApplicationName(); + + public abstract Version getVersion(); + + public ApplicationConfiguration(ApplicationConfig applicationConfig) { + this.applicationConfig = applicationConfig; + } + + public ApplicationConfig getApplicationConfig() { + return applicationConfig; + } +} Property changes on: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationConfiguration.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationContext.java =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationContext.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationContext.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,41 @@ +package fr.ifremer.shared.application; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Context of application, may contains config, data sources, ... + * <p/> + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public interface ApplicationContext { + + /** + * @return the application configuration + */ + ApplicationConfiguration getConfiguration(); +} Property changes on: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationContext.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationDataUtil.java =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationDataUtil.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationDataUtil.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,138 @@ +package fr.ifremer.shared.application; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.apache.commons.beanutils.PropertyUtils; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; + +import static org.nuiton.i18n.I18n._; + +/** + * Useful methods on data. + * <p/> + * TODO Needs some javadoc. + * <p/> + * Created on 11/24/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationDataUtil { + + public static final double EARTH_RADIUS = 6378288.0; + + private static DecimalFormatSymbols symbols; + + private static DecimalFormat decimalFormat; + + public static int computeDistanceInMeters(Float startLatitude, + Float startLongitude, + Float endLatitude, + Float endLongitude) { + + double sLat = startLatitude * Math.PI / 180.0; + double sLong = startLongitude * Math.PI / 180.0; + double eLat = endLatitude * Math.PI / 180.0; + double eLong = endLongitude * Math.PI / 180.0; + + Double d = EARTH_RADIUS * + (Math.PI / 2 - Math.asin(Math.sin(eLat) * Math.sin(sLat) + + Math.cos(eLong - sLong) * Math.cos(eLat) * Math.cos(sLat))); + return d.intValue(); + } + + public static String getDistanceInMilles(Float distance) { + String distanceText; + if (distance != null) { + Float distanceInMilles = distance / 1852; + distanceText = String.format("%.3f", distanceInMilles); + + } else { + distanceText = ""; + } + return distanceText; + } + + public static float getRoundedLengthStep(float lengthStep, boolean aroundUp) { + int intValue = (int) ((lengthStep + (aroundUp ? 0.001f : 0f)) * 10); + float result = intValue / 10f; + return result; + } + + public static void setProperty(Object bean, String property, Object value) { + Preconditions.checkNotNull(bean); + Preconditions.checkNotNull(property); + try { + PropertyUtils.setSimpleProperty(bean, property, value); + } catch (Exception e) { + throw new ApplicationTechnicalException(_("application.property.set.error", property, bean.getClass().getName()), e); + } + } + + public static Object getProperty(Object bean, String property) { + Preconditions.checkNotNull(bean); + Preconditions.checkNotNull(property); + try { + return PropertyUtils.getSimpleProperty(bean, property); + } catch (Exception e) { + throw new ApplicationTechnicalException(_("application.property.get.error", property, bean.getClass().getName()), e); + } + } + + public static DecimalFormatSymbols getDecimalFormatSymbols() { + if (symbols == null) { + symbols = new DecimalFormatSymbols(); + symbols.setDecimalSeparator('.'); + symbols.setGroupingSeparator(' '); + } + return symbols; + } + + public static DecimalFormat getDecimalFormat(int minDecimal, int maxDecimal) { + if (decimalFormat == null) { + decimalFormat = new DecimalFormat(); + decimalFormat.setDecimalFormatSymbols(getDecimalFormatSymbols()); + decimalFormat.setGroupingUsed(false); + } + decimalFormat.setMinimumFractionDigits(minDecimal); + decimalFormat.setMaximumFractionDigits(maxDecimal); + return decimalFormat; + } + + public static String getWeightStringValue(Float weight) { + String textValue; + if (weight != null) { + DecimalFormat weightDecimalFormat = getDecimalFormat(1, 3); + textValue = weightDecimalFormat.format(weight); + + } else { + textValue = ""; + } + return textValue; + } +} Property changes on: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationDataUtil.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationIOUtil.java =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationIOUtil.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationIOUtil.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,256 @@ +package fr.ifremer.shared.application; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Charsets; +import com.google.common.io.Files; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.FileSelector; +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.commons.vfs2.FileType; +import org.apache.commons.vfs2.VFS; +import org.nuiton.util.ZipUtil; + +import java.io.Closeable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.List; +import java.util.UUID; + +import static org.nuiton.i18n.I18n._; + +/** + * Useful methods around IO, all method errors are boxes a + * {@link ApplicationTechnicalException}. + * <p/> + * Created on 11/24/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationIOUtil { + + protected ApplicationIOUtil() { + // no instance + } + + public static void close(Closeable toClose, String errorMessage) { + + try { + toClose.close(); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void zip(File source, File archiveFile, String errorMessage) { + try { + ZipUtil.compress(archiveFile, source); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void zip(File source, File archiveFile, List<File> files, String errorMessage) { + try { + ZipUtil.compressFiles(archiveFile, source, files); + } catch (IOException e) { + throw new ApplicationTechnicalException(_(errorMessage, archiveFile), e); + } + } + + public static FileObject resolveFile(String file, String errorMessage) { + try { + FileSystemManager manager = VFS.getManager(); + FileObject targetObject = manager.resolveFile(file); + return targetObject; + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static FileObject[] getChildren(FileObject objectFile, String errorMessage) { + try { + return objectFile.getChildren(); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static FileObject getChild(FileObject objectFile, String name, String errorMessage) { + try { + return objectFile.getChild(name); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + + public static FileType getType(FileObject objectFile, String errorMessage) { + try { + return objectFile.getType(); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void explode(FileObject archiveFile, + File target, + FileSelector fileSelector, String errorMessage) { + try { + FileSystemManager manager = VFS.getManager(); + FileObject targetObject = manager.toFileObject(target); + targetObject.copyFrom(archiveFile, fileSelector); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void forceMkdir(File dir, String errorMessage) { + try { + FileUtils.forceMkdir(dir); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void cleanDirectory(File dir, String errorMessage) { + try { + FileUtils.cleanDirectory(dir); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void deleteDirectory(File dir, String errorMessage) { + try { + FileUtils.deleteDirectory(dir); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void forceDeleteOnExit(File dir, String errorMessage) { + try { + FileUtils.forceDeleteOnExit(dir); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void copyDirectory(File source, File target, String errorMessage) { + try { + FileUtils.copyDirectory(source, target); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void copyFileToDirectory(File source, File target, String errorMessage) { + try { + FileUtils.copyFileToDirectory(source, target); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void copyFile(File source, File target, String errorMessage) { + try { + FileUtils.copyFile(source, target); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void deleteFile(File file, String errorMessage) { + try { + FileUtils.forceDelete(file); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static String getBaseName(String file) { + return FilenameUtils.getBaseName(file); + } + + public static String getExtension(String file) { + return FilenameUtils.getExtension(file); + } + + public static Reader newReader(File file, String errorMessage) { + try { + return Files.newReader(file, Charsets.UTF_8); + + } catch (FileNotFoundException e) { + throw new ApplicationTechnicalException(_(errorMessage, file), e); + } + } + + public static Writer newWriter(File file, String errorMessage + ) { + try { + return Files.newWriter(file, Charsets.UTF_8); + + } catch (FileNotFoundException e) { + throw new ApplicationTechnicalException(_(errorMessage, file), e); + } + } + + public static File explodeZip(File rootDirectory, + File file, + String errorMessage) { + File tempDir = new File(rootDirectory, UUID.randomUUID().toString()); + try { + ZipUtil.uncompress(file, tempDir); + } catch (IOException e) { + throw new ApplicationTechnicalException(_(errorMessage, file), e); + } + return tempDir; + } + + public static String readContent(File file, String errorMessage) { + + try { + return Files.readFirstLine(file, Charsets.UTF_8); + + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } + + public static void writeContent(File file, String content, String errorMessage) { + try { + FileUtils.write(file, content, Charsets.UTF_8); + } catch (IOException e) { + throw new ApplicationTechnicalException(errorMessage, e); + } + } +} Property changes on: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationIOUtil.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationTechnicalException.java =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationTechnicalException.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationTechnicalException.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,50 @@ +package fr.ifremer.shared.application; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Application Technical exception. + * + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationTechnicalException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ApplicationTechnicalException(String message) { + super(message); + } + + public ApplicationTechnicalException(String message, Throwable cause) { + super(message, cause); + } + + public ApplicationTechnicalException(Throwable cause) { + super(cause); + } +} Property changes on: application/trunk/application/src/main/java/fr/ifremer/shared/application/ApplicationTechnicalException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: application/trunk/application/src/main/java/fr/ifremer/shared/application/type/ApplicationProgressionModel.java (from rev 1377, trunk/tutti-persistence/src/main/java/fr/ifremer/tutti/persistence/ProgressionModel.java) =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/type/ApplicationProgressionModel.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/type/ApplicationProgressionModel.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,115 @@ +package fr.ifremer.shared.application.type; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +/** + * Simple model for a progression long task. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationProgressionModel extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_TOTAL = "total"; + + public static final String PROPERTY_CURRENT = "current"; + + public static final String PROPERTY_RATE = "rate"; + + public static final String PROPERTY_MESSAGE = "message"; + + protected int total; + + protected int current; + + protected float rate; + + protected String message; + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + Object oldValue = getTotal(); + this.total = total; + firePropertyChange(PROPERTY_TOTAL, oldValue, total); + setCurrent(0); + } + + public void adaptTotal(int total) { + int current = getCurrent(); + setTotal(total); + increments(current); + Object oldValue = getTotal(); + this.total = total; + firePropertyChange(PROPERTY_TOTAL, oldValue, total); + setCurrent(current); + } + + public int getCurrent() { + return current; + } + + public void setCurrent(int current) { + Object oldValue = getCurrent(); + this.current = current; + firePropertyChange(PROPERTY_CURRENT, oldValue, current); + } + + public void increments(int nb) { + setCurrent(current + nb); + setRate(getCurrent() / getTotal()); + } + + public float getRate() { + return rate; + } + + public void setRate(float rate) { + Object oldValue = getRate(); + this.rate = rate; + firePropertyChange(PROPERTY_RATE, oldValue, rate); + } + + public String getMessage() { + return message; + } + + public void increments(String message) { + increments(1); + setMessage(message); + } + + public void setMessage(String message) { + Object oldValue = getMessage(); + this.message = message; + firePropertyChange(PROPERTY_MESSAGE, oldValue, message); + } +} Added: application/trunk/application/src/main/java/fr/ifremer/shared/application/type/CoordinateEditorType.java =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/type/CoordinateEditorType.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/type/CoordinateEditorType.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,48 @@ +package fr.ifremer.shared.application.type; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Coordinate formats. + * <p/> + * Created on 11/24/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public enum CoordinateEditorType { + /** + * Degre-Minute-second. + */ + DMS, + /** + * Degre decimal. + */ + DD, + /** + * Degre minute decimal + */ + DMD +} Property changes on: application/trunk/application/src/main/java/fr/ifremer/shared/application/type/CoordinateEditorType.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/java/fr/ifremer/shared/application/type/WeightUnit.java =================================================================== --- application/trunk/application/src/main/java/fr/ifremer/shared/application/type/WeightUnit.java (rev 0) +++ application/trunk/application/src/main/java/fr/ifremer/shared/application/type/WeightUnit.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,118 @@ +package fr.ifremer.shared.application.type; + +/* + * #%L + * Ifremer shared :: Application + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; + +/** + * Different types of weight unit. + * <p/> + * Created on 09/22/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public enum WeightUnit { + + G(n_("application.common.unit.g"), n_("application.common.unit.short.g"), 1, "\\d{0,6}(\\.\\d{0,1})?") { + @Override + public Float fromEntity(Float weight) { + return weight == null ? null : weight * 1000; + } + + @Override + public Float toEntity(Float weight) { + return weight == null ? null : weight / 1000.0f; + } + }, + KG(n_("application.common.unit.kg"), n_("application.common.unit.short.kg"), 4, "\\d{0,6}(\\.\\d{0,4})?") { + @Override + public Float fromEntity(Float weight) { + return weight; + } + + @Override + public Float toEntity(Float weight) { + return weight; + } + }; + + private final String i18nShortKey; + + private final String i18nKey; + + private final int numberDigits; + + private final String numberEditorPattern; + + WeightUnit(String i18nKey, String i18nShortKey, int numberDigits, String numberEditorPattern) { + this.i18nKey = i18nKey; + this.i18nShortKey = i18nShortKey; + this.numberDigits = numberDigits; + this.numberEditorPattern = numberEditorPattern; + } + + public String getLabel() { + return _(i18nKey); + } + + public String getShortLabel() { + return _(i18nShortKey); + } + + public int getNumberDigits() { + return numberDigits; + } + + public String getNumberEditorPattern() { + return numberEditorPattern; + } + + /** + * Transform the given {@code weight} coming from db to ui. + * + * @param weight weigth to transform + * @return the ui representation of the given {@code weight}. + */ + public abstract Float fromEntity(Float weight); + + /** + * Transform the given {@code weight} coming from ui to db. + * + * @param weight weigth to transform + * @return the db representation of the given {@code weight}. + */ + public abstract Float toEntity(Float weight); + + public String decorateLabel(String label) { + return String.format("%s (%s)", label, getShortLabel()); + } + + public String decorateTip(String tip) { + String unit = _("application.common.unit"); + return String.format("%s (%s %s)", tip, unit, getLabel()); + } +} \ No newline at end of file Property changes on: application/trunk/application/src/main/java/fr/ifremer/shared/application/type/WeightUnit.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/resources/i18n/application_en_GB.properties =================================================================== --- application/trunk/application/src/main/resources/i18n/application_en_GB.properties (rev 0) +++ application/trunk/application/src/main/resources/i18n/application_en_GB.properties 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,7 @@ +application.common.unit=Unit +application.common.unit.g=Gram +application.common.unit.kg=Kilogram +application.common.unit.short.g=g +application.common.unit.short.kg=kg +application.property.get.error= +application.property.set.error= Property changes on: application/trunk/application/src/main/resources/i18n/application_en_GB.properties ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application/src/main/resources/i18n/application_fr_FR.properties =================================================================== --- application/trunk/application/src/main/resources/i18n/application_fr_FR.properties (rev 0) +++ application/trunk/application/src/main/resources/i18n/application_fr_FR.properties 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,7 @@ +application.common.unit=Unité +application.common.unit.g=Gramme +application.common.unit.kg=Kilogramme +application.common.unit.short.g=g +application.common.unit.short.kg=kg +application.property.get.error=Propriété %1s non trouvée sur l'objet de type %2s +application.property.set.error=Propriété %1s non trouvée sur l'objet de type %2s Property changes on: application/trunk/application/src/main/resources/i18n/application_fr_FR.properties ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Property changes on: application/trunk/application-swing ___________________________________________________________________ Added: svn:ignore + target .idea *.ipr *.iws *.iml Property changes on: application/trunk/application-swing/LICENSE.txt ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Property changes on: application/trunk/application-swing/README.txt ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application-swing/pom.xml =================================================================== --- application/trunk/application-swing/pom.xml (rev 0) +++ application/trunk/application-swing/pom.xml 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,244 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + Ifremer shared :: Application Swing + %% + Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/gpl-3.0.html>. + #L% + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>fr.ifremer.shared</groupId> + <artifactId>shared-pom</artifactId> + <version>1.0-SNAPSHOT</version> + </parent> + + <artifactId>application-swing</artifactId> + <name>Ifremer shared :: Application Swing</name> + + <properties> + + <!-- jaxx configuration --> + <jaxx.addProjectClassPath>true</jaxx.addProjectClassPath> + <jaxx.addSourcesToClassPath>true</jaxx.addSourcesToClassPath> + <jaxx.defaultErrorUIFQN> + jaxx.runtime.validator.swing.ui.ImageValidationUI + </jaxx.defaultErrorUIFQN> + <!--<jaxx.useUIManagerForIcon>true</jaxx.useUIManagerForIcon>--> + <jaxx.generateHelp>true</jaxx.generateHelp> + <jaxx.generateSearch>false</jaxx.generateSearch> + <jaxx.autoImportCss>true</jaxx.autoImportCss> + <jaxx.autoRecurseInCss>false</jaxx.autoRecurseInCss> + + <!-- Post Release configuration --> + <skipPostRelease>false</skipPostRelease> + + </properties> + + <dependencies> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>application</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-config</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-updater</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-decorator</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-csv</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <!-- used forApplicationUpdater --> + <dependency> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + <scope>test</scope> + <classifier>tests</classifier> + </dependency> + + <!-- librairie Jaxx --> + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-runtime</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-config</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-validator</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-widgets</artifactId> + </dependency> + + <!-- swing widgets --> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-core</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-common</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-autocomplete</artifactId> + </dependency> + + <!-- Logging --> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-jcl</artifactId> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + </dependencies> + + <build> + + <plugins> + + <plugin> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>i18n-maven-plugin</artifactId> + <executions> + <execution> + <id>scan-sources</id> + <!--configuration> + <entries> + <entry> + <basedir>${maven.gen.dir}/java/</basedir> + </entry> + </entries> + </configuration--> + <goals> + <goal>parserJava</goal> + <goal>parserValidation</goal> + <goal>gen</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + +</project> Property changes on: application/trunk/application-swing/pom.xml ___________________________________________________________________ Added: svn:mime-type + text/xml Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/AbstractApplicationUIHandler.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/AbstractApplicationUIHandler.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/AbstractApplicationUIHandler.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,1070 @@ +package fr.ifremer.shared.application.swing; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import fr.ifremer.shared.application.ApplicationDataUtil; +import fr.ifremer.shared.application.swing.table.ColumnIdentifier; +import fr.ifremer.shared.application.type.WeightUnit; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.swing.JAXXWidgetUtil; +import jaxx.runtime.swing.editor.FileEditor; +import jaxx.runtime.swing.editor.NumberEditor; +import jaxx.runtime.swing.editor.SimpleTimeEditor; +import jaxx.runtime.swing.editor.bean.BeanDoubleList; +import jaxx.runtime.swing.editor.bean.BeanFilterableComboBox; +import jaxx.runtime.swing.editor.bean.BeanUIUtil; +import jaxx.runtime.swing.editor.cell.NumberCellEditor; +import jaxx.runtime.swing.editor.gis.DmdCoordinateEditor; +import jaxx.runtime.swing.editor.gis.DmsCoordinateEditor; +import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import jaxx.runtime.swing.renderer.DecoratorTableCellRenderer; +import jaxx.runtime.validator.swing.SwingValidator; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXDatePicker; +import org.jdesktop.swingx.JXTable; +import org.jdesktop.swingx.autocomplete.ComboBoxCellEditor; +import org.jdesktop.swingx.autocomplete.ObjectToStringConverter; +import org.jdesktop.swingx.table.TableColumnExt; +import org.nuiton.decorator.Decorator; +import org.nuiton.decorator.JXPathDecorator; + +import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JSpinner; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.JViewport; +import javax.swing.ListCellRenderer; +import javax.swing.ListSelectionModel; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.LineBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumnModel; +import javax.swing.text.JTextComponent; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.ItemEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.Serializable; +import java.text.ParseException; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n._; + +/** + * Handler of any ui. + * <p/> + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public abstract class AbstractApplicationUIHandler<M, UI extends ApplicationUI<M, ?>> { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(AbstractApplicationUIHandler.class); + + public abstract void beforeInitUI(); + + public abstract void afterInitUI(); + + public abstract void onCloseUI(); + + public abstract SwingValidator<M> getValidator(); + + public abstract Component getTopestUI(); + + public abstract <E> Decorator<E> getDecorator(Class<E> beanType, String decoratorContext); + + /** + * Hook to prepare popup just before showing it. + * <p/> + * The right place to update actions accessibility; a quite better design + * than trying to update each time something change in the table... + * + * @param modelRowIndex selected row index (or lowest selected one) + * @param modelColumnIndex selected column index + * @since 2.6 + */ + protected void beforeOpenPopup(int modelRowIndex, int modelColumnIndex) { + // by default do nothing + } + + /** + * Global application context. + */ + private final ApplicationUIContext context; + + /** + * UI handled. + */ + protected final UI ui; + + protected AbstractApplicationUIHandler(ApplicationUIContext context, UI ui) { + this.context = context; + this.ui = ui; + } + + //------------------------------------------------------------------------// + //-- Public methods --// + //------------------------------------------------------------------------// + + public DefaultComboBoxModel newComboModel(Object... items) { + return new DefaultComboBoxModel(items); + } + + public final M getModel() { + return ui.getModel(); + } + + public final UI getUI() { + return ui; + } + + public ApplicationUIContext getContext() { + return context; + } + + public void setText(KeyEvent event, String property) { + JTextComponent field = (JTextComponent) event.getSource(); + String value = field.getText(); + ApplicationDataUtil.setProperty(getModel(), property, value); + } + + public void setFile(ActionEvent event, String property) { + FileEditor field = (FileEditor) event.getSource(); + File value = field.getSelectedFile(); + ApplicationDataUtil.setProperty(getModel(), property, value); + } + + public void setBoolean(ItemEvent event, String property) { + boolean value = event.getStateChange() == ItemEvent.SELECTED; + ApplicationDataUtil.setProperty(getModel(), property, value); + } + + public void setDate(ActionEvent event, String property) { + JXDatePicker field = (JXDatePicker) event.getSource(); + Date value = field.getDate(); + ApplicationDataUtil.setProperty(getModel(), property, value); + } + + public void selectListData(ListSelectionEvent event, String property) { + if (!event.getValueIsAdjusting()) { + JList list = (JList) event.getSource(); + ListSelectionModel selectionModel = list.getSelectionModel(); + + selectionModel.setValueIsAdjusting(true); + try { + List selectedList = Lists.newLinkedList(); + + for (int index : list.getSelectedIndices()) { + Object o = list.getModel().getElementAt(index); + selectedList.add(o); + } + ApplicationDataUtil.setProperty(getModel(), property, selectedList); + } finally { + selectionModel.setValueIsAdjusting(false); + } + } + } + +// public void openDialog(TuttiUI dialogContent, +// String title, Dimension dim) { +// Component topestUI = getTopestUI(); +// +// JDialog result; +// if (topestUI instanceof Frame) { +// result = new JDialog((Frame) topestUI, title, true); +// } else { +// result = new JDialog((Dialog) topestUI, title, true); +// } +// +// result.add((Component) dialogContent); +// result.setResizable(true); +// +// result.setSize(dim); +// +// final AbstractTuttiUIHandler handler = dialogContent.getHandler(); +// +// if (handler instanceof Cancelable) { +// +// // add a auto-close action +// JRootPane rootPane = result.getRootPane(); +// +// KeyStroke shortcutClosePopup = getConfig().getShortcutClosePopup(); +// +// rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( +// shortcutClosePopup, "close"); +// rootPane.getActionMap().put("close", new AbstractAction() { +// private static final long serialVersionUID = 1L; +// +// @Override +// public void actionPerformed(ActionEvent e) { +// ((Cancelable) handler).cancel(); +// } +// }); +// } +// +// result.addWindowListener(new WindowAdapter() { +// +// @Override +// public void windowClosed(WindowEvent e) { +// Component ui = (Component) e.getSource(); +// if (log.isDebugEnabled()) { +// log.debug("Destroy ui " + ui); +// } +// JAXXUtil.destroy(ui); +// } +// }); +// SwingUtil.center(getContext().getMainUI(), result); +// result.setVisible(true); +// } +// +// public void closeDialog(ApplicationUI ui) { +// SwingUtil.getParentContainer(ui, JDialog.class).setVisible(false); +// } + + public static final String CONFIRMATION_FORMAT = "<html>%s<hr/><br/>%s</html>"; + + public int askSaveBeforeLeaving(String message) { + String htmlMessage = String.format( + CONFIRMATION_FORMAT, + message, + _("application.common.askSaveBeforeLeaving.help")); + int result = JOptionPane.showConfirmDialog( + getTopestUI(), + htmlMessage, + _("application.common.askSaveBeforeLeaving.title"), + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE); + return result; + } + + public boolean askCancelEditBeforeLeaving(String message) { + String htmlMessage = String.format( + CONFIRMATION_FORMAT, + message, + _("application.common.askCancelEditBeforeLeaving.help")); + int i = JOptionPane.showConfirmDialog( + getTopestUI(), + htmlMessage, + _("application.common.askCancelEditBeforeLeaving.title"), + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE); + + boolean result = i == JOptionPane.OK_OPTION; + return result; + } + + public void showSuccessMessage(String title, String message) { + + Component topestUI = getTopestUI(); + boolean alwaysOnTop = false; + + if (topestUI instanceof JDialog) { + alwaysOnTop = ((JDialog) topestUI).isAlwaysOnTop(); + } + + if (alwaysOnTop) { + ((JDialog) topestUI).setAlwaysOnTop(false); + } + try { + + JOptionPane.showMessageDialog( + topestUI, + message, + title, + JOptionPane.INFORMATION_MESSAGE, + UIManager.getIcon("info") + ); + } finally { + if (alwaysOnTop) { + ((JDialog) topestUI).setAlwaysOnTop(true); + } + } + } + + +// public void clearValidators() { +// MainUI main = context.getMainUI(); +// Preconditions.checkNotNull( +// main, "No mainUI registred in application context"); +// MainUIHandler handler = main.getHandler(); +// handler.clearValidators(); +// } + + public void autoSelectRowInTable(MouseEvent e, JPopupMenu popup) { + + boolean rightClick = SwingUtilities.isRightMouseButton(e); + + if (rightClick || SwingUtilities.isLeftMouseButton(e)) { + + // get the coordinates of the mouse click + Point p = e.getPoint(); + + JXTable source = (JXTable) e.getSource(); + + int[] selectedRows = source.getSelectedRows(); + int[] selectedColumns = source.getSelectedColumns(); + + // get the row index at this point + int rowIndex = source.rowAtPoint(p); + + // get the column index at this point + int columnIndex = source.columnAtPoint(p); + + if (log.isDebugEnabled()) { + log.debug("At point [" + p + "] found Row " + rowIndex + ", Column " + columnIndex); + } + + boolean canContinue = true; + + if (source.isEditing()) { + + // stop editing + boolean stopEdit = source.getCellEditor().stopCellEditing(); + if (!stopEdit) { + if (log.isWarnEnabled()) { + log.warn("Could not stop edit cell..."); + } + canContinue = false; + } + } + + if (canContinue) { + + // select row (could empty selection) + if (rowIndex == -1) { + source.clearSelection(); + } else if (!ArrayUtils.contains(selectedRows, rowIndex)) { + if (ListSelectionModel.MULTIPLE_INTERVAL_SELECTION == source.getSelectionMode()) { + // add to selection + source.addRowSelectionInterval(rowIndex, rowIndex); + } else { + // set selection + source.setRowSelectionInterval(rowIndex, rowIndex); + } + } + + // select column (could empty selection) + if (columnIndex == -1) { + source.clearSelection(); + } else if (!ArrayUtils.contains(selectedColumns, columnIndex)) { + source.setColumnSelectionInterval(columnIndex, columnIndex); + } + + if (rightClick) { + + // use now model coordinate + int modelRowIndex = source.convertRowIndexToModel(rowIndex); + int modelColumnIndex = source.convertColumnIndexToModel(columnIndex); + + beforeOpenPopup(modelRowIndex, modelColumnIndex); + + // on right click show popup + popup.show(source, e.getX(), e.getY()); + } + } + } + } + + public void openRowMenu(KeyEvent e, JPopupMenu popup) { + + if (e.getKeyCode() == KeyEvent.VK_CONTEXT_MENU) { + + JXTable source = (JXTable) e.getSource(); + + // get the lowest selected row + int[] selectedRows = source.getSelectedRows(); + int lowestRow = -1; + for (int row : selectedRows) { + lowestRow = Math.max(lowestRow, row); + } + // get the selected column + int selectedColumn = source.getSelectedColumn(); + Rectangle r = source.getCellRect(lowestRow, selectedColumn, true); + + // get the point in the middle lower of the cell + Point p = new Point(r.x + r.width / 2, r.y + r.height); + + if (log.isDebugEnabled()) { + log.debug("Row " + lowestRow + " found t point [" + p + "]"); + } + + boolean canContinue = true; + + if (source.isEditing()) { + + // stop editing + boolean stopEdit = source.getCellEditor().stopCellEditing(); + if (!stopEdit) { + if (log.isWarnEnabled()) { + log.warn("Could not stop edit cell..."); + } + canContinue = false; + } + } + + if (canContinue) { + + // use now model coordinate + int rowIndex = source.convertRowIndexToModel(lowestRow); + int columnIndex = source.convertColumnIndexToModel(selectedColumn); + beforeOpenPopup(rowIndex, columnIndex); + + popup.show(source, p.x, p.y); + } + } + } + + //------------------------------------------------------------------------// + //-- Init methods --// + //------------------------------------------------------------------------// + + protected void initUIComponent(Object component) { + if (component instanceof NumberEditor) { + + initNumberEditor((NumberEditor) component); + } else if (component instanceof JXDatePicker) { + + initDatePicker((JXDatePicker) component); + } else if (component instanceof SimpleTimeEditor) { + + initTimeEditor((SimpleTimeEditor) component); + } else if (component instanceof JLabel) { + + initLabel((JLabel) component); + } else if (component instanceof JTextField) { + + initTextField((JTextField) component); + } else if (component instanceof AbstractButton) { + + initButton((AbstractButton) component); + } else if (component instanceof JScrollPane) { + + initScrollPane((JScrollPane) component); + } else if (component instanceof DmsCoordinateEditor) { + + initCoordinateDMSEditor((DmsCoordinateEditor) component); + } else if (component instanceof DmdCoordinateEditor) { + + initCoordinateDMDEditor((DmdCoordinateEditor) component); + } + } + + protected void initUI(UI ui) { + + for (Map.Entry<String, Object> entry : ui.get$objectMap().entrySet()) { + Object component = entry.getValue(); + initUIComponent(component); + } + + ((Component) ui).addHierarchyListener(new HierarchyListener() { + @Override + public void hierarchyChanged(HierarchyEvent e) { + JComponent component = getComponentToFocus(); + if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) > 0 + && e.getChanged().isShowing() + && component != null) { + component.requestFocus(); + } + } + }); + } + + protected abstract JComponent getComponentToFocus(); + + protected void initTextField(JTextField jTextField) { +// Boolean computed = (Boolean) jTextField.getClientProperty("computed"); +// if (computed != null && computed) { +// Font font = jTextField.getFont().deriveFont(Font.ITALIC); +// jTextField.setFont(font); +// jTextField.setEditable(false); +// jTextField.setEnabled(false); +// jTextField.setDisabledTextColor(getConfig().getColorComputedWeights()); +// } + if (isAutoSelectOnFocus(jTextField)) { + addAutoSelectOnFocus(jTextField); + } + } + + protected void initLabel(JLabel jLabel) { + Boolean strongStyle = (Boolean) jLabel.getClientProperty("strongStyle"); + Boolean italicStyle = (Boolean) jLabel.getClientProperty("italicStyle"); + Font font = jLabel.getFont(); + int style = font.getStyle(); + if (strongStyle != null && strongStyle) { + style |= Font.BOLD; + } + if (italicStyle != null && italicStyle) { + style |= Font.ITALIC; + } + jLabel.setFont(font.deriveFont(style)); + +// WeightUnit weightUnit = (WeightUnit) jLabel.getClientProperty("addWeightUnit"); +// if (weightUnit != null) { +// String text = weightUnit.decorateLabel(jLabel.getText()); +// jLabel.setText(text); +// +// String tip = weightUnit.decorateTip(jLabel.getToolTipText()); +// jLabel.setToolTipText(tip); +// +// Component labelFor = jLabel.getLabelFor(); +// if (labelFor instanceof TuttiComputedOrNotDataEditor) { +// +// // set also the number of digits (4 for kg, 1 for g) +// TuttiComputedOrNotDataEditor editor = (TuttiComputedOrNotDataEditor) labelFor; +// editor.setNumberPattern(weightUnit.getNumberEditorPattern()); +// editor.setDecimalNumber(weightUnit.getNumberDigits()); +// } else if (labelFor instanceof NumberEditor) { +// +// // set also the number of digits (4 for kg, 1 for g) +// NumberEditor editor = (NumberEditor) labelFor; +// editor.setNumberPattern(weightUnit.getNumberEditorPattern()); +// } +// } + } + +// protected void initButtonAttachment(ButtonAttachment component) { +// +// component.init(); +// } + + protected void initButton(AbstractButton abstractButton) { + + Class actionName = (Class) abstractButton.getClientProperty("applicationAction"); + if (actionName != null) { + Action action = getContext().getActionFactory().createUIAction(this, abstractButton, actionName); + abstractButton.setAction(action); + } + } + + /** + * Prépare un component de choix d'entités pour un type d'entité donné et + * pour un service de persistance donné. + * + * @param comboBox le component graphique à initialiser + */ + protected <E> void initBeanFilterableComboBox( + BeanFilterableComboBox<E> comboBox, + List<E> data, + E selectedData) { + + initBeanFilterableComboBox(comboBox, data, selectedData, null); + } + + protected <E> void initBeanFilterableComboBox( + BeanFilterableComboBox<E> comboBox, + List<E> data, + E selectedData, + String decoratorContext) { + + Preconditions.checkNotNull(comboBox, "No comboBox!"); + + Class<E> beanType = comboBox.getBeanType(); + + Preconditions.checkNotNull(beanType, "No beanType on the combobox!"); + + Decorator<E> decorator = getDecorator(beanType, decoratorContext); + + if (data == null) { + data = Lists.newArrayList(); + } + + if (log.isDebugEnabled()) { + log.debug("entity comboBox list [" + beanType.getName() + "] : " + + (data == null ? 0 : data.size())); + } + + comboBox.setI18nPrefix(context.getI18nPrefix()); + + // add data list to combo box + comboBox.init((JXPathDecorator<E>) decorator, data); + + comboBox.setSelectedItem(selectedData); + + if (log.isDebugEnabled()) { + log.debug("combo [" + beanType.getName() + "] : " + + comboBox.getData().size()); + } + } + + /** + * Prépare un component de choix d'entités pour un type d'entité donné et + * pour un service de persistance donné. + * + * @param list le component graphique à initialiser + * @param data la liste des données à mettre dans la liste de gauche + * @param selectedData la liste des données à mettre dans la liste de droite + */ + protected <E> void initBeanList( + BeanDoubleList<E> list, + List<E> data, + List<E> selectedData, + Decorator<E> selectedDecorator) { + + Preconditions.checkNotNull(list, "No list!"); + + Class<E> beanType = list.getBeanType(); + Preconditions.checkNotNull(beanType, "No beanType on the double list!"); + + Decorator<E> decorator = getDecorator(beanType, null); + + if (log.isDebugEnabled()) { + log.debug("entity list [" + beanType.getName() + "] : " + + (data == null ? 0 : data.size())); + } + + list.setI18nPrefix(context.getI18nPrefix()); + + // add data list to combo box + list.init((JXPathDecorator<E>) decorator, + (JXPathDecorator<E>) selectedDecorator, + data, + selectedData); + + if (log.isDebugEnabled()) { + log.debug("Jlist [" + beanType.getName() + "] : " + + list.getUniverseList().getModel().getSize()); + } + } + + /** + * Prépare un component de choix d'entités pour un type d'entité donné et + * pour un service de persistance donné. + * + * @param list le component graphique à initialiser + * @param data la liste des données à mettre dans la liste de gauche + * @param selectedData la liste des données à mettre dans la liste de droite + */ + protected <E> void initBeanList( + BeanDoubleList<E> list, + List<E> data, + List<E> selectedData) { + + initBeanList(list, data, selectedData, null); + } + + protected void initNumberEditor(NumberEditor editor) { + if (log.isDebugEnabled()) { + log.debug("init number editor " + editor.getName()); + } + editor.init(); + + // Force binding if value is already in model + Number model = editor.getModel(); + if (model != null) { + editor.setModel(null); + editor.setModel(model); + } + + if (isAutoSelectOnFocus(editor)) { + + addAutoSelectOnFocus(editor.getTextField()); + } + } + + protected void initTimeEditor(SimpleTimeEditor editor) { + if (log.isDebugEnabled()) { + log.debug("init time editor " + editor.getName() + + " for property " + editor.getModel().getProperty()); + } + editor.init(); + + if (isAutoSelectOnFocus(editor)) { + addAutoSelectOnFocus(((JSpinner.DefaultEditor) editor.getHour().getEditor()).getTextField()); + addAutoSelectOnFocus(((JSpinner.DefaultEditor) editor.getMinute().getEditor()).getTextField()); + } + } + + protected void initCoordinateDMSEditor(DmsCoordinateEditor editor) { + editor.init(); + } + + protected void initCoordinateDMDEditor(DmdCoordinateEditor editor) { + editor.init(); + } + + protected void initDatePicker(final JXDatePicker picker) { + + if (log.isDebugEnabled()) { + log.debug("disable JXDatePicker editor" + picker.getName()); + } + String dateFormat = context.getDateFormat(); + picker.setFormats(dateFormat); + picker.setToolTipText(_("application.common.datefield.tip", dateFormat)); + picker.getEditor().addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + try { + picker.commitEdit(); + + } catch (ParseException ex) { + if (log.isDebugEnabled()) { + log.debug("format error", ex); + } + picker.requestFocus(); + } + } + }); + + if (isAutoSelectOnFocus(picker)) { + addAutoSelectOnFocus(picker.getEditor()); + } + } + + protected void initScrollPane(JScrollPane scrollPane) { + Boolean onlyVerticalScrollable = (Boolean) scrollPane.getClientProperty("onlyVerticalScrollable"); + if (onlyVerticalScrollable != null && onlyVerticalScrollable) { + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + + final JViewport viewport = scrollPane.getViewport(); + viewport.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + Dimension newDimension = new Dimension(viewport.getExtentSize().width, + viewport.getViewSize().height); + viewport.setViewSize(newDimension); + } + }); + } + } + + protected boolean isAutoSelectOnFocus(JComponent comp) { + Object selectOnFocus = comp.getClientProperty("selectOnFocus"); + return selectOnFocus != null && Boolean.valueOf(selectOnFocus.toString()); + } + + protected void addAutoSelectOnFocus(JTextField jTextField) { + jTextField.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(final FocusEvent e) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JTextField source = (JTextField) e.getSource(); + source.selectAll(); + } + }); + + } + }); + } + + protected boolean quitScreen(boolean modelIsValid, + boolean modelIsModify, + String askGiveUpMessage, + String askSaveMessage, + Action saveAction) { + boolean result; + + if (!modelIsValid) { + + // model is not valid + // ask user to qui or not + result = askCancelEditBeforeLeaving(askGiveUpMessage); + + } else if (modelIsModify) { + + // something is modify ask user what to do + int answer = askSaveBeforeLeaving(askSaveMessage); + switch (answer) { + case JOptionPane.YES_OPTION: + + // ok save + saveAction.actionPerformed(null); + result = true; + break; + case JOptionPane.NO_OPTION: + + // do not save but can still quit the screen (so nothing to do) + result = true; + break; + default: + // do not save and stay here (so nothing to do) + result = false; + + } + } else { + + // model is valid and not modify, can safely quit screen + result = true; + } + return result; + } + + //------------------------------------------------------------------------// + //-- Decorator API --// + //------------------------------------------------------------------------// + + protected String decorate(Serializable object) { + return decorate(object, null); + } + + protected String decorate(Serializable object, String context) { + String result = ""; + if (object != null) { + result = getDecorator(object.getClass(), context).toString(object); + } + return result; + } + + //------------------------------------------------------------------------// + //-- List API --// + //------------------------------------------------------------------------// + + protected <O> ListCellRenderer newListCellRender(Class<O> type) { + + return newListCellRender(type, null); + } + + protected <O> ListCellRenderer newListCellRender(Class<O> type, String name) { + + Decorator<O> decorator = getDecorator(type, name); + return newListCellRender(decorator); + } + + protected <O> ListCellRenderer newListCellRender(Decorator<O> decorator) { + + Preconditions.checkNotNull(decorator); + + ListCellRenderer result = new DecoratorListCellRenderer(decorator); + return result; + } + + protected <B> void changeValidatorContext(String newContext, + SwingValidator<B> validator) { + B bean = validator.getBean(); + validator.setContext(newContext); + validator.setBean(bean); + } + + //------------------------------------------------------------------------// + //-- Table API --// + //------------------------------------------------------------------------// + + protected <R> TableColumnExt addColumnToModel(TableColumnModel model, + TableCellEditor editor, + TableCellRenderer renderer, + ColumnIdentifier<R> identifier) { + + return addColumnToModel(model, editor, renderer, identifier, null); + } + + protected <R> TableColumnExt addColumnToModel(TableColumnModel model, + TableCellEditor editor, + TableCellRenderer renderer, + ColumnIdentifier<R> identifier, + WeightUnit weightUnit) { + + TableColumnExt col = new TableColumnExt(model.getColumnCount()); + col.setCellEditor(editor); + col.setCellRenderer(renderer); + String label = _(identifier.getHeaderI18nKey()); + if (weightUnit != null) { + label = weightUnit.decorateLabel(label); + } + col.setHeaderValue(label); + String tip = _(identifier.getHeaderTipI18nKey()); + if (weightUnit != null) { + tip = weightUnit.decorateTip(tip); + } + col.setToolTipText(tip); + + col.setIdentifier(identifier); + model.addColumn(col); + // by default no column is sortable, must specify it + col.setSortable(false); + return col; + } + + protected <R> TableColumnExt addColumnToModel(TableColumnModel model, + ColumnIdentifier<R> identifier) { + + return addColumnToModel(model, null, null, identifier, null); + } + + protected <R> TableColumnExt addFloatColumnToModel(TableColumnModel model, + ColumnIdentifier<R> identifier, + String numberPattern, + JTable table) { + + NumberCellEditor<Float> editor = + JAXXWidgetUtil.newNumberTableCellEditor(Float.class, false); + editor.getNumberEditor().setSelectAllTextOnError(true); + editor.getNumberEditor().getTextField().setBorder(new LineBorder(Color.GRAY, 2)); + editor.getNumberEditor().setNumberPattern(numberPattern); + + TableCellRenderer renderer = + newNumberCellRenderer(table.getDefaultRenderer(Number.class)); + + return addColumnToModel(model, editor, renderer, identifier, null); + } + + protected <R> TableColumnExt addFloatColumnToModel(TableColumnModel model, + ColumnIdentifier<R> identifier, + WeightUnit weightUnit, + JTable table) { + + Preconditions.checkNotNull(weightUnit); + NumberCellEditor<Float> editor = + JAXXWidgetUtil.newNumberTableCellEditor(Float.class, false); + editor.getNumberEditor().setSelectAllTextOnError(true); + editor.getNumberEditor().getTextField().setBorder(new LineBorder(Color.GRAY, 2)); + editor.getNumberEditor().setNumberPattern(weightUnit.getNumberEditorPattern()); + + TableCellRenderer renderer = + newNumberCellRenderer(table.getDefaultRenderer(Number.class)); + + return addColumnToModel(model, editor, renderer, identifier, weightUnit); + } + + protected <R> TableColumnExt addIntegerColumnToModel(TableColumnModel model, + ColumnIdentifier<R> identifier, + String numberPattern, + JTable table) { + + NumberCellEditor<Integer> editor = + JAXXWidgetUtil.newNumberTableCellEditor(Integer.class, false); + editor.getNumberEditor().setSelectAllTextOnError(true); + editor.getNumberEditor().getTextField().setBorder(new LineBorder(Color.GRAY, 2)); + editor.getNumberEditor().setNumberPattern(numberPattern); + + TableCellRenderer renderer = newNumberCellRenderer(table.getDefaultRenderer(Number.class)); + return addColumnToModel(model, editor, renderer, identifier, null); + } + + + TableCellRenderer newNumberCellRenderer(final TableCellRenderer defaultRenderer) { + TableCellRenderer result = new TableCellRenderer() { + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + Component result = defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (result instanceof JLabel) { + JLabel jLabel = (JLabel) result; + jLabel.setHorizontalTextPosition(SwingConstants.RIGHT); + + } + return result; + } + }; + return result; + } + + + protected <R> TableColumnExt addBooleanColumnToModel(TableColumnModel model, + ColumnIdentifier<R> identifier, + JTable table) { + + return addColumnToModel(model, + table.getDefaultEditor(Boolean.class), + table.getDefaultRenderer(Boolean.class), + identifier, + null); + } + + protected <R, B> TableColumnExt addComboDataColumnToModel(TableColumnModel model, + ColumnIdentifier<R> identifier, + Decorator<B> decorator, + List<B> data) { + JComboBox comboBox = new JComboBox(); + comboBox.setRenderer(newListCellRender(decorator)); + + List<B> dataToList = Lists.newArrayList(data); + + // add a null value at first position + if (!dataToList.isEmpty() && dataToList.get(0) != null) { + dataToList.add(0, null); + } + SwingUtil.fillComboBox(comboBox, dataToList, null); + + ObjectToStringConverter converter = BeanUIUtil.newDecoratedObjectToStringConverter(decorator); + BeanUIUtil.decorate(comboBox, converter); + ComboBoxCellEditor editor = new ComboBoxCellEditor(comboBox); + + return addColumnToModel(model, + editor, + newTableCellRender(decorator), + identifier, + null); + } + + protected <O> TableCellRenderer newTableCellRender(Class<O> type) { + + return newTableCellRender(type, null); + } + + protected <O> TableCellRenderer newTableCellRender(Class<O> type, String name) { + + Decorator<O> decorator = getDecorator(type, name); + + TableCellRenderer result = newTableCellRender(decorator); + return result; + } + + protected <O> TableCellRenderer newTableCellRender(Decorator<O> decorator) { + + Preconditions.checkNotNull(decorator); + + DecoratorTableCellRenderer result = new DecoratorTableCellRenderer(decorator, true); + return result; + } +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/AbstractApplicationUIHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUI.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUI.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUI.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,146 @@ +package fr.ifremer.shared.application.swing; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import jaxx.runtime.JAXXObject; +import fr.ifremer.shared.application.type.WeightUnit; + +import javax.swing.UIManager; +import java.awt.Font; + +/** + * Contract to place on each ui. + * <p/> + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public interface ApplicationUI<M, H extends AbstractApplicationUIHandler<M, ?>> extends JAXXObject { + + M getModel(); + + H getHandler(); + + /** + * Pattern to use for short numeric values in editors with max 1 digits. + * + * @since 0.2 + */ + public static final String INT_1_DIGITS_PATTERN = "\\d{0,1}"; + + /** + * Pattern to use for short numeric values in editors with max 2 digits. + * + * @since 0.1 + */ + public static final String INT_2_DIGITS_PATTERN = "\\d{0,2}"; + + /** + * Pattern to use for signed numeric values in editors with max 2 digits. + * + * @since 1.0 + */ + public static final String SIGNED_INT_2_DIGITS_PATTERN = "-?\\d{0,2}"; + + /** + * Pattern to use for short numeric values in editors with max 3 digits. + * + * @since 0.1 + */ + public static final String INT_3_DIGITS_PATTERN = "\\d{0,3}"; + + /** + * Pattern to use for singed numeric values in editors with max 3 digits. + * + * @since 1.0 + */ + public static final String SIGNED_INT_3_DIGITS_PATTERN = "-?\\d{0,3}"; + + /** + * Pattern to use for short numeric values in editors with max 4 digits. + * + * @since 0.2 + */ + public static final String INT_4_DIGITS_PATTERN = "\\d{0,4}"; + + /** + * Pattern to use for integer numeric values in editors with max 6 digits. + * + * @since 0.1 + */ + public static final String INT_6_DIGITS_PATTERN = "\\d{0,6}"; + + /** + * Pattern to use for integer numeric values in editors with max 7 digits. + * + * @since 0.1 + */ + public static final String INT_7_DIGITS_PATTERN = "\\d{0,7}"; + + /** + * Pattern to use for decimal numeric values with 1 decimal digits in + * editors. + * + * @since 0.1 + */ + public static final String DECIMAL1_PATTERN = WeightUnit.G.getNumberEditorPattern(); + + /** + * Pattern to use for decimal numeric values with 2 decimal digits in + * editors. + * + * @since 0.1 + */ + public static final String DECIMAL2_PATTERN = "\\d{0,6}(\\.\\d{0,2})?"; + + /** + * Pattern to use for decimal numeric values with 3 decimal digits in + * editors. + * + * @since 0.1 + */ + public static final String DECIMAL3_PATTERN = "\\d{0,6}(\\.\\d{0,3})?"; + + /** + * Pattern to use for decimal numeric values with 4 decimal digits in + * editors. + * + * @since 2.6 + */ + public static final String DECIMAL4_PATTERN = WeightUnit.KG.getNumberEditorPattern(); + + /** + * Pattern to use for decimal numeric values with 2 digits + 3 decimal digits in + * editors. + * + * @since 1.0 + */ + public static final String DECIMAL2_DIGITS_PATTERN = "\\d{0,2}(\\.\\d*)?"; + + public static final Font TEXTFIELD_NORMAL_FONT = UIManager.getDefaults().getFont("TextField.font"); + + public static final Font TEXTFIELD_COMPUTED_FONT = UIManager.getDefaults().getFont("TextField.font").deriveFont(Font.ITALIC); +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUI.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUIContext.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUIContext.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUIContext.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,77 @@ +package fr.ifremer.shared.application.swing; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.shared.application.ApplicationContext; +import fr.ifremer.shared.application.swing.action.ApplicationActionEngine; +import fr.ifremer.shared.application.swing.action.ApplicationActionFactory; +import fr.ifremer.shared.application.swing.action.ApplicationActionUI; +import fr.ifremer.shared.application.swing.util.ApplicationErrorHelper; + +import java.awt.Color; +import java.awt.Component; + +/** + * Created on 11/24/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public interface ApplicationUIContext extends ApplicationContext { + + /** + * @return the main ui of the application. + */ + Component getMainUI(); + + /** + * @return the ui used to display long action. + */ + ApplicationActionUI getActionUI(); + + Component getBodyUI(); + + Component getStatusUI(); + + boolean isBusy(); + + void setBusy(boolean busy); + + boolean isHideBody(); + + void setHideBody(boolean b); + + Color getColorBlockingLayer(); + + ApplicationActionFactory getActionFactory(); + + ApplicationActionEngine getActionEngine(); + + ApplicationErrorHelper getErrorHelper(); + + String getI18nPrefix(); + + String getDateFormat(); +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/ApplicationUIContext.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/AbstractApplicationAction.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/action/AbstractTuttiAction.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/AbstractApplicationAction.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/AbstractApplicationAction.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,360 @@ +package fr.ifremer.shared.application.swing.action; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import fr.ifremer.shared.application.ApplicationConfiguration; +import fr.ifremer.shared.application.swing.AbstractApplicationUIHandler; +import fr.ifremer.shared.application.swing.ApplicationUI; +import fr.ifremer.shared.application.swing.ApplicationUIContext; +import fr.ifremer.shared.application.type.ApplicationProgressionModel; +import jaxx.runtime.FileChooserUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.beans.AbstractBean; +import org.nuiton.decorator.Decorator; + +import javax.swing.JOptionPane; +import java.io.File; + +import static org.nuiton.i18n.I18n._; + +/** + * Tutti base action. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public abstract class AbstractApplicationAction<M extends AbstractBean, UI extends ApplicationUI<M, ?>, H extends AbstractApplicationUIHandler<M, UI>> + extends AbstractBean { + + /** Logger. */ + private static final Log log = LogFactory.getLog(AbstractApplicationAction.class); + + public static final String PROPERTY_DONE = "done"; + + protected final H handler; + + protected String actionDescription; + + protected final boolean hideBody; + + protected final Object lock = new Object(); + + public abstract void doAction() throws Exception; + + protected AbstractApplicationAction(H handler, boolean hideBody) { + this.handler = handler; + this.hideBody = hideBody; + } + + public boolean prepareAction() throws Exception { + // by default nothing to prepare + return true; + } + + protected void releaseAction() { + // by default nothing to clean + firePropertyChange(PROPERTY_DONE, null, true); + } + + public void postSuccessAction() { + // by default nothing to do after action + } + + public void postFailedAction(Throwable error) { + // by default nothing to do after action + } + + public H getHandler() { + return handler; + } + + public M getModel() { + return handler.getModel(); + } + + public final UI getUI() { + return handler.getUI(); + } + + public ApplicationUIContext getContext() { + return handler.getContext(); + } + + public String getActionDescription() { + return actionDescription; + } + + public void setActionDescription(String actionDescription) { + this.actionDescription = actionDescription; + } + + public void setProgressionModel(ApplicationProgressionModel progressionModel) { + getContext().getActionUI().getModel().setProgressionModel(progressionModel); + } + + protected ApplicationProgressionModel getProgressionModel() { + return getContext().getActionUI().getModel().getProgressionModel(); + } + + public boolean isHideBody() { + return hideBody; + } + + protected ApplicationConfiguration getConfig() { + return getContext().getConfiguration(); + } + + protected abstract void sendMessage(String message); + + protected <O> Decorator<O> getDecorator(Class<O> type, String name) { + Decorator<O> decorator = handler.getDecorator(type, name); + Preconditions.checkNotNull(decorator); + return decorator; + } + + protected String decorate(Object object) { + return getDecorator(object.getClass(), null).toString(object); + } + + protected String decorate(Object object, String context) { + return getDecorator(object.getClass(), context).toString(object); + } + +// protected boolean askAdminPassword(String askMessage, +// String askMessageTitle, +// String errorMessage, +// String errorMessageTitle) { +// +// Component container = getContext().getActionUI(); +// +// String answer; +// boolean result; +// do { +// answer = JOptionPane.showInputDialog(container, +// askMessage, +// askMessageTitle, +// JOptionPane.WARNING_MESSAGE); +// if (answer != null) { +// String cryptedAnswer = StringUtil.encodeMD5(answer); +// String correctAnswer = getConfig().getAdminPassword(); +// result = StringUtils.equals(cryptedAnswer, correctAnswer); +// +// if (!result) { +// JOptionPane.showMessageDialog(container, +// errorMessage, +// errorMessageTitle, +// JOptionPane.ERROR_MESSAGE); +// } +// +// } else { +// result = false; +// } +// +// } while (!result && answer != null); +// return result; +// } + + /** + * Choisir un fichier via un sélecteur graphique de fichiers. + * + * @param title le titre du dialogue de sélection + * @param buttonLabel le label du boutton d'acceptation + * @param filters les filtres + descriptions sur le sélecteur de + * fichiers + * @return le fichier choisi ou le fichier incoming si l'opération a été + * annulée + */ + protected File chooseFile(String title, + String buttonLabel, + String... filters) { + + File file = FileChooserUtil.getFile(title, + buttonLabel, + getContext().getMainUI(), + filters); + if (log.isDebugEnabled()) { + log.debug(title + " : " + file); + } + if (file != null) { + File newDir = file.isDirectory() ? file : file.getParentFile(); + FileChooserUtil.setCurrentDirectory(newDir); + } + return file; + } + + /** + * Sauver un fichier via un sélecteur graphique de fichiers. + * + * @param title le titre du dialogue de sélection + * @param buttonLabel le label du boutton d'acceptation + * @param filters les filtres + descriptions sur le sélecteur de + * fichiers + * @return le fichier choisi ou {@code null} si pas de fichier choisi ou + * pas voulu écrasé un fichier existant. + */ + protected File saveFile(File defaultFile, + String filename, + String extension, + String title, + String buttonLabel, + String... filters) { + + if (defaultFile != null && FileChooserUtil.isCurrentDirectoryDefault()) { + + // set default directory to this one + FileChooserUtil.setCurrentDirectory(defaultFile); + } + File file = saveFile(filename, extension, title, buttonLabel, filters); + return file; + } + + /** + * Sauver un fichier via un sélecteur graphique de fichiers. + * + * @param title le titre du dialogue de sélection + * @param buttonLabel le label du boutton d'acceptation + * @param filters les filtres + descriptions sur le sélecteur de + * fichiers + * @return le fichier choisi ou {@code null} si pas de fichier choisi ou + * pas voulu écrasé un fichier existant. + */ + protected File saveFile(String filename, + String extension, + String title, + String buttonLabel, + String... filters) { + + boolean withExtension = StringUtils.isNotBlank(extension); + String filenameSuffix = withExtension ? "." + extension : ""; + File file = FileChooserUtil.saveFile(filename + filenameSuffix, title, buttonLabel, getContext().getMainUI(), filters); + if (log.isDebugEnabled()) { + log.debug(title + " : " + file); + } + if (file != null) { + Preconditions.checkState(!file.isDirectory()); + + // add extension if missing + if (withExtension && !file.getName().endsWith(filenameSuffix)) { + file = new File(file.getParentFile(), file.getName() + filenameSuffix); + } + + // ask user to confirm overwrite. + boolean confirm = askOverwriteFile(file); + + if (confirm) { + + // on conserve le répertoire (pour une prochaine utilisation) + FileChooserUtil.setCurrentDirectory(file.getParentFile()); + } else { + + // l'utilisateur n'a pas confirmé l'écrasement + // donc pas de fichier en retour + file = null; + } + } + + return file; + } + + protected boolean askOverwriteFile(File file) { + boolean result; + if (file.exists()) { + + // file exists ask user to overwrite + String htmlMessage = String.format( + AbstractApplicationUIHandler.CONFIRMATION_FORMAT, + _("application.common.askOverwriteFile.message", file), + _("application.common.askOverwriteFile.help")); + + result = JOptionPane.showConfirmDialog( + getHandler().getTopestUI(), + htmlMessage, + _("application.common.askOverwriteFile.title"), + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; + } else { + + // file does not exist + result = true; + } + return result; + } + + protected boolean askBeforeDelete(String title, String message) { + String htmlMessage = String.format( + AbstractApplicationUIHandler.CONFIRMATION_FORMAT, + message, + _("application.common.askBeforeDelete.help")); + int i = JOptionPane.showConfirmDialog( + getHandler().getTopestUI(), + htmlMessage, + title, + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE); + + boolean result = i == JOptionPane.OK_OPTION; + return result; + } + + protected void displayInfoMessage(String title, String message) { + JOptionPane.showMessageDialog( + getHandler().getTopestUI(), + message, + title, + JOptionPane.INFORMATION_MESSAGE); + } + + protected void displayWarningMessage(String title, String message) { + JOptionPane.showMessageDialog( + getHandler().getTopestUI(), + message, + title, + JOptionPane.WARNING_MESSAGE); + } + + protected void createProgressionModelIfRequired(int total) { + ApplicationProgressionModel progressionModel = getProgressionModel(); + if (progressionModel == null) { + progressionModel = new ApplicationProgressionModel(); + progressionModel.setTotal(total); + progressionModel.setMessage(""); + progressionModel.setCurrent(0); + setProgressionModel(progressionModel); + } else { + progressionModel.adaptTotal(total); + } + } + + public ApplicationActionFactory getActionFactory() { + return getContext().getActionFactory(); + } + + public ApplicationActionEngine getActionEngine() { + return getContext().getActionEngine(); + } +} Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionEngine.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionEngine.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionEngine.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,101 @@ +package fr.ifremer.shared.application.swing.action; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.shared.application.swing.AbstractApplicationUIHandler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.AbstractButton; + +/** + * To create and consume {@link AbstractApplicationAction}. + * Created on 11/24/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationActionEngine { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(ApplicationActionEngine.class); + + private final ApplicationActionFactory actionFactory; + + public ApplicationActionEngine(ApplicationActionFactory actionFactory) { + this.actionFactory = actionFactory; + } + + public <A extends AbstractApplicationAction> void runInternalAction(A action) { + Throwable error = null; + + try { + action.doAction(); + action.postSuccessAction(); + } catch (Throwable e) { + error = e; + if (log.isErrorEnabled()) { + log.error("Error in action:", e); + } + throw ApplicationActionException.propagateError(action, e); + } finally { + try { + if (error != null) { + action.postFailedAction(error); + } + } finally { + + action.releaseAction(); + } + } + } + + public <A extends AbstractApplicationAction> void runInternalAction(AbstractApplicationUIHandler handler, + Class<A> actionName) { + A action = actionFactory.createLogicAction(handler, actionName); + runInternalAction(action); + } + + public <A extends AbstractApplicationAction> void runAction(A action) { + ApplicationUIAction<A> uiAction = actionFactory.createUIAction(null, action); + uiAction.actionPerformed(null); + } + + public void runAction(AbstractButton button) { + button.getAction().actionPerformed(null); + } + + public <A extends AbstractApplicationAction> void runActionAndWait(A action) { + ApplicationUIAction<A> uiAction = actionFactory.createUIAction(null, action); + uiAction.launchActionAndWait(); + } + + public <A extends AbstractApplicationAction> void runActionAndWait(AbstractApplicationUIHandler handler, + Class<A> actionName) { + A logicAction = actionFactory.createLogicAction(handler, actionName); + runActionAndWait(logicAction); + } +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionEngine.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionException.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/action/TuttiActionException.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionException.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionException.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,58 @@ +package fr.ifremer.shared.application.swing.action; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * To box any error of a {@link AbstractApplicationAction}. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationActionException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + private final AbstractApplicationAction action; + + public ApplicationActionException(AbstractApplicationAction action, Throwable cause) { + super(cause); + this.action = action; + } + + public static ApplicationActionException propagateError(AbstractApplicationAction action, + Throwable cause) { + ApplicationActionException result; + if (cause instanceof ApplicationActionException) { + result = ((ApplicationActionException) cause); + } else { + result = new ApplicationActionException(action, cause); + } + return result; + } + + public AbstractApplicationAction getAction() { + return action; + } +} Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionFactory.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionFactory.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionFactory.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,99 @@ +package fr.ifremer.shared.application.swing.action; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import fr.ifremer.shared.application.ApplicationTechnicalException; +import fr.ifremer.shared.application.swing.AbstractApplicationUIHandler; +import org.apache.commons.lang3.reflect.ConstructorUtils; + +import javax.swing.AbstractButton; +import javax.swing.Action; + +import static org.nuiton.i18n.I18n._; + +/** + * Factory of actions. + * <p/> + * Created on 11/24/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationActionFactory { + + public <A extends AbstractApplicationAction> ApplicationUIAction<A> createUIAction(AbstractApplicationUIHandler handler, + Class<A> actionName) { + return createUIAction(handler, null, actionName); + } + + + public <A extends AbstractApplicationAction> ApplicationUIAction<A> createUIAction(AbstractApplicationUIHandler handler, + AbstractButton abstractButton, + Class<A> actionName) { + try { + + // create logic action + A logicAction = createLogicAction(handler, actionName); + + // create ui action + ApplicationUIAction<A> result = createUIAction(abstractButton, logicAction); + return result; + } catch (Exception e) { + throw new ApplicationTechnicalException(_("application.action.create.error", actionName), e); + } + + } + + public <A extends AbstractApplicationAction> ApplicationUIAction<A> createUIAction(AbstractButton abstractButton, + A logicAction) { + + // create ui action + ApplicationUIAction<A> result = new ApplicationUIAction<A>(abstractButton, + logicAction); + return result; + + + } + + public <A extends AbstractApplicationAction> A createLogicAction(AbstractApplicationUIHandler handler, + Class<A> actionName) { + try { + + // create action + A result = ConstructorUtils.invokeConstructor(actionName, handler); + return result; + } catch (Exception e) { + throw new ApplicationTechnicalException(_("application.action.create.error", actionName), e); + } + } + + public <A extends AbstractApplicationAction> A getLogicAction(AbstractButton b) { + Action action = b.getAction(); + Preconditions.checkNotNull(action); + Preconditions.checkState(action instanceof ApplicationUIAction); + return ((ApplicationUIAction<A>) action).getLogicAction(); + } +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionFactory.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionSwingWorker.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/action/TuttiActionSwingWorker.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionSwingWorker.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionSwingWorker.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,186 @@ +package fr.ifremer.shared.application.swing.action; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Timer; +import java.util.TimerTask; + +/** + * Worker to execute logic action. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationActionSwingWorker<A extends AbstractApplicationAction> extends SwingWorker<Void, String> { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(ApplicationActionSwingWorker.class); + + /** + * Timer used to launch timerTask (to open load dialog). + * + * @since 1.0.2 + */ + private static final Timer t = new Timer(); + + protected final ApplicationActionUI actionUI; + + protected final A action; + + protected Throwable error; + + protected TimerTask timer; + + protected ApplicationActionSwingWorker(A action) { + + this.action = action; + this.actionUI = action.getContext().getActionUI(); + } + + public Throwable getError() { + return error; + } + + public boolean isFailed() { + return error != null; + } + + @Override + protected Void doInBackground() throws Exception { + + if (!isCancelled()) { + + timer = new TuttiActionTimerTask(); + + t.schedule(timer, 1000); + + try { + + action.doAction(); + + } catch (Throwable e) { + if (log.isErrorEnabled()) { + log.error("Task [" + this + "] Error while doAction: ", e); + } + error = e; + } finally { + if (log.isDebugEnabled()) { + log.debug("Task [" + this + "] done"); + } + } + } + return null; + } + + @Override + protected void done() { + super.done(); + + if (log.isDebugEnabled()) { + log.debug("Task [" + this + "] execute done method after all"); + } + + if (error == null) { + + // success hook + action.postSuccessAction(); + } else { + + // fail hook + action.postFailedAction(error); + } + + action.releaseAction(); + + if (timer != null) { + + timer.cancel(); + } + + actionUI.close(); + + updateBusyState(false); + } + + protected void updateBusyState(boolean busy) { + + boolean hideBody = action.isHideBody(); + + action.getContext().setBusy(busy); + + if (hideBody) { + action.getContext().setHideBody(!busy); + } + + } + + protected class TuttiActionTimerTask extends TimerTask { + + public TuttiActionTimerTask() { + action.addPropertyChangeListener(AbstractApplicationAction.PROPERTY_DONE, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + + if (actionUI.isVisible()) { + actionUI.close(); + } + + // we do NOT want the timer to wake up then the actionUI dialog + cancel(); + } + }); + } + + @Override + public void run() { + if (isCancelled() || isDone()) { + + if (log.isDebugEnabled()) { + log.debug("Task [" + action + "] was already canceled or done, do nothing"); + } + } else { + + if (log.isDebugEnabled()) { + log.debug("Task [" + action + "] is started, show waiting dialog"); + } + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + actionUI.open(action); + } + }); + } + } + } +} Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUI.css (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/action/TuttiActionUI.css) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUI.css (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUI.css 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,68 @@ +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +#busyBlockLayerUI { + useIcon:false; + blockingColor: {handler.getContext().getColorBlockingLayer()}; + block:{true}; +} + +#globalPanel { + border: {new TitledBorder((String) null)}; +} + +#globalActionLabel { + border: {new EmptyBorder(5, 5, 5, 5)}; +} + +#globalProgressBar { + indeterminate: true; +} + +#taskPanel { + visible: false; + border: {new TitledBorder((String) null)}; +} + +#taskProgressBar { + indeterminate: false; +} + +#taskActionLabel { + border: {new EmptyBorder(5, 5, 5, 5)}; +} + +#informationPanel { + visible: false; + border: {new TitledBorder((String) null)}; +} + +#informationLabel { + border: {new EmptyBorder(5, 5, 5, 5)}; +} + +#okAction { + actionIcon: information; + text: "tutti.action.ok"; +} Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUI.jaxx (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/action/TuttiActionUI.jaxx) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUI.jaxx (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUI.jaxx 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,82 @@ +<!-- + #%L + Ifremer shared :: Application Swing + $Id$ + $HeadURL$ + %% + Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/gpl-3.0.html>. + #L% + --> +<JDialog width='300' height='200' modal='true' + undecorated='true' + implements='fr.ifremer.shared.application.swing.ApplicationUI<ApplicationActionUIModel, ApplicationActionUIHandler>'> + <import> + + fr.ifremer.shared.application.swing.ApplicationUI + fr.ifremer.shared.application.swing.ApplicationUIContext + + jaxx.runtime.swing.BlockingLayerUI + + javax.swing.border.EmptyBorder + </import> + + <script><![CDATA[ + + public ApplicationActionUI(JFrame frame, ApplicationUIContext context) { + super(frame, true); + ApplicationActionUIHandler handler = new ApplicationActionUIHandler(context, this); + setContextValue(handler); + handler.beforeInitUI(); + } + + public void open(AbstractApplicationAction action) { + getModel().setAction(action); + } + + public void close() { + getModel().clear(); + } + + protected void $afterCompleteSetup() { + handler.afterInitUI(); + } + ]]></script> + + + <BlockingLayerUI id='busyBlockLayerUI'/> + + <ApplicationActionUIHandler id='handler' + initializer='getContextValue(ApplicationActionUIHandler.class)'/> + + <ApplicationActionUIModel id='model' + initializer='getContextValue(ApplicationActionUIModel.class)'/> + + <JPanel id='rootPanel' layout='{new BorderLayout()}' + constraints='BorderLayout.CENTER' decorator='boxed'> + <JPanel id='globalPanel' constraints='BorderLayout.NORTH' + layout='{new BorderLayout()}'> + <JLabel id='globalActionLabel' constraints='BorderLayout.CENTER'/> + <JProgressBar id='globalProgressBar' constraints='BorderLayout.SOUTH'/> + </JPanel> + <JPanel id='taskPanel' constraints='BorderLayout.CENTER' + layout='{new BorderLayout()}'> + <JLabel id='taskActionLabel' constraints='BorderLayout.CENTER'/> + <JProgressBar id='taskProgressBar' constraints='BorderLayout.SOUTH'/> + </JPanel> + </JPanel> + +</JDialog> \ No newline at end of file Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUIHandler.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/action/TuttiActionUIHandler.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUIHandler.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUIHandler.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,286 @@ +package fr.ifremer.shared.application.swing.action; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.shared.application.swing.AbstractApplicationUIHandler; +import fr.ifremer.shared.application.swing.ApplicationUIContext; +import fr.ifremer.shared.application.type.ApplicationProgressionModel; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.validator.swing.SwingValidator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.Decorator; + +import javax.swing.AbstractButton; +import javax.swing.JComponent; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import static org.nuiton.i18n.I18n._; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationActionUIHandler extends AbstractApplicationUIHandler<ApplicationActionUIModel, ApplicationActionUI> { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(ApplicationActionUIHandler.class); + + public ApplicationActionUIHandler(ApplicationUIContext context, ApplicationActionUI ui) { + super(context, ui); + } + + protected PropertyChangeListener progressionListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + + String propertyName = evt.getPropertyName(); + if (ApplicationProgressionModel.PROPERTY_MESSAGE.equals(propertyName)) { + + // change message + String newMessage = (String) evt.getNewValue(); + ui.getTaskActionLabel().setText("<html><body>" + newMessage + "</body></html>"); + ui.pack(); + } else if (ApplicationProgressionModel.PROPERTY_TOTAL.equals(propertyName)) { + + // change total progressbar max + ui.getTaskProgressBar().setMaximum((Integer) evt.getNewValue()); + + } else if (ApplicationProgressionModel.PROPERTY_CURRENT.equals(propertyName)) { + + // change value of progress bar + ui.getTaskProgressBar().setValue((Integer) evt.getNewValue()); + } + } + }; + + protected ComponentListener listener = new ComponentAdapter() { + boolean moving; + + boolean resizing; + + @Override + public void componentMoved(ComponentEvent e) { + + Component mainUI = (Component) e.getSource(); + + if (!moving && mainUI.isShowing()) { + + moving = true; + try { + setLocation(mainUI); + } finally { + moving = false; + } + } + } + + @Override + public void componentResized(ComponentEvent e) { + + Component mainUI = (Component) e.getSource(); + + if (!resizing && mainUI.isShowing()) { + + resizing = true; + try { + setSize(mainUI); + } finally { + resizing = false; + } + } + } + }; + + //------------------------------------------------------------------------// + //-- AbstractTuttiUIHandler methods --// + //------------------------------------------------------------------------// + + @Override + public void beforeInitUI() { + ApplicationActionUIModel model = new ApplicationActionUIModel(); + ui.setContextValue(model); + + model.addPropertyChangeListener(ApplicationActionUIModel.PROPERTY_ACTION, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + + // udpate global label + AbstractApplicationAction action = (AbstractApplicationAction) evt.getNewValue(); + + if (log.isDebugEnabled()) { + log.debug("Action to use: " + action); + } + if (action == null) { + + // stoping action + hideAction(); + } else { + + // starting action + showAction(action); + } + } + }); + + model.addPropertyChangeListener(ApplicationActionUIModel.PROPERTY_PROGRESSION_MODEL, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + + // change progression model + + ApplicationProgressionModel oldValue = (ApplicationProgressionModel) evt.getOldValue(); + ApplicationProgressionModel newValue = (ApplicationProgressionModel) evt.getNewValue(); + + if (log.isDebugEnabled()) { + log.debug("progression model: " + newValue); + } + if (oldValue != null) { + oldValue.removePropertyChangeListener(progressionListener); + } + + if (newValue == null) { + + // remove progression model + ui.getTaskPanel().setVisible(false); + } else { + + // use progression model + ui.getTaskPanel().setVisible(true); + + newValue.addPropertyChangeListener(progressionListener); + } + } + }); + } + + @Override + public void afterInitUI() { + + initUI(ui); + + // installation layer de blocage en mode busy + SwingUtil.setLayerUI(ui.getRootPanel(), ui.getBusyBlockLayerUI()); + + ui.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + } + + @Override + protected JComponent getComponentToFocus() { + return null; + } + + @Override + public void onCloseUI() { + + } + + @Override + public SwingValidator<ApplicationActionUIModel> getValidator() { + return null; + } + + @Override + public Component getTopestUI() { + return null; + } + + @Override + public <E> Decorator<E> getDecorator(Class<E> beanType, String decoratorContext) { + return null; + } + + //------------------------------------------------------------------------// + //-- Internal methods --// + //------------------------------------------------------------------------// + + protected void hideAction() { + ui.setVisible(false); + } + + protected void showAction(AbstractApplicationAction action) { + ui.setTitle(_("application.title.actionUI", + getContext().getConfiguration().getApplicationName(), + getContext().getConfiguration().getVersion(), + action.getActionDescription())); + ui.getGlobalActionLabel().setText( + _("application.message.action.running", + action.getActionDescription())); + ui.pack(); + + Component mainUI = getContext().getMainUI(); + if (mainUI != null) { + mainUI.addComponentListener(listener); + + setLocation(mainUI); + setSize(mainUI); + } + try { + ui.setVisible(true); + } finally { + if (mainUI != null) { + mainUI.removeComponentListener(listener); + } + } + } + + protected void setLocation(Component mainUI) { + Component component = getContext().getBodyUI(); + Component status = getContext().getStatusUI(); + int width = component == null ? 0 : component.getWidth(); + int height = component == null ? 0 : component.getHeight() + status.getHeight(); + + int x; + int y; + if (height == 0) { + x = mainUI.getX() + 5; + y = mainUI.getY() + 15; + } else { + x = mainUI.getX() + (mainUI.getWidth() - width); + y = mainUI.getY() + (mainUI.getHeight() - height); + } + ui.setLocation(x, y); + } + + protected void setSize(Component mainUI) { + // Better to let his own size to the action progress bar + // see http://forge.codelutin.com/issues/3263 +// Container component = mainUI.getBody(); +// int width = component == null ? 0 : component.getWidth(); + + ui.pack(); + +// if (width != 0 && ui.getWidth() < width) { +// ui.setSize(width, ui.getHeight()); +// } + } +} Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUIModel.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/action/TuttiActionUIModel.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUIModel.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationActionUIModel.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,75 @@ +package fr.ifremer.shared.application.swing.action; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import fr.ifremer.shared.application.type.ApplicationProgressionModel; +import org.jdesktop.beans.AbstractSerializableBean; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationActionUIModel extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_ACTION = "action"; + + public static final String PROPERTY_PROGRESSION_MODEL = "progressionModel"; + + protected AbstractApplicationAction action; + + protected ApplicationProgressionModel progressionModel; + + public ApplicationProgressionModel getProgressionModel() { + return progressionModel; + } + + public void setProgressionModel(ApplicationProgressionModel progressionModel) { + Object oldValue = getProgressionModel(); + this.progressionModel = progressionModel; + firePropertyChange(PROPERTY_PROGRESSION_MODEL, oldValue, progressionModel); + } + + public AbstractApplicationAction getAction() { + return action; + } + + public void setAction(AbstractApplicationAction action) { + Preconditions.checkNotNull(action, "action can not be null"); + Object oldValue = getAction(); + this.action = action; + firePropertyChange(PROPERTY_ACTION, oldValue, action); + } + + public void clear() { + setProgressionModel(null); + + Object oldValue = getAction(); + action = null; + firePropertyChange(PROPERTY_ACTION, oldValue, null); + } +} Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationUIAction.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/action/TuttiUIAction.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationUIAction.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/action/ApplicationUIAction.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,228 @@ +package fr.ifremer.shared.application.swing.action; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.TimeLog; + +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.SwingUtilities; +import java.awt.event.ActionEvent; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Abstract tutti ui action which launch a {@link AbstractApplicationAction}. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0.2 + */ +public class ApplicationUIAction<A extends AbstractApplicationAction> extends AbstractAction { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = LogFactory.getLog(ApplicationUIAction.class); + + private static final TimeLog TIME_LOG = new TimeLog(ApplicationUIAction.class); + + public static final ExecutorService waitingThread = + Executors.newSingleThreadExecutor(); + + private static final String LOGIC_ACTION = "logicAction"; + + private final Object lock = new Object(); + + private boolean wait; + + private long t0; + + public ApplicationUIAction(AbstractButton button, A action) { + + putValue(LOGIC_ACTION, action); + + // fill the ui action from the button + setActionKey(action.getClass().getName()); + if (button != null) { + setActionIcon(button.getIcon()); + setActionName(button.getText()); + setActionDescription(button.getToolTipText()); + setActionMnemonic(button.getMnemonic()); + } + } + + public void launchActionAndWait() { + wait = true; + actionPerformed(null); + lock(); + } + + + @Override + public final void actionPerformed(final ActionEvent event) { + + t0 = TimeLog.getTime(); + + if (log.isInfoEnabled()) { + log.info("Task [" + getLogicAction().getClass().getSimpleName() + "] starting"); + } + + // prepare action + boolean doAction; + + A action = getLogicAction(); + + // reset status message + action.sendMessage(""); + + try { + doAction = action.prepareAction(); + } catch (Exception e) { + action.releaseAction(); + throw ApplicationActionException.propagateError(action, e); + } + + if (doAction) { + + final ApplicationActionSwingWorker<A> worker = + new ApplicationActionSwingWorker<A>(action); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + + // make ui busy + worker.updateBusyState(true); + + } + }); + + if (log.isDebugEnabled()) { + log.debug("Before execute of action " + action); + } + + // perform and release action + worker.execute(); + + // wait until action is done + waitingThread.execute( + new Runnable() { + @Override + public void run() { + + A action = getLogicAction(); + try { + try { + worker.get(); + } catch (ExecutionException e) { + // don't care . + } catch (CancellationException e) { + // dont care ? + } catch (InterruptedException e) { + // don't care ? + } + if (log.isDebugEnabled()) { + log.debug("After execute of action " + action + " (worker done? " + worker.isDone() + ")"); + } + + if (worker.isFailed()) { + + throw ApplicationActionException.propagateError(action, worker.getError()); + } + } finally { + unlock(); + } + } + } + ); + + } else { + + try { + // release action + action.releaseAction(); + + } finally { + unlock(); + } + } + } + + public void setActionIcon(Icon actionIcon) { + putValue(SMALL_ICON, actionIcon); + putValue(LARGE_ICON_KEY, actionIcon); + } + + public void setActionKey(String actionKey) { + putValue(ACTION_COMMAND_KEY, actionKey); + } + + public void setActionName(String actionName) { + putValue(NAME, actionName); + } + + public void setActionDescription(String actionDescription) { + putValue(SHORT_DESCRIPTION, actionDescription); + getLogicAction().setActionDescription(actionDescription); + } + + public void setActionMnemonic(int key) { + putValue(MNEMONIC_KEY, key); + } + + public A getLogicAction() { + return (A) getValue(LOGIC_ACTION); + } + + protected void lock() { + if (wait) { + synchronized (lock) { + try { + + lock.wait(); + + } catch (InterruptedException e) { + throw ApplicationActionException.propagateError(getLogicAction(), e); + } finally { + wait = false; + } + } + } + } + + protected void unlock() { + TIME_LOG.log(t0, "Task [" + getLogicAction().getClass().getSimpleName() + "] End"); + if (wait) { + synchronized (lock) { + lock.notifyAll(); + } + } + } +} Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationAction.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationAction.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationAction.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,60 @@ +package fr.ifremer.shared.application.swing.actionng; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Contract of an application action. + * <p/> + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public interface ApplicationAction { + + /** + * Hook to + * + * @return {@code true} if action can be execute, {@code false} otherwise. + */ + boolean prepare(); + + /** + * Real action code. + */ + void action(); + + /** + * Executed when action ended with success. + */ + void done(); + + /** + * Executed when action failed. + * + * @param error failure exception + */ + void fail(Exception error); +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationAction.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEngine.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEngine.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEngine.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,103 @@ +package fr.ifremer.shared.application.swing.actionng; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import javax.swing.event.EventListenerList; + +/** + * Engine what consumes incoming actions. + * <p/> + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationActionEngine { + + private final EventListenerList eventList; + + public ApplicationActionEngine() { + eventList = new EventListenerList(); + } + + public void addAction(ApplicationAction action) { + + } + + //------------------------------------------------------------------------// + //--- ApplicationActionListener API ---// + //------------------------------------------------------------------------// + + public void addApplicationEventListener(ApplicationActionListener listener) { + eventList.add(ApplicationActionListener.class, listener); + } + + public void removeApplicationEventListener(ApplicationActionListener listener) { + eventList.remove(ApplicationActionListener.class, listener); + } + + protected void fireInit(ApplicationAction action) { + ApplicationActionEvent event = new ApplicationActionEvent(action, ApplicationActionEvent.EventType.INIT); + + ApplicationActionListener[] listeners = eventList.getListeners(ApplicationActionListener.class); + for (ApplicationActionListener listener : listeners) { + listener.actionStarted(event); + } + } + + protected void fireStart(ApplicationAction action) { + ApplicationActionEvent event = new ApplicationActionEvent(action, ApplicationActionEvent.EventType.START); + + ApplicationActionListener[] listeners = eventList.getListeners(ApplicationActionListener.class); + for (ApplicationActionListener listener : listeners) { + listener.actionStarted(event); + } + } + + protected void fireDone(ApplicationAction action) { + ApplicationActionEvent event = new ApplicationActionEvent(action, ApplicationActionEvent.EventType.DONE); + ApplicationActionListener[] listeners = eventList.getListeners(ApplicationActionListener.class); + for (ApplicationActionListener listener : listeners) { + listener.actionDone(event); + } + } + + protected void fireFail(ApplicationAction action, Exception error) { + ApplicationActionEvent event = new ApplicationActionEvent(action, ApplicationActionEvent.EventType.FAIL); + event.setError(error); + ApplicationActionListener[] listeners = eventList.getListeners(ApplicationActionListener.class); + for (ApplicationActionListener listener : listeners) { + listener.actionFailed(event); + } + } + + protected void fireProgressionChange(ApplicationAction action) { + ApplicationActionEvent event = new ApplicationActionEvent(action, ApplicationActionEvent.EventType.PROGRESSION_CHANGE); + ApplicationActionListener[] listeners = eventList.getListeners(ApplicationActionListener.class); + for (ApplicationActionListener listener : listeners) { + listener.actionProgressionChanged(event); + } + } +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEngine.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEvent.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEvent.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEvent.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,97 @@ +package fr.ifremer.shared.application.swing.actionng; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import java.util.EventObject; + +/** + * Events... + * + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationActionEvent extends EventObject { + + private static final long serialVersionUID = 1L; + + public enum EventType { + /** + * Before starting action. + */ + INIT, + /** + * When action is started. + */ + START, + /** + * When action end with succes. + */ + DONE, + /** + * When action failed. + */ + FAIL, + /** + * When progression changed. + */ + PROGRESSION_CHANGE + } + + private Exception error; + + private final EventType eventType; + + /** + * Constructs a prototypical Event. + * + * @param source The object on which the Event initially occurred. + * @param eventType The type of event + * @throws IllegalArgumentException if source is null. + */ + public ApplicationActionEvent(ApplicationAction source, + EventType eventType) { + super(source); + this.eventType = eventType; + } + + @Override + public ApplicationAction getSource() { + return (ApplicationAction) super.getSource(); + } + + public Exception getError() { + return error; + } + + public void setError(Exception error) { + this.error = error; + } + + public EventType getEventType() { + return eventType; + } +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionEvent.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionListener.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionListener.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionListener.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,49 @@ +package fr.ifremer.shared.application.swing.actionng; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import java.util.EventListener; + +/** + * To listen {@link ApplicationActionEngine} events. + * <p/> + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public interface ApplicationActionListener extends EventListener { + + void actionInit(ApplicationActionEvent event); + + void actionStarted(ApplicationActionEvent event); + + void actionProgressionChanged(ApplicationActionEvent event); + + void actionDone(ApplicationActionEvent event); + + void actionFailed(ApplicationActionEvent event); + +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/actionng/ApplicationActionListener.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/AbstractApplicationTableModel.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractTuttiTableModel.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/AbstractApplicationTableModel.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/AbstractApplicationTableModel.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,303 @@ +package fr.ifremer.shared.application.swing.table; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.table.TableColumnModelExt; + +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableColumn; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +/** + * Abstract model of a table. + * + * @param <R> type of a row. + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public abstract class AbstractApplicationTableModel<R extends Serializable> extends AbstractTableModel { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = + LogFactory.getLog(AbstractApplicationTableModel.class); + + /** + * Data in the model. + * + * @since 0.2 + */ + protected List<R> rows; + + /** + * Set of non editable columns. + * + * @since 0.2 + */ + protected Set<ColumnIdentifier<?>> noneEditableCols; + + /** + * Creates a new row when moving to next editable cell / row ? + * + * @since 0.3 + */ + protected final boolean createNewRow; + + /** + * Creates a first empty row when setting a null or empty list of rows ? + * + * @since 0.3 + */ + protected final boolean createEmptyRowIsEmpty; + + /** + * Identifiers of columns (in initial order). + * + * @since 1.1 + */ + protected final List<ColumnIdentifier<R>> identifiers; + + public abstract R createNewRow(); + + protected AbstractApplicationTableModel(TableColumnModelExt columnModel, + boolean createNewRow, + boolean createEmptyRowIsEmpty) { + this.identifiers = Lists.newArrayListWithCapacity(columnModel.getColumnCount()); + for (TableColumn tc : columnModel.getColumns(true)) { + this.identifiers.add((ColumnIdentifier<R>) tc.getIdentifier()); + } + this.createNewRow = createNewRow; + this.createEmptyRowIsEmpty = createEmptyRowIsEmpty; + } + + public final List<R> getRows() { + return rows; + } + + public final void setRows(List<R> data) { + + // can't accept a empty data list + Preconditions.checkNotNull(data, "Data list can not be null."); + + this.rows = null; + if (createEmptyRowIsEmpty && data.isEmpty()) { + + if (log.isDebugEnabled()) { + log.debug("Creates a first empty row on tableModel " + this); + } + // add a first edit line + data.add(createNewRow()); + } + if (log.isDebugEnabled()) { + log.debug("Set " + data.size() + " row(s) in table model " + this); + } + this.rows = data; + onRowsChanged(data); + fireTableDataChanged(); + } + + public boolean isCreateNewRow() { + return createNewRow; + } + + public boolean isCreateEmptyRowIsEmpty() { + return createEmptyRowIsEmpty; + } + + public final void addNewRow() { + R newValue = createNewRow(); + addNewRow(newValue); + } + + public final void addNewRow(R newValue) { + + addNewRow(getRowCount(), newValue); + } + + public final void addNewRow(int rowIndex, R newValue) { + + Preconditions.checkNotNull(newValue, "Row can not be null."); + + List<R> data = getRows(); + Preconditions.checkNotNull(data, "Data list can not be null."); + + data.add(rowIndex, newValue); + + onRowAdded(rowIndex, newValue); + fireTableRowsInserted(rowIndex, rowIndex); + } + + public final void fireTableRowsInserted(R newValue) { + + Preconditions.checkNotNull(newValue, "Row can not be null."); + + int rowIndex = getRowIndex(newValue); + fireTableRowsInserted(rowIndex, rowIndex); + } + + public final int updateRow(R row) { + Preconditions.checkNotNull(row, "Row can not be null."); + + List<R> data = getRows(); + Preconditions.checkNotNull(data, "Data list can not be null."); + + int rowIndex = data.indexOf(row); + + fireTableRowsUpdated(rowIndex, rowIndex); + return rowIndex; + } + + public final R removeRow(int rowIndex) { + SwingUtil.ensureRowIndex(this, rowIndex); + + List<R> data = getRows(); + + R result = data.remove(rowIndex); + + fireTableRowsDeleted(rowIndex, rowIndex); + return result; + } + + protected void onRowsChanged(List<R> data) { + // by default do nothing + } + + protected void onRowAdded(int rowIndex, R newValue) { + // by default do nothing + } + + public final int getRowIndex(R row) { + int result = rows == null ? -1 : rows.indexOf(row); + return result; + } + + public final R getEntry(int rowIndex) { + SwingUtil.ensureRowIndex(this, rowIndex); + List<R> data = getRows(); + R result = data == null ? null : data.get(rowIndex); + return result; + } + + public final void setNoneEditableCols(ColumnIdentifier<?>... noneEditableCols) { + this.noneEditableCols = Sets.newHashSet(noneEditableCols); + } + + @Override + public final int getRowCount() { + return rows == null ? 0 : rows.size(); + } + + @Override + public final int getColumnCount() { + return identifiers.size(); + } + + @Override + public final Object getValueAt(int rowIndex, int columnIndex) { + R entry = getEntry(rowIndex); + ColumnIdentifier<R> identifier = getIdentifier(columnIndex); + if (log.isDebugEnabled()) { + log.debug("columnIndex: " + columnIndex + " :: " + identifier.getPropertyName()); + } + Object result = identifier.getValue(entry); + return result; + } + + @Override + public final void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if (log.isDebugEnabled()) { + log.debug("setValueAt " + aValue); + } + R entry = getEntry(rowIndex); + ColumnIdentifier<R> identifier = getIdentifier(columnIndex); + setValueAt(aValue, rowIndex, columnIndex, identifier, entry); + } + + @Override + public final boolean isCellEditable(int rowIndex, int columnIndex) { + ColumnIdentifier<R> identifier = getIdentifier(columnIndex); + boolean result = isCellEditable(rowIndex, columnIndex, identifier); + return result; + } + + protected void setValueAt(Object aValue, + int rowIndex, + int columnIndex, + ColumnIdentifier<R> propertyName, + R entry) { + if (log.isDebugEnabled()) { + log.debug("setValueAt " + aValue); + } + propertyName.setValue(entry, aValue); + } + + protected boolean isCellEditable(int rowIndex, + int columnIndex, + ColumnIdentifier<R> propertyName) { + boolean result = !noneEditableCols.contains(propertyName); + return result; + } + + public final void fireTableCellUpdated(int rowIndex, + ColumnIdentifier<R>... identifiers) { + for (ColumnIdentifier<R> identifier : identifiers) { + int columnIndex = this.identifiers.indexOf(identifier); + fireTableCellUpdated(rowIndex, columnIndex); + } + } + + public final void fireTableRowUpdatedShell(Set<R> shell) { + + int minRowIndex1 = getColumnCount(); + int maxRowIndex1 = 0; + + for (R r : shell) { + int rowIndex1 = getRowIndex(r); + minRowIndex1 = Math.min(minRowIndex1, rowIndex1); + maxRowIndex1 = Math.max(maxRowIndex1, rowIndex1); + } + fireTableRowsUpdated(minRowIndex1, maxRowIndex1); + } + + protected void collectShell(R row, Set<R> collectedRows) { + + // by default just add the incoming row + collectedRows.add(row); + } + + protected ColumnIdentifier<R> getIdentifier(int columnIndex) { + ColumnIdentifier<R> identifier = identifiers.get(columnIndex); + return identifier; + } +} Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/AbstractSelectTableAction.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/AbstractSelectTableAction.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/AbstractSelectTableAction.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/AbstractSelectTableAction.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,103 @@ +package fr.ifremer.shared.application.swing.table; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.shared.application.swing.util.ApplicationUIUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.AbstractAction; +import javax.swing.JTable; + +/** + * Abstract action to select a cell in a table. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public abstract class AbstractSelectTableAction<M extends AbstractApplicationTableModel> extends AbstractAction { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = + LogFactory.getLog(AbstractSelectTableAction.class); + + private final M model; + + private final JTable table; + + public AbstractSelectTableAction(M model, JTable table) { + this.model = model; + this.table = table; + } + + protected void doSelectCell(int rowIndex, int columnIndex) { + + if (log.isDebugEnabled()) { + log.debug("Will select cell at " + + getCellCoordinate(rowIndex, columnIndex)); + } + ApplicationUIUtil.doSelectCell(table, rowIndex, columnIndex); + } + + protected int getSelectedRow() { + int result = table.getSelectedRow(); + return result; + } + + protected int getSelectedColumn() { + int result = table.getSelectedColumn(); + return result; + } + + protected int getRowCount() { + return table.getRowCount(); + } + + protected int getColumnCount() { + return table.getColumnCount(); + } + + protected boolean isCellEditable(int rowIndex, int columnIndex) { + boolean result; + result = rowIndex > -1 && columnIndex > -1 && +// rowIndex < getRowCount() && columnIndex < getColumnCount() && + table.isCellEditable(rowIndex, columnIndex); + return result; + } + + protected boolean isCreateNewRow() { + return model.isCreateNewRow(); + } + + protected String getCellCoordinate(int rowIndex, int columnIndex) { + return " [" + rowIndex + ", " + columnIndex + "]"; + } + + protected void addNewRow() { + model.addNewRow(); + } +} Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/ColumnIdentifier.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/ColumnIdentifier.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/ColumnIdentifier.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,105 @@ +package fr.ifremer.shared.application.swing.table; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.shared.application.ApplicationDataUtil; + +import java.io.Serializable; + +/** + * To represent a column of a table. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ColumnIdentifier<R> implements Serializable { + + private static final long serialVersionUID = 1L; + + private final String propertyName; + + private final String headerI18nKey; + + private final String headerTipI18nKey; + + public static <R> ColumnIdentifier<R> newId(String propertyName, + String headerI18nKey, + String headerTipI18nKey) { + return new ColumnIdentifier<R>(propertyName, + headerI18nKey, + headerTipI18nKey); + } + + public static <R> ColumnIdentifier<R> newReadOnlyId(String propertyName, + String headerI18nKey, + String headerTipI18nKey) { + return new ColumnIdentifier<R>(propertyName, + headerI18nKey, + headerTipI18nKey) { + + private static final long serialVersionUID = 1L; + + @Override + public void setValue(R entry, Object value) { + // no set + } + }; + } + + protected ColumnIdentifier(String propertyName, + String headerI18nKey, + String headerTipI18nKey) { + this.propertyName = propertyName; + this.headerI18nKey = headerI18nKey; + this.headerTipI18nKey = headerTipI18nKey; + } + + public String getPropertyName() { + return propertyName; + } + + public String getHeaderI18nKey() { + return headerI18nKey; + } + + public String getHeaderTipI18nKey() { + return headerTipI18nKey; + } + + public Object getValue(R entry) { + Object result = null; + if (propertyName != null && entry != null) { + result = ApplicationDataUtil.getProperty(entry, propertyName); + } + return result; + } + + public void setValue(R entry, Object value) { + if (propertyName != null) { + ApplicationDataUtil.setProperty(entry, propertyName, value); + } + } + +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/ColumnIdentifier.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToNextEditableCellAction.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableCellAction.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToNextEditableCellAction.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToNextEditableCellAction.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,102 @@ +package fr.ifremer.shared.application.swing.table; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTable; +import java.awt.event.ActionEvent; + +/** + * Action to select next editable cell in a table. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class MoveToNextEditableCellAction<M extends AbstractApplicationTableModel> extends AbstractSelectTableAction<M> { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = + LogFactory.getLog(MoveToNextEditableCellAction.class); + + public static <M extends AbstractApplicationTableModel> MoveToNextEditableCellAction<M> newAction(M model, JTable table) { + return new MoveToNextEditableCellAction<M>(model, table); + } + + protected MoveToNextEditableCellAction(M model, JTable table) { + super(model, table); + } + + @Override + public void actionPerformed(ActionEvent e) { + + int currentRow = getSelectedRow(); + int currentColumn = getSelectedColumn(); + + if (log.isDebugEnabled()) { + log.debug("Move to previous editable cell " + + getCellCoordinate(currentRow, currentColumn)); + } + + int columnCount = getColumnCount(); + + int rowCount = getRowCount(); + + if (currentRow <= rowCount || currentColumn <= columnCount) { + + // go to next cell + currentColumn++; + boolean canSelect = true; + + // select next cell + if (currentColumn >= columnCount) { + + // no more cell, so will move to next editable column on next row + currentColumn = 0; + currentRow++; + + if (currentRow == rowCount) { + + if (isCreateNewRow()) { + + // create a new row in model + addNewRow(); + } else { + + // can not create new row, so do nothing + canSelect = false; + } + } + } + + if (canSelect) { + doSelectCell(currentRow, currentColumn); + } + } + } +} \ No newline at end of file Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToNextEditableRowAction.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToNextEditableRowAction.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToNextEditableRowAction.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToNextEditableRowAction.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,95 @@ +package fr.ifremer.shared.application.swing.table; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTable; +import java.awt.event.ActionEvent; + +/** + * Action to select next editable row in a table. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class MoveToNextEditableRowAction<M extends AbstractApplicationTableModel> extends AbstractSelectTableAction<M> { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = + LogFactory.getLog(MoveToNextEditableRowAction.class); + + public static <M extends AbstractApplicationTableModel> MoveToNextEditableRowAction<M> newAction(M model, JTable table) { + return new MoveToNextEditableRowAction<M>(model, table); + } + + protected MoveToNextEditableRowAction(M model, JTable table) { + super(model, table); + } + + @Override + public void actionPerformed(ActionEvent e) { + int currentRow = getSelectedRow(); + int currentColumn = getSelectedColumn(); + + if (log.isDebugEnabled()) { + log.debug("Move to next row editable cell " + + getCellCoordinate(currentRow, currentColumn)); + } + + int rowCount = getRowCount(); + + // I commented the part of the code to skip the not editable cells (ref #2704) +// while (currentRow < rowCount) { + if (currentRow < rowCount) { + // go to next cell + currentRow++; + boolean canSelect = true; + + // select next cell + if (currentRow >= rowCount) { + + if (log.isDebugEnabled()) { + log.debug("No next row"); + } + if (isCreateNewRow()) { + + // create a new row in model + addNewRow(); + + } else { + canSelect = false; + } + } + + if (canSelect) { + doSelectCell(currentRow, currentColumn); + } + } + } +} Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToPreviousEditableCellAction.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToPreviousEditableCellAction.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToPreviousEditableCellAction.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToPreviousEditableCellAction.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,92 @@ +package fr.ifremer.shared.application.swing.table; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTable; +import java.awt.event.ActionEvent; + +/** + * Action to select previous editable cell in a table. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class MoveToPreviousEditableCellAction<M extends AbstractApplicationTableModel> extends AbstractSelectTableAction<M> { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = + LogFactory.getLog(MoveToPreviousEditableCellAction.class); + + public static <M extends AbstractApplicationTableModel> MoveToPreviousEditableCellAction<M> newAction(M model, JTable table) { + return new MoveToPreviousEditableCellAction<M>(model, table); + } + + protected MoveToPreviousEditableCellAction(M model, JTable table) { + super(model, table); + } + + @Override + public void actionPerformed(ActionEvent e) { + int currentRow = getSelectedRow(); + int currentColumn = getSelectedColumn(); + + if (log.isDebugEnabled()) { + log.debug("Move to previous editable cell, " + + getCellCoordinate(currentRow, currentColumn)); + } + + int columnCount = getColumnCount(); + + // I commented the part of the code to skip the not editable cells (ref #2704) +// while (currentRow > 0 || currentColumn > 0) { + if (currentRow > 0 || currentColumn > 0) { + + // go to next cell + currentColumn--; + + // select next cell + if (currentColumn < 0) { + + currentColumn = columnCount - 1; + currentRow--; + } + +// if (isCellEditable(currentRow, currentColumn)) { + doSelectCell(currentRow, currentColumn); +// break; +// } else { +// if (log.isDebugEnabled()) { +// log.debug("Cell not editable at " + +// getCellCoordinate(currentRow, currentColumn)); +// } +// } + } + } +} \ No newline at end of file Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToPreviousEditableRowAction.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/table/MoveToPreviousEditableRowAction.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToPreviousEditableRowAction.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/table/MoveToPreviousEditableRowAction.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,88 @@ +package fr.ifremer.shared.application.swing.table; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTable; +import java.awt.event.ActionEvent; + +/** + * Action to select previous editable row in a table. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class MoveToPreviousEditableRowAction<M extends AbstractApplicationTableModel> extends AbstractSelectTableAction<M> { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = + LogFactory.getLog(MoveToPreviousEditableRowAction.class); + + public static <M extends AbstractApplicationTableModel> MoveToPreviousEditableRowAction<M> newAction(M model, JTable table) { + return new MoveToPreviousEditableRowAction<M>(model, table); + } + + protected MoveToPreviousEditableRowAction(M model, JTable table) { + super(model, table); + } + + @Override + public void actionPerformed(ActionEvent e) { + + int currentRow = getSelectedRow(); + int currentColumn = getSelectedColumn(); + + if (log.isDebugEnabled()) { + log.debug("Move to previous row editable cell " + + getCellCoordinate(currentRow, currentColumn)); + } + + int rowCount = getRowCount(); + + // I commented the part of the code to skip the not editable cells (ref #2704) +// while (currentRow > 0) { + if (currentRow > 0) { + + // go to next cell + currentRow--; +// boolean canSelect = isCellEditable(currentRow, currentColumn); +// +// if (canSelect) { + doSelectCell(currentRow, currentColumn); + +// break; +// } else { +// if (log.isDebugEnabled()) { +// log.debug("Cell not editable at " + +// getCellCoordinate(currentRow, currentColumn)); +// } +// } + } + } +} Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationColorHighlighter.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationColorHighlighter.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationColorHighlighter.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,66 @@ +package fr.ifremer.shared.application.swing.util; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.jdesktop.swingx.decorator.AbstractHighlighter; +import org.jdesktop.swingx.decorator.ComponentAdapter; +import org.jdesktop.swingx.decorator.HighlightPredicate; +import org.jdesktop.swingx.util.PaintUtils; + +import java.awt.Color; +import java.awt.Component; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationColorHighlighter extends AbstractHighlighter { + + protected Color color; + + protected boolean foreground; + + public ApplicationColorHighlighter(HighlightPredicate predicate, Color color, boolean foreground) { + super(predicate); + this.color = color; + this.foreground = foreground; + } + + @Override + protected Component doHighlight(Component component, ComponentAdapter adapter) { + + if (foreground) { + component.setForeground(color); + + } else { + component.setBackground(color); + if (adapter.isSelected()) { + component.setForeground(PaintUtils.computeForeground(color)); + } + } + + return component; + } +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationColorHighlighter.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationErrorHelper.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/TuttiErrorHelper.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationErrorHelper.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationErrorHelper.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,113 @@ +package fr.ifremer.shared.application.swing.util; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.shared.application.ApplicationBusinessException; +import fr.ifremer.shared.application.swing.ApplicationUIContext; +import org.jdesktop.swingx.JXErrorPane; +import org.jdesktop.swingx.error.ErrorInfo; +import org.jdesktop.swingx.error.ErrorReporter; +import org.nuiton.csv.ImportRuntimeException; + +import javax.swing.JOptionPane; + +import static org.nuiton.i18n.I18n._; + +/** + * Helper to display errors. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationErrorHelper implements ErrorReporter { + + protected ApplicationUIContext context; + + public ApplicationErrorHelper(ApplicationUIContext context) { + this.context = context; + } + + /** + * Display a user friendly error frame. + * + * @param message message for user + * @param cause exception cause + */ + public void showErrorDialog(String message, Throwable cause) { + + if (cause == null) { + JOptionPane.showMessageDialog(context.getMainUI(), "<html><body>" + message + "</body></html>", + _("application.error.ui.business.error"), + JOptionPane.ERROR_MESSAGE); + } else if (cause instanceof ApplicationBusinessException) { + JOptionPane.showMessageDialog(context.getMainUI(), "<html><body>" + cause.getMessage() + "</body></html>", + _("application.error.ui.business.error"), + JOptionPane.ERROR_MESSAGE); + } else if (cause instanceof ImportRuntimeException) { + JOptionPane.showMessageDialog(context.getMainUI(), cause.getMessage(), + _("application.error.ui.business.error"), + JOptionPane.ERROR_MESSAGE); + } else { + + JXErrorPane pane = new JXErrorPane(); + ErrorInfo info = new ErrorInfo(_("application.error.ui.other.error"), + _("application.error.errorpane.htmlmessage", message), null, null, + cause, null, null); + pane.setErrorInfo(info); + pane.setErrorReporter(this); + JXErrorPane.showDialog(context.getActionUI(), pane); + } + + } + + /** + * Display a user friendly error frame. + * + * @param message message for user + */ + public void showErrorDialog(String message) { + showErrorDialog(message, null); + } + + @Override + public void reportError(ErrorInfo errorInfo) throws NullPointerException { + + showErrorDialog(errorInfo.getBasicErrorMessage(), errorInfo.getErrorException()); + } + + /** + * Display a user friendly warning frame. + * + * @param message message for user + */ + public void showWarningDialog(String message) { + + JOptionPane.showMessageDialog(context.getMainUI(), "<html><body>" + message + "</body></html>", + _("application.error.ui.business.warning"), + JOptionPane.WARNING_MESSAGE); + + } + +} Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationExceptionHandler.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/TuttiExceptionHandler.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationExceptionHandler.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationExceptionHandler.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,91 @@ +package fr.ifremer.shared.application.swing.util; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.shared.application.ApplicationTechnicalException; +import jaxx.runtime.swing.JAXXRuntimeException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Global exception handler. + * <p/> + * Catch all application uncaught and display it in a custom JoptionPane + * or JXErrorPane. + * <p/> + * See http://stackoverflow.com/a/4448569/1165234 for details. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationExceptionHandler implements Thread.UncaughtExceptionHandler { + + private static final Log log = + LogFactory.getLog(ApplicationExceptionHandler.class); + + final ApplicationErrorHelper errorHelper; + + public ApplicationExceptionHandler(ApplicationErrorHelper errorHelper) { + this.errorHelper = errorHelper; + } + + @Override + public void uncaughtException(Thread t, Throwable ex) { + handleException(t.getName(), ex); + } + + public void handle(Throwable thrown) { + // for EDT exceptions + handleException(Thread.currentThread().getName(), thrown); + } + + protected void handleException(String tname, Throwable ex) { + if (log.isErrorEnabled()) { + log.error("Global application exception [" + tname + "]", ex); + } + + Throwable cause = getCause(ex); + + showErrorDialog(cause.getMessage(), cause); + } + + protected Throwable getCause(Throwable ex) { + + Throwable cause = ex; + + if (cause instanceof ApplicationTechnicalException) { + cause = cause.getCause(); + } + + if (cause instanceof JAXXRuntimeException) { + cause = cause.getCause(); + } + return cause; + } + + public void showErrorDialog(String message, Throwable cause) { + errorHelper.showErrorDialog(message, cause); + } +} Added: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationUIUtil.java =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationUIUtil.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationUIUtil.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,216 @@ +package fr.ifremer.shared.application.swing.util; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.shared.application.ApplicationTechnicalException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTable; +import org.jdesktop.swingx.decorator.HighlightPredicate; +import org.jdesktop.swingx.decorator.Highlighter; + +import javax.swing.JTable; +import java.awt.Color; +import java.awt.Desktop; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + +import static org.nuiton.i18n.I18n._; + +/** + * Useful ui methods. + * <p/> + * Created on 11/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.0 + */ +public class ApplicationUIUtil { + + /** Logger. */ + private static final Log log = LogFactory.getLog(ApplicationUIUtil.class); + + protected ApplicationUIUtil() { + // avoid instanciate util class + } + + public static Highlighter newBackgroundColorHighlighter(HighlightPredicate predicate, Color color) { + return new ApplicationColorHighlighter(predicate, color, false); + } + + public static Highlighter newForegroundColorHighlighter(HighlightPredicate predicate, Color color) { + return new ApplicationColorHighlighter(predicate, color, true); + } + + public static void openLink(URL url) { + try { + openLink(url.toURI()); + } catch (URISyntaxException e) { + throw new ApplicationTechnicalException(_("application.error.cannot.open.link", url), e); + } + } + + public static Desktop getDesktopForBrowse() { + + if (!Desktop.isDesktopSupported()) { + throw new ApplicationTechnicalException( + _("application.error.desktop.not.supported")); + } + + Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.BROWSE)) { + + throw new ApplicationTechnicalException( + _("application.error.desktop.browse.not.supported")); + } + + return desktop; + } + + public static void openLink(URI uri) { + + Desktop desktop = getDesktopForBrowse(); + + try { + + desktop.browse(uri); + } catch (Exception e) { + + throw new ApplicationTechnicalException( + _("application.error.cannot.open.link", uri), e); + } + } + + public static Desktop getDesktopForMail() { + + if (!Desktop.isDesktopSupported()) { + throw new ApplicationTechnicalException( + _("application.error.desktop.not.supported")); + } + + Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.MAIL)) { + + throw new ApplicationTechnicalException( + _("application.error.desktop.mail.not.supported")); + } + + return desktop; + } + + public static void mail(String subject, String body) { + + Desktop desktop = getDesktopForMail(); + + try { + URI mailtoURI = new URI("mailto", null, null, "subject=" + subject + "&body=" + body, null); + desktop.mail(mailtoURI); + + } catch (Exception e) { + + throw new ApplicationTechnicalException( + _("application.error.cannot.mail"), e); + } + } + + public static void selectFirstCellOnFirstRowAndStopEditing(JXTable table) { + + // select first cell + doSelectCell(table, 0, 0); + + if (table.isEditing()) { + + // but no edit it + table.getCellEditor().stopCellEditing(); + } + } + + public static void selectFirstCellOnLastRow(JXTable table) { + + // select first cell + doSelectCell(table, table.getRowCount() - 1, 0); + } + + public static void selectFirstCellOnRow(JXTable table, int row, boolean stopEdit) { + + // select first cell + doSelectCell(table, row, 0); + + if (stopEdit && table.isEditing()) { + + table.getCellEditor().stopCellEditing(); + } + } + + public static void doSelectCell(JTable table, + int rowIndex, + int columnIndex) { + + int rowCount = table.getRowCount(); + if (rowCount == 0) { + + // no row, can not selected any cell + if (log.isWarnEnabled()) { + log.warn("No row in table, can not select any cell"); + } + return; + } + int columnCount = table.getColumnCount(); + if (columnCount == 0) { + + // no column, can not selected any cell + if (log.isWarnEnabled()) { + log.warn("No column in table, can not select any cell"); + } + return; + } + if (columnIndex > columnCount) { + if (log.isWarnEnabled()) { + log.warn(String.format("ColumnIndex: %s is more than columnCount %s", columnIndex, columnCount)); + } + columnIndex = columnCount - 1; + } + if (columnIndex < 0) { + columnIndex = 0; + } + if (rowIndex >= rowCount) { + if (log.isWarnEnabled()) { + log.warn(String.format("RowIndex: %s is more than rowCount %s", rowIndex, rowCount)); + } + rowIndex = rowCount - 1; + } + if (rowIndex < 0) { + rowIndex = 0; + } + + table.setColumnSelectionInterval(columnIndex, columnIndex); + table.setRowSelectionInterval(rowIndex, rowIndex); + table.editCellAt(rowIndex, columnIndex); + } + +} Property changes on: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/ApplicationUIUtil.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/CloseableUI.java (from rev 1377, trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/CloseableUI.java) =================================================================== --- application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/CloseableUI.java (rev 0) +++ application/trunk/application-swing/src/main/java/fr/ifremer/shared/application/swing/util/CloseableUI.java 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,44 @@ +package fr.ifremer.shared.application.swing.util; + +/* + * #%L + * Ifremer shared :: Application Swing + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Place this contract on any handler of ui that need some check before closing. + * + * Contract to close an ui. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0 + */ +public interface CloseableUI { + + /** + * Try to quit UI. + * + * @return {@code true} if ui is safe to quit, {@code false} otherwise + * (means must stay on it). + */ + boolean quitUI(); +} Added: application/trunk/application-swing/src/main/resources/i18n/application-swing_en_GB.properties =================================================================== --- application/trunk/application-swing/src/main/resources/i18n/application-swing_en_GB.properties (rev 0) +++ application/trunk/application-swing/src/main/resources/i18n/application-swing_en_GB.properties 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,21 @@ +application.action.create.error= +application.common.askBeforeDelete.help= +application.common.askCancelEditBeforeLeaving.help= +application.common.askCancelEditBeforeLeaving.title= +application.common.askOverwriteFile.help= +application.common.askOverwriteFile.message= +application.common.askOverwriteFile.title= +application.common.askSaveBeforeLeaving.help= +application.common.askSaveBeforeLeaving.title= +application.common.datefield.tip= +application.error.cannot.mail= +application.error.cannot.open.link= +application.error.desktop.browse.not.supported= +application.error.desktop.mail.not.supported= +application.error.desktop.not.supported= +application.error.errorpane.htmlmessage= +application.error.ui.business.error= +application.error.ui.business.warning= +application.error.ui.other.error= +application.message.action.running= +application.title.actionUI= Property changes on: application/trunk/application-swing/src/main/resources/i18n/application-swing_en_GB.properties ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/application-swing/src/main/resources/i18n/application-swing_fr_FR.properties =================================================================== --- application/trunk/application-swing/src/main/resources/i18n/application-swing_fr_FR.properties (rev 0) +++ application/trunk/application-swing/src/main/resources/i18n/application-swing_fr_FR.properties 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,21 @@ +application.action.create.error=Erreur à l'instanciation de l'action %s +application.common.askBeforeDelete.help=Que voulez-vous faire ?<ul><li><strong>Annuler</strong> pour ne pas supprimer</li><li><strong>OK</strong> pour supprimer l'objet en question</li></ul> +application.common.askCancelEditBeforeLeaving.help=Que voulez-vous faire ?<ul><li><strong>Annuler</strong> pour rester sur cet écran</li><li><strong>OK</strong> pour quitter l'écran en abandonnant les modifications</li></ul> +application.common.askCancelEditBeforeLeaving.title=Modifications non enregistrées mais invalides +application.common.askOverwriteFile.help=Que voulez-vous faire ?<ul><li><strong>Annuler</strong> pour ne pas écraser le fichier et annuler l'opération</li><li><strong>Oui</strong> pour écraser le fichier et continuer l'opération</li></ul> +application.common.askOverwriteFile.message=Le fichier %s existe déjà, confirmer pour l'écraser +application.common.askOverwriteFile.title=Confirmer l'écrasement d'un fichier... +application.common.askSaveBeforeLeaving.help=Que voulez-vous faire?<ul><li><strong>Annuler</strong> pour rester sur cet écran</li><li><strong>Non</strong> pour quitter l'écran en abandonnant les modifications en cours</li><li><strong>Oui</strong> pour quitter l'écran après enregistrement des modifications</li></ul> +application.common.askSaveBeforeLeaving.title=Modifications non enregistrées +application.common.datefield.tip=Format attendu \: %s +application.error.cannot.mail=Erreur lors de l'ouverture du client mail +application.error.cannot.open.link=Impossible d'ouvrir le fichier %s +application.error.desktop.browse.not.supported=Le navigateur n'a pas pu être ouvert. Vérifiez que vous avez défini un navigateur par défaut dans votre système +application.error.desktop.mail.not.supported=Le client mail n'a pas pu être ouvert. Vérifiez que vous avez défini un client mail par défaut dans votre système +application.error.desktop.not.supported=Votre système ne permet pas d'ouvrir des liens ou fichiers en dehors de l'application +application.error.errorpane.htmlmessage=<html><body><b>Une erreur s'est produite</b>\:<br/>%s</body></html> +application.error.ui.business.error=Erreur +application.error.ui.business.warning=Avertissement +application.error.ui.other.error=Erreur +application.message.action.running=<html>Action <strong>%s</strong> en cours d'exécution...</html> +application.title.actionUI=%s - v %s [%s] Property changes on: application/trunk/application-swing/src/main/resources/i18n/application-swing_fr_FR.properties ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: application/trunk/pom.xml =================================================================== --- application/trunk/pom.xml (rev 0) +++ application/trunk/pom.xml 2013-11-24 22:44:33 UTC (rev 1379) @@ -0,0 +1,676 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +#%L +Ifremer shared +%% +Copyright (C) 2013 Ifremer, CodeLutin, Tony CHEMIT +%% +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public +License along with this program. If not, see +<http://www.gnu.org/licenses/gpl-3.0.html>. +#L% +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>mavenpom4redmine</artifactId> + <version>4.3</version> + </parent> + + <groupId>fr.ifremer.shared</groupId> + <artifactId>shared-pom</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <name>Ifremer shared</name> + <description> + Module commun à l'écriture d'applications Ifremer. + </description> + <url>http://forge.codelutin.com/projects/tutti</url> + <inceptionYear>2013</inceptionYear> + <organization> + <name>Ifremer</name> + <url>http://www.ifremer.fr/</url> + </organization> + <licenses> + <license> + <name>General Public License (GPL)</name> + <url>http://www.gnu.org/licenses/gpl.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <developers> + <developer> + <id>chemit</id> + <name>Tony Chemit</name> + <email>chemit at codelutin dot com</email> + <organization>CodeLutin</organization> + <organizationUrl>http://www.codelutin.com</organizationUrl> + <roles> + <role>developer</role> + </roles> + <timezone>Europe/Paris</timezone> + </developer> + </developers> + + <modules> + <module>application</module> + <module>application-swing</module> + </modules> + + <scm> + <url>http://svn.forge.codelutin.com/svn/tutti/application/trunk</url> + <connection> + scm:svn:http://svn.forge.codelutin.com/svn/tutti/application/trunk + </connection> + <developerConnection> + scm:svn:http://svn.forge.codelutin.com/svn/tutti/application/trunk + </developerConnection> + </scm> + <distributionManagement> + <site> + <id>${platform}</id> + <url>${our.site.repository}/tutti/${projectId}</url> + </site> + <snapshotRepository> + <id>nuiton-nexus-deploy</id> + <url> + http://nexus.nuiton.org/nexus/content/repositories/tutti-snapshot + </url> + </snapshotRepository> + </distributionManagement> + + <properties> + + <platform>forge.codelutin.com</platform> + <projectId>tutti</projectId> + + <!-- Java version --> + <!--<maven.compiler.source>1.7</maven.compiler.source>--> + <!--<maven.compiler.target>1.7</maven.compiler.target>--> + <!--<signatureArtifactId>java17</signatureArtifactId>--> + <!--<signatureVersion>1.0</signatureVersion>--> + + <!-- libraries version --> + + <nuitonI18nVersion>2.5.2</nuitonI18nVersion> + <nuitonConfigVersion>3.0-alpha-1</nuitonConfigVersion> + <nuitonCsvVersion>3.0-alpha-1</nuitonCsvVersion> + <nuitonDecoratorVersion>3.0-alpha-2</nuitonDecoratorVersion> + <nuitonUpdaterVersion>3.0-alpha-1</nuitonUpdaterVersion> + <nuitonUtilsVersion>2.7.1</nuitonUtilsVersion> + <nuitonValidatorVersion>3.0-alpha-1</nuitonValidatorVersion> + + <jaxxVersion>2.6-SNAPSHOT</jaxxVersion> + <swingXVersion>1.6.4</swingXVersion> + <xworkVersion>2.3.15.1</xworkVersion> + + <slf4jVersion>1.7.5</slf4jVersion> + + <i18n.bundles>fr_FR,en_GB</i18n.bundles> + <i18n.silent>true</i18n.silent> + + <!-- locales for the site generation, by default only french --> + <locales>fr</locales> + + <!-- do not relatize links in generated site --> + <relativizeDecorationLinks>false</relativizeDecorationLinks> + + <!-- license header configuration --> + <license.organizationName>Ifremer, CodeLutin</license.organizationName> + <license.licenseName>gpl_v3</license.licenseName> + + </properties> + + <repositories> + <repository> + <id>tutti-public-group</id> + <url>http://nexus.nuiton.org/nexus/content/groups/tutti-group/</url> + <snapshots> + <enabled>true</enabled> + <checksumPolicy>fail</checksumPolicy> + </snapshots> + <releases> + <enabled>true</enabled> + <checksumPolicy>fail</checksumPolicy> + </releases> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>tutti-public-group</id> + <url>http://nexus.nuiton.org/nexus/content/groups/tutti-group/</url> + <snapshots> + <enabled>true</enabled> + <checksumPolicy>fail</checksumPolicy> + </snapshots> + <releases> + <enabled>true</enabled> + <checksumPolicy>fail</checksumPolicy> + </releases> + </pluginRepository> + </pluginRepositories> + + <dependencyManagement> + <dependencies> + + <!-- librairies utils --> + + <dependency> + <groupId>org.milyn</groupId> + <artifactId>flute</artifactId> + <version>1.3</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-profiling</artifactId> + <version>2.7.1</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + <version>${nuitonUtilsVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-decorator</artifactId> + <version>${nuitonDecoratorVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-config</artifactId> + <version>${nuitonConfigVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-updater</artifactId> + <version>${nuitonUpdaterVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-csv</artifactId> + <version>${nuitonCsvVersion}</version> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>${guavaVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + <version>${nuitonI18nVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + <version>${nuitonValidatorVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + <version>${nuitonValidatorVersion}</version> + <scope>test</scope> + <classifier>tests</classifier> + </dependency> + + <dependency> + <groupId>org.apache.struts.xwork</groupId> + <artifactId>xwork-core</artifactId> + <version>${xworkVersion}</version> + </dependency> + + <!-- librairie Jaxx --> + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>${jaxxVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-validator</artifactId> + <version>${jaxxVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-application</artifactId> + <version>${jaxxVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-widgets</artifactId> + <version>${jaxxVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-config</artifactId> + <version>${jaxxVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>${jaxxVersion}</version> + <scope>test</scope> + <classifier>tests</classifier> + </dependency> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>jxlayer</artifactId> + <version>3.0.4</version> + <scope>compile</scope> + </dependency> + + <!-- swing widgets --> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-core</artifactId> + <version>${swingXVersion}</version> + </dependency> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-common</artifactId> + <version>${swingXVersion}</version> + </dependency> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-autocomplete</artifactId> + <version>${swingXVersion}</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-vfs2</artifactId> + <version>2.0</version> + <exclusions> + <exclusion> + <groupId>org.apache.maven.scm</groupId> + <artifactId>maven-scm-api</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.maven.scm</groupId> + <artifactId>maven-scm-provider-svnexe</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-core</artifactId> + <version>${hibernateVersion}</version> + </dependency> + + <dependency> + <groupId>fr.ifremer.adagio</groupId> + <artifactId>adagio-core-allegro</artifactId> + <version>${adagioVersion}</version> + <exclusions> + <exclusion> + <groupId>org.andromda.profiles.emf.uml2</groupId> + <artifactId>andromda-profile-common</artifactId> + </exclusion> + <exclusion> + <groupId>org.andromda.cartridges</groupId> + <artifactId>andromda-spring-cartridge</artifactId> + </exclusion> + <exclusion> + <groupId>org.andromda.cartridges</groupId> + <artifactId>andromda-hibernate-cartridge</artifactId> + </exclusion> + <exclusion> + <groupId>org.andromda.cartridges</groupId> + <artifactId>andromda-java-cartridge</artifactId> + </exclusion> + </exclusions> + </dependency> + + <!-- Logging --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4jVersion}</version> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-jcl</artifactId> + <version>${slf4jVersion}</version> + </dependency> + + <!-- Pour SPRING : --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <version>${spring.version}</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + <version>${spring.version}</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>${spring.version}</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-jdbc</artifactId> + <version>${spring.version}</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-tx</artifactId> + <version>${spring.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <version>${spring.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>${commonsIoVersion}</version> + </dependency> + + <dependency> + <groupId>org.eclipse.birt.runtime</groupId> + <artifactId>org.eclipse.birt.runtime</artifactId> + <version>${birtVersion}</version> + <exclusions> + <exclusion> + <groupId>milyn</groupId> + <artifactId>flute</artifactId> + </exclusion> + <exclusion> + <groupId>org.milyn</groupId> + <artifactId>flute</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>hsqldb</groupId> + <artifactId>hsqldb</artifactId> + <version>${jdbc.hsqldb.version}</version> + </dependency> + + <dependency> + <groupId>org.hsqldb</groupId> + <artifactId>hsqldb</artifactId> + <version>${hsqldb.version}</version> + </dependency> + + <dependency> + <groupId>com.esotericsoftware.yamlbeans</groupId> + <artifactId>yamlbeans</artifactId> + <version>1.06</version> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>1.9.5</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>com.itextpdf</groupId> + <artifactId>itextpdf</artifactId> + <version>5.4.1</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.xhtmlrenderer</groupId> + <artifactId>flying-saucer-pdf-itext5</artifactId> + <version>9.0.2</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.freemarker</groupId> + <artifactId>freemarker</artifactId> + <version>2.3.19</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>net.sf.bluecove</groupId> + <artifactId>bluecove</artifactId> + <version>${bluecoveVersion}</version> + </dependency> + + <dependency> + <groupId>net.sf.bluecove</groupId> + <artifactId>bluecove-gpl</artifactId> + <version>${bluecoveVersion}</version> + </dependency> + + </dependencies> + + </dependencyManagement> + + <build> + <pluginManagement> + <plugins> + + <!-- plugin site --> + <plugin> + <artifactId>maven-site-plugin</artifactId> + <dependencies> + <dependency> + <groupId>org.nuiton.jrst</groupId> + <artifactId>doxia-module-jrst</artifactId> + <version>${jrstPluginVersion}</version> + </dependency> + </dependencies> + </plugin> + + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>i18n-maven-plugin</artifactId> + <version>${nuitonI18nVersion}</version> + </plugin> + + <plugin> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <version>${jaxxVersion}</version> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>animal-sniffer-maven-plugin</artifactId> + <version>${animalSnifferPluginVersion}</version> + <configuration> + <signature> + <groupId>org.codehaus.mojo.signature</groupId> + <artifactId>java16-sun</artifactId> + <version>1.10</version> + </signature> + </configuration> + </plugin> + + </plugins> + </pluginManagement> + <extensions> + <!-- Enabling the use of scpexe with maven 3.0 --> + <extension> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-ssh-external</artifactId> + <version>1.0</version> + </extension> + </extensions> + </build> + + <reporting> + <excludeDefaults>true</excludeDefaults> + </reporting> + + <profiles> + + <profile> + <id>license-profile</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <build> + <defaultGoal>generate-resources</defaultGoal> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>license-maven-plugin</artifactId> + <executions> + <execution> + <id>update-file-header-on-pom</id> + <goals> + <goal>update-file-header</goal> + </goals> + <phase>generate-resources</phase> + <configuration> + <roots> + <root>${project.basedir}</root> + </roots> + <includes> + <include>pom.xml</include> + </includes> + <addSvnKeyWords>false</addSvnKeyWords> + <verbose>false</verbose> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + + <profile> + <id>reporting</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <reporting> + <plugins> + + <plugin> + <artifactId>maven-project-info-reports-plugin</artifactId> + <version>${projectInfoReportsPluginVersion}</version> + <reportSets> + <reportSet> + <reports> + <report>project-team</report> + <report>mailing-list</report> + <report>cim</report> + <report>issue-tracking</report> + <report>license</report> + <report>scm</report> + <report>dependencies</report> + <report>dependency-convergence</report> + <report>dependency-info</report> + <report>plugin-management</report> + <report>plugins</report> + <report>dependency-management</report> + <report>summary</report> + </reports> + </reportSet> + </reportSets> + </plugin> + + </plugins> + </reporting> + + </profile> + + <profile> + <id>update-file-header</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <properties> + <license.descriptor>src/license/project.xml</license.descriptor> + </properties> + <build> + <defaultGoal>process-resources</defaultGoal> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>license-maven-plugin</artifactId> + <executions> + <execution> + <id>update-file-header</id> + <goals> + <goal>update-file-header</goal> + </goals> + <configuration> + <addSvnKeyWords>true</addSvnKeyWords> + <excludes> + <exclude>**/i18n/*.properties</exclude> + <exclude>**/help/*.properties</exclude> + <exclude>**/THIRD-PARTY.properties</exclude> + <!-- since sh scripts must begins by the line #!/bin/sh, + can not use the mojo for the mojo --> + <exclude>**/*.sh</exclude> + </excludes> + </configuration> + <phase>process-resources</phase> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + + </profiles> +</project> Property changes on: application/trunk/pom.xml ___________________________________________________________________ Added: svn:mime-type + text/xml Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native