Finish refactoring of platform code.
This commit finally unifies all main() functions and moves the few remaining application-wide functions where they belong.pull/339/head
parent
350d2ad211
commit
5853fa0421
|
@ -20,10 +20,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(util_SOURCES
|
set(util_SOURCES
|
||||||
platform/w32util.cpp)
|
platform/utilwin.cpp)
|
||||||
else()
|
else()
|
||||||
set(util_SOURCES
|
set(util_SOURCES
|
||||||
platform/unixutil.cpp)
|
platform/utilunix.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
@ -102,11 +102,13 @@ else()
|
||||||
message(FATAL_ERROR "Unsupported OpenGL version ${OPENGL}")
|
message(FATAL_ERROR "Unsupported OpenGL version ${OPENGL}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(platform_SOURCES
|
||||||
|
${gl_SOURCES}
|
||||||
|
platform/entrygui.cpp)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(platform_SOURCES
|
list(APPEND platform_SOURCES
|
||||||
platform/w32main.cpp
|
platform/guiwin.cpp)
|
||||||
platform/guiwin.cpp
|
|
||||||
${gl_SOURCES})
|
|
||||||
|
|
||||||
set(platform_LIBRARIES
|
set(platform_LIBRARIES
|
||||||
comctl32
|
comctl32
|
||||||
|
@ -115,16 +117,12 @@ elseif(APPLE)
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
-fobjc-arc)
|
-fobjc-arc)
|
||||||
|
|
||||||
set(platform_SOURCES
|
list(APPEND platform_SOURCES
|
||||||
platform/cocoamain.mm
|
|
||||||
platform/guimac.mm
|
|
||||||
render/rendergl.cpp
|
render/rendergl.cpp
|
||||||
${gl_SOURCES})
|
platform/guimac.mm)
|
||||||
else()
|
else()
|
||||||
set(platform_SOURCES
|
list(APPEND platform_SOURCES
|
||||||
platform/gtkmain.cpp
|
platform/guigtk.cpp)
|
||||||
platform/guigtk.cpp
|
|
||||||
${gl_SOURCES})
|
|
||||||
|
|
||||||
set(platform_LIBRARIES
|
set(platform_LIBRARIES
|
||||||
${SPACEWARE_LIBRARIES})
|
${SPACEWARE_LIBRARIES})
|
||||||
|
@ -137,9 +135,9 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(every_platform_SOURCES
|
set(every_platform_SOURCES
|
||||||
platform/w32main.cpp
|
platform/guiwin.cpp
|
||||||
platform/gtkmain.cpp
|
platform/guigtk.cpp
|
||||||
platform/cocoamain.mm)
|
platform/guimac.mm)
|
||||||
|
|
||||||
# solvespace library
|
# solvespace library
|
||||||
|
|
||||||
|
@ -362,7 +360,7 @@ target_compile_options(solvespace-headless
|
||||||
# solvespace command-line executable
|
# solvespace command-line executable
|
||||||
|
|
||||||
add_executable(solvespace-cli
|
add_executable(solvespace-cli
|
||||||
platform/climain.cpp
|
platform/entrycli.cpp
|
||||||
$<TARGET_PROPERTY:resources,EXTRA_SOURCES>)
|
$<TARGET_PROPERTY:resources,EXTRA_SOURCES>)
|
||||||
|
|
||||||
target_link_libraries(solvespace-cli
|
target_link_libraries(solvespace-cli
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Our main() function, and Cocoa-specific stuff to set up our windows and
|
|
||||||
// otherwise handle our interface to the operating system. Everything
|
|
||||||
// outside platform/... should be standard C++ and OpenGL.
|
|
||||||
//
|
|
||||||
// Copyright 2015 <whitequark@whitequark.org>
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#include "solvespace.h"
|
|
||||||
#import <AppKit/AppKit.h>
|
|
||||||
|
|
||||||
using SolveSpace::dbp;
|
|
||||||
|
|
||||||
/* Miscellanea */
|
|
||||||
|
|
||||||
void SolveSpace::OpenWebsite(const char *url) {
|
|
||||||
[[NSWorkspace sharedWorkspace] openURL:
|
|
||||||
[NSURL URLWithString:[NSString stringWithUTF8String:url]]];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SolveSpace::Platform::Path> SolveSpace::GetFontFiles() {
|
|
||||||
std::vector<SolveSpace::Platform::Path> fonts;
|
|
||||||
|
|
||||||
NSArray *fontNames = [[NSFontManager sharedFontManager] availableFonts];
|
|
||||||
for(NSString *fontName in fontNames) {
|
|
||||||
CTFontDescriptorRef fontRef =
|
|
||||||
CTFontDescriptorCreateWithNameAndSize ((__bridge CFStringRef)fontName, 10.0);
|
|
||||||
CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute);
|
|
||||||
NSString *fontPath = [NSString stringWithString:[(NSURL *)CFBridgingRelease(url) path]];
|
|
||||||
fonts.push_back(
|
|
||||||
Platform::Path::From([[NSFileManager defaultManager]
|
|
||||||
fileSystemRepresentationWithPath:fontPath]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return fonts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Application lifecycle */
|
|
||||||
|
|
||||||
@interface ApplicationDelegate : NSObject<NSApplicationDelegate>
|
|
||||||
- (IBAction)preferences:(id)sender;
|
|
||||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename;
|
|
||||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation ApplicationDelegate
|
|
||||||
- (IBAction)preferences:(id)sender {
|
|
||||||
SolveSpace::SS.TW.GoToScreen(SolveSpace::TextWindow::Screen::CONFIGURATION);
|
|
||||||
SolveSpace::SS.ScheduleShowTW();
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename {
|
|
||||||
SolveSpace::Platform::Path path = SolveSpace::Platform::Path::From([filename UTF8String]);
|
|
||||||
return SolveSpace::SS.Load(path.Expand(/*fromCurrentDirectory=*/true));
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
|
|
||||||
[[[NSApp mainWindow] delegate] windowShouldClose:nil];
|
|
||||||
return NSTerminateCancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationTerminatePrompt {
|
|
||||||
SolveSpace::SS.MenuFile(SolveSpace::Command::EXIT);
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
|
||||||
ApplicationDelegate *delegate = [[ApplicationDelegate alloc] init];
|
|
||||||
[[NSApplication sharedApplication] setDelegate:delegate];
|
|
||||||
|
|
||||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:nil topLevelObjects:nil];
|
|
||||||
|
|
||||||
NSArray *languages = [NSLocale preferredLanguages];
|
|
||||||
for(NSString *language in languages) {
|
|
||||||
if(SolveSpace::SetLocale([language UTF8String])) break;
|
|
||||||
}
|
|
||||||
if([languages count] == 0) {
|
|
||||||
SolveSpace::SetLocale("en_US");
|
|
||||||
}
|
|
||||||
|
|
||||||
SolveSpace::Platform::Open3DConnexion();
|
|
||||||
SolveSpace::SS.Init();
|
|
||||||
|
|
||||||
[NSApp run];
|
|
||||||
|
|
||||||
SolveSpace::Platform::Close3DConnexion();
|
|
||||||
SolveSpace::SK.Clear();
|
|
||||||
SolveSpace::SS.Clear();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Our main() function for the graphical interface.
|
||||||
|
//
|
||||||
|
// Copyright 2018 <whitequark@whitequark.org>
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#include "solvespace.h"
|
||||||
|
#if defined(WIN32)
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace SolveSpace;
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
std::vector<std::string> args = InitPlatform(argc, argv);
|
||||||
|
|
||||||
|
Platform::InitGui(argc, argv);
|
||||||
|
Platform::Open3DConnexion();
|
||||||
|
SS.Init();
|
||||||
|
|
||||||
|
if(args.size() >= 2) {
|
||||||
|
if(args.size() > 2) {
|
||||||
|
dbp("Only the first file passed on command line will be opened.");
|
||||||
|
}
|
||||||
|
|
||||||
|
SS.Load(Platform::Path::From(args.back()).Expand(/*fromCurrentDirectory=*/true));
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform::RunGui();
|
||||||
|
|
||||||
|
Platform::Close3DConnexion();
|
||||||
|
SS.Clear();
|
||||||
|
|
||||||
|
SK.Clear();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
|
LPSTR lpCmdLine, INT nCmdShow) {
|
||||||
|
return main(0, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,140 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Our main() function, and GTK2/3-specific stuff to set up our windows and
|
|
||||||
// otherwise handle our interface to the operating system. Everything
|
|
||||||
// outside platform/... should be standard C++ and OpenGL.
|
|
||||||
//
|
|
||||||
// Copyright 2015 <whitequark@whitequark.org>
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <json-c/json_object.h>
|
|
||||||
#include <json-c/json_util.h>
|
|
||||||
|
|
||||||
#include <glibmm/main.h>
|
|
||||||
#include <glibmm/convert.h>
|
|
||||||
#include <giomm/file.h>
|
|
||||||
#include <gdkmm/cursor.h>
|
|
||||||
#include <gtkmm/cssprovider.h>
|
|
||||||
#include <gtkmm/drawingarea.h>
|
|
||||||
#include <gtkmm/glarea.h>
|
|
||||||
#include <gtkmm/scrollbar.h>
|
|
||||||
#include <gtkmm/entry.h>
|
|
||||||
#include <gtkmm/eventbox.h>
|
|
||||||
#include <gtkmm/hvbox.h>
|
|
||||||
#include <gtkmm/fixed.h>
|
|
||||||
#include <gtkmm/adjustment.h>
|
|
||||||
#include <gtkmm/separatormenuitem.h>
|
|
||||||
#include <gtkmm/menuitem.h>
|
|
||||||
#include <gtkmm/checkmenuitem.h>
|
|
||||||
#include <gtkmm/radiomenuitem.h>
|
|
||||||
#include <gtkmm/radiobuttongroup.h>
|
|
||||||
#include <gtkmm/menu.h>
|
|
||||||
#include <gtkmm/menubar.h>
|
|
||||||
#include <gtkmm/filechooserdialog.h>
|
|
||||||
#include <gtkmm/messagedialog.h>
|
|
||||||
#include <gtkmm/main.h>
|
|
||||||
|
|
||||||
#include <cairomm/xlib_surface.h>
|
|
||||||
#include <pangomm/fontdescription.h>
|
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
#include <fontconfig/fontconfig.h>
|
|
||||||
|
|
||||||
#include <GL/glx.h>
|
|
||||||
|
|
||||||
#include "solvespace.h"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
namespace SolveSpace {
|
|
||||||
|
|
||||||
void OpenWebsite(const char *url) {
|
|
||||||
gtk_show_uri(Gdk::Screen::get_default()->gobj(), url, GDK_CURRENT_TIME, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fontconfig is already initialized by GTK */
|
|
||||||
std::vector<Platform::Path> GetFontFiles() {
|
|
||||||
std::vector<Platform::Path> fonts;
|
|
||||||
|
|
||||||
FcPattern *pat = FcPatternCreate();
|
|
||||||
FcObjectSet *os = FcObjectSetBuild(FC_FILE, (char *)0);
|
|
||||||
FcFontSet *fs = FcFontList(0, pat, os);
|
|
||||||
|
|
||||||
for(int i = 0; i < fs->nfont; i++) {
|
|
||||||
FcChar8 *filenameFC = FcPatternFormat(fs->fonts[i], (const FcChar8*) "%{file}");
|
|
||||||
fonts.push_back(Platform::Path::From((const char *)filenameFC));
|
|
||||||
FcStrFree(filenameFC);
|
|
||||||
}
|
|
||||||
|
|
||||||
FcFontSetDestroy(fs);
|
|
||||||
FcObjectSetDestroy(os);
|
|
||||||
FcPatternDestroy(pat);
|
|
||||||
|
|
||||||
return fonts;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
/* It would in principle be possible to judiciously use
|
|
||||||
Glib::filename_{from,to}_utf8, but it's not really worth
|
|
||||||
the effort.
|
|
||||||
The setlocale() call is necessary for Glib::get_charset()
|
|
||||||
to detect the system character set; otherwise it thinks
|
|
||||||
it is always ANSI_X3.4-1968.
|
|
||||||
We set it back to C after all. */
|
|
||||||
setlocale(LC_ALL, "");
|
|
||||||
if(!Glib::get_charset()) {
|
|
||||||
dbp("Sorry, only UTF-8 locales are supported.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
setlocale(LC_ALL, "C");
|
|
||||||
|
|
||||||
/* If we don't do this, gtk_init will set the C standard library
|
|
||||||
locale, and printf will format floats using ",". We will then
|
|
||||||
fail to parse these. Also, many text window lines will become
|
|
||||||
ambiguous. */
|
|
||||||
gtk_disable_setlocale();
|
|
||||||
|
|
||||||
Gtk::Main main(argc, argv);
|
|
||||||
|
|
||||||
// Add our application-specific styles, to override GTK defaults.
|
|
||||||
Glib::RefPtr<Gtk::CssProvider> style_provider = Gtk::CssProvider::create();
|
|
||||||
style_provider->load_from_data(R"(
|
|
||||||
entry {
|
|
||||||
background: white;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
)");
|
|
||||||
Gtk::StyleContext::add_provider_for_screen(Gdk::Screen::get_default(),
|
|
||||||
style_provider,
|
|
||||||
600 /*Gtk::STYLE_PROVIDER_PRIORITY_APPLICATION*/);
|
|
||||||
|
|
||||||
const char* const* langNames = g_get_language_names();
|
|
||||||
while(*langNames) {
|
|
||||||
if(SetLocale(*langNames++)) break;
|
|
||||||
}
|
|
||||||
if(!*langNames) {
|
|
||||||
SetLocale("en_US");
|
|
||||||
}
|
|
||||||
|
|
||||||
SS.Init();
|
|
||||||
|
|
||||||
if(argc >= 2) {
|
|
||||||
if(argc > 2) {
|
|
||||||
dbp("Only the first file passed on command line will be opened.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure the argument is valid UTF-8. */
|
|
||||||
Glib::ustring arg(argv[1]);
|
|
||||||
SS.Load(Platform::Path::From(arg).Expand(/*fromCurrentDirectory=*/true));
|
|
||||||
}
|
|
||||||
|
|
||||||
main.run();
|
|
||||||
|
|
||||||
SK.Clear();
|
|
||||||
SS.Clear();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -359,7 +359,12 @@ FileDialogRef CreateSaveFileDialog(WindowRef parentWindow);
|
||||||
// Application-wide APIs
|
// Application-wide APIs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void Exit();
|
std::vector<Platform::Path> GetFontFiles();
|
||||||
|
void OpenInBrowser(const std::string &url);
|
||||||
|
|
||||||
|
void InitGui(int argc, char **argv);
|
||||||
|
void RunGui();
|
||||||
|
void ExitGui();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <json-c/json_object.h>
|
#include <json-c/json_object.h>
|
||||||
#include <json-c/json_util.h>
|
#include <json-c/json_util.h>
|
||||||
|
#include <glibmm/convert.h>
|
||||||
#include <glibmm/main.h>
|
#include <glibmm/main.h>
|
||||||
#include <gtkmm/box.h>
|
#include <gtkmm/box.h>
|
||||||
#include <gtkmm/checkmenuitem.h>
|
#include <gtkmm/checkmenuitem.h>
|
||||||
|
#include <gtkmm/cssprovider.h>
|
||||||
#include <gtkmm/entry.h>
|
#include <gtkmm/entry.h>
|
||||||
#include <gtkmm/filechooserdialog.h>
|
#include <gtkmm/filechooserdialog.h>
|
||||||
#include <gtkmm/fixed.h>
|
#include <gtkmm/fixed.h>
|
||||||
|
@ -281,7 +283,7 @@ public:
|
||||||
MenuItemImplGtk() : gtkMenuItem(this) {}
|
MenuItemImplGtk() : gtkMenuItem(this) {}
|
||||||
|
|
||||||
void SetAccelerator(KeyboardEvent accel) override {
|
void SetAccelerator(KeyboardEvent accel) override {
|
||||||
guint accelKey;
|
guint accelKey = 0;
|
||||||
if(accel.key == KeyboardEvent::Key::CHARACTER) {
|
if(accel.key == KeyboardEvent::Key::CHARACTER) {
|
||||||
if(accel.chr == '\t') {
|
if(accel.chr == '\t') {
|
||||||
accelKey = GDK_KEY_Tab;
|
accelKey = GDK_KEY_Tab;
|
||||||
|
@ -720,15 +722,14 @@ protected:
|
||||||
class GtkWindow : public Gtk::Window {
|
class GtkWindow : public Gtk::Window {
|
||||||
Platform::Window *_receiver;
|
Platform::Window *_receiver;
|
||||||
Gtk::VBox _vbox;
|
Gtk::VBox _vbox;
|
||||||
Gtk::MenuBar *_menu_bar;
|
Gtk::MenuBar *_menu_bar = NULL;
|
||||||
Gtk::HBox _hbox;
|
Gtk::HBox _hbox;
|
||||||
GtkEditorOverlay _editor_overlay;
|
GtkEditorOverlay _editor_overlay;
|
||||||
Gtk::VScrollbar _scrollbar;
|
Gtk::VScrollbar _scrollbar;
|
||||||
bool _is_fullscreen;
|
bool _is_fullscreen = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GtkWindow(Platform::Window *receiver) :
|
GtkWindow(Platform::Window *receiver) : _receiver(receiver), _editor_overlay(receiver) {
|
||||||
_receiver(receiver), _menu_bar(NULL), _editor_overlay(receiver) {
|
|
||||||
_hbox.pack_start(_editor_overlay, /*expand=*/true, /*fill=*/true);
|
_hbox.pack_start(_editor_overlay, /*expand=*/true, /*fill=*/true);
|
||||||
_hbox.pack_end(_scrollbar, /*expand=*/false, /*fill=*/false);
|
_hbox.pack_end(_scrollbar, /*expand=*/false, /*fill=*/false);
|
||||||
_vbox.pack_end(_hbox, /*expand=*/true, /*fill=*/true);
|
_vbox.pack_end(_hbox, /*expand=*/true, /*fill=*/true);
|
||||||
|
@ -926,6 +927,7 @@ public:
|
||||||
switch(cursor) {
|
switch(cursor) {
|
||||||
case Cursor::POINTER: gdkCursorType = Gdk::ARROW; break;
|
case Cursor::POINTER: gdkCursorType = Gdk::ARROW; break;
|
||||||
case Cursor::HAND: gdkCursorType = Gdk::HAND1; break;
|
case Cursor::HAND: gdkCursorType = Gdk::HAND1; break;
|
||||||
|
default: ssassert(false, "Unexpected cursor");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto gdkWindow = gtkWindow.get_gl_widget().get_window();
|
auto gdkWindow = gtkWindow.get_gl_widget().get_window();
|
||||||
|
@ -1122,9 +1124,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddButton(std::string name, Response response, bool isDefault) override {
|
void AddButton(std::string name, Response response, bool isDefault) override {
|
||||||
int responseId;
|
int responseId = 0;
|
||||||
switch(response) {
|
switch(response) {
|
||||||
case Response::NONE: ssassert(false, "Invalid response");
|
case Response::NONE: ssassert(false, "Unexpected response");
|
||||||
case Response::OK: responseId = Gtk::RESPONSE_OK; break;
|
case Response::OK: responseId = Gtk::RESPONSE_OK; break;
|
||||||
case Response::YES: responseId = Gtk::RESPONSE_YES; break;
|
case Response::YES: responseId = Gtk::RESPONSE_YES; break;
|
||||||
case Response::NO: responseId = Gtk::RESPONSE_NO; break;
|
case Response::NO: responseId = Gtk::RESPONSE_NO; break;
|
||||||
|
@ -1295,8 +1297,78 @@ FileDialogRef CreateSaveFileDialog(WindowRef parentWindow) {
|
||||||
// Application-wide APIs
|
// Application-wide APIs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void Exit() {
|
std::vector<Platform::Path> GetFontFiles() {
|
||||||
Gtk::Main::quit();
|
std::vector<Platform::Path> fonts;
|
||||||
|
|
||||||
|
// fontconfig is already initialized by GTK
|
||||||
|
FcPattern *pat = FcPatternCreate();
|
||||||
|
FcObjectSet *os = FcObjectSetBuild(FC_FILE, (char *)0);
|
||||||
|
FcFontSet *fs = FcFontList(0, pat, os);
|
||||||
|
|
||||||
|
for(int i = 0; i < fs->nfont; i++) {
|
||||||
|
FcChar8 *filenameFC = FcPatternFormat(fs->fonts[i], (const FcChar8*) "%{file}");
|
||||||
|
fonts.push_back(Platform::Path::From((const char *)filenameFC));
|
||||||
|
FcStrFree(filenameFC);
|
||||||
|
}
|
||||||
|
|
||||||
|
FcFontSetDestroy(fs);
|
||||||
|
FcObjectSetDestroy(os);
|
||||||
|
FcPatternDestroy(pat);
|
||||||
|
|
||||||
|
return fonts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenInBrowser(const std::string &url) {
|
||||||
|
gtk_show_uri(Gdk::Screen::get_default()->gobj(), url.c_str(), GDK_CURRENT_TIME, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::Main *gtkMain;
|
||||||
|
|
||||||
|
void InitGui(int argc, char **argv) {
|
||||||
|
// It would in principle be possible to judiciously use Glib::filename_{from,to}_utf8,
|
||||||
|
// but it's not really worth the effort.
|
||||||
|
// The setlocale() call is necessary for Glib::get_charset() to detect the system
|
||||||
|
// character set; otherwise it thinks it is always ANSI_X3.4-1968.
|
||||||
|
// We set it back to C after all so that printf() and friends behave in a consistent way.
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
if(!Glib::get_charset()) {
|
||||||
|
dbp("Sorry, only UTF-8 locales are supported.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
setlocale(LC_ALL, "C");
|
||||||
|
|
||||||
|
gtkMain = new Gtk::Main(argc, argv, /*set_locale=*/false);
|
||||||
|
|
||||||
|
// Add our application-specific styles, to override GTK defaults.
|
||||||
|
Glib::RefPtr<Gtk::CssProvider> style_provider = Gtk::CssProvider::create();
|
||||||
|
style_provider->load_from_data(R"(
|
||||||
|
entry {
|
||||||
|
background: white;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
Gtk::StyleContext::add_provider_for_screen(
|
||||||
|
Gdk::Screen::get_default(), style_provider,
|
||||||
|
600 /*Gtk::STYLE_PROVIDER_PRIORITY_APPLICATION*/);
|
||||||
|
|
||||||
|
// Set locale from user preferences.
|
||||||
|
// This apparently only consults the LANGUAGE environment variable.
|
||||||
|
const char* const* langNames = g_get_language_names();
|
||||||
|
while(*langNames) {
|
||||||
|
if(SetLocale(*langNames++)) break;
|
||||||
|
}
|
||||||
|
if(!*langNames) {
|
||||||
|
SetLocale("en_US");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunGui() {
|
||||||
|
gtkMain->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExitGui() {
|
||||||
|
gtkMain->quit();
|
||||||
|
delete gtkMain;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1405,7 +1405,82 @@ FileDialogRef CreateSaveFileDialog(WindowRef parentWindow) {
|
||||||
// Application-wide APIs
|
// Application-wide APIs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void Exit() {
|
std::vector<Platform::Path> GetFontFiles() {
|
||||||
|
std::vector<SolveSpace::Platform::Path> fonts;
|
||||||
|
|
||||||
|
NSArray *fontNames = [[NSFontManager sharedFontManager] availableFonts];
|
||||||
|
for(NSString *fontName in fontNames) {
|
||||||
|
CTFontDescriptorRef fontRef =
|
||||||
|
CTFontDescriptorCreateWithNameAndSize ((__bridge CFStringRef)fontName, 10.0);
|
||||||
|
CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute);
|
||||||
|
NSString *fontPath = [NSString stringWithString:[(NSURL *)CFBridgingRelease(url) path]];
|
||||||
|
fonts.push_back(
|
||||||
|
Platform::Path::From([[NSFileManager defaultManager]
|
||||||
|
fileSystemRepresentationWithPath:fontPath]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fonts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenInBrowser(const std::string &url) {
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:Wrap(url)]];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@interface SSApplicationDelegate : NSObject<NSApplicationDelegate>
|
||||||
|
- (IBAction)preferences:(id)sender;
|
||||||
|
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename;
|
||||||
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SSApplicationDelegate
|
||||||
|
- (IBAction)preferences:(id)sender {
|
||||||
|
SolveSpace::SS.TW.GoToScreen(SolveSpace::TextWindow::Screen::CONFIGURATION);
|
||||||
|
SolveSpace::SS.ScheduleShowTW();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename {
|
||||||
|
SolveSpace::Platform::Path path = SolveSpace::Platform::Path::From([filename UTF8String]);
|
||||||
|
return SolveSpace::SS.Load(path.Expand(/*fromCurrentDirectory=*/true));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
|
||||||
|
[[[NSApp mainWindow] delegate] windowShouldClose:nil];
|
||||||
|
return NSTerminateCancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationTerminatePrompt {
|
||||||
|
SolveSpace::SS.MenuFile(SolveSpace::Command::EXIT);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
namespace SolveSpace {
|
||||||
|
namespace Platform {
|
||||||
|
|
||||||
|
static SSApplicationDelegate *ssDelegate;
|
||||||
|
|
||||||
|
void InitGui(int argc, char **argv) {
|
||||||
|
ssDelegate = [[SSApplicationDelegate alloc] init];
|
||||||
|
NSApplication.sharedApplication.delegate = ssDelegate;
|
||||||
|
|
||||||
|
[NSBundle.mainBundle loadNibNamed:@"MainMenu" owner:nil topLevelObjects:nil];
|
||||||
|
|
||||||
|
NSArray *languages = NSLocale.preferredLanguages;
|
||||||
|
for(NSString *language in languages) {
|
||||||
|
if(SolveSpace::SetLocale([language UTF8String])) break;
|
||||||
|
}
|
||||||
|
if(languages.count == 0) {
|
||||||
|
SolveSpace::SetLocale("en_US");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunGui() {
|
||||||
|
[NSApp run];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExitGui() {
|
||||||
[NSApp setDelegate:nil];
|
[NSApp setDelegate:nil];
|
||||||
[NSApp terminate:nil];
|
[NSApp terminate:nil];
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,27 +139,21 @@ FileDialogRef CreateSaveFileDialog(WindowRef parentWindow) {
|
||||||
// Application-wide APIs
|
// Application-wide APIs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void Exit() {
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Dialogs
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void OpenWebsite(const char *url) {
|
|
||||||
ssassert(false, "Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Resources
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
std::vector<Platform::Path> fontFiles;
|
std::vector<Platform::Path> fontFiles;
|
||||||
std::vector<Platform::Path> GetFontFiles() {
|
std::vector<Platform::Path> GetFontFiles() {
|
||||||
return fontFiles;
|
return fontFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenInBrowser(const std::string &url) {}
|
||||||
|
|
||||||
|
void InitGui(int argc, char **argv) {}
|
||||||
|
|
||||||
|
void RunGui() {}
|
||||||
|
|
||||||
|
void ExitGui() {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1580,7 +1580,49 @@ FileDialogRef CreateSaveFileDialog(WindowRef parentWindow) {
|
||||||
// Application-wide APIs
|
// Application-wide APIs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void Exit() {
|
std::vector<Platform::Path> GetFontFiles() {
|
||||||
|
std::vector<Platform::Path> fonts;
|
||||||
|
|
||||||
|
std::wstring fontsDirW(MAX_PATH, '\0');
|
||||||
|
fontsDirW.resize(GetWindowsDirectoryW(&fontsDirW[0], fontsDirW.length()));
|
||||||
|
fontsDirW += L"\\fonts\\";
|
||||||
|
Platform::Path fontsDir = Platform::Path::From(Narrow(fontsDirW));
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW wfd;
|
||||||
|
HANDLE h = FindFirstFileW((fontsDirW + L"*").c_str(), &wfd);
|
||||||
|
while(h != INVALID_HANDLE_VALUE) {
|
||||||
|
fonts.push_back(fontsDir.Join(Narrow(wfd.cFileName)));
|
||||||
|
if(!FindNextFileW(h, &wfd)) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fonts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenInBrowser(const std::string &url) {
|
||||||
|
ShellExecuteW(NULL, L"open", Widen(url).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitGui(int argc, char **argv) {
|
||||||
|
INITCOMMONCONTROLSEX icc;
|
||||||
|
icc.dwSize = sizeof(icc);
|
||||||
|
icc.dwICC = ICC_STANDARD_CLASSES|ICC_BAR_CLASSES;
|
||||||
|
InitCommonControlsEx(&icc);
|
||||||
|
|
||||||
|
if(!SetLocale((uint16_t)GetUserDefaultLCID())) {
|
||||||
|
SetLocale("en_US");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunGui() {
|
||||||
|
MSG msg;
|
||||||
|
// The return value of the following functions doesn't indicate success or failure.
|
||||||
|
while(GetMessage(&msg, NULL, 0, 0)) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExitGui() {
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -439,7 +439,7 @@ bool WriteFile(const Platform::Path &filename, const std::string &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Loading resources, on Windows.
|
// Loading resources, on Windows
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
|
@ -457,7 +457,7 @@ const void *LoadResource(const std::string &name, size_t *size) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Loading resources, on *nix.
|
// Loading resources, on *nix
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
@ -568,5 +568,9 @@ const void *LoadResource(const std::string &name, size_t *size) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Command-line argument handling
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Our WinMain() functions, and Win32-specific stuff to set up our windows
|
|
||||||
// and otherwise handle our interface to the operating system. Everything
|
|
||||||
// outside platform/... should be standard C++ and gl.
|
|
||||||
//
|
|
||||||
// Copyright 2008-2013 Jonathan Westhues.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "solvespace.h"
|
|
||||||
|
|
||||||
// Include after solvespace.h to avoid identifier clashes.
|
|
||||||
#include <windows.h>
|
|
||||||
#include <shellapi.h>
|
|
||||||
#include <commctrl.h>
|
|
||||||
#include <commdlg.h>
|
|
||||||
|
|
||||||
using Platform::Narrow;
|
|
||||||
using Platform::Widen;
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Utility routines
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void SolveSpace::OpenWebsite(const char *url) {
|
|
||||||
ShellExecuteW((HWND)SS.GW.window->NativePtr(),
|
|
||||||
L"open", Widen(url).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Platform::Path> SolveSpace::GetFontFiles() {
|
|
||||||
std::vector<Platform::Path> fonts;
|
|
||||||
|
|
||||||
std::wstring fontsDirW(MAX_PATH, '\0');
|
|
||||||
fontsDirW.resize(GetWindowsDirectoryW(&fontsDirW[0], fontsDirW.length()));
|
|
||||||
fontsDirW += L"\\fonts\\";
|
|
||||||
Platform::Path fontsDir = Platform::Path::From(Narrow(fontsDirW));
|
|
||||||
|
|
||||||
WIN32_FIND_DATA wfd;
|
|
||||||
HANDLE h = FindFirstFileW((fontsDirW + L"*").c_str(), &wfd);
|
|
||||||
while(h != INVALID_HANDLE_VALUE) {
|
|
||||||
fonts.push_back(fontsDir.Join(Narrow(wfd.cFileName)));
|
|
||||||
if(!FindNextFileW(h, &wfd)) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fonts;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Entry point into the program.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
||||||
LPSTR lpCmdLine, INT nCmdShow)
|
|
||||||
{
|
|
||||||
INITCOMMONCONTROLSEX icc;
|
|
||||||
icc.dwSize = sizeof(icc);
|
|
||||||
icc.dwICC = ICC_STANDARD_CLASSES|ICC_BAR_CLASSES;
|
|
||||||
InitCommonControlsEx(&icc);
|
|
||||||
|
|
||||||
std::vector<std::string> args = InitPlatform(0, NULL);
|
|
||||||
|
|
||||||
// Use the user default locale, then fall back to English.
|
|
||||||
if(!SetLocale((uint16_t)GetUserDefaultLCID())) {
|
|
||||||
SetLocale("en_US");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call in to the platform-independent code, and let them do their init
|
|
||||||
SS.Init();
|
|
||||||
|
|
||||||
// A filename may have been specified on the command line.
|
|
||||||
if(args.size() >= 2) {
|
|
||||||
SS.Load(Platform::Path::From(args[1]).Expand(/*fromCurrentDirectory=*/true));
|
|
||||||
}
|
|
||||||
|
|
||||||
// And now it's the message loop. All calls in to the rest of the code
|
|
||||||
// will be from the wndprocs.
|
|
||||||
MSG msg;
|
|
||||||
while(GetMessage(&msg, NULL, 0, 0)) {
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the memory we've used; anything that remains is a leak.
|
|
||||||
SK.Clear();
|
|
||||||
SS.Clear();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -271,7 +271,7 @@ void SolveSpaceUI::Exit() {
|
||||||
// And the default styles, colors and line widths and such.
|
// And the default styles, colors and line widths and such.
|
||||||
Style::FreezeDefaultStyles(settings);
|
Style::FreezeDefaultStyles(settings);
|
||||||
|
|
||||||
Platform::Exit();
|
Platform::ExitGui();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpaceUI::ScheduleGenerateAll() {
|
void SolveSpaceUI::ScheduleGenerateAll() {
|
||||||
|
@ -907,7 +907,7 @@ void SolveSpaceUI::ShowNakedEdges(bool reportOnlyWhenNotOkay) {
|
||||||
void SolveSpaceUI::MenuHelp(Command id) {
|
void SolveSpaceUI::MenuHelp(Command id) {
|
||||||
switch(id) {
|
switch(id) {
|
||||||
case Command::WEBSITE:
|
case Command::WEBSITE:
|
||||||
OpenWebsite("http://solvespace.com/helpmenu");
|
Platform::OpenInBrowser("http://solvespace.com/helpmenu");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Command::ABOUT:
|
case Command::ABOUT:
|
||||||
|
|
|
@ -142,10 +142,6 @@ extern Platform::Path RecentFile[MAX_RECENT];
|
||||||
|
|
||||||
#define AUTOSAVE_EXT "slvs~"
|
#define AUTOSAVE_EXT "slvs~"
|
||||||
|
|
||||||
std::vector<Platform::Path> GetFontFiles();
|
|
||||||
|
|
||||||
void OpenWebsite(const char *url);
|
|
||||||
|
|
||||||
void dbp(const char *str, ...);
|
void dbp(const char *str, ...);
|
||||||
#define DBPTRI(tri) \
|
#define DBPTRI(tri) \
|
||||||
dbp("tri: (%.3f %.3f %.3f) (%.3f %.3f %.3f) (%.3f %.3f %.3f)", \
|
dbp("tri: (%.3f %.3f %.3f) (%.3f %.3f %.3f) (%.3f %.3f %.3f)", \
|
||||||
|
|
|
@ -88,7 +88,7 @@ void TextWindow::ScreenShowEditView(int link, uint32_t v) {
|
||||||
SS.TW.GoToScreen(Screen::EDIT_VIEW);
|
SS.TW.GoToScreen(Screen::EDIT_VIEW);
|
||||||
}
|
}
|
||||||
void TextWindow::ScreenGoToWebsite(int link, uint32_t v) {
|
void TextWindow::ScreenGoToWebsite(int link, uint32_t v) {
|
||||||
OpenWebsite("http://solvespace.com/txtlink");
|
Platform::OpenInBrowser("http://solvespace.com/txtlink");
|
||||||
}
|
}
|
||||||
void TextWindow::ShowListOfGroups() {
|
void TextWindow::ShowListOfGroups() {
|
||||||
const char *radioTrue = " " RADIO_TRUE " ",
|
const char *radioTrue = " " RADIO_TRUE " ",
|
||||||
|
|
|
@ -56,7 +56,7 @@ TtfFontList::~TtfFontList() {
|
||||||
void TtfFontList::LoadAll() {
|
void TtfFontList::LoadAll() {
|
||||||
if(loaded) return;
|
if(loaded) return;
|
||||||
|
|
||||||
for(const Platform::Path &font : GetFontFiles()) {
|
for(const Platform::Path &font : Platform::GetFontFiles()) {
|
||||||
TtfFont tf = {};
|
TtfFont tf = {};
|
||||||
tf.fontFile = font;
|
tf.fontFile = font;
|
||||||
if(tf.LoadFromFile(fontLibrary))
|
if(tf.LoadFromFile(fontLibrary))
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace SolveSpace {
|
namespace SolveSpace {
|
||||||
|
namespace Platform {
|
||||||
// These are defined in headless.cpp, and aren't exposed in solvespace.h.
|
// These are defined in headless.cpp, and aren't exposed in solvespace.h.
|
||||||
extern std::vector<Platform::Path> fontFiles;
|
extern std::vector<Platform::Path> fontFiles;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The paths in __FILE__ are from the build system, but defined(WIN32) returns
|
// The paths in __FILE__ are from the build system, but defined(WIN32) returns
|
||||||
// the value for the host system.
|
// the value for the host system.
|
||||||
|
@ -338,7 +340,7 @@ int main(int argc, char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fontFiles.push_back(HostRoot().Join("Gentium-R.ttf"));
|
Platform::fontFiles.push_back(HostRoot().Join("Gentium-R.ttf"));
|
||||||
|
|
||||||
// Wreck order dependencies between tests!
|
// Wreck order dependencies between tests!
|
||||||
std::random_shuffle(testCasesPtr->begin(), testCasesPtr->end());
|
std::random_shuffle(testCasesPtr->begin(), testCasesPtr->end());
|
||||||
|
|
Loading…
Reference in New Issue