AARON SMITH’S CODE ENDEAVOR

Archive for August, 2009

Snow Leopard Clean Install - Disk Utility Error: Could not unmount disk

I was doing a clean install of Snow Leopard on an older MBP, and got the message “Error: Could not unmount disk.” Somewhat confused at first - I tried it a couple times, restarted the machine, etc. Still no go.

For some reason the hard drive had some open files or applications - which would cause the error. The solution is not obvious, and I just happened to randomly try this and it worked!

-Boot to your into the Snow Leopard installer.
-Open Disk Utilities
-Select the “Macintosh HD” partition, and press the “Unmount” button. (You’ll get an error asking you to make sure all files and applications are closed)
-Select the DVD-Drive (not the disk) (mine was MATSHITA DVD-RXXXXX), now press the “Eject” button in the toolbar. (You’ll get the same error as above)
-Select the “Macintosh HD” partition again, and press the “Unmount” button. This time, it will successfully unmount.

Now you can continue to erase the Macintosh HD partition, and do a clean install of Snow.

Hopefully this works for more people than just me.

3 comments

XCode and Clang Static Analyzer

First, check out clang static analyzer.

To get it running form Xcode make a new “Shell Script Target,” call it “Clang,” and for it’s “script build phase” put this in it:

/usr/bin/scan-build -V xcodebuild -configuration $CONFIGURATION

This is assuming the scan-build tool is in /usr/bin/, change the path if you need to. Now, change your build target to Clang, and build it. All it does is run the script, which will in turn build the project for your configuration (usually debug or release). And, if clang finds any problems, it will automatically open your browser to show you the output, if no problems are present, it’s just a successful build.

No comments

Guttershark Service Manager: SOAP

Ok folks, here’s how you can hook up soap with guttershark.

Here’s a main class: (there are a couple things I explain next)

package
{
 
	public class Main extends Sprite
	{
 
		private var sm:ServiceManager;
 
		public function Main()
		{
			sm=ServiceManager.gi();
			sm.createSOAPService("myWSDL","http://www.example.com/wsdl",3,5000);
			callSoap();
		}
 
		public function callSoap()
		{
			sm.myWSDL.someMethod({
				params:{someParameter:"hello world"},
				resultHandlerClass:MySoapResultHandler,
				onResult:onSoapResult,
				onFault:onSoapFault,
				onFirstCall:onFirstCall,
				onMethodNotAvailable:onMethodNotAvailable,
			});
		}
 
		public function onFirstCall():void
		{
			trace("trying soap service");
			showLoader();
		}
 
		public function onSoapFault(sf:SoapFault):void
		{
			trace("fault");
		}
 
		public function onSoapResult(sr:SoapResult):void
		{
			trace("result");
			trace(sr.raw);
			trace(sr.handler); //instance of resultHandlerClass.
		}
 
		public function onMethodNotAvailable():void
		{
			trace("method was not available on wsdl");
		}
	}
}

When you create a soap service (createSOAPService), the service manager downloads your WSDL and parses it out. It stores some information that you can get at runtime. For example, if you wanted to list out the supported methods on this wsdl:

sm.myWSDL.listMethods();

That’s generally all that you need, and that’s only needed in support of debugging.

Generating the Soap Message

The service manager generates the soap message to send to the server based off of the params object you give it. In the above code example, it’s going to generate a soap message that looks like this:

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <someMethod xmlns="http://webservicelocation/">
      <someParameter>hello world</someParameter>
    </someMethod>
  </soap:Body>
</soap:Envelope>

Handling the Result

The service manager requires you to give it a “result handler class.” This handler class gives you a hook to handle the soap result, before it’s handed off to your callbacks.

In the above example, there is this line (part of call props):

resultHandlerClass:MySoapResultHandler,

“MySoapResultHandler” needs to be a class that you create, to handle the result. Here’s that class:

