First revision of SparseArray (kind of like an IntMap).

Strict

Import assert

#Rem
Monkey Collections Framework
Based loosely on the Java Collections Framework
#End

'''' Top level Collection stuff ''''

#Rem
	AbstractCollection
	Due to limitations with generics in Monkey, ToArray cannot work with an array of type E.  We must return Object[] instead.
#End
Class AbstractCollection<E> Abstract
Private
	' A custom comparator to use for sorting and comparing items.
	Field comparator:AbstractComparator = Null

Public
' Abstract
	Method Add:Bool(o:E) Abstract
	Method AddAll:Bool(c:AbstractCollection<E>) Abstract
	Method Clear:Void() Abstract
	Method Contains:Bool(o:E) Abstract
	Method ContainsAll:Bool(c:AbstractCollection<E>) Abstract
	Method Enumerator:AbstractEnumerator<E>() Abstract
	Method FillArray:Int(arr:Object[]) Abstract ' populates the passed array and returns the number of items filled. best used for android
	Method IsEmpty:Bool() Abstract
	Method Remove:Bool(o:E) Abstract
	Method RemoveAll:Bool(c:AbstractCollection<E>) Abstract
	Method RetainAll:Bool(c:AbstractCollection<E>) Abstract
	Method Size:Int() Property Abstract
	Method Sort:Void(reverse:Bool = False, comp:AbstractComparator = Null) Abstract
	Method ToArray:Object[]() Abstract ' creates a new array of the correct size and returns it

' Methods
	Method ObjectEnumerator:AbstractEnumerator<E>()
		Return Enumerator()
	End

' Properties
	' Property to read comparator
	Method Comparator:AbstractComparator() Property
		Return comparator
	End

	' Property to write comparator
	Method Comparator:Void(comparator:AbstractComparator) Property
		Self.comparator = comparator
	End
End

#Rem
	AbstractEnumerator
	Used in the ObjectEnumerator method for calls to EachIn.
	If retrieved and used manually, the HasPrevious/PreviousObject/Remove/First/Last methods can be called.
#End
Class AbstractEnumerator<E>
' Abstract
	Method HasNext:Bool() Abstract
	Method HasPrevious:Bool() Abstract
	Method NextObject:E() Abstract
	Method PreviousObject:E() Abstract
	Method Remove:Void() Abstract
	Method First:Void() Abstract
	Method Last:Void() Abstract
	Method Reset:Void() Abstract
End

#Rem
	Comparable
	Allows developers to sort a collection without using a Comparator.  Each class is responsible
	for providing its own logic to determine how it should be sorted.
#End
Interface Comparable
	Method Compare:Int(o:Object)
	Method CompareBool:Bool(o:Object)
End

#Rem
	AbstractComparator
	This is a way for developers to provide a custom comparison method for sorting lists.
	It's sort of like a function pointer.
#End
Class AbstractComparator Abstract
' Abstract
	Method Compare:Int(o1:Object, o2:Object) Abstract

' Methods
	Method CompareBool:Bool(o1:Object, o2:Object)
		Return o1 = o2 Or Compare(o1, o2) = 0
	End

	Method HashCode:Int(o:Object)
		Return 0
	End
End

#Rem
	DefaultComparator
	Implements an AbstractComparator to handle primitive wrappers and strings.
#End
Global DEFAULT_COMPARATOR:DefaultComparator = New DefaultComparator
Class DefaultComparator Extends AbstractComparator
' Methods
	' Overrides AbstractComparator
	Method Compare:Int(o1:Object, o2:Object)
		If IntObject(o1) <> Null And IntObject(o2) <> Null Then
			If IntObject(o1).value < IntObject(o2).value Then Return -1
			If IntObject(o1).value > IntObject(o2).value Then Return 1
			Return 0
		ElseIf FloatObject(o1) <> Null And FloatObject(o2) <> Null Then
			If FloatObject(o1).value < FloatObject(o2).value Then Return -1
			If FloatObject(o1).value > FloatObject(o2).value Then Return 1
			Return 0
		ElseIf StringObject(o1) <> Null And StringObject(o2) <> Null Then
			If StringObject(o1).value < StringObject(o2).value Then Return -1
			If StringObject(o1).value > StringObject(o2).value Then Return 1
			Return 0
		End
		If o1 = o2 Then Return 0
		If o1 = Null Then Return -1
		If o2 = Null Then Return 1
		Return 0 ' don't know what to do!
	End

	' Overrides AbstractComparator
	Method CompareBool:Bool(o1:Object, o2:Object)
		If IntObject(o1) <> Null And IntObject(o2) <> Null Then
			Return IntObject(o1).value = IntObject(o2).value
		ElseIf FloatObject(o1) <> Null And FloatObject(o2) <> Null Then
			Return FloatObject(o1).value = FloatObject(o2).value
		ElseIf StringObject(o1) <> Null And StringObject(o2) <> Null Then
			Return StringObject(o1).value = StringObject(o2).value
		End
		Return o1 = o2
	End
End

'''' List stuff ''''

#Rem
	AbstractList
	Extends AbstractCollection to implement some of the abstract methods that apply to any kind of list.
#End
Class AbstractList<E> Extends AbstractCollection<E> Abstract
Private
	' If true, bounds checking should be performed.
#if CONFIG="debug"
	Field rangeChecking:Bool = True
#else
	Field rangeChecking:Bool = False
#end

	' A counter for modifications to the list.  Used for concurrency checks.
	Field modCount:Int = 0

	' Performs a range check.
	Method RangeCheck:Void(index:Int)
		Local size:Int = Self.Size()
		' range check doesn't use assert, for speed
		If index < 0 Or index >= size Then Error("AbstractList.RangeCheck: Index out of bounds: " + index + " is not 0<=index<" + size)
	End

Public
' Abstract
	Method AddLast:Bool(o:E) Abstract
	Method RemoveLast:E() Abstract
	Method GetLast:E() Abstract
	Method AddFirst:Bool(o:E) Abstract
	Method RemoveFirst:E() Abstract
	Method GetFirst:E() Abstract
	Method Get:E(index:Int) Abstract
	Method Insert:Void(index:Int, o:E) Abstract
	Method InsertAll:Bool(index:Int, c:AbstractCollection<E>) Abstract
	Method IndexOf:Int(o:E) Abstract
	Method LastIndexOf:Int(o:E) Abstract
	Method RemoveAt:E(index:Int) Abstract ' Can't overload Remove since it's an inherited method, and Monkey doesn't support that.
	Method RemoveRange:Void(fromIndex:Int, toIndex:Int) Abstract
	Method Set:E(index:Int, o:E) Abstract

' Methods
	' Overrides AbstractCollection
	Method Enumerator:AbstractEnumerator<E>()
		Return New ListEnumerator<E>(Self)
	End

' Properties
	' Property to read rangeChecking
	Method RangeChecking:Bool() Property
		Return rangeChecking
	End

	' Property to write rangeChecking
	Method RangeChecking:Void(rangeChecking:Bool) Property
		Self.rangeChecking = rangeChecking
	End
End

#Rem
	ListEnumerator
	Extends AbstractEnumerator to provide support for EachIn.  Blocks concurrent modification, but allows elements to be removed on the fly.
#End
Class ListEnumerator<E> Extends AbstractEnumerator<E>
Private
	Field lst:AbstractList<E>
	Field lastIndex:Int = 0
	Field index:Int = 0
	Field expectedModCount:Int = 0

	Method CheckConcurrency:Void()
		' for speed we don't use assert
		If lst.modCount <> expectedModCount Then Error("ListEnumerator.CheckConcurrency: Concurrent list modification")
	End

Public
' Constructors
	Method New(lst:AbstractList<E>)
		Self.lst = lst
		expectedModCount = lst.modCount
	End

' Methods
	' Overrides AbstractEnumerator
	Method HasNext:Bool()
		CheckConcurrency()
		Return index < lst.Size
	End

	' Overrides AbstractEnumerator
	Method HasPrevious:Bool()
		CheckConcurrency()
		Return index > 0
	End

	' Overrides AbstractEnumerator
	Method NextObject:E()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return lst.Get(lastIndex)
	End

	' Overrides AbstractEnumerator
	Method PreviousObject:E()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return lst.Get(lastIndex)
	End

	' Overrides AbstractEnumerator
	Method Remove:Void()
		CheckConcurrency()
		lst.RemoveAt(lastIndex)
		If lastIndex < index Then index -= 1
		lastIndex = -1
		expectedModCount = lst.modCount
	End

	' Overrides AbstractEnumerator
	Method First:Void()
		CheckConcurrency()
		index = 0
	End

	' Overrides AbstractEnumerator
	Method Last:Void()
		CheckConcurrency()
		index = lst.Size
	End

	' Overrides AbstractEnumerator
	Method Reset:Void()
		index = 0
		expectedModCount = lst.modCount
	End
End

#Rem
	ArrayListEnumerator
	Extends ListEnumerator to avoid some method calls.
#End
Class ArrayListEnumerator<E> Extends ListEnumerator<E>
Private
	Field alst:ArrayList<E>

Public
' Constructors
	Method New(lst:ArrayList<E>)
		Super.New(lst)
		Self.alst = lst
		expectedModCount = alst.modCount
	End

' Methods
	' Overrides ListEnumerator
	Method HasNext:Bool()
		CheckConcurrency()
		Return index < alst.size
	End

	' Overrides ListEnumerator
	Method NextObject:E()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return alst.elements[lastIndex]
	End

	' Overrides ListEnumerator
	Method PreviousObject:E()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return alst.elements[lastIndex]
	End
End

Class IntListEnumerator Extends ListEnumerator<IntObject>
' Constructors
	Method New(lst:AbstractList<IntObject>)
		Super.New(lst)
	End

' Methods
	Method NextInt:Int()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return lst.Get(lastIndex).value
	End

	Method PreviousInt:Int()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return lst.Get(lastIndex).value
	End
End

Class FloatListEnumerator Extends ListEnumerator<FloatObject>
' Constructors
	Method New(lst:AbstractList<FloatObject>)
		Super.New(lst)
	End

' Methods
	Method NextFloat:Float()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return lst.Get(lastIndex).value
	End

	Method PreviousFloat:Float()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return lst.Get(lastIndex).value
	End
End

Class StringListEnumerator Extends ListEnumerator<StringObject>
' Constructors
	Method New(lst:AbstractList<IntObject>)
		Super.New(lst)
	End

' Methods
	Method NextString:String()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return lst.Get(lastIndex).value
	End

	Method PreviousString:String()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return lst.Get(lastIndex).value
	End
End

#Rem
	ArrayList
	Concrete implementation of AbstractList that uses a dynamically sized array to store elements.
	Has best performance when it is initialised with a capacity large enough to hold the expected number of elements.
#End
Class ArrayList<E> Extends AbstractList<E>
Private
	' fields
	Field elements:Object[]
	Field size:Int = 0

	' resizes the elements array if necessary to ensure it can fit minCapacity elements
	Method EnsureCapacity:Void(minCapacity:Int)
		Local oldCapacity:Int = elements.Length
		If minCapacity > oldCapacity Then
			Local newCapacity:Int = (oldCapacity * 3) / 2 + 1
			If newCapacity < minCapacity Then newCapacity = minCapacity
			elements = elements.Resize(newCapacity)
			modCount += 1
		End
	End

	Method RangeCheck:Void(index:Int)
		' range check doesn't use assert, for speed
		If index < 0 Or index >= size Then Error("ArrayList.RangeCheck: Index out of bounds: " + index + " is not 0<=index<" + size)
	End

	Field tempArr:Object[] = New Object[128] ' temp array used for internal call to ToArray (so we don't create an object)

Public
' Constructors
	Method New()
		Self.elements = New Object[10]
	End

	Method New(initialCapacity:Int)
		AssertGreaterThanOrEqual(initialCapacity, 0, "ArrayList.New: Illegal Capacity:")
		Self.elements = New Object[initialCapacity]
	End

	Method New(c:AbstractCollection<E>)
		elements = c.ToArray()
		size = elements.Length
	End

