Gwt form question - gwt

I have a gwt form which has about 70-100 widgets (textboxes,listboxes,custom widgets etc)
I am trying to implement the features of CUT ,COPY in this form .For this i have 2 buttons right on top of the form.
Now the problem i have is that when i click on the copy button , the widget that was focused in the form looses focus and i dont know which text to copy(or which widget was last focused before the focus getting to the copy button)
I was planning to implement blur handlers on all the widgets but i feel is a very laborious and not a good solution.
How can i get around this issue?
Thanks

Perhaps someone with a deeper insight might provide a better approach but I beleive adding blur handlers is perfectly valid. I do not quite see why you think it would be laborious, after all you don't need a different handler for each of your widgets, you can get away with only one(at most a couple for a variety of controls..), here is a very simple example,
public class CustomBlurHandler implements BlurHandler{
Object lastSource;
String text;
#Override
public void onBlur(BlurEvent event) {
if (event.getSource() instanceof TextBox) {
lastSource = event.getSource();
text = textBox.getSelectedText();
}
}
public Object getLastSource() {
return lastSource;
}
public String getText() {
return text;
}
}
and onModuleLoad :
public class Test implements EntryPoint {
CustomBlurHandler handler = new CustomBlurHandler();
public void onModuleLoad() {
TextBox text1 = new TextBox();
TextBox text2 = new TextBox();
text1.addBlurHandler(handler);
text2.addBlurHandler(handler);
Button b = new Button("Get last selected text");
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert(handler.getLastSource()+ " " + handler.getText());
}
});
RootPanel.get().add(text1);
RootPanel.get().add(text2);
RootPanel.get().add(b);
}
}

Related

change moved widget on drop with gwt-dnd 3.3.0

situation
I'm writing a admintool to change a GWT based GUI via Browser.
I want the Admin to use drag and drop to create and change the GUI.
To realize the dnd I use gwt-dnd 3.3.0
I have a toolbar in my admintool, from which I can drag the different objects.
Every object in the toolbar is a plain HTML widget with text inside.
I would like to change the Widget when it is droped.It should change from the HTML widget to the original widget I like to use.
problem & tried solution
At the moment I can change the widget on Drop, then it throws an exception and the "moving widget" don't get removed from the page. The "moving widget" is still dragable and shows the "move designe"
I think this happens, because the Drag or Drophandler do not know the moving widget, because i changed the drop widget...
Here is the code:
dragController.addDragHandler(new DragHandler(){
public void onDragEnd(DragEndEvent event) {
...
}
public void onDragStart(DragStartEvent event) {
...
}
public void onPreviewDragEnd(DragEndEvent event)
throws VetoDragException {
final DragContext mycontent = event.getContext();
List<Widget> mywl = mycontent.selectedWidgets;
for(int i = 0; i < mywl.size(); i++)
{
String stemp = ((HTML)mywl.get(i)).getText();
if(stemp.contains("Container")&&!stemp.contains("SubContainer"))
{
FlowPanel mypanel = new FlowPanel();
HTML htmltemp = new HTML("Label");
htmltemp.setStyleName("edit-dndcontainer");
mypanel.add(htmltemp);
mypanel.setStyleName("edit-dndcontainer");
mywl.add(i, mypanel);
dragController.makeDraggable(mypanel);
mywl.get(i).removeFromParent();
mywl.remove(i+1);
mycontent.selectedWidgets = mywl;
}
else if(stemp.contains("Label"))
{
...
}
else
{
...
throw new VetoDragException();
}
}
}
public void onPreviewDragStart(DragStartEvent event)
throws VetoDragException
{
...
}
});
question
Is gwt-dnd the correct lib to use for this behaviour, or should I use native dnd of GWT?
How can I change the dnd-widget on drop with gwt-dnd?
Thanks for your help
My approach was not that bad, but instead of working with the DragContext, I have to work with the getSelectedWidgets().iterator() from the DragController.
edit
I switched my code to onDragEnd(), in this case I don't screw up the moving widget. And I changed the Draggable widget to a Panel. I just have to add and remove widgets from it.
answer
Samplecode:
dragController.addDragHandler(new DragHandler(){
public void onDragEnd(DragEndEvent event) {
Iterable<Widget> myiterable = myDragCTRL_subcont.getSelectedWidgets();
Widget mywidget = myiterable.iterator().next();
FlowPanel flowtemp = ((FlowPanel)mywidget);
flowtemp.add(new HTML("label"));
...
...
}
public void onDragStart(DragStartEvent event) {
...
}
public void onPreviewDragEnd(DragEndEvent event)
throws VetoDragException {
...
}
public void onPreviewDragStart(DragStartEvent event)
throws VetoDragException {
...
}
});

