Package org.yaac.client.ui

Source Code of org.yaac.client.ui.BrowserViewImpl$BrowserDataProvider

package org.yaac.client.ui;

import static com.google.common.base.Strings.isNullOrEmpty;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.yaac.client.YaacCallback;
import org.yaac.client.activity.BrowserActivity;
import org.yaac.client.util.ExceptionManager;
import org.yaac.shared.crud.MetaNamespace;
import org.yaac.shared.editor.EntityInfo;
import org.yaac.shared.util.StringUtils;


import com.google.gwt.cell.client.SafeHtmlCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.Range;

/**
* @author Max Zhu (thebbsky@gmail.com)
*
*/
public class BrowserViewImpl extends Composite implements BrowserView {

  private static BrowserViewImplUiBinder uiBinder = GWT.create(BrowserViewImplUiBinder.class);

  @UiTemplate("BrowserView.ui.xml")
  interface BrowserViewImplUiBinder extends UiBinder<Widget, BrowserViewImpl> {
  }
 
  @UiField
  ListBox namespaceListBox;
 
  @UiField
  ListBox kindListBox;
 
  @UiField
  TextBox filtersTxt;
 
  // internal status for filters text
  private boolean waitingForFirstClick;
 
  @UiField(provided=true)
  SimplePager pager;
 
  @UiField(provided=true)
  CellTable<EntityInfo> entityTable;
 
  private BrowserActivity listener;
 
  private List<MetaNamespace> namespaces;
 
  // make sure metadata will only be loaded once by activity
  private boolean isMetaDataInit;
 
  private final ExceptionManager exceptionManager;
 
  @Inject
  BrowserViewImpl(ExceptionManager exceptionManager) {
    this.exceptionManager = exceptionManager;
   
    // init entity table
    entityTable = new CellTable<EntityInfo>();
    entityTable.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
     
    // Create a Pager to control the table.
      SimplePager.Resources pagerResources = GWT.create(SimplePager.Resources.class);
      pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0, true);
      pager.setDisplay(entityTable);
     
    initWidget(uiBinder.createAndBindUi(this));
   
    // disable them at the begining
    namespaceListBox.setEnabled(false);
    kindListBox.setEnabled(false);
    filtersTxt.setEnabled(false);
    this.waitingForFirstClick = true;
   
