Random Thoughts – Tylermac.Net

September 25th, 2009

Draggable & Resizable Widgets in Flex 3

Filed under: Flex — Tags: , , , , , , , — Tyler @ 9:56 PM

Working on a project, a requirement was for widgets to be placed on the main view. These widgets where required to be moveable and resizable.

In the past, I have used FlexLib’s MDI Canvas to accomplish this. In this instance however, I wanted to use pre existing components, and didn’t want to have to extend other classes.

My solutions was to create a wrapper for MXML for TitleWindows that would turn any container into bounds for the TitleWindows.

(more…)

September 6th, 2009

How I’m using Smarty Templates with Haxe/PHP project in FlashDevelop

Filed under: Haxe — Tags: , , , — Tyler @ 3:10 PM

So I have been playing with Haxe for a little while now. I’ve decided I’m ready to build a hobby project using this new language. It will be a PHP browser game with Flash elements to utilize AMF remoting.

Skip to Implementation

The first thing I did (after the unit testing framework failed to work with PHP) was to decide I didn’t want to hardcode my HTML in code. Having worked on many PHP projects in the past, I have become a fan of using Smarty to abstract my views.

So in order to learn how to include Smarty in my project, I begin by looking up examples for using external libraries. It shows how to use the extern keyword on classes to make references that the Haxe Compiler can’t interpret.

Using this, I was able to create a Smarty.hx file that implemented all the functionality I needed.

//empty package because they are not natively supported by the PHP target
package ;

//Using NativeArray, since that is what Smarty is expecting
import php.NativeArray;

extern class Smarty 
{
    public var template_dir:String;
    public var compile_dir:String;
    public var config_dir:String;
    public var plugins_dir :NativeArray;
    public var debugging:Bool;
    public var error_reporting :Int;
    public var compile_check:Bool;
    public var force_compile :Bool;

    public function assign(tpl_var:Dynamic, ?value:Dynamic):Void;
    public function append(tpl_var:Dynamic, ?value:Dynamic, ?merge:Bool):Void;
    public function clear_assign(tpl_var:String):Void;
    public function clear_all_assign():Void;

    public function register_block(block:String, block_impl:String, ?cacheable:Bool, ?cache_attrs:Dynamic):Void;
    public function unregister_block(block:String):Void;

    public function display(resource_name:String, ?cache_id:String, ?compile_id:String):Void;
    //Returns Boolean or String containing parsed template
    public function fetch(resource_name:String, ?cache_id:String, ?compile_id:String, ?display:Bool):Dynamic;
}

Using this class will trigger a runtime error of not being able to locate the class file. Makes sense since we haven’t installed it yet. So next was to figure out how to how to include this file.

The first option was just to require the Smarty file using “untyped __call__('require_once', smarty_location);” in the main file. Although this may be alright for this scenario, I wasn’t happy with it because I do not require this library when I will start with remoting.

EDIT: It’s also possible to include this code in a static __inline__ function in the external class, which eliminates this issue.

So I began digging into what the compiled PHP looked like. One of the first relevant bits I came across, in lib/php/Boot.class.php, was _hx_register_type that would allow the path to be declared for the class file. This could have worked, by implementing a mapping between external libraries and their types.

However, I started then noticing the structure of the generated PHP’s for the base package. They are simply in the form of (class name).class.php. So I simply copied the contents of Smarty’s libs directory into the generated lib directory of my project, and confirmed it worked.

This worked because:

  1. My extern class was in the base package. (to avoid the compiler’s work around for packages in PHP)
  2. The Smarty class file was called Smarty.class.php, which is the format expected by Haxe’s auto_load function.

Now that I’ve confirmed this is working, I then went ahead to create it as part of my build.

Implementation

So first I created a Haxe/PHP project in FlashDevelop. I deleted the generated Bin folder and pointed the output to a subfolder oh my htdocs, changing the custom run command at the same time.

Next I created a lib directory in the root of my project directory and copied the Smarty libs there.

I then created all the default folders for Smarty under the root of my project.

  • templates
  • templates_c
  • configs
  • cache

I created a simple html page and saved it as index.tpl under the the templates folder.

I created my main class to test the template.

static function main()
{
    var template = new Smarty();
    template.display('index.tpl');
}

Next I have to make sure these files get copied to during the build. Since I’m using Vista, I decided to make use of RoboCopy for this step. I created a batch file called doCopy.bat and placed in the the project’s root directory, and set it as the the pre build command.