How to programmatically open a gwt listbox?

I have a user form with a lot of gwt listbox. The form is like an excel form with named list.
It's ugly and the arrows take place.
I would like the cells were like in excel. The arrow appears only when you click in the cell.
I start to program my own widget with a textbox and a listbox embedded into a DeckPanel, switching when you click on the textbox or when the value change. But with this solution, it is necessary to click again to open the listbox.
Now, it will be great, if when you click on the textbox, the listbox will be displayed already open.
In the code below, I try to do this into the method onClick wih this line:
DomEvent.fireNativeEvent(event.getNativeEvent(), listBox);
But it has no effects.
public class CustomListBox extends Composite implements ClickHandler,
ChangeHandler, HasChangeHandlers {
private final StringListBox listBox;
private final TextBox textBox;
private final DeckPanel panel;
public CustomListBox() {
textBox = new TextBox();
textBox.addClickHandler(this);
textBox.setReadOnly(true);
listBox = new StringListBox();
listBox.addChangeHandler(this);
panel = new DeckPanel();
panel.add(textBox);
panel.add(listBox);
panel.showWidget(0);
// All composites must call initWidget() in their constructors.
initWidget(panel);
}
#Override
public void onClick(ClickEvent event) {
Object sender = event.getSource();
if (sender == textBox) {
panel.showWidget(1);
DomEvent.fireNativeEvent(event.getNativeEvent(), listBox);
}
}
public void addItem(String item) {
listBox.addItem(item);
}
public int getSelectedIndex() {
return listBox.getSelectedIndex();
}
public String getItemText(int selectedIndex) {
return listBox.getItemText(selectedIndex);
}
#Override
public HandlerRegistration addChangeHandler(ChangeHandler handler) {
return listBox.addChangeHandler(handler);
}
#Override
public void onChange(ChangeEvent event) {
Object sender = event.getSource();
if (sender == listBox) {
textBox.setText(getItemText(getSelectedIndex()));
panel.showWidget(0);
}
}
}
Since you are already programming your own widget, why don't you go all the way. Don't swap out the text box for a list box widget. Instead of a textbox use a label. Add an arrow to your label background when you mouse over, then use a popupPanel for the list itself. In the popupPanel you can make the list items whatever you like, just make sure when you click on it, it sets the text in your original label.

GWT - How to associate a business object to a widget

I'd like a way to easily tie a widget back to the business object it is rendering. So when the user interacts with a widget I can easily determine the business object holding the data for that widget.
For example, if we imagine a calendar widget that we're going to implement with an AbsolutePanel. For each appt object we'll add a label to the calendar. Then when a user clicks on a label he can update the appt. So I need to know which appt object that label refers to.
For instance, if we look at the following code; if the label for an appointment receives a click, how can I find out to which appt it represented ? The only solution I can see is to create a ApptLabel sub-class for Label which would hold a reference to its appt. This is fine, but the example illustrates a more general need which is to associate widgets with data objects; however this would mean that every object that has a presence in a view needs to subclass a widget. that seems heavy - I expected to find something in the framework e.g. a string property in a widget that I can set to an object key
other approaches I tried; maintaining a map of Map -- this didnt work as the label object I create doesnt appear to be the same (in terms of the Object.equals which I guess is what HashMap uses)
class WidgetCalendar extends Composite {
AbsolutePanel m_panel = new AbsolutePanel();
m_panel.setStylePrimaryName("calendar");
m_panel.setPixelSize(width, height);
public WidgetCalendar(ArrayList<BomAppt> appts) {
initWidget(m_panel);
for (BomAppt a : appts) {
Label l = new Label();
l.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// how do I know my BomAppt in here ?
}
m_panel.add(l, someX, someY);
}
}
}
Ideally I can do something like this
class WidgetCalendar extends Composite {
AbsolutePanel m_panel = new AbsolutePanel();
m_panel.setStylePrimaryName("calendar");
m_panel.setPixelSize(width, height);
public WidgetCalendar(ArrayList<BomAppt> appts) {
initWidget(m_panel);
for (BomAppt a : appts) {
Label l = new Label();
l.setItemData(a.getUniqueId());
l.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
BomAppt a = BomAppt.getApptWithId(e.getItemData())
}
}
m_panel.add(l, someX, someY);
}
}
}
This is the solution where I create a subclass, this seems heavy to me and I'd prefer something simpler
class ApptLabel extends Label {
public ApptLabel(BomAppt a) {
m_a = a;
this.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
m_a.doSomething();
});
}
BomAppt m_a;
}
class WidgetCalendar extends Composite {
AbsolutePanel m_panel = new AbsolutePanel();
m_panel.setStylePrimaryName("calendar");
m_panel.setPixelSize(width, height);
public WidgetCalendar(ArrayList<BomAppt> appts) {
initWidget(m_panel);
for (BomAppt a : appts) {
BomLabel l = new BomLabel();
l.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// how do I know my BomAppt in here ?
}
m_panel.add(l, someX, someY);
}
}
}
For instance, if we look at the following code; if the label for an
appointment receives a click, how can I find out to which appt it
represented ?
By using Composite pattern you can find out which widget was clicked, initially you should create your own custom Appointment widget which is responsible for drawing one appointment. And in you Appointment widget you can have a set of other widgets, in your case, for Label add click handler. Once user clicks that label, you can execute business logic with its data and you can represent data.
public class Appointment extends Composite {
private AppointmentDetails data;
public Appointment(AppointmentDetails data){
draw(data);
}
private void draw(AppointmentDetails data){
Label label = new Label();
label.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// do your business logic with this AppointmentDetails
}
});
}
}
After that you should have one Calendar widget which contains several Appointments.
Keep in your mind: your classes each serve a single, very clearly defined purpose, separated from other classes with other clearly defined purposes.

