Creating a GWT iFrame like screen - java

I have been developing an app with Java + GAE (1.8.6) + GWT (2.5.1) and now, as per a requirement of my client, i need to create a screen layout divided in two parts (25%,75%), being in the left side the options, and in the other 75% of the screen, the result of the option clicked (like a screen set as an iFrame).
I have tried to use a DockLayoutPanel with west and center panel added to them, but i cant manage to load the contents of each link placed in the west panel on the center panel.
I have been Google'ing for a solution or some code to adapt it to my needs, but so far I havent had much success.
¿Could you please help me out?. I bought also GWT in Action by Manning ed. but havent found much about this matter there.
Meanwhile i will keep looking around / trying to find a solution on my own.
Thank you in advance,
Kind regards,

The solution i found was:
//define framedPanel for later use
private FramedPanel fupanel;
//Instantiate the widget i want to add when the option is clicked
final FileUp fileUp = new FileUp();
//Create the HtmlLayoutContainer in which add the widget later on
HtmlLayoutContainer conEnlaces = new HtmlLayoutContainer(getTablaEnlaces());
public Widget asWidget() {
if (fupanel == null) {
fupanel = new FramedPanel();
fupanel.setHeadingText("Administración");
(some other code here)
VerticalLayoutContainer p = new VerticalLayoutContainer();
conEnlaces.setWidth(Window.getClientWidth());
fupanel.add(p);
p.add(conEnlaces);
Hyperlink fileUph = new Hyperlink();
fileUph.setText("- Importación de CSV");
conEnlaces.add(fileUph, new HtmlData(".fileUph"));
filexh.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
conEnlaces.add(filex, new HtmlData(".resultado"));
}
});
fupanel.add(conEnlaces);
}
return fupanel;
}
private native String getTablaEnlaces() /*-{
return [ '<table border="0" cellspacing="0" cellpadding="0">',
'<tr><td>',
'<table border="0" width="75%">',
'<tr><td class=fileUph></td></tr>',
'</table></td>',
'<td><table border="0" style="margin-left: 25px;">',
'<tr><td class=resultado></td></tr>',
'</table>',
'</td></tr></table>'
].join("");
}-*/;
public void onModuleLoad() {
RootPanel.get().add(asWidget());
}
And like this my problem has been solved. I have shown you my code because i get angry at times when using stackoverflow forums, and people say to have reached a solution, but dont explain how.
Thank you for your response and time,

Related

Vaadin Grid Detail doesn't show Image correctly

I have a Problem with my Vaadin Grid.
Its a rather simple Grid that just shows some cars with name, model, ps, etc.
If you click on one of the rows, the grid detail opens, and shows a picture of the car.
If you click on the first row in the grid, the Image is cut of and you cant scroll.
But if you click around a bit, for example you click on the 6th row , then the Picture is fine.
Also then you can scroll and if you click on the first row, the image is now shown correctly.
Is this a mistake by me or is this a bug?
public FahrzeugView()
{
final Grid<Fahrzeug> grid = new Grid<>(Fahrzeug.class, false);
grid.setWidthFull();
grid.setHeight("800px");
grid.addColumn(Fahrzeug::getId).setHeader("Id").setSortable(true);
grid.addColumn(Fahrzeug::getMarke).setHeader("Marke").setSortable(true);
grid.addColumn(Fahrzeug::getModell).setHeader("Modell").setSortable(true);
grid.addColumn(Fahrzeug::getPs).setHeader("Ps").setSortable(true).setId("ps");
grid.setItemDetailsRenderer(this.createFahrzeugDetailsRenderer());
final List<Fahrzeug> fahrzeuge = Fahrzeug.setData();
grid.setItems(fahrzeuge);
this.add(grid);
}
private Renderer<Fahrzeug> createFahrzeugDetailsRenderer()
{
return new ComponentRenderer<>(FahrzeugDetailLayout::new,
FahrzeugDetailLayout::setFahrzeug);
}
}
public class FahrzeugDetailLayout extends FormLayout
{
private final Image image = new Image("", "");
public FahrzeugDetailLayout()
{
setResponsiveSteps(new ResponsiveStep("0", 1));
setColspan(this.image, 1);
this.add(this.image);
}
public void setFahrzeug(final Fahrzeug fahrzeug)
{
this.image.setAlt("Bild wird nicht angezeigt!");
this.image.setSrc(fahrzeug.getUrl());
}
}
I dont understand why it is only cut of when you first open the detail and not when you click around and click on it again.
I dont really know what to try to fix this, because i dont know what is causing it to happen.
I tryed google for it but this Problem is very specific.
Thankfull for all the help!

How do I display Button in Nifty GUI without XML?

I'm trying to make a GUI for my game. I've tried various libraries and I've ended up with Nifty. I haven't found any useful tutorial and therefore I'm learning from code examples.
I want to display a simple Button, but it seems that my code is not working. I've tried setting background color of Panel which has been working. I have no idea why the Button is not displaying.
Here's what I have:
protected void prepareNifty(Nifty nifty) {
ScreenBuilder sb = new ScreenBuilder("start");
LayerBuilder lb = new LayerBuilder();
PanelBuilder pb = new PanelBuilder();
pb.control(new ButtonBuilder("btn1", "First Button!"){{
alignCenter();
valignCenter();
height("5%");
width("15%");
backgroundColor(Color.WHITE);
}});
pb.childLayoutCenter();
lb.childLayoutVertical();
lb.panel(pb);
sb.layer(lb);
nifty.addScreen("start", sb.build(nifty));
}
I should add I'm using Slick2D and my class extends NiftyBasicGame.
How can I display the Button and set it an absolute position?
You'll need to load the controls and the styles too when you want to use the default controls, like the Button control.
Try something like:
nifty.loadStyleFile("nifty-default-styles.xml");
nifty.loadControlFile("nifty-default-controls.xml");
new ScreenBuilder("start") {{
layer(new LayerBuilder("background") {{
backgroundColor("#f008");
childLayoutAbsolute();
control(new ButtonBuilder("showPopupButton", "SHOW") {{
x(SizeValue.px(100));
y(SizeValue.px(100));
interactOnClick("showPopup()");
}});
}});
}}.build(nifty);
nifty.gotoScreen("start");
Besides that, it might help to read the nifty-gui-the-manual-1.3.2.pdf

Call javascript function from wicket 6, Link's "onclick ()"

I have the following java and html code:
this.leakageModel = new PropertyListView<Leakage> ( "leakage", new ArrayList<Leakage> ()) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem (final ListItem<Leakage> item) {
Link<String> brandLink = new Link<String> ("brandLink") {
private static final long serialVersionUID = -480222850475280108L;
#Override
public void onClick () {
//change another model in the page to update
//another table when the link is clicked
}
};
brandLink.add (new Label ("brand"));
item.add (brandLink);
} };
add (this.leakageModel);
html file:
<tr wicket:id="leakage" class="testClass">
<td class="testClass">
<a wicket:id="brandLink" href="#">
<span wicket:id="brand"></span>
</a>
</td>
</tr>
What I want to do is to be able to call a javascript function from inside the onClick() method.
The model update that I currently do inside the onClick method works well and updates another table on the page.
However everything I have tried to call a javascript function or change the css style has failed.
For instance:
Adding a css class:
add (new AttributeAppender("class", new Model("anotherclass"), " "));
Using an AjaxLink type instead, and a number of other things I have tried to no avail.
On a related note, my original intention is to hide all rows in the table except the one I have clicked. Maybe I can do this just from the Java code and have no need for Javascript at all, but updating the css as above doesn't work.
Any suggestions as to what am I doing wrong?
On a related note, my original intention is to hide all rows in the
table except the one I have clicked.
Instead of answering your question, I will try to provide a solution to your problem :).
It makes perfect sense to hide the table row via javascript. I would suggest doing it with Jquery as described in Hiding all but first table row with jQuery:
$("#myTbl tr:not(nth-child(3))").hide();
Now, you have to execute the above javascript snippet each time a user clicks your Wicket link. For this, you can for example create your own link class like this:
public class JavascriptLink extends Label{
public JavascriptLink(String id, String label) {
super(id, label);
add(new AttributeAppender("onclick", "...your javascript here..."));
}
}
I leave it to you to combine the jquery with the JavascriptLink to meet your requirements. It should work going in this direction.

How to disable / change style of wicket button link in onClick()

