Поиск по этому блогу

понедельник, 18 февраля 2013 г.

GWT CellTable Custom Cell. Как в GWT создать свою ячейку в CellTable.

GWT предоставляет множество готовых компонентов и широкие возможности для разработки графических интерфейсов. Но для некоторых задач нет заранее подготовленных компонентов, поэтому возникает необходимость создавать свои собственные. Например, в данном случае мне понадобилось создать свою собственную ячейку таблицы, которая будет выводить данные таким образом как это необходимо мне.
Задача состоит в следующем. Необходимо создать ячейку таблицы, в которой будет выводиться текст, а под ним кнопка. По нажатию на кнопку должно появляться диалоговое окно, после ввода данных в котором, в ячейке должен отображаться только текст без кнопки.


Алгоритм действий следующий


1. Создаём класс ячейки StatusCell


Создаем класс нашей ячейки StatusCell, который расширяет класс AbstractCell . В этом классе будем описывать нашу ячейку.

1.1. Определяем конструктор класса. В конструктор передаем слушатель события нажатия по кнопке внутри ячейке. В конструкторе регистрируем событие “click”, которое и будем обрабатывать. А также устанавливаем слушатель события.

public StatusCell(ClickListener clickListener) {
       // регистрируем событие, которое будем обрабатывать
       super("click");
       this.clickListener = clickListener;
}

1.2. Переопределяем метод render. В этом методе определяем, что будет выводиться в ячейке. Устанавливаем ячейке стиль. Создаем вертикальную панель, помещаем на неё элементы, потом преобразовываем панель в строку и эту строку добавляем к объекту sb класса SafeHtmlBuilder, который и будет формировать отображение содержимого ячейки.

@Override
public void render(Context context, CargoStatus value, SafeHtmlBuilder sb) {
 // внутри ячейки создаем div элемент
 sb.appendHtmlConstant
 ("<div  style='padding:0px; border-top-width:0px !important; '>");
 if (value != null) {
  VerticalPanel vp = new VerticalPanel();
  vp.setBorderWidth(0);
  vp.addStyleName("status-cell");
  vp.add(new Label(value.getValue()));
  if (CargoStatus.DELIVERED == value) {
   Button confirm = new Button("Подтвердить");
   vp.add(confirm);
  }
  // преобразуем созданную VerticalPanel в строку
  // и добавляем к html builder
  sb.appendHtmlConstant(vp.toString());
 }
 sb.appendHtmlConstant("</div>");
}

1.3. Переопределяем метод onBrowserEvent. Для обработки события нажатия по кнопке, которая находится внутри ячейки таблицы необходимо переопределить метод onBrowserEvent. В этом методе необходимо сначала определить, что произошло событие “click”, потом найти элемент, по которому кликнул пользователь, и проверить является ли этот элемент кнопкой.

@Override
public void onBrowserEvent(Context context, Element parent,
  CargoStatus value, NativeEvent event,
  ValueUpdater<CargoStatus> valueUpdater) {
 super.onBrowserEvent(context, parent, value, event, valueUpdater);
 // выполняем какие-то действия, если произошло событие click
 if ("click".equals(event.getType())) {
  // получаем объект, по котрому кликнул пользователь
  EventTarget eventTarget = event.getEventTarget();
  // проверяем содержит ли родительский объект
  // элемент по которому кликнул пользователь
  if (parent.isOrHasChild(Element.as(eventTarget))) {
   // получаем элемент по которому кликнул пользователь
   Element el = Element.as(eventTarget);
   // если элемент имеет класс btn,
   // тогда вызываем метод в слушателе события
   // и передаем ему номер строки в которой
   // содержится ячейка с кнопкой
   if (el.getClassName().equals("btn")) {
    clickListener.onClick(context.getIndex());
   }
  }
 }
}

2. Создаем класс нашего столбца StatusColumn


Создаем класс нашего столбца StatusColumn, который расширяет класс Column. В родительский класс Column передаем два параметра ITransportedCargoDto и CargoStatus. Где ITransportedCargoDto – это тип всей строки таблицы, а CargoStatus – тип столбца таблицы. Класс StatusColumn используем для определения собственного столбца таблицы. Этот класс абстрактный, в нем определяем только конструктор, в который передаем слушатель события нажатия по кнопке в ячейке. Внутри самого конструктора вызываем конструктор родительского класса Column, в который передаем экземпляр класса StatusCell , в который передаем наш слушатель события нажатия по кнопке в ячейке таблицы

package com.ipoint.trucking.web.client.ui.transportations.status;

import com.google.gwt.user.cellview.client.Column;
import com.ipoint.trucking.web.client.ui.transportations.ClickListener;
import com.ipoint.trucking.web.commons.enums.CargoStatus;
import com.ipoint.trucking.web.commons.model.ITransportedCargoDto;

// Класс нашего столбца
// в качестве параметров в Column передаем
// 1 параметр ITransportedCargoDto - тип строки
// 2 параметр CargoStatus - тип столбца
public abstract class StatusColumn extends
  Column<ITransportedCargoDto, CargoStatus> {

 public StatusColumn(ClickListener clickListener) {
  super(new StatusCell(clickListener));
 }

}

3. Interface ClickListener


Создаем интерфейс с методом для обработки события нажатия по кнопке в ячейке таблицы. Определяем в этом интерфейсе только один метод onClick(), в который передаем индекс строки, в которой произошло нажатие на ячейку.

package com.ipoint.trucking.web.client.ui.transportations;

// создаем интерфейс для обработки события
// нажатия на кнопке в ячейке таблицы
public interface ClickListener {

 public void onClick(int rowIndex);

}


4. Создаем реализацию интерфейса ClickListener


// Создаем слушателя для события нажатия
// на кнопке в ячейке таблицы
ClickListener clickListener = new ClickListener() {

 // реализуем метод описанный в интерфейсе
 @Override
 public void onClick(int rowIndex) {
  ITransportedCargoDto dto = dataProvider
   .getList().get(rowIndex);
  getUiHandlers().showDriverRatingDialog(dto);
 }
};

5. Создаем таблицу


CellTable<ITransportedCargoDto> table = new CellTable<ITransportedCargoDto>();

6. Создаем столбец и добавляем его в таблицу


Инициализируем наш столбец и добавляем его в таблицу. Так как класс StatusColumn абстрактный, то при инициализации переопределяем метод getValue() родительского класса Column. Метод getValue() будет возвращать значение, которое должно выводиться в ячейке таблицы. 

// создаем нашу колонку и передаем ей слушателя в конструкторе
StatusColumn statusColumn = new StatusColumn(clickListener) {

 // определяем реализацию абстрактного метода getValue
 // возвращаем значение которое будет выводится в ячейке
 // передаем объект который представляет собой строку в таблице
 @Override
 public CargoStatus getValue(ITransportedCargoDto object) {
  return object.getStatus();
 }
};
// добавляем нашу колонку в таблицу
table.addColumn(statusColumn, "Статус");

Комментариев нет:

Отправить комментарий