Pygtk: Disable moving separator in a gtk.Paned (HPaned/VPaned) - gtk

Is there a way I can stop the user from dragging around the separator in a gtk.Paned? I don't want to disable it completely... if any child resized or set_position() was called, the separator should still change position.
Thanks!

One possible (dirty :)) way would be to track Paned' events and re-set its size:
def handle_cb (pane, param):
# detect if paned is locked
# or its position has changed - ommited
pane.set_position(10)
return True
pane = gtk.VPaned()
...
pane.connect("notify", handle_cb)
I'd try to set child widgets unshrinkable first, though.

Related

How do you stop scrolling to top when grid store is reloaded

I have an app that uses ExtJS 3.3.0. It uses an EditorGridPanel in which after the store is reloaded - I would like it to preserve the scroll position of the grid rather than sending it back up to the top.
Because this is an earlier version of ExtJS - this DOES NOT work:
viewConfig: {
preserveScrollOnRefresh: true
}
So far the only thing I can come up with is to save the position of the scroll bar prior to loading - and then reset the position once the reload is complete.
I can get as far as saving the position:
var scrollPos;
bodyscroll: function(sl, st) {
scrollPos = st;
},
However I can't figure out how to set the position afterwards.
Any suggestions?
Thanks in advance.
There might be multiple ways to do this but one way is to use the scroller element, which is accessible through the grid's gridview. See fiddle here: Grid scoll save/restore.
To get scroll value (which you've already got figured out):
var top = grid.getView().scroller.getScroll().top;
To restore:
grid.getView().scroller.scrollTo('top',top);

Can QML drag-and-drop mechanic work without drag item moving?

I have a listview and a rectangle on top of it. The ListView's delegates have DropAreas in them and the rectangle has drag enabled on Y axis with its relevant properties (hotspot, target).
When I move the rectangle up and down on the ListView, the DropAreas of the delegates are registering onEntered signals. Working as intended.
However, I am using SmoothedAnimation to scroll the list up and down when the rectangle is at the most top and bottom coordinates (list.y = 0 and list.height). So the rectangle is not moving, and the DropAreas of the list's delegates are moving under it. In that case, the onEntered is not registered because there is no dragging, the rectangle is completely still and although its hotspot is entering and leaving the DropAreas, there is no interaction.
This is because dragging mechanic is sending events all the time when moving and any DropAreas it comes inside can register the event. In my case there is no dragging and therefore no events.
Question: Can drag events be manually activated? Can I somehow simulate drag?
At first, you should change the drag.target: parent to drag.target: this. In this way instead of dragging the parent item, you drag only the mouseArea. After that, you should grab an image from the item that you want to drag. The code is here:
Rectangle {
id: rec
width: 100
height: 100
Drag.active: dragArea.drag.active
Drag.dragType: Drag.Automatic
Drag.supportedActions: Qt.CopyAction
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: this
onPressed:{
parent.grabToImage(function(result) {
parent.Drag.imageSource = result.url
})
}
}
}
I have managed to induce drag events by manually changing the hotSpot property of the rectangle above the list. QML Drag documentation says:
Changes to hotSpot trigger a new drag move with the updated position.
So I have done this every time Listview contentY changes (vertical scrolling happens)
onContentYChanged:
{
rectangle.Drag.hotSpot.x += 0.0001
rectangle.Drag.hotSpot.x -= 0.0001
}
In hindsight, however, this is a 'hacky' solution. hotSpot property is a QPointF class property (link). This means it can be set using various methods (setX, setY, rx, ry..). For example, this:
rectangle.hotSpot += Qt.point(0,0)
or
rectangle.hotSpot = Qt.point(rectangle.hotSpot.x,rectangle.hotSpot.y)
should work in theory by resetting the hotSpot point when contentY changes, but testing revealed it unfortunately does not trigger a new drag move. (bug or intended, I don't know)
Now some of you that are more into Qt and QML might know more about this and how to properly adress the issue, but the above solution works for me and after testing everything I could imagine to get a cleaner solution, I settled on it.

GWT drag and drop animation

I have a flow panel with many photo-widgets inside (gallery with random number of rows and columns, depends on screen size) for which I want to implement drag and drop behavior to change their order. I am using gwt-dnd library. Its FlowPanelDropController allows you to define your own positioner (delimiter) which shows the candidate location for dropping the dragged widget.
I want this positioner to be the empty space with defined width, and the challenging thing is to implement sliding animation effect for the when positioner is added and removed.
If you are a desktop Picasa app user you know what I mean: the target row slides both sides (little to the left, little to the right) extending the space between the items where you are going to drop a photo.
The whole thing is complex enough, but any help related to how to apply the animation for positioner attach/detach is appreciated. Maybe I need to use a different approach (e.g., use GWT native dnd instead of gwt-dnd lib and no "positioners" at all) if you have any ideas how this could be helpful.
Thanks.
Well, I ended up overriding AbstractPositioningDropController (parent of FlowPanelDropController) and adding some extra features.
1) newPositioner() method now builds the Label, which is vertical space with some small width, height and decoration. This widget's element has constant id (say, "POSITIONER"), which helps to distinguish between multiple positioners if you plan to have several of them while navigating with a drag object over multiple drop targets. Also some transition CSS effects were applied to the Label, which will be responsible for handling animated extension of Label's width.
2) in onEnter() I do the following
...
removePositioner(getPositionerElement());
Widget positioner = newPositioner();
dropTarget.insert(positioner, targetIndex);
animatePositionerExtension();
where getPositionerElement() returns DOM.getElementById(POSITIONER)
At the same time removePositioner(..) resets the id of this element to something abstract and ideally should provide some animation before calling .removeFromParent(). But I didn't have enough time to properly debug this so ended up just removing the old positioner with no animation.
Method animatePositionerExtension() contains the code that changes the width of the positioner widget, so that CSS transition will catch that and provides animation.
All access to positioner widget in the class should be provided through updated methods.
3) onLeave() contains line removePositioner(getPositionerElement());
4) In the end of onMove() I added a couple of lines:
galleryWidget.extendHoveredRow(targetIndex - 1);
animatePositionerExtension();
where extendHoveredRow(hoveredWidgetOrdinal) implemented the logic to "limit" the sliding effect in the single line:
int rowHovered = -1;
public void extendHoveredRow(int hoveredWidgetOrdinal) {
int newRowHovered = getRowByOrdinalHovered(hoveredWidgetOrdinal);
if (rowHovered != newRowHovered) {
// adjust position of items in the previously hovered row
int firstInPreviouslyHoveredRow = (rowHovered - 1) * itemsInARow;
shiftFirstItemLeft(firstInPreviouslyHoveredRow, false);
rowHovered = newRowHovered;
// extend this row
int firstInThisRow = getOrdinalFirstInThisRowByOrdinal(hoveredWidgetOrdinal);
shiftFirstItemLeft(firstInThisRow, true);
}
}
This is in short how I did the thing. And still there's some room for improvements, like adding animated removal.
Again, it's all about overriding DropController and manipulations with elements inside the "gallery" widget. The benefit of this approach is that I remain in the gwt-dnd operations framework, and also reused a bunch of existent code.
Some notes:
CSS transition is not supported in IE pre-9, but this is unrelated to
this topic.
Put a transparent "glass" div on top of the Image widget if you use it
as a face of dragProxy. This will save you tons of time trying to
understand why either setting element's draggable to false, or
calling event.preventDefault() somewhere else, or other workarounds don't work in one or several browsers and the image itself is being dragged instead of the whole dragProxy widget.