' Methods
	' Overrides AbstractCollection
	Method Add:Bool(o:E)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		elements[size] = o
		size+=1
		modCount += 1
		Return True
	End

	' Overrides AbstractCollection
	Method AddAll:Bool(c:AbstractCollection<E>)
		If c.IsEmpty() Then Return False
		Local newItemCount:Int = c.Size
		If size + newItemCount > elements.Length Then EnsureCapacity(size+newItemCount)
		If tempArr.Length < newItemCount Then tempArr = tempArr.Resize(newItemCount)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = 0 Until len
			elements[size] = tempArr[i]
			size+=1
		End
		modCount += 1
		Return newItemCount <> 0
	End

	' Overrides AbstractCollection
	Method Clear:Void()
		For Local i:Int = 0 Until size
			elements[i] = Null
		Next
		modCount += 1
		size = 0
	End

	' Overrides AbstractCollection
	Method Contains:Bool(o:E)
		For Local i:Int = 0 Until size
			If elements[i] = o Then Return True
		Next
		Return False
	End

	' Overrides AbstractCollection
	Method ContainsAll:Bool(c:AbstractCollection<E>)
		If c.IsEmpty() Then Return True
		If tempArr.Length < c.Size Then tempArr = tempArr.Resize(c.Size)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = 0 Until len
			If Not Self.Contains(E(tempArr[i])) Then Return False
		Next
		Return True
	End

	' Overrides AbstractCollection
	Method Enumerator:AbstractEnumerator<E>()
		Return New ArrayListEnumerator<E>(Self)
	End

	' Overrides AbstractCollection
	Method FillArray:Int(arr:Object[])
		AssertGreaterThanOrEqual(arr.Length, size, "ArrayList.FillArray: Array too small:")
		For Local i:Int = 0 Until size
			arr[i] = elements[i]
		Next
		Return size
	End

	' Overrides AbstractCollection
	Method IsEmpty:Bool()
		Return size = 0
	End

	' Overrides AbstractCollection
	Method Remove:Bool(o:E)
		For Local i:Int = 0 Until size
			If elements[i] = o Then
				RemoveAt(i)
				modCount += 1
				Return True
			End
		Next
		Return False
	End

	' Overrides AbstractCollection
	Method RemoveAll:Bool(c:AbstractCollection<E>)
		If c.IsEmpty() Then Return False
		Local modified:Bool = False
		If tempArr.Length < c.Size Then tempArr = tempArr.Resize(c.Size)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = 0 Until len
			If Self.Contains(E(tempArr[i])) Then
				Self.Remove(E(tempArr[i]))
			End
		Next
		If modified Then modCount += 1
		Return modified
	End

	' Overrides AbstractCollection
	Method RetainAll:Bool(c:AbstractCollection<E>)
		Local modified:Bool = False
		If tempArr.Length < c.Size Then tempArr = tempArr.Resize(c.Size)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = 0 Until len
			If Not Self.Contains(E(tempArr[i])) Then
				Self.Remove(E(tempArr[i]))
				modified = True
			End
		Next
		If modified Then modCount += 1
		Return modified
	End

	' Overrides AbstractCollection
	Method Size:Int() Property
		Return size
	End

	' Overrides AbstractCollection
	Method Sort:Void(reverse:Bool = False, comp:AbstractComparator = Null)
		If size <= 1 Then Return ' can't sort 0 or 1 elements
		If comp = Null Then comp = Self.Comparator
		If comp = Null Then comp = DEFAULT_COMPARATOR
		QuickSort(elements, 0, size-1, comp, reverse)
		modCount += 1
	End

	' Overrides AbstractCollection
	Method ToArray:Object[]()
		Local arr:Object[] = New Object[size]
		For Local i:Int = 0 Until size
			arr[i] = elements[i]
		Next
		Return arr
	End

	' Overrides AbstractList
	Method AddLast:Bool(o:E)
		Return Add(o)
	End

	' Overrides AbstractList
	Method RemoveLast:E()
		Return RemoveAt(size-1)
	End

	' Overrides AbstractList
	Method GetLast:E()
		Return Get(size-1)
	End

	' Overrides AbstractList
	Method AddFirst:Bool(o:E)
		Insert(0, o)
		Return True
	End

	' Overrides AbstractList
	Method RemoveFirst:E()
		Return Remove(0)
	End

	' Overrides AbstractList
	Method GetFirst:E()
		Return Get(0)
	End

	' Overrides AbstractList
	Method Get:E(index:Int)
		If rangeChecking Then RangeCheck(index)
		Return E(elements[index])
	End

	' Overrides AbstractList
	Method Insert:Void(index:Int, o:E)
		If rangeChecking Then RangeCheck(index)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		For Local i:Int = size Until index Step -1
			elements[i] = elements[i-1]
		Next
		elements[index] = o
		size+=1
		modCount += 1
	End

	' Overrides AbstractList
	Method InsertAll:Bool(index:Int, c:AbstractCollection<E>)
		Local newItemCount:Int = c.Size
		If newItemCount = 0 Then Return False
		If size + newItemCount > elements.Length Then EnsureCapacity(size+newItemCount)
		If tempArr.Length < newItemCount Then tempArr = tempArr.Resize(newItemCount)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = size - 1 To index Step -1
			elements[i+newItemCount] = elements[i]
		Next
		For Local i:Int = 0 Until newItemCount
			elements[index+i] = tempArr[i]
		End
		size += newItemCount
		modCount += 1
		Return newItemCount <> 0
	End

	' Overrides AbstractList
	Method IndexOf:Int(o:E)
		For Local i:Int = 0 Until size
			If elements[i] = o Then Return i
		Next
		Return -1
	End

	' Overrides AbstractList
	Method LastIndexOf:Int(o:E)
		For Local i:Int = size-1 To 0 Step -1
			If elements[i] = o Then Return i
		Next
		Return -1
	End

	' Overrides AbstractList
	Method RemoveAt:E(index:Int)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:E = E(elements[index])
		For Local i:Int = index Until size-1
			elements[i] = elements[i+1]
		Next
		elements[size-1] = Null
		size-=1
		modCount += 1
		Return oldValue
	End

	' Overrides AbstractList
	Method RemoveRange:Void(fromIndex:Int, toIndex:Int)
		AssertLessThanOrEqual(fromIndex, toIndex, "ArrayList.RemoveRange: fromIndex > toIndex:")
		If rangeChecking Then
			RangeCheck(fromIndex)
			RangeCheck(toIndex)
		End
		For Local i:Int = 0 Until toIndex - fromIndex
			RemoveAt(fromIndex)
		Next
	End

	' Overrides AbstractList
	Method Set:E(index:Int, o:E)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:E = E(elements[index])
		elements[index] = o
		modCount += 1
		Return oldValue
	End
End

' ArrayList wrapper classes

Class IntArrayList Extends ArrayList<IntObject>
' Methods
	Method AddInt:Bool(o:Int)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		elements[size] = New IntObject(o)
		size+=1
		modCount += 1
		Return True
	End

	Method ContainsInt:Bool(o:Int)
		For Local i:Int = 0 Until size
			If IntObject(elements[i]).value = o Then Return True
		Next
		Return False
	End

	' Overrides ArrayList
	Method Enumerator:AbstractEnumerator<IntObject>()
		Return New IntListEnumerator(Self)
	End

	Method RemoveInt:Bool(o:Int)
		For Local i:Int = 0 Until size
			If IntObject(elements[i]).value = o Then
				RemoveAt(i)
				modCount += 1
				Return True
			End
		Next
		Return False
	End

	Method ToIntArray:Int[]()
		Local arr:Int[] = New Int[size]
		For Local i:Int = 0 Until size
			arr[i] = IntObject(elements[i]).value
		Next
		Return arr
	End

	Method GetInt:Int(index:Int)
		If rangeChecking Then RangeCheck(index)
		Return IntObject(elements[index]).value
	End

	Method InsertInt:Void(index:Int, o:Int)
		If rangeChecking Then RangeCheck(index)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		For Local i:Int = size Until index Step -1
			elements[i] = elements[i-1]
		Next
		elements[index] = New IntObject(o)
		size+=1
		modCount += 1
	End

	Method IndexOfInt:Int(o:Int)
		For Local i:Int = 0 Until size
			If IntObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method LastIndexOfInt:Int(o:E)
		For Local i:Int = size-1 To 0 Step -1
			If IntObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method SetInt:Int(index:Int, o:Int)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:Int = IntObject(elements[index]).value
		If elements[index] <> Null Then
			IntObject(elements[index]).value = o ' XXX: not sure whether we can change value on the fly
		End
		modCount += 1
		Return oldValue
	End

	Method FillIntArray:Int(arr:Int[])
		AssertLessThan(arr.Length, size, "IntArrayList.FillIntArray: Array too small:")
		For Local i:Int = 0 Until size
			arr[i] = IntObject(elements[i]).value
		Next
		Return size
	End
End

Class FloatArrayList Extends ArrayList<FloatObject>
' Methods
	Method AddFloat:Bool(o:Float)
		If size + 1 > elements.Length Then EnsureCapacity(size + 1)
		elements[size] = New FloatObject(o)
		size += 1
		modCount += 1
		Return True
	End

	Method ContainsFloat:Bool(o:Float)
		For Local i:Int = 0 Until size
			If FloatObject(elements[i]).value = o Then Return True
		Next
		Return False
	End

	' Overrides ArrayList
	Method Enumerator:AbstractEnumerator<FloatObject>()
		Return New FloatListEnumerator(Self)
	End

	Method RemoveFloat:Bool(o:Float)
		For Local i:Int = 0 Until size
			If FloatObject(elements[i]).value = o Then
				RemoveAt(i)
				modCount += 1
				Return True
			End
		Next
		Return False
	End

	Method ToFloatArray:Float[]()
		Local arr:Float[] = New Float[size]
		For Local i:Int = 0 Until size
			arr[i] = FloatObject(elements[i]).value
		Next
		Return arr
	End

	Method GetFloat:Float(index:Int)
		If rangeChecking Then RangeCheck(index)
		Return FloatObject(elements[index]).value
	End

	Method InsertFloat:Void(index:Int, o:Float)
		If rangeChecking Then RangeCheck(index)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		For Local i:Int = size Until index Step -1
			elements[i] = elements[i-1]
		Next
		elements[index] = New FloatObject(o)
		size+=1
		modCount += 1
	End

	Method IndexOfFloat:Int(o:Float)
		For Local i:Int = 0 Until size
			If FloatObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method LastIndexOfFloat:Int(o:Float)
		For Local i:Int = size-1 To 0 Step -1
			If FloatObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method SetFloat:Float(index:Int, o:Float)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:Float = FloatObject(elements[index]).value
		If elements[index] <> Null Then
			FloatObject(elements[index]).value = o ' XXX: not sure whether we can change value on the fly
		End
		modCount += 1
		Return oldValue
	End

	Method FillFloatArray:Int(arr:Float[])
		AssertLessThan(arr.Length, size, "FloatArrayList.FillFloatArray: Array too small:")
		For Local i:Int = 0 Until size
			arr[i] = FloatObject(elements[i]).value
		Next
		Return size
	End
End

Class StringArrayList Extends ArrayList<StringObject>
' Methods
	Method AddString:Bool(o:String)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		elements[size] = New StringObject(o)
		size+=1
		modCount += 1
		Return True
	End

	Method ContainsString:Bool(o:String)
		For Local i:Int = 0 Until size
			If StringObject(elements[i]).value = o Then Return True
		Next
		Return False
	End

	' Overrides ArrayList
	Method Enumerator:AbstractEnumerator<StringObject>()
		Return New StringListEnumerator(Self)
	End

	Method RemoveString:Bool(o:String)
		For Local i:Int = 0 Until size
			If StringObject(elements[i]).value = o Then
				RemoveAt(i)
				modCount += 1
				Return True
			End
		Next
		Return False
	End

	Method ToStringArray:String[]()
		Local arr:String[] = New String[size]
		For Local i:Int = 0 Until size
			arr[i] = StringObject(elements[i]).value
		Next
		Return arr
	End

	Method GetString:String(index:Int)
		If rangeChecking Then RangeCheck(index)
		Return StringObject(elements[index]).value
	End

	Method InsertString:Void(index:Int, o:String)
		If rangeChecking Then RangeCheck(index)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		For Local i:Int = size Until index Step -1
			elements[i] = elements[i-1]
		Next
		elements[index] = New StringObject(o)
		size+=1
		modCount += 1
	End

	Method IndexOfString:Int(o:String)
		For Local i:Int = 0 Until size
			If StringObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method LastIndexOfString:Int(o:String)
		For Local i:Int = size-1 To 0 Step -1
			If StringObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method SetString:String(index:Int, o:String)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:String = StringObject(elements[index]).value
		If elements[index] <> Null Then
			StringObject(elements[index]).value = o ' XXX: not sure whether we can change value on the fly
		End
		modCount += 1
		Return oldValue
	End

	Method FillStringArray:Int(arr:String[])
		AssertLessThan(arr.Length, size, "StringArrayList.FillStringArray: Array too small:")
		For Local i:Int = 0 Until size
			If StringObject(elements[i]).value = value Then
				Remove(elements[i])
				modCount += 1
				Return True
			End
		Next
		Return False
	End
End

Class SparseArray<E>
Private
	Field elements:Object[]
	Field indices:Int[]
	Field size:Int
	Field arraySize:Int
	Field defaultValue:E

	' resizes the arrays if necessary to ensure they can fit minCapacity elements
	Method EnsureCapacity:Void(minCapacity:Int)
		Local oldCapacity:Int = elements.Length
		If minCapacity > oldCapacity Then
			Local newCapacity:Int = (oldCapacity * 3) / 2 + 1
			If newCapacity < minCapacity Then newCapacity = minCapacity
			elements = elements.Resize(newCapacity)
			indices = indices.Resize(newCapacity)
		End
	End

