(trunk gtk) experimentally remove sexy-icon-entry from the GTK+ client... GtkEntry can handle it now
This commit is contained in:
parent
83bdedec8e
commit
92e989f553
|
@ -7,13 +7,6 @@ endif
|
||||||
# these should go in GTK_EXTRA_CPPFLAGS at some point, but not yet because it breaks libnotify's headers
|
# these should go in GTK_EXTRA_CPPFLAGS at some point, but not yet because it breaks libnotify's headers
|
||||||
# -DG_DISABLE_SINGLE_INCLUDES -DGTK_DISABLE_SINGLE_INCLUDES
|
# -DG_DISABLE_SINGLE_INCLUDES -DGTK_DISABLE_SINGLE_INCLUDES
|
||||||
|
|
||||||
sexy-marshal.h: marshal.list
|
|
||||||
glib-genmarshal --prefix=sexy_marshal ./marshal.list --header > sexy-marshal.h
|
|
||||||
|
|
||||||
sexy-marshal.c: marshal.list
|
|
||||||
echo '#include "sexy-marshal.h"' > sexy-marshal.c
|
|
||||||
glib-genmarshal --prefix=sexy_marshal ./marshal.list --body >> sexy-marshal.c
|
|
||||||
|
|
||||||
AM_CPPFLAGS = \
|
AM_CPPFLAGS = \
|
||||||
-I$(top_srcdir) \
|
-I$(top_srcdir) \
|
||||||
-DTRANSMISSIONLOCALEDIR=\""$(transmissionlocaledir)"\" \
|
-DTRANSMISSIONLOCALEDIR=\""$(transmissionlocaledir)"\" \
|
||||||
|
@ -57,8 +50,6 @@ noinst_HEADERS = \
|
||||||
ratio-icon.h \
|
ratio-icon.h \
|
||||||
relocate.h \
|
relocate.h \
|
||||||
stats.h \
|
stats.h \
|
||||||
sexy-icon-entry.h \
|
|
||||||
sexy-marshal.h \
|
|
||||||
torrent-cell-renderer.h \
|
torrent-cell-renderer.h \
|
||||||
tracker-list.h \
|
tracker-list.h \
|
||||||
tr-core.h \
|
tr-core.h \
|
||||||
|
@ -91,8 +82,6 @@ transmission_gtk_SOURCES = \
|
||||||
msgwin.c \
|
msgwin.c \
|
||||||
notify.c \
|
notify.c \
|
||||||
relocate.c \
|
relocate.c \
|
||||||
sexy-icon-entry.c \
|
|
||||||
sexy-marshal.c \
|
|
||||||
stats.c \
|
stats.c \
|
||||||
torrent-cell-renderer.c \
|
torrent-cell-renderer.c \
|
||||||
tracker-list.c \
|
tracker-list.c \
|
||||||
|
@ -156,8 +145,6 @@ transmission.res: transmission.rc
|
||||||
$(WINDRES) -J rc -i transmission.rc -O coff -o transmission.res
|
$(WINDRES) -J rc -i transmission.rc -O coff -o transmission.res
|
||||||
|
|
||||||
BUILT_SOURCES = \
|
BUILT_SOURCES = \
|
||||||
sexy-marshal.h \
|
|
||||||
sexy-marshal.c \
|
|
||||||
setransmission.res
|
setransmission.res
|
||||||
|
|
||||||
CLEANFILES += \
|
CLEANFILES += \
|
||||||
|
@ -169,10 +156,4 @@ transmission_gtk_LDADD += \
|
||||||
transmission_gtk_LDFLAGS = \
|
transmission_gtk_LDFLAGS = \
|
||||||
-mwindows
|
-mwindows
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
BUILT_SOURCES = \
|
|
||||||
sexy-marshal.h \
|
|
||||||
sexy-marshal.c
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
144
gtk/filter.c
144
gtk/filter.c
|
@ -25,16 +25,8 @@
|
||||||
#define DIRTY_KEY "tr-filter-dirty-key"
|
#define DIRTY_KEY "tr-filter-dirty-key"
|
||||||
#define SESSION_KEY "tr-session-key"
|
#define SESSION_KEY "tr-session-key"
|
||||||
#define TEXT_KEY "tr-filter-text-key"
|
#define TEXT_KEY "tr-filter-text-key"
|
||||||
#define TEXT_MODE_KEY "tr-filter-text-mode-key"
|
|
||||||
#define TORRENT_MODEL_KEY "tr-filter-torrent-model-key"
|
#define TORRENT_MODEL_KEY "tr-filter-torrent-model-key"
|
||||||
|
|
||||||
#if !GTK_CHECK_VERSION( 2,16,0 )
|
|
||||||
/* FIXME: when 2.16 has been out long enough, it would be good to
|
|
||||||
* get rid of libsexy because of its makefile strangeness */
|
|
||||||
#define USE_SEXY
|
|
||||||
#include "sexy-icon-entry.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
****
|
****
|
||||||
**** CATEGORIES
|
**** CATEGORIES
|
||||||
|
@ -847,80 +839,28 @@ activity_combo_box_new( GtkTreeModel * tmodel )
|
||||||
*****
|
*****
|
||||||
****/
|
****/
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
TEXT_MODE_NAME,
|
|
||||||
TEXT_MODE_FILES,
|
|
||||||
TEXT_MODE_TRACKER,
|
|
||||||
TEXT_MODE_N_TYPES
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
testText( const tr_torrent * tor, const char * key, int mode )
|
testText( const tr_torrent * tor, const char * key )
|
||||||
{
|
{
|
||||||
gboolean ret;
|
|
||||||
tr_file_index_t i;
|
tr_file_index_t i;
|
||||||
|
gboolean ret = FALSE;
|
||||||
const tr_info * inf = tr_torrentInfo( tor );
|
const tr_info * inf = tr_torrentInfo( tor );
|
||||||
|
|
||||||
switch( mode )
|
for( i=0; i<inf->fileCount && !ret; ++i )
|
||||||
{
|
{
|
||||||
case TEXT_MODE_FILES:
|
char * pch = g_utf8_casefold( inf->files[i].name, -1 );
|
||||||
for( i=0; i<inf->fileCount && !ret; ++i ) {
|
ret = !key || strstr( pch, key ) != NULL;
|
||||||
char * pch = g_utf8_casefold( inf->files[i].name, -1 );
|
g_free( pch );
|
||||||
ret = !key || strstr( pch, key ) != NULL;
|
|
||||||
g_free( pch );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TEXT_MODE_TRACKER:
|
|
||||||
if( inf->trackerCount > 0 ) {
|
|
||||||
char * pch = g_utf8_casefold( inf->trackers[0].announce, -1 );
|
|
||||||
ret = !key || ( strstr( pch, key ) != NULL );
|
|
||||||
g_free( pch );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* NAME */
|
|
||||||
if( !inf->name )
|
|
||||||
ret = TRUE;
|
|
||||||
else {
|
|
||||||
char * pch = g_utf8_casefold( inf->name, -1 );
|
|
||||||
ret = !key || ( strstr( pch, key ) != NULL );
|
|
||||||
g_free( pch );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_SEXY
|
|
||||||
static void
|
static void
|
||||||
entry_icon_released( SexyIconEntry * entry UNUSED,
|
entry_clear( GtkEntry * e )
|
||||||
SexyIconEntryPosition icon_pos,
|
|
||||||
int button UNUSED,
|
|
||||||
gpointer menu )
|
|
||||||
{
|
{
|
||||||
if( icon_pos == SEXY_ICON_ENTRY_PRIMARY )
|
gtk_entry_set_text( e, "" );
|
||||||
gtk_menu_popup( GTK_MENU( menu ), NULL, NULL, NULL, NULL, 0,
|
|
||||||
gtk_get_current_event_time( ) );
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static void
|
|
||||||
entry_icon_release( GtkEntry * entry UNUSED,
|
|
||||||
GtkEntryIconPosition icon_pos,
|
|
||||||
GdkEventButton * event UNUSED,
|
|
||||||
gpointer menu )
|
|
||||||
{
|
|
||||||
if( icon_pos == GTK_ENTRY_ICON_SECONDARY )
|
|
||||||
gtk_entry_set_text( entry, "" );
|
|
||||||
|
|
||||||
if( icon_pos == GTK_ENTRY_ICON_PRIMARY )
|
|
||||||
gtk_menu_popup( GTK_MENU( menu ), NULL, NULL, NULL, NULL, 0,
|
|
||||||
gtk_get_current_event_time( ) );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
filter_entry_changed( GtkEditable * e, gpointer filter_model )
|
filter_entry_changed( GtkEditable * e, gpointer filter_model )
|
||||||
|
@ -936,14 +876,6 @@ filter_entry_changed( GtkEditable * e, gpointer filter_model )
|
||||||
gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( filter_model ) );
|
gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( filter_model ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
filter_text_toggled_cb( GtkCheckMenuItem * menu_item, gpointer filter_model )
|
|
||||||
{
|
|
||||||
g_object_set_data( filter_model, TEXT_MODE_KEY,
|
|
||||||
g_object_get_data( G_OBJECT( menu_item ), TEXT_MODE_KEY ) );
|
|
||||||
gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( filter_model ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
******
|
******
|
||||||
******
|
******
|
||||||
|
@ -961,7 +893,6 @@ struct filter_data
|
||||||
static gboolean
|
static gboolean
|
||||||
is_row_visible( GtkTreeModel * model, GtkTreeIter * iter, gpointer vdata )
|
is_row_visible( GtkTreeModel * model, GtkTreeIter * iter, gpointer vdata )
|
||||||
{
|
{
|
||||||
int mode;
|
|
||||||
const char * text;
|
const char * text;
|
||||||
tr_torrent * tor;
|
tr_torrent * tor;
|
||||||
struct filter_data * data = vdata;
|
struct filter_data * data = vdata;
|
||||||
|
@ -970,11 +901,10 @@ is_row_visible( GtkTreeModel * model, GtkTreeIter * iter, gpointer vdata )
|
||||||
gtk_tree_model_get( model, iter, MC_TORRENT_RAW, &tor, -1 );
|
gtk_tree_model_get( model, iter, MC_TORRENT_RAW, &tor, -1 );
|
||||||
|
|
||||||
text = (const char*) g_object_get_data( o, TEXT_KEY );
|
text = (const char*) g_object_get_data( o, TEXT_KEY );
|
||||||
mode = GPOINTER_TO_INT( g_object_get_data( o, TEXT_MODE_KEY ) );
|
|
||||||
|
|
||||||
return ( tor != NULL ) && testCategory( data->category, tor )
|
return ( tor != NULL ) && testCategory( data->category, tor )
|
||||||
&& testActivity( data->activity, tor )
|
&& testActivity( data->activity, tor )
|
||||||
&& testText( tor, text, mode );
|
&& testText( tor, text );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -987,21 +917,14 @@ selection_changed_cb( GtkComboBox * combo UNUSED, gpointer vdata )
|
||||||
GtkWidget *
|
GtkWidget *
|
||||||
gtr_filter_bar_new( tr_session * session, GtkTreeModel * tmodel, GtkTreeModel ** filter_model )
|
gtr_filter_bar_new( tr_session * session, GtkTreeModel * tmodel, GtkTreeModel ** filter_model )
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
GtkWidget * l;
|
GtkWidget * l;
|
||||||
GtkWidget * w;
|
GtkWidget * w;
|
||||||
GtkWidget * h;
|
GtkWidget * h;
|
||||||
GtkWidget * s;
|
GtkWidget * s;
|
||||||
GtkWidget * menu;
|
|
||||||
GtkWidget * activity;
|
GtkWidget * activity;
|
||||||
GtkWidget * category;
|
GtkWidget * category;
|
||||||
GSList * sl;
|
|
||||||
const char * str;
|
const char * str;
|
||||||
struct filter_data * data;
|
struct filter_data * data;
|
||||||
const char * filter_text_names[] = {
|
|
||||||
N_( "Name" ), N_( "Files" ), N_( "Tracker" )
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
data = g_new( struct filter_data, 1 );
|
data = g_new( struct filter_data, 1 );
|
||||||
data->activity = activity = activity_combo_box_new( tmodel );
|
data->activity = activity = activity_combo_box_new( tmodel );
|
||||||
|
@ -1046,45 +969,22 @@ gtr_filter_bar_new( tr_session * session, GtkTreeModel * tmodel, GtkTreeModel **
|
||||||
gtk_box_pack_start( GTK_BOX( h ), w, FALSE, FALSE, 0 );
|
gtk_box_pack_start( GTK_BOX( h ), w, FALSE, FALSE, 0 );
|
||||||
|
|
||||||
/* add the entry field */
|
/* add the entry field */
|
||||||
#ifdef USE_SEXY
|
#if GTK_CHECK_VERSION( 2,16,0 )
|
||||||
s = sexy_icon_entry_new( );
|
s = gtk_entry_new( );
|
||||||
sexy_icon_entry_add_clear_button( SEXY_ICON_ENTRY( s ) );
|
gtk_entry_set_icon_from_stock( GTK_ENTRY( s ), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR );
|
||||||
w = gtk_image_new_from_stock( GTK_STOCK_FIND, GTK_ICON_SIZE_MENU );
|
g_signal_connect( s, "icon-release", G_CALLBACK( entry_clear ), NULL );
|
||||||
sexy_icon_entry_set_icon( SEXY_ICON_ENTRY( s ),
|
gtk_box_pack_start( GTK_BOX( h ), s, TRUE, TRUE, 0 );
|
||||||
SEXY_ICON_ENTRY_PRIMARY,
|
|
||||||
GTK_IMAGE( w ) );
|
|
||||||
g_object_unref( w );
|
|
||||||
sexy_icon_entry_set_icon_highlight( SEXY_ICON_ENTRY( s ),
|
|
||||||
SEXY_ICON_ENTRY_PRIMARY, TRUE );
|
|
||||||
#else
|
#else
|
||||||
s = gtk_entry_new( );
|
s = gtk_entry_new( );
|
||||||
gtk_entry_set_icon_from_stock( GTK_ENTRY( s ),
|
|
||||||
GTK_ENTRY_ICON_PRIMARY,
|
|
||||||
GTK_STOCK_FIND);
|
|
||||||
gtk_entry_set_icon_from_stock( GTK_ENTRY( s ),
|
|
||||||
GTK_ENTRY_ICON_SECONDARY,
|
|
||||||
GTK_STOCK_CLEAR );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
menu = gtk_menu_new( );
|
|
||||||
sl = NULL;
|
|
||||||
for( i=0; i<TEXT_MODE_N_TYPES; ++i )
|
|
||||||
{
|
|
||||||
const char * name = _( filter_text_names[i] );
|
|
||||||
GtkWidget * w = gtk_radio_menu_item_new_with_label ( sl, name );
|
|
||||||
sl = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM( w ) );
|
|
||||||
g_object_set_data( G_OBJECT( w ), TEXT_MODE_KEY, GINT_TO_POINTER( i ) );
|
|
||||||
g_signal_connect( w, "toggled", G_CALLBACK( filter_text_toggled_cb ), data->filter_model );
|
|
||||||
gtk_menu_shell_append( GTK_MENU_SHELL( menu ), w );
|
|
||||||
gtk_widget_show( w );
|
|
||||||
}
|
|
||||||
#ifdef USE_SEXY
|
|
||||||
g_signal_connect( s, "icon-released", G_CALLBACK( entry_icon_released ), menu );
|
|
||||||
#else
|
|
||||||
g_signal_connect( s, "icon-release", G_CALLBACK( entry_icon_release ), menu );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gtk_box_pack_start( GTK_BOX( h ), s, TRUE, TRUE, 0 );
|
gtk_box_pack_start( GTK_BOX( h ), s, TRUE, TRUE, 0 );
|
||||||
|
w = gtk_button_new( );
|
||||||
|
gtk_button_set_relief( GTK_BUTTON( w ), GTK_RELIEF_NONE );
|
||||||
|
l = gtk_image_new_from_stock( GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU );
|
||||||
|
gtk_button_set_image( GTK_BUTTON( w ), l );
|
||||||
|
gtk_box_pack_start( GTK_BOX( h ), w, FALSE, FALSE, 0 );
|
||||||
|
g_signal_connect_swapped( w, "clicked", G_CALLBACK( entry_clear ), s );
|
||||||
|
#endif
|
||||||
|
|
||||||
g_signal_connect( s, "changed", G_CALLBACK( filter_entry_changed ), data->filter_model );
|
g_signal_connect( s, "changed", G_CALLBACK( filter_entry_changed ), data->filter_model );
|
||||||
|
|
||||||
*filter_model = data->filter_model;
|
*filter_model = data->filter_model;
|
||||||
|
|
|
@ -1,946 +0,0 @@
|
||||||
/*
|
|
||||||
* @file libsexy/sexy-icon-entry.c Entry widget
|
|
||||||
*
|
|
||||||
* @Copyright (C) 2004-2006 Christian Hammond.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
#if !GTK_CHECK_VERSION( 2,16,0 ) /* these features were added to GtkEntry in 2.16 */
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "sexy-icon-entry.h"
|
|
||||||
#include "sexy-marshal.h"
|
|
||||||
|
|
||||||
#define ICON_MARGIN 2
|
|
||||||
#define MAX_ICONS 2
|
|
||||||
|
|
||||||
#define IS_VALID_ICON_ENTRY_POSITION(pos) \
|
|
||||||
((pos) == SEXY_ICON_ENTRY_PRIMARY || \
|
|
||||||
(pos) == SEXY_ICON_ENTRY_SECONDARY)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GtkImage *icon;
|
|
||||||
gboolean highlight;
|
|
||||||
gboolean hovered;
|
|
||||||
GdkWindow *window;
|
|
||||||
|
|
||||||
} SexyIconInfo;
|
|
||||||
|
|
||||||
struct _SexyIconEntryPriv
|
|
||||||
{
|
|
||||||
SexyIconInfo icons[MAX_ICONS];
|
|
||||||
|
|
||||||
gulong icon_released_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
ICON_PRESSED,
|
|
||||||
ICON_RELEASED,
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
static void sexy_icon_entry_editable_init(GtkEditableClass *iface);
|
|
||||||
static void sexy_icon_entry_finalize(GObject *obj);
|
|
||||||
static void sexy_icon_entry_destroy(GtkObject *obj);
|
|
||||||
static void sexy_icon_entry_map(GtkWidget *widget);
|
|
||||||
static void sexy_icon_entry_unmap(GtkWidget *widget);
|
|
||||||
static void sexy_icon_entry_realize(GtkWidget *widget);
|
|
||||||
static void sexy_icon_entry_unrealize(GtkWidget *widget);
|
|
||||||
static void sexy_icon_entry_size_request(GtkWidget *widget,
|
|
||||||
GtkRequisition *requisition);
|
|
||||||
static void sexy_icon_entry_size_allocate(GtkWidget *widget,
|
|
||||||
GtkAllocation *allocation);
|
|
||||||
static gint sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event);
|
|
||||||
static gint sexy_icon_entry_enter_notify(GtkWidget *widget,
|
|
||||||
GdkEventCrossing *event);
|
|
||||||
static gint sexy_icon_entry_leave_notify(GtkWidget *widget,
|
|
||||||
GdkEventCrossing *event);
|
|
||||||
static gint sexy_icon_entry_button_press(GtkWidget *widget,
|
|
||||||
GdkEventButton *event);
|
|
||||||
static gint sexy_icon_entry_button_release(GtkWidget *widget,
|
|
||||||
GdkEventButton *event);
|
|
||||||
|
|
||||||
static GtkEntryClass *parent_class = NULL;
|
|
||||||
static guint signals[LAST_SIGNAL] = {0};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_EXTENDED(SexyIconEntry, sexy_icon_entry, GTK_TYPE_ENTRY,
|
|
||||||
0,
|
|
||||||
G_IMPLEMENT_INTERFACE(GTK_TYPE_EDITABLE,
|
|
||||||
sexy_icon_entry_editable_init));
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_class_init(SexyIconEntryClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
GtkObjectClass *object_class;
|
|
||||||
GtkWidgetClass *widget_class;
|
|
||||||
GtkEntryClass *entry_class;
|
|
||||||
|
|
||||||
parent_class = g_type_class_peek_parent(klass);
|
|
||||||
|
|
||||||
gobject_class = G_OBJECT_CLASS(klass);
|
|
||||||
object_class = GTK_OBJECT_CLASS(klass);
|
|
||||||
widget_class = GTK_WIDGET_CLASS(klass);
|
|
||||||
entry_class = GTK_ENTRY_CLASS(klass);
|
|
||||||
|
|
||||||
gobject_class->finalize = sexy_icon_entry_finalize;
|
|
||||||
|
|
||||||
object_class->destroy = sexy_icon_entry_destroy;
|
|
||||||
|
|
||||||
widget_class->map = sexy_icon_entry_map;
|
|
||||||
widget_class->unmap = sexy_icon_entry_unmap;
|
|
||||||
widget_class->realize = sexy_icon_entry_realize;
|
|
||||||
widget_class->unrealize = sexy_icon_entry_unrealize;
|
|
||||||
widget_class->size_request = sexy_icon_entry_size_request;
|
|
||||||
widget_class->size_allocate = sexy_icon_entry_size_allocate;
|
|
||||||
widget_class->expose_event = sexy_icon_entry_expose;
|
|
||||||
widget_class->enter_notify_event = sexy_icon_entry_enter_notify;
|
|
||||||
widget_class->leave_notify_event = sexy_icon_entry_leave_notify;
|
|
||||||
widget_class->button_press_event = sexy_icon_entry_button_press;
|
|
||||||
widget_class->button_release_event = sexy_icon_entry_button_release;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SexyIconEntry::icon-pressed:
|
|
||||||
* @entry: The entry on which the signal is emitted.
|
|
||||||
* @icon_pos: The position of the clicked icon.
|
|
||||||
* @button: The mouse button clicked.
|
|
||||||
*
|
|
||||||
* The ::icon-pressed signal is emitted when an icon is clicked.
|
|
||||||
*/
|
|
||||||
signals[ICON_PRESSED] =
|
|
||||||
g_signal_new("icon_pressed",
|
|
||||||
G_TYPE_FROM_CLASS(gobject_class),
|
|
||||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
|
||||||
G_STRUCT_OFFSET(SexyIconEntryClass, icon_pressed),
|
|
||||||
NULL, NULL,
|
|
||||||
sexy_marshal_VOID__INT_INT,
|
|
||||||
G_TYPE_NONE, 2,
|
|
||||||
G_TYPE_INT,
|
|
||||||
G_TYPE_INT);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SexyIconEntry::icon-released:
|
|
||||||
* @entry: The entry on which the signal is emitted.
|
|
||||||
* @icon_pos: The position of the clicked icon.
|
|
||||||
* @button: The mouse button clicked.
|
|
||||||
*
|
|
||||||
* The ::icon-released signal is emitted on the button release from a
|
|
||||||
* mouse click.
|
|
||||||
*/
|
|
||||||
signals[ICON_RELEASED] =
|
|
||||||
g_signal_new("icon_released",
|
|
||||||
G_TYPE_FROM_CLASS(gobject_class),
|
|
||||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
|
||||||
G_STRUCT_OFFSET(SexyIconEntryClass, icon_released),
|
|
||||||
NULL, NULL,
|
|
||||||
sexy_marshal_VOID__INT_INT,
|
|
||||||
G_TYPE_NONE, 2,
|
|
||||||
G_TYPE_INT,
|
|
||||||
G_TYPE_INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_editable_init(GtkEditableClass *iface G_GNUC_UNUSED)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_init(SexyIconEntry *entry)
|
|
||||||
{
|
|
||||||
entry->priv = g_new0(SexyIconEntryPriv, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_finalize(GObject *obj)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry;
|
|
||||||
|
|
||||||
g_return_if_fail(obj != NULL);
|
|
||||||
g_return_if_fail(SEXY_IS_ICON_ENTRY(obj));
|
|
||||||
|
|
||||||
entry = SEXY_ICON_ENTRY(obj);
|
|
||||||
|
|
||||||
g_free(entry->priv);
|
|
||||||
|
|
||||||
if (G_OBJECT_CLASS(parent_class)->finalize)
|
|
||||||
G_OBJECT_CLASS(parent_class)->finalize(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_destroy(GtkObject *obj)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry;
|
|
||||||
|
|
||||||
entry = SEXY_ICON_ENTRY(obj);
|
|
||||||
|
|
||||||
sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_PRIMARY, NULL);
|
|
||||||
sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_SECONDARY, NULL);
|
|
||||||
|
|
||||||
if (GTK_OBJECT_CLASS(parent_class)->destroy)
|
|
||||||
GTK_OBJECT_CLASS(parent_class)->destroy(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_map(GtkWidget *widget)
|
|
||||||
{
|
|
||||||
if (GTK_WIDGET_REALIZED(widget) && !GTK_WIDGET_MAPPED(widget))
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS(parent_class)->map(widget);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
gdk_window_show(entry->priv->icons[i].window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_unmap(GtkWidget *widget)
|
|
||||||
{
|
|
||||||
if (GTK_WIDGET_MAPPED(widget))
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
gdk_window_hide(entry->priv->icons[i].window);
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS(parent_class)->unmap(widget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
get_icon_width(SexyIconEntry *entry, SexyIconEntryPosition icon_pos)
|
|
||||||
{
|
|
||||||
GtkRequisition requisition;
|
|
||||||
gint menu_icon_width;
|
|
||||||
gint width;
|
|
||||||
SexyIconInfo *icon_info = &entry->priv->icons[icon_pos];
|
|
||||||
|
|
||||||
if (icon_info->icon == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
gtk_widget_size_request(GTK_WIDGET(icon_info->icon), &requisition);
|
|
||||||
gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &menu_icon_width, NULL);
|
|
||||||
|
|
||||||
width = MAX(requisition.width, menu_icon_width);
|
|
||||||
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_borders(SexyIconEntry *entry, gint *xborder, gint *yborder)
|
|
||||||
{
|
|
||||||
GtkWidget *widget = GTK_WIDGET(entry);
|
|
||||||
gint focus_width;
|
|
||||||
gboolean interior_focus;
|
|
||||||
|
|
||||||
gtk_widget_style_get(widget,
|
|
||||||
"interior-focus", &interior_focus,
|
|
||||||
"focus-line-width", &focus_width,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (gtk_entry_get_has_frame(GTK_ENTRY(entry)))
|
|
||||||
{
|
|
||||||
*xborder = widget->style->xthickness;
|
|
||||||
*yborder = widget->style->ythickness;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*xborder = 0;
|
|
||||||
*yborder = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!interior_focus)
|
|
||||||
{
|
|
||||||
*xborder += focus_width;
|
|
||||||
*yborder += focus_width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_text_area_size(SexyIconEntry *entry, GtkAllocation *alloc)
|
|
||||||
{
|
|
||||||
GtkWidget *widget = GTK_WIDGET(entry);
|
|
||||||
GtkRequisition requisition;
|
|
||||||
gint xborder, yborder;
|
|
||||||
|
|
||||||
gtk_widget_get_child_requisition(widget, &requisition);
|
|
||||||
get_borders(entry, &xborder, &yborder);
|
|
||||||
|
|
||||||
alloc->x = xborder;
|
|
||||||
alloc->y = yborder;
|
|
||||||
alloc->width = widget->allocation.width - xborder * 2;
|
|
||||||
alloc->height = requisition.height - yborder * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_icon_allocation(SexyIconEntry *icon_entry,
|
|
||||||
gboolean left,
|
|
||||||
GtkAllocation *widget_alloc G_GNUC_UNUSED,
|
|
||||||
GtkAllocation *text_area_alloc,
|
|
||||||
GtkAllocation *allocation,
|
|
||||||
SexyIconEntryPosition *icon_pos)
|
|
||||||
{
|
|
||||||
gboolean rtl;
|
|
||||||
|
|
||||||
rtl = (gtk_widget_get_direction(GTK_WIDGET(icon_entry)) ==
|
|
||||||
GTK_TEXT_DIR_RTL);
|
|
||||||
|
|
||||||
if (left)
|
|
||||||
*icon_pos = (rtl ? SEXY_ICON_ENTRY_SECONDARY : SEXY_ICON_ENTRY_PRIMARY);
|
|
||||||
else
|
|
||||||
*icon_pos = (rtl ? SEXY_ICON_ENTRY_PRIMARY : SEXY_ICON_ENTRY_SECONDARY);
|
|
||||||
|
|
||||||
allocation->y = text_area_alloc->y;
|
|
||||||
allocation->width = get_icon_width(icon_entry, *icon_pos);
|
|
||||||
allocation->height = text_area_alloc->height;
|
|
||||||
|
|
||||||
if (left)
|
|
||||||
allocation->x = text_area_alloc->x + ICON_MARGIN;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
allocation->x = text_area_alloc->x + text_area_alloc->width -
|
|
||||||
allocation->width - ICON_MARGIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_realize(GtkWidget *widget)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
GdkWindowAttr attributes;
|
|
||||||
gint attributes_mask;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS(parent_class)->realize(widget);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
{
|
|
||||||
SexyIconInfo *icon_info;
|
|
||||||
|
|
||||||
attributes.window_type = GDK_WINDOW_CHILD;
|
|
||||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
|
||||||
attributes.visual = gtk_widget_get_visual(widget);
|
|
||||||
attributes.colormap = gtk_widget_get_colormap(widget);
|
|
||||||
attributes.event_mask = gtk_widget_get_events(widget);
|
|
||||||
attributes.event_mask |=
|
|
||||||
(GDK_EXPOSURE_MASK
|
|
||||||
| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
|
|
||||||
| GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
|
|
||||||
|
|
||||||
attributes_mask = GDK_WA_X | GDK_WA_Y |
|
|
||||||
GDK_WA_VISUAL | GDK_WA_COLORMAP;
|
|
||||||
|
|
||||||
icon_info = &entry->priv->icons[i];
|
|
||||||
icon_info->window = gdk_window_new(widget->window, &attributes,
|
|
||||||
attributes_mask);
|
|
||||||
gdk_window_set_user_data(icon_info->window, widget);
|
|
||||||
|
|
||||||
gdk_window_set_background(icon_info->window,
|
|
||||||
&widget->style->base[GTK_WIDGET_STATE(widget)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_queue_resize(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_unrealize(GtkWidget *widget)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS(parent_class)->unrealize(widget);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
{
|
|
||||||
SexyIconInfo *icon_info = &entry->priv->icons[i];
|
|
||||||
|
|
||||||
gdk_window_destroy(icon_info->window);
|
|
||||||
icon_info->window = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_size_request(GtkWidget *widget, GtkRequisition *requisition)
|
|
||||||
{
|
|
||||||
GtkEntry *gtkentry;
|
|
||||||
SexyIconEntry *entry;
|
|
||||||
gint icon_widths = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
gtkentry = GTK_ENTRY(widget);
|
|
||||||
entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
{
|
|
||||||
int icon_width = get_icon_width(entry, i);
|
|
||||||
|
|
||||||
if (icon_width > 0)
|
|
||||||
icon_widths += icon_width + ICON_MARGIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS(parent_class)->size_request(widget, requisition);
|
|
||||||
|
|
||||||
if (icon_widths > requisition->width)
|
|
||||||
requisition->width += icon_widths;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
place_windows(SexyIconEntry *icon_entry, GtkAllocation *widget_alloc)
|
|
||||||
{
|
|
||||||
SexyIconEntryPosition left_icon_pos;
|
|
||||||
SexyIconEntryPosition right_icon_pos;
|
|
||||||
GtkAllocation left_icon_alloc;
|
|
||||||
GtkAllocation right_icon_alloc;
|
|
||||||
GtkAllocation text_area_alloc;
|
|
||||||
|
|
||||||
get_text_area_size(icon_entry, &text_area_alloc);
|
|
||||||
get_icon_allocation(icon_entry, TRUE, widget_alloc, &text_area_alloc,
|
|
||||||
&left_icon_alloc, &left_icon_pos);
|
|
||||||
get_icon_allocation(icon_entry, FALSE, widget_alloc, &text_area_alloc,
|
|
||||||
&right_icon_alloc, &right_icon_pos);
|
|
||||||
|
|
||||||
if (left_icon_alloc.width > 0)
|
|
||||||
{
|
|
||||||
text_area_alloc.x = left_icon_alloc.x + left_icon_alloc.width +
|
|
||||||
ICON_MARGIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (right_icon_alloc.width > 0)
|
|
||||||
text_area_alloc.width -= right_icon_alloc.width + ICON_MARGIN;
|
|
||||||
|
|
||||||
text_area_alloc.width -= text_area_alloc.x;
|
|
||||||
|
|
||||||
gdk_window_move_resize(icon_entry->priv->icons[left_icon_pos].window,
|
|
||||||
left_icon_alloc.x, left_icon_alloc.y,
|
|
||||||
left_icon_alloc.width, left_icon_alloc.height);
|
|
||||||
|
|
||||||
gdk_window_move_resize(icon_entry->priv->icons[right_icon_pos].window,
|
|
||||||
right_icon_alloc.x, right_icon_alloc.y,
|
|
||||||
right_icon_alloc.width, right_icon_alloc.height);
|
|
||||||
|
|
||||||
gdk_window_move_resize(GTK_ENTRY(icon_entry)->text_area,
|
|
||||||
text_area_alloc.x, text_area_alloc.y,
|
|
||||||
text_area_alloc.width, text_area_alloc.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sexy_icon_entry_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
|
|
||||||
{
|
|
||||||
g_return_if_fail(SEXY_IS_ICON_ENTRY(widget));
|
|
||||||
g_return_if_fail(allocation != NULL);
|
|
||||||
|
|
||||||
widget->allocation = *allocation;
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation);
|
|
||||||
|
|
||||||
if (GTK_WIDGET_REALIZED(widget))
|
|
||||||
place_windows(SEXY_ICON_ENTRY(widget), allocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdkPixbuf *
|
|
||||||
get_pixbuf_from_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos)
|
|
||||||
{
|
|
||||||
GdkPixbuf *pixbuf = NULL;
|
|
||||||
gchar *stock_id;
|
|
||||||
SexyIconInfo *icon_info = &entry->priv->icons[icon_pos];
|
|
||||||
GtkIconSize size;
|
|
||||||
|
|
||||||
switch (gtk_image_get_storage_type(GTK_IMAGE(icon_info->icon)))
|
|
||||||
{
|
|
||||||
case GTK_IMAGE_PIXBUF:
|
|
||||||
pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(icon_info->icon));
|
|
||||||
g_object_ref(pixbuf);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GTK_IMAGE_STOCK:
|
|
||||||
gtk_image_get_stock(GTK_IMAGE(icon_info->icon), &stock_id, &size);
|
|
||||||
pixbuf = gtk_widget_render_icon(GTK_WIDGET(entry),
|
|
||||||
stock_id, size, NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pixbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Kudos to the gnome-panel guys. */
|
|
||||||
static void
|
|
||||||
colorshift_pixbuf(GdkPixbuf *dest, GdkPixbuf *src, int shift)
|
|
||||||
{
|
|
||||||
gint i, j;
|
|
||||||
gint width, height, has_alpha, src_rowstride, dest_rowstride;
|
|
||||||
guchar *target_pixels;
|
|
||||||
guchar *original_pixels;
|
|
||||||
guchar *pix_src;
|
|
||||||
guchar *pix_dest;
|
|
||||||
int val;
|
|
||||||
guchar r, g, b;
|
|
||||||
|
|
||||||
has_alpha = gdk_pixbuf_get_has_alpha(src);
|
|
||||||
width = gdk_pixbuf_get_width(src);
|
|
||||||
height = gdk_pixbuf_get_height(src);
|
|
||||||
src_rowstride = gdk_pixbuf_get_rowstride(src);
|
|
||||||
dest_rowstride = gdk_pixbuf_get_rowstride(dest);
|
|
||||||
original_pixels = gdk_pixbuf_get_pixels(src);
|
|
||||||
target_pixels = gdk_pixbuf_get_pixels(dest);
|
|
||||||
|
|
||||||
for (i = 0; i < height; i++)
|
|
||||||
{
|
|
||||||
pix_dest = target_pixels + i * dest_rowstride;
|
|
||||||
pix_src = original_pixels + i * src_rowstride;
|
|
||||||
|
|
||||||
for (j = 0; j < width; j++)
|
|
||||||
{
|
|
||||||
r = *(pix_src++);
|
|
||||||
g = *(pix_src++);
|
|
||||||
b = *(pix_src++);
|
|
||||||
|
|
||||||
val = r + shift;
|
|
||||||
*(pix_dest++) = CLAMP(val, 0, 255);
|
|
||||||
|
|
||||||
val = g + shift;
|
|
||||||
*(pix_dest++) = CLAMP(val, 0, 255);
|
|
||||||
|
|
||||||
val = b + shift;
|
|
||||||
*(pix_dest++) = CLAMP(val, 0, 255);
|
|
||||||
|
|
||||||
if (has_alpha)
|
|
||||||
*(pix_dest++) = *(pix_src++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
draw_icon(GtkWidget *widget, SexyIconEntryPosition icon_pos)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
SexyIconInfo *icon_info = &entry->priv->icons[icon_pos];
|
|
||||||
GdkPixbuf *pixbuf;
|
|
||||||
gint x, y, width, height;
|
|
||||||
|
|
||||||
if (icon_info->icon == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((pixbuf = get_pixbuf_from_icon(entry, icon_pos)) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
gdk_drawable_get_size(icon_info->window, &width, &height);
|
|
||||||
|
|
||||||
if (gdk_pixbuf_get_height(pixbuf) > height)
|
|
||||||
{
|
|
||||||
GdkPixbuf *temp_pixbuf;
|
|
||||||
int scale;
|
|
||||||
|
|
||||||
scale = height - (2 * ICON_MARGIN);
|
|
||||||
|
|
||||||
temp_pixbuf = gdk_pixbuf_scale_simple(pixbuf, scale, scale,
|
|
||||||
GDK_INTERP_BILINEAR);
|
|
||||||
|
|
||||||
g_object_unref(pixbuf);
|
|
||||||
|
|
||||||
pixbuf = temp_pixbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = (width - gdk_pixbuf_get_width(pixbuf)) / 2;
|
|
||||||
y = (height - gdk_pixbuf_get_height(pixbuf)) / 2;
|
|
||||||
|
|
||||||
if (icon_info->hovered)
|
|
||||||
{
|
|
||||||
GdkPixbuf *temp_pixbuf;
|
|
||||||
|
|
||||||
temp_pixbuf = gdk_pixbuf_copy(pixbuf);
|
|
||||||
|
|
||||||
colorshift_pixbuf(temp_pixbuf, pixbuf, 30);
|
|
||||||
|
|
||||||
g_object_unref(pixbuf);
|
|
||||||
|
|
||||||
pixbuf = temp_pixbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
gdk_draw_pixbuf(icon_info->window, widget->style->black_gc, pixbuf,
|
|
||||||
0, 0, x, y, -1, -1,
|
|
||||||
GDK_RGB_DITHER_NORMAL, 0, 0);
|
|
||||||
|
|
||||||
g_object_unref(pixbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry;
|
|
||||||
|
|
||||||
g_return_val_if_fail(SEXY_IS_ICON_ENTRY(widget), FALSE);
|
|
||||||
g_return_val_if_fail(event != NULL, FALSE);
|
|
||||||
|
|
||||||
entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
|
|
||||||
if (GTK_WIDGET_DRAWABLE(widget))
|
|
||||||
{
|
|
||||||
gboolean found = FALSE;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS && !found; i++)
|
|
||||||
{
|
|
||||||
SexyIconInfo *icon_info = &entry->priv->icons[i];
|
|
||||||
|
|
||||||
if (event->window == icon_info->window)
|
|
||||||
{
|
|
||||||
gint width;
|
|
||||||
GtkAllocation text_area_alloc;
|
|
||||||
|
|
||||||
get_text_area_size(entry, &text_area_alloc);
|
|
||||||
gdk_drawable_get_size(icon_info->window, &width, NULL);
|
|
||||||
|
|
||||||
gtk_paint_flat_box(widget->style, icon_info->window,
|
|
||||||
GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
|
|
||||||
NULL, widget, "entry_bg",
|
|
||||||
0, 0, width, text_area_alloc.height);
|
|
||||||
|
|
||||||
draw_icon(widget, i);
|
|
||||||
|
|
||||||
found = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_icon(GObject *obj G_GNUC_UNUSED, GParamSpec *param, SexyIconEntry *entry)
|
|
||||||
{
|
|
||||||
if (param != NULL)
|
|
||||||
{
|
|
||||||
const char *name = g_param_spec_get_name(param);
|
|
||||||
|
|
||||||
if (strcmp(name, "pixbuf") && strcmp(name, "stock") &&
|
|
||||||
strcmp(name, "image") && strcmp(name, "pixmap") &&
|
|
||||||
strcmp(name, "icon_set") && strcmp(name, "pixbuf_animation"))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_queue_resize(GTK_WIDGET(entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
sexy_icon_entry_enter_notify(GtkWidget *widget, GdkEventCrossing *event)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
{
|
|
||||||
if (event->window == entry->priv->icons[i].window)
|
|
||||||
{
|
|
||||||
if (sexy_icon_entry_get_icon_highlight(entry, i))
|
|
||||||
{
|
|
||||||
entry->priv->icons[i].hovered = TRUE;
|
|
||||||
|
|
||||||
update_icon(NULL, NULL, entry);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
sexy_icon_entry_leave_notify(GtkWidget *widget, GdkEventCrossing *event)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
{
|
|
||||||
if (event->window == entry->priv->icons[i].window)
|
|
||||||
{
|
|
||||||
if (sexy_icon_entry_get_icon_highlight(entry, i))
|
|
||||||
{
|
|
||||||
entry->priv->icons[i].hovered = FALSE;
|
|
||||||
|
|
||||||
update_icon(NULL, NULL, entry);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
sexy_icon_entry_button_press(GtkWidget *widget, GdkEventButton *event)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
{
|
|
||||||
if (event->window == entry->priv->icons[i].window)
|
|
||||||
{
|
|
||||||
if (event->button == 1 &&
|
|
||||||
sexy_icon_entry_get_icon_highlight(entry, i))
|
|
||||||
{
|
|
||||||
entry->priv->icons[i].hovered = FALSE;
|
|
||||||
|
|
||||||
update_icon(NULL, NULL, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_signal_emit(entry, signals[ICON_PRESSED], 0, i, event->button);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GTK_WIDGET_CLASS(parent_class)->button_press_event)
|
|
||||||
return GTK_WIDGET_CLASS(parent_class)->button_press_event(widget,
|
|
||||||
event);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
sexy_icon_entry_button_release(GtkWidget *widget, GdkEventButton *event)
|
|
||||||
{
|
|
||||||
SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_ICONS; i++)
|
|
||||||
{
|
|
||||||
GdkWindow *icon_window = entry->priv->icons[i].window;
|
|
||||||
|
|
||||||
if (event->window == icon_window)
|
|
||||||
{
|
|
||||||
int width, height;
|
|
||||||
gdk_drawable_get_size(icon_window, &width, &height);
|
|
||||||
|
|
||||||
if (event->button == 1 &&
|
|
||||||
sexy_icon_entry_get_icon_highlight(entry, i) &&
|
|
||||||
event->x >= 0 && event->y >= 0 &&
|
|
||||||
event->x <= width && event->y <= height)
|
|
||||||
{
|
|
||||||
entry->priv->icons[i].hovered = TRUE;
|
|
||||||
|
|
||||||
update_icon(NULL, NULL, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_signal_emit(entry, signals[ICON_RELEASED], 0, i, event->button);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GTK_WIDGET_CLASS(parent_class)->button_release_event)
|
|
||||||
return GTK_WIDGET_CLASS(parent_class)->button_release_event(widget,
|
|
||||||
event);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sexy_icon_entry_new
|
|
||||||
*
|
|
||||||
* Creates a new SexyIconEntry widget.
|
|
||||||
*
|
|
||||||
* Returns a new #SexyIconEntry.
|
|
||||||
*/
|
|
||||||
GtkWidget *
|
|
||||||
sexy_icon_entry_new(void)
|
|
||||||
{
|
|
||||||
return GTK_WIDGET(g_object_new(SEXY_TYPE_ICON_ENTRY, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sexy_icon_entry_set_icon
|
|
||||||
* @entry: A #SexyIconEntry.
|
|
||||||
* @position: Icon position.
|
|
||||||
* @icon: A #GtkImage to set as the icon.
|
|
||||||
*
|
|
||||||
* Sets the icon shown in the entry
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sexy_icon_entry_set_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos,
|
|
||||||
GtkImage *icon)
|
|
||||||
{
|
|
||||||
SexyIconInfo *icon_info;
|
|
||||||
|
|
||||||
g_return_if_fail(entry != NULL);
|
|
||||||
g_return_if_fail(SEXY_IS_ICON_ENTRY(entry));
|
|
||||||
g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos));
|
|
||||||
g_return_if_fail(icon == NULL || GTK_IS_IMAGE(icon));
|
|
||||||
|
|
||||||
icon_info = &entry->priv->icons[icon_pos];
|
|
||||||
|
|
||||||
if (icon == icon_info->icon)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (icon_pos == SEXY_ICON_ENTRY_SECONDARY &&
|
|
||||||
entry->priv->icon_released_id != 0)
|
|
||||||
{
|
|
||||||
g_signal_handler_disconnect(entry, entry->priv->icon_released_id);
|
|
||||||
entry->priv->icon_released_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (icon == NULL)
|
|
||||||
{
|
|
||||||
if (icon_info->icon != NULL)
|
|
||||||
{
|
|
||||||
gtk_widget_destroy(GTK_WIDGET(icon_info->icon));
|
|
||||||
icon_info->icon = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_signal_connect(G_OBJECT(icon), "notify",
|
|
||||||
G_CALLBACK(update_icon), entry);
|
|
||||||
|
|
||||||
icon_info->icon = icon;
|
|
||||||
|
|
||||||
g_object_ref(icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_icon(NULL, NULL, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sexy_icon_entry_set_icon_highlight
|
|
||||||
* @entry: A #SexyIconEntry;
|
|
||||||
* @position: Icon position.
|
|
||||||
* @highlight: TRUE if the icon should highlight on mouse-over
|
|
||||||
*
|
|
||||||
* Determines whether the icon will highlight on mouse-over.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sexy_icon_entry_set_icon_highlight(SexyIconEntry *entry,
|
|
||||||
SexyIconEntryPosition icon_pos,
|
|
||||||
gboolean highlight)
|
|
||||||
{
|
|
||||||
SexyIconInfo *icon_info;
|
|
||||||
|
|
||||||
g_return_if_fail(entry != NULL);
|
|
||||||
g_return_if_fail(SEXY_IS_ICON_ENTRY(entry));
|
|
||||||
g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos));
|
|
||||||
|
|
||||||
icon_info = &entry->priv->icons[icon_pos];
|
|
||||||
|
|
||||||
if (icon_info->highlight == highlight)
|
|
||||||
return;
|
|
||||||
|
|
||||||
icon_info->highlight = highlight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sexy_icon_entry_get_icon
|
|
||||||
* @entry: A #SexyIconEntry.
|
|
||||||
* @position: Icon position.
|
|
||||||
*
|
|
||||||
* Retrieves the image used for the icon
|
|
||||||
*
|
|
||||||
* Returns: A #GtkImage.
|
|
||||||
*/
|
|
||||||
GtkImage *
|
|
||||||
sexy_icon_entry_get_icon(const SexyIconEntry *entry,
|
|
||||||
SexyIconEntryPosition icon_pos)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail(entry != NULL, NULL);
|
|
||||||
g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), NULL);
|
|
||||||
g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), NULL);
|
|
||||||
|
|
||||||
return entry->priv->icons[icon_pos].icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sexy_icon_entry_get_icon_highlight
|
|
||||||
* @entry: A #SexyIconEntry.
|
|
||||||
* @position: Icon position.
|
|
||||||
*
|
|
||||||
* Retrieves whether entry will highlight the icon on mouseover.
|
|
||||||
*
|
|
||||||
* Returns: TRUE if icon highlights.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
sexy_icon_entry_get_icon_highlight(const SexyIconEntry *entry,
|
|
||||||
SexyIconEntryPosition icon_pos)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail(entry != NULL, FALSE);
|
|
||||||
g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), FALSE);
|
|
||||||
g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), FALSE);
|
|
||||||
|
|
||||||
return entry->priv->icons[icon_pos].highlight;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clear_button_clicked_cb(SexyIconEntry *icon_entry,
|
|
||||||
SexyIconEntryPosition icon_pos,
|
|
||||||
int button)
|
|
||||||
{
|
|
||||||
if (icon_pos != SEXY_ICON_ENTRY_SECONDARY || button != 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
gtk_entry_set_text(GTK_ENTRY(icon_entry), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sexy_icon_entry_add_clear_button
|
|
||||||
* @icon_entry: A #SexyIconEntry.
|
|
||||||
*
|
|
||||||
* A convenience function to add a clear button to the end of the entry.
|
|
||||||
* This is useful for search boxes.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sexy_icon_entry_add_clear_button(SexyIconEntry *icon_entry)
|
|
||||||
{
|
|
||||||
GtkWidget *icon;
|
|
||||||
|
|
||||||
g_return_if_fail(icon_entry != NULL);
|
|
||||||
g_return_if_fail(SEXY_IS_ICON_ENTRY(icon_entry));
|
|
||||||
|
|
||||||
icon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
|
|
||||||
gtk_widget_show(icon);
|
|
||||||
sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(icon_entry),
|
|
||||||
SEXY_ICON_ENTRY_SECONDARY,
|
|
||||||
GTK_IMAGE(icon));
|
|
||||||
sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(icon_entry),
|
|
||||||
SEXY_ICON_ENTRY_SECONDARY, TRUE);
|
|
||||||
g_object_unref(icon);
|
|
||||||
|
|
||||||
if (icon_entry->priv->icon_released_id != 0)
|
|
||||||
{
|
|
||||||
g_signal_handler_disconnect(icon_entry,
|
|
||||||
icon_entry->priv->icon_released_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
icon_entry->priv->icon_released_id =
|
|
||||||
g_signal_connect(G_OBJECT(icon_entry), "icon_released",
|
|
||||||
G_CALLBACK(clear_button_clicked_cb), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* #if !GTK_CHECK_VERSION( 2,16,0 ) */
|
|
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
* @file libsexy/sexy-icon-entry.h Entry widget
|
|
||||||
*
|
|
||||||
* @Copyright (C) 2004-2006 Christian Hammond.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
#ifndef _SEXY_ICON_ENTRY_H_
|
|
||||||
#define _SEXY_ICON_ENTRY_H_
|
|
||||||
|
|
||||||
typedef struct _SexyIconEntry SexyIconEntry;
|
|
||||||
typedef struct _SexyIconEntryClass SexyIconEntryClass;
|
|
||||||
typedef struct _SexyIconEntryPriv SexyIconEntryPriv;
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#define SEXY_TYPE_ICON_ENTRY ( sexy_icon_entry_get_type( ) )
|
|
||||||
#define SEXY_ICON_ENTRY( obj ) \
|
|
||||||
( G_TYPE_CHECK_INSTANCE_CAST( ( obj ), SEXY_TYPE_ICON_ENTRY,\
|
|
||||||
SexyIconEntry ) )
|
|
||||||
#define SEXY_ICON_ENTRY_CLASS( klass ) \
|
|
||||||
( G_TYPE_CHECK_CLASS_CAST( ( klass ), SEXY_TYPE_ICON_ENTRY,\
|
|
||||||
SexyIconEntryClass ) )
|
|
||||||
#define SEXY_IS_ICON_ENTRY( obj ) \
|
|
||||||
( G_TYPE_CHECK_INSTANCE_TYPE( ( obj ), SEXY_TYPE_ICON_ENTRY ) )
|
|
||||||
#define SEXY_IS_ICON_ENTRY_CLASS( klass ) \
|
|
||||||
( G_TYPE_CHECK_CLASS_TYPE( ( klass ), SEXY_TYPE_ICON_ENTRY ) )
|
|
||||||
#define SEXY_ICON_ENTRY_GET_CLASS( obj ) \
|
|
||||||
( G_TYPE_INSTANCE_GET_CLASS ( ( obj ), SEXY_TYPE_ICON_ENTRY,\
|
|
||||||
SexyIconEntryClass ) )
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
SEXY_ICON_ENTRY_PRIMARY,
|
|
||||||
SEXY_ICON_ENTRY_SECONDARY
|
|
||||||
} SexyIconEntryPosition;
|
|
||||||
|
|
||||||
struct _SexyIconEntry
|
|
||||||
{
|
|
||||||
GtkEntry parent_object;
|
|
||||||
|
|
||||||
SexyIconEntryPriv * priv;
|
|
||||||
|
|
||||||
void ( *gtk_reserved1 )( void );
|
|
||||||
void ( *gtk_reserved2 )( void );
|
|
||||||
void ( *gtk_reserved3 )( void );
|
|
||||||
void ( *gtk_reserved4 )( void );
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _SexyIconEntryClass
|
|
||||||
{
|
|
||||||
GtkEntryClass parent_class;
|
|
||||||
|
|
||||||
/* Signals */
|
|
||||||
void ( *icon_pressed )( SexyIconEntry * entry,
|
|
||||||
SexyIconEntryPosition icon_pos,
|
|
||||||
int button );
|
|
||||||
void ( *icon_released )( SexyIconEntry * entry,
|
|
||||||
SexyIconEntryPosition icon_pos,
|
|
||||||
int button );
|
|
||||||
|
|
||||||
void ( *gtk_reserved1 )( void );
|
|
||||||
void ( *gtk_reserved2 )( void );
|
|
||||||
void ( *gtk_reserved3 )( void );
|
|
||||||
void ( *gtk_reserved4 )( void );
|
|
||||||
};
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
GType sexy_icon_entry_get_type( void );
|
|
||||||
|
|
||||||
GtkWidget *sexy_icon_entry_new( void );
|
|
||||||
|
|
||||||
void sexy_icon_entry_set_icon( SexyIconEntry * entry,
|
|
||||||
SexyIconEntryPosition position,
|
|
||||||
GtkImage * icon );
|
|
||||||
|
|
||||||
void sexy_icon_entry_set_icon_highlight(
|
|
||||||
SexyIconEntry *entry,
|
|
||||||
SexyIconEntryPosition
|
|
||||||
position,
|
|
||||||
gboolean
|
|
||||||
highlight );
|
|
||||||
|
|
||||||
GtkImage * sexy_icon_entry_get_icon( const SexyIconEntry * entry,
|
|
||||||
SexyIconEntryPosition position );
|
|
||||||
|
|
||||||
gboolean sexy_icon_entry_get_icon_highlight(
|
|
||||||
const SexyIconEntry *entry,
|
|
||||||
SexyIconEntryPosition
|
|
||||||
position );
|
|
||||||
|
|
||||||
void sexy_icon_entry_add_clear_button( SexyIconEntry *icon_entry );
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* _SEXY_ICON_ENTRY_H_ */
|
|
|
@ -27,13 +27,6 @@
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
#if !GTK_CHECK_VERSION( 2,16,0 )
|
|
||||||
/* FIXME: when 2.16 has been out long enough, it would be really nice to
|
|
||||||
* get rid of this libsexy usage because of its makefile strangeness */
|
|
||||||
#define USE_SEXY
|
|
||||||
#include "sexy-icon-entry.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <libtransmission/transmission.h>
|
#include <libtransmission/transmission.h>
|
||||||
|
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
|
|
Loading…
Reference in New Issue