SmartGwt get VLayout height after add members - gwt

I have problem a with getting VLayout height after I add a member to it
VLayot layout = new VLayout();
in presenter I have code
display.getAnswerPanel().removeMembers(display.getAnswerPanel().getMembers());
which clear all members, and I add another (I have buttons, when I clik them, it clears all VLayout and adds new members)
layout.addMember(new Button("Example"));
I need to get offsetHeight of this VLayout on start and everytime I click the button, my problem is that in first time when I load the page, my `offsetHeigh is 1px, each next time when I click button is ok, it shows me the correct value. Can someone help me?
I tried to use this code
scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
layout.getOffsetHeight();
}
but the situation is the same, First time I don't have the correct value.

we can get the height and width of any widget only after the widget is being loaded or on button click.

Scheduler#scheduleDeferred() executes at the end of the GWT loop, so there's still no time for the layout to update either. I guess there's not much you can do besides using the traditional timer hack (in case any reader is in doubt, yes, I meant using setTimeout() or Scheduler.get().scheduleWithFixedDelay(cmd, 200) ).

Related

Wicket AjaxLink javascript handler shows strange behaviour

I have a ListView that displays a list of Panels, one below the other. Every panel features a button (implemented via AjaxLink) that closes the panel and removes it from the list.
This is how the ListView is initalized and how the panels are created:
panelsList = new ArrayList<MyPanel>();
pnlContainer = new WebMarkupContainer("pnlContainer");
ListView<MyPanel> pnlItems = new ListView<MyPanel>("pnlItems", panelsList) {
#Override
protected void populateItem(final ListItem<MyPanel> item) {
item.add(item.getModelObject());
item.add(new AjaxLink<Void>("pnlClose") {
#Override
public void onClick(AjaxRequestTarget target) {
panelsList.remove(item.getModelObject());
target.add(pnlContainer); // repaint panel container
}
});
}
};
pnlContainer.setOutputMarkupId(true);
pnlContainer.add(pnlItems);
add(pnlContainer);
This works so far - the actions that trigger adding new panels (usually also AjaxLinks) do what they should and the new panel is added and displayed correctly. But I have problems getting the close button to fully work.
Please see the following steps:
1) I start the server and navigate to the main page. The ListView is initially populated with one panel.
Close-button-code of this panel:
<a wicket:id="pnlClose" id="pnlClose7" href="javascript:;">Close</a>
Searching the page code for pnlClose7 finds the following javascript code that makes the button work as expected:
Wicket.Ajax.ajax({"u":"./?0-1.IBehaviorListener.0-pnlContainer-pnlItems-0-pnlClose","e":"click","c":"pnlClose7"});;
Note: I do not press the button now, if i would, it would work as expected (thoroughly tested).
2) I trigger an action that opens a second panel. The panel is displayed below the first one as expected.
Close-button of the first panel:
<a wicket:id="pnlClose" id="pnlClosef" href="javascript:;">X</i></a>
Close-button of the second panel:
<a wicket:id="pnlClose" id="pnlClose10" href="javascript:;">X</i></a>
But now, neither searching for pnlClosef nor pnlClose10 finds some javascript code. The buttons (both!) do not work. I can still find the javascript code for pnlClose7.
3) I reload the page via pressing F5.
The button IDs change to pnlClose1a and pnlClose1b. Both IDs have javascript counterparts and work.
4) I press the first button (upper panel, ID pnlClose1a). The panel is closed as expected.
The remaining button's ID changes to pnlClose1c, again without a javascript counterpart. Javascript code for pnlClose1a and pnlClose1b is still present.
To make a long story short, the javascript handlers for my AjaxLinks seem to have shyness issues and only appear after I press F5 or reload the whole page in any other manner. I guess thats because repainting the pnlContainer changes the IDs of the current panels - but why is the linked javascript not updated at the same time? Is there anything I can change in my code to update the whole page without completely reloading it?
Wierd thing is that I am pretty sure this worked before... But I checked the whole class history and can't find any major change that would have triggered that. The ListView-code is mainly static since I added it.
I was had similiar problem. if you have any hardcoded javascript code in your page or panels html file (using <script> tag) remove it and set that js code in renderHead of your panel.

bugs about using DataGrid wrapped by StackLayoutPanel

I tried to use DataGrid and put it in the stacklayoutpanel.At the time when I provide the data for the ListDataProvider, the CellTable is not visible in the browser because it's on a non active tab (although it's visible in the DOM tree). After switching to the tab containing the CellTable there is no data in it. If the tab is active at time of data provisioning the table is filled correctly. Since I have made a column sortable, if I clicked the sorting, the data would be displayed correctly. I want the data to be displayed automatically when I click the other inative tab. This will not be the problem if I switch to use celltable.
I knew this was the bug in GWT and it is fixed in GWT 2.5 RC. But my boss does not want me to use GWT2.5RC yet. I have to workaround to fix this. I knew that someone said datagrid.redraw() could sort of fix it. I tired it, but the display is weird. For example, I have 10 rows in DataGrid, after selecting the 2nd tab, redraw() is called, the data is automatically displayed, but there is only like 10px of block displaying the data and the scroll bar. I have to scroll down to see other rows. There are lots of space in the bottom of the tab not being used. Could anyone tell me how to fix this? So did I use the wrong way to fix it?
is there anything else I can do to fix this problem.
Could anyone give me some tips please.
Thanks
Best Regards
I have been struggled with this thing for almost 3 days. Thanks for Papick G. Taboada and Thomas Broyer.
You guys' ideas are really helpful. Bascially either of your solution does not solve the problem. but after I combined both solutions, dang~ it worked!!.
So. the completed solution is that, add the selection handler on the non-active tab, then when the event is called, used datagrid.onResize() and then stackLayoutPanel.forcelayout(). This can solve my problem. I have also tried replacing datagrid.onResize() with datagrid.redraw(). It works as well.
I hope this can help other people who have the same problem before using GWT 2.5RC
I came across this problem with a DataGrid within and Panel that was in a StackPanelLayout. DataGrid implements RequiresResize, so I made the Panel that contained the DataGrid implement RequiresResize so it could call onResize() for the DataGrid.
in the Panel that contained the DataGrid
#Override
public void onResize()
{
dataGrid.onResize();
}
On the StackLayoutPanel
stackLayoutPanel.addSelectionHandler(new SelectionHandler<Integer>() {
// http://code.google.com/p/google-web-toolkit/issues/detail?id=6889
#Override
public void onSelection(SelectionEvent<Integer> event) {
Integer selectedItem = event.getSelectedItem();
StackLayoutPanel panel = (StackLayoutPanel) event.getSource();
Widget selectedWidget = panel.getWidget(selectedItem);
if (selectedWidget != null && selectedWidget instanceof RequiresResize)
{
((RequiresResize)selectedWidget).onResize();
}
}
});
I believe a more general answer would be that any container in a StackLayoutPanel that contains a widget that implements RequiresResize should also implement RequiresResize and pass it on.

Nvigation within a GWT application

I intend to build a web application where users can enter their time every week and have been struggling to get my head around the concept of a single page in GWT that gets repainted with data depending on the user actions. After researching a lot on this site and google, I found one link that I would like to emulate but dont know how to go about doing it in GWT. Although their source code is available, I dont think it is full and complete. I got some idea from this link - Multiple pages tutorial in Google Web Toolkit (GWT) but again dont know how to implement it into a working version. One small working sample would be great to help me understand and get started.
Could anyone please guide me as to how to achieve the look and feel of the screen with the link below and how the content can be repainted with data from the server ? Would I need to put all the logic in one EntryPoint class ? I would like to have the hyperlinks in the left navigation panel and show the content in the right panel. I seem to be completely lost after a few hours of research.
http://gwt.google.com/samples/Showcase/Showcase.html#!CwHyperlink
Thanks a lot for your help.
Regards,
Sonu.
A single page application layout is actually quite easy to achieve.
The first thing you do is define the general layout, using GWTs layout panels. For your layout, I'd suggest using a DockLayoutPanel.
Content content = new Content();
Button switchContent = new Button(content);
Navigation navigation = new Navigation();
navigation.add(switchContent);
DockLayoutPanel pageLayout = new DockLayoutPanel(Unit.EM);
p.addWest(new HTML(navigation), 7.5);
p.add(new HTML(content));
Here, the width of the navigation panel will be fixed, whereas the content will take the remaining space. You have to pass a reference of the button (or some other widget) which does the switch of the content area, add the button to the navigation area, and so on.
Put this into a class, e.g. called MasterPageFactory:
public class MasterPageFactory {
private MasterPageFactory() {}
public static MasterPage newInstance() {
Content content = new Content();
Button switchContent = new Button(content);
Navigation navigation = new Navigation();
navigation.add(switchContent);
DockLayoutPanel masterPage = new DockLayoutPanel(Unit.EM);
masterPage.addWest(new HTML(navigation), 7.5);
masterPage.add(new HTML(content));
return masterPage;
}
}
Now, in your EntryPoint class, call the factory:
RootLayoutPanel.get().add(MasterPageFactory.newInstance());
This example should get you an idea. Other options would be using a DI framework like Guice or the Command pattern.
Your question is mixing up a couple of concepts. If you want the user to click something that looks like a link, and in reponse the application sends a request to the server and shows a page that looks different than the page they're on, and that page has fresh data that just came from the server, then you want a perfectly normal anchor or form submit button. You don't need anything special or weird from GWT.
The showcase example you referenced lets the user click something that looks like a link, and looks like it loads a new page, even to the point of letting the back button work as expected, but does not actually hit the server to get a new page or new data.

Get the GWT ScrollPanel to start its vertical scrollbar at the bottom

I know there are some questions out there about the GWT ScrollPanel and how it works, but allow me to explain the situation.
I'm working on a project to implement QoS on routers. I'm now at the developping stage of the project and I need to make a webinterface to add protocols such as ssh and http and give them their bandwidth.
To save memory usage and network traffic, I do not use GWT-EXT or Smart GWT. So to set the bandwidths I use a ScrollPanel with an empty SimplePanel in it (which is way too big), leaving only the scrollbar.
Now here's the problem:
I want each scrollbar for each added protocol to start at the bottom, not the top. I can get it working through the code if I manually move the scrollbar first, then any function works, like a scrollToBottom(), or a setScrollPosition(). If I want to move scrollbars through code before moving the scrollbar manually, however, I can't call a function on it.
(I would post a picture but I can't yet - new user)
Summary:
So if I add a protocol (using a button called btnAjouter), the two slidebars (One for guaranteed bandwidth and one for the maximum bandwidth) for each protocol start at the top. I want them to start at the bottom on the load of the widget.
Is there a way to do this?
Thanks in advance!
Glenn
Okay, my colleage found the solution. It's a rather dirty one, though.
The thing is, the functions only work when the element in question is attached to the DOM. I did do a check with a Window.alert() to see if it was attached, and it was. But the prolem was that the functions were called to early, for example on a buttonclick it would've worked. The creation and attachment of the elements all happens very fast, so the Javascript can't keep up, this is the solution:
Timer t1 = new Timer()
{
#Override
public void run()
{
s1.getScroll().scrollToBottom();
s2.getScroll().scrollToBottom();
}
};
t1.schedule(20);
Using a timer isn't the most clean solution around, but it works. s1 and s2 are my custom slidebars, getScroll() gets the ScrollPanel attached to it.
You can extend ScrollPanel and override the onLoad method. This method is called immediately after a widget becomes attached to the browser's document.
#Override
protected void onLoad() {
scrollToBottom();
}
Could you attach a handler to listen to the add event and inside that handler do something like this:
panel.getElement().setScrollTop(panel.getElement().getScrollHeight());
"panel" is the panel that you add your protocol to. It doesn't have to be a ScrollPanel. An HTMLPanel will work.
You can wrap this method in a command and pass it to Schedule.scheduleDeferred if it needs to be called after the browser event loop returns:
Schedule.scheduleDeferred(new Scheduler.ScheduledCommand(
public void execute() {
panel.getElement().setScrollTop(panel.getElement().getScrollHeight());
}
));

CellEditor in EditorGrid loses content when you scroll the grid

I have an issue where a user enters some data in an EditorGrid cell. Then the user scrolls the grid without clicking anywhere first. Upon scrolling, the edited cell gets reset and the entered data is lost. I recorded this behavior using the GXT editablegrid sample:
recording: http://goo.gl/dqqhK
I am trying to prevent the entered data loss if the users scrolls. I have been experimenting with the CellEditor's onBlur(...) method, which is called when the users scrolls, but it seems that its FieldEvent argument has already lost the entered value. So the completeEdit() just stores nothing.
Is there any way that I can prevent that "data loss" when a user scrolls? Any help is greatly appreciated.
Thank you.
Thomas Amsler
Sakai Project (UC Davis)
This works for me, hope it helps:
grid.addListener(Events.OnMouseWheel, new Listener<BaseEvent>() {
#Override
public void handleEvent(BaseEvent be) {
grid.stopEditing();
}
});
Events.BodyScroll works, because when you click up/down arrow of scroll bar or click anywhere of scroll bar is not a MouseWheel event.
I think this should be a GXT bug, hope it will be fixed in the future.