package
{
 
	import net.guttershark.support.servicemanager.soap.SoapFaultError;
	import net.guttershark.support.servicemanager.soap.SoapResultHandler;
 
	public class MySoapResultHandler extends SoapResultHandler
	{
 
		public var somePropertyOnTheResult;
 
		override protected function process():void
		{
			super.process();
			super.setNamespace();
			super.setBody();
			super.setFault();
 
			//if it get's passed this its an ok result.
			if(soapFault) throw new SoapFaultError(soapFault);
 
			somePropertyOnTheResult = soapBody.someResult.toString();
		}
	}
}

The reason we create this soap result handler class is to delegate processing of the result XML into this class, and abstract it out of your application and the service manager.

There’s one thing to note that’s special about the SoapResultHandler, if you throw a “SoapFaultErorr”, anywhere from the process method, it will be raised back up through the service manager, and trigger your “onFault” callback.

So, in the above handler class, if “soapFault” is set, it throws an error - as mentioned this will ultimately trigger your onFault callback.

Now let’s take a look at an updated “onResult” callback function from the Main class, to do something with our handler:

public function onSoapResult(sr:SoapResult):void
{
    trace("result");
    trace(sr.raw); //raw soap xml response.
    trace(sr.handler); //this is the instance of your result handler - an instance of MySoapResultHandler.
    trace(sr.handler.somePropertyOnTheResult);
}

After the service manager processes your soap result handler, it calls your onResult handler. There’s a property on the SoapResult class called “handler”, which will be an instance of your handler class.

The service manager uses your handler class as a middle man so you can do what you want with the result - before it’s passed on. Hopefully you can see how nice this is. It keeps everything abstract from your application, and allows you to just focus on business logic. And also not clutter the methods that do all the work with a result.

Generally, for every soap method you’re going to call, you create a soap handler class. Each soap handler class can process the result specifically for that method call.

Other things to note

There’s one additional property you can set on a service call “showSoapRequest”:

sm.myWSDL.someMethod({
  params:{someParameter:"hello world"},
  resultHandlerClass:MySoapResultHandler,
  onResult:onSoapResult,
  onFault:onSoapFault,
  onFirstCall:onFirstCall,
  onMethodNotAvailable:onMethodNotAvailable,
  showSoapRequest:true, //
});

This option will trace the generated soap request that’s being sent to the server.

Integrating Soap With The Model

Here’s a model file:

<xml version="1.0" encoding="utf-8">
<model>
	<services>
		<service id="mySoapService" wsdl="mySoapServiceWSDL" attempts="3" timeout="5000" />
		<wsdl id="mySoapServiceWSDL" endpoint="http://www.example.com/wsdl" />
	</services>
</model>

And here’s the update class file:

package
{
 
	import net.guttershark.control.DocumentController;
 
	public class Main extends DocumentController
	{
 
		override protected function flashvarsForStandalone():Object
		{
			return {
				model:"model.xml",
				initServices:true,
			}
		}
 
		override protected function setupComplete():void
		{
			callSoap();
		}
 
		public function callSoap()
		{
			sm.myWSDL.someMethod({
				params:{someParameter:"hello world"},
				resultHandlerClass:MySoapResultHandler,
				onResult:onSoapResult,
				onFault:onSoapFault,
				onFirstCall:onFirstCall,
				onMethodNotAvailable:onMethodNotAvailable,
				showSoapRequest:true,
			});
		}
 
		public function onFirstCall():void
		{
			trace("trying soap service");
			showLoader();
		}
 
		public function onSoapFault(sf:SoapFault):void
		{
			trace("fault");
		}
 
		public function onSoapResult(sr:SoapResult):void
		{
			trace("result");
			trace(sr.raw);
			trace(sr.handler); //instance of resultHandlerClass.
			trace(sr.handler.somePropertyOnTheResult);
		}
 
		public function onMethodNotAvailable():void
		{
			trace("method was not available on wsdl");
		}
	}
}

Crossdomain Issues