@echo off
REM USE: in prebuild use 
REM $(ProjectDir)\doCopy.bat "$(ProjectDir)" "$(OutputDir)\$(OutputName)"

REM copy the full directory to the output directory, removing generated and deleted files
robocopy %1 %2 /MIR /XD *src /XF *.hxproj *.bat

REM robocopy return and exit code between 0 and 8 for success
REM FlashDevelop will only continue for exit code 0
EXIT /B 0

Testing, I ran into the follow error

uncaught exception: unlink(templates_c\%%3F^3F5^3F5AD92D%%MainTemplate.tpl.php) [function.unlink]: No such file or directory (errno: 2) in C:\dev\httpdocs\FirstSite\lib\internals\core.write_file.php at line #46unlink(templates_c\%%3F^3F5^3F5AD92D%%MainTemplate.tpl.php) [function.unlink]: No such file or directory

Called from net.tylermac.PHPIndex::runApp
Called from net.tylermac.PHPIndex::main

Line 44 (not 46) of lib/internals/core.write_file.php contains @unlink($params['filename']);. Of course, the @ in PHP is suppose to suppress errors, however, it doesn’t if there is a error handler set. Haxe sets one up for us, so this line throws an error if the filename does not exists. (It doesn’t on first run). So to correct it, I simply modified as follows

if (file_exists($params['filename']))
{
	@unlink($params['filename']);
}

This causes a small performance hit rather then trying to silently ignore the error, but I find it acceptable.

Running the code again, and suddenly I have the html displaying for me.

May 20th, 2008

What is in a brand?

Filed under: Site News — Tags: , , — Tyler @ 1:59 PM

Current DraftSo I’ve been thinking about branding a new site for myself. I’ve been working with George Matthews on creating a logo for the new design.

This is the current design. Nice, clean, functional design. I’ll extract the symbol to use as a favicon on the site as well.

I’ll be putting the site together through out the next month. I’ll post here when it is complete.

May 19th, 2008

Geak Speak?

Filed under: Development — Tags: , , — Tyler @ 7:55 PM

Here’s a question:

Are good programmers a product of an inherit ability, or is the ability more cognitive? Is programming an art, like music or writing where some can become decent, but only a few can become great; or is it more like a language, where those who are exposed to it before they finalize their thinking model can just get it?

Of course, some would say that anyone can become a great developer? Is this true, or is it just people trying to make ourselves feel good?

February 23rd, 2008

Eventful F#

Filed under: Development — Tags: , , — Tyler @ 12:30 PM

Working with events in F# is super easy. No more delegates, just events as values. Now with this under my belt, it leads to way to highly reactive programming.

let add, remove, event =
 let doChange, changeEvent = IEvent.create() in
 let value = ref 0 in (
  (fun x ->
	value := !value + x;
	doChange(x, !value);
	!value;
  ),
  (fun y ->
	value := !value - y;
	doChange((y * (-1)), !value);
	!value;
   ), changeEvent);;

event.Add(fun (x,y) -> printfn "changed by %d to make %d" x y);;

Here is a simple example with two closures sharing a single state, throwing an event whenever the state changes. The state can now be listened to anywhere without affected the original code. Makes maintenance easier to manage.

The real benefit here will be when used in conjunction with asynchronous functions, for parallel execution.

For more reference, check out Don Syme’s Article on Events.

February 17th, 2008

Success with F#

Filed under: Development — Tags: , — Tyler @ 10:00 PM

Ah, much better. Still will need to practice more with the language, but I can see where programming functionally has it’s benefits. The results are much more streamline, and easier to understand. Closer to a declarative then traditional C derived languages.

Here is the first successful attempt. Not the prettiest, or exactly correct, but just a test.

let memo name f =
 let m = ref ([] : ('a * 'b) list) in 
 fun x -> (
  if List.mem_assoc x !m then (
   printfn "Found %s %s" name (any_to_string x);
   List.assoc x !m;
  ) else (
   printfn "Calling %s %s" name (any_to_string x);
   let v = f x in (
    m := (x, v) :: !m;
	v;
   )
  )
 );;
  
let fib n =
 let rec f = memo "fib" (function
  | small when small < 1 -> 0
  | 1 -> 1
  | n -> f (n-2) + f (n-1)
 ) in f n;;

let fact n =
 let rec f = memo "fact" (function
  | small when small < 2 -> 1
  | n -> n * f (n - 1)
 ) in f n;;