Public
	Method New(arraySize:Int=-1, defaultCapacity=100, defaultValue:E=Null)
		AssertGreaterThan(defaultCapacity, 0, "Default capacity must be greater than 0!")
		elements = New Object[defaultCapacity]
		indices = New Int[defaultCapacity]
		Self.arraySize = arraySize
		Self.defaultValue = defaultValue
	End

	Method Size:Int() Property
		Return size
	End

	Method ArraySize:Int() Property
		Return arraySize
	End

	Method ArraySize:Void(arraySize:Int) Property
		AssertGreaterThan(arraySize, size, "The SparseArray contains more mappings than the requested size.")
		Self.arraySize = arraySize
	End

	Method DefaultValue:E() Property
		Return defaultValue
	End

	Method DefaultValue:Void(defaultValue:E) Property
		Self.defaultValue = defaultValue
	End

	Method Get:E(index:Int)
		AssertRange(index, 0, arraySize, "Array index out of bounds.")
		For Local i% = 0 Until size
			If indices[i] = index Then Return E(elements[i])
		Next
		Return defaultValue
	End

	Method Set:E(index:Int, value:E)
		AssertRange(index, 0, arraySize, "Array index out of bounds.")
		For Local i% = 0 Until size
			If indices[i] = index Then
				Local oldVal:Object = elements[i]
				elements[i] = value
				Return E(oldVal)
			End
		Next
		ResizeArrays()
		indices[size] = index
		elements[size] = value
		size += 1
		Return defaultValue
	End

	Method Clear:Int()
		For Local i% = 0 Until size
			elements[i] = Null
		Next
		Local oldSize:Int = size
		size = 0
		Return oldSize
	End
End

Class SparseIntArray
Private
	Field elements:Int[]
	Field indices:Int[]
	Field size:Int
	Field arraySize:Int
	Field defaultValue:E

	' resizes the arrays if necessary to ensure they can fit minCapacity elements
	Method EnsureCapacity:Void(minCapacity:Int)
		Local oldCapacity:Int = elements.Length
		If minCapacity > oldCapacity Then
			Local newCapacity:Int = (oldCapacity * 3) / 2 + 1
			If newCapacity < minCapacity Then newCapacity = minCapacity
			elements = elements.Resize(newCapacity)
			indices = indices.Resize(newCapacity)
		End
	End

Public
	Method New(arraySize:Int=-1, defaultCapacity=100, defaultValue:Int=0)
		AssertGreaterThan(defaultCapacity, 0, "Default capacity must be greater than 0!")
		elements = New Int[defaultCapacity]
		indices = New Int[defaultCapacity]
		Self.arraySize = arraySize
		Self.defaultValue = defaultValue
	End

	Method Size:Int() Property
		Return size
	End

	Method ArraySize:Int() Property
		Return arraySize
	End

	Method ArraySize:Void(arraySize:Int) Property
		AssertGreaterThan(arraySize, size, "The SparseIntArray contains more mappings than the requested size.")
		Self.arraySize = arraySize
	End

	Method DefaultValue:Int() Property
		Return defaultValue
	End

	Method DefaultValue:Void(defaultValue:Int) Property
		Self.defaultValue = defaultValue
	End

	Method Get:Int(index:Int)
		If arraySize >= 0 Then
			AssertRange(index, 0, arraySize, "Array index out of bounds.")
		Else
			AssertGreaterThanOrEqual(index, 0, "Array index out of bounds.")
		End
		For Local i% = 0 Until size
			If indices[i] = index Then Return elements[i]
		Next
		Return defaultValue
	End

	Method Set:Int(index:Int, value:Int)
		If arraySize >= 0 Then
			AssertRange(index, 0, arraySize, "Array index out of bounds.")
		Else
			AssertGreaterThanOrEqual(index, 0, "Array index out of bounds.")
		End
		For Local i% = 0 Until size
			If indices[i] = index Then
				Local oldVal:Int = elements[i]
				elements[i] = value
				Return oldVal
			End
		Next
		ResizeArrays()
		indices[size] = index
		elements[size] = value
		size += 1
		Return defaultValue
	End

	Method Clear:Int()
		For Local i% = 0 Until size
			elements[i] = 0
		Next
		Local oldSize:Int = size
		size = 0
		Return oldSize
	End
End

Class SparseStringArray
Private
	Field elements:String[]
	Field indices:Int[]
	Field size:Int
	Field arraySize:Int
	Field defaultValue:String

	' resizes the arrays if necessary to ensure they can fit minCapacity elements
	Method EnsureCapacity:Void(minCapacity:Int)
		Local oldCapacity:Int = elements.Length
		If minCapacity > oldCapacity Then
			Local newCapacity:Int = (oldCapacity * 3) / 2 + 1
			If newCapacity < minCapacity Then newCapacity = minCapacity
			elements = elements.Resize(newCapacity)
			indices = indices.Resize(newCapacity)
		End
	End

Public
	Method New(arraySize:Int=-1, defaultCapacity=100, defaultValue:String=Null)
		AssertGreaterThan(defaultCapacity, 0, "Default capacity must be greater than 0!")
		elements = New String[defaultCapacity]
		indices = New Int[defaultCapacity]
		Self.arraySize = arraySize
		Self.defaultValue = defaultValue
	End

	Method Size:Int() Property
		Return size
	End

	Method ArraySize:Int() Property
		Return arraySize
	End

	Method ArraySize:Void(arraySize:Int) Property
		If arraySize >= 0 Then AssertGreaterThan(arraySize, size, "The SparseIntArray contains more mappings than the requested size.")
		Self.arraySize = arraySize
	End

	Method DefaultValue:String() Property
		Return defaultValue
	End

	Method DefaultValue:Void(defaultValue:String) Property
		Self.defaultValue = defaultValue
	End

	Method Get:String(index:Int)
		If arraySize >= 0 Then
			AssertRange(index, 0, arraySize, "Array index out of bounds.")
		Else
			AssertGreaterThanOrEqual(index, 0, "Array index out of bounds.")
		End
		For Local i% = 0 Until size
			If indices[i] = index Then Return elements[i]
		Next
		Return defaultValue
	End

	Method Set:String(index:Int, value:String)
		If arraySize >= 0 Then
			AssertRange(index, 0, arraySize, "Array index out of bounds.")
		Else
			AssertGreaterThanOrEqual(index, 0, "Array index out of bounds.")
		End
		For Local i% = 0 Until size
			If indices[i] = index Then
				Local oldVal:String = elements[i]
				elements[i] = value
				Return oldVal
			End
		Next
		ResizeArrays()
		indices[size] = index
		elements[size] = value
		size += 1
		Return defaultValue
	End

	Method Clear:Int()
		For Local i% = 0 Until size
			elements[i] = Null
		Next
		Local oldSize:Int = size
		size = 0
		Return oldSize
	End
End

Class SparseFloatArray
Private
	Field elements:Float[]
	Field indices:Int[]
	Field size:Int
	Field arraySize:Int
	Field defaultValue:Float

	' resizes the arrays if necessary to ensure they can fit minCapacity elements
	Method EnsureCapacity:Void(minCapacity:Int)
		Local oldCapacity:Int = elements.Length
		If minCapacity > oldCapacity Then
			Local newCapacity:Int = (oldCapacity * 3) / 2 + 1
			If newCapacity < minCapacity Then newCapacity = minCapacity
			elements = elements.Resize(newCapacity)
			indices = indices.Resize(newCapacity)
		End
	End

Public
	Method New(arraySize:Int=-1, defaultCapacity=100, defaultValue:Float=0)
		AssertGreaterThan(defaultCapacity, 0, "Default capacity must be greater than 0!")
		elements = New Int[defaultCapacity]
		indices = New Int[defaultCapacity]
		Self.arraySize = arraySize
		Self.defaultValue = defaultValue
	End

	Method Size:Int() Property
		Return size
	End

	Method ArraySize:Int() Property
		Return arraySize
	End

	Method ArraySize:Void(arraySize:Int) Property
		AssertGreaterThan(arraySize, size, "The SparseIntArray contains more mappings than the requested size.")
		Self.arraySize = arraySize
	End

	Method DefaultValue:Float() Property
		Return defaultValue
	End

	Method DefaultValue:Void(defaultValue:Float) Property
		Self.defaultValue = defaultValue
	End

	Method Get:Float(index:Int)
		If arraySize >= 0 Then
			AssertRange(index, 0, arraySize, "Array index out of bounds.")
		Else
			AssertGreaterThanOrEqual(index, 0, "Array index out of bounds.")
		End
		For Local i% = 0 Until size
			If indices[i] = index Then Return elements[i]
		Next
		Return defaultValue
	End

	Method Set:Float(index:Int, value:Float)
		If arraySize >= 0 Then
			AssertRange(index, 0, arraySize, "Array index out of bounds.")
		Else
			AssertGreaterThanOrEqual(index, 0, "Array index out of bounds.")
		End
		For Local i% = 0 Until size
			If indices[i] = index Then
				Local oldVal:Float = elements[i]
				elements[i] = value
				Return oldVal
			End
		Next
		ResizeArrays()
		indices[size] = index
		elements[size] = value
		size += 1
		Return defaultValue
	End

	Method Clear:Int()
		For Local i% = 0 Until size
			elements[i] = 0
		Next
		Local oldSize:Int = size
		size = 0
		Return oldSize
	End
End

Function QuickSort:Void(arr:Object[], left:Int, right:Int, comp:AbstractComparator, reverse:Bool = False)
	If right > left Then
		Local pivotIndex:Int = left + (right-left)/2
		Local pivotNewIndex:Int = QuickSortPartition(arr, left, right, pivotIndex, comp, reverse)
		QuickSort(arr, left, pivotNewIndex - 1, comp, reverse)
		QuickSort(arr, pivotNewIndex + 1, right, comp, reverse)
	End
End

Function QuickSortPartition:Int(arr:Object[], left:Int, right:Int, pivotIndex:Int, comp:AbstractComparator, reverse:Bool = False)
	Local pivotValue:Object = arr[pivotIndex]
	arr[pivotIndex] = arr[right]
	arr[right] = pivotValue
	Local storeIndex:Int = left, val:Object
	For Local i:Int = left Until right
		If Comparable(arr[i]) <> Null Then
			If Not reverse And Comparable(arr[i]).Compare(pivotValue) <= 0 Or reverse And Comparable(arr[i]).Compare(pivotValue) >= 0 Then
				val = arr[i]
				arr[i] = arr[storeIndex]
				arr[storeIndex] = val
				storeIndex += 1
			End
		Else
			If Not reverse And comp.Compare(arr[i], pivotValue) <= 0 Or reverse And comp.Compare(arr[i], pivotValue) >= 0 Then
				val = arr[i]
				arr[i] = arr[storeIndex]
				arr[storeIndex] = val
				storeIndex += 1
			End
		End
	Next
	val = arr[storeIndex]
	arr[storeIndex] = arr[right]
	arr[right] = val
	Return storeIndex
End

Strict

Import assert

#Rem
Monkey Collections Framework
Based loosely on the Java Collections Framework
#End

'''' Top level Collection stuff ''''

#Rem
	AbstractCollection
	Due to limitations with generics in Monkey, ToArray cannot work with an array of type E.  We must return Object[] instead.
#End
Class AbstractCollection<E> Abstract
Private
	' A custom comparator to use for sorting and comparing items.
	Field comparator:AbstractComparator = Null

Public
' Abstract
	Method Add:Bool(o:E) Abstract
	Method AddAll:Bool(c:AbstractCollection<E>) Abstract
	Method Clear:Void() Abstract
	Method Contains:Bool(o:E) Abstract
	Method ContainsAll:Bool(c:AbstractCollection<E>) Abstract
	Method Enumerator:AbstractEnumerator<E>() Abstract
	Method FillArray:Int(arr:Object[]) Abstract ' populates the passed array and returns the number of items filled. best used for android
	Method IsEmpty:Bool() Abstract
	Method Remove:Bool(o:E) Abstract
	Method RemoveAll:Bool(c:AbstractCollection<E>) Abstract
	Method RetainAll:Bool(c:AbstractCollection<E>) Abstract
	Method Size:Int() Property Abstract
	Method Sort:Void(reverse:Bool = False, comp:AbstractComparator = Null) Abstract
	Method ToArray:Object[]() Abstract ' creates a new array of the correct size and returns it

' Methods
	Method ObjectEnumerator:AbstractEnumerator<E>()
		Return Enumerator()
	End

' Properties
	' Property to read comparator
	Method Comparator:AbstractComparator() Property
		Return comparator
	End

	' Property to write comparator
	Method Comparator:Void(comparator:AbstractComparator) Property
		Self.comparator = comparator
	End
End

#Rem
	AbstractEnumerator
	Used in the ObjectEnumerator method for calls to EachIn.
	If retrieved and used manually, the HasPrevious/PreviousObject/Remove/First/Last methods can be called.
