Catching the scrolling event in gtk# - gtk

Which event from which widget should I catch when I need to run some code when ScrolledWindow is scrolled?
Ths widgets tree I am using is:
(my widget : Gtk.Container) > Viewport > ScrolledWindow
I tried many combinations of ScrollEvent, ScrollChild, etc. event handlers connected to all of them, but the only one that runs anything is an event from Viewport that about SetScrollAdjutstments being changed to (x=0,y=0) when the application starts.

You should attach to the GtkAdjustment living in the relevant scrollbar, and react to its "changed" event. Since Scrollbars are Ranges, you use the gtk_range_get_adjustment() call to do this.

unwind's answer was correct.
Just posting my code in case someone needs a full solution:
// in the xxx : Gtk.Container class:
protected override void OnParentSet(Widget previous_parent) {
Parent.ParentSet += HandleParentParentSet;
}
void HandleParentParentSet(object o, ParentSetArgs args) {
ScrolledWindow swn = (o as Widget).Parent as ScrolledWindow;
swn.Vadjustment.ValueChanged += HandleScrollChanged;
}
void HandleScrollChanged(object sender, EventArgs e) {
// vertical value changed
}
If you need to change the parent of any of those widgets, or may need to change the types and change the hardcoded types and handle disconnecting from the previous parent.

Related

Avoid GWT DataGrid Rows Scrolling

In a GWT DataGrid I wan to to avoid / prevent the table data rows scrolling in case of some peculiar application status.
I already tried to catch ScrollEvent, but I think that such event was fired “after” rows scrolling has been done.
I also tried to “hide” every “tool” that a user can manage in order to get rows scrolling; so I tried:
.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.DISABLED);
and
scrollPanel.removeVerticalScrollbar();
but Mouse Wheel Actions still keep fire rows scrolling ... therefore maybe should be enough to avoid mouse wheel scrolling actions to reach my goal ?
Please note that I don’t want to remove Horizontal Scrolling.
Any suggestions will be appreciated.
Thanks in advance
Here are two solutions. try any one
DOM.sinkEvents(getDocElement(), Event.ONMOUSEWHEEL);
Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(final NativePreviewEvent event) {
if (event.getTypeInt() == Event.ONMOUSEWHEEL) {
event.getNativeEvent().preventDefault();
}
}
});
dataGrid.sinkEvents(Event.ONMOUSEWHEEL);
Not a good solution but still you can try this one also.
dataGrid.addCellPreviewHandler(new Handler<Contact>() {
#Override
public void onCellPreview(CellPreviewEvent<Contact> event) {
dataGrid.getRowElement(0).scrollIntoView();
}
});

How to set the Droppable/Draggable Event on the mouse cursor

I've implemented the Drag-n-Drop effects in Wicket using the Ajax Behavior. If I dragg the Image over the tree nodes, the position of droppable accept is in the middle of image. How to set this position (event) on the cursor?
Thank you.
Also I found it. The solution is:
DroppableAjaxBehavior b = new DroppableAjaxBehavior() {
#Override
public void onDrop(Component droppedComponent, AjaxRequestTarget target) {
//do something to handle event
}
};
b.setTolerance(ToleranceEnum.POINTER);

Programatically Detect window maximization/Minimization??? Eclipse RCP

