이곳의 내용은 ref.1 의 내용을 필요한 부분만 정리한 내용이다. 자세한 내용은 책을 참고하자.
Widget
event 에 반응하는 component 가 아니라면
- simple HTML item
- UIBinder 로 만든 HTML components
로 만들어라. application 에 의해 managed 되지 않기 때문에 노력을 절약할 수 있다.
widget 은 DOM 을 가지고 직접 만들거나,
기존의 widget 을 상속 받아서 만들수 있다.
Composite Widget
non-Composite Widget
Widget 은 Panel 을 포함한다.
GWT 가 제공하는 class 들이 점차적으로 DOM element 를 wrapping 하고 있다. GWT 2.2. 에서는 span element 를 InlineLabel 로 wrapping 했고, GWT 2.3 에서는 canvas element 를 wrapping 했다. 이 wrapping 된 녀석이 하나의 widget 이라고 생각하면 될 듯 하다.
그러나 아직 모든 element 들이 wrapping 된 것이 아니다. 그래서 이런 경우에는 DOM 에서 바로 Widget 을 만들어야 한다.
간단한 widget 은 GWT in Action 의 source 에서 찾아볼 수 있다.
Widget 을 상속받아서 만든다.
그리고 원하는 event 를 처리할 interface 를 implement 한다.
event 를 처리하는 interface 도 있지만 event 와 관련이 없는 interface 들도 있다. 예를 들면 text 를 가지고 있는 지 여부를 알려주는 HasText() 같은 녀석들이 있다.
widget 에서 event 를 다루려면 아래 2 가지를 처리해야 한다.
- sink the event : widget 이 어떤 event 를 받아서 처리할 것인가를 결정하는 것
- event 가 발생했을 때 처리
event 받기(sinkEvents)
widget 에 onBrowserEvent() 함수를 override 해서 원하는 event 를 처리할 수 있다.
event 처리
처리하길 원하는 event 에 대한 interace 를 implement 하고, 그와 관련된 methods 를 만들고, 그 안에서 addDomHandler 를 통해 handler 를 등록하게 한다.
HasXXXXXHandler 모양의 interface 를 implement 하고,
addXXXXXHandler 의 method 를 만든다.
Panel
panel 은 위젯의 한 종류이다. 위젯 중에 다른 위젯을 추가하고, 삭제하는 등 기능을 제공하는 method 를 가지고 있는 녀석 보면 된다.Composit
기존의 widget 등을 모아서 하나의 widget 처럼 사용하고 싶은 경우에 사용하게 하고 싶다면 Composite 을 이용하자.Application 에 add 되기 전에 initWidget 을 반드시 호출해 줘야 한다.
initWidget 이 하는일
- 만들어진 composite(위젯)의 parent 를 설정하는 작업을 해준다.
- ...
자그마한 구조를 이 composite 으로 만들고, 이 작은 구조들을 RootPanel 이나 RootLayoutPanel 에 더해서 만들 면 전체적인 구조가 된다.
Composit widget 의 container 를 만들 때 panel 을 사용할 수 있다.
- FlowPanel
- VerticalPanel
- DockPanel
- ...
application 에 사용하는 layout 은 GWT 에서 제공하는 LayoutPanel 을 사용하는 것이 좋다. 이 layout 들은 예상할 수 있는 layout(predictable layout) 을 제공하는데, 그래서 browser engine 이 아주 빠르게 layout 을 그릴 수 있게 도와준다.
Layout panels
browser 의 standards mode 에서 predictable layout 를 제공한다. 이 layout 들은 table 이 아니라 style constraints 를 바탕으로 만들어졌다. 그래서 application layout 에 적합하다.근데 이녀석들은 standards mode 에서만 동작하기 때문에, HTML page 의 상단에 아래와 같은 declaration 이 필요하다.
<!DOCTYPE html>
configure
animate
standard mode
아래글에서 layout 과 관련돼서 간단하게 정리를 해준다. 참고하자.
ProvidesResize
layout panel 을 사용할 때는 ProvidesResize interface 를 구현한 container 안에 넣는게 좋다.
이 interface 를 구현하지 않은 녀석을 사용한다면, panel 의 size 를 상황에 맞게(resize 가 되는 경우) 계속 설정 해 줘야 한다.
RootLayoutPanel
Layout panel 을 page 에 바로 추가할 때는 RootPanel 대신에 RootLayoutPanel 을 사용해야 한다.ResizeComposite
composit widget 의 container 로 layout panel 을 사용할 때는 Composite class 대신에 ResizeComposite class 를 사용해야 한다. 그러면composite 밖에서 발생하는 resize 요청들이 container(layout panel) 로 잘 route 된다.page 의 부분으로 layout panel 을 사용한다면, resize 들이 잘 전달되기 위해서 이 panel 을 SimpleLayoutPanel 로 wrap 해야 한다.
Visibility
layout panel 안에 있는 widget 은 setVisibility(false) 를 사용할 수 없다. widget 이 아닌 container 의 visibility 를 set 해야 한다.forceLayout
layout 에 constraints 를 설정한 후에 forceLayout() 을 해줘야 실제로 적용이 된다.animation
animation 을 가지고 있는 widget 도 있고, 그렇지 않은 widget 도 있다. HasAnimation interface 가 있는데, 이 녀석을 구현한 녀석들이 animation 을 가진 widget 들이다. 이런 widget 은
- setAnimationEnabled(true)
를 통해서 animation 이 구동되게 할 수 있다.
직접 animation 을 만들수도 있다.
GWT animation 은 0.0 ~ 1.0 사이의 값을 progress 값(progression) 으로 해서 만들어 졌다.
animation 이 실행되는 동안 defined time slot 안에서 연속적인 onUpdate() 호출 이 이뤄진다.(대부분 single thread 의 animation 은 이런식으로 구현되는 듯 하다. android 의 animation 도 같은 느낌이다. android 도 UI thread 는 한개이다.)
참고로, 브라우저는 single thread 이다. 그래서 animation 의 frame rate 은 보장하지 못한다. 하지만 onUpdate 로 전달되는 progress 값은 확신할 수 있다. 예를 들어 2초짜리 animation 이 있다면, 0 초에서는 progress 값은 0.0 이 전달 될 것이며, 2 초에는 1.0 이 전달 될 것이다.
Animation class 를 상속받고 onUpdate 를 구현해서 만들면 된다. 그리고 new 후에, run 을 이용해서 실행하면 된다.
TestAnimation ta = new TestAnimation(); ... public ... onClickEvent(){ ta.run(5000); }
widget 의 lifecycle
Create > Add > Remove > Destroy
parent 가 DOM 에 attach 된 상태라면, setParent() 안에서 widget 의 onAttach method 를 호출한다.
// Panel.java protected final void adopt(Widget child) { assert (child.getParent() == null); child.setParent(this); } // Widget.java void setParent(Widget parent) { Widget oldParent = this.parent; if (parent == null) { try { if (oldParent != null && oldParent.isAttached()) { onDetach(); ... } } finally { this.parent = null; } } else { if (oldParent != null) { throw new IllegalStateException } this.parent = parent; if (parent.isAttached()) { onAttach(); ...
onAttach
onAttach 를 override 하는 대신에- onLoad 를 attach 하자.
- AttachEventHandler
References
- GWT in Action 2nd Edition, Chapter 4
댓글 없음:
댓글 쓰기