Last active
September 20, 2019 10:12
-
-
Save branflake2267/d5f7b546f7c0dbe83df07a2d4d687695 to your computer and use it in GitHub Desktop.
GXT 4 split grid with left side that locks.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.gwt.event.shared.EventHandler; | |
import com.google.gwt.event.shared.GwtEvent; | |
import com.google.gwt.event.shared.HandlerRegistration; | |
import com.google.gwt.user.client.Event; | |
import com.sencha.gxt.test.client.grid_splitgrid.cust.GridRightClickEvent.GridRightHandler; | |
/** | |
* Fires after the reset selection event | |
*/ | |
public class GridRightClickEvent extends GwtEvent<GridRightHandler> { | |
public interface HasGridRightClickHandlers { | |
HandlerRegistration addGridRightClickHandler(GridRightHandler handler); | |
} | |
public interface GridRightHandler extends EventHandler { | |
void onRightClick(GridRightClickEvent event); | |
} | |
/** | |
* Handler type. | |
*/ | |
private static Type<GridRightHandler> TYPE; | |
/** | |
* Gets the type associated with this event. | |
* | |
* @return returns the handler type | |
*/ | |
public static Type<GridRightHandler> getType() { | |
if (TYPE == null) { | |
TYPE = new Type<GridRightHandler>(); | |
} | |
return TYPE; | |
} | |
private int rowIndex; | |
private int colIndex; | |
private Event event; | |
/** | |
* Create a new right click event on row/cell | |
* | |
* @param event | |
* is the event target | |
* @param rowIndex | |
* @param colIndex | |
*/ | |
public GridRightClickEvent(Event event, int rowIndex, int colIndex) { | |
this.event = event; | |
this.rowIndex = rowIndex; | |
this.colIndex = colIndex; | |
} | |
@SuppressWarnings({ "unchecked", "rawtypes" }) | |
@Override | |
public Type<GridRightHandler> getAssociatedType() { | |
return (Type) TYPE; | |
} | |
@Override | |
protected void dispatch(GridRightHandler handler) { | |
handler.onRightClick(this); | |
} | |
public int getRowIndex() { | |
return rowIndex; | |
} | |
public int getColIndex() { | |
return colIndex; | |
} | |
public Event getEvent() { | |
return event; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.sencha.gxt.test.client.grid_splitgrid.cust; | |
import java.util.ArrayList; | |
import java.util.List; | |
import com.google.gwt.core.client.GWT; | |
import com.google.gwt.core.client.Scheduler; | |
import com.google.gwt.core.client.Scheduler.ScheduledCommand; | |
import com.google.gwt.dom.client.Element; | |
import com.google.gwt.event.logical.shared.ResizeEvent; | |
import com.google.gwt.event.logical.shared.ResizeHandler; | |
import com.google.gwt.event.shared.HandlerRegistration; | |
import com.google.gwt.user.client.Event; | |
import com.google.gwt.user.client.ui.FlowPanel; | |
import com.google.gwt.user.client.ui.HasVerticalAlignment; | |
import com.google.gwt.user.client.ui.Widget; | |
import com.sencha.gxt.core.client.GXT; | |
import com.sencha.gxt.core.client.dom.XDOM; | |
import com.sencha.gxt.core.client.dom.XElement; | |
import com.sencha.gxt.core.client.gestures.PointerEventsSupport; | |
import com.sencha.gxt.core.client.util.Margins; | |
import com.sencha.gxt.data.shared.ListStore; | |
import com.sencha.gxt.data.shared.loader.PagingLoadConfig; | |
import com.sencha.gxt.data.shared.loader.PagingLoadResult; | |
import com.sencha.gxt.data.shared.loader.PagingLoader; | |
import com.sencha.gxt.test.client.grid_livegrid.checkbox.CountingCheckBoxSelectionModel_LGV; | |
import com.sencha.gxt.test.client.grid_splitgrid.cust.GridRightClickEvent.GridRightHandler; | |
import com.sencha.gxt.test.client.grid_splitgrid.cust.SplitGridView.GridSide; | |
import com.sencha.gxt.widget.core.client.Composite; | |
import com.sencha.gxt.widget.core.client.container.HorizontalLayoutContainer; | |
import com.sencha.gxt.widget.core.client.container.HorizontalLayoutContainer.HorizontalLayoutData; | |
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer; | |
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData; | |
import com.sencha.gxt.widget.core.client.event.ReconfigureEvent; | |
import com.sencha.gxt.widget.core.client.grid.ColumnConfig; | |
import com.sencha.gxt.widget.core.client.grid.ColumnModel; | |
import com.sencha.gxt.widget.core.client.grid.Grid; | |
import com.sencha.gxt.widget.core.client.grid.GridView; | |
public class SplitGrid<M> extends Composite { | |
/** | |
* Use for left and right grids. | |
*/ | |
public class GridExt<M> extends Grid<M> { | |
private HorizontalLayoutContainer maskOnWidget; | |
public GridExt(ListStore<M> store, ColumnModel<M> cm, GridView<M> view) { | |
super(store, cm, view); | |
// right click | |
sinkEvents(Event.ONCONTEXTMENU); | |
} | |
@Override | |
protected void onRightClick(Event event) { | |
// ignore the native context menu | |
event.preventDefault(); | |
event.stopPropagation(); | |
Element target = Element.as(event.getEventTarget()); | |
int rowIndex = view.findRowIndex(target); | |
if (rowIndex != -1) { | |
int colIndex = view.findCellIndex(target, null); | |
fireEvent(new GridRightClickEvent(event, rowIndex, colIndex)); | |
} | |
} | |
public HandlerRegistration addRightClickHandler(GridRightHandler handler) { | |
return addHandler(handler, GridRightClickEvent.getType()); | |
} | |
@Override | |
public void mask() { | |
// causing issues | |
} | |
@Override | |
public void unmask() { | |
// causing issues | |
} | |
@Override | |
protected void onLoaderBeforeLoad() { | |
maskGrids(); | |
} | |
@Override | |
protected void onLoaderLoadException() { | |
unMaskGrids(); | |
} | |
@Override | |
protected void onLoadLoader() { | |
unMaskGrids(); | |
} | |
public void maskGrids() { | |
// TODO would you like this? or just keep a loading icon in paging toolbar | |
// if (maskOnWidget == null) { | |
// return; | |
// } | |
// maskOnWidget.mask(DefaultMessages.getMessages().loadMask_msg()); | |
} | |
public void unMaskGrids() { | |
// // TODO would you like this? or just keep a loading icon in paging toolbar | |
// if (maskOnWidget == null) { | |
// return; | |
// } | |
// maskOnWidget.unmask(); | |
} | |
public void setMaskOnWidget(HorizontalLayoutContainer maskOnWidget) { | |
this.maskOnWidget = maskOnWidget; | |
} | |
@Override | |
public void reconfigure(ListStore<M> store, ColumnModel<M> cm) { | |
if (!viewReady) { | |
this.store = store; | |
this.cm = cm; | |
setSelectionModel(sm); | |
return; | |
} | |
// if (isLoadMask()) { | |
// mask(DefaultMessages.getMessages().loadMask_msg()); | |
// } | |
// view.initData(store, cm); | |
initDataJsni(view, store, cm); | |
this.store = store; | |
this.cm = cm; | |
sinkCellEvents(); | |
// rebind the sm | |
setSelectionModel(sm); | |
if (isViewReady()) { | |
view.refresh(true); | |
} | |
// if (isLoadMask()) { | |
// unmask(); | |
// } | |
fireEvent(new ReconfigureEvent()); | |
} | |
public native void initDataJsni(GridView<M> view, ListStore<M> store, ColumnModel<M> cm) /*-{ | |
view.@com.sencha.gxt.widget.core.client.grid.GridView::initData(*)(store, cm); | |
}-*/; | |
/** | |
* Reconfigure will try to set the selection model again. the selection model only needs to be set in beginning. | |
*/ | |
public void setSelectionModel(CountingCheckBoxSelectionModel_LGV<M> sm) { | |
if (this.sm != null) { | |
this.sm.bindGrid(null); | |
} | |
this.sm = sm; | |
if (sm != null) { | |
sm.bindGrid(this); | |
} | |
} | |
@Override | |
protected void onTouch(Event event) { | |
// GWT.log("onTouch(e) ----- "); | |
// super.onTouch(event); // ~~~ workaround for edge | |
} | |
@Override | |
protected void onMouseDown(Event e) { | |
GWT.log("onMouseDown(e) ********* "); | |
super.onMouseDown(e); | |
} | |
@Override | |
public void onBrowserEvent(Event ce) { | |
super.onBrowserEvent(ce); | |
switch (ce.getTypeInt()) { | |
case Event.ONCLICK: | |
// ~~~ workaround for edge - correlates with onTouch being disabled | |
if (PointerEventsSupport.impl.isSupported()) { | |
onClick(ce); | |
} | |
break; | |
} | |
} | |
} | |
// views | |
private SplitGridView<M> leftGridView; | |
private SplitGridView<M> rightGridView; | |
// grids | |
private GridExt<M> leftGrid; | |
private GridExt<M> rightGrid; | |
private HorizontalLayoutContainer grids; | |
private HorizontalLayoutData leftGridScrollSpacer; | |
// selection | |
private ListStore<M> listStore; | |
// grid configs | |
private PagingLoader<PagingLoadConfig, PagingLoadResult<M>> pagingLoader; | |
private List<ColumnConfig<M, ?>> leftColumns; | |
private List<ColumnConfig<M, ?>> rightColumns; | |
private SplitPagingToolBar<M> pagingToolbar; | |
/** | |
* This is used to eliminate recursive calls when setting scroll top | |
*/ | |
private int scrollLeftRigthTrack = 0; | |
public SplitGrid(ListStore<M> listStore, PagingLoader<PagingLoadConfig, PagingLoadResult<M>> pagingLoader, | |
List<ColumnConfig<M, ?>> leftColumns, List<ColumnConfig<M, ?>> rightColumns) { | |
this.listStore = listStore; | |
this.pagingLoader = pagingLoader; | |
this.leftColumns = leftColumns; | |
this.rightColumns = rightColumns; | |
initWidget(initSplitGrid()); | |
} | |
private Widget initSplitGrid() { | |
leftGridView = new SplitGridView<M>(GridSide.LEFT); | |
rightGridView = new SplitGridView<M>(GridSide.RIGHT); | |
leftGridView.setRightGridView(rightGridView); | |
rightGridView.setLeftGridView(leftGridView); | |
leftGrid = initLeftGrid(listStore, pagingLoader); | |
rightGrid = initRightGrid(listStore, pagingLoader); | |
String borderColorClassName = "#cccccc"; // GENERAL_CSS.borderColorPrimaryAsBackground(); | |
// grid center splitter line | |
FlowPanel centerSplitter = new FlowPanel(); | |
centerSplitter.setWidth("2px"); | |
centerSplitter.setHeight("100%"); | |
centerSplitter.getElement().addClassName(borderColorClassName); | |
// grid bottom border | |
FlowPanel bottomBorder = new FlowPanel(); | |
bottomBorder.setHeight("2px"); | |
bottomBorder.setWidth("100%"); | |
bottomBorder.getElement().addClassName(borderColorClassName); | |
// left spacer for windows | |
leftGridScrollSpacer = new HorizontalLayoutData(300, 1); | |
leftGridScrollSpacer.setMargins(new Margins(0, 0, getLeftGridMargin(), 0)); | |
// horz - grids | |
grids = new HorizontalLayoutContainer(); | |
grids.add(leftGrid, leftGridScrollSpacer); | |
grids.add(centerSplitter, new HorizontalLayoutData(-1, 1)); | |
grids.add(rightGrid, new HorizontalLayoutData(1, 1)); | |
grids.addResizeHandler(new ResizeHandler() { | |
@Override | |
public void onResize(ResizeEvent event) { | |
resizeLeftGridMargin(); | |
} | |
}); | |
// blank space on the left for windows | |
grids.getElement().getStyle().setBackgroundColor("#b9b9b9"); | |
leftGrid.setMaskOnWidget(grids); | |
rightGrid.setMaskOnWidget(grids); | |
// vert - toolbar/grid | |
VerticalLayoutContainer widget = new VerticalLayoutContainer(); | |
widget.add(grids, new VerticalLayoutData(1, 1)); | |
widget.add(bottomBorder, new VerticalLayoutData(1, -1)); | |
widget.add(getPagingToolbar(), new VerticalLayoutData(-1, -1)); | |
// Make sure both column headers are the same height | |
leftGridView.getHeader().setHeight(28); | |
rightGridView.getHeader().setHeight(28); | |
return widget; | |
} | |
/** | |
* Determine if the left grid should have a margin based on the right grid having a scroll bar or not. | |
*/ | |
private void resizeLeftGridMargin() { | |
if (!GXT.isWindows()) { | |
return; | |
} | |
Scheduler.get().scheduleDeferred(new ScheduledCommand() { | |
@Override | |
public void execute() { | |
leftGridScrollSpacer.setMargins(new Margins(0, 0, getLeftGridMargin(), 0)); | |
grids.forceLayout(); | |
} | |
}); | |
} | |
private int getLeftGridMargin() { | |
if (!GXT.isWindows()) { | |
return 0; | |
} | |
int margin = 0; | |
XElement dataTable = getDataTable(rightGrid.getView()); | |
// does the right side have a scroll bar | |
if (dataTable != null && rightGrid.getView().getScroller().getScrollWidth() <= dataTable.getOffsetWidth()) { | |
margin = XDOM.getScrollBarWidth() - 1; // 1px fix, like a border causing it to be higher | |
} | |
return margin; | |
} | |
private native XElement getDataTable(GridView<?> view) /*-{ | |
return view.@com.sencha.gxt.widget.core.client.grid.GridView::dataTable; | |
}-*/; | |
private SplitPagingToolBar<M> getPagingToolbar() { | |
// The page size is set with the paging limit. | |
pagingToolbar = new SplitPagingToolBar<M>(200); | |
pagingToolbar.bind(pagingLoader); | |
return pagingToolbar; | |
} | |
/** | |
* Left Grid | |
*/ | |
private GridExt<M> initLeftGrid(ListStore<M> listStore, | |
final PagingLoader<PagingLoadConfig, PagingLoadResult<M>> pagingLoader) { | |
ColumnModel<M> leftCM = new ColumnModel<M>(getLeftColumns()); | |
final GridExt<M> leftGrid = new GridExt<M>(listStore, leftCM, leftGridView) { | |
@Override | |
public void onBrowserEvent(Event ce) { | |
if (ce.getTypeInt() == Event.ONSCROLL && scrollLeftRigthTrack == 0) { | |
scrollLeftRigthTrack++; | |
rightGrid.getView().getScroller().setScrollTop(getView().getScroller().getScrollTop()); | |
} else if (ce.getTypeInt() == Event.ONSCROLL) { | |
scrollLeftRigthTrack = 0; | |
} | |
super.onBrowserEvent(ce); | |
} | |
}; | |
//leftGrid.setSelectionModel(selectionModel); | |
leftGrid.setLoader(pagingLoader); | |
// styles | |
leftGrid.getView().setForceFit(true); | |
leftGrid.setBorders(false); | |
leftGrid.setColumnReordering(true); | |
leftGrid.getView().setStripeRows(true); | |
leftGrid.getView().setColumnLines(false); | |
leftGrid.setLoadMask(true); | |
return leftGrid; | |
} | |
protected void clearSelection() { | |
//selectionModel.deselectAll(); | |
} | |
/** | |
* Right Grid | |
*/ | |
private GridExt<M> initRightGrid(ListStore<M> listStore, | |
final PagingLoader<PagingLoadConfig, PagingLoadResult<M>> pagingLoader) { | |
ColumnModel<M> rightCM = new ColumnModel<M>(getRightColumns()); | |
GridExt<M> rightGrid = new GridExt<M>(listStore, rightCM, rightGridView) { | |
@Override | |
public void onBrowserEvent(Event ce) { | |
if (ce.getTypeInt() == Event.ONSCROLL && scrollLeftRigthTrack == 0) { | |
scrollLeftRigthTrack++; | |
leftGrid.getView().getScroller().setScrollTop(getView().getScroller().getScrollTop()); | |
} else if (ce.getTypeInt() == Event.ONSCROLL) { | |
scrollLeftRigthTrack = 0; | |
} | |
super.onBrowserEvent(ce); | |
} | |
}; | |
//rightGrid.setSelectionModelRight(selectionModel); | |
rightGrid.setLoader(pagingLoader); | |
// grid styles | |
rightGrid.setBorders(false); | |
rightGrid.setColumnReordering(true); | |
rightGrid.getView().setStripeRows(true); | |
rightGrid.getView().setColumnLines(false); | |
rightGrid.setLoadMask(true); | |
return rightGrid; | |
} | |
/** | |
* Get left columns but include the checkbox column | |
*/ | |
private List<ColumnConfig<M, ?>> getLeftColumns() { | |
List<ColumnConfig<M, ?>> columns = new ArrayList<>(); | |
// dev columns | |
columns.addAll(leftColumns); | |
return columns; | |
} | |
private List<ColumnConfig<M, ?>> getRightColumns() { | |
return rightColumns; | |
} | |
public ListStore<M> getStore() { | |
return listStore; | |
} | |
public SplitGridView<M> getLeftView() { | |
return leftGridView; | |
} | |
public SplitGridView<M> getRightView() { | |
return rightGridView; | |
} | |
public void setEmptyText(String emptyText) { | |
leftGridView.setEmptyText(""); | |
rightGridView.setEmptyText(emptyText); | |
} | |
public void refresh(boolean headerToo) { | |
leftGridView.refresh(headerToo); | |
rightGridView.refresh(headerToo); | |
clearSelection(); | |
} | |
public HandlerRegistration addLeftGridRightClickhandler(GridRightHandler handler) { | |
return leftGrid.addRightClickHandler(handler); | |
} | |
public HandlerRegistration addRightGridRightClickhandler(GridRightHandler handler) { | |
return rightGrid.addRightClickHandler(handler); | |
} | |
public void scrollToTop() { | |
pagingToolbar.first(); | |
} | |
public Grid<M> getLeftGrid() { | |
return leftGrid; | |
} | |
public Grid<M> getRightGrid() { | |
return rightGrid; | |
} | |
public void reconfigure(List<ColumnConfig<M, ?>> columnsLeft, List<ColumnConfig<M, ?>> columnsRight) { | |
this.leftColumns = columnsLeft; | |
this.rightColumns = columnsRight; | |
ColumnModel<M> leftCM = new ColumnModel<M>(getLeftColumns()); | |
ColumnModel<M> rightCM = new ColumnModel<M>(getRightColumns()); | |
leftGrid.reconfigure(listStore, leftCM); | |
rightGrid.reconfigure(listStore, rightCM); | |
resizeLeftGridMargin(); | |
} | |
public SplitPagingToolBar<M> getPagingToolBar() { | |
return pagingToolbar; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.List; | |
import com.google.gwt.core.client.EntryPoint; | |
import com.google.gwt.core.client.GWT; | |
import com.google.gwt.dom.client.StyleInjector; | |
import com.google.gwt.safehtml.shared.SafeHtml; | |
import com.google.gwt.safehtml.shared.SafeHtmlUtils; | |
import com.google.gwt.user.client.Timer; | |
import com.google.gwt.user.client.rpc.AsyncCallback; | |
import com.google.gwt.user.client.ui.HasHorizontalAlignment; | |
import com.google.gwt.user.client.ui.HorizontalPanel; | |
import com.google.gwt.user.client.ui.RootPanel; | |
import com.sencha.gxt.core.client.ValueProvider; | |
import com.sencha.gxt.data.client.loader.RpcProxy; | |
import com.sencha.gxt.data.shared.ListStore; | |
import com.sencha.gxt.data.shared.ModelKeyProvider; | |
import com.sencha.gxt.data.shared.loader.DataProxy; | |
import com.sencha.gxt.data.shared.loader.LoadResultListStoreBinding; | |
import com.sencha.gxt.data.shared.loader.PagingLoadConfig; | |
import com.sencha.gxt.data.shared.loader.PagingLoadConfigBean; | |
import com.sencha.gxt.data.shared.loader.PagingLoadResult; | |
import com.sencha.gxt.data.shared.loader.PagingLoader; | |
import com.sencha.gxt.test.client.grid_splitgrid.cust.SplitGridView.GridSide; | |
import com.sencha.gxt.widget.core.client.button.TextButton; | |
import com.sencha.gxt.widget.core.client.container.SimpleContainer; | |
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer; | |
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData; | |
import com.sencha.gxt.widget.core.client.container.Viewport; | |
import com.sencha.gxt.widget.core.client.event.SelectEvent; | |
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler; | |
import com.sencha.gxt.widget.core.client.grid.ColumnConfig; | |
import com.sencha.gxt.widget.core.client.grid.filters.StringFilter; | |
public class SplitGridExample implements EntryPoint { | |
private static final int COLUMNS_SIZE = 20; | |
private static final int TOTAL_LENGTH = 5000; | |
public class CustomPagingLoader<C extends PagingLoadConfig, D extends PagingLoadResult<?>> | |
extends PagingLoader<C, D> { | |
public CustomPagingLoader(DataProxy<C, D> proxy) { | |
super(proxy); | |
} | |
@Override | |
public boolean load() { | |
return super.load(); | |
} | |
} | |
@Override | |
public void onModuleLoad() { | |
ListStore<Data> listStore = getStore(); | |
final CustomPagingLoader<PagingLoadConfig, PagingLoadResult<Data>> pagingLoader = getLoader(listStore); | |
pagingLoader.setLimit(200); | |
List<ColumnConfig<Data, ?>> leftColumns = getColumns(GridSide.LEFT, 0, 3); | |
List<ColumnConfig<Data, ?>> rightColumns = getColumns(GridSide.RIGHT, 3, COLUMNS_SIZE); | |
SplitGrid<Data> grid = new SplitGrid<Data>(listStore, pagingLoader, leftColumns, rightColumns); | |
TextButton loadbutton = new TextButton("Load"); | |
loadbutton.addSelectHandler(new SelectHandler() { | |
@Override | |
public void onSelect(SelectEvent event) { | |
pagingLoader.load(); | |
} | |
}); | |
HorizontalPanel hp = new HorizontalPanel(); | |
hp.add(loadbutton); | |
SimpleContainer top = new SimpleContainer(); | |
top.add(hp); | |
VerticalLayoutContainer vlc = new VerticalLayoutContainer(); | |
vlc.add(top, new VerticalLayoutData(1, 100)); | |
vlc.add(grid, new VerticalLayoutData(1, 1)); | |
Viewport vp = new Viewport(); | |
vp.add(vlc); | |
RootPanel.get().add(vp); | |
} | |
/** | |
* Columns | |
*/ | |
private List<ColumnConfig<Data, ?>> getColumns(GridSide gridSide, int start, int limit) { | |
List<ColumnConfig<Data, ?>> columns = new ArrayList<ColumnConfig<Data, ?>>(); | |
// TODO move to ClientBundle | |
// TODO account for older browser transparency/opacity | |
StyleInjector.inject(".headBlack { background-color: black; } .colGray { background-color: rgba(0, 0, 0, 0.1); }"); | |
for (int c = start; c < limit; c++) { | |
String header = "COL" + c; | |
SafeHtml safeHtml = SafeHtmlUtils.fromSafeConstant(header); | |
ColumnConfig<Data, String> col = new ColumnConfig<Data, String>(new ValueProviderExt(c), 70); | |
col.setHeader(safeHtml); | |
// Align Column Content | |
col.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT); | |
col.setHorizontalHeaderAlignment(HasHorizontalAlignment.ALIGN_LEFT); | |
if (c == 3) { | |
col.setColumnHeaderClassName("headBlack"); | |
col.setColumnTextClassName("colGray"); | |
} | |
columns.add(col); | |
} | |
return columns; | |
} | |
/** | |
* Loader | |
* | |
* TODO dont' load on left side | |
* | |
* @param listStore | |
*/ | |
private CustomPagingLoader<PagingLoadConfig, PagingLoadResult<Data>> getLoader(ListStore<Data> listStore) { | |
RpcProxy<PagingLoadConfig, PagingLoadResult<Data>> proxy = new RpcProxy<PagingLoadConfig, PagingLoadResult<Data>>() { | |
@Override | |
public void load(final PagingLoadConfig loadConfig, final AsyncCallback<PagingLoadResult<Data>> callback) { | |
GWT.log("pause loading"); | |
Timer t = new Timer() { | |
@Override | |
public void run() { | |
GWT.log("load() " + loadConfig.getOffset() + " " + loadConfig.getLimit() + " Loading..."); | |
getDatas(loadConfig, callback); | |
} | |
}; | |
t.schedule(500); | |
} | |
}; | |
CustomPagingLoader<PagingLoadConfig, PagingLoadResult<Data>> loader = new CustomPagingLoader<PagingLoadConfig, PagingLoadResult<Data>>( | |
proxy); | |
loader.useLoadConfig(new PagingLoadConfigBean()); | |
loader.addLoadHandler(new LoadResultListStoreBinding<PagingLoadConfig, Data, PagingLoadResult<Data>>(listStore)); | |
loader.setRemoteSort(true); | |
return loader; | |
} | |
private ListStore<Data> getStore() { | |
ListStore<Data> store = new ListStore<Data>(new ModelKeyProvider<Data>() { | |
@Override | |
public String getKey(Data item) { | |
return item.getKey(); | |
} | |
}); | |
return store; | |
} | |
private void getDatas(PagingLoadConfig loadConfig, AsyncCallback<PagingLoadResult<Data>> callback) { | |
final int offset = loadConfig.getOffset(); | |
int limit = loadConfig.getLimit(); | |
GWT.log("getDatas: offset=" + offset + " limit=" + limit); | |
final List<Data> datas = new ArrayList<Data>(); | |
for (int i = offset; i < offset + limit; i++) { | |
datas.add(getData(i)); | |
} | |
PagingLoadResult<Data> result = new PagingLoadResult<Data>() { | |
@Override | |
public List<Data> getData() { | |
return datas; | |
} | |
@Override | |
public void setTotalLength(int totalLength) { | |
} | |
@Override | |
public void setOffset(int offset) { | |
} | |
@Override | |
public int getTotalLength() { | |
return TOTAL_LENGTH; | |
} | |
@Override | |
public int getOffset() { | |
return offset; | |
} | |
}; | |
callback.onSuccess(result); | |
} | |
private Data getData(int row) { | |
String key = "key" + row; | |
String[] values = new String[COLUMNS_SIZE]; | |
for (int col = 0; col < COLUMNS_SIZE; col++) { | |
values[col] = "" + col + "," + row; | |
} | |
Data data = new Data(key, values); | |
return data; | |
} | |
public class ValueProviderExt implements ValueProvider<Data, String> { | |
private int index; | |
public ValueProviderExt(int index) { | |
this.index = index; | |
} | |
@Override | |
public String getValue(Data data) { | |
return data.getValue(index); | |
} | |
@Override | |
public void setValue(Data object, String value) { | |
} | |
@Override | |
public String getPath() { | |
return "path" + index; | |
} | |
} | |
public class StringFilterExt extends StringFilter<Data> { | |
public StringFilterExt(int index) { | |
super(new ValueProviderExt(index)); | |
} | |
} | |
public class Data { | |
private String key; | |
private String[] values; | |
public Data(String key, String[] values) { | |
this.key = key; | |
this.values = values; | |
} | |
public String getKey() { | |
return key; | |
} | |
public void setKey(String key) { | |
this.key = key; | |
} | |
public String getValue(int index) { | |
return values[index]; | |
} | |
public void setValue(int index, String value) { | |
this.values[index] = value; | |
} | |
@Override | |
public String toString() { | |
String s = "Data("; | |
s += "key=" + key; | |
s += ")"; | |
return s; | |
} | |
@Override | |
public int hashCode() { | |
final int prime = 31; | |
int result = 1; | |
result = prime * result + ((key == null) ? 0 : key.hashCode()); | |
return result; | |
} | |
@Override | |
public boolean equals(Object obj) { | |
if (this == obj) | |
return true; | |
if (obj == null) | |
return false; | |
if (getClass() != obj.getClass()) | |
return false; | |
Data other = (Data) obj; | |
if (key == null) { | |
if (other.key != null) | |
return false; | |
} else if (!key.equals(other.key)) | |
return false; | |
return true; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.gwt.core.client.Scheduler; | |
import com.google.gwt.core.client.Scheduler.ScheduledCommand; | |
import com.google.gwt.dom.client.Element; | |
import com.google.gwt.dom.client.Style.Cursor; | |
import com.sencha.gxt.core.client.ValueProvider; | |
import com.sencha.gxt.core.client.dom.XElement; | |
import com.sencha.gxt.core.client.util.Region; | |
import com.sencha.gxt.data.shared.SortDir; | |
import com.sencha.gxt.data.shared.SortInfoBean; | |
import com.sencha.gxt.fx.client.DragEndEvent; | |
import com.sencha.gxt.fx.client.DragStartEvent; | |
import com.sencha.gxt.widget.core.client.ComponentHelper; | |
import com.sencha.gxt.widget.core.client.event.XEvent; | |
import com.sencha.gxt.widget.core.client.grid.ColumnConfig; | |
import com.sencha.gxt.widget.core.client.grid.ColumnHeader; | |
import com.sencha.gxt.widget.core.client.grid.ColumnModel; | |
import com.sencha.gxt.widget.core.client.grid.Grid; | |
import com.sencha.gxt.widget.core.client.grid.GridView; | |
import com.sencha.gxt.widget.core.client.menu.Menu; | |
/** | |
* LiveGridView overrides | |
*/ | |
public class SplitGridView<M> extends GridView<M> { | |
public class ColumnHeaderExt<M> extends ColumnHeader<M> { | |
public ColumnHeaderExt(Grid<M> container, ColumnModel<M> cm) { | |
super(container, cm); | |
} | |
public void setEnableColumnResizing(boolean enable) { | |
if (bar == null && enable) { | |
bar = new GridSplitBar() { | |
protected void onDragStart(DragStartEvent e) { | |
drag(true, "1px solid black", 1, 1); | |
getElement().getStyle().setCursor(Cursor.DEFAULT); | |
startX = e.getX(); | |
int cols = cm.getColumnCount(); | |
for (int i = 0, len = cols; i < len; i++) { | |
if (cm.isHidden(i) || !cm.isResizable(i)) continue; | |
Element hd = getHead(i).getElement(); | |
if (hd != null) { | |
Element hdParent = hd.getParentElement(); // Workaround for bad width when menu is not present | |
Region rr = XElement.as(hdParent).getRegion(); | |
//GWT.log("rr=" + rr + " startX=" + startX + " right=" + (rr.getRight() - 5)); | |
if (startX > rr.getRight() - 5 && startX < rr.getRight() + 5) { | |
colIndex = heads.indexOf(getHead(i)); | |
//GWT.log("~~~~~~DRAG colIndex=" + colIndex); | |
if (colIndex != -1) break; | |
} | |
} | |
} | |
//GWT.log("~~~~~~DRAG colIndex=" + colIndex); | |
if (colIndex > -1) { | |
Element c = getHead(colIndex).getElement(); | |
int x = startX; | |
int minx = x - XElement.as(c).getX() - minColumnWidth; | |
int maxx = (XElement.as(container.getElement()).getX() + XElement.as(container.getElement()).getWidth(false)) | |
- e.getNativeEvent().<XEvent>cast().getXY().getX(); | |
d.setXConstraint(minx, maxx); | |
} | |
} | |
protected void onDragEnd(DragEndEvent e) { | |
drag(false, "none", 0, splitterWidth); | |
int endX = e.getX(); | |
int diff = endX - startX; | |
int width = Math.max(getMinColumnWidth(), cm.getColumnWidth(colIndex) + diff); | |
cm.setUserResized(true); | |
cm.setColumnWidth(colIndex, width); | |
} | |
}; | |
container.getElement().appendChild(bar.getElement()); | |
if (isAttached()) { | |
ComponentHelper.doAttach(bar); | |
} | |
bar.show(); | |
} else if (bar != null && !enable) { | |
ComponentHelper.doDetach(bar); | |
bar.getElement().removeFromParent(); | |
bar = null; | |
} | |
} | |
} | |
/** | |
* Designates left or right grid | |
*/ | |
public enum GridSide { | |
LEFT, RIGHT | |
} | |
//private HashSet<M> selected; | |
private GridSide gridSide; | |
private SplitGridView<M> leftGridView; | |
private SplitGridView<M> rightGridView; | |
public SplitGridView(GridSide gridSide) { | |
this.gridSide = gridSide; | |
vbar = false; | |
if (gridSide == GridSide.LEFT) { | |
// fix white space by decrementing 1 | |
scrollOffset = -1; | |
} | |
} | |
public void setLeftGridView(SplitGridView<M> leftGridView) { | |
this.leftGridView = leftGridView; | |
this.rightGridView = this; | |
} | |
public void setRightGridView(SplitGridView<M> rightGridView) { | |
this.rightGridView = rightGridView; | |
this.leftGridView = this; | |
} | |
@Override | |
public void onRowSelect(final int rowIndex) { | |
super.onRowSelect(rowIndex); | |
if (gridSide == GridSide.LEFT) { | |
// ~~~ workaround, there is something that is causing the issue before this frame. | |
// TODO This causes a small flicker, but brings it into a working state - do to changing views and reselect | |
Scheduler.get().scheduleDeferred(new ScheduledCommand() { | |
@Override | |
public void execute() { | |
rightGridView.onRowSelectSync(rowIndex); | |
} | |
}); | |
} else if (gridSide == GridSide.RIGHT) { | |
leftGridView.onRowSelectSync(rowIndex); | |
} | |
} | |
@Override | |
public void onRowDeselect(int rowIndex) { | |
super.onRowDeselect(rowIndex); | |
if (gridSide == GridSide.LEFT) { | |
rightGridView.onRowDeselectSync(rowIndex); | |
} else if (gridSide == GridSide.RIGHT) { | |
leftGridView.onRowDeselectSync(rowIndex); | |
} | |
} | |
@Override | |
public void onRowOver(Element row) { | |
super.onRowOver(row); | |
int rowIndex = findRowIndex(row); | |
if (rowIndex < 0) { | |
return; | |
} | |
if (gridSide == GridSide.LEFT) { | |
Element rightRow = rightGridView.getRow(rowIndex); | |
rightGridView.onRowOverSync(rightRow); | |
} else if (gridSide == GridSide.RIGHT) { | |
Element leftRow = leftGridView.getRow(rowIndex); | |
leftGridView.onRowOverSync(leftRow); | |
} | |
} | |
@Override | |
public void onRowOut(Element row) { | |
super.onRowOut(row); | |
int rowIndex = findRowIndex(row); | |
if (rowIndex < 0) { | |
return; | |
} | |
if (gridSide == GridSide.LEFT) { | |
Element rightRow = rightGridView.getRow(rowIndex); | |
rightGridView.onRowOutSync(rightRow); | |
} else if (gridSide == GridSide.RIGHT) { | |
Element leftRow = leftGridView.getRow(rowIndex); | |
leftGridView.onRowOutSync(leftRow); | |
} | |
} | |
private void onRowSelectSync(int rowIndex) { | |
super.onRowSelect(rowIndex); | |
} | |
private void onRowOverSync(Element row) { | |
if (row == null) { | |
return; | |
} | |
super.onRowOver(row); | |
} | |
private void onRowOutSync(Element row) { | |
if (row == null) { | |
return; | |
} | |
super.onRowOut(row); | |
} | |
private void onRowDeselectSync(int rowIndex) { | |
super.onRowDeselect(rowIndex); | |
} | |
@Override | |
protected void doSort(int colIndex, SortDir sortDir) { | |
// Left delegate to the right Grid loader | |
if (gridSide == GridSide.LEFT) { | |
ColumnConfig<M, ?> column = cm.getColumn(colIndex); | |
ValueProvider<? super M, ?> vp = column.getValueProvider(); | |
SortInfoBean bean = new SortInfoBean(vp, sortDir); | |
if (sortDir == null && sortState != null && vp.getPath().equals(sortState.getSortField())) { | |
bean.setSortDir(sortState.getSortDir() == SortDir.ASC ? SortDir.DESC : SortDir.ASC); | |
} else if (sortDir == null) { | |
bean.setSortDir(SortDir.ASC); | |
} | |
grid.getLoader().clearSortInfo(); | |
grid.getLoader().addSortInfo(bean); | |
//maskView(); | |
} else if (gridSide == GridSide.RIGHT) { | |
super.doSort(colIndex, sortDir); | |
} | |
} | |
@Override | |
protected void initHeader() { | |
if (header == null) { | |
header = new ColumnHeaderExt<M>(grid, cm) { | |
@Override | |
protected Menu getContextMenu(int column) { | |
return super.getContextMenu(column); | |
} | |
}; | |
} | |
// ~~~ workaround for setting context menu upstream | |
// Use the defined factory in forensics grid | |
// header.setMenuFactory(new HeaderContextMenuFactory() { | |
// @Override | |
// public Menu getMenuForColumn(int columnIndex) { | |
// return createContextMenu(columnIndex); | |
// } | |
// }); | |
header.setSplitterWidth(splitterWidth); | |
} | |
@Override | |
protected void initElements() { | |
super.initElements(); | |
// hide scroll bar | |
if (gridSide == GridSide.LEFT) { | |
//scroller.addClassName(GENERAL_CSS.hideScrollBar()); | |
} | |
} | |
/** | |
* changed visibility | |
*/ | |
@Override | |
public void onNoNext(int index) { | |
super.onNoNext(index); | |
} | |
/** | |
* changed visibility | |
*/ | |
@Override | |
protected void onNoPrev() { | |
super.onNoPrev(); | |
} | |
/** | |
* changed visbility | |
*/ | |
@Override | |
protected void onHighlightRow(int rowIndex, boolean highlight) { | |
super.onHighlightRow(rowIndex, highlight); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.gwt.core.client.GWT; | |
import com.google.gwt.core.client.Scheduler; | |
import com.google.gwt.core.client.Scheduler.ScheduledCommand; | |
import com.google.gwt.event.dom.client.KeyCodes; | |
import com.google.gwt.event.dom.client.KeyDownEvent; | |
import com.google.gwt.event.dom.client.KeyDownHandler; | |
import com.google.gwt.event.shared.HandlerRegistration; | |
import com.google.gwt.uibinder.client.UiConstructor; | |
import com.google.gwt.user.client.ui.TextBox; | |
import com.sencha.gxt.core.client.gestures.TapGestureRecognizer; | |
import com.sencha.gxt.core.client.gestures.TouchData; | |
import com.sencha.gxt.core.client.gestures.TouchEventToGestureAdapter; | |
import com.sencha.gxt.core.client.resources.CommonStyles; | |
import com.sencha.gxt.core.client.util.Util; | |
import com.sencha.gxt.data.shared.loader.BeforeLoadEvent; | |
import com.sencha.gxt.data.shared.loader.LoadEvent; | |
import com.sencha.gxt.data.shared.loader.LoadExceptionEvent; | |
import com.sencha.gxt.data.shared.loader.LoaderHandler; | |
import com.sencha.gxt.data.shared.loader.PagingLoadConfig; | |
import com.sencha.gxt.data.shared.loader.PagingLoadResult; | |
import com.sencha.gxt.data.shared.loader.PagingLoadResultBean; | |
import com.sencha.gxt.data.shared.loader.PagingLoader; | |
import com.sencha.gxt.messages.client.DefaultMessages; | |
import com.sencha.gxt.widget.core.client.button.TextButton; | |
import com.sencha.gxt.widget.core.client.event.SelectEvent; | |
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler; | |
import com.sencha.gxt.widget.core.client.toolbar.FillToolItem; | |
import com.sencha.gxt.widget.core.client.toolbar.LabelToolItem; | |
import com.sencha.gxt.widget.core.client.toolbar.PagingToolBar.PagingToolBarAppearance; | |
import com.sencha.gxt.widget.core.client.toolbar.PagingToolBar.PagingToolBarMessages; | |
import com.sencha.gxt.widget.core.client.toolbar.SeparatorToolItem; | |
import com.sencha.gxt.widget.core.client.toolbar.ToolBar; | |
/** | |
* Copied from PagingToolbar | |
*/ | |
public class SplitPagingToolBar<M> extends ToolBar { | |
protected static class DefaultPagingToolBarMessages implements PagingToolBarMessages { | |
@Override | |
public String afterPageText(int page) { | |
return DefaultMessages.getMessages().pagingToolBar_afterPageText(page); | |
} | |
@Override | |
public String beforePageText() { | |
return DefaultMessages.getMessages().pagingToolBar_beforePageText(); | |
} | |
@Override | |
public String displayMessage(int start, int end, int total) { | |
return DefaultMessages.getMessages().pagingToolBar_displayMsg(start, end, total); | |
} | |
@Override | |
public String emptyMessage() { | |
return DefaultMessages.getMessages().pagingToolBar_emptyMsg(); | |
} | |
@Override | |
public String firstText() { | |
return DefaultMessages.getMessages().pagingToolBar_firstText(); | |
} | |
@Override | |
public String lastText() { | |
return DefaultMessages.getMessages().pagingToolBar_lastText(); | |
} | |
@Override | |
public String nextText() { | |
return DefaultMessages.getMessages().pagingToolBar_nextText(); | |
} | |
@Override | |
public String prevText() { | |
return DefaultMessages.getMessages().pagingToolBar_prevText(); | |
} | |
@Override | |
public String refreshText() { | |
return DefaultMessages.getMessages().pagingToolBar_refreshText(); | |
} | |
} | |
protected int activePage = -1, pages; | |
protected LabelToolItem beforePage, afterText, displayText; | |
protected PagingLoadConfig config; | |
protected TextButton first, prev, next, last, refresh; | |
protected PagingLoader<PagingLoadConfig, ?> loader; | |
protected TextBox pageText; | |
protected boolean showToolTips = true; | |
protected int start, pageSize, totalLength; | |
private final PagingToolBarAppearance appearance; | |
private boolean loading; | |
private boolean buttonsEnabled; | |
// flag to track if refresh was clicked since setIcon will steal focus. If it was focused, we must refocus after icon change | |
private boolean activeRefresh = false; | |
private LoaderHandler<PagingLoadConfig, ?> handler = new LoaderHandler<PagingLoadConfig, PagingLoadResult<?>>() { | |
@Override | |
public void onBeforeLoad(final BeforeLoadEvent<PagingLoadConfig> event) { | |
loading = true; | |
doEnableButtons(false); | |
refresh.setIcon(appearance.loading()); | |
if (activeRefresh) { | |
refresh.focus(); | |
} | |
Scheduler.get().scheduleFinally(new ScheduledCommand() { | |
@Override | |
public void execute() { | |
if (event.isCancelled()) { | |
refresh.setIcon(appearance.refresh()); | |
if (activeRefresh) { | |
refresh.focus(); | |
} | |
doEnableButtons(true); | |
SplitPagingToolBar.this.onLoad(new LoadEvent<PagingLoadConfig, PagingLoadResult<?>>(config, | |
new PagingLoadResultBean<Object>(null, totalLength, start))); | |
} | |
} | |
}); | |
} | |
@Override | |
public void onLoad(LoadEvent<PagingLoadConfig, PagingLoadResult<?>> event) { | |
refresh.setIcon(appearance.refresh()); | |
if (activeRefresh) { | |
refresh.focus(); | |
activeRefresh = false; | |
} | |
doEnableButtons(true); | |
SplitPagingToolBar.this.onLoad(event); | |
} | |
@Override | |
public void onLoadException(LoadExceptionEvent<PagingLoadConfig> event) { | |
refresh.setIcon(appearance.refresh()); | |
if (activeRefresh) { | |
refresh.focus(); | |
activeRefresh = false; | |
} | |
doEnableButtons(true); | |
//setting this here since we never get into onLoad | |
loading = false; | |
} | |
}; | |
private HandlerRegistration handlerRegistration; | |
private PagingToolBarMessages messages; | |
private boolean reuseConfig = true; | |
/** | |
* Creates a new paging tool bar. | |
* | |
* @param pageSize the page size | |
*/ | |
@UiConstructor | |
public SplitPagingToolBar(int pageSize) { | |
this(GWT.<ToolBarAppearance>create(ToolBarAppearance.class), | |
GWT.<PagingToolBarAppearance>create(PagingToolBarAppearance.class), pageSize); | |
} | |
/** | |
* Creates a new tool bar. | |
* | |
* @param toolBarAppearance the tool bar appearance | |
* @param appearance the paging tool bar appearance | |
* @param pageSize the page size | |
*/ | |
public SplitPagingToolBar(ToolBarAppearance toolBarAppearance, PagingToolBarAppearance appearance, int pageSize) { | |
super(toolBarAppearance); | |
this.appearance = appearance; | |
this.pageSize = pageSize; | |
//addStyleName("x-paging-toolbar-mark"); | |
first = new TextButton(); | |
first.setIcon(appearance.first()); | |
first.addSelectHandler(new SelectHandler() { | |
@Override | |
public void onSelect(SelectEvent event) { | |
first(); | |
} | |
}); | |
prev = new TextButton(); | |
prev.setIcon(appearance.prev()); | |
prev.addSelectHandler(new SelectHandler() { | |
@Override | |
public void onSelect(SelectEvent event) { | |
previous(); | |
} | |
}); | |
next = new TextButton(); | |
next.setIcon(appearance.next()); | |
next.addSelectHandler(new SelectHandler() { | |
@Override | |
public void onSelect(SelectEvent event) { | |
next(); | |
} | |
}); | |
last = new TextButton(); | |
last.setIcon(appearance.last()); | |
last.addSelectHandler(new SelectHandler() { | |
@Override | |
public void onSelect(SelectEvent event) { | |
last(); | |
} | |
}); | |
refresh = new TextButton(); | |
refresh.setIcon(appearance.refresh()); | |
refresh.addSelectHandler(new SelectHandler() { | |
@Override | |
public void onSelect(SelectEvent event) { | |
refresh(); | |
} | |
}); | |
beforePage = new LabelToolItem(); | |
beforePage.setLabel(getMessages().beforePageText()); | |
afterText = new LabelToolItem(); | |
pageText = new TextBox(); | |
pageText.setWidth("30px"); | |
pageText.addKeyDownHandler(new KeyDownHandler() { | |
public void onKeyDown(KeyDownEvent event) { | |
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { | |
onPageChange(); | |
} | |
} | |
}); | |
new TouchEventToGestureAdapter(pageText, new TapGestureRecognizer() { | |
@Override | |
protected void onTap(TouchData touchData) { | |
super.onTap(touchData); | |
pageText.setFocus(true); | |
} | |
}); | |
displayText = new LabelToolItem(); | |
displayText.addStyleName(CommonStyles.get().nowrap()); | |
addToolTips(); | |
add(first); | |
add(prev); | |
add(new SeparatorToolItem()); | |
add(beforePage); | |
add(pageText); | |
add(afterText); | |
add(new SeparatorToolItem()); | |
add(next); | |
add(last); | |
add(new SeparatorToolItem()); | |
add(refresh); | |
add(new FillToolItem()); | |
add(displayText); | |
} | |
/** | |
* Binds the toolbar to the loader. | |
* | |
* @param loader the loader | |
*/ | |
@SuppressWarnings({"unchecked", "rawtypes"}) | |
public void bind(PagingLoader<? extends PagingLoadConfig, ?> loader) { | |
if (this.loader != null) { | |
handlerRegistration.removeHandler(); | |
} | |
this.loader = (PagingLoader) loader; | |
if (loader != null) { | |
loader.setLimit(pageSize); | |
// the loader and the handler have the same generics, the cast is required | |
// because neither one cares about the data in the load result. Unsure of | |
// a better way to express this. | |
handlerRegistration = loader.addLoaderHandler((LoaderHandler) handler); | |
} | |
} | |
/** | |
* Clears the current toolbar text. | |
*/ | |
public void clear() { | |
pageText.setText(""); | |
afterText.setLabel(""); | |
displayText.setLabel(""); | |
} | |
/** | |
* Called when a load request is initialed and called after completion of the load request. Subclasses may override as | |
* needed. | |
* | |
* @param enabled the enabled state | |
*/ | |
protected void doEnableButtons(boolean enabled) { | |
buttonsEnabled = enabled; | |
first.setEnabled(enabled); | |
prev.setEnabled(enabled); | |
beforePage.setEnabled(enabled); | |
pageText.setEnabled(enabled); | |
afterText.setEnabled(enabled); | |
next.setEnabled(enabled); | |
last.setEnabled(enabled); | |
displayText.setEnabled(enabled); | |
} | |
/** | |
* Moves to the first page. | |
*/ | |
public void first() { | |
if (!loading) { | |
doLoadRequest(0, pageSize); | |
} | |
} | |
/** | |
* Returns the active page. | |
* | |
* @return the active page | |
*/ | |
public int getActivePage() { | |
return activePage; | |
} | |
/** | |
* Returns the toolbar appearance. | |
* | |
* @return the appearance | |
*/ | |
public PagingToolBarAppearance getPagingToolbarAppearance() { | |
return appearance; | |
} | |
/** | |
* Returns the toolbar messages. | |
* | |
* @return the messages | |
*/ | |
public PagingToolBarMessages getMessages() { | |
if (messages == null) { | |
messages = new DefaultPagingToolBarMessages(); | |
} | |
return messages; | |
} | |
/** | |
* Returns the current page size. | |
* | |
* @return the page size | |
*/ | |
public int getPageSize() { | |
return pageSize; | |
} | |
/** | |
* Returns the total number of pages. | |
* | |
* @return the total pages | |
*/ | |
public int getTotalPages() { | |
return pages; | |
} | |
/** | |
* Returns true if the paging toolbar buttons are enabled. | |
* | |
* @return the buttons enabled. | |
*/ | |
public boolean isButtonsEnabled() { | |
return buttonsEnabled; | |
} | |
/** | |
* Returns true if the previous load config is reused. | |
* | |
* @return the reuse config state | |
*/ | |
public boolean isReuseConfig() { | |
return reuseConfig; | |
} | |
/** | |
* Returns true if tooltip are enabled. | |
* | |
* @return the show tooltip state | |
*/ | |
public boolean isShowToolTips() { | |
return showToolTips; | |
} | |
/** | |
* Moves to the last page. | |
*/ | |
public void last() { | |
if (!loading) { | |
if (totalLength > 0) { | |
int extra = totalLength % pageSize; | |
int lastStart = extra > 0 ? (totalLength - extra) : totalLength - pageSize; | |
doLoadRequest(lastStart, pageSize); | |
} | |
} | |
} | |
/** | |
* Moves to the last page. | |
*/ | |
public void next() { | |
if (!loading) { | |
doLoadRequest(start + pageSize, pageSize); | |
} | |
} | |
/** | |
* Moves the the previous page. | |
*/ | |
public void previous() { | |
if (!loading) { | |
doLoadRequest(Math.max(0, start - pageSize), pageSize); | |
} | |
} | |
/** | |
* Refreshes the data using the current configuration. | |
*/ | |
public void refresh() { | |
if (!loading) { | |
activeRefresh = true; | |
doLoadRequest(start, pageSize); | |
} | |
} | |
/** | |
* Sets the active page (1 to page count inclusive). | |
* | |
* @param page the page | |
*/ | |
public void setActivePage(int page) { | |
if (page > pages) { | |
last(); | |
return; | |
} | |
if (page != activePage && page > 0 && page <= pages) { | |
doLoadRequest(--page * pageSize, pageSize); | |
} else { | |
pageText.setText(String.valueOf((int) activePage)); | |
} | |
} | |
/** | |
* Sets the toolbar messages. | |
* | |
* @param messages the messages | |
*/ | |
public void setMessages(PagingToolBarMessages messages) { | |
this.messages = messages; | |
} | |
/** | |
* Sets the current page size. This method does not effect the data currently being displayed. The new page size will | |
* not be used until the next load request. | |
* | |
* @param pageSize the new page size | |
*/ | |
public void setPageSize(int pageSize) { | |
this.pageSize = pageSize; | |
} | |
/** | |
* True to reuse the previous load config (defaults to true). | |
* | |
* @param reuseConfig true to reuse the load config | |
*/ | |
public void setReuseConfig(boolean reuseConfig) { | |
this.reuseConfig = reuseConfig; | |
} | |
/** | |
* Sets if the button tool tips should be displayed (defaults to true, pre-render). | |
* | |
* @param showToolTips true to show tool tips | |
*/ | |
public void setShowToolTips(boolean showToolTips) { | |
this.showToolTips = showToolTips; | |
if (showToolTips) { | |
addToolTips(); | |
} else { | |
removeToolTips(); | |
} | |
} | |
protected void doLoadRequest(int offset, int limit) { | |
if (reuseConfig && config != null) { | |
config.setOffset(offset); | |
config.setLimit(pageSize); | |
loader.load(config); | |
} else { | |
loader.setLimit(pageSize); | |
loader.load(offset, limit); | |
} | |
} | |
protected void onLoad(LoadEvent<PagingLoadConfig, PagingLoadResult<?>> event) { | |
loading = false; | |
config = event.getLoadConfig(); | |
PagingLoadResult<?> result = event.getLoadResult(); | |
start = result.getOffset(); | |
totalLength = result.getTotalLength(); | |
activePage = (int) Math.ceil((double) (start + pageSize) / pageSize); | |
pages = totalLength < pageSize ? 1 : (int) Math.ceil((double) totalLength / pageSize); | |
if (activePage > pages && totalLength > 0) { | |
last(); | |
return; | |
} else if (activePage > pages) { | |
start = 0; | |
activePage = 1; | |
} | |
pageText.setText(String.valueOf((int) activePage)); | |
String after = null, display = null; | |
after = getMessages().afterPageText(pages); | |
afterText.setLabel(after); | |
first.setEnabled(activePage != 1); | |
prev.setEnabled(activePage != 1); | |
next.setEnabled(activePage != pages); | |
last.setEnabled(activePage != pages); | |
int temp = activePage == pages ? totalLength : start + pageSize; | |
display = getMessages().displayMessage(start + 1, (int) temp, totalLength); | |
String msg = display; | |
if (totalLength == 0) { | |
msg = getMessages().emptyMessage(); | |
} | |
displayText.setLabel(msg); | |
forceLayout(); | |
} | |
protected void onPageChange() { | |
String value = pageText.getText(); | |
if (value.equals("") || !Util.isInteger(value)) { | |
pageText.setText(String.valueOf((int) activePage)); | |
return; | |
} | |
int p = Integer.parseInt(value); | |
setActivePage(p); | |
} | |
/** | |
* Helper method to apply the tool tip messages to built-in toolbar buttons. Additional tooltips can be set by | |
* overriding {@link #setShowToolTips(boolean)}. | |
*/ | |
private void addToolTips() { | |
PagingToolBarMessages m = getMessages(); | |
first.setToolTip(m.firstText()); | |
prev.setToolTip(m.prevText()); | |
next.setToolTip(m.nextText()); | |
last.setToolTip(m.lastText()); | |
refresh.setToolTip(m.refreshText()); | |
} | |
/** | |
* Helper method to remove the tool tip messages from built-in toolbar buttons. Additional tooltips can be set by | |
* overriding {@link #setShowToolTips(boolean)}. | |
*/ | |
private void removeToolTips() { | |
first.removeToolTip(); | |
prev.removeToolTip(); | |
next.removeToolTip(); | |
last.removeToolTip(); | |
refresh.removeToolTip(); | |
} | |
} |
Hello and thanks for providing this example. One question though: How complete is this example (haven't tried to run it yet) - can it be used in production?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://plus.google.com/+BrandonDonnelson/posts/chxCsY9hQym