/lenasys/0.1

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/lenasys/0.1
1 by Henrik G.
First seed of Lenasys ... Needs to be Organized Further
1
/********************************************************************************
4.11.3 by a11patfr at his
Fixed formatting trunk/ErModeller/dugga.js.
2
  Mouse coordinate and canvas globals
3
  Handles both Touch and Mouse/Keyboard input at the same time
4
 *********************************************************************************/
5
6
// Mouse coordinate globals
7
var gridx, gridy;
8
var clickstate = 0;
9
var acanvas;
10
var context;
11
12
/********************************************************************************
13
  Canvas Setup and Click Handling Code
14
15
  Handles both Touch and Mouse/Keyboard input at the same time and executes 
16
  handler callbacks.
17
  Also declares canvas globals
18
 *********************************************************************************/
19
20
function setupcanvas() {
21
	acanvas = document.getElementById('a');
22
	context = acanvas.getContext("2d");		
23
	setTimeout("foo();",50);
24
	setupClickHandling();		
25
}
26
27
function setupClickHandling() {
28
	// Mouse and Keyboard Events
29
	acanvas.addEventListener('mousemove', ev_mousemove, false);
30
	acanvas.addEventListener('mouseup', ev_mouseup, false);
31
	acanvas.addEventListener('mousedown', ev_mousedown, false);
32
33
	// Touch Events
34
	acanvas.addEventListener('touchstart', ev_touchstart, false);
35
	acanvas.addEventListener('touchend', ev_touchend, false);
36
	acanvas.addEventListener('touchmove', ev_touchmove, false);		
37
}						
38
39
// Keyboard/Mouse Mouse Up Handler
40
function ev_mouseup(ev) {
41
	handler_mouseup();
42
}
43
44
// Keyboard/Mouse Mouse Down Handler
45
function ev_mousedown(ev) {
46
	handler_mousedown();		
47
}
48
49
// Keyboard/Mouse Mouse Move Handler
50
function ev_mousemove (ev) {
51
	var cx, cy = 0;
52
	if (ev.layerX || ev.layerX == 0) { // Firefox
53
		cx = ev.layerX - acanvas.offsetLeft;
54
		cy = ev.layerY - acanvas.offsetTop;
55
	} else if (ev.offsetX || ev.offsetX == 0) { // Opera
56
		cx = ev.offsetX - acanvas.offsetLeft;
57
		cy = ev.offsetY - acanvas.offsetTop;
58
	}
59
	coord = findPos(acanvas);
60
	cx = cx - coord.x;
61
	cy = cy - coord.y;
62
	handler_mousemove(cx, cy);
63
}		
64
65
// Touch start event
66
function ev_touchstart(event) {  
67
	event.preventDefault();  
68
	var numtouch = event.touches.length;  
69
	targetEvent =  event.touches.item(0);
70
	var cx = targetEvent.pageX;
71
	var cy = targetEvent.pageY;
72
	gridx = cx;
73
	gridy = cy;
74
	handler_mousedown();
75
};  
76
77
// Touch end event
78
function ev_touchend(event) {  
79
	event.preventDefault();  
80
	var numtouch = event.touches.length;  
81
	handler_mouseup();
82
};
83
84
// Touch move event
85
function ev_touchmove(event) {  
86
	event.preventDefault();  
87
	var numtouch = event.touches.length;  
88
	targetEvent =  event.touches.item(0);
89
	var cx = targetEvent.pageX;
90
	var cy = targetEvent.pageY;
91
	handler_mousemove(cx, cy);				
92
};
93
94
// Fix scrolling on touch devices
95
var ScrollFix = function(elem) {
96
	// Variables to track inputs
97
	var startY, startTopScroll;
98
	elem = elem || document.querySelector(elem);
99
100
	// If there is no element, then do nothing  
101
	if(!elem) {
102
		return;
103
	}
104
105
	// Handle the start of interactions
106
	elem.addEventListener('touchstart', function(event) {
107
		startY = event.touches[0].pageY;
108
		startTopScroll = elem.scrollTop;
109
110
		if(startTopScroll <= 0) {
111
			elem.scrollTop = 1;
112
		}
113
114
		if(startTopScroll + elem.offsetHeight >= elem.scrollHeight) {
115
			elem.scrollTop = elem.scrollHeight - elem.offsetHeight - 1;
116
		}
117
	}, false);
118
};
119
120
/********************************************************************************
121
  Canvas Diagram Drawing Code
122
 *********************************************************************************/
