/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// __________ Imports __________

import com.sun.star.uno.UnoRuntime;
import com.sun.star.lang.XComponent;

import com.sun.star.awt.Point;
import com.sun.star.awt.Size;

import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.XPropertySet;

import com.sun.star.container.XNamed;

import com.sun.star.drawing.PolygonFlags;
import com.sun.star.drawing.PolyPolygonBezierCoords;
import com.sun.star.drawing.XShape;
import com.sun.star.drawing.XShapes;
import com.sun.star.drawing.XShapeGrouper;
import com.sun.star.drawing.XDrawPage;

import java.util.Random;


// __________ Implementation __________

/** drawing demo
    @author Sven Jacobi
 */

// This drawing demo will create/load a document, and show how to
// handle pages and shapes using the Office API,

// Calling this demo two parameter can be used. The first parameter
// describes if a document is to create or load: "draw" creates a
// draw document, "impress" creates an impress document, any other
// parameter is interpreted as URL and loads the corresponding
// document. ( example for a URL is: "file:///c:/test.odp" )
// The second parameter is the connection that is to use. If no parameter
// is given a standard impress document is created by using following
// connection: "uno:socket,host=localhost,port=2083;urp;StarOffice.ServiceManager";

public class DrawingDemo
{
    public static void main( String args[] )
    {
		XComponent xDrawDoc = null;
		try
		{
            // get the remote office context of a running office (a new office
            // instance is started if necessary)
			com.sun.star.uno.XComponentContext xOfficeContext = Helper.connect();

			String sURL;
			if ( args.length == 0 )
				sURL = "impress";
			else
				sURL = args[ 0 ];

			if ( sURL.equals( "draw" ) )
				sURL = "private:factory/sdraw";
			else if ( sURL.equals( "impress" ) )
				sURL = "private:factory/simpress";

			// suppress Presentation Autopilot when opening the document
			// properties are the same as described for
			// com.sun.star.document.MediaDescriptor
			PropertyValue[] pPropValues = new PropertyValue[ 1 ];
			pPropValues[ 0 ] = new PropertyValue();
			pPropValues[ 0 ].Name = "Silent";
			pPropValues[ 0 ].Value = new Boolean( true );

			xDrawDoc = Helper.createDocument( xOfficeContext,
				sURL, "_blank", 0, pPropValues );
		}
		catch( Exception ex )
		{
            System.out.println( ex );
			System.exit( 0 );
		}

 
		Demo_PageCreation( xDrawDoc, 10 );
		Demo_PageNaming( xDrawDoc, "this page is called: LastPage" );
		Demo_ShapeCreation( xDrawDoc );	
		Demo_PolyPolygonBezier( xDrawDoc );
		Demo_Group1( xDrawDoc );
		Demo_Group2( xDrawDoc );
        System.exit( 0 );
    }

	// This method appends draw pages to the document, so that a
	// minimum of n draw pages will be available.
	// For each second draw page also a new master page is created.
	public static void Demo_PageCreation( XComponent xDrawDoc, int n )
	{
		try
		{
			// If the document has less than n draw pages, append them,
			// a minimum of n draw pages will be available
			int i, nDrawPages;
			for ( nDrawPages = PageHelper.getDrawPageCount( xDrawDoc );
				nDrawPages < n; nDrawPages++ )
				PageHelper.insertNewDrawPageByIndex( xDrawDoc, nDrawPages );
			// Create a master page for each second drawpage
			int nMasterPages;
			for ( nMasterPages = PageHelper.getMasterPageCount( xDrawDoc );
				nMasterPages < ( ( nDrawPages + 1 ) / 2 ); nMasterPages++ )
				PageHelper.insertNewMasterPageByIndex( xDrawDoc, nMasterPages );

			// Now connect master page 1 to draw page 1 and 2, 
			// master page 2 to draw page 3 and 4 and so on.			
			for ( i = 0; i < nDrawPages; i++ )
			{
				XDrawPage xDrawPage = PageHelper.getDrawPageByIndex( xDrawDoc, i );
				XDrawPage xMasterPage = PageHelper.getMasterPageByIndex(
                    xDrawDoc, i / 2 );
				PageHelper.setMasterPage( xDrawPage, xMasterPage );
			}
		}
		catch( Exception ex )
		{
			System.out.println("Demo_PageCreation: I have a page creation problem");
		}
	}

