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