#End
Class AbstractEnumerator<E>
' Abstract
	Method HasNext:Bool() Abstract
	Method HasPrevious:Bool() Abstract
	Method NextObject:E() Abstract
	Method PreviousObject:E() Abstract
	Method Remove:Void() Abstract
	Method First:Void() Abstract
	Method Last:Void() Abstract
	Method Reset:Void() Abstract
End

#Rem
	Comparable
	Allows developers to sort a collection without using a Comparator.  Each class is responsible
	for providing its own logic to determine how it should be sorted.
#End
Interface Comparable
	Method Compare:Int(o:Object)
	Method CompareBool:Bool(o:Object)
End

#Rem
	AbstractComparator
	This is a way for developers to provide a custom comparison method for sorting lists.
	It's sort of like a function pointer.
#End
Class AbstractComparator Abstract
' Abstract
	Method Compare:Int(o1:Object, o2:Object) Abstract

' Methods
	Method CompareBool:Bool(o1:Object, o2:Object)
		Return o1 = o2 Or Compare(o1, o2) = 0
	End

	Method HashCode:Int(o:Object)
		Return 0
	End
End

#Rem
	DefaultComparator
	Implements an AbstractComparator to handle primitive wrappers and strings.
#End
Global DEFAULT_COMPARATOR:DefaultComparator = New DefaultComparator
Class DefaultComparator Extends AbstractComparator
' Methods
	' Overrides AbstractComparator
	Method Compare:Int(o1:Object, o2:Object)
		If IntObject(o1) <> Null And IntObject(o2) <> Null Then
			If IntObject(o1).value < IntObject(o2).value Then Return -1
			If IntObject(o1).value > IntObject(o2).value Then Return 1
			Return 0
		ElseIf FloatObject(o1) <> Null And FloatObject(o2) <> Null Then
			If FloatObject(o1).value < FloatObject(o2).value Then Return -1
			If FloatObject(o1).value > FloatObject(o2).value Then Return 1
			Return 0
		ElseIf StringObject(o1) <> Null And StringObject(o2) <> Null Then
			If StringObject(o1).value < StringObject(o2).value Then Return -1
			If StringObject(o1).value > StringObject(o2).value Then Return 1
			Return 0
		End
		If o1 = o2 Then Return 0
		If o1 = Null Then Return -1
		If o2 = Null Then Return 1
		Return 0 ' don't know what to do!
	End

	' Overrides AbstractComparator
	Method CompareBool:Bool(o1:Object, o2:Object)
		If IntObject(o1) <> Null And IntObject(o2) <> Null Then
			Return IntObject(o1).value = IntObject(o2).value
		ElseIf FloatObject(o1) <> Null And FloatObject(o2) <> Null Then
			Return FloatObject(o1).value = FloatObject(o2).value
		ElseIf StringObject(o1) <> Null And StringObject(o2) <> Null Then
			Return StringObject(o1).value = StringObject(o2).value
		End
		Return o1 = o2
	End
End

'''' List stuff ''''

#Rem
	AbstractList
	Extends AbstractCollection to implement some of the abstract methods that apply to any kind of list.
#End
Class AbstractList<E> Extends AbstractCollection<E> Abstract
Private
	' If true, bounds checking should be performed.
#if CONFIG="debug"
	Field rangeChecking:Bool = True
#else
	Field rangeChecking:Bool = False
#end

	' A counter for modifications to the list.  Used for concurrency checks.
	Field modCount:Int = 0

	' Performs a range check.
	Method RangeCheck:Void(index:Int)
		Local size:Int = Self.Size()
		' range check doesn't use assert, for speed
		If index < 0 Or index >= size Then Error("AbstractList.RangeCheck: Index out of bounds: " + index + " is not 0<=index<" + size)
	End

Public
' Abstract
	Method AddLast:Bool(o:E) Abstract
	Method RemoveLast:E() Abstract
	Method GetLast:E() Abstract
	Method AddFirst:Bool(o:E) Abstract
	Method RemoveFirst:E() Abstract
	Method GetFirst:E() Abstract
	Method Get:E(index:Int) Abstract
	Method Insert:Void(index:Int, o:E) Abstract
	Method InsertAll:Bool(index:Int, c:AbstractCollection<E>) Abstract
	Method IndexOf:Int(o:E) Abstract
	Method LastIndexOf:Int(o:E) Abstract
	Method RemoveAt:E(index:Int) Abstract ' Can't overload Remove since it's an inherited method, and Monkey doesn't support that.
	Method RemoveRange:Void(fromIndex:Int, toIndex:Int) Abstract
	Method Set:E(index:Int, o:E) Abstract

' Methods
	' Overrides AbstractCollection
	Method Enumerator:AbstractEnumerator<E>()
		Return New ListEnumerator<E>(Self)
	End

' Properties
	' Property to read rangeChecking
	Method RangeChecking:Bool() Property
		Return rangeChecking
	End

	' Property to write rangeChecking
	Method RangeChecking:Void(rangeChecking:Bool) Property
		Self.rangeChecking = rangeChecking
	End
End

#Rem
	ListEnumerator
	Extends AbstractEnumerator to provide support for EachIn.  Blocks concurrent modification, but allows elements to be removed on the fly.
#End
Class ListEnumerator<E> Extends AbstractEnumerator<E>
Private
	Field lst:AbstractList<E>
	Field lastIndex:Int = 0
	Field index:Int = 0
	Field expectedModCount:Int = 0

	Method CheckConcurrency:Void()
		' for speed we don't use assert
		If lst.modCount <> expectedModCount Then Error("ListEnumerator.CheckConcurrency: Concurrent list modification")
	End

Public
' Constructors
	Method New(lst:AbstractList<E>)
		Self.lst = lst
		expectedModCount = lst.modCount
	End

' Methods
	' Overrides AbstractEnumerator
	Method HasNext:Bool()
		CheckConcurrency()
		Return index < lst.Size
	End

	' Overrides AbstractEnumerator
	Method HasPrevious:Bool()
		CheckConcurrency()
		Return index > 0
	End

	' Overrides AbstractEnumerator
	Method NextObject:E()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return lst.Get(lastIndex)
	End

	' Overrides AbstractEnumerator
	Method PreviousObject:E()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return lst.Get(lastIndex)
	End

	' Overrides AbstractEnumerator
	Method Remove:Void()
		CheckConcurrency()
		lst.RemoveAt(lastIndex)
		If lastIndex < index Then index -= 1
		lastIndex = -1
		expectedModCount = lst.modCount
	End

	' Overrides AbstractEnumerator
	Method First:Void()
		CheckConcurrency()
		index = 0
	End

	' Overrides AbstractEnumerator
	Method Last:Void()
		CheckConcurrency()
		index = lst.Size
	End

	' Overrides AbstractEnumerator
	Method Reset:Void()
		index = 0
		expectedModCount = lst.modCount
	End
End

#Rem
	ArrayListEnumerator
	Extends ListEnumerator to avoid some method calls.
#End
Class ArrayListEnumerator<E> Extends ListEnumerator<E>
Private
	Field alst:ArrayList<E>

Public
' Constructors
	Method New(lst:ArrayList<E>)
		Super.New(lst)
		Self.alst = lst
		expectedModCount = alst.modCount
	End

' Methods
	' Overrides ListEnumerator
	Method HasNext:Bool()
		CheckConcurrency()
		Return index < alst.size
	End

	' Overrides ListEnumerator
	Method NextObject:E()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return alst.elements[lastIndex]
	End

	' Overrides ListEnumerator
	Method PreviousObject:E()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return alst.elements[lastIndex]
	End
End

Class IntListEnumerator Extends ListEnumerator<IntObject>
' Constructors
	Method New(lst:AbstractList<IntObject>)
		Super.New(lst)
	End

' Methods
	Method NextInt:Int()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return lst.Get(lastIndex).value
	End

	Method PreviousInt:Int()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return lst.Get(lastIndex).value
	End
End

Class FloatListEnumerator Extends ListEnumerator<FloatObject>
' Constructors
	Method New(lst:AbstractList<FloatObject>)
		Super.New(lst)
	End

' Methods
	Method NextFloat:Float()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return lst.Get(lastIndex).value
	End

	Method PreviousFloat:Float()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return lst.Get(lastIndex).value
	End
End

Class StringListEnumerator Extends ListEnumerator<StringObject>
' Constructors
	Method New(lst:AbstractList<IntObject>)
		Super.New(lst)
	End

' Methods
	Method NextString:String()
		CheckConcurrency()
		lastIndex = index
		index += 1
		Return lst.Get(lastIndex).value
	End

	Method PreviousString:String()
		CheckConcurrency()
		index -= 1
		lastIndex = index
		Return lst.Get(lastIndex).value
	End
End

#Rem
	ArrayList
	Concrete implementation of AbstractList that uses a dynamically sized array to store elements.
	Has best performance when it is initialised with a capacity large enough to hold the expected number of elements.
#End
Class ArrayList<E> Extends AbstractList<E>
Private
	' fields
	Field elements:Object[]
	Field size:Int = 0

	' resizes the elements array if necessary to ensure it can fit minCapacity elements
	Method EnsureCapacity:Void(minCapacity:Int)
		Local oldCapacity:Int = elements.Length
		If minCapacity > oldCapacity Then
			Local newCapacity:Int = (oldCapacity * 3) / 2 + 1
			If newCapacity < minCapacity Then newCapacity = minCapacity
			elements = elements.Resize(newCapacity)
			modCount += 1
		End
	End

	Method RangeCheck:Void(index:Int)
		' range check doesn't use assert, for speed
		If index < 0 Or index >= size Then Error("ArrayList.RangeCheck: Index out of bounds: " + index + " is not 0<=index<" + size)
	End

	Field tempArr:Object[] = New Object[128] ' temp array used for internal call to ToArray (so we don't create an object)

Public
' Constructors
	Method New()
		Self.elements = New Object[10]
	End

	Method New(initialCapacity:Int)
		AssertGreaterThanOrEqual(initialCapacity, 0, "ArrayList.New: Illegal Capacity:")
		Self.elements = New Object[initialCapacity]
	End

	Method New(c:AbstractCollection<E>)
		elements = c.ToArray()
		size = elements.Length
	End

