File: realizeable.h

package info (click to toggle)
yapet 2.6-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 11,920 kB
  • sloc: cpp: 32,397; sh: 5,032; makefile: 880; ansic: 36; sed: 16
file content (251 lines) | stat: -rw-r--r-- 7,485 bytes parent folder | download | duplicates (4)
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
// -*- mode: c++ -*-
//
// This file is part of libyacurs.
// Copyright (C) 2013  Rafael Ostertag
//
// 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 3 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, see
// <http://www.gnu.org/licenses/>.
//
//
// $Id$

#ifndef REALIZEABLE_H
#define REALIZEABLE_H 1

#include <string>

#include "area.h"

namespace YACURS {
/**
 * Realization states that can be assumed by an object.
 */
enum REALIZATION_STATE { REALIZING, REALIZED, UNREALIZING, UNREALIZED };

/**
 * Realizeable defines a basic interfaces for displaying and resizing
 * Curses objects on the screen.
 *
 * Realizeable classes display objects on the screen, or provide a way
 * for other objects to be displayed (see Pack).
 *
 * The functions
 *
 * - refresh()
 * - realize()
 * - unrealize()
 * - resize()
 *
 * must not rely on being only called when the object is in the proper
 * state. They must handle calls while being in inproper state
 * gracefully, i.e. not throwing exceptions due to an unexpected
 * state. For instance: refresh() must not throw an exception when
 * called on unrealized objects. Another example would be realize()
 * being called twice.
 *
 * Realizing consists of two states
 *
 * - REALIZING: the object is in the course of being realized, its
 *     state might not be stable
 *
 * - REALIZED: the object is realized. Its state is stable
 *
 *
 * Unrealizing consists of two state
 *
 * - UNREALIZING: the object is in the course of being unrealized, its
 *     state might not be stable
 *
 * - UNREALIZED: the object is unrealized. Its state is stable.
 *
 * Please keep in mind, the implementation has to set the proper
 * states. The helper macros @c REALIZE_ENTER and @c REALIZE_LEAVE can
 * be used when entering and leaving realize() function, @c
 * UNREALIZE_ENTER and @c UNREALIZE_LEAVE for unrealize.
 *
 */
class Realizeable {
   private:
    /**
     * The realization state of the object.
     */
    REALIZATION_STATE _realization_state;

   protected:
    /**
     * Set realization state.
     *
     * @param s state of the object.
     */
    virtual void realization(REALIZATION_STATE s);

   public:
    Realizeable();

    virtual ~Realizeable();

    /**
     * Refresh the object. Derrived classes have to implement two
     * modes:
     *
     * - immediate refresh makes changes immediately visible using
     *   Curses wrefresh().
     * - non-immediate refresh has to prepare for a Curses
     *   doupdate()
     *
     * A refresh is supposed make changes to the screen. Adding
     * text to a curses window, for instance, would be implemented
     * in a refresh.
     *
     * @param immediate @c true indicating an immediate refresh,
     * @c false indicating non-immediate refresh.
     */
    virtual void refresh(bool immediate) = 0;

    /**
     * Resizes the object.
     *
     * How the new Area is interpreted depends on the
     * implementation.
     *
     * @param _a the new Area available to the object.
     *
     * @internal
     *
     * A resize must not refresh. It is usually a sequence of
     * unrealize(), realize().
     */
    virtual void resize(const Area& _a) = 0;

    /**
     * Realize the object by calling Curses functions and prepare
     * the object for a refresh.
     *
     * Realize is supposed to create curses window. It should not
     * be used for adding text for instance. Adding text and
     * related operations would be implemented in refresh().
     */
    virtual void realize() = 0;

    /**
     * Unrealize the object again.
     */
    virtual void unrealize() = 0;

    /**
     * Get the realization state of the object.
     *
     * @return the realization state.
     */
    REALIZATION_STATE realization() const;
};
}  // namespace YACURS

/**
 * @relates YACURS::Realizeable
 *
 * This macro should be used when implementing realize(). It has to be
 * called first. It will ensure that the REALIZATION_STATE is set
 * properly when REALIZE_LEAVE is called.
 *
 * The main purpose this macro exists, is that derrived classes don't
 * have to rewrite the logic for maintaining proper realization
 * state. For instance, the following pseudo code should always yield
 * the proper realization state, regardless whether or not
 * A::realize() or B::realize() is called, i.e. as long as the first
 * call to realize() is not finished, the state has to be REALIZING.
 *
 * <pre>
 *  void A::realize() {
 *    REALIZE_ENTER;
 *
 *    // Object realization_state() == REALIZING
 *
 *    REALIZE_LEAVE;
 *  }
 *
 *  void B::realize() {
 *    REALIZE_ENTER;
 *
 *    A::realize();
 *
 *    // Object realization_state() == REALIZING
 *
 *    REALIZE_LEAVE;
 * </pre>
 */
#define REALIZE_ENTER                          \
    bool __was_realizing_on_enter__ = false;   \
    switch (realization()) {                   \
        case REALIZED:                         \
        case UNREALIZING:                      \
            return;                            \
        case UNREALIZED:                       \
            realization(REALIZING);            \
            break;                             \
        case REALIZING:                        \
            __was_realizing_on_enter__ = true; \
            break;                             \
        default:                               \
            assert(0);                         \
            break;                             \
    }

/**
 * @relates YACURS::Realizeable
 *
 * Helper macro to be used in realize()
 *
 * Has to be the last call in realize(). It ensures that the
 * realization state is set properly.
 *
 * @warning if realize() has to be left due to error condition, do not
 * use REALIZE_LEAVE, instead set realization() to the proper
 * realization state (which, in that case, is most likely @c
 * UNREALIZED).
 */
#define REALIZE_LEAVE \
    if (!__was_realizing_on_enter__) realization(REALIZED);

/**
 * @relates YACURS::Realizeable
 *
 * The same purpose as REALIZE_ENTER.
 */
#define UNREALIZE_ENTER                          \
    bool __was_unrealizing_on_enter__ = false;   \
    switch (realization()) {                     \
        case REALIZED:                           \
            realization(UNREALIZING);            \
            break;                               \
        case UNREALIZING:                        \
            __was_unrealizing_on_enter__ = true; \
            break;                               \
        case UNREALIZED:                         \
        case REALIZING:                          \
            return;                              \
        default:                                 \
            assert(0);                           \
            break;                               \
    }

/**
 * @relates YACURS::Realizeable
 *
 * The same purpose as REALIZE_LEAVE.
 */
#define UNREALIZE_LEAVE \
    if (!__was_unrealizing_on_enter__) realization(UNREALIZED);

#endif  // REALIZEABLE_H