1 /*
2  * IpatchStateItem.c - Base class for state (undo/redo) items
3  *
4  * libInstPatch
5  * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; version 2.1
10  * of the License only.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301, USA or on the web at http://www.gnu.org.
21  */
22 #include <stdio.h>
23 #include <glib.h>
24 #include <glib-object.h>
25 
26 #include "IpatchStateItem.h"
27 
28 static void ipatch_state_item_class_init(IpatchStateItemClass *klass);
29 static void ipatch_state_item_finalize(GObject *gobject);
30 
31 gpointer item_parent_class = NULL;
32 
33 GType
ipatch_state_item_get_type(void)34 ipatch_state_item_get_type(void)
35 {
36     static GType item_type = 0;
37 
38     if(!item_type)
39     {
40         static const GTypeInfo item_info =
41         {
42             sizeof(IpatchStateItemClass), NULL, NULL,
43             (GClassInitFunc) ipatch_state_item_class_init, NULL, NULL,
44             sizeof(IpatchStateItem), 0,
45             (GInstanceInitFunc) NULL,
46         };
47 
48         item_type = g_type_register_static(G_TYPE_OBJECT, "IpatchStateItem",
49                                            &item_info, G_TYPE_FLAG_ABSTRACT);
50     }
51 
52     return (item_type);
53 }
54 
55 static void
ipatch_state_item_class_init(IpatchStateItemClass * klass)56 ipatch_state_item_class_init(IpatchStateItemClass *klass)
57 {
58     GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
59 
60     item_parent_class = g_type_class_peek_parent(klass);
61     gobj_class->finalize = ipatch_state_item_finalize;
62 }
63 
64 static void
ipatch_state_item_finalize(GObject * gobject)65 ipatch_state_item_finalize(GObject *gobject)
66 {
67     IpatchStateItem *item = IPATCH_STATE_ITEM(gobject);
68 
69     if(item->node)
70     {
71         g_node_destroy(item->node);    /* destroy item's tree node */
72     }
73 
74     if(item->group)
75     {
76         g_object_unref(item->group);    /* -- unref item's group */
77     }
78 
79     if(G_OBJECT_CLASS(item_parent_class)->finalize)
80     {
81         G_OBJECT_CLASS(item_parent_class)->finalize(gobject);
82     }
83 }
84 
85 /**
86  * ipatch_state_item_restore:
87  * @item: State item to restore
88  *
89  * Restore the state saved by @item.
90  */
91 void
ipatch_state_item_restore(const IpatchStateItem * item)92 ipatch_state_item_restore(const IpatchStateItem *item)
93 {
94     IpatchStateItemClass *klass;
95     g_return_if_fail(IPATCH_IS_STATE_ITEM(item));
96 
97     klass = IPATCH_STATE_ITEM_GET_CLASS(item);
98     g_return_if_fail(klass->restore != NULL);
99     (*klass->restore)(item);
100 }
101 
102 /**
103  * ipatch_state_item_depend:
104  * @item1: First item
105  * @item2: Second item
106  *
107  * Check if @item1 is dependent on @item2.
108  *
109  * Returns: %TRUE if @item1 is dependent on @item2, %FALSE otherwise.
110  */
111 gboolean
ipatch_state_item_depend(const IpatchStateItem * item1,const IpatchStateItem * item2)112 ipatch_state_item_depend(const IpatchStateItem *item1,
113                          const IpatchStateItem *item2)
114 {
115     IpatchStateItemClass *klass;
116     g_return_val_if_fail(IPATCH_IS_STATE_ITEM(item1), FALSE);
117     g_return_val_if_fail(IPATCH_IS_STATE_ITEM(item2), FALSE);
118 
119     klass = IPATCH_STATE_ITEM_GET_CLASS(item1);
120     return (!klass->depend || (*klass->depend)(item1, item2));
121 }
122 
123 /**
124  * ipatch_state_item_conflict:
125  * @item1: First item
126  * @item2: Second item
127  *
128  * Check if @item1 conflicts with @item2.
129  *
130  * Returns: %TRUE if @item1 conflicts with @item2, %FALSE otherwise.
131  */
132 gboolean
ipatch_state_item_conflict(const IpatchStateItem * item1,const IpatchStateItem * item2)133 ipatch_state_item_conflict(const IpatchStateItem *item1,
134                            const IpatchStateItem *item2)
135 {
136     IpatchStateItemClass *klass;
137     g_return_val_if_fail(IPATCH_IS_STATE_ITEM(item1), FALSE);
138     g_return_val_if_fail(IPATCH_IS_STATE_ITEM(item2), FALSE);
139 
140     klass = IPATCH_STATE_ITEM_GET_CLASS(item1);
141     return (!klass->conflict || (*klass->conflict)(item1, item2));
142 }
143 
144 /**
145  * ipatch_state_item_describe:
146  * @item: Item to describe
147  *
148  * Get a detailed description of the action that created the @item state.
149  *
150  * Returns: Newly allocated description of the @item action or %NULL if
151  * no description available. String should be freed when no longer needed.
152  */
153 char *
ipatch_state_item_describe(const IpatchStateItem * item)154 ipatch_state_item_describe(const IpatchStateItem *item)
155 {
156     IpatchStateItemClass *klass;
157     g_return_val_if_fail(IPATCH_IS_STATE_ITEM(item), NULL);
158 
159     klass = IPATCH_STATE_ITEM_GET_CLASS(item);
160 
161     if(klass->describe)
162     {
163         return ((*klass->describe)(item));
164     }
165     else
166     {
167         return (NULL);
168     }
169 }
170