Finding children of a GtkWidget - gtk

I need to be able to explore a GTK GUI's structure programmatically. I have the GtkWidget and I want to find any children of that widget. Now I know that GtkContainer's have a function to find children and that GtkContainer is derived from GtkWidget.
Is there anyway I can check if a widget is a GtkContainer and then perform the cast? If not, is there any other way I can discover the GtkWidget's that are children of the one I have?

Yes, there are macros for every GObject type to check whether an object is of that type:
if(GTK_IS_CONTAINER(widget)) {
GList *children = gtk_container_get_children(GTK_CONTAINER(widget));
...
}
If the widget is a GtkBin it has only one child. In that case, the following is simpler than dealing with a GList:
if(GTK_IS_BIN(widget)) {
GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget));
...
}

In the following code I have implemented find_child function which recursively searches for the widget by name. Ideas build on the answer of #ptomato and from the following PHP example:
#include <gtk/gtk.h>
GtkWidget*
find_child(GtkWidget* parent, const gchar* name)
{
if (g_strcasecmp(gtk_widget_get_name((GtkWidget*)parent), (gchar*)name) == 0) {
return parent;
}
if (GTK_IS_BIN(parent)) {
GtkWidget *child = gtk_bin_get_child(GTK_BIN(parent));
return find_child(child, name);
}
if (GTK_IS_CONTAINER(parent)) {
GList *children = gtk_container_get_children(GTK_CONTAINER(parent));
while ((children = g_list_next(children)) != NULL) {
GtkWidget* widget = find_child(children->data, name);
if (widget != NULL) {
return widget;
}
}
}
return NULL;
}
int
main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *frame = gtk_frame_new(NULL);
GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
GtkWidget *textView = gtk_text_view_new();
GtkWidget *hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
GtkWidget *button1 = gtk_button_new_with_label("button1");
gtk_widget_set_name(button1, "btn1");
GtkWidget *button2 = gtk_button_new_with_label("button2");
gtk_widget_set_name(button2, "btn2");
gtk_window_set_title(GTK_WINDOW(window), "Hello");
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
gtk_window_set_default_size(GTK_WINDOW(window), 450, 400);
gtk_container_add(GTK_CONTAINER(window), frame);
gtk_container_add(GTK_CONTAINER(frame), vbox1);
gtk_box_pack_start(GTK_BOX(vbox1), textView, 1, 1, 0);
gtk_box_pack_start(GTK_BOX(vbox1), hbox1, 0, 1, 0);
gtk_box_pack_start(GTK_BOX(hbox1), button1, 0, 1, 0);
gtk_box_pack_start(GTK_BOX(hbox1), button2, 0, 1, 0);
gtk_widget_show_all(window);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
GtkWidget* child = find_child(window, "btn2");
if (child == button2) {
g_print("found it!\n");
} else {
g_print("not found it!\n");
}
gtk_main();
return 0;
}

I created these functions that are based on the same principal as the accepted answer.
In find_child_by_index, depth is equal to the amount of indices you need to pass. The first index is for the children of parent, the second index is for the grandchildren and so forth.
void print_children_helper(GtkWidget* parent, int indent_size, int depth)
{
for (int i = 0; i < depth * indent_size; i++)
printf(" ");
printf("%s\n", gtk_widget_get_name(parent));
GList* children = NULL;
if (GTK_IS_CONTAINER(parent))
children = gtk_container_get_children(GTK_CONTAINER(parent));
while (children != NULL)
{
print_children(children->data, indent_size, depth + 1);
children = children->next;
}
}
void print_children(GtkWidget* parent, int indent_size)
{
print_children_helper(parent, indent_size, 0);
}
GtkWidget* find_child_by_name(GtkWidget* parent, const gchar* name)
{
if (g_strcmp0(gtk_widget_get_name(parent), name) == 0)
return parent;
GList* children = NULL;
if (GTK_IS_CONTAINER(parent))
children = gtk_container_get_children(GTK_CONTAINER(parent));
while (children != NULL)
{
GtkWidget* widget = find_child_by_name(children->data, name);
if (widget != NULL)
return widget;
children = children->next;
}
return NULL;
}
GtkWidget* find_child_by_index(GtkWidget* parent, int depth, ...)
{
va_list argp;
va_start(argp, depth);
for (int i = 0; i < depth; i++)
{
int index = va_arg(argp, int);
GList* children = NULL;
if (GTK_IS_CONTAINER(parent))
children = gtk_container_get_children(GTK_CONTAINER(parent));
for (int j = 0; j < index; j++)
if (children != NULL)
children = children->next;
if (children != NULL)
parent = children->data;
else
return NULL;
}
va_end(argp);
return parent;
}

A different approach is needed if using GTK4 as GtkContainer no longer exists. See migration guide
A simple function traversing the widget heirarchy:
void print_widget_names(GtkWidget* parent, int level) {
for (int i=0; i < level; i++) {
g_print(" ");
}
level++;
g_print("%s\n", gtk_widget_get_name(GTK_WIDGET(parent)));
GtkWidget *widget = gtk_widget_get_first_child(GTK_WIDGET(parent));
GtkWidget *next;
if (widget != NULL) {
print_widget_names(widget, level);
while ((next = gtk_widget_get_next_sibling(widget)) != NULL) {
widget = next;
print_widget_names(widget, level);
}
}
}

Related

Is it possible to use GtkPopover while writing a xfce4 panel plugin

