From kmorin@users.forge.codelutin.com Thu Dec 13 18:13:47 2012 From: kmorin@users.forge.codelutin.com To: tutti-commits@list.forge.codelutin.com Subject: [Tutti-commits] r57 - in trunk/tutti-ui-swing/src/main: java/fr/ifremer/tutti/ui/swing/content/operation/species java/fr/ifremer/tutti/ui/swing/util java/fr/ifremer/tutti/ui/swing/util/editor resources/i18n Date: Thu, 13 Dec 2012 18:13:46 +0100 Message-ID: <20121213171346.DD26A15954@nuiton.codelutin.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============3726849494443812617==" --===============3726849494443812617== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Author: kmorin Date: 2012-12-13 18:13:46 +0100 (Thu, 13 Dec 2012) New Revision: 57 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/57 Log: create comment editor Added: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/Componen= tMover.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/Componen= tResizer.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/L= ongTextCellComponent.java trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/L= ongTextEditorUI.css trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/L= ongTextEditorUI.jaxx trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/L= ongTextEditorUIHandler.java Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/opera= tion/species/SpeciesBatchUI.jaxx trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/opera= tion/species/SpeciesBatchUIHandler.java trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.properti= es Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/conten= t/operation/species/SpeciesBatchUI.jaxx =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/oper= ation/species/SpeciesBatchUI.jaxx 2012-12-13 15:37:44 UTC (rev 56) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/oper= ation/species/SpeciesBatchUI.jaxx 2012-12-13 17:13:46 UTC (rev 57) @@ -30,6 +30,7 @@ fr.ifremer.tutti.ui.swing.TuttiUIContext fr.ifremer.tutti.ui.swing.content.operation.FishingOperationsUI fr.ifremer.tutti.ui.swing.content.operation.species.SpeciesFrequencyUI + fr.ifremer.tutti.ui.swing.util.editor.LongTextEditorUI =20 org.jdesktop.swingx.JXTable =20 @@ -76,6 +77,8 @@ =20 + =20 + =20 =20 Modified: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/conten= t/operation/species/SpeciesBatchUIHandler.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/oper= ation/species/SpeciesBatchUIHandler.java 2012-12-13 15:37:44 UTC (rev 56) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/content/oper= ation/species/SpeciesBatchUIHandler.java 2012-12-13 17:13:46 UTC (rev 57) @@ -41,6 +41,7 @@ import fr.ifremer.tutti.ui.swing.content.operation.FishingOperationsUI; import fr.ifremer.tutti.ui.swing.util.TuttiBeanMonitor; import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; +import fr.ifremer.tutti.ui.swing.util.editor.LongTextCellComponent; import fr.ifremer.tutti.ui.swing.util.table.AbstractTuttiTableUIHandler; import fr.ifremer.tutti.ui.swing.util.table.TableRowModificationListener; import jaxx.runtime.SwingUtil; @@ -299,6 +300,8 @@ { // Comment column =20 addColumnToModel(columnModel, + LongTextCellComponent.newEditor(ui.getLongTextE= ditorUI()), + LongTextCellComponent.newRender(), SpeciesBatchTableModel.COMMENT); } =20 Added: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/Comp= onentMover.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/Compone= ntMover.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/Compone= ntMover.java 2012-12-13 17:13:46 UTC (rev 57) @@ -0,0 +1,375 @@ +package fr.ifremer.tutti.ui.swing.util; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; + +/** + * This class allows you to move a Component by using a mouse. The Component + * moved can be a high level Window (ie. Window, Frame, Dialog) in which ca= se + * the Window is moved within the desktop. Or the Component can belong to a + * Container in which case the Component is moved within the Container. + * + * When moving a Window, the listener can be added to a child Component of + * the Window. In this case attempting to move the child will result in the + * Window moving. For example, you might create a custom "Title Bar" for an + * undecorated Window and moving of the Window is accomplished by moving the + * title bar only. Multiple components can be registered as "window movers". + * + * Components can be registered when the class is created. Additional + * components can be added at any time using the registerComponent() method. + */ +public class ComponentMover extends MouseAdapter +{ + private Insets dragInsets =3D new Insets(0, 0, 0, 0); + private Dimension snapSize =3D new Dimension(1, 1); + private Insets edgeInsets =3D new Insets(0, 0, 0, 0); + private boolean changeCursor =3D true; + private boolean autoLayout =3D false; + + private Class destinationClass; + private Component destinationComponent; + private Component destination; + private Component source; + + private Point pressed; + private Point location; + + private Cursor originalCursor; + private boolean autoscrolls; + private boolean potentialDrag; + + + /** + * Constructor for moving individual components. The components must be + * regisetered using the registerComponent() method. + */ + public ComponentMover() + { + } + + /** + * Constructor to specify a Class of Component that will be moved when + * drag events are generated on a registered child component. The events + * will be passed to the first ancestor of this specified class. + * + * @param destinationClass the Class of the ancestor component + * @param component the Components to be registered for forwarding + * drag events to the ancestor Component. + */ + public ComponentMover(Class destinationClass, Component... components) + { + this.destinationClass =3D destinationClass; + registerComponent( components ); + } + + /** + * Constructor to specify a parent component that will be moved when drag + * events are generated on a registered child component. + * + * @param destinationComponent the component drage events should be forwa= reded to + * @param components the Components to be registered for forwarding drag + * events to the parent component to be moved + */ + public ComponentMover(Component destinationComponent, Component... componen= ts) + { + this.destinationComponent =3D destinationComponent; + registerComponent( components ); + } + + /** + * Get the auto layout property + * + * @return the auto layout property + */ + public boolean isAutoLayout() + { + return autoLayout; + } + + /** + * Set the auto layout property + * + * @param autoLayout when true layout will be invoked on the parent conta= iner + */ + public void setAutoLayout(boolean autoLayout) + { + this.autoLayout =3D autoLayout; + } + + /** + * Get the change cursor property + * + * @return the change cursor property + */ + public boolean isChangeCursor() + { + return changeCursor; + } + + /** + * Set the change cursor property + * + * @param changeCursor when true the cursor will be changed to the + * Cursor.MOVE_CURSOR while the mouse is pressed + */ + public void setChangeCursor(boolean changeCursor) + { + this.changeCursor =3D changeCursor; + } + + /** + * Get the drag insets + * + * @return the drag insets + */ + public Insets getDragInsets() + { + return dragInsets; + } + + /** + * Set the drag insets. The insets specify an area where mouseDragged + * events should be ignored and therefore the component will not be moved. + * This will prevent these events from being confused with a + * MouseMotionListener that supports component resizing. + * + * @param dragInsets + */ + public void setDragInsets(Insets dragInsets) + { + this.dragInsets =3D dragInsets; + } + + /** + * Get the bounds insets + * + * @return the bounds insets + */ + public Insets getEdgeInsets() + { + return edgeInsets; + } + + /** + * Set the edge insets. The insets specify how close to each edge of the p= arent + * component that the child component can be moved. Positive values means = the + * component must be contained within the parent. Negative values means the + * component can be moved outside the parent. + * + * @param edgeInsets + */ + public void setEdgeInsets(Insets edgeInsets) + { + this.edgeInsets =3D edgeInsets; + } + + /** + * Remove listeners from the specified component + * + * @param component the component the listeners are removed from + */ + public void deregisterComponent(Component... components) + { + for (Component component : components) + component.removeMouseListener( this ); + } + + /** + * Add the required listeners to the specified component + * + * @param component the component the listeners are added to + */ + public void registerComponent(Component... components) + { + for (Component component : components) + component.addMouseListener( this ); + } + + /** + * Get the snap size + * + * @return the snap size + */ + public Dimension getSnapSize() + { + return snapSize; + } + + /** + * Set the snap size. Forces the component to be snapped to + * the closest grid position. Snapping will occur when the mouse is + * dragged half way. + */ + public void setSnapSize(Dimension snapSize) + { + if (snapSize.width < 1 + || snapSize.height < 1) + throw new IllegalArgumentException("Snap sizes must be greater than 0"); + + this.snapSize =3D snapSize; + } + + /** + * Setup the variables used to control the moving of the component: + * + * source - the source component of the mouse event + * destination - the component that will ultimately be moved + * pressed - the Point where the mouse was pressed in the destination + * component coordinates. + */ + @Override + public void mousePressed(MouseEvent e) + { + source =3D e.getComponent(); + int width =3D source.getSize().width - dragInsets.left - dragInsets.righ= t; + int height =3D source.getSize().height - dragInsets.top - dragInsets.botto= m; + Rectangle r =3D new Rectangle(dragInsets.left, dragInsets.top, width, heig= ht); + + if (r.contains(e.getPoint())) + setupForDragging(e); + } + + private void setupForDragging(MouseEvent e) + { + source.addMouseMotionListener( this ); + potentialDrag =3D true; + + // Determine the component that will ultimately be moved + + if (destinationComponent !=3D null) + { + destination =3D destinationComponent; + } + else if (destinationClass =3D=3D null) + { + destination =3D source; + } + else // forward events to destination component + { + destination =3D SwingUtilities.getAncestorOfClass(destinationClass, sourc= e); + } + + pressed =3D e.getLocationOnScreen(); + location =3D destination.getLocation(); + + if (changeCursor) + { + originalCursor =3D source.getCursor(); + source.setCursor( Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR) ); + } + + // Making sure autoscrolls is false will allow for smoother dragging of + // individual components + + if (destination instanceof JComponent) + { + JComponent jc =3D (JComponent)destination; + autoscrolls =3D jc.getAutoscrolls(); + jc.setAutoscrolls( false ); + } + } + + /** + * Move the component to its new location. The dragged Point must be in + * the destination coordinates. + */ + @Override + public void mouseDragged(MouseEvent e) + { + Point dragged =3D e.getLocationOnScreen(); + int dragX =3D getDragDistance(dragged.x, pressed.x, snapSize.width); + int dragY =3D getDragDistance(dragged.y, pressed.y, snapSize.height); + + int locationX =3D location.x + dragX; + int locationY =3D location.y + dragY; + + // Mouse dragged events are not generated for every pixel the mouse + // is moved. Adjust the location to make sure we are still on a + // snap value. + + while (locationX < edgeInsets.left) + locationX +=3D snapSize.width; + + while (locationY < edgeInsets.top) + locationY +=3D snapSize.height; + + Dimension d =3D getBoundingSize( destination ); + + while (locationX + destination.getSize().width + edgeInsets.right > d.widt= h) + locationX -=3D snapSize.width; + + while (locationY + destination.getSize().height + edgeInsets.bottom > d.he= ight) + locationY -=3D snapSize.height; + + // Adjustments are finished, move the component + + destination.setLocation(locationX, locationY); + } + + /* + * Determine how far the mouse has moved from where dragging started + * (Assume drag direction is down and right for positive drag distance) + */ + private int getDragDistance(int larger, int smaller, int snapSize) + { + int halfway =3D snapSize / 2; + int drag =3D larger - smaller; + drag +=3D (drag < 0) ? -halfway : halfway; + drag =3D (drag / snapSize) * snapSize; + + return drag; + } + + /* + * Get the bounds of the parent of the dragged component. + */ + private Dimension getBoundingSize(Component source) + { + if (source instanceof Window) + { + GraphicsEnvironment env =3D GraphicsEnvironment.getLocalGraphicsEnvironme= nt(); + Rectangle bounds =3D env.getMaximumWindowBounds(); + return new Dimension(bounds.width, bounds.height); + } + else + { + return source.getParent().getSize(); + } + } + + /** + * Restore the original state of the Component + */ + @Override + public void mouseReleased(MouseEvent e) + { + if (!potentialDrag) return; + + source.removeMouseMotionListener( this ); + potentialDrag =3D false; + + if (changeCursor) + source.setCursor( originalCursor ); + + if (destination instanceof JComponent) + { + ((JComponent)destination).setAutoscrolls( autoscrolls ); + } + + // Layout the components on the parent container + + if (autoLayout) + { + if (destination instanceof JComponent) + { + ((JComponent)destination).revalidate(); + } + else + { + destination.validate(); + } + } + } +} Added: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/Comp= onentResizer.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/Compone= ntResizer.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/Compone= ntResizer.java 2012-12-13 17:13:46 UTC (rev 57) @@ -0,0 +1,458 @@ +package fr.ifremer.tutti.ui.swing.util; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; + +/** + * The ComponentResizer allows you to resize a component by dragging a bord= er + * of the component. + */ +public class ComponentResizer extends MouseAdapter +{ + private final static Dimension MINIMUM_SIZE =3D new Dimension(10, 10); + private final static Dimension MAXIMUM_SIZE =3D + new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + + private static Map cursors =3D new HashMap(); + { + cursors.put(1, Cursor.N_RESIZE_CURSOR); + cursors.put(2, Cursor.W_RESIZE_CURSOR); + cursors.put(4, Cursor.S_RESIZE_CURSOR); + cursors.put(8, Cursor.E_RESIZE_CURSOR); + cursors.put(3, Cursor.NW_RESIZE_CURSOR); + cursors.put(9, Cursor.NE_RESIZE_CURSOR); + cursors.put(6, Cursor.SW_RESIZE_CURSOR); + cursors.put(12, Cursor.SE_RESIZE_CURSOR); + } + + private Insets dragInsets; + private Dimension snapSize; + + private int direction; + protected static final int NORTH =3D 1; + protected static final int WEST =3D 2; + protected static final int SOUTH =3D 4; + protected static final int EAST =3D 8; + + private Cursor sourceCursor; + private boolean resizing; + private Rectangle bounds; + private Point pressed; + private boolean autoscrolls; + + private Dimension minimumSize =3D MINIMUM_SIZE; + private Dimension maximumSize =3D MAXIMUM_SIZE; + + /** + * Convenience contructor. All borders are resizable in increments of + * a single pixel. Components must be registered separately. + */ + public ComponentResizer() + { + this(new Insets(5, 5, 5, 5), new Dimension(1, 1)); + } + + /** + * Convenience contructor. All borders are resizable in increments of + * a single pixel. Components can be registered when the class is created + * or they can be registered separately afterwards. + * + * @param components components to be automatically registered + */ + public ComponentResizer(Component... components) + { + this(new Insets(5, 5, 5, 5), new Dimension(1, 1), components); + } + + /** + * Convenience contructor. Eligible borders are resisable in increments of + * a single pixel. Components can be registered when the class is created + * or they can be registered separately afterwards. + * + * @param dragInsets Insets specifying which borders are eligible to be + * resized. + * @param components components to be automatically registered + */ + public ComponentResizer(Insets dragInsets, Component... components) + { + this(dragInsets, new Dimension(1, 1), components); + } + + /** + * Create a ComponentResizer. + * + * @param dragInsets Insets specifying which borders are eligible to be + * resized. + * @param snapSize Specify the dimension to which the border will snap to + * when being dragged. Snapping occurs at the halfway mark. + * @param components components to be automatically registered + */ + public ComponentResizer(Insets dragInsets, Dimension snapSize, Component...= components) + { + setDragInsets( dragInsets ); + setSnapSize( snapSize ); + registerComponent( components ); + } + + /** + * Get the drag insets + * + * @return the drag insets + */ + public Insets getDragInsets() + { + return dragInsets; + } + + /** + * Set the drag dragInsets. The insets specify an area where mouseDragged + * events are recognized from the edge of the border inwards. A value of + * 0 for any size will imply that the border is not resizable. Otherwise + * the appropriate drag cursor will appear when the mouse is inside the + * resizable border area. + * + * @param dragInsets Insets to control which borders are resizeable. + */ + public void setDragInsets(Insets dragInsets) + { + validateMinimumAndInsets(minimumSize, dragInsets); + + this.dragInsets =3D dragInsets; + } + + /** + * Get the components maximum size. + * + * @return the maximum size + */ + public Dimension getMaximumSize() + { + return maximumSize; + } + + /** + * Specify the maximum size for the component. The component will still + * be constrained by the size of its parent. + * + * @param maximumSize the maximum size for a component. + */ + public void setMaximumSize(Dimension maximumSize) + { + this.maximumSize =3D maximumSize; + } + + /** + * Get the components minimum size. + * + * @return the minimum size + */ + public Dimension getMinimumSize() + { + return minimumSize; + } + + /** + * Specify the minimum size for the component. The minimum size is + * constrained by the drag insets. + * + * @param minimumSize the minimum size for a component. + */ + public void setMinimumSize(Dimension minimumSize) + { + validateMinimumAndInsets(minimumSize, dragInsets); + + this.minimumSize =3D minimumSize; + } + + /** + * Remove listeners from the specified component + * + * @param component the component the listeners are removed from + */ + public void deregisterComponent(Component... components) + { + for (Component component : components) + { + component.removeMouseListener( this ); + component.removeMouseMotionListener( this ); + } + } + + /** + * Add the required listeners to the specified component + * + * @param component the component the listeners are added to + */ + public void registerComponent(Component... components) + { + for (Component component : components) + { + component.addMouseListener( this ); + component.addMouseMotionListener( this ); + } + } + + /** + * Get the snap size. + * + * @return the snap size. + */ + public Dimension getSnapSize() + { + return snapSize; + } + + /** + * Control how many pixels a border must be dragged before the size of + * the component is changed. The border will snap to the size once + * dragging has passed the halfway mark. + * + * @param snapSize Dimension object allows you to separately spcify a + * horizontal and vertical snap size. + */ + public void setSnapSize(Dimension snapSize) + { + this.snapSize =3D snapSize; + } + + /** + * When the components minimum size is less than the drag insets then + * we can't determine which border should be resized so we need to + * prevent this from happening. + */ + private void validateMinimumAndInsets(Dimension minimum, Insets drag) + { + int minimumWidth =3D drag.left + drag.right; + int minimumHeight =3D drag.top + drag.bottom; + + if (minimum.width < minimumWidth + || minimum.height < minimumHeight) + { + String message =3D "Minimum size cannot be less than drag insets"; + throw new IllegalArgumentException( message ); + } + } + + /** + */ + @Override + public void mouseMoved(MouseEvent e) + { + Component source =3D e.getComponent(); + Point location =3D e.getPoint(); + direction =3D 0; + + if (location.x < dragInsets.left) + direction +=3D WEST; + + if (location.x > source.getWidth() - dragInsets.right - 1) + direction +=3D EAST; + + if (location.y < dragInsets.top) + direction +=3D NORTH; + + if (location.y > source.getHeight() - dragInsets.bottom - 1) + direction +=3D SOUTH; + + // Mouse is no longer over a resizable border + + if (direction =3D=3D 0) + { + source.setCursor( sourceCursor ); + } + else // use the appropriate resizable cursor + { + int cursorType =3D cursors.get( direction ); + Cursor cursor =3D Cursor.getPredefinedCursor( cursorType ); + source.setCursor( cursor ); + } + } + + @Override + public void mouseEntered(MouseEvent e) + { + if (! resizing) + { + Component source =3D e.getComponent(); + sourceCursor =3D source.getCursor(); + } + } + + @Override + public void mouseExited(MouseEvent e) + { + if (! resizing) + { + Component source =3D e.getComponent(); + source.setCursor( sourceCursor ); + } + } + + @Override + public void mousePressed(MouseEvent e) + { + // The mouseMoved event continually updates this variable + + if (direction =3D=3D 0) return; + + // Setup for resizing. All future dragging calculations are done based + // on the original bounds of the component and mouse pressed location. + + resizing =3D true; + + Component source =3D e.getComponent(); + pressed =3D e.getPoint(); + SwingUtilities.convertPointToScreen(pressed, source); + bounds =3D source.getBounds(); + + // Making sure autoscrolls is false will allow for smoother resizing + // of components + + if (source instanceof JComponent) + { + JComponent jc =3D (JComponent)source; + autoscrolls =3D jc.getAutoscrolls(); + jc.setAutoscrolls( false ); + } + } + + /** + * Restore the original state of the Component + */ + @Override + public void mouseReleased(MouseEvent e) + { + resizing =3D false; + + Component source =3D e.getComponent(); + source.setCursor( sourceCursor ); + + if (source instanceof JComponent) + { + ((JComponent)source).setAutoscrolls( autoscrolls ); + } + } + + /** + * Resize the component ensuring location and size is within the bounds + * of the parent container and that the size is within the minimum and + * maximum constraints. + * + * All calculations are done using the bounds of the component when the + * resizing started. + */ + @Override + public void mouseDragged(MouseEvent e) + { + if (resizing =3D=3D false) return; + + Component source =3D e.getComponent(); + Point dragged =3D e.getPoint(); + SwingUtilities.convertPointToScreen(dragged, source); + + changeBounds(source, direction, bounds, pressed, dragged); + } + + protected void changeBounds(Component source, int direction, Rectangle boun= ds, Point pressed, Point current) + { + // Start with original locaton and size + + int x =3D bounds.x; + int y =3D bounds.y; + int width =3D bounds.width; + int height =3D bounds.height; + + // Resizing the West or North border affects the size and location + + if (WEST =3D=3D (direction & WEST)) + { + int drag =3D getDragDistance(pressed.x, current.x, snapSize.width); + int maximum =3D Math.min(width + x, maximumSize.width); + drag =3D getDragBounded(drag, snapSize.width, width, minimumSize.width, m= aximum); + + x -=3D drag; + width +=3D drag; + } + + if (NORTH =3D=3D (direction & NORTH)) + { + int drag =3D getDragDistance(pressed.y, current.y, snapSize.height); + int maximum =3D Math.min(height + y, maximumSize.height); + drag =3D getDragBounded(drag, snapSize.height, height, minimumSize.height= , maximum); + + y -=3D drag; + height +=3D drag; + } + + // Resizing the East or South border only affects the size + + if (EAST =3D=3D (direction & EAST)) + { + int drag =3D getDragDistance(current.x, pressed.x, snapSize.width); + Dimension boundingSize =3D getBoundingSize( source ); + int maximum =3D Math.min(boundingSize.width - x, maximumSize.width); + drag =3D getDragBounded(drag, snapSize.width, width, minimumSize.width, m= aximum); + width +=3D drag; + } + + if (SOUTH =3D=3D (direction & SOUTH)) + { + int drag =3D getDragDistance(current.y, pressed.y, snapSize.height); + Dimension boundingSize =3D getBoundingSize( source ); + int maximum =3D Math.min(boundingSize.height - y, maximumSize.height); + drag =3D getDragBounded(drag, snapSize.height, height, minimumSize.height= , maximum); + height +=3D drag; + } + + source.setBounds(x, y, width, height); + source.validate(); + } + + /* + * Determine how far the mouse has moved from where dragging started + */ + private int getDragDistance(int larger, int smaller, int snapSize) + { + int halfway =3D snapSize / 2; + int drag =3D larger - smaller; + drag +=3D (drag < 0) ? -halfway : halfway; + drag =3D (drag / snapSize) * snapSize; + + return drag; + } + + /* + * Adjust the drag value to be within the minimum and maximum range. + */ + private int getDragBounded(int drag, int snapSize, int dimension, int minim= um, int maximum) + { + while (dimension + drag < minimum) + drag +=3D snapSize; + + while (dimension + drag > maximum) + drag -=3D snapSize; + + + return drag; + } + + /* + * Keep the size of the component within the bounds of its parent. + */ + private Dimension getBoundingSize(Component source) + { + if (source instanceof Window) + { + GraphicsEnvironment env =3D GraphicsEnvironment.getLocalGraphicsEnvironme= nt(); + Rectangle bounds =3D env.getMaximumWindowBounds(); + return new Dimension(bounds.width, bounds.height); + } + else + { + return source.getParent().getSize(); + } + } +} Added: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/edit= or/LongTextCellComponent.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/= LongTextCellComponent.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/= LongTextCellComponent.java 2012-12-13 17:13:46 UTC (rev 57) @@ -0,0 +1,268 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package fr.ifremer.tutti.ui.swing.util.editor; + +import fr.ifremer.tutti.ui.swing.util.ComponentResizer; +import com.google.common.base.Preconditions; +import fr.ifremer.tutti.ui.swing.AbstractTuttiBeanUIModel; +import fr.ifremer.tutti.ui.swing.util.ComponentMover; +import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; +import fr.ifremer.tutti.ui.swing.util.table.AbstractSelectTableAction; +import fr.ifremer.tutti.ui.swing.util.table.AbstractTuttiTableModel; +import fr.ifremer.tutti.ui.swing.util.table.ColumnIdentifier; +import java.awt.event.WindowAdapter; +import java.awt.Color; +import java.awt.Component; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowEvent; +import javax.swing.AbstractCellEditor; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JTable; +import javax.swing.border.LineBorder; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import jaxx.runtime.JAXXUtil; +import jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import static org.nuiton.i18n.I18n._; + +/** + * Component to edit a cell in a popup with a text area + *=20 + * @author kmorin + * @since 0.2 + */ +public class LongTextCellComponent extends JButton{ + =20 + /** Logger. */ + private static final Log log =3D LogFactory.getLog(LongTextCellComponent= .class); + + public LongTextCellComponent() { + setContentAreaFilled(false); + setOpaque(false); + setIcon(SwingUtil.createActionIcon("edit")); + } + + public static TableCellRenderer newRender() { + return new LongTextCellRenderer(); + } + + public static TableCellEditor newEditor(LongTextEditorUI ui) { + return new LongTextCellEditor(ui); + } + =20 + =20 + public static class LongTextCellEditor extends AbstractCellEditor implem= ents TableCellEditor { + + public static final int DEFAULT_EDITOR_WIDTH =3D 400; + public static final int DEFAULT_EDITOR_HEIGHT =3D 200; + =20 + protected final LongTextCellComponent component; + + protected final LongTextEditorUI ui; + + protected Frame frame; + =20 + protected JTable table; + + protected AbstractTuttiTableModel tableMod= el; + + protected ColumnIdentifier columnIdentifie= r; + + protected AbstractTuttiBeanUIModel editRow; + + protected Integer rowIndex; + + protected Integer columnIndex; + =20 + public LongTextCellEditor(LongTextEditorUI ui) { + this.ui =3D ui; + =20 + component =3D new LongTextCellComponent(); + component.setBorder(new LineBorder(Color.BLACK)); + component.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() =3D=3D KeyEvent.VK_ENTER || + e.getKeyCode() =3D=3D KeyEvent.VK_SPACE) { + e.consume(); + startEdit(); + } + } + }); + + component.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + e.consume(); + startEdit(); + } + }); + } + + protected void startEdit() { + if (frame =3D=3D null) { + frame =3D SwingUtil.getParentContainer(ui, Frame.class); + } + =20 + ui.setBorder(BorderFactory.createTitledBorder(_(columnIdentifier= .getHeaderI18nKey()))); + ui.setBean(editRow); + ui.setProperty(columnIdentifier.getPropertyName()); + =20 + JDialog editor =3D new JDialog(frame, true); + editor.setUndecorated(true); + editor.add(ui); + editor.setSize(DEFAULT_EDITOR_WIDTH, DEFAULT_EDITOR_HEIGHT); + editor.setResizable(true); + =20 + ComponentResizer cr =3D new ComponentResizer(); + cr.registerComponent(editor); + ComponentMover cm =3D new ComponentMover(); + cm.setDragInsets(cr.getDragInsets()); + cm.registerComponent(editor); + =20 + editor.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosed(WindowEvent e) { + Component ui =3D (Component) e.getSource(); + if (log.isInfoEnabled()) { + log.info("Destroy ui " + ui); + } + JAXXUtil.destroy(ui); + } + }); + =20 + // Computes the location of bottom left corner of the cell + Component comp =3D component; + int x =3D 0; + int y =3D component.getHeight(); + while (comp !=3D null) { + x +=3D comp.getX(); + y +=3D comp.getY(); + comp =3D comp.getParent(); + } + // if the editor is too big on the right, + // then align its right side to the right side of the cell + if (x + editor.getWidth() > frame.getX() + frame.getWidth()) { + x =3D x - editor.getWidth() + component.getWidth(); + } + editor.setLocation(x, y); + editor.setVisible(true); + =20 + int r =3D rowIndex; + int c =3D columnIndex; + + // stop edition + stopCellEditing(); + + // reselect this cell + AbstractSelectTableAction.doSelectCell(table, r, c); + } + =20 + @Override + public Component getTableCellEditorComponent(JTable table, + Object value, + boolean isSelected, + int row, + int column) { + if (tableModel =3D=3D null) { + tableModel =3D (AbstractTuttiTableModel) table.getModel(); + this.table =3D table; + columnIdentifier =3D tableModel.getPropertyName(column); + } + + rowIndex =3D row; + columnIndex =3D column; + + editRow =3D tableModel.getEntry(row); + + return component; + } + + @Override + public Object getCellEditorValue() { + + Preconditions.checkNotNull(editRow, "No editRow found in editor.= "); + + String propertyName =3D columnIdentifier.getPropertyName(); + Object result =3D TuttiUIUtil.getProperty(editRow, propertyName); + if (log.isInfoEnabled()) { + log.info("editor value (" + propertyName + "): " + result); + } + + return result; + } + + @Override + public boolean stopCellEditing() { + boolean b =3D super.stopCellEditing(); + if (b) { + rowIndex =3D null; + editRow =3D null; + columnIndex =3D null; + } + return b; + } + + @Override + public void cancelCellEditing() { + super.cancelCellEditing(); + rowIndex =3D null; + columnIndex =3D null; + editRow =3D null; + } + } + =20 + public static class LongTextCellRenderer implements TableCellRenderer { + + protected final LongTextCellComponent component; + =20 + protected String propertyName; + + public LongTextCellRenderer() { + component =3D new LongTextCellComponent(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + + String text; + if (value =3D=3D null) { + if (propertyName =3D=3D null) { + AbstractTuttiTableModel tableModel =3D=20 + (AbstractTuttiTableModel) table.getModel(); + ColumnIdentifier columnIdentifier =3D tableModel.getProp= ertyName(column); + propertyName =3D columnIdentifier.getPropertyName(); + } + // use HTML to show the tooltip in italic + text =3D "" + _("tutti.tooltip." + propertyNa= me + ".none") + ""; + =20 + } else { + // use html to display the tooltip on several lines + text =3D "" + String.valueOf(value).replace("\n"= , "
") + ""; + } + =20 + boolean editable =3D table.isCellEditable(row, column); + component.setEnabled(editable); + component.setToolTipText(text); + return component; + } + } +} Added: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/edit= or/LongTextEditorUI.css =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/= LongTextEditorUI.css (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/= LongTextEditorUI.css 2012-12-13 17:13:46 UTC (rev 57) @@ -0,0 +1,4 @@ +#closeButton { + actionIcon: "close"; + text: "tutti.action.close"; +} Copied: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/edi= tor/LongTextEditorUI.jaxx (from rev 55, trunk/tutti-ui-swing/src/main/java/fr= /ifremer/tutti/ui/swing/content/operation/species/SpeciesFrequencyUI.jaxx) =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/= LongTextEditorUI.jaxx (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/= LongTextEditorUI.jaxx 2012-12-13 17:13:46 UTC (rev 57) @@ -0,0 +1,48 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file Added: trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/edit= or/LongTextEditorUIHandler.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/= LongTextEditorUIHandler.java (rev 0) +++ trunk/tutti-ui-swing/src/main/java/fr/ifremer/tutti/ui/swing/util/editor/= LongTextEditorUIHandler.java 2012-12-13 17:13:46 UTC (rev 57) @@ -0,0 +1,75 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package fr.ifremer.tutti.ui.swing.util.editor; + +import fr.ifremer.tutti.ui.swing.AbstractTuttiBeanUIModel; +import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil; +import java.awt.Window; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import jaxx.runtime.SwingUtil; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Handler of the LongTextEditorUI + * @author kmorin + * @since 0.2 + */ +public class LongTextEditorUIHandler { + =20 + private static final Log log =3D LogFactory.getLog(LongTextEditorUIHandl= er.class); + =20 + private final LongTextEditorUI ui; + + public LongTextEditorUIHandler(LongTextEditorUI longTextEditorUI) { + ui =3D longTextEditorUI; + =20 + ui.addPropertyChangeListener(new PropertyChangeListener() { + + public void propertyChange(PropertyChangeEvent evt) { + AbstractTuttiBeanUIModel bean =3D ui.getBean(); + String property =3D ui.getProperty(); + if (bean !=3D null && !StringUtils.isEmpty(property)) { + Object value =3D TuttiUIUtil.getProperty(bean, property); + if (value =3D=3D null) { + value =3D ""; + } + ui.getTextContent().setText(value.toString()); + } + } + }); + } + =20 + /** + * pushes the typed text in the property of the bean + */ + public void setText() { + String value =3D ui.getTextContent().getText(); + AbstractTuttiBeanUIModel bean =3D ui.getBean(); + String property =3D ui.getProperty(); + TuttiUIUtil.setProperty(bean, property, value); + } + =20 + public void resetText() { + AbstractTuttiBeanUIModel bean =3D ui.getBean(); + String property =3D ui.getProperty(); + TuttiUIUtil.setProperty(bean, property, null); + =20 + ui.getTextContent().setText(""); + } + =20 + /** + * closes the editor + */ + public void close() { + if (log.isInfoEnabled()) { + log.info("Will close UI " + ui); + } + SwingUtil.getParentContainer(ui, Window.class).dispose(); + } + +} Modified: trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.p= roperties =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.propert= ies 2012-12-13 15:37:44 UTC (rev 56) +++ trunk/tutti-ui-swing/src/main/resources/i18n/tutti-ui-swing_fr_FR.propert= ies 2012-12-13 17:13:46 UTC (rev 57) @@ -1,7 +1,7 @@ tutti.about.bottomText=3DCopyright %s - %s - version %s -tutti.about.message=3D

