GWT 2.5.1 CellTable and SimplePager issue - java

I am using GWT 2.5.1. I have a CellTable in which paging is done by SimplePager. I am seeing following issues with the SimplePager.
The number of rows displayed in the last page is incorrect. Let's say there are total 22 rows and the page size is set to 10. So, the third page should show 21-22 of 22. Instead, it shows 13-22 of 22. The last page always shows 10 rows, it takes some from the previous page.
There is no Last page button. There is a fast forward button which is also disabled.
When there is no data, the text says 1-1 of 0.
I know these are known issues as I did a lot of research on this topic. Wanted to know if this is still not fixed in GWT 2.5.1. Any wrappers that are available yet? Any workaround for this bug?
I am writing my custom pager which extends SimplePager as below.
public class MySimplePager extends SimplePager {
public MySimplePager() {
this.setRangeLimited(true);
}
public MySimplePager(TextLocation location, Resources resources, boolean showFastForwardButton, int fastForwardRows, boolean showLastPageButton) {
super(location, resources, showFastForwardButton, fastForwardRows, showLastPageButton);
this.setRangeLimited(true);
}
#Override
public void setPageStart(int index) {
if (this.getDisplay() != null) {
Range range = getDisplay().getVisibleRange();
int pageSize = range.getLength();
if (!isRangeLimited() && getDisplay().isRowCountExact()) {
index = Math.min(index, getDisplay().getRowCount() - pageSize);
}
index = Math.max(0, index);
if (index != range.getStart()) {
getDisplay().setVisibleRange(index, pageSize);
}
}
}
}
I am instantiating the pager as:
SimplePager.Resources resources = GWT.create(SimplePager.Resources.class);
usersPager = new MySimplePager(SimplePager.TextLocation.CENTER, resources, false,10, true);
But, this does not work at all. Strange thing is, the method setPageStart() is not being invoked at any point. I put some log messages in it, but they did not get displayed. Anything I am doing wrong here or missing?
Any help would be greatly appreciated.
Thanks.

I don't face your first 2 problems. Third issue was there in 2.5.1 RC1 release but it has been rectified in the 2.5.1 release.
1) There are hacks to overcome this, but I forgot what is it.
2) Use the following constructor to enable fastforwardbutton and last page button
public SimplePager(TextLocation location, boolean showFastForwardButton,
boolean showLastPageButton)
3) This is fixed in latest release.
For more info check out this.

Related

Why does SWT Edge browser stuck on browser.evaluate()?

all! Asking for your help.
I'm pretty new to SWT - so please do not judge me strictly for questions.
I have a big/old RCP app. It has many views that use embedded browser.
Recently made 2 major updates:
Updated Eclipse platform from 3.7.2 to 4.21;
switch from IE to Edge browser;
The package that I'm using has version:
org.eclipse.swt.win32.win32.x86_64
Bundle-Version: 3.117.0.v20210906-0842
OS: Windows 10
Problem:
After clicking the button on embedded browser page, JavaScript calls the Java MyFunction extends BrowserFunction. Which prepares the data to refresh the page. And before refresh it calls browser.evaluate() to get some number from JS side:
Double numberFromJS = (Double) browser.evaluate("return 2+2; //this expression just for example")
The main thread stuck in the while loop, because pstr[0] == null always true.
package org.eclipse.swt.browser;
class Edge extends WebBrowser {
...
static int callAndWait(String[] pstr, ToIntFunction<IUnknown> callable) {
int[] phr = new int[1];
IUnknown completion = newCallback((result, pszJson) -> {
phr[0] = (int)result;
if ((int)result == COM.S_OK) {
pstr[0] = wstrToString(pszJson, false);
}
return COM.S_OK;
});
pstr[0] = null;
phr[0] = callable.applyAsInt(completion);
completion.Release();
Display display = Display.getCurrent();
while (phr[0] == COM.S_OK && pstr[0] == null) { // <-------------- here
if (!display.readAndDispatch()) display.sleep();
}
return phr[0];
}
}
investigation:
Here https://www.eclipse.org/swt/faq.php I found a limitation about Edge and evaluate, but there is no Exception throwed;
Tried to debug the display.readAndDispatch(), but there is lack of java docs and it jumps into native methods - not clear for me what should exactly happen.
As I understood in general it should handle message from OS and pass it into completion callback from above and set some value into pstr[0];
interesting observation - the evaluate() method for this browser is successfully passed just on it creation. Looks like it became broken after something.
Questions:
Any suggestion to pay attention/check some places?
Is there known issues for that method and workarounds for it?
Is it possible that the messages from system are intercepted from some other place?
Thanks in advance!

