GWT: веб-страница с вкладками

Веб-страница с вкладками в последнее время без преувеличения стала одним из доминирующих шаблонов.


В GWT есть специальные классы для того, чтобы быстро такой макет реализовать: TabPanel и TabLayoutPanel.

TabLayout появился на ранних этапах развития GWT и всем, вроде, был хорош, за исключением того, что при реализации вкладок использовались тэги <table>, что в нынешнюю эпоху «дивной верстки» счтается некошерным. Поэтому TabPanel обозван в документации всякими нехорошими словами (типа «quirk» и чуть ли не «deprecated»).

TabLayoutPanel, появившийся в свежих версиях GWT (начиная с 2.0) и призванный прийти на замену TabPanel, формируется уже на чистых div'ах, но на него много жалуются разработчики: высота объекта получается фиксированной и если в отведенное пространство что-то не влезает, то просто подрезается, причем даже без появления полос прокрутки. Может от нас что-то скрывают, но найти корректного решения так и не удалось. Пришлось накидать собственный класс, который, кроме всего прочего, может считывать содержимое вкладок в формате JSON. Это очень удобно для управления контентом.

package net.sf.lab3f.gwt.tablayoutpanel.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;

import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;

import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;

import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.Response;

import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;

import com.google.gwt.dom.client.Style.Unit;

public abstract class Main extends FlowPanel{ 

 private HTML content;// = new SimplePanel();	
 private TabLayoutPanel tabs;
 private JSONArray data;
 private FlowPanel flow;

 private class TabHandler implements SelectionHandler{
  int pos;
  TabHandler(int p){pos = p;}  
  public void onSelection(SelectionEvent e){
   if(content != null)remove(content);	  
   int n = (Integer)e.getSelectedItem();	  
   Widget w = getWidget(n); 
   if(w != null){flow.add(w);return;}
   content = new HTML(dequote(data.get(n).isObject().get("html").isString().toString()));
   content.setStyleName("content");
   flow.add(content);
  }	 
 }

 public Main(int w, int h){
  super();
  flow = this;
  tabs = new TabLayoutPanel(h, Unit.PX);
  tabs.addSelectionHandler(new TabHandler(0));
  HTML ht = new HTML(" ");
  ht.getElement().getStyle().setProperty("display", "block");
  ht.setHeight (h + "px");
  ht.setWidth  (w + "px");
  tabs.setWidth(w + "px");
  setWidth     (w + "px");
  add(tabs);
  add(ht);
  RequestBuilder tabsBuilder = new RequestBuilder(RequestBuilder.GET, GWT.getModuleBaseURL() + "tabs.txt?r=" + Math.random());
  try{
   tabsBuilder.sendRequest("", new RequestCallback(){
    public void onResponseReceived(Request req, Response resp){
     String rsp  = resp.getText();
     data = JSONParser.parse(rsp.replace('\n', ' ').replace('\r', ' ')).isArray();
     for(int i = 0; i < data.size(); i++){
      JSONObject jso = data.get(i).isObject();
      tabs.add(new HTML(" "), dequote(jso.get("tab").isString().toString()));
     }	     
    } 
    public void onError(Request req, Throwable thr){Window.alert(thr.toString());}
   });	  
  } 
  catch(Exception ex){}
 }	 

 private String dequote(String s){
  String r = s.trim();
  if(r.startsWith("\""))r = r.substring(1);
  if(r.endsWith("\""))  r = r.substring(0, r.length() - 1);
  return r;
 }	 

 public Main(int w){
  this(w, 30);
 }	 

 public Main(){
  this(1000, 30);
 }	 

 public abstract Widget getWidget(int n);
}


JSON-файл, наполняющий вкладки, выглядит примерно так:

{tab: "Главная", html: "

       <h1>Заголовок-приветствие</h1>   

       <img src='img/intro.png' style='float: left; margin: 0 15px 15px 0'/> 

       <p class='first'>Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... </p>
       <p>Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... </p> 

"},
    {tab: "Каталог", html: "Здесь модно нарисовать каталог товаров"},
    {tab: "Консультант", html: "Поговорить с консультантом..."},
    {tab: "Контакты", html: "Схема проезда, телефоны и т.п."},
]


Поскольку класс абстрактный, в реальных программах нужно использовать наследующие его сущности. В простейшем случае так:

package ru.hhhhzzzz.index.client;

import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

public class Main{

 private Tabs main = new Tabs(900, 25);
	
 public void onModuleLoad(){
  RootPanel.get("main").add(main);	 
 }	

 private class Tabs extends net.sf.lab3f.gwt.tablayoutpanel.client.Main{
  Tabs(int w, int h){super(w, h);}	 
  public Widget getWidget(int n){return null;}	 
 }	 
}


В реализации метода getWidget(int n) класса Tabs можно создавать любые, самые причудливые виджеты со сложным поведением и «навешивать» их на вкладки с соответствующими номерами.

В конечном итоге получается что-то такое:

Комментарии (1)

RSS свернуть / развернуть
+
0
Вот это элегантно:

{tab: "Главная", html: "

       <h1>Заголовок-приветствие</h1>   

       <img src='img/intro.png' style='float: left; margin: 0 15px 15px 0'/> 

       <p class='first'>Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... </p>
       <p>Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... Что говорить, когда нечего говорить... </p> 

"},
    {tab: "Каталог", html: "Здесь модно нарисовать каталог товаров"},
    {tab: "Консультант", html: "Поговорить с консультантом..."},
    {tab: "Контакты", html: "Схема проезда, телефоны и т.п."},
]


Чтоб всегда так и у всех
avatar

Sergei_T

  • 16 августа 2011, 19:54

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.