1. #1
    Ext GWT Premium Member
    Join Date
    Jan 2009
    Location
    Colorado Springs, CO
    Posts
    381
    Vote Rating
    5
    DavidHoffer is on a distinguished road

      0  

    Question GXT & gwt-dnd

    GXT & gwt-dnd


    I'm trying to use GXT with gwt-dnd because I need to perform some custom DnD behavior. I'm using the GXT Window as my DnD widget and for some reason this fails to call the onMove() method on the AbstractPositioningDropController, if I switch to a GWT widget like HTML then it works correctly.

    Perhaps I can do this with just GXT DnD I'm not sure...I need to allow DnD on a specified grid pattern where each Window can be the size of one or more grid cells.

    Anyone have any ideas why the GXT Window doesn't work with gwt-dnd or know how to do this with just GXT?

  2. #2
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,734
    Vote Rating
    90
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      0  

    Default


    I've always implemented custom DnD behavior with GXT using either the events available from the components (the Window class has a getDraggable() to get access to the events), or by extending Draggable or the DragSource/DropTarget classes.

    Window's own setDraggable code might be interfering with the events from being consumed by gwt-dnd - if you must use gwt-dnd, make sure that you call setDraggable(false) on the window instance.

  3. #3
    Ext GWT Premium Member
    Join Date
    Jan 2009
    Location
    Colorado Springs, CO
    Posts
    381
    Vote Rating
    5
    DavidHoffer is on a distinguished road

      0  

    Default


    Do you have some examples of extending DragSource/DropTarget you could send?

    I'm trying to use this but it isn't working right for some reason, I'm following the code in the online examples. However the DragSource's onDragStart() gets fired but the DropTarget's onDragDrop() generally does not...I say generally a few times it did but I have yet to figure out why it fired a couple times. In the examples they use simple HTML widgets, I have complex objects such as Windows I am drag and dropping. Also how to set the allow drop status?

    Most examples I find online are for 2.x which are different. If someone has 3.x examples that would be great.

  4. #4
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,734
    Vote Rating
    90
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      0  

    Default


    The DnD code hasn't changed significantly in 3, so examples should still be relevant.

    Perhaps instead of my building/pointing to examples of how to do it, you can share what you have so far, and what it does or doesn't do - with regard to having onDragDrop called, it will only be called if the status is set to true, and there is currently a DropTarget active (i.e. about to be dropped on).

    If you are building some kind of tiling window manager, you'll probably want the DragSource/DropTarget classes. If you just need to track/change window sizes/positions, the window.getDraggable() should expose most of what you need. Again, a clearer description of what you are after, what you've tried will help to assist further.

  5. #5
    Ext GWT Premium Member
    Join Date
    Jan 2009
    Location
    Colorado Springs, CO
    Posts
    381
    Vote Rating
    5
    DavidHoffer is on a distinguished road

      0  

    Question


    I found that in 3.x several of the 2.x types don't exist anymore.. In any case here is an example of the code. What is happening is that I can drag and drop the Windows in the GridPanel however GridPanelDropTarget#onDragDrop() is not being called and I need it to because I want to control the drop location. Also while being dragged it shows the red circle so I assume that is why GridPanelDropTarget#onDragDrop() is not being called but I don't know how to control when and what is drag and dropable.

    Also what is happening now is that the contents of the Windows are also drag and dropable and it does show the green checkbox indicating that it is drag and dropable but I don't want it to be, nothing in the Window should have DnD enabled but it currently does. Again I'm not understanding how to control what and when items are drag and dropable.

    Code:
    public class GridPanelDropTarget extends DropTarget {
    
        private int standardConversationX;
        private int standardConversationY;
        private final AbsolutePanel gridPanel;
    
        public GridPanelDropTarget(AbsolutePanel gridPanel) {
            super(gridPanel);
            this.gridPanel = gridPanel;
    
            setGroup("grid");
            setOverStyle("drag-ok");
        }
    
        @Override
        protected void onDragDrop(DndDropEvent event) {
            super.onDragDrop(event);
            Window window = (Window) event.getData();
    
            Point location = calculateClosestDropLocation(window);
            gridPanel.add(window, location.getX(), location.getY());
        }
    
        public void setStandardConversationX(int standardConversationX) {
            this.standardConversationX = standardConversationX;
        }
    
        public void setStandardConversationY(int standardConversationY) {
            this.standardConversationY = standardConversationY;
        }
    
        private Point calculateClosestDropLocation(Widget target) {
    
            if (standardConversationX == 0 || standardConversationY == 0){
                throw new IllegalStateException("must set x & y");
            }
    
            final int absoluteLeft = target.getAbsoluteLeft();
            final int absoluteTop = target.getAbsoluteTop();
    
            int x = (int) Math.round((double) absoluteLeft / (double) standardConversationX) * standardConversationX;
            int y = (int) Math.round((double) absoluteTop / (double) standardConversationY) * standardConversationY;
    
            return new Point(x, y);
        }
    }
    
    public class GridPanelDragSource extends DragSource {
    
        private final Window window;
    
        public GridPanelDragSource(Window window) {
            super(window);
            this.window = window;
    
            setGroup("grid");
        }
    
        protected void onDragStart(DndDragStartEvent event) {
            super.onDragStart(event);
    
            event.setData(window);
        }
    }
    
    public class GridPanel extends SimplePanel {
        private final Resources resources;
        private final AbsolutePanel gridPanel;
        private static final int MARGIN = 4;
        private GridPanelDropTarget dropTarget;
    
        public GridPanel(Resources resources) {
            this.resources = resources;
    
            // Create a boundary panel to constrain all DnD operations
            gridPanel = new AbsolutePanel();
            gridPanel.setPixelSize(1200, 1200);
    
            dropTarget = new GridPanelDropTarget(gridPanel);
    
            setWidget(gridPanel);
        }
    
        private ContentPanel buildConversationPanel(String title, final int width, final int height) {
            final Window window = new Window();
    
            window.setMinHeight(200);
            window.setMinWidth(200);
            window.setPixelSize(width, height);
            window.setCollapsible(false);
            window.getHeader().setIcon(resources.webtasavailable_24());
            window.setBodyStyleName("pad-text");
            window.setHeadingText(title);
            window.setResize(true);
            window.setClosable(false);
    
            applyHeaderTools(window);
    
            BorderLayoutContainer borderLayoutContainer = new BorderLayoutContainer();
    
            final ListView<String, String> list = getSampleConversation();
            borderLayoutContainer.setCenterWidget(list, new MarginData(0));
    
            final BorderLayoutContainer.BorderLayoutData southLayoutData = new BorderLayoutContainer.BorderLayoutData(30);
            southLayoutData.setMargins(new Margins(0));
            southLayoutData.setCollapsible(true);
            southLayoutData.setSplit(true);
            southLayoutData.setCollapseMini(false);
            borderLayoutContainer.setSouthWidget(buildSendConversationPanel(), southLayoutData);
    
            window.add(borderLayoutContainer, new MarginData(0));
    
            // I want users to be able to drag & drop windows by DnD it's title bar.
            DragSource source = new GridPanelDragSource(window);
    
            return window;
        }
    
        public void onInitialLoad() {
    
            int left = 0;
            int top = 0;
    
            final ContentPanel conversationPanel1 = buildConversationPanel("#private", 200, 200);
            PanelDimensions panelDimensions = getActualPanelDimensions(conversationPanel1);
            gridPanel.add(conversationPanel1, left, 0);
    
            dropTarget.setStandardConversationX(panelDimensions.getWidth() + MARGIN);
            dropTarget.setStandardConversationY(panelDimensions.getHeight() + MARGIN);
    
            left += panelDimensions.getWidth() + MARGIN;
            top += panelDimensions.getHeight() + MARGIN;
    
            final ContentPanel conversationPanel2 = buildConversationPanel("bob", 200, 200);
            panelDimensions = getActualPanelDimensions(conversationPanel2);
            gridPanel.add(conversationPanel2, left, 0);
            left += panelDimensions.getWidth() + MARGIN;
    
            final ContentPanel conversationPanel3 = buildConversationPanel("#tom", 400, top + 200);
            gridPanel.add(conversationPanel3, left, 0);
    
            left = 0;
    
            final ContentPanel conversationPanel4 = buildConversationPanel("randy", 200, top + 200);
            panelDimensions = getActualPanelDimensions(conversationPanel4);
            gridPanel.add(conversationPanel4, left, top);
            left += panelDimensions.getWidth() + MARGIN;
    
            final ContentPanel conversationPanel5 = buildConversationPanel("#foo", 200, 200);
            gridPanel.add(conversationPanel5, left, top);
        }
    
        private PanelDimensions getActualPanelDimensions(ContentPanel conversationPanel) {
            RootPanel.get().add(conversationPanel, -500, -500);
            int offsetWidth = conversationPanel.getOffsetWidth();
            int offsetHeight = conversationPanel.getOffsetHeight();
            conversationPanel.removeFromParent();
            return new PanelDimensions(offsetWidth, offsetHeight);
        }
    
        private HBoxLayoutContainer buildSendConversationPanel() {
            final HBoxLayoutContainer sendLayoutContainer = new HBoxLayoutContainer(HBoxLayoutContainer.HBoxLayoutAlign.STRETCH);
            // set content here...
            return sendLayoutContainer;
        }
    
        private void applyHeaderTools(ContentPanel cp1) {
            cp1.getHeader().insertTool(buildCollabButton(), 0);
            cp1.getHeader().insertTool(buildClipboardButton(), 1);
            cp1.getHeader().insertTool(buildSaveButton(), 2);
            cp1.getHeader().insertTool(buildClearButton(), 3);
            cp1.getHeader().insertTool(buildCloseButton(), 4);
        }
    
        private TextButton buildCloseButton() {
            final TextButton close = new TextButton("", resources.close_20());
            close.setPixelSize(24, 24);
            return close;
        }
    
        private TextButton buildClearButton() {
            final TextButton clear = new TextButton("", resources.clearconversation_20());
            clear.setPixelSize(24, 24);
            return clear;
        }
    
        private TextButton buildSaveButton() {
            final TextButton save = new TextButton("", resources.save_20());
            save.setPixelSize(24, 24);
            return save;
        }
    
        private TextButton buildClipboardButton() {
            final TextButton clipboard = new TextButton("", resources.clipboard());
            clipboard.setPixelSize(24, 24);
            return clipboard;
        }
    
        private TextButton buildCollabButton() {
            final TextButton collab = new TextButton("", resources.collab_20());
            collab.setPixelSize(24, 24);
            return collab;
        }
    
        private ListView<String, String> getSampleConversation() {
            final ListStore<String> listStore = new ListStore<String>(new ModelKeyProvider<String>() {
                @Override
                public String getKey(String s) {
                    return "A";
                }
            });
            final ListView<String, String> list = new ListView<String, String>(listStore, new ValueProvider<String, String>() {
                @Override
                public String getValue(String s) {
                    return "(Dec 12 2011) Dave: Conversation log...";
                }
    
                @Override
                public void setValue(String s, String s1) {
                }
    
                @Override
                public String getPath() {
                    return null;
                }
            });
            list.setSelectionModel(null);
    
            listStore.add("A");
            listStore.add("B");
            listStore.add("C");
            listStore.add("D");
            listStore.add("E");
            listStore.add("F");
            listStore.add("G");
            listStore.add("H");
            listStore.add("I");
            listStore.add("J");
            return list;
        }
    }

  6. #6
    Ext GWT Premium Member
    Join Date
    Jan 2009
    Location
    Colorado Springs, CO
    Posts
    381
    Vote Rating
    5
    DavidHoffer is on a distinguished road

      0  

    Default


    Also I should note that if I replace the previous code with just a DragHandler on the Window's Draggable that does work as expected but I don't know if that will be enough because I would like to show a drop target in the UI so users know exactly where the window will be positioned. (With just a DragHandler it just goes to the closest grid cell.)

  7. #7
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,734
    Vote Rating
    90
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      0  

    Default


    GridPanelDropTarget is only present in old versions of GXT 2 that still have the GridPanel, deprecated and replaced by Grid, GridDragSource, GridDropTarget. These types should all be present in GXT 3. Additionally, TreePanel, TreePanelDragSource, TreePanelDropTarget from 2 have been renamed Tree, TreeDragSource, TreeDropTarget.

    If you create DragSource instances for the Window, the GridDropTarget might try to accept it as data to be dropped within the grid - if that is not what you mean, then I don't understand how a Window can be dropped within a Grid.

    What are you trying to customize, beyond the ability for the Window to be dragged by its header to another position?

  8. #8
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,734
    Vote Rating
    90
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      0  

    Default


    Quote Originally Posted by David Hoffer View Post
    Also I should note that if I replace the previous code with just a DragHandler on the Window's Draggable that does work as expected but I don't know if that will be enough because I would like to show a drop target in the UI so users know exactly where the window will be positioned. (With just a DragHandler it just goes to the closest grid cell.)
    Okay, so you are intending to drop a Window into a position in a Grid - can you elaborate on what you mean by grid, and grid cell? Are we talking about the GXT grid, or your own layout container? From your earlier post , I see now you seem to be using an AbsolutePanel as your 'grid panel', and all of the positioning is within that.

    The DragHandler is probably what you mean - you can use the onDragMove to see every time the user moves the window, and try to show what it will look like if they drop there with some sort of proxy.

    Windows almost certainly shouldn't be added to another parent - they already know how to manage themselves as floating windows. Instead, consider wrapping up a ContentPanel with a Draggable, so it doesnt try to add itself. The ContentPanel's header should be the draggable portion.

  9. #9
    Ext GWT Premium Member
    Join Date
    Jan 2009
    Location
    Colorado Springs, CO
    Posts
    381
    Vote Rating
    5
    DavidHoffer is on a distinguished road

      0  

    Default


    The GridPanel is custom, e.g.
    Code:
    GridPanel extends SimplePanel
    so it has nothing to do with a GXT grid. The reason I can't use GXT grid (correct me if I am wrong here) is that in my case the grid cells that go in the grid will be of varying size, e.g. some will be 1 cell x 1 cell some 2x1 some 3x3, etc. So yes I was trying to make my own grid layout using an AbsolutePanel, if there is a better way please advise.

    Okay I will try to use a ContentPanel wrapped with Draggable instead of Window, I don't yet understand why Windows shouldn't be used but I will try the other approach. Wait...I do need the cell/widget to be resizable...I think I started with some other container and it wasn't resizable so I switched to using Window. Can I make a ContentPanel wrapped with Draggable resizeable?

  10. #10
    Sencha - GXT Dev Team
    Join Date
    Feb 2009
    Location
    Minnesota
    Posts
    2,734
    Vote Rating
    90
    Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light Colin Alworth is a glorious beacon of light

      0  

    Default


    The main reason to wrap a ContentPanel instead of a Window is that the Window class really isn't intended for use in this manner, rendered as a child of another component - it expects to be responsible for adding/removing itself from the dom, and watching for other windows it needs to remain above/below.

    The edges of a ContentPanel or other Component can be made into resizing bars using the com.sencha.gxt.fx.client.Resizable class. Note that this accepts handlers for its resize events.

    Grid won't work, correct - it is intended to be used as a way to display tabular data, not to layout and position other widgets. It excels in drawing large amounts of data provided to it by a ListStore, but positioning widgets should be left to a panel, as you are doing.

Thread Participants: 1