change moved widget on drop with gwt-dnd 3.3.0 - gwt

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 {
...
}
});

Related

CellTable click swallowed

I've an combo box which is composed of a text field and a popup with a CellTable showing the suggestion items. The text field has a change handler that updates the CellTable's selection.
When typing a character and clicking an already selected suggestion, the first click is swallowed. The second click works and triggers the selection via the CellTable.addDomHandler(...).
Any idea why first click is swallowed?
Example code:
private static class SuggestFieldTextAndPopupSandbox extends SimplePanel {
private final TextField mText;
private CellTable<Handle<String>> mTable;
private SingleSelectionModel<Handle<String>> mTableSelection;
private SingleSelectionModel<Handle<String>> mSelection;
private ProvidesKey<Handle<String>> mKeyProvider = new SimpleKeyProvider<Handle<String>>();
private PopupPanel mPopup;
private List<Handle<String>> mData;
public SuggestFieldTextAndPopupSandbox() {
mData = Lists.newArrayList(new Handle<String>("AAA"), new Handle<String>("AAB"), new Handle<String>("ABB"));
mSelection = new SingleSelectionModel<Handle<String>>();
mText = new TextField();
mText.addKeyPressHandler(new KeyPressHandler() {
#Override
public void onKeyPress(KeyPressEvent pEvent) {
mPopup.showRelativeTo(mText);
}
});
mText.addBlurHandler(new BlurHandler() {
#Override
public void onBlur(BlurEvent pEvent) {
mTableSelection.setSelected(startsWith(mText.getValue()), true);
}
});
mText.addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent pEvent) {
mText.setText(mText.getText().toUpperCase());
}
});
mTable = new CellTable<Handle<String>>(0, GWT.<TableResources>create(TableResources.class));
mTable.setTableLayoutFixed(false);
mTableSelection = new SingleSelectionModel<Handle<String>>(mKeyProvider);
mTable.setSelectionModel(mTableSelection);
mTable.addDomHandler(new ClickHandler() {
#Override
public void onClick(final ClickEvent pEvent) {
Scheduler.get().scheduleFinally(new ScheduledCommand() {
#Override
public void execute() {
mSelection.setSelected(mTableSelection.getSelectedObject(), true);
mText.setFocus(true);
mPopup.hide();
}
});
}
}, ClickEvent.getType());
mTable.addColumn(new TextColumn<Handle<String>>() {
#Override
public String getValue(Handle<String> pObject) {
return pObject.get();
}
});
mTable.setRowData(mData);
mPopup = new PopupPanel();
mPopup.setAutoHideEnabled(true);
mPopup.setWidget(mTable);
mPopup.setWidth("200px");
mPopup.setHeight("200px");
VerticalPanel p = new VerticalPanel();
p.add(mText);
setWidget(p);
}
private Handle<String> startsWith(final String pValue) {
final String val = nullToEmpty(pValue).toLowerCase();
int i = 0;
for (Handle<String> item : mData) {
String value = item.get();
if (value != null && value.toLowerCase().startsWith(val)) {
return item;
}
i++;
}
return null;
}
}
I reproduced your issue and here is the problem:
when you click on the suggestions the following is happening:
The text field is loosing focus which causes the corresponding ChangeEvent to be dealt with followed by the BlurEvent.
The click causes the popup to get the focus now which is why it is swallowed.
If you remove the ChangeHandler and the BlurHandler of the text field the issue disappears. But I think I found another solution
Try replacing the DOM handler of the mTable with a selection handler relative to the mTableSelection as follows:
mTableSelection.addSelectionChangeHandler(new Handler(){
#Override
public void onSelectionChange(SelectionChangeEvent event) {
Scheduler.get().scheduleFinally(new ScheduledCommand() {
#Override
public void execute() {
mSelection.setSelected(mTableSelection.getSelectedObject(), true);
mText.setFocus(true);
mPopup.hide();
}
});
}
});
Found a way how to properly solve this.
Skipping the blur handler when user hovers the suggestion list area seemed to fix that issue, at least from the tests that were done didn't see any more issues.
This was necessary because just before the user clicks a suggestion item, the text is blurred and it fires a selection change. This in turn cancels the selection made when user clicks an item.

style for GXT menu button

I see GXT Menu can only be set on CellButtonBase subclasses' instances through setMenu() method.
I'd like to show an image instead of a button and show a menu when user clicks that image. unfortunately, Image is not a subclass of CellButtonBase and thus I can't attach a GXT Menu to it.
so how can I make TextButton (which seems to be my only choice here) look like an image if I have to use it?
There's no documentation or examples on this subject. I asked on Sencha GXT forum support, but got no response.
ok, I found a way to do this without TextButton. add an Image and call menu.show(...) in click handler.
private void createMenu() {
menu = new Menu();
Image menuButtonImage = new Image(Resources.INSTANCE.nav_preferences());
menuButtonImage.addStyleName(CSS.header_bar_icon());
menuButtonImage.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
menu.showAt(getAbsoluteLeft(), getAbsoluteTop() + MENU_OFFSET_FROM_IMAGE_TOP);
}
});
menu.addShowHandler(new ShowEvent.ShowHandler() {
#Override
public void onShow(ShowEvent event) {
highlight();
}
});
menu.addHideHandler(new HideEvent.HideHandler() {
#Override
public void onHide(HideEvent event) {
removeHighlight();
}
});
menu.setStyleName(CSS.menu());
add(menuButtonImage);
}
private void addUserSettings() {
MenuItem userSettingsItem = new MenuItem("User Settings");
userSettingsItem.addSelectionHandler(new SelectionHandler<Item>() {
#Override
public void onSelection(SelectionEvent<Item> event) {
_coreLayout.showUserSettingsPage();
}
});
userSettingsItem.setStyleName(CSS.menu_item());
menu.add(userSettingsItem);
}
private void highlight() {
addStyleName(CSS.header_bar_icon_box_selected());
}
private void removeHighlight() {
removeStyleName(CSS.header_bar_icon_box_selected());
}