	// this method shows how to name a page, this is exemplary
	// be done for the last draw page
	public static void Demo_PageNaming(
		XComponent xDrawDoc, String sLastPageName )
	{
		try
		{
			XDrawPage xLastPage = PageHelper.getDrawPageByIndex( xDrawDoc,
				PageHelper.getDrawPageCount( xDrawDoc ) - 1 );

			// each drawpage is supporting an XNamed interface
			XNamed xNamed = (XNamed)UnoRuntime.queryInterface(
				XNamed.class, xLastPage );

			// beware, the page must have an unique name
			xNamed.setName( sLastPageName );
		}
		catch( Exception ex )
		{
			System.out.println( "Demo_PageNaming: can't set page name" );
		}
	}

	// This method will add one rectangle shape into the lower left quarter of
	// every page that is available,
	public static void Demo_ShapeCreation( XComponent xDrawDoc )
	{
		try
		{
			boolean bIsImpressDocument = PageHelper.isImpressDocument( xDrawDoc );

			int nDrawingPages = PageHelper.getDrawPageCount( xDrawDoc );
			int nMasterPages =  PageHelper.getMasterPageCount( xDrawDoc );
			int nGlobalPageCount = nDrawingPages + nMasterPages;

			if ( bIsImpressDocument )
			{
				// in impress each draw page also has a notes page
				nGlobalPageCount += nDrawingPages;
				// for each drawing master is also a notes master available
				nGlobalPageCount += nMasterPages;
				// one handout is existing
				nGlobalPageCount += 1;
			}

			// create and fill a container with all draw pages
			XDrawPage[] pPages = new XDrawPage[ nGlobalPageCount ];
			int i, nCurrentPageIndex = 0;

			// insert handout page
			if ( bIsImpressDocument )
				pPages[ nCurrentPageIndex++ ] = PageHelper.getHandoutMasterPage(
                    xDrawDoc );

			// inserting all master pages
			for( i = 0; i < nMasterPages; i++ )
			{
				XDrawPage xMasterPage = PageHelper.getMasterPageByIndex(
                    xDrawDoc, i );
				pPages[ nCurrentPageIndex++ ] = xMasterPage;

				// if the document is an impress, get the corresponding notes
				// master page
				if ( bIsImpressDocument )
					pPages[ nCurrentPageIndex++ ] = PageHelper.getNotesPage(
                        xMasterPage );
			}
			for ( i = 0; i < nDrawingPages; i++ )
			{
				XDrawPage xDrawPage = PageHelper.getDrawPageByIndex( xDrawDoc, i );
				pPages[ nCurrentPageIndex++ ] = xDrawPage;

				// if the document is an impress, get the corresponding notes page
				if ( bIsImpressDocument )
					pPages[ nCurrentPageIndex++ ] = PageHelper.getNotesPage(
                        xDrawPage );
			}

			// Now a complete list of pages is available in pPages.
			// The following code will insert a rectangle into each page.
			for ( i = 0; i < nGlobalPageCount; i++ )
			{
				Size aPageSize = PageHelper.getPageSize( pPages[ i ] );
				int nHalfWidth  = aPageSize.Width / 2;
				int nHalfHeight = aPageSize.Height / 2;

	            Random aRndGen = new Random();
				int nRndObjWidth  = aRndGen.nextInt( nHalfWidth );
				int nRndObjHeight = aRndGen.nextInt( nHalfHeight );

				int	nRndObjPosX = aRndGen.nextInt( nHalfWidth - nRndObjWidth );
				int nRndObjPosY = aRndGen.nextInt( nHalfHeight - nRndObjHeight )
                    + nHalfHeight;

				XShapes xShapes = (XShapes)
					UnoRuntime.queryInterface( XShapes.class, pPages[ i ] );
				ShapeHelper.createAndInsertShape( xDrawDoc, xShapes, 
					new Point( nRndObjPosX, nRndObjPosY ),
						new Size( nRndObjWidth, nRndObjHeight ),
							"com.sun.star.drawing.RectangleShape" );
			}
		}
		catch( Exception ex )
		{
			System.out.println( "Demo_ShapeCreation:" + ex );
		}
	}