With SOAP, Flash has to send over a header called “SOAPAction”, so you’re crossdomains need to allow headers for this.

Conclusion

Soap services are greatly simplified with guttershark - which allows you to focus on business logic of you’re application. Additionally, I hate wasting time on code that’s already been written, don’t you?

Additionally, you should read through the source of the classes that support SOAP functionality. They are in “net.guttershark.support.servicemanager.soap.”

6 comments

Guttershark Service Manager: HTTP Calls

A key thing in flash that has to be done all too often is making some sort of service call. If you’re not using an AS3 api for a social service, like (cough twitter), it tends to be annoying to implement - because you always write the same code to accomplish some http call, but it’s just sending different parameters.

Guttershark has a service manager that handles doing all this for you, with built-in options for retries, timeouts, maximum attempts, and a bunch of other stuff. And it’s all integrated with the Model, or you can use it by itself. Let’s take a look.

Manually setting up the service manager:

package
{
 
	import net.guttershark.managers.ServiceManager;
	import net.guttershark.support.servicemanager.shared.CallResult;
 
	public class Main extends Sprite
	{
 
		private var sm:ServiceManager;
 
		public function Main()
		{
			sm = ServiceManager.gi();
			sm.createHTTPService("searchGoogle","http://www.google.com/",3,5000);
			var data:Object = {};
			data.q = "Guttershark";
			sm.searchGoogle({
				method:"get",
				data:data,
				responseFormat:"text",
				onResult:onGoogleResult,
				onFault:onGoogleFault,
				onRetry:onGoogleRetry,
				onTimeout:onGoogleTimedOut,
				onFirstCall:onGoogleFirstCall,
			});
		}
 
		public function onGoogleResult(cr:CallResult):void
		{
			trace(cr.result);
			hideStatusIndicator();
		}
 
		public function onGoogleFault(cf:CallFault):void
		{
			trace("FAULT");
			hideStatusIndicator();
		}
 
		public function onGoogleFirstCall():void
		{
			trace("first call to google service.");
			statusIndicator.show();
		}
 
		public function onGoogleRetry():void
		{
			trace("retrying google service");
		}
 
		public function onGoogleTimedOut():void
		{
			trace("timedout");
			hideStatusIndicator();
		}
 
		private function hideStatusIndicator():void
		{
			statusIndicator.hide();
		}
	}
}

Quick side note, please bare with me - some of this is a mix of psuedo code just to illustrate how the callbacks can be used to control different elements.

The above code is somewhat obvious, except for one line:

sm.createHTTPService("searchGoogle","http://www.google.com/",3,5000);

This creates a service called “searchGoogle”, who’s endpoint is that URL.. 3 is the number of attempts to allow, and 5000 is the timeout for each attempt. So in this case, it will call the service once, if a result or fault doesn’t happen within 5000 milliseconds, another attempt will be fired, so on and so fourth.

The service manager, like a couple other classes in Guttershark is a dynamic classes. So, when you create the http service, you can access it like a property of the service manager (sm.searchGoogle).

Easy though right? Let’s look at how it’s integrated with the model:

Model XML:

<?xml version="1.0" encoding="utf-8">
<model>
	<services>
		<service id="searchGoogle" url="http://www.google.com/" attempts="3" timeout="5000" />
	<services>
</model>

Here’s an update Main class file that extends doc controller to integrate the model:

package
{
 
	import net.guttershark.control.DocumentController;
	import net.guttershark.managers.ServiceManager;
	import net.guttershark.support.servicemanager.shared.CallResult;
 
	public class Main extends DocumentController
	{
 
		override protected function flashvarsForStandalone():Object
		{
			return {
				model:"model.xml",
				initServices:true
			}
		}
 
		override protected function setupComplete():void
		{
			var data:Object = {};
			data.q = "Guttershark";
			sm.searchGoogle({
				method:"get",
				data:data,
				responseFormat:"text",
				onResult:onGoogleResult,
				onFault:onGoogleFault,
				onRetry:onGoogleRetry,
				onTimeout:onGoogleTimedOut,
				onFirstCall:onGoogleFirstCall,
			});
		}
 
		public function onGoogleResult(cr:CallResult):void
		{
			trace(cr.result);
			hideStatusIndicator();
		}
 
		public function onGoogleFault(cf:CallFault):void
		{
			trace("FAULT");
			hideStatusIndicator();
		}
 
		public function onGoogleFirstCall():void
		{
			trace("first call to google service.");
			statusIndicator.show();
		}
 
		public function onGoogleRetry():void
		{
			trace("retrying google service");
		}
 
		public function onGoogleTimedOut():void
		{
			trace("timedout");
			hideStatusIndicator();
		}
 
		private function hideStatusIndicator():void
		{
			statusIndicator.hide();
		}
	}
}

Response Formats

The service manager, handles a few different types of response formats: text, binary, xml, and variables. The service manager will intelligently handle results, based off of those types.

For example, let’s say you make a service call to get some XML data. Let’s assume the request completed with a 200 OK. But, there was an error on the server side that caused a result to be returned that isn’t the expected data. As long as structure the XML a certain way, the service manager will call you onFault callback. Here’s an example:

XML Response Format

The service call:

sm.createHTTPService("myXMLService","http://example.com/xmlService",3,5000);
sm.myXMLService({method:"post",responseFormat:"xml",...});

Successful result (will call the onResult callback):

<?xml version="1.0" encoding="utf-8">
<response>
	<someData>Hello World</someData>
</response>

Trigger a fault:

<?xml version="1.0" encoding="utf-8">
<response>
	<fault>There was an error</fault>
</response>

Variables Response Format

The service call:

sm.createHTTPService("myXMLService","http://example.com/xmlService",3,5000);
sm.myXMLService({method:"post",responseFormat:"variables",...});

Successful result (will call the onResult callback):

&name=Aaron&lname=Smith&site=codeendeavor.com

Trigger a fault:

&fault=There was an error

You can access the result variables as an object on the CallResult, for example:

function onResult(cr:CallResult):void
{
    trace(cr.result.lname);
}

The only response formats that are intelligently handled are variables and xml. The other formats are raw data so you’d have to handle it yourself in the result callback.

Routes with Web Frameworks

The service manager can also handle routes for http services. The general ideas is that the “service” is the base URL to the site that exposes routes, then you tell the service manager which routes to append. For example:

sm.createHTTPService("myRestfulSite","http://www.example.com/",3,5000);
var username:String = "b00g3r";
sm.myRestfulService({method:"GET", routes:["user",username,"friends"], responseFormat:"xml"});

This example will end up calling “http://www.example.com/user/b00g3r/friends”.

Conclusion

That’s all there is for HTTP services with the service manager. The service manager also exposes remoting, and SOAP - in the same dynamic/simplistic manner.

I would recommend reading the source that supports HTTP services:

net.guttershark.managers.ServiceManager;
net.guttershark.support.servicemanager.shared.BaseCall
net.guttershark.support.servicemanager.shared.CallResult
net.guttershark.support.servicemanager.shared.CallFault
net.guttershark.support.servicemanager.http.Service
net.guttershark.support.servicemanager.http.ServiceCall

I’ll show you the remoting, and SOAP support next.

No comments

Apple System Log Cocoa Wrapper

Here’s a quick apple system log cocoa wrapper. Open the terminal, and type “man asl,” asl is the wrapper around syslog - which seems to be the first syslog for apple. The Console app (/Applications/Utilities/Console) shows all messages sent through asl.

Here’s a link to the files:

GDASLLog.h
GDASLLog.m
GDASLLogManager.h
GDASLLogManager.m

And here’s how you want to use it:

GDASLLog * log = [[GDASLLog alloc] initWithSender:@"MyAppName" facility:@"com.codeendeavor.MyAppName" connectsImmediately:TRUE];
 