Tutti

Outil de saisie de donn=C3=A9= es d'op=C3=A9rations et de captures au cours des campagnes halieutiques.


Ce logiciel permettra la saisie en mer des donn=C3=A9es d'op= =C3=A9ration de p=C3=AAche (positions, environnement, engin, etc) et des capt= ures associ=C3=A9es (composition de la capture en esp=C3=A8ces scientifiques = avec poids, nombres, tailles etc) pour l'ensemble des campagnes halieutiques = r=C3=A9alis=C3=A9es par l'Ifremer.

Ce projet a =C3=A9t=C3=A9 initi=C3= =A9e en 2012 par l'Ifremer et r=C3=A9= alis=C3=A9 par la soci=C3=A9t=C3=A9 Codelu= tin.



Pour plus d'informations, vous pouvez visiter le site du projet.

Projet h=C3=A9berg=C3=A9 sur la forge Forge.codelutin.com.

-tutti.action.about=3D=C3=80 propos -tutti.action.about.tip=3D=C3=80 Propos +tutti.about.message=3D

Tutti

Outil de saisie de donn\u00c3= \u00a9es d'op\u00c3\u00a9rations et de captures au cours des campagnes halieu= tiques.


Ce logiciel permettra la saisie en mer des donn\u= 00c3\u00a9es d'op\u00c3\u00a9ration de p\u00c3\u00aache (positions, environne= ment, engin, etc) et des captures associ\u00c3\u00a9es (composition de la cap= ture en esp\u00c3\u00a8ces scientifiques avec poids, nombres, tailles etc) po= ur l'ensemble des campagnes halieutiques r\u00c3\u00a9alis\u00c3\u00a9es par = l'Ifremer.

