DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
unit StreamAdapter.pas
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com
unit StreamAdapter;
interface
uses
Classes;
type
IStream = interface( IInterface )
['{FBEF199A-09BC-4B61-89EA-1EF8B22C93A5}']
function Read(var Buffer; const Count: Longint): Longint;
function Write(const Buffer; const Count: Longint): Longint;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
procedure ReadBuffer(var Buffer; const Count: Longint);
procedure WriteBuffer(const Buffer; const Count: Longint);
function CopyFrom(Source: TStream; const Count: Int64): Int64;
function WriteTo(Dest: TStream; const Count: Int64): Int64;
procedure SetPosition( const Value: Int64 );
procedure SetSize( const Value: Int64 );
function GetPosition: Int64;
function GetSize: Int64;
property Position: Int64 read GetPosition write SetPosition;
property Size: Int64 read GetSize write SetSize;
end;
TStreamAdapter = class( TInterfacedObject, IStream )
private
FStream: TStream;
procedure SetPosition( const Value: Int64 );
procedure SetSize( const Value: Int64 );
function GetPosition: Int64;
function GetSize: Int64;
public
constructor Create( Stream: TStream );
destructor Destroy; override;
function Read(var Buffer; const Count: Longint): Longint;
function Write(const Buffer; const Count: Longint): Longint;
procedure ReadBuffer(var Buffer; const Count: Longint);
procedure WriteBuffer(const Buffer; const Count: Longint);
function CopyFrom(Source: TStream; const Count: Int64): Int64;
function WriteTo(Dest: TStream; const Count: Int64): Int64;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
property Position: Int64 read GetPosition write SetPosition;
property Size: Int64 read GetSize write SetSize;
end;
implementation
{ TStreamAdapter }
function TStreamAdapter.CopyFrom(Source: TStream; const Count: Int64): Int64;
begin
Result := FStream.CopyFrom( Source, Count );
end;
constructor TStreamAdapter.Create(Stream: TStream);
begin
FStream := Stream;
end;
destructor TStreamAdapter.Destroy;
begin
FStream.Free;
inherited;
end;
function TStreamAdapter.GetPosition: Int64;
begin
Result := FStream.Position;
end;
function TStreamAdapter.GetSize: Int64;
begin
Result := FStream.Size;
end;
function TStreamAdapter.Read(var Buffer; const Count: Integer): Longint;
begin
Result := FStream.Read( Buffer, Count );
end;
procedure TStreamAdapter.ReadBuffer(var Buffer; const Count: Integer);
begin
FStream.ReadBuffer( Buffer, Count );
end;
function TStreamAdapter.Seek(const Offset: Int64;
Origin: TSeekOrigin): Int64;
begin
Result := FStream.Seek( Offset, Origin );
end;
procedure TStreamAdapter.SetPosition(const Value: Int64);
begin
FStream.Position := Value;
end;
procedure TStreamAdapter.SetSize(const Value: Int64);
begin
FStream.Size := Value;
end;
function TStreamAdapter.Write(const Buffer; const Count: Integer): Longint;
begin
Result := FStream.Write( Buffer, Count );
end;
procedure TStreamAdapter.WriteBuffer(const Buffer; const Count: Integer);
begin
FStream.WriteBuffer( Buffer, Count );
end;
function TStreamAdapter.WriteTo(Dest: TStream; const Count: Int64): Int64;
begin
Result := Dest.CopyFrom( FStream, Count );
end;
end.
unit PersistentTree.pas
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com
unit PersistentTree;
interface
uses
Windows, Classes, SysUtils, StreamAdapter;
type
EPersistentTree = class( Exception );
TPersistentTree = class;
TPersistentTreeClass = class of TPersistentTree;
TPersistentTree = class( TStream )
private
FStream: IStream;
FList: TList;
FBaseClass: TPersistentTreeClass;
FOwner, FParent: TPersistentTree;
FOwnStream: Boolean;
FDataFilename, FFilename: string;
FLastPosition, FDataBegin, FDataLength: Int64;
function GetItem(const Index: Integer): TPersistentTree;
function GetCount: Integer;
function GetStream: TStream;
function Import( Item: TPersistentTree ): Boolean;
procedure ClearData;
procedure RecreateStream( const Pos: Int64; const Deep: Boolean = False );
procedure Synchronize;
protected
//override to provide writing/reading notifications
procedure Loaded; virtual;
procedure Saving; virtual;
//derived from TStream
function GetSize: Int64; override;
procedure SetSize(NewSize: Longint); override;
procedure SetSize(const NewSize: Int64); override;
public
constructor Create; virtual;
destructor Destroy; override;
//derived from TStream
function Read( var Buffer; Count: Longint ): Longint; override;
function Write( const Buffer; Count: Longint ): Longint; override;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
function Truncate: Int64;
function ReadString: string;
procedure WriteString( const Data: string );
procedure Save( const AFilename: string ); overload;
procedure Save( Stream: TStream ); overload;
procedure Load( const AFilename: string ); overload;
procedure Load( Stream: IStream ); overload;
procedure Load( Stream: TStream ); overload;
function Add: TPersistentTree; overload;
function Add( Item: TPersistentTree ): Integer; overload;
procedure Insert( const Index: Integer; Item: TPersistentTree);
function IndexOf( Item: TPersistentTree ): Integer;
function Remove( Item: TPersistentTree ): Integer;
procedure Delete( const Index: Integer);
function Extract( Item: TPersistentTree ): TPersistentTree;
procedure Exchange( const IndexA, IndexB: Integer );
procedure Move(const CurIndex, NewIndex: Integer);
procedure Clear;
property Items[ const Index: Integer ]: TPersistentTree read GetItem; default;
property Count: Integer read GetCount;
property Owner: TPersistentTree read FOwner;
property Parent: TPersistentTree read FParent;
property Filename: string read FFilename;
property BaseClass: TPersistentTreeClass read FBaseClass write FBaseClass;
end;
TPersistentTreeHeader = packed record
Sig: array[0..4] of Char;
Ver: Word;
end;
const
PERSISTENT_TREE_HEADER: TPersistentTreeHeader = ( Sig: 'PTREE'; Ver: 1 );
function GetTempFile: string;
implementation
function GetTempFile: string;
var
Path: array[0..MAX_PATH-1] of Char;
begin
GetTempPath( MAX_PATH, Path );
GetTempFileName( Path, 'BUF', 0, Path );
Result := Path;
end;
{ TPersistentTree }
procedure TPersistentTree.Clear;
var
I: Integer;
begin
for I := FList.Count - 1 downto 0 do
begin
TPersistentTree( FList[I] ).Free;
FList.Delete( I );
end;
end;
constructor TPersistentTree.Create;
begin
FBaseClass := TPersistentTreeClass( Self.ClassType );
FList := TList.Create;
FStream := TStreamAdapter.Create( GetStream );
FOwnStream := True;
end;
destructor TPersistentTree.Destroy;
begin
ClearData;
FList.Free;
inherited;
end;
procedure TPersistentTree.Exchange(const IndexA, IndexB: Integer);
begin
FList.Exchange( IndexA, IndexB );
end;
function TPersistentTree.GetCount: Integer;
begin
Result := FList.Count;
end;
function TPersistentTree.GetItem(const Index: Integer): TPersistentTree;
begin
Result := FList[ Index ];
end;
function TPersistentTree.IndexOf(
Item: TPersistentTree): Integer;
begin
Result := FList.IndexOf( Item );
end;
procedure TPersistentTree.Load(const AFilename: string);
var
FS: TFileStream;
//Header: TPersistentTreeHeader;
begin
FS := TFileStream.Create( AFilename, fmOpenRead or fmShareDenyWrite );
try
//FS.Read( Header, SizeOf( TPersistentTreeHeader ) );
//if not CompareMem( @Header, @PERSISTENT_TREE_HEADER, SizeOf( TPersistentTreeHeader ) ) then
// raise EPersistentTree.CreateFmt( '%s.LoadFromFile :: "%s" Not Recognized', [ClassName, AFilename] );
Load( FS );
FFilename := AFilename;
except
FS.Free;
raise;
end;
end;
procedure TPersistentTree.Load(Stream: TStream);
begin
Load( TStreamAdapter.Create( Stream ) );
end;
function TPersistentTree.Remove(Item: TPersistentTree): Integer;
begin
Result := FList.Remove( Item );
if Result >= 0 then
Item.Free;
end;
procedure TPersistentTree.Save( const AFilename: string );
var
FS: TFileStream;
begin
FS := TFileStream.Create( AFilename, fmCreate or fmShareDenyWrite );
try
//FS.Write( PERSISTENT_TREE_HEADER, SizeOf( TPersistentTreeHeader ) );
Save( FS );
finally
FS.Free;
end;
end;
procedure TPersistentTree.Save(Stream: TStream);
var
I: LongInt;
begin
Seek( 0, soBeginning );
Saving;
FDataLength := Size;
Stream.Write( FDataLength, SizeOf( FDataLength ) );
Stream.CopyFrom( Self, 0 );
I := FList.Count;
Stream.Write( I, SizeOf( I ) );
for I := 0 to FList.Count-1 do
Self[I].Save( Stream );
end;
function TPersistentTree.Write( const Buffer; Count: Longint ): Longint;
begin
if FOwnStream then
Result := FStream.Write( Buffer, Count )
else
begin
Synchronize;
if Position + Count > Size then
RecreateStream( Position );
Result := FStream.Write( Buffer, Count );
FLastPosition := FStream.Position;
end;
end;
function TPersistentTree.Read( var Buffer; Count: Longint): Longint;
begin
if FOwnStream then
Result := FStream.Read( Buffer, Count )
else
begin
Synchronize;
if Count < 0 then
Count := 0
else if Count > Size - Position then
Count := Size - Position;
Result := FStream.Read( Buffer, Count );
FLastPosition := FStream.Position;
end
end;
function TPersistentTree.Seek(const Offset: Int64;
Origin: TSeekOrigin): Int64;
begin
if FOwnStream then
Result := FStream.Seek( Offset, Origin )
else
begin
Synchronize;
case Origin of
soBeginning: Result := FDataBegin + Offset;
soCurrent: Result := FStream.Position + Offset;
soEnd: Result := FDataBegin + Size - Offset;
else
Result := 0;
end;
if Result > -1 then
if Result <= FDataBegin + Size then
Result := FStream.Seek( Result, soBeginning ) - FDataBegin
else
begin
RecreateStream( Size );
Result := FStream.Seek( Result, soBeginning );
end;
FLastPosition := FStream.Position;
end;
end;
procedure TPersistentTree.SetSize(const NewSize: Int64);
begin
if FOwnStream then
FStream.Size := NewSize
else begin
if NewSize <= 0 then
RecreateStream( 0 )
else if NewSize > Size then
RecreateStream( Size )
else
begin
FDataLength := NewSize;
Seek( 0, soEnd );
end;
FLastPosition := FStream.Position;
end;
end;
procedure TPersistentTree.Synchronize;
begin
if not FOwnStream and ( ( FStream.Position < FDataBegin ) or ( FStream.Position - FDataBegin > FDataLength ) ) then
FStream.Seek( FLastPosition, soBeginning );
end;
procedure TPersistentTree.Load( Stream: IStream);
var
I: LongInt;
begin
ClearData;
FStream := Stream;
FOwnStream := False;
Stream.Read( FDataLength, SizeOf( FDataLength ) );
FDataBegin := FStream.Position;
FLastPosition := FDataBegin;
Stream.Seek( FDataLength, soCurrent );
Stream.Read( I, SizeOf( I ) );
for I := I - 1 downto 0 do
Add.Load( FStream );
//Seek( 0, soBeginning ); it isnt needed since synchonize will do it anyway
Loaded;
FStream.Seek( FDataBegin + FDataLength + SizeOf( I ), soBeginning );
end;
function TPersistentTree.Extract( Item: TPersistentTree): TPersistentTree;
begin
Result := FList.Extract( Item );
if Assigned( Result ) then begin
Result.FParent := nil;
Result.FOwner := nil;
Result.RecreateStream( Size, True );
end;
end;
function TPersistentTree.GetSize: Int64;
begin
if FOwnStream then
Result := FStream.Size
else
Result := FDataLength;
end;
procedure TPersistentTree.WriteString(const Data: string);
var
I: LongWord;
begin
I := Length( Data );
Write( I, SizeOf( I ) );
Write( Pointer( Data )^, I );
end;
function TPersistentTree.ReadString: string;
var
I: LongWord;
begin
Read( I, SizeOf( I ) );
SetLength( Result, I );
Read( Pointer( Result )^, I );
end;
procedure TPersistentTree.SetSize(NewSize: Integer);
begin
SetSize( Int64( NewSize ) );
end;
procedure TPersistentTree.RecreateStream( const Pos: Int64; const Deep: Boolean );
var
FS: TStream;
I: Integer;
begin
if not FOwnStream then
begin
FS := GetStream;
if Pos > 0 then
begin
Seek( 0, soBeginning );
FS.CopyFrom( Self, Pos );
end;
FStream := TStreamAdapter.Create( FS );
FOwnStream := True;
end;
if Deep then
for I := 0 to FList.Count - 1 do
Self[I].RecreateStream( Self[I].Size, True );
end;
procedure TPersistentTree.ClearData;
begin
FStream := nil;
if FOwnStream then
DeleteFile( FDataFilename );
Clear;
end;
function TPersistentTree.GetStream: TStream;
begin
FDataFilename := GetTempFile;
Result := TFileStream.Create( FDataFilename, fmCreate or fmShareDenyWrite );
end;
function TPersistentTree.Add: TPersistentTree;
begin
Result := TPersistentTreeClass( FBaseClass ).Create;
Add( Result );
end;
function TPersistentTree.Add( Item: TPersistentTree): Integer;
begin
if Import( Item ) then
Result := FList.Add( Item )
else
Result := FList.IndexOf( Item );
end;
procedure TPersistentTree.Delete(const Index: Integer);
begin
TPersistentTree( FList[Index] ).Free;
FList.Delete( Index );
end;
procedure TPersistentTree.Insert(const Index: Integer; Item: TPersistentTree);
begin
if Import( Item ) then
FList.Insert( Index, Item )
else
FList.Move( FList.IndexOf( Item ), Index );
end;
procedure TPersistentTree.Move(const CurIndex, NewIndex: Integer);
begin
FList.Move( CurIndex, NewIndex );
end;
function TPersistentTree.Truncate: Int64;
begin
Result := Position;
Size := Result;
end;
function TPersistentTree.Import(Item: TPersistentTree): Boolean;
begin
Result := not Assigned( Item.FParent ) or ( ( Item.FParent <> Self ) and Assigned( Item.FParent.Extract( Item ) ) );
if Result then
begin
Item.FParent := Self;
if FOwner <> nil then
Item.FOwner := FOwner
else
Item.FOwner := Self;
end;
end;
procedure TPersistentTree.Saving;
begin
//override to provide extra save features
end;
procedure TPersistentTree.Loaded;
begin
//override to provide extra load features
end;
end.
this code analyses the first 5*1024 bytes of data from a file and tells which break type it uses, or if it's a binary file...
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com
type
TBreakType = ( btNone, btWin, btMac, btLin, btBin );
---------
function GetBreakType( const Filename: string; const MaxDataToRead: Cardinal = 5*1024 ): TBreakType;
var
FS: TFileStream;
Buffer, BufferStart, BufferEnd: PChar;
begin
Result := btNone;
if not FileExists( Filename ) then
raise Exception.Create( 'GetBreakType: nome de arquivo inválido' );
try
FS := TFileStream.Create( Filename, fmOpenRead );
GetMem( Buffer, MaxDataToRead+1 );
BufferEnd := ( Buffer + FS.Read( Buffer^, MaxDataToRead ) );
BufferStart := Buffer;
BufferEnd^ := #0;
except
raise Exception.Create( 'GetBreakType: erro alocando memória.' );
end;
try
while Buffer^ <> #0 do begin
if Result = btNone then
if Buffer^ = ASCII_CR then begin
if (Buffer+1)^ = ASCII_LF then begin
Result := btWin;
Inc( Buffer );
end
else
Result := btMac;
end
else if Buffer^ = ASCII_LF then
Result := btLin;
Inc( Buffer );
end;
if Buffer <> BufferEnd then
Result := btBin;
finally
FreeMem( BufferStart, MaxDataToRead+1 );
FS.Free;
end;
end;
<a href="http://www.jsfromhell.com/number/fmt-money">
Formats strings/numbers into "money format" without loops :)
Defaults:
float ploint cutoff = 2 decimal places
decimal separator = ','
thousands separator = '.'
[UPDATED CODE AND HELP CAN BE FOUND HERE]
</a>
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/number/fmt-money [v1.1]
Number.prototype.formatMoney = function(c, d, t){
var n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "," : d, t = t == undefined ? "." : t, s = n < 0 ? "-" : "", i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};
Usage
(123456789.12345).formatMoney(2, '.', ',');
<a href="http://jsfromhell.com/forms/enter-as-tab">
Tabulation on fields through the enter key, i didnt allowed it to work on <select> and <textarea> since the enter is required to use this fields, so find a nice place to use it :]
Usage: just add the code on the end of your page or call it on the onload event (worse solution) and "the enter tabulation" will be added for all fields enclosed by the <form> tag.
[UPDATED CODE AND HELP CAN BE FOUND HERE]
</a>
@REQUIRES <a href="http://jsfromhell.com/geral/event-listener">Event-Listener</a>
//Requires http://jsfromhell.com/geral/event-listener
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/forms/enter-as-tab [v1.0]
enterAsTab = function(){
for( var f, i = ( f = document.forms ).length; i; addEventListener( f[--i], "keypress", function( evt ){
var el, l, k = evt.key == 13, e = evt.target;
if( k && !/textarea|select/i.test( e.type ) && !evt.preventDefault() ){
for( l = k = ( el = e.form.elements ).length; el[--k] != e; );
while( !(e = el[ k = ++k * ( k < l ) ]).type || e.disabled );
e.focus();
}
} ) );
};
Example:
<form action=""> <p> <input type="text" /> <br /><input type="text" /> <br /> <input type="radio" name="aaa" /> opção 1 <input type="radio" name="aaa" checked="checked" /> opção 2 <br /><textarea rows="3" cols="15">aaaaaa pode dar enter q ele naum pula hahah</textarea> <br /><select><option>opção blablablabla</option><option>opção bleblebleble</option></select> <br /><input type="text" /> </p> </form> <script type="text/javascript"> //<![CDATA[ enterAsTab(); //]]> </script>
pys60 1.1.3 provide some graphics capabilitis.
One of them is using icons in Listbox
(code taken from pys60 API reference)
icon1 = appuifw.Icon(u"z:\\system\\data\\avkon.mbm", 28, 29)
icon2 = appuifw.Icon(u"z:\\system\\data\\avkon.mbm ", 40, 41)
entries = [(u"Signal", icon1),
(u"Battery", icon2)]
lb = appuifw.Listbox(entries, lbox_observe)
Listbox is one of the 3 types that can be assigned to app.body (i.e. Text, Listbox, Canvas) So, to make code above able to run, you must add
appuifw.app.body = lb
and the function lbox_observe that will handle the selection need to be defined.
appuifw.app.menu = [(u"item 1", item1), (u"Submenu 1", ((u"sub item 1", subitem1), (u"sub item 2", subitem2) )) ] # item1, subitem1, subitem2 are callback
In pys60 1.1.3 and later, you can specify different screen size
appuifw.app.screen='normal' #(a normal screen with title pane and softkeys) appuifw.app.screen='large' #(only softkeys visible) appuifw.app.screen='full' #(a full screen)
Presuming the element you want the text from is element:
REXML::XPath.match(element, './/text()').inject { |str, text| str << text.to_s }
Here is a really cheap way in Perl to append an XML fragment to an existing XML doc. It appends it just before the last closing tag. Note that there is no validation or well-formedness checking. Use at your own risk. That said, it can be handy if you know that your XML is going to be OK.
#!/usr/bin/perl
sub xappend(\$$) { ${$_[0]} =~ s/(<\/[^>]+>\s*)$/$_[1]$1/s }
$a = "<doc><item>foo</item></doc>";
xappend($a,"<item>bar</item>");
print $a; # prints <doc><item>foo</item><item>bar</item></doc>
Taken (will some mod.) from
http://discussion.forum.nokia.com/forum/showthread.php?s=&threadid=63464
pys60 (the full name is python for series 60) 1.1.3
provide both camera and graphics display.
So, it is trivial to take photo and preview.
from appuifw import *
import camera
canvas=Canvas()
app.body=canvas
running=1
def quit():
global running
running=0
app.exit_key_handler=quit
while running:
image = camera.take_photo(size= (160,120))
canvas.blit(image, target=(8, 12, 168, 132)) # center it
Here I use the small size (160x120) for preview. When the real photo is taken I can use the full (defualt) size of (640x480) on my 6600 phone.
I got 1000 word files. Each contains 1 main image and some decorations.
(This is actually a big book scanned into 1-file-per-page format)
I need to extract all the images. What do I do?
Python can do some automation using COM. (or something like that)
import pythoncom, win32com.client
app = win32com.client.gencache.EnsureDispatch("Word.Application")
doc = 'C:\\lang\\try\\bdham\\p1'
app.Documents.Open(doc + '.doc')
app.ActiveDocument.SaveAs(doc + '.html', FileFormat=win32com.client.constants.wdFormatHTML)
app.ActiveDocument.Close()
# now repeat with p2, p3, etc.
Actually, I should put it in a loop. But this non-loop version is easier to read and remember.
Some of my friends who practise mindfulness meditation
use an alarm device that vibrate every 2 minutes and
he will become mindful then.
Danny O'Brien of Life Hacks fame asked me about this too.
So, here's a short example (without parameter setting GUI)
that does exactly this.
You need to have miso library install. Only Series 60
2nd Ed FP2 device (Nokia 6630, Nokia 6680) can be used.
See vibrate(...) in miso documentation
http://pdis.hiit.fi/pdis/download/miso/miso-1.40-api.html
import appuifw, miso, e32
# run-and-break type of app
running = 1
def set_exit():
global running
running = 0
appuifw.app.exit_key_handler= set_exit
# main loop
while running:
miso.vibrate(500, 100) # vibrate for 500 millisec, at full speed
e32.ao_sleep(10) # vibrate every 10 seconds
I don't have a FP2 phone to test this. Though the code is pretty straight forward, please report if there is a problem.
py_s60 1.1.3 was released a week ago.
I wonder why there's no more people playing with it.
So, I have created a simple game as an example.
I don't know what this game is called. It has 4x4 square box
with 15 pieces (1 piece missing). You need to move all the
pieces into sorting order.
Since the program is so simple, I decided to make the
moving of a piece smoother by moving it bit by bit.
Hope this doesn't make the code to hard to read.
from appuifw import *
from key_codes import *
import e32, random
# run and break-loop type of app
sleep = e32.ao_sleep
running = 1
def set_exit():
global running
running = 0
app.exit_key_handler= set_exit
# canvas and typical colors
c = Canvas()
app.body = c
red, green, blue, gray, white = 0xff0000, 0x00ff00, 0x0000ff, 0x777777, 0xffffff
# randomize number order for pieces
seq = range(1,17)
random.shuffle(seq)
b = [seq[0:4], seq[4:8], seq[8:12], seq[12:16]]
def piece(i, j, n):
if n < 10:
c.text( (12+20*i, 20+20*j), unicode(n))
else:
c.text( (7+20*i, 20+20*j), unicode(n))
def box(i, j, color, fill=None):
c.rectangle( [5+20*i, 5+20*j, 25+20*i, 25+20*j], color, fill)
# draw board pieces
for k in range(16):
j, i = divmod(k, 4)
piece(i, j, b[j][i])
y, x = divmod(seq.index(16), 4)
box(x, y, white, white)
moving = 0 # cursor to lock if animating
# move cursor in dx, dy direction
def move(dx, dy):
global x,y, moving
if moving:
return
moving = 1
if 0 <= x-dx < 4 and 0 <= y-dy < 4:
b[y][x] = b[y-dy][x-dx]
animate(x-dx, y-dy, dx, dy, b[y][x])
x -= dx # the hole move in opposite direction
y -= dy
moving = 0
# moving a piece for x,y to dx, dy direction
def animate(x, y, dx, dy, n):
if n < 10:
px = 12
else:
px = 7
for i in range(5):
c.text( (px+20*x + 4*i*dx, 20+20*y + 4*i*dy), unicode(n))
sleep(0.05)
c.text( (px+20*x + 4*i*dx, 20+20*y + 4*i*dy), unicode(n), white)
c.text( [px+20*(x+dx), 20+20*(y+dy)], unicode(n) )
# bind arrow keys
c.bind(EKeyRightArrow,lambda:move(1, 0))
c.bind(EKeyLeftArrow,lambda:move(-1, 0))
c.bind(EKeyUpArrow,lambda:move(0, -1))
c.bind(EKeyDownArrow,lambda:move(0, 1))
# main loop, just wait
while running:
sleep(0.1)
py_s60 1.1.3 has its drawing API very similar to PIL.
Porting from PIL to S60 is very easy. Here's an example
that I port a sparkline drawing function from
Joe Gregorio's article at xml.com
# modified from Joe Gregorio's article at
# http://www.xml.com/pub/a/2005/06/22/sparklines.html
from appuifw import *
import e32
lock = e32.Ao_lock()
c = Canvas()
app.body = c
draw = c._draw
red, green, blue, gray = 0xff0000, 0x00ff00, 0x0000ff, 0x777777
def plot_sparkline(results, step=2, height=20, \
min_m=None, max_m=None, last_m=None, \
min_color=blue, max_color=green, last_color=red):
coords = zip(range(1,len(results)*step+1, step), \
[height - 3 - y/(101.0/(height-4)) for y in results])
draw.line(coords, gray)
if min_m:
min_pt = coords[results.index(min(results))]
draw.rectangle([min_pt[0]-1, min_pt[1]-1, min_pt[0]+1, min_pt[1]+1], fill=min_color)
if max_m:
max_pt = coords[results.index(max(results))]
draw.rectangle([max_pt[0]-1, max_pt[1]-1, max_pt[0]+1, max_pt[1]+1], fill=max_color)
if last_m:
end = coords[-1]
draw.rectangle([end[0]-1, end[1]-1, end[0]+1, end[1]+1], fill=last_color)
results = [88,84,82,92,82,86,66,82,44,64,66,88,96,80,24,26, \
14,0,0,26,8,6,6,24,52,66,36,6,10,14,30]
plot_sparkline(results, 3, 30, min_m=1, max_m=1, last_m=1)
app.exit_key_handler = lock.signal
lock.wait()
This will take a phrase and truncate it at the word level
<?php
function trunc($phrase, $max_words)
{
$phrase_array = explode(' ',$phrase);
if(count($phrase_array) > $max_words && $max_words > 0)
$phrase = implode(' ',array_slice($phrase_array, 0, $max_words)).'...'
return $phrase;
}
?>





