ink-comboboxentry-action.cpp revision 05f67cb24e85f68a8affabd568f5147a8df47f2c
/*
* A subclass of GtkAction that wraps a GtkComboBoxEntry.
* Features:
* Setting GtkEntryBox width in characters.
* Passing a function for formatting cells.
* Displaying a warning if entry text isn't in list.
* Check comma separated values in text against list. (Useful for font-family fallbacks.)
* Setting names for GtkComboBoxEntry and GtkEntry (actionName_combobox, actionName_entry)
* to allow setting resources.
*
* Author(s):
* Tavmjong Bah
* Jon A. Cruz <jon@joncruz.org>
*
* Copyright (C) 2010 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
/*
* We must provide for both a toolbar item and a menu item.
* As we don't know which widgets are used (or even constructed),
* we must keep track of things like active entry ourselves.
*/
#include <iostream>
#include <string.h>
#include <gdk/gdkkeysyms.h>
#include "ink-comboboxentry-action.h"
// Must handle both tool and menu items!
// Internal
static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude = false );
// Callbacks
static gboolean match_selected_cb( GtkEntryCompletion* widget, GtkTreeModel* model, GtkTreeIter* iter, gpointer data );
enum {
PROP_MODEL = 1,
};
enum {
CHANGED = 0,
};
{
// Free any allocated resources.
}
static void ink_comboboxentry_action_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
switch(property_id) {
case PROP_MODEL:
break;
case PROP_COMBOBOX:
break;
case PROP_ENTRY:
break;
case PROP_ENTRY_WIDTH:
break;
case PROP_EXTRA_WIDTH:
break;
case PROP_CELL_DATA_FUNC:
break;
case PROP_SEPARATOR_FUNC:
break;
case PROP_POPUP:
break;
case PROP_FOCUS_WIDGET:
break;
default:
}
}
static void ink_comboboxentry_action_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
switch(property_id) {
case PROP_MODEL:
break;
case PROP_COMBOBOX:
break;
case PROP_ENTRY:
break;
case PROP_ENTRY_WIDTH:
break;
case PROP_EXTRA_WIDTH:
break;
case PROP_CELL_DATA_FUNC:
break;
case PROP_SEPARATOR_FUNC:
break;
case PROP_POPUP:
break;
case PROP_FOCUS_WIDGET:
break;
default:
}
}
static void
{
/* Override any proxy properties. */
// if (GTK_IS_MENU_ITEM (proxy)) {
// }
}
static void
{
g_param_spec_object ("model",
"Tree Model",
"Tree Model",
g_param_spec_object ("combobox",
"GtkComboBoxEntry",
"GtkComboBoxEntry",
g_param_spec_object ("entry",
"GtkEntry",
"GtkEntry",
g_param_spec_int ("entry_width",
"EntryBox width",
"EntryBox width (characters)",
-1.0, 100, -1.0,
g_param_spec_int ("extra_width",
"Extra width",
"Extra width (px)",
-1.0, 500, -1.0,
g_param_spec_pointer ("cell_data_func",
"Cell Data Func",
"Cell Deta Function",
g_param_spec_pointer ("separator_func",
"Separator Func",
"Separator Function",
g_param_spec_boolean ("popup",
"Entry Popup",
"Entry Popup",
false,
g_param_spec_pointer( "focus-widget",
"Focus Widget",
"The widget to return focus to",
// We need to know when GtkComboBoxEvent or Menu ready for reading
G_TYPE_NONE, 0);
// Probably not needed... originally to keep track of key-presses.
G_TYPE_NONE, 0);
}
{
action->info_cb_id = 0;
action->info_cb_blocked = false;
action->warning_cb_id = 0;
action->warning_cb_blocked = false;
}
void *cell_data_func,
void *separator_func,
{
"name", name,
"label", label,
"tooltip", tooltip,
"stock-id", stock_id,
"model", model,
"entry_width", entry_width,
"extra_width", extra_width,
"cell_data_func", cell_data_func,
"separator_func", separator_func,
"focus-widget", focusWidget,
NULL);
}
// Create a widget for a toolbar.
{
g_free( action_name );
GtkWidget* comboBoxEntry = gtk_combo_box_new_with_model_and_entry (ink_comboboxentry_action->model);
// Name it so we can muck with it using an RC file
g_free( combobox_name );
{
}
// Optionally add formatting...
}
// Optionally add separator function...
}
// Optionally widen the combobox width... which widens the drop-down list in list mode.
if( ink_comboboxentry_action->extra_width > 0 ) {
#if GTK_CHECK_VERSION(3,0,0)
#else
#endif
}
// Get reference to GtkEntry and fiddle a bit with it.
// Name it so we can muck with it using an RC file
g_free( entry_name );
// Change width
if( ink_comboboxentry_action->entry_width > 0 ) {
}
// Add pop-up entry completion if required
if( ink_comboboxentry_action->popup ) {
}
// Add altx_name if required
if( ink_comboboxentry_action->altx_name ) {
g_object_set_data( G_OBJECT( child ), ink_comboboxentry_action->altx_name, ink_comboboxentry_action->entry );
}
// Add signal for GtkEntry to check if finished typing.
}
} else {
}
return item;
}
// Create a drop-down menu.
{
g_warning( "ink_comboboxentry_action: create_menu_item not implemented" );
// One can easily modify ege-select-one-action routine to implement this.
return item;
}
}
}
return text;
}
gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* ink_comboboxentry_action, const gchar* text ) {
// Get active row or -1 if none
ink_comboboxentry_action->active = get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text );
// Set active row, check that combobox has been created.
if( ink_comboboxentry_action->combobox ) {
gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox ), ink_comboboxentry_action->active );
}
// Fiddle with entry
if( ink_comboboxentry_action->entry ) {
// Explicitly set text in GtkEntry box (won't be set if text not in list).
// Show or hide warning -- this might be better moved to text-toolbox.cpp
if( ink_comboboxentry_action->info_cb_id != 0 &&
ink_comboboxentry_action->info_cb_blocked = true;
}
if( ink_comboboxentry_action->warning_cb_id != 0 &&
}
bool set = false;
if (isStock) {
} else {
}
// Can't add tooltip until icon set
warning += ": ";
if( ink_comboboxentry_action->warning_cb ) {
// Add callback if we haven't already
if( ink_comboboxentry_action->warning_cb_id == 0 ) {
"icon-press",
}
// Unblock signal
ink_comboboxentry_action->warning_cb_blocked = false;
}
}
set = true;
}
}
if( ink_comboboxentry_action->info_cb ) {
// Add callback if we haven't already
if( ink_comboboxentry_action->info_cb_id == 0 ) {
"icon-press",
}
// Unblock signal
if( ink_comboboxentry_action->info_cb_blocked ) {
ink_comboboxentry_action->info_cb_blocked = false;
}
}
set = true;
}
if( !set ) {
NULL );
NULL );
}
}
// Return if active text in list
return found;
}
void ink_comboboxentry_action_set_entry_width( Ink_ComboBoxEntry_Action* action, gint entry_width ) {
// Widget may not have been created....
}
}
void ink_comboboxentry_action_set_extra_width( Ink_ComboBoxEntry_Action* action, gint extra_width ) {
// Widget may not have been created....
#if GTK_CHECK_VERSION(3,0,0)
#else
#endif
}
}
// Widget may not have been created....
// Check we don't already have a GtkEntryCompletion
if( action->entry_completion ) return;
g_signal_connect (G_OBJECT (action->entry_completion), "match-selected", G_CALLBACK (match_selected_cb), action );
}
}
if( action->entry_completion ) {
action->entry_completion = 0;
}
}
void ink_comboboxentry_action_set_tooltip( Ink_ComboBoxEntry_Action* action, const gchar* tooltip ) {
// Widget may not have been created....
}
}
}
// Widget may not have been created....
}
}
}
void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, const gchar* warning ) {
// Widget may not have been created....
}
}
void ink_comboboxentry_action_set_warning_cb( Ink_ComboBoxEntry_Action* action, gpointer warning_cb ) {
}
void ink_comboboxentry_action_set_altx_name( Ink_ComboBoxEntry_Action* action, const gchar* altx_name ) {
// Widget may not have been created....
}
}
// Internal ---------------------------------------------------
// Return row of active text or -1 if not found. If exclude is true,
// use 3d colunm if available to exclude row from checking (useful to
// skip rows added for font-families included in doc and not on
// system)
gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude ) {
// Check if text in list
while ( valid ) {
// See if we should exclude a row
}
if( check ) {
// Get text from list entry
// Check for match
found = true;
break;
}
}
++row;
}
return row;
}
// Checks if all comma separated text fragments are in the list and
// returns a ustring with a list of missing fragments.
// This is useful for checking if all fonts in a font-family fallback
// list are available on the system.
//
// This routine could also create a Pango Markup string to show which
// fragments are invalid in the entry box itself. See:
// However... it appears that while one can retrieve the PangoLayout
// for a GtkEntry box, it is only a copy and changing it has no effect.
// PangoLayout * pl = gtk_entry_get_layout( entry );
// pango_layout_set_markup( pl, "NEW STRING", -1 ); // DOESN'T WORK
// Parse fallback_list using a comma as deliminator
gint i = 0;
// Remove any surrounding white space.
g_strstrip( tokens[i] );
missing += ", ";
}
++i;
}
g_strfreev( tokens );
// Remove extra comma and space from end.
}
return missing;
}
// Callbacks ---------------------------------------------------
// Two things can happen to get here:
// An item is selected in the drop-down menu.
// Text is typed.
// We only react here if an item is selected.
// Get action
// Check if item selected:
if( newActive >= 0 ) {
// Now let the world know
}
}
}
// Get text from entry box.. check if it matches a menu entry.
// Get action
// Get text
// Get row
// Set active row
gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active );
// Now let the world know
}
static gboolean match_selected_cb( GtkEntryCompletion* /*widget*/, GtkTreeModel* model, GtkTreeIter* iter, gpointer data )
{
// Get action
if( entry) {
// Set text in GtkEntry
// Set text in GtkAction
// Get row
// Set active row
gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active );
// Now let the world know
return true;
}
return false;
}
{
if ( action->focusWidget ) {
}
}
{
0, &key, 0, 0, 0 );
switch ( key ) {
case GDK_KEY_Escape:
{
//gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), action->private_data->lastVal );
wasConsumed = TRUE;
}
break;
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
{
//wasConsumed = TRUE;
}
break;
}
return wasConsumed;
}