Atlas - SDL_haikudialog.cc

Home / ext / SDL / src / dialog / haiku Lines: 1 | Size: 8496 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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" 22extern "C" { 23#include "../SDL_dialog.h" 24#include "../SDL_dialog_utils.h" 25} 26#include "../../core/haiku/SDL_BeApp.h" 27#include "../../video/haiku/SDL_BWin.h" 28 29#include <string> 30#include <vector> 31 32#include <sys/stat.h> 33 34#include <FilePanel.h> 35#include <Entry.h> 36#include <Looper.h> 37#include <Messenger.h> 38#include <Path.h> 39#include <TypeConstants.h> 40 41bool StringEndsWith(const std::string& str, const std::string& end) 42{ 43 return str.size() >= end.size() && !str.compare(str.size() - end.size(), end.size(), end); 44} 45 46std::vector<std::string> StringSplit(const std::string& str, const std::string& split) 47{ 48 std::vector<std::string> result; 49 std::string s = str; 50 size_t pos = 0; 51 52 while ((pos = s.find(split)) != std::string::npos) { 53 result.push_back(s.substr(0, pos)); 54 s = s.substr(pos + split.size()); 55 } 56 57 result.push_back(s); 58 59 return result; 60} 61 62class SDLBRefFilter : public BRefFilter 63{ 64public: 65 SDLBRefFilter(const SDL_DialogFileFilter *filters, int nfilters) : 66 BRefFilter(), 67 m_filters(filters), 68 m_nfilters(nfilters) 69 { 70 } 71 72 virtual bool Filter(const entry_ref *ref, BNode *node, struct stat_beos *stat, const char *mimeType) override 73 { 74 BEntry entry(ref); 75 BPath path; 76 entry.GetPath(&path); 77 std::string result = path.Path(); 78 79 if (!m_filters) 80 return true; 81 82 struct stat info; 83 node->GetStat(&info); 84 if (S_ISDIR(info.st_mode)) 85 return true; 86 87 for (int i = 0; i < m_nfilters; i++) { 88 for (const auto& suffix : StringSplit(m_filters[i].pattern, ";")) { 89 if (StringEndsWith(result, std::string(".") + suffix)) { 90 return true; 91 } 92 } 93 } 94 95 return false; 96 } 97 98private: 99 const SDL_DialogFileFilter * const m_filters; 100 int m_nfilters; 101}; 102 103class CallbackLooper : public BLooper 104{ 105public: 106 CallbackLooper(SDL_DialogFileCallback callback, void *userdata) : 107 m_callback(callback), 108 m_userdata(userdata), 109 m_files(), 110 m_messenger(), 111 m_panel(), 112 m_filter() 113 { 114 } 115 116 ~CallbackLooper() 117 { 118 delete m_messenger; 119 delete m_panel; 120 delete m_filter; 121 } 122 123 void SetToBeFreed(BMessenger *messenger, BFilePanel *panel, SDLBRefFilter *filter) 124 { 125 m_messenger = messenger; 126 m_panel = panel; 127 m_filter = filter; 128 } 129 130 virtual void MessageReceived(BMessage *msg) override 131 { 132 entry_ref file; 133 BPath path; 134 BEntry entry; 135 std::string result; 136 const char *filename; 137 int32 nFiles = 0; 138 139 switch (msg->what) 140 { 141 case B_REFS_RECEIVED: // Open 142 msg->GetInfo("refs", NULL, &nFiles); 143 for (int i = 0; i < nFiles; i++) { 144 msg->FindRef("refs", i, &file); 145 entry.SetTo(&file); 146 entry.GetPath(&path); 147 result = path.Path(); 148 m_files.push_back(result); 149 } 150 break; 151 152 case B_SAVE_REQUESTED: // Save 153 msg->FindRef("directory", &file); 154 entry.SetTo(&file); 155 entry.GetPath(&path); 156 result = path.Path(); 157 result += "/"; 158 msg->FindString("name", &filename); 159 result += filename; 160 m_files.push_back(result); 161 break; 162 163 case B_CANCEL: // Whenever the dialog is closed (Cancel but also after Open and Save) 164 { 165 nFiles = m_files.size(); 166 const char *files[nFiles + 1]; 167 for (int i = 0; i < nFiles; i++) { 168 files[i] = m_files[i].c_str(); 169 } 170 files[nFiles] = NULL; 171 m_callback(m_userdata, files, -1); 172 Quit(); 173 SDL_QuitBeApp(); 174 delete this; 175 } 176 break; 177 178 default: 179 BHandler::MessageReceived(msg); 180 break; 181 } 182 } 183 184private: 185 SDL_DialogFileCallback m_callback; 186 void *m_userdata; 187 std::vector<std::string> m_files; 188 189 // Only to free stuff later 190 BMessenger *m_messenger; 191 BFilePanel *m_panel; 192 SDLBRefFilter *m_filter; 193}; 194 195void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props) 196{ 197 SDL_Window *window = (SDL_Window *)SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL); 198 SDL_DialogFileFilter *filters = (SDL_DialogFileFilter *)SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL); 199 int nfilters = (int) SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0); 200 bool many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false); 201 const char *location = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, NULL); 202 const char *title = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_TITLE_STRING, NULL); 203 const char *accept = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_ACCEPT_STRING, NULL); 204 const char *cancel = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_CANCEL_STRING, NULL); 205 206 bool modal = !!window; 207 208 bool save = false; 209 bool folder = false; 210 211 switch (type) { 212 case SDL_FILEDIALOG_SAVEFILE: 213 save = true; 214 break; 215 216 case SDL_FILEDIALOG_OPENFILE: 217 break; 218 219 case SDL_FILEDIALOG_OPENFOLDER: 220 folder = true; 221 break; 222 }; 223 224 if (!SDL_InitBeApp()) { 225 char *err = SDL_strdup(SDL_GetError()); 226 SDL_SetError("Couldn't init Be app: %s", err); 227 SDL_free(err); 228 callback(userdata, NULL, -1); 229 return; 230 } 231 232 if (filters) { 233 const char *msg = validate_filters(filters, nfilters); 234 235 if (msg) { 236 SDL_SetError("%s", msg); 237 callback(userdata, NULL, -1); 238 return; 239 } 240 } 241 242 if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) { 243 SDL_SetError("File dialog driver unsupported"); 244 callback(userdata, NULL, -1); 245 return; 246 } 247 248 // No unique_ptr's because they need to survive the end of the function 249 CallbackLooper *looper = new(std::nothrow) CallbackLooper(callback, userdata); 250 BMessenger *messenger = new(std::nothrow) BMessenger(NULL, looper); 251 SDLBRefFilter *filter = new(std::nothrow) SDLBRefFilter(filters, nfilters); 252 253 if (looper == NULL || messenger == NULL || filter == NULL) { 254 delete looper; 255 delete messenger; 256 delete filter; 257 SDL_OutOfMemory(); 258 callback(userdata, NULL, -1); 259 return; 260 } 261 262 BEntry entry; 263 entry_ref entryref; 264 if (location) { 265 entry.SetTo(location); 266 entry.GetRef(&entryref); 267 } 268 269 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); 270 271 if (title) { 272 panel->Window()->SetTitle(title); 273 } 274 275 if (accept) { 276 panel->SetButtonLabel(B_DEFAULT_BUTTON, accept); 277 } 278 279 if (cancel) { 280 panel->SetButtonLabel(B_CANCEL_BUTTON, cancel); 281 } 282 283 if (window) { 284 SDL_BWin *bwin = (SDL_BWin *)(window->internal); 285 panel->Window()->SetLook(B_MODAL_WINDOW_LOOK); 286 panel->Window()->SetFeel(B_MODAL_SUBSET_WINDOW_FEEL); 287 panel->Window()->AddToSubset(bwin); 288 } 289 290 looper->SetToBeFreed(messenger, panel, filter); 291 looper->Run(); 292 panel->Show(); 293} 294
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.