weird phenomenon about android Debugger (CloseableReference)

There I have a loop:
public void updateDrawee(View view) {
if (begin) {
begin = false;
for (int i = 0; i < 5; i++) {
CloseableReference<CloseableImage> reference = createBitmapRefer(i);
Log.i("reference", reference+"");
imgList.add(reference);
}Log.i("imgList", imgList.toString());Log.i("imgList.0", imgList.get(0)+"");
}
//...some code
}
and the method createBitmapRefer(int count) follow:
public CloseableReference<CloseableImage> createBitmapRefer(int count) {
ImagePipeline pipeline = Fresco.getImagePipeline();
int[] drawableIds = {R.drawable.alpha1, R.drawable.alpha2,
R.drawable.alpha3, R.drawable.alpha4, R.drawable.alpha5};
ImageRequest levelRequest
= ImageRequestBuilder.newBuilderWithResourceId(drawableIds[count])//++
.setProgressiveRenderingEnabled(true)//逐行加载
.build();
CloseableReference<CloseableImage> bmpReference = null;
DataSource<CloseableReference<CloseableImage>> dataSource
= pipeline.fetchImageFromBitmapCache(levelRequest, this);
try {
if (!dataSource.hasResult()) {
dataSource = pipeline.fetchDecodedImage(levelRequest, this);
}
//count %= 5;
Log.i("dataSource has result", dataSource.hasResult() +"");
Log.i("dataSource fail?", dataSource.hasFailed() + "");
bmpReference = dataSource.getResult();
Log.i("bmpRefer", bmpReference+"");
if (bmpReference != null) {
CloseableReference<CloseableImage> returnRef;
returnRef = bmpReference.clone();
return returnRef;
}else {
return null;
}
}finally {
dataSource.close();
CloseableReference.closeSafely(bmpReference);
}
}
when I debug, if i click step into and see the code step by step, it will return a CloseableReference just as I want, and the imgList(its a ArrayList) can get the element too.BUT if I step over the for loop, it return nothing!
Is there any different between keep looking at it or not???
the watches show elements in imgList, when index=1 and 4, I clicked step into.
and the logcat show what Log.i() print.
Or because I have not use this classCloseableReference in Standardized way?
Let me try to explain what happens here.
You are not using Fresco in the intended way. I will step back for a moment and strongly suggest that you use SimpleDraweView if you just need to display images. If however you really need the underlying bitmap, you can get it from the ImagePipeline in way similar to what you already doing, but with one key difference. Fetching images happens asynchronously. What that means is that you can't just do dataSource = pipeline.fetchDecodedImage(...) and then immediately dataSource.getResult. If the image was not found in the memory cache, getResult will just return null. What you need to do instead is to subscribe to the DataSource as explained in the Fresco documentation. I strongly suggest that you read those few chapters about ImagePipeline if you intend to use it directly. Otherwise you may cause your app to leak the memory or to crash because of rendering recycled bitmap.
What you see in debugger is exactly what I described above. The array of size 5 looks like this:
0 = null,
1 = CloseableReference#4908,
2 = null,
3 = null,
4 = CloseableReference#5231
The AndroidStudio UI just hides the null entries for brevity. You can turn this off if you don't like it by right-clicking there and opening options. The reason you get something for 1 and 4 is because the image has been found in the bitmap memory cache and was retrieved from it immediately. The reason you get null for 0, 2 and 3 is because the image has not been loaded yet. Fresco might need to download the image, and even if it is already downloaded and in the disk cache, it may need to decode the image. All of this takes some time and is not instantaneous. That's why you need to subscribe your callback and ImagePipeline will notify you when the image is ready.

GWT infinite scroll with discarding start-of-list results

Looking for a GWT DataGrid component which implements infinite scroll, BUT also makes sure to discard the results no longer visible on the screen : such as the previously loaded results that are not shown anymore.
This is to avoid a memory hog.
I've been trying to find this on Google, but no luck so far.
Please note : I could take a JS library and adapt it to what I need, but I don't think it would work good with GWT's DataGrid component.
Edit: I am interested specifically in an infinite scroll which ALSO discards/releases the topmost results that are not visible (and loads them up as appropriate).
Any ideas ?
As a matter of fact the showcase example has an infinite scrolling CellList. (you can find the code there).
Although this was done with a CellList the same principles should also apply to a DataGrid.
Check out the ShowMorePagerPanel.java file.
Update:
The onScroll function of ShowMorePagerPanel.java will add the new records at the bottom. However you can easily change the behavior:
Something along the lines (not tested tough):
HasRows display = getDisplay();
if (display == null) {
return;
}
boolean loadData = false;
// If scrolling up, change newStart
int oldScrollPos = lastScrollPos;
lastScrollPos = scrollable.getVerticalScrollPosition();
// get the current visible Range
Range currentRange = display.getVisibleRange();
if (oldScrollPos >= lastScrollPos) {
int newStart = Math.max(
currentRange.getStart() - incrementSize,0);
loadData = true;
}
int maxScrollTop = scrollable.getWidget().getOffsetHeight()
- scrollable.getOffsetHeight();
if (lastScrollPos >= maxScrollTop) {
// We are near the end, so increase the page size.
int newPageSize = Math.min(
display.getVisibleRange().getLength() + incrementSize,
display.getRowCount());
loadData = true;
}
if (loadData) {
display.setVisibleRange(newStart, newPageSize);
}

Fest slows down while testing with swingx jxtreetable

I am not sure how to explain this. But I'll try.. Fest slows down to crawl while working with JXTreeTable of swingx. It doesn't slow down initially. It works fine for a while, but after a while when the same actions are repeated it slows down badly.
I have raised a bug for this in github. Please tell me if this is something that I am doing wrong instead. I am not able to reproduce the problem when I tried to create an SSCCE.
Anyway, here's a video of it slowing down.
http://screencast.com/t/liNttCw2In0w
At times 0.39s to 0.40 a set of operations are performed. These are done when there is one row in the JXTreeTable.
At time 0.49 to end of recording the same operation is repeated but there are now 3 rows in the table, it takes very long for the mouse to click.
I have attached a screenshot taken at the time when fest slows down, which attempts to explain it more
This is the code that does the work:
Step 1) Selecting a node from the tree is done as below:
JTreeFixture folioTreeFixture = importShareholders.panel("treePanel").tree("folioTree");
folioTreeFixture.separator("~");
folioTreeFixture.selectPath(new StringWrapper("Shareholders", true)+"~"+
(ShareType.isEquity(shareType) ? new StringWrapper("Equity Folios", true) : new StringWrapper("Preference Folios", true))+"~"+
new FolioTreeRep(folio.getName(),folioNo, shareType).toString());
Step 2) Searching and selecting a row from the JXTreeTable
int selectRow=-1;
JTableFixture table=importShareholders.table("historyTable");
for(int i=0;i<table.rowCount();i++){
String certificateNumber = table.cell(TableCell.row(i).column(ShareholderHistoryTable.columnIndex(ShareholderHistoryTable.CERT_NO))).value();
String remarks=table.cell(TableCell.row(i).column(ShareholderHistoryTable.columnIndex(ShareholderHistoryTable.REMARKS))).value();
if(StringUtils.isEmpty(remarks) && StringUtils.isNotEmpty(certificateNumber) && Integer.parseInt(certificateNumber)==certNo){
selectRow=i;
break;
}
}
if(selectRow==-1){
fail("Couldn't find certificate number to transfer");
}
Step 3) Showing the pop up menu and clicking the row
table.showPopupMenuAt(TableCell.row(selectRow).column(0)).menuItem("btnTransfer").click();
I am not sure why its slowing down. Please let me know if there is any more info I can help with. Would be grateful for some help in solving the problem
I have profiled the application and I dont find anything untoward happening. I dont have a lot of experience profiling applications. I would be grateful if someone could have a second look at this. I profiled it with yourkit and have uploaded the snapshot dump here:
https://www.dropbox.com/s/dh976v01q9c3sgj/ImportShareholderData.shouldTransferAndSplit-2013-06-14-shutdown.snapshot.zip
Any help will be greatly appreciated..
EDIT:
I think I forgot to mention the same thing works when I do it manually. It only slows down with fest. That leads me to believe that there is an issue with fest maybe?
Sorry about that.
EDIT 2:
As request by Marcin (sorry for the delay Marcin).. Here's the code when the first row is getting split
public List<Integer> splitRowEqually(ShareType shareType, String date, int folioNo, int certNo, int... certnos) throws NoSuchFieldException, TorqueException {
//select a tree node
selectFolioInTree(shareType, folioNo);
Pause.pause(new Condition("Wait until tab is created") {
#Override
public boolean test() {
return importShareholders.tabbedPane().tabTitles().length>0;
}
});
//select a row on the table to split
int row=selectRowWithCertNunber(certNo);
List<Integer> rowsIndexes=new ArrayList<Integer>();
JTableFixture table = importShareholders.table();
//show popup menu on that row and select split
table.showPopupMenuAt(row(row).column(columnIndex(TRANS_TYPE))).menuItem("btnSplit").click();
DialogFixture splitDialog=FinderUtilities.getDialogWithTitle("Split Share Certificate");
splitDialog.textBox("tfDateOfSplit").setText(date);
int noOfShares= Integer.parseInt(table.cell(row(row).column(columnIndex(NO_OF_SHARES))).value());
int distFrom= Integer.parseInt(table.cell(row(row).column(columnIndex(DIST_NO_FROM))).value());
int distTo= Integer.parseInt(table.cell(row(row).column(columnIndex(DIST_NO_TO))).value());
//split the row into the number of times decided by the certnos array
int noOfSharesInEachSplit=noOfShares/certnos.length;
for(int i=0;i<certnos.length;i++){
int distToInSplit = distFrom + noOfSharesInEachSplit-1;
enterSplitRowDetails(splitDialog, certnos[i], distFrom, distToInSplit<=distTo ? distToInSplit : distTo);
distFrom=distToInSplit+1;
rowsIndexes.add(row++);
}
splitDialog.button("btnSplit").click();
return rowsIndexes;
}
//selects a node from the left hand side tree
public void selectFolioInTree(final ShareType shareType,final int folioNo) throws TorqueException {
JTreeFixture folioTreeFixture = importShareholders.panel("treePanel").tree("folioTree");
folioTreeFixture.separator("~");
// I use these wrapper classes - StringWrapper and FolioTreeRep, so that I can get a html
// string for the tree node like <html><b>Shareholder</b></html>
String treePath = new StringWrapper("Shareholders", true) + "~" +
(ShareType.isEquity(shareType) ? new StringWrapper("Equity Folios", true) : new StringWrapper("Preference Folios", true)) + "~" +
new FolioTreeRep(mapOfFolioNames.get(folioNo), folioNo, shareType).toString();
folioTreeFixture.clickPath(treePath);
}
//search the table for a row that contains the cert no provided in the Certificate Number column.
private int selectRowWithCertNunber(int certNo) throws NoSuchFieldException {
int selectRow=-1;
JTableFixture table=importShareholders.table("historyTable");
for(int i=0;i<table.rowCount();i++){
String certificateNumber = table.cell(row(i).column(columnIndex(CERT_NO))).value();
String remarks=table.cell(row(i).column(columnIndex(REMARKS))).value();
if(StringUtils.isEmpty(remarks) && StringUtils.isNotEmpty(certificateNumber)
&& Integer.parseInt(certificateNumber)==certNo){
selectRow=i;
break;
}
}
if(selectRow==-1){
fail("Couldn't find certificate number to transfer");
}
return selectRow;
}
// enter details on the table in the SplitDialog
private void enterSplitRowDetails(DialogFixture splitDialog, int cert, int distFrom, int distTo) {
splitDialog.button("btnAdd").click();
int row = splitDialog.table().rowCount();
splitDialog.table().enterValue(row(row - 1).column(0), String.valueOf(cert));
splitDialog.table().enterValue(row(row - 1).column(1), String.valueOf(distFrom));
splitDialog.table().enterValue(row(row - 1).column(2), String.valueOf(distTo));
}
Emm... It is quite interesting question;
I suppose the question contains less really required details especially the robot integration and IO solutions details so I cannot just give you a proper answer...
Anyway, I'll try to analyze the problem in voice a little bit in my way...
First. According to your screenshot comments, I can notice that all "30s pauses or so" occur on some, as I can get it, stream reading process "select/search" (your app gets some data to output etc). So maybe it is much deeper than you think because it is probably thread problem;
I couldn't find the GuiQuery/GuiTask/GuiActionRunne classes usage in your code snippets so I may suggest the "synch problem" may take place in the mentioned case...
Second. OK... If it is still the thread problem I may suggest the robot and IO solutions are both in some ONE thread (the Main thread or something) because, according to your tips as "At times 0.39s to 0.40 a set of operations are performed. These are done when there is one row in the JXTreeTable." ... GUI is waiting for some process to be completed...
Third.
And again... According to this issue as
"It is recommended to turn on an automated check to verify that all
Swing components updates are done in Swing’s EDT (Event Dispatcher
Thread). For those unfamiliar with the EDT, it is responsible for
handling and updating all Swing widgets in a separate thread, causing
that the application never loses responsiveness to user gestures (just
in short, more about the EDT here). To do that, we add the following
hook to the test:"
import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
import org.junit.BeforeClass;
...
#BeforeClass
public static void setUpOnce() {
FailOnThreadViolationRepaintManager.install();
}
Next step is to launch the frame or dialog. As JUnit runs in its own
thread, we must launch the frame or dialog through Fest, to ensure,
again, that EDT is properly used:
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.fixture.FrameFixture;
import org.junit.Before;
...
private FrameFixture testFrame;
private AllTypesFrame frame;
...
#Before
public void setUp() {
frame = GuiActionRunner.execute(new GuiQuery<AllTypesFrame>() {
protected AllTypesFrame executeInEDT() {
return new AllTypesFrame();
}
});
testFrame = new FrameFixture(frame);
testFrame.show();
}
... makes me think it is maybe the "thread-problem" which is described in the First and Second tips...
so, as a conclusion, I can say that maybe you have to multi-thread your test a little more because it is obviously some kind of synch problem...
P.S.
#sethu, before you start your debugging I want to point a little...
I still suspect threads conflict is taking place here (see my previous tips) because, as I may notice, your code snippets are showing static expressions usage to invoke methods like Pause.pause(...) or FinderUtilities.getDialogWithTitle(...) etc I cannot see the whole project architecture so it is hard to analyze according the represented bits but it is pretty clear the "manual testing" goes fine because action listeners react in real time but fest testing does the annoying delays because it uses some "timer" to countdown until a click emulation occurs etc and of course it is a background process which needs a separate thread... Watch debugging carefully maybe somewhere in your code UI thread and fest thread do conflict (see static methods, thread.sleep etc) the points where fest thread could block (override) the UI's one... :S By the way what method Pause.pause(...) does?
P.P.S.
If you have some additional information please comment my answer
Report if my answer helps you
I do not know what are your robot settings but you can at least try to set idleTimeout and other timeouts for the robot you use. The default timeout is 10 sec (look in org.fest.swing.core.Settings). After I decrease it (first 1000ms, next 100ms) I noticed that robot works faster.
robot().settings().idleTimeout(YOUR_TIMEOUT)
Here is my test setup and one test method. Hope is clear.
Here you have my before/after
private static int testMethodCounter = 0;
private static EmergencyAbortListener mEmergencyAbortListener;
private FrameFixture workbenchFrame;
private Robot robot2;
private static final int myIdleTimeout = 100;
#Before
public void setUp() throws Exception {
// my workaround to be able to start the app once and reuse for all tests
if (testMethodCounter == 0) {
robot2 = BasicRobot.robotWithNewAwtHierarchy();
GuiActionRunner.execute(new GuiTask() {
#Override
protected void executeInEDT() throws Throwable {
ApplicationLauncher.application(ProgramRun.class).start();
}
});
} else {
// the second test method see all before created gui components
robot2 = BasicRobot.robotWithCurrentAwtHierarchy();
}
testMethodCounter++;
robot2.settings().idleTimeout(myIdleTimeout);
workbenchFrame = WindowFinder.findFrame(FrameNames.WORKBENCH.getName()).withTimeout(10000)
.using(robot2);
}
#After
public void tearDown() {
// current window will not be closed
robot2.cleanUpWithoutDisposingWindows();
}
#Test
public void someSmokeTest() throws Exception {
Pause.pause(1000);
// perform some test specific gui actions
// here is very important moment, I need new robot because
// workbenchFrame.button(ButtonNames.SOME_BUTTON_NAME).click(); creates new dialog
// which will be avilable in AWT stack after creation
robot2.cleanUpWithoutDisposingWindows();
robot2 = BasicRobot.robotWithCurrentAwtHierarchy();
// the new Robot needs timeout setup
// without this I have long breaks between gui events
robot2.settings().idleTimeout(myIdleTimeout);
workbenchFrame.button(ButtonNames.SOME_BUTTON_NAME).click();
DialogFixture dialog = WindowFinder.findDialog("dialog2")
.withTimeout(5000).using(robot2);
// some actions on the dialog
// once again next new dialog
workbenchFrame.menuItem(MenuItemNames.NAME).click();
robot2.cleanUpWithoutDisposingWindows();
robot2 = BasicRobot.robotWithCurrentAwtHierarchy();
// and idleTimeout setup once again, new Robot needs new setup
robot2.settings().idleTimeout(myIdleTimeout);
// next actions + assertion
}