' Methods
	' Overrides AbstractCollection
	Method Add:Bool(o:E)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		elements[size] = o
		size+=1
		modCount += 1
		Return True
	End

	' Overrides AbstractCollection
	Method AddAll:Bool(c:AbstractCollection<E>)
		If c.IsEmpty() Then Return False
		Local newItemCount:Int = c.Size
		If size + newItemCount > elements.Length Then EnsureCapacity(size+newItemCount)
		If tempArr.Length < newItemCount Then tempArr = tempArr.Resize(newItemCount)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = 0 Until len
			elements[size] = tempArr[i]
			size+=1
		End
		modCount += 1
		Return newItemCount <> 0
	End

	' Overrides AbstractCollection
	Method Clear:Void()
		For Local i:Int = 0 Until size
			elements[i] = Null
		Next
		modCount += 1
		size = 0
	End

	' Overrides AbstractCollection
	Method Contains:Bool(o:E)
		For Local i:Int = 0 Until size
			If elements[i] = o Then Return True
		Next
		Return False
	End

	' Overrides AbstractCollection
	Method ContainsAll:Bool(c:AbstractCollection<E>)
		If c.IsEmpty() Then Return True
		If tempArr.Length < c.Size Then tempArr = tempArr.Resize(c.Size)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = 0 Until len
			If Not Self.Contains(E(tempArr[i])) Then Return False
		Next
		Return True
	End

	' Overrides AbstractCollection
	Method Enumerator:AbstractEnumerator<E>()
		Return New ArrayListEnumerator<E>(Self)
	End

	' Overrides AbstractCollection
	Method FillArray:Int(arr:Object[])
		AssertGreaterThanOrEqual(arr.Length, size, "ArrayList.FillArray: Array too small:")
		For Local i:Int = 0 Until size
			arr[i] = elements[i]
		Next
		Return size
	End

	' Overrides AbstractCollection
	Method IsEmpty:Bool()
		Return size = 0
	End

	' Overrides AbstractCollection
	Method Remove:Bool(o:E)
		For Local i:Int = 0 Until size
			If elements[i] = o Then
				RemoveAt(i)
				modCount += 1
				Return True
			End
		Next
		Return False
	End

	' Overrides AbstractCollection
	Method RemoveAll:Bool(c:AbstractCollection<E>)
		If c.IsEmpty() Then Return False
		Local modified:Bool = False
		If tempArr.Length < c.Size Then tempArr = tempArr.Resize(c.Size)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = 0 Until len
			If Self.Contains(E(tempArr[i])) Then
				Self.Remove(E(tempArr[i]))
			End
		Next
		If modified Then modCount += 1
		Return modified
	End

	' Overrides AbstractCollection
	Method RetainAll:Bool(c:AbstractCollection<E>)
		Local modified:Bool = False
		If tempArr.Length < c.Size Then tempArr = tempArr.Resize(c.Size)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = 0 Until len
			If Not Self.Contains(E(tempArr[i])) Then
				Self.Remove(E(tempArr[i]))
				modified = True
			End
		Next
		If modified Then modCount += 1
		Return modified
	End

	' Overrides AbstractCollection
	Method Size:Int() Property
		Return size
	End

	' Overrides AbstractCollection
	Method Sort:Void(reverse:Bool = False, comp:AbstractComparator = Null)
		If size <= 1 Then Return ' can't sort 0 or 1 elements
		If comp = Null Then comp = Self.Comparator
		If comp = Null Then comp = DEFAULT_COMPARATOR
		QuickSort(elements, 0, size-1, comp, reverse)
		modCount += 1
	End

	' Overrides AbstractCollection
	Method ToArray:Object[]()
		Local arr:Object[] = New Object[size]
		For Local i:Int = 0 Until size
			arr[i] = elements[i]
		Next
		Return arr
	End

	' Overrides AbstractList
	Method AddLast:Bool(o:E)
		Return Add(o)
	End

	' Overrides AbstractList
	Method RemoveLast:E()
		Return RemoveAt(size-1)
	End

	' Overrides AbstractList
	Method GetLast:E()
		Return Get(size-1)
	End

	' Overrides AbstractList
	Method AddFirst:Bool(o:E)
		Insert(0, o)
		Return True
	End

	' Overrides AbstractList
	Method RemoveFirst:E()
		Return Remove(0)
	End

	' Overrides AbstractList
	Method GetFirst:E()
		Return Get(0)
	End

	' Overrides AbstractList
	Method Get:E(index:Int)
		If rangeChecking Then RangeCheck(index)
		Return E(elements[index])
	End

	' Overrides AbstractList
	Method Insert:Void(index:Int, o:E)
		If rangeChecking Then RangeCheck(index)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		For Local i:Int = size Until index Step -1
			elements[i] = elements[i-1]
		Next
		elements[index] = o
		size+=1
		modCount += 1
	End

	' Overrides AbstractList
	Method InsertAll:Bool(index:Int, c:AbstractCollection<E>)
		Local newItemCount:Int = c.Size
		If newItemCount = 0 Then Return False
		If size + newItemCount > elements.Length Then EnsureCapacity(size+newItemCount)
		If tempArr.Length < newItemCount Then tempArr = tempArr.Resize(newItemCount)
		Local len:Int = c.FillArray(tempArr)
		For Local i:Int = size - 1 To index Step -1
			elements[i+newItemCount] = elements[i]
		Next
		For Local i:Int = 0 Until newItemCount
			elements[index+i] = tempArr[i]
		End
		size += newItemCount
		modCount += 1
		Return newItemCount <> 0
	End

	' Overrides AbstractList
	Method IndexOf:Int(o:E)
		For Local i:Int = 0 Until size
			If elements[i] = o Then Return i
		Next
		Return -1
	End

	' Overrides AbstractList
	Method LastIndexOf:Int(o:E)
		For Local i:Int = size-1 To 0 Step -1
			If elements[i] = o Then Return i
		Next
		Return -1
	End

	' Overrides AbstractList
	Method RemoveAt:E(index:Int)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:E = E(elements[index])
		For Local i:Int = index Until size-1
			elements[i] = elements[i+1]
		Next
		elements[size-1] = Null
		size-=1
		modCount += 1
		Return oldValue
	End

	' Overrides AbstractList
	Method RemoveRange:Void(fromIndex:Int, toIndex:Int)
		AssertLessThanOrEqual(fromIndex, toIndex, "ArrayList.RemoveRange: fromIndex > toIndex:")
		If rangeChecking Then
			RangeCheck(fromIndex)
			RangeCheck(toIndex)
		End
		For Local i:Int = 0 Until toIndex - fromIndex
			RemoveAt(fromIndex)
		Next
	End

	' Overrides AbstractList
	Method Set:E(index:Int, o:E)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:E = E(elements[index])
		elements[index] = o
		modCount += 1
		Return oldValue
	End
End

' ArrayList wrapper classes

Class IntArrayList Extends ArrayList<IntObject>
' Methods
	Method AddInt:Bool(o:Int)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		elements[size] = New IntObject(o)
		size+=1
		modCount += 1
		Return True
	End

	Method ContainsInt:Bool(o:Int)
		For Local i:Int = 0 Until size
			If IntObject(elements[i]).value = o Then Return True
		Next
		Return False
	End

	' Overrides ArrayList
	Method Enumerator:AbstractEnumerator<IntObject>()
		Return New IntListEnumerator(Self)
	End

	Method RemoveInt:Bool(o:Int)
		For Local i:Int = 0 Until size
			If IntObject(elements[i]).value = o Then
				RemoveAt(i)
				modCount += 1
				Return True
			End
		Next
		Return False
	End

	Method ToIntArray:Int[]()
		Local arr:Int[] = New Int[size]
		For Local i:Int = 0 Until size
			arr[i] = IntObject(elements[i]).value
		Next
		Return arr
	End

	Method GetInt:Int(index:Int)
		If rangeChecking Then RangeCheck(index)
		Return IntObject(elements[index]).value
	End

	Method InsertInt:Void(index:Int, o:Int)
		If rangeChecking Then RangeCheck(index)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		For Local i:Int = size Until index Step -1
			elements[i] = elements[i-1]
		Next
		elements[index] = New IntObject(o)
		size+=1
		modCount += 1
	End

	Method IndexOfInt:Int(o:Int)
		For Local i:Int = 0 Until size
			If IntObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method LastIndexOfInt:Int(o:E)
		For Local i:Int = size-1 To 0 Step -1
			If IntObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method SetInt:Int(index:Int, o:Int)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:Int = IntObject(elements[index]).value
		If elements[index] <> Null Then
			IntObject(elements[index]).value = o ' XXX: not sure whether we can change value on the fly
		End
		modCount += 1
		Return oldValue
	End

	Method FillIntArray:Int(arr:Int[])
		AssertLessThan(arr.Length, size, "IntArrayList.FillIntArray: Array too small:")
		For Local i:Int = 0 Until size
			arr[i] = IntObject(elements[i]).value
		Next
		Return size
	End
End

Class FloatArrayList Extends ArrayList<FloatObject>
' Methods
	Method AddFloat:Bool(o:Float)
		If size + 1 > elements.Length Then EnsureCapacity(size + 1)
		elements[size] = New FloatObject(o)
		size += 1
		modCount += 1
		Return True
	End

	Method ContainsFloat:Bool(o:Float)
		For Local i:Int = 0 Until size
			If FloatObject(elements[i]).value = o Then Return True
		Next
		Return False
	End

	' Overrides ArrayList
	Method Enumerator:AbstractEnumerator<FloatObject>()
		Return New FloatListEnumerator(Self)
	End

	Method RemoveFloat:Bool(o:Float)
		For Local i:Int = 0 Until size
			If FloatObject(elements[i]).value = o Then
				RemoveAt(i)
				modCount += 1
				Return True
			End
		Next
		Return False
	End

	Method ToFloatArray:Float[]()
		Local arr:Float[] = New Float[size]
		For Local i:Int = 0 Until size
			arr[i] = FloatObject(elements[i]).value
		Next
		Return arr
	End

	Method GetFloat:Float(index:Int)
		If rangeChecking Then RangeCheck(index)
		Return FloatObject(elements[index]).value
	End

	Method InsertFloat:Void(index:Int, o:Float)
		If rangeChecking Then RangeCheck(index)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		For Local i:Int = size Until index Step -1
			elements[i] = elements[i-1]
		Next
		elements[index] = New FloatObject(o)
		size+=1
		modCount += 1
	End

	Method IndexOfFloat:Int(o:Float)
		For Local i:Int = 0 Until size
			If FloatObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method LastIndexOfFloat:Int(o:Float)
		For Local i:Int = size-1 To 0 Step -1
			If FloatObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method SetFloat:Float(index:Int, o:Float)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:Float = FloatObject(elements[index]).value
		If elements[index] <> Null Then
			FloatObject(elements[index]).value = o ' XXX: not sure whether we can change value on the fly
		End
		modCount += 1
		Return oldValue
	End

	Method FillFloatArray:Int(arr:Float[])
		AssertLessThan(arr.Length, size, "FloatArrayList.FillFloatArray: Array too small:")
		For Local i:Int = 0 Until size
			arr[i] = FloatObject(elements[i]).value
		Next
		Return size
	End
End

Class StringArrayList Extends ArrayList<StringObject>
' Methods
	Method AddString:Bool(o:String)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		elements[size] = New StringObject(o)
		size+=1
		modCount += 1
		Return True
	End

	Method ContainsString:Bool(o:String)
		For Local i:Int = 0 Until size
			If StringObject(elements[i]).value = o Then Return True
		Next
		Return False
	End

	' Overrides ArrayList
	Method Enumerator:AbstractEnumerator<StringObject>()
		Return New StringListEnumerator(Self)
	End

	Method RemoveString:Bool(o:String)
		For Local i:Int = 0 Until size
			If StringObject(elements[i]).value = o Then
				RemoveAt(i)
				modCount += 1
				Return True
			End
		Next
		Return False
	End

	Method ToStringArray:String[]()
		Local arr:String[] = New String[size]
		For Local i:Int = 0 Until size
			arr[i] = StringObject(elements[i]).value
		Next
		Return arr
	End

	Method GetString:String(index:Int)
		If rangeChecking Then RangeCheck(index)
		Return StringObject(elements[index]).value
	End

	Method InsertString:Void(index:Int, o:String)
		If rangeChecking Then RangeCheck(index)
		If size+1 > elements.Length Then EnsureCapacity(size+1)
		For Local i:Int = size Until index Step -1
			elements[i] = elements[i-1]
		Next
		elements[index] = New StringObject(o)
		size+=1
		modCount += 1
	End

	Method IndexOfString:Int(o:String)
		For Local i:Int = 0 Until size
			If StringObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method LastIndexOfString:Int(o:String)
		For Local i:Int = size-1 To 0 Step -1
			If StringObject(elements[i]).value = o Then Return i
		Next
		Return -1
	End

	Method SetString:String(index:Int, o:String)
		If rangeChecking Then RangeCheck(index)
		Local oldValue:String = StringObject(elements[index]).value
		If elements[index] <> Null Then
			StringObject(elements[index]).value = o ' XXX: not sure whether we can change value on the fly
		End
		modCount += 1
		Return oldValue
	End

	Method FillStringArray:Int(arr:String[])
		AssertLessThan(arr.Length, size, "StringArrayList.FillStringArray: Array too small:")
		For Local i:Int = 0 Until size
			If StringObject(elements[i]).value = value Then
				Remove(elements[i])
				modCount += 1
				Return True
			End
		Next
		Return False
	End
End

Function QuickSort:Void(arr:Object[], left:Int, right:Int, comp:AbstractComparator, reverse:Bool = False)
	If right > left Then
		Local pivotIndex:Int = left + (right-left)/2
		Local pivotNewIndex:Int = QuickSortPartition(arr, left, right, pivotIndex, comp, reverse)
		QuickSort(arr, left, pivotNewIndex - 1, comp, reverse)
		QuickSort(arr, pivotNewIndex + 1, right, comp, reverse)
	End
End

Function QuickSortPartition:Int(arr:Object[], left:Int, right:Int, pivotIndex:Int, comp:AbstractComparator, reverse:Bool = False)
	Local pivotValue:Object = arr[pivotIndex]
	arr[pivotIndex] = arr[right]
	arr[right] = pivotValue
	Local storeIndex:Int = left, val:Object
	For Local i:Int = left Until right
		If Comparable(arr[i]) <> Null Then
			If Not reverse And Comparable(arr[i]).Compare(pivotValue) <= 0 Or reverse And Comparable(arr[i]).Compare(pivotValue) >= 0 Then
				val = arr[i]
				arr[i] = arr[storeIndex]
				arr[storeIndex] = val
				storeIndex += 1
			End
		Else
			If Not reverse And comp.Compare(arr[i], pivotValue) <= 0 Or reverse And comp.Compare(arr[i], pivotValue) >= 0 Then
				val = arr[i]
				arr[i] = arr[storeIndex]
				arr[storeIndex] = val
				storeIndex += 1
			End
		End
	Next
	val = arr[storeIndex]
	arr[storeIndex] = arr[right]
	arr[right] = val
	Return storeIndex
End


Removed unneeded import

Removed unneeded import

--HG--
extra : convert_revision : svn%3Ae934d3cd-0d57-f34a-94d0-9e8d31ae1c29/trunk%40150

Strict

Import mojo
Import diddy

Function Main:Int()
	game = New MyGame
	Return 0
End

Global titleScreen:TitleScreen
Global gameScreen:GameScreen

Class MyGame Extends DiddyApp
	Method OnCreate:Int()
		Super.OnCreate()
		titleScreen = New TitleScreen
		gameScreen = new GameScreen
		titleScreen.PreStart()
		Return 0
	End
End