	// This method will show how to create a PolyPolygonBezier that lies is in the
	// topleft quarter of the page and positioned at the back
	public static void Demo_PolyPolygonBezier( XComponent xDrawDoc )
	{
		try
		{
			XShape xPolyPolygonBezier = ShapeHelper.createShape( xDrawDoc,
				new Point( 0, 0 ),
					new Size( 0, 0 ),
						"com.sun.star.drawing.ClosedBezierShape" );
	
			// the fact that the shape must have been added to the page before
			// it is possible to apply changes to the PropertySet, it is a good
			// proceeding to add the shape as soon as possible
			XDrawPage xDrawPage;
			// if possible insert our new shape in the master page
			if ( PageHelper.isImpressDocument( xDrawDoc ) )
				xDrawPage = PageHelper.getMasterPageByIndex( xDrawDoc, 0 );
			else
				xDrawPage = PageHelper.getDrawPageByIndex( xDrawDoc, 0 );
			XShapes xShapes = (XShapes)
				UnoRuntime.queryInterface( XShapes.class, xDrawPage );
			xShapes.add( xPolyPolygonBezier );

			XPropertySet xShapeProperties = (XPropertySet)
				UnoRuntime.queryInterface( XPropertySet.class, xPolyPolygonBezier );

			// get pagesize
			XPropertySet xPageProperties = (XPropertySet)
				UnoRuntime.queryInterface( XPropertySet.class, xDrawPage );
			int nPageWidth = ((Integer)xPageProperties.getPropertyValue( "Width" )).intValue() / 2;
			int nPageHeight = ((Integer)xPageProperties.getPropertyValue( "Height" )).intValue() / 2;

			PolyPolygonBezierCoords aCoords = new PolyPolygonBezierCoords();
			// allocating the outer sequence
			int nPolygonCount = 50;
			aCoords.Coordinates = new Point[ nPolygonCount ][ ];	
			aCoords.Flags = new PolygonFlags[ nPolygonCount ][ ];
			int i, n, nY;
			// fill the inner point sequence now
			for ( nY = 0, i = 0; i < nPolygonCount; i++, nY += nPageHeight / nPolygonCount )
			{
				// create a polygon using two normal and two control points
				// allocating the inner sequence
				int nPointCount = 8;
				Point[]			pPolyPoints = new Point[ nPointCount ];
				PolygonFlags[]	pPolyFlags	= new PolygonFlags[ nPointCount ];

				for ( n = 0; n < nPointCount; n++ )
					pPolyPoints[ n ] = new Point();

				pPolyPoints[ 0 ].X = 0;
				pPolyPoints[ 0 ].Y = nY;
				pPolyFlags[ 0 ] = PolygonFlags.NORMAL;
				pPolyPoints[ 1 ].X = nPageWidth / 2;
				pPolyPoints[ 1 ].Y = nPageHeight;
				pPolyFlags[ 1 ] = PolygonFlags.CONTROL;
				pPolyPoints[ 2 ].X = nPageWidth / 2;;
				pPolyPoints[ 2 ].Y = nPageHeight;
				pPolyFlags[ 2 ] = PolygonFlags.CONTROL;
				pPolyPoints[ 3 ].X = nPageWidth;
				pPolyPoints[ 3 ].Y = nY;
				pPolyFlags[ 3 ] = PolygonFlags.NORMAL;

				pPolyPoints[ 4 ].X = nPageWidth - 1000;
				pPolyPoints[ 4 ].Y = nY;
				pPolyFlags[ 4 ] = PolygonFlags.NORMAL;
				pPolyPoints[ 5 ].X = nPageWidth / 2;
				pPolyPoints[ 5 ].Y = nPageHeight / 2;
				pPolyFlags[ 5 ] = PolygonFlags.CONTROL;
				pPolyPoints[ 6 ].X = nPageWidth / 2;;
				pPolyPoints[ 6 ].Y = nPageHeight / 2;
				pPolyFlags[ 6 ] = PolygonFlags.CONTROL;
				pPolyPoints[ 7 ].X = 1000;
				pPolyPoints[ 7 ].Y = nY;
				pPolyFlags[ 7 ] = PolygonFlags.NORMAL;

				aCoords.Coordinates[ i ]= pPolyPoints;
				aCoords.Flags[ i ]		= pPolyFlags;
			}
			xShapeProperties.setPropertyValue( "PolyPolygonBezier", aCoords );

			// move the shape to the back by changing the ZOrder
			xShapeProperties.setPropertyValue( "ZOrder", new Integer( 1 ) );
		}
		catch ( Exception ex )
		{
			System.out.println( "Demo_PolyPolygonBezier:" + ex );
		}
	}

