Prevent or revert drag & drop in Primefaces tree - ajax

I have a Primefaces 4 tree in which I want enable drag and drop. But I have constraints which do not allow to move some node types to other (i.e. only leafs can be moved and they can be moved only to the same type of parent nodes).
How can I prevent or cancel such drag and drop operation if the constraints fail? I would expect the onDragDrop event handler to return false or so in such cases but this method has void return type. I can check constraints in event handler but the drag and drop operation is already done.
What to do here?

Related

Programming custom GUI OPenGL

I am creating my own GUI in OpenTK.
I want to fire a mouse event when the cursor is, for example, in one of the GUI controls. How can I do that? Because now I'm just iterating through a list of items in the main class, and in the Opentk´s window´s MouseMove event I'm just checking if the mouse coordinates are within the "region" of the component I'm drawing.
This works for now, but I think it could be done in a better way. This way my code is unordered and in the main class, and I would rather have it in the specific component class.
What I would like is to have an event attached to each component of my GUI, so that I can define many events for one component.
I mean, I would like to have for example a button component where I can override or just use a method that fires when an event occurs. Same as OpenGL´s window where you can override events.
This is not a complete answer, because your question is quite broad, but I hope it helps.
In order to implement such a system, here are the core components for a potential design:
UI Components: Some kind of standard interface where different component types can define logic for interactions. Depending on the language, the most common approach is probably something like a parent class Component, with methods to be overridden. These would probably include things like:
Mouse Hover
Mouse Click (press / release)
Click drag
It will also likely need some additional associated information:
Some way to determine the component's location. Could be providing a bounding box, or perhaps a method that tests if a given point is within this component or not.
Information or functionality for drawing the component.
Display and layering settings (is it visible or hidden, should it draw on top of other components or behind).
UI Context: The context is a structure that defines the set of components that are existent in the UI. This could be something like a list structure of Components. In order to build your UI, you would add components to this context. The context will define some behaviour:
Managing components (add / remove / modify).
How to draw the entire context (for example, looping over each component and executing the draw functionality for each).
Handling of events (see next section)
Event Dispatch: To make your UI usable, you can insert an "adapter" layer that handles events from your windowing library (OpenTK) then translates them into usable events for your components and dispatches them. Here is an example of how this might work for a "click" event (pseudo-code):
function TK_Event_ClickPressed(point) {
for component in context {
if component.ContainsPoint(point) {
component.EventClickPressed()
}
}
}
This is actually the more tricky part of the design, in my opinion, because there are some tricky conventions around how component based UI works. You don't necessarily have to follow them, but they're important to be aware of at least because it is probably how people expect your UI to work:
After click press, click drag continues to occur until click release, even if the cursor leaves the component area.
"Actions" occur on click release.
Click release only takes action if the corresponding click press occurred on the same component.
The click release doesn't take any action if the cursor is no longer inside the component (leaving and re-entering the component before release still does the action, though).
You can only be actively clicking one component at a time (the one shown on top), even if multiple components overlap at that spot.
Assuming that you follow these conventions, this means that dispatching events is actually a bit more complicated than just checking if the event point was in a given component or not. You need to maintain some kind of state to keep track of whether the context is currently in a click or not, and which component, if any, is "consuming" the current click. That is, which component should be given the click release and drag events if they occur.
With these systems in place, you just need to create a window, create a UI context, register the adapter layer to the window to act on that context, set up the window to draw the context on frame, then use the context to add / remove / modify components in your program.

MFC: How do you handle putting up a right drag-and-drop context menu?

I have a drop target (CTreeView) that accepts CF_HDROP. When I drag/drop using left mouse button, it works as expected (with Move/Copy option via shift/ctrl keys), when I do a drag/drop using the right button, it treats it the same as the left, no context menu. I've tried dragging from the desktop to the tree view (as well as internally from a list view to the tree view).
I am aware of the method of showing a context menu when the program internally handles the process of checking when the right button down, track when dragging when mouse moves, and releasing button to do drop. But since this is a drop-target from anything (using OnDrop()), how do I handle getting the context menu to show for the option to either copy or move?
Thanks!!

