]> git.mxchange.org Git - flightgear.git/blob - src/GUI/FileDialog.cxx
FlightRecorder: smarter log warning.
[flightgear.git] / src / GUI / FileDialog.cxx
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
26 #include "FileDialog.hxx"
27
28 #include <boost/shared_ptr.hpp>
29
30 #include <simgear/nasal/cppbind/from_nasal.hxx>
31 #include <simgear/nasal/cppbind/to_nasal.hxx>
32 #include <simgear/nasal/cppbind/NasalHash.hxx>
33
34 #include <Main/globals.hxx>
35 #include <Scripting/NasalSys.hxx>
36 #include "PUIFileDialog.hxx"
37
38 #ifdef SG_MAC
39     #include "CocoaFileDialog.hxx"
40 #endif
41
42 FGFileDialog::FGFileDialog(Usage use) :
43     _usage(use),
44     _showHidden(false)
45 {
46     
47 }
48
49 FGFileDialog::~FGFileDialog()
50 {
51     // ensure this is concrete so callback gets cleaned up.
52 }
53
54 void FGFileDialog::setTitle(const std::string& aText)
55 {
56     _title = aText;
57 }
58
59 void FGFileDialog::setButton(const std::string& aText)
60 {
61     _buttonText = aText;
62 }
63
64 void FGFileDialog::setDirectory(const SGPath& aPath)
65 {
66     _initialPath = aPath;
67 }
68
69 void FGFileDialog::setFilterPatterns(const string_list& patterns)
70 {
71     _filterPatterns = patterns;
72 }
73
74 void FGFileDialog::setPlaceholderName(const std::string& aName)
75 {
76     _placeholder = aName;
77 }
78
79 void FGFileDialog::setCallback(Callback* aCB)
80 {
81     _callback.reset(aCB);
82 }
83
84 void FGFileDialog::setShowHidden(bool show)
85 {
86     _showHidden = show;
87 }
88
89 naRef FGFileDialog::openFromNasal(const nasal::CallContext& ctx)
90 {
91     exec();
92     return naNil();
93 }
94
95 naRef FGFileDialog::closeFromNasal(const nasal::CallContext& ctx)
96 {
97     close();
98     return naNil();
99 }
100
101 class NasalCallback : public FGFileDialog::Callback
102 {
103 public:
104     NasalCallback(naRef f, naRef obj) :
105         func(f),
106         object(obj)
107     {
108         FGNasalSys* sys = static_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
109         _gcKeys[0] = sys->gcSave(f);
110         _gcKeys[1] = sys->gcSave(obj);
111     }
112     
113     virtual void onFileDialogDone(FGFileDialog* instance, const SGPath& aPath)
114     {
115         FGNasalSys* sys = static_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
116         naContext ctx = sys->context();
117         
118         naRef args[1];
119         args[0] = nasal::to_nasal(ctx, aPath);
120         
121         sys->callMethod(func, object, 1, args, naNil() /* locals */);
122     }
123     
124     ~NasalCallback()
125     {
126         FGNasalSys* sys = static_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
127         sys->gcRelease(_gcKeys[0]);
128         sys->gcRelease(_gcKeys[1]);
129     }
130 private:
131     naRef func;
132     naRef object;
133     int _gcKeys[2];
134 };
135
136 naRef FGFileDialog::setCallbackFromNasal(const nasal::CallContext& ctx)
137 {
138     // wrap up the naFunc in our callback type
139     naRef func = ctx.requireArg<naRef>(0);
140     naRef object = ctx.getArg<naRef>(1, naNil());
141     
142     setCallback(new NasalCallback(func, object));
143     return naNil();
144 }
145
146 typedef boost::shared_ptr<FGFileDialog> FileDialogPtr;
147 typedef nasal::Ghost<FileDialogPtr> NasalFileDialog;
148
149 /**
150  * Create new Canvas and get ghost for it.
151  */
152 static naRef f_createFileDialog(naContext c, naRef me, int argc, naRef* args)
153 {
154     nasal::CallContext ctx(c, argc, args);
155     FGFileDialog::Usage usage = (FGFileDialog::Usage) ctx.requireArg<int>(0);
156   
157 #ifdef SG_MAC
158     FileDialogPtr fd(new CocoaFileDialog(usage));
159 #else
160     FileDialogPtr fd(new PUIFileDialog(usage));
161 #endif
162     
163     return NasalFileDialog::create(c, fd);
164 }
165
166 void postinitNasalGUI(naRef globals, naContext c)
167 {
168     NasalFileDialog::init("gui._FileDialog")
169     .member("title", &FGFileDialog::getTitle,  &FGFileDialog::setTitle)
170     .member("button", &FGFileDialog::getButton,  &FGFileDialog::setButton)
171     .member("directory", &FGFileDialog::getDirectory, &FGFileDialog::setDirectory)
172     .member("show_hidden", &FGFileDialog::showHidden, &FGFileDialog::setShowHidden)
173     .member("placeholder", &FGFileDialog::getPlaceholder, &FGFileDialog::setPlaceholderName)
174     .member("pattern", &FGFileDialog::filterPatterns, &FGFileDialog::setFilterPatterns)
175     .method<&FGFileDialog::openFromNasal>("open")
176     .method<&FGFileDialog::closeFromNasal>("close")
177     .method<&FGFileDialog::setCallbackFromNasal>("setCallback");
178
179     nasal::Hash guiModule = nasal::Hash(globals, c).get<nasal::Hash>("gui");
180     
181     guiModule.set("FILE_DIALOG_OPEN_FILE", (int) FGFileDialog::USE_OPEN_FILE);
182     guiModule.set("FILE_DIALOG_SAVE_FILE", (int) FGFileDialog::USE_SAVE_FILE);
183     guiModule.set("FILE_DIALOG_CHOOSE_DIR", (int) FGFileDialog::USE_CHOOSE_DIR);
184     guiModule.set("_createFileDialog", f_createFileDialog);
185 }