From: <had...@us...> - 2008-10-30 16:04:56
|
Revision: 4114 http://fudaa.svn.sourceforge.net/fudaa/?rev=4114&view=rev Author: hadouxad Date: 2008-10-30 16:04:39 +0000 (Thu, 30 Oct 2008) Log Message: ----------- - correction de plusieurs bug - robustesse du systeme de sauvegarde des layouts Modified Paths: -------------- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/EbliWidget.java branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/actions/EbliWidgetGroupAction.java branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/actions/EbliWidgetUngroupAction.java branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetCreatorLegende.java branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetFusionCalques.java branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetVueCalque.java branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/graphe/EbliWidgetCreatorLegende.java branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/graphe/EbliWidgetGraphe.java branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/TrPostScene.java branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/TrPostVisuPanelPersistManager.java branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/persist/TrPostPersistanceErrorManager.java branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/persist/TrPostPersistenceManager.java Modified: branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/EbliWidget.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/EbliWidget.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/EbliWidget.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -538,5 +538,7 @@ return null; } - + public void setSattelite(List<EbliWidget> liste) { + + } } \ No newline at end of file Modified: branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/actions/EbliWidgetGroupAction.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/actions/EbliWidgetGroupAction.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/actions/EbliWidgetGroupAction.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -13,6 +13,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.fudaa.ctulu.CtuluCommand; @@ -148,6 +149,8 @@ final EbliWidget ew = (EbliWidget) findWidget; ew.getController().removeActionResize(); // scene_.removeNode((EbliNode) object); + + findWidget.removeFromParent(); final int dx = rec.x - min.x; final int dy = rec.y - min.y; Modified: branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/actions/EbliWidgetUngroupAction.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/actions/EbliWidgetUngroupAction.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/actions/EbliWidgetUngroupAction.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -51,6 +51,8 @@ final Point p = widget.getLocation(); final Point toScene = w.convertLocalToScene(p); final EbliNode n = (EbliNode) _scene.findObject(widget); + List<EbliWidget> listeSattellites=((EbliWidget)widget).getSattelite(); + widget.removeFromParent(); // -- utilis\xE9 pour enlever les propertychange listener @@ -68,6 +70,9 @@ // widget.setPreferredLocation(toScene); _scene.addNode(n).setPreferredLocation(toScene); n.getWidget().getController().replaceActionResize(); + if(listeSattellites!=null) + n.getWidget().getIntern().setSattelite(listeSattellites); + } _scene.removeNode(_n); // } Modified: branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetCreatorLegende.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetCreatorLegende.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetCreatorLegende.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -1,6 +1,7 @@ package org.fudaa.ebli.visuallibrary.calque; import java.awt.Font; +import java.util.List; import java.util.Map; import org.fudaa.ebli.calque.BCalque; @@ -129,6 +130,33 @@ // -- mise a jour des sattelites --// ((EbliWidgetControllerCalque) widget.getController()).setNodeLegende((EbliNode) parameters.get("node")); + }else{ + ((List<String>)parameters.get("errorMsg")).add("Erreur, la frame Legende ne trouve pas sa frame calque d'ID "+idCalque); + + //-- recherche dans les children de la scene le premier calque qui fera l'affaire --// + for(EbliNode nodeSubstitut:scene.getNodes()){ + + if(nodeSubstitut.getWidget().getIntern() instanceof EbliWidgetVueCalque){ + ((List<String>)parameters.get("errorMsg")).add("Par consequent, la frame Legende sera rattachee a la frame calque d'ID "+nodeSubstitut.getWidget().getId()); + widget=nodeSubstitut.getWidget().getIntern(); + ZEbliCalquesPanel calque=((EbliWidgetControllerCalque) widget.getController()).getVisuPanel(); + + //-- recuperation du bon calque --// + calqueCible_= (BCalque) calque.getArbreCalqueModel().getChild(calque.getArbreCalqueModel().getRoot(), indexCalque); + IdPossessor_=idCalque; + //g=new BCalqueLegendePanel((BCalqueAffichage) calqueCible_,calqueCible_.getTitle()); + BCalqueLegendePanel legendePanel=((CalqueLegendeWidgetAdapter)calque.getCqLegend()).legendePanel_; + g=legendePanel; + // -- mise a jour des sattelites --// + ((EbliWidgetControllerCalque) widget.getController()).setNodeLegende((EbliNode) parameters.get("node")); + break; + } + + + } + + + } Modified: branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetFusionCalques.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetFusionCalques.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetFusionCalques.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -4,6 +4,7 @@ import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import org.fudaa.ebli.calque.BVueCalque; import org.fudaa.ebli.calque.ZCalqueSondeInteraction; @@ -187,4 +188,25 @@ managerSondesFusion_.removeAllListenningSonde(); } + + public boolean hasSattelite() { + + return true; + + } + + public List<EbliWidget> getSattelite() { + + List<EbliWidget> liste = new ArrayList<EbliWidget>(); + + for (int i = listeWidgetCalque_.size() - 1; i >= 0; i--) { + EbliWidgetVueCalque vue = listeWidgetCalque_.get(i); + if(vue.hasSattelite()) + liste.addAll(vue.getSattelite()); + } + return liste; + + } + + } Modified: branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetVueCalque.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetVueCalque.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/calque/EbliWidgetVueCalque.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -23,6 +23,7 @@ import org.fudaa.ebli.calque.ZEbliCalquesPanel; import org.fudaa.ebli.geometrie.GrBoite; import org.fudaa.ebli.visuallibrary.EbliNode; +import org.fudaa.ebli.visuallibrary.EbliNodeDefault; import org.fudaa.ebli.visuallibrary.EbliScene; import org.fudaa.ebli.visuallibrary.EbliWidget; import org.fudaa.ebli.visuallibrary.animation.EbliWidgetAnimatedItem; @@ -278,5 +279,17 @@ return liste; } + + public void setSattelite(List<EbliWidget> liste) { + if(liste.size()<=0) + return; + + EbliWidget widg=liste.get(0); + + EbliNodeDefault node= (EbliNodeDefault) getEbliScene().findObject(widg); + getCalqueController().setNodeLegende( node); + + + } } Modified: branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/graphe/EbliWidgetCreatorLegende.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/graphe/EbliWidgetCreatorLegende.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/graphe/EbliWidgetCreatorLegende.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -1,7 +1,11 @@ package org.fudaa.ebli.visuallibrary.graphe; +import java.util.List; import java.util.Map; +import org.fudaa.ebli.calque.BCalque; +import org.fudaa.ebli.calque.BCalqueLegendePanel; +import org.fudaa.ebli.calque.ZEbliCalquesPanel; import org.fudaa.ebli.courbe.EGGraphe; import org.fudaa.ebli.courbe.EGGrapheTreeModel; import org.fudaa.ebli.visuallibrary.EbliNode; @@ -10,6 +14,9 @@ import org.fudaa.ebli.visuallibrary.EbliWidget; import org.fudaa.ebli.visuallibrary.EbliWidgetBordureSingle; import org.fudaa.ebli.visuallibrary.EbliWidgetWithBordure; +import org.fudaa.ebli.visuallibrary.calque.CalqueLegendeWidgetAdapter; +import org.fudaa.ebli.visuallibrary.calque.EbliWidgetControllerCalque; +import org.fudaa.ebli.visuallibrary.calque.EbliWidgetVueCalque; import org.fudaa.ebli.visuallibrary.creator.EbliWidgetCreator; public class EbliWidgetCreatorLegende implements EbliWidgetCreator { @@ -86,6 +93,7 @@ idPossessor_ = (String) data; // -- recuperation du node graphe--// + final EbliNode nodeGraphe = ((EbliScene) parameters.get("scene")).findByWidgetId(idPossessor_); if (nodeGraphe != null && nodeGraphe.getCreator() instanceof EbliWidgetCreatorGraphe) { @@ -96,7 +104,31 @@ .get("node")); - } else g = new EGGraphe(new EGGrapheTreeModel()); + } else{ + ((List<String>)parameters.get("errorMsg")).add("Erreur, la frame Legende ne trouve pas sa frame graphe d'ID "+idPossessor_); + + //-- recherche dans les children de la scene le premier calque qui fera l'affaire --// + for(EbliNode nodeSubstitut:((EbliScene) parameters.get("scene")).getNodes()){ + + if(nodeSubstitut.getCreator() instanceof EbliWidgetCreatorGraphe){ + ((List<String>)parameters.get("errorMsg")).add("Par consequent, la frame Legende sera rattachee a la frame graphe d'ID "+nodeSubstitut.getWidget().getId()); + g = ((EbliWidgetCreatorGraphe)nodeSubstitut.getCreator()).getGraphe(); + + + // -- mise a jour des sattelites --// + ((EbliWidgetGraphe) nodeSubstitut.getWidget().getIntern()).setNodeLegende((EbliNodeDefault) parameters + .get("node")); + break; + } + + + } + + + + } + + //else g = new EGGraphe(new EGGrapheTreeModel()); } else g = new EGGraphe(new EGGrapheTreeModel()); } Modified: branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/graphe/EbliWidgetGraphe.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/graphe/EbliWidgetGraphe.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/ebli/src/org/fudaa/ebli/visuallibrary/graphe/EbliWidgetGraphe.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -18,6 +18,7 @@ import org.fudaa.ebli.courbe.EGGraphe; import org.fudaa.ebli.courbe.EGGrapheModelListener; import org.fudaa.ebli.courbe.EGObject; +import org.fudaa.ebli.visuallibrary.EbliNode; import org.fudaa.ebli.visuallibrary.EbliNodeDefault; import org.fudaa.ebli.visuallibrary.EbliScene; import org.fudaa.ebli.visuallibrary.EbliWidget; @@ -290,4 +291,16 @@ } + public void setSattelite(List<EbliWidget> liste) { + if(liste.size()<=0) + return; + + EbliWidget widg=liste.get(0); + + EbliNodeDefault node= (EbliNodeDefault) getEbliScene().findObject(widg); + setNodeLegende( node); + + + } + } Modified: branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/TrPostScene.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/TrPostScene.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/TrPostScene.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -104,6 +104,7 @@ EGGraphe graphe=((EbliWidgetCreatorGraphe)node.getCreator()).getGraphe(); if(graphe.getModel() instanceof MvProfileTreeModel){ MvProfileTreeModel model=(MvProfileTreeModel) graphe.getModel() ; + if(model !=null && model.target_!=null) if(model.target_.getData() !=null && model.target_.getData() instanceof TrPostSource){ TrPostSource sourceGraphe=(TrPostSource) model.target_.getData(); if(sourceGraphe==src) Modified: branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/TrPostVisuPanelPersistManager.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/TrPostVisuPanelPersistManager.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/TrPostVisuPanelPersistManager.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.util.List; import java.util.Map; import org.fudaa.ctulu.CtuluArkSaver; @@ -86,7 +87,13 @@ if (src == null) { // TrPostMultiSourceActivator activator = new TrPostMultiSourceActivator(projet); // activator.active(new File(idSource), projet.getImpl()); - return null; + ((List<String>)parameters.get("errorMsg")).add("Erreur, la frame calque ne trouve pas le fichier r\xE9sultat qui correspond \xE0 l'ID "+idSource); + if(projet.listeSrc_.size()>0){ + ((List<String>)parameters.get("errorMsg")).add("Le calque chargera en contrepartie le fichier r\xE9sultat "+projet.getSource(0).getFile().getPath()); + //return null; + src=projet.getSource(0); + } + else return null; } // -- etape 3: creation du legende adapter --// Modified: branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/persist/TrPostPersistanceErrorManager.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/persist/TrPostPersistanceErrorManager.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/persist/TrPostPersistanceErrorManager.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -2,18 +2,24 @@ import java.awt.BorderLayout; import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; +import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; +import javax.swing.event.TableModelListener; import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableModel; import org.fudaa.ctulu.CtuluUI; import org.fudaa.ctulu.gui.CtuluLibSwing; +import org.fudaa.ebli.ressource.EbliResource; import org.fudaa.fudaa.tr.common.TrResource; @@ -34,44 +40,60 @@ public void clear(){ listeMessageError.clear(); + } - private class ModeleTableError extends DefaultTableModel{ - - - java.util.List<String> listeMessageError_; - + private static class ModeleTableError implements TableModel{ + java.util.List<String> liste_; public ModeleTableError(List<String> listeMessage) { - - - listeMessageError_ = listeMessage; + super(); + liste_ = listeMessage; } - @Override public int getColumnCount() { // TODO Auto-generated method stub return 1; } - @Override public String getColumnName(int column) { // TODO Auto-generated method stub return "Messages"; } - @Override public int getRowCount() { // TODO Auto-generated method stub - return listeMessageError_.size(); + return liste_.size(); } - @Override public Object getValueAt(int row, int column) { // TODO Auto-generated method stub - return listeMessageError_.get(row); + return liste_.get(row); } - - + @Override + public void addTableModelListener(TableModelListener l) { + // TODO Auto-generated method stub + + } + @Override + public Class<?> getColumnClass(int columnIndex) { + // TODO Auto-generated method stub + return String.class; + } + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + // TODO Auto-generated method stub + return false; + } + @Override + public void removeTableModelListener(TableModelListener l) { + // TODO Auto-generated method stub + + } + @Override + public void setValueAt(Object value, int rowIndex, int columnIndex) { + // TODO Auto-generated method stub + + } } public void showDialog(CtuluUI ui){ @@ -81,18 +103,32 @@ return; } - JTable table=new JTable(new DefaultTableModel(listeMessageError.toArray(),listeMessageError.size())); + JTable table=new JTable(new ModeleTableError(listeMessageError)); final Frame f = CtuluLibSwing.getFrameAncestorHelper(ui.getParentComponent()); - JDialog dialog_ = new JDialog(f); + final JDialog dialog_ = new JDialog(f); dialog_.setModal(true); dialog_.setTitle("Chargement termin\xE9"); final JPanel container = new JPanel(new BorderLayout()); container.add(new JScrollPane(table), BorderLayout.CENTER); container.add(new JLabel( TrResource.getS("Chargement termin\xE9 avec erreur(s)")),BorderLayout.NORTH); + + JButton ajouter_ = new JButton("Valider", EbliResource.EBLI.getIcon("crystal_valider")); + ajouter_.addActionListener(new ActionListener(){ + + @Override + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + dialog_.dispose(); + } + + }); + container.add((new JPanel()).add(ajouter_),BorderLayout.SOUTH); + dialog_.setContentPane(container); dialog_.setLocationRelativeTo(ui.getParentComponent()); - dialog_.setSize(300,200); + //dialog_.pack(); + dialog_.setSize(600,250); dialog_.setVisible(true); } Modified: branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/persist/TrPostPersistenceManager.java =================================================================== --- branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/persist/TrPostPersistenceManager.java 2008-10-30 14:27:59 UTC (rev 4113) +++ branches/Prepro-0.92-SNAPSHOT/fudaa/src/org/fudaa/fudaa/tr/post/persist/TrPostPersistenceManager.java 2008-10-30 16:04:39 UTC (rev 4114) @@ -346,7 +346,7 @@ final int nbFichiersToGenrate = listeFilles.size(); out.writeInt(nbFichiersToGenrate); - for (int i = 0; i < nbFichiersToGenrate; i++) { + for (int i = nbFichiersToGenrate-1; i >=0; i--) { // creation du fichier de desciption des scenes dans le repertoire de meme nom. String nomLayout=FuLib.clean(listeFilles.get(i).previousTitleFrame); String nomFichierLayout = nomLayout + EXTENSION_REPLAYOUT + File.separator + DESCRIPTORSCENE ; @@ -909,8 +909,8 @@ parametres.put("path", projet_.getAbsolutePath()); parametres.put("ui", ui_); parametres.put("TrPostProjet", trprojet_); + parametres.put("errorMsg", managerError.listeMessageError); - // -- etape 5 lecture de la liste des couples nomsfRAME /ID --// file = new File(projet_.getAbsolutePath() + File.separator + FileWidgetNames); final List<EbliWidgetSerializeXml.CoupleNomId> listeCouplesNoms = loadNomsFrames(file); @@ -1121,6 +1121,7 @@ for (final CoupleNomId couple : listeCouplesNoms) { if (couple.id.equals(idWidget)) return couple.nom; } + this.managerError.addMessageError(this.FileWidgetNames+": Il n'existe pas de nom correspondant \xE0 la frame d'ID "+idWidget); return ""; } @@ -1175,7 +1176,12 @@ for (int i = 0; i < sceneXml.getNbFrames(); i++) { // lecture xml de l objet - final EbliWidgetSerializeXml widgetXml = (EbliWidgetSerializeXml) in.readObject(); + final Object objetXml = in.readObject(); + if(objetXml==null || !(objetXml instanceof EbliWidgetSerializeXml)){ + managerError.addMessageError(nomRepertoireLayout+": l'objet xml N\xB0"+i+" lu n'est pas un descripteur de frame valide"); + }else{ + final EbliWidgetSerializeXml widgetXml =(EbliWidgetSerializeXml) objetXml; + if(!widgetXml.isLinked()){ // generation de la widget dans la scene parametres.put("nodeName", getNodeName(listeCouplesNoms, widgetXml.getId())); @@ -1204,6 +1210,7 @@ } } + } // --On executre les widgets liees --// for (EbliWidgetSerializeXml widgetXml : listeWidgetLinked) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |