summaryrefslogtreecommitdiff
path: root/gio/src/action.hg
blob: 3e26652bfd91bbed5a4e2a52c43774cb25fc12c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-

/* Copyright (C) 2011 The giomm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <glibmm/interface.h>
#include <glibmm/varianttype.h>
#include <gio/gio.h>

_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/interface_p.h)
_PINCLUDE(gio/gio.h)

#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef struct _GActionInterface GActionInterface;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

namespace Glib
{

class VariantBase;

}

namespace Gio
{

/** Action - An action.
 * Action represents a single named action.
 *
 * The main interface to an action is that it can be activated with activate().
 * This results in the signal_activate() signal being emitted. An activation
 * has a Glib::VariantBase parameter (which may be <tt>0</tt>). The correct
 * type for the parameter is determined by a static parameter type (which is
 * given at construction time).
 *
 * An action may optionally have a state, in which case the state may be set
 * with change_state(). This call takes a Glib::VariantBase. The correct type
 * for the state is determined by a static state type (which is given at
 * construction time).
 *
 * The state may have a hint associated with it, specifying its valid range.
 *
 * Action is merely the interface to the concept of an action, as described
 * above. Various implementations of actions exist, including SimpleAction and
 * Gtk::Action.
 *
 * In all cases, the implementing class is responsible for storing the name of
 * the action, the parameter type, the enabled state, the optional state type
 * and the state and emitting the appropriate signals when these change. The
 * implementor responsible for filtering calls to activate() and change_state()
 * for type safety and for the state being enabled.
 *
 * Probably the only useful thing to do with a Action is to put it inside of a
 * SimpleActionGroup.
 *
 * @newin{2,32}
 */
class Action : public Glib::Interface
{
  _CLASS_INTERFACE(Action, GAction, G_ACTION, GActionInterface)

public:
  _WRAP_METHOD(Glib::ustring get_name() const, g_action_get_name)
  _WRAP_METHOD(Glib::VariantType get_parameter_type() const, g_action_get_parameter_type)
  _WRAP_METHOD(Glib::VariantType get_state_type() const, g_action_get_state_type)

  //TODO: Docs
  //TODO: Is there any specific type that can really be used with this? A std::list<>. We must test this.
  //  See also ActionGroup:::get_action_state_hint().
  template <typename T_Value>
  void get_state_hint(T_Value& value) const;

  //TODO: When we can break ABI, Return a Glib::VariantContainerBase,
  // as we already do for ActionGroup::get_action_state_hint(), 
  // because that is what this returns (to specify a range).
  _WRAP_METHOD(Glib::VariantBase get_state_hint_variant() const, g_action_get_state_hint)

  _WRAP_METHOD(bool get_enabled() const, g_action_get_enabled)

  /** Request for the state of @a action to be changed to @a value,
   * assuming that the action has the expected state type.
   * 
   * See get_state_type().
   * 
   * This call merely requests a change.  The action may refuse to change
   * its state or may change its state to something other than @a value.
   * See get_state_hint().
   * 
   * @newin{2,38}
   * @param value The new state.
   */
  template <typename T_Value>
  void change_state(const T_Value& value);

  //This is just here to maintain API compatibility,
  //by stopping the compiler from calling the
  //regular change_state() with a Variant,
  //if the application code previously called change_state(VariantBase).
  template <typename T_Value>
  void change_state(const Glib::Variant<T_Value>& value);

  _WRAP_METHOD(void change_state_variant(const Glib::VariantBase& value), g_action_change_state)

  _WRAP_METHOD(void change_state(const Glib::VariantBase& value), g_action_change_state, deprecated "Use the templated method instead, passing a normal C++ type.")

  //TODO: Docs
  template <typename T_Value>
  void get_state(T_Value& value) const;

  _WRAP_METHOD(Glib::VariantBase get_state_variant() const, g_action_get_state)

  //TODO: Docs
  template <typename T_Value>
  void activate(const T_Value& parameter);

  //This is just here to maintain API compatibility,
  //by stopping the compiler from calling the
  //regular change_state() with a Variant,
  //if the application code previously called activate(VariantBase).
  template <typename T_Value>
  void activate(const Glib::Variant<T_Value>& parameter);

  _WRAP_METHOD(void activate_variant(const Glib::VariantBase& parameter), g_action_activate)

  _WRAP_METHOD(void activate(const Glib::VariantBase& parameter), g_action_activate, deprecated "Use the templated method instead, passing a normal C++ type.")

  _WRAP_METHOD(static bool name_is_valid(const Glib::ustring& action_name), g_action_name_is_valid )

