ViewStack이나 TabNavigator 등 다른 컴포넌트들을 포함하면서
필요에 따라 일부는 보여주고, 나머지는 숨기는 레이아웃 컴포넌트들이 있다.
이런 것들은 creationPolicy라는 속성이 있는데,
이 속성값을 all로 하면 ViewStack이나 TabNavigator를 생성할 때 포함된 컴포넌트까지 모두 생성하고(포함된 컴포넌트가 많을수록 로딩속도가 느려짐),
auto로 하면 포함된 컴포넌트를 보여달라는 요청이 올 때에 컴포넌트를 생성한다.
(ViewStack은 해당 화면을 보여 줄 때, TabNavigator는 해당 탭을 선택했을 때)
그러므로, Application 안의 ViewStack에 업무화면들을 잔뜩 쌓아 놓고 메뉴에 따라 보여주는 형태라면 이 ViewStack의 creationPolicy를 auto로 하는 것이 로딩속도 향상에 좋다.
책을 보면 로딩속도 향상을 위해 작은 단위로 module을 만들어 놓고 필요할 때마다 moduleLoader 같은 걸로 띄우라고 하는데 귀찮아서 이것저것 보던 중에 creationPolicy라는 좋은 속성을 발견해서 쉽게 해결했다.
단, ViewStack에 creationPolicy를 설정하면 그 안에 포함된 화면 안에 있는 ViewStack이나 TabNavigator들에 creationPolicy 설정하지 않으면 상위 컴포넌트의 creationPolicy를 따라간다.
경험상 Application 안의 ViewStack 외에 그 안에서 사용하는 ViewStack이나 TabNavigator는 creationPolicy를 all로 하는 게 좋다. auto로 하면 안 보이는 탭이나 화면의 컴포넌트들이 null 상태인데, 이 때 안 보이는 컴포넌트들을 참조하려고 하면 맨 처음 한 번은 null 오류가 발생하기 때문이다.
2009년 4월 13일 월요일
FormItem 안의 내용을 옆으로 배치
일반적으로 입력/수정 폼 형태에는 Form 컴포넌트를 사용하는 게 좋다.
그런데, 한 내용에 가로로 2개의 입력이 필요할 경우에는 FormItem의 direction 속성을 horizontal로 설정하면 된다. 이 속성을 사용하지 않으면 세로로 위치한다.
<mx:FormItem label="비밀번호" labelWidth="200" direction="horizontal">
<mx:TextInput id="pw1" width="200"/>
<mx:TextInput id="pw2" width="200"/>
</mx:FormItem>
그런데, 한 내용에 가로로 2개의 입력이 필요할 경우에는 FormItem의 direction 속성을 horizontal로 설정하면 된다. 이 속성을 사용하지 않으면 세로로 위치한다.
<mx:FormItem label="비밀번호" labelWidth="200" direction="horizontal">
<mx:TextInput id="pw1" width="200"/>
<mx:TextInput id="pw2" width="200"/>
</mx:FormItem>
라벨:
가로,
direction,
Flex,
form,
horizontal
Label, TextInput에 손 모양 커서 적용
Label과 TextInput에 click 이벤트 처리하면 스크립트를 실행시킬 수는 있다.
그런데, click 이벤트 처리한다고 여기에 마우스를 올렸을 때 자동으로 마우스 커서가 손모양으로 바뀌진 않는다.
아래의 3개 속성을 설정해 주어야 된다.
useHandCursor="true"
buttonMode="true"
mouseChildren="false"
물론 다른 컴포넌트도 적용할 수 있을 것 같긴 한데 내가 적용해 본 것은 여기까지.
내 생각엔 useHandCursor 하나만으로 적용되어야 할 것 같은데 3개나 해 줘야 하다니...
그런데, click 이벤트 처리한다고 여기에 마우스를 올렸을 때 자동으로 마우스 커서가 손모양으로 바뀌진 않는다.
아래의 3개 속성을 설정해 주어야 된다.
useHandCursor="true"
buttonMode="true"
mouseChildren="false"
물론 다른 컴포넌트도 적용할 수 있을 것 같긴 한데 내가 적용해 본 것은 여기까지.
내 생각엔 useHandCursor 하나만으로 적용되어야 할 것 같은데 3개나 해 줘야 하다니...
라벨:
Flex,
handcursor,
label,
TextInput
2009년 4월 12일 일요일
2009년 3월 2일 월요일
다국어 코드 적용하기
대단한 프로그램은 아니고,
이번에 프로그램을 한참 개발하고 다국어 버전으로 변경할 일이 있었는데
30여개의 소스 파일을 일일이 뒤지면서 한글로 만들어 놓은 코드를 다국어 처리코드로 바꾸는 게 여간 힘든 작업이 아니었다.
(눈과 팔이 너무 아팠다. ^^;)
만만하게 보고 그냥 무식하게 하려다가, 결국 반 정도를 한 후에 프로그램을 만들었다. ^^;
아래에 있는 소스가 자바로 만든 변환 프로그램.
[code java]
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
public class I18NReplace {
private static final String I18N_CODE_PREFIX = "{resourceManager.getString('rb','";
private static final String I18N_CODE_POSTFIX = "')}";
/**
* @param args
*/
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
BufferedReader br = null;
BufferedReader brSrc = null;
try {
// 다국어 코드, 값이 정의된 리소스번들 파일
br = new BufferedReader(new InputStreamReader(
new FileInputStream("code.properties"), "UTF-8"));
// 다국어 버전으로 변환할 소스 파일
brSrc = new BufferedReader(new InputStreamReader(
new FileInputStream("test.mxml"), "UTF-8"));
String line = null;
// 다국어 코드, 값을 HashMap에 저장
while ( (line = br.readLine()) != null ) {
String[] arr = line.split("=");
if (arr.length == 2) {
map.put(arr[0], arr[1]);
}
}
Object[] keys = map.keySet().toArray();
// 길이가 긴 문자열부터 변환하기 위해 문자열 길이 내림차순으로 키를 정렬
Arrays.sort(keys, new KeyOrderComparator());
String srcLine = null;
while ( (srcLine = brSrc.readLine()) != null ) {
// 주석 라인은 skip
if (!srcLine.trim().startsWith("//") &&
!srcLine.trim().startsWith("/*") &&
!srcLine.trim().startsWith("<!--")) {
for (int i = 0; i < keys.length; i++) {
if (srcLine.indexOf((String)keys[i]) > -1) {
srcLine = srcLine.replaceAll((String)keys[i],
I18N_CODE_PREFIX + (String)map.get(keys[i]) + I18N_CODE_POSTFIX);
}
}
}
System.out.println(srcLine);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (Exception e) {}
try {
if (brSrc != null)
brSrc.close();
} catch (Exception e) {}
}
}
}
class KeyOrderComparator implements Comparator {
/**
* 문자열의 길이에 따라 내림차순 정렬
*/
public int compare(Object key1, Object key2) {
return ((String)key2).length() - ((String)key1).length();
}
}
[/code]
I18NReplace.java
[code]
데이터=data
[/code]
code.properties
[code xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" title="데이터">
...
</mx:TitleWindow>
[/code]
test.mxml
사용법이 복잡하진 않지만, 급하게 대강 만든 프로그램이라 GUI 등의 친절한 기능은 없다.
1. code.properties는 코드와 값을 넣은 건데 일반적인 순서와는 반대다.
이유는, 다국어 적용하기 전에 '데이터'라고 코딩을 했는데 이를 다국어 처리하기 위해서는
한글용 리소스번들 파일에 'data=데이터' 라는 내용이 있어야 한다.
그리고, '데이터' 대신에 다국어 처리 코드( Flex를 예로 들면, {resourceManager.getString('rb','data')} )를 넣으면
언어 설정에 따라 한국어일 때는 '데이터', 영어일 때는 'Data'라는 내용이 보이게 된다.
그런데, 지금 할 일이 '데이터'라고 하드코딩되어 있는 부분을 {resourceManager.getString('rb','data')}로 바꾸는 것이니까
code.properties 파일에는 '데이터=data' 즉, message=key 형태로 되어 있어야 한다.
2. test.mxml은 '데이터'라는 내용이 하드코딩되어 있는 소스 파일
3. I18N_CODE_PREFIX는 다국어처리코드에서 key 앞에 붙는 코드, I18N_CODE_POSTFIX는 key 뒤에 붙는 코드
참고로, 중간에 Arrays.sort 는 문자열길이에 따라 내림차순으로 정렬하는 건데,
그래야 '데이터 관리'라는 문자열이 소스에서 나왔을 때, '데이터 관리'라는 게 code.properties에 있을 때 우선적으로 처리하고
이게 없으면 '데이터'나 '관리'를 따로 변환하게 되어 원치 않는 결과가 나오게 된다.
이렇게 '데이터 관리'를 하나의 단어로 정의하는 것은 언어에 따라 어순이 바뀌거나,
두 단어 이상이 합쳐져서 만들어진 단어의 경우 언어에 따라 다른 의미가 될 수 있어서이다.
또, 참고로 파일을 읽을 때 "UTF-8"라는 설정이 있는데 이것은 "UTF-8" 인코딩으로 저장한 파일을 읽기 위해 사용한 것이다.
소스 파일이나 리소스번들 파일의 인코딩 형태에 따라 빼거나 고쳐서 사용하면 된다.
이렇게 설정한 상태에서 이 I18NReplace을 실행하면 치환된 결과가 표준출력으로 나오고,
이 결과를 원래 소스에 붙인 다음에 잘못 된 부분을 수정해서 저장하면 다국어 처리가 끝난다.
꼭 다국어 처리 변환에만 사용할 필요는 없고, 어떤 규칙에 따라 문자열을 치환해야 하는 경우 사용하면 되겠다.
당연한 얘기지만, code.properties 파일 정의시 띄어쓰기는 정확히 맞춰 주어야 한다.
2009년 2월 13일 금요일
2009년 2월 12일 목요일
오라클에서 SYSDATE를 이용한 시간 연산
[code sql]
SELECT TO_CHAR(SYSDATE, 'YYYY/MM/DD HH:MI SS') "NOW",
TO_CHAR(SYSDATE+1, 'YYYY/MM/DD HH:MI SS') "1 DAY AFTER",
TO_CHAR(SYSDATE+1/24, 'YYYY/MM/DD HH:MI SS') "1 HOUR AFTER",
TO_CHAR(SYSDATE+1/24/60, 'YYYY/MM/DD HH:MI SS') "1 MINUTE AFTER",
TO_CHAR(SYSDATE+1/24/60/60, 'YYYY/MM/DD HH:MI SS') "1 SECOND AFTER"
FROM DUAL
[/code]
당연히,
SYSDATE에 숫자를 더하면 현재시간 이후를 의미하고,
SYSDATE에서 숫자를 빼면 현재시간 이전을 의미
이런 쿼리를 사용하면 오라클이 아닌 다른 DB를 사용하게 되면
프로그램 고치는 일이 엄청나게 커지니까 오라클만 쓸 생각일 경우에만 사용해야 할 듯
시스템 운영자와 사이가 안 좋을 땐 이런 지뢰를 심어 놓는 방법이... ㅋㅋ
당연히,
SYSDATE에 숫자를 더하면 현재시간 이후를 의미하고,
SYSDATE에서 숫자를 빼면 현재시간 이전을 의미
이런 쿼리를 사용하면 오라클이 아닌 다른 DB를 사용하게 되면
프로그램 고치는 일이 엄청나게 커지니까 오라클만 쓸 생각일 경우에만 사용해야 할 듯
시스템 운영자와 사이가 안 좋을 땐 이런 지뢰를 심어 놓는 방법이... ㅋㅋ
피드 구독하기:
글 (Atom)