I am trying to write a plugin for xfce4 panel. It should show a popup with complex container like GtkBox.
My code in vala is:
using Xfce;
public class ButtonPlugin : Xfce.PanelPlugin {
private Gtk.MenuButton button;
private Gtk.Popover popover;
public override void #construct () {
button = new Gtk.MenuButton();
popover = new Gtk.Popover(button);
button.set_image(
new Gtk.Image.from_icon_name (
"open-menu-symbolic",
Gtk.IconSize.LARGE_TOOLBAR
)
);
var menu_container = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
menu_container.pack_start(new Gtk.Label("Hello World 1"));
menu_container.pack_start(new Gtk.Label("Hello World 2"));
menu_container.pack_start(new Gtk.Label("Hello World 3"));
popover.add(menu_container);
popover.show_all ();
popover.hide();
button.popover = popover;
add (button);
//button.show ();
add_action_widget (button);
save.connect (() => { message ("save yourself"); });
free_data.connect (() => { message ("free yourself"); });
size_changed.connect (() => { message ("panel size changed"); return false; });
menu_show_about ();
about.connect (() => {
Gtk.show_about_dialog (null,
"program-name", "Button",
"comments", "Test plugin for the Xfce 4.14 Panel",
null);
});
destroy.connect (() => { Gtk.main_quit (); });
show_all();
}
}
[ModuleInit]
public Type xfce_panel_module_init (TypeModule module) {
return typeof (ButtonPlugin);
}
The plugin starts, but doesn't show the popover when clicked.
Is it possible using Popover or should I switch to another widget ?
From what I understand, no, popovers won't work in Xfce panel plugins.
Take a look at this gist: https://gist.github.com/andreldm/83c9b99e7aa133c924fb4165acc8427a
The standalone app shows the popover correctly, but try making the window as small as the button, there is no room left for the popover, that's the same problem in a panel plugin. If I'm not mistaken context menus work because they are completely new windows while popover aren't.
In the same gist you can find a diff against xfce4-sample-plugin with code similar to what you are trying.
Popover is not designed to work as a standalone menu.
It does not have it's own window.
There has to be a window and popover has to be attached to the widget.
Let's say dummy widget as a 1x1 pixel transparent image.
This is a standalone (sort of) popover in C:
#include <gtk/gtk.h>
/* save this file as standalone-popover.c
create a 1x1 pixel transparent png image in the same folder
and name it dummy.png
compile with:
gcc standalone-popover.c -o standalone-popover `pkg-config --cflags --libs gtk+-3.0`
*/
#define DUMMY_PNG "dummy.png"
void destroy(GtkWidget* widget, gpointer data)
{
gtk_main_quit();
}
int main(int argc, char* argv[])
{
GtkWidget *window;
GtkWidget *popover;
GtkWidget *dummy_png_top_left;
GtkWidget *dummy_png_top_center;
GtkWidget *dummy_png_top_right;
GtkWidget *box;
GtkWidget *dummy_box_top;
GtkWidget *label;
GtkWidget *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_type_hint (GTK_WINDOW(window),
GDK_WINDOW_TYPE_HINT_POPUP_MENU);
gtk_widget_set_size_request(window, 250, 220);
gtk_window_set_resizable (GTK_WINDOW(window), TRUE);
gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
gtk_window_stick (GTK_WINDOW (window));
gtk_window_set_decorated (GTK_WINDOW(window), FALSE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
gtk_widget_set_events (window, GDK_FOCUS_CHANGE_MASK);
g_signal_connect(window, "destroy",
G_CALLBACK(destroy), NULL);
g_signal_connect (G_OBJECT (GTK_WINDOW (window)),
"focus-out-event",
G_CALLBACK (destroy),
NULL);
gtk_window_present (GTK_WINDOW(window));
gtk_container_set_border_width(GTK_CONTAINER(window), 20);
dummy_png_top_left = gtk_image_new_from_file (DUMMY_PNG);
dummy_png_top_center = gtk_image_new_from_file (DUMMY_PNG);
dummy_png_top_right = gtk_image_new_from_file (DUMMY_PNG);
dummy_box_top = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_set_homogeneous (GTK_BOX (dummy_box_top), TRUE);
gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_left, TRUE, FALSE, 0);
gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_center, TRUE, FALSE, 0);
gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_right, TRUE, FALSE, 0);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
gtk_widget_show(dummy_png_top_left);
gtk_widget_show(dummy_png_top_center);
gtk_widget_show(dummy_png_top_right);
label = gtk_label_new ("Standalone GtkPopover");
button = gtk_button_new_with_label("OK");
gtk_box_pack_start (GTK_BOX(box), dummy_box_top, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX(box), label, TRUE, FALSE, 10);
gtk_box_pack_start (GTK_BOX(box), button, TRUE, FALSE, 10);
/* here we use the dummy widget to position the popover arrows */
popover = gtk_popover_new(dummy_png_top_center);
gtk_container_add(GTK_CONTAINER(window), popover);
gtk_container_add(GTK_CONTAINER(popover), box);
gtk_popover_set_modal(GTK_POPOVER(popover), FALSE);
g_signal_connect(G_OBJECT(button),
"clicked",
G_CALLBACK(destroy),
window);
gtk_widget_show_all(window);
/* need this to focus a window */
gtk_window_present_with_time(GTK_WINDOW(window),GDK_CURRENT_TIME);
gtk_window_activate_focus (GTK_WINDOW (window));
gtk_widget_grab_focus(GTK_WIDGET(window));
gtk_main();
return 0;
}
What adds more complications are the arrows.
You have to calculate where to position the window next to the panel plugin button.
Above that you have to position the arrow correctly which does not look so easy.
https://www.youtube.com/watch?v=eXZzwDDQlZ8
Perhaps putting 8 or more dummy images around the popover and point to them depending on the panel's orientation and plugin's position on the screen.
The code in the video:
/*
* Copyright © 2020 misko_2083
*
* Distributed under terms of the GPL2 license.
*
* Compile:
* gcc -Wall -s -shared -fPIC -g desktop-icons-applet.c -o desktop-icons-applet $(pkg-config --libs --cflags gtk+-3.0 libxfce4panel-2.0 libxfconf-0)
* move to lib dir (Debian 64bit here):
* mv libdicons.so /usr/lib/x86_64-linux-gnu/xfce4/panel/plugins/libdicons.so
*/
#include <libxfce4util/libxfce4util.h>
#include <libxfce4panel/xfce-panel-plugin.h>
#include <xfconf/xfconf.h>
#define DEFAULT_ICON_NAME "emblem-desktop"
#define DEFAULT_TOOLTIP_MESSAGE "Show/Hide Desktop Icons"
#define DEFAULT_TITLE "dicons"
#define XFCE_PLUGIN_VERSION "0.1"
/* change the path here to a 1 pixel transparent png */
#define DUMMY_PNG "/home/misko/Desktop/null.png"
typedef struct _DiconsPlugin {
XfcePanelPlugin *plugin;
GtkWidget *button;
GtkWidget *icon;
GtkWidget *window;
GtkWidget *popover;
GtkWidget *dummy_png_top_left;
GtkWidget *dummy_png_top_center;
GtkWidget *dummy_png_top_right;
GtkWidget *dummy_png_bottom_left;
GtkWidget *dummy_png_bottom_center;
GtkWidget *dummy_png_bottom_right;
gchar *icon_name;
} DiconsPlugin;
static void
button_clicked (GtkWidget *button,
DiconsPlugin *dicons);
static gboolean
on_popup_focus_out (GtkWidget *widget,
GdkEventFocus *event,
gpointer data);
static gboolean
on_key_pressed (GtkWidget *widget,
GdkEventKey *event,
gpointer data);
static const char dicons_plugin_copyright[] =
"Copyright \xc2\xa9 2020 Miloš Pavlović\n";
static void dicons_about(XfcePanelPlugin *plugin)
{
const gchar *auth[] = { "Miloš Pavlović", NULL };
GdkPixbuf *icon;
icon = xfce_panel_pixbuf_from_source("emblem-desktop", NULL, 32);
gtk_show_about_dialog(NULL,
"logo", icon,
"license", xfce_get_license_text(XFCE_LICENSE_TEXT_GPL),
"version", XFCE_PLUGIN_VERSION,
"program-name", "dicons-applet",
"comments", _("Opens a configuration menu for desktop icons"),
"website", "https://github.com/Misko-2083",
"copyright", _(dicons_plugin_copyright),
"authors", auth,
NULL);
if (icon)
g_object_unref(G_OBJECT(icon));
}
static void
_quit_cb (GtkWidget *button, GtkWidget *window, gpointer data)
{
(void)data; /* Avoid compiler warnings */
gtk_widget_hide (window);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
return;
}
static gboolean
on_popup_focus_out (GtkWidget *widget,
GdkEventFocus *event,
gpointer data)
{
gtk_widget_hide (widget);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), FALSE);
return TRUE;
}
static gboolean
on_key_pressed (GtkWidget *widget,
GdkEventKey *event,
gpointer data)
{
if (event->keyval == GDK_KEY_Escape){
gtk_widget_hide (widget);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), FALSE);
return TRUE;
}
return FALSE;
}
static gboolean
on_switch_home (GtkWidget *widget,
gboolean *state,
gpointer user_data)
{
XfconfChannel *channel;
xfconf_init(NULL);
channel = xfconf_channel_get("xfce4-desktop");
if (state)
xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-home", TRUE);
else
xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-home", FALSE);
xfconf_shutdown();
return FALSE;
}
static gboolean
on_switch_trash (GtkWidget *widget,
gboolean *state,
gpointer user_data)
{
XfconfChannel *channel;
xfconf_init(NULL);
channel = xfconf_channel_get("xfce4-desktop");
if (state)
xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-trash", TRUE);
else
xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-trash", FALSE);
xfconf_shutdown();
return FALSE;
}
static gboolean
on_switch_filesystem (GtkWidget *widget,
gboolean *state,
gpointer user_data)
{
XfconfChannel *channel;
xfconf_init(NULL);
channel = xfconf_channel_get("xfce4-desktop");
if (state)
xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-filesystem", TRUE);
else
xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-filesystem", FALSE);
xfconf_shutdown();
return FALSE;
}
static gboolean
on_switch_removable (GtkWidget *widget,
gboolean *state,
gpointer user_data)
{
XfconfChannel *channel;
xfconf_init(NULL);
channel = xfconf_channel_get("xfce4-desktop");
if (state)
xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-removable", TRUE);
else
xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-removable", FALSE);
xfconf_shutdown();
return FALSE;
}
static gboolean dicons_size_changed (XfcePanelPlugin *plugin,
gint size,
DiconsPlugin *dicons)
{
XfceScreenPosition position;
position = xfce_panel_plugin_get_screen_position(plugin);
if (xfce_screen_position_is_horizontal(position)) {
/* horizontal */
if (xfce_screen_position_is_top(position)) {
/* top panel position */
gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_top_left);
}
if (xfce_screen_position_is_bottom(position)) {
/* bottom */
gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_bottom_left);
}
if (xfce_screen_position_is_floating(position)) {
/* floating */
gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_top_left);
/* TO DO: check if the button is in the top or bottom side
* of the screen and set the correct dummy widget
*/
}
} else {
/* vertical */
if (xfce_screen_position_is_left(position)) {
/* left */
gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_top_left);
}
if (xfce_screen_position_is_right(position)) {
/* right */
gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_top_left);
}
if (xfce_screen_position_is_floating(position)) {
/* floating */
gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_bottom_left);
/* TO DO: check if the button is in the left or right side
* of the screen and set the correct dummy widget
*/
}
}
size = size / xfce_panel_plugin_get_nrows(plugin);
gtk_widget_set_size_request (GTK_WIDGET (plugin), size, size);
return TRUE;
}
static void button_clicked(GtkWidget *button,
DiconsPlugin *dicons)
{
gint x, y;
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dicons->button)))
{
dicons_size_changed(dicons->plugin, xfce_panel_plugin_get_size (dicons->plugin), dicons);
xfce_panel_plugin_block_autohide(dicons->plugin, TRUE);
if (GTK_IS_TOGGLE_BUTTON (button)) {
xfce_panel_plugin_position_widget(XFCE_PANEL_PLUGIN (dicons->plugin),
GTK_WIDGET(dicons->window),
button, &x, &y);
} else {
GdkDisplay *display = gdk_display_get_default();
GdkSeat *seat = gdk_display_get_default_seat(display);
GdkDevice *device = gdk_seat_get_pointer(seat);
gdk_window_get_device_position(gdk_get_default_root_window(),
device, &x, &y, NULL);
}
gtk_popover_popup(GTK_POPOVER(dicons->popover));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dicons->button), TRUE);
if (!gtk_widget_get_mapped(dicons->window))
gtk_widget_show_all(GTK_WIDGET(dicons->window));
gtk_window_move (GTK_WINDOW(dicons->window), x, y);
/* fix me: this function is called twice */
} else {
_quit_cb(dicons->button, dicons->window, NULL);
if (GTK_IS_TOGGLE_BUTTON (button))
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
xfce_panel_plugin_block_autohide(dicons->plugin, FALSE);
gtk_popover_popdown(GTK_POPOVER(dicons->popover));
}
}
static DiconsPlugin *dicons_init(XfcePanelPlugin *plugin)
{
GtkWidget *box;
GtkWidget *box_a;
GtkWidget *box_b;
GtkWidget *boxl;
GtkWidget *about_button;
GtkWidget *cancel_button;
GtkWidget *question;
GtkWidget *label_home;
GtkWidget *label_trash;
GtkWidget *label_filesystem;
GtkWidget *label_removable;
GtkWidget *image;
GtkWidget *switch_home;
GtkWidget *switch_trash;
GtkWidget *switch_filesystem;
GtkWidget *switch_removable;
GdkWindow *pwindow;
GtkWidget *dummy_box_top;
GtkWidget *dummy_box_bottom;
XfconfChannel *channel;
DiconsPlugin *dicons = g_slice_new0(DiconsPlugin);
dicons->plugin = plugin;
dicons->icon_name = g_strdup(DEFAULT_ICON_NAME);
dicons->button = xfce_panel_create_toggle_button();
xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (dicons->plugin),
dicons->button);
gtk_init(NULL, NULL);
dicons->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_type_hint (GTK_WINDOW(dicons->window),
GDK_WINDOW_TYPE_HINT_POPUP_MENU);
gtk_widget_set_size_request(dicons->window, 250, 220);
gtk_window_set_resizable (GTK_WINDOW(dicons->window), TRUE);
gtk_window_set_keep_above (GTK_WINDOW (dicons->window), TRUE);
gtk_window_stick (GTK_WINDOW (dicons->window));
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dicons->window), TRUE);
gtk_window_set_title (GTK_WINDOW (dicons->window), "Desktop Icons");
gtk_widget_set_events (dicons->window, GDK_FOCUS_CHANGE_MASK);
g_signal_connect (G_OBJECT (GTK_WINDOW (dicons->window)),
"focus-out-event",
G_CALLBACK (on_popup_focus_out),
dicons->button);
gtk_widget_set_events (GTK_WIDGET(dicons->window), GDK_KEY_PRESS_MASK);
g_signal_connect (G_OBJECT (GTK_WINDOW (dicons->window)),
"key-press-event",
G_CALLBACK (on_key_pressed),
dicons->button);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
box_a = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
box_b = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
boxl = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
image = gtk_image_new_from_icon_name (dicons->icon_name,
GTK_ICON_SIZE_DND);
question = gtk_label_new ("\nDesktop Icons");
label_home = gtk_label_new ("Home");
label_trash = gtk_label_new ("Trash");
label_filesystem = gtk_label_new ("Filesystem");
label_removable = gtk_label_new ("Removable");
switch_home = gtk_switch_new ();
switch_trash = gtk_switch_new ();
switch_filesystem = gtk_switch_new ();
switch_removable = gtk_switch_new ();
g_signal_connect (G_OBJECT (switch_home),
"state-set",
G_CALLBACK (on_switch_home),
NULL);
g_signal_connect (G_OBJECT (switch_trash),
"state-set",
G_CALLBACK (on_switch_trash),
NULL);
g_signal_connect (G_OBJECT (switch_filesystem),
"state-set",
G_CALLBACK (on_switch_filesystem),
NULL);
g_signal_connect (G_OBJECT (switch_removable),
"state-set",
G_CALLBACK (on_switch_removable),
NULL);
xfconf_init(NULL);
channel = xfconf_channel_get("xfce4-desktop");
/* set initial switches */
if (xfconf_channel_get_bool(channel, "/desktop-icons/file-icons/show-home", TRUE))
gtk_switch_set_state (GTK_SWITCH(switch_home), TRUE);
else
gtk_switch_set_state (GTK_SWITCH(switch_home), FALSE);
if (xfconf_channel_get_bool(channel, "/desktop-icons/file-icons/show-trash", TRUE))
gtk_switch_set_state (GTK_SWITCH(switch_trash), TRUE);
else
gtk_switch_set_state (GTK_SWITCH(switch_trash), FALSE);
if (xfconf_channel_get_bool(channel, "/desktop-icons/file-icons/show-filesystem", TRUE))
gtk_switch_set_state (GTK_SWITCH(switch_filesystem), TRUE);
else
gtk_switch_set_state (GTK_SWITCH(switch_filesystem), FALSE);
if (xfconf_channel_get_bool(channel, "/desktop-icons/file-icons/show-removable", TRUE))
gtk_switch_set_state (GTK_SWITCH(switch_removable), TRUE);
else
gtk_switch_set_state (GTK_SWITCH(switch_removable), FALSE);
xfconf_shutdown();
dicons->dummy_png_top_left = gtk_image_new_from_file (DUMMY_PNG);
dicons->dummy_png_top_center = gtk_image_new_from_file (DUMMY_PNG);
dicons->dummy_png_top_right = gtk_image_new_from_file (DUMMY_PNG);
dummy_box_top = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start (GTK_BOX(dummy_box_top), dicons->dummy_png_top_left, TRUE, FALSE, 0);
gtk_box_pack_start (GTK_BOX(dummy_box_top), dicons->dummy_png_top_center, TRUE, FALSE, 0);
gtk_box_pack_start (GTK_BOX(dummy_box_top), dicons->dummy_png_top_right, TRUE, FALSE, 0);
dicons->dummy_png_bottom_left = gtk_image_new_from_file (DUMMY_PNG);
dicons->dummy_png_bottom_center = gtk_image_new_from_file (DUMMY_PNG);
dicons->dummy_png_bottom_right = gtk_image_new_from_file (DUMMY_PNG);
dummy_box_bottom = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start (GTK_BOX(dummy_box_bottom), dicons->dummy_png_bottom_left, TRUE, FALSE, 0);
gtk_box_pack_start (GTK_BOX(dummy_box_bottom), dicons->dummy_png_bottom_center, TRUE, FALSE, 0);
gtk_box_pack_start (GTK_BOX(dummy_box_bottom), dicons->dummy_png_bottom_right, TRUE, FALSE, 0);
gtk_widget_show(dicons->dummy_png_top_left);
gtk_widget_show(dicons->dummy_png_top_center);
gtk_widget_show(dicons->dummy_png_top_right);
gtk_widget_show(dicons->dummy_png_bottom_left);
gtk_widget_show(dicons->dummy_png_bottom_center);
gtk_widget_show(dicons->dummy_png_bottom_right);
dicons->popover = gtk_popover_new(dicons->dummy_png_top_left);
gtk_popover_set_constrain_to(GTK_POPOVER(dicons->popover), GTK_POPOVER_CONSTRAINT_NONE);
/* modal blocks the panel preferences process,
* it needs to be set to FALSE */
gtk_popover_set_modal(GTK_POPOVER(dicons->popover), FALSE);
gtk_container_add(GTK_CONTAINER(dicons->window), dicons->popover);
gtk_container_add(GTK_CONTAINER(dicons->popover), boxl);
gtk_box_pack_start (GTK_BOX(box_a), label_home, TRUE, TRUE, 10);
gtk_box_pack_start (GTK_BOX(box_a), switch_home, FALSE, TRUE, 10);
gtk_box_pack_start (GTK_BOX(box_a), label_trash, TRUE, TRUE, 10);
gtk_box_pack_start (GTK_BOX(box_a), switch_trash, FALSE, TRUE, 10);
gtk_box_pack_start (GTK_BOX(box_b), label_filesystem, TRUE, TRUE, 10);
gtk_box_pack_start (GTK_BOX(box_b), switch_filesystem, FALSE, TRUE, 10);
gtk_box_pack_start (GTK_BOX(box_b), label_removable, TRUE, TRUE, 10);
gtk_box_pack_start (GTK_BOX(box_b), switch_removable, FALSE, TRUE, 10);
about_button = gtk_button_new_with_label("About");
cancel_button = gtk_button_new_with_label("Cancel");
g_signal_connect(G_OBJECT(cancel_button),
"clicked",
G_CALLBACK(_quit_cb),
dicons->window);
g_signal_connect(G_OBJECT(about_button),
"clicked",
G_CALLBACK(dicons_about),
plugin);
gtk_box_pack_start (GTK_BOX(boxl), dummy_box_top, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX(boxl), image, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX(boxl), question, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX(boxl), box_a, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX(boxl), box_b, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX(box), about_button, TRUE, TRUE, 10);
gtk_box_pack_start (GTK_BOX (box), cancel_button, TRUE, TRUE, 10);
gtk_box_pack_start (GTK_BOX(boxl), box, TRUE, TRUE, 10);
gtk_box_pack_end (GTK_BOX(boxl), dummy_box_bottom, TRUE, TRUE, 0);
gtk_window_set_decorated (GTK_WINDOW(dicons->window), FALSE);
gtk_widget_show(dicons->button);
/*gtk_window_set_attached_to(GTK_WINDOW(dicons->window),
dicons->button);*/
pwindow = gtk_widget_get_parent_window(dicons->button);
gtk_window_set_transient_for(GTK_WINDOW(dicons->window),
GTK_WINDOW(pwindow));
g_signal_connect(G_OBJECT(dicons->button), "toggled",
G_CALLBACK(button_clicked), dicons);
gtk_widget_set_tooltip_text (GTK_WIDGET(dicons->button),
DEFAULT_TOOLTIP_MESSAGE);
dicons->icon = xfce_panel_image_new_from_source(dicons->icon_name);
gtk_widget_show(dicons->icon);
gtk_container_add(GTK_CONTAINER(dicons->button), dicons->icon);
return dicons;
}
static void dicons_free(XfcePanelPlugin *plugin, DiconsPlugin *dicons)
{
gtk_widget_destroy(dicons->button);
gtk_widget_destroy(dicons->icon);
if (GTK_IS_WIDGET (dicons->window))
gtk_widget_destroy(dicons->window);
if (GTK_IS_WIDGET (dicons->popover))
gtk_widget_destroy(dicons->popover);
g_slice_free(DiconsPlugin, dicons);
}
static void set_button_active (GtkToggleButton *button)
{
if (GTK_IS_TOGGLE_BUTTON(button)) {
if (!gtk_toggle_button_get_active(button)) {
gtk_toggle_button_set_active(button, TRUE);
}
else
{
gtk_toggle_button_set_active(button, FALSE);
}
}
}
static gboolean dicons_remote (XfcePanelPlugin *plugin,
gchar *name,
GValue *value,
DiconsPlugin *dicons)
{
g_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE);
if (strcmp (name, "popup") == 0
&& !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dicons->button))
&& gtk_widget_get_visible (GTK_WIDGET (plugin)) )
{
if (value != NULL
&& G_VALUE_HOLDS_BOOLEAN (value)
&& g_value_get_boolean (value))
{
set_button_active(GTK_TOGGLE_BUTTON(dicons->button));
/* popup here at mouse pointer , where X is an internal id
* xfce4-panel --plugin-event=desktop-icons-applet-X:popup:bool:true
*/
button_clicked(NULL, dicons);
}
else
{
set_button_active(GTK_TOGGLE_BUTTON(dicons->button));
/* popup here, where X is an internal id
* xfce4-panel --plugin-event=desktop-icons-applet-X:popup:bool:false
*/
button_clicked(dicons->button, dicons);
}
return TRUE;
}
return FALSE;
}
static void dicons_construct(XfcePanelPlugin *plugin)
{
DiconsPlugin *dicons;
dicons = dicons_init(plugin);
gtk_container_add(GTK_CONTAINER(plugin), dicons->button);
xfce_panel_plugin_add_action_widget(plugin, dicons->button);
xfce_panel_plugin_menu_show_about(plugin);
g_signal_connect (G_OBJECT(plugin),
"free-data",
G_CALLBACK(dicons_free), dicons);
g_signal_connect (G_OBJECT(plugin),
"size-changed",
G_CALLBACK(dicons_size_changed), dicons);
g_signal_connect (G_OBJECT (plugin),
"remote-event",
G_CALLBACK(dicons_remote), dicons);
g_signal_connect (G_OBJECT (plugin),
"about",
G_CALLBACK (dicons_about), dicons);
}
XFCE_PANEL_PLUGIN_REGISTER(dicons_construct);
And the desktop file
/usr/share/xfce4/panel/plugins/desktop-icons-applet.desktop
[Xfce Panel]
Type=X-XFCE-PanelPlugin
Encoding=UTF-8
Name=Desktop Icons
Comment=Show and Hide desktop icons
Icon=emblem-desktop
X-XFCE-Module=dicons
X-XFCE-Internal=true
X-XFCE-Unique=false
X-XFCE-API=2.0