GWT Tab panel close

I am building an application in GWT. I have a decorated tabpanel in
my application.Where in am adding panels to it dynamically.Now i want
to achieve the closing of these tabs. I want to add a close image to
the tab bar and event to that image for closing. I am using UIbinder.
the working code is like that;
private Widget getTabTitle(final Widget widget, final String title) {
final HorizontalPanel hPanel = new HorizontalPanel();
final Label label = new Label(title);
DOM.setStyleAttribute(label.getElement(), "whiteSpace", "nowrap");
ImageAnchor closeBtn = new ImageAnchor();
closeBtn.setResource(images.cross());
closeBtn.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
int widgetIndex = tabs.getWidgetIndex(widget);
if (widgetIndex == tabs.getSelectedIndex()) {
tabs.selectTab(widgetIndex - 1);
}
tabs.remove(widgetIndex);
}
});
hPanel.add(label);
hPanel.add(new HTML("&nbsp&nbsp&nbsp"));
hPanel.add(closeBtn);
hPanel.setStyleName("gwt-TabLayoutPanelTab");
return hPanel;
}
In order to add tab,
public void addTab() {
TabWriting tw = new TabWriting(); /* TabWriting in my case, this can be any widget */
tabs.add(tw, getTabTitle(tw, "Writing"));
tabs.selectTab(tw);
}
You'll going to need, ImageAnchorClass
public class ImageAnchor extends Anchor {
public ImageAnchor() {
}
public void setResource(ImageResource imageResource) {
Image img = new Image(imageResource);
img.setStyleName("navbarimg");
DOM.insertBefore(getElement(), img.getElement(), DOM
.getFirstChild(getElement()));
}}
It isn't supported natively in GWT.
You can manually try to add it.
Read this - http://groups.google.com/group/google-web-toolkit/browse_thread/thread/006bc886c1ccf5e1?pli=1
I haven't tried it personally, but look at the solution by gregor (last one).
You kinda need to do something along the lines of this
GWT Close button in title bar of DialogBox
First you need to pass in the tab header when you create the new tab. The header you pass in should have your tab text and also an X image or text label to click on. Then add a event handler on the close object that gets the widget you are adding to the tabPanel and removes it. Here is some inline code that works
public void loadTab(final Widget widget, String headingText, String tooltip) {
HorizontalPanel panel = new HorizontalPanel();
panel.setStyleName("tabHeader");
panel.setTitle(tooltip);
Label text = new Label();
text.setText(headingText);
text.setStyleDependentName("text", true);
Label close = new Label();
close.setText("X");
close.setTitle(closeText_ + headingText);
text.setStyleDependentName("close", true);
close.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("close this tab");
ClientGlobal.LOG.info("widget : " + tabPanel_.getWidgetIndex(widget));
tabPanel_.remove(tabPanel_.getWidgetIndex(widget));
}
});
panel.add(text);
panel.add(close);
panel.setCellHorizontalAlignment(text, HasHorizontalAlignment.ALIGN_LEFT);
panel.setCellHorizontalAlignment(close, HasHorizontalAlignment.ALIGN_RIGHT);
tabPanel_.add(widget, panel);
tabPanel_.getTabWidget(widget).setTitle(tooltip);
tabPanel_.selectTab(widget);
}