Class TitleScreen Extends Screen
	Method New()
		name = "Title"
	End

	Method Start:Void()
		game.screenFade.Start(50, false)
	End

	Method Render:Void()
		Cls
		DrawText "TITLE SCREEN", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
		DrawText "CLICK TO PLAY", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 10, 0.5, 0.5
		FPSCounter.Draw(0,0)
	End

	Method Update:Void()
		if game.mouseHit
			game.screenFade.Start(50, True, True, True)
			game.nextScreen = gameScreen
		End
	End
End

Class GameScreen Extends Screen
	Field tilemap:MyTileMap
	Field offsetX:Int, offsetY:Int
	Field str$

	Method New()
		name = "Game"
	End

	Method Start:Void()
		Local reader:MyTiledTileMapReader = New MyTiledTileMapReader
		Local tm:TileMap = reader.LoadMap("maps/map.xml")
		tilemap = MyTileMap(tm)
		game.screenFade.Start(50, false)
	End

	Method Render:Void()
		Cls
		tilemap.RenderMap(offsetX, offsetY, SCREEN_WIDTH, SCREEN_HEIGHT)

		FPSCounter.Draw(0,0)
	End

	Method Update:Void()
		If KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, True)
			game.nextScreen = game.exitScreen
		End
		If KeyDown(KEY_UP) Then offsetY -= 4
		If KeyDown(KEY_DOWN) Then offsetY += 4
		If KeyDown(KEY_LEFT) Then offsetX -= 4
		If KeyDown(KEY_RIGHT) Then offsetX += 4

		tilemap.UpdateAnimation(dt.frametime)
	End
End

Class MyTiledTileMapReader Extends TiledTileMapReader
	Method CreateMap:TileMap()
		Return New MyTileMap
	End
End

Class MyTileMap Extends TileMap
	Method ConfigureLayer:Void(tileLayer:TileMapLayer)
		SetAlpha(tileLayer.opacity)
	End

	Method DrawTile:Void(tileLayer:TileMapTileLayer, mapTile:TileMapTile, x:Int, y:Int)
		mapTile.image.DrawTile(x, y, mapTile.id, 0, 1, 1)
	End
End

Strict

Import mojo
Import diddy
Import diddy.tile

Function Main:Int()
	game = New MyGame
	Return 0
End

Global titleScreen:TitleScreen
Global gameScreen:GameScreen

Class MyGame Extends DiddyApp
	Method OnCreate:Int()
		Super.OnCreate()
		titleScreen = New TitleScreen
		gameScreen = new GameScreen
		titleScreen.PreStart()
		Return 0
	End
End

Class TitleScreen Extends Screen
	Method New()
		name = "Title"
	End

	Method Start:Void()
		game.screenFade.Start(50, false)
	End

	Method Render:Void()
		Cls
		DrawText "TITLE", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
		FPSCounter.Draw(0,0)
	End

	Method Update:Void()
		if game.mouseHit
			game.screenFade.Start(50, True, True, True)
			game.nextScreen = gameScreen
		End
	End
End

Class GameScreen Extends Screen
	Field tilemap:MyTileMap
	Field offsetX:Int, offsetY:Int
	Field str$

	Method New()
		name = "Game"
	End

	Method Start:Void()
		Local reader:MyTiledTileMapReader = New MyTiledTileMapReader
		Local tm:TileMap = reader.LoadMap("maps/map.xml")
		tilemap = MyTileMap(tm)
		game.screenFade.Start(50, false)
	End

	Method Render:Void()
		Cls
		tilemap.RenderMap(offsetX, offsetY, SCREEN_WIDTH, SCREEN_HEIGHT)

		FPSCounter.Draw(0,0)
	End

	Method Update:Void()
		If KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, True)
			game.nextScreen = game.exitScreen
		End
		If KeyDown(KEY_UP) Then offsetY -= 4
		If KeyDown(KEY_DOWN) Then offsetY += 4
		If KeyDown(KEY_LEFT) Then offsetX -= 4
		If KeyDown(KEY_RIGHT) Then offsetX += 4

		tilemap.UpdateAnimation(dt.frametime)
	End
End

Class MyTiledTileMapReader Extends TiledTileMapReader
	Method CreateMap:TileMap()
		Return New MyTileMap
	End
End

Class MyTileMap Extends TileMap
	Method ConfigureLayer:Void(tileLayer:TileMapLayer)
		SetAlpha(tileLayer.opacity)
	End

	Method DrawTile:Void(tileLayer:TileMapTileLayer, mapTile:TileMapTile, x:Int, y:Int)
		mapTile.image.DrawTile(x, y, mapTile.id, 0, 1, 1)
	End
End


very simple test/example added

very simple test/example added

Strict

Import mojo
Import bass

Class MyBassTestApp Extends App
	Field sample%
	Field startStop? = False

	Method OnEnter%()
		BASS_Init(-1, 44100, BASS_DEVICE_LATENCY)

		Local info:BASS_INFO = new BASS_INFO()
		BASS_GetInfo(info)
		Print "BUFFER: " + info.minbuf

		BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 5)
		BASS_SetConfig(BASS_CONFIG_BUFFER, 5 + info.minbuf)

		Print(BASS_GetConfig(BASS_CONFIG_BUFFER))

		sample = BASS_SampleLoad("sfx/Jump 140bpm/6.ogg", 0, 0, 1, BASS_SAMPLE_LOOP)
	End

	Method OnLeave%()
	End

	Method OnUpdate%()
		If TouchHit()
			startStop = Not startStop
			If (startStop)
				BASS_ChannelPlay(BASS_SampleGetChannel(sample, false), true);
			Else
				BASS_ChannelStop(sample);
			End
		End
	End

	Method OnRender%()
	End
End

Function Main:Int()
	Local app := New MyBassTestApp()
    Return 0
End

error: pathspec 'examples/test.monkey' did not match any file(s) known to git


Initial revision of config demo, included with permission from Jonathan Pittock.

--HG--
extra : convert_revision : svn%3Ae934d3cd-0d57-f34a-94d0-9e8d31ae1c29/trunk%4096

Import mojo
Import config

Function Main()
	New App
	Local c1 := LoadConfig("<options><option>one</option><option>two</option><option>three</option></options>")
	Local c2 := LoadConfig("<items><item id=apple x=0 y=0 width=128 height=128 /><item id=orange x=128 y=0 width=128 height=128 /><item id=pear x=256 y=0 width=128 height=128 /></items>")

	'parse c1
	Print "config1:"
	Local nodes := c1.FindNodesByPath("options/option")
	For Local node := Eachin nodes
		Print " -> "+node.GetName()+" = "+node.GetValue()
	Next

	'parse c2
	Print "config2:"
	nodes = c2.FindNodesByPath("items/item")
	For Local node := Eachin nodes
		Print " -> "+node.GetName()+"(x="+node.GetAttribute("x")+" y="+node.GetAttribute("y")+" width="+node.GetAttribute("width")+" height="+node.GetAttribute("height")+" )"
	Next
End

error: pathspec 'examples/Config/configdemo.monkey' did not match any file(s) known to git


Create maniacGraphics.monkey

Create maniacGraphics.monkey

#Rem monkeydoc Module maniac.maniacGraphics
	Graphics Module - Version 0.1.2 (alpha)  ~n
	Copyright (C) 2015  Stephan Duckerschein~n

	Here You can find some "ad-Hoc" Graphic-Elements to use for your App.
	They have to be managed by the Programmer.

	ToDo For v. 0.1.3:
		- Complete Colors: GELB,ORANGE,MAGENTA,BROWN,PURPLE +####
		- Make Primitives rotateable
		- Complete ManiacImage ImageEffects
		~n
	VERSION HISTORY: ~n
	0.1.2~n
		Added: some more Green , Blue & Yellow Colors~n
		Added ManiacImage
	0.1.1~n
		Added Lighning,Maniac_Color~n
		~n

#End

Import mojo
Import maniacLowLevel
Import maniacDebug

#rem
	Included Functions:
		- Drawing outline Rect
		- Drawing an outlining Ellipsis
		- Drawing a Lighning Effect
		- Drawing a Grid
		- Set the Current Color to RenderMode with Maniac_Color using Maniac_Color Convention
		- ManiacImage Class

#end
#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Outlining Rectangle at the Position _X,_Y with the Dimensions _Witdth and _Height with the thickness _Thickness.
	You must call this within the OnRender() Method
#End
Function Drw_Rect:Int(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Thickness:Int=1)
	'Maniac_Debug.addRenderedObject()
	If MANIAC_DEBUG = True
		Maniac_Debug.addTotDraws(4*_Thickness)
	endif
	'Maniac_Debug.
	'Maniac_Debug.
	For Local i:Int = 0 until _Thickness
		'Obere Kante
		DrawLine (_X-i,_Y-i,_X +_Width+i,_Y-i)

		'Untere Kante
		DrawLine (_X-i,_Y+_Height+i,_X+_Width+i,_Y+_Height+i)

		'Linke Seite
		DrawLine (_X-i,_Y-i,_X-i,_Y+_Height+i)

		'Recht Seite
		DrawLine (_X+_Width+i,_Y-i,_X+_Width+i,_Y+_Height+i)
	Next

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a outlining ellipsis at _X,_Y with the Dimensions _Witdth and _Height and the number of cells in x and y direction.
	You must call this within the OnRender() Method
#End
Function Drw_Ellipsis( posx:Float, posy:Float, width:Float, height:Float)

   	Local x:Float
   	Local y:Float
   	Local rx:Float = width / 2
   	Local ry:Float = height / 2

   	Local r:Int = Abs(rx) + Abs(ry)

   	x = 0
   	y = r

   	Local d:Int
   	Local ddf_x:Int
   	Local ddf_y:Int

   	d = 1 - r
   	ddf_x = 3
	ddf_y = -2 * r + 5

   	While y >= x And r
		If MANIAC_DEBUG = True
			Maniac_Debug.addTotDraws(8)
		endif
	    DrawPoint( posx + x * rx/r, posy + y * ry/r )
	    DrawPoint( posx + y * rx/r, posy + x * ry/r )
	    DrawPoint( posx + y * rx/r, posy - x * ry/r )
	    DrawPoint( posx + x * rx/r, posy - y * ry/r )
	    DrawPoint( posx - x * rx/r, posy - y * ry/r )
	    DrawPoint( posx - y * rx/r, posy - x * ry/r )
	    DrawPoint( posx - y * rx/r, posy + x * ry/r )
	    DrawPoint( posx - x * rx/r, posy + y * ry/r )

	    If d < 0
	       d= d + ddf_x
	       ddf_x= ddf_x+ 2
	       ddf_y=ddf_y+ 2
	       x=x + 1
	    Else
	       d= d+ ddf_y
	       ddf_x=ddf_x+ 2
	       ddf_y=ddf_y+ 4
	       x=x+ 1
	       y=y- 1
	    EndIf
	Wend
End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Grid at the Position _X,_Y with the Dimensions _Witdth and _Height and the number of cells in x and y direction
	You must call this within the OnRender() Method
#End
Function Drw_Grid:Void(_X:Float,_Y:Float,_Width:Float,_Height:Float,_CellsX:Int,_CellsY:Int)
	If MANIAC_DEBUG = True
		Maniac_Debug.addTotDraws(2*cntx*cnty)
	endif
	'zeichnet ein Gitter an Position posx,posy (links oben), w/h breite bzw. hÃƒÂ¶he (des gesamten Grids) und zieht dabei cntx/cnty striche in der horizontalen,bzw vertikalen
	'allerdings wird hierbei das Gitter automatisch angepasst

	'1. bestimmen der breite eines KÃƒÂ¤stchens anhand der Breite und der anzahl
	Local cell_w:Float = _Width/_CellsX
	Local cell_h:Float = _Height/_CellsY

	For Local x:Int = 1 To cntx-1
		For Local y:Int = 1 To cnty-1

			'Vertikale
			DrawLine(_X+x*cell_w,_Y,_X+x*cell_w,_Y+cnty*cell_h)

			'Horizontale
			DrawLine(_X,_Y+y*cell_h,_X+cntx*cell_w,_Y+y*cell_h)

		Next
	Next

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a "Star-Bar" @ _X,_Y with the Dimensions _Witdth and _Height and the number of _MaxStars.~n
	_FullStars is the number of Colored Stars from Left
	You must call this within the OnRender() Method
#End
Function Drw_Stars(_X:Float,_Y:Float,_Width:Float,_Height:Float,_MaxStars:Int = 5,_FullStars:Int = 3)
	Local starWidth:Float = ll_Width(_Width,_MaxStars,5)

	For Local i:Int = 0 Until _MaxStars
		If i < _FullStars
			SetColor 255,0,0
		Else
			SetColor 75,75,75
		Endif

		DrawImage MANIAC_IMG_STAR, _X + 5 + i*(starWidth+5), _Y+5, 0 , starWidth/MANIAC_IMG_STAR.Width(),_Height/MANIAC_IMG_STAR.Height()
	Next
