SDL

Форк
0
/
SDL_haikudialog.cc 
259 строк · 7.6 Кб
1
/*
2
  Simple DirectMedia Layer
3
  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
4

5
  This software is provided 'as-is', without any express or implied
6
  warranty.  In no event will the authors be held liable for any damages
7
  arising from the use of this software.
8

9
  Permission is granted to anyone to use this software for any purpose,
10
  including commercial applications, and to alter it and redistribute it
11
  freely, subject to the following restrictions:
12

13
  1. The origin of this software must not be misrepresented; you must not
14
     claim that you wrote the original software. If you use this software
15
     in a product, an acknowledgment in the product documentation would be
16
     appreciated but is not required.
17
  2. Altered source versions must be plainly marked as such, and must not be
18
     misrepresented as being the original software.
19
  3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "SDL_internal.h"
22
extern "C" {
23
#include "../SDL_dialog_utils.h"
24
}
25
#include "../../core/haiku/SDL_BeApp.h"
26

27
#include <string>
28
#include <vector>
29

30
#include <sys/stat.h>
31

32
#include <FilePanel.h>
33
#include <Entry.h>
34
#include <Looper.h>
35
#include <Messenger.h>
36
#include <Path.h>
37
#include <TypeConstants.h>
38

39
bool StringEndsWith(const std::string& str, const std::string& end)
40
{
41
    return str.size() >= end.size() && !str.compare(str.size() - end.size(), end.size(), end);
42
}
43

44
std::vector<std::string> StringSplit(const std::string& str, const std::string& split)
45
{
46
    std::vector<std::string> result;
47
    std::string s = str;
48
    size_t pos = 0;
49

50
    while ((pos = s.find(split)) != std::string::npos) {
51
        result.push_back(s.substr(0, pos));
52
        s = s.substr(pos + split.size());
53
    }
54

55
    result.push_back(s);
56

57
    return result;
58
}
59

60
class SDLBRefFilter : public BRefFilter
61
{
62
public:
63
    SDLBRefFilter(const SDL_DialogFileFilter *filters, int nfilters) :
64
        BRefFilter(),
65
        m_filters(filters),
66
        m_nfilters(nfilters)
67
    {
68
    }
69

70
    virtual bool Filter(const entry_ref *ref, BNode *node, struct stat_beos *stat, const char *mimeType) override
71
    {
72
        BEntry entry(ref);
73
        BPath path;
74
        entry.GetPath(&path);
75
        std::string result = path.Path();
76

77
        if (!m_filters)
78
            return true;
79

80
        struct stat info;
81
        node->GetStat(&info);
82
        if (S_ISDIR(info.st_mode))
83
            return true;
84

85
        for (int i = 0; i < m_nfilters; i++) {
86
            for (const auto& suffix : StringSplit(m_filters[i].pattern, ";")) {
87
                if (StringEndsWith(result, std::string(".") + suffix)) {
88
                    return true;
89
                }
90
            }
91
        }
92

93
        return false;
94
    }
95

96
private:
97
    const SDL_DialogFileFilter * const m_filters;
98
    int m_nfilters;
99
};
100

101
class CallbackLooper : public BLooper
102
{
103
public:
104
    CallbackLooper(SDL_DialogFileCallback callback, void *userdata) :
105
        m_callback(callback),
106
        m_userdata(userdata),
107
        m_files(),
108
        m_messenger(),
109
        m_panel(),
110
        m_filter()
111
    {
112
    }
113

114
    ~CallbackLooper()
115
    {
116
        delete m_messenger;
117
        delete m_panel;
118
        delete m_filter;
119
    }
120

121
    void SetToBeFreed(BMessenger *messenger, BFilePanel *panel, SDLBRefFilter *filter)
122
    {
123
        m_messenger = messenger;
124
        m_panel = panel;
125
        m_filter = filter;
126
    }
127

128
    virtual void MessageReceived(BMessage *msg) override
129
    {
130
        entry_ref file;
131
        BPath path;
132
        BEntry entry;
133
        std::string result;
134
        const char *filename;
135
        int32 nFiles = 0;
136

137
        switch (msg->what)
138
        {
139
        case B_REFS_RECEIVED: // Open
140
            msg->GetInfo("refs", NULL, &nFiles);
141
            for (int i = 0; i < nFiles; i++) {
142
                msg->FindRef("refs", i, &file);
143
                entry.SetTo(&file);
144
                entry.GetPath(&path);
145
                result = path.Path();
146
                m_files.push_back(result);
147
            }
148
            break;
149

150
        case B_SAVE_REQUESTED: // Save
151
            msg->FindRef("directory", &file);
152
            entry.SetTo(&file);
153
            entry.GetPath(&path);
154
            result = path.Path();
155
            result += "/";
156
            msg->FindString("name", &filename);
157
            result += filename;
158
            m_files.push_back(result);
159
            break;
160

161
        case B_CANCEL: // Whenever the dialog is closed (Cancel but also after Open and Save)
162
        {
163
            nFiles = m_files.size();
164
            const char* files[nFiles + 1];
165
            for (int i = 0; i < nFiles; i++) {
166
                files[i] = m_files[i].c_str();
167
            }
168
            files[nFiles] = NULL;
169
            m_callback(m_userdata, files, -1);
170
            Quit();
171
            SDL_QuitBeApp();
172
            delete this;
173
        }
174
            break;
175

176
        default:
177
            BHandler::MessageReceived(msg);
178
            break;
179
        }
180
    }
181

182
private:
183
    SDL_DialogFileCallback m_callback;
184
    void *m_userdata;
185
    std::vector<std::string> m_files;
186

187
    // Only to free stuff later
188
    BMessenger *m_messenger;
189
    BFilePanel *m_panel;
190
    SDLBRefFilter *m_filter;
191
};
192

193
void ShowDialog(bool save, SDL_DialogFileCallback callback, void *userdata, bool many, bool modal, const SDL_DialogFileFilter *filters, int nfilters, bool folder, const char *location)
194
{
195
    if (!SDL_InitBeApp()) {
196
        char* err = SDL_strdup(SDL_GetError());
197
        SDL_SetError("Couldn't init Be app: %s", err);
198
        SDL_free(err);
199
        callback(userdata, NULL, -1);
200
        return;
201
    }
202

203
    if (filters) {
204
        const char *msg = validate_filters(filters, nfilters);
205

206
        if (msg) {
207
            SDL_SetError("%s", msg);
208
            callback(userdata, NULL, -1);
209
            return;
210
        }
211
    }
212

213
    if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) {
214
        SDL_SetError("File dialog driver unsupported");
215
        callback(userdata, NULL, -1);
216
        return;
217
    }
218

219
    // No unique_ptr's because they need to survive the end of the function
220
    CallbackLooper *looper = new(std::nothrow) CallbackLooper(callback, userdata);
221
    BMessenger *messenger = new(std::nothrow) BMessenger(NULL, looper);
222
    SDLBRefFilter *filter = new(std::nothrow) SDLBRefFilter(filters, nfilters);
223

224
    if (looper == NULL || messenger == NULL || filter == NULL) {
225
        SDL_free(looper);
226
        SDL_free(messenger);
227
        SDL_free(filter);
228
        SDL_OutOfMemory();
229
        callback(userdata, NULL, -1);
230
        return;
231
    }
232

233
    BEntry entry;
234
    entry_ref entryref;
235
    if (location) {
236
        entry.SetTo(location);
237
        entry.GetRef(&entryref);
238
    }
239

240
    BFilePanel *panel = new BFilePanel(save ? B_SAVE_PANEL : B_OPEN_PANEL, messenger, location ? &entryref : NULL, folder ? B_DIRECTORY_NODE : B_FILE_NODE, many, NULL, filter, modal);
241
    looper->SetToBeFreed(messenger, panel, filter);
242
    looper->Run();
243
    panel->Show();
244
}
245

246
void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location, SDL_bool allow_many)
247
{
248
    ShowDialog(false, callback, userdata, allow_many == true, !!window, filters, nfilters, false, default_location);
249
}
250

251
void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location)
252
{
253
    ShowDialog(true, callback, userdata, false, !!window, filters, nfilters, false, default_location);
254
}
255

256
void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char* default_location, SDL_bool allow_many)
257
{
258
    ShowDialog(false, callback, userdata, allow_many == true, !!window, NULL, 0, true, default_location);
259
}
260

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.