[컴][웹] GWT 사용하기 - 1 - Widget




이곳의 내용은 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 가지를 처리해야 한다.

  1. sink the event : widget 이 어떤 event 를 받아서 처리할 것인가를 결정하는 것
  2. 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 하는 대신에

  1. onLoad 를 attach 하자.
  2. AttachEventHandler





References

  1. GWT in Action 2nd Edition, Chapter 4

댓글 없음:

댓글 쓰기