Your SlideShare is downloading. ×
GWT widget development
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

GWT widget development

2,305

Published on

Even though widget libraries for GWT exist, it’s sometimes necessary to create a widget on your own. Widget creation will confront you with challenges like GWT specifics or the way browsers …

Even though widget libraries for GWT exist, it’s sometimes necessary to create a widget on your own. Widget creation will confront you with challenges like GWT specifics or the way browsers work.
Participants will learn how to compose existing widgets as well as creating new ones based on DOM elements. As it is important to know how browsers behave, topics like DOM API, reflows and event propagation will be explained. But there are also GWT specific aspects, like important interfaces and classes or how to prevent code injection.

Published in: Technology
2 Comments
0 Likes
Statistics
Notes
  • Be the first to like this

No Downloads
Views
Total Views
2,305
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
0
Comments
2
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. GWT widget development Even though widget libraries for GWT exist, it’s sometimes necessary to create a widget on your own. Widget creation will confront you with challenges like GWT specifics or the way browsers work.! Participants will learn how to compose existing widgets as well as creating new ones based on DOM elements. As it is important to know how browsers behave, topics like DOM API, reflows and event propagation will be explained. But there are also GWT specific aspects, like important interfaces and classes or how to prevent code injection.
  • 2. http://pgt.de PAPICK http://oio.de STEFFEN
  • 3. Finally NoWidgets Layouts Panels Composite Simple widgets Committing to web development Getting started
  • 4. Why widget development?
  • 5. It’s all about having the choice
  • 6. Choice of using existing
  • 7. Choice of using existing
  • 8. building your own
  • 9. or buying.
  • 10. or buying. + support + vendor lock-in
  • 11. Freedom of choice?
  • 12. We only have 60 Minutes We must assume you are not new to GWT
  • 13. Mission: give some directions
  • 14. What are components? com·po·nent kəmˈpōnənt/ ! a part or element of a larger whole, esp. a part of a machine or vehicle.
  • 15. What are UI components?
  • 16. What for? code reuse separation of concerns
  • 17. Code reuse? Just import library into project, and use this progress bar. Don‘t reinvent the wheel, unless it is a better wheel...
  • 18. Code reuse by composition
  • 19. ... composition ...
  • 20. separation of concerns? The coders at 
 gwt-bootstrap did the progress bar widget magic.! ! I will never build widgets!!!! ! It is not of my concern. I simply use them!!!
  • 21. RIGHT? Yes…! ! But still…! ! …third party widgets are generic components.
  • 22. RIGHT? Yes…! ! But still…! ! …third party widgets are generic components.
  • 23. Don‘t use generic tools, unless you are Mac Gyver… MAC GYVER All he needed was a ball-point pen and a paper clip
  • 24. Code duplication
  • 25. Code duplication
  • 26. You got the picture,
 right?
  • 27. You got the picture,
 right? Label VerticalPanel HorizontalPanel VerticalPanel HorizontalPanel Label Label FlexTable FlexTable VerticalPanel HorizontalPanel FlexTable HorizontalPanel Label Label Label
  • 28. Unfortunately, we are modern Mac Gyvers! <div /> WEB DEVELOPER A div is all you need
  • 29. GWT 
 Efficiency custom components: code reuse + separation of concerns + composition + type safety
  • 30. So what is a GWT Widget?
  • 31. It‘s a JS thing holding a DOM element <div />
  • 32. Created to workaround IE6 memory leaks
  • 33. Widgets are quite heavy weight
  • 34. Each widget includes full event management... ...even if there is nothing to see
  • 35. Custom components ‣ Increase efficiency in development! ‣ Domain driven! ‣ Avoid composition abuse! ‣ Implement custom design! ‣ Create more effective widgets! ‣ Cheaper in the long run !35 © 2013 Orientation in Objects GmbH
  • 36. Finally NoWidgets Layouts Panels Composite Simple widgets Committing to web development Getting started
  • 37. We are not Swing developers! ‣ GWT development is web development! ‣ GWT applications are JavaScript applications! ‣ GWT is very good at hiding this! ‣ We can deny knowledge about it! ‣ … but not forever Java JavaScript !37 © 2013 Orientation in Objects GmbH
  • 38. JS Apps do DOM manipulation ‣ GWT widget API hides this from the user! ‣ Abuse of composition leads to heavy DOM manipulation! ‣ Custom components are important, and there are things that we should be aware of... © 2013 Orientation in Objects GmbH !38
  • 39. DOM API ‣ Document Object Model! ‣ Representation of HTML document in memory! – Tree stucture! ‣ Manipulation/creation of elements! ‣ Navigation of elements !39 © 2013 Orientation in Objects GmbH
  • 40. DOM API in GWT DivElement  element  =       Document.get().createDivElement(); element.appendChild(otherElement); element.getChild(0); element.removeChild(otherElement);
  • 41. DOM events ‣ Bubbling:! ! The process by which an event propagates upward ! through its ancestors after being handled by the event's ! target. ! Source: http://www.w3.org/TR/DOM-Level-2-Events/events.htm#Events-overview-terminology ! ‣ Event.stopPropagation! – The event won‘t be delivered to listeners of ancestors! ! ‣ Event.preventDefault! – Prevents default browser behavior !41 © 2013 Orientation in Objects GmbH
  • 42. DOM events ‣ Sinking: Event.sinkEvents(element,  Event.ONCLICK); Event.setEventListener(element,  new   EventListener()  {      @Override        public  void  onBrowserEvent(Event  event)  {            if  (event.getTypeInt()  ==  Event.ONCLICK)  {                  […]            }      } }); !42 © 2013 Orientation in Objects GmbH
  • 43. Reflows ‣ Layout update! ‣ DOM changes do not directly result in a visual/layout update! – All Updates that occur in one JS execution result in one update! ‣ Effective size and position of elements are only available after update !43 © 2013 Orientation in Objects GmbH
  • 44. Distinct phases ! ! ! ! ! ! ‣ JS Execution! ‣ CSS/ Layout update! Browsers are single-threaded ‣ Render !44 © 2013 Orientation in Objects GmbH
  • 45. Hooks idle Scheduler.scheduleEntry(); GWT application code .scheduleFinally(); Browser event loop .scheduleDeferred();
  • 46. JavaScript execution defers rendering ‣ Long lasting JS execution causes delay in rendering! – The browser hangs...! ‣ Try to keep JS execution short! – Execute incrementally! – Animations! ‣ Try to avoid JS executions !46 © 2013 Orientation in Objects GmbH
  • 47. CSS ‣ Use CSS layouts to handle resizing without JavaScript! ‣ Bad CSS selectors can lead to slow down of rendering! – Define the right most selector as specific as possible! – Avoid selectors that are too complex! – […]! ‣ Try to express states as CSS classes CSS is the new 
 native !47 © 2013 Orientation in Objects GmbH
  • 48. Too many divs... ‣ Semantic markup ! – ul/li vs div/span! ‣ Accessibility! – WAI-ARIA !48 © 2013 Orientation in Objects GmbH
  • 49. Compatibility Source: http://caniuse.com
  • 50. Finally NoWidgets Layouts Panels Composite Simple widgets Committing to web development Getting started
  • 51. Bad Smell: refused bequest Subclasses get to inherit the methods and data of their parents. But what if they don’t want or need what they are given? They are given all these great gifts and pick just a few to play with. ! The traditional story is that this means the hierarchy is wrong. http://sourcemaking.com/refactoring/refused-bequest 978-0201485677
  • 52. WhatYouNeed(tm) YourGreatWidget
  • 53. Nooooooooo!!!!!! FlexTable YourGreatWidget
  • 54. Don’t extend FlexTable Flextable
  • 55. Use a Composite, the thing holding a Widget Widget
  • 56. Use a Composite, the thing holding a Widget
  • 57. The trick Widget
  • 58. The trick Widget Composite
  • 59. The trick Widget Composite YourGreatWidget
  • 60. You end up exposing only widget + YourGreatInterface Widget Composite YourGreatWidget
  • 61. In a hurry? Widget Composite YourGreatWidget FlexTable
  • 62. The trick Widget initWidget( flexThing ) Composite YourGreatWidget FlexTable
  • 63. Internals are locked away Widget Composite YourGreatWidget FlexTable
  • 64. Finally NoWidgets Layouts Panels Composite Simple widgets Committing to web development Getting started
  • 65. GWT Widgets and DOM elements
  • 66. GWT Widgets and DOM elements div input div
  • 67. GWT Widgets and DOM elements SearchBox div input div
  • 68. GWT Widgets and DOM elements ‣ Two representations! – Logical (Java)! – Physical (HTML/DOM) SearchBox div input div !68 © 2013 Orientation in Objects GmbH
  • 69. The contract of GWT widgets ‣ setElement(Element)! ! Sets  this  object's  browser  element.   ! UIObject  subclasses  must  call  this   method  before  attempting  to  call  any   ! other  methods,  and  it  may  only  be   ! called  once. ! ! ! ‣ To be on the safe side: do it in the constructor !69 © 2013 Orientation in Objects GmbH
  • 70. Widget lifecycle - Construction public  Led()  {        setElement(Document.get().createDivElement());        setStyleName(getResources().style().led());        […]   }
  • 71. Widget lifecycle - Attach ‣ void onLoad()! This  method  is  called  immediately  after  a   ! widget  becomes  attached  to  the  browser's   document. ! ‣ AttachEvent.Handler.onAttachOrDetach(…) Fired  when  the  event  source  is  attached  to  the   browser's  document  or  detached  from  it. !71 © 2013 Orientation in Objects GmbH
  • 72. Widget lifecycle - Detach ‣ void onUnload()! This  method  is  called  immediately  before  a   ! widget  will  be  detached  from  the  browser's   document. ! ‣ AttachEvent.Handler.onAttachOrDetach(…) Fired  when  the  event  source  is  attached  to  the   browser's  document  or  detached  from  it. !72 © 2013 Orientation in Objects GmbH
  • 73. GWT Events ! ! ! ! CloseEvent ! ! ‣ GWTEvent JavaScriptObject NativeEvent OpenEvent ResizeEvent DOMEvent BlurEvent Native events are not enough!! – Tab selection?! ‣ SelectionEvent ! Fire existing GwtEvents! HasNativeEvent FocusEvent ChangeEvent KeyEvent – SelectionEvent! – SelectionChangeEvent! – ValueChangeEvent! ‣ ! If none matches your use-case: define your own! !73 © 2013 Orientation in Objects GmbH
  • 74. Custom event development Events between 
 Widgets by sending
 and listening to GwtEvents GwtEvent GwtEvent Event handling in 
 the component, listen to 
 native events Event onBrowserEvent(Event event)
  • 75. Custom event development Events between 
 Widgets by sending
 and listening to GwtEvents Event handling in 
 the component, listen to 
 native events ValueChangeEvent Event LEDActivationEvent Event.ONCLICK, 
 Event.ONKEYDOWN
  • 76. Basic handling of DOM events public  Led()  {        sinkEvents(Event.ONCLICK); } ! @Override   public  void  onBrowserEvent(Event  event)  {      if  (event.getTypeInt()  ==  Event.ONCLICK)  {            toggleLed();      }      […] }
  • 77. Providing events to the user @Override   public  HandlerRegistration  addValueChangeHandler( ValueChangeHandler<Boolean>  handler)  {      return  addHandler(handler,                            ValueChangeEvent.getType()); } ! @Override   public  void  setValue(Boolean  value,  boolean  fireEvents)  {      this.value  =  value;        if(fireEvents)  {            ValueChangeEvent.fire(this,  value);      } }
  • 78. Custom Events generics... GwtEvent EventHandler generics... MyEvent MyEventHandler
  • 79. Define your own events: handler… public  class  ExampleEvent  extends   GwtEvent<ExampleEvent.Handler>  { ! […] ! !      public  interface  Handler  extends  EventHandler  {            void  onSomethingHappened(ExampleEvent  event);      } ! […] ! }
  • 80. Define your own events: payload public  class  ExampleEvent  extends   GwtEvent<ExampleEvent.Handler>  {   ! […] !      private  final  int  value;        public  ExampleEvent(int  value)  {            this.value  =  value;      }   !      public  int  getValue()  {            return  value;      }   ! ! } […]
  • 81. Define your own events: dispatching public  class  ExampleEvent  extends   GwtEvent<ExampleEvent.Handler>  {   ! […] ! !      protected  void  dispatch(Handler  handler)  {            handler.onSomethingHappened(this);      } ! ! } […]
  • 82. Define your own events: allow registration public  HandlerRegistration  addExampleHandler( ExampleHandler  handler)  {      return  addHandler(handler,  ExampleEvent.getType()); }
  • 83. Eventmanager Event ? Handler Handler Handler
  • 84. Eventmanager Event ! Handler Handler Handler
  • 85. Define your own events public  class  ExampleEvent  extends   GwtEvent<ExampleEvent.Handler>  { !      private  static  Type<ExampleEvent.Handler>  type; !      public  static  Type<ExampleEvent.Handler>  getType()  {            if  (type  ==  null)  {                  type  =  new  Type<ExampleEvent.Handler>();            }            return  type;      }      @Override        public  Type<Handler>  getAssociatedType()  {            return  getType();      } }
  • 86. Use GWT Optimizations ‣ ClientBundle! ‣ CSSResource! ‣ ImageResource connection bottleneck HTTP 1.1! 8.1.4 Practical Considerations! A single-user client SHOULD NOT maintain more than 2 connections © 2013 Orientation in Objects GmbH with any server or proxy. !86
  • 87. Use GWT Optimizations public  interface  Resources  extends  ClientBundle  {        @Source("SearchBox.css")        Style  style();   !      @Source("search.png")        ImageResource  search();   }   ! public  interface  Style  extends  CssResource  {        String  root();        String  text();        String  icon();   }
  • 88. How to build widgets ‣ Manual DOM manipulation! ‣ UiBinder !88 © 2013 Orientation in Objects GmbH
  • 89. UiBinder <ui:UiBinder   xmlns:ui="urn:ui:com.google.gwt.uibinder"   xmlns:g="urn:import:com.google.gwt.user.client.ui" >        <ui:with  type=„[…]"  field="style"></ui:with>        <div  class="{style.root}">              <input  type="text"  class="{style.text}"  />              <div  class="{style.icon}"></div>        </div>   </ui:UiBinder>  
  • 90. Finally NoWidgets Layouts Panels Composite Simple widgets Committing to web development Getting started
  • 91. Composite Pattern ‣ Something that contains widgets and IS a widget! ‣ We know that from other UI toolkits (e.g. Swing)! ‣ In GWT we use **Panels for this !91 © 2013 Orientation in Objects GmbH
  • 92. We all did it already verticalPanel.add(new  Label("Hello  GWT  world!")); dockLayoutPanel.addWest(new  CustomerForm(),  300); headerPanel.setContentWidget(new  CustomerForm());
  • 93. Widgets, panels and DOM elements Panel div div label Label div input TextBox
  • 94. The magic behind it ‣ The Panel ensures that the widget‘s underlying DOM element is correctly attached to the document! ‣ Structure of logical and physical representation 
 must be consistent !94 © 2013 Orientation in Objects GmbH
  • 95. The magic behind it public  void  add(Widget  widget)  {        […]        element.appendChild(widget.getElement());        adopt(widget);        […]   }
  • 96. Contract public  interface  HasWidgets  extends   Iterable<Widget>  {   !      void  add(Widget  w); !      void  clear(); !      Iterator<Widget>  iterator(); !      boolean  remove(Widget  w); }
  • 97. Coding against interfaces is possible public  interface  IsWidget  {      Widget  asWidget(); } interface  ForIsWidget  extends  HasWidgets  {      void  add(IsWidget  w); !      boolean  remove(IsWidget  w); }
  • 98. Supporting UiBinder ‣ Supporting UiBinder is easy as long as we have ….! – Default constructor! – Default add method! ‣ We can improve the UiBinder compatibility of our widgets! – @UiConstructor! – @UiChild !98 © 2013 Orientation in Objects GmbH
  • 99. UiChild example @UiChild   public  void  addField(Widget  widget,  String   label)  {        […]   } <ui:UiBinder  […]  xmlns:oio="urn:import:[…]">        <oio:SimpleFormPanel>              <oio:field  label="Firstname">                    <g:TextBox  />              </oio:field>        </oio:SimpleFormPanel>   </ui:UiBinder>  
  • 100. UiChild example @UiChild   public  void  addField(Widget  widget,  String   label)  {        […]   } <ui:UiBinder  […]  xmlns:oio="urn:import:[…]">        <oio:SimpleFormPanel>              <oio:field  label="Firstname">                    <g:TextBox  />              </oio:field>        </oio:SimpleFormPanel>   </ui:UiBinder>  
  • 101. UiChild example @UiChild   public  void  addField(Widget  widget,  String   label)  {        […]   } <ui:UiBinder  […]  xmlns:oio="urn:import:[…]">        <oio:SimpleFormPanel>              <oio:field  label="Firstname">                    <g:TextBox  />              </oio:field>        </oio:SimpleFormPanel>   </ui:UiBinder>  
  • 102. UiChild example @UiChild   public  void  addField(Widget  widget,  String   label)  {        […]   } <ui:UiBinder  […]  xmlns:oio="urn:import:[…]">        <oio:SimpleFormPanel>              <oio:field  label="Firstname">                    <g:TextBox  />              </oio:field>        </oio:SimpleFormPanel>   </ui:UiBinder>  
  • 103. Finally NoWidgets Layouts Panels Composite Simple widgets Committing to web development Getting started
  • 104. What about Layouts? When we think
 of layouts, we
 think of structuring
 the UI from
 a bigger perspektive
  • 105. Structuring Relationship between widgets, MVP, Eventbus, etc... ! ! Not here, not now...
  • 106. Positioning JS positioning CSS Layout
  • 107. Web page layouts Desktop like, 
 full page Long page,
 scroll up/ down
 page
  • 108. Standard widgets Resize inside out
  • 109. Layout widgets resize chaining through ! ProvidesResize RequiresResize ! ! ! Chaining is required,
 resize event only top level, not propagated by browser Resize outside in
  • 110. Full page application, inside out & outside in RootLayoutPanel
  • 111. Scrolling page application
  • 112. Finally NoWidgets Layouts Panels Composite Simple widgets Committing to web development Getting started
  • 113. Widgets do not scale…
  • 114. Widgets do not scale…
  • 115. Heap dumping Total memory No grid, mostly empty Object count 4.8 > 98,000 15.6 > 570,000 Grid, Text 6.5 > 180,000 SafeHTML 4.9 > 99,000 Grid, Widgets
  • 116. Why? setInnerHtml, job done As with CSS: native vs JS Many, many objects and 
 DOM manipulation
  • 117. Bonus feature ‣ SafeHTML provides some level 
 of security against script injection! ‣ SafeHTML templates 
 provides some 
 pain easing in HTML
 development! ‣ Getting used to SafeHTML 
 ! helps getting used to cell widgets, 
 ! ! helps getting used to cell grids, … © 2013 Orientation in Objects GmbH !117
  • 118. SafeHtmlTemplates interface  MyTemplate  extends  
 SafeHtmlTemplates  { !      @Template("<td>{0}</td>")      SafeHtml  cell(String  content); !      @Template("<tr>{0}</tr>")      SafeHtml  row(SafeHtml  cells); !      @Template("<table>{0}</table>")      SafeHtml  table(SafeHtml  rows);   }
  • 119. Finally NoWidgets Layouts Panels Composite Simple widgets Committing to web development Getting started
  • 120. Go native whenever possible ‣ CSS is run natively by the browser! ‣ Optimize DOM manipulation by providing bigger HTML chunks 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 010101010101010101010101010101010101010101010101 !120 © 2013 Orientation in Objects GmbH
  • 121. Separate browser specifics Don‘t if – then – else for different browsers, use deferred binding <replace-with class="de...MyEntryPointIE"> <when-type-is class="de...MyEntryPointDefault" /> <any> <when-property-is name="user.agent" value="ie6" /> <when-property-is name="user.agent" value="ie8" /> <when-property-is name="user.agent" value="ie9" /> <when-property-is name="user.agent" value="opera" /> </any> </replace-with> !121 © 2013 Orientation in Objects GmbH
  • 122. Avoid spaghetti code ‣ Try software engineering, it‘s ok! ‣ Many known patterns work well with GWT! ‣ If you don‘t know better, use MVP !122 © 2013 Orientation in Objects GmbH
  • 123. SINGLETON You must not public static instance
  • 124. Thank you for your attention !

×