How to place multiple selected files in the dialog_choose a gtk_tree_view

This code takes a file from dialogo_chosser and adds in a gtk_tree_view...
I would take more files from one gtkfilechosser and add them in a gtk_tree_view...
I saw that you must enter this function:
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE)
but I do not know how to take the selected files :(
I ask "politely" a small example for this solution
my code is:
#include "header.h"
#include <string.h>
#include <gtk/gtk.h>
GtkWidget *list;
GtkWidget *win;
char *filename;
void Add_Items_List(GtkWidget *widget, gpointer data)
{
GtkListStore *store;
GtkTreeIter iter;
store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, filename, -1);
}
void Dialog_Chooser(GtkWidget *widget, gpointer gst)
{
GtkWidget *dialog;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
GtkFileChooser *chooser;
gint res;
dialog = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), action,
"Cancel", GTK_RESPONSE_CANCEL,
"Open", GTK_RESPONSE_ACCEPT, NULL);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if(res == GTK_RESPONSE_ACCEPT){
chooser = GTK_FILE_CHOOSER(dialog);
filename = gtk_file_chooser_get_filename(chooser);
Add_Items_List(NULL, NULL);
g_free(filename);
}
gtk_widget_destroy(dialog);
}
void Delete_Item_List(GtkWidget *widget, gpointer selection)
{
GtkTreeModel *model;
GtkTreeIter iter;
model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
if(gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter)){
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
}
}
void Delete_All_Items_List(GtkWidget *widget, gpointer selection)
{
GtkListStore *store;
GtkTreeIter iter;
store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
gtk_list_store_clear(store);
}
void Inizializes_The_List(GtkWidget *list)
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkListStore *store;
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("Lenguages", renderer, "text", 0, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
store = gtk_list_store_new(1, G_TYPE_STRING);
gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));
g_object_unref(store);
}
void Add_Lista(GtkWidget *list, const gchar *str)
{
GtkListStore *store;
GtkTreeIter iter;
store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, str, -1);
}
int main(int argc, char **argv)
{
GtkWidget *Button_remove;
GtkWidget *button_remove_all;
GtkWidget *button_chosser;
GtkWidget *sw;
GtkWidget *hbox;
GtkWidget *vbox;
GtkTreeSelection *selection;
gtk_init(&argc, &argv);
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(win), "Simple chosser list");
gtk_window_set_default_size(GTK_WINDOW(win), 200, 200);
gtk_container_set_border_width(GTK_CONTAINER(win), 10);
sw = gtk_scrolled_window_new(NULL, NULL);
list = gtk_tree_view_new();
gtk_container_add(GTK_CONTAINER(sw), list);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 5);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
Button_remove = gtk_button_new_with_label("Delete");
button_remove_all = gtk_button_new_with_label("Delte All");
button_chosser = gtk_button_new_with_label("List");
gtk_box_pack_start(GTK_BOX(hbox), Button_remove, FALSE, TRUE, 3);
gtk_box_pack_start(GTK_BOX(hbox), button_remove_all, FALSE, TRUE, 3);
gtk_box_pack_start(GTK_BOX(hbox), button_chosser, FALSE, TRUE, 3);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 3);
gtk_container_add(GTK_CONTAINER(win), vbox);
Inizializes_The_List(list);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
g_signal_connect(G_OBJECT(button_chosser), "clicked", G_CALLBACK(Dialog_Chooser), NULL);
g_signal_connect(Button_remove, "clicked", G_CALLBACK(Delete_Item_List), selection);
g_signal_connect(button_remove_all, "clicked", G_CALLBACK(Delete_All_Items_List), selection);
g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(destroy), NULL);
gtk_widget_show_all(win);
gtk_main();
return 0;
}
ps: use gtk+3 on ubuntu 16.04
For now, I have found this solution:
void Dialog_Chooser(GtkWidget *widget, gpointer gst)
{
GtkWidget *dialog;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
GtkFileChooser *chooser;
gint res;
dialog = gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(win), action, "Cancel",
GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if(res == GTK_RESPONSE_ACCEPT){
GSList *filenamepus;
chooser = GTK_FILE_CHOOSER(dialog);
//filename = gtk_file_chooser_get_filename(chooser);
filenamepus = gtk_file_chooser_get_filenames(chooser);
int nIndex;
GSList *node;
for(nIndex = 0; node = g_slist_nth(filenamepus, nIndex); nIndex++){
filename = (char *) node->data; //g_slist_nth(filenamepus, nIndex);
Add_Items_List(NULL, NULL);
//g_print ("%s\n", filename); //(char *) node->data);
}
//Add_Items_List(NULL, NULL);
g_free(filename);
}
gtk_widget_destroy(dialog);
}
If anyone knows a better solution, I would still love to hear it.

