Get associated mouse click from ExpandTree event in SWT - java

I'm trying to stop the tree from collapsing or expanding when the user double clicks a column on a tree. It should only be allowed if the user clicks on the first column.
See, if a user double clicks the checkbox on node2 world1, the tree expands or collapses. I don't want that to happen. My tree needs SWT.FULL_SELECTION to detect the clicks on each of the columns, so that's not the way to go.
My listener looks like this
tree.addTreeListener(new TreeListener() {
#Override
public void treeExpanded(TreeEvent e) {
TreeItem parent = (TreeItem) e.item;
Point p = new Point (e.x, e.y);
int column = CheckboxClickListener.getColumn(p,parent);
if (column > 0) {
e.doit = false;
}
}
#Override
public void treeCollapsed(TreeEvent e) {
TreeItem parent = (TreeItem) e.item;
Point p = new Point (e.x, e.y);
int column = CheckboxClickListener.getColumn(p,parent);
if (column != 0) {
e.doit = false;
}
}
});
Problem is, the mouse event that generated the click is not the same as the TreeEvent that expands the tree. Thus, the e.x and e.y are both zero, making my Point detection useless. Listening to the mouse event and maintaining the last x and y to check here in the TreeExpand event seems bug-prone since the user may also expand the tree using the keyboard (thus the x and y may not reflect the user action). I also considered adding a time constraint to check that but seems like a bad way to handle the issue.
How can I detect which mouse event triggered the expand event?
PS: e.doit=false does nothing, even outside the if condition, so help with stopping the tree from expanding/collapsing would be appreciated as well :)
Thank you!

I found someone saying this is a bug at this link http://www.eclipse.org/forums/index.php/t/257325/
The following code stops the tree from expanding on doubleclick but I'm not sure why or what are the side effects.
tree.addListener (SWT.MeasureItem, new Listener(){
#Override
public void handleEvent(Event event) {}
});
This stops the expanding when doubleclicking ANY column. Clicking on the small arrow at the left of the TreeItem still expands the tree (as it should).

Related

Scroll a list while the user is dragging an object near the bounds

I have a problem that I have been unable to solve in a way that I am very happy with.
I have a view that I am dragging and dropping into a list. That list is created using a recyclerView. The drag object works fine, and the recyclerView's items can all receive the events no problem. Now I want to make the list scroll as the user drags their finger close to the top or bottom of the list. My first step was to add a dragEvent listener to the recyclerView, and attempt to start scrolling each time I got a location near the top or bottom edge. So, my DragEvent.Location case looks something like this:
case DragEvent.ACTION_DRAG_LOCATION: {
removeDragScrollCallBack();
float y = event.getY();
final int scrollAreaHeight = v.getHeight()/4;
final int delayMills = 16;
int scrollAmount = 0;
if (y > v.getHeight() - scrollAreaHeight) {
scrollAmount = 10;
} else if (y < scrollAreaHeight) {
scrollAmount = -10;
}
if (Math.abs(scrollAmount) > 0) {
final int finalScrollAmount = scrollAmount;
dragScrollRunnable = new Runnable() {
#Override
public void run() {
if (canScrollVertically(finalScrollAmount)) {
scrollBy(0, finalScrollAmount);
if (dragScrollHandler != null && dragScrollRunnable != null) {
dragScrollHandler.postDelayed(this, delayMills);
}
}
}
};
dragScrollRunnable.run();
}
return true;
}
It kinda works. Things scroll in the right direction. It seems to sputter a bit though, and generally not scroll very smoothly. Additionally, the drag and drop drop event sometimes doesn't make it to the children while the recycler view is still scrolling.
So, I went to the google example of doing a similar thing in a using a list view - link. I modified the code they used for their list view and tried to handle my recyclerView in a similar manner. This had even poorer results for me.
I have tried various other alterations of these techniques, and swapped to using the smoothScroll function instead of the standard scroll function, but I'm not too happy with any of the results.
Does anyone have a good solution for how to handle this?
Update: I now believe that many of my problems with this functionality are due to the drag listener being fairly unreliable. At sometimes the recycler fails to get events when it's children are receiving events.
Turns out the drag listener on a view is not terribly reliable. At random times as I moved my finger around the screen, the drag listener wouldn't recieve all of the events. I believe the reason for this was the way that the children of the recyclerView were also recieving the on drag callbacks. The solution was to do what I had tried originally, but through a listener on the fragment itself. Now when I get an event, I check the coordinates to see what view it is in, and then convert it to local coordinates for that view. Then I can determine exactly how I need to handle it.