Ce projet a \u00c3\u00a9t\u00c3\u00a9 initi\u00c3\u00a9e en = 2012 par l'Ifremer et r\u00c3\u00a9al= is\u00c3\u00a9 par la soci\u00c3\u00a9t\u00c3\u00a9 Codelutin.



Pour plus d'informations, vous pouve= z visiter le site d= u projet.

Projet h\u00c3\u00a9berg\u00c3\u00a9 sur la forge Forge.codelutin.com.

+tutti.action.about=3D\u00c3\u0080 propos +tutti.action.about.tip=3D\u00c3\u0080 Propos tutti.action.cancel=3DAnnuler tutti.action.casino-import=3DImport Casino tutti.action.catches=3DCaptures @@ -13,21 +13,21 @@ tutti.action.exit.tip=3DQuitter l'application tutti.action.fillCatches=3DCaptures tutti.action.fillCatches.tip=3DSaisir des captures -tutti.action.generate=3DG=C3=A9n=C3=A9rer -tutti.action.generateCampaignName=3DG=C3=A9n=C3=A9rer le nom +tutti.action.generate=3DG\u00c3\u00a9n\u00c3\u00a9rer +tutti.action.generateCampaignName=3DG\u00c3\u00a9n\u00c3\u00a9rer le nom tutti.action.manageProtocol=3DProtocole -tutti.action.manageProtocol.tip=3DG=C3=A9rer les protocoles +tutti.action.manageProtocol.tip=3DG\u00c3\u00a9rer les protocoles tutti.action.new=3DNouveau tutti.action.pupitri-import=3DImport PUPITRI tutti.action.reload.actions=3DRecharger les actions tutti.action.reload.home=3DReload home screen tutti.action.reload.ui=3DRecharger l'interface graphique -tutti.action.reset.fishingOperationValidState=3DR=C3=A9initialiser +tutti.action.reset.fishingOperationValidState=3DR\u00c3\u00a9initialiser tutti.action.save=3DEnregistrer tutti.action.selectCampaign=3DCampagne -tutti.action.selectCampaign.tip=3DS=C3=A9lectionner la campagne =C3=A0 utili= ser +tutti.action.selectCampaign.tip=3DS\u00c3\u00a9lectionner la campagne \u00c3= \u00a0 utiliser tutti.action.site=3DSite -tutti.action.site.tip=3DAcc=C3=A9der au site du projet Tutti +tutti.action.site.tip=3DAcc\u00c3\u00a9der au site du projet Tutti tutti.application.config=3DConfiguration de l'application Tutti tutti.application.name=3DTutti tutti.config.category.applications=3DApplication @@ -36,84 +36,84 @@ tutti.config.category.other.description=3DAutres options tutti.config.category.shortcuts=3DRaccourcis tutti.config.category.shortcuts.description=3DListe des raccourcis clavier -tutti.config.cruiseId=3DIdentifiant de la derni=C3=A8re campagne utilis=C3= =A9e -tutti.config.programId=3DIdentifiant de la derni=C3=A8re s=C3=A9rie de campa= gne utilis=C3=A9e -tutti.config.ui.autoPopupNumberEditor=3DToujours afficher le pav=C3=A9 num= =C3=A9rique lors de l'=C3=A9dition d'un nombre +tutti.config.cruiseId=3DIdentifiant de la derni\u00c3\u00a8re campagne utili= s\u00c3\u00a9e +tutti.config.programId=3DIdentifiant de la derni\u00c3\u00a8re s\u00c3\u00a9= rie de campagne utilis\u00c3\u00a9e +tutti.config.ui.autoPopupNumberEditor=3DToujours afficher le pav\u00c3\u00a9= num\u00c3\u00a9rique lors de l'\u00c3\u00a9dition d'un nombre tutti.config.ui.config=3DChemin du fichier de configuration des interfaces g= raphiques -tutti.config.ui.showNumberEditorButton=3DAfficher le pav=C3=A9 num=C3=A9riqu= e de saisie -tutti.label.benthos.sampleTotalWeight=3DPoids total =C3=A9chantillonn=C3=A9 +tutti.config.ui.showNumberEditorButton=3DAfficher le pav\u00c3\u00a9 num\u00= c3\u00a9rique de saisie +tutti.label.benthos.sampleTotalWeight=3DPoids total \u00c3\u00a9chantillonn\= u00c3\u00a9 tutti.label.benthos.totalWeight=3DPoids total tutti.label.comment=3DCommentaire tutti.label.cruise=3DCampagne -tutti.label.cruise.beginDate=3DDate de d=C3=A9but +tutti.label.cruise.beginDate=3DDate de d\u00c3\u00a9but tutti.label.cruise.country=3DPays tutti.label.cruise.endDate=3DDate de fin tutti.label.cruise.name=3DNom tutti.label.cruise.poche=3DNombre de poches -tutti.label.cruise.program=3DS=C3=A9rie -tutti.label.cruise.surveyPart=3DS=C3=A9rie partielle -tutti.label.cruise.year=3DAnn=C3=A9e -tutti.label.fishingOperation.averageBottomSalinity=3DSalinit=C3=A9 de fond m= oyenne -tutti.label.fishingOperation.averageBottomTemperature=3DTemp=C3=A9rature de = fond moyenne +tutti.label.cruise.program=3DS\u00c3\u00a9rie +tutti.label.cruise.surveyPart=3DS\u00c3\u00a9rie partielle +tutti.label.cruise.year=3DAnn\u00c3\u00a9e +tutti.label.fishingOperation.averageBottomSalinity=3DSalinit\u00c3\u00a9 de = fond moyenne +tutti.label.fishingOperation.averageBottomTemperature=3DTemp\u00c3\u00a9ratu= re de fond moyenne tutti.label.fishingOperation.beaufortScale=3DForce du vent tutti.label.fishingOperation.date=3DDate -tutti.label.fishingOperation.distanceChalutee=3DDistance chalut=C3=A9e -tutti.label.fishingOperation.duree=3DDur=C3=A9e +tutti.label.fishingOperation.distanceChalutee=3DDistance chalut\u00c3\u00a9e +tutti.label.fishingOperation.duree=3DDur\u00c3\u00a9e tutti.label.fishingOperation.fishingOperationInvalid=3DTrait invalide -tutti.label.fishingOperation.fishingOperationNumber=3DNum=C3=A9ro de Trait +tutti.label.fishingOperation.fishingOperationNumber=3DNum\u00c3\u00a9ro de T= rait tutti.label.fishingOperation.fishingOperationRectiligne=3DTrait rectiligne tutti.label.fishingOperation.fishingOperationValid=3DTrait valide tutti.label.fishingOperation.gearDate=3DDate tutti.label.fishingOperation.gearLatitude=3DLatitude tutti.label.fishingOperation.gearLongitude=3DLongitude tutti.label.fishingOperation.gearShootingEnd=3DFin de traine -tutti.label.fishingOperation.gearShootingEndBottomSalinity=3DSalinit=C3=A9 d= e fond fin de traine -tutti.label.fishingOperation.gearShootingEndBottomTemperature=3DTemp=C3=A9ra= ture de fond fin de traine +tutti.label.fishingOperation.gearShootingEndBottomSalinity=3DSalinit\u00c3\u= 00a9 de fond fin de traine +tutti.label.fishingOperation.gearShootingEndBottomTemperature=3DTemp\u00c3\u= 00a9rature de fond fin de traine tutti.label.fishingOperation.gearShootingEndDepth=3DProfondeur fin de traine -tutti.label.fishingOperation.gearShootingEndSurfaceSalinity=3DSalinit=C3=A9 = de surface fin de traine +tutti.label.fishingOperation.gearShootingEndSurfaceSalinity=3DSalinit\u00c3\= u00a9 de surface fin de traine tutti.label.fishingOperation.gearShootingEndSurfaceTemperature=3DTemperature= de surface fin de traine -tutti.label.fishingOperation.gearShootingStart=3DD=C3=A9but de traine -tutti.label.fishingOperation.gearShootingStartBottomSalinity=3DSalinit=C3=A9= de fond d=C3=A9but de traine -tutti.label.fishingOperation.gearShootingStartBottomTemperature=3DTemp=C3=A9= rature de fond d=C3=A9but de traine -tutti.label.fishingOperation.gearShootingStartDepth=3DProfondeur d=C3=A9but = de traine -tutti.label.fishingOperation.gearShootingStartSurfaceSalinity=3DSalinit=C3= =A9 de surface d=C3=A9but de traine -tutti.label.fishingOperation.gearShootingStartSurfaceTemperature=3DTemperatu= re de surface d=C3=A9but de traine +tutti.label.fishingOperation.gearShootingStart=3DD\u00c3\u00a9but de traine +tutti.label.fishingOperation.gearShootingStartBottomSalinity=3DSalinit\u00c3= \u00a9 de fond d\u00c3\u00a9but de traine +tutti.label.fishingOperation.gearShootingStartBottomTemperature=3DTemp\u00c3= \u00a9rature de fond d\u00c3\u00a9but de traine +tutti.label.fishingOperation.gearShootingStartDepth=3DProfondeur d\u00c3\u00= a9but de traine +tutti.label.fishingOperation.gearShootingStartSurfaceSalinity=3DSalinit\u00c= 3\u00a9 de surface d\u00c3\u00a9but de traine +tutti.label.fishingOperation.gearShootingStartSurfaceTemperature=3DTemperatu= re de surface d\u00c3\u00a9but de traine tutti.label.fishingOperation.gearTime=3DHeure -tutti.label.fishingOperation.geometrieMesuree=3DG=C3=A9om=C3=A9trie mesur=C3= =A9e -tutti.label.fishingOperation.localite=3DLocalit=C3=A9 +tutti.label.fishingOperation.geometrieMesuree=3DG\u00c3\u00a9om\u00c3\u00a9t= rie mesur\u00c3\u00a9e +tutti.label.fishingOperation.localite=3DLocalit\u00c3\u00a9 tutti.label.fishingOperation.longueurBras=3DLongueur des funes tutti.label.fishingOperation.longueurFunes=3DLongueur des bras tutti.label.fishingOperation.ouvertureHorizontale=3DOuverture horizontale tutti.label.fishingOperation.ouvertureVerticale=3DOuverture verticale tutti.label.fishingOperation.seaState=3DEtat de la mer -tutti.label.fishingOperation.stationNumber=3DNum=C3=A9ro de la station +tutti.label.fishingOperation.stationNumber=3DNum\u00c3\u00a9ro de la station tutti.label.fishingOperation.strata=3DStrate tutti.label.fishingOperation.subStrata=3DSous strate -tutti.label.fishingOperation.systemeFermetureCul=3DSyst=C3=A8me de fermeture= de cul +tutti.label.fishingOperation.systemeFermetureCul=3DSyst\u00c3\u00a8me de fer= meture de cul tutti.label.fishingOperation.windDirection=3DDirection du vent tutti.label.frequencyConfiguration.maxStep=3DClasse max tutti.label.frequencyConfiguration.minStep=3DClasse min -tutti.label.frequencyConfiguration.mode.autoGen=3DG=C3=A9n=C3=A9ration des c= lasses -tutti.label.frequencyConfiguration.mode.autoGen.tip=3DMode o=C3=B9 toutes le= s classes de taille sont g=C3=A9n=C3=A9r=C3=A9es +tutti.label.frequencyConfiguration.mode.autoGen=3DG\u00c3\u00a9n\u00c3\u00a9= ration des classes +tutti.label.frequencyConfiguration.mode.autoGen.tip=3DMode o\u00c3\u00b9 tou= tes les classes de taille sont g\u00c3\u00a9n\u00c3\u00a9r\u00c3\u00a9es tutti.label.frequencyConfiguration.mode.rafale=3DMode "rafale" -tutti.label.frequencyConfiguration.mode.rafale.tip=3DMode o=C3=B9 on ne sais= it uniquement la classe de taille (les nombres seront alors incr=C3=A9ment=C3= =A9s...) +tutti.label.frequencyConfiguration.mode.rafale.tip=3DMode o\u00c3\u00b9 on n= e saisit uniquement la classe de taille (les nombres seront alors incr\u00c3\= u00a9ment\u00c3\u00a9s...) tutti.label.frequencyConfiguration.mode.simple=3DMode simple -tutti.label.frequencyConfiguration.mode.simple.tip=3DMode par d=C3=A9faut on= on doit tout saisir (les classes de tailles et les nombres) +tutti.label.frequencyConfiguration.mode.simple.tip=3DMode par d\u00c3\u00a9f= aut on on doit tout saisir (les classes de tailles et les nombres) tutti.label.frequencyConfiguration.no.configuration=3D< Pas de configuration= > -tutti.label.frequencyConfiguration.rafaleStep=3DClasse de taille =C3=A0 incr= =C3=A9menter +tutti.label.frequencyConfiguration.rafaleStep=3DClasse de taille \u00c3\u00a= 0 incr\u00c3\u00a9menter tutti.label.frequencyConfiguration.step=3DPas de la classe de taille tutti.label.list.gear=3DEngin(s) tutti.label.list.headOfMission=3DChef(s) de mission tutti.label.list.headOfSortRoom=3DReponsable(s) de salle de tri tutti.label.list.vessel=3DNavire(s) tutti.label.macroWaste.totalWeight=3DPoids total -tutti.label.no.fishingOperation.selected=3D< Aucun trait s=C3=A9lectionn=C3= =A9 > -tutti.label.plankton.sampleTotalWeight=3DPoids total =C3=A9chantillonn=C3=A9 +tutti.label.no.fishingOperation.selected=3D< Aucun trait s\u00c3\u00a9lectio= nn\u00c3\u00a9 > +tutti.label.plankton.sampleTotalWeight=3DPoids total \u00c3\u00a9chantillonn= \u00c3\u00a9 tutti.label.plankton.totalWeight=3DPoids total -tutti.label.program=3DS=C3=A9rie de campagne +tutti.label.program=3DS\u00c3\u00a9rie de campagne tutti.label.program.name=3DNom tutti.label.program.zone=3DZone -tutti.label.species.sampleVracWeight=3DPoids total vrac =C3=A9chant. +tutti.label.species.sampleVracWeight=3DPoids total vrac \u00c3\u00a9chant. tutti.label.species.totalHorsVracWeight=3DPoids total hors vrac tutti.label.species.totalVracWeight=3DPoids total vrac tutti.label.species.totalWeight=3DPoids total @@ -122,12 +122,12 @@ tutti.label.tab.fishingOperation=3DTrait tutti.label.tab.fishingOperation.environment=3DEnvironnement tutti.label.tab.fishingOperation.gearShooting=3DMise en oeuvre de l'engin -tutti.label.tab.fishingOperation.general=3DCaract=C3=A9ristiques g=C3=A9n=C3= =A9rales -tutti.label.tab.fishingOperation.hydrology=3DParam=C3=A8tres hydrologiques -tutti.label.tab.macroDechet=3DMacro d=C3=A9chets +tutti.label.tab.fishingOperation.general=3DCaract\u00c3\u00a9ristiques g\u00= c3\u00a9n\u00c3\u00a9rales +tutti.label.tab.fishingOperation.hydrology=3DParam\u00c3\u00a8tres hydrologi= ques +tutti.label.tab.macroDechet=3DMacro d\u00c3\u00a9chets tutti.label.tab.observationIndividuel=3DObservations individuelles tutti.label.tab.plancton=3DPlancton -tutti.label.tab.species=3DEsp=C3=A8ces +tutti.label.tab.species=3DEsp\u00c3\u00a8ces tutti.legend.frequencyConfiguration=3DConfiguration tutti.menu.actions=3DActions tutti.menu.actions.tip=3DActions @@ -135,8 +135,8 @@ tutti.menu.file.tip=3DFichier tutti.menu.help=3DAide tutti.menu.help.tip=3DAide -tutti.menu.synchronisationAllegro=3DAll=C3=A9gro -tutti.menu.synchronisationAllegro.tip=3DSynchronisation All=C3=A9gro +tutti.menu.synchronisationAllegro=3DAll\u00c3\u00a9gro +tutti.menu.synchronisationAllegro.tip=3DSynchronisation All\u00c3\u00a9gro tutti.menu.synchronisationExport=3DExport tutti.menu.synchronisationExport.tip=3DEffectuer des exports tutti.menu.synchronisationImport=3DImport @@ -144,71 +144,72 @@ tutti.menu.synchronisations=3DSynchronisation tutti.menu.synchronisations.tip=3DImport/Export tutti.table.benthos.batch.header.comment=3DCommentaire -tutti.table.benthos.batch.header.elevationRate=3DFraction d'=C3=A9l=C3=A9vat= ion -tutti.table.benthos.batch.header.file=3DPi=C3=A8ces jointes -tutti.table.benthos.batch.header.sampleWeight=3DPoids =C3=A9chantillonn=C3=A9 -tutti.table.benthos.batch.header.speciesByCode=3DEsp=C3=A8ce -tutti.table.benthos.batch.header.speciesByGenusCode=3DEsp=C3=A8ce +tutti.table.benthos.batch.header.elevationRate=3DFraction d'\u00c3\u00a9l\u0= 0c3\u00a9vation +tutti.table.benthos.batch.header.file=3DPi\u00c3\u00a8ces jointes +tutti.table.benthos.batch.header.sampleWeight=3DPoids \u00c3\u00a9chantillon= n\u00c3\u00a9 +tutti.table.benthos.batch.header.speciesByCode=3DEsp\u00c3\u00a8ce +tutti.table.benthos.batch.header.speciesByGenusCode=3DEsp\u00c3\u00a8ce tutti.table.benthos.batch.header.toConfirm=3DA Confirmer tutti.table.benthos.batch.header.weight=3DPoids tutti.table.macrowaste.batch.header.comment=3DCommentaire -tutti.table.macrowaste.batch.header.file=3DPi=C3=A8ces jointes -tutti.table.macrowaste.batch.header.speciesByCode=3DEsp=C3=A8ce -tutti.table.macrowaste.batch.header.speciesByGenusCode=3DEsp=C3=A8ce +tutti.table.macrowaste.batch.header.file=3DPi\u00c3\u00a8ces jointes +tutti.table.macrowaste.batch.header.speciesByCode=3DEsp\u00c3\u00a8ce +tutti.table.macrowaste.batch.header.speciesByGenusCode=3DEsp\u00c3\u00a8ce tutti.table.macrowaste.batch.header.weight=3DPoids tutti.table.plankton.batch.header.comment=3DCommentaire -tutti.table.plankton.batch.header.elevationRate=3DFraction d'=C3=A9l=C3=A9va= tion -tutti.table.plankton.batch.header.file=3DPi=C3=A8ces jointes -tutti.table.plankton.batch.header.sampleWeight=3DPoids =C3=A9chantillonn=C3= =A9 -tutti.table.plankton.batch.header.speciesByCode=3DEsp=C3=A8ce -tutti.table.plankton.batch.header.speciesByGenusCode=3DEsp=C3=A8ce +tutti.table.plankton.batch.header.elevationRate=3DFraction d'\u00c3\u00a9l\u= 00c3\u00a9vation +tutti.table.plankton.batch.header.file=3DPi\u00c3\u00a8ces jointes +tutti.table.plankton.batch.header.sampleWeight=3DPoids \u00c3\u00a9chantillo= nn\u00c3\u00a9 +tutti.table.plankton.batch.header.speciesByCode=3DEsp\u00c3\u00a8ce +tutti.table.plankton.batch.header.speciesByGenusCode=3DEsp\u00c3\u00a8ce tutti.table.plankton.batch.header.toConfirm=3DA Confirmer tutti.table.plankton.batch.header.weight=3DPoids tutti.table.species.batch.header.age=3DAge tutti.table.species.batch.header.comment=3DCommentaire -tutti.table.species.batch.header.computedNumber=3DNombre calcul=C3=A9 -tutti.table.species.batch.header.computedWeight=3DPoids calcul=C3=A9 -tutti.table.species.batch.header.elevationRate=3DFraction d'=C3=A9l=C3=A9vat= ion -tutti.table.species.batch.header.file=3DPi=C3=A8ces jointes -tutti.table.species.batch.header.maturity=3DMaturit=C3=A9 -tutti.table.species.batch.header.sampleWeight=3DPoids =C3=A9chantillonn=C3=A9 +tutti.table.species.batch.header.computedNumber=3DNombre calcul\u00c3\u00a9 +tutti.table.species.batch.header.computedWeight=3DPoids calcul\u00c3\u00a9 +tutti.table.species.batch.header.elevationRate=3DFraction d'\u00c3\u00a9l\u0= 0c3\u00a9vation +tutti.table.species.batch.header.file=3DPi\u00c3\u00a8ces jointes +tutti.table.species.batch.header.maturity=3DMaturit\u00c3\u00a9 +tutti.table.species.batch.header.sampleWeight=3DPoids \u00c3\u00a9chantillon= n\u00c3\u00a9 tutti.table.species.batch.header.sex=3DSexe -tutti.table.species.batch.header.speciesByCode=3DEsp=C3=A8ce -tutti.table.species.batch.header.speciesByGenusCode=3DEsp=C3=A8ce +tutti.table.species.batch.header.speciesByCode=3DEsp\u00c3\u00a8ce +tutti.table.species.batch.header.speciesByGenusCode=3DEsp\u00c3\u00a8ce tutti.table.species.batch.header.toConfirm=3DA Confirmer tutti.table.species.batch.header.vracHorsVrac=3DVrac / Hors Vrac tutti.table.species.batch.header.weight=3DPoids -tutti.table.species.batch.header.weightCategory=3DCat=C3=A9gorie Poids -tutti.table.species.frequency.header.computedWeight=3DPoids calcul=C3=A9 +tutti.table.species.batch.header.weightCategory=3DCat\u00c3\u00a9gorie Poids +tutti.table.species.frequency.header.computedWeight=3DPoids calcul\u00c3\u00= a9 tutti.table.species.frequency.header.lengthStep=3DClasse de taille tutti.table.species.frequency.header.number=3DNombre -tutti.table.species.frequency.header.weight=3DPoids observ=C3=A9 +tutti.table.species.frequency.header.weight=3DPoids observ\u00c3\u00a9 tutti.timeeditor.H=3DH -tutti.title.about=3D=C3=80 propos de Tutti -tutti.title.create.cruise=3DCr=C3=A9er une nouvelle campagne -tutti.title.create.program=3DCr=C3=A9er une nouvelle s=C3=A9rie de campagne +tutti.title.about=3D\u00c3\u0080 propos de Tutti +tutti.title.create.cruise=3DCr\u00c3\u00a9er une nouvelle campagne +tutti.title.create.program=3DCr\u00c3\u00a9er une nouvelle s\u00c3\u00a9rie = de campagne tutti.title.edit.cruise=3DEditer une campagne existante -tutti.title.edit.operations=3DSaisie des op=C3=A9rations de p=C3=AAches (%s) -tutti.title.edit.program=3DEditer une s=C3=A9rie de campagne existante +tutti.title.edit.operations=3DSaisie des op\u00c3\u00a9rations de p\u00c3\u0= 0aaches (%s) +tutti.title.edit.program=3DEditer une s\u00c3\u00a9rie de campagne existante tutti.title.frequency=3DSaisie des mensurations -tutti.title.home=3DS=C3=A9lection de la campagne -tutti.title.noSelectedCruise=3DPas de campagne s=C3=A9lectionn=C3=A9 -tutti.title.noSelectedProgram=3DPas de s=C3=A9rie de campagne s=C3=A9lection= n=C3=A9 +tutti.title.home=3DS\u00c3\u00a9lection de la campagne +tutti.title.noSelectedCruise=3DPas de campagne s\u00c3\u00a9lectionn\u00c3\u= 00a9 +tutti.title.noSelectedProgram=3DPas de s\u00c3\u00a9rie de campagne s\u00c3\= u00a9lectionn\u00c3\u00a9 tutti.title.selectedCruise=3DCampagne %s -tutti.title.selectedProgram=3DS=C3=A9rie de campagne %s +tutti.title.selectedProgram=3DS\u00c3\u00a9rie de campagne %s tutti.to.be.done=3D< A FAIRE > -tutti.validator.error.cruise.beginDate.required=3DLa date de d=C3=A9but est = obligatoire +tutti.tooltip.comment.none=3DAucun +tutti.validator.error.cruise.beginDate.required=3DLa date de d\u00c3\u00a9bu= t est obligatoire tutti.validator.error.cruise.country.required=3DLe pays est obligatoire tutti.validator.error.cruise.endDate.required=3DLa date de fin est obligatoi= re -tutti.validator.error.cruise.gear.required=3DAu moins un engin doit =C3=AAtr= e s=C3=A9lectionn=C3=A9 -tutti.validator.error.cruise.headOfMission.required=3DAu moins un chef de mi= ssion doit =C3=AAtre s=C3=A9lectionn=C3=A9 -tutti.validator.error.cruise.headOfSortRoom.required=3DAu moins un responsab= le de salle de tri doit =C3=AAtre s=C3=A9lectionn=C3=A9 +tutti.validator.error.cruise.gear.required=3DAu moins un engin doit \u00c3\u= 00aatre s\u00c3\u00a9lectionn\u00c3\u00a9 +tutti.validator.error.cruise.headOfMission.required=3DAu moins un chef de mi= ssion doit \u00c3\u00aatre s\u00c3\u00a9lectionn\u00c3\u00a9 +tutti.validator.error.cruise.headOfSortRoom.required=3DAu moins un responsab= le de salle de tri doit \u00c3\u00aatre s\u00c3\u00a9lectionn\u00c3\u00a9 tutti.validator.error.cruise.name.required=3DLe nom de la campagne est oblig= atoire tutti.validator.error.cruise.poche.required=3DLe nombre de poche est obligat= oire -tutti.validator.error.cruise.program.required=3DLa s=C3=A9rie est obligatoire -tutti.validator.error.cruise.vessel.required=3DAu moins un bateau doit =C3= =AAtre s=C3=A9lectionn=C3=A9 -tutti.validator.error.cruise.year.required=3DL'ann=C3=A9e est obligatoire +tutti.validator.error.cruise.program.required=3DLa s\u00c3\u00a9rie est obli= gatoire +tutti.validator.error.cruise.vessel.required=3DAu moins un bateau doit \u00c= 3\u00aatre s\u00c3\u00a9lectionn\u00c3\u00a9 +tutti.validator.error.cruise.year.required=3DL'ann\u00c3\u00a9e est obligato= ire tutti.validator.error.fishingOperation.date.required=3DLa date du fishingOpe= ration est obligatoire -tutti.validator.error.fishingOperation.stationNumber.required=3DLe num=C3=A9= ro de station est obligatoire -tutti.validator.error.program.name.required=3DLe nom de la s=C3=A9rie est ob= ligatoire -tutti.validator.error.program.zone.required=3DLa zone de la s=C3=A9rie est o= bligatoire +tutti.validator.error.fishingOperation.stationNumber.required=3DLe num\u00c3= \u00a9ro de station est obligatoire +tutti.validator.error.program.name.required=3DLe nom de la s\u00c3\u00a9rie = est obligatoire +tutti.validator.error.program.zone.required=3DLa zone de la s\u00c3\u00a9rie= est obligatoire --===============3726849494443812617==--