FlightGear next
FileDialog.cxx
Go to the documentation of this file.
1// FileDialog -- generic FileDialog interface and Nasal wrapper
2//
3// Written by James Turner, started 2012.
4//
5// Copyright (C) 2012 James Turner <zakalawe@mac.com>
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License as
9// published by the Free Software Foundation; either version 2 of the
10// License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful, but
13// WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15// General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
21#ifdef HAVE_CONFIG_H
22# include "config.h"
23#endif
24
25#include "FileDialog.hxx"
26
27#include <simgear/nasal/cppbind/Ghost.hxx>
28
29#include <Main/globals.hxx>
31
32#if defined(SG_MAC)
33 #include "CocoaFileDialog.hxx"
34#endif
35
36#if defined(HAVE_QT)
37 #include "QtFileDialog.hxx"
38#endif
39
41 _usage(use),
42 _showHidden(false)
43{
44
45}
46
48{
49 // ensure this is concrete so callback gets cleaned up.
50}
51
52void FGFileDialog::setTitle(const std::string& aText)
53{
54 _title = aText;
55}
56
57void FGFileDialog::setButton(const std::string& aText)
58{
59 _buttonText = aText;
60}
61
62void FGFileDialog::setDirectory(const SGPath& aPath)
63{
64 _initialPath = aPath;
65}
66
68{
69 _filterPatterns = patterns;
70}
71
72void FGFileDialog::setPlaceholderName(const std::string& aName)
73{
74 _placeholder = aName;
75}
76
78{
79 _callback.reset(aCB);
80}
81
83{
84 _showHidden = show;
85}
86
88{
89public:
90 NasalCallback(naRef f, naRef obj) :
91 func(f),
92 object(obj)
93 {
94 auto sys = globals->get_subsystem<FGNasalSys>();
95 _gcKeys[0] = sys->gcSave(f);
96 _gcKeys[1] = sys->gcSave(obj);
97 }
98
99 void onFileDialogDone(FGFileDialog* instance, const SGPath& aPath) override
100 {
101 auto sys = globals->get_subsystem<FGNasalSys>();
102
103 naContext ctx = naNewContext();
104 naRef args[1];
105 args[0] = nasal::to_nasal(ctx, aPath);
106
107 sys->callMethod(func, object, 1, args, naNil() /* locals */);
108 naFreeContext(ctx);
109 }
110
112 {
113 auto sys = globals->get_subsystem<FGNasalSys>();
114 if (!sys) // happens during Nasal shutdown on reset
115 return;
116
117 sys->gcRelease(_gcKeys[0]);
118 sys->gcRelease(_gcKeys[1]);
119 }
120private:
121 naRef func;
122 naRef object;
123 int _gcKeys[2];
124};
125
126void FGFileDialog::setCallbackFromNasal(const nasal::CallContext& ctx)
127{
128 // wrap up the naFunc in our callback type
129 naRef func = ctx.requireArg<naRef>(0);
130 naRef object = ctx.getArg<naRef>(1, naNil());
131
132 setCallback(new NasalCallback(func, object));
133}
134
135typedef std::shared_ptr<FGFileDialog> FileDialogPtr;
136typedef nasal::Ghost<FileDialogPtr> NasalFileDialog;
137
141static naRef f_createFileDialog(const nasal::CallContext& ctx)
142{
143 FGFileDialog::Usage usage = (FGFileDialog::Usage) ctx.requireArg<int>(0);
144
145#if defined(SG_MAC)
147#elif defined(HAVE_QT)
149#else
150 // we need a fallback implementation
151 FileDialogPtr fd;
152#endif
153
154 return ctx.to_nasal(fd);
155}
156
157void postinitNasalGUI(naRef globals, naContext c)
158{
159 NasalFileDialog::init("gui._FileDialog")
166 .method("open", &FGFileDialog::exec)
167 .method("close", &FGFileDialog::close)
168 .method("setCallback", &FGFileDialog::setCallbackFromNasal);
169
170 nasal::Hash guiModule = nasal::Hash(globals, c).get<nasal::Hash>("gui");
171
172 guiModule.set("FILE_DIALOG_OPEN_FILE", (int) FGFileDialog::USE_OPEN_FILE);
173 guiModule.set("FILE_DIALOG_SAVE_FILE", (int) FGFileDialog::USE_SAVE_FILE);
174 guiModule.set("FILE_DIALOG_CHOOSE_DIR", (int) FGFileDialog::USE_CHOOSE_DIR);
175 guiModule.set("_createFileDialog", f_createFileDialog);
176}
nasal::Ghost< FileDialogPtr > NasalFileDialog
void postinitNasalGUI(naRef globals, naContext c)
std::shared_ptr< FGFileDialog > FileDialogPtr
static naRef f_createFileDialog(const nasal::CallContext &ctx)
Create new FGFileDialog and get ghost for it.
SGPath _initialPath
std::string getTitle() const
string_list _filterPatterns
void setDirectory(const SGPath &aPath)
void setButton(const std::string &aText)
void setPlaceholderName(const std::string &aName)
FGFileDialog(Usage use)
virtual void close()=0
virtual void exec()=0
void setShowHidden(bool show)
void setTitle(const std::string &aTitle)
string_list filterPatterns() const
bool showHidden() const
std::string _buttonText
const Usage _usage
std::string getButton() const
void setCallbackFromNasal(const nasal::CallContext &ctx)
SGPath getDirectory() const
std::string _placeholder
std::string getPlaceholder() const
for saving
std::unique_ptr< Callback > _callback
std::string _title
virtual ~FGFileDialog()
Destructor.
virtual void setCallback(Callback *aCB)
void setFilterPatterns(const string_list &patterns)
int gcSave(naRef r)
void gcRelease(int key)
NasalCallback(naRef f, naRef obj)
void onFileDialogDone(FGFileDialog *instance, const SGPath &aPath) override
FGGlobals * globals
Definition globals.cxx:142
std::vector< std::string > string_list
Definition globals.hxx:36
naCFunction func
int usage()