  //TODO: _WRAP_METHOD(static bool parse_detailed_name(const Glib::ustring& detailed_name, gchar** action_name, GVariant** target_value), g_action_parse_detailed_name, errthrow)

  //TODO: Docs.
  template <typename T_Value>
  Glib::ustring print_detailed_name(const Glib::ustring& action_name, const T_Value& value);

  _WRAP_METHOD(static Glib::ustring print_detailed_name_variant(const Glib::ustring& action_name, const Glib::VariantBase& parameter), g_action_print_detailed_name)

  _WRAP_PROPERTY("enabled", bool)
  _WRAP_PROPERTY("name", Glib::ustring)
  _WRAP_PROPERTY("parameter-type", Glib::VariantType)
  _WRAP_PROPERTY("state", Glib::VariantBase)
  _WRAP_PROPERTY("state-type", Glib::VariantType)

#m4 _CONVERSION(`Glib::ustring',`const gchar*',`g_strdup($3.c_str())')
  _WRAP_VFUNC(Glib::ustring get_name() const, "get_name")

#m4 _CONVERSION(`Glib::VariantType',`const GVariantType*',`$3.gobj_copy()')

  _WRAP_VFUNC(Glib::VariantType get_parameter_type() const, "get_parameter_type")
  _WRAP_VFUNC(Glib::VariantType get_state_type() const, "get_state_type")

#m4 _CONVERSION(`Glib::VariantBase',`GVariant*',`$3.gobj_copy()')

  _WRAP_VFUNC(Glib::VariantBase get_state_hint() const, "get_state_hint")

  _WRAP_VFUNC(bool get_enabled() const, "get_enabled")

  _WRAP_VFUNC(Glib::VariantBase get_state() const, "get_state")

#m4 _CONVERSION(`GVariant*',`const Glib::VariantBase&',`Glib::wrap($3, true)')
  _WRAP_VFUNC(void change_state(const Glib::VariantBase& value), "change_state")
  _WRAP_VFUNC(void activate(const Glib::VariantBase& parameter), "activate")
};

template <typename T_Value>
void Action::get_state(T_Value& value) const
{
  value = T_Value(); //Make sure that it is initialized.

  typedef Glib::Variant<T_Value> type_glib_variant;

  g_return_if_fail(
    g_variant_type_equal(g_action_get_state_type(const_cast<GAction*>(gobj())), type_glib_variant::variant_type().gobj()));

  const Glib::VariantBase variantBase = get_state_variant();
  const type_glib_variant variantDerived = variantBase.cast_dynamic<type_glib_variant>(variantBase);
  value = variantDerived.get();
}

template <typename T_Value>
void Action::get_state_hint(T_Value& value) const
{
  value = T_Value(); //Make sure that it is initialized.

  typedef Glib::Variant<T_Value> type_glib_variant;

  const Glib::VariantBase variantBase = get_state_hint_variant();

  // We can't check the type (a range) that will be returned before getting the range hint.
  g_return_if_fail(
    variantBase.is_of_type(type_glib_variant::variant_type()) );

  const type_glib_variant variantDerived = variantBase.cast_dynamic<type_glib_variant>(variantBase);
  value = variantDerived.get();
}

template <typename T_Value>
Glib::ustring Action::print_detailed_name(const Glib::ustring& action_name, const T_Value& parameter)
{
  typedef Glib::Variant<T_Value> type_glib_variant;

  g_return_val_if_fail(
    g_variant_type_equal(g_action_get_parameter_type(const_cast<GAction*>(gobj())), type_glib_variant::variant_type().gobj()),
    Glib::ustring());
  return print_detailed_name_variant(type_glib_variant::create(parameter));
}

template <typename T_Value>
void Action::change_state(const T_Value& value)
{
  typedef Glib::Variant<T_Value> type_glib_variant;

  g_return_if_fail(
    g_variant_type_equal(g_action_get_state_type(const_cast<GAction*>(gobj())), type_glib_variant::variant_type().gobj()));

  change_state_variant(type_glib_variant::create(value));
}

template <typename T_Value>
void Action::change_state(const Glib::Variant<T_Value>& value)
{
  change_state_variant(value);
}

template <typename T_Value>
void Action::activate(const T_Value& parameter)
{
  typedef Glib::Variant<T_Value> type_glib_variant;

  g_return_if_fail(
    g_variant_type_equal(g_action_get_parameter_type(const_cast<GAction*>(gobj())), type_glib_variant::variant_type().gobj()));

  activate_variant(type_glib_variant::create(parameter));
}


template <typename T_Value>
void Action::activate(const Glib::Variant<T_Value>& value)
{
  activate(value);
}


} // namespace Gio