123
124
// Draws a stroked rectangle of certain thicknes and color
125
function drawrect(x1, y1, x2, y2, color) {
126
	context.lineWidth = 1.5;
127
	context.strokeStyle = color;
128
	context.strokeRect(x1, y1, x2 - x1, y2 - y1);
129
}
130
131
// Draws a perfect round circle
132
function drawcircle(radius, color) {
133
	context.lineWidth = 1.5;
134
	context.strokeStyle = color;
135
	context.arc(0, 0, radius, 0 , 2 * Math.PI, false);
136
}
137
138
// Draws 90 degree arc
139
function drawellipse(x1, y1, x2, y2) {
140
	var rx = (x2 - x1) * 0.5;
141
	var ry = (y2 - y1) * 0.5;
142
	context.beginPath();					
143
	context.moveTo(x1, y1 + ry);
144
	context.quadraticCurveTo(x1, y1, x1 + rx, y1);
145
	context.quadraticCurveTo(x2, y1, x2, y1 + ry);
146
	context.quadraticCurveTo(x2, y2, x2 - rx, y2);
147
	context.quadraticCurveTo(x1, y2, x1, y1 + ry);
148
	context.stroke();
149
}	
150
151
// Draw a point		
152
function point(x, y, col) {
153
	context.strokeStyle = "#000";
154
	context.lineWidth = 1;
155
	context.fillStyle = col;
156
	context.fillRect(x - 4, y - 4, 8, 8);		
157
	context.strokeRect(x - 4, y - 4, 8, 8);						
158
}
159
160
// Draw a box around a point to indicate highlight
161
function highlight(px, py) {
162
	context.strokeStyle = "#aaa";
163
	context.lineWidth = 1;
164
	context.strokeRect(px - 8, py - 8, 16, 16);						
165
}
166
167
// Draw a line using current context
168
function drawline(x1, y1, x2, y2, strokestyle, linewidth) {
169
	context.strokeStyle = strokestyle;
170
	context.lineWidth = linewidth;
171
	context.beginPath();
172
	context.moveTo(x1, y1);
173
	context.lineTo(x2, y2);
174
	context.stroke();
175
}
176
177
function fourpoints(x1, y1, x2, y2, x3, y3, x4, y4, col) {
178
	point(x1, y1, col);
179
	point(x2, y2, col);
180
	point(x3, y3, col);
181
	point(x4, y4, col);				
182
}
183
184
function drawdiamond(x1, y1, x2, y2) {
185
	var rx = (x2 - x1) * 0.5;
186
	var ry = (y2 - y1) * 0.5;
187
	context.beginPath();					
188
	context.moveTo(x1, y1 + ry);
189
	context.lineTo(x1 + rx, y2);
190
	context.lineTo(x2, y1 + ry);
191
	context.lineTo(x1 + rx, y1);
192
	context.lineTo(x1, y1 + ry);			
193
	context.stroke();											
194
}
195
196
// Dashed Line in Segments of given size
197
function dashedline(sx, sy, ex, ey, dashlen, linewidth, col) {
198
	var dx = ex - sx;
199
	var dy = ey - sy;
200
	len = Math.sqrt((dx * dx) + (dy * dy));
201
	notimes = Math.round(len / dashlen);
202
	dx = dx / notimes;
203
	dy = dy / notimes;
204
	context.lineWidth = linewidth;
205
	context.strokeStyle = col;
206
	context.beginPath();
207
	var xk, yk;
208
	xk = sx;
209
	yk = sy;
210
	xh = dx / 2.0;
211
	yh = dy / 2.0;
212
	for(var i = 0; i < notimes; i++) {
213
		context.moveTo(xk, yk);				
214
		context.lineTo(xk + xh, yk + yh);
215
		xk += dx;
216
		yk += dy;
217
	}
218
	context.stroke();
219
}
220
221
// Arcto only works if both x1 and y2 are on circle border
222
function arcto(x0, y0, x1, y1, x2, y2) {
223
	var r = Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
224
	var x = x0 - r;
225
	var y = y0 - r;
226
	var startAngle = (180 / Math.PI * Math.atan2(y1 - y0, x1 - x0));
227
	var endAngle = (180 / Math.PI * Math.atan2(y2 - y0, x2 - x0));
228
	context.arc(x0, y0, r, 0, Math.PI * 2.0, 1.0);
229
}
230
231
// Draws 90 degree arc
232
function arcdeg(x1, y1, x2, y2, x3, y3) {
233
	// First quadrant positive positive			
234
	dashedline(x1, y1, x2, y2, 8, 1.0, "#999");
235
	dashedline(x3, y3, x2, y2, 8, 1.0, "#999");					
236
	point(x1, y1, "#ff5");
237
	point(x2, y2, "#f55");
238
	point(x3, y3, "#f55");
239
240
	k = (y3 - y1) / (x3 - x1);					
241
	yk = y1 + ((x2 - x1) * k);
242
	rx = x3 - x1;
243
	ry = y3 - y1;
244
	point(x2, yk, "#f5f");
245
246
	context.strokeStyle = '#49f';
247
	context.lineWidth = 1.0;					
248
	context.beginPath();					
249
	context.moveTo(x1, y1);
250
	for(i = 0; i < 48; i++) {
251
		if(y3 >= y1) {
252
			if(yk >= y2) {
253
				context.lineTo(x1 + (Math.sin(((Math.PI / 96.0) * -i) + (Math.PI * 1.0)) * rx), y3 + (Math.cos(((Math.PI / 96.0) * -i) + (Math.PI * 1.0)) * ry));
254
			} else {
255
				context.lineTo(x3 + (Math.sin(((Math.PI / 96.0) * i) + (Math.PI * 1.5)) * rx), y1 + (Math.cos(((Math.PI / 96.0) * i) + (Math.PI * 1.5)) * ry));
256
			}
257
		} else {
258
			if(yk <= y2) {
259
				context.lineTo(x1 + (Math.sin(((Math.PI / 96.0) * -i) + (Math.PI * 1.0)) * rx), y3 + (Math.cos(((Math.PI / 96.0) * -i) + (Math.PI * 1.0)) * ry));
260
			} else {
261
				context.lineTo(x3 + (Math.sin(((Math.PI / 96.0) * i) + (Math.PI * 1.5)) * rx), y1 + (Math.cos(((Math.PI / 96.0) * i) + (Math.PI * 1.5)) * ry));
262
			}
263
		}
264
	}
265
	context.stroke();
266
}
267
268
// function that draws one part of the sun	
269
function sundial(radius, angle, scale) {
270
	cosv = Math.cos(angle);
271
	sinv = Math.sin(angle);
272
	yaddx = scale * cosv;
273
	yaddy = scale * sinv;
274
	xaddx = -scale * sinv;
275
	xaddy = scale * cosv;
276
	xk = cosv * radius;
277
	yk = sinv * radius;
278
279
	context.bezierCurveTo((-1.5 * xaddx) + (yaddx * 1.5) + xk, (-1.5 * xaddy) + (yaddy * 1.5) + yk, xaddx + (yaddx * 2.0) + xk, xaddy + (yaddy * 2.0) + yk, xaddx + (yaddx * 3.0) + xk, xaddy + (yaddy * 3.0) + yk);
280
	context.bezierCurveTo(xaddx + yaddx + xk, xaddy + yaddy + yk, (1.5 * xaddx) + yaddx + xk, (1.5 * xaddy) + yaddy + yk, (3.0 * xaddx) + xk, (3.0 * xaddy) + yk);
281
}
282
283
// function that daws the sun
284
function drawsun() {
285
	context.fillStyle = "#fe9";
286
	context.strokeStyle = "#d82";
287
	context.lineWidth = 1.5;
288
	context.beginPath();
289
	context.moveTo(30, 0);
290
	for(i = 0.0; i < 360.0; i += 22.5) {
291
		angle = (i / 360.0) * 2 * Math.PI;
292
		sundial(30, angle, 3);
293
	}
294
	context.stroke();
295
	context.fill();															
296
}
297
298
// Draws the ball (used in various examples)
299
function drawball(cx, cy, radie, innerradie, ballradie, col1, inangle, inangleadd) {
300
301
	angleadd = (inangleadd / 360.0) * 2 * Math.PI;
302
	context.fillStyle = col1;					
303
	for(i = 0; i < 360; i += inangle) {
304
		angle = (i / 360.0) * 2 * Math.PI;
305
		angle2 = angle + angleadd;
306
		angle3 = angle + (angleadd * 2.0);
307
		angle4 = angle - angleadd;
308
309
		cosv = Math.cos(angle);
310
		sinv = Math.sin(angle);
311
312
		cosv2 = Math.cos(angle2);
313
		sinv2 = Math.sin(angle2);
314
315
		cosv4 = Math.cos(angle4);
316
		sinv4 = Math.sin(angle4);
317
318
		context.beginPath();
319
320
		context.moveTo(cx, cy);
321
		context.quadraticCurveTo(cx + (cosv * innerradie), cy + (sinv * innerradie), cx + (cosv2 * radie), cy + (sinv2 * radie));							
322
		context.arc(cx, cy, radie, angle2, angle, 1.0);
323
		context.quadraticCurveTo(cx + (cosv4 * innerradie), cy + (sinv4 * innerradie), cx, cy);							
324
		context.fill();	
325
	}
326
327
	context.beginPath();
328
	context.arc(cx, cy, radie, 0, Math.PI * 2.0, 1.0);												
329
	context.stroke();															
330
}
331
332
// Draws underlined/dashed underlined text clipped inside a rectangle, a quadratic curve ellipsis or a diamond
333
function cliptext(x1, y1, x2, y2, tex, font, align, edgeoffs, baseline, color, clipkind, underlinekind) {
334
	var rx = (x2 - x1) * 0.5;
335
	var ry = (y2 - y1) * 0.5;
336
	var tx = x1;    		
337
338
	if(clipkind != 0) {
339
		context.save();
340
		context.beginPath();				
341
	}
342
343
	// Make Rectangle / Ellipse / Diamond Clipping Paths
344
	if(clipkind == 1) {
345
		context.moveTo(x1, y1);
346
		context.lineTo(x1, y2);
347
		context.lineTo(x2 - edgeoffs, y2);
348
		context.lineTo(x2 - edgeoffs, y1);
349
		context.lineTo(x1, y1);
350
	} else if(clipkind == 2) {
351
		context.moveTo(x1, y1 + ry);
352
		context.quadraticCurveTo(x1 + edgeoffs, y1 + edgeoffs, x1 + edgeoffs + rx, y1 + edgeoffs);
353
		context.quadraticCurveTo(x2 - edgeoffs, y1 + edgeoffs, x2 - edgeoffs , y1 + ry + edgeoffs);
354
		context.quadraticCurveTo(x2 - edgeoffs, y2 - edgeoffs, x2 - rx - edgeoffs, y2 - edgeoffs);
355
		context.quadraticCurveTo(x1 + edgeoffs, y2 - edgeoffs, x1 + edgeoffs, y1 + ry + edgeoffs);
356
	} else if(clipkind == 3) {
357
		context.moveTo(x1, y1 + ry);
358
		context.lineTo(x1 + rx, y2);
359
		context.lineTo(x2, y1 + ry);
360
		context.lineTo(x1 + rx, y1);
361
		context.lineTo(x1, y1 + ry);			
362
	}
363
364
	if(clipkind != 0) {
365
		context.clip();				
366
	}
367
368
	context.font = font;
369
	context.textAlign = "left";
370
	context.fillStyle = color;
371
372
	var metrics = context.measureText(tex);
373
	var hwidth = metrics.width * 0.5;
374
375
	// Compute left-justified centered coordinate    		
376
	if((rx - hwidth - edgeoffs) < 0) {
377
		tx = x1 + edgeoffs;
378
	} else {
379
		tx = x1 + rx - hwidth;
380
	}
381
382
	context.fillText(tex, tx, y2 - ry + baseline);
383
384
	// Draw underlining - can handle dashed underline!
385
	if(underlinekind == 1) {
386
		drawline(tx, y2 - ry + baseline + 5.0, tx + (hwidth*2), y2 - ry + baseline + 5.0, "#000", 2.0);										
387
	}
388
389
	if(clipkind != 0) context.restore(); 
390
391
}
392
393
// Draws cardinality at a certain offset from a coordinate
394
function drawcardinality(x, y, side, tex, xoffs, yoffs, font, baseline, sign, color)
395
{
396
	// Xoffs is along line
397
	xoffs = 0;
398
	// Yoffs is distance from line
399
	yoffs = 10;
400
401
	var metrics = context.measureText(tex);
402
	var twidth = metrics.width;
403
	var theight = 12;
404
405
	point(x, y, "#f8f");
406
407
	context.font = font;
408
	context.textAlign = "left";
409
	context.fillStyle = color;
410
411
	if(side == 1 && sign == 1){
412
		context.fillText(tex, x - twidth - xoffs, y - yoffs);
413
		drawrect(x - twidth - xoffs, y - yoffs,x - xoffs, y - yoffs - theight);
414
	}else if(side == 2 && sign == 1){
415
		context.fillText(tex, x + yoffs, y + xoffs + theight);					
416
		drawrect(x + yoffs, y + xoffs + theight,x + yoffs + twidth, y + xoffs);
417
	}else if(side == 3 && sign == 1){
418
		context.fillText(tex, x + xoffs, y - yoffs);
419
	}else if(side == 4 && sign == 1){
420
		context.fillText(tex, x + yoffs, y - xoffs);					
421
	}else if(side == 1 && sign == 2){
422
		context.fillText(tex, x - twidth - xoffs, y + theight + yoffs);					
423
		drawrect(x - twidth - xoffs, y + yoffs,x - xoffs, y + theight + yoffs);
424
	}else if(side == 2 && sign == 2){
425
		context.fillText(tex, x - yoffs - twidth, y + xoffs + theight);					
426
		drawrect(x - yoffs - twidth, y + xoffs,x - yoffs, y + xoffs + theight);
427
	}else if(side == 3 && sign == 2){
428
		context.fillText(tex, x + xoffs, y + theight + yoffs);
429
	}else if(side == 4 && sign == 2){
430
		context.fillText(tex, x - yoffs - twidth, y - xoffs);					
431
	}
432
}
433
434
/********************************************************************************
435
  Canvas and Diagram Measuring Functions
436
437
  These functions allow us to measure pixels in diagram and other apps
438
 *********************************************************************************/