//optionally set the file to write to. You'll still see logs in Console if you don't set this,
//but this way you can get the log file if needed.
[log setLogFile:@"/Library/Logs/MyApp"];
 
[log info:@"HELLO WORLD"];

And there’s a manager to hold references to your logs:

GDASLLogManager * gdLogMan = [GDASLLogManager sharedInstance];
[gdLogMan setLog:log forKey:@"logID"];
 
//GDASLLog * log = [gdLogMan getLogForKey:@"logID"];

I’ve been using this in an app to log some problems that were happening on another computer. I don’t leave these in when it’s ready to go. This just simplifies writing out some logs.

Enjoy.

1 comment

Mac Volume Ejector: Ejectlet

I wrote this quick little menulet to replace Apple’s built in eject menu, which only lets you eject the dvd drive.

Here’s a snapshot:

Ejectlet

Download it. (10.5 Universal)

3 comments

Font Libraries with Guttershark

Another key thing when working with Flash is fonts. It can be somewhat intimidating as the documentation for using font library symbols doesn’t make anything obvious. It takes a bit of reading and messing around to get it right.

If you do some snooping around on google, there are quite a few articles that outline the basics of using embedded fonts, or font libraries. I’ll take you beyond what the basics are, and show you how to integrate font libraries with guttershark.

First things first, let’s look at the model file for loading fonts:

<model>
	<assets>
		<asset libraryName="fonts" src="fonts.swf" preload="true" />
	</assets>
	<fonts>
		<font libraryName="LucidaGrandeBold" />
		<font libraryName="LucidaGrandeRegular" />
	</fonts>
</model>

This model file defines an asset to load, which is a swf that contains our fonts. And it declares two fonts that need to be registered with Flash’s Font.registerFont method.

Now let’s look at the first pass of a document controller:

package
{
 
	import flash.text.TextFormat;
	import flash.text.TextField;
	import flash.events.Event;
	import net.guttershark.control.PreloadController;
	import net.guttershark.control.DocumentController;
 
	public class Main extends DocumentController
	{
 
		override protected function flashvarsForStandalone():Object
		{
			return {model:"model.xml"};
		}
 
		override protected function setupComplete():void
		{
			pc=new PreloadController();
			pc.addItems(ml.getAssetsForPreload());
			pc.addEventListener(Event.COMPLETE,onComplete);
			pc.start();
		}
 
		private function onComplete(e:Event):void
		{
			//this registers every font that is declared in model XML.
			ml.registerFonts();
		}
	}
}

This document controller set’s up the bare minimum to get fonts loaded in and registered. From there, we’re ready to start using embedded fonts on text fields with text formats, or stylesheets.

Before we do that, let’s take a look at some some key methods that guttershark has for getting and setting stylesheets or text formats, and i’ll explain what they do internally.

Two key methods:

 - Model#getTextFormatById()
 - Model#getStyleSheetById()

The most important thing that these two methods do is automatically resolve fonts to their “proper name”. A proper name is the name of a font instance - the “fontName” property of a Font instance.

Here’s an addition to the model for a textformat:

...
<textformats>
		<textformat id="labelText" font="LucidaGrandeBold" size="14" />
</textformats>
...

In this example, the “font=LucidaGrandeBold” indicates that the font to use is the font “LucidaGrandeBold” which in turn is the “export for actionscript” name in the fonts swf. Internally, the getTextFormatById method retrieves an instance of this font object, and assigns the “font” property of a textformat with “font.fontName”.

Here’s some psuedo code to show what this method does:

function getTextFormatById(id:String):TextFormat
{
    finalTextFormat = new TextFormat();
    tfNode = getXMLNodeByID;
    fontName = tfNode.@font;
    fontClass = getFontFromLibrary(fontName);
    Font.registerFont(fontClass);
    fontInstance = fontClass();
    finaltextFormat.font = fontInstance.fontName; //KEY
    //apply other node attribtues to textFormat (bold, size, etc)
    return finalTextFormat;
}

