Fossil SCM
Improvements to the layout of merge arrows in the graph.
Commit
313cd3c8322e2ab9a27845e432139407004ecdf9
Parent
66951fa6bd0d7a9…
2 files changed
+39
-21
+15
-13
+39
-21
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -253,10 +253,47 @@ | ||
| 253 | 253 | assert( pPrior!=0 ); |
| 254 | 254 | } |
| 255 | 255 | } |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | +/* | |
| 259 | +** Create a merge-arrow riser going from pParent up to pChild. | |
| 260 | +*/ | |
| 261 | +static void createMergeRiser( | |
| 262 | + GraphContext *p, | |
| 263 | + GraphRow *pParent, | |
| 264 | + GraphRow *pChild | |
| 265 | +){ | |
| 266 | + int u; | |
| 267 | + u32 mask; | |
| 268 | + GraphRow *pLoop; | |
| 269 | + | |
| 270 | + if( pParent->mergeOut<0 ){ | |
| 271 | + u = pParent->aiRiser[pParent->iRail]; | |
| 272 | + if( u>0 && u<pChild->idx ){ | |
| 273 | + /* The thick arrow up to the next primary child of pDesc goes | |
| 274 | + ** further up than the thin merge arrow riser, so draw them both | |
| 275 | + ** on the same rail. */ | |
| 276 | + pParent->mergeOut = pParent->iRail; | |
| 277 | + pParent->mergeUpto = pChild->idx; | |
| 278 | + }else{ | |
| 279 | + /* The thin merge arrow riser is taller than the thick primary | |
| 280 | + ** child riser, so use separate rails. */ | |
| 281 | + int iTarget = pParent->iRail; | |
| 282 | + pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, | |
| 283 | + 0, iTarget); | |
| 284 | + pParent->mergeUpto = pChild->idx; | |
| 285 | + mask = 1<<pParent->mergeOut; | |
| 286 | + for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; | |
| 287 | + pLoop=pLoop->pNext){ | |
| 288 | + pLoop->railInUse |= mask; | |
| 289 | + } | |
| 290 | + } | |
| 291 | + } | |
| 292 | + pChild->mergeIn |= 1<<pParent->mergeOut; | |
| 293 | +} | |
| 294 | + | |
| 258 | 295 | |
| 259 | 296 | /* |
| 260 | 297 | ** Compute the complete graph |
| 261 | 298 | */ |
| 262 | 299 | void graph_finish(GraphContext *p, int omitDescenders){ |
| @@ -431,21 +468,11 @@ | ||
| 431 | 468 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 432 | 469 | pLoop->railInUse |= mask; |
| 433 | 470 | } |
| 434 | 471 | }else{ |
| 435 | 472 | /* Merge from an on-screen node */ |
| 436 | - if( pDesc->mergeOut<0 ){ | |
| 437 | - int iTarget = (pRow->iRail + pDesc->iRail)/2; | |
| 438 | - pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1,0,iTarget); | |
| 439 | - pDesc->mergeUpto = pRow->idx; | |
| 440 | - mask = 1<<pDesc->mergeOut; | |
| 441 | - for(pLoop=pRow->pNext; pLoop && pLoop->rid!=parentRid; | |
| 442 | - pLoop=pLoop->pNext){ | |
| 443 | - pLoop->railInUse |= mask; | |
| 444 | - } | |
| 445 | - } | |
| 446 | - pRow->mergeIn |= 1<<pDesc->mergeOut; | |
| 473 | + createMergeRiser(p, pDesc, pRow); | |
| 447 | 474 | } |
| 448 | 475 | } |
| 449 | 476 | } |
| 450 | 477 | |
| 451 | 478 | /* |
| @@ -454,20 +481,11 @@ | ||
| 454 | 481 | if( hasDup ){ |
| 455 | 482 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 456 | 483 | if( !pRow->isDup ) continue; |
| 457 | 484 | pDesc = hashFind(p, pRow->rid); |
| 458 | 485 | assert( pDesc!=0 && pDesc!=pRow ); |
| 459 | - if( pDesc->mergeOut<0 ){ | |
| 460 | - int iTarget = (pRow->iRail + pDesc->iRail)/2; | |
| 461 | - pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1, 0, iTarget); | |
| 462 | - pDesc->mergeUpto = pRow->idx; | |
| 463 | - mask = 1<<pDesc->mergeOut; | |
| 464 | - for(pLoop=pRow->pNext; pLoop && pLoop!=pDesc; pLoop=pLoop->pNext){ | |
| 465 | - pLoop->railInUse |= mask; | |
| 466 | - } | |
| 467 | - } | |
| 468 | - pRow->mergeIn |= 1<<pDesc->mergeOut; | |
| 486 | + createMergeRiser(p, pDesc, pRow); | |
| 469 | 487 | } |
| 470 | 488 | } |
| 471 | 489 | |
| 472 | 490 | /* |
| 473 | 491 | ** Find the maximum rail number. |
| 474 | 492 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -253,10 +253,47 @@ | |
| 253 | assert( pPrior!=0 ); |
| 254 | } |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | |
| 259 | /* |
| 260 | ** Compute the complete graph |
| 261 | */ |
| 262 | void graph_finish(GraphContext *p, int omitDescenders){ |
| @@ -431,21 +468,11 @@ | |
| 431 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 432 | pLoop->railInUse |= mask; |
| 433 | } |
| 434 | }else{ |
| 435 | /* Merge from an on-screen node */ |
| 436 | if( pDesc->mergeOut<0 ){ |
| 437 | int iTarget = (pRow->iRail + pDesc->iRail)/2; |
| 438 | pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1,0,iTarget); |
| 439 | pDesc->mergeUpto = pRow->idx; |
| 440 | mask = 1<<pDesc->mergeOut; |
| 441 | for(pLoop=pRow->pNext; pLoop && pLoop->rid!=parentRid; |
| 442 | pLoop=pLoop->pNext){ |
| 443 | pLoop->railInUse |= mask; |
| 444 | } |
| 445 | } |
| 446 | pRow->mergeIn |= 1<<pDesc->mergeOut; |
| 447 | } |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | /* |
| @@ -454,20 +481,11 @@ | |
| 454 | if( hasDup ){ |
| 455 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 456 | if( !pRow->isDup ) continue; |
| 457 | pDesc = hashFind(p, pRow->rid); |
| 458 | assert( pDesc!=0 && pDesc!=pRow ); |
| 459 | if( pDesc->mergeOut<0 ){ |
| 460 | int iTarget = (pRow->iRail + pDesc->iRail)/2; |
| 461 | pDesc->mergeOut = findFreeRail(p, pRow->idx, pDesc->idx-1, 0, iTarget); |
| 462 | pDesc->mergeUpto = pRow->idx; |
| 463 | mask = 1<<pDesc->mergeOut; |
| 464 | for(pLoop=pRow->pNext; pLoop && pLoop!=pDesc; pLoop=pLoop->pNext){ |
| 465 | pLoop->railInUse |= mask; |
| 466 | } |
| 467 | } |
| 468 | pRow->mergeIn |= 1<<pDesc->mergeOut; |
| 469 | } |
| 470 | } |
| 471 | |
| 472 | /* |
| 473 | ** Find the maximum rail number. |
| 474 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -253,10 +253,47 @@ | |
| 253 | assert( pPrior!=0 ); |
| 254 | } |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | /* |
| 259 | ** Create a merge-arrow riser going from pParent up to pChild. |
| 260 | */ |
| 261 | static void createMergeRiser( |
| 262 | GraphContext *p, |
| 263 | GraphRow *pParent, |
| 264 | GraphRow *pChild |
| 265 | ){ |
| 266 | int u; |
| 267 | u32 mask; |
| 268 | GraphRow *pLoop; |
| 269 | |
| 270 | if( pParent->mergeOut<0 ){ |
| 271 | u = pParent->aiRiser[pParent->iRail]; |
| 272 | if( u>0 && u<pChild->idx ){ |
| 273 | /* The thick arrow up to the next primary child of pDesc goes |
| 274 | ** further up than the thin merge arrow riser, so draw them both |
| 275 | ** on the same rail. */ |
| 276 | pParent->mergeOut = pParent->iRail; |
| 277 | pParent->mergeUpto = pChild->idx; |
| 278 | }else{ |
| 279 | /* The thin merge arrow riser is taller than the thick primary |
| 280 | ** child riser, so use separate rails. */ |
| 281 | int iTarget = pParent->iRail; |
| 282 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 283 | 0, iTarget); |
| 284 | pParent->mergeUpto = pChild->idx; |
| 285 | mask = 1<<pParent->mergeOut; |
| 286 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 287 | pLoop=pLoop->pNext){ |
| 288 | pLoop->railInUse |= mask; |
| 289 | } |
| 290 | } |
| 291 | } |
| 292 | pChild->mergeIn |= 1<<pParent->mergeOut; |
| 293 | } |
| 294 | |
| 295 | |
| 296 | /* |
| 297 | ** Compute the complete graph |
| 298 | */ |
| 299 | void graph_finish(GraphContext *p, int omitDescenders){ |
| @@ -431,21 +468,11 @@ | |
| 468 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 469 | pLoop->railInUse |= mask; |
| 470 | } |
| 471 | }else{ |
| 472 | /* Merge from an on-screen node */ |
| 473 | createMergeRiser(p, pDesc, pRow); |
| 474 | } |
| 475 | } |
| 476 | } |
| 477 | |
| 478 | /* |
| @@ -454,20 +481,11 @@ | |
| 481 | if( hasDup ){ |
| 482 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 483 | if( !pRow->isDup ) continue; |
| 484 | pDesc = hashFind(p, pRow->rid); |
| 485 | assert( pDesc!=0 && pDesc!=pRow ); |
| 486 | createMergeRiser(p, pDesc, pRow); |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | /* |
| 491 | ** Find the maximum rail number. |
| 492 |
+15
-13
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -398,11 +398,11 @@ | ||
| 398 | 398 | ** md: A bitmask of rails on which merge-arrow descenders should be |
| 399 | 399 | ** drawn from this row to the bottom of the page. The least |
| 400 | 400 | ** significant bit (1) corresponds to rail 0. The 2-bit corresponds |
| 401 | 401 | ** to rail 1. And so forth. This value is 0 if there are no |
| 402 | 402 | ** merge-arrow descenders. |
| 403 | - ** u: Draw a think child-line out of the top of this node and up to | |
| 403 | + ** u: Draw a thick child-line out of the top of this node and up to | |
| 404 | 404 | ** the node with an id equal to this value. 0 if there is no |
| 405 | 405 | ** thick-line riser. |
| 406 | 406 | ** au: An array of integers that define thick-line risers for branches. |
| 407 | 407 | ** The integers are in pairs. For each pair, the first integer is |
| 408 | 408 | ** is the rail on which the riser should run and the second integer |
| @@ -411,19 +411,20 @@ | ||
| 411 | 411 | ** merge arrows should be drawn into this node. |
| 412 | 412 | */ |
| 413 | 413 | cgi_printf("var rowinfo = [\n"); |
| 414 | 414 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 415 | 415 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:", |
| 416 | - pRow->idx, | |
| 417 | - pRow->zBgClr, | |
| 418 | - pRow->iRail, | |
| 419 | - pRow->bDescender, | |
| 420 | - pRow->mergeOut+1, | |
| 421 | - pRow->mergeUpto, | |
| 422 | - pRow->mergeDown, | |
| 423 | - pRow->aiRiser[pRow->iRail] | |
| 416 | + pRow->idx, /* id */ | |
| 417 | + pRow->zBgClr, /* bg */ | |
| 418 | + pRow->iRail, /* r */ | |
| 419 | + pRow->bDescender, /* d */ | |
| 420 | + pRow->mergeOut+1, /* mo */ | |
| 421 | + pRow->mergeUpto, /* mu */ | |
| 422 | + pRow->mergeDown, /* md */ | |
| 423 | + pRow->aiRiser[pRow->iRail] /* u */ | |
| 424 | 424 | ); |
| 425 | + /* u */ | |
| 425 | 426 | cSep = '['; |
| 426 | 427 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 427 | 428 | if( i==pRow->iRail ) continue; |
| 428 | 429 | if( pRow->aiRiser[i]>0 ){ |
| 429 | 430 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -430,10 +431,11 @@ | ||
| 430 | 431 | cSep = ','; |
| 431 | 432 | } |
| 432 | 433 | } |
| 433 | 434 | if( cSep=='[' ) cgi_printf("["); |
| 434 | 435 | cgi_printf("],mi:"); |
| 436 | + /* mi */ | |
| 435 | 437 | cSep = '['; |
| 436 | 438 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 437 | 439 | if( pRow->mergeIn & (1<<i) ){ |
| 438 | 440 | cgi_printf("%c%d", cSep, i); |
| 439 | 441 | cSep = ','; |
| @@ -516,17 +518,17 @@ | ||
| 516 | 518 | @ } |
| 517 | 519 | @ if( p.d ){ |
| 518 | 520 | @ drawUpArrow(p.x, p.y+6, btm); |
| 519 | 521 | @ } |
| 520 | 522 | @ if( p.mo>0 ){ |
| 521 | - @ var x1 = (p.mo-1)*20 + left; | |
| 523 | + @ var x1 = (p.mo-1)*20 + left + 4; | |
| 522 | 524 | @ var y1 = p.y-3; |
| 523 | 525 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 524 | 526 | @ var u = rowinfo[p.mu-1]; |
| 525 | 527 | @ var y0 = u.y+5; |
| 526 | - @ if( x1==p.x ){ | |
| 527 | - @ y1 -= 2; | |
| 528 | + @ if( x1==p.x+4 ){ | |
| 529 | + @ y1 = p.y-5; | |
| 528 | 530 | @ }else{ |
| 529 | 531 | @ drawThinLine(x0,y1,x1,y1); |
| 530 | 532 | @ } |
| 531 | 533 | @ drawThinLine(x1,y0,x1,y1); |
| 532 | 534 | @ } |
| @@ -546,11 +548,11 @@ | ||
| 546 | 548 | @ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3); |
| 547 | 549 | @ } |
| 548 | 550 | @ } |
| 549 | 551 | @ for(var j in p.mi){ |
| 550 | 552 | @ var y0 = p.y+5; |
| 551 | - @ var mx = p.mi[j]*20 + left; | |
| 553 | + @ var mx = p.mi[j]*20 + left + 4; | |
| 552 | 554 | @ if( mx>p.x ){ |
| 553 | 555 | @ drawThinArrow(y0,mx,p.x+6); |
| 554 | 556 | @ }else{ |
| 555 | 557 | @ drawThinArrow(y0,mx,p.x-5); |
| 556 | 558 | @ } |
| 557 | 559 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -398,11 +398,11 @@ | |
| 398 | ** md: A bitmask of rails on which merge-arrow descenders should be |
| 399 | ** drawn from this row to the bottom of the page. The least |
| 400 | ** significant bit (1) corresponds to rail 0. The 2-bit corresponds |
| 401 | ** to rail 1. And so forth. This value is 0 if there are no |
| 402 | ** merge-arrow descenders. |
| 403 | ** u: Draw a think child-line out of the top of this node and up to |
| 404 | ** the node with an id equal to this value. 0 if there is no |
| 405 | ** thick-line riser. |
| 406 | ** au: An array of integers that define thick-line risers for branches. |
| 407 | ** The integers are in pairs. For each pair, the first integer is |
| 408 | ** is the rail on which the riser should run and the second integer |
| @@ -411,19 +411,20 @@ | |
| 411 | ** merge arrows should be drawn into this node. |
| 412 | */ |
| 413 | cgi_printf("var rowinfo = [\n"); |
| 414 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 415 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:", |
| 416 | pRow->idx, |
| 417 | pRow->zBgClr, |
| 418 | pRow->iRail, |
| 419 | pRow->bDescender, |
| 420 | pRow->mergeOut+1, |
| 421 | pRow->mergeUpto, |
| 422 | pRow->mergeDown, |
| 423 | pRow->aiRiser[pRow->iRail] |
| 424 | ); |
| 425 | cSep = '['; |
| 426 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 427 | if( i==pRow->iRail ) continue; |
| 428 | if( pRow->aiRiser[i]>0 ){ |
| 429 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -430,10 +431,11 @@ | |
| 430 | cSep = ','; |
| 431 | } |
| 432 | } |
| 433 | if( cSep=='[' ) cgi_printf("["); |
| 434 | cgi_printf("],mi:"); |
| 435 | cSep = '['; |
| 436 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 437 | if( pRow->mergeIn & (1<<i) ){ |
| 438 | cgi_printf("%c%d", cSep, i); |
| 439 | cSep = ','; |
| @@ -516,17 +518,17 @@ | |
| 516 | @ } |
| 517 | @ if( p.d ){ |
| 518 | @ drawUpArrow(p.x, p.y+6, btm); |
| 519 | @ } |
| 520 | @ if( p.mo>0 ){ |
| 521 | @ var x1 = (p.mo-1)*20 + left; |
| 522 | @ var y1 = p.y-3; |
| 523 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 524 | @ var u = rowinfo[p.mu-1]; |
| 525 | @ var y0 = u.y+5; |
| 526 | @ if( x1==p.x ){ |
| 527 | @ y1 -= 2; |
| 528 | @ }else{ |
| 529 | @ drawThinLine(x0,y1,x1,y1); |
| 530 | @ } |
| 531 | @ drawThinLine(x1,y0,x1,y1); |
| 532 | @ } |
| @@ -546,11 +548,11 @@ | |
| 546 | @ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3); |
| 547 | @ } |
| 548 | @ } |
| 549 | @ for(var j in p.mi){ |
| 550 | @ var y0 = p.y+5; |
| 551 | @ var mx = p.mi[j]*20 + left; |
| 552 | @ if( mx>p.x ){ |
| 553 | @ drawThinArrow(y0,mx,p.x+6); |
| 554 | @ }else{ |
| 555 | @ drawThinArrow(y0,mx,p.x-5); |
| 556 | @ } |
| 557 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -398,11 +398,11 @@ | |
| 398 | ** md: A bitmask of rails on which merge-arrow descenders should be |
| 399 | ** drawn from this row to the bottom of the page. The least |
| 400 | ** significant bit (1) corresponds to rail 0. The 2-bit corresponds |
| 401 | ** to rail 1. And so forth. This value is 0 if there are no |
| 402 | ** merge-arrow descenders. |
| 403 | ** u: Draw a thick child-line out of the top of this node and up to |
| 404 | ** the node with an id equal to this value. 0 if there is no |
| 405 | ** thick-line riser. |
| 406 | ** au: An array of integers that define thick-line risers for branches. |
| 407 | ** The integers are in pairs. For each pair, the first integer is |
| 408 | ** is the rail on which the riser should run and the second integer |
| @@ -411,19 +411,20 @@ | |
| 411 | ** merge arrows should be drawn into this node. |
| 412 | */ |
| 413 | cgi_printf("var rowinfo = [\n"); |
| 414 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 415 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:", |
| 416 | pRow->idx, /* id */ |
| 417 | pRow->zBgClr, /* bg */ |
| 418 | pRow->iRail, /* r */ |
| 419 | pRow->bDescender, /* d */ |
| 420 | pRow->mergeOut+1, /* mo */ |
| 421 | pRow->mergeUpto, /* mu */ |
| 422 | pRow->mergeDown, /* md */ |
| 423 | pRow->aiRiser[pRow->iRail] /* u */ |
| 424 | ); |
| 425 | /* u */ |
| 426 | cSep = '['; |
| 427 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 428 | if( i==pRow->iRail ) continue; |
| 429 | if( pRow->aiRiser[i]>0 ){ |
| 430 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -430,10 +431,11 @@ | |
| 431 | cSep = ','; |
| 432 | } |
| 433 | } |
| 434 | if( cSep=='[' ) cgi_printf("["); |
| 435 | cgi_printf("],mi:"); |
| 436 | /* mi */ |
| 437 | cSep = '['; |
| 438 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 439 | if( pRow->mergeIn & (1<<i) ){ |
| 440 | cgi_printf("%c%d", cSep, i); |
| 441 | cSep = ','; |
| @@ -516,17 +518,17 @@ | |
| 518 | @ } |
| 519 | @ if( p.d ){ |
| 520 | @ drawUpArrow(p.x, p.y+6, btm); |
| 521 | @ } |
| 522 | @ if( p.mo>0 ){ |
| 523 | @ var x1 = (p.mo-1)*20 + left + 4; |
| 524 | @ var y1 = p.y-3; |
| 525 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 526 | @ var u = rowinfo[p.mu-1]; |
| 527 | @ var y0 = u.y+5; |
| 528 | @ if( x1==p.x+4 ){ |
| 529 | @ y1 = p.y-5; |
| 530 | @ }else{ |
| 531 | @ drawThinLine(x0,y1,x1,y1); |
| 532 | @ } |
| 533 | @ drawThinLine(x1,y0,x1,y1); |
| 534 | @ } |
| @@ -546,11 +548,11 @@ | |
| 548 | @ drawBox("#600000",u.x-11,u.y-2,u.x-10,u.y+3); |
| 549 | @ } |
| 550 | @ } |
| 551 | @ for(var j in p.mi){ |
| 552 | @ var y0 = p.y+5; |
| 553 | @ var mx = p.mi[j]*20 + left + 4; |
| 554 | @ if( mx>p.x ){ |
| 555 | @ drawThinArrow(y0,mx,p.x+6); |
| 556 | @ }else{ |
| 557 | @ drawThinArrow(y0,mx,p.x-5); |
| 558 | @ } |
| 559 |