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 }