Simple right? Now let’s make an addition in the model for stylesheets:

...
<stylesheets>
		<stylesheet id="example">
			<![CDATA[
				.body{
					font:LucidaGrandeRegular;
					fontSize:10;
				}
			]]>
		</stylesheet>
</stylesheets>
...

Gutteshark supports a custom css property “font”, which indicates to guttershark that it should look up that font, and get the right “proper name” for that font, and use it as the “fontFamily” property.

Here’s some psuedo code for this method:

function getStyleSheetById(id:String):StyleSheet
{
    styleSheet = getStyleSheetNodeFromXML;
    styleSheet = CSS.parseCSS(styleSheet.toString());
    styleNames = styleSheet.styleNames;
    var finalFontFamily:String;
    l = styleNames.length;
    i = 0;
    for(i;i<l;i++)
    {
        style = styleSheet.getStyle(styleNames[i])
        for(key in style)
        {
            if(key=="font")
            {
                fontClass = AssetManager.gi().getClass(style[key]);
                Font.registerFont(fontClass);
                fontInstance = fontClass();
                finalFontFamily = fontInstance.fontName;
                delete style[key];
            }
        }
        if(finalFontFamily) style['fontFamily'] = finalFontFamily; //KEY
        styleSheet.setStyle(styleNames[i],style); //update final style
    }
    return styleSheet;
}

Fairly simple right?

The benefit of all this is that you no longer need to write exhaustive code for every text field, and with the help of some shortcuts, we can setup up embedded text fields into a few lines of code.

Here’s an example of the work required for setting up text formats for each text field, without the help of guttershark:

var fc:FontClass = AssetManager.gi().getClass("MyFontLibraryName");
Font.registerFont(fc);
var fi:Font = fc();
 
var tf:TextFormat = new TextFormat();
tf.font = fi.fontName;
//set other textFormat properties
 
var tfield:TextField = myTFOnTheStage;
tfield.embedFonts = true;
tfield.defaultTextFormat = tf;
tfield.text = "Hello World";

Here’s an example with guttershark’s help:

var tf:TextFormat = ml.getTextFormatById("example");
var tfield:TextField = myTextFieldOnTheStage;
utils.text.textFormat(tfield,tf);
tfield.text = "Hello World";

Much cleaner.

Ok, so let’s put some of this together with a real example. Here’s the final model xml file:

<?xml version="1.0" encoding="utf-8"?>
<model>
 
	<assets>
		<asset libraryName="fonts" src="fonts.swf" preload="true" />
	</assets>
 
	<fonts>
		<font libraryName="LucidaGrandeBold" />
		<font libraryName="LucidaGrandeRegular" />
	</fonts>
 
	<textformats>
		<textformat id="labelText" font="LucidaGrandeBold" size="14" />
		<textformat id="lucidaGBold10" font="LucidaGrandeBold" size="10" bold="true" />
		<textformat id="lucidaGBold12" font="LucidaGrandeBold" size="12" bold="true" />
		<textformat id="lucidaGRegular10" font="LucidaGrandeRegular" size="10" />
		<textformat id="lucidaGRegular12" font="LucidaGrandeRegular" size="12" />
	</textformats>
 
	<stylesheets>
		<stylesheet id="example">
			<![CDATA[
				.body{
					font:LucidaGrandeRegular;
					fontSize:10;
				}
			]]>
		</stylesheet>
 
		<stylesheet id="example2">
			<![CDATA[
				.body{
					font:LucidaGrandeRegular;
					fontSize:10;
				}
				.bold{
					font:LucidaGrandeBold;
					fontWeight:bold;
					fontSize:14;
					color:#FF0066;
				}
			]]>
		</stylesheet>
	</stylesheets>
</model>

And here’s the final document controller:

package
{
 
	import flash.text.TextFormat;
	import flash.text.TextField;
	import flash.events.Event;
	import net.guttershark.control.PreloadController;
	import net.guttershark.control.DocumentController;
 
	public class Main extends DocumentController
	{
 
		//bunch of fields on stage..
		public var stylesheetsLabel:TextField;
		public var textFormatsLabel:TextField;
		public var txf1:TextField;
		public var txf2:TextField;
		public var txf3:TextField;
		public var txf4:TextField;
		public var txf5:TextField;
		public var txf6:TextField;
		public var txf7:TextField;
		public var ss1:TextField;
		public var ss2:TextField;
		public var ss3:TextField;
		public var ss4:TextField;
		public var ss5:TextField;
		public var ss6:TextField;
		public var ss7:TextField;
 
		override protected function flashvarsForStandalone():Object
		{
			return {model:"model.xml"};
		}
 
		override protected function setupComplete():void
		{
			pc=new PreloadController();
			pc.addItems(ml.getAssetsForPreload());
			pc.addEventListener(Event.COMPLETE,onComplete);
			pc.start();
		}
 
		private function onComplete(e:Event):void
		{
			//this registers every font that is declared in XML.
			ml.registerFonts();
 
			//set up the labels.
			var labelTF:TextFormat = ml.getTextFormatById("labelText");
			stylesheetsLabel.embedFonts=true;
			stylesheetsLabel.setTextFormat(labelTF);
			textFormatsLabel.embedFonts=true;
			textFormatsLabel.setTextFormat(labelTF);
 
 
			//TEXTFIELDS
 
			txf1.embedFonts=true;
			txf1.setTextFormat(ml.getTextFormatById("lucidaGBold10"));
 
			txf2.embedFonts=true;
			txf2.setTextFormat(ml.getTextFormatById("lucidaGBold12"));
 
			//use shortcuts for other textformats.
			utils.text.textFormat(txf3,ml.getTextFormatById("lucidaGRegular10"));
			utils.text.textFormat(txf4,ml.getTextFormatById("lucidaGRegular12"));
 
			//another shortcut type.
			utils.setters.textFormat(ml.getTextFormatById("lucidaGRegular10"),txf5,txf6,txf7);
 
 
			//STYLESHEETS
 
			ss1.embedFonts=true;
			ss1.styleSheet=ml.getStyleSheetById("example");
			ss1.htmlText="<span class=\"body\">"+ss1.text+"</span>";
 
			ss2.embedFonts=true;
			ss2.styleSheet=ml.getStyleSheetById("example2");
			ss2.htmlText="<span class=\"body\">"+ss2.text+"<span class=\"bold\">. and this is bold.</span></span>";
 
			//stylsheet shortcuts
			utils.text.styleSheet(ss3,ml.getStyleSheetById("example"));
			ss3.htmlText="<span class=\"body\">"+ss3.text+"</span>";
 
			utils.text.styleSheet(ss4,ml.getStyleSheetById("example"));
			ss4.htmlText="<span class=\"body\">"+ss4.text+"</span>";
 
			//another shortcut type
			utils.setters.stylesheet(ml.getStyleSheetById("example"),ss5,ss6,ss7);
			ss5.htmlText="<span class=\"body\">"+ss5.text+"</span>";
			ss6.htmlText="<span class=\"body\">"+ss6.text+"</span>";
			ss7.htmlText="<span class=\"body\">"+ss7.text+"</span>";
		}
	}
}

This example uses some other great shortcuts for preparing text fields for stylesheets, or text formats:

- utils.text.textFormat
- utils.text.textWithTextFormat
- utils.text.textWithTextFormatFromLocaleString
- utils.text.textWithFormattingFromXML
- utils.text.styleSheet
- utils.setters.textFormat
- utils.setters.styleSheet

I’m not going to explain all of those, I’d recommend reading the source for those methods. As well as reading the source for the two model methods (getTextFormatById, and getStyleSheetById).

I put this example in the guttershark repository for all. Pull down the latest version, and checkout “examples/other/font_libs/ex1″. You can get the latest version in git.

enjoy.

3 comments