I would like to make all the handles in my editor to show even when a given game object is not selected, in such a way that when the mouse point hovers over a given handle it becomes selectable. How can I do this?
See here, how to make custom handles?
There is recommended JetBrains DotPeek.
The most important things to understand are (A) the use of HandleUtility.nearestControl and HandleUtility.hotControl to manage input focus, with IDs generated by GUIUtility.GetControlID() and (B) the way OnSceneGUI is called multiple times for different events requiring very different handling.
Use it like:
void OnSceneGui()
{
MyHandles.DragHandleResult dhResult;
Vector3 newPosition = MyHandles.DragHandle(position, size, Handles.SphereCap, Color.red, out dhResult);
switch (dhResult)
{
case MyHandles.DragHandleResult.LMBDoubleClick:
// do something
break;
}
}
At the beginning of my Gtk-Gdk-Cairo-Pango app, I create the window:
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
First, there is GtkWindow, but gtk_create_window returns GtkWidget, not GtkWindow, why?
Then, some functions, like gdk_window_process_updates(..) require GdkWindow*.
gtk_window_set_geometry_hints() on the other hand requires GtkWindow*.
In documentation there is also GdkWindow* gdk_window_new() that returns GdkWindow.
Sure there is documentation saying:
A GdkWindow is a rectangular region on the screen. It's a low-level
object, used to implement high-level objects such as GtkWidget and
GtkWindow on the GTK+ level. A GtkWindow is a toplevel window, the
thing a user might think of as a "window" with a titlebar and so on; a
GtkWindow may contain many GdkWindow.
But it still does not tell me, when and why I should create Gtk or Gdk windows?
What is the pattern here to follow?
Now you ask, what particular problem I am trying to solve? Sure, I try to draw text using cairo+pango on top of gtk+gdk, right after mouse moves. The problem is that although the actual drawing seems to be fast performing, I cannot get it happen exactly as mouse moves. In my motion_notify_event I just call gtk_widget_queue_draw(GtkWidget) but there is obvious lag behind the actual mouse moving on screen, even if I draw single character it is not aligned with the mouse pointer during the move phase and only catches it after the mouse is stopped.
What I tried is to speed up the update by calling gdk_window_process_updates(GDK_WINDOW(window), false);, the compiler eats it, but I got runtime assertion: Gdk-CRITICAL **: gdk_window_process_updates: assertion 'GDK_IS_WINDOW (window)' failed. I cannot find any information on this macro and how/when to use it.
#include <cairo.h>
#include <gtk/gtk.h>
#define TXT "1234567890"
int X = 0, Y = 0;
static void do_drawing(cairo_t *);
GtkWidget *window;
PangoLayout *layout = 0;
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
gpointer user_data) {
do_drawing(cr);
return FALSE;
}
static void do_drawing(cairo_t *cr) {
if (layout == 0) {
layout = pango_cairo_create_layout (cr);
pango_layout_set_text (layout, TXT, -1);
}
for (int y = 0; y < 2; y++) {
cairo_set_source_rgb (cr, 1, 0, 1);
cairo_move_to (cr, 0+X, 0 + y * 20 + Y);
pango_cairo_show_layout (cr, layout);
}
gtk_widget_queue_draw(window);
}
static gint onmouse(GtkWidget *widget, GdkEventMotion *event) {
X = event->x; Y = event->y;
gtk_widget_queue_draw(widget);
gdk_window_process_updates(GDK_WINDOW(widget), false);
}
int main(int argc, char *argv[]) {
GtkWidget *darea;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_widget_set_events (window, GDK_EXPOSURE_MASK
| GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(window, "motion_notify_event", G_CALLBACK(onmouse), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 5000, 5000);
gtk_window_set_title(GTK_WINDOW(window), "Lines");
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Window managers (X11, Wayland, Windows's user32.dll, and the one in Mac OS X whose name I don't remember) do not (necessarily) provide much functionality on their own. What they give you is:
the ability to create on-screen regions, called windows, which you can draw on, move around, resize, reshape, minimize, hide behind other windows, and control in other basic ways — but the most important of these for our discussion is "draw on"
mouse event handling for windows: notifications when the mouse moves into or out of a window, around inside a window, or when the mouse buttons are clicked when the mouse cursor is over a window
the concept of a window which receives keyboard input (the focused window) and keyboard events for this window: when the user types into a window
miscellaneous other functions (drawing mouse cursors, for instance)
When combined with a facility to do vector graphics and text rendering into a window (which is often provided by other libraries, such as cairo and pango), the GUI toolkit comes into play. This is what takes the window manager window and divides it into all the little controls that you're familiar with: buttons, text fields, lists, tabs, web page renderers, etc.
GTK+ is the GUI toolkit in this case. It provides the plethora of controls that you use in your programs.
When you use a GUI toolkit, you don't typically interact with the window manager directly. So instead, the GUI toolkit provides its own window. When you create a GUI toolkit window, the GUI toolkit creates the underlying window manager window, then takes control of all the drawing and events so that it can handle the work of giving you all those neat controls in that window.
For GTK+, this is GtkWindow.
The designers of GTK+ did not want to have all the window manager interaction code for each individual platform that GTK+ supports in GTK+ itself. Instead, they created a separate library (included with the GTK+ source code), called GDK. GDK provides a consistent portable API around the low-level platform-specific window manager functions.
So GdkWindow is the type that wraps around a window manager window and provides the portable interface that GTK+ uses. When you create a GdkWindow, you're creating one of these low-level window manager windows, not the richer GtkWindow that you place controls on.
X11 has historically been very resource-constraining. GTK+ doesn't create a window manager window for every control; it only creates these for GtkWindow, GtkPopover, and other similar controls that act as what we as users think of as windows.
Armed with all this knowledge, you can now figure the answer to your question: you almost always want to use GtkWindow, and almost never want to use GdkWindow. GdkWindow is only really useful for the implementation of certain GTK+ controls.
And GdkWindow and GtkWindow are NOT interchangeable.
(This is a still-reasonably-accurate oversimplification of what's going on. It does not hold true for all environments. People who write native Windows programs, for instance, generally do create window manager windows for each control, and the window manager provides some basic controls, such as buttons. I may have also gotten some details in the above explanation wrong.)
The separation between GDK and GTK+ also has several other advantages. Adding Wayland support, for instance, did not (as far as I know; I could very well be wrong about this) require many changes to GTK+ itself, and there is a GDK layer called broadway which lets normal GTK+ programs render in a web browser.
Updates, since I seem to be linking this a lot:
There was a time when most GtkWidgets actually had their own GdkWindows; here's what happened. Now, the situation I described is the case.
There's so many questions in there that I'm not going to try answering all.
About latency of drawing: most likely option is that there's a bug or unoptimized code in your implementation: the draw cycle is quite unique in application code in that it really, really needs to be fast...
Things to note:
you call gtk_widget_queue_draw(window) from your draw-event handler: that seems unnecessary
you always redraw on a mouse event without checking if it's really necessary (possibly you do want to queue draw on all motion events: please make sure of that though)
you always redraw the whole widget: this can be very expensive and you shouldn't do it if you only need to change a small area at a time and are doing frequent redraws like you are. See gtk_widget_queue_draw_region ().
drawing text can be expensive: I'm not familiar with the functions you use but you may want to start with just drawing a box or something to see where the problem is
Is there way to implement mouse wheel listener for ScrollPane? I looked at couple of options:
Viewport does not seem to have mouse wheel listener
Played with gef's MouseWheelHelper but the y value only changes when I click within the ScrollPane, not when mouse wheel is scrolled. Although event is being fired.
Also, there is no vertical scroll bar for the ScrollPane by design.
Ok, the magic number here is org.eclipse.swt.widgets.Event.count. This number tells you "number of lines or pages to scroll using the mouse wheel". Combining this and MouseWheelHelper interface I was able to make the scroll with mouse wheel work:
public class MyEditPart extends TreeEditPart implements MouseWheelHelper{
private static final int SCROLL_OFFSET = 10;
...
...
#Override
public void handleMouseWheelScrolled(Event event) {
pane.scrollVerticalTo(pane.getViewport().getVerticalRangeModel().getValue() + (event.count * SCROLL_OFFSET));
}
}
What's neat is that by changing SCROLL_OFFSET I can control the speed with which Viewport scrolls.
The only thing to check is definition of Event.count that says:
depending on the event type, the number of following
paint events that are pending which may always be zero
on some platforms, or the number of lines or pages to
scroll using the mouse wheel, or the number of times the
mouse has been clicked
Not sure how this will play out on other OSes.
I am using the wonderful GWTQuery library to add drag drop support to my GWT cell widgets.
I have a CellTable, and a CellTree both in different modules of my application (I am using GWTP, so everything is decoupled). Neither of these widgets are allowed to know about each other, they simply accept draggables/droppables, check the underlying datatype and then handle them appropriately.
The problem I am having is that I need to support dragging "in between" my cell tree nodes. IE: The typical functionality where if you drag directly over an element in the tree, it drops into that element, BUT if you drag just slightly below or above, you are given a visual indicator (usually a horizontal line) that indicates to the user they can drag the current item in between nodes as well.
And here-in lies the problem, thus far I have no found a way to provide this functionality becuase the setOnDrag() method does not tell me anything about detected droppables, and setOnOver only fires once when it first encounters a droppable.
So far as I can tell this leaves me with only two options:
1.) Add extra "invisible" nodes into my CellTree which are also droppable and sit in between my other nodes.
2.) Implement some custom event handler which I attach to the helper draggable before drag start and use to compare positions of the helper and the droppable once the draggable is actually over the droppable.
Option 1 is really unsavory because it seriously mucks up my CellTree design, and potentially impacts efficiency pretty badly.
Option 2 is really unsavory because it requires a lot of extra code and hacks to get it to work just right.
So I am hoping there is an Option 3 which I might not have though of, any help would be much appreciated.
Cheers,
Casey
I think I have found a solution although it may not be the best, but it is working for me at the moment. In the setOnDrag method, I determine where the item is being dragged at which point I can either add a line before or after the element, or put some css on the element to denote that I am dropping the dragged item on top. I create a GQuery place holder to show the before/after line, and putting a border around element with css for dropping on top.
To know which element I am dropping on top of, I set a global variable in the setOnOver method. Here is a simple mock up:
private GQuery placeHolder = $("<div id='cellPlaceHolder' style=' outline: thin dashed #B5D5FF; height: 2px; background:#B5D5FF;'></div> ");
private Element oldEl = null;
options.setOnOver(new DroppableFunction() {
#Override
public void f(DragAndDropContext context) {
oldEl = context.getDroppable();
}
});
options.setOnDrag(new DragFunction() {
#Override
public void f(DragContext context) {
if (oldEl != null) {
int difference = Math.abs(oldEl.getAbsoluteTop() - context.getHelperPosition().top);
if (difference > 0 && difference < 16) {
/* dragging on top edge, so insert place holder */
oldEl.getFirstChildElement().getStyle().clearProperty("border");
placeHolder.insertBefore(oldEl.getFirstChildElement());
} else if (difference > 26 && difference < 53) {
/* dragging on bottom edge, so insert place holder */
oldEl.getFirstChildElement().getStyle().clearProperty("border");
placeHolder.insertAfter(oldEl.getFirstChildElement());
}else if (difference > 15 && difference < 27) {
/* dragging in middle so add border */
placeHolder.remove();
oldEl.getFirstChildElement().getStyle().setProperty("border", "2px solid red");
}
}
}
});
This way uses several global variables, but it seems to be the best method I have found since the drag options do not include info about the droppable element. And you will have to add the logic to know if it is being dropped before/after/or on and do what you want with it at that point.
I Created a window and vbox with 3 buttons in Glade. All buttons have connected "Clicked" event to same handler. Handler looks like this:
CLICKED_btn(GtkObject *object, gpointer user_data)
{
g_print("CLICKED\n");
}
CLICKED appears on terminal for any click to any button.
Is here a way, through object or other to know which button invokes event Clicked in case where all buttons uses same handler?
The object parameter refers to the object that generates the event, in your case the button. Then you can use gtk_widget_get_name() or any other GtkObject/GtkWidget/GtkButton function to make a difference.
UPDATE:
As it seems, newer versions of GTK/Glade do not set the name of the widgets to their id, so it is left to the default, that is the name of the type. In order to get the id of the object you can use the function gtk_buildable_get_name() that works with any buildable object.
With that you'll get button1, button2 or whatever name you put to these buttons.
Please, do not use the label to make a difference between the buttons. Yes, it works, but it is a bad habit: hard to maintain, bad with internationalization, and defeats the main purpose of Glade: to have the interface and the code separated.
First use the documentation to have the right prototype for the "clicked" signal of a GtkButton.
You then know that your callback's prototype should look like:
void on_button_cliked (GtkButton *button, gpointer user_data)
The button parameter is the object which received the signal, ie. the button on which you clicked.