Revision 25507

View differences:

tags/3D_Animation_v1_0alpha_Build_5/libraries/libAnimation2D/src/test/java/com/iver/cit/gvsig/animation/AppTest.java
1
package com.iver.cit.gvsig.animation;
2

  
3
import junit.framework.Test;
4
import junit.framework.TestCase;
5
import junit.framework.TestSuite;
6

  
7
/**
8
 * Unit test for simple App.
9
 */
10
public class AppTest 
11
    extends TestCase
12
{
13
    /**
14
     * Create the test case
15
     *
16
     * @param testName name of the test case
17
     */
18
    public AppTest( String testName )
19
    {
20
        super( testName );
21
    }
22

  
23
    /**
24
     * @return the suite of tests being tested
25
     */
26
    public static Test suite()
27
    {
28
        return new TestSuite( AppTest.class );
29
    }
30

  
31
    /**
32
     * Rigourous Test :-)
33
     */
34
    public void testApp()
35
    {
36
        assertTrue( true );
37
    }
38
}
tags/3D_Animation_v1_0alpha_Build_5/libraries/libAnimation2D/src/main/java/com/iver/cit/gvsig/animation/animationType/AnimationTypeFactoryLayer2D.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*/
19

  
20
package com.iver.cit.gvsig.animation.animationType;
21

  
22
import com.iver.cit.gvsig.animation.AnimationFactory;
23

  
24
public class AnimationTypeFactoryLayer2D extends AnimationFactory {
25

  
26
	public static String registerName = "AnimationLayer2D";
27
	
28
	
29
	public static AnimationLayer2D animationLayer2D;
30
	
31
	static {
32
		if (animationLayer2D == null) {
33
			animationLayer2D = new AnimationLayer2D();
34
			animationLayer2D.setClassName("AnimationLayer2D");
35
			animationLayer2D.setName("AnimationLayer2D");
36
			animationLayer2D.setDescription("Animacion basada en encuadres para vista 2D.");
37
		}
38
	}
39
	
40

  
41
	
42
	public Object create() {
43
		
44
       return animationLayer2D;
45
	}
46
	
47
	/**
48
	 * Registers in the points of extension the Factory with alias.
49
	 * 
50
	 */
51
	public static void register() {
52
		register(registerName, new AnimationTypeFactoryLayer2D(), "com.iver.cit.gvsig.animation.test.AnimationLayer2D");
53
	}
54

  
55
	public String getRegisterName() {
56
		return registerName;
57
	}
58

  
59
}
tags/3D_Animation_v1_0alpha_Build_5/libraries/libAnimation2D/src/main/java/com/iver/cit/gvsig/animation/animationType/AnimationLayer2D.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*/
19

  
20
package com.iver.cit.gvsig.animation.animationType;
21

  
22
import com.iver.andami.PluginServices;
23
import com.iver.andami.ui.mdiManager.IWindow;
24
import com.iver.cit.gvsig.animation.IAnimationType;
25
import com.iver.cit.gvsig.animation.animatedObject.AnimationObject2D;
26
import com.iver.cit.gvsig.animation.interpolator.Interpolator2D;
27
import com.iver.cit.gvsig.animation.keyFrame.KeyFrame2D;
28
import com.iver.cit.gvsig.animation.keyframe.IAnimationTypeKeyFrame;
29
import com.iver.cit.gvsig.animation.keyframe.interpolator.FuntionFactory;
30
import com.iver.cit.gvsig.animation.keyframe.interpolator.IInterpolator;
31
import com.iver.cit.gvsig.animation.keyframe.interpolator.IInterpolatorTimeFuntion;
32
import com.iver.cit.gvsig.project.ProjectExtent;
33
import com.iver.cit.gvsig.project.documents.view.gui.BaseView;
34
import com.iver.cit.gvsig.project.documents.view.gui.View;
35
import com.iver.utiles.IPersistence;
36
import com.iver.utiles.XMLEntity;
37

  
38
public class AnimationLayer2D implements IAnimationTypeKeyFrame {
39

  
40
	private String className = "AnimationLayer2D";
41
	private String description = "Animacion para zoom de capas";
42
	private String name = "Animacion de zoom capas";
43
	private int typeTrack = IAnimationType.TIME_TYPE_TRACK;
44
	private IInterpolator interpolator;
45
	private View view;
46
	private AnimationObject2D animationObject2D = new AnimationObject2D() ;
47
	private String titleWindow;
48

  
49
	public AnimationLayer2D() {
50
		this.interpolator = new Interpolator2D();
51
	}
52

  
53
	public String getClassName() {
54
		return className;
55
	}
56

  
57
	public String getDescription() {
58
		return description;
59
	}
60

  
61
	public String getName() {
62
		return name;
63
	}
64

  
65
	public void setClassName(String className) {
66
		this.className = className;
67
	}
68

  
69
	public void setDescription(String description) {
70
		this.description = description;
71
	}
72

  
73
	public void setName(String name) {
74
		this.name = name;
75
	}
76

  
77
	public void AppliesToObject(Object animated) {
78

  
79
		// Casting the animated object
80
		KeyFrame2D keyFrame2D = (KeyFrame2D) animated;
81
		this.view = (View) this.animationObject2D.getAnimatedView();
82
		this.view.getMapControl().getViewPort().setExtent(
83
				((ProjectExtent) keyFrame2D.getAnimatedObject()).getExtent());
84
		// Repainting the object
85
		this.view.getMapControl().drawMap(true);
86
	}
87

  
88
	public int getTypeTrack() {
89
		return typeTrack;
90
	}
91

  
92
	public void setTypeTrack(int typeTrack) {
93
		this.typeTrack = typeTrack;
94
	}
95

  
96
	public IInterpolator getInterpolator() {
97
		return this.interpolator;
98
	}
99

  
100
	public void setInterpolator(IInterpolator interpolator) {
101
		this.interpolator = interpolator;
102
	}
103

  
104
	
105
	public Object getAnimatedObject() {
106
		if(this.animationObject2D != null) {
107
			// getting all views.
108
			try{
109
				IWindow[] viewArray = PluginServices.getMDIManager().getAllWindows();
110
				for (int i = 0; i < viewArray.length; i++) {
111
					IWindow window = viewArray[i];
112
						if(window.getWindowInfo().getTitle().equals(this.titleWindow)){
113
							BaseView newView = (BaseView)window;
114
							this.animationObject2D.setAnimatedView(newView);
115
							this.setAnimatedObject(this.animationObject2D);
116
							IInterpolatorTimeFuntion funtion = FuntionFactory.createObject("com.iver.cit.gvsig.animation.keyframe.interpolator.LinearFuntion");
117
							this.interpolator.setFuntion(funtion);
118
						}
119
				}
120
			}catch(Exception e) {
121
				e.printStackTrace();
122
			}
123
		}
124
		return this.animationObject2D;
125
	}
126
	
127
	
128
	public void setAnimatedObject(Object object) {
129
		if (object instanceof AnimationObject2D)
130
			this.animationObject2D = (AnimationObject2D) object;
131

  
132
	}
133
public XMLEntity getXMLEntity() {
134
		
135
		View myActualView = null;
136
		
137
		XMLEntity xml = new XMLEntity();
138
		xml.putProperty("className", this.getClassName());
139
		xml.putProperty("description", description);
140
		xml.putProperty("animationTrackTipe", typeTrack);
141
		myActualView = (View) animationObject2D.getAnimatedView();
142
		titleWindow = myActualView.getWindowInfo().getTitle();
143
		xml.putProperty("titleWindow", titleWindow);
144
		xml.addChild(((IPersistence)this.interpolator).getXMLEntity());
145
		return xml;
146
	}
147

  
148
	public void setXMLEntity(XMLEntity xml) {
149
		if (xml.contains("className"))
150
			this.className=	xml.getStringProperty("className");
151
		if (xml.contains("animationTrackTipe"))
152
			this.typeTrack = xml.getIntProperty("animationTrackTipe");
153
		if (xml.contains("titleWindow"))
154
			this.titleWindow = xml.getStringProperty("titleWindow");
155
		
156
		XMLEntity xmlInterpolator = xml.getChild(0);
157
		
158
		try {
159
			String class_name = xmlInterpolator.getStringProperty("className");
160
			Class<?> classInterpolator = Class.forName(class_name);
161
			Object obj = classInterpolator .newInstance();
162
			IPersistence objPersist = (IPersistence) obj;
163
			objPersist.setXMLEntity(xmlInterpolator);
164
			this.interpolator = (IInterpolator) obj;
165
			this.setInterpolator(interpolator);
166
			
167
		} catch (Exception e) {
168
			e.printStackTrace();
169
		}
170
	}
171

  
172
}
tags/3D_Animation_v1_0alpha_Build_5/libraries/libAnimation2D/src/main/java/com/iver/cit/gvsig/animation/interpolator/Interpolator2D.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*/
19

  
20
package com.iver.cit.gvsig.animation.interpolator;
21

  
22
import java.awt.geom.Rectangle2D;
23
import java.util.List;
24

  
25
import com.iver.cit.gvsig.animation.keyFrame.KeyFrame2D;
26
import com.iver.cit.gvsig.animation.keyframe.IKeyFrame;
27
import com.iver.cit.gvsig.animation.keyframe.interpolator.IInterpolator;
28
import com.iver.cit.gvsig.animation.keyframe.interpolator.IInterpolatorTimeFuntion;
29
import com.iver.cit.gvsig.project.ProjectExtent;
30
import com.iver.utiles.XMLEntity;
31

  
32
public class Interpolator2D implements IInterpolator {
33

  
34
	private String description = "Interpolaci?n basada en encuadres";
35
	private String name = "Interpolator2D";
36
	
37
	private IInterpolatorTimeFuntion funtion; 
38

  
39
	public IKeyFrame interpolate(List<IKeyFrame> kfList, int index, double time) {
40
		KeyFrame2D KF = new KeyFrame2D();
41

  
42
		if (kfList == null)
43
			return null;
44

  
45

  
46
		switch (kfList.size()) {
47
		// this case when there are only has 2 keyframes
48
		case 2:
49
			// getting the keyframes
50
			KeyFrame2D kf1 = (KeyFrame2D) kfList.get(0);
51
			KeyFrame2D kf2 = (KeyFrame2D) kfList.get(1);
52

  
53
			if (index == 1) {
54
				KeyFrame2D kaux = kf1;
55
				kf1 = kf2;
56
				kf2 = kaux;
57
			}
58

  
59
			ProjectExtent vp1 = (ProjectExtent) kf1.getAnimatedObject();
60
			ProjectExtent vp2 = (ProjectExtent) kf2.getAnimatedObject();
61

  
62

  
63
			double min1 = vp1.getExtent().getMinX();
64
			double time1 = kf1.getTime();
65
			double min2 = vp2.getExtent().getMinX();
66
			double time2 = kf2.getTime();
67
			double left = linearInterpolate(min1, min2, time1, time2, time);
68
			min1 = vp1.getExtent().getMinY();
69
			min2 = vp2.getExtent().getMinY();
70
			double top = linearInterpolate(min1, min2, time1, time2, time);
71
			min1 = vp1.getExtent().getWidth();
72
			min2 = vp2.getExtent().getWidth();
73
			double right = linearInterpolate(min1, min2, time1, time2, time);
74
			min1 = vp1.getExtent().getHeight();
75
			min2 = vp2.getExtent().getHeight();
76
			double bottom = linearInterpolate(min1, min2, time1, time2, time);
77

  
78
			Rectangle2D newExtent = new Rectangle2D.Double(left, top, right,
79
					bottom);
80
			ProjectExtent pe = new ProjectExtent();
81
			pe.setExtent(newExtent);
82
			KF.setAnimatedObject(pe);
83
			break;
84
		}
85

  
86
		return KF;
87
	}
88

  
89
	private double linearInterpolate(double minX, double minX2, double timePos,
90
			double timePos2, double time) {
91
		// P1 + (P2-P1)*((t-t1)/(t2-t1))
92
		return (minX + (minX2 - minX)
93
				* ((time - timePos) / (timePos2 - timePos)));
94
	}
95

  
96
	public IInterpolatorTimeFuntion getFuntion() {
97
		return this.funtion;
98
	}
99

  
100
	public void setFuntion(IInterpolatorTimeFuntion funtion) {
101
		this.funtion = funtion;
102
	}
103

  
104
	public String getClassName() {
105
		return this.getClass().getName();
106
	}
107

  
108
	public String getDescription() {
109
		return this.description;
110
	}
111

  
112
	public String getName() {
113
		return this.name;
114
	}
115

  
116
	public XMLEntity getXMLEntity() {
117
		XMLEntity xml = new XMLEntity();	
118
		xml.putProperty("className", this.getClassName());
119
		xml.putProperty("description", this.description);
120
		return xml;
121
	}
122
	
123
	public void setXMLEntity(XMLEntity xml) {
124
		if (xml.contains("description"))
125
			this.description = xml.getStringProperty("description");
126
		
127
	}
128
}
tags/3D_Animation_v1_0alpha_Build_5/libraries/libAnimation2D/src/main/java/com/iver/cit/gvsig/animation/keyFrame/AnimationKeyFrame2DFactory.java
1
package com.iver.cit.gvsig.animation.keyFrame;
2

  
3
import com.iver.cit.gvsig.animation.AnimationFactory;
4

  
5

  
6
public class AnimationKeyFrame2DFactory extends AnimationFactory {
7

  
8
	public static String registerName = "KeyFrame2D";
9
	
10
	
11
	/**
12
	 * Creating a new keyFrmame 2D in the factory.
13
	 */
14
	public Object create() {
15
		KeyFrame2D keyFrameFlat = new KeyFrame2D();
16
        return keyFrameFlat;
17
	}
18
	
19
	/**
20
	 * Registers in the points of extension the Factory with alias.
21
	 */
22
	public static void register() {
23
		register(registerName, new AnimationKeyFrame2DFactory(), "com.iver.cit.gvsig.animation.KeyFrame2D");
24
	}
25

  
26
	public String getRegisterName() {
27
		return registerName;
28
	}
29

  
30
}
tags/3D_Animation_v1_0alpha_Build_5/libraries/libAnimation2D/src/main/java/com/iver/cit/gvsig/animation/keyFrame/KeyFrame2D.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*/
19

  
20
package com.iver.cit.gvsig.animation.keyFrame;
21

  
22
import java.awt.geom.Rectangle2D;
23
import java.util.List;
24

  
25
import com.iver.cit.gvsig.animation.keyframe.IKeyFrame;
26
import com.iver.cit.gvsig.project.ProjectExtent;
27
import com.iver.utiles.XMLEntity;
28

  
29
public class KeyFrame2D implements IKeyFrame {
30

  
31
	private String name;
32
	private double time;
33
	private  String aliasKeyFrame = "KeyFrame2D";
34

  
35
	ProjectExtent projectExtent = null;
36
	private double valueX;
37
	private double valueY;
38
	private double valueW;
39
	private double valueH;
40

  
41

  
42
	public void CapturesProperties() {
43
		// TODO Auto-generated method stub
44
	}
45

  
46
	public void CapturesProperties(ProjectExtent projectExtent) {
47
		this.projectExtent = projectExtent;
48
	}
49

  
50
	public String getName() {
51
		return this.name;
52
	}
53

  
54
	public List<IKeyFrame> getPropertiesList() {
55
		// TODO Auto-generated method stub
56
		return null;
57
	}
58

  
59
	public void setName(String name) {
60
		this.name = name;
61

  
62
	}
63

  
64
	public void setPropertiesList(List<IKeyFrame> list) {
65
		// TODO Auto-generated method stub
66
	}
67

  
68
	public String toString() {
69
		String result;
70
		result = " keyframe2D:\n";
71
		result += " tiempo: " + this.time;
72
		result += " nombre del extent: " + this.projectExtent.getDescription();
73

  
74
		return result;
75
	}
76

  
77

  
78
	public Object getAnimatedObject() {
79
		return projectExtent;
80
	}
81
	public void setAnimatedObject(Object object) {
82
		this.projectExtent = (ProjectExtent) object;
83
	}
84

  
85
	public double getTime() {
86
		return time;
87
	}
88

  
89
	public void setTime(double time) {
90
		this.time = time;
91
	}
92

  
93
	public String getClassName() {
94
		return this.getClass().getName();
95
	}
96

  
97
	public XMLEntity getXMLEntity() {
98
		XMLEntity xml = new XMLEntity();
99
		
100
		xml.putProperty("className", this.getClassName());
101
		xml.putProperty("keyFrameAlias", aliasKeyFrame);
102
		xml.putProperty("time", time);
103
		
104
		xml.addChild((this.projectExtent).getXMLEntity());
105
		
106
		return xml;
107
	}
108

  
109
	public void setXMLEntity(XMLEntity xml) {
110
		
111
		if (xml.contains("time"))
112
			this.time = xml.getDoubleProperty("time");
113
		if (xml.contains("keyFrameAlias"))
114
			this.aliasKeyFrame = xml.getStringProperty("keyFrameAlias");
115
		
116
		XMLEntity xmlProp = xml.getChild(0);
117
		if (xmlProp.contains("extentX")) {
118
			valueX = xmlProp.getDoubleProperty("extentX");
119
		}
120
		if (xmlProp.contains("extentY")) {
121
			valueY = xmlProp.getDoubleProperty("extentY");
122
		}
123
		if (xmlProp.contains("extentW")) {
124
			valueW = xmlProp.getDoubleProperty("extentW");
125
		}
126
		if (xmlProp.contains("extentH")) {
127
			valueH = xmlProp.getDoubleProperty("extentH");
128
		}
129
		
130
		Rectangle2D rectangle2D = new Rectangle2D.Double(valueX, valueY, valueW, valueH);
131
		this.projectExtent = new ProjectExtent();
132
		this.projectExtent.setExtent(rectangle2D);
133
		
134
	}
135
}
tags/3D_Animation_v1_0alpha_Build_5/libraries/libAnimation2D/src/main/java/com/iver/cit/gvsig/animation/animatedObject/AnimationObject2D.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*/
19

  
20

  
21
package com.iver.cit.gvsig.animation.animatedObject;
22

  
23

  
24
public class AnimationObject2D extends AnimatedObjectBase {
25
	
26
	private String nameClassView;
27
	
28
	public String getClassName() {
29
		return this.getClass().getName();
30
	}
31
	
32
	public void setClassName(String className) {
33
	}
34
	
35
	public String getNameClassView() {
36
		return nameClassView;
37
		
38
	}
39
	
40
	public void setNameView(String nameView) {
41
		this.nameClassView = nameView;
42
		
43
	}
44
	
45
	public Object getAnimatedView() {
46
		return this.getAnimatedObject("view2D");
47
	}
48
	
49
	public void setAnimatedView(Object object) {
50
		this.addAnimatedObject("view2D", object);
51
	}
52
	
53
	
54
}
tags/3D_Animation_v1_0alpha_Build_5/libraries/libAnimation2D/pom.xml
1
<project xmlns="http://maven.apache.org/POM/4.0.0"
2
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4
	<modelVersion>4.0.0</modelVersion>