End Function

Function Drw_LoadingBar(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Caption:String,_Prozent:Float)
	If _Prozent >= 0.0 And _Prozent <= 1.0
		SetColor 75,75,75
		DrawRect(_X,_Y,_Width*_Prozent,_Height)

		SetColor 255,255,255
		Drw_Rect(_X,_Y,_Width,_Height,2)

		SetColor 255,0,0
		Local l:Int = MANIAC_FONT.getW(( Int(_Prozent*100))+ " %")
		MANIAC_FONT.Wrap((Int(_Prozent*100))+ " %",_X+_Width*0.5-l/2+1,_Y,_Width,_Height,15)
	Endif
End Function

#Rem monkeydoc
	### READY TO USE ###~n
	This Function Draws a Loading-Bar at the Position _X,_Y with the Dimensions _Witdth and _Height
	You must call this within the OnRender() Method
#End
Function Drw_LoadingBar(_X:Float,_Y:Float,_Width:Float,_Height:Float,_Caption:String,_CurrValue:Float,_MaxValue:Float)
	Local pr:Float = _CurrValue/_MaxValue

	SetColor 75,75,75
	DrawRect(_X,_Y,_Width*pr,_Height)

	SetColor 255,255,255
	Drw_Rect(_X,_Y,_Width,_Height,2)

	SetColor 255,0,0
	Local l:Int = MANIAC_FONT.getW(( Int(pr*100))+ " %")
	MANIAC_FONT.Wrap((Int(pr*100))+ " %",_X+_Width*0.5-l/2+1,_Y,_Width,_Height,15)
End Function

#Rem monkeydoc
	This Functions Draws an LoadingBar @ position ix,iy with w,h in Pixels
	istartTime is the Beginning Time, length is the max Time (both in ms)
#End
Function Drw_TimingBar(ix:Int,iy:Int,w:Int,h:Int,istartTime:Int,ilengthTime:Int,iStyle:Int = 0)

	Duke_Drw_Rect(ix,iy,w,h,2)
	Local lw:Int = ( ( Millisecs()-istartTime ) * w ) / ilengthTime
	If iStyle = 0
		DrawRect(ix,iy,w-lw,h)
	Elseif iStyle = 1
		DrawRect(ix,iy,w-lw,h)
	Endif

End Function

#Rem monkeydoc
	### READY TO USE ###~n
	Draw 2d Lightning.
	Pass the starting and ending points.  Depth parameters refers to recursion.  Don't want to blow the stack!

	You must call this within the OnRender() Method
	Example:
	<pre>
		'Within the On Render you jast call the Lightning
		Method OnRender:Int()
			Cls
			Drw_Lightning(0,0,DW*0.5,DH*0.5)
			Return 0
		End
	</pre>

	Credits:
	this Code is from http://www.blitzbasic.com/codearcs/codearcs.php?code=3119
	Matt Lloyd Lightning Implementation.
	and is translated into monkey by Stephan D
	Free To use as you wish. Play around with the parameters.
#End
Function Drw_Lightning(sx#,sy#,fx#,fy#,depth=4)

	'Local dx#,dy#,dist#,ox#,oy#,x#,y#,udx#,udy#
	Local i

	'play around with these numbers to see the effects
	Local shakiness#=-2.5 ;
	Local branchchance=6;
	Local wr1 = 16
	Local wr2 = 16
	Local hr1 = 4
	Local hr2 = 24

	If(depth<=0) Then Return ';;as said - don't want to go too deep in the stack...

	Local dx#=fx-sx
	Local dy#=fy-sy
	Local dist#=Sqrt(dx*dx+dy*dy)

	If(dist=0) Then Return ' ;no need To do any lightning If our start And ending points are on top of each other...And also avoid nasty division by zeroes...

	Local udx#=dx/dist'	;unit vectors in direction of lightning...
	Local udy#=dy/dist

	Local x#=sx
	Local y#=sy
	Local ox#=x
	Local oy#=y

	For i=1 To dist
		If MANIAC_DEBUG = True
			Maniac_Debug.addTotDraws(5)
		endif
		x=x+udx+Rnd(-shakiness,shakiness)
		y=y+udy+Rnd(-shakiness,shakiness)

		ll_ColorCentre()
		DrawLine x,y,ox,oy

		ll_ColorInnerEdge()
		DrawLine x-udy,y+udx, ox-udy,oy+udx
		DrawLine x+udy,y-udx,ox+udy,oy-udx

		ll_ColorOuterEdge()
		DrawLine x-udy*2.0,y+udx*2.0, ox-udy*2.0,oy+udx*2.0
		DrawLine x+udy*2.0,y-udx*2.0,ox+udy*2.0,oy-udx*2.0

		ox=x
		oy=y

		If(Rnd(1,100)<branchchance) Then
			If MANIAC_DEBUG = True
				Maniac_Debug.addTotDraws()
			endif
			Drw_Lightning(ox,oy,ox+Rnd(-wr1,wr2),oy+Rnd(-hr1,hr2),depth-1)
		EndIf

	Next
End Function

Const COLOR_BLACK:Int 		= 	0
Const COLOR_GRAY:Int		=	4
Const COLOR_WHITE:Int		= 	9
Const COLOR_RED:Int			=	10
Const COLOR_GREEN:Int		=	20
Const COLOR_DARKGREEN:Int 	= 	27
Const COLOR_BLUE:Int		= 	30
Const COLOR_YELLOW:Int 		= 	40
Const COLOR_ORANGE:Int 		= 	50
Const COLOR_MAGENTA:Int		= 	60
Const COLOR_BROWN:Int		= 	70
Const COLOR_PURPLE:Int		= 	80

Const COLOR_PLAYER1:Int =  801
Const COLOR_PLAYER2:Int =  802
Const COLOR_PLAYER3:Int	=  803
Const COLOR_PLAYER4:Int =  804

#Rem monkeydoc
	### EXPERIMENTAL ### ~n
	This Function sets the Render-Color to a predefined color by The Maniac-Color-Consts.
	You can find the Colors in the Functions Section.~n
	Details:
	COLOR_BLACK = 0, COLOR_GRAY = 4, COLOR_WHITE = 9
	COLOR_RED = 10 To 19 ; 10 is 255,0,0, the part of Red decreases by higher ID
	So, every COlOR has 10 brightnes grades.
	You can use it like

	Duke_Color2(COLOR_GREEN + brightness), whereas brightness can be an int Value between 0 and 9
	so, COLOR_GREEN + 8 is a very dark green
#End
Function Maniac_Color(_Color:Int)
	'Maniac_Debug.addCall()
	Select _Color
		Case 0	'Schwarz
			SetColor 0,0,0
		Case 1
			SetColor 50,50,50
		Case 2
			SetColor 75,75,75
		Case 3
			SetColor 100,100,100
		Case 4
			SetColor 125,125,125
		Case 5
			SetColor 150,150,150
		Case 6
			SetColor 175,175,175
		Case 7
			SetColor 200,200,200
		Case 8
			SetColor 225,225,225
		Case 9	'Weiss
			SetColor 255,255,255

			'### ROT ### colors 10-19
		Case 10
			SetColor 255,0,0
		Case 11
			SetColor 230,0,0
		Case 12
			SetColor 210,0,0
		Case 13
			SetColor 190,0,0
		Case 14
			SetColor 170,0,0
		Case 14
			SetColor 150,0,0
		Case 15
			SetColor 130,0,0
		Case 16
			SetColor 110,0,0
		Case 17
			SetColor 90,0,0
		Case 18
			SetColor 70,0,0
		Case 19
			SetColor 50,0,0

			'### GRUEN ### 20-29
		Case 20
			SetColor 0,255,0
		Case 21
			SetColor 0,230,0
		Case 22
			SetColor 0,210,0
		Case 23
			SetColor 0,190,0
		Case 24
			SetColor 0,170,0
		Case 25
			SetColor 0,150,0
		Case 26
			SetColor 0,130,0
		Case 27
			SetColor 0,110,0
		Case 28
			SetColor 0,90,0
		Case 29
			SetColor 0,70,0

			'### BLAU ###
		Case 30
			SetColor 0,0,255
		Case 31
			SetColor 0,0,230
		Case 32
			SetColor 0,0,210
		Case 33
			SetColor 0,0,190
		Case 34
			SetColor 0,0,170
		Case 35
			SetColor 0,0,150
		Case 36
			SetColor 0,0,130
		Case 37
			SetColor 0,0,110
		Case 38
			SetColor 0,0,90
		Case 39
			SetColor 0,0,70

			'### GELB ###
		Case 40
			SetColor 255,255,0
		Case 41
			SetColor 255,255,120
		Case 42
			SetColor 255,255,50
		Case 43
			SetColor 215,215,0

		'###	ORANGE ###
		Case 50
			SetColor 255,140,0

		'### MAGENTA ###
		Case 60
			SetColor 255,0,255

		'### BROWN ###
		Case 70
			SetColor 165,42, 42

		'### PURPLE +####
		Case 80
			SetColor 75,0,130

		Case COLOR_PLAYER1
			SetColor 0,0,255

		Case COLOR_PLAYER2
			SetColor 0,255,0

		Case COLOR_PLAYER3
			SetColor 255,0,0

		Case COLOR_PLAYER4
			SetColor 255,255,255

	End Select
End Function

Const IMGEFFECT_MIRRORX:Int = 1
Const IMGEFFECT_MIRRORY:Int = 2

Const IMGEFFECT_ROTATE_SHEARX45:Int = 7

Const IMGANIMAGION_FADE_IN:Int = 3
Const IMGANIMATION_DROP_IN:Int = 4
Const IMGANIMATION_SPIRAL_IN:Int = 5
Const IMGANIMATION_WAVE_IN:Int = 6

Const IMGGLOW_STYLE_SIN:Int 	= 0

Const IMG_ALIGN_LEFT:Int		= 0
Const IMG_ALIGN_MIDDLE:Int		= 1
Const IMG_ALIGN_RIGHT:Int		= 2

Const IMG_ALIGN_ONTOP:Int		= 3
Const IMG_ALIGN_TOP:Int			= 4
Const IMG_ALIGN_BOTTOM:Int		= 5
Const IMG_ALIGN_UNDERBOTTOM:Int	= 6

#Rem monkeydoc
	This is kind of an extended mojo Image.~n
	It provides some additional features.

	-InstantEffects:
		- Glow
		- Shearing,rotation & stuff

	-Complex-Animations

	-MoveAnimation

	BUGLIST:
		The Caption is not rendered correctly with RenderMode - Done
#End
Class ManiacImage
	Field MidX:Float,MidY:Float,Width:Float,Height:Float
	Field Caption:String
	Field CaptionColor:Int		'Color of the Caption
	Field AlignX:Int
	Field AlignY:Int

	Field img:Image
	Field bFramed:Bool = False
	Field bBlink = True
	Field Color:Int = 9
	Field angle:Float =0.0
	Field mode:Int = 0

	'### Glow Effects ###
	Field bGlow:Bool  = False
	Field GlowAlpha:Float
	Field HertzAlpha:Float 		'
	Field AlphaFrom:Float		= 0.2
	Field AlphaTo:Float			= 0.95
	Field GlowStyle:Int		= 0	'0 - If Alpha reases max, it decreases from max ; 1 - if Alpha reaches max, it jumps to min
	Field bAlphaDirection:Bool = True		'if True, Alpha raises, if false, Alpha decreases
	Field HertzIncreaseeAlpha:Float	=0.4
	Field HertzDecreaseAlpha:Float	=1

	Field AddWidthByMO:Int 		= 0
	Field AddHeightByMO:Int		= 0
	Field Scale:Float = 1.0

	#Rem monkeydoc
		Creates a new ManiacImage.
		midX and midy are both the midhandled coordiantes of the image.
		String the is Sourcepath to the Image
		_Caption if wanted is will be shown withing the Image
	#End
	Method New(midx:Float,midy:Float,width:Float,height:Float,Path:String,_Caption:String="",_AlignX:Int = 0,_AlignY:Int = 3,_Hertz:Float = 1.0 )
		img = LoadImage(Path)
		MidX = midx
		MidY = midy
		Width = width
		Height = height
		Caption = _Caption
		CaptionColor = COLOR_BLUE
		AlignX = _AlignX
		AlignY = _AlignY
		HertzAlpha = _Hertz
		mode = 0
	End Method

	Method setCaption:Void(_Caption:String,_AlignX:Int,_AlignY:int)
		Caption = _Caption
	End Method

	Method setMode(_mode:Int)
		mode = _mode
	End Method

	Method getMode:Int()
		Return mode
	End Method

	Method setGlow(_isGlowing:Bool = True)
		bGlow = _isGlowing
	End Method

	Method setCostomMode(shearx:Int,sheary:Int,anglespeed:Float=4.0,scale:Float = 1.0)

	End Method

	Method setFrame(_isFramed:Bool = True,_FrameColor:Int = 0)
		bFramed = _isFramed
		FrameColor = _FrameColor
	End Method

	Method Draw()

		If bGlow = True
			If bAlphaDirection = True
				GlowAlpha += EqToFPS(HertzIncreaseeAlpha)
				If GlowAlpha >= AlphaTo
					If GlowStyle = 0
						bAlphaDirection = False
					Elseif GlowStyle = 1
						bAlphaDirection = True
						GlowAlpha = AlphaFrom
					Endif
				Endif
			Else
				GlowAlpha -= EqToFPS(HertzDecreaseAlpha)
				If GlowAlpha <= AlphaFrom
					If GlowStyle = 0
						bAlphaDirection = true
					Elseif GlowStyle = 1
						bAlphaDirection = false
						GlowAlpha = AlphaTo
					Endif
				Endif
			Endif
		Endif

		'
		'DrawText "mode: " +mode, 300,200
		Select mode
            Case IMGEFFECT_MIRRORX
                MirrorXAt(MidX, MidY)
            Case IMGEFFECT_MIRRORY
                MirrorYAt(MidX, MidY)

            Case 3
                angle += EqToFPS(45)
                ScaleAt(MidX, MidY, 0.6, 0.6)
                ShearXAt(MidX, MidY, Cos(angle))
                ShearYAt(MidX,MidY,	angle)
                RotateAt(MidX, MidY, angle)

            Case 4
                ShearXAt(MidX, MidY, Sin(angle))
            Case 5
                ShearYAt(MidX, MidY, -angle)
            Case 6
                ShearXAt(MidX, MidY, 30)
                ShearYAt(MidX, MidY, 30)

            Case IMGEFFECT_ROTATE_SHEARX45
                'ScaleAt(MidX, MidY, 1, 0.3)
                ShearXAt(MidX, MidY, 45)
                RotateAt(MidX, MidY, angle)
            Case 8
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.3)
                RotateAt(MidX, MidY, -angle)
                ShearXAt(MidX, MidY, 45)
                ShearYAt(MidX, MidY, 45)
                RotateAt(MidX, MidY, angle)
            Case 9
            	angle += EqToFPS(180)
                RotateAt(MidX, MidY, -angle)
                ShearXAt(MidX, MidY, 45)
                ShearYAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 10
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.1)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 11
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.2)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 12
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.4)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 13
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 0.8)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 14
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 1.6)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 15
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 3.2)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 16
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, 6.4)
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 17
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 3, 1)
                ShearYAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, -angle)
            Case 18
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearXAt(MidX, MidY, angle-80)
            Case 19
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearYAt(MidX, MidY, angle-80)
            Case 20
            	angle += EqToFPS(180)
                If angle=160 Then angle = 0
                ShearXAt(MidX, MidY,-angle+80)
                ShearYAt(MidX, MidY, angle-80)
            Case 21
            	angle += EqToFPS(180)
                ScaleAt(MidX, MidY, 1, Sin(angle))
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)
            Case 22
            	angle += ATan(EqToFPS(180))
                ScaleAt(MidX, MidY, 1, Sin(angle))
                ShearXAt(MidX, MidY, -45)
                RotateAt(MidX, MidY, angle)

        End Select

        Maniac_Color(Color)
        '###### GLOW EFFECT STUFF #####
		If bGlow = true
			SetAlpha GlowAlpha
			DrawImage MANIAC_IMG_FRAME_BLUR, MidX,MidY,angle,Width*1.3/MANIAC_IMG_FRAME_BLUR.Width(),Height*1.3/MANIAC_IMG_FRAME_BLUR.Height()
		End If

        DrawImage img,MidX-Width*0.5,MidY-Height*0.5,0,Width/img.Width(),Height/img.Height()

        '###### BUTTON FRAME ########
		If bFramed = True
			'Maniac_Color(FrameColor)
			DrawImage MANIAC_IMG_FRAME_RAW , MidX,MidY,angle,(Width+AddWidthByMO)/MANIAC_IMG_FRAME_RAW.Width(),(Height+AddHeightByMO)/MANIAC_IMG_FRAME_RAW.Height()
		Endif

        '##### DRAWING THE CAPTION TO THE BUTTON #####
		SetAlpha 1
		Maniac_Color(CaptionColor)
		Select AlignX
			Case IMG_ALIGN_LEFT
				MANIAC_FONT.Wrap(Caption,MidX-Width/2,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
			Case IMG_ALIGN_MIDDLE
				Local l:Int = MANIAC_FONT.getW(Caption)
				MANIAC_FONT.Wrap(Caption,MidX-l/2+1,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
			Case IMG_ALIGN_RIGHT
				Local l:Int = MANIAC_FONT.getW(Caption)
				MANIAC_FONT.Wrap(Caption,MidX+Width/2-l,MidY-Height/5,Width,Height,Caption.Length())
				ResetMatrix()
		End Select

        ResetMatrix()

        SetAlpha 1
	End Method

End Class

error: pathspec 'maniac/maniacGraphics.monkey' did not match any file(s) known to git


Framework example

Framework example

--HG--
extra : convert_revision : svn%3Ae934d3cd-0d57-f34a-94d0-9e8d31ae1c29/trunk%4023

Strict

Import mojo
Import diddy

Function Main:Int()
	game = new MyGame()
	Return 0
End Function

Global titleScreen:TitleScreen
Global gameScreen:GameScreen

Class MyGame extends DiddyApp
	Method OnCreate:Int()
		Super.OnCreate()

		titleScreen = New TitleScreen
		gameScreen = new GameScreen
		titleScreen.PreStart()
		return 0
	End Method
End

Class TitleScreen Extends Screen
	Method New()
		name = "Title"
	End

	Method Start:Void()
		game.screenFade.Start(50, false)
	End Method

	Method Render:Void()
		Cls
		DrawText "TITLE SCREEN!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
		DrawText "Press Space to Play!", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 20, 0.5, 0.5
		DrawText "Press Escape to Quit!", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 40, 0.5, 0.5
	End

	Method Update:Void()
		If KeyHit(KEY_SPACE)
			game.screenFade.Start(50, true)
			game.nextScreen = gameScreen
		End

		If KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, true)
			game.nextScreen = game.exitScreen
		End
	End
End

Class GameScreen Extends Screen
	Method New()
		name = "Game"
	End

	Method Start:Void()
		game.screenFade.Start(50, false)
	End Method

	Method Render:Void()
		Cls
		DrawText "GAME SCREEN!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
	End

	Method Update:Void()
		If KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, true)
			game.nextScreen = titleScreen
		End
	End