ScrolledComposite splits the screen vertically and content is displayed in the right half

I am using the ScrolledComposite for a existing control(with many children) based on the method2 mentioned here :http://www.placelab.org/toolkit/doc/javadoc/org/placelab/util/swt/SwtScrolledComposite.html
The only change is instead of creating a new shell & display I am using the existing control's parent.
I am seeing the scroll bars as expected but the existing control/content is displayed form the centre & not from the start. The first half(vertically split) of the layout is empty & the actual control/content gets displayed in the right-half.
I checked bounds, Origin, size etc. they seem to be fine.
screenshot putup here :http://img818.imageshack.us/i/contentstartsfrommiddle.jpg
Any clues
Thanks in advance
Did you delete the Composite c1? maybe that is in the left side.
You could also provide what is exactly your change to the code.

GTK detecting window resize from the user

In GTK (or pygtk or gtkmm...)
How can I detect that an application window has been manually resized by the user, as is typically done by dragging the window's edge?
I need to find a way to differentiate manual resizes from resizes that originate from gtk, such as changes in window content.
Have you tried connecting to the GDK_CONFIGURE event?
Check out this example under the
"Moving window" section. The example shows a callback doing something when the window is moved, but the configure event is a catch-all for moving, resizing and stack order events.
I managed to pull this off by watching for size_allocate and size_request signals on the GtkWindow. If size_request ever got smaller, I called resize(1,1). If size_allocate was ever bigger than expected, I turned the system off.
One thing I made sure to handle was size_request returning big, then small, and having size_allocate be big and then small. I don't know if this is possible, but I fixed it by making sure to only decrease the expected values for size_allocate when I got a smaller size_allocate, not when I got a smaller size_request.
Make sure that your size_request handler comes after the base class' handler so that you get the right values. I did this by overriding the method and then calling the base class method first.
I've tried this in both 1 and 2 dimensions and it seems to work either way.
In my case I was trying to distinguish between a user resizing a Gtk.Paned from the user resizing the whole window. Both emitted the notify::position signal.
My solution was, since I can't know if the user is resizing the window from the widget, reverse what I wanted to know. Record if the user has re-positioned the widget and ignore updates if the user didn't initiate them on my widget.
That is to say, instead of testing "if window being resized" I recorded the button-press-event and button-release-event's locally so I could instead test "if widget being re-positioned"
from gi.repository import Gtk
class MyPaned(Gtk.Paned):
_user_activated = False
def on_position(self, _, gparamspec):
if self._user_activated:
# widget touched
else:
# window resized (probably)
def on_button_press(self, *_):
self._user_activated = True
def on_button_release(self, *_):
self._user_activated = False
dev __init__(self, *args):
super(MyPaned, self).__init__(*args)
self.connect('notify::position', self.on_position)
self.connect('button-press-event', self.on_button_press)
self.connect('button-release-event', self.on_button_release)
Effectively by recorded when the user started and ended interacting with my widget directly, I could assume the rest of the time was due to the window being resized. (Until I find more cases)
In PyGTK, I've always watched for the expose_event for a window resize, then use the get_allocation method to get the new size.
You may be able to throw something together by using gdk_window_get_root_origin to get the top left corner of the window and gdk_window_get_geometry to get the width and height. Then you could hook a callback into the GDK_BUTTON_PRESS_MASK and check to see if the button press occurs near/on one of the edges of the window.
Of course, this seems quite hackish and it really bothers me that I couldn't find some simple way in the documentation for GdkWindow to do this. There is a gdk_window_begin_resize_drag function which really makes me think there's a cleaner way to do this, but I didn't see anything more obvious than my answer.