5
	<groupId>org.gvsig</groupId>
6
	<artifactId>libAnimation2D</artifactId>
7
	<packaging>jar</packaging>
8
	<version>1.0-SNAPSHOT</version>
9
	<name>libAnimation2D</name>
10
	<url>http://maven.apache.org</url>
11
	<parent>
12
		<groupId>org.gvsig</groupId>
13
		<artifactId>gvsig-library-base-pom</artifactId>
14
		<version>1.0-SNAPSHOT</version>
15
	</parent>
16
	<dependencies>
17
		<dependency>
18
			<groupId>org.gvsig</groupId>
19
			<artifactId>libAnimation</artifactId>
20
			<version>1.0-SNAPSHOT</version>
21
		</dependency>
22
		<dependency>
23
			<groupId>org.gvsig</groupId>
24
			<artifactId>_fwAndami</artifactId>
25
			<version>2.1-SNAPSHOT</version>
26
		</dependency>
27
		<dependency>
28
			<groupId>org.gvsig</groupId>
29
			<artifactId>appgvSIG</artifactId>
30
			<version>2.1-SNAPSHOT</version>
31
		</dependency>
32
		<dependency>
33
			<groupId>org.gvsig</groupId>
34
			<artifactId>libFMap</artifactId>
35
			<version>2.1-SNAPSHOT</version>
36
		</dependency>
37
	</dependencies>
38
</project>
0 39

  

Also available in: Unified diff