End

error: pathspec 'examples/testFramework.monkey' did not match any file(s) known to git


Changed structure to allow expansion

Changed structure to allow expansion

--HG--
extra : convert_revision : svn%3Ae934d3cd-0d57-f34a-94d0-9e8d31ae1c29/trunk%4017

Import "native/diddy.${TARGET}.${LANG}"

Extern

	#If LANG="cpp" Then
		Function RealMillisecs:Int() = "diddy::systemMillisecs"
		Function FlushKeys:Void() = "diddy::flushKeys"
		Function HideMouse:Void() = "diddy::hideMouse"
		Function ShowMouse:Void() = "diddy::showMouse"
	#Else
		Function RealMillisecs:Int() = "diddy.systemMillisecs"
		Function FlushKeys:Void() = "diddy.flushKeys"
		Function HideMouse:Void() = "diddy.hideMouse"
		Function ShowMouse:Void() = "diddy.showMouse"
	#End

Public

Function ExitApp:Void()
	Error ""
End

error: pathspec 'src/diddy/functions.monkey' did not match any file(s) known to git


XML examples.

XML examples.

Strict

Import diddy.xml

Function Main:Int()
	Local parser:XMLParser = New XMLParser
	Local doc:XMLDocument = parser.ParseString(LoadString("server.xml"))
	'Local doc:XMLDocument = parser.ParseString("<?xml version=~q1.0~q encoding=~qUTF-8~q?><Server port=~q8005~q shutdown=~qSHUTD&<OWN~q>  <Listener className=~qorg.apache.catalina.core.AprLifecycleListener~q/>  <Listener className=~qorg.apache.catalina.mbeans.ServerLifecycleListener~q/>  <Listener className=~qorg.apache.catalina.mbeans.GlobalResourcesLifecycleListener~q/>  <Listener className=~qorg.apache.catalina.storeconfig.StoreConfigLifecycleListener~q/>  <GlobalNamingResources>    <Environment name=~qsimpleValue~q type=~qjava.lang.Integer~q value=~q30~q/>    <Resource auth=~qContainer~q driverClassName=~qoracle.jdbc.OracleDriver~q maxActive=~q20~q maxIdle=~q10~q maxWait=~q-1~q name=~qjdbc/tmsicsd~q password=~qpndev~q type=~qjavax.sql.DataSource~q url=~qjdbc:oracle:thin:@//pnlvsun30:9086/TMSV10D~q username=~qtms_own~q/>    <Resource auth=~qContainer~q driverClassName=~qoracle.jdbc.OracleDriver~q maxActive=~q20~q maxIdle=~q10~q maxWait=~q-1~q name=~qjdbc/tmsicss~q password=~qTMSS1TS~q type=~qjavax.sql.DataSource~q url=~qjdbc:oracle:thin:@//pnlvsun30:9186/TMSV10S~q username=~qTMS_OWN~q/>  </GlobalNamingResources>  <Service name=~qCatalina~q>    <Connector acceptCount=~q100~q connectionTimeout=~q20000~q disableUploadTimeout=~qtrue~q enableLookups=~qfalse~q maxHttpHeaderSize=~q8192~q maxSpareThreads=~q75~q maxThreads=~q150~q minSpareThreads=~q25~q port=~q8080~q redirectPort=~q8443~q/>    <Connector enableLookups=~qfalse~q port=~q8009~q protocol=~qAJP/1.3~q redirectPort=~q8443~q/>    <Engine defaultHost=~qlocalhost~q name=~qCatalina~q>      <Host appBase=~qwebapps~q autoDeploy=~qtrue~q name=~qlocalhost~q unpackWARs=~qtrue~q xmlNamespaceAware=~qfalse~q xmlValidation=~qfalse~q>        <Context docBase=~qFreightWeb~q path=~q/FreightWeb~q reloadable=~qtrue~q source=~qorg.eclipse.jst.j2ee.server:FreightWeb~q>          <!--<ResourceLink global=~qjdbc/tmsicsd~q name=~qjdbc/pnonline~q type=~qjavax.sql.DataSource~q/>-->          <ResourceLink global=~qjdbc/tmsicsd~q name=~qjdbc/pnonline~q type=~qoracle.jdbc.pool.OracleDataSource~q/>          <!-- <ResourceLink global=~qjdbc/tmsicss~q name=~qjdbc/pnonline~q type=~qjavax.sql.DataSource~q/> -->        </Context>      <Context docBase=~qPNOnline~q path=~q/PNOnline~q reloadable=~qtrue~q source=~qorg.eclipse.jst.j2ee.server:PNOnline~q/></Host>    </Engine>  </Service></Server>")
	Print doc.root.GetAttribute("shutdown")
	Print doc.root.Children.Get(0).Parent.Name
	Print doc.ExportString()
#Rem
	Local doc:XMLDocument = New XMLDocument
	doc.root = New XMLElement
	doc.root.name = "root"

	Local child1 := New XMLElement
	child1.name = "mychild"
	child1.SetAttribute("foo", "bar")
	child1.SetAttribute("hello", "world")
	doc.root.AddChild(child1)

	Local child2 := New XMLElement
	child2.name = "mychild"
	child2.SetAttribute("david", "jones")
	child2.SetAttribute("harvey", "norman")
	doc.root.AddChild(child2)

	Print(doc.ExportString())
	Print(doc.ExportString(False))
	Return 0
#End
End

error: pathspec 'examples/XML/testXML.monkey' did not match any file(s) known to git


added sample file

added sample file

Strict

#rem
this is a
#rem
nested
#end
comment
even other preproc keywords are nested within!
#If TARGET
#End
#end

Import mojo

Const ONECONST:Int = 1
Const TWOCONST := 2
Const THREECONST := 3, FOURCONST:Int = 4

Class Game Extends App

    ' radial sprial with axis aligned phase

    Function DrawSpiral(clock)
        Local w=DeviceWidth/2
        For Local i#=0 Until w*1.5 Step .2
            Local x#,y#
            x=w+i*Sin(i*3+clock)
            y=w+i*Cos(i*2+clock)
            DrawRect  x,y,1,1
        Next
        hitbox.Collide(event.pos)
    End

    Field updateCount

    Method OnCreate()
        Print "spiral"

        SetUpdateRate 60
    End

    Method OnUpdate()
        updateCount+=1
    End

    Method OnRender()
        Cls
        DrawSpiral updateCount
        DrawSpiral updateCount*1.1
    End

End

Class VectorNode Extends Node<Vector2D>
End

Function Main()
    New Game()
End

error: pathspec 'tests/examplefiles/example.monkey' did not match any file(s) known to git


added sample file

added sample file