DialogBox in GWT isn't draggable or centred

I'm new to GWT programming. So far I have a DialogBox which is supposed to collect a login and a password, which can if required launch another DialogBox that allows someone to create a new account.
The first of these two DialogBoxes always appears at the top left of the browser screen, and can't be dragged, although part of the definition of a DialogBox is that it can be dragged. However, the second DialogBox can be dragged about the screen without any problem.
What I'd really like is for the first DialogBox to appear in the middle of the screen & be draggable, both of which I thought would happen automatically, but there's not.
So, what things can stop a DialogBox from being draggable? There is nothing on the RootPanel yet. Does that make a difference?
Code fragments available if they help, but perhaps this general outline is enough for some pointers.
Thanks
Neil
Use dialogBox.center() This will center your DialogBox in the middle of the screen. Normally a DialogBox is by default draggable.
Just tried it out and it doens't matter if your RootPanel is empty our not. When I just show the DialogBox on ModuleLoad it is draggable and it is centered. Probably the problem is situated somewhere else.
This is the example of google itself:
public class DialogBoxExample implements EntryPoint, ClickListener {
private static class MyDialog extends DialogBox {
public MyDialog() {
// Set the dialog box's caption.
setText("My First Dialog");
// DialogBox is a SimplePanel, so you have to set its widget property to
// whatever you want its contents to be.
Button ok = new Button("OK");
ok.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
MyDialog.this.hide();
}
});
setWidget(ok);
}
}
public void onModuleLoad() {
Button b = new Button("Click me");
b.addClickListener(this);
RootPanel.get().add(b);
}
public void onClick(Widget sender) {
// Instantiate the dialog box and show it.
new MyDialog().show();
}
}
Here more information about the DialogBox.
Without seeing any of your code it's hard to tell what's going wrong. The following code works for me (ignore the missing styling...):
public void onModuleLoad() {
FlowPanel login = new FlowPanel();
Button create = new Button("create");
login.add(new TextBox());
login.add(new TextBox());
login.add(create);
create.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
final DialogBox box = new DialogBox();
FlowPanel panel = new FlowPanel();
Button close = new Button("close");
close.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
box.hide();
}
});
panel.add(new Label("some content"));
panel.add(close);
box.setWidget(panel);
box.center();
}
});
DialogBox firstBox = new DialogBox(false, true);
firstBox.setWidget(login);
firstBox.center();
}
Both boxes are draggable and shown in the center of your browser window.
Looks like you're overriding this method in Widget:
public void fireEvent(GwtEvent<?> event) {
if (handlerManager != null) {
handlerManager.fireEvent(event);
}
}
In Widget, handlerManager refers to a private HandlerManager.
Either add super.fireEvent(event) to your method or as you have done rename it.
Well, with vast amounts of trial and error I have found the problem, which was just this: I had a method in an object I'd based on DialogBox called fireEvent, which looked like this:
public void fireEvent(GwtEvent<?> event)
{
handlerManager.fireEvent(event);
}
Then, when a button was clicked on the DialogBox, an event would be created and sent off to the handlerManager to be fired properly.
And it turns out that if I change it to this (LoginEvent is a custom-built event):
public void fireEvent(LoginEvent event)
{
handlerManager.fireEvent(event);
}
... or to this ....
public void fireAnEvent(GwtEvent<?> event)
{
handlerManager.fireEvent(event);
}
the DialogBox is draggable. However, if the method begins with the line
public void fireEvent(GwtEvent<?> event)
then the result is a DialogBox which can't be dragged.
I'm a bit unsettled by this, because I can't fathom a reason why my choice of name of a method should affect the draggability of a DialogBox, or why using a base class (GwtEvent) instead of a custom class that extends it should affect the draggability. And I suspect there are dozens of similar pitfalls for a naive novice like me.
(Expecting the DialogBox to centre itself was simply my mistake.)