As the title shows, I want to add a listener to my rcp user interface in order to detect maximization and minimization. Actually, it not that my real purpose, but I think it is a way to solve my problem. I have a view with some shapes in the center, and I wonna keep the drawing exactly in the center even if the window is resized. To do so, I used the following listener :
public void createPartControl(final Composite parent) {
display = parent.getDisplay();
white= display.getSystemColor(SWT.COLOR_WHITE);
parent.setLayout(new FillLayout(SWT.VERTICAL));
final ScrolledComposite sc = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
sc.setExpandHorizontal(true);
sc.setExpandVertical(true);
sc.setMinHeight(100);
sc.setMinWidth(100);
sc.setSize(565, 305);
final Composite child = new Composite(sc,SWT.NONE);
child.setLayout(new FillLayout());
// Set child as the scrolled content of the ScrolledComposite
sc.setContent(child);
child.setBackground(white);
gc = new GC(child);
parent.addListener (SWT.Resize, new Listener () {
public void handleEvent (Event e) {
x = child.getBounds().width/2;
y = child.getBounds().height/2;
child.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {
dessin(gc); // draw my shapes
}
});
}
everything goes well except when I maximize the window and then minimize it, in this case I loose the drawing (it is in the corner).
Any idea please? I'm I thinking in the right way?
The two events to detect minimization and un-minimization (not necessarily maximization) are Iconify and Deiconify which only occur on the Shell. See the javadocs for Shell.
Consider moving the resize event is seen for the parent, as the child need not necessarily be resized yet.
In order to keep something in the center of something else all you need is the SWT.Resize event, so this question is a classic case of the XY Problem. (Except that the OP in this case seems to already suspect that this may be an XY Problem.)
However, many people arrive at this question with a legitimate need to programmatically detect window minimized / maximized / restored events, for the following reason:
If you want to be able to save the bounds of your application window on exit, you cannot just save whatever is returned by Shell.getBounds(), because your application may be terminated while minimized or maximized or fullscreen, in which case its bounds should not be persisted. What should be persisted is the minimized/normal/maximized/fullscreen state of the shell, (I call it "posture",) and the bounds of the shell last time its posture was "normal". So, essentially, you need to keep track of when the posture is "normal", and for that you need to have a "posture changed" event.
The problem is that when SWT issues the "deiconified" event, it has not calculated the bounds of the shell yet, so the value that you get in that case is bogus.
So, here is the solution to that:
You are going to need a method which recalculates the posture as follows:
private void recalculatePosture()
{
Posture posture = swtShell.getFullScreen()? Posture.FULLSCREEN
: swtShell.getMinimized()? Posture.MINIMIZED
: swtShell.getMaximized()? Posture.MAXIMIZED
: Posture.NORMAL;
if( posture != previousPosture )
{
issue event...
previousPosture = posture;
}
}
In order to generate the "maximized", "restored (from maximized)" and "fullscreen" events you can use Shell.addListener() to listen for the SWT.Move and SWT.Resize event, and invoke recalculatePosture() when they occur.
In order to generate the "minimized" event you can use the shellIconified() method of the ShellListener as #the.duckman said, and again, invoke recalculatePosture().
In order to generate the "restored (from minimized)" event, you need to do the following in your ShellListener:
#Override
protected void onShellDeiconified( ShellEvent e )
{
display.asyncExec( () -> recalculatePosture() );
}
This will cause the recalculation of posture a short time after the 'deiconified' event, at which point SWT will have gotten around to properly calculating the bounds of the shell.

GWT: How to center element containing CellTable?

I'm trying to center an element that contains a CellTable. The actual
centering logic works okay, but I'm having problems with all those
attaching/detaching events. Basically, I'm doing this in my container
widget:
#Override
public void onLoad() {
super.onLoad();
center();
}
However, it seems that onLoad on the container does not mean that all
children have loaded, so... the actual centering routine is called too
early and Element.getOffsetWidth/getOffsetHeight are both returning 0.
This results in the container being displayed with the left upper corner
in the center of the screen.
Same thing happens if I use an AttachEvent.Handler on the CellTable.
So... is there any event on CellTable, or on Widget or whatever that
allows me to trigger an action when the DOM subtree has been attached to
the DOM?
Thanks in advance.
Take a look at scheduleDeferred. A deferred command is executed after the browser event loop returns.
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
center();
}
});
Override onAttach instead of onLoad. onAttach default implementation calls onLoad followed by doAttachChildren (which calls onAttach on each child widget), so the following code should call center after the children have been attached:
#Override
public void onAttach() {
super.onAttach();
center();
}
(BTW, the default implementation of onLoad is a no-op)

I need to know when a VerticalPanel changes size

I'm using gwt-dnd to implement drag-and-drop functionality in my GWT program. To get scrolling to work right, I need
<ScrollPanel>
<AbsolutePanel>
<VerticalPanel>
<!-- lots of draggable widgets -->
</VerticalPanel>
</AbsolutePanel>
</ScrollPanel>
I have to manually set the size of the AbsolutePanel to be large enough to contain the VerticalPanel. When I add widgets to the VerticalPanel, though, the size reported by VerticalPanel.getOffsetHeight() isn't immediately updated - I guess it has to be rendered by the browser first. So I can't immediately update the AbsolutePanel's size, and it ends up being too small. Argh!
My stop-gap solution is to set up a timer to resize the panel 500ms later. By then, getOffsetHeight will usually be returning the updated values. Is there any way to immediately preview the size change, or anything? Or, alternatively, can I force a render loop immediately so that I can get the new size without setting up a timer that's bound to be error-prone?
This is a common problem with DOM manipulations. The offsetHeight doesn't update until a short time after components are added. I like to handle this using a recursive timer until a pre-condition is violated. E.g. In your case let there be a function which adds components and will be defined as below:
public void addComponent(Widget w)
{
final int verticalPanelHeight = verticalPanel.getOffsetHeight();
verticalPanel.add(w);
final Timer t = new Timer(){
public void run()
{
if(verticalPanelHeight != verticalPanel.getOffsetHeight())
absolutePanel.setHeight(verticalPanel.getOffsetHeight() + 10 + "px");
else
this.schedule(100);
}
};
t.schedule(100);
}