Implement a Finder-like treeview and representing its nodes with lazy loading using NSOutlineview

When implement a big file system tree in NSOutlineview, it lacks an event notification when user click the left side down arrow triangle icon of a node. This is very important when lazy-loading a large amount of file nodes into a directory node and represent it into NSOutlineview. Otherwise, developer have to load entire directory into it, in this way, the loading will force end user to wait, this is not acceptable. In short, current version of NSOutlineview can't implement lazy-loading caused by this issue. Does anyone meet this issue or have an alternative solution to implement a Finder-like treeview with Cocoa NSOutlineview, any help will be great appreciate.
In Addition:
NSOutlineview does not emit an outlineViewItemWillExpand event when click the icon, and there still lacks enough info to get which node will expand even that event emitted, [NSOutlineview selectedRow] can't work because the node which will be expanded have not been selected yet.
I load my child nodes in the following call in NSOutlineViewDataSource:
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
guard let node = item as? Node else { return false }
return node.children.count > 0
}
The children property of my Node class is lazy, and hence forced to load here.
This method is only called on Nodes that are visible in the outliner. This way you are only loading one layer ahead of the visible tree. The disclosure triangle (expand arrow) will then be visible if children exist.
If you have an efficient way to know the number of children a node has without actually loading them, then it may be better just to return the child count in outlineView(_: isItemExpandable:) and then do the actual load in outlineViewItemWillExpand(_:) as Willeke has suggested in the comments.

Stopping clicks on object on one stage going through to the nextStage in EaselJS / CreateJS

I have two canvases and two stages in CreateJS / EaselJS. The first stage has autoClear set to false and I am doing dynamic drawing on it starting with a stagemousedown event. The second stage uses nextStage to send mouse events to the first stage. The second stage has interface such as a Bitmap that I want to press on to go to another page. When I click on the Bitmap, the stage beneath does the dynamic drawing. I want the click on the Bitmap not to go through to the first stage but stopImmediatePropagation does not work, nor does putting a clone of the Bitmap with mouseEnabled false on it underneath. I can just use mousedown on the Bitmap so the user does not notice as much, but was wondering if there is a way to disable mouse events from passing through the top stage if they are acting on an object with an event set to capture? Thanks in advance.
The stagemousedown and other stage events are decoupled from the EaselJS object event model. They are catch-all events, which basically represent mouse interaction with the . Because of this, catching and stopping these events won't interrupt the display list hierarchy.
Typically if you want to block other events in the same stage, you can create a canvas-size box (Shape, etc) that will block the interaction. When dealing with nextStage, this is especially true, since we are passing on events that are unhandled by objects in the EaselJS display list.
A better approach might be to toggle the nextStage on stagemousedown, so it is null during the click event. Not sure if this will work, but its a start.

Disable Events on Child

Im using Ext JS 4. I have a button inside a container. I want the container to receive mouseover, mouseout, and click events, but the button is causing the mouseover and mouseout event handlers to be called twice on the container. How can i disable the events on the child button?
I believe you are running to 4.0's new bubbleEvents behavior. Components now propagate some events to their parent containers. This happens in code, independent of DOM event bubbling, up the component hierarchy.
http://dev.sencha.com/deploy/ext-4.0.0/docs/api/Ext.container.Container.html
The best fix is to simply stop the event once you've handled it. That should prevent all bubbling, component or DOM. It is generally a good idea to do this for click events to make sure one and only one thing happens in response to a click, but I'm less certain it's appropriate for mouseover and mouseout.
panel.on('click', function(e) {
e.stopEvent();
// do your stuff
});
another fix you could try (I haven't) is to wipe bubbleEvents on the button.
Another, possibly less robust fix is to turn on event buffering:
el.on('click', this.onClick, this, {buffer: 10});
Buffering collapses duplicate events in a configurable time window into one and it's useful for smoothing out rapid fire or duplicate UI events, but I'm not sure how it plays with bubbling.
{
...
preventDefault: true,
...
}

Resources