Compare commits
16 Commits
gpu-fix-la
...
wip/matthi
Author | SHA1 | Date | |
---|---|---|---|
|
de10f4a640 | ||
|
d21ec4ce9d | ||
|
0291f49dad | ||
|
817c35f39f | ||
|
ff50fcbdd5 | ||
|
e77e5f66e2 | ||
|
1e8f5486bb | ||
|
e085243879 | ||
|
49dd76bb0d | ||
|
699c6d77e3 | ||
|
5fc4e78155 | ||
|
1e18a876ea | ||
|
ff5fb53e68 | ||
|
3ecd776f96 | ||
|
3531125982 | ||
|
26ab45a3e0 |
@@ -164,6 +164,7 @@ gtk_public_h_sources = \
|
|||||||
gtkcontainer.h \
|
gtkcontainer.h \
|
||||||
gtkcssprovider.h \
|
gtkcssprovider.h \
|
||||||
gtkcsssection.h \
|
gtkcsssection.h \
|
||||||
|
gtkdatechooserwidget.h \
|
||||||
gtkdebug.h \
|
gtkdebug.h \
|
||||||
gtkdialog.h \
|
gtkdialog.h \
|
||||||
gtkdnd.h \
|
gtkdnd.h \
|
||||||
@@ -424,6 +425,7 @@ gtk_private_h_sources = \
|
|||||||
gtkcssvalueprivate.h \
|
gtkcssvalueprivate.h \
|
||||||
gtkcsswidgetnodeprivate.h \
|
gtkcsswidgetnodeprivate.h \
|
||||||
gtkcustompaperunixdialog.h \
|
gtkcustompaperunixdialog.h \
|
||||||
|
gtkdatechooserdayprivate.h \
|
||||||
gtkdialogprivate.h \
|
gtkdialogprivate.h \
|
||||||
gtkdndprivate.h \
|
gtkdndprivate.h \
|
||||||
gtkentryprivate.h \
|
gtkentryprivate.h \
|
||||||
@@ -472,6 +474,7 @@ gtk_private_h_sources = \
|
|||||||
gtkmodifierstyle.h \
|
gtkmodifierstyle.h \
|
||||||
gtkmodulesprivate.h \
|
gtkmodulesprivate.h \
|
||||||
gtkmountoperationprivate.h \
|
gtkmountoperationprivate.h \
|
||||||
|
gtkmultichoiceprivate.h \
|
||||||
gtkorientableprivate.h \
|
gtkorientableprivate.h \
|
||||||
gtkpango.h \
|
gtkpango.h \
|
||||||
gtkpathbar.h \
|
gtkpathbar.h \
|
||||||
@@ -668,6 +671,8 @@ gtk_base_c_sources = \
|
|||||||
gtkcsstypes.c \
|
gtkcsstypes.c \
|
||||||
gtkcssvalue.c \
|
gtkcssvalue.c \
|
||||||
gtkcsswidgetnode.c \
|
gtkcsswidgetnode.c \
|
||||||
|
gtkdatechooserday.c \
|
||||||
|
gtkdatechooserwidget.c \
|
||||||
gtkdialog.c \
|
gtkdialog.c \
|
||||||
gtkdrawingarea.c \
|
gtkdrawingarea.c \
|
||||||
gtkeditable.c \
|
gtkeditable.c \
|
||||||
@@ -749,6 +754,7 @@ gtk_base_c_sources = \
|
|||||||
gtkmodifierstyle.c \
|
gtkmodifierstyle.c \
|
||||||
gtkmodules.c \
|
gtkmodules.c \
|
||||||
gtkmountoperation.c \
|
gtkmountoperation.c \
|
||||||
|
gtkmultichoice.c \
|
||||||
gtknotebook.c \
|
gtknotebook.c \
|
||||||
gtkoffscreenwindow.c \
|
gtkoffscreenwindow.c \
|
||||||
gtkorientable.c \
|
gtkorientable.c \
|
||||||
@@ -1080,6 +1086,7 @@ templates = \
|
|||||||
ui/gtkcolorchooserdialog.ui \
|
ui/gtkcolorchooserdialog.ui \
|
||||||
ui/gtkcoloreditor.ui \
|
ui/gtkcoloreditor.ui \
|
||||||
ui/gtkcombobox.ui \
|
ui/gtkcombobox.ui \
|
||||||
|
ui/gtkdatechooserwidget.ui \
|
||||||
ui/gtkdialog.ui \
|
ui/gtkdialog.ui \
|
||||||
ui/gtkfilechooserbutton.ui \
|
ui/gtkfilechooserbutton.ui \
|
||||||
ui/gtkfilechooserwidget.ui \
|
ui/gtkfilechooserwidget.ui \
|
||||||
@@ -1090,6 +1097,7 @@ templates = \
|
|||||||
ui/gtkinfobar.ui \
|
ui/gtkinfobar.ui \
|
||||||
ui/gtklockbutton.ui \
|
ui/gtklockbutton.ui \
|
||||||
ui/gtkmessagedialog.ui \
|
ui/gtkmessagedialog.ui \
|
||||||
|
ui/gtkmultichoice.ui \
|
||||||
ui/gtkpagesetupunixdialog.ui \
|
ui/gtkpagesetupunixdialog.ui \
|
||||||
ui/gtkpathbar.ui \
|
ui/gtkpathbar.ui \
|
||||||
ui/gtkplacesview.ui \
|
ui/gtkplacesview.ui \
|
||||||
|
@@ -81,6 +81,7 @@
|
|||||||
#include <gtk/gtkcontainer.h>
|
#include <gtk/gtkcontainer.h>
|
||||||
#include <gtk/gtkcssprovider.h>
|
#include <gtk/gtkcssprovider.h>
|
||||||
#include <gtk/gtkcsssection.h>
|
#include <gtk/gtkcsssection.h>
|
||||||
|
#include <gtk/gtkdatechooserwidget.h>
|
||||||
#include <gtk/gtkdebug.h>
|
#include <gtk/gtkdebug.h>
|
||||||
#include <gtk/gtkdialog.h>
|
#include <gtk/gtkdialog.h>
|
||||||
#include <gtk/gtkdnd.h>
|
#include <gtk/gtkdnd.h>
|
||||||
|
370
gtk/gtkdatechooserday.c
Normal file
370
gtk/gtkdatechooserday.c
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gtkdatechooserdayprivate.h"
|
||||||
|
#include "gtklabel.h"
|
||||||
|
#include "gtkgesturemultipress.h"
|
||||||
|
#include "gtkrender.h"
|
||||||
|
#include "gtkwidgetprivate.h"
|
||||||
|
#include "gtkselection.h"
|
||||||
|
#include "gtkdnd.h"
|
||||||
|
|
||||||
|
#include "gtkintl.h"
|
||||||
|
#include "gtkprivate.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <langinfo.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SELECTED,
|
||||||
|
LAST_DAY_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint day_signals[LAST_DAY_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
struct _GtkDateChooserDay
|
||||||
|
{
|
||||||
|
GtkBin parent;
|
||||||
|
GtkWidget *label;
|
||||||
|
GDateTime *date;
|
||||||
|
GdkWindow *event_window;
|
||||||
|
GtkGesture *multipress_gesture;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GtkDateChooserDayClass
|
||||||
|
{
|
||||||
|
GtkBinClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GtkDateChooserDay, gtk_date_chooser_day, GTK_TYPE_BIN)
|
||||||
|
|
||||||
|
static void
|
||||||
|
day_pressed (GtkGestureMultiPress *gesture,
|
||||||
|
gint n_press,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
GtkDateChooserDay *day)
|
||||||
|
{
|
||||||
|
gint button;
|
||||||
|
|
||||||
|
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
|
||||||
|
|
||||||
|
if (button == GDK_BUTTON_PRIMARY)
|
||||||
|
{
|
||||||
|
if (n_press == 1)
|
||||||
|
g_signal_emit (day, day_signals[SELECTED], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_date_chooser_day_key_press (GtkWidget *widget,
|
||||||
|
GdkEventKey *event)
|
||||||
|
{
|
||||||
|
GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget);
|
||||||
|
|
||||||
|
if (event->keyval == GDK_KEY_space ||
|
||||||
|
event->keyval == GDK_KEY_Return ||
|
||||||
|
event->keyval == GDK_KEY_ISO_Enter||
|
||||||
|
event->keyval == GDK_KEY_KP_Enter ||
|
||||||
|
event->keyval == GDK_KEY_KP_Space)
|
||||||
|
{
|
||||||
|
g_signal_emit (day, day_signals[SELECTED], 0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->key_press_event (widget, event))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_init (GtkDateChooserDay *day)
|
||||||
|
{
|
||||||
|
GtkWidget *widget = GTK_WIDGET (day);
|
||||||
|
|
||||||
|
gtk_widget_set_can_focus (widget, TRUE);
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "day");
|
||||||
|
|
||||||
|
day->label = gtk_label_new ("");
|
||||||
|
gtk_widget_show (day->label);
|
||||||
|
gtk_widget_set_halign (day->label, GTK_ALIGN_CENTER);
|
||||||
|
gtk_widget_set_valign (day->label, GTK_ALIGN_CENTER);
|
||||||
|
gtk_widget_set_hexpand (day->label, TRUE);
|
||||||
|
gtk_widget_set_vexpand (day->label, TRUE);
|
||||||
|
gtk_label_set_xalign (GTK_LABEL (day->label), 1.0);
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (day), day->label);
|
||||||
|
|
||||||
|
day->multipress_gesture = gtk_gesture_multi_press_new (widget);
|
||||||
|
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (day->multipress_gesture), 0);
|
||||||
|
g_signal_connect (day->multipress_gesture, "pressed",
|
||||||
|
G_CALLBACK (day_pressed), day);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (object);
|
||||||
|
|
||||||
|
g_clear_object (&day->multipress_gesture);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gtk_date_chooser_day_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_date_chooser_day_draw (GtkWidget *widget,
|
||||||
|
cairo_t *cr)
|
||||||
|
{
|
||||||
|
GtkStyleContext *context;
|
||||||
|
GtkStateFlags state;
|
||||||
|
gint x, y, width, height;
|
||||||
|
|
||||||
|
context = gtk_widget_get_style_context (widget);
|
||||||
|
state = gtk_widget_get_state_flags (widget);
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
width = gtk_widget_get_allocated_width (widget);
|
||||||
|
height = gtk_widget_get_allocated_height (widget);
|
||||||
|
|
||||||
|
gtk_render_background (context, cr, x, y, width, height);
|
||||||
|
gtk_render_frame (context, cr, x, y, width, height);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->draw (widget, cr);
|
||||||
|
|
||||||
|
if (gtk_widget_has_visible_focus (widget))
|
||||||
|
{
|
||||||
|
GtkBorder border;
|
||||||
|
|
||||||
|
gtk_style_context_get_border (context, state, &border);
|
||||||
|
gtk_render_focus (context, cr, border.left, border.top,
|
||||||
|
gtk_widget_get_allocated_width (widget) - border.left - border.right,
|
||||||
|
gtk_widget_get_allocated_height (widget) - border.top - border.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_map (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->map (widget);
|
||||||
|
|
||||||
|
gdk_window_show (day->event_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_unmap (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget);
|
||||||
|
|
||||||
|
gdk_window_hide (day->event_window);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->unmap (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_realize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget);
|
||||||
|
GtkAllocation allocation;
|
||||||
|
GdkWindow *window;
|
||||||
|
GdkWindowAttr attributes;
|
||||||
|
gint attributes_mask;
|
||||||
|
|
||||||
|
gtk_widget_get_allocation (widget, &allocation);
|
||||||
|
gtk_widget_set_realized (widget, TRUE);
|
||||||
|
|
||||||
|
attributes.window_type = GDK_WINDOW_CHILD;
|
||||||
|
attributes.x = allocation.x;
|
||||||
|
attributes.y = allocation.y;
|
||||||
|
attributes.width = allocation.width;
|
||||||
|
attributes.height = allocation.height;
|
||||||
|
attributes.wclass = GDK_INPUT_ONLY;
|
||||||
|
attributes.event_mask = gtk_widget_get_events (widget);
|
||||||
|
attributes.event_mask |= GDK_BUTTON_PRESS_MASK
|
||||||
|
| GDK_BUTTON_RELEASE_MASK
|
||||||
|
| GDK_TOUCH_MASK;
|
||||||
|
|
||||||
|
attributes_mask = GDK_WA_X | GDK_WA_Y;
|
||||||
|
|
||||||
|
window = gtk_widget_get_parent_window (widget);
|
||||||
|
gtk_widget_set_window (widget, window);
|
||||||
|
g_object_ref (window);
|
||||||
|
|
||||||
|
day->event_window = gdk_window_new (window, &attributes, attributes_mask);
|
||||||
|
gtk_widget_register_window (widget, day->event_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_unrealize (GtkWidget *widget)
|
||||||
|
{
|
||||||
|
GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget);
|
||||||
|
|
||||||
|
if (day->event_window)
|
||||||
|
{
|
||||||
|
gtk_widget_unregister_window (widget, day->event_window);
|
||||||
|
gdk_window_destroy (day->event_window);
|
||||||
|
day->event_window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->unrealize (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_size_allocate (GtkWidget *widget,
|
||||||
|
GtkAllocation *allocation)
|
||||||
|
{
|
||||||
|
GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget);
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (gtk_date_chooser_day_parent_class)->size_allocate (widget, allocation);
|
||||||
|
|
||||||
|
if (gtk_widget_get_realized (widget))
|
||||||
|
gdk_window_move_resize (day->event_window,
|
||||||
|
allocation->x,
|
||||||
|
allocation->y,
|
||||||
|
allocation->width,
|
||||||
|
allocation->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_drag_data_get (GtkWidget *widget,
|
||||||
|
GdkDragContext *context,
|
||||||
|
GtkSelectionData *selection_data,
|
||||||
|
guint info,
|
||||||
|
guint time)
|
||||||
|
{
|
||||||
|
GtkDateChooserDay *day = GTK_DATE_CHOOSER_DAY (widget);
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
text = g_date_time_format (day->date, "%x");
|
||||||
|
gtk_selection_data_set_text (selection_data, text, -1);
|
||||||
|
g_free (text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_day_class_init (GtkDateChooserDayClass *class)
|
||||||
|
{
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||||
|
|
||||||
|
object_class->dispose = gtk_date_chooser_day_dispose;
|
||||||
|
|
||||||
|
widget_class->draw = gtk_date_chooser_day_draw;
|
||||||
|
widget_class->realize = gtk_date_chooser_day_realize;
|
||||||
|
widget_class->unrealize = gtk_date_chooser_day_unrealize;
|
||||||
|
widget_class->map = gtk_date_chooser_day_map;
|
||||||
|
widget_class->unmap = gtk_date_chooser_day_unmap;
|
||||||
|
widget_class->key_press_event = gtk_date_chooser_day_key_press;
|
||||||
|
widget_class->size_allocate = gtk_date_chooser_day_size_allocate;
|
||||||
|
widget_class->drag_data_get = gtk_date_chooser_day_drag_data_get;
|
||||||
|
|
||||||
|
day_signals[SELECTED] = g_signal_new (I_("selected"),
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gtk_date_chooser_day_new (void)
|
||||||
|
{
|
||||||
|
return GTK_WIDGET (g_object_new (GTK_TYPE_DATE_CHOOSER_DAY, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_day_set_date (GtkDateChooserDay *day,
|
||||||
|
GDateTime *date)
|
||||||
|
{
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
if (day->date)
|
||||||
|
g_date_time_unref (day->date);
|
||||||
|
day->date = g_date_time_ref (date);
|
||||||
|
|
||||||
|
text = g_strdup_printf ("%d", g_date_time_get_day_of_month (date));
|
||||||
|
gtk_label_set_label (GTK_LABEL (day->label), text);
|
||||||
|
g_free (text);
|
||||||
|
}
|
||||||
|
|
||||||
|
GDateTime *
|
||||||
|
gtk_date_chooser_day_get_date (GtkDateChooserDay *day)
|
||||||
|
{
|
||||||
|
return day->date;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_day_set_other_month (GtkDateChooserDay *day,
|
||||||
|
gboolean other_month)
|
||||||
|
{
|
||||||
|
GtkStyleContext *context;
|
||||||
|
|
||||||
|
context = gtk_widget_get_style_context (GTK_WIDGET (day));
|
||||||
|
if (other_month)
|
||||||
|
{
|
||||||
|
gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
|
||||||
|
gtk_drag_source_unset (GTK_WIDGET (day));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_DIM_LABEL);
|
||||||
|
gtk_drag_source_set (GTK_WIDGET (day),
|
||||||
|
GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
|
||||||
|
NULL, 0,
|
||||||
|
GDK_ACTION_COPY);
|
||||||
|
gtk_drag_source_add_text_targets (GTK_WIDGET (day));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_day_set_selected (GtkDateChooserDay *day,
|
||||||
|
gboolean selected)
|
||||||
|
{
|
||||||
|
if (selected)
|
||||||
|
gtk_widget_set_state_flags (GTK_WIDGET (day), GTK_STATE_FLAG_SELECTED, FALSE);
|
||||||
|
else
|
||||||
|
gtk_widget_unset_state_flags (GTK_WIDGET (day), GTK_STATE_FLAG_SELECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_day_set_options (GtkDateChooserDay *day,
|
||||||
|
GtkDateChooserDayOptions options)
|
||||||
|
{
|
||||||
|
GtkStyleContext *context;
|
||||||
|
|
||||||
|
context = gtk_widget_get_style_context (GTK_WIDGET (day));
|
||||||
|
if (options & GTK_DATE_CHOOSER_DAY_WEEKEND)
|
||||||
|
gtk_style_context_add_class (context, "weekend");
|
||||||
|
else
|
||||||
|
gtk_style_context_remove_class (context, "weekend");
|
||||||
|
if (options & GTK_DATE_CHOOSER_DAY_HOLIDAY)
|
||||||
|
gtk_style_context_add_class (context, "holiday");
|
||||||
|
else
|
||||||
|
gtk_style_context_remove_class (context, "holiday");
|
||||||
|
if (options & GTK_DATE_CHOOSER_DAY_MARKED)
|
||||||
|
gtk_style_context_add_class (context, "marked");
|
||||||
|
else
|
||||||
|
gtk_style_context_remove_class (context, "marked");
|
||||||
|
}
|
51
gtk/gtkdatechooserdayprivate.h
Normal file
51
gtk/gtkdatechooserdayprivate.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_DATE_CHOOSER_DAY_PRIVATE_H__
|
||||||
|
#define __GTK_DATE_CHOOSER_DAY_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <gtk/gtkbin.h>
|
||||||
|
#include <gtk/gtkdatechooserwidget.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GTK_TYPE_DATE_CHOOSER_DAY (gtk_date_chooser_day_get_type ())
|
||||||
|
#define GTK_DATE_CHOOSER_DAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_DATE_CHOOSER_DAY, GtkDateChooserDay))
|
||||||
|
#define GTK_DATE_CHOOSER_DAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_DATE_CHOOSER_DAY, GtkDateChooserDayClass))
|
||||||
|
#define GTK_IS_DATE_CHOOSER_DAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DATE_CHOOSER_DAY))
|
||||||
|
#define GTK_IS_DATE_CHOOSER_DAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DATE_CHOOSER_DAY))
|
||||||
|
#define GTK_DATE_CHOOSER_DAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_DATE_CHOOSER_DAY, GtkDateChooserDayClass))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GtkDateChooserDay GtkDateChooserDay;
|
||||||
|
typedef struct _GtkDateChooserDayClass GtkDateChooserDayClass;
|
||||||
|
|
||||||
|
GType gtk_date_chooser_day_get_type (void) G_GNUC_CONST;
|
||||||
|
GtkWidget * gtk_date_chooser_day_new (void);
|
||||||
|
void gtk_date_chooser_day_set_date (GtkDateChooserDay *day,
|
||||||
|
GDateTime *date);
|
||||||
|
GDateTime *gtk_date_chooser_day_get_date (GtkDateChooserDay *day);
|
||||||
|
void gtk_date_chooser_day_set_other_month (GtkDateChooserDay *day,
|
||||||
|
gboolean other_month);
|
||||||
|
void gtk_date_chooser_day_set_selected (GtkDateChooserDay *day,
|
||||||
|
gboolean selected);
|
||||||
|
void gtk_date_chooser_day_set_options (GtkDateChooserDay *day,
|
||||||
|
GtkDateChooserDayOptions options);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GTK_DATE_CHOOSER_DAY_PRIVATE_H__ */
|
792
gtk/gtkdatechooserwidget.c
Normal file
792
gtk/gtkdatechooserwidget.c
Normal file
@@ -0,0 +1,792 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gtkdatechooserwidget.h"
|
||||||
|
#include "gtkdatechooserdayprivate.h"
|
||||||
|
#include "gtkstack.h"
|
||||||
|
#include "gtklabel.h"
|
||||||
|
#include "gtkgrid.h"
|
||||||
|
#include "gtkselection.h"
|
||||||
|
#include "gtkdnd.h"
|
||||||
|
#include "gtkmultichoiceprivate.h"
|
||||||
|
|
||||||
|
#include "gtkintl.h"
|
||||||
|
#include "gtkprivate.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <langinfo.h>
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MONTH_CHANGED,
|
||||||
|
DAY_SELECTED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint calendar_signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_DATE = 1,
|
||||||
|
PROP_SHOW_HEADING,
|
||||||
|
PROP_SHOW_DAY_NAMES,
|
||||||
|
PROP_SHOW_WEEK_NUMBERS,
|
||||||
|
PROP_NO_MONTH_CHANGE,
|
||||||
|
NUM_PROPERTIES
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *calendar_properties[NUM_PROPERTIES] = { NULL, };
|
||||||
|
|
||||||
|
struct _GtkDateChooserWidget
|
||||||
|
{
|
||||||
|
GtkBin parent;
|
||||||
|
|
||||||
|
GtkWidget *month_choice;
|
||||||
|
GtkWidget *grid;
|
||||||
|
|
||||||
|
GtkWidget *day_grid;
|
||||||
|
GtkWidget *corner;
|
||||||
|
GtkWidget *cols[7];
|
||||||
|
GtkWidget *rows[6];
|
||||||
|
GtkWidget *days[6][7];
|
||||||
|
|
||||||
|
GDateTime *date;
|
||||||
|
|
||||||
|
gint this_year;
|
||||||
|
gint week_start;
|
||||||
|
|
||||||
|
gboolean show_heading;
|
||||||
|
gboolean show_day_names;
|
||||||
|
gboolean show_week_numbers;
|
||||||
|
gboolean no_month_change;
|
||||||
|
|
||||||
|
GtkDateChooserDayOptionsCallback day_options_cb;
|
||||||
|
gpointer day_options_data;
|
||||||
|
GDestroyNotify day_options_destroy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GtkDateChooserWidgetClass
|
||||||
|
{
|
||||||
|
GtkBinClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GtkDateChooserWidget, gtk_date_chooser_widget, GTK_TYPE_BIN)
|
||||||
|
|
||||||
|
static const guint month_length[2][13] =
|
||||||
|
{
|
||||||
|
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||||
|
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
leap (guint year)
|
||||||
|
{
|
||||||
|
return ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_compute_days (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gint year, month, day;
|
||||||
|
gint other_year, other_month;
|
||||||
|
gint ndays_in_month;
|
||||||
|
gint ndays_in_prev_month;
|
||||||
|
gint first_day;
|
||||||
|
gint row;
|
||||||
|
gint col;
|
||||||
|
GtkDateChooserDay *d;
|
||||||
|
GDateTime *date;
|
||||||
|
|
||||||
|
g_date_time_get_ymd (calendar->date, &year, &month, NULL);
|
||||||
|
|
||||||
|
ndays_in_month = month_length[leap (year)][month];
|
||||||
|
|
||||||
|
date = g_date_time_new_local (year, month, 1, 1, 1, 1);
|
||||||
|
first_day = g_date_time_get_day_of_week (date);
|
||||||
|
g_date_time_unref (date);
|
||||||
|
|
||||||
|
first_day = (first_day + 7 - calendar->week_start) % 7;
|
||||||
|
if (first_day == 0)
|
||||||
|
first_day = 7;
|
||||||
|
|
||||||
|
/* Compute days of previous month */
|
||||||
|
if (month > 1)
|
||||||
|
ndays_in_prev_month = month_length[leap (year)][month - 1];
|
||||||
|
else
|
||||||
|
ndays_in_prev_month = month_length[leap (year - 1)][12];
|
||||||
|
day = ndays_in_prev_month - first_day + 1;
|
||||||
|
|
||||||
|
other_year = year;
|
||||||
|
other_month = month - 1;
|
||||||
|
if (other_month == 0)
|
||||||
|
{
|
||||||
|
other_month = 12;
|
||||||
|
other_year -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (col = 0; col < first_day; col++)
|
||||||
|
{
|
||||||
|
d = GTK_DATE_CHOOSER_DAY (calendar->days[0][col]);
|
||||||
|
date = g_date_time_new_local (other_year, other_month, day, 1, 1, 1);
|
||||||
|
gtk_date_chooser_day_set_date (d, date);
|
||||||
|
gtk_date_chooser_day_set_other_month (d, TRUE);
|
||||||
|
g_date_time_unref (date);
|
||||||
|
day++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute days of current month */
|
||||||
|
row = first_day / 7;
|
||||||
|
col = first_day % 7;
|
||||||
|
|
||||||
|
for (day = 1; day <= ndays_in_month; day++)
|
||||||
|
{
|
||||||
|
d = GTK_DATE_CHOOSER_DAY (calendar->days[row][col]);
|
||||||
|
date = g_date_time_new_local (year, month, day, 1, 1, 1);
|
||||||
|
gtk_date_chooser_day_set_date (d, date);
|
||||||
|
gtk_date_chooser_day_set_other_month (d, FALSE);
|
||||||
|
g_date_time_unref (date);
|
||||||
|
|
||||||
|
col++;
|
||||||
|
if (col == 7)
|
||||||
|
{
|
||||||
|
row++;
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute days of next month */
|
||||||
|
|
||||||
|
other_year = year;
|
||||||
|
other_month = month + 1;
|
||||||
|
if (other_month == 13)
|
||||||
|
{
|
||||||
|
other_month = 1;
|
||||||
|
other_year += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
day = 1;
|
||||||
|
for (; row < 6; row++)
|
||||||
|
{
|
||||||
|
for (; col < 7; col++)
|
||||||
|
{
|
||||||
|
d = GTK_DATE_CHOOSER_DAY (calendar->days[row][col]);
|
||||||
|
date = g_date_time_new_local (other_year, other_month, day, 1, 1, 1);
|
||||||
|
gtk_date_chooser_day_set_date (d, date);
|
||||||
|
gtk_date_chooser_day_set_other_month (d, TRUE);
|
||||||
|
g_date_time_unref (date);
|
||||||
|
day++;
|
||||||
|
}
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update week numbers */
|
||||||
|
for (row = 0; row < 6; row++)
|
||||||
|
{
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
d = GTK_DATE_CHOOSER_DAY (calendar->days[row][6]);
|
||||||
|
date = gtk_date_chooser_day_get_date (d);
|
||||||
|
text = g_strdup_printf ("%d", g_date_time_get_week_of_year (date));
|
||||||
|
gtk_label_set_label (GTK_LABEL (calendar->rows[row]), text);
|
||||||
|
g_free (text);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_date_chooser_widget_invalidate_day_options (calendar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 0 == sunday */
|
||||||
|
static gchar *
|
||||||
|
calendar_get_weekday_name (gint i)
|
||||||
|
{
|
||||||
|
GDateTime *date;
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
date = g_date_time_new_local (2015, 1, 4 + i, 1, 1, 1);
|
||||||
|
text = g_date_time_format (date, "%a");
|
||||||
|
g_date_time_unref (date);
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 0 = january */
|
||||||
|
static gchar *
|
||||||
|
calendar_get_month_name (gint i)
|
||||||
|
{
|
||||||
|
GDateTime *date;
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
date = g_date_time_new_local (2015, i + 1, 1, 1, 1, 1);
|
||||||
|
text = g_date_time_format (date, "%B");
|
||||||
|
g_date_time_unref (date);
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_init_weekday_display (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
for (i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
text = calendar_get_weekday_name ((i + calendar->week_start) % 7);
|
||||||
|
gtk_label_set_label (GTK_LABEL (calendar->cols[i]), text);
|
||||||
|
g_free (text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
format_month (GtkMultiChoice *choice,
|
||||||
|
gint value,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkDateChooserWidget *calendar = data;
|
||||||
|
gint month;
|
||||||
|
gint year;
|
||||||
|
gchar *month_name;
|
||||||
|
|
||||||
|
month = value % 12;
|
||||||
|
year = value / 12;
|
||||||
|
|
||||||
|
month_name = calendar_get_month_name (month);
|
||||||
|
|
||||||
|
if (year == calendar->this_year)
|
||||||
|
return month_name;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
text = g_strdup_printf ("%s %d", month_name, year);
|
||||||
|
g_free (month_name);
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_init_month_display (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
gchar *month;
|
||||||
|
gchar *months[13];
|
||||||
|
|
||||||
|
for (i = 0; i < 12; i++)
|
||||||
|
{
|
||||||
|
month = calendar_get_month_name (i);
|
||||||
|
months[i] = g_strdup_printf ("%s 9999", month);
|
||||||
|
g_free (month);
|
||||||
|
}
|
||||||
|
months[12] = NULL;
|
||||||
|
|
||||||
|
gtk_multi_choice_set_choices (GTK_MULTI_CHOICE (calendar->month_choice),
|
||||||
|
(const gchar **)months);
|
||||||
|
|
||||||
|
for (i = 0; i < 12; i++)
|
||||||
|
g_free (months[i]);
|
||||||
|
|
||||||
|
gtk_multi_choice_set_format_callback (GTK_MULTI_CHOICE (calendar->month_choice),
|
||||||
|
format_month, calendar, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_update_selected_day_display (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gint row, col;
|
||||||
|
GtkDateChooserDay *d;
|
||||||
|
GDateTime *date;
|
||||||
|
|
||||||
|
for (row = 0; row < 6; row++)
|
||||||
|
for (col = 0; col < 7; col++)
|
||||||
|
{
|
||||||
|
d = GTK_DATE_CHOOSER_DAY (calendar->days[row][col]);
|
||||||
|
date = gtk_date_chooser_day_get_date (d);
|
||||||
|
gtk_date_chooser_day_set_selected (d, g_date_time_equal (date, calendar->date));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_update_selected_day (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gint month_len;
|
||||||
|
gint year, month, day;
|
||||||
|
GDateTime *date;
|
||||||
|
|
||||||
|
g_date_time_get_ymd (calendar->date, &year, &month, &day);
|
||||||
|
|
||||||
|
month_len = month_length[leap (year)][month];
|
||||||
|
|
||||||
|
if (month_len < day)
|
||||||
|
{
|
||||||
|
date = g_date_time_new_local (year, month, month_len, 1, 1, 1);
|
||||||
|
gtk_date_chooser_widget_set_date (calendar, date);
|
||||||
|
g_date_time_unref (date);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
calendar_update_selected_day_display (calendar);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
calendar_get_week_start (void)
|
||||||
|
{
|
||||||
|
union { unsigned int word; char *string; } langinfo;
|
||||||
|
gint week_1stday = 0;
|
||||||
|
gint first_weekday = 1;
|
||||||
|
guint week_origin;
|
||||||
|
|
||||||
|
langinfo.string = nl_langinfo (_NL_TIME_FIRST_WEEKDAY);
|
||||||
|
first_weekday = langinfo.string[0];
|
||||||
|
langinfo.string = nl_langinfo (_NL_TIME_WEEK_1STDAY);
|
||||||
|
week_origin = langinfo.word;
|
||||||
|
if (week_origin == 19971130) /* Sunday */
|
||||||
|
week_1stday = 0;
|
||||||
|
else if (week_origin == 19971201) /* Monday */
|
||||||
|
week_1stday = 1;
|
||||||
|
else
|
||||||
|
g_warning ("Unknown value of _NL_TIME_WEEK_1STDAY.");
|
||||||
|
|
||||||
|
return (week_1stday + first_weekday - 1) % 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
day_selected_cb (GtkDateChooserDay *d,
|
||||||
|
GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gtk_date_chooser_widget_set_date (calendar, gtk_date_chooser_day_get_date (d));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_widget_init (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gint row, col;
|
||||||
|
GtkWidget *label;
|
||||||
|
gint year, month;
|
||||||
|
|
||||||
|
calendar->show_heading = TRUE;
|
||||||
|
calendar->show_day_names = TRUE;
|
||||||
|
calendar->show_week_numbers = TRUE;
|
||||||
|
calendar->no_month_change = FALSE;
|
||||||
|
|
||||||
|
calendar->date = g_date_time_new_now_local ();
|
||||||
|
g_date_time_get_ymd (calendar->date, &calendar->this_year, NULL, NULL);
|
||||||
|
|
||||||
|
calendar->week_start = calendar_get_week_start ();
|
||||||
|
|
||||||
|
gtk_widget_init_template (GTK_WIDGET (calendar));
|
||||||
|
|
||||||
|
for (col = 0; col < 7; col++)
|
||||||
|
{
|
||||||
|
calendar->cols[col] = gtk_label_new ("");
|
||||||
|
g_object_bind_property (calendar, "show-day-names",
|
||||||
|
calendar->cols[col], "visible",
|
||||||
|
G_BINDING_SYNC_CREATE);
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (calendar->cols[col]), "weekday");
|
||||||
|
gtk_grid_attach (GTK_GRID (calendar->grid), calendar->cols[col], col, -1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (row = 0; row < 6; row++)
|
||||||
|
{
|
||||||
|
calendar->rows[row] = gtk_label_new ("");
|
||||||
|
g_object_bind_property (calendar, "show-week-numbers",
|
||||||
|
calendar->rows[row], "visible",
|
||||||
|
G_BINDING_SYNC_CREATE);
|
||||||
|
gtk_label_set_xalign (GTK_LABEL (calendar->rows[row]), 1.0);
|
||||||
|
gtk_widget_show (calendar->rows[row]);
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (calendar->rows[row]), "weeknum");
|
||||||
|
gtk_grid_attach (GTK_GRID (calendar->grid), calendar->rows[row], -1, row, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are using a stack here to keep the week number column from shrinking
|
||||||
|
* when all the weeks are single-digit
|
||||||
|
*/
|
||||||
|
calendar->corner = gtk_stack_new ();
|
||||||
|
gtk_grid_attach (GTK_GRID (calendar->grid), calendar->corner, -1, -1, 1, 1);
|
||||||
|
label = gtk_label_new ("");
|
||||||
|
gtk_widget_show (label);
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (label), "weekday");
|
||||||
|
gtk_container_add (GTK_CONTAINER (calendar->corner), label);
|
||||||
|
|
||||||
|
label = gtk_label_new ("99");
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (label), "weeknum");
|
||||||
|
gtk_container_add (GTK_CONTAINER (calendar->corner), label);
|
||||||
|
|
||||||
|
calendar->day_grid = gtk_grid_new ();
|
||||||
|
gtk_widget_show (calendar->day_grid);
|
||||||
|
gtk_widget_set_halign (calendar->day_grid, GTK_ALIGN_FILL);
|
||||||
|
gtk_widget_set_valign (calendar->day_grid, GTK_ALIGN_FILL);
|
||||||
|
gtk_grid_attach (GTK_GRID (calendar->grid), calendar->day_grid, 0, 0, 7, 6);
|
||||||
|
|
||||||
|
for (row = 0; row < 6; row++)
|
||||||
|
for (col = 0; col < 7; col++)
|
||||||
|
{
|
||||||
|
calendar->days[row][col] = gtk_date_chooser_day_new ();
|
||||||
|
g_signal_connect (calendar->days[row][col], "selected", G_CALLBACK (day_selected_cb), calendar);
|
||||||
|
gtk_widget_show (calendar->days[row][col]);
|
||||||
|
gtk_grid_attach (GTK_GRID (calendar->day_grid), calendar->days[row][col], col, row, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
calendar_init_month_display (calendar);
|
||||||
|
calendar_init_weekday_display (calendar);
|
||||||
|
|
||||||
|
calendar_compute_days (calendar);
|
||||||
|
g_date_time_get_ymd (calendar->date, &year, &month, NULL);
|
||||||
|
gtk_multi_choice_set_value (GTK_MULTI_CHOICE (calendar->month_choice), 12 * year + month - 1);
|
||||||
|
calendar_update_selected_day_display (calendar);
|
||||||
|
|
||||||
|
gtk_drag_dest_set (GTK_WIDGET (calendar), GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY);
|
||||||
|
gtk_drag_dest_add_text_targets (GTK_WIDGET (calendar));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_set_property (GObject *obj,
|
||||||
|
guint property_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkDateChooserWidget *calendar = GTK_DATE_CHOOSER_WIDGET (obj);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_DATE:
|
||||||
|
gtk_date_chooser_widget_set_date (calendar, g_value_get_boxed (value));
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_HEADING:
|
||||||
|
gtk_date_chooser_widget_set_show_heading (calendar, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_DAY_NAMES:
|
||||||
|
gtk_date_chooser_widget_set_show_day_names (calendar, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_WEEK_NUMBERS:
|
||||||
|
gtk_date_chooser_widget_set_show_week_numbers (calendar, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_NO_MONTH_CHANGE:
|
||||||
|
gtk_date_chooser_widget_set_no_month_change (calendar, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_get_property (GObject *obj,
|
||||||
|
guint property_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkDateChooserWidget *calendar = GTK_DATE_CHOOSER_WIDGET (obj);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_DATE:
|
||||||
|
g_value_set_boxed (value, calendar->date);
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_HEADING:
|
||||||
|
g_value_set_boolean (value, calendar->show_heading);
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_DAY_NAMES:
|
||||||
|
g_value_set_boolean (value, calendar->show_day_names);
|
||||||
|
break;
|
||||||
|
case PROP_SHOW_WEEK_NUMBERS:
|
||||||
|
g_value_set_boolean (value, calendar->show_week_numbers);
|
||||||
|
break;
|
||||||
|
case PROP_NO_MONTH_CHANGE:
|
||||||
|
g_value_set_boolean (value, calendar->no_month_change);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_month_changed (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gint value;
|
||||||
|
gint year, month, day;
|
||||||
|
GDateTime *date;
|
||||||
|
|
||||||
|
value = gtk_multi_choice_get_value (GTK_MULTI_CHOICE (calendar->month_choice));
|
||||||
|
year = value / 12;
|
||||||
|
month = value % 12 + 1;
|
||||||
|
g_date_time_get_ymd (calendar->date, NULL, NULL, &day);
|
||||||
|
|
||||||
|
date = g_date_time_new_local (year, month, day, 1, 1, 1);
|
||||||
|
gtk_date_chooser_widget_set_date (calendar, date);
|
||||||
|
g_date_time_unref (date);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calendar_drag_data_received (GtkWidget *widget,
|
||||||
|
GdkDragContext *context,
|
||||||
|
gint x,
|
||||||
|
gint y,
|
||||||
|
GtkSelectionData *selection_data,
|
||||||
|
guint info,
|
||||||
|
guint time)
|
||||||
|
{
|
||||||
|
GtkDateChooserWidget *calendar = GTK_DATE_CHOOSER_WIDGET (widget);
|
||||||
|
gchar *text;
|
||||||
|
GDate *gdate;
|
||||||
|
gint year, month, day;
|
||||||
|
GDateTime *date;
|
||||||
|
|
||||||
|
gdate = g_date_new ();
|
||||||
|
text = (gchar *)gtk_selection_data_get_text (selection_data);
|
||||||
|
if (text)
|
||||||
|
{
|
||||||
|
g_date_set_parse (gdate, text);
|
||||||
|
g_free (text);
|
||||||
|
}
|
||||||
|
if (!g_date_valid (gdate))
|
||||||
|
{
|
||||||
|
g_date_free (gdate);
|
||||||
|
gtk_drag_finish (context, FALSE, FALSE, time);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
year = g_date_get_year (gdate);
|
||||||
|
month = g_date_get_month (gdate);
|
||||||
|
day = g_date_get_day (gdate);
|
||||||
|
|
||||||
|
g_date_free (gdate);
|
||||||
|
|
||||||
|
gtk_drag_finish (context, TRUE, FALSE, time);
|
||||||
|
|
||||||
|
if (!calendar->show_heading || calendar->no_month_change)
|
||||||
|
g_date_time_get_ymd (calendar->date, &year, &month, NULL);
|
||||||
|
|
||||||
|
date = g_date_time_new_local (year, month, day, 1, 1, 1);
|
||||||
|
gtk_date_chooser_widget_set_date (calendar, date);
|
||||||
|
g_date_time_unref (date);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_date_chooser_widget_class_init (GtkDateChooserWidgetClass *class)
|
||||||
|
{
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||||
|
|
||||||
|
g_type_ensure (GTK_TYPE_MULTI_CHOICE);
|
||||||
|
|
||||||
|
object_class->set_property = calendar_set_property;
|
||||||
|
object_class->get_property = calendar_get_property;
|
||||||
|
|
||||||
|
widget_class->drag_data_received = calendar_drag_data_received;
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtkdatechooserwidget.ui");
|
||||||
|
|
||||||
|
calendar_properties[PROP_DATE] =
|
||||||
|
g_param_spec_boxed ("date", P_("Date"), P_("The selected date"),
|
||||||
|
G_TYPE_DATE_TIME,
|
||||||
|
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
calendar_properties[PROP_SHOW_HEADING] =
|
||||||
|
g_param_spec_boolean ("show-heading", P_("Show Heading"), P_("If TRUE, a heading is displayed"),
|
||||||
|
TRUE, G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
calendar_properties[PROP_SHOW_DAY_NAMES] =
|
||||||
|
g_param_spec_boolean ("show-day-names", P_("Show Day Names"), P_("If TRUE, day names are displayed"),
|
||||||
|
TRUE, G_PARAM_READWRITE);
|
||||||
|
calendar_properties[PROP_SHOW_WEEK_NUMBERS] =
|
||||||
|
g_param_spec_boolean ("show-week-numbers", P_("Show Week Numbers"), P_("If TRUE, week numbers are displayed"),
|
||||||
|
TRUE, G_PARAM_READWRITE);
|
||||||
|
calendar_properties[PROP_NO_MONTH_CHANGE] =
|
||||||
|
g_param_spec_boolean ("no-month-change", P_("No Month Change"), P_("If TRUE, the selected month cannot be changed"),
|
||||||
|
FALSE, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_properties (object_class, NUM_PROPERTIES, calendar_properties);
|
||||||
|
|
||||||
|
calendar_signals[MONTH_CHANGED] = g_signal_new (I_("month-changed"),
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
calendar_signals[DAY_SELECTED] = g_signal_new (I_("day-selected"),
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, month_choice);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GtkDateChooserWidget, grid);
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, calendar_month_changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gtk_date_chooser_widget_new (void)
|
||||||
|
{
|
||||||
|
return GTK_WIDGET (g_object_new (GTK_TYPE_DATE_CHOOSER_WIDGET, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_widget_set_show_heading (GtkDateChooserWidget *calendar,
|
||||||
|
gboolean setting)
|
||||||
|
{
|
||||||
|
if (calendar->show_heading == setting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
calendar->show_heading = setting;
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (calendar),
|
||||||
|
calendar_properties[PROP_SHOW_HEADING]);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_date_chooser_widget_get_show_heading (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
return calendar->show_heading;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_widget_set_show_day_names (GtkDateChooserWidget *calendar,
|
||||||
|
gboolean setting)
|
||||||
|
{
|
||||||
|
if (calendar->show_day_names == setting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
calendar->show_day_names = setting;
|
||||||
|
|
||||||
|
gtk_widget_set_visible (calendar->corner, calendar->show_day_names && calendar->show_week_numbers);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (calendar),
|
||||||
|
calendar_properties[PROP_SHOW_DAY_NAMES]);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_date_chooser_widget_get_show_day_names (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
return calendar->show_day_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_widget_set_show_week_numbers (GtkDateChooserWidget *calendar,
|
||||||
|
gboolean setting)
|
||||||
|
{
|
||||||
|
if (calendar->show_week_numbers == setting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
calendar->show_week_numbers = setting;
|
||||||
|
|
||||||
|
gtk_widget_set_visible (calendar->corner, calendar->show_day_names && calendar->show_week_numbers);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (calendar),
|
||||||
|
calendar_properties[PROP_SHOW_WEEK_NUMBERS]);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_date_chooser_widget_get_show_week_numbers (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
return calendar->show_week_numbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_widget_set_no_month_change (GtkDateChooserWidget *calendar,
|
||||||
|
gboolean setting)
|
||||||
|
{
|
||||||
|
if (calendar->no_month_change == setting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
calendar->no_month_change = setting;
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (calendar),
|
||||||
|
calendar_properties[PROP_NO_MONTH_CHANGE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_date_chooser_widget_get_no_month_change (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
return calendar->no_month_change;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_widget_set_date (GtkDateChooserWidget *calendar,
|
||||||
|
GDateTime *date)
|
||||||
|
{
|
||||||
|
gint y1, m1, d1, y2, m2, d2;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (calendar));
|
||||||
|
|
||||||
|
g_date_time_get_ymd (calendar->date, &y1, &m1, &d1);
|
||||||
|
g_date_time_get_ymd (date, &y2, &m2, &d2);
|
||||||
|
|
||||||
|
g_date_time_unref (calendar->date);
|
||||||
|
calendar->date = g_date_time_ref (date);
|
||||||
|
|
||||||
|
if (y1 != y2 || m1 != m2)
|
||||||
|
{
|
||||||
|
gtk_multi_choice_set_value (GTK_MULTI_CHOICE (calendar->month_choice), 12 * y2 + m2 - 1);
|
||||||
|
calendar_compute_days (calendar);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y1 != y2 || m1 != m2 || d1 != d2)
|
||||||
|
{
|
||||||
|
calendar_update_selected_day (calendar);
|
||||||
|
g_signal_emit (calendar, calendar_signals[DAY_SELECTED], 0);
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (calendar), calendar_properties[PROP_DATE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (calendar));
|
||||||
|
}
|
||||||
|
|
||||||
|
GDateTime *
|
||||||
|
gtk_date_chooser_widget_get_date (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
return calendar->date;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_widget_set_day_options_callback (GtkDateChooserWidget *calendar,
|
||||||
|
GtkDateChooserDayOptionsCallback callback,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify destroy)
|
||||||
|
{
|
||||||
|
if (calendar->day_options_destroy)
|
||||||
|
calendar->day_options_destroy (calendar->day_options_data);
|
||||||
|
|
||||||
|
calendar->day_options_cb = callback;
|
||||||
|
calendar->day_options_data = data;
|
||||||
|
calendar->day_options_destroy = destroy;
|
||||||
|
|
||||||
|
gtk_date_chooser_widget_invalidate_day_options (calendar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_date_chooser_widget_invalidate_day_options (GtkDateChooserWidget *calendar)
|
||||||
|
{
|
||||||
|
gint row, col;
|
||||||
|
GDateTime *date;
|
||||||
|
GtkDateChooserDay *d;
|
||||||
|
GtkDateChooserDayOptions options;
|
||||||
|
|
||||||
|
for (row = 0; row < 6; row++)
|
||||||
|
for (col = 0; col < 7; col++)
|
||||||
|
{
|
||||||
|
d = GTK_DATE_CHOOSER_DAY (calendar->days[row][col]);
|
||||||
|
date = gtk_date_chooser_day_get_date (d);
|
||||||
|
if (calendar->day_options_cb)
|
||||||
|
options = calendar->day_options_cb (calendar, date, calendar->day_options_data);
|
||||||
|
else
|
||||||
|
options = GTK_DATE_CHOOSER_DAY_NONE;
|
||||||
|
gtk_date_chooser_day_set_options (d, options);
|
||||||
|
}
|
||||||
|
}
|
96
gtk/gtkdatechooserwidget.h
Normal file
96
gtk/gtkdatechooserwidget.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_DATE_CHOOSER_WIDGET_H__
|
||||||
|
#define __GTK_DATE_CHOOSER_WIDGET_H__
|
||||||
|
|
||||||
|
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||||
|
#error "Only <gtk/gtk.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gtk/gtkwidget.h>
|
||||||
|
|
||||||
|
#ifndef GDK_AVAILABLE_IN_3_20
|
||||||
|
#define GDK_AVAILABLE_IN_3_20 _GDK_EXTERN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GTK_TYPE_DATE_CHOOSER_WIDGET (gtk_date_chooser_widget_get_type ())
|
||||||
|
#define GTK_DATE_CHOOSER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_DATE_CHOOSER_WIDGET, GtkDateChooserWidget))
|
||||||
|
#define GTK_DATE_CHOOSER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_DATE_CHOOSER_WIDGET, GtkDateChooserWidgetClass))
|
||||||
|
#define GTK_IS_DATE_CHOOSER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DATE_CHOOSER_WIDGET))
|
||||||
|
#define GTK_IS_DATE_CHOOSER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DATE_CHOOSER_WIDGET))
|
||||||
|
#define GTK_DATE_CHOOSER_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_DATE_CHOOSER_WIDGET, GtkDateChooserWidgetClass))
|
||||||
|
|
||||||
|
typedef struct _GtkDateChooserWidget GtkDateChooserWidget;
|
||||||
|
typedef struct _GtkDateChooserWidgetClass GtkDateChooserWidgetClass;
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
GType gtk_date_chooser_widget_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
GtkWidget * gtk_date_chooser_widget_new (void);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
void gtk_date_chooser_widget_set_date (GtkDateChooserWidget *chooser,
|
||||||
|
GDateTime *dt);
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
GDateTime * gtk_date_chooser_widget_get_date (GtkDateChooserWidget *chooser);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GTK_DATE_CHOOSER_DAY_NONE = 0,
|
||||||
|
GTK_DATE_CHOOSER_DAY_WEEKEND = 1,
|
||||||
|
GTK_DATE_CHOOSER_DAY_HOLIDAY = 2,
|
||||||
|
GTK_DATE_CHOOSER_DAY_MARKED = 4
|
||||||
|
} GtkDateChooserDayOptions;
|
||||||
|
|
||||||
|
typedef GtkDateChooserDayOptions (* GtkDateChooserDayOptionsCallback) (GtkDateChooserWidget *chooser,
|
||||||
|
GDateTime *date,
|
||||||
|
gpointer data);
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
void gtk_date_chooser_widget_set_day_options_callback (GtkDateChooserWidget *chooser,
|
||||||
|
GtkDateChooserDayOptionsCallback callback,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify destroy);
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
void gtk_date_chooser_widget_invalidate_day_options (GtkDateChooserWidget *widget);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
void gtk_date_chooser_widget_set_no_month_change (GtkDateChooserWidget *chooser,
|
||||||
|
gboolean setting);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
void gtk_date_chooser_widget_set_show_heading (GtkDateChooserWidget *chooser,
|
||||||
|
gboolean setting);
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
gboolean gtk_date_chooser_widget_get_show_heading (GtkDateChooserWidget *chooser);
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
void gtk_date_chooser_widget_set_show_day_names (GtkDateChooserWidget *chooser,
|
||||||
|
gboolean setting);
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
gboolean gtk_date_chooser_widget_get_show_day_names (GtkDateChooserWidget *chooser);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
void gtk_date_chooser_widget_set_show_week_numbers (GtkDateChooserWidget *chooser,
|
||||||
|
gboolean setting);
|
||||||
|
GDK_AVAILABLE_IN_3_20
|
||||||
|
gboolean gtk_date_chooser_widget_get_show_week_numbers (GtkDateChooserWidget *chooser);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GTK_DATE_CHOOSER_WIDGET_H__ */
|
478
gtk/gtkmultichoice.c
Normal file
478
gtk/gtkmultichoice.c
Normal file
@@ -0,0 +1,478 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gtkmultichoiceprivate.h"
|
||||||
|
#include "gtkbox.h"
|
||||||
|
#include "gtklabel.h"
|
||||||
|
#include "gtkstack.h"
|
||||||
|
#include "gtkwidgetprivate.h"
|
||||||
|
#include "gtkmarshalers.h"
|
||||||
|
|
||||||
|
#include "gtkintl.h"
|
||||||
|
#include "gtkprivate.h"
|
||||||
|
|
||||||
|
struct _GtkMultiChoice
|
||||||
|
{
|
||||||
|
GtkBox parent;
|
||||||
|
GtkWidget *down_button;
|
||||||
|
GtkWidget *stack;
|
||||||
|
GtkWidget *up_button;
|
||||||
|
gint value;
|
||||||
|
gint min_value;
|
||||||
|
gint max_value;
|
||||||
|
gboolean wrap;
|
||||||
|
gboolean animate;
|
||||||
|
GtkWidget **choices;
|
||||||
|
gint n_choices;
|
||||||
|
guint click_id;
|
||||||
|
GtkWidget *active;
|
||||||
|
GtkWidget *label1;
|
||||||
|
GtkWidget *label2;
|
||||||
|
GtkMultiChoiceFormatCallback format_cb;
|
||||||
|
gpointer format_data;
|
||||||
|
GDestroyNotify format_destroy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GtkMultiChoiceClass
|
||||||
|
{
|
||||||
|
GtkBoxClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_VALUE = 1,
|
||||||
|
PROP_MIN_VALUE,
|
||||||
|
PROP_MAX_VALUE,
|
||||||
|
PROP_WRAP,
|
||||||
|
PROP_ANIMATE,
|
||||||
|
PROP_CHOICES,
|
||||||
|
NUM_PROPERTIES
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *choice_properties[NUM_PROPERTIES] = { NULL, };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WRAPPED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint choice_signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GtkMultiChoice, gtk_multi_choice, GTK_TYPE_BOX)
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
get_value_string (GtkMultiChoice *choice,
|
||||||
|
gint value)
|
||||||
|
{
|
||||||
|
if (choice->format_cb)
|
||||||
|
return choice->format_cb (choice, value, choice->format_data);
|
||||||
|
else if (0 <= value && value < choice->n_choices)
|
||||||
|
return g_strdup (gtk_label_get_label (GTK_LABEL (choice->choices[value])));
|
||||||
|
else
|
||||||
|
return g_strdup_printf ("%d", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_value (GtkMultiChoice *choice,
|
||||||
|
gint value,
|
||||||
|
GtkStackTransitionType transition)
|
||||||
|
{
|
||||||
|
gchar *text;
|
||||||
|
const gchar *name;
|
||||||
|
GtkWidget *label;
|
||||||
|
|
||||||
|
value = CLAMP (value, choice->min_value, choice->max_value);
|
||||||
|
|
||||||
|
if (choice->value == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
choice->value = value;
|
||||||
|
|
||||||
|
if (gtk_stack_get_visible_child (GTK_STACK (choice->stack)) == choice->label1)
|
||||||
|
{
|
||||||
|
name = "label2";
|
||||||
|
label = choice->label2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = "label1";
|
||||||
|
label = choice->label1;
|
||||||
|
}
|
||||||
|
|
||||||
|
text = get_value_string (choice, value);
|
||||||
|
gtk_label_set_text (GTK_LABEL (label), text);
|
||||||
|
g_free (text);
|
||||||
|
|
||||||
|
if (!choice->animate)
|
||||||
|
transition = GTK_STACK_TRANSITION_TYPE_NONE;
|
||||||
|
|
||||||
|
gtk_stack_set_visible_child_full (GTK_STACK (choice->stack), name, transition);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (choice->down_button,
|
||||||
|
choice->wrap || choice->value > choice->min_value);
|
||||||
|
gtk_widget_set_sensitive (choice->up_button,
|
||||||
|
choice->wrap || choice->value < choice->max_value);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (choice), choice_properties[PROP_VALUE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
go_up (GtkMultiChoice *choice)
|
||||||
|
{
|
||||||
|
gint value;
|
||||||
|
gboolean wrapped = FALSE;
|
||||||
|
|
||||||
|
value = choice->value + 1;
|
||||||
|
if (value > choice->max_value)
|
||||||
|
{
|
||||||
|
if (!choice->wrap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
value = choice->min_value;
|
||||||
|
wrapped = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_value (choice, value, GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT);
|
||||||
|
|
||||||
|
if (wrapped)
|
||||||
|
g_signal_emit (choice, choice_signals[WRAPPED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
go_down (GtkMultiChoice *choice)
|
||||||
|
{
|
||||||
|
gint value;
|
||||||
|
gboolean wrapped = FALSE;
|
||||||
|
|
||||||
|
value = choice->value - 1;
|
||||||
|
if (value < choice->min_value)
|
||||||
|
{
|
||||||
|
if (!choice->wrap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
value = choice->max_value;
|
||||||
|
wrapped = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_value (choice, value, GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT);
|
||||||
|
|
||||||
|
if (wrapped)
|
||||||
|
g_signal_emit (choice, choice_signals[WRAPPED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
button_activate (GtkMultiChoice *choice,
|
||||||
|
GtkWidget *button)
|
||||||
|
{
|
||||||
|
if (button == choice->down_button)
|
||||||
|
go_down (choice);
|
||||||
|
else if (button == choice->up_button)
|
||||||
|
go_up (choice);
|
||||||
|
else
|
||||||
|
g_assert_not_reached ();
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
button_timeout (gpointer user_data)
|
||||||
|
{
|
||||||
|
GtkMultiChoice *choice = GTK_MULTI_CHOICE (user_data);
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
if (choice->click_id == 0)
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
|
||||||
|
res = button_activate (choice, choice->active);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
g_source_remove (choice->click_id);
|
||||||
|
choice->click_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
button_press_cb (GtkWidget *widget,
|
||||||
|
GdkEventButton *button,
|
||||||
|
GtkMultiChoice *choice)
|
||||||
|
{
|
||||||
|
gint double_click_time;
|
||||||
|
|
||||||
|
if (button->type != GDK_BUTTON_PRESS)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
g_object_get (gtk_widget_get_settings (widget),
|
||||||
|
"gtk-double-click-time", &double_click_time,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (choice->click_id != 0)
|
||||||
|
g_source_remove (choice->click_id);
|
||||||
|
|
||||||
|
choice->active = widget;
|
||||||
|
|
||||||
|
choice->click_id = gdk_threads_add_timeout (double_click_time,
|
||||||
|
button_timeout,
|
||||||
|
choice);
|
||||||
|
g_source_set_name_by_id (choice->click_id, "[gtk+] button_timeout");
|
||||||
|
button_timeout (choice);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
button_release_cb (GtkWidget *widget,
|
||||||
|
GdkEventButton *event,
|
||||||
|
GtkMultiChoice *choice)
|
||||||
|
{
|
||||||
|
if (choice->click_id != 0)
|
||||||
|
{
|
||||||
|
g_source_remove (choice->click_id);
|
||||||
|
choice->click_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
choice->active = NULL;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
button_clicked_cb (GtkWidget *button,
|
||||||
|
GtkMultiChoice *choice)
|
||||||
|
{
|
||||||
|
if (choice->click_id != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
button_activate (choice, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_multi_choice_init (GtkMultiChoice *choice)
|
||||||
|
{
|
||||||
|
gtk_widget_init_template (GTK_WIDGET (choice));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_multi_choice_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GtkMultiChoice *choice = GTK_MULTI_CHOICE (object);
|
||||||
|
|
||||||
|
if (choice->click_id != 0)
|
||||||
|
{
|
||||||
|
g_source_remove (choice->click_id);
|
||||||
|
choice->click_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (choice->choices);
|
||||||
|
choice->choices = NULL;
|
||||||
|
|
||||||
|
if (choice->format_destroy)
|
||||||
|
{
|
||||||
|
choice->format_destroy (choice->format_data);
|
||||||
|
choice->format_destroy = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gtk_multi_choice_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_multi_choice_get_property (GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkMultiChoice *choice = GTK_MULTI_CHOICE (object);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_VALUE:
|
||||||
|
g_value_set_int (value, choice->value);
|
||||||
|
break;
|
||||||
|
case PROP_MIN_VALUE:
|
||||||
|
g_value_set_int (value, choice->min_value);
|
||||||
|
break;
|
||||||
|
case PROP_MAX_VALUE:
|
||||||
|
g_value_set_int (value, choice->max_value);
|
||||||
|
break;
|
||||||
|
case PROP_WRAP:
|
||||||
|
g_value_set_boolean (value, choice->wrap);
|
||||||
|
break;
|
||||||
|
case PROP_ANIMATE:
|
||||||
|
g_value_set_boolean (value, choice->animate);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_multi_choice_set_property (GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkMultiChoice *choice = GTK_MULTI_CHOICE (object);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_VALUE:
|
||||||
|
gtk_multi_choice_set_value (choice, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
case PROP_MIN_VALUE:
|
||||||
|
choice->min_value = g_value_get_int (value);
|
||||||
|
g_object_notify_by_pspec (object, choice_properties[PROP_MIN_VALUE]);
|
||||||
|
gtk_multi_choice_set_value (choice, choice->value);
|
||||||
|
break;
|
||||||
|
case PROP_MAX_VALUE:
|
||||||
|
choice->max_value = g_value_get_int (value);
|
||||||
|
g_object_notify_by_pspec (object, choice_properties[PROP_MAX_VALUE]);
|
||||||
|
gtk_multi_choice_set_value (choice, choice->value);
|
||||||
|
break;
|
||||||
|
case PROP_WRAP:
|
||||||
|
choice->wrap = g_value_get_boolean (value);
|
||||||
|
g_object_notify_by_pspec (object, choice_properties[PROP_WRAP]);
|
||||||
|
break;
|
||||||
|
case PROP_ANIMATE:
|
||||||
|
choice->animate = g_value_get_boolean (value);
|
||||||
|
g_object_notify_by_pspec (object, choice_properties[PROP_ANIMATE]);
|
||||||
|
break;
|
||||||
|
case PROP_CHOICES:
|
||||||
|
gtk_multi_choice_set_choices (choice, (const gchar **)g_value_get_boxed (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_multi_choice_class_init (GtkMultiChoiceClass *class)
|
||||||
|
{
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||||
|
|
||||||
|
object_class->dispose = gtk_multi_choice_dispose;
|
||||||
|
object_class->set_property = gtk_multi_choice_set_property;
|
||||||
|
object_class->get_property = gtk_multi_choice_get_property;
|
||||||
|
|
||||||
|
choice_properties[PROP_VALUE] =
|
||||||
|
g_param_spec_int ("value", P_("Value"), P_("Value"),
|
||||||
|
G_MININT, G_MAXINT, 0,
|
||||||
|
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
choice_properties[PROP_MIN_VALUE] =
|
||||||
|
g_param_spec_int ("min-value", P_("Minimum Value"), P_("Minimum Value"),
|
||||||
|
G_MININT, G_MAXINT, 0,
|
||||||
|
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
choice_properties[PROP_MAX_VALUE] =
|
||||||
|
g_param_spec_int ("max-value", P_("Maximum Value"), P_("Maximum Value"),
|
||||||
|
G_MININT, G_MAXINT, 0,
|
||||||
|
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
choice_properties[PROP_WRAP] =
|
||||||
|
g_param_spec_boolean ("wrap", P_("Wrap"), P_("Wrap"),
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
choice_properties[PROP_ANIMATE] =
|
||||||
|
g_param_spec_boolean ("animate", P_("Animate"), P_("Animate"),
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
choice_properties[PROP_CHOICES] =
|
||||||
|
g_param_spec_boxed ("choices", P_("Choices"), P_("Choices"),
|
||||||
|
G_TYPE_STRV,
|
||||||
|
G_PARAM_WRITABLE|G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
g_object_class_install_properties (object_class, NUM_PROPERTIES, choice_properties);
|
||||||
|
|
||||||
|
choice_signals[WRAPPED] =
|
||||||
|
g_signal_new (I_("wrapped"),
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
_gtk_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtkmultichoice.ui");
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GtkMultiChoice, down_button);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GtkMultiChoice, up_button);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GtkMultiChoice, stack);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GtkMultiChoice, label1);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, GtkMultiChoice, label2);
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, button_clicked_cb);
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, button_press_cb);
|
||||||
|
gtk_widget_class_bind_template_callback (widget_class, button_release_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gtk_multi_choice_new (void)
|
||||||
|
{
|
||||||
|
return GTK_WIDGET (g_object_new (GTK_TYPE_MULTI_CHOICE, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_multi_choice_set_value (GtkMultiChoice *choice,
|
||||||
|
gint value)
|
||||||
|
{
|
||||||
|
set_value (choice, value, GTK_STACK_TRANSITION_TYPE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
gtk_multi_choice_get_value (GtkMultiChoice *choice)
|
||||||
|
{
|
||||||
|
return choice->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_multi_choice_set_choices (GtkMultiChoice *choice,
|
||||||
|
const gchar **choices)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; i < choice->n_choices; i++)
|
||||||
|
gtk_container_remove (GTK_CONTAINER (choice->stack), choice->choices[i]);
|
||||||
|
g_free (choice->choices);
|
||||||
|
|
||||||
|
choice->n_choices = g_strv_length ((gchar **)choices);
|
||||||
|
choice->choices = g_new (GtkWidget *, choice->n_choices);
|
||||||
|
for (i = 0; i < choice->n_choices; i++)
|
||||||
|
{
|
||||||
|
choice->choices[i] = gtk_label_new (choices[i]);
|
||||||
|
gtk_widget_show (choice->choices[i]);
|
||||||
|
gtk_stack_add_named (GTK_STACK (choice->stack),
|
||||||
|
choice->choices[i],
|
||||||
|
choices[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (choice), choice_properties[PROP_CHOICES]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_multi_choice_set_format_callback (GtkMultiChoice *choice,
|
||||||
|
GtkMultiChoiceFormatCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
GDestroyNotify destroy)
|
||||||
|
{
|
||||||
|
if (choice->format_destroy)
|
||||||
|
choice->format_destroy (choice->format_data);
|
||||||
|
|
||||||
|
choice->format_cb = callback;
|
||||||
|
choice->format_data = user_data;
|
||||||
|
choice->format_destroy = destroy;
|
||||||
|
}
|
56
gtk/gtkmultichoiceprivate.h
Normal file
56
gtk/gtkmultichoiceprivate.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_MULTI_CHOICE_PRIVATE_H__
|
||||||
|
#define __GTK_MULTI_CHOICE_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <gtk/gtkbin.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GTK_TYPE_MULTI_CHOICE (gtk_multi_choice_get_type ())
|
||||||
|
#define GTK_MULTI_CHOICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MULTI_CHOICE, GtkMultiChoice))
|
||||||
|
#define GTK_MULTI_CHOICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_MULTI_CHOICE, GtkMultiChoiceClass))
|
||||||
|
#define GTK_IS_MULTI_CHOICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_MULTI_CHOICE))
|
||||||
|
#define GTK_IS_MULTI_CHOICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_MULTI_CHOICE))
|
||||||
|
#define GTK_MULTI_CHOICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MULTI_CHOICE, GtkMultiChoiceClass))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GtkMultiChoice GtkMultiChoice;
|
||||||
|
typedef struct _GtkMultiChoiceClass GtkMultiChoiceClass;
|
||||||
|
|
||||||
|
GType gtk_multi_choice_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GtkWidget *gtk_multi_choice_new (void);
|
||||||
|
void gtk_multi_choice_set_value (GtkMultiChoice *choice,
|
||||||
|
gint value);
|
||||||
|
gint gtk_multi_choice_get_value (GtkMultiChoice *choice);
|
||||||
|
void gtk_multi_choice_set_choices (GtkMultiChoice *choice,
|
||||||
|
const gchar **choices);
|
||||||
|
|
||||||
|
typedef gchar * (* GtkMultiChoiceFormatCallback) (GtkMultiChoice *choice,
|
||||||
|
gint value,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
void gtk_multi_choice_set_format_callback (GtkMultiChoice *choice,
|
||||||
|
GtkMultiChoiceFormatCallback callback,
|
||||||
|
gpointer user_data,
|
||||||
|
GDestroyNotify notify);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GTK_MULTI_CHOICE_PRIVATE_H__ */
|
@@ -2746,6 +2746,34 @@ GtkCalendar {
|
|||||||
border-color: $backdrop_borders_color;
|
border-color: $backdrop_borders_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* New widget */
|
||||||
|
.weekday {
|
||||||
|
background-color: $base_color; /* doesn't seem to work */
|
||||||
|
color: lighten($fg_color,20%);
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 80%;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
.weeknum { color: lighten($fg_color,20%); }
|
||||||
|
.day {
|
||||||
|
color: $fg_color;
|
||||||
|
padding: 0.4em; /* doesn't seem to work */
|
||||||
|
text-align: center; /* haha, dream on */
|
||||||
|
}
|
||||||
|
.day.dim-label{ color: $insensitive_fg_color; }
|
||||||
|
.day.day:selected {
|
||||||
|
color: $selected_fg_color;
|
||||||
|
background-color: $selected_bg_color;
|
||||||
|
padding: 0.4em;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.day.holiday,
|
||||||
|
.day.weekend {
|
||||||
|
background-color: transparentize(red, 0.9);
|
||||||
|
}
|
||||||
|
.day.marked {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
/***********
|
/***********
|
||||||
* Dialogs *
|
* Dialogs *
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
32
gtk/ui/gtkdatechooserwidget.ui
Normal file
32
gtk/ui/gtkdatechooserwidget.ui
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.18.1 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.16"/>
|
||||||
|
<template class="GtkDateChooserWidget" parent="GtkBin">
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMultiChoice" id="month_choice">
|
||||||
|
<property name="visible" bind-source="GtkDateChooserWidget" bind-property="show-heading" bind-flags="sync-create"/>
|
||||||
|
<property name="halign">fill</property>
|
||||||
|
<property name="min-value">0</property>
|
||||||
|
<property name="max-value">120000</property>
|
||||||
|
<property name="animate">False</property>
|
||||||
|
<property name="value">0</property>
|
||||||
|
<signal name="notify::value" handler="calendar_month_changed" swapped="yes"/>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="grid">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
65
gtk/ui/gtkmultichoice.ui
Normal file
65
gtk/ui/gtkmultichoice.ui
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface domain="gtk30">
|
||||||
|
<requires lib="gtk+" version="3.16"/>
|
||||||
|
<template class="GtkMultiChoice" parent="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="down_button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="relief">none</property>
|
||||||
|
<signal name="button-press-event" handler="button_press_cb"/>
|
||||||
|
<signal name="button-release-event" handler="button_release_cb"/>
|
||||||
|
<signal name="clicked" handler="button_clicked_cb"/>
|
||||||
|
<style>
|
||||||
|
<class name="image-button"/>
|
||||||
|
</style>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="icon_name">pan-start-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStack" id="stack">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="name">label1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="name">label2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="up_button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="relief">none</property>
|
||||||
|
<signal name="button-press-event" handler="button_press_cb"/>
|
||||||
|
<signal name="button-release-event" handler="button_release_cb"/>
|
||||||
|
<signal name="clicked" handler="button_clicked_cb"/>
|
||||||
|
<style>
|
||||||
|
<class name="image-button"/>
|
||||||
|
</style>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="icon_name">pan-end-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
@@ -168,6 +168,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
|||||||
testpopover \
|
testpopover \
|
||||||
gdkgears \
|
gdkgears \
|
||||||
listmodel \
|
listmodel \
|
||||||
|
testdatechooser \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
if USE_X11
|
if USE_X11
|
||||||
@@ -308,6 +309,7 @@ testrevealer_DEPENDENCIES = $(TEST_DEPS)
|
|||||||
testtitlebar_DEPENDENCIES = $(TEST_DEPS)
|
testtitlebar_DEPENDENCIES = $(TEST_DEPS)
|
||||||
testwindowsize_DEPENDENCIES = $(TEST_DEPS)
|
testwindowsize_DEPENDENCIES = $(TEST_DEPS)
|
||||||
listmodel_DEPENDENCIES = $(TEST_DEPS)
|
listmodel_DEPENDENCIES = $(TEST_DEPS)
|
||||||
|
testdatechooser_DEPENDENCIES = $(TEST_DEPS)
|
||||||
|
|
||||||
animated_resizing_SOURCES = \
|
animated_resizing_SOURCES = \
|
||||||
animated-resizing.c \
|
animated-resizing.c \
|
||||||
@@ -542,6 +544,8 @@ testglblending_SOURCES = \
|
|||||||
|
|
||||||
listmodel_SOURCES = listmodel.c
|
listmodel_SOURCES = listmodel.c
|
||||||
|
|
||||||
|
testdatechooser_SOURCES = testdatechooser.c
|
||||||
|
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
gradient1.png \
|
gradient1.png \
|
||||||
testgtk.1 \
|
testgtk.1 \
|
||||||
|
72
tests/testdatechooser.c
Normal file
72
tests/testdatechooser.c
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
date_changed (GObject *calendar,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GDateTime *date;
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
date = gtk_date_chooser_widget_get_date (GTK_DATE_CHOOSER_WIDGET (calendar));
|
||||||
|
text = g_date_time_format (date, "selected: %x");
|
||||||
|
g_print ("%s\n", text);
|
||||||
|
g_free (text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkDateChooserDayOptions
|
||||||
|
get_day_options (GtkDateChooserWidget *calendar,
|
||||||
|
GDateTime *date,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkDateChooserDayOptions options;
|
||||||
|
|
||||||
|
options = GTK_DATE_CHOOSER_DAY_NONE;
|
||||||
|
|
||||||
|
if (g_date_time_get_day_of_week (date) == 6 ||
|
||||||
|
g_date_time_get_day_of_week (date) == 7)
|
||||||
|
options |= GTK_DATE_CHOOSER_DAY_WEEKEND;
|
||||||
|
|
||||||
|
/* 4th of July */
|
||||||
|
if (g_date_time_get_month (date) == 7 &&
|
||||||
|
g_date_time_get_day_of_month (date) == 4)
|
||||||
|
options |= GTK_DATE_CHOOSER_DAY_HOLIDAY;
|
||||||
|
|
||||||
|
/* Bastille day */
|
||||||
|
if (g_date_time_get_month (date) == 7 &&
|
||||||
|
g_date_time_get_day_of_month (date) == 14)
|
||||||
|
options |= GTK_DATE_CHOOSER_DAY_HOLIDAY;
|
||||||
|
|
||||||
|
/* my birthday */
|
||||||
|
if (g_date_time_get_month (date) == 3 &&
|
||||||
|
g_date_time_get_day_of_month (date) == 1)
|
||||||
|
options |= GTK_DATE_CHOOSER_DAY_MARKED;
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GtkWidget *window, *calendar;
|
||||||
|
|
||||||
|
gtk_init (NULL, NULL);
|
||||||
|
|
||||||
|
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||||
|
|
||||||
|
calendar = gtk_date_chooser_widget_new ();
|
||||||
|
g_signal_connect (calendar, "notify::date",
|
||||||
|
G_CALLBACK (date_changed), NULL);
|
||||||
|
gtk_date_chooser_widget_set_day_options_callback (GTK_DATE_CHOOSER_WIDGET (calendar),
|
||||||
|
get_day_options,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (window), calendar);
|
||||||
|
|
||||||
|
gtk_widget_show_all (window);
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -97,10 +97,9 @@ main (int argc,
|
|||||||
|
|
||||||
#ifdef GDK_WINDOWING_X11
|
#ifdef GDK_WINDOWING_X11
|
||||||
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) ;
|
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) ;
|
||||||
return 0; /* gtk_test functions don't work well elsewhere */
|
else
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
return 0; /* gtk_test functions don't work well outside X11 */
|
||||||
|
|
||||||
g_test_add_func ("/expander/click-expander", test_click_expander);
|
g_test_add_func ("/expander/click-expander", test_click_expander);
|
||||||
g_test_add_func ("/expander/click-content-widget", test_click_content_widget);
|
g_test_add_func ("/expander/click-content-widget", test_click_content_widget);
|
||||||
|
Reference in New Issue
Block a user