439
440
// Recursive Pos of div in document - should work in most browsers
441
function findPos(obj) {
442
	var curleft = curtop = 0;
443
	if(obj.offsetParent) {
444
		curleft = obj.offsetLeft;
445
		curtop = obj.offsetTop;
446
		while (obj = obj.offsetParent) {
447
			curleft += obj.offsetLeft;
448
			curtop += obj.offsetTop;
449
		}
450
	}
451
	return {
452
		x:curleft,
453
		y:curtop
454
	};
455
}
456
457
// Make side coordinates for drawing Model
458
function makeside(side, x1, y1, x2, y2, perc) {
459
	var xk = 0;
460
	var yk = 0;
461
462
	if(side == 1) {
463
		xk = x1;
464
		yk = y1  +  ((y2 - y1) * perc);
465
	} else if(side == 2) {
466
		xk = x1 + ((x2 - x1) * perc);
467
		yk = y2;
468
	} else if(side == 3){
469
		xk = x2;
470
		yk = y1 + ((y2 - y1) * perc);						
471
	} else if(side == 4){
472
		xk = x1 + ((x2 - x1) * perc)
473
		yk = y1;
474
	}
475
476
	return {
477
		x:xk, 
478
		y:yk
479
	};
480
}		
481
482
// Computes side identifier for a mouse coordinate and object coordinates
483
function computeside(x, y, x1, y1, x2, y2, sidetol) {
484
	var obj_sidentifier = "None";
485
	var obj_sideperc = 0;
486
	var obj_centerdist = 0;
487
488
	// Left Side
489
	if(x > x1 - sidetol && x < x1 + sidetol && y > y1 - sidetol && y < y2 + sidetol) {
490
		obj_sidentifier = 1;
491
		obj_sideperc = makesideperc(y, y1, y2);
492
		obj_centerdist = centerdist(y, y1, y2);
493
	}
494
495
	// Bottom Not Including Left Side or Right Side
496
	if(x > x1 + sidetol && x < x2 - sidetol && y > y2 - sidetol && y < y2 + sidetol) {
497
		obj_sidentifier = 2;
498
		obj_sideperc = makesideperc(x, x1, x2);
499
		obj_centerdist = centerdist(x, x1, x2);
500
	}
501
502
	// Right Side
503
	if(x > x2 - sidetol && x < x2 + sidetol && y > y1 - sidetol && y < y2 + sidetol) {
504
		obj_sidentifier = 3;
505
		obj_sideperc = makesideperc(y, y1, y2);
506
		obj_centerdist=centerdist(y, y1, y2);
507
	}
508
509
	// Top Not Including Left Side or Right Side
510
	if(x > x1 + sidetol && x < x2 - sidetol && y > y1 - sidetol && y < y1 + sidetol) {
511
		obj_sidentifier = 4;
512
		obj_sideperc = makesideperc(x, x1, x2);
513
		obj_centerdist=centerdist(x, x1, x2);
514
	}
515
516
	return {
517
		side:obj_sidentifier,
518
		perc:obj_sideperc,
519
		dist:obj_centerdist
520
	};
521
}		
522
523
// Make side perc for ER model
524
function makesideperc(x, x1, x2) {
525
	r = x2 - x1;
526
	perc = (x - x1) / r;
527
528
	if(perc > 1.0) perc = 1.0;
529
	if(perc < 0.0) perc = 0.0;
530
531
	return perc;
532
}
533
534
function centerdist(x, x1, x2){
535
	r = x1 + ((x2 - x1) * 0.5);
536
537
	return (x - r);
538
}
539
540
// Euclidian distance - Yo!
541
function distance(x1, y1, x2, y2) {
542
	var dist = Math.sqrt(((y2 - y1) * (y2 - y1)) + ((x2 - x1) * (x2 - x1)));
543
544
	return dist;
545
}
546
547
// Are we over a line or not.
548
function overline(x, y, x1, y1, x2, y2, tolerance) {
549
	var distance = 10000;
550
	dx = x2 - x1;
551
	dy = y2- y1;
552
553
	straighttolerance = 2.0;
554
555
	var box1, boy1, box2, boy2;
556
557
	if(x1 > x2) {
558
		box1 = x2;
559
		box2 = x1;
560
	} else {
561
		box1 = x1;
562
		box2 = x2;				
563
	}
564
565
	if(y1 > y2) {
566
		boy1 = y2;
567
		boy2 = y1;
568
	} else {
569
		boy1 = y1;
570
		boy2 = y2;				
571
	}
572
573
	//drawrect(box1-tolerance,boy1-tolerance,box2+tolerance,boy2+tolerance,"#aaa");
574
	if((x > (box1 - tolerance)) && (x < (box2 + tolerance)) && (y > (boy1 - tolerance)) && (y < (boy2 + tolerance))) {
575
		// Straight X, Straight Y or Positive or Negative Incline
576
		if(Math.abs(dx) < straighttolerance) {
577
			if(y1 < y2) {
578
				if(y > y1 - tolerance && y < y2 + tolerance) {
579
					distance = Math.abs(x1 - x);
580
				}
581
			} else {
582
				if(y > y2 - tolerance && y < y1 + tolerance) {
583
					distance = Math.abs(x1 - x);
584
				}		
585
			}
586
		} else if(Math.abs(dy) < straighttolerance) {
587
			if(x1 < x2){
588
				if(x > x1 - tolerance && x < x2 + tolerance) {
589
					distance = Math.abs(y1 - y);
590
				}
591
			} else {
592
				if(x > x2 - tolerance && x < x1 + tolerance) {
593
					distance = Math.abs(y1 - y);
594
				}
595
			}
596
		} else if(Math.abs(dx) >= Math.abs(dy)) {
597
			k = dy / dx;								
598
			yk = y1 + ((x - x1) * k);
599
			distance = Math.abs(yk - y);
600
		} else {
601
			k = dx / dy;
602
			xk = x1 + ((y - y1) * k);
603
			distance = Math.abs(xk - x);						
604
		}
605
	}
606
607
	return distance;
608
}