camera preview showing blank screen

public class cameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Activity act;
private int currentCameraId;
private boolean cameraFront;
private boolean InPreview;
//private SurfaceView SV;
public cameraPreview(Context context, Activity A, SurfaceView SFV) {
super(context);
mCamera = null;
mHolder = null;
InPreview = false;
act = A;
mHolder = SFV.getHolder();
mHolder.addCallback(this);
initialzeCamera();
}
private void initialzeCamera()
{
initializeCameraBool();
OpenCamera();
}
public void OpenCamera()
{
if(mCamera==null)
{
Log.e("open", "sesami");
if(cameraFront)
mCamera.open(cameraPreview.findFrontFacingCamera());
else
mCamera.open(cameraPreview.findBackFacingCamera());
}
//StartPreview();
}
private void StartPreview()
{
if (mHolder.getSurface() == null || mCamera == null){
Log.e("Stop", "in the name of the law");
return;
}
Log.e("Started", "from the bottom");
if(InPreview)
{
mCamera.stopPreview();
InPreview = false;
}
setCameraDisplayOrientation();
if(!InPreview)
{
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
InPreview = true;
}
}
public void releaseCamera()
{
if (mCamera != null) {
if(InPreview)
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
public void surfaceCreated(SurfaceHolder holder) {
StartPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
public void setCameraDisplayOrientation() {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(currentCameraId, info);
int rotation = act.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
if(mCamera!=null)
mCamera.setDisplayOrientation(result);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
StartPreview();
}
public static int findBackFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
break;
}
}
return cameraId;
}
public static int findFrontFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
break;
}
}
return cameraId;
}
private void initializeCameraBool()
{
if(cameraPreview.findBackFacingCamera()>=0)
cameraFront = false;
else
cameraFront = true;
}
}
So the surfaceview that I pass in comes from the main activity and it's getting it from the layout. The layout is just a surfaceview. When I launch it though it only shows a black screen. I don't understand why this is happening. It should be launching the preview display but for some reason it doesn't show it.