Gxt tree grid double click to show pop up

How do I catch double click event in gxt tree grid?
I already try this from :
Click Handlers for Trees in GXT 3?
tree.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
tree.getSelectionModel().addSelectionHandler(new SelectionHandler<MenuView.MenuDto>() {
public void onSelection(SelectionEvent<MenuDto> event) {
MenuDto mnu = event.getSelectedItem();
Info.display("Tree Handler", mnu.getDescripcion());
}
});
But it only works for single click, not double click.
I want if user press double click, pop up will show.
Selection has specific meaning in this case - are you sure you want doubleclick to cause selection to happen, and only then you want to be notified?
Instead, look at grid.addRowDoubleClickHandler - your handler will be given the row index that was clicked, and you can then ask the store what item is in that row.
Relevant GXT Javadoc:
grid.addRowDoubleClickHandler(...)
RowDoubleClickEvent
This is the code, i only test to see info display :
tree.addRowDoubleClickHandler(new RowDoubleClickHandler() {
#Override
public void onRowDoubleClick(RowDoubleClickEvent event) {
Info.display("hello", "double click");
}
});

ListSelectionEvent, firing an event when clicking the currently selected item in JList

Let 'x' be an item in the JList. When I click it for the first time, the event fires, when I click it again, the event does not fire. I have to click some other item and then come back to 'x'.
How can I fire the event repeatedly from 'x' without having to deal with other items.
This is my code:
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false) {
if (list.getSelectedIndex() == -1) {} else {
String clicked = (String)list.getSelectedValue();
//method to fire is here
}
}
updateDisplays();
}
The ListSelectionListener reflects changes to the lists selection, you could use a MouseListener instead...
For example...
MouseListener ml = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt) {
if (SwingUtilities.isLeftMouseButton(evt) && evt.getClickCount() == 1) {
if (list.getSelectedIndex() != -1) {
int index = list.locationToIndex(evt.getPoint());
System.out.println("You clicked item # " + index);
}
}
}
}
list.addMouseListener(ml);
You can add a MouseListener and watch for clicks. Note that a click that changes the selection will fire both the MouseListener and your ListSelectionListener.
Another option is to immediately clear the selection from your ListSelectionListener; that way the next click will reselect and retrigger, although you will lose the ability to navigate through items with the keyboard.
It seems like sort of an unusual UX decision, though, to assign significance to a click on an already selected item in a list.
Adding based on your question comments: If you go the MouseListener route, I recommend looking for double-clicks instead of single-clicks if the click is going to execute an action (especially if the action changes data and is not undoable). Also note that your ListSelectionListener will execute actions as you navigate through the list with the keyboard, which may not be what you intend.
If your commands in your history list are typed, you could also consider using a drop-down combo box for both command entry and the history list, where a selection from history fills in the command text but does not execute. You'd also have an opportunity to add auto-complete from command history.

How to dynamically add .css to a custom Javafx LineChart Node?

