Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

splash.cpp

Go to the documentation of this file.
00001 /*
00002  *  Celestia GTK+ Front-End
00003  *  Copyright (C) 2005 Pat Suwalski <pat@suwalski.net>
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  $Id: splash.cpp,v 1.3 2006/01/09 19:02:54 suwalski Exp $
00011  */
00012 
00013 #ifdef HAVE_CONFIG_H
00014 #include <config.h>
00015 #endif /* HAVE_CONFIG_H */
00016 
00017 #include <gtk/gtk.h>
00018 
00019 #ifdef CAIRO
00020 #include <cairo/cairo.h>
00021 #endif /* CAIRO */
00022 
00023 #include "splash.h"
00024 #include "common.h"
00025 
00026 
00027 /* Declarations */
00028 static gboolean splashExpose(GtkWidget* win, GdkEventExpose *event, SplashData* ss);
00029 
00030 
00031 /* OBJECT: Overrides ProgressNotifier to receive feedback from core */
00032 GtkSplashProgressNotifier::GtkSplashProgressNotifier(SplashData* _splash) :
00033         splash(_splash) {};
00034 
00035 void GtkSplashProgressNotifier::update(const string& filename)
00036 {
00037         splashSetText(splash, filename.c_str());
00038 }
00039 
00040 GtkSplashProgressNotifier::~GtkSplashProgressNotifier() {};
00041 
00042 
00043 /* ENTRY: Creates a new SplashData struct, starts the splash screen */
00044 SplashData* splashStart(AppData* app, gboolean showSplash)
00045 {
00046         SplashData* ss = g_new0(SplashData, 1);
00047 
00048         ss->app = app;
00049         ss->notifier = new GtkSplashProgressNotifier(ss);
00050         ss->hasARGB = FALSE;
00051         ss->redraw = TRUE;
00052 
00053         /* Continue the "wait" cursor until the splash is done */
00054         gtk_window_set_auto_startup_notification(FALSE);
00055         
00056         /* Don't do anything else if the splash is not to be shown */
00057         if (showSplash == FALSE) return ss;
00058 
00059         ss->splash = gtk_window_new(GTK_WINDOW_POPUP);
00060         gtk_window_set_position(GTK_WINDOW(ss->splash), GTK_WIN_POS_CENTER);
00061         gtk_widget_set_app_paintable(ss->splash, TRUE);
00062 
00063         #ifdef CAIRO
00064         /* Colormap Magic */
00065         GdkScreen* screen = gtk_widget_get_screen(ss->splash);
00066         GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen);
00067         if (colormap != NULL)
00068         {
00069                 gtk_widget_set_colormap(ss->splash, colormap);
00070                 ss->hasARGB = TRUE;
00071         }
00072         #endif
00073 
00074         GtkWidget* gf = gtk_fixed_new();
00075         gtk_container_add(GTK_CONTAINER(ss->splash), gf);
00076 
00077         GtkWidget* i = gtk_image_new_from_file("splash/splash.png");
00078         gtk_fixed_put(GTK_FIXED(gf), i, 0, 0);
00079 
00080         /* The information label is right-aligned and biased to the lower-right
00081          * of the window. It's designed to be the full width and height of the
00082          * opaque parts of the splash. */
00083         ss->label = gtk_label_new(NULL);
00084         gtk_misc_set_alignment(GTK_MISC(ss->label), 1, 1);
00085         gtk_label_set_justify(GTK_LABEL(ss->label), GTK_JUSTIFY_RIGHT);
00086         gtk_widget_modify_fg(ss->label, GTK_STATE_NORMAL, &ss->label->style->white);
00087 
00088         gtk_widget_show_all(ss->splash);
00089 
00090         /* Size allocations available after showing splash. */
00091         gtk_widget_set_size_request(ss->label, i->allocation.width - 80,
00092                                                i->allocation.height / 2);
00093         gtk_fixed_put(GTK_FIXED(gf), ss->label, 40, i->allocation.height / 2 - 40);
00094         gtk_widget_show(ss->label);
00095 
00096         g_signal_connect (ss->splash, "expose_event",
00097                           G_CALLBACK (splashExpose),
00098                           ss);
00099         
00100         while (gtk_events_pending()) gtk_main_iteration();
00101 
00102         return ss;
00103 }
00104 
00105 
00106 /* ENTRY: destroys the splash screen */
00107 void splashEnd(SplashData* ss)
00108 {
00109         if (ss->splash)
00110                 gtk_widget_destroy(ss->splash);
00111 
00112         /* Return the cursor from wait to normal */
00113         gdk_notify_startup_complete();
00114 
00115         delete ss->notifier;
00116         g_free(ss);
00117 }
00118 
00119 
00120 /* ENTRY: Sets the text to be shown in the splash */
00121 void splashSetText(SplashData* ss, const char* text)
00122 {
00123         char message[255];
00124 
00125         if (!ss->splash)
00126                 return;
00127 
00128         sprintf(message, "Version " VERSION "\n%s", text);
00129 
00130         gtk_label_set_text(GTK_LABEL(ss->label), message);
00131 
00132         /* Update the GTK event queue */
00133         while (gtk_events_pending()) gtk_main_iteration();
00134 }
00135 
00136 
00137 /* CALLBACK: Called when the splash screen is exposed */
00138 static gboolean splashExpose(GtkWidget* win, GdkEventExpose *event, SplashData* ss)
00139 {
00140         /* All of this code is only needed at the very first drawing. This
00141          * operation is quite expensive. */
00142         if (ss->redraw != TRUE) return FALSE;
00143 
00144         if (ss->hasARGB)
00145         {
00146                 #ifdef CAIRO
00147                 /* Use cairo for true transparent windows */
00148                 cairo_t *cr = gdk_cairo_create(win->window);    
00149         
00150                 cairo_rectangle(cr, event->area.x,
00151                                     event->area.y,
00152                                     event->area.width,
00153                                     event->area.height);
00154                 cairo_clip(cr);
00155         
00156                 /* Draw a fully transparent rectangle the size of the window */
00157                 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0);
00158         
00159                 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
00160                 cairo_paint(cr);
00161         
00162                 cairo_destroy(cr);
00163                 #endif /* CAIRO */
00164         }
00165         else
00166         {
00167                 /* Fall back to compositing a screenshot of whatever is below the
00168                  * area we are drawing in. */
00169                 GdkPixbuf* bg;
00170                 int x, y, w, h;
00171 
00172                 gdk_window_get_root_origin(win->window, &x, &y);
00173                 gdk_drawable_get_size(win->window, &w, &h);
00174 
00175                 bg = gdk_pixbuf_get_from_drawable(NULL,
00176                                                   gtk_widget_get_root_window(win),
00177                                                   NULL, x, y, 0, 0, w, h);
00178                 gdk_draw_pixbuf(win->window, NULL, bg, 0, 0, 0, 0, w, h,
00179                                 GDK_RGB_DITHER_NONE, 0, 0);
00180         }
00181         
00182         /* Never redraw again */
00183         ss->redraw = FALSE;
00184 
00185         return FALSE;
00186 }

Generated on Sat Jan 14 22:30:30 2006 for Celestia by  doxygen 1.4.1