Thursday, July 05, 2007

Squeak Tutorial

หัดเล่น squeak + seaside มาระยะหนึ่งแล้ว
อุปสรรคอย่างแรกสุดในการใช้ ก็คือ สภาพแวดล้อมในการพัฒนา
ที่ค่อนข้างบิดมุมไปจากสิ่งที่เคยคุ้นเคยมา
แถมยังหา tutorial ที่พูดถึงสิ่งที่เราต้องการรู้ได้ยาก
ส่วนใหญ่จะพูดถึงแต่เรื่อง Graphpics (Morphic)

โชคดีที่ใน version 3.9 นี้ มี tutorial ที่ดีมากออกมาด้วย
http://squeak.preeminent.org/tut2007/html/index.html
หลังจากลองเล่นไป section หนึ่ง
ก็ยิ่งพบว่าสภาพแวดล้อมการพัฒนาแบบนี้ มันเจ๋งใช้ได้เลย
จากที่่เคยได้ยินว่า eclipse ได้รับอิทธิพลจาก smalltalk IDE
ก็เห็นชัดเจนแจ่มแจ๋ว
หรือที่เคยรู้ว่า xunit ก็ได้อิทธิพลจาก sunit ของ smalltalk
พอมาใช้ sunit (แม้จะใช้แค่นิดเดียว) แต่ก็รู้สึกถึงความ powerful ของมันได้

อุปสรรคที่สองที่พบเวลาหัดใช้ squeak ก็คือ ตัว image ที่ให้มา
มันไม่เหมาะกับการเป็น developer tool สักเท่าไร
เช่น ไม่มี syntax highlight, ไม่มี code completion
การแก้ไขก็คือ ควรจะ download
เอา image ที่เตรียมไว้สำหรับ developer มาใช้

Related link from Roti

Monday, July 02, 2007

Image in seaside

วันก่อนนั่งแกะ seaside ซึ่งเป็น web application framework ของค่าย smalltalk
ไปเจอ code ส่วนที่จัดการกับ static file เช่นพวก image, css
หน้าตาเป็นแบบนี้

WAFileLibrary subclass: #WAFileLibraryDemo
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Seaside-Examples-Misc'

mainJpg
^ #(255 216 255 224 0 16 74 70 73 70 0 1
1 1 0 72 0 72 0 0 255 225 0 22 69 120 105
102 0 0 77 77 0 42 0 0 0 8 0 0 0 0 0 0 255
219 0 67 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
...)


อืมม์น่าสนใจวิธีการเก็บ static file มาก
เล่นเก็บเป็น bytearray ใน instance variable เลยแฮะ
ที่เป็นเช่นนี้เพราะโลกของ smalltalk มันเป็นโลกของ virtual machine
ที่มีแต่ object เวียนว่ายตายเกิดในนั้น
การเก็บข้อมูลในรูปแบบนี้ ก็สวยงามไปอีกแบบ

ต่อจากนั้น ก็เลยไปตามหาเอกสารอ่านดู
แน่นอนว่า seaside ของแท้
เอกสารถึงจะค้นใน google ก็ไม่มีให้ดู
ต้องตามไปดู code อย่างเดียว
โชคดีที่ code ที่ port ไปลง cincom smalltalk มีอธิบายไว้ละเอียด

ตัว class ที่รับผิดชอบในการเก็บ static content มีชื่อว่า WAFileLibrary
วิธีที่นิยมใช้กันก็คือ extend ออกมาเป็น class ของเราต่างหาก
จากนั้นก็สามารถใช้ หน้าจอ config ของ seaside upload content ขึ้นไปได้



เวลา render เป็น image tag ก็อ้างถึงแบบนี้
renderContentOn: html
html image
url: WAFileLibraryDemo / #mainJpg


Note: '/' คือชื่อ class method ส่วน #testJpg คือ symbol ที่แทนรูปที่ต้องการ
มี pattern คือ ชื่อ file ของเรา + file extension ที่แปลงตัวแรกเป็นตัวใหญ่
test.jpg -> testJpg

Related link from Roti

Sunday, July 01, 2007

Chart with Flex

