As announced yesterday, Quartam PDF Library for LiveCode is now a free / open source software project, available under the terms of the GNU Affero General Public License (AGPL).
One of the advantages of version 1.1.0 is that it comes with support for LiveCode Server and On-Rev. I just put up a page with demos so that you can see how straightforward it is to port your desktop PDF generation scripts to .irev scripts.
As it turns out, there are two bugs to address: loading images throws errors, and callback messages have problems as well. Unfortunately, I'm working frantically to finish my presentations for RunRevLive.11 - but now that it's an open source project, anyone can go and take a stab at fixing bugs. So I'm looking forward to your helping hand in finding solutions so we can put out an update soon.
Onwards!
Friday, April 22, 2011
Thursday, April 21, 2011
Quartam PDF Library goes open source
Today, Quartam Software is proud to announce the release of Quartam PDF Library for LiveCode version 1.1, as open source under a dual license. Quartam PDF Library allows LiveCode developers to go beyond 'print to pdf file' as it offers pin-point control, extensive graphics support and much more.
Where does Quartam PDF Library come from?
Back in December 2005, I started Quartam PDF Library as a research project for adding PDF export to Quartam Reports. It was spun off as a separate commercial product and used in a wide variety of LiveCode-based projects, such as BlueMango's ScreenSteps.
Although I had kept working on new features, more pressing matters (like my day-job) kept me from pushing ahead and wrapping up a new release. The advent of 'print to pdf' features in LiveCode 4.5 triggered a soul search and eventually led to the decision to release the new version as open source.
The end result: nearly 7300 lines of production quality code, ready for you to use in your LiveCode projects.
So what is new in version 1.1?
The code got a good cleanup, complies with the rules of variable checking, and replaces most string literals with constants to prevent bugs.
Plus, the following features were added:
- Transformations (scale, translate, rotate, skew, mirror)
- Transparency and blendmodes
- Gradients
- Clipping
- Text box fitting
- Inserting pages (ideal for building a table of contents with bookmarks)
- Compression
- Experimental support for including EPS files (Emulated PostScript)
And for the first time, we offer support for generating PDF documents in LiveCode Server scripts, including On-Rev!
Quartam PDF Library now requires Revolution 3.0 or later, with LiveCode 4.6 highly recommended.
How do you mean: open source under a dual license?
Although Quartam PDF Library is a free/open source software (F/OSS) project, giving you a lot of freedom and flexibility as to how you use it in your own projects, this doesn't mean you're free to do anything you want with it: you have to respect the GNU Affero General Public License (AGPL).
You can be released from the requirements of the AGPL license by purchasing a commercial license from Quartam Software.
Buying such a license is mandatory as soon as you develop commercial activities involving Quartam PDF Library without disclosing the source code of your own applications. These activities include: offering paid services to customers as an ASP, serving PDF documents generated dynamically in a web application, shipping Quartam PDF Library with a closed source product.
Such a commercial license releases you from the requirements of the copyleft AGPL license, which include: distribution of all source code, including your own product; licensing of your own product under the AGPL license; prominent mention of the Quartam copyright and the AGPL license; and disclosure of modifications to the library.
In addition, the commercial license releases you from the requirement not to change the PDF Producer line in the generated PDF document properties.
What about my previous commercial license for Quartam PDF Library version 1.0?
Of course you can keep using the closed source version 1.0 in your projects. And if your project is open source, you can use version 1.1 without an additional charge.
However, if you want to use version 1.1 in a commercial activity, you have to purchase an upgrade for USD 49 from the Quartam Software Online Store.
And if you never bought a copy of Quartam PDF Library, you can purchase the commercial license for USD 149 from the Quartam Software Online Store or the LiveCode Marketplace.
How can I contribute to the Quartam PDF Library project?
I'm glad you asked - the plan is to build a community around Quartam PDF Library in order to streamline the development of newer versions. If you can help with squashing bugs, researching new features, improving documentation, or any other way, you're more than welcome to join us.
All you need to do is download, sign and email back the Quartam Open Source Contributor Agreement so that your contributions can be incorporated into the project. Quartam Software has the role of project custodian, taking care of versioning and distribution.
One such contribution was made by John Craig (Splash21) to add compression support to the library, which is included in Quartam PDF Library version 1.1 - another contribution was made by Trevor DeVore (BlueMango) who offered code for writing LiveCode htmlText to a PDF document, which I have yet to integrate but looks really promising.
And I have some experimental code that I'd love to share and put into the project after review - so any reports of this library's death were greatly exaggerated.
So roll up your sleeves, download the new version and get stuck in!
Where does Quartam PDF Library come from?
Back in December 2005, I started Quartam PDF Library as a research project for adding PDF export to Quartam Reports. It was spun off as a separate commercial product and used in a wide variety of LiveCode-based projects, such as BlueMango's ScreenSteps.
Although I had kept working on new features, more pressing matters (like my day-job) kept me from pushing ahead and wrapping up a new release. The advent of 'print to pdf' features in LiveCode 4.5 triggered a soul search and eventually led to the decision to release the new version as open source.
The end result: nearly 7300 lines of production quality code, ready for you to use in your LiveCode projects.
So what is new in version 1.1?
The code got a good cleanup, complies with the rules of variable checking, and replaces most string literals with constants to prevent bugs.
Plus, the following features were added:
- Transformations (scale, translate, rotate, skew, mirror)
- Transparency and blendmodes
- Gradients
- Clipping
- Text box fitting
- Inserting pages (ideal for building a table of contents with bookmarks)
- Compression
- Experimental support for including EPS files (Emulated PostScript)
And for the first time, we offer support for generating PDF documents in LiveCode Server scripts, including On-Rev!
Quartam PDF Library now requires Revolution 3.0 or later, with LiveCode 4.6 highly recommended.
How do you mean: open source under a dual license?
Although Quartam PDF Library is a free/open source software (F/OSS) project, giving you a lot of freedom and flexibility as to how you use it in your own projects, this doesn't mean you're free to do anything you want with it: you have to respect the GNU Affero General Public License (AGPL).
You can be released from the requirements of the AGPL license by purchasing a commercial license from Quartam Software.
Buying such a license is mandatory as soon as you develop commercial activities involving Quartam PDF Library without disclosing the source code of your own applications. These activities include: offering paid services to customers as an ASP, serving PDF documents generated dynamically in a web application, shipping Quartam PDF Library with a closed source product.
Such a commercial license releases you from the requirements of the copyleft AGPL license, which include: distribution of all source code, including your own product; licensing of your own product under the AGPL license; prominent mention of the Quartam copyright and the AGPL license; and disclosure of modifications to the library.
In addition, the commercial license releases you from the requirement not to change the PDF Producer line in the generated PDF document properties.
What about my previous commercial license for Quartam PDF Library version 1.0?
Of course you can keep using the closed source version 1.0 in your projects. And if your project is open source, you can use version 1.1 without an additional charge.
However, if you want to use version 1.1 in a commercial activity, you have to purchase an upgrade for USD 49 from the Quartam Software Online Store.
And if you never bought a copy of Quartam PDF Library, you can purchase the commercial license for USD 149 from the Quartam Software Online Store or the LiveCode Marketplace.
How can I contribute to the Quartam PDF Library project?
I'm glad you asked - the plan is to build a community around Quartam PDF Library in order to streamline the development of newer versions. If you can help with squashing bugs, researching new features, improving documentation, or any other way, you're more than welcome to join us.
All you need to do is download, sign and email back the Quartam Open Source Contributor Agreement so that your contributions can be incorporated into the project. Quartam Software has the role of project custodian, taking care of versioning and distribution.
One such contribution was made by John Craig (Splash21) to add compression support to the library, which is included in Quartam PDF Library version 1.1 - another contribution was made by Trevor DeVore (BlueMango) who offered code for writing LiveCode htmlText to a PDF document, which I have yet to integrate but looks really promising.
And I have some experimental code that I'd love to share and put into the project after review - so any reports of this library's death were greatly exaggerated.
So roll up your sleeves, download the new version and get stuck in!
Sunday, April 17, 2011
Presenting at RunRevLive.11
Next week I'll be at the RunRevLive.11 conference in sunny San Jose, California, giving two presentations: Advanced Databases and Extending LiveCode with Java. Here is a brief description for both sessions.
--
Advanced databases:
You've just finished a desktop application that stores its data in a local SQLite database. All works well, and now you're asked to make a multi-user version, so that other users can access and update the data as well. Unfortunately, you can't just load the data into a MySQL dataabse and be done with it: your data structures and business logic have to be ready as well!
In this presentation, I'll take a desktop SQLite application and turn it into a front-end for a networked MySQL database. Along the way, you'll get crucial tips to avoid the pitfalls of such a transformation.
Extending LiveCode with Java:
We all love LiveCode for its cross-platform abilities, combined with an elegant and productive scripting language. But the 200-pound gorilla in this space is indubitably Java. In this presentation we will see how we can leverage Java libraries from within LiveCode through process communication.
This allows us to extend our LiveCode desktop applications with Zeroconf discovery, XML schemas, PDF file enhancements and image processing.
--
Last but not least, you're invited to drop by the LiveCode Marketplace vendor area and ask me any questions you have regarding the Quartam developer tools for LiveCode. You might even get a sneak preview of Quartam Reports 1.2 :-)
--
Advanced databases:
You've just finished a desktop application that stores its data in a local SQLite database. All works well, and now you're asked to make a multi-user version, so that other users can access and update the data as well. Unfortunately, you can't just load the data into a MySQL dataabse and be done with it: your data structures and business logic have to be ready as well!
In this presentation, I'll take a desktop SQLite application and turn it into a front-end for a networked MySQL database. Along the way, you'll get crucial tips to avoid the pitfalls of such a transformation.
Extending LiveCode with Java:
We all love LiveCode for its cross-platform abilities, combined with an elegant and productive scripting language. But the 200-pound gorilla in this space is indubitably Java. In this presentation we will see how we can leverage Java libraries from within LiveCode through process communication.
This allows us to extend our LiveCode desktop applications with Zeroconf discovery, XML schemas, PDF file enhancements and image processing.
--
Last but not least, you're invited to drop by the LiveCode Marketplace vendor area and ask me any questions you have regarding the Quartam developer tools for LiveCode. You might even get a sneak preview of Quartam Reports 1.2 :-)
Sunday, March 6, 2011
Locale aware formatting in LiveCode using Java
Recently on the Use-LiveCode mailing list, Peter Haworth asked how he could get a hold of the date/times/number/currency format preferences to ensure that data display corresponded to the user locale. For date and time, you can use 'the system date' and 'the system time' for quick formatting, and 'the dateFormat' to figure out some of the details. But formatting numbers is quite a different challenge. And even if you can get the 'system' information, what to do if you're building a text that shouldn't be in English or user formatting?
At the risk of sounding like a broken record: let's use Java - it has powerful formatting capabilities for all the required items, and its concept of Locale is robust. To avoid startup overhead and improve response time, we'll use the same approach as for the Zeroconf example: process communication to start a helper process, interact with it, and finally close it when we're done.
So let's write a helper class in Java that will (a) give us the default Locale, (b) list the available locales, (c) allows us to format a LiveCode number as currency, integer or decimal number, applying a given or the default locale, (d) allows us to format a LiveCode date as short, medium, long or full date, applying a given or the default locale, and (e) allows us to format a LiveCode time as short, medium, long or full time, applying a given or the default locale. Sounds like a lot to do, but it's actually quite straightforward to implement:
With the Java helper class written, we can turn our attention to the LiveCode side. Let's create a new stack:

