static gboolean ctk_banner_expose_event( GtkWidget *widget, GdkEventExpose *event ) { CtkBanner *ctk_banner = CTK_BANNER(widget); GdkRectangle *rects; int n_rects; int i; /* copy the backing pixbuf into the exposed portion of the window */ gdk_region_get_rectangles(event->region, &rects, &n_rects); for (i = 0; i < n_rects; i++) { gdk_draw_pixbuf(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], ctk_banner->back.pixbuf, rects[i].x, rects[i].y, rects[i].x, rects[i].y, rects[i].width, rects[i].height, GDK_RGB_DITHER_NORMAL, 0, 0); } g_free(rects); return FALSE; }
/* * CTK composited banner image widget creation * */ GtkWidget* ctk_banner_image_new_with_callback(BannerArtworkType artwork, ctk_banner_composite_callback callback, void *data) { GtkWidget *image; GtkWidget *hbox; GtkWidget *frame; image = ctk_banner_new(artwork); if (!image) return NULL; ctk_banner_set_composite_callback(CTK_BANNER(image), callback, data); hbox = gtk_hbox_new(FALSE, 0); frame = gtk_frame_new(NULL); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(frame), image); return hbox; }
static void ctk_banner_size_request( GtkWidget *widget, GtkRequisition *requisition ) { CtkBanner *ctk_banner = CTK_BANNER(widget); requisition->width = MAX(400, ctk_banner->logo->w + ctk_banner->artwork.w + ctk_banner->logo_pad_x + ctk_banner->artwork_pad_x); requisition->height = ctk_banner->background->h; }
static gboolean ctk_banner_draw_event( GtkWidget *widget, cairo_t *cr_i ) { CtkBanner *ctk_banner = CTK_BANNER(widget); cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget)); /* copy the backing pixbuf into the exposed portion of the window */ gdk_cairo_set_source_pixbuf(cr, ctk_banner->back.pixbuf, 0, 0); cairo_paint(cr); cairo_destroy(cr); return FALSE; }
static void ctk_banner_finalize( GObject *object ) { CtkBanner *ctk_banner = CTK_BANNER(object); if (ctk_banner->back.pixbuf) g_object_unref(ctk_banner->back.pixbuf); if (ctk_banner->artwork.pixbuf) g_object_unref(ctk_banner->artwork.pixbuf); if (ctk_banner->logo->pixbuf) g_object_unref(ctk_banner->logo->pixbuf); if (ctk_banner->background->pixbuf) g_object_unref(ctk_banner->background->pixbuf); }
GtkWidget* ctk_banner_new(BannerArtworkType artwork) { GObject *object; CtkBanner *ctk_banner; const GdkPixdata *pixdata; int tall, pad_x; if (!select_artwork(artwork, &tall, &pad_x, &pixdata)) { return NULL; } object = g_object_new(CTK_TYPE_BANNER, NULL); ctk_banner = CTK_BANNER(object); ctk_banner->back.pixbuf = NULL; ctk_banner->artwork.pixbuf = NULL; ctk_banner->artwork_pad_x = pad_x; /* load the global images */ if (!Background.pixbuf) { Background.pixbuf = gdk_pixbuf_from_pixdata(&background_pixdata, TRUE, NULL); Background.w = gdk_pixbuf_get_width(Background.pixbuf); Background.h = gdk_pixbuf_get_height(Background.pixbuf); } g_object_ref(Background.pixbuf); if (!TallBackground.pixbuf) { TallBackground.pixbuf = gdk_pixbuf_from_pixdata(&background_tall_pixdata, TRUE, NULL); TallBackground.w = gdk_pixbuf_get_width(TallBackground.pixbuf); TallBackground.h = gdk_pixbuf_get_height(TallBackground.pixbuf); } g_object_ref(TallBackground.pixbuf); if (!Logo.pixbuf) { Logo.pixbuf = gdk_pixbuf_from_pixdata(&logo_pixdata, TRUE, NULL); Logo.w = gdk_pixbuf_get_width(Logo.pixbuf); Logo.h = gdk_pixbuf_get_height(Logo.pixbuf); } g_object_ref(Logo.pixbuf); if (!TallLogo.pixbuf) { TallLogo.pixbuf = gdk_pixbuf_from_pixdata(&logo_tall_pixdata, TRUE, NULL); TallLogo.w = gdk_pixbuf_get_width(TallLogo.pixbuf); TallLogo.h = gdk_pixbuf_get_height(TallLogo.pixbuf); } g_object_ref(TallLogo.pixbuf); /* * assign fields based on whether the artwork is tall; XXX these * may need to be tweaked */ if (tall) { ctk_banner->logo_pad_x = 11; ctk_banner->logo_pad_y = 0; ctk_banner->background = &TallBackground; ctk_banner->logo = &TallLogo; } else { ctk_banner->logo_pad_x = 10; ctk_banner->logo_pad_y = 10; ctk_banner->background = &Background; ctk_banner->logo = &Logo; } /* load the artwork pixbuf */ ctk_banner->artwork.pixbuf = gdk_pixbuf_from_pixdata(pixdata, TRUE, NULL); ctk_banner->artwork.w = gdk_pixbuf_get_width(ctk_banner->artwork.pixbuf); ctk_banner->artwork.h = gdk_pixbuf_get_height(ctk_banner->artwork.pixbuf); return GTK_WIDGET(object); }
static gboolean ctk_banner_configure_event( GtkWidget *widget, GdkEventConfigure *event ) { CtkBanner *ctk_banner = CTK_BANNER(widget); int x, y, w, h, needed_w, needed_h; /* free the pixbuf we already have one */ if (ctk_banner->back.pixbuf) g_object_unref(ctk_banner->back.pixbuf); /* allocate a backing pixbuf the size of the new window */ ctk_banner->back.pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, // colorSpace FALSE, // has_alpha (no alpha needed for backing pixbuf) gdk_pixbuf_get_bits_per_sample (ctk_banner->background->pixbuf), event->width, event->height); ctk_banner->back.w = gdk_pixbuf_get_width(ctk_banner->back.pixbuf); ctk_banner->back.h = gdk_pixbuf_get_height(ctk_banner->back.pixbuf); /* clear the backing pixbuf to black */ gdk_pixbuf_fill(ctk_banner->back.pixbuf, 0x00000000); /* copy the base image into the backing pixbuf */ w = MIN(ctk_banner->background->w, ctk_banner->back.w); h = MIN(ctk_banner->background->h, ctk_banner->back.h); gdk_pixbuf_copy_area(ctk_banner->background->pixbuf, // src 0, // src_x 0, // src_y w, // width h, // height ctk_banner->back.pixbuf, // dest 0, // dest_x 0); // dest_y /* * composite the logo into the backing pixbuf; positioned in the * upper right corner of the backing pixbuf. We should only do * this, though, if the backing pixbuf is large enough to contain * the logo */ needed_w = ctk_banner->logo->w + ctk_banner->logo_pad_x; needed_h = ctk_banner->logo->h + ctk_banner->logo_pad_y; if ((ctk_banner->back.w >= needed_w) && (ctk_banner->back.h >= needed_h)) { w = ctk_banner->logo->w; h = ctk_banner->logo->h; x = ctk_banner->back.w - w; y = 0; ctk_banner->logo_x = x - ctk_banner->logo_pad_x; ctk_banner->logo_y = y + ctk_banner->logo_pad_y; gdk_pixbuf_composite(ctk_banner->logo->pixbuf, // src ctk_banner->back.pixbuf, // dest ctk_banner->logo_x, // dest_x ctk_banner->logo_y, // dest_y w, // dest_width h, // dest_height ctk_banner->logo_x, // offset_x ctk_banner->logo_y, // offset_y 1.0, // scale_x 1.0, // scale_y GDK_INTERP_BILINEAR, // interp_type 255); // overall_alpha } /* * composite the artwork into the lower left corner of the backing * pixbuf */ needed_w = ctk_banner->artwork.w + ctk_banner->artwork_pad_x; needed_h = ctk_banner->artwork.h; if ((ctk_banner->back.w >= needed_w) && (ctk_banner->back.h >= needed_h)) { w = ctk_banner->artwork.w; h = ctk_banner->artwork.h; x = 0; y = ctk_banner->back.h - h; ctk_banner->artwork_x = x + ctk_banner->artwork_pad_x; ctk_banner->artwork_y = y; gdk_pixbuf_composite(ctk_banner->artwork.pixbuf, // src ctk_banner->back.pixbuf, // dest ctk_banner->artwork_x, // dest_x ctk_banner->artwork_y, // dest_y w, // dest_width h, // dest_height ctk_banner->artwork_x, // offset_x ctk_banner->artwork_y, // offset_y 1.0, // scale_x 1.0, // scale_y GDK_INTERP_BILINEAR, // interp_type 255); // overall_alpha /* Do any user-specific compositing */ if (ctk_banner->callback_func) { ctk_banner->callback_func(ctk_banner, ctk_banner->callback_data); } } return FALSE; }