Author: jannis Date: 2007-03-18 02:23:12 +0000 (Sun, 18 Mar 2007) New Revision: 25185
Added: libfrap/trunk/libfrap/menu/frap-menu-layout.c libfrap/trunk/libfrap/menu/frap-menu-layout.h libfrap/trunk/libfrap/menu/frap-menu-separator.c libfrap/trunk/libfrap/menu/frap-menu-separator.h Modified: libfrap/trunk/libfrap/menu/ChangeLog libfrap/trunk/libfrap/menu/Makefile.am libfrap/trunk/libfrap/menu/STATUS libfrap/trunk/libfrap/menu/frap-menu.c libfrap/trunk/libfrap/menu/frap-menu.h libfrap/trunk/libfrap/menu/libfrapmenu.h libfrap/trunk/libfrap/menu/tests/test-display-root-menu.c Log: * frap-menu-layout.{c,h}: FrapMenuLayout added. It only supports <Filename>, <Separator> and <Merge> elements currently. * frap-menu-separator.{c,h}: FrapMenuSeparator added. This is a singleton to be inserted into the GSList returned by frap_menu_get_layout_items() whenever a separator is required. * frap-menu.{c,h}: Implement parsing of <Layout>, <Separator> and <Merge> elements. Add layout member to the FrapMenu struct. Add method to fetch all items based on the layout: frap_menu_get_layout_items(). Call _frap_menu_separator_init() in frap_menu_init() and _frap_menu_separator_shutdown() in frap_menu_shutdown(). Check filename != NULL in frap_menu_new(). * libfrapmenu.h: Add separator and layout to the main header. * tests/test-display-root-menu.c: Use frap_menu_get_layout_items() instead of frap_menu_get_items(). * Makefile.am: Add separator and layout sources. * STATUS: Status updated. Modified: libfrap/trunk/libfrap/menu/ChangeLog =================================================================== --- libfrap/trunk/libfrap/menu/ChangeLog 2007-03-17 22:54:06 UTC (rev 25184) +++ libfrap/trunk/libfrap/menu/ChangeLog 2007-03-18 02:23:12 UTC (rev 25185) @@ -1,5 +1,25 @@ -2007-02-14 Janins Pohlmann <[EMAIL PROTECTED]> +2007-03-18 Jannis Pohlmann <[EMAIL PROTECTED]> + * frap-menu-layout.{c,h}: FrapMenuLayout added. It only supports + <Filename>, <Separator> and <Merge> elements currently. + * frap-menu-separator.{c,h}: FrapMenuSeparator added. This is a + singleton to be inserted into the GSList returned by + frap_menu_get_layout_items() whenever a separator is required. + * frap-menu.{c,h}: Implement parsing of <Layout>, <Separator> + and <Merge> elements. Add layout member to the FrapMenu struct. + Add method to fetch all items based on the layout: + frap_menu_get_layout_items(). Call _frap_menu_separator_init() + in frap_menu_init() and _frap_menu_separator_shutdown() in + frap_menu_shutdown(). Check filename != NULL in + frap_menu_new(). + * libfrapmenu.h: Add separator and layout to the main header. + * tests/test-display-root-menu.c: Use + frap_menu_get_layout_items() instead of frap_menu_get_items(). + * Makefile.am: Add separator and layout sources. + * STATUS: Status updated. + +2007-02-14 Jannis Pohlmann <[EMAIL PROTECTED]> + * STATUS: Menu spec test suite results added. * tests/test-display-root-menu.c: Fix warning caused by copying a string into a const gchar*. Modified: libfrap/trunk/libfrap/menu/Makefile.am =================================================================== --- libfrap/trunk/libfrap/menu/Makefile.am 2007-03-17 22:54:06 UTC (rev 25184) +++ libfrap/trunk/libfrap/menu/Makefile.am 2007-03-18 02:23:12 UTC (rev 25185) @@ -14,6 +14,8 @@ libfrapmenu_la_SOURCES = \ frap-menu.c \ + frap-menu-separator.c \ + frap-menu-layout.c \ frap-menu-directory.c \ frap-menu-rules.c \ frap-menu-standard-rules.c \ @@ -32,6 +34,8 @@ noinst_HEADERS = \ libfrapmenu.h \ frap-menu.h \ + frap-menu-separator.h \ + frap-menu-layout.h \ frap-menu-directory.h \ frap-menu-rules.h \ frap-menu-standard-rules.h \ Modified: libfrap/trunk/libfrap/menu/STATUS =================================================================== --- libfrap/trunk/libfrap/menu/STATUS 2007-03-17 22:54:06 UTC (rev 25184) +++ libfrap/trunk/libfrap/menu/STATUS 2007-03-18 02:23:12 UTC (rev 25185) @@ -84,15 +84,18 @@ [ ] <New> - [ ] <Layout> + [-] <Layout> + The <Layout> element is parsed including all children, but the + layout attributes are not handled yet. + [ ] <DefaultLayout> [ ] <Menuname> - [ ] <Separator> + [x] <Separator> - [ ] <Merge> + [x] <Merge> Added: libfrap/trunk/libfrap/menu/frap-menu-layout.c =================================================================== --- libfrap/trunk/libfrap/menu/frap-menu-layout.c (rev 0) +++ libfrap/trunk/libfrap/menu/frap-menu-layout.c 2007-03-18 02:23:12 UTC (rev 25185) @@ -0,0 +1,337 @@ +/* $Id$ */ +/* vi:set expandtab sw=2 sts=2: */ +/*- + * Copyright (c) 2007 Jannis Pohlmann <[EMAIL PROTECTED]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <frap-menu-layout.h> + + + +#define FRAP_MENU_LAYOUT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), FRAP_TYPE_MENU_LAYOUT, FrapMenuLayoutPrivate)) + + + +/* Property identifiers */ +enum +{ + PROP_0, +}; + + + +struct _FrapMenuLayoutNode +{ + FrapMenuLayoutNodeType type; + union + { + gchar *filename; + FrapMenuLayoutMergeType merge_type; + } data; +}; + + + +static void frap_menu_layout_class_init (FrapMenuLayoutClass *klass); +static void frap_menu_layout_init (FrapMenuLayout *layout); +static void frap_menu_layout_finalize (GObject *object); +static void frap_menu_layout_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void frap_menu_layout_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void frap_menu_layout_free_node (FrapMenuLayoutNode *node); + + + +struct _FrapMenuLayoutClass +{ + GObjectClass __parent__; +}; + +struct _FrapMenuLayoutPrivate +{ + GSList *nodes; +}; + +struct _FrapMenuLayout +{ + GObject __parent__; + + /* < private > */ + FrapMenuLayoutPrivate *priv; +}; + + + +static GObjectClass *frap_menu_layout_parent_class = NULL; + + + +GType +frap_menu_layout_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + static const GTypeInfo info = + { + sizeof (FrapMenuLayoutClass), + NULL, + NULL, + (GClassInitFunc) frap_menu_layout_class_init, + NULL, + NULL, + sizeof (FrapMenuLayout), + 0, + (GInstanceInitFunc) frap_menu_layout_init, + NULL, + }; + + type = g_type_register_static (G_TYPE_OBJECT, "FrapMenuLayout", &info, 0); + } + + return type; +} + + + +static void +frap_menu_layout_class_init (FrapMenuLayoutClass *klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (FrapMenuLayoutPrivate)); + + /* Determine parent type class */ + frap_menu_layout_parent_class = g_type_class_peek_parent (klass); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = frap_menu_layout_finalize; + gobject_class->get_property = frap_menu_layout_get_property; + gobject_class->set_property = frap_menu_layout_set_property; +} + + + +static void +frap_menu_layout_init (FrapMenuLayout *layout) +{ + layout->priv = FRAP_MENU_LAYOUT_GET_PRIVATE (layout); + layout->priv->nodes = NULL; +} + + + +static void +frap_menu_layout_finalize (GObject *object) +{ + FrapMenuLayout *layout = FRAP_MENU_LAYOUT (object); + + /* Free nodes */ + g_slist_foreach (layout->priv->nodes, (GFunc) frap_menu_layout_free_node, NULL); + g_slist_free (layout->priv->nodes); + + (*G_OBJECT_CLASS (frap_menu_layout_parent_class)->finalize) (object); +} + + + +static void +frap_menu_layout_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FrapMenuLayout *layout = FRAP_MENU_LAYOUT (layout); + + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + + +static void +frap_menu_layout_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FrapMenuLayout *layout = FRAP_MENU_LAYOUT (layout); + + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + + +FrapMenuLayout* +frap_menu_layout_new (void) +{ + return g_object_new (FRAP_TYPE_MENU_LAYOUT, NULL); +} + + + +static void +frap_menu_layout_free_node (FrapMenuLayoutNode *node) +{ + if (node->type == FRAP_MENU_LAYOUT_NODE_FILENAME) + g_free (node->data.filename); + + g_free (node); +} + + + +void +frap_menu_layout_add_filename (FrapMenuLayout *layout, + const gchar *filename) +{ + g_return_if_fail (FRAP_IS_MENU_LAYOUT (layout)); + g_return_if_fail (filename != NULL); + + /* Build filename node */ + FrapMenuLayoutNode *node = g_new0 (FrapMenuLayoutNode, 1); + node->type = FRAP_MENU_LAYOUT_NODE_FILENAME; + node->data.filename = g_strdup (filename); + + g_debug ("frap_menu_layout_add_filename ('%s')", filename); + + /* Append node to the list */ + layout->priv->nodes = g_slist_append (layout->priv->nodes, node); +} + + + +void +frap_menu_layout_add_separator (FrapMenuLayout *layout) +{ + g_return_if_fail (FRAP_IS_MENU_LAYOUT (layout)); + + /* Build separator node */ + FrapMenuLayoutNode *node = g_new0 (FrapMenuLayoutNode, 1); + node->type = FRAP_MENU_LAYOUT_NODE_SEPARATOR; + + g_debug ("frap_menu_layout_add_separator ()"); + + /* Append node to the list */ + layout->priv->nodes = g_slist_append (layout->priv->nodes, node); +} + + + +void +frap_menu_layout_add_merge (FrapMenuLayout *layout, + FrapMenuLayoutMergeType type) +{ + g_return_if_fail (FRAP_IS_MENU_LAYOUT (layout)); + + /* Build merge node */ + FrapMenuLayoutNode *node = g_new0 (FrapMenuLayoutNode, 1); + node->type = FRAP_MENU_LAYOUT_NODE_MERGE; + node->data.merge_type = type; + + g_debug ("frap_menu_layout_add_merge (%d)", type); + + /* Append node to the list */ + layout->priv->nodes = g_slist_append (layout->priv->nodes, node); +} + + + +GSList* +frap_menu_layout_get_nodes (FrapMenuLayout *layout) +{ + g_return_val_if_fail (FRAP_IS_MENU_LAYOUT (layout), NULL); + return layout->priv->nodes; +} + + + +gboolean +frap_menu_layout_get_filename_used (FrapMenuLayout *layout, + const gchar *filename) +{ + FrapMenuLayoutNode *node; + GSList *iter; + gboolean found = FALSE; + + g_return_val_if_fail (FRAP_IS_MENU_LAYOUT (layout), FALSE); + g_return_val_if_fail (filename != NULL, FALSE); + + for (iter = layout->priv->nodes; iter != NULL; iter = g_slist_next (iter)) + { + node = (FrapMenuLayoutNode *)iter->data; + + if (G_UNLIKELY (node == NULL)) + continue; + + if (G_UNLIKELY (node->type == FRAP_MENU_LAYOUT_NODE_FILENAME && g_utf8_collate (node->data.filename, filename) == 0)) + { + found = TRUE; + break; + } + } + + return found; +} + + + +FrapMenuLayoutNodeType +frap_menu_layout_node_get_type (FrapMenuLayoutNode *node) +{ + g_return_val_if_fail (node != NULL, FRAP_MENU_LAYOUT_NODE_INVALID); + return node->type; +} + + + +const gchar* +frap_menu_layout_node_get_filename (FrapMenuLayoutNode *node) +{ + g_return_val_if_fail (node != NULL && node->type == FRAP_MENU_LAYOUT_NODE_FILENAME, NULL); + return node->data.filename; +} + + + + +FrapMenuLayoutMergeType +frap_menu_layout_node_get_merge_type (FrapMenuLayoutNode *node) +{ + g_return_val_if_fail (node != NULL && node->type == FRAP_MENU_LAYOUT_NODE_MERGE, FRAP_MENU_LAYOUT_MERGE_ALL); + return node->data.merge_type; +} Property changes on: libfrap/trunk/libfrap/menu/frap-menu-layout.c ___________________________________________________________________ Name: svn:keywords + Id Author Date Revision Added: libfrap/trunk/libfrap/menu/frap-menu-layout.h =================================================================== --- libfrap/trunk/libfrap/menu/frap-menu-layout.h (rev 0) +++ libfrap/trunk/libfrap/menu/frap-menu-layout.h 2007-03-18 02:23:12 UTC (rev 25185) @@ -0,0 +1,85 @@ +/* $Id$ */ +/* vi:set expandtab sw=2 sts=2: */ +/*- + * Copyright (c) 2007 Jannis Pohlmann <[EMAIL PROTECTED]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if !defined(LIBFRAPMENU_INSIDE_LIBFRAPMENU_H) && !defined(LIBFRAPMENU_COMPILATION) +#error "Only <libfrapmenu/libfrapmenu.h> can be included directly. This file may disappear or change contents." +#endif + +#ifndef __FRAP_MENU_LAYOUT_H__ +#define __FRAP_MENU_LAYOUT_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS; + +typedef enum +{ + FRAP_MENU_LAYOUT_MERGE_MENUS, + FRAP_MENU_LAYOUT_MERGE_FILES, + FRAP_MENU_LAYOUT_MERGE_ALL, +} FrapMenuLayoutMergeType; + +typedef enum +{ + FRAP_MENU_LAYOUT_NODE_INVALID, + FRAP_MENU_LAYOUT_NODE_FILENAME, + FRAP_MENU_LAYOUT_NODE_MENUNAME, + FRAP_MENU_LAYOUT_NODE_SEPARATOR, + FRAP_MENU_LAYOUT_NODE_MERGE, +} FrapMenuLayoutNodeType; + +typedef struct _FrapMenuLayoutNode FrapMenuLayoutNode; + +typedef struct _FrapMenuLayoutPrivate FrapMenuLayoutPrivate; +typedef struct _FrapMenuLayoutClass FrapMenuLayoutClass; +typedef struct _FrapMenuLayout FrapMenuLayout; + +#define FRAP_TYPE_MENU_LAYOUT (frap_menu_layout_get_type()) +#define FRAP_MENU_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FRAP_TYPE_MENU_LAYOUT, FrapMenuLayout)) +#define FRAP_MENU_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FRAP_TYPE_MENU_LAYOUT, FrapMenuLayoutClass)) +#define FRAP_IS_MENU_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FRAP_TYPE_MENU_LAYOUT)) +#define FRAP_IS_MENU_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FRAP_TYPE_MENU_LAYOUT)) +#define FRAP_MENU_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FRAP_TYPE_MENU_LAYOUT, FrapMenuLayoutClass)) + +GType frap_menu_layout_get_type (void) G_GNUC_CONST; + +FrapMenuLayout *frap_menu_layout_new (void) G_GNUC_MALLOC; +void frap_menu_layout_add_filename (FrapMenuLayout *layout, + const gchar *filename); +void frap_menu_layout_add_separator (FrapMenuLayout *layout); +void frap_menu_layout_add_merge (FrapMenuLayout *layout, + FrapMenuLayoutMergeType type); +GSList *frap_menu_layout_get_nodes (FrapMenuLayout *layout); +gboolean frap_menu_layout_get_filename_used (FrapMenuLayout *layout, + const gchar *filename); + +FrapMenuLayoutNodeType frap_menu_layout_node_get_type (FrapMenuLayoutNode *node); +const gchar *frap_menu_layout_node_get_filename (FrapMenuLayoutNode *node); +FrapMenuLayoutMergeType frap_menu_layout_get_merge_type (FrapMenuLayoutNode *node); + +G_END_DECLS; + +#endif /* !__FRAP_MENU_LAYOUT_H__ */ + Property changes on: libfrap/trunk/libfrap/menu/frap-menu-layout.h ___________________________________________________________________ Name: svn:keywords + Id Author Date Revision Added: libfrap/trunk/libfrap/menu/frap-menu-separator.c =================================================================== --- libfrap/trunk/libfrap/menu/frap-menu-separator.c (rev 0) +++ libfrap/trunk/libfrap/menu/frap-menu-separator.c 2007-03-18 02:23:12 UTC (rev 25185) @@ -0,0 +1,136 @@ +/* $Id$ */ +/* vim:set et ai sw=2 sts=2: */ +/*- + * Copyright (c) 2007 Jannis Pohlmann <[EMAIL PROTECTED]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <frap-menu-separator.h> + + + +static void frap_menu_separator_class_init (FrapMenuSeparatorClass *klass); +static void frap_menu_separator_init (FrapMenuSeparator *separator); +static void frap_menu_separator_finalize (GObject *object); + + + +static FrapMenuSeparator *_frap_menu_separator = NULL; + + + +void +_frap_menu_separator_init (void) +{ + if (G_LIKELY (_frap_menu_separator == NULL)) + _frap_menu_separator = g_object_new (FRAP_TYPE_MENU_SEPARATOR, NULL); +} + + + +void +_frap_menu_separator_shutdown (void) +{ + if (G_LIKELY (_frap_menu_separator != NULL)) + g_object_unref (G_OBJECT (_frap_menu_separator)); +} + + + +struct _FrapMenuSeparatorClass +{ + GObjectClass __parent__; +}; + +struct _FrapMenuSeparator +{ + GObject __parent__; +}; + + + +static GObjectClass *frap_menu_separator_parent_class = NULL; + + + +GType +frap_menu_separator_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + static const GTypeInfo info = + { + sizeof (FrapMenuSeparatorClass), + NULL, + NULL, + (GClassInitFunc) frap_menu_separator_class_init, + NULL, + NULL, + sizeof (FrapMenuSeparator), + 0, + (GInstanceInitFunc) frap_menu_separator_init, + NULL, + }; + + type = g_type_register_static (G_TYPE_OBJECT, "FrapMenuSeparator", &info, 0); + } + + return type; +} + + + +static void +frap_menu_separator_class_init (FrapMenuSeparatorClass *klass) +{ + GObjectClass *gobject_class; + + /* Determine parent type class */ + frap_menu_separator_parent_class = g_type_class_peek_parent (klass); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = frap_menu_separator_finalize; +} + + + +static void +frap_menu_separator_init (FrapMenuSeparator *separator) +{ +} + + + +static void +frap_menu_separator_finalize (GObject *object) +{ + (*G_OBJECT_CLASS (frap_menu_separator_parent_class)->finalize) (object); +} + + + +FrapMenuSeparator* +frap_menu_separator_get_default (void) +{ + return _frap_menu_separator; +} Property changes on: libfrap/trunk/libfrap/menu/frap-menu-separator.c ___________________________________________________________________ Name: svn:keywords + Id Author Date Revision Added: libfrap/trunk/libfrap/menu/frap-menu-separator.h =================================================================== --- libfrap/trunk/libfrap/menu/frap-menu-separator.h (rev 0) +++ libfrap/trunk/libfrap/menu/frap-menu-separator.h 2007-03-18 02:23:12 UTC (rev 25185) @@ -0,0 +1,59 @@ +/* $Id$ */ +/* vi:set et ai sw=2 sts=2: */ +/*- + * Copyright (c) 2007 Jannis Pohlmann <[EMAIL PROTECTED]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if !defined(LIBFRAPMENU_INSIDE_LIBFRAPMENU_H) && !defined(LIBFRAPMENU_COMPILATION) +#error "Only <libfrapmenu/libfrapmenu.h> can be included directly. This file may disappear or change contents." +#endif + +#ifndef __FRAP_MENU_SEPARATOR_H__ +#define __FRAP_MENU_SEPARATOR_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS; + +typedef struct _FrapMenuSeparatorClass FrapMenuSeparatorClass; +typedef struct _FrapMenuSeparator FrapMenuSeparator; + +#define FRAP_TYPE_MENU_SEPARATOR (frap_menu_separator_get_type()) +#define FRAP_MENU_SEPARATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FRAP_TYPE_MENU_SEPARATOR, FrapMenuSeparator)) +#define FRAP_MENU_SEPARATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FRAP_TYPE_MENU_SEPARATOR, FrapMenuSeparatorClass)) +#define FRAP_IS_MENU_SEPARATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FRAP_TYPE_MENU_SEPARATOR)) +#define FRAP_IS_MENU_SEPARATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FRAP_TYPE_MENU_SEPARATOR)) +#define FRAP_MENU_SEPARATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FRAP_TYPE_MENU_SEPARATOR, FrapMenuSeparatorClass)) + + +GType frap_menu_separator_get_type (void) G_GNUC_CONST; + +FrapMenuSeparator *frap_menu_separator_get_default (void); + +#if defined(LIBFRAPMENU_COMPILATION) +void _frap_menu_separator_init (void) G_GNUC_INTERNAL; +void _frap_menu_separator_shutdown (void) G_GNUC_INTERNAL; +#endif + +G_END_DECLS; + +#endif /* !__FRAP_MENU_SEPARATOR_H__ */ Property changes on: libfrap/trunk/libfrap/menu/frap-menu-separator.h ___________________________________________________________________ Name: svn:keywords + Id Author Date Revision Modified: libfrap/trunk/libfrap/menu/frap-menu.c =================================================================== --- libfrap/trunk/libfrap/menu/frap-menu.c 2007-03-17 22:54:06 UTC (rev 25184) +++ libfrap/trunk/libfrap/menu/frap-menu.c 2007-03-18 02:23:12 UTC (rev 25185) @@ -40,6 +40,8 @@ #include <frap-menu-item-pool.h> #include <frap-menu-item-cache.h> #include <frap-menu-move.h> +#include <frap-menu-layout.h> +#include <frap-menu-separator.h> #include <frap-menu.h> @@ -95,6 +97,9 @@ /* Initialize the directory module */ _frap_menu_directory_init (); + + /* Creates the menu separator */ + _frap_menu_separator_init (); } } @@ -113,6 +118,9 @@ /* Unset desktop environment */ frap_menu_set_environment (NULL); + /* Destroys the menu separator */ + _frap_menu_separator_shutdown (); + /* Shutdown the directory module */ _frap_menu_directory_shutdown (); @@ -136,6 +144,7 @@ FRAP_MENU_PARSE_STATE_RULE, FRAP_MENU_PARSE_STATE_END, FRAP_MENU_PARSE_STATE_MOVE, + FRAP_MENU_PARSE_STATE_LAYOUT, } FrapMenuParseState; @@ -342,6 +351,9 @@ /* Shared menu item cache */ FrapMenuItemCache *cache; + /* Menu layout */ + FrapMenuLayout *layout; + /* Parse information (used for resolving) */ FrapMenuParseInfo *parse_info; }; @@ -495,6 +507,7 @@ menu->priv->rules = NULL; menu->priv->moves = NULL; menu->priv->pool = frap_menu_item_pool_new (); + menu->priv->layout = frap_menu_layout_new (); /* Take reference on the menu item cache */ menu->priv->cache = frap_menu_item_cache_get_default (); @@ -548,6 +561,9 @@ /* Free item pool */ g_object_unref (G_OBJECT (menu->priv->pool)); + /* Free menu layout */ + g_object_unref (G_OBJECT (menu->priv->layout)); + /* Release item cache reference */ g_object_unref (G_OBJECT (menu->priv->cache)); @@ -711,7 +727,7 @@ { FrapMenu *menu; - g_return_val_if_fail (g_path_is_absolute (filename), NULL); + g_return_val_if_fail (filename != NULL && g_path_is_absolute (filename), NULL); /* Create new menu */ menu = g_object_new (FRAP_TYPE_MENU, "filename", filename, NULL); @@ -1216,6 +1232,11 @@ /* Set parse state */ menu_context->state = FRAP_MENU_PARSE_STATE_MOVE; } + else if (g_utf8_collate (element_name, "Layout") == 0) + { + /* Set parse state */ + menu_context->state = FRAP_MENU_PARSE_STATE_LAYOUT; + } break; @@ -1289,6 +1310,53 @@ menu_context->node_type = FRAP_MENU_PARSE_NODE_TYPE_NEW; break; + + case FRAP_MENU_PARSE_STATE_LAYOUT: + /* Fetch current menu from stack */ + current_menu = g_list_first (menu_context->menu_stack)->data; + + if (g_utf8_collate (element_name, "Filename") == 0) + { + /* Set node type */ + menu_context->node_type = FRAP_MENU_PARSE_NODE_TYPE_FILENAME; + } + else if (g_utf8_collate (element_name, "Separator") == 0) + { + /* Add separator to the menu layout */ + frap_menu_layout_add_separator (current_menu->priv->layout); + } + else if (g_utf8_collate (element_name, "Merge") == 0) + { + FrapMenuLayoutMergeType type = FRAP_MENU_LAYOUT_MERGE_ALL; + + gboolean type_found = FALSE; + gint i; + + /* Find 'type' attribute */ + for (i = 0; i < g_strv_length (attribute_names); ++i) + { + if (g_utf8_collate (attribute_names[i], "type") == 0) + { + /* Determine merge type */ + if (g_utf8_collate (attribute_values[i], "menus") == 0) + type = FRAP_MENU_LAYOUT_MERGE_MENUS; + else if (g_utf8_collate (attribute_values[i], "files") == 0) + type = FRAP_MENU_LAYOUT_MERGE_FILES; + else if (g_utf8_collate (attribute_values[i], "all") == 0) + type = FRAP_MENU_LAYOUT_MERGE_ALL; + else + g_warning ("Unsupported layout merge type <Merge type='%s'/> detected. Using type 'all'.", attribute_values[i]); + + type_found = TRUE; + } + } + + if (G_UNLIKELY (!type_found)) + g_warning ("Type attribute missing for <Merge> element. Using type 'all'."); + + /* Add merge to the menu layout */ + frap_menu_layout_add_merge (current_menu->priv->layout, type); + } } } @@ -1370,6 +1438,16 @@ else if (g_utf8_collate (element_name, "New") == 0) menu_context->move = NULL; break; + + case FRAP_MENU_PARSE_STATE_LAYOUT: + if (g_utf8_collate (element_name, "Layout") == 0) + { + if (g_list_length (menu_context->menu_stack) > 1) + menu_context->state = FRAP_MENU_PARSE_STATE_MENU; + else + menu_context->state = FRAP_MENU_PARSE_STATE_ROOT; + } + break; } } @@ -1416,8 +1494,13 @@ break; case FRAP_MENU_PARSE_NODE_TYPE_FILENAME: - if (G_LIKELY (current_rule != NULL)) - frap_menu_rules_add_filename (current_rule, content); + if (menu_context->state == FRAP_MENU_PARSE_STATE_RULE) + { + if (G_LIKELY (current_rule != NULL)) + frap_menu_rules_add_filename (current_rule, content); + } + else if (menu_context->state == FRAP_MENU_PARSE_STATE_LAYOUT) + frap_menu_layout_add_filename (current_menu->priv->layout, content); break; case FRAP_MENU_PARSE_NODE_TYPE_CATEGORY: @@ -2473,6 +2556,53 @@ static void frap_menu_resolve_moves (FrapMenu *menu) { + FrapMenuMove *move; + FrapMenu *source; + FrapMenu *destination; + GSList *iter; + + g_return_if_fail (FRAP_IS_MENU (menu)); + + /* Recurse into the submenus which need to perform move actions first */ + for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter)) + { + source = FRAP_MENU (iter->data); + + /* Resolve moves of the child menu */ + frap_menu_resolve_moves (source); + } + + /* Iterate over move instructions */ + for (iter = menu->priv->moves; iter != NULL; iter = g_slist_next (iter)) + { + move = FRAP_MENU_MOVE (iter->data); + + g_critical ("Moving %s to %s ...", frap_menu_move_get_old (move), frap_menu_move_get_new (move)); + + /* Determine submenu with the old name */ + source = frap_menu_get_menu_with_name (menu, frap_menu_move_get_old (move)); + + g_critical ("source = 0x%x", source); + + /* Skip if there is no such submenu */ + if (G_LIKELY (source == NULL)) + continue; + + /* Determine destination submenu */ + destination = frap_menu_get_menu_with_name (menu, frap_menu_move_get_new (move)); + + g_critical ("destination = 0x%x", destination); + + /* If destination does not exist, simply reset the name of the source menu */ + if (G_LIKELY (destination == NULL)) + frap_menu_set_name (source, frap_menu_move_get_new (move)); + else + { + /* TODO: See section "Merging" in the menu specification. */ + } + } + +#if 0 FrapMenu *submenu; FrapMenu *target_submenu; FrapMenuMove *move; @@ -2532,6 +2662,7 @@ } } } +#endif } @@ -2617,3 +2748,73 @@ return items; } + + + +GSList* +frap_menu_get_layout_items (FrapMenu *menu) +{ + GSList *items = NULL; + GSList *menu_items; + GSList *nodes; + GSList *iter; + + g_return_val_if_fail (FRAP_IS_MENU (menu), NULL); + + /* Fetch layout nodes */ + nodes = frap_menu_layout_get_nodes (menu->priv->layout); + + /* Only process layout if there are any layout information at all */ + if (G_UNLIKELY (nodes != NULL)) + { + g_debug ("Menu has layout"); + + /* Process layout nodes in order */ + for (iter = nodes; iter != NULL; iter = g_slist_next (iter)) + { + FrapMenuLayoutNode *node = (FrapMenuLayoutNode *)iter->data; + FrapMenuLayoutNodeType type; + FrapMenuItem *item; + FrapMenuSeparator *separator; + + /* Determine layout node type */ + type = frap_menu_layout_node_get_type (node); + + switch (type) + { + case FRAP_MENU_LAYOUT_NODE_FILENAME: + item = frap_menu_item_pool_lookup (menu->priv->pool, frap_menu_layout_node_get_filename (node)); + if (G_LIKELY (item != NULL)) + items = g_slist_append (items, item); + break; + case FRAP_MENU_LAYOUT_NODE_SEPARATOR: + items = g_slist_append (items, frap_menu_separator_get_default ()); + break; + case FRAP_MENU_LAYOUT_NODE_MERGE: + switch (node->data.merge_type) + { + case FRAP_MENU_LAYOUT_MERGE_ALL: + /* TODO Fetch all items which are not used in the layout yet and sort them + * by displayed name (ascending) */ + break; + case FRAP_MENU_LAYOUT_MERGE_FILES: + /* TODO Fetch all menu items which are not used in the layout yet and sort them + * by displayed name (ascending) */ + break; + case FRAP_MENU_LAYOUT_MERGE_MENUS: + /* TODO Fetch all submenus which are not used in the layout yet and sort them + * by displayed name (ascending) */ + break; + } + break; + } + } + } + else + { + /* No layout used - just return items without layout */ + items = frap_menu_get_items (menu); + } + + return items; +} Modified: libfrap/trunk/libfrap/menu/frap-menu.h =================================================================== --- libfrap/trunk/libfrap/menu/frap-menu.h 2007-03-17 22:54:06 UTC (rev 25184) +++ libfrap/trunk/libfrap/menu/frap-menu.h 2007-03-18 02:23:12 UTC (rev 25185) @@ -77,6 +77,7 @@ FrapMenu *frap_menu_get_parent (FrapMenu *menu); FrapMenuItemPool *frap_menu_get_item_pool (FrapMenu *menu); GSList *frap_menu_get_items (FrapMenu *menu); +GSList *frap_menu_get_layout_items (FrapMenu *menu); G_END_DECLS; Modified: libfrap/trunk/libfrap/menu/libfrapmenu.h =================================================================== --- libfrap/trunk/libfrap/menu/libfrapmenu.h 2007-03-17 22:54:06 UTC (rev 25184) +++ libfrap/trunk/libfrap/menu/libfrapmenu.h 2007-03-18 02:23:12 UTC (rev 25185) @@ -33,6 +33,8 @@ #include <frap-menu-and-rules.h> #include <frap-menu-not-rules.h> #include <frap-menu-directory.h> +#include <frap-menu-layout.h> +#include <frap-menu-separator.h> #include <frap-menu.h> #define LIBFRAPMENU_INSIDE_LIBFRAPMENU_H Modified: libfrap/trunk/libfrap/menu/tests/test-display-root-menu.c =================================================================== --- libfrap/trunk/libfrap/menu/tests/test-display-root-menu.c 2007-03-17 22:54:06 UTC (rev 25184) +++ libfrap/trunk/libfrap/menu/tests/test-display-root-menu.c 2007-03-18 02:23:12 UTC (rev 25185) @@ -163,8 +163,7 @@ void -create_item_widgets_for_menu (const gchar *desktop_id, - FrapMenuItem *item, +create_item_widgets_for_menu (FrapMenuItem *item, GtkWidget *widget) { GtkWidget *menu_item; @@ -206,65 +205,77 @@ GtkWidget *submenu; GtkWidget *image; GSList *iter; - GSList *menus; + GSList *items; const gchar *icon_name; GdkPixbuf *pixbuf; GtkIconTheme *icon_theme = gtk_icon_theme_get_default (); - /* Create sorted copy of the submenu list */ - menus = g_slist_sort (g_slist_copy (frap_menu_get_menus (menu)), (GCompareFunc) compare_menus); + /* Get submenus and items based on the menu layout */ + items = frap_menu_get_layout_items (menu); - for (iter = menus; iter != NULL; iter = g_slist_next (iter)) + /* Iterate over children */ + for (iter = items; iter != NULL; iter = g_slist_next (iter)) { - /* Get menu directory */ - directory = frap_menu_get_directory (FRAP_MENU (iter->data)); + if (FRAP_IS_MENU_ITEM (iter->data)) + { + /* Add menu item to the menu */ + create_item_widgets_for_menu (FRAP_MENU_ITEM (iter->data), widget); + } + else if (FRAP_IS_MENU (iter->data)) + { + FrapMenu *child_menu = FRAP_MENU (iter->data); - /* Skip if menu has no directory (and thus, no display information) */ - if (G_UNLIKELY (directory == NULL)) - continue; + /* Get menu directory */ + directory = frap_menu_get_directory (FRAP_MENU (child_menu)); - /* Skip if menu is empty */ - if (frap_menu_item_pool_get_empty (frap_menu_get_item_pool (iter->data))) - continue; + /* Skip if menu has no directory (and thus, no display information) */ + if (G_UNLIKELY (directory == NULL)) + continue; - /* Skip if menu is only shown in other environments or is not shown in - * this one */ - if (!frap_menu_directory_show_in_environment (directory)) - continue; + /* Skip if menu is empty */ + if (frap_menu_item_pool_get_empty (frap_menu_get_item_pool (child_menu))) + continue; - /* Determine icon name */ - icon_name = frap_menu_directory_get_icon (directory); + /* Skip if menu is only shown in other environments or is not shown in + * this one */ + if (!frap_menu_directory_show_in_environment (directory)) + continue; - /* Load menu icon */ - pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name, ICON_SIZE, GTK_ICON_LOOKUP_USE_BUILTIN, NULL); - if (G_UNLIKELY (pixbuf == NULL)) - pixbuf = gtk_icon_theme_load_icon (icon_theme, "applications-other", ICON_SIZE, GTK_ICON_LOOKUP_USE_BUILTIN, NULL); + /* Determine icon name */ + icon_name = frap_menu_directory_get_icon (directory); - /* Create image widget */ - image = gtk_image_new_from_pixbuf (pixbuf); + /* Load menu icon */ + pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name, ICON_SIZE, GTK_ICON_LOOKUP_USE_BUILTIN, NULL); + if (G_UNLIKELY (pixbuf == NULL)) + pixbuf = gtk_icon_theme_load_icon (icon_theme, "applications-other", ICON_SIZE, GTK_ICON_LOOKUP_USE_BUILTIN, NULL); - /* Create menu item */ - menu_item = gtk_image_menu_item_new_with_label (frap_menu_directory_get_name (directory)); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image); - gtk_menu_shell_append (GTK_MENU_SHELL (widget), menu_item); - gtk_widget_show (menu_item); + /* Create image widget */ + image = gtk_image_new_from_pixbuf (pixbuf); - /* Create submenu */ - submenu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), submenu); + /* Create menu item */ + menu_item = gtk_image_menu_item_new_with_label (frap_menu_directory_get_name (directory)); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image); + gtk_menu_shell_append (GTK_MENU_SHELL (widget), menu_item); + gtk_widget_show (menu_item); - /* Create widgets for submenu */ - create_widgets_for_menu (submenu, FRAP_MENU (iter->data)); + /* Create submenu */ + submenu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), submenu); + + /* Create widgets for submenu */ + create_widgets_for_menu (submenu, FRAP_MENU (child_menu)); + } + else if (FRAP_IS_MENU_SEPARATOR (iter->data)) + { + /* Add a separator to the menu */ + menu_item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (widget), menu_item); + gtk_widget_show (menu_item); + } } - /* Get item pool */ - pool = frap_menu_get_item_pool (menu); - - /* Create menu items */ - frap_menu_item_pool_foreach (pool, (GHFunc) create_item_widgets_for_menu, widget); - - /* Free submenu list */ - g_slist_free (menus); + /* Free items list */ + g_slist_free (items); } _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits