I am brand new to GWT and am trying to achieve the following:
Here's the code that I've cooked up:
public class MyWebApp implements EntryPoint {
// The main container for everything the user sees (the "view")
private LayoutPanel mainPanel;
// Simple HTML for the header ("MyWebApp") and subsequent <hr/>
private SafeHtml header;
// The three links "Dashboard", "Monitors" and "Help Desk"
private HorizontalPanel navMenu;
// The empty content that gets populated when user clicks one of
// the 3 links.
private Panel menuContent;
#Override
public void onModuleLoad() {
// The initial fragment contains the header, nav menu and empty "content" div.
// Each menu/screen then fills out content div.
initMainPanel();
RootPanel.get().add(mainPanel);
}
private void initMainPanel() {
SafeHtmlBuilder headerBuilder = new SafeHtmlBuilder();
navMenu = new HorizontalPanel();
// Leaving null until user clicks on one of the 3 menus.
// Then the menu will decide what panel gets injected for
// this panel.
menuContent = null;
// Create the simple HTML for the header.
headerBuilder.append("<h1>MyWebApp</h1><hr/>");
// Create the navMenu items.
Hyperlink dashboardLink, monitorsLink, helpDeskLink;
// Homepage is http://www.mywebapp.com
// I want the dashboardLink to inject menuContent and "redirect" user to
// http://www.mywebapp.com/dashboard
dashboardLink = new Hyperlink("???", "???");
// http://www.mywebapp.com/monitors
monitorsLink = new Hyperlink("???", "???");
// http://www.mywebapp.com/help-desk
helpDeskLink = new Hyperlink("???", "???");
navMenu.add(dashboardLink);
navMenu.add(monitorsLink);
navMenu.add(helpDeskLink);
// Add all widgets to the mainPanel.
mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString()));
mainPanel.add(navMenu);
mainPanel.add(menuContent);
// Position and size the widgets (omitted for brevity).
// mainPanel.setWidgetHorizontalPosition(...);
}
private HTML getDashboardMenuContent() {
return new HTML("This is the dashboard.");
}
private HTML getMonitorsMenuContent() {
return new HTML("These are the monitors.");
}
private HTML getHelpDeskMenuContent() {
return new HTML("This is the help desk.");
}
}
Most importantly:
How do I "wire up" the Hyperlinks so that when the user clicks them, I can call the appropriate getXXXMenuContent() method, and then add that to menuContent?
But also:
I feel like I'm doing something wrong here: mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString())); - if so what is it?!? How should I be adding a simple <h1> and <hr/> in a way that's secure (hence the use of the Safe* objects), efficient, and conforming to recommended practices?
Should I be implementing UiBinder here? If so, would I make UiBinders for each menu's content or for the entire mainPanel, or both?
Thanks in advance!
Hyperlink widgets trigger navigation. You don't want to handle clicks on them, you want to handle navigation (that could be triggered by clicking a Hyperlink or using the browser's back/forward buttons, a bookmark or link from elsewhere –including Ctrl+clicking a Hyperlink to open it in a new window/tab–, etc.)
To react to those navigation events, use History.addValueChangeHandler; and to handle the initial navigation on application start, call History.fireCurrentHistoryState() (after you add your handler of course).
More details in: https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsHistory
Would be better to split other questions to... other questions, but here are the answers anyway:
I feel like I'm doing something wrong here: mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString())); - if so what is it?!? How should I be adding a simple <h1> and <hr/> in a way that's secure (hence the use of the Safe* objects), efficient, and conforming to recommended practices?
The HTML widget has a constructor taking a SafeHtml so you don't need to call toString().
If you're only using a constant, you don't need a SafeHtmlBuilder; use SafeHtmlUtils instead. But constants are no more or less secure with or without SafeHtml, SafeHtml just makes it easier to find all occurrences of HTML in your code, to help in doing a security review of your app (BTW, we're doing HTML, so <hr>, not <hr/>; if you really want it to look like XML/XHTML, then use <hr /> but you're only cheating yourself here)
Should I be implementing UiBinder here? If so, would I make UiBinders for each menu's content or for the entire mainPanel, or both?
If you don't feel the need for UiBinder, you don't have to use it. But in this case it won't change anything: you're not handling widget events, but history events.
Something like
dashboardLink.addClickHandler(
new ClickHandler()
{
public void onClick( ClickEvent event )
{
mainPanel.setWidget( getDashboardMenuContent() );
}
} );
You should note that Hyperlink.addClickHandler(...) is deprecated and it is recommended to use Anchor.addClickHandler(...) instead.
As for the other questions: It is a lot more elegant and easier to build UI's with UIBinder, so definitely look into that, but do try to make "it" work first to avoid the added complexity of the .ui.xml setup :-)
Cheers,
I have one simple piece of advice to give you. Use what the framework has to offer.
The HTML widget should be your last escape. There are so many widgets that there is no need for you to write html almost anywhere in your code.
So instead of headerBuilder, you can user the following piece of code
Label header = new Label("MyWebApp");
header.setStyleName("headerStyle",true);
You can set the style properties in an external Css file and add the reference inside the base html file or the gwt.xml file. So that answers your question about mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString()));
In respect to the Hyperlink. If you choose to use hyperlinks, remember that the most effective usage is with the MVP pattern better known as Places and Activities (Lots of information on the web)
If you want something simpler instead the MenuBar and MenuItem classes should do the trick.
Look here for an example on how to use the MenuBar to control your application. There are many other ways but why not use the tools provided?
Also the UIBinder Vs the Designer/Classes methods is extensively discussed on stackoverflow resulting to a matter of choice and programming familiarity/preference.
Related
i am trying to create a jface wizard.
In my wizard i have my "startpage". The options i choose in my "startpage" depending on how many pages will follow. But in my opinion its not possible to do that. Because the addPages() method getting called after the wizard was started. The addPage() method is private. But i need to add my pages there, because when i do it somewhere else, the createControl(Composite parent) don't getting called.
Is there any solution how to solve that problem?
I thought about writing a own method sth. like this:
public void addNewPage() {
Page page = new Page("pagename");
page.createControl(parent);
page.setDescription("");}
...
But it doesn't work.
Do you guys have any solution for my problem?
You could add all your pages in the wizard addPages and then override getNextPage to control which pages is displayed when Next is pressed.
If that is not enough you can always write your own implementation of the IWizard interface.
You can do so by overriding org.eclipse.jface.wizard.Wizard.getNextPage to return a new page if conditions are met (conditionForMorePages in the snippet below):
#Override
public IWizardPage getNextPage() {
IWizardPage nextPage = super.getNextPage(page);
if (nextPage == null) {
if (conditionForMorePages){
// we need an additional page.
IWizardPage nextPage = new MyAdditionalPage();
}
}
return nextPage;
}
If your wizard start with only one page, "back" and "next" buttons do not appear by default. If there is a chance you have more steps coming up dynamically, you want to display the navigation buttons. You can do so by setting the proper flag using the API
public void setForcePreviousAndNextButtons(boolean b)
I am developing an Wicket application. But my question is not really Wicket related. In that app I have a horizontal menu. This menu is created by few links. On clicking the link you will be navigated to some page. Now based on the page you are currently viewing the css class attribute of the link of the menu will be changed to "selected". This is the description of the problem.
Now I am solving this problem by using a integer value. The value is saved in the session and it is updated when any one link has been clicked. Based on that saved value, which link will be "selected", will be determined at runtime.
I am implementing this in following way:
//On link click I set a number in session
public void onClick() {
session.setValue(1);// or 2 or 3
}
When the menu is created I switch between the value and modify the css class, as follows:
switch(session.getValue){
case 1: add css to home;
case 2: add css to profile;
// and so on.
}
I was wondering that is this the only right way to do it? Or there some other better techniques or design patterns exist which can help me to achieve this in better way?
Store the menu items in an array (or an ArrayList):
items[0] = home
items[1] = profile
And use the index of the array as menu identifier. When you receive the selected menu itentifier, retrieve the corresponding item with
items[selectedItem]
You could also use a Map if the identifiers are not numbers, or don't go from 0 to N.
For a start, use an enum or static constants instead of magic numbers (1, 2, 3).
The Visitor Pattern is commonly used to avoid this sort of switching. You might not want to implement the full pattern in your case, but it's worth knowning. JB Nizet's answer may be more practical in your situation.
See https://en.wikipedia.org/wiki/Visitor_pattern
These SO questions might give you some ideas, too
Java visitor pattern instead of instanceof switch
Java Enums - Switch statements vs Visitor Pattern on Enums - Performance benefits?
I have implemented it using EnumMap and an Enum type as its key. I have defined an Enum:
public enum NavigationStatus {
HOME,
PROFILE;
}
In session I set the value of the current navigation as:
private NavigationStatus activeUserNavigationStatus;
public NavigationStatus getActiveUserNavigationStatus() {
return activeUserNavigationStatus;
}
public void setActiveUserNavigationStatus(NavigationStatus activeUserNavigationStatus) {
this.activeUserNavigationStatus = activeUserNavigationStatus;
}
Primarily I set it to: setActiveUserNavigationStatus(NavigationStatus.HOME);
Now where the menu is building I created an EnumMap:
EnumMap<NavigationStatus, Component[]> menuMap = new EnumMap<NavigationStatus, Component[]>(NavigationStatus.class);
And added elements to it, as:
menuMap.put(NavigationStatus.HOME, new Component[] { homeContainer, home });
And also on click methods of the links I set the status value:
public void onClick() {
session.setActiveUserNavigationStatus(NavigationStatus.PROFILE);
}
Last of all I checked the current value from the session and set the css class accordingly:
Component[] menuComponents = menuMap.get(getSession().getActiveUserNavigationStatus());
menuComponents[0].add(new AttributeAppender("class", new Model<Serializable>(" active")));
menuComponents[1].add(new AttributeAppender("class", new Model<Serializable>(" active")));
This is without switch statement and combines the idea of JB Nizet's ArrayList index and Oli Charlesworth's Enum.
Thank you.
In a Wicket app, I have a modal dialog that contains a simple form and a button. User enters values (report parameters), and then clicks the button which starts the download of a report file (typically a PDF). (All form values are required, and Wicket's validation mechanism is used to make sure user entered them before the download can start.)
Maybe this is better explained with a picture:
I'm using here a jQuery UI Dialog (instead of Wicket's ModalWindow which felt a lot clumsier and uglier from user's perspective).
Everything is pretty much working, except closing the dialog when/after clicking the download button.
Current version (irrelevant bits omitted):
public class ReportDownloadLink extends Link {
public ReportDownloadLink(String id, ReportDto report) {
super(id);
this.report = report;
}
#Override
public void onClick() {
IResourceStream resourceStream = new AbstractResourceStreamWriter() {
#Override
public void write(OutputStream output) {
try {
reportService.generateReport(output, report);
} catch (ReportGenerationException e) {
// ...
}
}
#Override
public String getContentType() {
// ...
}
};
ResourceStreamRequestTarget target =
new ResourceStreamRequestTarget(resourceStream, report.getFileName());
getRequestCycle().setRequestTarget(target);
}
The dialog is a Wicket Panel (which makes use of ReportDownloadLink above), which we put in a certain div, and then when a report is selected in a list, the dialog is opened from an AjaxLink's onClick() quite simply like this:
target.appendJavascript(String.format("showReportExportDialog('%s')", ... ));
Which calls this JS function:
function showReportExportDialog(dialogTitle) {
$("#reportExportPanelContainer").dialog(
{modal:true, draggable:true, width: 320, height: 330, title: dialogTitle}
);
}
Some options:
Make ReportDownloadLink extend something else than Link, perhaps, and/or find an appropriate method to override which would allow me to execute the tiny bit of JavaScript needed to close the jQuery Dialog.
Investigate jQuery + Wicket libraries (such as jqwicket or wiquery) that supposedly make these two work better together.
Latest thing I tried was overriding method getOnClickScript() in ReportDownloadLink which seemed promising (according to the Javadocs, it returns "Any onClick JavaScript that should be used"):
#Override
protected CharSequence getOnClickScript(CharSequence url) {
return "closeDownloadDialog()";
}
Thing is, this causes onClick() not to be called at all, i.e., the download doesn't start.
Could I perhaps override some more "ajaxy" class from Wicket (than Link) to combine these things: first init the download, then call the JS for closing the dialog?
Any recommendations or experiences from similar cases? Note that I want to keep using the jQuery dialog here, even though it makes things like these more complicated. Using a DownloadLink (see related question) is fine too in case that makes things easier.
NB: if you recommend JQWicket or wiQuery, please provide an example of how to do this.
Maybe you can try to bind the close modal code to the button "click" event using only JQuery, in your modal panel page, add something similar to ${"#mySubmit").click(myCloseModalFunction). It should keep Wicket default's behavior and add modal closing in the mix.
The other way is to override the getOnClickScript(...) method but the javascript has to return true in order for the browser to call the continue link evaluation and load the corresponding href. If you return false, the evaluation stops. I would suggest something like
#Override
protected CharSequence getOnClickScript(CharSequence url) {
return "closeDownloadDialog();return true;";
}
Hope it helps...
See https://cwiki.apache.org/WICKET/ajax-update-and-file-download-in-one-blow.html for inspiration.
I have been working with a Java applet which is an applet that helps to write using only a mouse. For my case, I am trying to incorporate this into my webiste project as follows:
When the user clicks on any input element (textbox/textarea) on the page, this JAVA applet loads on the webpage itself. In the screenshot of the JAVA applet seen below, the user points to an alphabet to and the corresponding text gets written in the text box of the applet.
Now what I am trying to do is to get this text from the TextBox of the applet to the input element on the webpage. I know that this needs an interaction between the Java and JavaScript, but not being a pro, I really do not have the catch. Here's the Java applet and the code I have written.
Java applet and jQuery code (298kB): http://bit.ly/jItN9m
Please could somebdoy help for extending this code.
Thanks a lot!
Update
I searched somewhere and found this -> To get the text inside of Java text box, a getter method in the Applet to retrieve the text:
public class MyApplet extends JApplet {
// ...
public String getTextBoxText() { return myTextBox.getText(); }
}
In the JQuery code, the following lines are to be added I think:
var textBoxText = $("#applet-id")[0].getTextBoxText();
//Now do something with the text
For the code of the applet, I saw a GNOME git page here. The getText call already exists -- look at the bottom of this file: http://git.gnome.org/browse/dasher/tree/java/dasher/applet/JDasherApplet.java
I'd need to call 'getCurrentEditBoxText' but when should this method 'getCurrentEditBoxText' be called?
In my case, I would probably have to do it when the user clicks in a new input control etc.
You can have full communication between your Applet and any javascript method on the page. Kyle has a good post demonstrating how the Javascript can call the applet and request the text value. However, I presume you want the HTML Textfield to update with each mouse click, meaning the applet needs to communicate with the page. I would modify your javascript to something like this:
var activeTextArea = null;
$('textarea, input').click(function() {
$(this).dasher();
activeTextArea = this;
});
function updateText(text) {
// Careful: I think textarea and input have different
// methods for setting the value. Check the
// jQuery documentation
$(activeTextArea).val(text);
}
Assuming you have the source for the applet, you can have it communicate with the above javascript function. Add this import:
import netscape.javascript.JSObject;
And then, in whatever onClick handler you have for the mouse clicks, add:
// After the Applet Text has been updated
JSObject win = null;
try {
win = (JSObject) JSObject.getWindow(Applet.this);
win.call("updateText", new Object[] { textBox.getText() });
} catch (Exception ex) {
// oops
}
That will update the text each time that chunk of code is called. If you do NOT have access to the applet source, things get trickier. You'd need to set some manner of javascript timeout that constantly reads the value from the applet, but this assumes the applet has such a method that returns the value of the textbox.
See Also: http://java.sun.com/products/plugin/1.3/docs/jsobject.html
Update Modifying the applet is your best shot since that is where any event would be triggered. For example, if you want the HTML TextField to change on every click, the click happens in the applet which would need to be modified to trigger the update, as described above. Without modifying the applet, I see two options. Option #1 uses a timer:
var timer;
var activeTextArea;
$('textarea, input').click(function() {
$(this).dasher();
activeTextArea = this;
updateText();
}
function updateText() {
// Same warnings about textarea vs. input
$(activeTextArea).val($('#appletId')[0].getCurrentEditBoxText());
timer = setTimeout("updateText()", 50);
}
function stopUpdating() {
clearTimeout(timer);
}
This is similar to the code above except clicking on a text area triggers the looping function updateText() which will set the value of the HTML text field to the value of the Applet text field every 50ms. This will potentially introduce a minor delay between click and update, but it'll be small. You can increase the timer frequency, but that will add a performance drain. I don't see where you've 'hidden' the applet, but that same function should call stopUpdating so that we are no longer trying to contact a hidden applet.
Option #2 (not coded)
I would be to try and capture the click in the Applet as it bubbles through the HTML Dom. Then, you could skip the timer and put a click() behavior on the Applet container to do the same update. I'm not sure if such events bubble, though, so not sure if this would work. Even if it did, I'm not sure how compatible it would be across browsers.
Option #3
Third option is to not update the HTML text field on every click. This would simply be a combination of Kyle's and my posts above to set the value of the text field whenever you 'finish' with the applet.
Here's a possible solution. To get the text inside of your Java text box, write a getter method in the Applet to retrieve the text:
public class MyApplet extends JApplet {
// ...
public String getTextBoxText() { return myTextBox.getText(); }
}
In your JQuery code, add the following lines:
var textBoxText = $("#applet-id")[0].getTextBoxText();
//Now do something with the text
I found most of what I posted above here. Hope this helps.
This page explains how to manipulate DOM from a Java applet. To find the input element, simply call the document.getElementById(id) function with id of an id attribute of the text input box.
Hy,
I want to display a certain part (a div for example) of my wicket-template only under a certain condition (for example only if I have the data to fill it). The problem is:
If I only add the panel (filling the div) if I got the data, an exception is thrown every time I call the page without the data (because the referenced wicket-id is not added to the component-tree).
The only solution which came to my mind was to add a empty panel if there is no data. This is not an ideal solution because I got some unneeded code in the java-code and many empty divs in my rendered html.
So is there a better solution to include several parts of a wicket-template only under a condition?
Although this is an old question here could be one more solution: wicket:enclosure (and this )
Update: Now I needed this functionality by my self (for jetwick). I'm using WebMarkupContainer one for loggedIn state and one for loggedOut state and set the right visibility:
if (loggedIn()) {
WebMarkupContainer loggedInContainer = new WebMarkupContainer("loggedIn");
//## do something with the user
User user = getUserSomeWhere();
loggedInContainer.add(new UserSearchLink("userSearchLink"));
add(loggedInContainer);
add(WebMarkupContainer("loggedOut").setVisible(false));
} else {
add(new WebMarkupContainer("loggedIn").setVisible(false));
WebMarkupContainer loggedOutContainer = WebMarkupContainer("loggedOut");
loggedOutContainer.add(new LoginLink() {...});
add(loggedOutContainer);
}
The advantage of this for me is that I prevent a NullpointerExc in the //## marked line and the enclose feature of wicket would look more ugly to me in this case I think.
Like #miaubiz said, you can call setVisible(false), or you can override the isVisible() method, if the visibility is conditional to some other state (fields filled, for example).
Yup, you want to override isVisible. This will keep the isVisible=false html markup from even rendering to the final html page. Also, according to the docs (mentioned in EmptyPanel), you can use the WebMarkupContainer as the wrapping component.
this.add(new SimpleResourceModelLabel(NO_DATA_LABEL){
private static final long serialVersionUID = 1L;
#Override
public boolean isVisible() { return myList.isEmpty(); }
});
final WebMarkupContainer table = new WebMarkupContainer(MY_DATA_TABLE){
private static final long serialVersionUID = 1L;
#Override
public boolean isVisible() { return !myList.isEmpty(); }
};
I guess this is why there's EmptyPanel. Without knowing about your code more I can only say that what I think you're doing is something I'd do with combination of some child of AbstractRepeater and Fragment. If you're willing to tell more about what you want to do and maybe provide some code too, I'll be happy to help as much as I can.
you can call setVisible(false); on the component you want to hide.