So, my issue is this: I'm attempting to define a custom set of nodes for a Javafx XYChart LineChart, where each node corresponds to a point that was plotted directly from the datasets. After looking around a little bit, Jewlesea actually had a solution at one point about how to add dynamic labels to nodes on a linechart graph that gave me enough of a push in the right direction to create black symbols (they are dots at the moment, but they can be many different things). Now I have a requirement that requires me to change ONE of the nodes on the XY chart into an 'X'. this could be either through loading an image in place of the 'node', or through physically manipulating the 'shape' parameter in .css.
The problem begins when I try to add this property dynamically, since which node has the 'x' will always be changing. Here are the things I've tried, and they all end up with no results whatsoever, regardless of the property used.
private XYChart.Data datum( Double x, Double y )
{
final XYChart.Data data = new XYChart.Data(x, y);
data.setNode(
new HoveredThresholdNode(x, y));
//data.getNode().setStyle("-fx-background-image: url(\"redX.png\");");
data.getNode().styleProperty().bind(
new SimpleStringProperty("-fx-background-color: #0181e2;")
.concat("-fx-font-size: 20px;")
.concat("-fx-background-radius: 0;")
.concat("-fx-background-insets: 0;")
.concat("-fx-shape: \"M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,10 L0,10 L0,8 L4,5 L0,2 L0,0 Z\";")
);
data.getNode().toFront();
return data;
}
So in the above, you can see that this is adding a property through the use of the 'bind' function after the dataNode has already been created. Also note above, I tried doing it through the 'setStyle' interface at this level to give it a background image, with no success. Also, no errors are being thrown, no 'invalid css' or anything of the sort, just simply no display on the graph at all when done this way.
now, in the HoveredThresholdNode (Again a big thanks to Jewelsea for being a master of Javafx and putting this bit of code online, it's where 90% of this class came from.) I tried essentially the same thing, at a different level. (actually being IN the node creation class, as opposed to a layer above it).
class HoveredThresholdNode extends StackPane {
/**
*
* #param x the x value of our node (this gets passed around a bunch)
* #param y the y value of our node (also gets passed around a bunch)
*/
HoveredThresholdNode(Double x, Double y) {
//The preferred size of each node of the graph
//getStylesheets().add(getClass().getResource("style/XYChart.css").toExternalForm());
//getStyleClass().add("xyChart-Node");
//setOpacity(.8);
styleProperty().bind(
new SimpleStringProperty("-fx-background-color: #0181e2;")
.concat("-fx-font-size: 20px;")
.concat("-fx-background-radius: 0;")
.concat("-fx-background-insets: 0;")
.concat("-fx-shape: \"M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,10 L0,10 L0,8 L4,5 L0,2 L0,0 Z\";")
);
//this label is the 'tooltip' label for the graph.
final Label label = createDataThresholdLabel(x, y);
final double Myx = x;
final double Myy = y;
setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
if (Myx == 0) {
label.setTextFill(Color.DARKGRAY);
} else if (Myx > 0) {
label.setTextFill(Color.SPRINGGREEN);
} else {
label.setTextFill(Color.FIREBRICK);
}
label.setText("Current position: " + Myx + " , " + Myy);
//setCursor(Cursor.NONE);
toFront();
}
});
setOnMouseExited(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
//getChildren().clear();
//setCursor(Cursor.CROSSHAIR);
}
});
}
Now note, I also tried the setStyle(java.lang.String) method, with all of the same type of CSS, with no success. I have NO idea why this isn't styling dynamically. It's almost as if the custom nodes are simply ignoring all new .css that I define at runtime?
Any help would be greatly appreciated, please don't be shy if you need more details or explanation on any points.
So, I did finally find a good workaround to solve my problem, although not in the way I thought it would happen. The main problem I was having, was that I was extending from stackPane to create my node, which only had a very small number of graphical display options available to it, and by switching the 'prefSize()' property, I was simply changing the size of that stackPane, and then filling in the background area of that stack pane black, giving it a very deceptive shape-look to it.
So rather than use a stack pane, whenever I reached the node that I needed to place the red 'X' on, I simply called a different Datum method that returned a datum with an ImageView Attached, like so:
private XYChart.Data CoLDatum(Double x, Double y){
final XYChart.Data data = new XYChart.Data(x, y);
ImageView myImage = new ImageView(new Image(getClass().getResource("style/redX.png").toExternalForm()));
data.setNode(myImage);
data.getNode().setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
main_label.setText("Some Text.");
}
});
data.getNode().setOnMouseExited(new EventHandler<MouseEvent>(){
#Override public void handle(MouseEvent mouseEvent) {
main_label.setText("");
}
});
return data;
}
and since ImageView is an implementing class of Node, this worked out just fine, and allowed me to load up an image for that one single node in the graph, while still maintaining a listener to give custom text to our information label when the red 'x' was hovered over with a mouse. Sometimes, it's the simple solutions that slip right past you.
I imagine that, had I employed stackPane properties properly with the setStyle(java.lang.String) method, they would have absolutely shown up, and I was just butchering the nature of a stack pane. Interesting.
Hopefully this helps somebody else stuck with similar problems!

Java Mouse After a Drag

I'm making a small game project in Java. In it you have a character that shoots in the direction of the mouse when "pressed" or "dragged" (you know, in Java's terms). The only problem is that if you stop dragging but you still hold the left mouse button down you stop shooting.
Is there a way to detect if the mouse button is down after a drag?
NOTE: the mouse is not sensed as "pressed" after the drag.
You will get the information when a mouse button is pressed and when it is released again. If you want to know the state in between, you need to use a boolean to store that information.
Example:
final boolean[] buttonStates = new boolean[3];
public void mousePressed(MouseEvent e) {
buttonStates[e.getButton()] = true;
}
public void mouseReleased(MouseEvent e) {
buttonStates[e.getButton()] = false;
}
You would do the same for keyboard input by the way.

Categories

Resources