3rd party GUI w/ jME

Wow, you guys are rabid for this.  I have the supporting code written up already.

I'll try and get it put together tonight and added to the tutorials on the wiki.

Whackjack said:

@Todi: I haven't tried it myself, but there are classes in there that are supposed to support DnD.

I had a short look and saw those too, but they seem to be related to drag n drop within a container, rather than drag n drop between them ?

That's outside the scope of my FengGUI expertise.  In fact, my FengGUI knowledge is just enough

to make it work pretty well with jME.  No more, no less.  :stuck_out_tongue:

I'll bring it up on the FengGUI mailing list.

First a big thanks to Whackjack for monitoring this forum!


I had a short look and saw those too, but they seem to be related to drag n drop within a container, rather than drag n drop between them ?



The DnD capabilities of FengGUI are not confined to containers only. You can use them with every widget. However, DnD is not very easy as it requires to register a DnDListener globally in the Display instance and several things you need to consider when implementing DnDListener. I added an entry in the table of contents of our user guide as a reminder to write a tutorial about drag and drop. As a first aid you can check out the following code which I extracted from org.fenggui.composites.Window. It is used to drag the windows around (when clicked on the title bar).



   class WindowDnDListenerImpl implements IDragAndDropListener
   {
      int oldX = 0;
      int oldY = 0;
      
      public void select(int x, int y)
      {
         oldX = x;
         oldY = y;
      }

      public void drag(int x, int y)
      {
         move(x-oldX, y-oldY); // moves the window arround (the method 'move' is not visible in his example)
         oldX = x;
         oldY = y;
      }

      public void drop(int x, int y, Widget dropOn)
      {
// we don't need to handle the actual drop message as we always update the window's position when it is dragged around.
      }

            // Returns true if w trigger the DnD
      public boolean isDndWidget(Widget w, int x, int y)
      {
         // A window can be dragged around by clicking on the title bar:
         return w.equals(title) || w.equals(titleBar);
                        // however, the content of the window is not supposed to trigger the DnD routine!
      }
   }



I hope this helps. If not feel free to write me a mail (johannes.schaback at gmail dot com).

As for the performance... well, FengGUI is designed to render widgets as fast as OpenGL allows. However at the current state of development we are more focusing on robustness than on speed. FengGUI is making several redundant state changes, it is not using display lists, etc. etc. We will optimize that in the future of course, but we do not start working on that before FengGUI is feature complete (= to contain all standard widgets, not some fancy stuff like animated textures or so). Thus, you can expect FengGUI to become faster in spring '07. However, I believe FengGUI is already faster than Swing being rendered on a texture such that it makes sense to use FengGUI at this state of development.

Big steps ahead in the near future are expected to be the XML streaming stuff that allows to describe GUIs in XML and to serialize them to XML (binary serialization for transfor over the network will be possible as well). Also, I just added the tree widget and I am currently working on tab containers.

Johannes

Thanks for the reply, i will have a look during this week and try some code if i can. I try to implement an inventory and allow for drag and drop of components (icons) between "bags"

I try to implement an inventory and allow for drag and drop of components (icons) between "bags"


Ah, that sounds cool. And yes it is possible. Let me know if you have difficulties.

Hmm ,

ok i have been playing around a bit.

Rudimentary it works, but i have trouble especially with multiple windows. I guess its something "obvious" again (my usual problem while programming).

Here is the code if you want to have a look. Might be worth to add this as an example later.

Problem description:

  1. When dragging and dropping it sometimes happens that the droppedon target receives the message and displays a "dropped" but the original Button where i started the drag is still in existence directly at the spot where i dropped it.
  2. When using multiple windows AFTER the drag (everything seems fine at that moment), when i open another dndexample suddenly the (some) buttons are displayed again.
  3. Havent found a way yet to get the image of a button directly to create a cursor
  4. TODO: include that in a JME Game



package org.fenggui.example;

import org.fenggui.Button;
import org.fenggui.Display;
import org.fenggui.Widget;
import org.fenggui.composites.Window;
import org.fenggui.event.IDragAndDropListener;
import org.fenggui.layout.RowLayout;
import org.fenggui.layout.StaticLayout;
import org.fenggui.render.Binding;


public class DNDExample implements IExample {

  private Window filesFrame = null;
  private Display desk;

  public void buildGUI(Display d) {
    desk = d;

    filesFrame = new Window(true, false, false);
    desk.addWidget(filesFrame);
    filesFrame.setX(50);
    filesFrame.setY(50);
    filesFrame.setSize(300, 100);
    filesFrame.setTitle("DND");

    filesFrame.getContentContainer().setLayoutManager(new RowLayout(false));

    final Button label = new Button("Please move me ...!");
    // label.get
    desk.addDndListener(new ButtonDNDListener());
    filesFrame.getContentContainer().addWidget(label);
 
    final Button label2 = new Button("...here");
    filesFrame.getContentContainer().addWidget(label2);

    desk.layout();

    StaticLayout.center(filesFrame, desk);

  }

  public String getExampleName() {
    return "DND Example";
  }

  public String getExampleDescription() {
    return "Demonstrates a DND";
  }

  class ButtonDNDListener implements IDragAndDropListener {
    private Button startButton;
   // private Background background;

    int oldX = 0;
    int oldY = 0;
    int startX = 0;
    int startY = 0;

    public void select(int x, int y) {
      startButton.setText("selected");
      oldX = x;
      oldY = y;
      startX = startButton.getX();
      startY = startButton.getY();
      Binding.getInstance().getCursorFactory().getHandCursor().show();
    }

    public void drag(int x, int y) {
      startButton.move(x - oldX, y - oldY);
      oldX = x;
      oldY = y;
    }

    public void drop(int x, int y, Widget dropOn) {
      System.out.println("dropped");
      System.out.println("x,y"+x+","+y);
      if (dropOn instanceof Button && (!dropOn.equals(startButton))) {
        ((Button) dropOn).setText("Dropped");
//        Iterable<Widget> widgets = desk.getWidgets();
//        for (Widget widget : widgets) {
//          if (widget instanceof Window) {
//            ((Window)widget).removeWidget(startButton);
//          }
//        }
        filesFrame.getContentContainer().removeWidget(startButton);
        Binding.getInstance().getCursorFactory().getDefaultCursor().show();
      } else {
        System.out.println("moving back to origin");
        startButton.setXY(startX, startY);
      }
    }

    // Returns true if w trigger the DnD
    public boolean isDndWidget(Widget w, int x, int y) {
      System.out.println("isDndWidget");
      if (w instanceof Button) {
        startButton = (Button) w;
        //TODO: how do we get a cursor that corresponds to the image/texture of the button ?
     //   background = startButton.getBackground();
     //   Binding.getInstance().getCursorFactory().createCursor(0,0, );
        return true;
      }
      return false;
    }
  }

}

Ah, great! A DnD Example! Thanks Todi! And of course, sorry for not checking back for about two months  :wink: I will check it out as soon as I am back to work. After resolving the issues I am happy to add it to the FengGUI repository. I keep you posted.



Johannes