    this.isMetaDataInit = false;
  }

  @UiHandler("filtersTxt")
  void onFiltersTxtClick(ClickEvent event) {
    if (waitingForFirstClick) {
      filtersTxt.setText("");
      waitingForFirstClick = false;
    }
  }
 
  @UiHandler("filtersTxt")
  void onFiltersTxtKeyPress(KeyPressEvent event) {
    char key = event.getCharCode();
    if (KeyCodes.KEY_ENTER == key) {
      refreshDataGrid();
    }
  }
 
  @Override
  public void setPresenter(BrowserActivity listener) {
    this.listener = listener;
  }
 
  @Override
  public void onMetadataReady(List<MetaNamespace> namespaces) {
    this.isMetaDataInit = true;
   
    this.namespaces = namespaces;
   
    this.namespaceListBox.setEnabled(true);
    this.kindListBox.setEnabled(true);
    this.filtersTxt.setEnabled(true);
   
    this.namespaceListBox.clear();
    for (MetaNamespace namespace : namespaces) {
      this.namespaceListBox.addItem(namespace.getNamespaceName())
    }
   
    this.refreshKindListBox();
  }
 
  private void refreshKindListBox() {
    String selectedNamespace = namespaceListBox.getValue(namespaceListBox.getSelectedIndex());
    for (MetaNamespace namespace : namespaces) {
      // we want to make null == empty string here
      // reason it list box will convert null to emtpy string automatically
      if ((isNullOrEmpty(namespace.getNamespaceName()) && isNullOrEmpty(selectedNamespace))
          || namespace.getNamespaceName().equals(selectedNamespace)) {
        this.kindListBox.clear();
        for (String kindName : namespace.getKindsMap().keySet())  {
          this.kindListBox.addItem(kindName);
        }
       
        break;
      }
    }
   
    this.refreshDataGrid();
  }
 
  private void refreshDataGrid() {
    String selectedKindName = kindListBox.getValue(kindListBox.getSelectedIndex());
    String filters = waitingForFirstClick ? null : filtersTxt.getText().trim();
    this.updateEntityTable(selectedKindName, filters);
  }

  @UiHandler("namespaceListBox")
  void onNamespaceListBoxChange(ChangeEvent event) {
    this.refreshKindListBox();
  }
 
  @UiHandler("kindListBox")
  void onKindListBoxChange(ChangeEvent event) {
    this.filtersTxt.setText("")// clear filters
    this.refreshDataGrid();
  }
 
  private BrowserDataProvider currDataProvider;
 
  /**
   * no need to reload when kind is not changed
   */
  private String currKind;
 
  private String currFilter;
 
  /**
   * current column map, to make sure same column will not be duplicated
   */
  private Map<String, Column<EntityInfo, SafeHtml>> currColMap;
 
  private void updateEntityTable(String kind, String filter) {   
    if (!StringUtils.sameStr(kind, currKind) || !StringUtils.sameStr(filter, currFilter)) {
      currKind = kind;
      currFilter = filter;
      currColMap = new HashMap<String, Column<EntityInfo, SafeHtml>>();
     
      // step 1 : prepare tables based on selected properties
      // remove all existing columns
      while (entityTable.getColumnCount() > 0) {
        entityTable.removeColumn(0);     
      }
     
      // only key now, all columns are dynamic
      entityTable.addColumn(new Column<EntityInfo, SafeHtml>(new SafeHtmlCell()) {
        @Override
        public SafeHtml getValue(EntityInfo entity) {
          SafeHtmlBuilder sb = new SafeHtmlBuilder();
          sb.appendHtmlConstant(entity.getKey().asHtml());
          return sb.toSafeHtml();
        }
      }, "ID/Name")// TODO : i18n
     
      // reset to first page
      pager.firstPage();
     
      // step 2 : load table
      // replace current data provider with new one
      if (currDataProvider != null) {       
        entityTable.setRowCount(0, false);
        currDataProvider.removeDataDisplay(entityTable);
      }
     
      currDataProvider = new BrowserDataProvider(currKind, currFilter);
      currDataProvider.addDataDisplay(entityTable);
    }
  }
 
  /**
   * check all entities, make sure no column(s) is missing
   *
   * @param vals
   */
  private void ensureNewColumns(List<EntityInfo> vals) {
    for (EntityInfo entity : vals) {
      for (final String propertyName : entity.getPropertisMap().keySet()) {
        if (!currColMap.containsKey(propertyName)) {
          Column<EntityInfo, SafeHtml> col = new Column<EntityInfo, SafeHtml>(new SafeHtmlCell()) {
            @Override
            public SafeHtml getValue(EntityInfo entity) {
              String html = entity.propertyAsHtml(propertyName);
              SafeHtmlBuilder sb = new SafeHtmlBuilder();
              sb.appendHtmlConstant(html);
              return sb.toSafeHtml();
            }
          };
         
          entityTable.addColumn(col, propertyName);
          currColMap.put(propertyName, col);
        }
      }
    }
  }
 
  /**
   * @author Max Zhu (thebbsky@gmail.com)
   *
   */
  private class BrowserDataProvider extends AsyncDataProvider<EntityInfo> {
   
    private final String kindName;
   
    private final String filter;
   
    private final List<EntityInfo> cache;
   
    BrowserDataProvider(String kindName, String filter) {
      super();
      this.kindName = kindName;
      this.filter = filter;
     
      // it's less likely that user will browse more than 1000 records
      this.cache = new ArrayList<EntityInfo>(1000);
    }

    @Override
    protected void onRangeChanged(HasData<EntityInfo> display) {
      Range range = display.getVisibleRange();
      final int start = range.getStart();
      final int length = range.getLength();
     
      if (start + length < cache.size()) {
        List<EntityInfo> vals = cache.subList(start, start + length);
        updateRowData(start, vals);
      } else {
        listener.loadEntities(kindName, filter, start, length,
            new YaacCallback<List<EntityInfo>>() {

          @Override
          public void onSuccess(List<EntityInfo> vals) {
            if (vals.isEmpty()) {
              Window.alert("No result returned");
            }
           
            cache.addAll(start, vals);
            ensureNewColumns(vals);
            updateRowData(start, vals);
          }

          @Override
          public void onFailure(Throwable caught) {
            exceptionManager.handle(caught);
          }
        })
      }
    }
  }

  @Override
  public boolean isMetaDataInit() {
    return this.isMetaDataInit;
  }
}
TOP

Related Classes of org.yaac.client.ui.BrowserViewImpl$BrowserDataProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.