In a Wicket app, I have a bunch of <button> elements to which I'm attacking a Link component. Now in the onClick() method of the component I want to disable or change the style of the button. How can I do that? Calling setEnabled(false) has no effect.
Repeated uses of onClick() are operating on the same object in memory. If you're not using Ajax, you can still maintain some state in an anonymous subclass of Link. Then, you can use onBeforeRender() and onComponentTag() to change how it is displayed each time.
Link<Void> link = new Link<Void>("myLink") {
private String customCSS = null;
private boolean customEnabled = true;
public void onClick() {
if (/* test to determine disabled */) {
customCSS = "disabled";
customEnabled = false;
} else {
customCSS = null;
customEnabled = true;
}
}
#Override
protected void onComponentTag(ComponentTag tag) {
super.onComponentTag(tag);
if (customCSS != null)
tag.put("class", customCSS);
}
#Override
public boolean isEnabled() {
return super.isEnabled() && customEnabled;
}
};
AttributeModifiers (or other behaviors) aren't good for this case because, if you add them in the onClick() method, they will begin stacking on the same link for each click - since they are maintained as part of the Link's state.
Your Link can keep track of all manner of state, allowing your onClick() method to enable/disable/change/etc with repeated clicks.
You can also override onBeforeRender(), isVisible(), and other methods that are run each time the link is displayed on the page. The constructor, onConfigure(), and others are run just once, regardless of how many times you click the button.
I don't think this is an entirely good idea in Wicket. Of course it could be done by trickery, but it's far simpler to either:
Override the isEnabled() method to return a value derived from the model of the form/component.
Attach an AttributeModifier when you create the component, and use a model for it which returns a value derived as above.
Whichever you choose, the principle is to let Wicket "pull" rendering information in rather than pushing it explicitly.
The answer provided by Michael Borgwardt is nearly correct.
The problem is that you use Link. Disabled Links use <span> instead of
<a>/<button> and are surrounded with <em> by default. Using Button
component will set 'disabled' attribute in the element.
I would like to add, that you need to use HTML button element instead of <a> (link). Original answer can be counfusing, because Link and Button also exist in Wicket.
I think AjaxCallDecorator should be the class you need to use to disable/change style of the button.
The problem is that you use Link. Disabled Links use <span> instead of <a>/<button> and are surrounded with <em> by default.
Using Button component will set 'disabled' attribute in the element.
Take a look at SimpleAttributeModifier and AttributeAppender. Depending on your actual requirements one of those should do the trick. SimpleAttributeModifier adds or replaces an attribute of any HTML-Tag that has a prepresentation in wicket (replaces the css class), while AttributeAppender appends to the attributes (adds another css class). This should work for enabling/disabling buttons as well but I haven't tried that.
Example:
Label label = new Label("id", "Some silly text.")
add(label);
label.add(new SimpleAttributeModifier("class", "my-css-class");
For Ajax you'll have to add the component to the target as well.
More detailed example:
Java code:
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.Model;
public class DemoPage extends WebPage {
public DemoPage() {
Form form = new Form("form");
add(form);
final WebMarkupContainer wmc = new WebMarkupContainer("greenText");
form.add(wmc);
form.add(new Link("redLink"){
#Override
public void onClick() {
wmc.add(new SimpleAttributeModifier("class", "redText"));
}});
final Button boldButton = new Button("boldButton"){
#Override
public void onSubmit() {
wmc.add(new AttributeAppender("class", true, new Model<String>("boldText"), " "));
}};
form.add(boldButton);
Link disabler = new Link("buttonDisabler") {
#Override
public void onClick() {
boldButton.add(new AttributeAppender("disabled", true, new Model<String>("disabled"), " "));
}
};
form.add(disabler);
}
}
corresponding HTML:
<html>
<head>
<style>
.redText {
color: red;
}
.greenText {
color: green;
}
.boldText {
font-weight: bold;
}
</style>
</head>
<body>
<form wicket:id="form">
<div class="greenText" wicket:id="greenText">This is Green.</div><br />
Make it red<br />
<input type="submit" wicket:id="boldButton" value="Make it bold" /><br />
Disable the button
</form>
</body>
</html>

Wicket: make a generated csv available to a dygraphs JavaScript

I'm trying to figure out how to make a dynamically generated csv available to a dygraphs JavaScript.
I'm using a wicket behavior to add the dygraph (JavaScript graph) to my markup like shown in the codesample bellow. Right now I've hardcoded it to use a csv file named "dygraph.csv". I want to change this, and instead make dygraph use the values from String csv, how do I achieve this?
Any help help is greatly appreciated.
public class DygraphBehavior extends AbstractBehavior {
private static final long serialVersionUID = -516501274090062937L;
private static final CompressedResourceReference DYGRAPH_JS = new CompressedResourceReference(DygraphBehavior.class, "dygraph-combined.js");
#Override
public void renderHead(IHeaderResponse response) {
response.renderJavascriptReference(DYGRAPH_JS);
}
#Override
public void onRendered(Component component) {
final String id = component.getId();
Response response = component.getResponse();
response.write(JavascriptUtils.SCRIPT_OPEN_TAG);
response.write("new Dygraph(document.getElementById(\""+id+"\"), \"dygraph.csv\", {rollPeriod: 7, showRoller: true, errorBars: true});");
response.write(JavascriptUtils.SCRIPT_CLOSE_TAG);
}
}
public class Dygraph extends WebPage {
public Dygraph() {
String csv = "Date,ms\n20070101,62\n20070102,62";
add(new ResourceLink<File>("csv", new ByteArrayResource("text/csv", csv.getBytes())));
add(new Label("graphdiv").add(new DygraphBehavior()));
}
}
<div>
<h1>Dygraph:</h1>
<div wicket:id="graphdiv" id="graphdiv" style="width:500px; height:300px;"></div>
<a wicket:id="csv" href="#">dl generated csv</a>
</div>
public class Dygraph extends WebPage {
public Dygraph() {
String csv = "Date,ms\n20070101,62\n20070102,62";
ResourceLink<File> link = new ResourceLink<File>("csv", new ByteArrayResource("text/csv", csv.getBytes()));
add( link );
//this is the url that should be passed to the javascript code
CharSequence url = link.urlFor( IResourceListener.INTERFACE );
add(new Label("graphdiv").add(new DygraphBehavior()));
}
}
There are other solutions based on the scope of your resource, maybe a dynamic shared resource would work better (if your graph parameters can simply be passed as url parameters), but this will work.
The JavaScript needs to see the data in some way after the page has been rendered. So you have two options:
Embed the data in the page (say in a hidden div) and then let JavaScript read the data from there as text.
Create a servlet where the JavaScript can download the data from.
The second option means that your page rendering code has to pass the data somehow to the servlet. You can try to put it into the session but then, it will sit there, occupying RAM. Probably not a problem if it's just a little bit of data and you have only a few users. But if that's not true, option #1 is probably better.

Categories