/* This function returns the current time in the clock's timezone. *Notethatthisreturnsanewobjecteverytime,soweneedto *remembertounrefitafteruse.
*/ static GDateTime *
gtk_clock_get_time (GtkClock *clock)
{ if (clock->timezone) return g_date_time_new_now (clock->timezone); else return g_date_time_new_now_local ();
}
/* Here, we implement the functionality required by the GdkPaintable *interface.Thiswaywehaveatrivialwaytodisplayananalogclock. *Italsoallowsdemonstratinghowtodirectlyuseobjectsinthe *listviewlaterbymakingthisobjectdosomethinginteresting.
*/ staticvoid
gtk_clock_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot, double width, double height)
{
GtkClock *self = GTK_CLOCK (paintable);
GDateTime *time;
GskRoundedRect outline;
#define BLACK ((GdkRGBA) { 0, 0, 0, 1 })
/* save/restore() is necessary so we can undo the transforms we start *outwith.
*/
gtk_snapshot_save (snapshot);
/* First, we move the (0, 0) point to the center of the area so *wecandraweverythingrelativetoit.
*/
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2, height / 2));
/* Next we scale it, so that we can pretend that the clock is *100pxinsize.Thatway,wedon'tneedtodoanycomplicated *mathlater.WeuseMIN()heresothatweusethesmaller *dimensionforsizing.Thatwaywedon'toverdrawbutkeep *theaspectratio.
*/
gtk_snapshot_scale (snapshot, MIN (width, height) / 100.0, MIN (width, height) / 100.0);
/* Now we have a circle with diameter 100px (and radius 50px) that *hasits(0,0)pointatthecenter.Let'sdrawasimpleclockintoit.
*/
time = gtk_clock_get_time (self);
/* First, draw a circle. This is a neat little trick to draw a circle *withoutrequiringCairo.
*/
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-50, -50, 100, 100), 50);
gtk_snapshot_append_border (snapshot,
&outline,
(float[4]) { 4, 4, 4, 4 },
(GdkRGBA [4]) { BLACK, BLACK, BLACK, BLACK });
/* And the same as above for the minute hand. Just make this one longer *sopeoplecantellthehandsapart.
*/
gtk_snapshot_save (snapshot);
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_minute (time));
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 45), 2);
gtk_snapshot_push_rounded_clip (snapshot, &outline);
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
gtk_snapshot_pop (snapshot);
gtk_snapshot_restore (snapshot);
/* Initialize the paintable interface. This way we turn our clocks *intoobjectsthatcanbedrawn.Therearemorefunctionstothis *interfacetodefinedesiredsize,butthisisenough.
*/ staticvoid
gtk_clock_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = gtk_clock_snapshot;
iface->get_intrinsic_width = gtk_clock_get_intrinsic_width;
iface->get_intrinsic_height = gtk_clock_get_intrinsic_height;
}
/* Finally, we define the type. The important part is adding the *paintableinterface,soGTKknowsthatthisobjectcanindeed *bedrawn.
*/
G_DEFINE_TYPE_WITH_CODE (GtkClock, gtk_clock, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_clock_paintable_init))
/* This is the list of all the ticking clocks */ static GSList *ticking_clocks = NULL;
/* This is the ID of the timeout source that is updating all *tickingclocks.
*/ static guint ticking_clock_id = 0;
/* Every second, this function is called to tell everybody that *theclocksareticking.
*/ static gboolean
gtk_clock_tick (gpointer unused)
{
GSList *l;
for (l = ticking_clocks; l; l = l->next)
{
GtkClock *clock = l->data;
/* We will now return a different value for the time property, *sonotifyaboutthat.
*/
g_object_notify_by_pspec (G_OBJECT (clock), properties[PROP_TIME]);
/* We will also draw the hands of the clock differently. *Sonotifyaboutthat,too.
*/
gdk_paintable_invalidate_contents (GDK_PAINTABLE (clock));
}
/* If no clock is remaining, stop running the tick updates */ if (ticking_clocks == NULL && ticking_clock_id != 0)
g_clear_handle_id (&ticking_clock_id, g_source_remove);
}
staticvoid
gtk_clock_start_ticking (GtkClock *self)
{ /* if no clock is ticking yet, start */ if (ticking_clock_id == 0)
ticking_clock_id = g_timeout_add_seconds (1, gtk_clock_tick, NULL);
/* And this function is the crux for this whole demo. *Itshowshowtouseexpressionstosetupbindings.
*/ staticvoid
setup_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *box, *picture, *location_label, *time_label;
GtkExpression *clock_expression, *expression;
/* First, we create an expression that gets us the clock from the listitem: *1.Createanexpressionthatgetsthelistitem. *2.Usethatexpression's"item"propertytogettheclock
*/
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
clock_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
/* Bind the clock's location to a label. *Thisiseasy:Wejustgetthe"location"propertyoftheclock.
*/
expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
gtk_expression_ref (clock_expression), "location"); /* Now create the label and bind the expression to it. */
location_label = gtk_label_new (NULL);
gtk_expression_bind (expression, location_label, "label", location_label);
gtk_box_append (GTK_BOX (box), location_label);
/* Here we bind the item itself to a GdkPicture. *Thisissimplydonebyusingtheclockexpressionitself.
*/
expression = gtk_expression_ref (clock_expression); /* Now create the widget and bind the expression to it. */
picture = gtk_picture_new ();
gtk_expression_bind (expression, picture, "paintable", picture);
gtk_box_append (GTK_BOX (box), picture);
gtk_accessible_update_relation (GTK_ACCESSIBLE (picture),
GTK_ACCESSIBLE_RELATION_LABELLED_BY, location_label, NULL,
-1);
/* And finally, everything comes together. *Wecreatealabelfordisplayingthetimeastext. *Forthat,weneedtotransformthe"GDateTime"ofthe *timepropertyintoastringsothatthelabelcandisplayit.
*/
expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
gtk_expression_ref (clock_expression), "time");
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL, 1, (GtkExpression *[1]) { expression },
G_CALLBACK (convert_time_to_string),
NULL, NULL); /* Now create the label and bind the expression to it. */
time_label = gtk_label_new (NULL);
gtk_expression_bind (expression, time_label, "label", time_label);
gtk_box_append (GTK_BOX (box), time_label);
/* This is the normal window setup code every demo does */
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Clocks");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
/* List widgets go into a scrolled window. Always. */
sw = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), sw);
/* Create the factory that creates the listitems. Because we *usedbindingsaboveduringsetup,weonlyneedtoconnect *tothesetupsignal. *Thebindingstakecareofthebindstep.
*/
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.