File indexing completed on 2024-04-21 05:46:54

0001 /*****************************************************************************
0002  *   Copyright 2003 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
0003  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
0004  *                                                                           *
0005  *   This program is free software; you can redistribute it and/or modify    *
0006  *   it under the terms of the GNU Lesser General Public License as          *
0007  *   published by the Free Software Foundation; either version 2.1 of the    *
0008  *   License, or (at your option) version 3, or any later version accepted   *
0009  *   by the membership of KDE e.V. (or its successor approved by the         *
0010  *   membership of KDE e.V.), which shall act as a proxy defined in          *
0011  *   Section 6 of version 3 of the license.                                  *
0012  *                                                                           *
0013  *   This program is distributed in the hope that it will be useful,         *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
0016  *   Lesser General Public License for more details.                         *
0017  *                                                                           *
0018  *   You should have received a copy of the GNU Lesser General Public        *
0019  *   License along with this library. If not,                                *
0020  *   see <http://www.gnu.org/licenses/>.                                     *
0021  *****************************************************************************/
0022 
0023 #include "combobox.h"
0024 
0025 #include <qtcurve-utils/gtkprops.h>
0026 
0027 namespace QtCurve {
0028 namespace ComboBox {
0029 
0030 /**
0031  * Setting appears-as-list on a non-editable combo creates a view over the
0032  * 'label' which is of 'base' colour. gtk_cell_view_set_background_color
0033  * removes this
0034  */
0035 static bool
0036 cellViewHasBgnd(GtkWidget *view)
0037 {
0038     gboolean val;
0039     g_object_get(view, "background-set", &val, nullptr);
0040     return val;
0041 }
0042 
0043 static void
0044 clearBgndColor(GtkWidget *widget)
0045 {
0046     GList *children = gtk_container_get_children(GTK_CONTAINER(widget));
0047     for (GList *child = children;child;child = child->next) {
0048         GtkWidget *boxChild = (GtkWidget*)child->data;
0049         if (GTK_IS_CELL_VIEW(boxChild) &&
0050             cellViewHasBgnd(boxChild)) {
0051             gtk_cell_view_set_background_color(GTK_CELL_VIEW(boxChild), nullptr);
0052         }
0053     }
0054     if (children) {
0055         g_list_free(children);
0056     }
0057 }
0058 
0059 static GtkWidget *comboFocus = nullptr;
0060 static GtkWidget *comboHover = nullptr;
0061 
0062 #if 0
0063 static bool
0064 appearsAsList(GtkWidget *widget)
0065 {
0066     gboolean rv;
0067     gtk_widget_style_get(widget, "appears-as-list", &rv, nullptr);
0068     return rv;
0069 }
0070 #endif
0071 
0072 static void
0073 cleanup(GtkWidget *widget)
0074 {
0075     if (!widget) {
0076         return;
0077     }
0078     GtkWidgetProps props(widget);
0079     if (props->comboBoxHacked) {
0080         props->comboBoxDestroy.disconn();
0081         props->comboBoxUnrealize.disconn();
0082         props->comboBoxStyleSet.disconn();
0083         props->comboBoxEnter.disconn();
0084         props->comboBoxLeave.disconn();
0085         props->comboBoxStateChange.disconn();
0086         props->comboBoxHacked = false;
0087     }
0088 }
0089 
0090 static gboolean
0091 styleSet(GtkWidget *widget, GtkStyle*, void*)
0092 {
0093     cleanup(widget);
0094     return false;
0095 }
0096 
0097 static gboolean
0098 destroy(GtkWidget *widget, GdkEvent*, void*)
0099 {
0100     cleanup(widget);
0101     return false;
0102 }
0103 
0104 static gboolean
0105 enter(GtkWidget *widget, GdkEventMotion*, void *data)
0106 {
0107     if (GTK_IS_EVENT_BOX(widget)) {
0108         GtkWidget *widget = (GtkWidget*)data;
0109         if (comboHover != widget) {
0110             comboHover = widget;
0111             gtk_widget_queue_draw(widget);
0112         }
0113     }
0114     return false;
0115 }
0116 
0117 static gboolean
0118 leave(GtkWidget *widget, GdkEventMotion*, void *data)
0119 {
0120     if (GTK_IS_EVENT_BOX(widget)) {
0121         GtkWidget *widget = (GtkWidget*)data;
0122         if (comboHover == widget) {
0123             comboHover = nullptr;
0124             gtk_widget_queue_draw(widget);
0125         }
0126     }
0127     return false;
0128 }
0129 
0130 static void
0131 stateChange(GtkWidget *widget, GdkEventMotion*, void*)
0132 {
0133     if (GTK_IS_CONTAINER(widget)) {
0134         clearBgndColor(widget);
0135     }
0136 }
0137 
0138 bool
0139 isFocusChanged(GtkWidget *widget)
0140 {
0141     if (comboFocus == widget) {
0142         if (!gtk_widget_has_focus(widget)) {
0143             comboFocus = nullptr;
0144             return true;
0145         }
0146     } else if (gtk_widget_has_focus(widget)) {
0147         comboFocus = widget;
0148         return true;
0149     }
0150     return false;
0151 }
0152 
0153 bool
0154 isHovered(GtkWidget *widget)
0155 {
0156     return widget == comboHover;
0157 }
0158 
0159 bool
0160 hasFocus(GtkWidget *widget, GtkWidget *mapped)
0161 {
0162     return gtk_widget_has_focus(widget) || (mapped && mapped == comboFocus);
0163 }
0164 
0165 void
0166 setup(GtkWidget *frame, GtkWidget *combo)
0167 {
0168     if (!combo || (!frame && hasFrame(combo))) {
0169         return;
0170     }
0171     GtkWidgetProps props(combo);
0172     if (!props->comboBoxHacked) {
0173         props->comboBoxHacked = true;
0174         clearBgndColor(combo);
0175         props->comboBoxStateChange.conn("state-changed", stateChange);
0176 
0177         if (frame) {
0178             GList *children = gtk_container_get_children(GTK_CONTAINER(frame));
0179             for (GList *child = children;child;child = child->next) {
0180                 if (GTK_IS_EVENT_BOX(child->data)) {
0181                     GtkWidgetProps childProps(child->data);
0182                     childProps->comboBoxDestroy.conn("destroy-event", destroy);
0183                     childProps->comboBoxUnrealize.conn("unrealize", destroy);
0184                     childProps->comboBoxStyleSet.conn("style-set", styleSet);
0185                     childProps->comboBoxEnter.conn("enter-notify-event",
0186                                                    enter, combo);
0187                     childProps->comboBoxLeave.conn("leave-notify-event",
0188                                                    leave, combo);
0189                 }
0190             }
0191             if (children) {
0192                 g_list_free(children);
0193             }
0194         }
0195     }
0196 }
0197 
0198 bool
0199 hasFrame(GtkWidget *widget)
0200 {
0201     gboolean val;
0202     g_object_get(widget, "has-frame", &val, nullptr);
0203     return val;
0204 }
0205 
0206 }
0207 }