for i = 1 to 3 do
 printfn "fib %d = %d" i (fib i);
 printfn "fact %d = %d" i (fact i);
done;;

More trouble with F#

Filed under: Development — Tyler @ 7:50 PM

Well, still trying to learn F# and I’ve gotten a better understanding of the syntax. I am still having trouble understand what I am doing wrong with closures though.

let rec fib x = (
 let m = ref [1,1;0,0] in
  match x with
   | n when List.mem_assoc n !m -> (
    printfn "Found %d" n;
	List.assoc n !m;
   )
   | n when n < 0 -> n
   | n -> (
    let v = fib (n - 1) + fib (n - 2) in (
	 printfn "Calculated %d = %d" n v;
	 m := (n, v) :: !m;
	 v;
	)
   )
);;

when I run this, it finds 1 and 0 correctly, but will still calculate all other repeatedly. I’m sure it’s something simple I’m missing, but I don’t know. I’m going to rewrite function with an accumulator instead to see how it works there.

February 15th, 2008

Trouble with F#

Filed under: Development — Tags: , — Tyler @ 11:29 PM

Well, I am having fun playing around with F#. It’s nice to see Microsoft bringing some of the power of new languages into the .NET framework.

I am enjoy the concept of lists, especially considering the whole source code is itself a list. It does take some getting use to, however.

I am attempting to play with simple a factorial function, using memoization. I am unable to get the Interactive console to accept my functions. I am missing something with this syntax, that I’m just not seeing tonight.

let fact x = (
	let map = new Dictionary();
	map.Add(1,1);
  
	let rec loop n = (
		if (!map.ContainsKey(n)) then
			map(n) &lt;- (n * loop (n - 1));

		map(n);
	);

	loop x
 );;
and
let fact x = (
 let rec loop n map = (
  if(!map.ContainsKey(n)) then
   map(n) &lt;- (n * loop (n - 1) map);
   
  map(n);
 );

 let dict = new Dictionary();
 dict(1) &lt;- 1;

 if x &lt; 1 then 0
 else loop x dict
);;

The trouble seems to be with how the functions are terminated, but it’s completely by passing me by tonight.

October 29th, 2007

Creating Dates in T-SQL

Filed under: T-SQL — Tags: , — Tyler @ 7:30 PM

[Ed. Note - article is unfinished.]

I was presented with an interesting question today. I was asked for a script to alter a datetime to a given year while retaining the month and day. The solution I provided was to add the difference between the years to the given date.

DECLARE @oldDate datetime, @year smallint;
SET @oldDate = getDate();
SET @year = 1990;

SELECT dateAdd(yy, @year - year(@oldDate), @oldDate) [newDate];

It got me thinking how working with dates is not very intuitive; therefore, I began looking into the different ways of creating dates with more scrutiny.

Originally, to create dates, we simple pass in a string and let SQL Server convert it for us.

SELECT CONVERT(datetime, '12/31/2007')
UNION ALL SELECT CONVERT(datetime, '31-dec-2007')
UNION ALL SELECT CONVERT(datetime, 'December 31, 2007')
UNION ALL SELECT CONVERT(datetime, 'Dec 31, 2007')

But now we have to know and remember which order the date format is on each machine we are deploying our scripts to, as well as educate all others that may need to insert a date. Instead of leaving room for human error, we should be making everything program as pessimistically as possible.

Thankfully, SQL 2000 and 2005 have UDFs; therefore, all we need is to decide on is a simple form of input. Since all dates are made up of years, months, and days; I’d say the input is already decided.

CREATE FUNCTION [dbo].[createDate] (
	yr smallint,
	mth tinyint,
	dy tinyint = 1
) RETURNS smalldatetime AS begin
	DECLARE @date varchar(12);

	-- Overrides language for this transaction
	SET DATEFORMAT ymd;

	-- Convert the numbers to the date format
	SET @date = convert(varchar(4), yr);
	SET @date = @date + '-' + convert(varchar(2), mth);
	SET @date = @date + '-' + convert(varchar(2), dy);

	RETURN convert(smalldatetime, @date)
end

Of course, we’d want to add in range checking for the inputs, so we can send back more verbose information then simply the SQL’s ‘unable to convert to datetime’ message.

June 16th, 2007

More to come

Filed under: Site News — Tyler @ 12:02 PM

Busy life. New job, and new baby in the family. Needless to say, things have been hectic around here. As things start to normalize somewhat, I will be able to return to my online homes.

Thanks for your patients.

Older Posts »

Theme: Silver is the New Black. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.