GWT: How to disable the anchor link event when clicked

I want to disable the anchor link event when it clicked one time. I used anchor.setenabled(false) but nothing happend. When I click the same button again the event e is true. I want false at that time.
public void onCellClick(GridPanel grid, int rowIndex, int colindex,EventObject e)
{
if(rowIndex==0 && colindex==2){
tomcatHandler = "Start";
anchorStart.setEnabled(false);
}else if(rowIndex==0 && colindex==3){
tomcatHandler = "Stop";
****anchorStop.setEnabled(false);
anchorStart.setEnabled(false);
anchorRestart.setEnabled(true);****
}else if(rowIndex==0 &&colindex==4){
tomcatHandler = "Restart";
anchorRestart.setEnabled(false);
}
AdminService.Util.getInstance().tomcat(tomcatHandler,new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
imageChangeEvent(result);
}
#Override
public void onFailure(Throwable caught) {
}
});}
Anchors in GWT have always had a problem with setEnabled() because HTML doesn't support such a property. A quick workaround is to create a new widget that subclasses GWT's Anchor, adding the following override:
#Override
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONDBLCLICK:
case Event.ONFOCUS:
case Event.ONCLICK:
if (!isEnabled()) {
return;
}
break;
}
super.onBrowserEvent(event);
}
This disables the passing of the browser event to GWT's Anchor class (summarily disabling all related handlers) when the link is double clicked, focused or clicked and is in a disabled state.
Source
It doesn't seem to actually disable the anchor, but it does retain the status that has been set with anchor.setEnabled(), so just test that within your handler e.g.
myAnchor.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent evt) {
// write to filter and then call reload
if (((Anchor) evt.getSource()).isEnabled()) {
//do stuff
}
}
});

Gwt form question

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);
}
}

Drag and Drop in GWT using gwt dnd

I have been really struggling to get Drag and Drop working in GWT. Last 3 days, I was trying to create a basic drag and drop application and failed. Currently I can drag it around, but I am unable to drop to any location.
How can we solve it? Do we need to modify onDragEnd - I am under the impression that unless I specifically have to do something, I dont have to? I am quite confused.
Also, how do I limit the drop to any single area? I do understand that we can do it using DropController. But I have defined the panels using UiBinder, so how do I get that panel back to link in the DropController? i.e. RootPanel.get() gives me the basic root panel and not the actual panel I want. I tried RootPanel.get("field-id"), but that is showing null even if that id is available. What am I doing wrong?
The code I have written is as follows:
public class TestPanel extends Composite implements
DragHandler, HasMouseDownHandlers, HasMouseUpHandlers, HasMouseMoveHandlers, HasMouseOutHandlers {
interface Binder extends UiBinder<Widget, TestPanel> { }
private static final Binder binder = GWT.create(Binder.class);
#UiField AbsolutePanel absolutePanel;
private PickupDragController TestDragController;
private Image img = new Image("./testicon.png");
public TestPanel(){
initWidget(binder.createAndBindUi(this));
absolutePanel.add(img);
TestDragController = new PickupDragController(RootPanel.get(), false);
AbsolutePositionDropController dropController = new AbsolutePositionDropController(
RootPanel.get());
TestDragController.registerDropController(dropController);
TestDragController.addDragHandler(this);
TestDragController.makeDraggable(this, getDragHandle());
}
private Widget getDragHandle() {
return img;
}
#Override
public void onDragEnd(DragEndEvent event) { }
#Override
public void onDragStart(DragStartEvent event) { }
#Override
public void onPreviewDragEnd(DragEndEvent event) throws VetoDragException { }
#Override
public void onPreviewDragStart(DragStartEvent event) throws VetoDragException { }
#Override
public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
return addDomHandler(handler, MouseDownEvent.getType());
}
#Override
public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
return addDomHandler(handler, MouseUpEvent.getType());
}
#Override
public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
return addDomHandler(handler, MouseMoveEvent.getType());
}
#Override
public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
return addDomHandler(handler, MouseOutEvent.getType());
}
}
and the testpanel uibinder looks like the following:
<g:AbsolutePanel ui:field="absolutePanel" styleName="{style.panel}">
</g:AbsolutePanel>
If somebody can help me out, I will be very much obliged.
K
P.S: To explain more: I was able to solve the first question by updating onDragEnd as the following:
#Override
public void onDragEnd(DragEndEvent event) {
DragContext context = event.getContext();
RootPanel.get().add(context.draggable, context.desiredDraggableX, context.desiredDraggableY);
}
but, I am not sure whether this is the correct solution - since I think I should not be doing the positioning myself.
If you're new to GWT dnd, why don't you try the working demo ?
There is a lot of examples and all the source code is available.
(And no, you're not supposed to do the positionning yourself)
You have to add a DragOverHandler on the drop target(s): even if it does nothing, it defines the component as a drop target.
Of course, you still need to define the DropHandler too on this component (and optionally, DragEnterHandler and DragLeaveHandler for visual feedback, in general).
The DragEndHandler is called even if the target isn't reached (drag abandoned in a non-drop area), it is used to change the state of the dragged object, you might need to set a way for the DropHandler to communicate success on dropping to the DragEndHandler (shared variable, EventBus, etc.).