How to program custom buttons to navigate through scroll view created with Scroll Rect combined with a Mask

I have a shop GUI, its content in a srollview created with Scroll Rect and Mask combination and can be scrolled down and up.
Right now, the scroll view scrolls by clicking and dragging with the mouse anywhere in scroll view area, or by interacting with a vertical scrollbar.
How do I use custom up and down buttons (circled in red on attached image below) to make the scroll happen?
Copy the following script to your project and apply ScrollRectSnap script to your scroll view . Know if you have done this to make your scroll view snap on button click simply do the following link UpArrowPressed and DownArrowPressed with your up and down buttons and do not forget to check Snap In V parameter in inspector of ScrollRectSnap if you have vertical scrollview and also do not get confused by snapper.DraggedOnRight() call in your DownArrowPressed function as if you have checked Snap In V parameter it will then act like snap down and similler thing with snapper.DraggedOnLeft() other parameters you can set according to your requirment you will have to play with values in order to get it according to your requirments.
public void UpArrowPressed()
{
ScrollRectSnap snapper = GetComponentInChildren<ScrollRectSnap>();
snapper.DraggedOnLeft();
}
public void DownArrowPressed()
{
ScrollRectSnap snapper = GetComponentInChildren<ScrollRectSnap>();
snapper.DraggedOnRight();
}
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class ScrollRectSnap : MonoBehaviour
{
float[] points;
[Tooltip("how many screens or pages are there within the content (steps)")]
public int screens = 1;
[Tooltip("How quickly the GUI snaps to each panel")]
public float snapSpeed;
public float inertiaCutoffMagnitude;
float stepSize;
ScrollRect scroll;
bool LerpH;
float targetH;
[Tooltip("Snap horizontally")]
public bool snapInH = true;
bool LerpV;
float targetV;
[Tooltip("Snap vertically")]
public bool snapInV = true;
public string controllTag;
bool dragInit = true;
int dragStartNearest;
float horizontalNormalizedPosition;
float verticalNormalizedPosition;
public static event Action<int,int> OnEndReached;
public static event Action<int,int,string> OnEndReachedWithTag;
// Use this for initialization
void Start()
{
Init();
// SnapToSelectedIndex(0);
}
void Init()
{
scroll = gameObject.GetComponent<ScrollRect>();
scroll.inertia = true;
if (screens > 0)
{
points = new float[screens];
stepSize = (float)Math.Round(1 / (float)(screens - 1),2);
for (int i = 0; i < screens; i++)
{
points[i] = i * stepSize;
}
}
else
{
points[0] = 0;
}
}
void OnEnable()
{
}
void Update()
{
horizontalNormalizedPosition = scroll.horizontalNormalizedPosition;
verticalNormalizedPosition = scroll.verticalNormalizedPosition;
if (LerpH)
{
scroll.horizontalNormalizedPosition = Mathf.Lerp(scroll.horizontalNormalizedPosition, targetH, snapSpeed * Time.deltaTime);
if (Mathf.Approximately((float)Math.Round(scroll.horizontalNormalizedPosition,2), targetH))
{
LerpH = false;
int target = FindNearest(scroll.horizontalNormalizedPosition, points);
// Debug.LogError("Target : " + target);
if (target == points.Length-1)
{
if (OnEndReached != null)
{
OnEndReached(1,target);
}
if(OnEndReachedWithTag != null)
{
OnEndReachedWithTag(1,target,controllTag);
}
}
else if (target == 0)
{
if (OnEndReached != null)
{
OnEndReached(-1,target);
}
if(OnEndReachedWithTag != null)
{
OnEndReachedWithTag(-1,target,controllTag);
}
}
else
{
if (OnEndReached != null)
{
OnEndReached(0,target);
}
if(OnEndReachedWithTag != null)
{
OnEndReachedWithTag(0,target,controllTag);
}
}
}
}
if (LerpV)
{
scroll.verticalNormalizedPosition = Mathf.Lerp(scroll.verticalNormalizedPosition, targetV, snapSpeed * Time.deltaTime);
if (Mathf.Approximately(scroll.verticalNormalizedPosition, targetV))
{
LerpV = false;
}
}
}
public void DragEnd()
{
int target = FindNearest(scroll.horizontalNormalizedPosition, points);
if (target == dragStartNearest && scroll.velocity.sqrMagnitude > inertiaCutoffMagnitude * inertiaCutoffMagnitude)
{
if (scroll.velocity.x < 0)
{
target = dragStartNearest + 1;
}
else if (scroll.velocity.x > 1)
{
target = dragStartNearest - 1;
}
target = Mathf.Clamp(target, 0, points.Length - 1);
}
if (scroll.horizontal && snapInH )
{
targetH = points[target];
LerpH = true;
}
if (scroll.vertical && snapInV && scroll.verticalNormalizedPosition > 0f && scroll.verticalNormalizedPosition < 1f)
{
targetH = points[target];
LerpH = true;
}
dragInit = true;
}
public void OnDrag()
{
if (dragInit)
{
if (scroll == null)
{
scroll = gameObject.GetComponent<ScrollRect>();
}
dragStartNearest = FindNearest(scroll.horizontalNormalizedPosition, points);
dragInit = false;
}
LerpH = false;
LerpV = false;
}
int FindNearest(float f, float[] array)
{
float distance = Mathf.Infinity;
int output = 0;
for (int index = 0; index < array.Length; index++)
{
if (Mathf.Abs(array[index] - f) < distance)
{
distance = Mathf.Abs(array[index] - f);
output = index;
}
}
return output;
}
public void DraggedOnLeft()
{
OnDrag();
if (scroll.horizontal && snapInH && scroll.horizontalNormalizedPosition > -0.001f && scroll.horizontalNormalizedPosition < 1.001f)
{
// Debug.Log("Before Press, LerpH : " + LerpH);
if (dragStartNearest < points.Length-1)
{
targetH = points[dragStartNearest+1];
LerpH = true;
}
else
{
targetH = points[dragStartNearest];
LerpH = true;
}
// Debug.Log("After Press, LerpH : " + LerpH);
}
if (scroll.vertical && snapInV && scroll.verticalNormalizedPosition > 0f && scroll.verticalNormalizedPosition < 1f)
{
if (dragStartNearest < points.Length-1)
{
targetV = points[dragStartNearest+1];
LerpV = true;
}
else
{
targetV = points[dragStartNearest];
LerpV = true;
}
}
dragInit = true;
}
public void DraggedOnRight()
{
OnDrag();
if (scroll.horizontal && snapInH && scroll.horizontalNormalizedPosition > -0.001f && scroll.horizontalNormalizedPosition < 1.001f)
{
if (dragStartNearest>0)
{
targetH = points[dragStartNearest-1];
LerpH = true;
}
else
{
targetH = points[dragStartNearest];
LerpH = true;
}
}
if (scroll.vertical && snapInV && scroll.verticalNormalizedPosition > 0f && scroll.verticalNormalizedPosition < 1f)
{
if (dragStartNearest > 0)
{
targetV = points[dragStartNearest-1];
LerpV = true;
}
else
{
targetV = points[dragStartNearest];
LerpV = true;
}
}
dragInit = true;
}
public void SnapToSelectedIndex(int index)
{
if (points == null)
{
Init();
}
dragInit = false;
LerpH = false;
LerpV = false;
targetH = points[index];
LerpH = true;
dragInit = true;
}
}