GWT - ListBox - pre-selecting an item

I got a doubt regarding pre-selecting(setSelectedIndex(index)) an item in a ListBox, Im using Spring + GWT.
I got a dialog that contains a panel, this panel has a FlexPanel, in which I've put a couple ListBox, this are filled up with data from my database.
But this Panel is for updates of an entity in my database, thus I wanted it to pre-select the current properties for this items, allowing the user to change at will.
I do the filling up in the update method of the widget.
I tried setting the selectedItem in the update method, but it gives me an null error.
I've searched a few places and it seems that the ListBox are only filled at the exact moment of the display. Thus pre-selecting would be impossible.
I thought about some event, that is fired when the page is displayed.
onLoad() doesnt work..
Anyone have something to help me out in here?
I really think you can set the selection before it's attached and displayed, but you have to have added the data before you can select an index. If this is a single select box you could write something like this:
void updateListContent(MyDataObject selected, List<MyDataObject> list){
for (MyDataObject anObject : list) {
theListBox.addItem(anObject.getTextToDisplay(), anObject.getKeyValueForList());
}
theListBox.setSelectedIndex(list.indexOf(selected));
}
If this is a multiple select box something like this may work:
void updateListContent(List<MyDataObject> allSelected, List<MyDataObject> list){
for (MyDataObject anObject : list) {
theMultipleListBox.addItem(anObject.getTextToDisplay(), anObject.getKeyValueForList());
}
for (MyDataObject selected : allSelected) {
theMultipleListBox.setItemSelected(list.indexOf(selected), true);
}
}
(Note I haven't actually compiled this, so there might be typos. And this assumes that the selected element(s) is really present in the list of possible values, so if you cant be sure of this you'll need to add some bounds checking.)
I've been happily setting both the values and the selection index prior to attachment so as far as I'm aware it should work. There's a bug however when setting the selected index to -1 on IE, see http://code.google.com/p/google-web-toolkit/issues/detail?id=2689.
private void setSelectedValue(ListBox lBox, String str) {
String text = str;
int indexToFind = -1;
for (int i = 0; i < lBox.getItemCount(); i++) {
if (lBox.getValue(i).equals(text)) {
indexToFind = i;
break;
}
}
lBox.setSelectedIndex(indexToFind);
}
Pre-selection should work also with setValue()-function. Thus, no complicated code is needed.

Categories

Resources