	// This method will create a group containing two ellipses 
	// the shapes will be added into the top right corner of the first
	// draw page
	public static void Demo_Group1( XComponent xDrawDoc )
	{
		try
		{
			XShape xGroup = ShapeHelper.createShape( xDrawDoc,
				new Point( 0, 0 ),
					new Size( 0, 0 ),
						"com.sun.star.drawing.GroupShape" );

			// before it is possible to insert shapes,
			// the group must have been added to the page
			XDrawPage xDrawPage = PageHelper.getDrawPageByIndex( xDrawDoc, 0 );
			XShapes xShapes = (XShapes)
				UnoRuntime.queryInterface( XShapes.class, xDrawPage );
			xShapes.add( xGroup );

			XShapes xShapesGroup = (XShapes)
				UnoRuntime.queryInterface( XShapes.class, xGroup );

			Size aPageSize = PageHelper.getPageSize( xDrawPage );

			int nWidth  = 4000; 
			int nHeight = 2000;
			int nPosX = ( aPageSize.Width * 3 ) / 4 - nWidth / 2;
			int nPosY1 = 2000;
			int nPosY2 = aPageSize.Height / 2 - ( nPosY1 + nHeight );
			XShape xRect1 = ShapeHelper.createShape( xDrawDoc,
				new Point( nPosX, nPosY1 ),
					new Size( nWidth, nHeight ),
						"com.sun.star.drawing.EllipseShape" );
			XShape xRect2 = ShapeHelper.createShape( xDrawDoc,
				new Point( nPosX, nPosY2 ),
					new Size( nWidth, nHeight ),
						"com.sun.star.drawing.EllipseShape" );

			xShapesGroup.add( xRect1 );
			xShapesGroup.add( xRect2 );
		}
		catch ( Exception ex )
		{
			System.out.println( "Demo_Group1:" + ex );
		}
	}

	// This method will group all available objects on the
	// first page.
	public static void Demo_Group2( XComponent xDrawDoc )
	{
		try
		{
			XDrawPage xDrawPage = PageHelper.getDrawPageByIndex( xDrawDoc, 0 );
			XShapeGrouper xShapeGrouper = (XShapeGrouper)
				UnoRuntime.queryInterface( XShapeGrouper.class, xDrawPage );

			XShapes xShapesPage = (XShapes)
				UnoRuntime.queryInterface( XShapes.class, xDrawPage );

			xShapeGrouper.group( xShapesPage );
		}
		catch ( Exception ex )
		{
			System.out.println( "Demo_Group2:" + ex );
		}
	}
}
