GWT Close Tabs


December 5, 2013 Maithilish

6.11. Close Tabs

Last thing we are going to do on the client side is to add a control to close the tabs.
ClosePanel
Figure 6.17. ClosePanel


Except the remove() method offered by TabLayoutPanel, there is no other well documented method to close the tab, but using this method to close tab is little cumbersome when there are multiple tabs. Hence, we are designing a custom widget to do the job.
Earlier, we used a text as header when tabs are added in addTab() method.
in.fins.client.widget/ContentPanel.java

        public void addTab(String text, Composite content) {
             tab.add(content, Text);
             tab.selectTab(tab.getWidgetCount() - 1);
        }

Instead of text, we can use TabLayoutPanel.add(Widget child, Widget tab) method to add a widget as header. When we remove this header widget from the parent using Widget.removeFromParent() method, TabLayoutPanel removes the associated tab as well and we are going to use this feature to close the tab.
ClosePanel is a HorizontalPanel with a HTML widget for text and an Image widget for close icon.
in.fins.client.widget/ClosePanel.gwt.xml

        <g:HorizontalPanel>
                <g:HTML ui:field="html" />
                <g:Image resource="{resource.blank}" width="15px" />
                <g:Image ui:field="close" resource="{resource.close}" />
        </g:HorizontalPanel>

ContentPanel.addTab() method uses ClosePanel as header while adding tab to the TabLayoutPanel.
in.fins.client.widget/ContentPanel.java

        public void addTab(String text, Composite content) {
                ClosePanel closePanel = new ClosePanel();
                closePanel.setText(text);
                closePanel.addCloseHandler(this);
                tab.add(content, closePanel);
                tab.selectTab(tab.getWidgetCount() - 1);
        }

 
CloseEvent

We can not create a CloseEvent like we use to create the custom events as it has protected constructor. Hence it is not possible to use EventBus mechanism instead, we have to use the traditional way of handling the events. ClickHandler is attached to the Close Icon and handler fires CloseEvent with ClosePanel as source and also as target.

 
in.fins.client.widget/ClosePanel.java

        @UiHandler("close")
        void handleClick(ClickEvent event) {
                CloseEvent.fire(this, this);
        }

ClosePanel has to implement HasCloseHandlers interface, which makes ClosePanel as a public source of CloseEvent events. HasCloseHandlers.addCloseHandle() method adds ContentPanel as handler.
in.fins.client.widget/ClosePanel.java

        @Override
        public HandlerRegistration addCloseHandler(CloseHandler<ClosePanel> handler) {
                return addHandler(handler, CloseEvent.getType());
        }

ContentPanel is set as a handler for CloseEvent, and TabLayoutPanel.removeFromParent() removes ClosePanel from tab in the handler which triggers removal of the tab.
in.fins.client.widget/ContentPanel.java



        public void addTab(String text, Composite content) {
                ....
                closePanel.addCloseHandler(this);
                tab.add(content, closePanel);
                tab.selectTab(tab.getWidgetCount() - 1);
        }

        @Override
        public void onClose(CloseEvent<ClosePanel> event) {
                if (tab.getWidgetCount() > 1) {
                        event.getTarget().removeFromParent();
                }
        }

With that, we come the end of GWT client side coding. Example code contains additional menu options and corresponding content pages to add and manage watch lists. These options are not covered in the book as they are similar in design, and readers may go through them after completing the server side concepts.
Next part the book deals with server side coding.