Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
3
 * It is copyright by its individual contributors, as recorded in the
4
 * project's Git history.  See COPYING.txt at the top level for license
5
 * terms and a link to the Git history.
6
 */
7
/*
8
 *  A 'window' is simply a canvas that can receive events.
9
 *  It can be anything from a simple message box to the
10
 *      game screen when playing.
11
 *
12
 *  See event.c for event handling code.
13
 *
14
 *      -kreator 2009-05-06
15
 */
16
 
17
#include "gr.h"
18
#include "window.h"
19
#include "u_mem.h"
20
#include "dxxerror.h"
21
#include "event.h"
22
 
23
namespace dcx {
24
 
25
static window *FrontWindow = nullptr;
26
static window *FirstWindow = nullptr;
27
 
28
window::window(grs_canvas &src, const int x, const int y, const int w, const int h) :
29
        // Default to visible and modal
30
        w_visible(1), w_modal(1), prev(FrontWindow), next(nullptr), w_exists(nullptr)
31
{
32
        gr_init_sub_canvas(w_canv, src, x, y, w, h);
33
 
34
        if (FirstWindow == nullptr)
35
                FirstWindow = this;
36
}
37
 
38
void window::send_creation_events(const void *const createdata)
39
{
40
        const auto prev_front = window_get_front();
41
        if (FrontWindow)
42
                FrontWindow->next = this;
43
        FrontWindow = this;
44
        if (prev_front)
45
        {
46
                const d_event event{EVENT_WINDOW_DEACTIVATED};
47
                WINDOW_SEND_EVENT(prev_front);
48
        }
49
        {
50
                const d_create_event event{EVENT_WINDOW_CREATED, createdata};
51
                WINDOW_SEND_EVENT(this);
52
        }
53
        {
54
                const d_event event{EVENT_WINDOW_ACTIVATED};
55
                WINDOW_SEND_EVENT(this);
56
        }
57
}
58
 
59
window::~window()
60
{
61
        if (w_exists)
62
                *w_exists = false;
63
        if (this == FrontWindow)
64
                FrontWindow = this->prev;
65
        if (this == FirstWindow)
66
                FirstWindow = this->next;
67
        if (this->next)
68
                this->next->prev = this->prev;
69
        if (this->prev)
70
                this->prev->next = this->next;
71
}
72
 
73
callback_window::callback_window(grs_canvas &src, const int x, const int y, const int w, const int h, const window_subfunction<void> event_callback, void *const data) :
74
        window(src, x, y, w, h),
75
        w_callback((assert(event_callback != nullptr), event_callback)), w_data(data)
76
{
77
}
78
 
79
window_event_result callback_window::event_handler(const d_event &event)
80
{
81
        return w_callback(this, event, w_data);
82
}
83
 
84
int window_close(window *wind)
85
{
86
        window *prev;
87
        window_event_result result;
88
 
89
        if (wind == window_get_front())
90
        {
91
                const d_event event{EVENT_WINDOW_DEACTIVATED};
92
                WINDOW_SEND_EVENT(wind);        // Deactivate first
93
        }
94
 
95
        {
96
                const d_event event{EVENT_WINDOW_CLOSE};
97
                result = WINDOW_SEND_EVENT(wind);
98
        }
99
        if (result == window_event_result::handled)
100
        {
101
                // User 'handled' the event, cancelling close
102
                if (wind == window_get_front())
103
                {
104
                        const d_event event{EVENT_WINDOW_ACTIVATED};
105
                        WINDOW_SEND_EVENT(wind);
106
                }
107
                return 0;
108
        }
109
 
110
        menu_destroy_hook(wind);
111
 
112
        if (result != window_event_result::deleted)     // don't attempt to re-delete
113
                delete wind;
114
 
115
        if ((prev = window_get_front()))
116
        {
117
                const d_event event{EVENT_WINDOW_ACTIVATED};
118
                WINDOW_SEND_EVENT(prev);
119
        }
120
 
121
        return 1;
122
}
123
 
124
// Get the top window that's visible
125
window *window_get_front(void)
126
{
127
        window *wind;
128
 
129
        for (wind = FrontWindow; (wind != NULL) && !wind->w_visible; wind = wind->prev) {}
130
 
131
        return wind;
132
}
133
 
134
window *window_get_first(void)
135
{
136
        return FirstWindow;
137
}
138
 
139
// Make wind the front window
140
void window_select(window &wind)
141
{
142
        window *prev = window_get_front();
143
        if (&wind == FrontWindow)
144
                return;
145
        if (&wind == FirstWindow && wind.next)
146
                FirstWindow = FirstWindow->next;
147
 
148
        if (wind.next)
149
                wind.next->prev = wind.prev;
150
        if (wind.prev)
151
                wind.prev->next = wind.next;
152
        wind.prev = FrontWindow;
153
        FrontWindow->next = &wind;
154
        wind.next = nullptr;
155
        FrontWindow = &wind;
156
 
157
        if (wind.is_visible())
158
        {
159
                if (prev)
160
                {
161
                        const d_event event{EVENT_WINDOW_DEACTIVATED};
162
                        WINDOW_SEND_EVENT(prev);
163
                }
164
                const d_event event{EVENT_WINDOW_ACTIVATED};
165
                WINDOW_SEND_EVENT(&wind);
166
        }
167
}
168
 
169
window *window_set_visible(window &w, int visible)
170
{
171
        window *prev = window_get_front();
172
        w.w_visible = visible;
173
        auto wind = window_get_front(); // get the new front window
174
        if (wind == prev)
175
                return wind;
176
 
177
        if (prev)
178
        {
179
                const d_event event{EVENT_WINDOW_DEACTIVATED};
180
                WINDOW_SEND_EVENT(prev);
181
        }
182
 
183
        if (wind)
184
        {
185
                const d_event event{EVENT_WINDOW_ACTIVATED};
186
                WINDOW_SEND_EVENT(wind);
187
        }
188
        return wind;
189
}
190
 
191
#if !DXX_USE_OGL
192
void window_update_canvases()
193
{
194
        window *wind;
195
 
196
        for (wind = FirstWindow; wind != NULL; wind = wind->next)
197
                gr_init_sub_bitmap (wind->w_canv.cv_bitmap,
198
                                                        *wind->w_canv.cv_bitmap.bm_parent,
199
                                                        wind->w_canv.cv_bitmap.bm_x,
200
                                                        wind->w_canv.cv_bitmap.bm_y,
201
                                                        wind->w_canv.cv_bitmap.bm_w,
202
                                                        wind->w_canv.cv_bitmap.bm_h);
203
}
204
#endif
205
 
206
}