From: <emm...@us...> - 2008-11-17 14:54:33
|
Revision: 4221 http://fudaa.svn.sourceforge.net/fudaa/?rev=4221&view=rev Author: emmanuel_martin Date: 2008-11-17 14:54:27 +0000 (Mon, 17 Nov 2008) Log Message: ----------- tache #88 (CDC 11.3.1) : "Inverser des profils" Modified Paths: -------------- branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/ZCalqueLigneBrisee.java branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlEditionManager.java branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlSceneEditor.java branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlVisuPanel.java branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/layer/MdlModel2dLine.java branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/sig/layer/FSigVisuPanel.java Added Paths: ----------- branches/FudaaModeleur_TC1Bis/fudaa_devel/ctulu/src/com/memoire/bu/fleche.png branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/action/SceneShowOrientationAction.java branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/action/SceneInvertAction.java Added: branches/FudaaModeleur_TC1Bis/fudaa_devel/ctulu/src/com/memoire/bu/fleche.png =================================================================== (Binary files differ) Property changes on: branches/FudaaModeleur_TC1Bis/fudaa_devel/ctulu/src/com/memoire/bu/fleche.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: svn:keywords + Id Modified: branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/ZCalqueLigneBrisee.java =================================================================== --- branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/ZCalqueLigneBrisee.java 2008-11-16 20:34:00 UTC (rev 4220) +++ branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/ZCalqueLigneBrisee.java 2008-11-17 14:54:27 UTC (rev 4221) @@ -124,6 +124,8 @@ protected EbliListeSelectionMulti selectionMulti_; /** Pour le trac\xE9 de la selection en mode atomique. */ protected ZSelectionTrace traceAtomic_; + /** On dessine une fl\xE8che sur chaque ligne pour indiquer le sens de celle-ci. */ + protected boolean showLineOrientation_; /** * @@ -142,9 +144,20 @@ iconModel_ = new TraceIconModel(TraceIcon.CARRE_PLEIN, 2, Color.BLACK); ligneModelOuvert_ = new TraceLigneModel(ligneModel_); iconeModelOuvert_ = new TraceIconModel(iconModel_); + showLineOrientation_=false; + } + public boolean getShowLineOrientation(){ + return showLineOrientation_; } - + + public void setShowLineOrientation(boolean _value){ + if(showLineOrientation_!=_value){ + showLineOrientation_=_value; + repaint(); + } + } + protected EbliListeSelectionMulti creeSelectionMulti() { return new EbliListeSelectionMulti(modeleDonnees().getNombre() / 2); } @@ -568,7 +581,19 @@ if (!isRapide()) initTrace(ligneModel, i); final GrPoint ptDest = new GrPoint(); - for (int j = nbPoints - 2; j >= 0; j--) { + // Dessine le premier segment avec une fleche si l'option est activ\xE9e + if(nbPoints>=2){ + modele_.point(ptDest, i, nbPoints - 2); + ptDest.autoApplique(versEcran); + // Pour les polygone \xE7a se passe plus loin + if(showLineOrientation_&&!modele_.isGeometryFermee(i)) + tl.dessineFleche(_g, (int)ptDest.x_, (int)ptDest.y_, (int)ptOri.x_, (int)ptOri.y_, 5, 3); + else + tl.dessineTrait(_g, ptOri.x_, ptOri.y_, ptDest.x_, ptDest.y_); + ptOri.initialiseAvec(ptDest); + } + // Dessine le reste + for (int j = nbPoints - 3; j >= 0; j--) { // le point de dest est initialise modele_.point(ptDest, i, j); ptDest.autoApplique(versEcran); @@ -578,7 +603,11 @@ if (modele_.isGeometryFermee(i)) { modele_.point(ptOri, i, nbPoints - 1); ptOri.autoApplique(versEcran); - tl.dessineTrait(_g, ptOri.x_, ptOri.y_, ptDest.x_, ptDest.y_); + // La fl\xE8che pour les polygone + if(showLineOrientation_) + tl.dessineFleche(_g, (int)ptOri.x_, (int)ptOri.y_, (int)ptDest.x_, (int)ptDest.y_, 5, 3); + else + tl.dessineTrait(_g, ptOri.x_, ptOri.y_, ptDest.x_, ptDest.y_); } modele_.point(ptOri, i, nbPoints - 1); ptOri.autoApplique(versEcran); Added: branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/action/SceneShowOrientationAction.java =================================================================== --- branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/action/SceneShowOrientationAction.java (rev 0) +++ branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/action/SceneShowOrientationAction.java 2008-11-17 14:54:27 UTC (rev 4221) @@ -0,0 +1,80 @@ +/* + * @creation 14 nov. 2008 + * @modification $Date:$ + * @license GNU General Public License 2 + * @copyright (c)1998-2008 CETMEF 2 bd Gambetta F-60231 Compiegne + * @mail fud...@li... + */ +package org.fudaa.ebli.calque.action; + +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; + +import org.fudaa.ebli.calque.BArbreCalqueModel; +import org.fudaa.ebli.calque.BCalque; +import org.fudaa.ebli.calque.BCalqueVisitor; +import org.fudaa.ebli.calque.ZCalqueLigneBrisee; +import org.fudaa.ebli.commun.EbliActionChangeState; +import org.fudaa.ebli.commun.EbliLib; + +import com.memoire.bu.BuResource; + +/** + * Une action pour montrer l'orientation des lignes dans les calques. + * @author Emmanuel MARTIN + * @version $Id:$ + */ +public class SceneShowOrientationAction extends EbliActionChangeState implements TreeModelListener { + + protected BArbreCalqueModel treeModel_; + + public SceneShowOrientationAction(BArbreCalqueModel _treeModel) { + super(EbliLib.getS("Affichage du sens des lignes"), BuResource.BU.getIcon("fleche"), "SHOW_ORIENTATION"); + treeModel_=_treeModel; + treeModel_.addTreeModelListener(this); + setEnabled(true); + } + + private void applyConf(){ + treeModel_.getRootCalque().apply(new BCalqueVisitor(){ + public boolean visit(BCalque _cq) { + if(_cq instanceof ZCalqueLigneBrisee) + ((ZCalqueLigneBrisee) _cq).setShowLineOrientation(isSelected()); + return true; + } + }); + } + + /* (non-Javadoc) + * @see javax.swing.event.TreeModelListener#treeNodesChanged(javax.swing.event.TreeModelEvent) + */ + public void treeNodesChanged(TreeModelEvent e) { + } + + /* (non-Javadoc) + * @see javax.swing.event.TreeModelListener#treeNodesInserted(javax.swing.event.TreeModelEvent) + */ + public void treeNodesInserted(TreeModelEvent e) { + applyConf(); + } + + /* (non-Javadoc) + * @see javax.swing.event.TreeModelListener#treeNodesRemoved(javax.swing.event.TreeModelEvent) + */ + public void treeNodesRemoved(TreeModelEvent e) { + } + + /* (non-Javadoc) + * @see javax.swing.event.TreeModelListener#treeStructureChanged(javax.swing.event.TreeModelEvent) + */ + public void treeStructureChanged(TreeModelEvent e) { + } + + /* (non-Javadoc) + * @see org.fudaa.ebli.commun.EbliActionChangeState#changeAction() + */ + @Override + public void changeAction() { + applyConf(); + } +} Property changes on: branches/FudaaModeleur_TC1Bis/fudaa_devel/ebli/src/org/fudaa/ebli/calque/action/SceneShowOrientationAction.java ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + native Modified: branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlEditionManager.java =================================================================== --- branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlEditionManager.java 2008-11-16 20:34:00 UTC (rev 4220) +++ branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlEditionManager.java 2008-11-17 14:54:27 UTC (rev 4221) @@ -29,6 +29,7 @@ import org.fudaa.fudaa.commun.FudaaLib; import org.fudaa.fudaa.modeleur.action.SceneDecimationAction; import org.fudaa.fudaa.modeleur.action.SceneInterpolationAction; +import org.fudaa.fudaa.modeleur.action.SceneInvertAction; import org.fudaa.fudaa.modeleur.action.SceneMoveInLayerAction; import org.fudaa.fudaa.modeleur.action.SceneProjectionAction; import org.fudaa.fudaa.modeleur.action.SceneRefinementAction; @@ -70,6 +71,7 @@ acts.add(new SceneMoveInLayerAction((MdlSceneEditor)sceneEditor_)); acts.add(new SceneDecimationAction((MdlSceneEditor)sceneEditor_)); acts.add(new SceneRefinementAction((MdlSceneEditor)sceneEditor_)); + acts.add(new SceneInvertAction((MdlSceneEditor)sceneEditor_)); acts.add(new SceneProjectionAction((MdlSceneEditor)sceneEditor_)); getSceneEditor().setActions(acts.toArray(new EbliActionAbstract[0])); } Modified: branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlSceneEditor.java =================================================================== --- branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlSceneEditor.java 2008-11-16 20:34:00 UTC (rev 4220) +++ branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlSceneEditor.java 2008-11-17 14:54:27 UTC (rev 4221) @@ -19,7 +19,9 @@ import javax.swing.JDialog; import javax.swing.JPanel; +import org.fudaa.ctulu.CtuluCommand; import org.fudaa.ctulu.CtuluCommandComposite; +import org.fudaa.ctulu.CtuluCommandContainer; import org.fudaa.ctulu.CtuluListSelection; import org.fudaa.ctulu.CtuluListSelectionInterface; import org.fudaa.ctulu.gis.GISAttributeConstants; @@ -454,4 +456,20 @@ } } } + + /** + * Inverse le sens de la polyligne. + */ + public void invertOrientationSelectedGeometries() { + CtuluCommandComposite cmd=new CtuluCommandComposite(FudaaLib.getS("Inversion de l'orientation")); + int[] geoms=getScene().getSelectionHelper().getSelectedIndexes(); + for (int i=0; i<geoms.length; i++) { + ZModeleDonnees mdld=getScene().getLayerForId(geoms[i]).modeleDonnees(); + if (mdld instanceof MdlModel2dLine) + ((MdlModel2dLine)mdld).invertOrientation(getScene().sceneId2LayerId(geoms[i]), cmd); + } + super.getScene().clearSelection(); + if (getMng()!=null) + getMng().addCmd(cmd.getSimplify()); + } } Modified: branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlVisuPanel.java =================================================================== --- branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlVisuPanel.java 2008-11-16 20:34:00 UTC (rev 4220) +++ branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/MdlVisuPanel.java 2008-11-17 14:54:27 UTC (rev 4221) @@ -9,11 +9,16 @@ import javax.swing.Action; +import org.fudaa.ebli.calque.BArbreCalque; import org.fudaa.ebli.calque.BGroupeCalque; import org.fudaa.ebli.calque.ZSelectionEvent; import org.fudaa.ebli.calque.ZSelectionListener; +import org.fudaa.ebli.calque.action.SceneSelectNextAction; +import org.fudaa.ebli.calque.action.SceneSelectPreviousAction; +import org.fudaa.ebli.calque.action.SceneShowOrientationAction; import org.fudaa.ebli.commun.EbliActionInterface; import org.fudaa.ebli.commun.EbliActionMap; +import org.fudaa.ebli.commun.EbliComponentFactory; import org.fudaa.ebli.ressource.EbliResource; import org.fudaa.fudaa.commun.FudaaLib; import org.fudaa.fudaa.commun.impl.FudaaCommonImplementation; @@ -39,6 +44,8 @@ import org.fudaa.fudaa.sig.layer.FSigVisuPanel; import org.fudaa.fudaa.tr.common.TrResource; +import com.memoire.bu.BuMenu; + /** * Le panneau de visu 2D des donn\xE9es du modeleur au travers des calques. Contient le composant vue * des calques + le composant d'affichage des coordonn\xE9es + le composant d'affichage du mode de selection @@ -70,6 +77,15 @@ mng_=editor.getMng(); return editor; } + + protected EbliActionInterface[] getActionsInterface(){ + EbliActionInterface[] actions=super.getActionsInterface(); + EbliActionInterface[] allActions=new EbliActionInterface[actions.length+1]; + for(int i=0;i<actions.length;i++) + allActions[i]=actions[i]; + allActions[allActions.length-1]=new SceneShowOrientationAction(gisEditor_.getPanel().getArbreCalqueModel()); + return allActions; + } public FSigLayerGroup getGroupGIS() { return /*parent_*/null; Added: branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/action/SceneInvertAction.java =================================================================== --- branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/action/SceneInvertAction.java (rev 0) +++ branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/action/SceneInvertAction.java 2008-11-17 14:54:27 UTC (rev 4221) @@ -0,0 +1,66 @@ +/* + * @creation 14 nov. 2008 + * @modification $Date:$ + * @license GNU General Public License 2 + * @copyright (c)1998-2008 CETMEF 2 bd Gambetta F-60231 Compiegne + * @mail fud...@li... + */ +package org.fudaa.fudaa.modeleur.action; + +import java.awt.event.ActionEvent; + +import org.fudaa.ebli.calque.ZScene; +import org.fudaa.ebli.calque.ZSelectionEvent; +import org.fudaa.ebli.calque.ZSelectionListener; +import org.fudaa.ebli.calque.ZScene.SceneSelectionHelper; +import org.fudaa.ebli.commun.EbliActionSimple; +import org.fudaa.ebli.ressource.EbliResource; +import org.fudaa.fudaa.modeleur.MdlSceneEditor; +import org.fudaa.fudaa.modeleur.layer.MdlLayer2dLine; + +/** + * Action permettant le changement de sens des polylignes selectionn\xE9es. + * @author Emmanuel MARTIN + * @version $Id:$ + */ +public class SceneInvertAction extends EbliActionSimple implements ZSelectionListener { + + protected MdlSceneEditor sceneEditor_; + + public SceneInvertAction(MdlSceneEditor _sceneEditor){ + super(EbliResource.EBLI.getString("Inverser"), null, "INVERSER"); + sceneEditor_=_sceneEditor; + sceneEditor_.getScene().addSelectionListener(this); + } + + public void actionPerformed(final ActionEvent _e) { + sceneEditor_.invertOrientationSelectedGeometries(); + } + + /** + * Autoris\xE9e si 1 ou plusieurs g\xE9om\xE9tries sont compl\xE8tes. + */ + public void updateForSelectionChanged() { + ZScene scn=sceneEditor_.getScene(); + SceneSelectionHelper hlp=sceneEditor_.getScene().getSelectionHelper(); + + boolean mdlLayer2dLine=true; + int i=-1; + int[] geom=hlp.getSelectedIndexes(); + while(mdlLayer2dLine&&++i<geom.length) + mdlLayer2dLine=scn.getLayerForId(geom[i]) instanceof MdlLayer2dLine; + + super.setEnabled(!scn.isSelectionEmpty()&&!scn.isAtomicMode()&&mdlLayer2dLine); + } + + public String getEnableCondition() { + return EbliResource.EBLI.getString("<p>En mode global, un ou plusieurs objet(s) de type polyligne ou polygone.</p>"); + } + + /* (non-Javadoc) + * @see org.fudaa.ebli.calque.ZSelectionListener#selectionChanged(org.fudaa.ebli.calque.ZSelectionEvent) + */ + public void selectionChanged(ZSelectionEvent _evt) { + updateForSelectionChanged(); + } +} Property changes on: branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/action/SceneInvertAction.java ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + native Modified: branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/layer/MdlModel2dLine.java =================================================================== --- branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/layer/MdlModel2dLine.java 2008-11-16 20:34:00 UTC (rev 4220) +++ branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/modeleur/layer/MdlModel2dLine.java 2008-11-17 14:54:27 UTC (rev 4221) @@ -15,11 +15,14 @@ import org.fudaa.ctulu.CtuluCommandContainer; import org.fudaa.ctulu.CtuluListSelection; import org.fudaa.ctulu.CtuluListSelectionInterface; +import org.fudaa.ctulu.CtuluNamedCommand; import org.fudaa.ctulu.gis.GISGeometryFactory; import org.fudaa.ctulu.gis.GISPolyligne; import org.fudaa.ctulu.gis.GISZoneCollectionLigneBrisee; import org.fudaa.ebli.calque.ZModelGeometryListener; +import org.fudaa.ebli.calque.ZModelListener; import org.fudaa.ebli.calque.edition.ZModeleLigneBriseeEditable; +import org.fudaa.fudaa.commun.FudaaLib; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateSequence; @@ -252,4 +255,33 @@ _cmd.addCmd(cmd.getSimplify()); return true; } + + /** + * Inverse le sens de la polyligne. + * @param _idxGeom index de la g\xE9om\xE9trie \xE0 inverser. + * @param _cmd Le container de commandes. + */ + public void invertOrientation(final int _idxGeom, CtuluCommandContainer _cmd){ + LineString geom=(LineString)getGeomData().getGeometry(_idxGeom); + CoordinateSequence seq=geom.getCoordinateSequence(); + for(int i=0;i<seq.size()/2;i++) + for(int j=0;j<3;j++){ + double valTmp=seq.getOrdinate(i, j); + seq.setOrdinate(i, j, seq.getOrdinate(seq.size()-1-i, j)); + seq.setOrdinate(seq.size()-1-i, j, valTmp); + } + fireModelAction(_idxGeom, geom, ZModelListener.GEOMETRY_ACTION_MODIFY); + if (_cmd!=null) + _cmd.addCmd(new CtuluNamedCommand() { + public void redo() { + invertOrientation(_idxGeom, null); + } + public void undo() { + invertOrientation(_idxGeom, null); + } + public String getName() { + return FudaaLib.getS("Inversion de l'orientation"); + } + }); + } } Modified: branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/sig/layer/FSigVisuPanel.java =================================================================== --- branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/sig/layer/FSigVisuPanel.java 2008-11-16 20:34:00 UTC (rev 4220) +++ branches/FudaaModeleur_TC1Bis/fudaa_devel/fudaa/src/org/fudaa/fudaa/sig/layer/FSigVisuPanel.java 2008-11-17 14:54:27 UTC (rev 4221) @@ -14,12 +14,9 @@ import javax.swing.JComponent; -import com.memoire.bu.BuMenu; - import org.fudaa.ctulu.CtuluCommandManager; import org.fudaa.ctulu.CtuluLib; import org.fudaa.ctulu.CtuluUndoRedoInterface; - import org.fudaa.ebli.calque.BArbreCalque; import org.fudaa.ebli.calque.BGroupeCalque; import org.fudaa.ebli.calque.ZCalqueGrille; @@ -29,8 +26,9 @@ import org.fudaa.ebli.calque.action.EditVisibilityAction; import org.fudaa.ebli.calque.action.SceneDeplacementAction; import org.fudaa.ebli.calque.action.SceneRotationAction; +import org.fudaa.ebli.calque.action.SceneSelectNextAction; import org.fudaa.ebli.calque.action.SceneSelectPreviousAction; -import org.fudaa.ebli.calque.action.SceneSelectNextAction; +import org.fudaa.ebli.calque.action.SceneShowOrientationAction; import org.fudaa.ebli.calque.edition.ZCalqueDeplacement; import org.fudaa.ebli.calque.edition.ZCalqueEditionGroup; import org.fudaa.ebli.calque.edition.ZEditorDefault; @@ -38,10 +36,11 @@ import org.fudaa.ebli.commun.EbliComponentFactory; import org.fudaa.ebli.commun.EbliFormatter; import org.fudaa.ebli.commun.EbliSelectionMode; - import org.fudaa.fudaa.commun.impl.FudaaCommonImplementation; import org.fudaa.fudaa.sig.FSigAttibuteTypeManager; +import com.memoire.bu.BuMenu; + /** * Le panneau de visualisation 2D g\xE9rant les calques. Cette classe ajoute la gestion * les calques SIG et des services associ\xE9s. @@ -120,16 +119,24 @@ return editor; } + /** + * @return un tableau contenant les actions sp\xE9cifiques \xE0 l'application qui + * seront dans le menu Vue2D. + */ + protected EbliActionInterface[] getActionsInterface(){ + return new EbliActionInterface[] { + null, + new SceneSelectPreviousAction(gisEditor_.getSceneEditor()), + new SceneSelectNextAction(gisEditor_.getSceneEditor()) + }; + } + protected BuMenu[] createSpecificMenus(final String _title) { final BuMenu[] res = new BuMenu[2]; res[0] = new BuMenu(_title, "LAYER"); res[0].setIcon(null); res[0].add(BArbreCalque.buildZNormalMenu(modelArbre_)); - EbliComponentFactory.INSTANCE.addActionsToMenu(new EbliActionInterface[] { - null, - new SceneSelectPreviousAction(gisEditor_.getSceneEditor()), - new SceneSelectNextAction(gisEditor_.getSceneEditor()) - },res[0]); + EbliComponentFactory.INSTANCE.addActionsToMenu(getActionsInterface(),res[0]); fillMenuWithToolsActions(res[0]); res[1] = getThemeMenu(); res[1].setMnemonic(res[1].getText().charAt(0)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |