Karima Rafes has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/76331


Change subject: Add tag extension lwgraph to insert a graph in the page (first 
graph : horizontal flow graph)
......................................................................

Add tag extension lwgraph to insert a graph in the page (first graph : 
horizontal flow graph)

Change-Id: I87650a8b611e86e96fb849b29c69f6dd7fa69051
---
M LinkedWiki.php
A js/flowchart.js
A js/lwgraph.js
3 files changed, 559 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/LinkedWiki 
refs/changes/31/76331/1

diff --git a/LinkedWiki.php b/LinkedWiki.php
index 377e969..b525f47 100644
--- a/LinkedWiki.php
+++ b/LinkedWiki.php
@@ -45,6 +45,15 @@
        'ext.LinkedWiki.table2CSV' => $linkedWikiTpl + array(
                'scripts' => 'table2CSV.js',
        ),
+       'ext.LinkedWiki.lwgraph' => $linkedWikiTpl + array(
+               'scripts' => 'lwgraph.js',
+       ),
+       'ext.LinkedWiki.flowchart' => $linkedWikiTpl + array(
+               'scripts' => 'flowchart.js',
+               'dependencies' => array(
+                       'ext.LinkedWiki.lwgraph',
+               )
+       ),
 );
 
 //Paths
@@ -82,6 +91,7 @@
        $parser->setFunctionHook( 'sparql', 'efSparqlParserFunction_Render' );
        $parser->setFunctionHook( 'wsparql', 'efWsparqlParserFunction_Render' );
        $parser->setFunctionHook( 'properties', 
'efPropertiesParserFunction_Render' );
+       $parser->setHook( 'lwgraph', 'efLwgraphRender' );
        
        return true;
 }
@@ -103,6 +113,42 @@
        return 
SparqlTools::decodeURItoIRI($resolverurl).$parser->getTitle()->getPrefixedDBkey();
 }
 
