I am trying to implement a ScalaFX TreeView representing a directory structure, with some TreeItem elements in the tree structure able to capture a MouseClicked event so that I can do further operations (subsequently show the contents of that directory). It seems that the only way to catch events is to adopt CellFactory in this relation. I am not sure how to get my head around this with such limited available documentation (even in JavaFX side).
Any pointers to code fragments addressing this type of scenario?
Related
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.
Gwt HTML5 Canvas wrapper can responds to mouse and keyboard events, it binds to 5 - 6 types of different events, my question is, it is possible to define entirely new event system such as CanvasEvent (and related handler CanvasEventHandler extends to GwtEvent etc), bind this to canvas object and then handle all events differently using a handler interface methods will be something like onDraw(), onDrag(), onMove(), onSelect() etc.
I dont have good clarity of GWT event system but i want to know is this possible without individuality attaching separate event handlers to form a logic for handling my problem, can I access all possible event as one consolidated object and fire custom event based on conditions. What would be the best way to do it, there are threads with GWT custom events but they include senders, whereas in my case sender is already present (Canvas)
Thanks much
Certainly - remember that all of the GwtEvent objects are completely artificial and are based off of events fired from the native JavaScript. That JavaScript event object, (which comes in via onBrowserEvent) gets wrapped up as a ClickEvent or a KeyDownEvent based on the details of the original object, and then fired off via the internal HandlerManager instance. In the same way, you could listen for a MouseDownEvent, set some state, then if a MouseMoveEvent occurs, fire your own CanvasDrag event. You'd probably stop listening to those move events once a MouseUpEvent happens, then you would issue something like a CanvasDropEvent. If isntead the MouseUpEvent occurred right away with no move, you could trigger a CanvasSelectEvent (or you might have something else in mind for that select event).
Each of these new event types you declare then might contain specifics about whatever is going on. For example, while a MouseMoveEvent just has the element that the mouse is over and the x/y coords, you might be indicating what is being dragged around the page. That might be in the form of the shape that was last clicked, or even the data it represents.
Yes, the 'sender', or source, is already there, but it'll be easier to use if you expose some kind of a method to add handlers like addCanvasDragHandler, etc. This is not required - all users of your code could just use addHandler, but it does make it a little ambiguous about whether or not the widget supports the event in question. You would then call fireEvent on the canvas object to make all handlers of that event type listen.
Or, you could make a new class that contains an internal Canvas widget - possibly a Composite object or just something that implements IsWidget (Canvas has a private constructor, so you can't subclass it). This would enable you to add your own particular handlers, and keep your own HandlerManager/EventBus to track the events you are concerned with.
I want to build a simple forms designer in Cocoa and need to move controls around on a form using the mouse (click, hold, move around, release).
Do I need to inherit new classes from all control classes to intercept those events ? Is there a way to implement it generically for any control?
One way might be to have a single large custom view that fills all the space the controls will be in. Implement the necessary methods to implement mouse events in this view, doing hit detection on the control views and moving them around. This approach requires only 1 custom subclass of NSView, and you can use any views or controls you want to move around without subclassing them.
Write a custom view to contain the controls. Override -hitTest: to ignore the controls and return self instead. Then when you receive mouse events, figure out which control they apply to and move as appropriate.
I am developing an Widget for Eclipse RCP. I made a Shell, which I want to combine with Events (Resize, Move etc.) in a View, in which I have a Composite. How from the Composite point of View I can get it's View, in which this Composite is placed?
You can always call getParent() to get the parent control. If the composite you are interested in is not the direct parent, consider passing the control you want into the constructor, and keeping track of it that way.
I have an NSTableView and an NSOutlineView, both with their content provided by bindings, that I'd like to have some drag-and-drop functionality:
Drag rows from Table A onto a row of Outline B, where they will be copied into a data structure which the row in Outline B represents.
Drag a row from Outline B onto another row in Outline B, which will copy the data represented by the first row into the data represented in the second row.
I've read Apple's drag-and-drop documentation and gotten just about nowhere. It doesn't really seem to apply to what I need to do. What am I missing?
The page you linked to is pretty clear about what you need to do. In table A's data source, implement registerForDraggedTypes: and tableView:writeRowsWithIndexes:toPasteboard: to put some private TableAPasteboardType data on the pasteboard.
In outline B's data source, implement the same two methods and put some private OutlineBPasteboardType data on the pasteboard.
Finally, implement tableView:validateDrop:proposedRow:proposedDropOperation: and tableView:acceptDrop:row:dropOperation: to check the pasteboard for either TableAPasteboardType or OutlineBPasteboardType and make the appropriate changes to your bound model, depending.
It's pretty straightforward once you just plow in and do it.
You need a data source—AFAIK, you can't make this happen with Bindings alone.
The unfinished Adium Xtras Creator, which is under the BSD license, includes an array controller that you can set as the data source to get drag-and-drop in a Bindings-powered table view.
This requirement may not apply to NSOutlineView and NSTreeController. I haven't tried that.
In MacOS 10.7 some new protocols were added to implement this.
There is a lack of documentation for tables at the moment but you can find some nice examples:
DragNDropOutlineView
SourceView
TableViewPlayground
For NSTableViwew the Protocol NSTableViewDataSource defines the following methods:
(BOOL)tableView:writeRowsWithIndexes:toPasteboard:
tableView:validateDrop:proposedRow:proposedDropOperation:
tableView:acceptDrop:row:dropOperation:
For NSOutlineView the Protocol NSOutlineViewDataSource defines the following methods:
(BOOL)outlineView:writeItems:toPasteboard:
(NSDragOperation)outlineView:validateDrop:proposedItem:proposedChildIndex:
(BOOL)outlineView:acceptDrop:item:childIndex:
These are the minimum requirements to implement for each view type.
The use cases are quite similar.
If the toPasteboard: method returns YES, the drag is started.
The validateDrop: method controls which target node is allowed by updating the marker in the view
Return YES for the acceptDrop: method if the drop was successful
This lead to two sub-usecases you have to manage. The first one is a drag & drop within the same view or the same operation between two views. Additionally you may distinguish between move, copy or delete operations. A nice example is how the breakpoints work with drag & drop in Xcode.
The tableView has some additional methods to customize drag & drop, but the ones I mentioned are the key methods to get it working.