ในงานล่าสุด UI element ต้องมีการแสดง chart ด้วย
โดยเป็น chart ที่มีลักษณะเป็น dynamic, control จาก javascript ได้
ตอนแรก ก็ใช้ plotkit ซึ่งเป็น opensource
แต่พอเอาไปให้ user ดู ก็เจอติเรื่องความสวยงาม
ซึ่งจริงๆถ้ามีเวลา ก็อาจจะไล่แก้โปรแกรม plotkit ทำสวยได้
แต่เมื่อไม่มีเวลา ก็เลยหาโอกาสเสียตังค์ลองใช้ flex ดู

ความรู้สึกหลังจากได้ทดลองพัฒนา component ดู
พบว่า
1. mxml ดีกว่าที่คิดไว้เยอะ
2. model การ binding parameter ของ component ก็งามดี
3. actionscript เขียนง่ายมาก, ถ้ามี background java + javascript
ก็น่าจะผ่านฉลุย
4. api library ออกแบบไว้ดี, ชอบที่เราสามารถ customize nature ของ widget
ได้ด้วยโดยการ pass customize function เข้าไปเป็น parameter (callback)
5. การ integrate กับ javascript ผ่านทาง ExternalInterface ก็ง่ายดาย
6. ถ้าใช้ SDK พัฒนา จะเบื่อกับ build time ที่นานเหลือเกิน (เดี๋ยวนี้ไม่กี่ิวิ ก็เริ่มทนไม่ได้แล้ว)
7. flex builder มันใช้ eclipse เป็นฐาน, ความคุ้นเคยต่างๆ ก็เลยเต็มร้อย

หน้าตาของ component ที่ทำออกมา



ตัวอย่าง javascript ที่ใช้ provide ข้อมูลให้ chart component
document.chart.setBaseAtZero(true);
datas = [{Year: 2005, ROE: 1000, Revenue: 200},
{Year: 2006, ROE: 500, Revenue: 300},
{Year: 2007, ROE: 300, Revenue: 1000}];

series = [{name: "ROE", displayName: "ROE"},
{name: "Revenue", displayName: "Revenue"}];

document.chart.loadChart("Compare", datas, series, "Year");


ส่วนอันนี้คือ mxml ที่เขียน

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initApp()"
paddingLeft="0"
paddingBottom="0"
paddingRight="0"
paddingTop="0">

<mx:Script>
<![CDATA[
import mx.charts.CategoryAxis;
import mx.charts.series.ColumnSeries;
import mx.charts.chartClasses.IAxis;

public function initApp():void {
if (ExternalInterface.available) {
ExternalInterface.addCallback("loadChart", loadChart);
ExternalInterface.addCallback("setBaseAtZero", setBaseAtZero);
ExternalInterface.addCallback("setLabelPrecision", setLabelPrecision);
}
}

private function setLabelPrecision(value:int):void {
numberFormatter.precision = value;
}

private function setBaseAtZero(value:Boolean):void {
linearAxis.baseAtZero = value;
}

private function loadChart(description:String, datas:Array, maps:Array, category:String):void {
panel.title = description;
var mySeries:Array = new Array();
for each (var obj:Object in maps) {
var ss:ColumnSeries = new ColumnSeries();
ss.xField = category;
ss.yField = obj.name;
ss.displayName = obj.displayName;
mySeries.push(ss);
}

myChart.series = mySeries;

var cat:CategoryAxis = new CategoryAxis();
cat.categoryField = category;
myChart.horizontalAxis = cat;

myChart.dataProvider = datas;

}

private function labelFunction(labelValue:Object, previousValue:Object, axis:IAxis):String {
return numberFormatter.format(labelValue);
}
]]>



</mx:Script>

<mx:NumberFormatter id="numberFormatter" precision="0"
useThousandsSeparator="true" useNegativeSign="true"/>

<mx:Panel id="panel" title="ColumnChart and BarChart Controls Example"
height="100%" width="100%" layout="horizontal">

<mx:ColumnChart id="myChart" height="100%" width="80%"
paddingLeft="5" paddingRight="5"
showDataTips="true" >

<mx:verticalAxis>
<mx:LinearAxis id="linearAxis" baseAtZero="true" labelFunction="labelFunction"/>
</mx:verticalAxis>

</mx:ColumnChart>

<mx:Legend dataProvider="{myChart}" width="20%" />

</mx:Panel>
</mx:Application>


User confirm เมื่อไร ก็เตรียมเสียตังค์ 900 เหรียญ

Related link from Roti