Portabl E's standard functionality
by Chris Handley Last updated 07.11.2022.
All the functionality listed here is intended to be completely portable (i.e. OS independant). However, some of the MODULEs may not be implemented yet for all supported OSes (typically Linux & Windows), so they list which OSes are supported.
If you are not sure which modules to use, then please be sure to read chapter 8. What do the different MODULEs do?.
NOTE 1: While methods are shown in the form METHOD method(), this is not valid syntax for Portabl E code (although that might change!).
NOTE 2: If you see OWNS as part of a variable's type, you can safely ignore it, because that is what Portabl E currently does! However, it is a hint that ownership (i.e. deallocation responsibility) is being handed over. Thus an OWNS parameter shows that the procedure takes ownership, while an OWNS return value shows that the procedure passes ownership to the caller.
This is a list of all the kinds of values that can be used:
These are documented in the original AmigaE manual:
This is a list of all expressions that can be used:
storage := expr ++ storage -- storage storage ++ storage --
array[expr] - expr ( expr )
expr !! type expr AND expr expr OR expr expr XOR expr expr SHL expr expr SHR expr expr BUT expr expr = expr expr >= expr expr > expr expr <= expr expr <> expr expr < expr expr + expr expr - expr expr * expr expr / expr
procedure(...) SUPER procedure(...) CALLBACK procedure()
NEW storage NEW object.method(...) object::objectType object.member object.method(...) SUPER self.method(...)
IF expr THEN expr ELSE expr NOT expr SIZEOF type TYPEOF objectType ADDRESSOF variable NATIVE {native group} ... ENDNATIVE EMPTY
Most of these expressions are documented in the original AmigaE manual:
But when reading that manual, please beware that:
Note that:
This is a list of all statements that can be used (inside of a procedure). The full version of each statement is given, with optional parts enclosed in [square brackets]. Note that [...] is used to indicate that the previous optional part may be repeated further.
expr statement ; statement IF expr THEN statement [ELSE statement] IF expr statements [ELSE IF expr statements] [ELSE IF expr statements] [...] [ELSE statements] ENDIF END storage [,storage] [,storage] [...] RETURN [ expr [,expr] [,expr] [...] ] FOR storage := expr TO expr [STEP expr] DO statement FOR storage := expr TO expr [STEP expr] statements ENDFOR [IF expr] LOOP statements ENDLOOP REPEAT statements UNTIL expr WHILE expr DO statement WHILE expr statements ENDWHILE [IF expr] SELECT expr [CASE expr ; statements] [CASE expr ; statements] [...] [DEFAULT ; statement] ENDSELECT SELECT constant OF expr [CASE constant [TO constant] [, constant] [...] ; statements] [CASE constant [TO constant] [, constant] [...] ; statements] [...] [DEFAULT ; statements] ENDSELECT
Most of these statements are documented in the original AmigaE manual:
This is a list of all the declarations & definitions which can be used (outside of a procedure). Note that [...] is used to indicate that the previous optional part may be repeated further, while [xxx ...] indicates that something comes after xxx but for brevity it is not shown. The | character is used to separate several possible options.
OPT option[=value] [, option[=value]] [...]
MODULE 'name' [, 'name'] [...]
RAISE quadcharacter IF procedure() comparison expression [, ...]
RAISE quadcharacter IF class.method() comparison expression [, ...]
CONST constant = expr [, constant = expr] [...]
ENUM constant [= expr] [, constant [= expr]] [...]
SET constant [, constant] [...]
TYPE type IS type
OBJECT object [OF object]
[PRIVATE|PROTECTED|PUBLIC|member[:type]] [, ...] [...] ENDOBJECT
CLASS object [[UNGENERIC] [ORPHAN] OF object [IMPLEMENTS object]]
[PRIVATE|PROTECTED|PUBLIC|member[:type]] [, ...] [...] ENDCLASS
STATIC variable IS [list|'immediate string']
DEF variable[:type] [, variable[:type]] [...]
PROC procedure(...) [[NEW] OF class [ORPHAN]] [RETURNS ...] [PROTOTYPE|REPLACEMENT] [IS ...]
[DEF ...] statements [FINALLY statements] ENDPROC [expr [, expr] [...]]
FUNC function(...) [OF function] [IS ...]
[DEF ...] statements [FINALLY statements] ENDPROC [expr [, expr] [...]]
Most of these statements are documented in the original AmigaE manual:
But when reading that manual, please beware that:
Note that:
This is a list of all procedures that are built-in to Portabl E.
PROC Print( fmtString:ARRAY OF CHAR, arg=0, ...) PROC PrintL(fmtString:ARRAY OF CHAR, args=NILL:ILIST) PROC PrintFlush()
Print() outputs the formatted string fmtString to stdout, with any additional arguments being used by the relevant soft escape codes (such as '\d'). Output may be buffered, and so may not appear immediately, especially if it does not end in a new line. Note that the "..." means it supports an unlimited number of parameters.
PrintL() is the same as Print(), except that it takes it's optional arguments as an ILIST. Can currently handle up to 20 optional items.
PrintFlush() flushes the output buffer, so everything that was Print()ed is shown.
PROC ReopenStdOut(fileName:ARRAY OF CHAR) PROC ReopenStdIn( fileName:ARRAY OF CHAR) PROC SetStdOut(fileHandle:PTR) RETURNS oldstdout:PTR ->depreciated PROC SetStdIn( fileHandle:PTR) RETURNS oldstdin :PTR ->depreciated PROC Out(fileHandle:PTR, char:CHAR) RETURNS value PROC Inp(fileHandle:PTR) RETURNS char:INT PROC OpenInOut(fileName:ARRAY OF CHAR) RETURNS fileHandle:PTR PROC CloseInOut(fileHandle:PTR)
ReopenStdOut() & ReopenStdIn() change the stdout & stdin streams (used by Print()/etc) to the given fileName. Note that on most targets the values of stdout & stdin won't change, but this is not guaranteed.
SetStdOut() & SetStdIn() change the stdout & stdin streams (used by Print()/etc) to the given fileHandle. Depreciated in favour of ReopenStdOut() & ReopenStdIn(). Note that SetStdIn() & SetStdOut() don't work on AROS anymore.
Out() writes the supplied character char to the file handle, returning the number of characters actually written - so anything other than 1 is an error. You would typically use the stdout file handle.
Inp() reads & returns one character from the supplied file handle. An error is indicated by returning -1. You would typically use the stdin file handle.
OpenInOut() returns a fileHandle for the given file, which can be used with SetStdOut()/etc.
CloseInOut() closes the fileHandle, so that it can't be used anymore.
PROC StrCmp( first:ARRAY OF CHAR, second:ARRAY OF CHAR, len=ALL, firstOffset=0, secondOffset=0) RETURNS match:BOOL PROC StrCmpNoCase(first:ARRAY OF CHAR, second:ARRAY OF CHAR, len=ALL, firstOffset=0, secondOffset=0) RETURNS match:BOOL PROC StrLen(string:ARRAY OF CHAR) RETURNS length PROC Val(string:ARRAY OF CHAR, addrRead=NILA:ARRAY OF LONG, startPos=0) RETURNS value, read ->addrRead is depreciated PROC InStr( haystack:ARRAY OF CHAR, needle:ARRAY OF CHAR, startPos=0) RETURNS matchPos PROC InStrNoCase(haystack:ARRAY OF CHAR, needle:ARRAY OF CHAR, startPos=0) RETURNS matchPos PROC TrimStr( string:ARRAY OF CHAR) RETURNS string:ARRAY OF CHAR PROC UpperStr(string:ARRAY OF CHAR) RETURNS string:ARRAY OF CHAR PROC LowerStr(string:ARRAY OF CHAR) RETURNS string:ARRAY OF CHAR PROC AstrCopy(destination:ARRAY, source:ARRAY OF CHAR, destSize) PROC OstrCmp( string1:ARRAY OF CHAR, string2:ARRAY OF CHAR, max=ALL, string1Offset=0, string2Offset=0) RETURNS sign:RANGE -1 TO 1 PROC OstrCmpNoCase(string1:ARRAY OF CHAR, string2:ARRAY OF CHAR, max=ALL, string1Offset=0, string2Offset=0) RETURNS sign:RANGE -1 TO 1 PROC QuadToStr(value:QUAD) RETURNS string:ARRAY OF CHAR
StrCmp() compares the first string against the second, and returns TRUE if they matched. len gives how many characters to compare (from the beginning), with the special ALL constant meaning compare everything. firstOffset & secondOffset allow you to specify an offset into the first & second strings respectively (to avoid pointer arithmetic).
StrCmpNoCase() is a case-insensitive version of StrCmp(). This procedure was not present in AmigaE.
StrLen() returns the length of the supplied zero-terminated string. It can be slow for very large strings.
Val() parses the supplied string, optionally starting from a startPos position other than 0, and returns the value of the integer number. Leading spaces & tabs are skipped. Hexadecimal & binary numbers are accepted if they are preceeded by $ or % respectively. A - minus sign will make the number negative. read is used to return the number of characters read, but will be 0 to indicate an error if no number could be parsed. addrRead is depreciated, but if it is supplied then the number of characters read is also written to the first item of that array.
InStr() searches the haystack string for an occurance of needle, optionally starting from a startPos position other than 0. It returns the position/offset at which needle was found, or -1 if there was no match.
InStrNoCase() is a case-insensitive version of InStr(). This procedure was not present in AmigaE.
TrimStr() returns a string pointing to the first non-empty character (not a tab, space, linefeed, etc) in the supplied string.
UpperStr() modifies the supplied string to be all uppercase. It returns the supplied string for convenience.
LowerStr() modifies the supplied string to be all lowercase. It returns the supplied string for convenience.
AstrCopy() stands for "Array STRing COPY", and copies the contents of the source string into the destination string, ensuring that the destination is always zero-terminated. destSize gives the maximum number of characters that destination can hold.
OstrCmp() performs an ordered string comparison between string1 & string2. Conceptually you can think of it as returning the Sign() of "string2 - string1". Thus it returns 0 if they are identical, 1 if string2 > string1, and -1 if string2 < string1. max gives how many characters to compare (from the beginning), with the special ALL constant meaning compare everything. string1Offset & string2Offset allow you to specify an offset into string1 & string2 respectively (to avoid pointer arithmetic).
OstrCmpNoCase() is a case-insensitive version of OstrCmp(). This procedure was not present in AmigaE.
QuadToStr() converts a QUAD value into a string, for easy Print()ing. Very useful for printing exception. Beware that it returns the same string each time (but modified to match the QUAD value), so you should copy it if you need to call QuadToStr() again before using the first returned string.
PROC And(a, b) RETURNS value ->depreciated, instead use AND PROC Or(a, b) RETURNS value ->depreciated, instead use OR PROC Xor(a, b) RETURNS value ->depreciated, instead use XOR PROC Shl(a, b) RETURNS value PROC Shr(a, b) RETURNS value PROC Not(a) RETURNS value ->depreciated, instead use NOT
And() returns a bit-wise And of the supplied values. Depreciated in favour of AND.
Or() returns a bit-wise Or of the supplied values. Depreciated in favour of OR.
Xor() returns a bit-wise Exclusive-Or of the supplied values. Depreciated in favour of XOR.
Shl() returns a arithmetically shifted left by b bits. Unlike SHL it accepts negative values for b.
Shr() returns a arithmetically shifted right by b bits. Unlike SHR it accepts negative values for b.
Not(a) returns a bit-wise inversion of the supplied value. Depreciated in favour of NOT.
PROC Mul(a, b) RETURNS value ->depreciated, instead use * PROC Div(a, b) RETURNS value ->depreciated, instead use / PROC Min(a, b) RETURNS value PROC Max(a, b) RETURNS value PROC Odd(a) RETURNS boolean:BOOL PROC Even(a) RETURNS boolean:BOOL PROC Rnd(max) RETURNS num PROC RndQ(seed) RETURNS num PROC Abs(a) RETURNS value PROC Sign(a) RETURNS value:RANGE -1 TO 1 PROC Bounds(num, min, max) RETURNS value PROC FastMod(a, b) RETURNS c PROC Mod(a, b) RETURNS c, d PROC Pow(a, b) RETURNS value
Mul() returns a multiplied by b. Depreciated in favour of *.
Div() returns a divided by b. Depreciated in favour of /.
Min() returns the smaller of the two supplied values.
Max() returns the larger of the two supplied values.
Odd() returns TRUE if the supplied value is odd (not wholly divisible by 2).
Even() returns TRUE if the supplied value is even (wholly divisible by 2).
Rnd() returns a pseudo-random number in the range 0 to max-1. To initialise the internal seed, call Rnd() with a negative number. The returned value may be limited to the range of LONG.
RndQ() returns a pseudo-random number quicker than Rnd() does, but the value covers the range of a whole VALUE (although it may be limited to the range of LONG for some targets). The returned value should be used as the value of seed in the next call.
Abs() returns the absolute (positive) version of the supplied value.
Sign() returns -1 if the supplied value is negative, +1 if it is positive, and 0 if it is 0.
Bounds() returns the number num bounded by the range min to max. It is equivalent to:
IF num < min THEN min ELSE IF num > max THEN max ELSE num
FastMod() divides a by b, returning ONLY the remainder c. It is roughly twice as fast as Mod().
Mod() divides a by b, returning the remainder c & the division result d. Mathematically c is equivalent to "a modulo b", while d is "a / b".
Pow() returns a raised to the power b. This procedure was not present in AmigaE.
PROC BigMax(a:BIGVALUE, b:BIGVALUE) RETURNS c:BIGVALUE PROC BigMin(a:BIGVALUE, b:BIGVALUE) RETURNS c:BIGVALUE PROC BigFastMod(a:BIGVALUE, b) RETURNS c
BigMax(), BigMin() & BigFastMod() perform BIGVALUE equivalents of Max(), Min() & FastMod().
PROC Fsin(a:FLOAT) RETURNS float:FLOAT PROC Fcos(a:FLOAT) RETURNS float:FLOAT PROC Ftan(a:FLOAT) RETURNS float:FLOAT PROC Fasin(a:FLOAT) RETURNS float:FLOAT PROC Facos(a:FLOAT) RETURNS float:FLOAT PROC Fatan(a:FLOAT) RETURNS float:FLOAT PROC Fsinh(a:FLOAT) RETURNS float:FLOAT PROC Fcosh(a:FLOAT) RETURNS float:FLOAT PROC Ftanh(a:FLOAT) RETURNS float:FLOAT PROC Fabs( a:FLOAT) RETURNS float:FLOAT PROC Ffloor(a:FLOAT) RETURNS float:FLOAT PROC Fceil( a:FLOAT) RETURNS float:FLOAT PROC Fexp( a:FLOAT) RETURNS float:FLOAT PROC Flog( a:FLOAT) RETURNS float:FLOAT PROC Flog10(a:FLOAT) RETURNS float:FLOAT PROC Fsqrt( a:FLOAT) RETURNS float:FLOAT PROC Fpow( a:FLOAT, b:FLOAT) RETURNS float:FLOAT PROC RealVal(string:ARRAY OF CHAR) RETURNS value:FLOAT, read
Fsin(), Fcos() & Ftan() perform floating-point Sine, Cosine & Tangent in radians.
Fasin(), Facos() & Fatan() perform floating-point Arc Sine, Arc Cosine & Arc Tangent in radians.
Fsinh(), Fcosh() & Ftanh() perform floating-point Hyperbolic Sine, Hyperbolic Cosine & Hyperbolic Tangent in radians.
Fabs() performs a floating-point version of Abs()
Ffloor() & Fceil() calculate the lowest & highest whole-number float of the supplied value.
Fexp() calculates e raised to the supplied power.
Flog() calculates the natural log of the supplied value.
Flog10() calculates the log base 10 of the supplied value.
Fsqrt() calculates the square root of the supplied value.
Fpow() performs a floating-point version of Pow(). Please be warned that the order of the parameters is the opposite of that in AmigaE.
RealVal() performs a floating-point version of Val().
PROC Raise(e:QUAD) ->depreciated, instead use Throw() PROC Throw(e:QUAD, i=NILA:ARRAY OF CHAR) PROC ReThrow() PROC PrintException()
Raise() throws exception e, with exceptionInfo set to NILA. This is depreciated in favour of Throw().
Throw() throws exception e, with exceptionInfo set to i.
ReThrow() throws the last exception again, if the global exception is not 0, otherwise it does nothing. Hardly needed since Portabl E automatically does this at the end of every FINALLY section.
PrintException() is an easy way of reporting an exception. If there was no exception then it will do nothing. If you want to customise the output, then you can easily write your own version using Print() & QuadToStr()!
PROC New( size, noClear=FALSE:BOOL) RETURNS mem:ARRAY PROC NewR(size, noClear=FALSE:BOOL) RETURNS mem:ARRAY PROC Dispose(mem:ARRAY) RETURNS NILA
New() allocates & returns a memory block of size bytes. Normally the memory is cleared (zeroed), but if noClear is TRUE then it isn't. If allocation fails then it returns NILA. Note that memory is automatically deallocated at the end of the program.
NewR() is the same as New(), except that if allocation fails it raises the MEM exception.
Dispose() deallocates the provided memory block, which must have been allocated with New() or NewR(). It allows mem to be NILA. It returns NILA for convenience.
PROC FastNew(size, noClear=FALSE:BOOL) RETURNS mem:ARRAY PROC FastDispose(mem:ARRAY, size) RETURNS NILA PROC MemCopy(target:ARRAY, source:ARRAY, sizeInBytes, targetOffsetInBytes=0, sourceOffsetInBytes=0) RETURNS target:ARRAY
FastNew() is like NewR(), except that it is super-fast & does not significantly fragment memory. It does this using an enhanced TLSF algorithm, which allocates memory in larger blocks. On more modern OSes this is unnecessary, and so it simply calls NewR() in thoses cases.
FastDispose() is the Dispose() equivalent for FastNew(), but it needs to know the size of the block being deallocated. Unlike AmigaE, memory is returned to the OS, although only if everything in the "larger block" has been deallocated (otherwise the memory is recycled for the next FastNew() call).
MemCopy() copies sizeInBytes bytes from the source memory block into the target. targetOffsetInBytes & sourceOffsetInBytes allow you to specify an offset into the target & source memory respectively (to avoid pointer arithmetic). It returns the target array for convenience. This procedure was not present in AmigaE, but it provides a portable alternative to the Amiga's CopyMem().
PROC NewArray(sizeInItems, itemSizeInBytes:INT) RETURNS mem:PTR PROC DisposeArray(array:ARRAY) RETURNS NILA PROC ArrayCopy(target:PTR, source:ARRAY, sizeInItems, itemSizeInBytes:INT) RETURNS target:ARRAY
NewArray() allocates & returns an array of sizeInItems items, which are itemSizeInBytes bytes per item. Although it should return an ARRAY, it currently returns a PTR to force you to use OPT POINTER (since it may not be implementable for Java-like languages).
DisposeArray() deallocates the provided array, which must have been allocated with NewArray(). It returns NILA for convenience.
ArrayCopy() copies sizeInItems items, which are itemSizeInBytes bytes per item, from the source array into the target array. It returns the target array for convenience. Although target should be an ARRAY, it is currently a PTR to force you to use OPT POINTER (since it may not be implementable for Java-like languages). Therefore you must cast target to a plain ARRAY type, using !!ARRAY , for it to compile.
PROC NewList(maxLen) RETURNS list:LIST PROC DisposeList(list:LIST) RETURNS NILL PROC ListCopy(list: LIST, other:ILIST, len=ALL) RETURNS list:LIST PROC ListAdd( list: LIST, other:ILIST, len=ALL) RETURNS list:LIST PROC ListMax( list: LIST) RETURNS max:VALUE PROC SetList( list: LIST, newLen) PROC ListLen( list:ILIST) RETURNS len:VALUE PROC ListCmp( list:ILIST, other:ILIST, len=ALL) RETURNS match:BOOL PROC ListItem(list:ILIST, index) RETURNS value
NewList() allocates & returns an e-list of maxLen items.
DisposeList() deallocates the provided e-list. It returns NILL for convenience.
ListCopy() replaces the contents of the list with that from the other list. len gives how many items to copy (from the beginning), with the special ALL constant meaning copy everything. It returns the list for convenience.
ListAdd() is similar to ListCopy(), except that the items are appended to the list.
ListMax() returns the maximum allowed length of the list.
SetList() changes the current length of the list to newLen items.
ListLen() returns the current length of the list.
ListCmp() compares the list against the other list, and returns TRUE if they match. len gives how many items to compare (from the beginning), with the special ALL constant meaning compare everything.
ListItem() returns item index from the list.
PROC NewString(maxLen) RETURNS eString:STRING PROC DisposeString(eString:STRING) RETURNS NILS PROC StrCopy( eString:STRING, string:ARRAY OF CHAR, len=ALL, pos=0) RETURNS eString:STRING PROC StrAdd( eString:STRING, string:ARRAY OF CHAR, len=ALL, pos=0) RETURNS eString:STRING PROC StrJoin(s1=NILA:ARRAY OF CHAR, ..., s19=NILA:ARRAY OF CHAR) RETURNS newString:STRING PROC EstrLen( eString:STRING) RETURNS len:VALUE PROC StrMax( eString:STRING) RETURNS max:VALUE PROC RightStr(eString:STRING, eString2:STRING, n) RETURNS eString:STRING PROC MidStr( eString:STRING, string:ARRAY OF CHAR, pos, len=ALL) RETURNS eString:STRING PROC SetStr( eString:STRING, newLen) PROC StringF( eString:STRING, fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) RETURNS eString:STRING, len PROC StringFL(eString:STRING, fmtString:ARRAY OF CHAR, args=NILL:ILIST) RETURNS eString:STRING, len PROC RealF( eString:STRING, value:FLOAT, decimalPlaces=8) RETURNS eString:STRING PROC ReadStr(fileHandle:PTR, eString:STRING) RETURNS fail:BOOL PROC Link( complex:STRING, tail:OWNS STRING) RETURNS complex:STRING PROC Next( complex:STRING) RETURNS tail:STRING PROC Forward( complex:STRING, num) RETURNS tail:STRING
NewString() allocates & returns an e-string of maxLen items.
DisposeString() deallocates the provided e-string. It returns NILS for convenience.
StrCopy() replaces the contents of the eString with that from the string. len gives how many characters to copy (from the beginning), with the special ALL constant meaning copy everything. pos gives the position of the first character to copy. It returns the eString for convenience.
StrAdd() is similar to StrCopy(), except that the items are appended to the eString.
StrJoin() returns a new e-string which contains all of the supplied strings appended together. If any supplied string is NILA, then it will simply be ignored. This procedure was not present in AmigaE.
EstrLen() returns the current length of the eString. This is much faster than StrLen().
StrMax() returns the maximum allowed length of the eString.
RightStr() fills the eString with the last n characters of eString2. It returns the eString for convenience.
MidStr() replaces the contents of the eString with the given range from the string. pos gives the start position in string (with 0 being the beginning), while len gives how many characters to copy (from the start position), with the special ALL constant meaning copy everything. It returns the eString for convenience.
SetStr() changes the current length of the eString to newLen characters.
StringF() is similar to Print(), except that output now goes to the eString instead of stdout.
StringFL() is the same as StringF(), except that it takes it's optional arguments as an ILIST. Can currently handle up to 20 optional items.
RealF() writes the float value into the eString as an ASCII representation, with decimalPlaces digits after the decimal point. It returns the eString for convenience.
NOTE: The name of this procedure isn't strictly correct, so it may eventually be changed.
ReadStr() reads a string (ending in ASCII 10) from the fileHandle into the eString. It returns TRUE if an error occured, or an EOF was reached. The only file handle you are likely to use is stdin.
Link() puts the tail e-string into the next field of the complex e-string. It returns the complex e-string for convenience. Note that the complex e-string now owns the tail e-string, and will deallocate it when it is deallocated.
Next() returns the next field of the complex e-string. Next(NILS) safely returns NILS.
Forward() is similar to Next(), except that it goes forward num links instead of 1. You may safely call Forward() with a num that is too large.
PROC CharToUnsigned(char:CHAR) RETURNS value PROC UnsignedToChar(value) RETURNS char:CHAR
CharToUnsigned() & UnsignedToChar() allow you to convert a CHAR to an unsigned value (typically between 0 & 255) & back again. You need this when comparing a CHAR with an integer value, because CHAR has unknown signedness in Portabl E.
PROC BigEndianINT( in:INT ) RETURNS out:INT PROC BigEndianLONG(in:LONG) RETURNS out:LONG PROC BigEndianBIGVALUE(in:BIGVALUE) RETURNS out:BIGVALUE
BigEndianINT(), BigEndianLONG() & BigEndianBIGVALUE() return a value with swapped endianness, when used on a Little Endian processor (like x86), while they do nothing to the value when used on a Big Endian processor (like 68k or PPC). They should be used when reading or writing a value that is stored in Big Endian format.
You are encouraged to use Big Endian format for storing values, partly because they are easily read using a hex editor (since the largest digits are on the left), and partly because this format takes less effort on Big Endian processors (which tend to be less powerful).
Note that these BigEndian...() functions are the equivalent of the depreciated EndianSwap...() functions (which are currently still provided).
PROC LittleEndianINT( in:INT ) RETURNS out:INT PROC LittleEndianLONG(in:LONG) RETURNS out:LONG PROC LittleEndianBIGVALUE(in:BIGVALUE) RETURNS out:BIGVALUE
LittleEndianINT(), LittleEndianLONG() & LittleEndianBIGVALUE() return a value with swapped endianness, when used on a Big Endian processor (like 68k or PPC), while they do nothing to the value when used on a Little Endian processor (like x86). They should be used when reading or writing a value that is stored in Little Endian format.
PROC SwapEndianINT( in:INT ) RETURNS out:INT PROC SwapEndianLONG(in:LONG) RETURNS out:LONG PROC SwapEndianBIGVALUE(in:BIGVALUE) RETURNS out:BIGVALUE
SwapEndianINT(), SwapEndianLONG() & SwapEndianBIGVALUE() always return a value with swapped endianness, whatever processor is used. These functions should not normally be needed, but are provided for completeness.
PROC IsBigEndian() RETURNS isBigEndian:BOOL PROC IsLittleEndian() RETURNS isLittleEndian:BOOL
IsBigEndian() & IsLittleEndian() return TRUE or FALSE to indicate whether it is being used on a Little Endian or Big Endian processor. (Might be useful to avoid processing all items of an array with BigEndian...() or LittleEndian...(), when they will do nothing for the current processor type. Or possibly to use SwapEndian...() only when needed.)
PROC HaveSameClassTypes(first:CLASSTYPE, second:CLASSTYPE) RETURNS same:BOOL
HaveSameClassTypes() compares the first class type against the second, and returns TRUE if they were the same. For more information please see the "Run Time Type Information (RTTI)" subchapter of the "Object orientation" chapter in Portabl E's main manual.
PROC GetBool( ptr:PTR TO BOOL ) RETURNS value:BOOL PROC GetByte( ptr:PTR TO BYTE ) RETURNS value:BYTE PROC GetChar( ptr:PTR TO CHAR ) RETURNS value:CHAR PROC GetInt( ptr:PTR TO INT ) RETURNS value:INT PROC GetLong( ptr:PTR TO LONG ) RETURNS value:LONG PROC GetQuad( ptr:PTR TO QUAD ) RETURNS value:QUAD PROC GetFloat(ptr:PTR TO FLOAT) RETURNS value:FLOAT PROC GetPtr( ptr:PTR TO PTR ) RETURNS value:PTR PROC GetArray(ptr:PTR TO ARRAY) RETURNS value:ARRAY PROC GetValue(ptr:PTR TO VALUE) RETURNS value:VALUE
These procedures peek the given ptr address, and return a value of the requested type.
PROC PutBool( ptr:PTR TO BOOL , value:BOOL ) PROC PutByte( ptr:PTR TO BYTE , value:BYTE ) PROC PutChar( ptr:PTR TO CHAR , value:CHAR ) PROC PutInt( ptr:PTR TO INT , value:INT ) PROC PutLong( ptr:PTR TO LONG , value:LONG ) PROC PutQuad( ptr:PTR TO QUAD , value:QUAD ) PROC PutFloat(ptr:PTR TO FLOAT, value:FLOAT) PROC PutPtr( ptr:PTR TO PTR , value:PTR ) PROC PutArray(ptr:PTR TO ARRAY, value:ARRAY) PROC PutValue(ptr:PTR TO VALUE, value:VALUE)
These procedures poke the provided value into the given ptr address.
PROC CleanUp(returnValue=0) PROC OptMultiThreaded() RETURNS multiThreaded:BOOL PROC FileLength(path:ARRAY OF CHAR) RETURNS size ->depreciated PROC KickVersion(version) ->currently always returns TRUE
CleanUp() exits the program at any point. It was depreciated in AmigaE, but has been reinstated in Portabl E by using the exception system. It throws a negative exception value (which are reserved for use by E).
OptMultiThreaded() returns whether the program used OPT MULTITHREADED or not. This can be used to optimise your general-purpose module, such that it avoids worrying about multi-threading unless it has to.
FileLength() returns the length of the given file, but it's use is depreciated because (1) it is unnecessary due to the 'std/cPath' module, and (2) the path it takes is not truely portable.
KickVersion() is supposed to check whether the current Amiga Kickstart version is >= the supplied version, but currently it always returns TRUE. If someone could tell me how to implement this procedure then it would likely be moved to the 'exec' module.
All classes have the following methods:
METHOD InfoClassType() RETURNS typeof:CLASSTYPE METHOD IsSameClassTypeAs(type:CLASSTYPE) RETURNS isSame:BOOL METHOD IsOfClassType(parent:CLASSTYPE) RETURNS isSubtype:BOOL
For more information please see the "Run Time Type Information (RTTI)" subchapter of the "Object orientation" chapter in Portabl E's main manual.
Some organisational changes have been made from AmigaE to ensure that Portabl E is truely OS independant.
Procedures for Dos, Exec, Graphics & Intuition are no-longer built-in, and must instead be requested using:
MODULE 'dos', 'exec', 'graphics', 'intuition'
This happens automatically when the compatibility mode is enabled.
AmigaE's built-in Graphics helper functions (like Plot() & TextF()) are not available, unless the Amiga 'graphics' module is used, or the compatibility mode is enabled. But they are now depreciated in favour of the 'std/cGfx' module.
AmigaE's built-in Intuition helper functions (like OpenW() & Gadget()) are not available, unless the Amiga 'intuition' module is used, or the compatibility mode is enabled. But they are now depreciated in favour of the 'std/cGui' module.
The arg variable is not available, unless the Amiga 'dos' module is used, or the compatibility mode is enabled. It would be better to use the ShellArgs() procedure from the 'std/pShell' module.
The wbmessage variable is not available, unless the Amiga 'wb' module is used, or the compatibility mode is enabled.
Please see the "Statements, expressions & functions" subchapter of the "Reversible changes from AmigaE" chapter in the main Portabl E manual for a list of procedures that have been renamed. Although if you look carefully in this documentation you should be able to find them anyway!
Also note that the exceptioninfo variable has been renamed exceptionInfo, unless the compatibility mode is enabled.
Because the list of MODULEs is quite large, and perhaps it would feel like a lot of effort to read every one until you found the right one, here is a quick explanation of the modules:
Basic stuff:
Commonly needed modules:
More powerful versions of some of the above modules:
Some smaller "sub-modules", if you don't need everything in 'std/cPath':
Obscure or advanced stuff:
This module allows you to quickly "box" a value inside of a class object, and then "unbox" it to retrieve that value. The intention is that you use it with set/getDataBox() methods (which expect a "PTR TO class"), so that you can store/retrieve any kind of value.
This module means there is no need for separate getter/setter methods for each type of data.
Supported OSes: All.
PROC BoxPTR(data:PTR) RETURNS box:OWNS PTR TO class PROC UnboxPTR(box:PTR TO class) RETURNS data:PTR PROC ReplaceBoxPTR(box:PTR TO class, data:PTR) RETURNS oldData:PTR
PROC BoxARRAY(data:ARRAY) RETURNS box:OWNS PTR TO class PROC UnboxARRAY(box:PTR TO class) RETURNS data:ARRAY PROC ReplaceBoxARRAY(box:PTR TO class, data:ARRAY) RETURNS oldData:ARRAY
PROC BoxSTRING(data:OWNS STRING) RETURNS box:OWNS PTR TO class PROC UnboxSTRING(box:PTR TO class) RETURNS data: STRING PROC ReplaceBoxSTRING(box:PTR TO class, data:OWNS STRING) RETURNS oldData:OWNS STRING
PROC BoxLIST(data:OWNS LIST) RETURNS box:OWNS PTR TO class PROC UnboxLIST(box:PTR TO class) RETURNS data: LIST PROC ReplaceBoxLIST(box:PTR TO class, data:OWNS LIST) RETURNS oldData:OWNS LIST
PROC BoxVALUE(data:VALUE) RETURNS box:OWNS PTR TO class PROC UnboxVALUE(box:PTR TO class, nilValue=0) RETURNS data:VALUE PROC ReplaceBoxVALUE(box:PTR TO class, data:VALUE) RETURNS oldData:VALUE
PROC BoxBIGVALUE(data:BIGVALUE) RETURNS box:OWNS PTR TO class PROC UnboxBIGVALUE(box:PTR TO class, nilValue=0:BIGVALUE) RETURNS data:BIGVALUE PROC ReplaceBoxBIGVALUE(box:PTR TO class, data:BIGVALUE) RETURNS oldData:BIGVALUE
As the procedures for different types behave similarly, here is a general explanation of each procedure for type FOO where FOO could be PTR, ARRAY, STRING or LIST:
BoxFOO creates & returns a class object which contains the supplied data (of type FOO). NOTE: As hinted by the use of "OWNS", when data is a STRING or LIST, the box takes ownership of it, so it will be destroyed when the box itself is destroyed.
UnboxFOO takes the previously created box, and returns the data (of type FOO) that is stored inside it. The data is still left inside the box, so it can be retrieved again.
UnboxVALUE takes the additional parameter nilValue, which is the value it will return if box is NIL. The other unboxing procedures always return NIL if box is NIL.
ReplaceBoxFOO replaces the oldData stored in the box with the new data supplied by you. The oldData is returned. You can supply NIL/etc as the new data.
This module allows you to call function pointers that are obtained using CALLBACK. It should be considered a hack, which will not be available for target languages like Java, and so should be avoided except when porting existing AmigaE code.
Supported OSes: All (currently!).
PROC call0empty(func:PTR) PROC call0 (func:PTR) RETURNS value PROC call0many (func:PTR) RETURNS value, ret2, ret3, ret4, ret5 PROC call1empty(func:PTR, p1) PROC call1 (func:PTR, p1) RETURNS value PROC call1many (func:PTR, p1) RETURNS value, ret2, ret3, ret4, ret5 PROC call2empty(func:PTR, p1, p2) PROC call2 (func:PTR, p1, p2) RETURNS value PROC call2many (func:PTR, p1, p2) RETURNS value, ret2, ret3, ret4, ret5 PROC call3empty(func:PTR, p1, p2, p3) PROC call3 (func:PTR, p1, p2, p3) RETURNS value PROC call3many (func:PTR, p1, p2, p3) RETURNS value, ret2, ret3, ret4, ret5 PROC call4empty(func:PTR, p1, p2, p3, p4) PROC call4 (func:PTR, p1, p2, p3, p4) RETURNS value PROC call4many (func:PTR, p1, p2, p3, p4) RETURNS value, ret2, ret3, ret4, ret5 PROC call5empty(func:PTR, p1, p2, p3, p4, p5) PROC call5 (func:PTR, p1, p2, p3, p4, p5) RETURNS value PROC call5many (func:PTR, p1, p2, p3, p4, p5) RETURNS value, ret2, ret3, ret4, ret5 PROC call6empty(func:PTR, p1, p2, p3, p4, p5, p6) PROC call6 (func:PTR, p1, p2, p3, p4, p5, p6) RETURNS value PROC call6many (func:PTR, p1, p2, p3, p4, p5, p6) RETURNS value, ret2, ret3, ret4, ret5
Hopefully it's use is fairly self-explanatory:
This module provides basic functionality that is usually needed for Shell programs.
Supported OSes: All.
CONST SHELL_RET_OK CONST SHELL_RET_WARN CONST SHELL_RET_ERROR CONST SHELL_RET_FAIL
SHELL_RET_OK can be returned by your main() procedure, to indicate your program finished successfully.
SHELL_RET_WARN can be returned by your main() procedure, to indicate a warning.
SHELL_RET_ERROR can be returned by your main() procedure, to indicate an error.
SHELL_RET_FAIL can be returned by your main() procedure, to indicate a failure.
PROC ExecuteCommand(command:ARRAY OF CHAR) RETURNS executed:BOOL PROC ProgramName() RETURNS progName:ARRAY OF CHAR PROC ShellArgs() RETURNS shellArgs:ARRAY OF CHAR PROC CtrlC() RETURNS pressed:BOOL
ExecuteCommand() takes a Shell command, and executes it. It returns TRUE if the command could be found & was executed, but this does not indicate whether the command was successful or not. Currently there is no portable way to determine the return value of a command.
While ExecuteCommand() may be portable (i.e. OS independant), the Shell command provided to it is not. Therefore you will need to check the pe_TargetOS variable with StrCmp() to decide what command should be executed.
ProgramName() returns a string containing the name of the program's executable file.
ShellArgs() returns a string containing the parameters passed to your Shell program. This string may be empty if it was not executed as a Shell command. Beware that the spacing between words may not be exactly preserved, so for example several spaces may become just one.
CtrlC() allows your program to determine whether the user has pressed Ctrl-C or not since the last CtrlC() call.
PROC HighlightOnString() RETURNS on:ARRAY OF CHAR PROC HighlightOffString() RETURNS off:ARRAY OF CHAR
HighlightOnString() returns a string that can be used to start highlighting (or at least mark) a section of Print()ed text.
HighlightOffString() returns a string that can be used to stop highlighting (or at least mark) a section of Print()ed text.
This module provides Amiga-like Shell parameter parsing, but is completely OS independant, and far less error prone than ReadArgs().
Supported OSes: All.
This is how easy it is to use:
DEF file:ARRAY OF CHAR, quiet:BOOL IF ParseParams('File/A, Quiet/S') = FALSE THEN Raise("QUIT") file := GetParam(0) quiet := GetParam(1) <> NILA
The following example programs use it:
Examples/std/Shell/AmigaAttributes.e Examples/std/Shell/BinDif.e Examples/std/Shell/DeleteModuleCache.e Examples/std/Shell/PEGCC.e Examples/std/Shell/RecursiveDir.e Examples/std/Shell/Timer.e
PROC ParseParams(template:ARRAY OF CHAR, shellArgs=NILA:ARRAY OF CHAR, silent=FALSE:BOOL) RETURNS success:BOOL PROC GetParam(index) RETURNS arg:ARRAY OF CHAR PROC NumberOfParams() RETURNS numberOfParams
ParseParams() uses the supplied template to parse the parameters provided to your Shell program. If you supply shellArgs then it will parse that instead.
It returns TRUE when the parameters were parsed without error. It returns FALSE when parameters did not match the template, for which an error will have already been reported to the user, so your program should just quit silently. If TRUE was given to silent then no error will be reported to the user.
GetParam() allows you to retrieve one of the parameters supplied to your program. The value of index specifies which parameter you want, with the first parameter being 0. The retrieved parameter is always returned as a string, even if the parameter only accepts numbers. If no such parameter was supplied, then it returns NILA.
NumberOfParams() returns the number of parameters in the template. It can be used to help emulate ReadArgs() if you wish.
Templates are of the form:
'Parameter1, Parameter2/X, Parameter3=P3/Y'
where P3 is an alternative name for Parameter3, and X & Y are flags. Multiple flags may be used, but each one must have a forward slash before it.
The template flags supported are:
/A = a required parameter /K = the keyword is required /S = the parameter is a switch /N = the parameter is a number /F = the parameter takes the rest of the line
The user's supplied parameters are parsed according to the template. If the user ends their parameters with a question mark, then the template is shown, and the user can enter additional parameters.
Read about AmigaDOS argument passing, which uses ReadArgs(), for a better idea how to use templates.
This module allows you to check the stack at run-time.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
These procedures are not currently supported by the Linux & Windows (POSIX) targets, but it isn't needed in those cases anyway.
PROC FreeStack() RETURNS bytes PROC StackSize() RETURNS bytes
FreeStack() returns the approximate number of bytes free in the stack.
StackSize() returns the total number of bytes allocated to the stack.
This module provides portable semaphores.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
These procedures are not currently supported by the Windows target, due to MinGW not supporting POSIX semaphores. It's also not supported by the Linux target, as I haven't yet needed it.
PROC NewSemaphore() RETURNS sem:SEMAPHORE PROC DisposeSemaphore(sem:SEMAPHORE) RETURNS nil:SEMAPHORE PROC SemLock(sem:SEMAPHORE) PROC SemUnlock(sem:SEMAPHORE) PROC SemTryLock(sem:SEMAPHORE) RETURNS success:BOOL
NewSemaphore() allocates an e-semaphore.
DisposeSemaphore() deallocates the provided e-semaphore. It returns NIL for convenience.
SemLock() attempts to obtain a lock on the provided sem e-semaphore, and blocks your program until it obtains it.
SemUnlock() unlocks the provided sem e-semaphore.
SemTryLock() is similar to SemLock(), except that it returns FALSE if it can't immediately obtain a lock (instead of blocking).
WARNING: These functions literally do nothing, unless your program has OPT MULTITHREADED at the top. This allows you to write modules that support multi-threading, without needing to suffer semaphore overhead in single-threaded programs.
This module provides portable time & date related functions.
Supported OSes: All.
The following example programs use it:
Examples/Graphics/Clock.e Examples/Shell/pTime.e
PROC CurrentTime(zone0local1utc2quick=0) RETURNS time:BIGVALUE
CurrentTime() returns the current time & date, as the number of seconds which have elapsed since 0:00:00 on 1st January 2000. Times & dates before then are negative values!
It takes a "zone" parameter to specify which timezone it should use. The default value of 0 means return the local time (including DST if appropriate). A value of 1 means return UTC time. A value of 2 means return whatever timezone is quickest to calculate, and should only be used for measuring the length of time periods.
This module provides basic support for unsigned number types. Beware that it has some limitations:
Supported OSes: All.
The following example programs use it:
Examples/std/Shell/crc32.e
UBYTE is an Unsigned BYTE (8-bits), and is a subtype of RANGE 0 TO 255.
UINT is an Unsigned INT (16-bits), and is a subtype of RANGE 0 TO 65535.
ULONG is an Unsigned LONG (32-bits), and is (somewhat incorrectly) a subtype of LONG (but this means you can use LONG where ULONG is expected, or vice versa, and it will automatically convert the type for you).
UBIGVALUE is an Unsigned BIGVALUE (usually 64-bits), and is (somewhat incorrectly) a subtype of BIGVALUE.
PROC BigEndianUINT( in:UINT ) RETURNS out:UINT PROC BigEndianULONG(in:ULONG) RETURNS out:ULONG PROC BigEndianUBIGVALUE(in:UBIGVALUE) RETURNS out:UBIGVALUE PROC LittleEndianUINT( in:UINT ) RETURNS out:UINT PROC LittleEndianULONG(in:ULONG) RETURNS out:ULONG PROC LittleEndianUBIGVALUE(in:UBIGVALUE) RETURNS out:UBIGVALUE PROC SwapEndianUINT( in:UINT ) RETURNS out:UINT PROC SwapEndianULONG(in:ULONG) RETURNS out:ULONG PROC SwapEndianUBIGVALUE(in:UBIGVALUE) RETURNS out:UBIGVALUE
These are the unsigned equivalents of the existing endian swapping procedures.
This module provides standard functions that your functions can inherit. The aim is to allow functions written by one person to be used by algorithms written by another person.
For example, LIST-based implementations of Fmap() & Freduce() are provided, and they will work with any functions that inherit the appropriate standard functions.
Supported OSes: All.
Be warned that this module is still considered an "alpha" version, and therefore may change significantly (or may have major bugs).
FUNC funcParam0empty() FUNC funcParam0 () OF funcParam0empty RETURNS value
FUNC funcParam1empty(p1) FUNC funcParam1 (p1) OF funcParam1empty RETURNS value
FUNC funcParam2empty(p1, p2) FUNC funcParam2 (p1, p2) OF funcParam2empty RETURNS value
FUNC funcParam3empty(p1, p2, p3) FUNC funcParam3 (p1, p2, p3) OF funcParam3empty RETURNS value
FUNC funcParam4empty(p1, p2, p3, p4) FUNC funcParam4 (p1, p2, p3, p4) OF funcParam4empty RETURNS value
FUNC funcParam5empty(p1, p2, p3, p4, p5) FUNC funcParam5 (p1, p2, p3, p4, p5) OF funcParam5empty RETURNS value
FUNC funcParam6empty(p1, p2, p3, p4, p5, p6) FUNC funcParam6 (p1, p2, p3, p4, p5, p6) OF funcParam6empty RETURNS value
FUNC funcParam7empty(p1, p2, p3, p4, p5, p6, p7) FUNC funcParam7 (p1, p2, p3, p4, p5, p6, p7) OF funcParam7empty RETURNS value
FUNC funcParam8empty(p1, p2, p3, p4, p5, p6, p7, p8) FUNC funcParam8 (p1, p2, p3, p4, p5, p6, p7, p8) OF funcParam8empty RETURNS value
For more information please see the "Functional programming" chapter of the main Portabl E manual.
PROC Fmap(function:PTR TO funcParam1, list:LIST) PROC Freduce(function:PTR TO funcParam2, list:ILIST, init)
For more information please see the "Functional programming" chapter of the main Portabl E manual.
Use this module instead of the cApp module, to simplify things for beginners.
This module is used to describe your program (Application) to the OS in a portable way. It is needed by several other modules (such as cGfx & cGui) so that they can work together (otherwise cGfx windows would seem to come from a different program to the cGui windows!).
Supported OSes: The same as cApp.
The simplest use of this module would be:
IsDesktopApp()
If you wanted your window to fully cover the screen:
IsFullWindowApp()
If you wanted your own screen:
IsFullScreenApp(640, 480)
One of the following procedures must be called before you open any windows (using cGfx or cGui). You must not call more than one procedure. Typically you would call it at the start of your program.
PROC IsDesktopApp( title=NILA:ARRAY OF CHAR) PROC IsFullWindowApp(title=NILA:ARRAY OF CHAR) PROC IsFullScreenApp(width, height, title=NILA:ARRAY OF CHAR)
IsDesktopApp() indicates that your program will appear on the computer's desktop (called Workbench on Amiga). You can supply a title (i.e. name) for your program, otherwise your executable's file name will be used. This must be called before opening any windows!
IsFullWindowApp() indicates that your program will have a window that takes up the whole screen. Typically used by 'serious' applications. You can supply a title (i.e. name) for your program, otherwise your executable's file name will be used. This must be called before opening any windows!
IsFullScreenApp() indicates that your program will use the whole screen, without any window borders. You must supply the width & height of the screen. Typically used by games. You can supply a title (i.e. name) for your program, otherwise your executable's file name will be used. This must be called before opening any windows!
This module is used to describe your program (Application) to the OS in a portable way. It is needed by several other modules (such as cGfx & cGui) so that they can work together (otherwise cGfx windows would seem to come from a different program to the cGui windows!).
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
The simplest use of this module would be:
CreateApp().build()
A better use of this module might look like this:
CreateApp('my program name').initVersion('v1.0').initDescription('a cliched demo').build()
It is not usually necessary, but you can also do this:
DEF app:PTR TO cApp app := CreateApp('my program name') app.initVersion('v1.0') app.initDescription('a cliched demo') app.build()
PROC CreateApp(title=NILA:ARRAY OF CHAR) RETURNS app:PTR TO cApp PROC DestroyApp() PROC MinimiseApp(undo=FALSE:BOOL)
CreateApp() creates & returns a cApp object that will represent your Application. You can supply a title (i.e. name) for your program, otherwise your executable's file name will be used. You should then use it's methods (see below) to describe your program, before finally building it. You are only allowed to create one cApp object!
DestroyApp() destroys your cApp object. Since there can only ever be one cApp object, you do not need to supply it. It will also destroy any resources that depend on it, such as open windows. Since it is automatically called when your program quits, you don't normally need to use it!
Since DestroyApp() is automatically called when your program quits, any open windows (and other resources) will also be automatically closed.
MinimiseApp() minimises your Application, or undoes minimisation when you supply TRUE for undo. The actual behaviour depends on the OS, but on AmigaOS it will cause MUI windows to be iconified (while cGfx windows are currently unaffected).
/* Methods of cApp */ METHOD initVersion( info:ARRAY OF CHAR) RETURNS self:PTR TO cApp METHOD initCopyright( info:ARRAY OF CHAR) RETURNS self:PTR TO cApp METHOD initAuthor( info:ARRAY OF CHAR) RETURNS self:PTR TO cApp METHOD initDescription(info:ARRAY OF CHAR) RETURNS self:PTR TO cApp METHOD initFullWindow() RETURNS self:PTR TO cApp METHOD initFullScreen(width, height) RETURNS self:PTR TO cApp METHOD build()
initVersion() sets a string that gives your program's version. This must be called before the App is built.
initCopyright() sets a string that gives your program's copyright information. This must be called before the App is built.
initAuthor() sets a string that gives your program's author (names). This must be called before the App is built.
initDescription() sets a string that gives a short description of your program's purpose. This must be called before the App is built.
initFullWindow() indicates that your program should have a window that takes up the whole screen. This must be called before the App is built. Typically used by 'serious' applications. You cannot use this with initFullScreen()!
initFullScreen() indicates that your program should use the whole screen, without any window borders. You must supply the width & height of the screen. This must be called before the App is built. Typically used by games. You cannot use this with initFullWindow()!
build() causes your Application to be built according to the information already given. So it should be called after using any init methods that you need. Other modules canNOT use cApp until it has been built!
/* more methods of cApp */ METHOD infoTitle() RETURNS info:ARRAY OF CHAR METHOD infoVersion() RETURNS info:ARRAY OF CHAR METHOD infoCopyright() RETURNS info:ARRAY OF CHAR METHOD infoAuthor() RETURNS info:ARRAY OF CHAR METHOD infoDescription() RETURNS info:ARRAY OF CHAR METHOD infoFullWindow() RETURNS fullWindow:BOOL METHOD infoFullScreen() RETURNS fullScreen:BOOL, width, height
infoTitle() returns the title you set using the CreateApp() procedure.
infoVersion() returns the version you set using the initVersion() method, or NILA if none was set.
infoCopyright() returns the copyright you set using the initCopyright() method, or NILA if none was set.
infoAuthor() returns the author you set using the initAuthor() method, or NILA if none was set.
infoDescription() returns the description you set using the initDescription() method, or NILA if none was set.
infoFullWindow() returns whether you used the initFullWindow() method or not.
infoFullScreen() returns whether you used the initFullScreen() method or not. It also returns the width & height of the screen you set.
/* more methods of cApp */ METHOD minimise(undo=FALSE:BOOL)
minimise() has the same effect as the MinimiseApp() procedure.
This module is the same as the cGfx module (which provides pixel-based graphics), except that it provides a few extras to simplify things for beginners. Those extras are detailed below.
Beware that you canNOT use this module at the same time as the cGfxSpritesSimple module, to draw within the same window. Use one or the other, but not both at the same time.
Supported OSes: The same as cGfx.
How to open a window:
IsDesktopApp() ->you only need to do this once! OpenWindow(640, 480)
How to draw in the window:
SetColour(RGB_ORANGE) DrawBox( 20,20, 50,50) SetColour(RGB_BLACK) DrawText(20,20, 'Hello world!')
Here is one way to show a picture in the window:
StoreBitmap('player', 0, LoadPicture('spaceship.gif')) UseBitmap('player', 0).draw(50,50)
Or you could do this:
StoreBitmap('player', 0, LoadPicture('spaceship.gif')) LastBitmap().draw(50,50)
Here's another way to show a picture in the window:
DEF player:PTR TO cGfxBitmap player := LoadPicture('spaceship.gif') player.draw(50,50)
The following example programs use it:
Examples/std/Graphics/Clock.e Examples/std/Graphics/Cosmic/cosmic_deluxe.e Examples/std/Graphics/IfsFern.e Examples/std/Graphics/Mandel.e Examples/std/Graphics/Pythagoras.e Examples/std/Graphics/StarsXY.e Examples/std/Graphics/StarsZ.e Examples/std/Graphics/StarsZYX.e Examples/std/Graphics/ToySketch.e Examples/std/Multimedia/ShadowOfTheBlitz_Scroller/sotb_orig.e Examples/std/Multimedia/StarsDemo.e
Released programs which are known to use it:
HueFlow ( os4depot.net/?function=showfile&file=game/puzzle/hueflow.lha ) Ami-Scratch ( os4depot.net/?function=showfile&file=graphics/misc/amiscratch.lha ) Ami-Bootguard ( os4depot.net/?function=showfile&file=utility/misc/ami-bootguard.lha ) Ami-Lineapolis ( www.lineapolis.dizzy.pl )
You do not need to use CreateGfxWindow(), because it is automatically called, with the result stored in the gfx global variable.
The 'std/cAppSimple' module is automatically available, so you can use it's procedures if you want.
The following RGB constants are provided for use with SetColour():
RGB_WHITE, RGB_BLACK, RGB_GRAY, RGB_GREY, RGB_SILVER, RGB_RED, RGB_GREEN, RGB_BLUE, RGB_YELLOW, RGB_MAGENTA, RGB_CYAN, RGB_ORANGE, RGB_PURPLE, RGB_PINK, RGB_BROWN
PROC LastBitmap() RETURNS bitmap:PTR TO cGfxBitmap PROC ChangeGfxWindow(title=NILA:ARRAY OF CHAR, hideMousePointer=FALSE:BOOL, enableAlphaChannel=FALSE:BOOL)
LastBitmap() gives you the last bitmap that was returned by one of the following procedures. If there was no last bitmap, then it protects you by throwing an exception.
ChangeGfxWindow() allows you to give a title (i.e. name) for your window. If you give TRUE for hideMousePointer then the mouse pointer will not be visible for the window. But you can only make these changes before opening the window!
If you give TRUE for enableAlphaChannel then loadPicture() will load the alpha-channel of a picture, if the OS supports it. infoAlphaChannel() will return TRUE if the OS supports it (and it has been enabled).
By default alpha-channel support is disabled in the 'std/cGfxSimple' module, so you need to call ChangeGfxWindow() to enable it.
PROC InfoScreenWidth() RETURNS width PROC InfoScreenHeight() RETURNS height PROC OpenWindow(width, height, resizable=FALSE:BOOL) PROC OpenFull() PROC CloseWindow() PROC CloseFull() PROC GetPosition() RETURNS x, y PROC SetPosition(x, y) PROC InfoWidth() RETURNS width PROC InfoHeight() RETURNS height PROC ChangeSize(width, height) PROC SetFrameSkipping(frameSkipping:BOOL) PROC SetAutoUpdate(autoUpdate:BOOL) PROC UpdateAndWaitForScreenRefresh() RETURNS skippingNextFrame:BOOL PROC WaitForScreenRefresh() PROC Clear(rgb) PROC SetColour(rgb) PROC GetColour() RETURNS rgb PROC SetColor(rgb) PROC GetColor() RETURNS rgb PROC ReadDot(x, y) RETURNS rgb PROC DrawDot(x, y) PROC DrawLine(x1, y1, x2, y2, thickness=1) PROC DrawBox(x, y, width, height, unfilled=FALSE:BOOL) PROC DrawCircle(x, y, radius, unfilled=FALSE:BOOL) PROC SetFont(name:ARRAY OF CHAR, size, style0plain1underlined2bold4italic=0) RETURNS success:BOOL PROC GetFont() RETURNS name:ARRAY OF CHAR, size, style PROC DrawText( x, y, fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) PROC DrawTextL(x, y, fmtString:ARRAY OF CHAR, args=NILL:ILIST, backgroundColour=-1) PROC InfoSizeOfTextL(fmtString:ARRAY OF CHAR, args=NILL:ILIST) RETURNS width, height PROC ScrollBox(dx, dy, x, y, width, height) PROC GetLastEvent() RETURNS type, subType, value, value2 PROC InfoScreenFPS() RETURNS fps PROC StoreBitmap(name:ARRAY OF CHAR, number, bitmap:PTR TO cGfxBitmap) RETURNS storedBitmap:PTR TO cGfxBitmap PROC UseBitmap( name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS bitmap:PTR TO cGfxBitmap PROC DestroyBitmap(bitmap:PTR TO cGfxBitmap) RETURNS nil:PTR TO cGfxBitmap PROC LoadPicture(file:ARRAY OF CHAR, maskFile=NILA:ARRAY OF CHAR, maskColour=-1) RETURNS pic:PTR TO cGfxBitmap PROC ExtractBitmap(x, y, width, height, notDrawable=FALSE:BOOL) RETURNS copy:PTR TO cGfxBitmap PROC MakeFractalBitmap(size, pen255colour, pen0colour, roughness=0, maskBelowPen=0, seed=0) RETURNS fractal:PTR TO cGfxBitmap
These are the same as cGfxWindows's methods (see chapter 21.3. Methods of cGfxWindow), but they look simpler because they are procedures. Only the most important methods are available as procedures, and unlike the methods they start with a capital letter.
If LoadPicture() could not load a picture, then it it protects you by throwing an exception.
(Note that both the CloseWindow() & CloseFull() procedures are the same as the close() method. And that the DestroyBitmap() procedure is essentially the same as the destroyDrawable() method.)
Don't forget the procedures from 21. MODULE 'std/cGfx'.
This module provides fairly easy pixel-based graphics, which is suitable for games, animation & multimedia. It is intended to be nearly as easy as AMOS, but more powerful.
Please note that many more features are planned for the future.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
The simplest way to open a window:
DEF win:PTR TO cGfxWindow CreateApp().build() ->you only need to do this once! win := CreateGfxWindow('demo') win.openWindow(640, 480)
How you open a full-screen window:
DEF win:PTR TO cGfxWindow, width, height CreateApp().initFullWindow().build() win := CreateGfxWindow('demo') win.openFull() width := win.infoWidth() height := win.infoHeight()
The simplest way to draw in the window:
win.setColour($FF8800) ->sets Red to $FF, Green to $88, and Blue to $00, giving an orange colour win.drawBox( 20,20, 50,50) win.setColour($000000) win.drawText(20,20, 'Hello world!')
How to do flicker-free (double buffered) drawing in the window:
DEF x win.setAutoUpdate(FALSE) ->THIS IS IMPORTANT win.setColour($FF8800) FOR x := 0 TO win.infoWidth() win.clear($808080) win.drawBox(x,20, 50,50) win.updateAndWaitForScreenRefresh() ->THIS IS IMPORTANT ENDFOR
How to show a picture in the window:
DEF pic:PTR TO cGfxBitmap pic := win.loadPicture('myPicture.gif') pic.draw(20,20)
How to handle events from a single open window:
DEF quit:BOOL, type, subType, value, value2 quit := FALSE REPEAT IF WaitForGfxWindowEvent() = win type, subType, value, value2 := win.getLastEvent() IF type = EVENT_WINDOW IF subType = EVENT_WINDOW_CLOSE THEN quit := TRUE ELSE IF type = EVENT_KEY IF subType = EVENT_KEY_ASCII win.setColour($FF0000) win.drawTextL(50, 50, 'You pressed the "\c" key.', [value], $808080) ENDIF ENDIF ENDIF UNTIL quit win.close()
The following example programs use it:
Examples/std/Graphics/StarsXY_ToySpaceshipSprite1.e Examples/std/Graphics/StarsZYX_ToySpaceshipSprite1.e Examples/std/Multimedia/StarsDemo.e
PROC CreateGfxWindow(title:ARRAY OF CHAR, hideMousePointer=FALSE:BOOL, enableAlphaChannel=FALSE:BOOL) RETURNS win:PTR TO cGfxWindow PROC DestroyGfxWindow(win:PTR TO cGfxWindow) RETURNS nil:PTR TO cGfxWindow PROC MakeRGB(red, green, blue) RETURNS rgb PROC Pause(delayInTenthsOfSecond) PROC WaitForGfxWindowEvent() RETURNS win:PTR TO cGfxWindow, type, subType, value, value2 PROC CheckForGfxWindowEvent(keepPreviousEvents=FALSE:BOOL) RETURNS win:PTR TO cGfxWindow, type, subType, value, value2
CreateGfxWindow() creates & returns a cGfxWindow object for a new graphics window. You must supply a title (i.e. name) for your window. If you give TRUE for hideMousePointer then the mouse pointer will not be visible for the window. The window starts off closed, so you must use a method to open it. You can create as many windows as you want!
If you give TRUE for enableAlphaChannel then loadPicture() will load the alpha-channel of a picture, if the OS supports it. infoAlphaChannel() will return TRUE if the OS supports it (and it has been enabled).
DestroyGfxWindow() destroys the supplied window. It will also destroy any resources that depend on it, such a bitmaps. Your windows will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
MakeRGB() returns an RGB value made of the supplied red, green & blue components. They must each be in the range 0 to 255 (inclusive).
Pause() waits for the delay given in 1/10th of a second. So 10 is one second.
WaitForGfxWindowEvent() waits for an event from any window. It then returns the window that the event came from, and also values that describe the event. Please see the 21.6. Events sub-chapter. You don't have to store the event values, as they can be retrieved from the window using the getLastEvent() method. Note WaitForGfxWindowEvent() does not clear the last event from other windows.
Also note that it will only remember the most recent events (typically the last 100), so ensure that you watch for events regularly.
CheckForGfxWindowEvent() checks whether any event has occured yet, and returns it if it has. But if no event has happened, then it returns NIL for win. This method DOES clear the last event from all others windows, unless you supplied TRUE for keepPreviousEvents.
The cGfxWindow class is a window in which you can draw graphics. The window has a "current drawing colour", which is used by some drawing methods.
Unlike some graphical systems, it does NOT have a "background drawing colour", nor does it have a "current drawing position" (because these were felt to either be unnecessary, or else more of a hiderance than a help).
/* Methods of cGfxWindow */ METHOD infoScreenWidth() RETURNS width METHOD infoScreenHeight() RETURNS height METHOD openWindow(width, height, resizable=FALSE:BOOL) METHOD openFull() METHOD close() METHOD infoIsOpen() RETURNS isOpen:BOOL METHOD infoTitle() RETURNS title:ARRAY OF CHAR METHOD infoAlphaChannel() RETURNS alphaChannelEnabled:BOOL METHOD getPosition() RETURNS x, y METHOD setPosition(x, y) METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD changeSize(width, height)
infoScreenWidth() & infoScreenHeight() return the size of the main screen. You can use them to decide what size window you should open.
openWindow() opens a window of the given size. If you use TRUE for resizable then the user will be allowed to resize the window (you will get an EVENT_WINDOW_RESIZED event when that happens). You may not use this method if the initFullWindow() or initFullScreen() methods were used on cApp.
openFull() opens a full window/screen, as previously specified by the initFullWindow() or initFullScreen() method that MUST have been used on cApp.
close() closes the window, loosing whatever was drawn in it. An exception will be thrown if the window is not open.
infoIsOpen() returns whether the window is open or not.
infoTitle() returns the title you set using the CreateGfxWindow() procedure.
infoAlphaChannel() returns whether alpha-channel support is enabled.
getPosition() return the position of the window.
setPosition() changes the position of the window. This can be done before the window is opened.
infoWidth() & infoHeight() return the size of the window.
changeSize() changes the size of the window, and cause an EVENT_WINDOW_RESIZED event (the same as when a user resizes the window).
NOTE: That on AmigaOS the window's size may not actually change for up to 0.1 seconds (i.e. 6 frames). You can find out when it has actually changed by checking for an EVENT_WINDOW_RESIZED event.
/* more methods of cGfxWindow */ METHOD getFrameSkipping() RETURNS frameSkipping:BOOL METHOD setFrameSkipping(frameSkipping:BOOL) METHOD setAutoUpdate(autoUpdate:BOOL) METHOD getAutoUpdate() RETURNS autoUpdate:BOOL METHOD updateAndWaitForScreenRefresh() RETURNS skippingNextFrame:BOOL METHOD infoSkippingNextFrame() RETURNS skippingNextFrame:BOOL METHOD waitForScreenRefresh()
getFrameSkipping() & setFrameSkipping() allow you to change & retrieve whether or not the window has frame skipping enabled. For frame skipping to work, it also needs auto-update to be disabled. Typically a new window defaults to FALSE for frameSkipping, which means that all frames will be displayed. With it set to TRUE, it will skip frames which have been missed. That means your program should run at the same speed on slower machines, but it can cause jerkiness due to the skipping of frames.
Note that on AROS frameSkipping defaults to TRUE, because AROS is usually run under emulation, and that is far too slow for a 60Hz frame rate.
setAutoUpdate() & getAutoUpdate() allow you to change & retrieve the window's auto-update mode. A new window defaults to TRUE for autoUpdate, which means that all changes to the window contents are immediately visible, although this can sometimes cause flickering. When autoUpdate is FALSE, no changes are shown in the window until the updateAndWaitForScreenRefresh() method is called, which allows you to have silky smooth graphics.
updateAndWaitForScreenRefresh() waits for the screen to have completed refreshing, before updating it with any changes you have made to the contents of the window. This is done using a double buffer, giving you "vsynced" graphics. AutoUpdate must have been disabled, or an exception will be thrown.
Normally it returns FALSE, but if it detects a screen refresh has been missed (and frame skipping is enabled), then it will return TRUE to indicate that it will automatically skip the next frame, to keep your program/game running smoothly. You can safely ignore this, but if you wish to optimise your program, then you can avoid doing any CPU or graphically intensive operations that are only needed for the next frame.
infoSkippingNextFrame() returns the same value as the last updateAndWaitForScreenRefresh() method call did.
waitForScreenRefresh() waits for the screen to have completed refreshing.
/* more methods of cGfxWindow */ METHOD clear(rgb) METHOD setColour(rgb) METHOD getColour() RETURNS rgb METHOD setColor(rgb) METHOD getColor() RETURNS rgb METHOD readDot(x, y) RETURNS rgb
clear() fills the entire contents of the window with the given colour. The current draw colour is unaffected.
setColour() sets the current draw colour to the given RGB value.
getColour() returns the current draw colour.
setColor() is the same as setColour().
getColor() is the same as getColour().
readDot() returns the colour of the pixel at x,y.
/* more methods of cGfxWindow */ METHOD drawDot(x, y) METHOD drawLine(x1, y1, x2, y2, thickness=1) METHOD drawBox(x, y, width, height, unfilled=FALSE:BOOL) METHOD drawCircle(x, y, radius, unfilled=FALSE:BOOL)
drawDot() draws a dot at position x,y using the current draw colour. Note that position 0,0 is the top left of the window.
drawLine() draws a line between position x1,y1 and x2,y2 using the current draw colour. The line has a width of 1 unless thickness is given. If the line goes outside of the drawable region then it is automatically clipped.
NOTE: Please beware that lines with a thickness>1 may not be exactly identical on different OSes.
drawBox() draws a rectangle, with the top left at the position x,y and with the given width & height (which must be not be negative). The rectangle is filled unless unfilled is TRUE. If the rectangle goes outside of the drawable region then it is automatically clipped.
drawCircle() draws a circle with centre at the position x,y and with the given radius (which must not be negative). The circle is filled, unless unfilled is TRUE. If the circle goes outside of the drawable region then it is automatically clipped.
/* more methods of cGfxWindow */ METHOD drawText( x, y, fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) METHOD drawTextL(x, y, fmtString:ARRAY OF CHAR, args=NILL:ILIST, backgroundColour=-1) METHOD setFont(name:ARRAY OF CHAR, size, style0plain1underlined2bold4italic=0) RETURNS success:BOOL METHOD getFont() RETURNS name:ARRAY OF CHAR, size, style
drawText() draws the fmtString text, with the top left at the position x,y. The text may contain formatting commands, the same as Print(), and any required parameters will be taken from arg1, etc. The drawn text's background is effectively transparent, so you may first need to clear the area where it will be drawn.
e.g. win.drawText(20,20, '\d + \d = \d\n', 1, 2, 3)
drawTextL() is similar to drawText(), except that any parameters required for formatted text will be taken from a supplied list. Unlike drawText() you can give a background colour, in which case the background will not be transparent (which on Amiga will be drawn much more efficiently, and can be anti-aliased).
e.g. win.drawTextL(20,20, '\d + \d = \d\n', [1, 2, 3])
setFont() allows you to change the current font, size & style used by drawText() & drawTextL(). If the named font is found then it will return TRUE. If the named font did not exist then it will return FALSE, and the current font will be unchanged. The plain style is 0, add 1 for underlining, add 2 for bold, and add 4 for italics. setFont() can be a slow operation if the specified size of font is not already in memory.
e.g. win.setFont('Times', 10)
getFont() returns the current font, size & style.
/* more methods of cGfxWindow */ METHOD makeText( fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) RETURNS text:PTR TO cGfxDrawable METHOD makeTextL(fmtString:ARRAY OF CHAR, args=NILL:ILIST, backgroundColour=-1) RETURNS text:PTR TO cGfxDrawable METHOD makeBitmapTextL(fmtString:ARRAY OF CHAR, args=NILL:ILIST, backgroundColour=-1, notDrawable=FALSE:BOOL) RETURNS text:PTR TO cGfxBitmap METHOD infoSizeOfTextL(fmtString:ARRAY OF CHAR, args=NILL:ILIST) RETURNS width, height
makeText() & makeTextL() are similar to the drawText() & drawTextL() methods, except that they return an object that can be used to repeatedly draw the text (at any position & any time). Using the draw() method of this object is exactly the same as using the window's drawText() method, except that it uses the colour & font that were 'current' when the object was created. Since the text is stored as a plain string, it is slower but more memory efficient than the makeBitmapTextL() method. You must use destroyDrawable() or END on the returned object when you no-longer need it.
makeBitmapTextL() is similar to the drawTextL() method, except that it draws the text into the bitmap which is returned. Using the draw() method of this bitmap will draw it in the window, just as if you had called the drawTextL() method. The behaviour is exactly the same as for the makeTextL() method, but it stores the text as a graphical bitmap instead of a string. This makes drawing it much faster, but it uses more memory. You must use destroyDrawable() or END on the returned object when you no-longer need it.
infoSizeOfTextL() this returns the size of the object you would get from the makeTextL() or makeBitmapTextL() method, without the need to create it. It is also the effective size of the text drawn by the drawTextL() method. It allows you efficiently modify the text, to get exactly the needed size, before you make or draw the text.
/* more methods of cGfxWindow */ METHOD setDrawableRegion(x=0,y=0, width=-1,height=-1) METHOD getDrawableRegion() RETURNS x, y, width, height METHOD scrollBox(dx, dy, x, y, width, height) METHOD getLastEvent() RETURNS type, subType, value, value2 METHOD setLastEvent(type, subType, value=0, value2=0)
setDrawableRegion() allows you to change the drawable region, which is usually the whole of the window. Any subsequent drawing won't make any changes outside of the drawable region. This can be very useful if you want to have different parts of the window used for different purposes, such as the game world & the status bar. If width/height is set to -1 then the right/bottom of the drawable region is set to the edge of the window.
getDrawableRegion() returns the current drawable region.
scrollBox() scrolls the area inside the given box by dx,dy pixels. If the box is outside of the drawable region then it is automatically clipped.
getLastEvent() returns the last event (for this window) that was returned by the WaitForGfxWindowEvent() or CheckForGfxWindowEvent() procedure. If there were no events, then it returns EVENT_NONE for type.
setLastEvent() allows you to fake (or clear) the last event.
/* more methods of cGfxWindow */ METHOD startTimer(periodInMilliSeconds=0) METHOD stopTimer() METHOD infoPeriodOfTimer() RETURNS periodInMilliSeconds METHOD infoScreenFPS() RETURNS fps
startTimer() starts a timer which repeats every periodInMilliSeconds thousandths of a second. When the timer runs out, it will generate an event with type=EVENT_TIMER & subType=EVENT_TIMER_EXPIRED. The event's value is the count of the number of times that the event has expired, since the last timer event was reported (normally this will be 1 unless you don't check events often enough).
stopTimer() stops the timer.
infoPeriodOfTimer() returns the period of the timer in thousandths of a second, or 0 if no timer is running.
infoScreenFPS() returns the screen's Frames Per Second, also known as it's refresh rate in Hertz. Use this to convert a desired delay (in seconds) into a delay of a whole number of frames, so that you can update something smoothly on screen. Beware that the first call to this method may pause your program for around a second, while it measures the screen's FPS.
/* more methods of cGfxWindow */ METHOD loadPicture(file:ARRAY OF CHAR, maskFile=NILA:ARRAY OF CHAR, maskColour=-1, notDrawable=FALSE:BOOL) RETURNS pic:PTR TO cGfxBitmap METHOD extractBitmap(x, y, width, height, notDrawable=FALSE:BOOL) RETURNS copy:PTR TO cGfxBitmap METHOD makeFractalBitmap(size, pen255colour, pen0colour, roughness=0, maskBelowPen=0, seed=0) RETURNS fractal:PTR TO cGfxBitmap METHOD storeBitmap(name:ARRAY OF CHAR, number, bitmap:PTR TO cGfxBitmap) RETURNS storedBitmap:PTR TO cGfxBitmap METHOD useBitmap( name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS bitmap:PTR TO cGfxBitmap METHOD destroyDrawable(drawable:PTR TO cGfxDrawable, force=FALSE:BOOL) RETURNS nil:PTR TO cGfxDrawable
loadPicture() loads the given picture, and returns a bitmap that can be used to draw the picture in the window. The file path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() procedure first.
If the picture has a mask then this will be used. Alternatively, you can use another file as the mask, in which case maskColour chooses the transparent colour. If you want to use the picture itself as the mask, then just use '' for maskFile.
When maskColour is -1 it uses the top-left pixel's colour, otherwise maskColour indicates the palette number or RGB value (depending on whether the picture has a depth <= 8 or not). Typically you would use 0 for maskColour.
Normally the bitmap is stored in video memory, and so can be drawn into the window. But if you wish to save video memory then give TRUE for notDrawable.
extractBitmap() creates & returns a bitmap containing part of the window. x,y gives the top left corner of the new bitmap, and width,height gives the size of the new bitmap. If you try to copy beyond the edge of the window then an exception will be thrown.
Beware that this can be quite slow, especially if width & height are large.
Normally the bitmap is stored in video memory, and so can be drawn into the window. But if you wish to save video memory then give TRUE for notDrawable.
makeFractalBitmap() creates & returns a bitmap containing a randomly generated 'cloud' or 'terrain' fractal. It can be very useful as a 'background' bitmap, since it tiles perfectly.
size gives the width & heigth of the bitmap, but if it isn't a power of two then it will be rounded-up to one. For example, if you supply 500 for size, then you will get a bitmap which is 512 by 512 pixels.
The bitmap effectively has a depth of 8-bits, since it contains 256 colours. pen255colour gives the RGB value of the highest pen colour, while pen0colour gives the lowest pen colour. The rest of the pen colours change smoothly between those two. For example, if you gave white for pen255colour & black for pen0colour, then you would get various shades of gray for the rest of the colours. For example, you might give a light & a dark shade of green to create a "grass bitmap":
win.makeFractalBitmap(size, $006000, $004000, 8)
Or give red & orange to create a "lava bitmap":
win.makeFractalBitmap(size, $FF0000, $FF6000)
roughness is value between 0 & 10 (inclusive) which controls how un-smooth the colour changes are. 0 is very smooth, while 10 is completely random. Values above 8 are unlikely to be useful!
maskBelowPen gives the pen number below which the bitmap is transparent. (It will also cause "pen0colour" to be the last non-transparent colour (so you are still giving the whole visible colour range).) For example, you could use it to make a whitish "cloud bitmap" which has gaps betweens clouds:
win.makeFractalBitmap(size, $606060, $E0E0E0, 0, 128)
seed allows you to give a particular random number seed, which will always give the same bitmap (even on different Portabl E targets!). This allows you to search for a good looking fractal bitmap, which you can then easily recreate (rather than having to save it for future use).
storeBitmap() & useBitmap() allow you to store & retrieve bitmaps using a name string, and optionally a number. The string must be an 'immediate string', not one you have created. It returns the stored bitmap, so you can use it straight away. Here's an example of how you might use it:
IF win.storeBitmap('player', 0, win.loadPicture('spaceship.gif')) = NIL THEN Print('Failed to load picture.\n') win.useBitmap('player', 0).draw(x,y)
If you try to store more than one bitmap with the same name & number combination, then an exception will be raised. This is to prevent you accidentally reusing them. And if you try to use a non-existant bitmap, then an exception will be raised; unless you gave TRUE for allowReturnNIL, in which case NIL will be returned.
destroyDrawable() takes the given bitmap/drawable & destroys it. You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
For safety it will NOT destroy a bitmap/etc if it is being used by another object (such as a sprite), UNLESS you give TRUE for force, as this would normally cause a crash.
/* more methods of cGfxWindow */ METHOD queryExtra(specific:QUAD) RETURNS value, unknown:BOOL METHOD registerForResizes( client:PTR TO cGfxNotifyOfWindowResize) METHOD unregisterForResizes(client:PTR TO cGfxNotifyOfWindowResize)
queryExtra() allows you to retrieve OS-specific information. For example, if you give "WIND", then it will return the Amiga window pointer. And "SCRN" will return the Amiga screen pointer. Please only use this method as a last resort, because it will stop your code from being portable!
registerForResizes() & unregisterForResizes() are used to tell this window when another object needs to know that it has been resized. You do not normally need to use these methods! (This is used by the cGfxStack class to redraw itself when it's window is resized.)
Note that any sub-class of cGfxNotifyOfWindowResize should implement this method:
windowHasResized(oldWidth, oldHeight)
cGfxDrawable is an abstract class for any fixed-size object that can be drawn inside a window. It does not have to be a bitmap, and can use any window draw methods. You can easily create your own sub-classes of cGfxDrawable, please see the 21.7. Creating your own cGfxDrawable sub-class sub-chapter.
/* Methods of cGfxDrawable */ METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD infoWindow() RETURNS win:PTR TO cGfxWindow METHOD infoIsTransparent() RETURNS isTransparent:BOOL METHOD draw(x, y) METHOD drawTiled(x, y, tileX:BOOL, tileY:BOOL)
infoWidth() & infoHeight() return the size of the drawable object.
infoWindow() returns the cGfxWindow that this object draws to.
infoIsTransparent() returns whether or not it is (partially) transparent. In the case of a bitmap, this would mean it has a mask.
draw() draws the object at the given position.
drawTiled() is the same as draw(), but it allows the object to be horizontally or vertically tiled, so it appears to be infinitely wide (when tileX is TRUE) and/or infinitely tall (when tileY is TRUE). When tiled, the drawable will be repeated in a 'tiled' fashion, thus allowing you to easily have background(s) that go on 'forever'.
The following methods are for advanced users only:
/* more methods of cGfxDrawable */ METHOD hitCheck(insideX, insideY) RETURNS hit:BOOL METHOD overlaps(drawable:PTR TO cGfxDrawable, insideX, insideY) RETURNS overlaps:BOOL
hitCheck() returns whether a particular point (relative to the top left of the drawable) will be drawn or not. (This is used by cGfxStack's findSpriteAt() method.)
overlaps() returns whether the provided drawable would overlap the current drawable, if the provided one was offset from the current one by the given coordinates (which are relative to the top left of the current drawable). If either drawable is a bitmap with a mask, then that will be taken into account. This method is handy for performing collision detection.
The following methods are for EXPERT users only:
/* more methods of cGfxDrawable */ METHOD changeUseCount(increaseBy) METHOD infoUseCount() RETURNS useCount METHOD changeVisibleCount(increaseBy) METHOD infoVisibleCount() RETURNS visibleCount METHOD registerForChanges( client:PTR TO cGfxNotifyOfDrawableChanges) METHOD unregisterForChanges(client:PTR TO cGfxNotifyOfDrawableChanges) METHOD addToGfx(gfx:PTR TO cGfxWindow)
changeUseCount() & infoUseCount() is used to change & retrieve how many times this object is used by things like sprites. The use count is reduced by using negative values for increaseBy. And useCount defaults to 0. You do not normally need to use these methods! (This is used by the cGfxSprite class to prevent it's drawable frames from being destroyed when it is still using them.)
changeVisibleCount() & infoVisibleCount() is used to change & retrieve how many times this object is visible within the current window. The visibile count is reduced by using negative values for increaseBy. And visibleCount defaults to 0. You do not normally need to use these methods! (This is used by the cGfxBitmap sub-class to make itself non-drawable when it's visible count drops to 0, to save video memory. The cGfxSprite class uses it.)
registerForChanges() & unregisterForChanges() are used to tell this drawable when another object needs to know that it's size or contents changes. You do not normally need to use these methods! (This is used by the cGfxSprite class to redraw itself when it's drawable is changed.)
Note that any sub-class of cGfxNotifyOfDrawableChanges should implement this method:
drawableHasChanged(oldWidth, oldHeight, drawable:PTR TO cGfxDrawable)
addToGfx() should only be called once, by the drawable itself. This registers it with the cGfxWindow that it draws to, so that it will be automatically destroyed when the cGfxWindow is destroyed. gfx is stored in the inherited member self.gfx, which you can read yourself if needed. You never need to use this method, unless you are creating your own cGfxDrawable sub-class.
The cGfxBitmap class is a special kind of cGfxDrawable class, which is a bitmap (picture) that can be drawn into the window. Bitmaps use video memory, unless they are made non-drawable (in which case the draw() method will throw an exception if you try to use it).
/* Methods of cGfxBitmap, which inherits cGfxDrawable */ METHOD clone(changeIsDrawable=FALSE:BOOL, isDrawable=FALSE:BOOL) RETURNS clone:PTR TO cGfxBitmap METHOD extract(x, y, width, height, changeIsDrawable=FALSE:BOOL, isDrawable=FALSE:BOOL) RETURNS copy:PTR TO cGfxBitmap METHOD setIsDrawable(isDrawable:BOOL) METHOD getIsDrawable() RETURNS isDrawable:BOOL
clone() creates & returns a copy of the bitmap. If you want to change the drawable state then give TRUE for changeIsDrawable, in which case isDrawable will indicate whether the new bitmap should be drawable or not.
extract() creates & returns a copy of part of the bitmap. x,y gives the top left corner of the new bitmap (where 0,0 is the existing corner), and width,height gives the size of the new bitmap. If you try to copy beyond the edge of the bitmap then an exception will be thrown. As with the clone() method, you can change the drawable state of the new bitmap.
setIsDrawable() & getIsDrawable() allow you to change & retrieve the drawable state. When a bitmap is drawable it uses video memory, and you are allowed to use the draw() method.
/* more methods of cGfxBitmap */ METHOD savePicture(file:ARRAY OF CHAR, ignoreMask=FALSE:BOOL) RETURNS success:BOOL METHOD flip(horizontally:BOOL, vertically:BOOL) METHOD rotate(degrees) METHOD scaleTo(newWidth, newHeight) METHOD scaleBy(multiplier, divider) METHOD makeScaledTo(newWidth, newHeight) RETURNS scaledBitmap:PTR TO cGfxBitmap METHOD makeScaledBy(multiplier, divider) RETURNS scaledBitmap:PTR TO cGfxBitmap ->plus methods inherited from cGfxDrawable
For the inherited methods read 21.4. Methods of cGfxDrawable.
savePicture() saves the current bitmap as a picture, in a standard format (IFF on Amiga, although it will be PNG on AROS). Normally the mask will be saved as part of the picture, but you can use TRUE for ignoreMask to prevent this. It returns whether saving the picture was successful or not.
flip() horizontally and/or vertically flips the bitmap, such that it becomes the mirror-image of itself.
rotate() rotates the bitmap clockwise. degrees must be in 90 degree steps, such that 0, 90, 180 and 270 are allowed.
scaleTo() enlarges or shrinks the bitmap to the given size.
scaleBy() enlarges or shrinks the bitmap by the ratio multiplier / divider. Thus it enlarges it by the integer multiplier, and shrinks it by the integer divider. Both width & height are scaled by the same amount.
makeScaledTo() & makeScaledBy() are the same as the scaleTo() & scaleBy() methods, except that they return a new (scaled) bitmap, rather than modify the existing one. (This is more efficient than clone()ing a bitmap & then using scaleTo() or scaleBy().)
All events are described by up to four returned values:
type, subType, value, value2
Where type can be one of the following values:
EVENT_NONE, EVENT_MOUSE, EVENT_KEY, EVENT_WINDOW, EVENT_TIMER, EVENT_UNKNOWN
Where subType gives more information on the kind of event:
EVENT_MOUSE_MOVE, EVENT_MOUSE_SCROLL, EVENT_MOUSE_DOUBLECLICK, EVENT_MOUSE_LEFT, EVENT_MOUSE_LEFTUP, EVENT_MOUSE_RIGHT, EVENT_MOUSE_RIGHTUP, EVENT_MOUSE_MIDDLE, EVENT_MOUSE_MIDDLEUP EVENT_KEY_ASCII, EVENT_KEY_ASCIIUP, EVENT_KEY_SPECIAL, EVENT_KEY_SPECIALUP EVENT_WINDOW_CLOSE, EVENT_WINDOW_ACTIVE, EVENT_WINDOW_INACTIVE, EVENT_WINDOW_RESIZED EVENT_TIMER_EXPIRED EVENT_UNKNOWN_DONOTUSE ->EVENT_SCREEN_REFRESH
Where value and value2 are optional, and their meaning depends on the event subType.
Beware that different event types can use the same subType values, so you MUST check type before you check subType. When type is EVENT_x, you need to check for subTypes that begin with EVENT_x_. For example, when type is EVENT_KEY, you must check for the subTypes EVENT_KEY_ASCII & EVENT_KEY_SPECIAL.
Here is a description of subTypes, and what value & value2 mean (if anything):
EVENT_MOUSE_MOVE indicates that the mouse has been moved to x,y location value,value2. EVENT_MOUSE_SCROLL indicates that the scroll wheel has been moved by value,value2 for x,y steps. EVENT_MOUSE_DOUBLECLICK indicates the left mouse button has been double-clicked at x,y location value,value2. EVENT_MOUSE_LEFT indicates the left mouse button has been depressed at x,y location value,value2. EVENT_MOUSE_RIGHT indicates the right mouse button has been depressed at x,y location value,value2. EVENT_MOUSE_MIDDLE indicates the middle mouse button has been depressed at x,y location value,value2. EVENT_MOUSE_LEFTUP indicates the left mouse button has been raised at x,y location value,value2. EVENT_MOUSE_RIGHTUP indicates the right mouse button has been raised at x,y location value,value2. EVENT_MOUSE_MIDDLEUP indicates the middle mouse button has been raised at x,y location value,value2. EVENT_KEY_ASCII indicates that a normal key has been pressed, with "value" for the ascii code. EVENT_KEY_SPECIAL indicates that a special key has been pressed, with "value" being a constant (see later). EVENT_KEY_ASCIIUP indicates that a normal key has been released (with "value" for the ascii code). EVENT_KEY_SPECIALUP indicates that a special key has been released (with "value" being a constant). EVENT_WINDOW_CLOSE indicates that the user has asked the window to close. EVENT_WINDOW_ACTIVE indicates that the window became active (e.g. the user clicked on it). EVENT_WINDOW_INACTIVE indicates that the window became inactive (e.g. the user clicked on another window). EVENT_WINDOW_RESIZED indicates that the window has changed size (with value,value2 being the new width,height). EVENT_TIMER_EXPIRED indicates that a cGfx timer has completed the given time. EVENT_UNKNOWN_DONOTUSE should not be used! EVENT_SCREEN_REFRESH indicates a screen refresh has occured. It is not guaranteed to be available, and may even be removed in the future!
When subType is EVENT_KEY_SPECIAL, value can be one of these self-explanatory constants:
EVENT_KEY_SPECIAL_ENTER, EVENT_KEY_SPECIAL_ESCAPE, EVENT_KEY_SPECIAL_TAB, EVENT_KEY_SPECIAL_BACKSPACE, EVENT_KEY_SPECIAL_INSERT, EVENT_KEY_SPECIAL_DELETE, EVENT_KEY_SPECIAL_HOME, EVENT_KEY_SPECIAL_END, EVENT_KEY_SPECIAL_PAGEUP, EVENT_KEY_SPECIAL_PAGEDOWN, EVENT_KEY_SPECIAL_UP, EVENT_KEY_SPECIAL_DOWN, EVENT_KEY_SPECIAL_LEFT, EVENT_KEY_SPECIAL_RIGHT, EVENT_KEY_SPECIAL_LSHIFT, EVENT_KEY_SPECIAL_RSHIFT, EVENT_KEY_SPECIAL_LCTRL, EVENT_KEY_SPECIAL_RCTRL, EVENT_KEY_SPECIAL_LALT, EVENT_KEY_SPECIAL_RALT, EVENT_KEY_SPECIAL_LCOMMAND, EVENT_KEY_SPECIAL_RCOMMAND, EVENT_KEY_SPECIAL_F1, EVENT_KEY_SPECIAL_F2, EVENT_KEY_SPECIAL_F3, EVENT_KEY_SPECIAL_F4, EVENT_KEY_SPECIAL_F5, EVENT_KEY_SPECIAL_F6, EVENT_KEY_SPECIAL_F7, EVENT_KEY_SPECIAL_F8, EVENT_KEY_SPECIAL_F9, EVENT_KEY_SPECIAL_F10
What does a sub-class of cGfxDrawable actually do? It is an object which behaves very much like a cGfxBitmap, and so you can (for example) ask it to draw itself at a particular location, using it's draw(x,y) method.
Why would you want to do that? On it's own this isn't much use, but if you write some code that draws a user-supplied bitmap somewhere, then it might be handy if it could also draw other things. One obvious example is the 'std/cGfxSprites' module, which allows you to have sprites. In that case you can have sprites draw something other than a simple bitmap (e.g. some text that changes). A specific example can be found here:
Examples/std/Graphics/StarsXY_ToySpaceshipSprite1.e
This example has an animated "3D star field" as a drawable object, and uses this as the background upon which a spaceship sprite moves around.
So how do you go about creating a cGfxDrawable sub-class? The previously mentioned example gives a nice concrete demonstration of how to do it, but you might like to know the theory behind it...
First you should take a look at the 21.4. Methods of cGfxDrawable sub-chapter, to see what methods your object will have. Back again? There were rather a lot of methods, right? Don't worry about that! Many of them have sensible defaults, so you can probably get away with writing only the following methods:
METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD draw(x, y)
They should be pretty self-explanatory. infoWidth() & infoHeight() simply report the actual size of your object. It is VERY important that your object has a fixed size. draw() simply uses the standard cGfx methods to draw your object at the given coordinates. It is VERY important that your object draws the same thing each time this method is called.
But what if you want to change the size of your object, or change what it draws? You can do that, but it should only happen when a method of your object is called. You will have to invent your own method! In the case of the previously mentioned example, the method is named setStarsOrigin() since it moves your viewpoint of the stars. In any case, it is VERY important that this method finishes with the following bit of code:
self.notifyClientsOfChange(oldWidth, oldHeight)
Where oldWidth & oldHeight give the OLD size of your object. You MUST do this even if your object's size has not changed, so that anything using your object will know that it's contents has changed, and thus redraw it if necessary.
But how does your object know it's size & target window in the first place? This is where your object's constructor comes in. While you can call this method anything you want, it is usual to call it new(). Thus you MIGHT have a constructor method that looks like this:
PROC new(win:PTR TO cGfxWindow, width, height) OF myDrawable self.addToGfx(win) self.width := width self.height := height ENDPROC
Note that your constructor MUST call the addToGfx() method. And you don't need to store win yourself, because it will do that for you in the inherited member self.gfx .
And then your object would look like this:
CLASS myDrawable OF cGfxDrawable width height ENDCLASS
And your "info" methods would look like this:
PROC infoWidth() OF myDrawable RETURNS width IS self.width PROC infoHeight() OF myDrawable RETURNS height IS self.height Of course your ||draw()|| method depends on exactly what your object draws! But it might look like this:
PROC draw(x, y) OF myDrawable self.gfx.setColour($FF0000) self.gfx.drawBox(x, y, self.width, self.height) ENDPROC
You would create your object using code along these lines:
DEF foo:PTR TO myDrawable NEW foo.new(gfx, 100, 100)
If you are creating a drawable for use as a background for sprites (as in the previously mentioned example), then you should be aware of an extra limitation. Usually your drawable will be tiled, which means it must look ok when it is tiled. This is usually easy to manage for 2D effects, but if it contains a fake 3D perspective then you cannot normally do it. It just so happens that the fake 3D parallax algorithm used by the StarsXY_ToySpaceshipSprite1.e example can be tiled, but that is a very unusual case.
What about those other cGfxDrawable methods that we ignored? If your object is transparent (i.e. it does NOT draw every pixel within it's given size) then you will need to consider writing the following methods:
METHOD infoIsTransparent() RETURNS isTransparent:BOOL METHOD hitCheck(insideX, insideY) RETURNS hit:BOOL METHOD overlaps(drawable:PTR TO cGfxDrawable, insideX, insideY) RETURNS overlaps:BOOL
infoIsTransparent() must return TRUE. You can ignore the other two methods, unless you want to perform accurate collision-detection on your drawable object. hitCheck() shouldn't be too hard to write, but overlaps() may be impossible! Probably the best you can do for overlaps() is to check whether drawable is one of your own objects (using the IsOfClassType() method), and only in that case will you have enough information that you can perform a more accurate overlap check (in all other cases you will need to fall-back on the default parent method, by calling SUPER self.overlaps(drawable, insideX, insideY)).
But what about those other methods we ignored? If your object contains other drawables (typically bitmaps), then you will need to write the following methods:
METHOD changeVisibleCount(increaseBy) METHOD registerForChanges( client:PTR TO cGfxNotifyOfDrawableChanges) METHOD unregisterForChanges(client:PTR TO cGfxNotifyOfDrawableChanges)
For each of these methods, you must call the same method on all the drawables you contain, and then call the parent method. For example, say that your drawable object contains the member picture:PTR TO cGfxBitmap, then your methods would look like this:
PROC changeVisibleCount(increaseBy) OF myDrawable self.picture.changeVisibleCount(increaseBy) SUPER self.changeVisibleCount(increaseBy) ENDPROC PROC registerForChanges(client:PTR TO cGfxNotifyOfDrawableChanges) OF myDrawable self.picture.registerForChanges(client) SUPER self.registerForChanges(client) ENDPROC PROC unregisterForChanges(client:PTR TO cGfxNotifyOfDrawableChanges) OF myDrawable self.picture.unregisterForChanges(client) SUPER self.unregisterForChanges(client) ENDPROC
That should cover everything you need to know, but as this is quite an advanced subject, feel free to ask me about anything that is not clear. And of course remember to look at the StarsXY_ToySpaceshipSprite1.e example.
This module is the same as the cGfxSprites module (which provides sprite-based graphics), except that it provides a few extras to simplify things for beginners. Those extras are detailed below.
Beware that you canNOT use this module at the same time as the cGfxSimple module, to draw within the same window. Use one or the other, but not both at the same time.
Supported OSes: The same as cGfx.
When you use this module, it automatically uses the window you open:
IsDesktopApp() ->you only need to do this once! OpenWindow(640, 480)
Here's one way to create & move a sprite.
StoreBitmap('player', 0, LoadPicture('spaceship.gif')) StoreSprite('player', 0, CreateSprite(20,20, LastBitmap())) Pause(20) ->wait 2 seconds UseSprite('player', 0).move(30,0) ->move the sprite horizontally LastSprite().move(50,0) ->move the sprite again
Here's another way to create & move a sprite:
DEF playerSprite:PTR TO cGfxSprite, playerBitmap:PTR TO cGfxBitmap playerBitmap := LoadPicture('spaceship.gif') playerSprite := CreateSprite(20,20, playerBitmap) Pause(20) ->wait 2 seconds playerSprite.move(30,0) ->move the sprite horizontally playerSprite.move(50,0) ->move the sprite again
Here's how to move a sprite smoothly:
SetAutoUpdate(FALSE) REPEAT playerSprite.move(1,0) UpdateAndWaitForScreenRefresh() UNTIL playerSprite.getPosition() >= InfoWidth()
The following example programs use it:
Examples/std/Graphics/StarsXY_ToySpaceshipSprite1.e Examples/std/Graphics/StarsZYX_ToySpaceshipSprite1.e Examples/std/Graphics/ToySpaceshipSprite1.e Examples/std/Graphics/ToySpaceshipSprite2.e Examples/std/Multimedia/ShadowOfTheBlitz_Scroller/SOTB.e
Released programs which are known to use it:
Ami-Ingenious ( os4depot.net/?function=showfile&file=game/board/ami-ingenious.lha ) Davideope puzzle ( os4depot.net/?function=showfile&file=game/puzzle/davidope_puzzle.lha ) FlowerWay ( os4depot.net/?function=showfile&file=game/puzzle/flowerway.lha ) 7-boings ( os4depot.net/?function=showfile&file=game/puzzle/7boings.lha ) Age of Thieves ( os4depot.net/?function=showfile&file=game/board/age_of_thieves.lha )
You do not need to use CreateGfxStack(), because it is automatically called, with the result stored in the gfxStack global variable. And the first layer is automatically stored in the gfxLayer global variable.
Note that you don't need to call CreateGfxWindow() either, because the cGfxSimple module is used.
PROC LastSprite() RETURNS sprite:PTR TO cGfxSprite
LastSprite() gives you the last sprite that was returned by one of the following procedures. If there was no last sprite, then it protects you by throwing an exception.
PROC DestroySprite(sprite:PTR TO cGfxSprite) RETURNS nil:PTR TO cGfxSprite PROC FindSpriteAt(x, y, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite PROC FindSpriteOverlapping(sprite:PTR TO cGfxSprite, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite PROC StoreSprite(name:ARRAY OF CHAR, number, sprite:PTR TO cGfxSprite) RETURNS storedSprite:PTR TO cGfxSprite PROC UseSprite( name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS sprite:PTR TO cGfxSprite PROC SetBackgroundColour(rgb) PROC SetBackgroundDrawable(drawable=NIL:PTR TO cGfxDrawable, x=0, y=0, noTileX=FALSE:BOOL, noTileY=FALSE:BOOL, noScrollX=FALSE:BOOL, noScrollY=FALSE:BOOL) PROC ScrollAllSprites(dx, dy) PROC ScrollAllLayers(dx, dy)
These are the same as cGfxStack's methods (see chapter 23.3. Methods of cGfxStack), but they look simpler because they are procedures. Only the most important methods are available as procedures, and unlike the methods they start with a capital letter.
(Note that cGfxSimple's UpdateAndWaitForScreenRefresh() procedure is modified to automatically call cGfxStack's redraw() method, so you don't need to. And cGfxSimple's SetAutoUpdate() procedure is modified to automatically call cGfxStack's setAutoRedraw() method, so you don't need to. The upshot of this is that the sprite system will work much more efficiently when you use SetAutoUpdate(FALSE).)
PROC ScrollSprites(dx, dy) PROC ScrollLayer(dx, dy) PROC SetOrigin(x, y) PROC GetOrigin() RETURNS x, y PROC CreateSprite(x, y, drawable:PTR TO cGfxDrawable, hidden=FALSE:BOOL) RETURNS sprite:PTR TO cGfxSprite
These are the same as cGfxLayer's methods (see chapter 23.4. Methods of cGfxLayer), but they look simpler because they are procedures. They always operate on gfxLayer, which is the top layer of sprites. Only the most important methods are available as procedures, and unlike the methods they start with a capital letter.
PROC FullyRedrawSprites()
FullyRedrawSprites() will force all the sprites to be redrawn. This is useful if you want to "clean up" after have directly drawn in the window using 'std/cGfx'.
This module provides fairly easy sprite-based graphics (and was written using the cGfx module itself).
While there are some advanced features, the default behaviour is quite simple: A cGfxStack covers the entire window, and is given the responsibility for all drawing in that window. It is a stack of cGfxLayers (you start with just one). Each cGfxLayer is a layer of cGfxSprites. And each cGfxSprite is just a bitmap that knows what position it should be drawn at.
A cGfxStack initially has one layer, and you can create sprites in that layer. You can change the position of sprites at any time, and see the result immediately.
You can get away with just using a single layer, but they are very handy for organising your sprites. For example:
Supported OSes: The same as cGfx.
The simplest way to create a stack:
DEF win:PTR TO cGfxWindow, stack:PTR TO cGfxStack CreateApp().build() win := CreateGfxWindow('demo') win.openWindow(640, 480) stack := CreateGfxStack(win)
How to create & move a sprite:
DEF layer:PTR TO cGfxLayer, sprite:PTR TO cGfxSprite layer := stack.infoTopLayer() sprite := layer.createSprite(20,20, win.loadPicture('SomePicture.jpg')) Pause(20) ->wait 2 seconds sprite.move(30,0) ->move the sprite horizontally
The following example programs use it:
Examples/std/Multimedia/ShootEmUp/ShootEmUp.e
Released programs which are known to use it:
PictureAlbum ( cshandley.co.uk )
PROC CreateGfxStack(gfx:PTR TO cGfxWindow) RETURNS stack:PTR TO cGfxStack PROC DestroyGfxStack(stack:PTR TO cGfxStack) RETURNS nil:PTR TO cGfxStack
CreateGfxStack() creates & returns a cGfxStack object using the supplied window. By default it covers the whole window, so you must use the setRegion() method if you want to change that.
DestroyGfxStack() destroys the supplied stack. It will also destroy all layers & sprites inside the stack. The stacks will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
A single cGfxStack normally covers the entire window, but it can be restricted to a region. It is given the responsibility for all drawing (and refreshing) of it's region, so you must never (use a cGfxWindow or cGfxBitmap to) draw there yourself! A cGfxStack is a stack of cGfxLayers, with each layer on top of the next one.
/* Methods of cGfxStack */ METHOD infoTopLayer() RETURNS top:PTR TO cGfxLayer METHOD infoBottomLayer() RETURNS bottom:PTR TO cGfxLayer METHOD destroyLayer(layer:PTR TO cGfxLayer) RETURNS nil:PTR TO cGfxLayer METHOD destroySprite(sprite:PTR TO cGfxSprite) RETURNS nil:PTR TO cGfxSprite METHOD findSpriteAt(x, y, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite METHOD findSpriteOverlapping(sprite:PTR TO cGfxSprite, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite METHOD storeSprite(name:ARRAY OF CHAR, number, sprite:PTR TO cGfxSprite) RETURNS storedSprite:PTR TO cGfxSprite METHOD useSprite( name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS sprite:PTR TO cGfxSprite
infoTopLayer() returns the layer at the top of the stack, whose sprites appear above all the other layers.
infoBottomLayer() returns the layer at the bottom of the stack, which is a special layer that is a solid (background) colour. You should not try to add sprites to this layer, nor destroy it.
destroyLayer() destroys the supplied layer, along with all it's sprites. You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
destroySprite() destroys the supplied sprite. The sprite's bitmap/drawable will not be destroyed. You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
findSpriteAt() searches all the layers (from the top downwards), looking for a sprite at the given position. It returns the first sprite that it finds. If you want to continue looking, then for lastMatch you must give the previously returned sprite.
findSpriteOverlapping() searches all the layers (from the top downwards), looking for a sprite which overlaps the given sprite. It returns the first sprite that it finds. If you want to continue looking, then for lastMatch you must give the previously returned sprite.
storeSprite() & useSprite() allow you to store & retrieve sprites using a name string, and optionally a number. The string must be an 'immediate string', not one you have created. It returns the stored sprite, so you can use it straight away. Here's an example of how you might use it:
stack.storeSprite('player', 0, layer.createSprite(x,y, playerBitmap, TRUE)) stack.useSprite('player', 0).setHidden(FALSE)
If you try to store more than one sprite with the same name & number combination, then an exception will be raised. This is to prevent you accidentally reusing them. And if you try to use a non-existant sprite, then an exception will be raised; unless you gave TRUE for allowReturnNIL, in which case NIL will be returned.
/* more methods of cGfxStack */ METHOD setBackgroundColour(rgb) METHOD getBackgroundColour() RETURNS rgb METHOD setBackgroundDrawable(drawable=NIL:PTR TO cGfxDrawable, x=0, y=0, noTileX=FALSE:BOOL, noTileY=FALSE:BOOL, noScrollX=FALSE:BOOL, noScrollY=FALSE:BOOL) METHOD getBackgroundDrawable() RETURNS drawable:PTR TO cGfxDrawable METHOD setRegion(x=0, y=0, width=-1, height=-1) METHOD getRegion() RETURNS x, y, width, height METHOD scrollAllSprites(dx, dy) METHOD scrollAllLayers(dx, dy)
setBackgroundColour() & getBackgroundColour() allow you to change & retrieve the colour of the special background layer.
setBackgroundDrawable() & getBackgroundDrawable() allow you to change & retrieve a drawable/bitmap for the special background layer. The drawable/bitmap will be tiled, unless you use noTileX & noTileY. The drawable/bitmap will be scrolled by the scrollAllSprites() & scrollAllLayers() methods, unless you use noScrollX & noScrollY, in which case scrolling canNOT be optimised. Note that if the bitmap has a mask then the background colour will show through.
setRegion() & getRegion() allow you to change & retrieve the rectangular region which the stack is responsible for drawing. If you set width/height to -1 then the right/bottom of the region is set to the edge of the window.
scrollAllSprites() causes all sprites to be to be moved by the same dx,dy pixels. It does this by changing the sprite positions. This is done very efficiently, without having to redraw most of the stack... UNLESS the background drawable is prevent from being scrolled (by noScrollX/Y). Or unless the scrolling is done in both X & Y directions.
You would tend to use this for game worlds where sprites only exist to be seen by the player (so you will want sprite positions to correspond to their on-screen position). For example Shoot-em'ups.
scrollAllLayers() causes all layers to be moved by dx,dy pixels (the sprites move along with their layer). It does this by changing the layer "origin". This is done very efficiently, without having to redraw most of the stack... UNLESS the background drawable is prevent from being scrolled (by noScrollX/Y)... Or unless the scrolling is done in both X & Y directions.
You would tend to use this for game worlds where sprites exist even when they cannot be seen by the player (so you will want the sprite positions to correspond to their position in the simulated game world). For example Real Time Strategy & RPG games.
/* more methods of cGfxStack */ METHOD setAutoRedraw(autoRedraw:BOOL) METHOD getAutoRedraw() RETURNS autoRedraw:BOOL METHOD redraw(forceFull=FALSE:BOOL)
setAutoRedraw() allows you to change whether the stack should automatically redraw itself after every change. It defaults to automatic redrawing, which is easier, but far less efficient.
If you disable autoRedraw then you must call the redraw() method when you have finished updating the stack. You would be advised to also disable cGfx's autoUpdate, and then call redraw() shortly before calling it's updateAndWaitForScreenRefresh() method. Note that the procedures of the 'std/cGfxSpriteSimple' module automatically call redraw(), so you don't have to.
getAutoRedraw() returns whether the stack is automatically redrawing or not.
redraw() forces the stack to redraw anything that you have changed since the last redraw(). If you give TRUE for forceFull then the entire stack will be redrawn, even where no sprites have changed. forceFull is useful if you want to "clean up" after have directly drawn inside the stack's area.
/* more methods of cGfxStack */ METHOD setAutoIsDrawable(autoIsDrawable:BOOL) METHOD getAutoIsDrawable() RETURNS autoIsDrawable:BOOL
setAutoIsDrawable() allows you to call cGfxLayer's setAutoIsDrawable() method on all the layers.
getAutoIsDrawable() returns the last value that the setAutoIsDrawable() method was called with. It is used by all layers that are created. By default autoIsDrawable is TRUE
Each cGfxLayer is a layer of cGfxSprites. Sprites in the layer above will always appear above the sprites in the layer below. Within a layer the sprites should not normally overlap, but if they do then those sprites will appear above or below each other according to their order in the layer (which you can change).
Sprite positions are relative to the "origin" of it's layer (which is normally the top left of the window). This can be used to make all the layer's sprites scroll in a direction.
/* Methods of cGfxLayer */ METHOD scrollSprites(dx, dy) METHOD scrollLayer(dx, dy) METHOD setOrigin(x, y) METHOD getOrigin() RETURNS x, y
scrollSprites() causes all sprites (on the layer) to be moved by dx,dy pixels. It does this by changing the sprite positions.
You would tend to use this for game worlds where sprites only exist to be seen by the player (so you will want sprite positions to correspond to their on-screen position). For example Shoot-em'ups.
scrollLayer() causes the layer to be moved by dx,dy pixels (the sprites will move along with the layer). It does this by changing the layer's "origin".
You would tend to use this for game worlds where sprites exist even when they cannot be seen by the player (so you will want the sprite positions to correspond to their position in the simulated game world). For example Real Time Strategy & RPG games.
setOrigin() & getOrigin() allow you to change & retrieve the "origin" of the layer, which will result in all the sprites moving.
/* more methods of cGfxLayer */ METHOD createSprite(x, y, drawable:PTR TO cGfxDrawable, hidden=FALSE:BOOL) RETURNS sprite:PTR TO cGfxSprite METHOD findSpriteAt(x, y, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite METHOD findSpriteOverlapping(sprite:PTR TO cGfxSprite, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite
createSprite() creates & returns a sprite at position x,y in the layer. You would usually give a bitmap for drawable, but other drawables (such as returned by the cGfx.makeText() method) are also fine. The sprite is created at the 'top' of the layer. If you give TRUE for hidden then the sprite won't be visible.
You can use the same bitmap/drawable for many sprites, allowing you to save video memory. But this also means you must NOT destroy the bitmap/drawable while you are using the sprite!
findSpriteAt() does the same as cGfxStack's findSpriteAt() method, except that it only searches this layer.
findSpriteOverlapping() does the same as cGfxStack's findSpriteOverlapping() method, except that it only searches this layer.
/* more methods of cGfxLayer */ METHOD createLayerBelow() RETURNS layer:PTR TO cGfxLayer METHOD infoAbove() RETURNS above:PTR TO cGfxLayer METHOD infoBelow() RETURNS below:PTR TO cGfxLayer METHOD infoHasSprites() RETURNS hasSprites:BOOL METHOD infoTopSprite() RETURNS sprite:PTR TO cGfxSprite METHOD infoBottomSprite() RETURNS sprite:PTR TO cGfxSprite
createLayerBelow() creates & returns a layer below the current one.
infoAbove() returns the layer above the current one, however if you are already on the top layer, then the bottom layer will be returned!
infoBelow() returns the layer below the current one, however if you are already on the bottom layer, then the top layer will be returned!
infoHasSprites() returns whether or not the layer contains any sprites.
infoTopSprite() returns the sprite at the top of the layer, which appears above all other sprites in that layer. If there are no sprites then an exception will be raised, so you should first check using infoHasSprites().
infoBottomSprite() returns the sprite at the bottom of the layer.
/* more methods of cGfxLayer */ METHOD setAutoIsDrawable(autoIsDrawable:BOOL) METHOD getAutoIsDrawable() RETURNS autoIsDrawable:BOOL
setAutoIsDrawable() allows you to change whether the sprites in this layer have their bitmaps/etc automatically made drawable or not (using cGfxBitmap's setIsDrawable() method) according to whether they are visible in the stack's region or not. Thus if a bitmap is not being used by any sprite that can be seen, then it will be made non-drawable, and so save your precious video memory! The downside to this is that it takes a short while to load the bitmap back into memory (when it becomes visible again), but you should not notice this unless many (or huge) bitmaps have to be loaded back at the same time.
The stack defaults to creating all layers with TRUE for autoIsDrawable.
getAutoIsDrawable() returns whether the sprites in this layer have their bitmaps/drawables automatically made drawable or not.
Each cGfxSprite is a bitmap that will be drawn at a given position. The position of sprites are unaffected by where cGfxStack's region is, and so are normally given using their actual position in the window. However, if the "origin" of the layer is moved away from the top left corner of the window, then the visible position of all sprites will be moved along with it.
/* Methods of cGfxSprite */ METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD infoLayer() RETURNS layer:PTR TO cGfxLayer METHOD infoAbove() RETURNS sprite:PTR TO cGfxSprite METHOD infoBelow() RETURNS sprite:PTR TO cGfxSprite METHOD infoIsInsideRegion(fullyInside=FALSE:BOOL) RETURNS insideRegion:BOOL
infoWidth() & infoHeight() return the size of the sprite.
infoLayer() returns the layer the sprite is in.
infoAbove() returns the sprite above the current one, however if you are already on the top sprite, then the bottom sprite will be returned!
infoBelow() returns the sprite below the current one, however if you are already on the bottom sprite, then the top sprite will be returned!
infoIsInsideRegion() returns whether the sprite is inside the stack's region (and thus potentially visible). By default fullyInside is FALSE, which means it returns TRUE even if the sprite is only partially inside the region. If you give TRUE for fullyInside then it only returns TRUE if the sprite is completely inside the region.
/* more methods of cGfxSprite */ METHOD move(dx, dy) METHOD setPosition(x, y) METHOD getPosition() RETURNS x, y METHOD setHidden(hidden:BOOL) METHOD getHidden() METHOD setDrawable(drawable:PTR TO cGfxDrawable, frame=0) METHOD getDrawable(frame=0) RETURNS drawable:PTR TO cGfxDrawable METHOD setFrame(frame) RETURNS exists:BOOL METHOD getFrame() RETURNS frame METHOD setTiled(tileX:BOOL, tileY:BOOL) METHOD getTiled() RETURNS tileX:BOOL, tileY:BOOL METHOD setData(data) METHOD getData() RETURNS data METHOD setDataBox(data:OWNS PTR TO class) METHOD getDataBox() RETURNS data:PTR TO class
move() allows you to change the sprite's position by dx,dy pixels.
setPosition() & getPosition() allow you to change & retrieve the position of the sprite within the layer. The position is relative to the layer's "origin".
setHidden() & getHidden() allow you to change & retrieve whether the sprite is invisible or not.
setDrawable() & getDrawable() allow you to change & retrieve the bitmap/drawable used by the sprite. If you supply a frame number, then you will store & retrieve the bitmap/drawable of the given animation frame.
Rather than just changing frame 0 to change the sprite's appearance, you should let the sprite know all the frames it will be showing, and then using setFrame() to change the shown frame. Not only is this easier to manage sprite animation, but the sprite will ensure that all frames are drawable (when autoIsDrawable is enabled) so that your animations are smooth.
setFrame() & getFrame() allow you to change & retrieve the currently shown frame number. setFrame() will return TRUE for exists when the given frame existed.
setTiled() & getTiled() allow you to change & retrieve whether the sprite is tiled across the whole window or not. Normal sprites are NOT tiled, but if you make them tiled then they appear to be infinitely wide (when tileX is TRUE) and/or infinitely tall (when tileY is TRUE). When tiled, their drawable will be repeated in a 'tiled' fashion, thus allowing you to easily have background(s) that go on 'forever'.
Note that tiled sprites can still be moved by changing their position. And you can still perform collision (hit/overlap) checks with tiled sprites.
setData() & getData() allow you to store & retrieve one piece of data for each sprite. If you need to store a PTR, ARRAY, STRING or LIST, then please use setDataBox() & getDataBox() instead.
setDataBox() & getDataBox() allow you to store & retrieve one box (containing a piece of data) for each sprite. This box typically contains some data related to the sprite. Note that the box is automatically deallocated.
Although you can store any class object, it is expected that typically you will store a "box", and thus will use the 'std/pBox' module. Here is a typical usage example:
mySprite.setDataBox(BoxARRAY('a string is an array!')) Print('The sprite contains "\s"\n', UnboxARRAY(mySprite.getDataBox()))
Here is a slightly more complex example:
mySprite.setDataBox(BoxSTRING(NEW 'this is turned into an e-STRING by NEW')) Print('The sprite contains "\s"\n', UnboxSTRING(mySprite.getDataBox()))
/* more methods of cGfxSprite */ METHOD overlaps(sprite:PTR TO cGfxSprite) RETURNS overlaps:BOOL METHOD moveToBottomOfLayer() METHOD moveToTopOfLayer() METHOD clone() RETURNS clone:PTR TO cGfxSprite
overlaps() returns whether the given sprite overlaps the current sprite. Bitmap masks are taken into account.
moveToBottomOfLayer() allows you to move the sprite to the 'bottom' of the layer, so all other sprites in the layer will appear above it.
moveToTopOfLayer() allows you to move the sprite to the 'top' of the layer, so all other sprites in the layer will appear below it.
clone() returns a new sprite, which is identical to the current one.
This module provides a fairly easy way of creating a GUI. It will look like a native GUI (such as MUI), but you don't need to know anything about the native GUI system, as it behaves the same whatever native GUI is used. It is rather easier to use than MUI, but not as flexible.
Currently it uses MUI (for all Amiga OSes), but it is hoped that eventually Reaction will be used for AmigaOS4.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
How to open a GUI window:
DEF win:PTR TO cGuiWindow, button:PTR TO cGuiButton CreateApp().build() ->you only need to do this once! win := CreateGuiWindow('demo') win.beginGroupVertical() win.addTextBox('label').setState('Hello world!').initFixedFont() button := win.addButton('OK') win.endGroup() win.build()
How to handle events from a single open window:
DEF quit:BOOL, item:PTR TO cGuiItem quit := FALSE REPEAT item := WaitForChangedGuiItem() IF item = NIL IF win.getCloseRequest() THEN quit := TRUE ELSE IF item = button quit := TRUE ENDIF UNTIL quit win.close()
How to handle events with SEVERAL open windows:
DEF quit:BOOL, item:PTR TO cGuiItem, itemWin:PTR TO cGuiWindow quit := FALSE REPEAT item, itemWin := WaitForChangedGuiItem() IF itemWin = win ->handle items of the "win" window IF item = NIL IF win.getCloseRequest() THEN quit := TRUE ELSE IF item = button quit := TRUE ENDIF ENDIF UNTIL quit win.close()
The following example programs use it:
Examples/std/GUI/SimpleCalculator.e Examples/std/GUI/SimpleModPlayer.e Examples/std/GUI/Amiga/DirList.e Examples/std/GUI/Amiga/NativeGuiExample.e Examples/std/GUI/Amiga/SimpleGameLauncher.e Examples/std/GUI/Amiga/Stacker.e
Released programs which are known to use it:
PictureAlbum ( cshandley.co.uk ) AmiSystemRestore ( os4depot.net/?function=showfile&file=utility/misc/amisystemrestore.lha ) Age of Thieves ( os4depot.net/?function=showfile&file=game/board/age_of_thieves.lha ) Ami-Ingenious ( os4depot.net/?function=showfile&file=game/board/ami-ingenious.lha ) FlowerWay ( os4depot.net/?function=showfile&file=game/puzzle/flowerway.lha ) HueFlow ( os4depot.net/?function=showfile&file=game/puzzle/hueflow.lha ) Ami-Scratch ( os4depot.net/?function=showfile&file=graphics/misc/amiscratch.lha ) Ami-Bootguard ( os4depot.net/?function=showfile&file=utility/misc/ami-bootguard.lha ) Ami-Lineapolis ( www.lineapolis.dizzy.pl )
CreateGuiWindow(title:ARRAY OF CHAR) RETURNS win:PTR TO cGuiWindow DestroyGuiWindow(win:PTR TO cGuiWindow) RETURNS nil:PTR TO cGuiWindow WaitForChangedGuiItem() RETURNS item:PTR TO cGuiItem, win:PTR TO cGuiWindow CheckForChangedGuiItem(keepPreviousChangedItems=FALSE:BOOL) RETURNS item:PTR TO cGuiItem, win:PTR TO cGuiWindow
CreateGuiWindow() creates & returns a cGuiWindow object for a new GUI window. You must supply a title (i.e. name) for your window. You must add GUI items to it, before building it. You can create as many windows as you want!
DestroyGuiWindow() destroys the supplied window, and it's contents. Your windows will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
WaitForChangedGuiItem() waits for a GUI item to be changed by the user (in any window). It then returns that item. You should find what has changed by checking the item's state (typically using the item's getState() method).
CheckForChangedGuiItem() checks whether any GUI item has been changed yet, and returns it if it has. But if nothing has changed, then it returns NIL for item. This method DOES clear the last event from all windows (except for the current one), unless you supplied TRUE for keepPreviousChangedItems.
When the GUI being used is MUI, you also get the following procedure:
PROC AddNativeSimple(win:PTR TO cGuiWindow, object:PTIO, triggerAttr=0, triggerValue=MUIV_NotTriggerValue, label=NIL:PTIO, isFixedWidth=TRUE:BOOL, isFixedHeight=TRUE:BOOL, useInCycleChain=TRUE:BOOL) RETURNS item:PTR TO cGuiNativeSimple
AddNativeSimple() creates a GUI object for user-specified MUI code, and adds it to the GUI. As there is no addNativeSimple() method for cGuiWindow, you must use this procedure instead.
You indicate the window using win. object is the MUI object to be embedded, while label is the optional label that will be shown next to the MUI object. triggerAttr & triggerValue are the MUI attribute & value (if any) that will cause WaitForChangedGuiItem()/etc to think this object has changed. triggerAttr is also used by the object's getState() method. isFixedWidth & isFixedHeight are used to indicate whether the MUI object has a fixed width or height, and is typically called during building to determine whether any padding needs to be added to allow the GUI to be resizable. useInCycleChain is used to indicate whether the MUI object should be part of the cycle chain.
Please see the following example for how this procedure would actually be used:
Examples/std/GUI/Amiga/NativeGuiExample.e
The cGuiWindow class is a window which contains a GUI. You must add GUI items to it, before building it. Once a GUI window is built, you cannot add any more GUI items. (In the future things may become a little more flexible.) Building the GUI will also open the window, unless you indicate otherwise. Windows may be opened & closed at any time.
GUI items are arranged within the window using groups, normally as horizontal & vertical rows. You can have groups inside of groups, which gives great flexibility. Beware that you cannot add any items to a window, until you have started a group.
Once a window is built, you must use the WaitForChangedGuiItem() or CheckForChangedGuiItem() procedure in a loop. They will tell you when the user changes a GUI item, as well as ensuring the GUI reacts to the user. You can also set GUI items to call a notification function when the user changes them.
/* Methods of cGuiWindow */ METHOD initAllowDropFiles() RETURNS self:PTR TO cGuiWindow METHOD infoAllowDropFiles() RETURNS allowDropFiles:BOOL METHOD initSaveID(id) RETURNS self:PTR TO cGuiWindow METHOD infoSaveID() RETURNS id
initAllowDropFiles() indicates that the window should allow files to be dropped on it. This must be called before the GUI is built.
infoAllowDropFiles() returns whether initAllowDropFiles() was used or not.
initSaveID() indicates the unique ID which should be used to identify the window, so that it's position & size can be automatically saved (when the window is closed) & reloaded (when the window is created again). It is suggested that you use a quad-character, such as "Main" or "Pref", although plain numbers (perhaps ENUMerated constants) are also fine. You are not allowed to use zero as an ID.
infoSaveID() returns the ID that was given to initSaveID(), or 0 if initSaveID() was never used.
/* more methods of cGuiWindow */ METHOD beginGroupHorizontal(borderTitle=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiGroupHorizontal METHOD beginGroupVertical( borderTitle=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiGroupVertical METHOD beginGroupGrid(width,borderTitle=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiGroupGrid METHOD beginGroupPage( borderTitle=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiGroupPage METHOD endGroup()
beginGroupHorizontal() marks the beginning of a horizontal group. All items in the group will be arranged horizontally. See 24.15. Methods of cGuiGroupHorizontal & cGuiGroupVertical for more info.
NOTE: If you give a borderTitle then the whole group itself has a name, and the group will gain a border if it doesn't already have one.
beginGroupVertical() marks the beginning of a vertical group. All items in the group will be arranged vertically. See 24.15. Methods of cGuiGroupHorizontal & cGuiGroupVertical for more info.
beginGroupGrid() marks the beginning of a grid group. All items in the group will be arranged in a grid.
You must give the width of the grid in items. Items added to the group get put in the first row, as if it was a horizontal group, but after width items have been added, further items will go into the next row, etc. See 24.16. Methods of cGuiGroupGrid for more info.
beginGroupPage() marks the beginning of a multi-page group. Each item in the group is treated as a separate "page", with only one page visible at a time. Normally each item would be a horizontal or vertical group. See 24.17. Methods of cGuiGroupPage for more info.
endGroup() marks the end of the current group.
/* more methods of cGuiWindow */ METHOD addBreak() METHOD addBar( title=NILA:ARRAY OF CHAR) METHOD addLabel( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiLabel METHOD addText( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiText METHOD addTextBox( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiTextBox METHOD addButton( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiButton METHOD addTick( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiTick METHOD addString( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiString METHOD addStringBox( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiStringBox METHOD addPathString( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiPathString METHOD addNumberString(label:ARRAY OF CHAR, min, max) RETURNS item:PTR TO cGuiNumberString METHOD addSlider( label:ARRAY OF CHAR, min, max) RETURNS item:PTR TO cGuiSlider METHOD addCycleChoice( label:ARRAY OF CHAR, stringChoices:ARRAY OF ARRAY OF CHAR) RETURNS item:PTR TO cGuiCycleChoice METHOD addRadioChoice( label:ARRAY OF CHAR, stringChoices:ARRAY OF ARRAY OF CHAR) RETURNS item:PTR TO cGuiRadioChoice METHOD addNative( newItem:OWNS PTR TO cGuiNativeItem) RETURNS item:PTR TO cGuiNativeItem METHOD infoCurrentBuildGroup() RETURNS item:PTR TO cGuiGroupItem
addBreak() adds an invisible separator (typically in a vertical group) between items, such that the items either side of the break are not aligned. It has a similar effect to addBar(), but there is no line visible.
addBar() adds a horizontal/vertical line (in a vertical/horizontal group). Used to clearly separate items within a group, and items either side of the line are not aligned. It may be given a title. See 24.18. Methods of cGuiBar for more info.
addLabel() adds text that looks the same as the labels of other items. It is typically used for displaying a single line of text, or as an 'empty item' in a page group. See 24.19. Methods of cGuiLabel for more info.
But it can also be used to fake your own "custom item". For example you can have a horizontal group, add an item with no label, and then add the label after it, to get a "custom item" that has the label on the right (instead of the left).
addText() adds a text line, for displaying a single line of text. You must supply the item's label. It's setState() method must be used to set the string to be displayed. See 24.20. Methods of cGuiText for more info.
addTextBox() adds a text box, for displaying multiple lines of text. You must supply the item's label. It's setState() method must be used to set the string to be displayed. See 24.21. Methods of cGuiTextBox for more info.
addButton() adds a button, which the user can click on. You must supply the item's label. See 24.22. Methods of cGuiButton for more info.
addTick() adds a tick button, which the user can toggle ticked or unticked. You must supply the item's label. It's setState() method can be used to set whether it is ticked or not. See 24.23. Methods of cGuiTick for more info.
addString() adds a string input line. You must supply the item's label. It's setState() method can be used to set the shown string. See 24.24. Methods of cGuiString for more info.
addStringBox() adds a multi-line string input box. You must supply the item's label. It's setState() method can be used to set the shown string. See 24.25. Methods of cGuiStringBox for more info.
addPathString() adds a path input line, for choosing the file/dir path of something. Typically it has a button that will open a file requester. You must supply the item's label. See 24.26. Methods of cGuiPathString for more info.
addNumberString() adds a number input line. You must supply the item's label, and the min & max allowed values. It's setState() method can be used to set the shown value. See 24.27. Methods of cGuiNumberString for more info.
addSlider() adds a slider, for choosing a number. You must supply the item's label, and the min & max allowed values. It's setState() method can be used to set the slider's position. See 24.28. Methods of cGuiSlider for more info.
addCycleChoice() adds a cyclable/pop-up choice box, for choosing from several fixed options. You must supply the item's label, and the list of actual choices for stringChoices, which must end with NILA:
e.g. ['first choice', 'second choice', 'etc', NILA]:ARRAY_OF_CHAR
It's setState() method can be used to set the selected choice. See 24.29. Methods of cGuiCycleChoice for more info.
addRadioChoice() adds a radio-style choice list, for choosing from several fixed options. You must supply the item's label, and the list of actual choices for stringChoices, which must end with NILA:
e.g. ['first choice', 'second choice', 'etc', NILA]:ARRAY_OF_CHAR
It's setState() method can be used to set the selected choice. See 24.30. Methods of cGuiRadioChoice for more info.
addNative() adds an already-created native object. The object would usually be a class which inherits from cGuiNativeHost.
infoCurrentBuildGroup() returns the current group that items are being added to. You are unlikely to need this method.
/* more methods of cGuiWindow */ METHOD beginFixedList(columns=1, borderTitle=NILA:ARRAY OF CHAR) OF cGuiWindow RETURNS item:PTR TO cGuiFixedList METHOD endFixedList() METHOD addFixedListEntry(label:ARRAY OF CHAR) OF cGuiWindow RETURNS item:PTR TO cGuiFixedListEntry METHOD beginList(columns=1, title=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiList METHOD endList() METHOD addListEntry(label:ARRAY OF CHAR, style=GUI_STYLE_NONE, marked=FALSE:BOOL, data=0, dataBox=NIL:OWNS PTR TO class)
beginFixedList() marks the beginning of a fixed list. columns defines how many 'vertically aligned labels' (aka columns) the list has. If you give a borderTitle then the whole list itself has a name, and the list will gain a border if it doesn't already have one. You may only add fixed list entries to it. See 24.31. Methods of cGuiFixedList for more info.
endFixedList() marks the end of the fixed list.
addFixedListEntry() adds an entry to the fixed list. Each entry is a single line of text, and they appear in the order they are added. The label defines the text for ALL columns of an entry, with each column being separated by a \t character. Each entry will have a tick box if the list was defined as having selectable entries. BEWARE that it always returns item=NIL if there is no tick box. See 24.32. Methods of cGuiFixedListEntry for more info.
beginList() marks the beginning of a (dynamic) list. columns defines how many columns the list has. If you give a title then the whole list itself has a visible name. You may only add (dynamic) list entries to it. See 24.33. Methods of cGuiList for more info.
endList() marks the end of the (dynamic) list.
addListEntry() adds a single entry to the (dynamic) list. Each entry is a single line of text, and they appear in the order they are added (if no sorting order is specified for the list). The label defines the text for ALL columns of an entry, with each column being separated by a \t character. See 24.33. Methods of cGuiList for more info, and especially it's "cursor" methods.
You can also specify if the entry should be shown with a style (GUI_STYLE_ALTCOLOUR or GUI_STYLE_BOLD), or be marked. You can also store data in it, which could be a dataBox.
/* more methods of cGuiWindow */ METHOD build(keepWindowClosed=FALSE:BOOL) METHOD open() METHOD close() METHOD infoIsOpen() METHOD infoTitle() RETURNS title:ARRAY OF CHAR
build() takes all the added GUI items, and creates the GUI using them. It then automatically opens the window, unless you gave TRUE for keepWindowClosed.
open() opens the window, so that it is visible.
close() closes the window, so that it is hidden. The GUI items will remember their last state, so they will appear about the same when the window is reopened.
infoIsOpen() returns whether the window is open or not.
infoTitle() returns the title you set using the CreateGuiWindow() procedure.
/* more methods of cGuiWindow */ METHOD getLastChangedItem() RETURNS item:PTR TO cGuiItem METHOD setLastChangedItem(item:PTR TO cGuiItem) METHOD getCloseRequest(doNotClear=FALSE:BOOL) RETURNS closeRequest:BOOL METHOD setCloseRequest(closeRequest:BOOL) METHOD getQuitRequest(doNotClear=FALSE:BOOL) RETURNS quitRequest:BOOL METHOD setQuitRequest(quitRequest:BOOL) METHOD getDroppedFile(doNotClear=FALSE:BOOL) RETURNS fileDropped:ARRAY OF CHAR METHOD setDroppedFile(fileDropped:ARRAY OF CHAR)
getLastChangedItem() returns the last item that was changed by the user.
setLastChangedItem() allows you to change (or clear) the indication of the last item that was changed by the user.
getCloseRequest() returns whether the window has received a close request, typically due to the user clicking on the window's close button. This information will be forgotten unless you supply TRUE for doNotClear.
setCloseRequest() allows you to change (or clear) the close request indication.
getQuitRequest() returns whether the App itself has received a quit request. All windows will receive the same quit request. This information will be forgotten unless you supply TRUE for doNotClear.
setQuitRequest() allows you to change (or clear) the quit request. This is shared by all windows.
getDroppedFile() returns the path of the file dropped on the window, or NILA if there was none. Beware that files will only be detected if initAllowDropFiles() was set. This information will be forgotten unless you supply TRUE for doNotClear.
setDroppedFile() allows you to change (or clear) the file dropped indication.
/* more methods of cGuiWindow */ METHOD getBusy() RETURNS busy:BOOL METHOD setBusy(busy:BOOL) METHOD getPosition() RETURNS x, y METHOD setPosition(x, y) METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD changeSize(width, height) METHOD queryExtra(specific:QUAD) RETURNS value, unknown:BOOL
getBusy() & setBusy() allow you to change & retrieve the window's busy state. A busy window will not accept user input, and the user will be able to see that the window is busy (depending on the target OS & GUI, it might appear ghosted or the mouse pointer might be an hourglass).
getPosition() return the position of the window.
setPosition() changes the position of the window. This can be done before the window is opened.
infoWidth() & infoHeight() return the size of the window.
changeSize() changes the size of the window. This can be done before the window is opened.
queryExtra() allows you to retrieve OS-specific information. For example, if you give "OBJT", then it will return the Amiga MUI window object. While "SIGS" will return all the Amiga MUI signals. "WIND" will return the Amiga window pointer. "SCRN" will return the Amiga screen pointer. And "APPL" will return the Amiga MUI application object. Please only use this method as a last resort, because it will stop your code from being portable!
The following GUI item classes are "abstract", which means they are never directly used for created objects. Instead they are used as parents of classes, to help organise similar GUI items together, and to allow them to share (some of) the same methods.
For example, the abstract cGuiInputItem class is used by all GUI items that allow the user to provide input, such as cGuiStringBox (but unlike cGuiLabel). The cGuiInputItem class (and all the classes that use it) has the setGhosted() method, which allows you to "ghost" the GUI item, preventing the user from changing it.
The name of every abstract class ends in "Item".
All GUI items eventually inherit this class. The main purpose is to allow all GUI items to be given to or returned as a PTR TO cGuiItem.
/* Methods of cGuiItem */ METHOD setData(data) RETURNS self:PTR TO cGuiItem METHOD getData() RETURNS data METHOD infoNextInGroup() RETURNS item:PTR TO cGuiItem METHOD queryExtra(specific:QUAD) RETURNS value, unknown:BOOL
setData() & getData() allow you to store & retrieve one value. This is useful if you have a large number of GUI items, and want to identify them by sequential numbers rather having a variable for each of their object pointers.
infoNextInGroup() returns the next item in the current group. You probably won't need to use this.
queryExtra() allows you to retrieve OS-specific information. At the moment there are very few uses of this method. Please only use this method as a last resort, because it will stop your code from being portable!
All groups inherit this class, and they are GUI items themselves.
/* Methods of cGuiGroupItem, which inherits from cGuiItem */ METHOD initScrollable() RETURNS self:PTR TO cGuiGroupItem METHOD initEqualSizedItems() RETURNS self:PTR TO cGuiGroupItem METHOD initUseLeastSpace() RETURNS self:PTR TO cGuiGroupItem METHOD infoHasBorder() RETURNS hasBorder:BOOL METHOD infoTitle() RETURNS title:ARRAY OF CHAR METHOD infoSize() RETURNS size METHOD infoFirstItem() RETURNS item:PTR TO cGuiItem METHOD infoLastItem() RETURNS item:PTR TO cGuiItem METHOD infoScrollable() RETURNS scrollable:BOOL METHOD infoEqualSizedItems() RETURNS equalSizedItems:BOOL METHOD infoUseLeastSpace() RETURNS useLeastSpace:BOOL METHOD setGhosted(ghosted:BOOL) RETURNS self:PTR TO cGuiGroupItem ->plus methods inherited from cGuiItem
For the inherited methods read 24.5. Methods of cGuiItem.
initScrollable() indicates that the group does not need to completely fit inside the window, and so will scroll if the window is too small.
initEqualSizedItems() indicates that all items in the group should have the same size (where possible).
initUseLeastSpace() indicates that the whole GUI group should use as little space as possible, including all items inside it. Beware that this could cause your window to have a fixed size.
infoHasBorder() returns TRUE if the group has a border, which it will if it was created with a string given to borderTitle.
infoTitle() returns the group's title, if it was not created with a non-empty string for borderTitle, otherwise it returns NILA. i.e. It returns NILA if '' was given for borderTitle.
infoSize() returns the number of items inside of the group.
infoFirstItem() returns the first item in the group.
infoLastItem() returns the last item in the group.
infoScrollable() returns whether initScrollable() was used or not.
infoEqualSizedItems() returns whether initEqualSizedItems() was used or not.
infoUseLeastSpace() returns whether initUseLeastSpace() was used or not.
setGhosted() calls the setGhosted() method on all the group's items.
This is inherited by any GUI item with a label. So it is used by most GUI items!
/* Methods of cGuiLabelledItem, which inherits from cGuiItem */ METHOD infoLabel() RETURNS label:ARRAY OF CHAR ->plus methods inherited from cGuiItem
For the inherited methods read 24.5. Methods of cGuiItem.
infoLabel() returns the label that the GUI item was created with.
This is inherited by any GUI item that can display some data. So it is used by most GUI items! It allows you to add a pop-up description to it.
/* Methods of cGuiOutputItem, which inherits from cGuiLabelledItem */ METHOD initUseLeastSpace() RETURNS self:PTR TO cGuiOutputItem METHOD infoUseLeastSpace() RETURNS useLeastSpace:BOOL METHOD setPopupHint(popupHint:NULL ARRAY OF CHAR) RETURNS self:PTR TO cGuiOutputItem METHOD getPopupHint() RETURNS popupHint:ARRAY OF CHAR ->plus methods inherited from cGuiLabelledItem
For the inherited methods read 24.7. Methods of cGuiLabelledItem.
initUseLeastSpace() indicates that the GUI item should use as little space as possible. Beware that this could cause your window to have a fixed size.
NOTE: This does not yet do anything for some GUI items.
infoUseLeastSpace() returns whether initUseLeastSpace() was used or not.
setPopupHint() & getPopupHint() allow you to change & retrieve a pop-up description to help the user. getPopupHint() will return NILA if there is no hint, while setPopupHint() may be supplied NILA to clear any existing hint. But don't rely on being able to change the pop-up hint after the GUI is built.
This is inherited by any GUI item that can accept some input from the user. It allows you to ghost the item, so that the user cannot change it. It also allows you to have a function called when the user changes it.
/* Methods of cGuiInputItem, which inherits from cGuiOutputItem */ METHOD setGhosted(ghosted:BOOL) RETURNS self:PTR TO cGuiInputItem METHOD getGhosted() RETURNS ghosted:BOOL METHOD setNotifyFunction(func:NULL PTR TO funcGuiNotify) RETURNS self:PTR TO cGuiItem METHOD getNotifyFunction() RETURNS func:PTR TO funcGuiNotify ->plus methods inherited from cGuiOutputItem
For the inherited methods read 24.8. Methods of cGuiOutputItem.
setGhosted() & getGhosted() allow you to change & retrieve the ghosted state. A ghosted item should not accept any user input.
setNotifyFunction() & getNotifyFunction() allow you to store & retrieve the notification function, which will be called whenever the user makes any changes. Your notification function must inherit funcGuiNotify, for example:
FUNC yourNotification(changedItem:PTR TO cGuiItem) OF funcGuiNotify IS ...
This is inherited by any GUI item that allows the user to change a string.
/* Methods of cGuiStringItem, which inherits from cGuiInputItem */ METHOD setState(string:ARRAY OF CHAR) RETURNS self:PTR TO cGuiStringItem METHOD getState() RETURNS string:ARRAY OF CHAR ->plus methods inherited from cGuiInputItem
For the inherited methods read 24.9. Methods of cGuiInputItem.
setState() & getState() allow you to change & retrieve the displayed string.
This is inherited by any GUI item that allows the user to change a number.
/* Methods of cGuiNumberItem, which inherits from cGuiInputItem */ METHOD setState(number) RETURNS self:PTR TO cGuiNumberItem METHOD getState() RETURNS number METHOD initUnit(unit:ARRAY OF CHAR) RETURNS self:PTR TO cGuiNumberItem METHOD infoUnit() RETURNS unit:ARRAY OF CHAR METHOD infoMin() RETURNS min METHOD infoMax() RETURNS max ->plus methods inherited from cGuiInputItem
For the inherited methods read 24.9. Methods of cGuiInputItem.
setState() & getState() allow you to change & retrieve the displayed number.
initUnit() sets the unit the number is a measure of; for example 'miles'.
infoUnit() returns the unit set using initUnit(), or NILA if none was set.
infoMin() & infoMax() returns the min & max values given when the item was created.
This is inherited by any GUI item that allows the user to choose from a list of several fixed options.
/* Methods of cGuiChoiceItem, which inherits from cGuiNumberItem */ METHOD setState(choice) RETURNS self:PTR TO cGuiChoiceItem METHOD getState() RETURNS choice METHOD infoChoices() RETURNS choices:ARRAY OF ARRAY OF CHAR ->plus methods inherited from cGuiNumberItem
For the inherited methods read 24.11. Methods of cGuiNumberItem.
setState() & getState() allow you to change & retrieve the currently selected choice. The first choice is 0.
infoChoices() returns the stringChoices given when the item was created.
This is inherited by any native GUI item, and indicates that it is basically an object wrapper for some (typically user-specified) native GUI code.
/* Methods of cGuiNativeItem, which inherits from cGuiItem */ ->plus methods inherited from cGuiItem
For the inherited methods read 24.5. Methods of cGuiItem.
The following GUI item classes are "real", which means they will be directly used for created objects. They will inherit an "abstract" class according to the kind of GUI items they are.
For example, the real cGuiStringBox class is an actual GUI item that you can add to the window. It inherits the abstract cGuiStringItem class, because it allows the user to change a string.
These are classes which arrange their GUI items in a horizontal or vertical row.
/* Methods of cGuiGroupHorizontal & cGuiGroupVertical, which inherits from cGuiGroupItem */ ->plus methods inherited from cGuiGroupItem
For the inherited methods read 24.6. Methods of cGuiGroupItem.
This class arranges it's GUI items in a grid.
/* Methods of cGuiGroupGrid, which inherits from cGuiGroupItem */ ->plus methods inherited from cGuiGroupItem
For the inherited methods read 24.6. Methods of cGuiGroupItem.
This class is a multi-page group. Each item in it is treated as a separate "page", with only one page visible at a time. Normally each item would be a horizontal or vertical group.
/* Methods of cGuiGroupPage, which inherits from cGuiGroupItem */ METHOD setState(pageNumber) RETURNS self:PTR TO cGuiGroupPage METHOD getState() RETURNS pageNumber METHOD setStateItem(pageItem:PTR TO cGuiItem) RETURNS self:PTR TO cGuiGroupPage METHOD getStateItem() RETURNS pageItem:PTR TO cGuiItem METHOD infoMaxPageNum() RETURNS pageNum METHOD infoPageNumOfPageItem(pageItem:PTR TO cGuiItem) RETURNS pageNumber METHOD infoPageItemOfPageNum(pageNumber) RETURNS pageItem:PTR TO cGuiItem ->plus methods inherited from cGuiGroupItem
For the inherited methods read 24.6. Methods of cGuiGroupItem.
setState() & getState() allow you to change & retrieve the currently shown page, using the page number. The first page is number 0.
setStateItem() & getStateItem() allow you to change & retrieve the currently shown page, using the actual page item to be shown.
infoMaxPageNum() returns the largest page number that exists.
infoPageNumOfPageItem() returns the page number of the provided page item.
infoPageItemOfPageNum() returns the page item of the provided page number.
This class is a horizontal/vertical line (in a vertical/horizontal group). It is used to clearly separate items within a group.
/* Methods of cGuiBar, which inherits from cGuiItem */ METHOD infoTitle() RETURNS title:ARRAY OF CHAR ->plus methods inherited from cGuiItem
For the inherited methods read 24.5. Methods of cGuiItem.
infoTitle() returns the title given when the item was created, or NILA if none was given.
This class shows some text that looks the same as the labels of other items.
/* Methods of cGuiLabel, which inherits from cGuiOutputItem */ METHOD initAlignLeft() RETURNS self:PTR TO cGuiLabel METHOD initAlignCenter() RETURNS self:PTR TO cGuiLabel METHOD initAlignRight() RETURNS self:PTR TO cGuiLabel METHOD infoAlignLeft() RETURNS isAlignedLeft :BOOL METHOD infoAlignCenter() RETURNS isAlignedCenter:BOOL METHOD infoAlignRight() RETURNS isAlignedRight :BOOL METHOD initStyle(style) RETURNS self:PTR TO cGuiLabel ->plus methods inherited from cGuiOutputItem
For the inherited methods read 24.8. Methods of cGuiOutputItem.
initAlignLeft(), initAlignCenter() & initAlignRight() indicates that the label should be left/center/right aligned. By default the alignment is the same as that used by the labels of other GUI items.
infoAlignCenter(), infoAlignCenter() & infoAlignRight() returns whether initAlignLeft(), initAlignCenter() & initAlignRight() was used or not.
initStyle() indicates that the label's text should be shown with the given style, which can be GUI_STYLE_ALTCOLOUR (typically a more noticable colour) or GUI_STYLE_BOLD. Styles of different types can be combined using the OR operator.
This class shows a single line of text. It usually defaults to a variable-width font, but it can use a fixed-width (mono-spaced) font if you want.
/* Methods of cGuiText, which inherits from cGuiOutputItem */ METHOD setState(text:ARRAY OF CHAR) RETURNS self:PTR TO cGuiText METHOD getState() RETURNS text:ARRAY OF CHAR METHOD initFixedFont() RETURNS self:PTR TO cGuiTextBox METHOD initAlignCenter() RETURNS self:PTR TO cGuiTextBox METHOD initAlignRight() RETURNS self:PTR TO cGuiTextBox METHOD infoFixedFont() RETURNS fixedFont:BOOL METHOD infoAlignCenter() RETURNS isAlignedCenter:BOOL METHOD infoAlignRight() RETURNS isAlignedRight :BOOL ->plus methods inherited from cGuiOutputItem
For the inherited methods read 24.8. Methods of cGuiOutputItem.
setState() & getState() allow you to change & retrieve the currently shown text.
initFixedFont() indicates that a fixed-width font should be used. This must be called before the GUI is built.
initAlignCenter() & initAlignRight() indicates that the shown text should be center/right aligned (rather than the default of left alignment).
infoFixedFont() returns whether initFixedFont() was used or not.
infoAlignCenter() & infoAlignRight() returns whether initAlignRight() or initAlignCenter() was used or not.
This class shows multiple lines of text. It usually defaults to a variable-width font, but it can use a fixed-width (mono-spaced) font if you want.
/* Methods of cGuiTextBox, which inherits from cGuiOutputItem */ METHOD setState(text:ARRAY OF CHAR) RETURNS self:PTR TO cGuiTextBox METHOD getState() RETURNS text:ARRAY OF CHAR METHOD initFixedFont() RETURNS self:PTR TO cGuiTextBox METHOD infoFixedFont() RETURNS fixedFont:BOOL ->plus methods inherited from cGuiOutputItem
For the inherited methods read 24.8. Methods of cGuiOutputItem.
setState() & getState() allow you to change & retrieve the currently shown text.
initFixedFont() indicates that a fixed-width font should be used. This must be called before the GUI is built.
infoFixedFont() returns whether initFixedFont() was used or not.
This class is for a button, which the user can click on. Although it has no "state", you will still be notified that is has changed when the user clicks on it.
/* Methods of cGuiButton, which inherits from cGuiInputItem */ METHOD initPic(picPath:ARRAY OF CHAR) RETURNS self:PTR TO cGuiInputItem METHOD infoPic() RETURNS picPath:ARRAY OF CHAR ->plus methods inherited from cGuiInputItem
For the inherited methods read 24.9. Methods of cGuiInputItem.
initPic() adds a picture to the button, next to it's label. The file path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() procedure first.
infoPic() returns the picture path set using initPic(), or NILA if none was set.
This class is a tick button, which the user can toggle ticked or unticked.
/* Methods of cGuiTick, which inherits from cGuiInputItem */ METHOD setState(ticked:BOOL) RETURNS self:PTR TO cGuiTick METHOD getState() RETURNS ticked:BOOL ->plus methods inherited from cGuiInputItem
For the inherited methods read 24.9. Methods of cGuiInputItem.
setState() & getState() allow you to change & retrieve the ticked/unticked state.
This class is a string input line, which allows the user to change the string.
/* Methods of cGuiString, which inherits from cGuiStringItem */ METHOD initMaxLength(maxLength) RETURNS self:PTR TO cGuiString ->plus methods inherited from cGuiStringItem ->METHOD setState(string:ARRAY OF CHAR) RETURNS self:PTR TO cGuiString ->METHOD getState() RETURNS string:ARRAY OF CHAR
For the inherited methods read 24.10. Methods of cGuiStringItem.
initMaxLength() indicates that maximum number of characters that the user may enter (some implementations may be unlimited & ignore this). This must be called before the GUI is built.
This class is a multi-line string input box, which allows the user to change the string. It usually defaults to a variable-width font, but it can use a fixed-width (mono-spaced) font if you want.
/* Methods of cGuiStringBox, which inherits from cGuiStringItem */ METHOD initFixedFont() RETURNS self:PTR TO cGuiStringBox METHOD infoFixedFont() RETURNS fixedFont:BOOL ->plus methods inherited from cGuiStringItem ->METHOD setState(string:ARRAY OF CHAR) RETURNS self:PTR TO cGuiStringBox ->METHOD getState() RETURNS string:ARRAY OF CHAR
For the inherited methods read 24.10. Methods of cGuiStringItem.
initFixedFont() indicates that a fixed-width font should be used. This must be called before the GUI is built.
infoFixedFont() returns whether initFixedFont() was used or not.
This class is a path input line, for choosing the file/dir path of something. Typically it has a button that will open a file requester.
It's getState() method is used to retrieve the chosen path. The path is returned in the portable format used by the cPath module, so you may need to use it's ExportPath() procedure afterwards.
It's setState() method can be used to set the shown path. The path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() or ImportDirPath() procedure first.
/* Methods of cGuiPathString, which inherits from cGuiStringItem */ METHOD initOnlyShowFolders() RETURNS self:PTR TO cGuiPathString METHOD initUseSaveMode() RETURNS self:PTR TO cGuiPathString METHOD initShowSystemFiles() RETURNS self:PTR TO cGuiPathString
initOnlyShowFolders() indicates that the file requester should only show folders (not files). This must be called before the GUI is built.
initUseSaveMode() indicates that the file requester should use 'save mode', which means it will ask about replacing existing files. This must be called before the GUI is built.
initShowSystemFiles() indicates that the file requester should show system files (which on the Amiga means show .info files). This must be called before the GUI is built.
/* more methods of cGuiPathString */ METHOD infoOnlyShowFolders() RETURNS onlyShowFolders:BOOL METHOD infoUseSaveMode() RETURNS useSaveMode:BOOL METHOD infoShowSystemFiles() RETURNS showSystemFiles:BOOL ->plus methods inherited from cGuiStringItem ->METHOD setState(string:ARRAY OF CHAR) RETURNS self:PTR TO cGuiPathString ->METHOD getState() RETURNS string:ARRAY OF CHAR
For the inherited methods read 24.10. Methods of cGuiStringItem.
infoOnlyShowFolders() returns whether initOnlyShowFolders() was used or not.
infoUseSaveMode() returns whether initUseSaveMode() was used or not.
infoShowSystemFiles() returns whether initShowSystemFiles() was used or not.
This class is a number input line, which only allows the user to enter a number. It also ensures that the number is within an allowed range.
/* Methods of cGuiNumberString, which inherits from cGuiNumberItem */ ->plus methods inherited from cGuiNumberItem ->METHOD setState(number) RETURNS self:PTR TO cGuiNumberString ->METHOD getState() RETURNS number ->METHOD initUnit(unit:ARRAY OF CHAR) RETURNS self:PTR TO cGuiNumberString ->METHOD infoUnit() RETURNS unit:ARRAY OF CHAR ->METHOD infoMin() RETURNS min ->METHOD infoMax() RETURNS max
For the inherited methods read 24.11. Methods of cGuiNumberItem.
This class is a slider, for choosing a number within an allowed range.
/* Methods of cGuiSlider, which inherits from cGuiNumberItem */ ->plus methods inherited from cGuiNumberItem ->METHOD setState(number) RETURNS self:PTR TO cGuiSlider ->METHOD getState() RETURNS number ->METHOD initUnit(unit:ARRAY OF CHAR) RETURNS self:PTR TO cGuiSlider ->METHOD infoUnit() RETURNS unit:ARRAY OF CHAR ->METHOD infoMin() RETURNS min ->METHOD infoMax() RETURNS max
For the inherited methods read 24.11. Methods of cGuiNumberItem.
This class is a cyclable/pop-up choice box, for choosing from several fixed options.
/* Methods of cGuiCycleChoice, which inherits from cGuiChoiceItem */ ->plus methods inherited from cGuiChoiceItem ->METHOD setState(choice) RETURNS self:PTR TO cGuiCycleChoice ->METHOD getState() RETURNS choice ->METHOD infoChoices() RETURNS choices:ARRAY OF ARRAY OF CHAR
For the inherited methods read 24.12. Methods of cGuiChoiceItem.
This class is a radio-style choice list, for choosing from several fixed options.
/* Methods of cGuiRadioChoice, which inherits from cGuiChoiceItem */ ->plus methods inherited from cGuiChoiceItem ->METHOD setState(choice) RETURNS self:PTR TO cGuiRadioChoice ->METHOD getState() RETURNS choice ->METHOD infoChoices() RETURNS choices:ARRAY OF ARRAY OF CHAR
For the inherited methods read 24.12. Methods of cGuiChoiceItem.
This class is a scrollable list of entries, where each entry is a single line of text. If the list is defined as having selectable entries, then each entry will have a tick box.
List entries canNOT be added after the GUI is built, nor can they be modified, hence the name "fixed list".
It is not suitable for very large lists, because every entry is built out of several other cGui items. This means that large lists will take a long time to build, and will probably use a lot of memory.
The main advantage of cGuiFixedList over the dynamic lists (of cGuiList) is that it is built using other GUI items, and so is much more likely to be supported by any newly-added GUI systems (on say Linux or whatever).
/* Methods of cGuiFixedList, which inherits from cGuiGroupItem */ METHOD initSelectableEntries(multiSelect=FALSE:BOOL) RETURNS self:PTR TO cGuiFixedList METHOD initColumnAlignment(alignment:ARRAY OF CHAR) RETURNS self:PTR TO cGuiFixedList METHOD initColumnTitles(titles:ARRAY OF CHAR) RETURNS self:PTR TO cGuiFixedList METHOD infoSelectableEntries() RETURNS selectable:BOOL, multiSelect:BOOL METHOD infoColumnAlignment() RETURNS alignment:ARRAY OF CHAR METHOD infoColumnTitles() RETURNS titles:ARRAY OF CHAR METHOD infoColumns() RETURNS columns METHOD infoSelectionCount() RETURNS selectionCount METHOD infoSingleSelectionEntry() RETURNS item:PTR TO cGuiFixedListEntry METHOD setMultiSelect(multiSelect:BOOL) METHOD getMultiSelect() RETURNS multiSelect:BOOL ->plus methods inherited from cGuiGroupItem ->METHOD infoHasBorder() RETURNS hasBorder:BOOL ->METHOD infoTitle() RETURNS title:ARRAY OF CHAR ->METHOD infoSize() RETURNS size ->METHOD infoFirstItem() RETURNS item:PTR TO cGuiFixedListEntry ->METHOD infoLastItem() RETURNS item:PTR TO cGuiFixedListEntry ->METHOD setGhosted(ghosted:BOOL) ->the following inherited methods are NOT supported ->METHOD initScrollable() RETURNS self:PTR TO cGuiFixedList ->METHOD initEqualSizedItems() RETURNS self:PTR TO cGuiFixedList ->METHOD infoScrollable() RETURNS scrollable:BOOL ->METHOD infoEqualSizedItems() RETURNS equalSizedItems:BOOL
For the inherited methods read 24.6. Methods of cGuiGroupItem.
initSelectableEntries() indicates that the list's entries are selectable by the user. Normally selecting a second entry will cause the first to become unselected, but if you give TRUE for multiSelect then all entries stay selected (until unselected). This method must be called before any entries are added.
initColumnAlignment() indicates how the columns should be aligned. alignment is a string, with one character per column, where "L" means left aligned, "C" means center aligned, and "R" means right aligned. Thus 'LLCR' means left align the first two columns, then center the next column, then right align the next column. By default everything is left aligned.
initColumnTitles() indicates what title should appear at the top of each column. The titles defines the text for ALL columns, with each column being separated by a \t character. BEWARE that the titles are a kludge, as they actually appear inside the scrollable list, and so they will not be visible when it is scrolled vertically.
infoSelectableEntries() returns whether initSelectableEntries() was used or not. It also returns what multiSelect was supplied when it was called.
infoColumnAlignment() returns the "alignment" string which represents how the columns will be aligned (see the initColumnAlignment() description for more details).
infoColumnTitles() returns the "titles" string which was given to initColumnTitles(), or NILA if none was given.
infoColumns returns the number of columns the list was created with.
infoSelectionCount() returns how many entries are selected.
infoSingleSelectionEntry() returns the selected entry, or NIL if nothing is selected. It may only be used when multiSelect=FALSE.
setMultiSelect() & getMultiSelect() allow you to change & retrieve multiSelect, but only if you used initSelectableEntries(TRUE).
This class is a single line of text, which appears inside a scrollable list. Optionally it can be selectable, which means that it will have a tick box next to the text.
/* Methods of cGuiFixedListEntry, which inherits from cGuiItem */ METHOD setState(ticked:BOOL) METHOD getState() RETURNS ticked:BOOL METHOD infoLabel() RETURNS label:ARRAY OF CHAR METHOD infoIndex() RETURNS index METHOD initStyle(style) RETURNS self:PTR TO cGuiFixedListEntry METHOD setGhosted(ghosted:BOOL) METHOD getGhosted() RETURNS ghosted:BOOL METHOD setNotifyFunction(func:NULL PTR TO funcGuiNotify) METHOD getNotifyFunction() RETURNS func:PTR TO funcGuiNotify ->plus methods inherited from cGuiItem ->setData(data) RETURNS self:PTR TO cGuiFixedListEntry ->getData() RETURNS data ->infoNextInGroup() RETURNS item:PTR TO cGuiFixedListEntry
For the inherited methods read 24.5. Methods of cGuiItem.
setState() & getState() allow you to change & retrieve the selection state.
infoLabel() returns the label that the GUI item was created with.
infoIndex() returns the unique number used to identify this entry. The first entry is 0, the second is 1, and so on. (If this is not a convenient way to identify entries, don't forget that you can use setData() & getData() as with any GUI item.)
initStyle() indicates that the line of text should be shown with the given style, which can be GUI_STYLE_ALTCOLOUR (typically a more noticable colour) or GUI_STYLE_GHOSTEDCOLOUR (typically a less noticable colour) or GUI_STYLE_BOLD. Styles of different types can be combined using the OR operator, but you can only use one colour.
setGhosted() & getGhosted() are the same as in 24.9. Methods of cGuiInputItem.
setNotifyFunction() & getNotifyFunction() are the same as in 24.9. Methods of cGuiInputItem.
This class is a scrollable list of entries, where each entry is a single line of text. If the list is defined as having selectable entries, then each entry can be (un)highlighted by clicking it.
List entries may be added before or after the GUI is built, and they can be modified (typically via the list's "cursor" methods). The list can also be sorted, which changes the order of the entries. This is why the list is described as "dynamic", and is a big advantage over cGuiFixedList.
It is suitable for very large lists, as the entries are stored & rendered in an efficient manner.
Several words have very specific meanings:
/* Methods of cGuiList, which inherits from cGuiInputItem */ METHOD initSelectableEntries(multiSelect=FALSE:BOOL, autoUnselect=FALSE:BOOL) RETURNS self:PTR TO cGuiList METHOD initColumnTitles(titles:ARRAY OF CHAR) RETURNS self:PTR TO cGuiList METHOD initColumnAlignment(alignment:ARRAY OF CHAR) RETURNS self:PTR TO cGuiList METHOD initColumnSortType(type:ARRAY OF CHAR) RETURNS self:PTR TO cGuiList METHOD infoSelectableEntries() RETURNS selectable:BOOL, multiSelect:BOOL, autoUnselect:BOOL METHOD infoColumnTitles() RETURNS titles:ARRAY OF CHAR METHOD infoColumnAlignment() RETURNS alignment:ARRAY OF CHAR METHOD infoColumnSortType() RETURNS type:ARRAY OF CHAR METHOD infoColumns() RETURNS columns METHOD infoSelectionCount() RETURNS selectionCount METHOD infoSingleSelectionEntry() RETURNS label:STRING METHOD infoTitle() RETURNS title:ARRAY OF CHAR METHOD infoSize() RETURNS size METHOD queryExtra(specific:QUAD) RETURNS value, unknown:BOOL
initSelectableEntries() indicates that the list's entries are selectable by the user. Normally selecting a second entry will cause the first to become unselected, but if you give TRUE for multiSelect then all entries stay selected (until unselected). Normally multi-selected entries stay selected until unselected by the user, but if you give TRUE for autoUnselect then any new selection(s) will automatically unselect any previous selections.
initColumnTitles() indicates what title should appear at the top of each column. The titles defines the text for ALL columns, with each column being separated by a \t character.
initColumnAlignment() indicates how the columns should be aligned. alignment is a string, with one character per column, where "L" means left aligned, "C" means center aligned, and "R" means right aligned. Thus 'LLCR' means left align the first two columns, then center the next column, then right align the next column. By default everything is left aligned.
initColumnSortType() indicates the how each column should be used for sorting. type is a string, with one character per column, where "I" means case Insensitive, "S" means case Sensitive, and "N" means Number (so that it is treated as a number). Thus 'IISN' means the first two columns should use case insensitive sorting, then the next column should use case sensitive sorting, then the next column should be sorted as a number. By default everything is sorted case insensitively.
infoSelectableEntries() returns whether initSelectableEntries() was used or not. It also returns what multiSelect & autoUnselect was supplied when it was called.
infoColumnTitles() returns the "titles" string which was given to initColumnTitles(), or NILA if none was given.
infoColumnAlignment() returns the "alignment" string which represents how the columns will be aligned (see the initColumnAlignment() description for more details).
infoColumnSortType() returns the "type" string which represents how the columns will be sorted (see the initColumnSortType() description for more details).
infoColumns returns the number of columns the list was created with.
infoSelectionCount() returns how many entries are selected.
infoSingleSelectionEntry() returns the selected entry, or NIL if nothing is selected. It may only be used when multiSelect=FALSE.
infoTitle() returns the title the list was created with, or NILA if none was specified.
infoSize() returns the number of entries in the list.
queryExtra() allows you to retrieve OS-specific information. For example, if you give "OBJT", then it will return the Amiga MUI object. Please only use this method as a last resort, because it will stop your code from being portable!
/* more methods of cGuiList */ METHOD addEntry(labels:OWNS STRING, style=GUI_STYLE_NONE, marked=FALSE:BOOL, data=0, dataBox=NIL:OWNS PTR TO class, moveCursorToEntry=FALSE:BOOL) METHOD update( labels:OWNS STRING) METHOD addEntryF(func:PTR TO fGuiListEntries) METHOD updateF( func:PTR TO fGuiListEntries)
addEntry() adds an entry to the list. The entry's position depends on the list's sorting mode, but it will add it to the bottom of an unsorted list. You can add more than one entry at a time, by making labels a linked-list of STRINGs (see Link() in section 5.10. E-strings).
Beware that the list takes ownership of the labels e-strings, so you must not destroy (nor access) them yourself.
You can also specify if the entry should be shown with an style (GUI_STYLE_ALTCOLOUR or GUI_STYLE_BOLD), or be marked. You can also store data in it, which could be a dataBox. Beware that if you are adding a linked-list of e-STRINGs, then only the first one will get dataBox.
If you supply TRUE for moveCursorToEntry then the list's cursor will be left on the added entry. If labels lists several entries, then the cursor is left on the first one.
Note that this is the only method which can change the list's contents before the GUI is built.
update() replaces the entire contents of the list with the entries given by the linked-list of e-string labels. This is better than deleting all entries & then adding them, because (a) already-existing entries stay selected/marked/etc, (b) it should be quicker, and (c) the user won't see all the entries disaappear & then reappear (rather new entries will be added & missing entries will be removed).
However, it is required that the list is sorted. And it is assumed that entries which are equal for sorting purposes, are actually the same entry, and thus the un-sorted parts of a label are updated with that given in the new label. You can use setSortByFunction() to ensure this makes sense, if setSortByColumn() isn't sufficient. Use setSortByFunction(fGuiListSort) if the entire label defines a unique entry.
Beware that the list takes ownership of the labels e-strings, so you must not destroy (nor access) them yourself.
addEntryF() adds multiple entries to the list. The supplied function is called, and every entry it returns is added to the list, stopping only when it returns labels=NILS. Your function must inherit fGuiListEntries, for example:
FUNC yourEntries() OF fGuiListEntries RETURNS label:OWNS STRING, style, marked:BOOL, data, dataBox:OWNS PTR TO class IS ...
See addEntry() for information about the returned variables. The main benefit of addEntryF() over addEntry() is that you can add multiple entries at the same time while still giving each entry unique values for style, marked, data & dataBox.
updateF() replaces the entire contents of the list with the entries returned by calling the supplied function (until it returns labels=NILS). It is better than deleting all entries & then adding them, for the same reasons as update(). It is better than update() in that each entry can have unique values for style, marked, data & dataBox. Your function must follow the same restrictions as for addEntryF().
/* more methods of cGuiList */ METHOD setSortByNone() METHOD getSortByNone() RETURNS isSortByNone:BOOL METHOD setSortByColumn(column, reverse=FALSE:BOOL) METHOD getSortByColumn() RETURNS isSortByColumn:BOOL, column, reverse:BOOL METHOD setSortByUser(initialColumn=0, initialReverse=FALSE:BOOL) METHOD getSortByUser() RETURNS isSortByUser:BOOL, column, reverse:BOOL METHOD setSortByFunction(sortFunc:PTR TO fGuiListSort) METHOD getSortByFunction() RETURNS isSortByFunction:BOOL, sortFunc:PTR TO fGuiListSort
setSortByNone() & getSortByNone() allow you to make the list unsorted (which is the default), and check whether this is the case. When the list is unsorted you can use the cursor_beforeInsert() & cursor_afterInsert() methods.
setSortByColumn() & getSortByColumn() allow you to make the list sorted by a particular column, and check whether this is the case. column indicates which column is sorted (the first column is 0). reverse indicates that the column is using the opposite of the normal sorting order.
setSortByUser() & getSortByUser() allow you to let the user sort the list how they like, and check whether this is the case. initialColumn & initialReverse indicate how the list should initially be sorted. column & reversed indicate how it is currently sorted.
setSortByFunction() & getSortByFunction() allow you to make the list sorted in an arbitrary manner, and check whether this is the case. The sortFunc function is called to compare the labels of two entries, to see if one entry should come before or after another entry.
A skeleton function looks like this:
FUNC yourSortFunc(firstLabel:ARRAY OF CHAR, secondLabel:ARRAY OF CHAR, firstData, secondData, firstDataBox:PTR TO class, secondDataBox:PTR TO class) OF fGuiListSort RETURNS order:RANGE -1 TO 1 ENDFUNC
Conceptually this function returns the Sign() of "second - first", although the implementation is up to you. For example, you might implement it like this:
order := OstrCmpNoCase(firstLabel, secondLabel)
More complex implementations might compare particular columns, by searching for \t characters within each label. Or if the entries contain Data or DataBox values, then it might compare these.
For getSortByFunction(), note that although isSortByFunction will be FALSE for SortByColumn & SortByUser, it will still return a valid sortFunc function that you can use.
/* more methods of cGuiList */ METHOD getEventSelectionChanged(doNotClear=FALSE:BOOL) RETURNS selectionChanged:BOOL METHOD setEventSelectionChanged(selectionChanged:BOOL) METHOD getEventDoubleClickedEntry(moveCursorToEntry=FALSE:BOOL, doNotClear=FALSE:BOOL) RETURNS label:ARRAY OF CHAR METHOD setEventDoubleClickedEntry() METHOD getEventSortedByUser(doNotClear=FALSE:BOOL) RETURNS sortedByUser:BOOL, column, reverse:BOOL METHOD setEventSortedByUser(sortedByUser:BOOL)
getEventSelectionChanged() returns whether the list's selections were changed by the user. This information will be forgotten unless you supply TRUE for doNotClear.
setEventSelectionChanged() allows you to change (or clear) the list selection indication.
getEventDoubleClickedEntry() returns the last entry that was double-clicked by the user, or NILA if none was. If you supply TRUE for moveCursorToEntry, then the cursor will be moved to the double-clicked entry. This information will be forgotten unless you supply TRUE for doNotClear.
setEventDoubleClickedEntry() allows you to change (or clear) the double-clicked indication.
getEventSortedByUser() returns whether the list was sorted by the user, and if so then how it is now sorted. This information will be forgotten unless you supply TRUE for doNotClear.
setEventSortedByUser() allows you to change (or clear) the sorted event indication.
/* more methods of cGuiList */ METHOD cursor_gotoStart() RETURNS success:BOOL METHOD cursor_gotoEnd() RETURNS success:BOOL METHOD cursor_gotoNext(steps=1) RETURNS movedSteps METHOD cursor_gotoPrev(steps=1) RETURNS movedSteps METHOD cursor_gotoFirstSelected() RETURNS success:BOOL METHOD cursor_gotoNextSelected() RETURNS success:BOOL METHOD cursor_find(label:ARRAY OF CHAR, noCase=FALSE:BOOL, compareLength=0, continueFromLastMatch=FALSE:BOOL) RETURNS success:BOOL METHOD cursor_walkToStart() RETURNS oldPosition METHOD cursor_isAtStart() RETURNS isAtStart:BOOL METHOD cursor_isAtEnd() RETURNS isAtEnd:BOOL
cursor_gotoStart() moves the cursor to the first entry of the list. It returns FALSE if the list is empty.
cursor_gotoEnd() moves the cursor to the last entry of the list. It returns FALSE if the list is empty.
cursor_gotoNext() moves the cursor forward by steps entries. steps may be zero or even negative. It returns the actual number of moved steps, which may be less than requested (or even zero) if the end of the list was reached.
cursor_gotoPrev() moves the cursor backwards by steps entries. steps may be zero or even negative. It returns the actual number of moved steps, which may be less than requested (or even zero) if the start of the list was reached.
cursor_gotoFirstSelected() moves the cursor to the first selected entry. It returns FALSE if there were no selected entries.
cursor_gotoNextSelected() moves the cursor to the next selected entry. It returns FALSE if there were no selected entries.
cursor_find() moves to the cursor to the entry matching the given label, returning FALSE if no match was found. Normally the matching is case sensitive, but if TRUE is given for noCase then it is case insensitive. If compareLength is >0 then only the first compareLength characters of label & the entry are compared. If compareLength is <0 then only the last -compareLength characters of label & the entry are compared. Normally the search starts from the beginning of the list, but if TRUE is given for continueFromLastMatch then it continues the search from the current cursor position, to look for another match.
cursor_walkToStart() goes to the first entry of the list, and returns how many entries it passed through (and thus what it's original position was). This is useful if you need to move the cursor & want to restore it's position later, but beware that it may be slow depending on how the target GUI implements a list. If the list is empty then it returns -1.
cursor_isAtStart() returns whether or not the cursor is on the first entry of the list.
cursor_isAtEnd() returns whether or not the cursor is on the last entry of the list.
/* more methods of cGuiList */ METHOD cursor_setLabel(label:ARRAY OF CHAR, goto0newSortedLocation1next2prev=0) METHOD cursor_getLabel() RETURNS label:ARRAY OF CHAR METHOD cursor_setStyle(style) METHOD cursor_getStyle() RETURNS style METHOD cursor_setState(selected:BOOL) METHOD cursor_getState() RETURNS selected:BOOL METHOD cursor_setMarked(marked:BOOL) METHOD cursor_getMarked() RETURNS marked:BOOL METHOD cursor_setData(data) METHOD cursor_getData() RETURNS data METHOD cursor_setDataBox(data:OWNS PTR TO class) METHOD cursor_getDataBox() RETURNS data:PTR TO class
cursor_setLabel() & cursor_getLabel() allow you to change & retrieve the label of the current entry.
When the label of an entry is changed in a sorted list, the entry will be moved to a different location. By default the cursor will follow the entry to it's new location, but you can use goto0newSortedLocation1next2prev to do something different (supply 1 to move the cursor to the next entry (before the entry is moved), or 2 to move the cursor to the previous entry).
cursor_setStyle() & cursor_getStyle() allow you to change & retrieve the style of the current entry. When style is GUI_STYLE_ALTCOLOUR, the text should appear in an alternative (typically more noticable) colour. When style is GUI_STYLE_GHOSTEDCOLOUR then the text should appear in a ghosted (typically less noticable) colour. When style is GUI_STYLE_BOLD then the text will be bold. Styles of different types can be combined using the OR operator, but you can only use one colour.
cursor_setState() & cursor_getState() allow you to change & retrieve the selection state of the current entry.
cursor_setMarked() & cursor_getMarked() allow you to change & retrieve whether or not the current entry is marked.
cursor_setData() & cursor_getData() allow you to store & retrieve one piece of data for the current entry. If you need to store a PTR, ARRAY, STRING or LIST, then please use setDataBox() & getDataBox() instead.
cursor_setDataBox() & cursor_getDataBox() allow you to store & retrieve one box (containing a piece of data) for the current entry. This box typically contains some data related to the entry. Note that the box is automatically deallocated.
Although you can store any class object, it is expected that typically you will store a "box", and thus will use the 'std/pBox' module. Here is a typical usage example:
myList.cursor_setDataBox(BoxARRAY('a string is an array!')) Print('The entry contains "\s"\n', UnboxARRAY(myList.cursor_getDataBox()))
Here is a slightly more complex example:
myList.cursor_setDataBox(BoxSTRING(NEW 'this is turned into an e-STRING by NEW')) Print('The entry contains "\s"\n', UnboxSTRING(myList.cursor_getDataBox()))
/* more methods of cGuiList */ METHOD cursor_beforeInsert(labels:OWNS STRING, style=GUI_STYLE_NONE, marked=FALSE:BOOL, data=0, dataBox=NIL:OWNS PTR TO class) METHOD cursor_afterInsert( labels:OWNS STRING, style=GUI_STYLE_NONE, marked=FALSE:BOOL, data=0, dataBox=NIL:OWNS PTR TO class) METHOD cursor_destroy(gotoPrev=FALSE:BOOL) RETURNS movedToExpectedEntry:BOOL METHOD cursor_remove( gotoPrev=FALSE:BOOL) RETURNS label:OWNS STRING, movedToExpectedEntry:BOOL
cursor_beforeInsert() & cursor_afterInsert() allow you to insert entries before or after the current cursor position. You can insert more than one entry at a time by supplying a linked-list of e-strings.
This may only be used on an UNsorted list.
Beware that the list takes ownership of the labels e-strings, so you must not destroy (nor access) them yourself.
You can also specify if the entry should be shown with a style, or be marked. You can also store data in it, which could be a dataBox. Beware that if you are adding a linked-list of e-STRINGs, then only the first one will get dataBox.
cursor_destroy() allows you to destroy the current entry. The cursor is moved to the next entry, unless you give TRUE to gotoPrev (in which case it is moved to the previous entry). If the cursor could not be moved in the expected direction (due to being at the edge of the list), then it will return FALSE for movedToExpectedEntry.
cursor_remove() allows you to remove the current entry. It is the same as the cursor_destroy() method, except that it returns the entry's label (as an e-string that you take ownership of & therefore must take care to destroy it).
/* more methods of cGuiList */ METHOD markAll() METHOD marked_unmark() METHOD marked_setStyle(style) METHOD marked_setState(selected:BOOL) METHOD marked_destroy(gotoPrevIfRemoved=FALSE:BOOL) RETURNS entriesDestroyed METHOD marked_remove( gotoPrevIfRemoved=FALSE:BOOL) RETURNS labels:OWNS STRING ->plus methods inherited from cGuiInputItem
For the inherited methods read 24.9. Methods of cGuiInputItem.
markAll() is a simple way to mark all the entries in the list. It is expected that you will do this before calling one of the "marked" methods (see below).
marked_unmark() allows you to unmark all entries.
marked_setStyle() allows you to set all marked entries to the same style.
marked_setState() allows you to set all marked entries to the same selection state.
marked_destroy() allows you to destroy all the marked entries. It returns the number of destroyed entries. If the cursor is on an entry being destroyed, then it will be moved to the next entry unless TRUE is given for gotoPrevIfRemoved (in which case it will be moved to the previous entry).
marked_remove() allows you to remove all the marked entries. It is the same as the marked_destroy() method, except that it returns all of the entry's labels (as a linked-list of e-strings, which you take ownership of).
This class is a wrapper for any native GUI code that has been added using the AddNativeSimple() procedure.
/* Methods of cGuiNativeSimple, which inherits from cGuiNativeItem */ METHOD setState(state) METHOD getState() RETURNS state ->plus methods inherited from cGuiNativeItem
For the inherited methods read 24.13. Methods of cGuiNativeItem.
setState() & getState() allow you to change & retrieve the state of the GUI element (atleast where such state can be represented by a single VALUE).
When the GUI being used is MUI, they allow you to change & retrieve the MUI attribute specified by the triggerAttr parameter given to AddNativeSimple().
This class is used as the parent of any "native GUI class", which the user can create to wrapper some native GUI code. Here is what a native Tick class might look like:
CLASS cGuiNativeTick OF cGuiNativeHost initialState:BOOL label :OWNS STRING ENDCLASS
/* Methods of cGuiNativeHost, which inherits from cGuiNativeItem */ METHOD initShared() METHOD infoGroupIsOfClassType(type:CLASSTYPE) RETURNS isOfClassType:BOOL ->plus methods inherited from cGuiNativeItem
For the inherited methods read 24.13. Methods of cGuiNativeItem.
initShared() must be called at the end of the constructor.
infoGroupIsOfClassType() allows the class to check what kind of group it is inside. This can be used during building to choose the best native GUI code.
There are also a whole bunch of methods that are specific to the native GUI system being used:
/* Methods of cGuiNativeHost, which are specific to MUI */ METHOD infoIsFixedWidth() RETURNS METHOD infoIsFixedHeight() RETURNS METHOD build() RETURNS muiItems:OWNS LIST, object:PTIO, label:PTIO METHOD setupNotify(watchObject:PTIO, actionHook:PTR TO hook, param:ILIST) METHOD infoUseInCycleChain() RETURNS useInCycleChain:BOOL METHOD infoObject() RETURNS object:PTIO METHOD infoLabel() RETURNS label :PTIO
infoIsFixedWidth() & infoIsFixedHeight() is used to indicate whether the MUI object has a fixed width or height. It is typically called during building (before build() is called) to determine whether any padding needs to be added to allow the GUI to be resizable.
build is used to create the MUI elements, as previously described in it's constructor & any subsequent set or init method calls. Here is how it might look for a CheckMark:
PROC build() OF cGuiNativeTick RETURNS muiItems:OWNS LIST, object:PTIO, label:PTIO muiItems := NEW [Child, label := Label2(self.label), Child, object := CheckMark(IF self.initialState THEN MUI_TRUE ELSE MUI_FALSE)] ENDPROC
setupNotify() is used to set-up notification for the MUI object, so that WaitForChangedGuiItem()/etc knows when the user has interacted with it. This method is automatically called after build(). Here is how it might look for a CheckMark:
PROC setupNotify(watchObject:PTIO, actionHook:PTR TO hook, param:ILIST) OF cGuiNativeTick muim_Notify_action(watchObject, MUIA_Selected, MUIV_EveryTime, actionHook, param) ENDPROC
infoUseInCycleChain() is used to indicate whether the MUI object should be part of the cycle chain. This method is automatically called after build().
infoObject() returns the MUI object created by the build() method. You might need to know this when implementing new methods for your class, such as getState() or setState() methods.
infoLabel() returns the MUI label object (if any) created by the build() method. You might need to know this when implementing new methods for your class.
Please see the following example for how this class would actually be used:
Examples/std/GUI/Amiga/NativeGuiExample.e
This module provides an easy way of playing music, which is suitable for games & multimedia.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
NOTE: Currently it can only load & play Protracker music (using the ptplay.library). I expect to add MP3 support in the future.
How to play music:
DEF music:PTR TO cMusic CreateApp().build() ->you only need to do this once! music := LoadMusic('MyMusic.mod') music.play()
How to wait for the music to finish playing:
music.waitForPlayToFinish()
A more flexible way to wait for the music to finish playing:
WHILE WaitForMusicEvent() <> music DO EMPTY
Here's another way to play music:
CreateApp().build() ->you only need to do this once! StoreMusic('test', 0, LoadMusic('MyMusic.mod')) UseMusic('test', 0).play()
The following example programs use it:
Examples/std/GUI/SimpleModPlayer.e Examples/std/Multimedia/ShadowOfTheBlitz_Scroller/SOTB.e Examples/std/Multimedia/ShootEmUp/ShootEmUp.e Examples/std/Multimedia/StarsDemo.e
PROC LoadMusic(file:ARRAY OF CHAR, allowReturnNIL=FALSE:BOOL) RETURNS music:PTR TO cMusic PROC DestroyMusic(music:PTR TO cMusic) RETURNS nil:PTR TO cMusic PROC WaitForMusicEvent() RETURNS music:PTR TO cMusic PROC CheckForMusicEvent() RETURNS music:PTR TO cMusic PROC StoreMusic(name:ARRAY OF CHAR, number, music:OWNS PTR TO cMusic) RETURNS storedMusic:PTR TO cMusic PROC UseMusic(name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS music:PTR TO cMusic
LoadMusic() loads the given music, and returns a cMusic object for it. The file path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() procedure first. If the file could not be loaded, then an exception will be raised (unless TRUE was given to allowReturnNIL, in which case NIL would be returned instead).
DestroyMusic() destroys the supplied music object. Your music will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
WaitForMusicEvent() waits for any playing music to stop (unless one has already stopped), and then returns that music. Note that it will only remember the most recent events (typically the last 100), so ensure that you watch for events regularly.
CheckForMusicEvent() checks if any previously playing music has stopped, and returns that music. If no music has stopped, then it returns NIL.
StoreMusic() & UseMusic() allow you to store & retrieve music using a name string, and optionally a number. The string must be an 'immediate string', not one you have created. It returns the stored music, so you can use it straight away. Here's an example of how you might use it:
StoreMusic('title', 0, LoadMusic('music/Title.mod')) UseMusic('title', 0).play()
If you try to store more than one music with the same name & number combination, then an exception will be raised. This is to prevent you accidentally reusing them. And if you try to use a non-existant music, then an exception will be raised; unless you gave TRUE for allowReturnNIL, in which case NIL will be returned.
The cMusic class is music which can be played. You can only play one piece of music at a time. Playing a new piece of music will stop the previously playing one.
/* Methods of cMusic */ METHOD play(playCount=1) METHOD stop() METHOD infoLength() RETURNS milliSeconds METHOD infoIsPlaying() RETURNS isPlaying:BOOL METHOD waitForPlayToFinish() METHOD setVolume(volume) RETURNS music:PTR TO cMusic METHOD getVolume() RETURNS volume
play() starts playing the music, using the given parameters. playCount indicates how many times the music should be played (back to back). Use 0 if you want the music to play forever.
stop() stops the music from playing.
infoLength() returns the length of the music in milliseconds.
infoIsPlaying() returns whether or not the music is currently playing.
waitForPlayToFinish() pauses until the music has stopped playing.
setVolume() & getVolume() allow you to change & retrieve volume. This is how loud the music will be played, where 100 is maximum volume, 50 is half volume, 0 is silent, and so on. It is used by subsequent play() calls, and it also affects the music if it is currently playing.
This module provides easy access to files & directories. It hides the host OS's path format (and any DOS quirks). So it should work identically whatever OS is used, and thus allow the same file/directory code everywhere.
As you typically only want to handle paths, or files, or directories, but not all three, this module has been split into three smaller modules, so that you can reduce your executable size & compile time. These modules are:
Supported OSes: All.
Note that you automatically get 'std/cPath_shared' if you use either 'std/cPath_File' or 'std/cPath_Dir'.
While the module has many procedures & methods (to do almost anything you could ever want), these examples should cover the main things you might want to do.
How to turn a host OS path into a portable path that we can use:
DEF portablePath:STRING portablePath := ImportFilePath('path of some file') Print('The portable path is "\s".\n', portablePath) IF ExistsPath(portablePath) THEN Print('It exists!\n') END portablePath
How to create or open a directory:
DEF dir:PTR TO cDir NEW dir.new() IF dir.open('examplePortablePath/') ->use the directory now IF dir.getAttributes() AND CPA_DELETE = 0 THEN Print('The folder is protected from deletion.\n') dir.close() ENDIF END dir
How to create or open a file:
DEF file:PTR TO cFile NEW file.new() IF file.open('examplePortablePath.txt') ->use the file now Print('The file size is \d bytes.\n', file.getSize() !!VALUE) file.close() ENDIF END file
How to read the contents of an opened file:
DEF buffer:ARRAY OF BYTE, size size := file.getSize() !!VALUE NEW buffer[size+1] file.setPosition(0) file.read(buffer, size) buffer[size] := 0 ->make it a valid string Print('The file contents:\n') Print('\s\n', buffer) END buffer
How to add an immediate string to the end of an opened file:
file.setPosition(-1) file.write('Hello world!\n', STRLEN)
How to add a variable string to the end of an opened file:
DEF myString:ARRAY OF CHAR myString := 'Hello world!\n' file.setPosition(-1) file.write(myString, StrLen(myString))
How to list the contents of an opened directory:
DEF list:PTR TO cDirEntryList Print('The folder "\s" contains:\n', dir.getName()) list := dir.makeEntryList() IF list.gotoFirst() REPEAT Print('* \s\n', list.infoName()) UNTIL list.gotoNext() = FALSE ENDIF END list
How to check a file or directory exists:
IF ExistsPath('portablePath') Print('It exists!\n') ENDIF
How to delete a file or (empty) directory:
IF DeletePath('portablePath') = FALSE Print('Failed to delete it!\n') ENDIF
How to turn a portable path back into a host OS path the user will expect:
DEF hostPath:STRING hostPath := ExportPath('portable/path/of/some file or directory') Print('The host OS path is "\s".\n', hostPath) END hostPath
The following example programs use it:
Examples/std/Shell/AmigaAttributes.e Examples/std/Shell/BinDif.e Examples/std/Shell/DeleteModuleCache.e Examples/std/Shell/PEGCC.e Examples/std/Shell/RecursiveDir.e Examples/std/Shell/ToyInterpreter/ToyInterpreter.e
Released programs which are known to use it:
FolderSync2 ( cshandley.co.uk ) AmigaAttributes ( cshandley.co.uk ) PictureAlbum ( cshandley.co.uk ) Age of Thieves ( os4depot.net/?function=showfile&file=game/board/age_of_thieves.lha ) Ami-Ingenious ( os4depot.net/?function=showfile&file=game/board/ami-ingenious.lha ) FlowerWay ( os4depot.net/?function=showfile&file=game/puzzle/flowerway.lha ) HueFlow ( os4depot.net/?function=showfile&file=game/puzzle/hueflow.lha ) Ami-Scratch ( os4depot.net/?function=showfile&file=graphics/misc/amiscratch.lha ) Ami-Bootguard ( os4depot.net/?function=showfile&file=utility/misc/ami-bootguard.lha ) Ami-Lineapolis ( www.lineapolis.dizzy.pl )
So that you can more easily understand the procedures & methods, here are a few common terms:
All of these procedures can also be found in the smaller 'std/cPath_shared' module, with the exception of DeleteDirPath(), CreateDirs() & RecurseDir().
PROC IsFile(path:ARRAY OF CHAR) RETURNS isFile:BOOL PROC IsDir( path:ARRAY OF CHAR) RETURNS isDir:BOOL PROC FastIsFile(path:STRING) RETURNS isFile:BOOL PROC FastIsDir( path:STRING) RETURNS isDir:BOOL PROC InvalidFilePath(filePath:ARRAY OF CHAR) RETURNS invalid:BOOL PROC InvalidFileName(fileName:ARRAY OF CHAR) RETURNS invalid:BOOL PROC InvalidDirPath( dirPath:ARRAY OF CHAR) RETURNS invalid:BOOL PROC InvalidDirName( dirName:ARRAY OF CHAR) RETURNS invalid:BOOL PROC StrCmpPath( path1:ARRAY OF CHAR, path2:ARRAY OF CHAR, len=ALL, firstOffset=0, secondOffset=0) RETURNS match:BOOL PROC OstrCmpPath(path1:ARRAY OF CHAR, path2:ARRAY OF CHAR, max=ALL, firstOffset=0, secondOffset=0) RETURNS sign:RANGE -1 TO 1
IsFile() & IsDir() check whether the given path is for a file or dir, by checking whether it ends in a slash or not. Since a dir always ends in a slash, this is completely reliable.
FastIsFile() & FastIsDir() are faster versions of IsFile() & IsDir(), but they require that the given path is an e-string.
InvalidFilePath(), InvalidFileName(), InvalidDirPath() & InvalidDirName() check whether the given path/name conforms to basic validity rules, such as ending with a slash or not.
StrCmpPath() is like StrCmp() & StrCmpNoCase(), but with the case-sensitivity determined by the host OS. i.e. Case-sensitive for Linux, and case-insensitive for everything else.
OstrCmpPath() is like OstrCmp() & OstrCmpNoCase(), but with the case-sensitivity determined by the host OS.
PROC FindName( path:ARRAY OF CHAR) RETURNS name:ARRAY OF CHAR, nameLength PROC ExtractName( path:ARRAY OF CHAR) RETURNS name:OWNS STRING PROC ExtractDevice( path:ARRAY OF CHAR) RETURNS devicePath:OWNS STRING PROC ExtractSubPath(path:ARRAY OF CHAR) RETURNS subPath:OWNS STRING
FindName() finds the name in a (file or directory) path, and returns a name array that points to it. It also returns the name length as nameLength.
ExtractName() returns an e-string containing a copy of the name in a path.
ExtractDevice() returns an e-string containing a copy of the device in a path (which will end in a :/), or an empty e-string if there is no device.
ExtractSubPath() returns an e-string containing a copy of everything except the name in a path.
PROC CurrentDirPath() RETURNS dirPath:OWNS STRING PROC ExistsPath( path:ARRAY OF CHAR, fileOrDir=FALSE:BOOL) RETURNS exists:BOOL PROC RenamePath( origPath:ARRAY OF CHAR, newPath:ARRAY OF CHAR, force=FALSE:BOOL) RETURNS success:BOOL PROC DeletePath( path:ARRAY OF CHAR, force=FALSE:BOOL, fileOrDir=FALSE:BOOL) RETURNS success:BOOL PROC DeleteDirPath(dirPath:ARRAY OF CHAR, force=FALSE:BOOL) RETURNS success:BOOL PROC ImportDirPath( hostDirPath:ARRAY OF CHAR) RETURNS dirPath:OWNS STRING PROC ImportFilePath(hostFilePath:ARRAY OF CHAR) RETURNS filePath:OWNS STRING PROC ExportPath(path:ARRAY OF CHAR) RETURNS hostPath:OWNS STRING PROC ExpandPath(path:ARRAY OF CHAR) RETURNS expandedPath:OWNS STRING PROC MakeUniquePath(file1dir2, dirPath:ARRAY OF CHAR, base=NILA:ARRAY OF CHAR) RETURNS newPath:OWNS STRING
CurrentDirPath() returns the program's current directory as an e-string.
ExistsPath() returns whether the given file/dir exists. If fileOrDir is TRUE then it will ignore whether the given path is for a file or dir (since many filingsystems disallow files with the same names as directories).
RenamePath() attempts to rename the given file/dir, changing it from origPath to newPath, and returning whether it succeeded or not. It will fail if the file is read or write protected, unless force is used to tell it to temporarily unprotect the file/dir.
DeletePath() attempts to delete the given file/dir, returning whether it succeeded or not. It will fail if the directory is not empty. If force is TRUE then it will unprotect the file/dir before attempting to delete it. If fileOrDir is TRUE then it will ignore whether the given path is for a file or dir (since many filingsystems disallow files with the same names as directories).
DeleteDirPath() attempts to delete the given dir, and everything it contains, including all sub-directories, returning whether it completely succeeded or not. If force is TRUE then it will unprotect any dirs before attempting to delete them.
ImportFilePath() & ImportDirPath() converts a host OS file/directory path into the portable format, returning an e-string. If a NILA parameter is supplied, then NILS will be returned.
ExportPath() converts a portable path into the host OS file/directory format, returning an e-string. If a NILA parameter is supplied, then NILS will be returned.
ExpandPath() takes a portable path and makes it as full & unamiguous as possible. Thus it replaces any aliases or links or assignments with the actual physical path, and ensures that the path is not relative to the current directory. It returns an e-string.
MakeUniquePath() creates an e-string path that does not yet exist inside dirPath. For file1dir2, 1 returns a file path, while 2 returns a dir path. If base is not given then it will default to 'TMP'. The name of the created path (inside dirPath) will begin with base, if it is supplied.
PROC ReadLink( path:ARRAY OF CHAR) RETURNS targetPath:OWNS STRING, specific:QUAD PROC CreateLink(path:ARRAY OF CHAR, targetPath:ARRAY OF CHAR, specific:QUAD) RETURNS success:BOOL, unknown:BOOL PROC CreateDirs(path:ARRAY OF CHAR, ignoreName=FALSE:BOOL) RETURNS success:BOOL PROC RecurseDir(dirPath:ARRAY OF CHAR, funcFile:PTR TO funcRecurseFile, funcDir=NIL:PTR TO funcRecurseDir, funcDirFailure=NIL:PTR TO funcRecurseDirFailure, funcDirAbort=NIL:PTR TO funcRecurseDirAbort)
ReadLink() examines a link at path, returning the targetPath of the link & the specific type of the link. If path is not a link (or does not exist at all), then it returns NILS for targetPath & 0 for specific.
It's main benefit is that it allows getting the target of a soft link, when the target does not exist (and so cannot be opened using cFile).
CreateLink() creates a link from path to targetPath of the type given by specific. path must not exist, while targetPath should exist, otherwise it will return FALSE for success. It will return FALSE for unknown unless specific was not recognised.
This is much more efficient than creating an empty file with cFile/cDir, and then using changeExtra() to turn it into a link. As with changeExtra(), targetPath must be in the portable format.
CreateDirs() ensures that all the dirs of a given path exist, creating them if necessary, and returning whether it succeeded or not. If ignoreName is TRUE then the final file/dir at the end of the path is ignored.
RecurseDir() recursively scans the dirPath directory (and sub-directories), calling the supplied funcFile function on every file it finds. If the optional funcDir function is supplied, then it calls that on every sub-directory it finds, and only scans that directory if the function returns TRUE. If the optional funcDirFailure function is supplied, then it calls that when opening a directory for scanning fails, and continues with further scans if the function returns TRUE. All three functions are passed the path as a STRING, with funcDirFailure also being passed two strings explaining the failure's origin & reason. Note that directory scanning is performed breadth-first & in alphanumerical (sorted) order.
If a Ctrl-C is received then scanning is halted. By default it will then raise a "BRK" exception, but if the optional funcDirAbort function is supplied, then it calls that with the next directory that would have been scanned, and then RecurseDir() returns.
Thus skeleton functions look like this:
FUNC yourFuncFile(filePath:STRING) OF funcRecurseFile ENDFUNC FUNC yourFuncDir(dirPath:STRING) OF funcRecurseDir RETURNS scanDir:BOOL scanDir := TRUE ENDFUNC FUNC yourFuncDirFailure(dirPath:STRING, failureOrigin=NILA:ARRAY OF CHAR, failureReason=NILA:ARRAY OF CHAR) OF funcRecurseDirFailure RETURNS continueScan:BOOL continueScan := TRUE ENDFUNC
FUNC yourFuncDirAbort(nextDirPath:STRING) OF funcRecurseDirAbort Raise("BRK") ENDFUNC
And RecurseDir() would use them like this:
RecurseDir('your dir', yourFuncFile, yourFuncDir, yourFuncDirFailure, yourFuncDirAbort)
But if you are feeling particularly clever, then you can combine the first two directory functions into one, whose skeleton looks like this:
FUNC yourFuncDir2(dirPath:STRING, failureOrigin=NILA:ARRAY OF CHAR, failureReason=NILA:ARRAY OF CHAR) OF funcRecurseDirFailure RETURNS doScan:BOOL IF failureOrigin doScan := TRUE ->equivalent to continueScan := TRUE ELSE doScan := TRUE ->equivalent to scanDir := TRUE ENDIF ENDFUNC
And you would use it like this:
RecurseDir('your dir', yourFuncFile, yourFuncDir2, yourFuncDir2)
Alternatively, another clever thing you can do is combine the file & first directory functions into one, whose skeleton looks like this:
FUNC yourFuncFileDir(path:STRING) OF funcRecurseDir RETURNS scanDir:BOOL
IF FastIsFile(path) ->do file stuff ELSE ->do dir stuff scanDir := TRUE ENDIF ENDFUNC
And you would use it like this:
RecurseDir('your dir', yourFuncFileDir, yourFuncFileDir, yourFuncDirFailure)
You could even combine this function with the funcDirFailure directory function, in a similar fashion to before, which is left as an exercise for the reader.
Note that the funcRecurseDirAbort function must always be implemented separately.
This (abstract) class is the parent of both the cFile & cDir classes, so that both files & directories share many methods. This mean that not only are there less methods for you to learn, but it also allows you to treat files & directories in a similar way.
(And advanced users can write procedures which take a cPath (instead of a cFile or cDir), so that they will work on both files & directories.)
So please keep in mind that the following methods apply to both files & directories!
The cPath class can also be found in the smaller 'std/cPath_shared' module.
/* Methods of cPath, which inherits cExtra */ METHOD open(path:ARRAY OF CHAR, readOnly=FALSE:BOOL, forceOpen=FALSE:BOOL) RETURNS success:BOOL METHOD create(path:ARRAY OF CHAR, doNotReplace=FALSE:BOOL, forceOpen=FALSE:BOOL) RETURNS success:BOOL METHOD close() METHOD flush() METHOD sleep() METHOD clone(writeNotRead=FALSE:BOOL) RETURNS clone:OWNS PTR TO cPath METHOD infoFailureReason() RETURNS reason:ARRAY OF CHAR METHOD infoFailureOrigin() RETURNS origin:ARRAY OF CHAR METHOD infoReadOnly() RETURNS readOnly:BOOL METHOD infoIsOpen() RETURNS isOpen:BOOL
open() must be used before any other method. And if you wish to use any setX() methods, then readOnly must be FALSE. If forceOpen is TRUE then it will *temporarily* clear any read or write protection, so that the file can be opened. Be sure to check that TRUE is returned for success, and if it isn't then you can use infoFailureReason()/etc just like for any other method that fails.
create() is an alternative to open, which ensures that an empty file/dir is created. If the file/dir already exists then normally it will delete that file/dir, but if doNotReplace is TRUE then it will just fail (returning FALSE).
close() must be used when you are finished with the file/dir, and before you use open() again. In read-write mode, all cached changes are comitted to disk.
flush() forces the cache to be emptied. In read-only mode the cache will be refreshed with current information, while in read-write mode all cached changes will be comitted to disk.
sleep() indicates you won't be accessing this file/dir for some time, and so it is OK to free any major resources (typically the file read/write cache), which MAY require flushing some caches. This allows you to have lots of files open, without wasting much memory on file caches.
clone() creates another object with the same file/dir open, but in read-only mode unless writeNotRead is TRUE. If it fails to open the file/dir, then it will return NIL.
infoFailureReason() & infoFailureOrigin() return strings that describe the reason for the last failure & the method in which the failure originated. No return codes are provided, because these would be inherantly non-portable.
infoReadOnly() returns the readOnly value that open() was supplied with.
infoIsOpen() returns whether anything is currently open.
/* more methods of cPath */ METHOD setAttributes(attr, mask=-1) RETURNS success:BOOL METHOD getAttributes() RETURNS attr METHOD getAttributesSupported() RETURNS mask METHOD setPath(path:ARRAY OF CHAR) RETURNS success:BOOL METHOD getPath() RETURNS path:ARRAY OF CHAR METHOD setSubPath(path:ARRAY OF CHAR) RETURNS success:BOOL METHOD getSubPath() RETURNS path:OWNS STRING METHOD setName(name:ARRAY OF CHAR) RETURNS success:BOOL METHOD getName() RETURNS name:ARRAY OF CHAR ->plus methods inherited from cExtra
For the inherited methods read 26.8. Methods of cExtra.
setAttributes() changes the attributes (flags) to attr, but only affects the attributes given by mask. The available attribute are:
CPA_STRICT, CPA_READ, CPA_WRITE, CPA_DELETE, CPA_HIDE, CPA_UNUSED1, CPA_UNUSED2, CPA_UNUSED3, CPA_UNUSED4
Note that CPA_STRICT affects how the other attributes are interpreted, for example: The FAT filing system combines the meaning of CPA_WRITE & CPA_DELETE into one flag. Without CPA_STRICT you must clear both CPA_WRITE & CPA_DELETE before either of them is cleared. But with CPA_STRICT you only need to clear either of CPA_WRITE or CPA_DELETE before both are cleared.
getAttributes() returns the current attributes, such as CPA_READ. Note that CPA_STRICT has no meaning here.
getAttributesSupported() returns a mask indicating which attributes are supported by the current host OS.
setPath() & getPath() allow you to change & retrieve the complete path (subpath & name) of the current file/dir as an e-string.
setSubPath() & getSubPath() allow you to change & retrieve the subpath of the current file/dir. Changing the subpath is equivalent to moving it. BEWARE that getSubPath() returns a new string, which you must END when you are finished with it.
setName() & getName() allow you to change & retrieve the name of the current file/dir. Changing the name is equivalent to renaming it.
This class is for handling files. You must create an object (using the new() method), after which you can open() & close() files as many times as you want.
The cFile class can also be found in the smaller 'std/cPath_File' module.
/* Methods of cFile, which inherits cPath */ METHOD new(padByte=0:BYTE) METHOD open(filePath:ARRAY OF CHAR, readOnly=FALSE:BOOL, forceOpen=FALSE:BOOL, atPastEndNotStart=FALSE:BOOL) RETURNS success:BOOL METHOD read( buffer:ARRAY, lengthInBytes, offsetInBytes=0, toByte=-1:INT) RETURNS nextPos:BIGVALUE, numOfPadBytes METHOD write(buffer:ARRAY, lengthInBytes, offsetInBytes=0, noAutoExtend=FALSE:BOOL) RETURNS nextPos:BIGVALUE, numOfLostBytes METHOD infoPadByte() RETURNS padByte:BYTE
new() is the object's constructor. You can specify a pad byte other than 0 here.
open() has the additional atPastEndNotStart parameter. Normally the read/write position is at the start of a file, but if atPastEndNotStart is TRUE then it will be just past the end of the file.
read() reads lengthInBytes bytes into the buffer from the current read/write position. The current position is not changed by this method, so you must use the setPosition() method to change it. Luckily it returns the next sequential position, nextPos, should you need it.
offsetInBytes is an offset into the buffer (to avoid pointer arithmetic). Pad bytes will appear if you read after the end of the file. If toByte is given then it will not read past the occurance of the first toByte byte, with the remainder of the buffer being filled with pad bytes. If you read past the end of the file, then the buffer will similarly be filled with pad bytes.
write() writes lengthInBytes bytes from the buffer to the current read/write position. The current position is not changed by this method, so you must use the setPosition() method to change it. Luckily it returns the next sequential position, nextPos, should you need it.
offsetInBytes is an offset into the buffer (to avoid pointer arithmetic). Normally writing past the end of a file will cause it's size to grow as needed, but if noAutoExtend is TRUE then the file will NOT grow any larger (in which case numOfLostBytes will indicate how many bytes were not written). If you start writing beyond the end of a file, then any gap between the end of the file & your start position will be filled with pad bytes.
infoPadByte() returns the padByte value that new() was supplied with.
/* more methods of cFile */ METHOD setPosition(pos:BIGVALUE) METHOD getPosition(fromEnd=FALSE:BOOL) RETURNS pos:BIGVALUE METHOD setSize(sizeInBytes:BIGVALUE) METHOD getSize() RETURNS sizeInBytes:BIGVALUE METHOD setTime(time:BIGVALUE) RETURNS success:BOOL METHOD getTime() RETURNS time:BIGVALUE METHOD makeCopy(path:ARRAY OF CHAR) RETURNS copy:OWNS PTR TO cFile ->plus methods inherited from cPath
For the inherited methods read 26.4. Methods of cPath.
setPosition() changes the current read/write position. You may go beyond the end of the file without changing the file's size. A negative pos indicates position from the end of the file (-1=after last byte, -2=last byte, etc). Note that an error will be raised if you attempt to go before the beginning of the file.
Positions are BIGVALUEs (which are typically 64-bit), although the host OS may not support positions which exceed 32-bits. (In fact no cFile implementation yet supports 64-bit values, but this will hopefully change.)
getPosition() retrieves the current read/write postion. If fromEnd is TRUE then it returns a negative position as measured from the end of the file (see setPosition()).
setSize() & getSize() allow you to change & retrieve the file's current size in bytes.
setTime() & getTime() allow you to change & retrieve the file's current time.
makeCopy() creates a precise copy of a file, including cExtra information, returning a file opened in write mode. It will not overwrite an existing file. It will return NIL if an error occured.
This class is for handling directories. You must create an object (using the new() method), after which you can open() & close() directories as many times as you want.
The cDir class can also be found in the smaller 'std/cPath_Dir' module.
/* Methods of cDir, which inherits cPath */ METHOD new() METHOD openParent(forceOpen=FALSE:BOOL) RETURNS success:BOOL METHOD openChild(relativePath:ARRAY OF CHAR, forceOpen=FALSE:BOOL) RETURNS success:BOOL METHOD makeEntryList() RETURNS list:OWNS PTR TO cDirEntryList ->plus methods inherited from cPath
For the inherited methods read 26.4. Methods of cPath.
new() is the object's constructor.
openParent() closes the current dir & opens the parent dir. If it fails then it will return FALSE for success & leave the original dir open. forceOpen has the same meaning as it does for the open() method.
openChild() closes the current dir & opens the given sub-dir, which must be a dirpath relative to the current dir. If it fails then it will return FALSE for success & leave the original dir open. forceOpen has the same meaning as it does for the open() method.
makeEntryList() returns a cDirEntryList object containing the result of a scan of the current directory.
This class is a sorted list containing the result of a directory scan. You can also do various things with it, such as combining two lists, and generating a "unique name" which is not present in the list.
The cDirEntryList class can also be found in the smaller 'std/cPath_Dir' module.
/* Methods of cDirEntryList */ METHOD clone() RETURNS clone:OWNS PTR TO cDirEntryList METHOD gotoFirst(any0file1dir2=0) RETURNS exists:BOOL METHOD gotoNext( any0file1dir2=0) RETURNS exists:BOOL METHOD infoName() RETURNS path:ARRAY OF CHAR METHOD findName(name:ARRAY OF CHAR, fileOrDir=FALSE:BOOL) RETURNS success:BOOL
clone() allows you to create an exact copy of the current object.
gotoFirst() changes the current position in the list to the first item. If any0file1dir2 is 1 then it goes to the first file in the list, while if it is 2 then it goes to the first directory in the list. Returns whether the requested item exists, with FALSE implying that the list is empty.
gotoNext() changes the current position in the list to the next item. If any0file1dir2 is 1 then it goes to the next file in the list, while if it is 2 then it goes to the next directory in the list. Returns whether the requested item exists, with FALSE implying that the end of the list has been reached.
infoName() returns the name of the current item.
findName() searches from the start of the list for the given name, returning whether it succeeded in finding a match. If fileOrDir is TRUE then it will ignore whether the given name is for a file or dir. If TRUE is returned for success then the current position is the matched item.
/* more methods of cDirEntryList */ METHOD remove() nextExists:BOOL METHOD add(name:ARRAY OF CHAR, toStartOfList=FALSE:BOOL) RETURNS success:BOOL METHOD addString(name:OWNS STRING, toStartOfList=FALSE:BOOL) RETURNS success:BOOL METHOD addList(list:PTR TO cDirEntryList) RETURNS numOfSameEntries METHOD sort(doNotCheckForDuplicates=FALSE:BOOL) RETURNS numOfSameEntries METHOD makeUniqueName(file1dir2, base=NILA:ARRAY OF CHAR) RETURNS name:OWNS STRING
remove() destroys the current item, moving to the next one. Returns whether there was a next item, with FALSE implying that the end of the list has been reached.
add() creates an item with the given name, and add's it to the list such that it stays sorted. Returns FALSE if there was already an item with that name, since duplicates are not allowed.
(If toStartOfList=TRUE then the item is simply added to the start of the list, in which case the list is NOT sorted, and no check for duplicates is made. This state is NOT ALLOWED, except temporarily, so once you are finished adding items you MUST call the sort() method. This feature is useful for both speed, and so that you can easily modify a whole list without processing any item more than once (modify an item by removing the old item & adding the new 'modified' item).)
addString() works like add(), but it uses the provided e-string for speed. The list will now handle deallocation of the e-string, so you must NOT deallocate it yourself. If it returns FALSE, then the e-string will be deallocated immediately.
addList() creates copies of all items in the provided list, and adds them to the current list. It returns the number of duplicates that were not added.
sort() ensures the list is sorted, returning the number of duplicates which were found & removed. If you know for sure that no duplicates are present, then you can speed it up by using doNotCheckForDuplicates=TRUE.
makeUniqueName() creates an e-string name that does not yet exist in the list. For file1dir2, supply 1 for a file path, or 2 for a dir path. If base is not given then it will default to 'TMP'. The created name will begin with base.
This class is used for all the host OS information which is not accessible by normal means. In the Amiga's case this means file comments & certain flags.
You must specify what item of information you want to read or change, using a specific:QUAD value. The supported values depend on the host OS. For example:
Take care using them, because they are not completely portable!
The cExtra class can also be found in the smaller 'std/cPath_shared' module.
/* Methods of cExtra */ METHOD setExtra(extra:PTR TO cExtra) RETURNS success:BOOL METHOD getExtra() RETURNS extra:OWNS PTR TO cExtra METHOD changeExtra(specific:QUAD, value) RETURNS success:BOOL, unknown:BOOL METHOD queryExtra( specific:QUAD) RETURNS value, unknown:BOOL
setExtra() makes the object have the same information as that stored by extra (which could be a cFile or cDir object). Returns FALSE if it could not set all of the information.
getExtra() returns a new cExtra object, which contains a copy of all the current object's cExtra information.
changeExtra() changes a particular piece of information (given by specific) in the object to the supplied value. Returns whether it succeeded or not, and if it failed then whether that failure was due to specific being unknown.
queryExtra() returns a particular piece of information (given by specific) in value. This will be 0 when specific is unknown, but for cases where this is a valid value you need to check unknown.
Portable paths are represented in the same format, whatever OS is being used. This means that manipulation of path strings is portable (and also quite easy). You must use ImportFilePath(), ImportDirPath() & ExportPath() to convert between the OS format & the portable format.
Here are a some examples of valid paths:
device:/subpath/filename device:/subpath/dirname/ subpath/filename
On Linux absolute paths must always start with a colon, unless it references another mount point:
:/tmp/tempfile :/root/.bashrc /media/drivename:/folder/file
Date & time is measured as the number of seconds since 0:00:00 (midnight) on 1st January 2000. Dates before that are negative! Values are BIGVALUEs, which are typically 64-bit, but may be 32-bit for some targets (such as AmigaE).
Here is a list of exceptions that are used:
exception exceptionInfo Reason "FULL" (description) Error due to disk being full (no space); file left in previous state. "FILE" (description) Error due to a serious filing system failure. "BRK" (description) Received a break signal (Ctrl-C) during a lengthy operation. "EMU" (description) Error from Method Use (an inappropriate argument or use). "EPU" (description) Error from Procedure Use (an inappropriate argument or use). "BUG" (description) Error due to a bug being detected. "MEM" NILA Error due to a lack of memory.
Windows & Linux do not support assignments (beyond single drive letters in Windows' case), so there is support for 'faking' them, which only works for programs compiled by Portabl E. The assigments are stored in one or more text files, in the following locations on Windows:
%USERPROFILE%\Assignments.txt C:\PortablE\Assignments.txt C:\Assignments.txt
And these on Linux:
$HOME/.portable/Assignments.txt /root/.portable/Assignments.txt
In case case on conflicting assignments in different files, the first file takes priority (as it is read last & overwrites any previous assignments).
Portabl E has the HOME: assignment built-in, which points to the user's home folder, and can even be used in the Assignments.txt files themselves.
As standard Portabl E requires the PEmodules: assignment, which would look something like this in the Assignments.txt file on Windows:
PEmodules: C:/PortablE/PEmodules
And like this on Linux:
PEmodules: HOME:/.portable/PEmodules
Each assignment is on a single line, with the assignment name ending in a colon, followed by some tabs or spaces, and then the target path (which must be absolute not relative). The target path must not have any spaces after it, as they will be treated as part of the path. Note that the target path can use previously declared assignments, as well as Windows network paths. Nonsensical lines will simply be ignored.
Here's an example Assignments.txt file for Windows:
Code: HOME:\Documents\Code PEmodules: Code:\PEmodules
And for Linux:
Code: HOME:/Code PEmodules: Code:/PEmodules
Various technical details have been overlooked so far, but you may find it useful to know some of them:
This module provides a easy way of playing sounds, which is suitable for games & multimedia.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
How to play a sound:
DEF snd:PTR TO cSnd CreateApp().build() ->you only need to do this once! snd := LoadSound('MySound.wav') snd.play()
How to wait for a sound to finish playing:
snd.waitForPlayToFinish()
A more flexible way to wait for a sound to finish playing:
WHILE WaitForSoundEvent() <> snd DO EMPTY
Here's another way to play a sound:
CreateApp().build() ->you only need to do this once! StoreSound('test', 0, LoadSound('MySound.wav')) UseSound('test', 0).play()
The following example programs use it:
Examples/std/Multimedia/ShootEmUp/ShootEmUp.e
Released programs which are known to use it:
Ami-Ingenious ( os4depot.net/?function=showfile&file=game/board/ami-ingenious.lha )
PROC LoadSound(file:ARRAY OF CHAR, allowReturnNIL=FALSE:BOOL) RETURNS sound:PTR TO cSnd PROC DestroySound(sound:PTR TO cSnd) RETURNS nil:PTR TO cSnd PROC WaitForSoundEvent() RETURNS sound:PTR TO cSnd PROC CheckForSoundEvent() RETURNS sound:PTR TO cSnd PROC StoreSound(name:ARRAY OF CHAR, number, sound:PTR TO cSnd) RETURNS storedSound:PTR TO cSnd PROC UseSound(name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS sound:PTR TO cSnd
LoadSound() loads the given sound, and returns a cSnd object for it. The file path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() procedure first. If the file could not be loaded, then an exception will be raised (unless TRUE was given to allowReturnNIL, in which case NIL would be returned instead).
DestroySound() destroys the supplied sound object. Your sounds will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
WaitForSoundEvent() waits for any playing sound to stop (unless one has already stopped), and then returns that sound. Note that it will only remember the most recent events (typically the last 100), so ensure that you watch for events regularly.
CheckForSoundEvent() checks if any previously playing sound has stopped, and returns that sound. If no sound has stopped, then it returns NIL.
StoreSound() & UseSound() allow you to store & retrieve sounds using a name string, and optionally a number. The string must be an 'immediate string', not one you have created. It returns the stored sound, so you can use it straight away. Here's an example of how you might use it:
StoreSound('explosion', 0, LoadSound('explosion.wav')) UseSound('explosion', 0).play()
If you try to store more than one sound with the same name & number combination, then an exception will be raised. This is to prevent you accidentally reusing them. And if you try to use a non-existant sound, then an exception will be raised; unless you gave TRUE for allowReturnNIL, in which case NIL will be returned.
The cSnd class is a sound which can be played. Not only can you play several different sounds (from different objects) at the same time, but you can also play the same sound (from one object) several times.
For example, you can have a "shoot" sound, and play it every time the player shoots. If he fires quickly enough, then several "shoot" sounds can be playing at once.
/* Methods of cSnd */ METHOD play(playCount=1, speed=100) METHOD stop() METHOD infoLength() RETURNS milliSeconds METHOD infoIsPlaying() RETURNS isPlaying:BOOL METHOD waitForPlayToFinish() METHOD setVolume(volume) RETURNS sound:PTR TO cSnd METHOD getVolume() RETURNS volume METHOD setPan(pan) RETURNS sound:PTR TO cSnd METHOD getPan() RETURNS pan
play() starts playing the sound, using the given parameters. playCount indicates how many times the sound should be played (back to back). Use 0 if you want the sound to play forever. speed allows you to change how fast the sound is played, where 100 is normal speed, 200 is double speed, 50 is half speed, and so on.
stop() stops the sound from playing (even if playing multiple times).
infoLength() returns the length of the sound in milliseconds.
infoIsPlaying() returns whether or not the sound is currently playing.
waitForPlayToFinish() pauses until the sound has stopped playing (completely).
setVolume() & getVolume() allow you to change & retrieve volume. This is how loud the sound will be played, where 100 is maximum volume, 50 is half volume, 0 is silent, and so on. It is used by subsequent play() calls.
setPan() & getPan() allow you to change & retrieve the pan. Pan allows the sound to be forced to come more from one speaker than the other, where -100 is entirely from the left speaker, 100 is entirely from the right speaker, 0 is evenly from both speakers, and so on. It will be used by subsequent play() calls.