SWT : showing animated gif with transparent background

I am trying to show a animated gif which has transparent background. but the result is that the background is not transparent, below is my code, what is wrong with it?
package amarsoft.rcp.base.widgets;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
/**
* 负责显示各种格式的图片
*
* #author ggfan#amarsoft
*/
public class ImageViewer extends Canvas {
protected Point origin = new Point(0, 0);
protected Image image;
protected ImageData[] imageDatas;
protected Image[] images;
protected int current;
private int repeatCount;
private Runnable animationTimer;
private Color bg;
private Display display;
public ImageViewer(Composite parent) {
super(parent,SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
bg = getBackground();
display = getDisplay();
addListeners();
}
public void setImage(ImageData imageData) {
checkWidget();
stopAnimationTimer();
if(imageData != null){
this.image = new Image(display, imageData);
}
this.imageDatas = null;
this.images = null;
redraw();
}
/**
* #param repeatCount
* 0 forever
*/
public void setImages(ImageData[] imageDatas, int repeatCount) {
checkWidget();
this.image = null;
this.imageDatas = imageDatas;
this.repeatCount = repeatCount;
convertImageDatasToImages();
startAnimationTimer();
redraw();
}
#Override
public Point computeSize(int wHint, int hHint, boolean changed) {
checkWidget();
Image image = getCurrentImage();
if (image != null) {
Rectangle rect = image.getBounds();
Rectangle trim = computeTrim(0, 0, rect.width, rect.height);
return new Point(trim.width, trim.height);
}
return new Point(wHint, hHint);
}
#Override
public void dispose() {
if (image != null)
image.dispose();
if (images != null)
for (int i = 0; i < images.length; i++)
images[i].dispose();
super.dispose();
}
protected void paint(Event e) {
Image image = getCurrentImage();
if (image == null)
return;
GC gc = e.gc;
gc.drawImage(image, origin.x, origin.y);
gc.setAntialias(SWT.ON);
//gc.setBackground(bg);
Rectangle rect = image.getBounds();
Rectangle client = getClientArea();
int marginWidth = client.width - rect.width;
if (marginWidth > 0) {
//gc.fillRectangle(rect.width, 0, marginWidth, client.height);
}
int marginHeight = client.height - rect.height;
if (marginHeight > 0) {
//gc.fillRectangle(0, rect.height, client.width, marginHeight);
}
}
void addListeners() {
addListener(SWT.Paint, new Listener() {
public void handleEvent(Event e) {
paint(e);
}
});
}
void convertImageDatasToImages() {
images = new Image[imageDatas.length];
// Step 1: Determine the size of the resulting images.
int width = imageDatas[0].width;
int height = imageDatas[0].height;
// Step 2: Construct each image.
int transition = SWT.DM_FILL_BACKGROUND;
for (int i = 0; i < imageDatas.length; i++) {
ImageData id = imageDatas[i];
images[i] = new Image(display, width, height);
GC gc = new GC(images[i]);
gc.setAntialias(SWT.ON);
// Do the transition from the previous image.
switch (transition) {
case SWT.DM_FILL_NONE:
case SWT.DM_UNSPECIFIED:
// Start from last image.
gc.drawImage(images[i - 1], 0, 0);
break;
case SWT.DM_FILL_PREVIOUS:
// Start from second last image.
gc.drawImage(images[i - 2], 0, 0);
break;
default:
// DM_FILL_BACKGROUND or anything else,
// just fill with default background.
//gc.setBackground(bg);
//gc.fillRectangle(0, 0, width, height);
break;
}
// Draw the current image and clean up.
Image img = new Image(display, id);
gc.drawImage(img, 0, 0, id.width, id.height, id.x, id.y, id.width,
id.height);
img.dispose();
gc.dispose();
// Compute the next transition.
// Special case: Can't do DM_FILL_PREVIOUS on the
// second image since there is no "second last"
// image to use.
transition = id.disposalMethod;
if (i == 0 && transition == SWT.DM_FILL_PREVIOUS)
transition = SWT.DM_FILL_NONE;
}
}
Image getCurrentImage() {
if (image != null)
return image;
if (images == null)
return null;
return images[current];
}
void startAnimationTimer() {
if (images == null || images.length < 2)
return;
final int delay = imageDatas[current].delayTime * 10;
display.timerExec(delay, animationTimer = new Runnable() {
public void run() {
if (isDisposed())
return;
current = (current + 1) % images.length;
redraw();
if (current + 1 == images.length && repeatCount != 0
&& --repeatCount <= 0)
return;
display.timerExec(delay, this);
}
});
}
void stopAnimationTimer() {
if (animationTimer != null)
display.timerExec(-1, animationTimer);
}
}
Wow, so much work for gif animation..
Anyway, check Transparency part of article about SWT Images, it might help you.