As you can see, we have two buttons at the top for starting/stopping the helper process, along with an option menu to list the available locales and a field to show the default locale. Now put the following into the stack script:
The script for the Start button is easy enough:
And the script of the Stop button is equally trivial:
The script for the Default button in the Number formatting section looks like this:
And the script for the Available button in the Number formatting section looks like this:
Likewise, the script for the Default button in the Date formatting section becomes:
Hence, the script for the Available button in the Date formatting section becomes:
Almost done - here's the script for the Default button in the Time formatting section:
Finally, the logical extension for the Available button in the Time formatting section:
Save the stack, and copy the compiled LiveCodeLocaleHelper.class file into the same directory where you saved the stack. Click the Start button, then play around with the rest of the user interface to enter different numbers, dates and times, clicking the buttons to see the formatting output, switching between the different available locales.
Download it here.
At the risk of sounding like a broken record: let's use Java - it has powerful formatting capabilities for all the required items, and its concept of Locale is robust. To avoid startup overhead and improve response time, we'll use the same approach as for the Zeroconf example: process communication to start a helper process, interact with it, and finally close it when we're done.
So let's write a helper class in Java that will (a) give us the default Locale, (b) list the available locales, (c) allows us to format a LiveCode number as currency, integer or decimal number, applying a given or the default locale, (d) allows us to format a LiveCode date as short, medium, long or full date, applying a given or the default locale, and (e) allows us to format a LiveCode time as short, medium, long or full time, applying a given or the default locale. Sounds like a lot to do, but it's actually quite straightforward to implement:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class LiveCodeLocaleHelper {
private final static String EXIT_COMMAND = "exit";
private final static String LIST_COMMAND = "list";
private final static String DEFAULT_COMMAND = "default";
private final static String CURRENCY_COMMAND = "currency";
private final static String INTEGER_COMMAND = "integer";
private final static String NUMBER_COMMAND = "number";
private final static String DATE_COMMAND = "date";
private final static String TIME_COMMAND = "time";
private static final MapLOCALE_MAP;
private static final DateFormat LC_DATE_FORMAT;
private static final DateFormat LC_TIME_FORMAT;
static {
Locale en_US_locale = null;
LOCALE_MAP = new HashMap();
for (Locale locale : Locale.getAvailableLocales()) {
if ("en".equals(locale.getLanguage()) && "US".equals(locale.getCountry())) {
en_US_locale = locale;
}
LOCALE_MAP.put(locale.toString(), locale);
}
LC_DATE_FORMAT = DateFormat.getDateInstance(DateFormat.SHORT, en_US_locale);
LC_TIME_FORMAT = DateFormat.getTimeInstance(DateFormat.SHORT, en_US_locale);
}
public static void main(final String[] args) throws IOException {
String commandLine = ""; // the last received command line
System.out.println("LiveCodeLocaleHelper started. Type the command you wish to execute (type 'exit' to stop):");
final InputStreamReader isr = new InputStreamReader(System.in);
final BufferedReader bir = new BufferedReader(isr);
while(!EXIT_COMMAND.equalsIgnoreCase(commandLine)) {
commandLine = bir.readLine();
final String[] commandParts = commandLine.split("\t");
final String commandName = commandParts[0];
if (EXIT_COMMAND.equalsIgnoreCase(commandName)) {
System.out.println("LiveCodeLocaleHelper is exiting");
} else if (LIST_COMMAND.equalsIgnoreCase(commandName)) {
handleListCommand(commandParts);
} else if (DEFAULT_COMMAND.equalsIgnoreCase(commandName)) {
handleDefaultCommand(commandParts);
} else if (CURRENCY_COMMAND.equalsIgnoreCase(commandName)) {
handleCurrencyCommand(commandParts);
} else if (INTEGER_COMMAND.equalsIgnoreCase(commandName)) {
handleIntegerCommand(commandParts);
} else if (NUMBER_COMMAND.equalsIgnoreCase(commandName)) {
handleNumberCommand(commandParts);
} else if (DATE_COMMAND.equalsIgnoreCase(commandName)) {
handleDateCommand(commandParts);
} else if (TIME_COMMAND.equalsIgnoreCase(commandName)) {
handleTimeCommand(commandParts);
} else {
System.out.println("Unrecognized command: " + commandLine);
}
}
}
private static void handleListCommand(final String[] commandParts) {
final ListlocaleIdentifiers = new ArrayList (LOCALE_MAP.keySet());
Collections.sort(localeIdentifiers);
for (String localeIdentifier : localeIdentifiers) {
System.out.println(localeIdentifier);
}
System.out.println(".");
}
private static void handleDefaultCommand(final String[] commandParts) {
System.out.println(Locale.getDefault().toString());
}
private static void handleCurrencyCommand(final String[] commandParts) {
double number;
try {
number = Double.parseDouble(commandParts[1]);
} catch (NumberFormatException e) {
System.out.println("Invalid number: " + commandParts[1]);
return;
}
NumberFormat currencyFormat = null;
if (commandParts.length > 2) {
final String localeIdentifier = commandParts[2];
currencyFormat = NumberFormat.getCurrencyInstance(LOCALE_MAP.get(localeIdentifier));
} else {
currencyFormat = NumberFormat.getCurrencyInstance();
}
System.out.println(currencyFormat.format(number));
}
private static void handleIntegerCommand(final String[] commandParts) {
double number;
try {
number = Double.parseDouble(commandParts[1]);
} catch (NumberFormatException e) {
System.out.println("Invalid number: " + commandParts[1]);
return;
}
NumberFormat integerFormat = null;
if (commandParts.length > 2) {
final String localeIdentifier = commandParts[2];
integerFormat = NumberFormat.getIntegerInstance(LOCALE_MAP.get(localeIdentifier));
} else {
integerFormat = NumberFormat.getIntegerInstance();
}
System.out.println(integerFormat.format(number));
}
private static void handleNumberCommand(final String[] commandParts) {
double number;
try {
number = Double.parseDouble(commandParts[1]);
} catch (NumberFormatException e) {
System.out.println("Invalid number: " + commandParts[1]);
return;
}
NumberFormat numberFormat = null;
if (commandParts.length > 2) {
final String localeIdentifier = commandParts[2];
numberFormat = NumberFormat.getNumberInstance(LOCALE_MAP.get(localeIdentifier));
} else {
numberFormat = NumberFormat.getNumberInstance();
}
System.out.println(numberFormat.format(number));
}
private static void handleDateCommand(final String[] commandParts) {
Date date = null;
try {
date = LC_DATE_FORMAT.parse(commandParts[1]);
} catch (ParseException e) {
System.out.println("Invalid date: " + commandParts[1]);
return;
}
int dateSize = DateFormat.SHORT;
final String dateFormatString = commandParts[2];
if ("medium".equalsIgnoreCase(dateFormatString)) {
dateSize = DateFormat.MEDIUM;
} else if ("long".equalsIgnoreCase(dateFormatString)) {
dateSize = DateFormat.LONG;
} else if ("full".equalsIgnoreCase(dateFormatString)) {
dateSize = DateFormat.FULL;
}
DateFormat dateFormat = null;
if (commandParts.length > 3) {
final String localeIdentifier = commandParts[3];
dateFormat = DateFormat.getDateInstance(dateSize, LOCALE_MAP.get(localeIdentifier));
} else {
dateFormat = DateFormat.getDateInstance(dateSize);
}
System.out.println(dateFormat.format(date));
}
private static void handleTimeCommand(final String[] commandParts) {
Date date = null;
try {
date = LC_TIME_FORMAT.parse(commandParts[1]);
} catch (ParseException e) {
System.out.println("Invalid time: " + commandParts[1]);
return;
}
int timeSize = DateFormat.SHORT;
final String dateFormatString = commandParts[2];
if ("medium".equalsIgnoreCase(dateFormatString)) {
timeSize = DateFormat.MEDIUM;
} else if ("long".equalsIgnoreCase(dateFormatString)) {
timeSize = DateFormat.LONG;
} else if ("full".equalsIgnoreCase(dateFormatString)) {
timeSize = DateFormat.FULL;
}
DateFormat dateFormat = null;
if (commandParts.length > 3) {
final String localeIdentifier = commandParts[3];
dateFormat = DateFormat.getTimeInstance(timeSize, LOCALE_MAP.get(localeIdentifier));
} else {
dateFormat = DateFormat.getTimeInstance(timeSize);
}
System.out.println(dateFormat.format(date));
}
}
With the Java helper class written, we can turn our attention to the LiveCode side. Let's create a new stack:

As you can see, we have two buttons at the top for starting/stopping the helper process, along with an option menu to list the available locales and a field to show the default locale. Now put the following into the stack script:
local sProcess
on Locale_StartHelper
if sProcess is empty then
local tDefaultFolder, tStackFolder
put Locale_StackFolder() into tStackFolder
put the defaultFolder into tDefaultFolder
set the defaultFolder to tStackFolder
put "java LiveCodeLocaleHelper" into sProcess
open process sProcess for update
set the defaultFolder to tDefaultFolder
--> make sure we're speaking with the right helper
read from process sProcess for 1 line
if it begins with "LiveCodeLocaleHelper started." then
disable button "Start"
enable button "Stop"
else
close process sProcess
put empty into sProcess
end if
end if
end Locale_StartHelper
function Locale_AvailableLocales
local tLocaleList
write ("list") & return to process sProcess
repeat forever
read from process sProcess for 1 line
if it begins with "." then exit repeat
put it after tLocaleList
end repeat
delete char -1 of tLocaleList
return tLocaleList
end Locale_AvailableLocales
function Locale_DefaultLocale
write ("default") & return to process sProcess
read from process sProcess for 1 line
return it
end Locale_DefaultLocale
function Locale_FormatCurrency pAmount, pLocale
if pLocale is empty then
write ("currency" & tab & pAmount) & return to process sProcess
else
write ("currency" & tab & pAmount & tab & pLocale) & return to process sProcess
end if
read from process sProcess for 1 line
return line 1 of it
end Locale_FormatCurrency
function Locale_FormatInteger pAmount, pLocale
if pLocale is empty then
write ("integer" & tab & pAmount) & return to process sProcess
else
write ("integer" & tab & pAmount & tab & pLocale) & return to process sProcess
end if
read from process sProcess for 1 line
return line 1 of it
end Locale_FormatInteger
function Locale_FormatNumber pAmount, pLocale
if pLocale is empty then
write ("number" & tab & pAmount) & return to process sProcess
else
write ("number" & tab & pAmount & tab & pLocale) & return to process sProcess
end if
read from process sProcess for 1 line
return line 1 of it
end Locale_FormatNumber
function Locale_FormatDate pDate, pSize, pLocale
if pLocale is empty then
write ("date" & tab & pDate & tab & pSize) & return to process sProcess
else
write ("date" & tab & pDate & tab & pSize & tab & pLocale) & return to process sProcess
end if
read from process sProcess for 1 line
return line 1 of it
end Locale_FormatDate
function Locale_FormatTime pTime, pSize, pLocale
if pLocale is empty then
write ("time" & tab & pTime & tab & pSize) & return to process sProcess
else
write ("time" & tab & pTime & tab & pSize & tab & pLocale) & return to process sProcess
end if
read from process sProcess for 1 line
return line 1 of it
end Locale_FormatTime
on Locale_StopHelper
write ("exit") & return to process sProcess
close process sProcess
enable button "Start"
disable button "Stop"
put empty into sProcess
end Locale_StopHelper
function Locale_StackFolder
local tStackFolder
put the effective filename of this stack into tStackFolder
set the itemDelimiter to slash
delete item -1 of tStackFolder
return tStackFolder
end Locale_StackFolder
The script for the Start button is easy enough:
on mouseUp
disable button "Start"
Locale_StartHelper
put Locale_AvailableLocales() into button "AvailableLocales"
put Locale_DefaultLocale() into field "DefaultLocale"
enable button "Stop"
end mouseUp
And the script of the Stop button is equally trivial:
on mouseUp
disable button "Stop"
Locale_StopHelper
enable button "Start"
end mouseUp
The script for the Default button in the Number formatting section looks like this:
on mouseUp
local tNumber
put field "Number" into tNumber
put "Currency:" & tab & Locale_FormatCurrency(tNumber) & return & \
"Integer:" & tab & Locale_FormatInteger(tNumber) & return & \
"Number:" & tab & Locale_FormatNumber(tNumber) \
into field "FormattedNumbers"
end mouseUp
And the script for the Available button in the Number formatting section looks like this:
on mouseUp
local tNumber, tLocale
put field "Number" into tNumber
put the label of button "AvailableLocales" into tLocale
put "Currency:" & tab & Locale_FormatCurrency(tNumber, tLocale) & return & \
"Integer:" & tab & Locale_FormatInteger(tNumber, tLocale) & return & \
"Number:" & tab & Locale_FormatNumber(tNumber, tLocale) \
into field "FormattedNumbers"
end mouseUp
Likewise, the script for the Default button in the Date formatting section becomes:
on mouseUp
local tDate
put field "Date" into tDate
put "Short:" & tab & Locale_FormatDate(tDate, "short") & return & \
"Medium:" & tab & Locale_FormatDate(tDate, "medium") & return & \
"Long:" & tab & Locale_FormatDate(tDate, "long") & return & \
"Full:" & tab & Locale_FormatDate(tDate, "full") \
into field "FormattedDates"
end mouseUp
Hence, the script for the Available button in the Date formatting section becomes:
on mouseUp
local tDate, tLocale
put field "Date" into tDate
put the label of button "AvailableLocales" into tLocale
put "Short:" & tab & Locale_FormatDate(tDate, "short", tLocale) & return & \
"Medium:" & tab & Locale_FormatDate(tDate, "medium", tLocale) & return & \
"Long:" & tab & Locale_FormatDate(tDate, "long", tLocale) & return & \
"Full:" & tab & Locale_FormatDate(tDate, "full", tLocale) \
into field "FormattedDates"
end mouseUp
Almost done - here's the script for the Default button in the Time formatting section:
on mouseUp
local tTime
put field "Time" into tTime
put "Short:" & tab & Locale_FormatTime(tTime, "short") & return & \
"Medium:" & tab & Locale_FormatTime(tTime, "medium") & return & \
"Long:" & tab & Locale_FormatTime(tTime, "long") & return & \
"Full:" & tab & Locale_FormatTime(tTime, "full") \
into field "FormattedTimes"
end mouseUp
Finally, the logical extension for the Available button in the Time formatting section:
on mouseUp
local tTime, tLocale
put field "Time" into tTime
put the label of button "AvailableLocales" into tLocale
put "Short:" & tab & Locale_FormatTime(tTime, "short", tLocale) & return & \
"Medium:" & tab & Locale_FormatTime(tTime, "medium", tLocale) & return & \
"Long:" & tab & Locale_FormatTime(tTime, "long", tLocale) & return & \
"Full:" & tab & Locale_FormatTime(tTime, "full", tLocale) \
into field "FormattedTimes"
end mouseUp
Save the stack, and copy the compiled LiveCodeLocaleHelper.class file into the same directory where you saved the stack. Click the Start button, then play around with the rest of the user interface to enter different numbers, dates and times, clicking the buttons to see the formatting output, switching between the different available locales.
Download it here.
Subscribe to:
Posts (Atom)