+function efLwgraphRender( $input, array $args, Parser $parser, PPFrame $frame 
) {
+      global $wgOut;
+       $html = "";
+        $width = isset($args["width"])?$args["width"]:"100%";
+        $height = isset($args["height"])?$args["height"]:"150px";
+        $border = isset($args["border"]) && $args["border"]>0 ? 
"border:".$args["border"]."px solid #000000;" : "" ;
+        
+       if (isset($args["debug"]) && $args["debug"] == "true"){        
+           $attr = array();    
+           foreach( $args as $name => $value )
+                   $attr[] =  $name . ' = ' .  $value ;
+                   
+           $html .= "<div><b>lwgraph DEBUG :</b><br/>".implode( '<br/>', $attr 
)."</div>";
+            $html .= "<pre>".htmlspecialchars( $input )."</pre>";            
+           
+        }
+        
+        if (isset($args["type"]) == "flow"){ 
+           $wgOut->addModules('ext.LinkedWiki.flowchart');   
+        }
+        
+        preg_match_all("/\[\[([^\]\|]*)(?:\|[^\]]*)?\]\]/U", $input,$out);
+        $arrayTitle = array_unique ($out[1]);
+        
+        $textGraph = $input;
+        foreach ($arrayTitle as $title) {
+         $titleObject = Title::newFromText( $title );
+         if ( !$titleObject->exists() ) 
+             $textGraph = str_replace("[[".$title, "~[[".$title, $textGraph);
+             $textGraph = str_replace("~~", "~", $textGraph);
+       }
+        $html .= "<canvas  class=\"lwgraph-flow\" style=\"".$border."width: 
".$width.";height:".$height."\">".$textGraph."</canvas>";
+        
+        return array($html, 'isHTML' => true);
+}
+
 function efSparqlParserFunction_Render( $parser) {
        //global 
$wgLinkedWikiLocalEndPoint,$wgLinkedWikiEndPoint,$wgLinkedWikiGraphWiki;
        global $wgOut;
diff --git a/js/flowchart.js b/js/flowchart.js
new file mode 100644
index 0000000..f37cd9b
--- /dev/null
+++ b/js/flowchart.js
@@ -0,0 +1,356 @@
+function lwFlowChart($canvas,graphStr){
+  this.tabLines = new Array();
+  this.margemin = 10;
+  this.margex = 10;
+  this.margey = 10;
+  this.a = $canvas[0].getContext('2d');
+  this.ratio = 0;
+  
+  //BEGIN CONSTRUCTOR
+  var regLine = 
/(?:=(?:(~*)\[\[([^\]\|]*)(?:\|([^\]]*))?\]\])?=>)?(~*)\[\[([^\]\|]*)(?:\|([^\]]*))?\]\]/g;
+  
+  //Read shape arrow and rect
+  //console.log(graphStr);
+  var lines = graphStr.split("\n");  
+  for(i in lines){
+    var line  = lines[i].trim();
+    //console.log(lines[i]); 
+    if(line != ""){
+      var flowChartLine = new lwFlowChartLine();
+      var first = true;
+      while ((myArray = regLine.exec(line)) !== null)
+      {
+       //var msg = myArray[0]+"\n";
+       //msg += "1 Exist property page: " +  myArray[1] +"\n";
+       //msg += "2 property title page: " +  myArray[2] +"\n";
+       //msg += "3 property label : " +  myArray[3]+"\n";
+       //msg += "4 Exist object page : " +  myArray[4]+"\n";
+       //msg += "5 object title page : " +  myArray[5]+"\n";
+       //msg += "6 object label : " +  myArray[6]+"\n";
+       //console.log(msg);
+       if(!first){
+         if(myArray[1] != undefined){
+           flowChartLine.addShape(new 
lwFlowChartShape(myArray[2],myArray[3],myArray[1]!="~",true));
+         }else{
+           flowChartLine.addShape(new lwFlowChartShape(null,null,null,true));
+         }
+       }
+       flowChartLine.addShape(new 
lwFlowChartShape(myArray[5],myArray[6],myArray[4]!="~",false));
+       first = false;
+      }
+      this.tabLines.push(flowChartLine);      
+    }      
+  }
+
+  //Calculate size
+  //console.log(this.tabLines);
+  var heightLine = 60;
+  var nbLine = 0;
+  for(var i in this.tabLines){
+      var line = this.tabLines[i];     
+      for(var j in line.shapes){
+       var shape = line.shapes[j];
+       shape.label = shape.label == null ? shape.title :  shape.label;
+       if(shape.isArrow){
+         shape.width = 
$canvas.lwDrawLineArrow(shape.label,"red",0,0,0,0,false); 
+       }else{
+         shape.width = $canvas.lwDrawRect(shape.label,"red",0,0,false);  
+       }
+       shape.height = 40;
+       shape.centery= heightLine*nbLine + heightLine/2;
+       var beforex = 0;
+       if(shape.pointerShapesBefore.length > 0){
+          beforex = shape.pointerShapesBefore[0].rightx ;
+       }
+       shape.centerx= beforex + shape.width/2;
+       
+       shape.rightx= shape.centerx + shape.width/2;
+       shape.righty= shape.centery;
+       
+       shape.leftx= shape.centerx - shape.width/2;
+       shape.lefty= shape.centery;
+       
+       shape.topx=shape.centerx;
+       shape.topy=shape.centery - heightLine/2;
+       shape.downx=shape.centerx;
+       shape.downy=shape.centery + heightLine/2;
+       
+       if(nbLine == 0)
+         shape.fixed=true;
+       
+      }
+      nbLine++;
+  }
+  ///////////////
+    
+  //Build array shape fixed and to link shapes 
+  var arrayShapeFixed = this.tabLines[0].shapes;
+  for(var iline = 1 ; iline < (this.tabLines.length) ; iline++){
+      for(var i = 0; i < arrayShapeFixed.length; i++){
+           var shapeFixed = arrayShapeFixed[i];
+           for(l in this.tabLines){
+               var line = this.tabLines[l];     
+               for(j in line.shapes){
+                 var shape = line.shapes[j];
+                 if(!shape.fixed && !shape.isArrow && shape.title == 
shapeFixed.title){
+                   for(var b = 0; b < shape.pointerShapesAfter.length; b++){
+                     shape.pointerShapesAfter[b].leftx = shapeFixed.rightx;
+                     shape.pointerShapesAfter[b].lefty = shapeFixed.righty;
+                     shape.pointerShapesAfter[b].removeShapeBefore(shape);
+                     shape.pointerShapesAfter[b].addShapeBefore(shapeFixed);
+                     shapeFixed.addShapeAfter(shape.pointerShapesAfter[b]);
+                   }
+                   for(var a = 0; a <  shape.pointerShapesBefore.length; a++){
+                     shape.pointerShapesBefore[a].rightx = shapeFixed.leftx;
+                     shape.pointerShapesBefore[a].righty = shapeFixed.lefty;
+                     shape.pointerShapesBefore[a].removeShapeAfter(shape);
+                     shape.pointerShapesBefore[a].addShapeAfter(shapeFixed);   
              
+                     shapeFixed.addShapeBefore(shape.pointerShapesBefore[a]);
+                   }
+                    line.shapes.splice(j,1);
+                 }               
+               } 
+           }
+      }
+      for(var s in this.tabLines[iline].shapes)
+       this.tabLines[iline].shapes[s].fixed = true;
+      arrayShapeFixed = arrayShapeFixed.concat(this.tabLines[iline].shapes);
+      //console.log(arrayShapeFixed);
+  }
+
+  //Calculate the good position
+   for(var s in arrayShapeFixed){
+       var shape = arrayShapeFixed[s];
+       shape.checkPlace();
+    } 
+      
+    //calc size of the graph
+    var xmax = 0;
+    var ymax = 0;
+   for(var s in arrayShapeFixed){
+       var shape = arrayShapeFixed[s];
+       if(shape.rightx > xmax)
+          xmax = shape.rightx;
+       if(shape.downy > ymax)
+          ymax = shape.downy;
+    } 
+    
+  //resize the graph in the canvas
+  var ratiox = $canvas[0].width / (this.margemin*2 + xmax);
+  var ratioy = $canvas[0].height / (this.margemin*2 +ymax );
+    //console.log("ratiox"+ratiox);
+    //console.log("ratioy"+ratioy);
+  
+    this.a.save();
+    if(ratiox<ratioy)
+    {
+      this.ratio = ratiox;
+    this.a.scale(this.ratio,this.ratio);
+      this.margex = this.margemin;
+      this.margey = ($canvas[0].height - ymax*ratiox)/2;
+    }
+    else
+    {
+      this.ratio = ratioy;
+    this.a.scale(this.ratio,this.ratio);
+      this.margex = ($canvas[0].width - xmax*ratioy)/2 ;
+      this.margey = this.margemin;
+    }       
+    
+    this.a.translate(this.margex ,this.margey );
+    
+   // a.beginPath();
+   // a.rect(0, 0, xmax, ymax);
+   // a.lineWidth = 2;
+   // a.strokeStyle = 'red';
+   // a.stroke();  
+    
+  ///////////////
+    
+  //draw the graph
+  for(i in this.tabLines){
+      var line = this.tabLines[i];     
+      for(j in line.shapes){
+       var shape = line.shapes[j];
+       var color = shape.isPageExist ? "black" : "red";
+       if(shape.isArrow){
+         shape.width = $canvas.lwDrawLineArrow(
+           shape.label,
+           color,
+           shape.leftx,
+           shape.lefty,
+           shape.rightx,
+           shape.righty,
+           true); 
+       }else{
+         
$canvas.lwDrawRect(shape.label,color,shape.centerx,shape.centery,true);     
+       }
+      }
+   }
+   
+  this.a.restore();
+  
+  //END CONSTRUCTOR
+  
+  //return the shape without the pointer
+  this.getShape= function (x,y)
+  {
+       for(i in this.tabLines){
+           var line = this.tabLines[i];     
+           for(j in line.shapes){
+             var shape = line.shapes[j];
+             var xmin = shape.leftx * this.ratio + this.margex ;
+             var xmax = shape.rightx * this.ratio + this.margex ;
+             var ymin = shape.topy * this.ratio + this.margey ;
+             var ymax = shape.downy * this.ratio + this.margey ;
+               if(x > xmin && x < xmax && y  > ymin && y < ymax )
+                 return shape;
+            }
+       }
+       return null;
+  }
+}
+
+function lwFlowChartLine()
+{
+  this.shapes=new Array();
+  this.addShape= function (shape)
+  {
+    if(this.shapes[this.shapes.length-1]!=undefined){
+       var shapeBefore =  this.shapes[this.shapes.length-1];
+      shape.addShapeBefore(shapeBefore);
+      shapeBefore.addShapeAfter(shape);
+    }
+    this.shapes.push(shape);
+  }
+}
+
+function lwFlowChartShape(title,label,isPageExist,isArrow)
+{
+  this.centerx=0;
+  this.centery=0;
+  this.topx=0;
+  this.topy=0;
+  this.rightx=0;
+  this.righty=0;
+  this.downx=0;
+  this.downy=0;
+  this.leftx=0;
+  this.lefty=0;
+  this.width=0;
+  this.height=0;
+  this.title=title;
+  this.label=label;
+  this.isPageExist=isPageExist;
+  this.isArrow=isArrow;
+  this.fixed=false;
+  this.pointerShapesBefore=new Array();
+  this.pointerShapesAfter=new Array();
+
+  this.addShapeBefore= function (shape)
+  {
+    this.pointerShapesBefore.push(shape);
+  }
+
+  this.addShapeAfter= function (shape)
+  {
+    this.pointerShapesAfter.push(shape);
+  }
+  
+  this.removeShapeBefore= function (shape)
+  {
+      for(var i = 0; i < this.pointerShapesBefore.length; i++) {
+         if(this.pointerShapesBefore[i] === shape) {
+           this.pointerShapesBefore.splice(i, 1);
+         }
+      }
+  }
+
+  this.removeShapeAfter= function (shape)
+  {
+      for(var i = 0; i < this.pointerShapesAfter.length; i++) {
+         if(this.pointerShapesAfter[i] === shape) {
+           this.pointerShapesAfter.splice(i, 1);
+         }
+      }
+  }  
+   
+  this.setLeftx= function (x)
+  {    
+         this.leftx = x ;
+         this.rightx = x + this.width;
+         this.centerx = this.leftx + this.width/2;     
+         this.topx=this.centerx;
+         this.downx=this.centerx;
+  }
+  this.setRightx= function (x)
+  {    
+         this.leftx = x - this.width;
+         this.rightx = x ;
+         this.centerx = this.leftx + this.width/2;     
+         this.topx=this.centerx;
+         this.downx=this.centerx;
+  }
+  
+  this.checkPlace= function ()
+  {
+     if(this.leftx > (this.rightx - this.width) ){
+       this.setLeftx(this.leftx);      
+       
+       for(var a in this.pointerShapesAfter){
+                 this.pointerShapesAfter[a].leftx = this.rightx;       
+       }
+       for(var b in this.pointerShapesBefore){
+         this.pointerShapesBefore[b].rightx = this.leftx;      
+       }
+       
+       for(var a in this.pointerShapesAfter){
+         this.pointerShapesAfter[a].checkPlace();
+       }
+       for(var b in this.pointerShapesBefore){
+         this.pointerShapesBefore[b].checkPlace();
+       }
+    }
+  }  
+}
+
+
+$( function () {
+
+     function getMousePos(canvas, evt) {
+        var rect = canvas.getBoundingClientRect();
+        return {
+          x: evt.clientX - rect.left,
+          y: evt.clientY - rect.top
+        };
+      }
+      
+      var $elsCanvas = $("canvas.lwgraph-flow");
+           
+      $elsCanvas.each(function(index, canvas) {
+      canvas.width = parseInt($(this).css('width'));
+      canvas.height =  parseInt($(this).css('height'));              
+ 
+        var graphFlow = new lwFlowChart($(this),$(this).text());
+       canvas.addEventListener('click', function(evt) {
+              var mousePos = getMousePos(canvas, evt);
+             var shape = graphFlow.getShape(mousePos.x ,mousePos.y)
+             if( shape != null){
+                var url = mw.config.get( 'wgScript' ) + '?title=' + 
encodeURIComponent(shape.title) ;
+               if(shape.isPageExist)
+                 window.location.href = url;
+               else              
+                 window.location.href = url+"&action=edit&redlink=1";
+             }
+       });
+       
+       canvas.addEventListener('mousemove', function(evt) {
+           var mousePos = getMousePos(canvas, evt);
+           var shape = graphFlow.getShape(mousePos.x ,mousePos.y)
+           if( shape != null)
+               $(this).css('cursor', 'pointer');
+           else
+             $(this).css('cursor', 'default');
+         }, false);
+      });          
+}); 
\ No newline at end of file
diff --git a/js/lwgraph.js b/js/lwgraph.js
new file mode 100644
index 0000000..1f16c1f
--- /dev/null
+++ b/js/lwgraph.js
@@ -0,0 +1,157 @@
+jQuery.fn.lwDrawPolygon = function(shape) {
+    var a = $(this)[0].getContext('2d');
+        
+    a.beginPath();
+    a.moveTo(shape[0][0],shape[0][1]);
+    for(p in shape)
+    if (p > 0) a.lineTo(shape[p][0],shape[p][1]);
+    a.lineTo(shape[0][0],shape[0][1]);
+    a.fill();
+
+};
+
+function lwTranslateShape(shape,x,y) {
+    var rv = [];
+    for(p in shape)
+    rv.push([ shape[p][0] + x, shape[p][1] + y ]);
+    return rv;
+
+};
+
+function lwRotateShape(shape,ang) {
+  
+    function rotatePoint(ang,x,y) {
+       return [
+               (x * Math.cos(ang)) - (y * Math.sin(ang)),
+               (x * Math.sin(ang)) + (y * Math.cos(ang))
+               ];
+    };
+  
+    var rv = [];
+    for(p in shape)
+    rv.push(rotatePoint(ang,shape[p][0],shape[p][1]));
+    return rv;
+
+};
+
+jQuery.fn.lwDrawLineArrow= function(text,color,x1,y1,x2,y2,draw) {
+    var a = $(this)[0].getContext('2d');
+    var arrow = [
+       [ 2, 0 ],
+       [ -10, -4 ],
+       [ -10, 4]
+       ];
+      var marge = 10 ;
+      var height = 14;
+      var width = 0;
+    if(text !=null){
+      a.save();
+
+       a.font = '14px Arial';
+       var metrics = a.measureText(text);
+       width = metrics.width;
+       
+       var cx = x1 > x2 ? x2 + x1 - x2 : x1 + x2 - x1;
+       var cy = y1 > y2 ? y2 + y1 - y2 : y1 + y2 - y1;
+       //a.translate(x1 - width/2 - marge -5 + x2-x1,y1 - height/2 + y2-y1);
+       a.translate(cx- width/2 - marge -5 ,cy - height/2 );
+       a.textAlign = 'center';
+           a.textBaseline = 'middle';
+           a.fillStyle = color;      
+           a.fillText(text, 0,0); 
+      a.restore();
+    }
+    if(draw){
+       a.beginPath();
+       a.moveTo(x1,y1);
+       a.lineTo(x2,y2);
+       a.stroke();
+       var ang = Math.atan2(y2-y1,x2-x1);
+       $(this).lwDrawPolygon(lwTranslateShape(lwRotateShape(arrow,ang),x2,y2));
+    }
+    
+    return width + marge*2;
+};
+
+
+jQuery.fn.lwDrawRect= function(text,color,x,y,draw) {
+    var a = $(this)[0].getContext('2d');
+    var rect = 
[[-30,30],[-30,-30],[30,-30],[30,30],[-28,30],[-28,28],[28,28],[28,-28],[-28,-28],[-28,30]];
+    var marge = 15;
+    a.save();
+
+      a.translate(x,y);
+      var height = 20;
+      a.font = '20px Arial';
+      var metrics = a.measureText(text);
+      
+      var width = metrics.width;   
+      if(draw){
+         for(var i = 0; i < rect.length ; i++){
+           //console.log(rect[i][0]);
+           //console.log(rect[i][1]);
+           rect[i][0] = rect[i][0]>0? rect[i][0] -(30-marge) + width/2: 
rect[i][0]+(30-marge) - width/2 ;
+           rect[i][1] = rect[i][1]>0? rect[i][1] -(30-marge) + height/2: 
rect[i][1]+(30-marge) - height/2 ;
+         }
+         $(this).lwDrawPolygon(lwTranslateShape(rect,0,0));
+         a.textAlign = 'center';
+         a.textBaseline = 'middle';
+         a.fillStyle = color;      
+         a.fillText(text, 0,0); 
+      }
+     a.restore();
+
+    return width + 30;
+    
+};
+
+// $( function () {
+//     // This code must not be executed before the document is loaded. 
+// 
+//      function getMousePos(canvas, evt) {
+//         var rect = canvas.getBoundingClientRect();
+//         return {
+//           x: evt.clientX - rect.left,
+//           y: evt.clientY - rect.top
+//         };
+//       }
+//       
+//       var $elsCanvas = $("canvas.lwgraph-flow");      
+//       $elsCanvas.css("border","2px solid black");      
+// 
+//       $elsCanvas.each(function(index, canvas) {
+//       canvas.width = parseInt($(this).css('width'));
+//       canvas.height =  parseInt($(this).css('height'));
+//     
+//           console.log( index + ": " + $(this).text() );
+//     
+//       canvas.addEventListener('click', function(evt) {
+//             var mousePos = getMousePos(canvas, evt);
+//             var shape = graphXXXX.getShape(mousePos.x ,mousePos.y)
+//             if( shape != null){
+//               var url = mw.config.get( 'wgScript' ) + '?title=' + 
encodeURIComponent(shape.title) ;
+//               if(shape.isPageExist)
+//                 window.location.href = url;
+//               else            
+//                 window.location.href = url+"&action=edit&redlink=1";
+//             }
+//       });
+//     
+//     canvas.addEventListener('mousemove', function(evt) {
+//               var mousePos = getMousePos(canvas, evt);
+//               //console.log('Mouse position: ' + mousePos.x + ',' + 
mousePos.y);
+//               var shape = graphXXXX.getShape(mousePos.x ,mousePos.y)
+//               if( shape != null)
+//                   $(this).css('cursor', 'pointer');
+//               else
+//                 $(this).css('cursor', 'default');
+//             }, false);
+//     
+// 
+//     //$(this).lwDrawPolygon(lwTranslateShape(lwRotateShape(shape,Math.PI 
),50,50));
+//     //$(this).lwDrawLineArrow(0,0,250,50);
+//     //$(this).lwDrawRect("tteteteteoto",250,50);  
+//     
+//       });
+//         
+// });

-- 
To view, visit https://gerrit.wikimedia.org/r/76331
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I87650a8b611e86e96fb849b29c69f6dd7fa69051
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/LinkedWiki
Gerrit-Branch: master
Gerrit-Owner: Karima Rafes <karima.ra...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to