summaryrefslogtreecommitdiff
path: root/src/ui/theme-viewer.c
diff options
context:
space:
mode:
authorPerberos <[email protected]>2011-12-01 23:52:01 -0300
committerPerberos <[email protected]>2011-12-01 23:52:01 -0300
commit28a029a4990d2a84f9d6a0b890eba812ea503998 (patch)
tree7a69477d0dd6bf351801fa9698d95224e4fe47b6 /src/ui/theme-viewer.c
downloadmarco-28a029a4990d2a84f9d6a0b890eba812ea503998.tar.bz2
marco-28a029a4990d2a84f9d6a0b890eba812ea503998.tar.xz
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'src/ui/theme-viewer.c')
-rw-r--r--src/ui/theme-viewer.c1338
1 files changed, 1338 insertions, 0 deletions
diff --git a/src/ui/theme-viewer.c b/src/ui/theme-viewer.c
new file mode 100644
index 00000000..c4a1fcd6
--- /dev/null
+++ b/src/ui/theme-viewer.c
@@ -0,0 +1,1338 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* Marco theme viewer and test app main() */
+
+/*
+ * Copyright (C) 2002 Havoc Pennington
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "util.h"
+#include "theme.h"
+#include "theme-parser.h"
+#include "preview-widget.h"
+#include <gtk/gtk.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libintl.h>
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+
+/* We need to compute all different button arrangements
+ * in terms of button location. We don't care about
+ * different arrangements in terms of button function.
+ *
+ * So if dups are allowed, from 0-4 buttons on the left, from 0-4 on
+ * the right, 5x5=25 combinations.
+ *
+ * If no dups, 0-4 on left determines the number on the right plus
+ * we have a special case for the "no buttons on either side" case.
+ */
+#ifndef ALLOW_DUPLICATE_BUTTONS
+#define BUTTON_LAYOUT_COMBINATIONS (MAX_BUTTONS_PER_CORNER + 1 + 1)
+#else
+#define BUTTON_LAYOUT_COMBINATIONS ((MAX_BUTTONS_PER_CORNER+1)*(MAX_BUTTONS_PER_CORNER+1))
+#endif
+
+enum
+{
+ FONT_SIZE_SMALL,
+ FONT_SIZE_NORMAL,
+ FONT_SIZE_LARGE,
+ FONT_SIZE_LAST
+};
+
+static MetaTheme *global_theme = NULL;
+static GtkWidget *previews[META_FRAME_TYPE_LAST*FONT_SIZE_LAST + BUTTON_LAYOUT_COMBINATIONS] = { NULL, };
+static double milliseconds_to_draw_frame = 0.0;
+
+static void run_position_expression_tests (void);
+#if 0
+static void run_position_expression_timings (void);
+#endif
+static void run_theme_benchmark (void);
+
+
+static GtkItemFactoryEntry menu_items[] =
+{
+ { N_("/_Windows"), NULL, NULL, 0, "<Branch>" },
+ { N_("/Windows/tearoff"), NULL, NULL, 0, "<Tearoff>" },
+ { N_("/Windows/_Dialog"), "<control>d", NULL, 0, NULL },
+ { N_("/Windows/_Modal dialog"), NULL, NULL, 0, NULL },
+ { N_("/Windows/_Utility"), "<control>u", NULL, 0, NULL },
+ { N_("/Windows/_Splashscreen"), "<control>s", NULL, 0, NULL },
+ { N_("/Windows/_Top dock"), NULL, NULL, 0, NULL },
+ { N_("/Windows/_Bottom dock"), NULL, NULL, 0, NULL },
+ { N_("/Windows/_Left dock"), NULL, NULL, 0, NULL },
+ { N_("/Windows/_Right dock"), NULL, NULL, 0, NULL },
+ { N_("/Windows/_All docks"), NULL, NULL, 0, NULL },
+ { N_("/Windows/Des_ktop"), NULL, NULL, 0, NULL }
+};
+
+static GtkWidget *
+normal_contents (void)
+{
+ GtkWidget *table;
+ GtkWidget *toolbar;
+ GtkWidget *handlebox;
+ GtkWidget *statusbar;
+ GtkWidget *contents;
+ GtkWidget *sw;
+ GtkItemFactory *item_factory;
+
+ table = gtk_table_new (1, 4, FALSE);
+
+ /* Create the menubar
+ */
+
+ item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", NULL);
+
+ gtk_item_factory_set_translate_func(item_factory,
+ (GtkTranslateFunc)gettext, NULL, NULL);
+
+ /* Set up item factory to go away */
+ g_object_ref (item_factory);
+ g_object_ref_sink (item_factory);
+ g_object_unref (item_factory);
+ g_object_set_data_full (G_OBJECT (table),
+ "<main>",
+ item_factory,
+ (GDestroyNotify) g_object_unref);
+
+ /* create menu items */
+ gtk_item_factory_create_items (item_factory, G_N_ELEMENTS (menu_items),
+ menu_items, NULL);
+
+ gtk_table_attach (GTK_TABLE (table),
+ gtk_item_factory_get_widget (item_factory, "<main>"),
+ /* X direction */ /* Y direction */
+ 0, 1, 0, 1,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ /* Create the toolbar
+ */
+ toolbar = gtk_toolbar_new ();
+
+ GtkToolItem *newButton = gtk_tool_button_new_from_stock(GTK_STOCK_NEW);
+ gtk_tool_item_set_tooltip_text(newButton,
+ "Open another one of these windows");
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ newButton,
+ -1); /*-1 means append to end of toolbar*/
+
+ GtkToolItem *openButton = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
+ gtk_tool_item_set_tooltip_text(openButton,
+ "This is a demo button with an \'open\' icon");
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ openButton,
+ -1); /*-1 means append to end of toolbar*/
+
+ GtkToolItem *quitButton = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
+ gtk_tool_item_set_tooltip_text(quitButton,
+ "This is a demo button with a \'quit\' icon");
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ quitButton,
+ -1); /*-1 means append to end of toolbar*/
+
+
+ handlebox = gtk_handle_box_new ();
+
+ gtk_container_add (GTK_CONTAINER (handlebox), toolbar);
+
+ gtk_table_attach (GTK_TABLE (table),
+ handlebox,
+ /* X direction */ /* Y direction */
+ 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ /* Create document
+ */
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+ GTK_SHADOW_IN);
+
+ gtk_table_attach (GTK_TABLE (table),
+ sw,
+ /* X direction */ /* Y direction */
+ 0, 1, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
+ 0, 0);
+
+ contents = gtk_text_view_new ();
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (contents),
+ PANGO_WRAP_WORD);
+
+ gtk_container_add (GTK_CONTAINER (sw),
+ contents);
+
+ /* Create statusbar */
+
+ statusbar = gtk_statusbar_new ();
+ gtk_table_attach (GTK_TABLE (table),
+ statusbar,
+ /* X direction */ /* Y direction */
+ 0, 1, 3, 4,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+
+ gtk_widget_show_all (table);
+
+ return table;
+}
+
+static void
+update_spacings (GtkWidget *vbox,
+ GtkWidget *action_area)
+{
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
+ gtk_box_set_spacing (GTK_BOX (action_area), 10);
+ gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
+}
+
+static GtkWidget*
+dialog_contents (void)
+{
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *action_area;
+ GtkWidget *label;
+ GtkWidget *image;
+ GtkWidget *button;
+
+ vbox = gtk_vbox_new (FALSE, 0);
+
+ action_area = gtk_hbutton_box_new ();
+
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (action_area),
+ GTK_BUTTONBOX_END);
+
+ button = gtk_button_new_from_stock (GTK_STOCK_OK);
+ gtk_box_pack_end (GTK_BOX (action_area),
+ button,
+ FALSE, TRUE, 0);
+
+ gtk_box_pack_end (GTK_BOX (vbox), action_area,
+ FALSE, TRUE, 0);
+
+ update_spacings (vbox, action_area);
+
+ label = gtk_label_new (_("This is a sample message in a sample dialog"));
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+
+ gtk_box_pack_start (GTK_BOX (hbox), image,
+ FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (hbox), label,
+ TRUE, TRUE, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox),
+ hbox,
+ FALSE, FALSE, 0);
+
+ gtk_widget_show_all (vbox);
+
+ return vbox;
+}
+
+static GtkWidget*
+utility_contents (void)
+{
+ GtkWidget *table;
+ GtkWidget *button;
+ int i, j;
+
+ table = gtk_table_new (3, 4, FALSE);
+
+ i = 0;
+ while (i < 3)
+ {
+ j = 0;
+ while (j < 4)
+ {
+ char *str;
+
+ str = g_strdup_printf ("_%c", (char) ('A' + 4*i + j));
+
+ button = gtk_button_new_with_mnemonic (str);
+
+ g_free (str);
+
+ gtk_table_attach (GTK_TABLE (table),
+ button,
+ /* X direction */ /* Y direction */
+ i, i+1, j, j+1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
+ 0, 0);
+
+ ++j;
+ }
+
+ ++i;
+ }
+
+ gtk_widget_show_all (table);
+
+ return table;
+}
+
+static GtkWidget*
+menu_contents (void)
+{
+ GtkWidget *vbox;
+ GtkWidget *mi;
+ int i;
+ GtkWidget *frame;
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame),
+ GTK_SHADOW_OUT);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+
+ i = 0;
+ while (i < 10)
+ {
+ char *str = g_strdup_printf (_("Fake menu item %d\n"), i + 1);
+ mi = gtk_label_new (str);
+ gtk_misc_set_alignment (GTK_MISC (mi), 0.0, 0.5);
+ g_free (str);
+ gtk_box_pack_start (GTK_BOX (vbox), mi, FALSE, FALSE, 0);
+
+ ++i;
+ }
+
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+
+ gtk_widget_show_all (frame);
+
+ return frame;
+}
+
+static GtkWidget*
+border_only_contents (void)
+{
+ GtkWidget *event_box;
+ GtkWidget *vbox;
+ GtkWidget *w;
+ GdkColor color;
+
+ event_box = gtk_event_box_new ();
+
+ color.red = 40000;
+ color.green = 0;
+ color.blue = 40000;
+ gtk_widget_modify_bg (event_box, GTK_STATE_NORMAL, &color);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
+
+ w = gtk_label_new (_("Border-only window"));
+ gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
+ w = gtk_button_new_with_label (_("Bar"));
+ gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
+
+ gtk_container_add (GTK_CONTAINER (event_box), vbox);
+
+ gtk_widget_show_all (event_box);
+
+ return event_box;
+}
+
+static GtkWidget*
+get_window_contents (MetaFrameType type,
+ const char **title)
+{
+ switch (type)
+ {
+ case META_FRAME_TYPE_NORMAL:
+ *title = _("Normal Application Window");
+ return normal_contents ();
+
+ case META_FRAME_TYPE_DIALOG:
+ *title = _("Dialog Box");
+ return dialog_contents ();
+
+ case META_FRAME_TYPE_MODAL_DIALOG:
+ *title = _("Modal Dialog Box");
+ return dialog_contents ();
+
+ case META_FRAME_TYPE_UTILITY:
+ *title = _("Utility Palette");
+ return utility_contents ();
+
+ case META_FRAME_TYPE_MENU:
+ *title = _("Torn-off Menu");
+ return menu_contents ();
+
+ case META_FRAME_TYPE_BORDER:
+ *title = _("Border");
+ return border_only_contents ();
+
+ case META_FRAME_TYPE_LAST:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return NULL;
+}
+
+static MetaFrameFlags
+get_window_flags (MetaFrameType type)
+{
+ MetaFrameFlags flags;
+
+ flags = META_FRAME_ALLOWS_DELETE |
+ META_FRAME_ALLOWS_MENU |
+ META_FRAME_ALLOWS_MINIMIZE |
+ META_FRAME_ALLOWS_MAXIMIZE |
+ META_FRAME_ALLOWS_VERTICAL_RESIZE |
+ META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
+ META_FRAME_HAS_FOCUS |
+ META_FRAME_ALLOWS_SHADE |
+ META_FRAME_ALLOWS_MOVE;
+
+ switch (type)
+ {
+ case META_FRAME_TYPE_NORMAL:
+ break;
+
+ case META_FRAME_TYPE_DIALOG:
+ case META_FRAME_TYPE_MODAL_DIALOG:
+ flags &= ~(META_FRAME_ALLOWS_MINIMIZE |
+ META_FRAME_ALLOWS_MAXIMIZE);
+ break;
+
+ case META_FRAME_TYPE_UTILITY:
+ flags &= ~(META_FRAME_ALLOWS_MINIMIZE |
+ META_FRAME_ALLOWS_MAXIMIZE);
+ break;
+
+ case META_FRAME_TYPE_MENU:
+ flags &= ~(META_FRAME_ALLOWS_MINIMIZE |
+ META_FRAME_ALLOWS_MAXIMIZE);
+ break;
+
+ case META_FRAME_TYPE_BORDER:
+ break;
+
+ case META_FRAME_TYPE_LAST:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return flags;
+}
+
+static GtkWidget*
+preview_collection (int font_size,
+ PangoFontDescription *base_desc)
+{
+ GtkWidget *box;
+ GtkWidget *sw;
+ GdkColor desktop_color;
+ int i;
+ GtkWidget *eventbox;
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+
+ box = gtk_vbox_new (FALSE, 0);
+ gtk_box_set_spacing (GTK_BOX (box), 20);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 20);
+
+ eventbox = gtk_event_box_new ();
+ gtk_container_add (GTK_CONTAINER (eventbox), box);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), eventbox);
+
+ desktop_color.red = 0x5144;
+ desktop_color.green = 0x75D6;
+ desktop_color.blue = 0xA699;
+
+ gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &desktop_color);
+
+ i = 0;
+ while (i < META_FRAME_TYPE_LAST)
+ {
+ const char *title = NULL;
+ GtkWidget *contents;
+ GtkWidget *align;
+ double xalign, yalign;
+ GtkWidget *eventbox2;
+ GtkWidget *preview;
+ PangoFontDescription *font_desc;
+ double scale;
+
+ eventbox2 = gtk_event_box_new ();
+
+ preview = meta_preview_new ();
+
+ gtk_container_add (GTK_CONTAINER (eventbox2), preview);
+
+ meta_preview_set_frame_type (META_PREVIEW (preview), i);
+ meta_preview_set_frame_flags (META_PREVIEW (preview),
+ get_window_flags (i));
+
+ meta_preview_set_theme (META_PREVIEW (preview), global_theme);
+
+ contents = get_window_contents (i, &title);
+
+ meta_preview_set_title (META_PREVIEW (preview), title);
+
+ gtk_container_add (GTK_CONTAINER (preview), contents);
+
+ if (i == META_FRAME_TYPE_MENU)
+ {
+ xalign = 0.0;
+ yalign = 0.0;
+ }
+ else
+ {
+ xalign = 0.5;
+ yalign = 0.5;
+ }
+
+ align = gtk_alignment_new (0.0, 0.0, xalign, yalign);
+ gtk_container_add (GTK_CONTAINER (align), eventbox2);
+
+ gtk_box_pack_start (GTK_BOX (box), align, TRUE, TRUE, 0);
+
+ switch (font_size)
+ {
+ case FONT_SIZE_SMALL:
+ scale = PANGO_SCALE_XX_SMALL;
+ break;
+ case FONT_SIZE_LARGE:
+ scale = PANGO_SCALE_XX_LARGE;
+ break;
+ default:
+ scale = 1.0;
+ break;
+ }
+
+ if (scale != 1.0)
+ {
+ font_desc = pango_font_description_new ();
+
+ pango_font_description_set_size (font_desc,
+ MAX (pango_font_description_get_size (base_desc) * scale, 1));
+
+ gtk_widget_modify_font (preview, font_desc);
+
+ pango_font_description_free (font_desc);
+ }
+
+ previews[font_size*META_FRAME_TYPE_LAST + i] = preview;
+
+ ++i;
+ }
+
+ return sw;
+}
+
+static MetaButtonLayout different_layouts[BUTTON_LAYOUT_COMBINATIONS];
+
+static void
+init_layouts (void)
+{
+ int i;
+
+ /* Blank out all the layouts */
+ i = 0;
+ while (i < (int) G_N_ELEMENTS (different_layouts))
+ {
+ int j;
+
+ j = 0;
+ while (j < MAX_BUTTONS_PER_CORNER)
+ {
+ different_layouts[i].left_buttons[j] = META_BUTTON_FUNCTION_LAST;
+ different_layouts[i].right_buttons[j] = META_BUTTON_FUNCTION_LAST;
+ ++j;
+ }
+ ++i;
+ }
+
+#ifndef ALLOW_DUPLICATE_BUTTONS
+ i = 0;
+ while (i <= MAX_BUTTONS_PER_CORNER)
+ {
+ int j;
+
+ j = 0;
+ while (j < i)
+ {
+ different_layouts[i].right_buttons[j] = (MetaButtonFunction) j;
+ ++j;
+ }
+ while (j < MAX_BUTTONS_PER_CORNER)
+ {
+ different_layouts[i].left_buttons[j-i] = (MetaButtonFunction) j;
+ ++j;
+ }
+
+ ++i;
+ }
+
+ /* Special extra case for no buttons on either side */
+ different_layouts[i].left_buttons[0] = META_BUTTON_FUNCTION_LAST;
+ different_layouts[i].right_buttons[0] = META_BUTTON_FUNCTION_LAST;
+
+#else
+ /* FIXME this code is if we allow duplicate buttons,
+ * which we currently do not
+ */
+ int left;
+ int i;
+
+ left = 0;
+ i = 0;
+
+ while (left < MAX_BUTTONS_PER_CORNER)
+ {
+ int right;
+
+ right = 0;
+
+ while (right < MAX_BUTTONS_PER_CORNER)
+ {
+ int j;
+
+ static MetaButtonFunction left_functions[MAX_BUTTONS_PER_CORNER] = {
+ META_BUTTON_FUNCTION_MENU,
+ META_BUTTON_FUNCTION_MINIMIZE,
+ META_BUTTON_FUNCTION_MAXIMIZE,
+ META_BUTTON_FUNCTION_CLOSE
+ };
+ static MetaButtonFunction right_functions[MAX_BUTTONS_PER_CORNER] = {
+ META_BUTTON_FUNCTION_MINIMIZE,
+ META_BUTTON_FUNCTION_MAXIMIZE,
+ META_BUTTON_FUNCTION_CLOSE,
+ META_BUTTON_FUNCTION_MENU
+ };
+
+ g_assert (i < BUTTON_LAYOUT_COMBINATIONS);
+
+ j = 0;
+ while (j <= left)
+ {
+ different_layouts[i].left_buttons[j] = left_functions[j];
+ ++j;
+ }
+
+ j = 0;
+ while (j <= right)
+ {
+ different_layouts[i].right_buttons[j] = right_functions[j];
+ ++j;
+ }
+
+ ++i;
+
+ ++right;
+ }
+
+ ++left;
+ }
+#endif
+}
+
+
+static GtkWidget*
+previews_of_button_layouts (void)
+{
+ static gboolean initted = FALSE;
+ GtkWidget *box;
+ GtkWidget *sw;
+ GdkColor desktop_color;
+ int i;
+ GtkWidget *eventbox;
+
+ if (!initted)
+ {
+ init_layouts ();
+ initted = TRUE;
+ }
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+
+ box = gtk_vbox_new (FALSE, 0);
+ gtk_box_set_spacing (GTK_BOX (box), 20);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 20);
+
+ eventbox = gtk_event_box_new ();
+ gtk_container_add (GTK_CONTAINER (eventbox), box);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), eventbox);
+
+ desktop_color.red = 0x5144;
+ desktop_color.green = 0x75D6;
+ desktop_color.blue = 0xA699;
+
+ gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &desktop_color);
+
+ i = 0;
+ while (i < BUTTON_LAYOUT_COMBINATIONS)
+ {
+ GtkWidget *align;
+ double xalign, yalign;
+ GtkWidget *eventbox2;
+ GtkWidget *preview;
+ char *title;
+
+ eventbox2 = gtk_event_box_new ();
+
+ preview = meta_preview_new ();
+
+ gtk_container_add (GTK_CONTAINER (eventbox2), preview);
+
+ meta_preview_set_theme (META_PREVIEW (preview), global_theme);
+
+ title = g_strdup_printf (_("Button layout test %d"), i+1);
+ meta_preview_set_title (META_PREVIEW (preview), title);
+ g_free (title);
+
+ meta_preview_set_button_layout (META_PREVIEW (preview),
+ &different_layouts[i]);
+
+ xalign = 0.5;
+ yalign = 0.5;
+
+ align = gtk_alignment_new (0.0, 0.0, xalign, yalign);
+ gtk_container_add (GTK_CONTAINER (align), eventbox2);
+
+ gtk_box_pack_start (GTK_BOX (box), align, TRUE, TRUE, 0);
+
+ previews[META_FRAME_TYPE_LAST*FONT_SIZE_LAST + i] = preview;
+
+ ++i;
+ }
+
+ return sw;
+}
+
+static GtkWidget*
+benchmark_summary (void)
+{
+ char *msg;
+ GtkWidget *label;
+
+ msg = g_strdup_printf (_("%g milliseconds to draw one window frame"),
+ milliseconds_to_draw_frame);
+ label = gtk_label_new (msg);
+ g_free (msg);
+
+ return label;
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window;
+ GtkWidget *collection;
+ GError *err;
+ clock_t start, end;
+ GtkWidget *notebook;
+ int i;
+
+ bindtextdomain (GETTEXT_PACKAGE, MARCO_LOCALEDIR);
+ textdomain(GETTEXT_PACKAGE);
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+
+ run_position_expression_tests ();
+#if 0
+ run_position_expression_timings ();
+#endif
+
+ gtk_init (&argc, &argv);
+
+ if (g_getenv ("MARCO_DEBUG") != NULL)
+ {
+ meta_set_debugging (TRUE);
+ meta_set_verbose (TRUE);
+ }
+
+ start = clock ();
+ err = NULL;
+ if (argc == 1)
+ global_theme = meta_theme_load ("ClearlooksRe", &err);
+ else if (argc == 2)
+ global_theme = meta_theme_load (argv[1], &err);
+ else
+ {
+ g_printerr (_("Usage: marco-theme-viewer [THEMENAME]\n"));
+ exit (1);
+ }
+ end = clock ();
+
+ if (global_theme == NULL)
+ {
+ g_printerr (_("Error loading theme: %s\n"),
+ err->message);
+ g_error_free (err);
+ exit (1);
+ }
+
+ g_print (_("Loaded theme \"%s\" in %g seconds\n"),
+ global_theme->name,
+ (end - start) / (double) CLOCKS_PER_SEC);
+
+ run_theme_benchmark ();
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 350, 350);
+
+ if (strcmp (global_theme->name, global_theme->readable_name)==0)
+ gtk_window_set_title (GTK_WINDOW (window),
+ global_theme->readable_name);
+ else
+ {
+ /* The theme directory name is different from the name the theme
+ * gives itself within its file. Display both, directory name first.
+ */
+ gchar *title = g_strconcat (global_theme->name, " - ",
+ global_theme->readable_name,
+ NULL);
+
+ gtk_window_set_title (GTK_WINDOW (window),
+ title);
+
+ g_free (title);
+ }
+
+ g_signal_connect (G_OBJECT (window), "destroy",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ gtk_widget_realize (window);
+ g_assert (window->style);
+ g_assert (window->style->font_desc);
+
+ notebook = gtk_notebook_new ();
+ gtk_container_add (GTK_CONTAINER (window), notebook);
+
+ collection = preview_collection (FONT_SIZE_NORMAL,
+ window->style->font_desc);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
+ collection,
+ gtk_label_new (_("Normal Title Font")));
+
+ collection = preview_collection (FONT_SIZE_SMALL,
+ window->style->font_desc);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
+ collection,
+ gtk_label_new (_("Small Title Font")));
+
+ collection = preview_collection (FONT_SIZE_LARGE,
+ window->style->font_desc);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
+ collection,
+ gtk_label_new (_("Large Title Font")));
+
+ collection = previews_of_button_layouts ();
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
+ collection,
+ gtk_label_new (_("Button Layouts")));
+
+ collection = benchmark_summary ();
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
+ collection,
+ gtk_label_new (_("Benchmark")));
+
+ i = 0;
+ while (i < (int) G_N_ELEMENTS (previews))
+ {
+ /* preview widget likes to be realized before its size request.
+ * it's lame that way.
+ */
+ gtk_widget_realize (previews[i]);
+
+ ++i;
+ }
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}
+
+
+static MetaFrameFlags
+get_flags (GtkWidget *widget)
+{
+ return META_FRAME_ALLOWS_DELETE |
+ META_FRAME_ALLOWS_MENU |
+ META_FRAME_ALLOWS_MINIMIZE |
+ META_FRAME_ALLOWS_MAXIMIZE |
+ META_FRAME_ALLOWS_VERTICAL_RESIZE |
+ META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
+ META_FRAME_HAS_FOCUS |
+ META_FRAME_ALLOWS_SHADE |
+ META_FRAME_ALLOWS_MOVE;
+}
+
+static int
+get_text_height (GtkWidget *widget)
+{
+ return meta_pango_font_desc_get_text_height (widget->style->font_desc,
+ gtk_widget_get_pango_context (widget));
+}
+
+static PangoLayout*
+create_title_layout (GtkWidget *widget)
+{
+ PangoLayout *layout;
+
+ layout = gtk_widget_create_pango_layout (widget, _("Window Title Goes Here"));
+
+ return layout;
+}
+
+static void
+run_theme_benchmark (void)
+{
+ GtkWidget* widget;
+ GdkPixmap *pixmap;
+ int top_height, bottom_height, left_width, right_width;
+ MetaButtonState button_states[META_BUTTON_TYPE_LAST] =
+ {
+ META_BUTTON_STATE_NORMAL,
+ META_BUTTON_STATE_NORMAL,
+ META_BUTTON_STATE_NORMAL,
+ META_BUTTON_STATE_NORMAL
+ };
+ PangoLayout *layout;
+ clock_t start;
+ clock_t end;
+ GTimer *timer;
+ int i;
+ MetaButtonLayout button_layout;
+#define ITERATIONS 100
+ int client_width;
+ int client_height;
+ int inc;
+
+ widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_realize (widget);
+
+ meta_theme_get_frame_borders (global_theme,
+ META_FRAME_TYPE_NORMAL,
+ get_text_height (widget),
+ get_flags (widget),
+ &top_height,
+ &bottom_height,
+ &left_width,
+ &right_width);
+
+ layout = create_title_layout (widget);
+
+ i = 0;
+ while (i < MAX_BUTTONS_PER_CORNER)
+ {
+ button_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
+ button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
+ ++i;
+ }
+
+ button_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU;
+
+ button_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE;
+ button_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE;
+ button_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
+
+ timer = g_timer_new ();
+ start = clock ();
+
+ client_width = 50;
+ client_height = 50;
+ inc = 1000 / ITERATIONS; /* Increment to grow width/height,
+ * eliminates caching effects.
+ */
+
+ i = 0;
+ while (i < ITERATIONS)
+ {
+ /* Creating the pixmap in the loop is right, since
+ * GDK does the same with its double buffering.
+ */
+ pixmap = gdk_pixmap_new (widget->window,
+ client_width + left_width + right_width,
+ client_height + top_height + bottom_height,
+ -1);
+
+ meta_theme_draw_frame (global_theme,
+ widget,
+ pixmap,
+ NULL,
+ 0, 0,
+ META_FRAME_TYPE_NORMAL,
+ get_flags (widget),
+ client_width, client_height,
+ layout,
+ get_text_height (widget),
+ &button_layout,
+ button_states,
+ meta_preview_get_mini_icon (),
+ meta_preview_get_icon ());
+
+ g_object_unref (G_OBJECT (pixmap));
+
+ ++i;
+ client_width += inc;
+ client_height += inc;
+ }
+
+ end = clock ();
+ g_timer_stop (timer);
+
+ milliseconds_to_draw_frame = (g_timer_elapsed (timer, NULL) / (double) ITERATIONS) * 1000;
+
+ g_print (_("Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g seconds wall clock time including X server resources (%g milliseconds per frame)\n"),
+ ITERATIONS,
+ ((double)end - (double)start) / CLOCKS_PER_SEC,
+ (((double)end - (double)start) / CLOCKS_PER_SEC / (double) ITERATIONS) * 1000,
+ g_timer_elapsed (timer, NULL),
+ milliseconds_to_draw_frame);
+
+ g_timer_destroy (timer);
+ g_object_unref (G_OBJECT (layout));
+ gtk_widget_destroy (widget);
+
+#undef ITERATIONS
+}
+
+typedef struct
+{
+ GdkRectangle rect;
+ const char *expr;
+ int expected_x;
+ int expected_y;
+ MetaThemeError expected_error;
+} PositionExpressionTest;
+
+#define NO_ERROR -1
+
+static const PositionExpressionTest position_expression_tests[] = {
+ /* Just numbers */
+ { { 10, 20, 40, 50 },
+ "10", 20, 30, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14.37", 24, 34, NO_ERROR },
+ /* Binary expressions with 2 ints */
+ { { 10, 20, 40, 50 },
+ "14 * 10", 150, 160, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14 + 10", 34, 44, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14 - 10", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8 / 2", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8 % 3", 12, 22, NO_ERROR },
+ /* Binary expressions with floats and mixed float/ints */
+ { { 10, 20, 40, 50 },
+ "7.0 / 3.5", 12, 22, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "12.1 / 3", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "12 / 2.95", 14, 24, NO_ERROR },
+ /* Binary expressions without whitespace after first number */
+ { { 10, 20, 40, 50 },
+ "14* 10", 150, 160, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14+ 10", 34, 44, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14- 10", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8/ 2", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "7.0/ 3.5", 12, 22, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "12.1/ 3", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "12/ 2.95", 14, 24, NO_ERROR },
+ /* Binary expressions without whitespace before second number */
+ { { 10, 20, 40, 50 },
+ "14 *10", 150, 160, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14 +10", 34, 44, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14 -10", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8 /2", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "7.0 /3.5", 12, 22, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "12.1 /3", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "12 /2.95", 14, 24, NO_ERROR },
+ /* Binary expressions without any whitespace */
+ { { 10, 20, 40, 50 },
+ "14*10", 150, 160, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14+10", 34, 44, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14-10", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8/2", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "7.0/3.5", 12, 22, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "12.1/3", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "12/2.95", 14, 24, NO_ERROR },
+ /* Binary expressions with parentheses */
+ { { 10, 20, 40, 50 },
+ "(14) * (10)", 150, 160, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "(14) + (10)", 34, 44, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "(14) - (10)", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "(8) / (2)", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "(7.0) / (3.5)", 12, 22, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "(12.1) / (3)", 14, 24, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "(12) / (2.95)", 14, 24, NO_ERROR },
+ /* Lots of extra parentheses */
+ { { 10, 20, 40, 50 },
+ "(((14)) * ((10)))", 150, 160, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "((((14)))) + ((((((((10))))))))", 34, 44, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "((((((((((14 - 10))))))))))", 14, 24, NO_ERROR },
+ /* Binary expressions with variables */
+ { { 10, 20, 40, 50 },
+ "2 * width", 90, 100, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "2 * height", 110, 120, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "width - 10", 40, 50, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "height / 2", 35, 45, NO_ERROR },
+ /* More than two operands */
+ { { 10, 20, 40, 50 },
+ "8 / 2 + 5", 19, 29, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8 * 2 + 5", 31, 41, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8 + 2 * 5", 28, 38, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8 + 8 / 2", 22, 32, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "14 / (2 + 5)", 12, 22, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "8 * (2 + 5)", 66, 76, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "(8 + 2) * 5", 60, 70, NO_ERROR },
+ { { 10, 20, 40, 50 },
+ "(8 + 8) / 2", 18, 28, NO_ERROR },
+ /* Errors */
+ { { 10, 20, 40, 50 },
+ "2 * foo", 0, 0, META_THEME_ERROR_UNKNOWN_VARIABLE },
+ { { 10, 20, 40, 50 },
+ "2 *", 0, 0, META_THEME_ERROR_FAILED },
+ { { 10, 20, 40, 50 },
+ "- width", 0, 0, META_THEME_ERROR_FAILED },
+ { { 10, 20, 40, 50 },
+ "5 % 1.0", 0, 0, META_THEME_ERROR_MOD_ON_FLOAT },
+ { { 10, 20, 40, 50 },
+ "1.0 % 5", 0, 0, META_THEME_ERROR_MOD_ON_FLOAT },
+ { { 10, 20, 40, 50 },
+ "! * 2", 0, 0, META_THEME_ERROR_BAD_CHARACTER },
+ { { 10, 20, 40, 50 },
+ " ", 0, 0, META_THEME_ERROR_FAILED },
+ { { 10, 20, 40, 50 },
+ "() () (( ) ()) ((()))", 0, 0, META_THEME_ERROR_FAILED },
+ { { 10, 20, 40, 50 },
+ "(*) () ((/) ()) ((()))", 0, 0, META_THEME_ERROR_FAILED },
+ { { 10, 20, 40, 50 },
+ "2 * 5 /", 0, 0, META_THEME_ERROR_FAILED },
+ { { 10, 20, 40, 50 },
+ "+ 2 * 5", 0, 0, META_THEME_ERROR_FAILED },
+ { { 10, 20, 40, 50 },
+ "+ 2 * 5", 0, 0, META_THEME_ERROR_FAILED }
+};
+
+static void
+run_position_expression_tests (void)
+{
+#if 0
+ int i;
+ MetaPositionExprEnv env;
+
+ i = 0;
+ while (i < (int) G_N_ELEMENTS (position_expression_tests))
+ {
+ GError *err;
+ gboolean retval;
+ const PositionExpressionTest *test;
+ PosToken *tokens;
+ int n_tokens;
+ int x, y;
+
+ test = &position_expression_tests[i];
+
+ if (g_getenv ("META_PRINT_TESTS") != NULL)
+ g_print ("Test expression: \"%s\" expecting x = %d y = %d",
+ test->expr, test->expected_x, test->expected_y);
+
+ err = NULL;
+
+ env.rect = meta_rect (test->rect.x, test->rect.y,
+ test->rect.width, test->rect.height);
+ env.object_width = -1;
+ env.object_height = -1;
+ env.left_width = 0;
+ env.right_width = 0;
+ env.top_height = 0;
+ env.bottom_height = 0;
+ env.title_width = 5;
+ env.title_height = 5;
+ env.icon_width = 32;
+ env.icon_height = 32;
+ env.mini_icon_width = 16;
+ env.mini_icon_height = 16;
+ env.theme = NULL;
+
+ if (err == NULL)
+ {
+ retval = meta_parse_position_expression (tokens, n_tokens,
+ &env,
+ &x, &y,
+ &err);
+ }
+
+ if (retval && err)
+ g_error (_("position expression test returned TRUE but set error"));
+ if (!retval && err == NULL)
+ g_error (_("position expression test returned FALSE but didn't set error"));
+ if (((int) test->expected_error) != NO_ERROR)
+ {
+ if (err == NULL)
+ g_error (_("Error was expected but none given"));
+ if (err->code != (int) test->expected_error)
+ g_error (_("Error %d was expected but %d given"),
+ test->expected_error, err->code);
+ }
+ else
+ {
+ if (err)
+ g_error (_("Error not expected but one was returned: %s"),
+ err->message);
+
+ if (x != test->expected_x)
+ g_error (_("x value was %d, %d was expected"), x, test->expected_x);
+
+ if (y != test->expected_y)
+ g_error (_("y value was %d, %d was expected"), y, test->expected_y);
+ }
+
+ if (err)
+ g_error_free (err);
+
+ meta_pos_tokens_free (tokens, n_tokens);
+ ++i;
+ }
+#endif
+}
+
+#if 0
+static void
+run_position_expression_timings (void)
+{
+ int i;
+ int iters;
+ clock_t start;
+ clock_t end;
+ MetaPositionExprEnv env;
+
+#define ITERATIONS 100000
+
+ start = clock ();
+
+ iters = 0;
+ i = 0;
+ while (iters < ITERATIONS)
+ {
+ const PositionExpressionTest *test;
+ int x, y;
+
+ test = &position_expression_tests[i];
+
+ env.x = test->rect.x;
+ env.y = test->rect.y;
+ env.width = test->rect.width;
+ env.height = test->rect.height;
+ env.object_width = -1;
+ env.object_height = -1;
+ env.left_width = 0;
+ env.right_width = 0;
+ env.top_height = 0;
+ env.bottom_height = 0;
+ env.title_width = 5;
+ env.title_height = 5;
+ env.icon_width = 32;
+ env.icon_height = 32;
+ env.mini_icon_width = 16;
+ env.mini_icon_height = 16;
+ env.theme = NULL;
+
+ meta_parse_position_expression (test->expr,
+ &env,
+ &x, &y, NULL);
+
+ ++iters;
+ ++i;
+ if (i == G_N_ELEMENTS (position_expression_tests))
+ i = 0;
+ }
+
+ end = clock ();
+
+ g_print (_("%d coordinate expressions parsed in %g seconds (%g seconds average)\n"),
+ ITERATIONS,
+ ((double)end - (double)start) / CLOCKS_PER_SEC,
+ ((double)end - (double)start) / CLOCKS_PER_SEC / (double) ITERATIONS);
+
+}
+#endif