Updated with upstream update
This commit is contained in:
@ -62,6 +62,7 @@ libpikawidgets_sources_introspectable = files(
|
||||
'pikalabeled.c',
|
||||
'pikalabelintwidget.c',
|
||||
'pikalabelspin.c',
|
||||
'pikalabelstringwidget.c',
|
||||
'pikalabelentry.c',
|
||||
'pikamemsizeentry.c',
|
||||
'pikanumberpairentry.c',
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
@ -29,9 +30,18 @@
|
||||
|
||||
#include "pikadialog.h"
|
||||
#include "pikahelpui.h"
|
||||
#include "pikawidgetsutils.h"
|
||||
|
||||
#include "libpika/libpika-intl.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <dwmapi.h>
|
||||
#include <gdk/gdkwin32.h>
|
||||
|
||||
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION: pikadialog
|
||||
@ -58,32 +68,35 @@ struct _PikaDialogPrivate
|
||||
PikaHelpFunc help_func;
|
||||
gchar *help_id;
|
||||
GtkWidget *help_button;
|
||||
|
||||
GBytes *window_handle;
|
||||
};
|
||||
|
||||
#define GET_PRIVATE(obj) (((PikaDialog *) (obj))->priv)
|
||||
|
||||
|
||||
static void pika_dialog_constructed (GObject *object);
|
||||
static void pika_dialog_dispose (GObject *object);
|
||||
static void pika_dialog_finalize (GObject *object);
|
||||
static void pika_dialog_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_dialog_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_dialog_constructed (GObject *object);
|
||||
static void pika_dialog_dispose (GObject *object);
|
||||
static void pika_dialog_finalize (GObject *object);
|
||||
static void pika_dialog_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_dialog_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void pika_dialog_hide (GtkWidget *widget);
|
||||
static gboolean pika_dialog_delete_event (GtkWidget *widget,
|
||||
GdkEventAny *event);
|
||||
static void pika_dialog_hide (GtkWidget *widget);
|
||||
static gboolean pika_dialog_delete_event (GtkWidget *widget,
|
||||
GdkEventAny *event);
|
||||
|
||||
static void pika_dialog_close (GtkDialog *dialog);
|
||||
static void pika_dialog_close (GtkDialog *dialog);
|
||||
|
||||
static void pika_dialog_response (GtkDialog *dialog,
|
||||
gint response_id);
|
||||
static void pika_dialog_response (GtkDialog *dialog,
|
||||
gint response_id);
|
||||
|
||||
static void pika_dialog_set_title_bar_theme (GtkWidget *dialog);
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (PikaDialog, pika_dialog, GTK_TYPE_DIALOG)
|
||||
|
||||
@ -157,6 +170,12 @@ pika_dialog_init (PikaDialog *dialog)
|
||||
g_signal_connect (dialog, "response",
|
||||
G_CALLBACK (pika_dialog_response),
|
||||
NULL);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
g_signal_connect (GTK_WIDGET (dialog), "map",
|
||||
G_CALLBACK (pika_dialog_set_title_bar_theme),
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -177,6 +196,8 @@ pika_dialog_constructed (GObject *object)
|
||||
_("_Help"),
|
||||
GTK_RESPONSE_HELP);
|
||||
}
|
||||
|
||||
pika_widget_set_native_handle (GTK_WIDGET (object), &private->window_handle);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -650,6 +671,10 @@ pika_dialog_run (PikaDialog *dialog)
|
||||
|
||||
gtk_window_present (GTK_WINDOW (dialog));
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
pika_dialog_set_title_bar_theme (GTK_WIDGET (dialog));
|
||||
#endif
|
||||
|
||||
response_handler = g_signal_connect (dialog, "response",
|
||||
G_CALLBACK (run_response_handler),
|
||||
&ri);
|
||||
@ -711,6 +736,26 @@ pika_dialog_set_alternative_button_order_from_array (PikaDialog *dialog,
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_dialog_get_native_handle:
|
||||
* @dialog: The #PikaDialog
|
||||
*
|
||||
* Returns an opaque data handle representing the window in the currently
|
||||
* running platform. You should not try to use this directly. Usually this is to
|
||||
* be used in functions such as [func@Gimp.brushes_popup] which will allow the
|
||||
* core process to set this [class@Dialog] as parent to the newly created popup.
|
||||
*
|
||||
* Returns: (transfer none): an opaque [struct@GLib.Bytes] identifying this
|
||||
* window.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
GBytes *
|
||||
pika_dialog_get_native_handle (PikaDialog *dialog)
|
||||
{
|
||||
return dialog->priv->window_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_dialogs_show_help_button: (skip)
|
||||
* @show: whether a help button should be added when creating a PikaDialog
|
||||
@ -724,3 +769,46 @@ pika_dialogs_show_help_button (gboolean show)
|
||||
{
|
||||
show_help_button = show ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
pika_dialog_set_title_bar_theme (GtkWidget *dialog)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
HWND hwnd;
|
||||
gboolean use_dark_mode = FALSE;
|
||||
GdkWindow *window = NULL;
|
||||
|
||||
window = gtk_widget_get_window (GTK_WIDGET (dialog));
|
||||
if (window)
|
||||
{
|
||||
GtkStyleContext *style;
|
||||
GdkRGBA *color = NULL;
|
||||
|
||||
hwnd = (HWND) gdk_win32_window_get_handle (window);
|
||||
/* Workaround since we don't have access to PikaGuiConfig.
|
||||
* If the background color is below the threshold, then we're
|
||||
* likely in dark mode.
|
||||
*/
|
||||
style = gtk_widget_get_style_context (GTK_WIDGET (dialog));
|
||||
gtk_style_context_get (style, gtk_style_context_get_state (style),
|
||||
GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &color,
|
||||
NULL);
|
||||
if (color)
|
||||
{
|
||||
if (color->red < 0.5 && color->green < 0.5 && color->blue < 0.5)
|
||||
use_dark_mode = TRUE;
|
||||
|
||||
gdk_rgba_free (color);
|
||||
}
|
||||
|
||||
DwmSetWindowAttribute (hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||
&use_dark_mode, sizeof (use_dark_mode));
|
||||
UpdateWindow (hwnd);
|
||||
ShowWindow (hwnd, 5);
|
||||
|
||||
/* Toggle the window's visibility so the title bar change appears */
|
||||
gdk_window_hide (window);
|
||||
gdk_window_show (window);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -98,6 +98,8 @@ void pika_dialog_set_alternative_button_order_from_array
|
||||
gint n_buttons,
|
||||
gint *order);
|
||||
|
||||
GBytes * pika_dialog_get_native_handle (PikaDialog *dialog);
|
||||
|
||||
/* for internal use only! */
|
||||
void pika_dialogs_show_help_button (gboolean show);
|
||||
|
||||
|
@ -461,13 +461,14 @@ pika_label_spin_set_increments (PikaLabelSpin *spin,
|
||||
gdouble upper;
|
||||
|
||||
g_return_if_fail (PIKA_IS_LABEL_SPIN (spin));
|
||||
g_return_if_fail (step < page);
|
||||
g_return_if_fail (step <= page);
|
||||
|
||||
spinbutton = GTK_SPIN_BUTTON (priv->spinbutton);
|
||||
|
||||
gtk_spin_button_get_range (spinbutton, &lower, &upper);
|
||||
g_return_if_fail (upper >= lower);
|
||||
g_return_if_fail (step < upper - lower && page < upper - lower);
|
||||
g_return_if_fail ((upper == lower || step <= upper - lower) &&
|
||||
(upper == lower || page <= upper - lower));
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (spinbutton));
|
||||
gtk_adjustment_set_step_increment (gtk_spin_button_get_adjustment (spinbutton), step);
|
||||
|
@ -572,7 +572,7 @@ pika_preview_area_draw (PikaPreviewArea *area,
|
||||
if (! priv->buf)
|
||||
{
|
||||
priv->rowstride = ((priv->width * 3) + 3) & ~3;
|
||||
priv->buf = g_new (guchar, priv->rowstride * priv->height);
|
||||
priv->buf = g_new0 (guchar, priv->rowstride * priv->height);
|
||||
}
|
||||
|
||||
size = 1 << (2 + priv->check_size);
|
||||
@ -880,7 +880,7 @@ pika_preview_area_blend (PikaPreviewArea *area,
|
||||
if (! priv->buf)
|
||||
{
|
||||
priv->rowstride = ((priv->width * 3) + 3) & ~3;
|
||||
priv->buf = g_new (guchar, priv->rowstride * priv->height);
|
||||
priv->buf = g_new0 (guchar, priv->rowstride * priv->height);
|
||||
}
|
||||
|
||||
size = 1 << (2 + priv->check_size);
|
||||
@ -1279,7 +1279,7 @@ pika_preview_area_mask (PikaPreviewArea *area,
|
||||
if (! priv->buf)
|
||||
{
|
||||
priv->rowstride = ((priv->width * 3) + 3) & ~3;
|
||||
priv->buf = g_new (guchar, priv->rowstride * priv->height);
|
||||
priv->buf = g_new0 (guchar, priv->rowstride * priv->height);
|
||||
}
|
||||
|
||||
size = 1 << (2 + priv->check_size);
|
||||
@ -1852,7 +1852,7 @@ pika_preview_area_fill (PikaPreviewArea *area,
|
||||
if (! priv->buf)
|
||||
{
|
||||
priv->rowstride = ((priv->width * 3) + 3) & ~3;
|
||||
priv->buf = g_new (guchar, priv->rowstride * priv->height);
|
||||
priv->buf = g_new0 (guchar, priv->rowstride * priv->height);
|
||||
}
|
||||
|
||||
dest = priv->buf + x * 3 + y * priv->rowstride;
|
||||
@ -1875,6 +1875,32 @@ pika_preview_area_fill (PikaPreviewArea *area,
|
||||
pika_preview_area_queue_draw (area, x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_preview_area_reset:
|
||||
* @area: a #PikaPreviewArea widget.
|
||||
*
|
||||
* Reset any previous drawing done through [class@GimpUi.PreviewArea] functions.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
void
|
||||
pika_preview_area_reset (PikaPreviewArea *area)
|
||||
{
|
||||
PikaPreviewAreaPrivate *priv = GET_PRIVATE (area);
|
||||
GtkAllocation allocation;
|
||||
|
||||
if (priv->buf)
|
||||
{
|
||||
g_free (priv->buf);
|
||||
|
||||
priv->buf = NULL;
|
||||
priv->rowstride = 0;
|
||||
}
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (area), &allocation);
|
||||
pika_preview_area_queue_draw (area, 0, 0, allocation.width, allocation.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_preview_area_set_offsets:
|
||||
* @area: a #PikaPreviewArea
|
||||
|
@ -103,6 +103,7 @@ void pika_preview_area_fill (PikaPreviewArea *area,
|
||||
guchar red,
|
||||
guchar green,
|
||||
guchar blue);
|
||||
void pika_preview_area_reset (PikaPreviewArea *area);
|
||||
|
||||
void pika_preview_area_set_offsets (PikaPreviewArea *area,
|
||||
gint x,
|
||||
|
@ -45,50 +45,49 @@
|
||||
|
||||
/* utility function prototypes */
|
||||
|
||||
static void set_param_spec (GObject *object,
|
||||
GtkWidget *widget,
|
||||
GParamSpec *param_spec);
|
||||
static void set_radio_spec (GObject *object,
|
||||
GParamSpec *param_spec);
|
||||
static GParamSpec * get_param_spec (GObject *object);
|
||||
static void set_param_spec (GObject *object,
|
||||
GtkWidget *widget,
|
||||
GParamSpec *param_spec);
|
||||
static void set_radio_spec (GObject *object,
|
||||
GParamSpec *param_spec);
|
||||
static GParamSpec * get_param_spec (GObject *object);
|
||||
|
||||
static GParamSpec * find_param_spec (GObject *object,
|
||||
const gchar *property_name,
|
||||
const gchar *strloc);
|
||||
static GParamSpec * check_param_spec_quiet (
|
||||
GObject *object,
|
||||
const gchar *property_name,
|
||||
GType type,
|
||||
const gchar *strloc);
|
||||
static GParamSpec * check_param_spec (GObject *object,
|
||||
const gchar *property_name,
|
||||
GType type,
|
||||
const gchar *strloc);
|
||||
static GParamSpec * check_param_spec_w (GObject *object,
|
||||
const gchar *property_name,
|
||||
GType type,
|
||||
const gchar *strloc);
|
||||
static GParamSpec * find_param_spec (GObject *object,
|
||||
const gchar *property_name,
|
||||
const gchar *strloc);
|
||||
static GParamSpec * check_param_spec_quiet (GObject *object,
|
||||
const gchar *property_name,
|
||||
GType type,
|
||||
const gchar *strloc);
|
||||
static GParamSpec * check_param_spec (GObject *object,
|
||||
const gchar *property_name,
|
||||
GType type,
|
||||
const gchar *strloc);
|
||||
static GParamSpec * check_param_spec_w (GObject *object,
|
||||
const gchar *property_name,
|
||||
GType type,
|
||||
const gchar *strloc);
|
||||
|
||||
static gboolean get_numeric_values (GObject *object,
|
||||
GParamSpec *param_spec,
|
||||
gdouble *value,
|
||||
gdouble *lower,
|
||||
gdouble *upper,
|
||||
const gchar *strloc);
|
||||
static gboolean get_numeric_values (GObject *object,
|
||||
GParamSpec *param_spec,
|
||||
gdouble *value,
|
||||
gdouble *lower,
|
||||
gdouble *upper,
|
||||
const gchar *strloc);
|
||||
|
||||
static void connect_notify (GObject *config,
|
||||
const gchar *property_name,
|
||||
GCallback callback,
|
||||
gpointer callback_data);
|
||||
static void connect_notify (GObject *config,
|
||||
const gchar *property_name,
|
||||
GCallback callback,
|
||||
gpointer callback_data);
|
||||
|
||||
static gboolean pika_prop_widget_double_to_factor (GBinding *binding,
|
||||
const GValue *from_value,
|
||||
GValue *to_value,
|
||||
gpointer user_data);
|
||||
static gboolean pika_prop_widget_double_from_factor (GBinding *binding,
|
||||
const GValue *from_value,
|
||||
GValue *to_value,
|
||||
gpointer user_data);
|
||||
static gboolean pika_prop_widget_double_to_factor (GBinding *binding,
|
||||
const GValue *from_value,
|
||||
GValue *to_value,
|
||||
gpointer user_data);
|
||||
static gboolean pika_prop_widget_double_from_factor (GBinding *binding,
|
||||
const GValue *from_value,
|
||||
GValue *to_value,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
/******************/
|
||||
@ -2543,6 +2542,11 @@ static void pika_prop_string_combo_box_notify (GObject *config,
|
||||
GParamSpec *param_spec,
|
||||
GtkWidget *widget);
|
||||
|
||||
static gboolean
|
||||
pika_prop_choice_combo_box_is_sensitive (const gchar *nick,
|
||||
PikaChoice *choice);
|
||||
|
||||
|
||||
/**
|
||||
* pika_prop_string_combo_box_new:
|
||||
* @config: Object to which property is attached.
|
||||
@ -2604,6 +2608,74 @@ pika_prop_string_combo_box_new (GObject *config,
|
||||
return combo_box;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_prop_choice_combo_box_new:
|
||||
* @config: Object to which property is attached.
|
||||
* @property_name: Name of %PikaChoice property controlled by combo box.
|
||||
*
|
||||
* Creates a #PikaStringComboBox widget to display and set the
|
||||
* specified property.
|
||||
*
|
||||
* Returns: (transfer full): The newly created #PikaStringComboBox widget.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
GtkWidget *
|
||||
pika_prop_choice_combo_box_new (GObject *config,
|
||||
const gchar *property_name)
|
||||
{
|
||||
GParamSpec *param_spec;
|
||||
PikaParamSpecChoice *cspec;
|
||||
GtkWidget *combo_box;
|
||||
GtkListStore *store;
|
||||
GList *values;
|
||||
GList *iter;
|
||||
|
||||
g_return_val_if_fail (G_IS_OBJECT (config), NULL);
|
||||
g_return_val_if_fail (property_name != NULL, NULL);
|
||||
|
||||
param_spec = check_param_spec_w (config, property_name,
|
||||
PIKA_TYPE_PARAM_CHOICE, G_STRFUNC);
|
||||
if (! param_spec)
|
||||
return NULL;
|
||||
|
||||
cspec = PIKA_PARAM_SPEC_CHOICE (param_spec);
|
||||
values = pika_choice_list_nicks (cspec->choice);
|
||||
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
for (iter = values; iter; iter = iter->next)
|
||||
{
|
||||
const gchar *nick = iter->data;
|
||||
const gchar *label = pika_choice_get_label (cspec->choice, nick);
|
||||
|
||||
gtk_list_store_insert_with_values (store, NULL, -1,
|
||||
0, nick,
|
||||
1, label,
|
||||
-1);
|
||||
|
||||
}
|
||||
|
||||
combo_box = pika_string_combo_box_new (GTK_TREE_MODEL (store), 0, 1);
|
||||
g_object_unref (store);
|
||||
|
||||
pika_string_combo_box_set_sensitivity (PIKA_STRING_COMBO_BOX (combo_box),
|
||||
(PikaStringSensitivityFunc) pika_prop_choice_combo_box_is_sensitive,
|
||||
cspec->choice, NULL);
|
||||
g_signal_connect_swapped (cspec->choice, "sensitivity-changed",
|
||||
G_CALLBACK (gtk_widget_queue_draw),
|
||||
combo_box);
|
||||
|
||||
g_object_bind_property (config, property_name,
|
||||
combo_box, "value",
|
||||
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
|
||||
pika_widget_set_bound_property (combo_box, config, property_name);
|
||||
|
||||
gtk_widget_show (combo_box);
|
||||
|
||||
return combo_box;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_prop_string_combo_box_callback (GtkWidget *widget,
|
||||
GObject *config)
|
||||
@ -2651,6 +2723,13 @@ pika_prop_string_combo_box_notify (GObject *config,
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_prop_choice_combo_box_is_sensitive (const gchar *nick,
|
||||
PikaChoice *choice)
|
||||
{
|
||||
return pika_choice_is_valid (choice, nick);
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* file chooser button */
|
||||
|
@ -23,8 +23,8 @@
|
||||
#error "Only <libpikawidgets/pikawidgets.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_PROP_WIDGETS_H__
|
||||
#define __PIKA_PROP_WIDGETS_H__
|
||||
#ifndef __PIKAWIDGETS_PROP_WIDGETS_H__
|
||||
#define __PIKAWIDGETS_PROP_WIDGETS_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -166,6 +166,8 @@ GtkWidget * pika_prop_string_combo_box_new (GObject *config,
|
||||
GtkTreeModel *model,
|
||||
gint id_column,
|
||||
gint label_column);
|
||||
GtkWidget * pika_prop_choice_combo_box_new (GObject *config,
|
||||
const gchar *property_name);
|
||||
|
||||
|
||||
/* PikaParamPath */
|
||||
@ -250,4 +252,4 @@ GtkWidget * pika_prop_icon_image_new (GObject *config,
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_PROP_WIDGETS_H__ */
|
||||
#endif /* __PIKAWIDGETS_PROP_WIDGETS_H__ */
|
||||
|
@ -390,10 +390,10 @@ pika_ruler_update_position (PikaRuler *ruler,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
PikaRulerPrivate *priv = GET_PRIVATE (ruler);
|
||||
PikaRulerPrivate *priv = GET_PRIVATE (ruler);
|
||||
GtkAllocation allocation;
|
||||
gdouble lower;
|
||||
gdouble upper;
|
||||
gdouble lower = 0;
|
||||
gdouble upper = 0;
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (ruler), &allocation);
|
||||
pika_ruler_get_range (ruler, &lower, &upper, NULL);
|
||||
@ -1005,7 +1005,8 @@ pika_ruler_draw_ticks (PikaRuler *ruler)
|
||||
gint i;
|
||||
gint width, height;
|
||||
gint length, ideal_length;
|
||||
gdouble lower, upper; /* Upper and lower limits, in ruler units */
|
||||
gdouble lower = 0; /* Upper and lower limits, in ruler units */
|
||||
gdouble upper = 0;
|
||||
gdouble increment; /* Number of pixels per unit */
|
||||
gint scale; /* Number of units per major unit */
|
||||
gdouble start, end, cur;
|
||||
@ -1209,7 +1210,8 @@ pika_ruler_get_pos_rect (PikaRuler *ruler,
|
||||
GtkAllocation allocation;
|
||||
GtkBorder border;
|
||||
gint width, height;
|
||||
gdouble upper, lower;
|
||||
gdouble upper = 0;
|
||||
gdouble lower = 0;
|
||||
gdouble increment;
|
||||
GdkRectangle rect = { 0, };
|
||||
|
||||
|
@ -46,29 +46,40 @@ enum
|
||||
PROP_0,
|
||||
PROP_ID_COLUMN,
|
||||
PROP_LABEL_COLUMN,
|
||||
PROP_ELLIPSIZE
|
||||
PROP_ELLIPSIZE,
|
||||
PROP_VALUE
|
||||
};
|
||||
|
||||
|
||||
struct _PikaStringComboBoxPrivate
|
||||
{
|
||||
gint id_column;
|
||||
gint label_column;
|
||||
GtkCellRenderer *text_renderer;
|
||||
gint id_column;
|
||||
gint label_column;
|
||||
GtkCellRenderer *text_renderer;
|
||||
|
||||
PikaStringSensitivityFunc sensitivity_func;
|
||||
gpointer sensitivity_data;
|
||||
GDestroyNotify sensitivity_destroy;
|
||||
};
|
||||
|
||||
#define GET_PRIVATE(obj) (((PikaStringComboBox *) (obj))->priv)
|
||||
|
||||
|
||||
static void pika_string_combo_box_constructed (GObject *object);
|
||||
static void pika_string_combo_box_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_string_combo_box_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_string_combo_box_constructed (GObject *object);
|
||||
static void pika_string_combo_box_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_string_combo_box_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void pika_string_combo_box_cell_data_func (GtkCellLayout *cell_layout,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
PikaStringComboBoxPrivate *priv);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (PikaStringComboBox, pika_string_combo_box,
|
||||
@ -138,6 +149,22 @@ pika_string_combo_box_class_init (PikaStringComboBoxClass *klass)
|
||||
PANGO_TYPE_ELLIPSIZE_MODE,
|
||||
PANGO_ELLIPSIZE_NONE,
|
||||
PIKA_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* PikaStringComboBox:value:
|
||||
*
|
||||
* The active value (different from the "active" property of
|
||||
* GtkComboBox which is the active index).
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (object_class, PROP_VALUE,
|
||||
g_param_spec_string ("value",
|
||||
"Value",
|
||||
"Value of active item",
|
||||
NULL,
|
||||
PIKA_PARAM_READWRITE |
|
||||
G_PARAM_EXPLICIT_NOTIFY));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -160,6 +187,16 @@ pika_string_combo_box_constructed (GObject *object)
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), cell,
|
||||
"text", priv->label_column,
|
||||
NULL);
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (object), priv->text_renderer,
|
||||
(GtkCellLayoutDataFunc) pika_string_combo_box_cell_data_func,
|
||||
priv, NULL);
|
||||
|
||||
/* The "changed" signal of the GtkComboBox also triggers a "value" property
|
||||
* notification.
|
||||
*/
|
||||
g_signal_connect (object, "changed",
|
||||
G_CALLBACK (g_object_notify),
|
||||
"value");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -184,6 +221,11 @@ pika_string_combo_box_set_property (GObject *object,
|
||||
g_object_set_property (G_OBJECT (priv->text_renderer),
|
||||
pspec->name, value);
|
||||
break;
|
||||
case PROP_VALUE:
|
||||
pika_string_combo_box_set_active (PIKA_STRING_COMBO_BOX (object),
|
||||
g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@ -212,6 +254,15 @@ pika_string_combo_box_get_property (GObject *object,
|
||||
g_object_get_property (G_OBJECT (priv->text_renderer),
|
||||
pspec->name, value);
|
||||
break;
|
||||
case PROP_VALUE:
|
||||
{
|
||||
gchar *v;
|
||||
|
||||
v = pika_string_combo_box_get_active (PIKA_STRING_COMBO_BOX (object));
|
||||
g_value_take_string (value, v);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@ -292,7 +343,7 @@ pika_string_combo_box_new (GtkTreeModel *model,
|
||||
* selected item in the @combo_box.
|
||||
*
|
||||
* Returns: %TRUE on success or %FALSE if there was no item for
|
||||
* this value.
|
||||
* this value.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
@ -315,6 +366,7 @@ pika_string_combo_box_set_active (PikaStringComboBox *combo_box,
|
||||
if (pika_string_model_lookup (model, column, id, &iter))
|
||||
{
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter);
|
||||
g_object_notify (G_OBJECT (combo_box), "value");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -323,6 +375,7 @@ pika_string_combo_box_set_active (PikaStringComboBox *combo_box,
|
||||
else
|
||||
{
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), -1);
|
||||
g_object_notify (G_OBJECT (combo_box), "value");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -362,3 +415,74 @@ pika_string_combo_box_get_active (PikaStringComboBox *combo_box)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_string_combo_box_set_sensitivity:
|
||||
* @combo_box: a #PikaStringComboBox
|
||||
* @func: a function that returns a boolean value, or %NULL to unset
|
||||
* @data: data to pass to @func
|
||||
* @destroy: destroy notification for @data
|
||||
*
|
||||
* Sets a function that is used to decide about the sensitivity of
|
||||
* rows in the @combo_box. Use this if you want to set certain rows
|
||||
* insensitive.
|
||||
*
|
||||
* Calling gtk_widget_queue_draw() on the @combo_box will cause the
|
||||
* sensitivity to be updated.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
void
|
||||
pika_string_combo_box_set_sensitivity (PikaStringComboBox *combo_box,
|
||||
PikaStringSensitivityFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
PikaStringComboBoxPrivate *priv;
|
||||
|
||||
g_return_if_fail (PIKA_IS_STRING_COMBO_BOX (combo_box));
|
||||
|
||||
priv = GET_PRIVATE (combo_box);
|
||||
|
||||
if (priv->sensitivity_destroy)
|
||||
{
|
||||
GDestroyNotify d = priv->sensitivity_destroy;
|
||||
|
||||
priv->sensitivity_destroy = NULL;
|
||||
d (priv->sensitivity_data);
|
||||
}
|
||||
|
||||
priv->sensitivity_func = func;
|
||||
priv->sensitivity_data = data;
|
||||
priv->sensitivity_destroy = destroy;
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (combo_box));
|
||||
}
|
||||
|
||||
|
||||
/* Private functions. */
|
||||
|
||||
static void
|
||||
pika_string_combo_box_cell_data_func (GtkCellLayout *cell_layout,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
PikaStringComboBoxPrivate *priv)
|
||||
{
|
||||
if (priv->sensitivity_func)
|
||||
{
|
||||
gchar *id;
|
||||
gboolean sensitive;
|
||||
|
||||
gtk_tree_model_get (tree_model, iter,
|
||||
priv->id_column, &id,
|
||||
-1);
|
||||
|
||||
sensitive = priv->sensitivity_func (id, priv->sensitivity_data);
|
||||
|
||||
g_object_set (cell,
|
||||
"sensitive", sensitive,
|
||||
NULL);
|
||||
g_free (id);
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,15 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
/**
|
||||
* PikaStringSensitivityFunc:
|
||||
* @id: the string value from the column @id_column as passed to [ctor@StringComboBox.new].
|
||||
* @data: (closure): the data passed in [method@StringComboBox.set_sensitivity].
|
||||
*/
|
||||
typedef gboolean (* PikaStringSensitivityFunc) (const gchar *id,
|
||||
gpointer data);
|
||||
|
||||
|
||||
#define PIKA_TYPE_STRING_COMBO_BOX (pika_string_combo_box_get_type ())
|
||||
#define PIKA_STRING_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_STRING_COMBO_BOX, PikaStringComboBox))
|
||||
#define PIKA_STRING_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_STRING_COMBO_BOX, PikaStringComboBoxClass))
|
||||
@ -63,15 +72,19 @@ struct _PikaStringComboBoxClass
|
||||
};
|
||||
|
||||
|
||||
GType pika_string_combo_box_get_type (void) G_GNUC_CONST;
|
||||
GType pika_string_combo_box_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_string_combo_box_new (GtkTreeModel *model,
|
||||
gint id_column,
|
||||
gint label_column);
|
||||
gboolean pika_string_combo_box_set_active (PikaStringComboBox *combo_box,
|
||||
const gchar *id);
|
||||
gchar * pika_string_combo_box_get_active (PikaStringComboBox *combo_box);
|
||||
GtkWidget * pika_string_combo_box_new (GtkTreeModel *model,
|
||||
gint id_column,
|
||||
gint label_column);
|
||||
gboolean pika_string_combo_box_set_active (PikaStringComboBox *combo_box,
|
||||
const gchar *id);
|
||||
gchar * pika_string_combo_box_get_active (PikaStringComboBox *combo_box);
|
||||
|
||||
void pika_string_combo_box_set_sensitivity (PikaStringComboBox *combo_box,
|
||||
PikaStringSensitivityFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -158,6 +158,7 @@ EXPORTS
|
||||
pika_dialog_add_button
|
||||
pika_dialog_add_buttons
|
||||
pika_dialog_add_buttons_valist
|
||||
pika_dialog_get_native_handle
|
||||
pika_dialog_get_type
|
||||
pika_dialog_new
|
||||
pika_dialog_new_valist
|
||||
@ -266,6 +267,9 @@ EXPORTS
|
||||
pika_label_spin_set_digits
|
||||
pika_label_spin_set_increments
|
||||
pika_label_spin_set_value
|
||||
pika_label_string_widget_get_type
|
||||
pika_label_string_widget_get_widget
|
||||
pika_label_string_widget_new
|
||||
pika_labeled_get_label
|
||||
pika_labeled_get_text
|
||||
pika_labeled_get_type
|
||||
@ -332,6 +336,7 @@ EXPORTS
|
||||
pika_preview_area_mask
|
||||
pika_preview_area_menu_popup
|
||||
pika_preview_area_new
|
||||
pika_preview_area_reset
|
||||
pika_preview_area_set_color_config
|
||||
pika_preview_area_set_colormap
|
||||
pika_preview_area_set_max_size
|
||||
@ -360,6 +365,7 @@ EXPORTS
|
||||
pika_prop_boolean_combo_box_new
|
||||
pika_prop_boolean_radio_frame_new
|
||||
pika_prop_check_button_new
|
||||
pika_prop_choice_combo_box_new
|
||||
pika_prop_color_area_new
|
||||
pika_prop_color_select_new
|
||||
pika_prop_coordinates_connect
|
||||
@ -468,6 +474,7 @@ EXPORTS
|
||||
pika_string_combo_box_get_type
|
||||
pika_string_combo_box_new
|
||||
pika_string_combo_box_set_active
|
||||
pika_string_combo_box_set_sensitivity
|
||||
pika_toggle_button_update
|
||||
pika_uint_adjustment_update
|
||||
pika_unit_combo_box_get_active
|
||||
@ -492,6 +499,7 @@ EXPORTS
|
||||
pika_widget_get_monitor
|
||||
pika_widget_set_bound_property
|
||||
pika_widget_set_identifier
|
||||
pika_widget_set_native_handle
|
||||
pika_widget_track_monitor
|
||||
pika_widgets_error_quark
|
||||
pika_widgets_init
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include <libpikawidgets/pikalabelentry.h>
|
||||
#include <libpikawidgets/pikalabelintwidget.h>
|
||||
#include <libpikawidgets/pikalabelspin.h>
|
||||
#include <libpikawidgets/pikalabelstringwidget.h>
|
||||
#include <libpikawidgets/pikamemsizeentry.h>
|
||||
#include <libpikawidgets/pikanumberpairentry.h>
|
||||
#include <libpikawidgets/pikaoffsetarea.h>
|
||||
|
@ -26,6 +26,16 @@
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <gdk/gdkwin32.h>
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
@ -61,6 +71,19 @@
|
||||
**/
|
||||
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
static void pika_widget_wayland_window_exported (GdkWindow *window,
|
||||
const char *handle,
|
||||
GBytes **phandle);
|
||||
#endif
|
||||
|
||||
static void pika_widget_set_handle_on_realize (GtkWidget *widget,
|
||||
GBytes **phandle);
|
||||
static gboolean pika_widget_set_handle_on_mapped (GtkWidget *widget,
|
||||
GdkEventAny *event,
|
||||
GBytes **phandle);
|
||||
|
||||
|
||||
static GtkWidget *
|
||||
find_mnemonic_widget (GtkWidget *widget,
|
||||
gint level)
|
||||
@ -1036,3 +1059,145 @@ pika_widget_get_color_transform (GtkWidget *widget,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_widget_set_native_handle:
|
||||
* @widget: a #GtkWindow
|
||||
* @handle: (out): pointer to store the native handle as a #GBytes.
|
||||
*
|
||||
* This function is used to store the handle representing @window into
|
||||
* @handle so that it can later be reused to set other windows as
|
||||
* transient to this one (even in other processes, such as plug-ins).
|
||||
*
|
||||
* Depending on the platform, the actual content of @handle can be
|
||||
* various types. Moreover it may be filled asynchronously in a
|
||||
* callback, so you should not assume that @handle is set after running
|
||||
* this function.
|
||||
*
|
||||
* This convenience function is safe to use even before @widget is
|
||||
* visible as it will set the handle once it is mapped.
|
||||
*/
|
||||
void
|
||||
pika_widget_set_native_handle (GtkWidget *widget,
|
||||
GBytes **handle)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (handle != NULL && *handle == NULL);
|
||||
|
||||
/* This may seem overly complicated but there is a reason: "map-event" can
|
||||
* only be received by widgets with their own windows (see description of
|
||||
* gtk_widget_set_events()). Instead we could just use "realize" which is
|
||||
* received by every widgets (even by the ones whose window actually belongs
|
||||
* to a parent widget), but this causes process locks on Wayland (see comment
|
||||
* in pika_widget_set_handle_on_mapped()).
|
||||
* This is why we do this weird case-based dance.
|
||||
*/
|
||||
if (gtk_widget_get_has_window (widget))
|
||||
{
|
||||
gtk_widget_add_events (widget, GDK_STRUCTURE_MASK);
|
||||
g_signal_connect (widget, "map-event",
|
||||
G_CALLBACK (pika_widget_set_handle_on_mapped),
|
||||
handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_signal_connect (widget, "realize",
|
||||
G_CALLBACK (pika_widget_set_handle_on_realize),
|
||||
handle);
|
||||
}
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
pika_widget_set_handle_on_mapped (widget, NULL, handle);
|
||||
}
|
||||
|
||||
|
||||
/* Private functions */
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
static void
|
||||
pika_widget_wayland_window_exported (GdkWindow *window,
|
||||
const char *handle,
|
||||
GBytes **phandle)
|
||||
{
|
||||
GBytes *wayland_handle;
|
||||
|
||||
wayland_handle = g_bytes_new (handle, strlen (handle));
|
||||
|
||||
g_bytes_unref (*phandle);
|
||||
*phandle = wayland_handle;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
pika_widget_set_handle_on_realize (GtkWidget *widget,
|
||||
GBytes **phandle)
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
|
||||
|
||||
gtk_widget_add_events (toplevel, GDK_STRUCTURE_MASK);
|
||||
g_signal_connect (toplevel, "map-event",
|
||||
G_CALLBACK (pika_widget_set_handle_on_mapped),
|
||||
phandle);
|
||||
|
||||
if (gtk_widget_get_mapped (toplevel))
|
||||
pika_widget_set_handle_on_mapped (widget, NULL, phandle);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_widget_set_handle_on_mapped (GtkWidget *widget,
|
||||
GdkEventAny *event,
|
||||
GBytes **phandle)
|
||||
{
|
||||
GdkWindow *surface;
|
||||
GBytes *handle = NULL;
|
||||
#if defined (GDK_WINDOWING_WIN32) || defined (GDK_WINDOWING_X11)
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
|
||||
|
||||
widget = toplevel;
|
||||
#endif
|
||||
|
||||
g_clear_pointer (phandle, g_bytes_unref);
|
||||
|
||||
surface = gtk_widget_get_window (GTK_WIDGET (widget));
|
||||
g_return_val_if_fail (surface != NULL, FALSE);
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (GDK_IS_WIN32_WINDOW (surface))
|
||||
{
|
||||
HANDLE id;
|
||||
|
||||
id = GDK_WINDOW_HWND (gtk_widget_get_window (GTK_WIDGET (widget)));
|
||||
handle = g_bytes_new (&id, sizeof (HANDLE));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (GDK_IS_X11_WINDOW (surface))
|
||||
{
|
||||
Window id;
|
||||
|
||||
id = GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (widget)));
|
||||
handle = g_bytes_new (&id, sizeof (Window));
|
||||
}
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW (surface))
|
||||
{
|
||||
/* I don't run this on "realize" event because somehow it locks
|
||||
* the whole processus in Wayland. The "map-event" happens
|
||||
* slightly after the window became visible and I didn't
|
||||
* experience any lock.
|
||||
*/
|
||||
if (! gdk_wayland_window_export_handle (surface,
|
||||
(GdkWaylandWindowExported) pika_widget_wayland_window_exported,
|
||||
phandle, NULL))
|
||||
g_printerr ("%s: gdk_wayland_window_export_handle() failed. "
|
||||
"It will not be possible to set windows in other processes as transient to this display shell.\n",
|
||||
G_STRFUNC);
|
||||
}
|
||||
#endif
|
||||
|
||||
*phandle = handle;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ PikaColorTransform * pika_widget_get_color_transform (GtkWidget *widget,
|
||||
PikaColorRenderingIntent proof_intent,
|
||||
gboolean proof_bpc);
|
||||
|
||||
void pika_widget_set_native_handle (GtkWidget *widget,
|
||||
GBytes **handle);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
Reference in New Issue
Block a user