diff --git a/color-schemes/editor/dark-background.json b/color-schemes/editor/dark-background.json new file mode 100644 index 00000000..c9fc3e01 --- /dev/null +++ b/color-schemes/editor/dark-background.json @@ -0,0 +1,31 @@ +{ + "name" : "For Dark Background", + "index" : 1100, + "paper" : "#272822", + "text" : "#ffffff", + "caret" : { + "width" : 2, + "foreground" : "#ffff00", + "line-background" : "#68e1687f" + }, + "colors" : { + "keyword1" : "#f12971", + "keyword2" : "#56dbf0", + "keyword3" : "#56d8f0", + "comment" : "#ccdf32", + "number" : "#af7dff", + "string" : "#e6db74", + "operator" : "#d8d8d8", + "commentline" : "#e6db74", + "selection-foreground" : "#ffff00", + "selection-background" : "#a0a0ff", + "margin-background" : "#14141496", + "margin-foreground" : "#fff", + "matched-brace-background" : "#333", + "matched-brace-foreground" : "#fff", + "unmatched-brace-background" : "#333", + "unmatched-brace-foreground" : "#fff", + "error-marker" : "#ff0000", + "edge" : "#ffffff" + } +} \ No newline at end of file diff --git a/color-schemes/editor/light-background.json b/color-schemes/editor/light-background.json new file mode 100644 index 00000000..35471b50 --- /dev/null +++ b/color-schemes/editor/light-background.json @@ -0,0 +1,31 @@ +{ + "name" : "For Light Background", + "index" : 1000, + "paper" : "#fff", + "text" : "#272822", + "caret" : { + "width" : 2, + "foreground" : "#000000", + "line-background" : "#ffe4e4" + }, + "colors" : { + "keyword1" : "Green", + "keyword2" : "Green", + "keyword3" : "DarkBlue", + "comment" : "DarkCyan", + "number" : "DarkRed", + "string" : "DarkMagenta", + "operator" : "Blue", + "commentline" : "DarkCyan", + "selection-foreground" : "#ffff00", + "selection-background" : "#a0a0ff", + "margin-background" : "#ccc", + "margin-foreground" : "#111", + "matched-brace-background" : "#333", + "matched-brace-foreground" : "#fff", + "unmatched-brace-background" : "#333", + "unmatched-brace-foreground" : "#fff", + "error-marker" : "#ff0000", + "edge" : "#ffffff" + } +} \ No newline at end of file diff --git a/color-schemes/editor/monokai.json b/color-schemes/editor/monokai.json new file mode 100644 index 00000000..17bf8f9a --- /dev/null +++ b/color-schemes/editor/monokai.json @@ -0,0 +1,31 @@ +{ + "name" : "Monokai", + "index" : 1200, + "paper" : "#272822", + "text" : "#f8f8f2", + "caret" : { + "width" : 2, + "foreground" : "#ffff00", + "line-background" : "#3e3d32" + }, + "colors" : { + "keyword1" : "#66c3b3", + "keyword2" : "#79abff", + "keyword3" : "#ffffff", + "comment" : "#ccdf32", + "number" : "#7fb347", + "string" : "#e6db74", + "operator" : "#d8d8d8", + "commentline" : "#75715e", + "selection-foreground" : "#ffff00", + "selection-background" : "#a0a0ff", + "margin-background" : "#757575", + "margin-foreground" : "#f8f8f2", + "matched-brace-background" : "#333", + "matched-brace-foreground" : "#fff", + "unmatched-brace-background" : "#333", + "unmatched-brace-foreground" : "#fff", + "error-marker" : "#ff0000", + "edge" : "#ffffff" + } +} \ No newline at end of file diff --git a/color-schemes/editor/solarized.json b/color-schemes/editor/solarized.json new file mode 100644 index 00000000..c9ee3dd3 --- /dev/null +++ b/color-schemes/editor/solarized.json @@ -0,0 +1,31 @@ +{ + "name" : "Solarized", + "index" : 1300, + "paper" : "#fdf6e3", + "text" : "#657b83", + "caret" : { + "width" : 2, + "foreground" : "#0000ff", + "line-background" : "#eeead5" + }, + "colors" : { + "keyword1" : "#268ad1", + "keyword2" : "#6c71c4", + "keyword3" : "#b58800", + "comment" : "#b58900", + "number" : "#cb4b16", + "string" : "#2aa198", + "operator" : "#859900", + "commentline" : "#b58800", + "selection-foreground" : "#fdf6e3", + "selection-background" : "#657b83", + "margin-background" : "#eee8d5", + "margin-foreground" : "#93a1a1", + "matched-brace-background" : "#333", + "matched-brace-foreground" : "#fff", + "unmatched-brace-background" : "#333", + "unmatched-brace-foreground" : "#fff", + "error-marker" : "#ff0000", + "edge" : "#ffffff" + } +} \ No newline at end of file diff --git a/color-schemes/render/beforedawn.json b/color-schemes/render/beforedawn.json new file mode 100644 index 00000000..9e09fcca --- /dev/null +++ b/color-schemes/render/beforedawn.json @@ -0,0 +1,18 @@ +{ + "name" : "BeforeDawn", + "index" : 1400, + "show-in-gui" : true, + + "colors" : { + "background" : "#333333", + "opencsg-face-front" : "#cccccc", + "opencsg-face-back" : "#5563dd", + "cgal-face-front" : "#cccccc", + "cgal-face-back" : "#5563dd", + "cgal-face-2d" : "#00bf99", + "cgal-edge-front" : "#ff0000", + "cgal-edge-back" : "#ff0000", + "cgal-edge-2d" : "#ff0000", + "crosshair" : "#f0f0f0" + } +} diff --git a/color-schemes/render/deepocean.json b/color-schemes/render/deepocean.json new file mode 100644 index 00000000..c325db8e --- /dev/null +++ b/color-schemes/render/deepocean.json @@ -0,0 +1,18 @@ +{ + "name" : "DeepOcean", + "index" : 1600, + "show-in-gui" : true, + + "colors" : { + "background" : "#333333", + "opencsg-face-front" : "#eeeeee", + "opencsg-face-back" : "#0babc8", + "cgal-face-front" : "#eeeeee", + "cgal-face-back" : "#0babc8", + "cgal-face-2d" : "#9370db", + "cgal-edge-front" : "#0000ff", + "cgal-edge-back" : "#0000ff", + "cgal-edge-2d" : "#ff00ff", + "crosshair" : "#f0f0f0" + } +} diff --git a/color-schemes/render/metallic.json b/color-schemes/render/metallic.json new file mode 100644 index 00000000..f2582e46 --- /dev/null +++ b/color-schemes/render/metallic.json @@ -0,0 +1,18 @@ +{ + "name" : "Metallic", + "index" : 1100, + "show-in-gui" : true, + + "colors" : { + "background" : "#aaaaff", + "opencsg-face-front" : "#ddddff", + "opencsg-face-back" : "#dd22dd", + "cgal-face-front" : "#ddddff", + "cgal-face-back" : "#dd22dd", + "cgal-face-2d" : "#00bf99", + "cgal-edge-front" : "#ff0000", + "cgal-edge-back" : "#ff0000", + "cgal-edge-2d" : "#ff0000", + "crosshair" : "#800000" + } +} diff --git a/color-schemes/render/monotone.json b/color-schemes/render/monotone.json new file mode 100644 index 00000000..1ce30005 --- /dev/null +++ b/color-schemes/render/monotone.json @@ -0,0 +1,19 @@ +{ + "name" : "Monotone", + "index" : 9999, + "show-in-gui" : false, + "description" : "Color scheme with no difference between 'back face' and 'front face'", + + "colors" : { + "background" : "#ffffe5", + "opencsg-face-front" : "#f9d72c", + "opencsg-face-back" : "#f9d72c", + "cgal-face-front" : "#f9d72c", + "cgal-face-back" : "#f9d72c", + "cgal-face-2d" : "#00bf99", + "cgal-edge-front" : "#ff0000", + "cgal-edge-back" : "#ff0000", + "cgal-edge-2d" : "#ff0000", + "crosshair" : "#800000" + } +} diff --git a/color-schemes/render/nature.json b/color-schemes/render/nature.json new file mode 100644 index 00000000..9e19932e --- /dev/null +++ b/color-schemes/render/nature.json @@ -0,0 +1,18 @@ +{ + "name" : "Nature", + "index" : 1500, + "show-in-gui" : true, + + "colors" : { + "background" : "#fafafa", + "opencsg-face-front" : "#16a085", + "opencsg-face-back" : "#dbf4da", + "cgal-face-front" : "#16a085", + "cgal-face-back" : "#dbf4da", + "cgal-face-2d" : "#00bf99", + "cgal-edge-front" : "#ff0000", + "cgal-edge-back" : "#ff0000", + "cgal-edge-2d" : "#ff0000", + "crosshair" : "#111111" + } +} diff --git a/color-schemes/render/solarized.json b/color-schemes/render/solarized.json new file mode 100644 index 00000000..06190ee9 --- /dev/null +++ b/color-schemes/render/solarized.json @@ -0,0 +1,18 @@ +{ + "name" : "Solarized", + "index" : 1700, + "show-in-gui" : true, + + "colors" : { + "background" : "#fdf6e3", + "opencsg-face-front" : "#b58800", + "opencsg-face-back" : "#882233", + "cgal-face-front" : "#b58800", + "cgal-face-back" : "#882233", + "cgal-face-2d" : "#6c71c4", + "cgal-edge-front" : "#b58800", + "cgal-edge-back" : "#b58800", + "cgal-edge-2d" : "#b58800", + "crosshair" : "#800000" + } +} diff --git a/color-schemes/render/starnight.json b/color-schemes/render/starnight.json new file mode 100644 index 00000000..0dbe702d --- /dev/null +++ b/color-schemes/render/starnight.json @@ -0,0 +1,18 @@ +{ + "name" : "Starnight", + "index" : 1300, + "show-in-gui" : true, + + "colors" : { + "background" : "#000000", + "opencsg-face-front" : "#ffffe0", + "opencsg-face-back" : "#00ffff", + "cgal-face-front" : "#ffffe0", + "cgal-face-back" : "#00ffff", + "cgal-face-2d" : "#9370db", + "cgal-edge-front" : "#0000ff", + "cgal-edge-back" : "#0000ff", + "cgal-edge-2d" : "#ff00ff", + "crosshair" : "#f0f0f0" + } +} diff --git a/color-schemes/render/sunset.json b/color-schemes/render/sunset.json new file mode 100644 index 00000000..072c361c --- /dev/null +++ b/color-schemes/render/sunset.json @@ -0,0 +1,18 @@ +{ + "name" : "Sunset", + "index" : 1200, + "show-in-gui" : true, + + "colors" : { + "background" : "#aa4444", + "opencsg-face-front" : "#ffaaaa", + "opencsg-face-back" : "#882233", + "cgal-face-front" : "#ffaaaa", + "cgal-face-back" : "#882233", + "cgal-face-2d" : "#00bf99", + "cgal-edge-front" : "#ff0000", + "cgal-edge-back" : "#ff0000", + "cgal-edge-2d" : "#ff0000", + "crosshair" : "#800000" + } +} diff --git a/openscad.pro b/openscad.pro index a2692b66..f926ac56 100644 --- a/openscad.pro +++ b/openscad.pro @@ -480,6 +480,10 @@ fonts.path = $$PREFIX/share/openscad/fonts/ fonts.files = fonts/* INSTALLS += fonts +colorschemes.path = $$PREFIX/share/openscad/color-schemes/ +colorschemes.files = color-schemes/* +INSTALLS += colorschemes + applications.path = $$PREFIX/share/applications applications.files = icons/openscad.desktop INSTALLS += applications diff --git a/scripts/installer.nsi b/scripts/installer.nsi index 96396169..d1fb7712 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -13,6 +13,7 @@ File openscad.com File /r /x mingw-cross-env examples File /r /x mingw-cross-env libraries File /r /x mingw-cross-env fonts +File /r /x mingw-cross-env color-schemes ${registerExtension} "$INSTDIR\openscad.exe" ".scad" "OpenSCAD_File" CreateShortCut $SMPROGRAMS\OpenSCAD.lnk $INSTDIR\openscad.exe WriteUninstaller $INSTDIR\Uninstall.exe @@ -27,6 +28,7 @@ Delete $INSTDIR\MyProg.exe Delete $SMPROGRAMS\OpenSCAD.lnk DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" RMDir /r $INSTDIR\fonts +RMDir /r $INSTDIR\color-schemes RMDir /r $INSTDIR\examples RMDir /r $INSTDIR\libraries\mcad Delete $INSTDIR\libraries\boxes.scad diff --git a/scripts/publish-macosx.sh b/scripts/publish-macosx.sh index de4713a1..5814529b 100755 --- a/scripts/publish-macosx.sh +++ b/scripts/publish-macosx.sh @@ -2,6 +2,11 @@ # NB! To build a release build, the VERSION and VERSIONDATE environment variables needs to be set. # See doc/release-checklist.txt +# +# Usage: +# ./scripts/publish-macosx.sh [buildonly] +# + export NUMCPU=$(sysctl -n hw.ncpu) human_filesize() @@ -40,6 +45,13 @@ update_www_download_links() fi } +# Cmd-line parameters +DOUPLOAD=1 +if [ "`echo $* | grep buildonly`" ]; then + echo "Build only, no upload" + DOUPLOAD= +fi + if test -z "$VERSIONDATE"; then VERSIONDATE=`date "+%Y.%m.%d"` fi @@ -76,6 +88,10 @@ if [[ $? != 0 ]]; then exit 1 fi +if [ ! $DOUPLOAD ]; then + exit 0 +fi + SIGNATURE=$(openssl dgst -sha1 -binary < OpenSCAD-$VERSION.dmg | openssl dgst -dss1 -sign $HOME/.ssh/openscad-appcast.pem | openssl enc -base64) if [[ $VERSION == $VERSIONDATE ]]; then diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 80402ef2..f3ab9f81 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -326,12 +326,14 @@ case $OS in EXAMPLESDIR=OpenSCAD.app/Contents/Resources/examples LIBRARYDIR=OpenSCAD.app/Contents/Resources/libraries FONTDIR=OpenSCAD.app/Contents/Resources/fonts + COLORSCHEMESDIR=OpenSCAD.app/Contents/Resources/color-schemes ;; UNIX_CROSS_WIN) cd $OPENSCADDIR EXAMPLESDIR=$DEPLOYDIR/openscad-$VERSION/examples/ LIBRARYDIR=$DEPLOYDIR/openscad-$VERSION/libraries/ FONTDIR=$DEPLOYDIR/openscad-$VERSION/fonts/ + COLORSCHEMESDIR=$DEPLOYDIR/openscad-$VERSION/color-schemes/ rm -rf $DEPLOYDIR/openscad-$VERSION mkdir $DEPLOYDIR/openscad-$VERSION ;; @@ -339,6 +341,7 @@ case $OS in EXAMPLESDIR=openscad-$VERSION/examples/ LIBRARYDIR=openscad-$VERSION/libraries/ FONTDIR=openscad-$VERSION/fonts/ + COLORSCHEMESDIR=openscad-$VERSION/color-schemes/ rm -rf openscad-$VERSION mkdir openscad-$VERSION ;; @@ -366,6 +369,11 @@ if [ -n $FONTDIR ]; then ;; esac fi +if [ -n $COLORSCHEMESDIR ]; then + echo $COLORSCHEMESDIR + mkdir -p $COLORSCHEMESDIR + cp -a color-schemes/* $COLORSCHEMESDIR +fi if [ -n $LIBRARYDIR ]; then echo $LIBRARYDIR mkdir -p $LIBRARYDIR diff --git a/src/PlatformUtils-mac.mm b/src/PlatformUtils-mac.mm index 418bbfed..c6ba6277 100644 --- a/src/PlatformUtils-mac.mm +++ b/src/PlatformUtils-mac.mm @@ -11,5 +11,12 @@ std::string PlatformUtils::documentsPath() return std::string([[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] UTF8String]); } +std::string PlatformUtils::userConfigPath() +{ + NSError *error; + NSURL *appSupportDir = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:&error]; + return std::string([[appSupportDir path] UTF8String]) + std::string("/") + PlatformUtils::OPENSCAD_FOLDER_NAME; +} + void PlatformUtils::ensureStdIO(void) {} diff --git a/src/PlatformUtils-posix.cc b/src/PlatformUtils-posix.cc index ab0dd9bd..64cc5dbe 100644 --- a/src/PlatformUtils-posix.cc +++ b/src/PlatformUtils-posix.cc @@ -19,5 +19,27 @@ std::string PlatformUtils::documentsPath() } } +// see http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html +std::string PlatformUtils::userConfigPath() +{ + fs::path config_path; + + const char *xdg_env = getenv("XDG_CONFIG_HOME"); + if (xdg_env && fs::exists(fs::path(xdg_env))) { + config_path = fs::path(xdg_env) / OPENSCAD_FOLDER_NAME; + } else { + const char *home = getenv("HOME"); + if (home) { + config_path = fs::path(home) / ".config" / OPENSCAD_FOLDER_NAME; + } + } + + if (fs::is_directory(config_path)) { + return boosty::stringy(boosty::absolute(config_path)); + } + + return ""; +} + void PlatformUtils::ensureStdIO(void) {} diff --git a/src/PlatformUtils-win.cc b/src/PlatformUtils-win.cc index 1091a229..a504bb1f 100644 --- a/src/PlatformUtils-win.cc +++ b/src/PlatformUtils-win.cc @@ -47,6 +47,27 @@ std::string winapi_wstr_to_utf8( std::wstring wstr ) return utf8_str; } +// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx +static const std::string getFolderPath(int nFolder) +{ + std::wstring path(MAX_PATH,0); + + HWND hwndOwner = 0; + HANDLE hToken = NULL; + DWORD dwFlags = SHGFP_TYPE_CURRENT; + LPTSTR pszPath = &path[0]; + + int result = SHGetFolderPathW( hwndOwner, nFolder, hToken, dwFlags, pszPath ); + + if (result == S_OK) { + path = std::wstring( path.c_str() ); // strip extra NULLs + //std::wcerr << "wchar path:" << "\n"; + const std::string retval = winapi_wstr_to_utf8( path ); + //PRINTB("Path found: %s",retval); + return retval; + } + return ""; +} // retrieve the path to 'My Documents' for the current user under windows // In XP this is 'c:\documents and settings\username\my documents' @@ -55,29 +76,22 @@ std::string winapi_wstr_to_utf8( std::wstring wstr ) // Mingw does not provide access to the updated SHGetKnownFolderPath std::string PlatformUtils::documentsPath() { - std::string retval; - std::wstring path(MAX_PATH,0); - - HWND hwndOwner = 0; - int nFolder = CSIDL_PERSONAL; - HANDLE hToken = NULL; - DWORD dwFlags = SHGFP_TYPE_CURRENT; - LPTSTR pszPath = &path[0]; - - int result = SHGetFolderPathW( hwndOwner, nFolder, hToken, dwFlags, pszPath ); - - if (result == S_OK) { - path = std::wstring( path.c_str() ); // stip extra NULLs - //std::wcerr << "wchar path:" << "\n"; - retval = winapi_wstr_to_utf8( path ); - //PRINTB("Path found: %s",retval); - } else { - PRINT("ERROR: Could not find My Documents location"); - retval = ""; + const std::string retval = getFolderPath(CSIDL_PERSONAL); + if (retval.empty()) { + PRINT("ERROR: Could not find My Documents location"); } return retval; } +std::string PlatformUtils::userConfigPath() +{ + const std::string retval = getFolderPath(CSIDL_LOCAL_APPDATA); + if (retval.empty()) { + PRINT("ERROR: Could not find Local AppData location"); + } + return retval + std::string("/") + PlatformUtils::OPENSCAD_FOLDER_NAME; +} + #include #include #include diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc index a7f6c61a..91f2b97a 100644 --- a/src/PlatformUtils.cc +++ b/src/PlatformUtils.cc @@ -14,6 +14,8 @@ namespace { std::string applicationpath; } +const char *PlatformUtils::OPENSCAD_FOLDER_NAME = "OpenSCAD"; + void PlatformUtils::registerApplicationPath(const std::string &apppath) { applicationpath = apppath; @@ -52,7 +54,7 @@ std::string PlatformUtils::userLibraryPath() //PRINTB("path size %i",boosty::stringy(path).size()); //PRINTB("lib path found: [%s]", path ); if (path.empty()) return ""; - path /= "OpenSCAD"; + path /= OPENSCAD_FOLDER_NAME; path /= "libraries"; //PRINTB("Appended path %s", path ); //PRINTB("Exists: %i", fs::exists(path) ); @@ -71,7 +73,7 @@ std::string PlatformUtils::backupPath() if (pathstr=="") return ""; path = boosty::canonical(fs::path( pathstr )); if (path.empty()) return ""; - path /= "OpenSCAD"; + path /= OPENSCAD_FOLDER_NAME; path /= "backups"; } catch (const fs::filesystem_error& ex) { PRINTB("ERROR: %s",ex.what()); @@ -101,31 +103,32 @@ std::string PlatformUtils::resourcesPath() { fs::path resourcedir(applicationPath()); fs::path tmpdir; +#ifndef WIN32 #ifdef __APPLE__ - // Resources can be bundled on Mac. If not, fall back to development layout - bool isbundle = is_directory(resourcedir / ".." / "Resources"); - if (isbundle) { - resourcedir /= "../Resources"; - // Fall back to dev layout - if (!is_directory(resourcedir / "libraries")) resourcedir /= "../../.."; - } -#elif !defined(WIN32) - tmpdir = resourcedir / "../share/openscad"; - if (is_directory(tmpdir / "libraries")) { + const char *searchpath[] = { + "../Resources", // Resources can be bundled on Mac. + "../../..", // Dev location + "..", // Test location + NULL + }; +#else + const char *searchpath[] = { + "../share/openscad", + "../../share/openscad", + ".", + "..", + "../..", + NULL + }; +#endif + for (int a = 0;searchpath[a] != NULL;a++) { + tmpdir = resourcedir / searchpath[a]; + if (is_directory(tmpdir / "libraries")) { resourcedir = tmpdir; + break; + } } - else { - tmpdir = resourcedir / "../../share/openscad"; - if (is_directory(tmpdir / "libraries")) { - resourcedir = tmpdir; - } else { - tmpdir = resourcedir / "../.."; - if (is_directory(tmpdir / "libraries")) { - resourcedir = tmpdir; - } - } - } -#endif +#endif // !WIN32 // resourcedir defaults to applicationPath return boosty::stringy(boosty::canonical(resourcedir)); } diff --git a/src/PlatformUtils.h b/src/PlatformUtils.h index ca28134c..11b58b08 100644 --- a/src/PlatformUtils.h +++ b/src/PlatformUtils.h @@ -3,6 +3,7 @@ #include namespace PlatformUtils { + extern const char *OPENSCAD_FOLDER_NAME; void registerApplicationPath(const std::string &applicationpath); std::string applicationPath(); @@ -10,6 +11,19 @@ namespace PlatformUtils { std::string documentsPath(); std::string resourcesPath(); std::string userLibraryPath(); + + /** + * Base path where user configuration can be read and written to. On + * Linux this is the $XDG_CONFIG_HOME, on Windows the local AppData + * folder CSIDL_LOCAL_APPDATA. + * On success the returned path can be used directly as base folder + * as it already includes an OpenSCAD specific part. + * + * @return absolute path to the writable configuration folder or + * an empty string if the config path does not exist. + */ + std::string userConfigPath(); + bool createUserLibraryPath(); std::string backupPath(); bool createBackupPath(); diff --git a/src/Preferences.cc b/src/Preferences.cc index ac6d3e6e..97b5e4d2 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -48,7 +48,10 @@ Q_DECLARE_METATYPE(Feature *); Preferences::Preferences(QWidget *parent) : QMainWindow(parent) { setupUi(this); +} +void Preferences::init() { + // Editor pane // Setup default font (Try to use a nice monospace font) QString fontfamily; @@ -136,9 +139,6 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) #endif this->polysetCacheSizeEdit->setValidator(validator); this->opencsgLimitEdit->setValidator(validator); - - setupFeaturesPage(); - updateGUI(); } Preferences::~Preferences() @@ -273,7 +273,7 @@ void Preferences::on_editorType_editTextChanged(const QString &type) settings.setValue("editor/editortype", type); } -void Preferences::on_syntaxHighlight_currentIndexChanged(const QString &s) +void Preferences::on_syntaxHighlight_activated(const QString &s) { QSettings settings; settings.setValue("editor/syntaxhighlight", s); @@ -459,7 +459,14 @@ void Preferences::updateGUI() QString shighlight = getValue("editor/syntaxhighlight").toString(); int shidx = this->syntaxHighlight->findText(shighlight); - if (shidx >= 0) this->syntaxHighlight->setCurrentIndex(shidx); + if (shidx >= 0) { + this->syntaxHighlight->setCurrentIndex(shidx); + } else { + int offidx = this->syntaxHighlight->findText("Off"); + if (offidx >= 0) { + this->syntaxHighlight->setCurrentIndex(offidx); + } + } QString editortypevar = getValue("editor/editortype").toString(); int edidx = this->editorType->findText(editortypevar); @@ -491,4 +498,29 @@ void Preferences::apply() const emit fontChanged(getValue("editor/fontfamily").toString(), getValue("editor/fontsize").toUInt()); emit requestRedraw(); emit openCSGSettingsChanged(); + emit syntaxHighlightChanged(getValue("editor/syntaxhighlight").toString()); +} + +void Preferences::create(QWidget *parent, QStringList colorSchemes) +{ + std::list names = ColorMap::inst()->colorSchemeNames(true); + QStringList renderColorSchemes; + foreach (std::string name, names) { + renderColorSchemes << name.c_str(); + } + + instance = new Preferences(parent); + instance->syntaxHighlight->clear(); + instance->syntaxHighlight->addItems(colorSchemes); + instance->colorSchemeChooser->clear(); + instance->colorSchemeChooser->addItems(renderColorSchemes); + instance->init(); + instance->setupFeaturesPage(); + instance->updateGUI(); +} + +Preferences *Preferences::inst() { + assert(instance != NULL); + + return instance; } diff --git a/src/Preferences.h b/src/Preferences.h index bfa7d144..a40e92cd 100644 --- a/src/Preferences.h +++ b/src/Preferences.h @@ -3,7 +3,6 @@ #include #include #include "ui_Preferences.h" -#include "colormap.h" class Preferences : public QMainWindow, public Ui::Preferences { @@ -11,9 +10,12 @@ class Preferences : public QMainWindow, public Ui::Preferences public: ~Preferences(); - static Preferences *inst() { if (!instance) instance = new Preferences(); return instance; } + + static void create(QWidget *parent, QStringList colorSchemes); + static Preferences *inst(); QVariant getValue(const QString &key) const; + void init(); void apply() const; public slots: @@ -22,7 +24,7 @@ public slots: void on_colorSchemeChooser_itemSelectionChanged(); void on_fontChooser_activated(const QString &); void on_fontSize_editTextChanged(const QString &); - void on_syntaxHighlight_currentIndexChanged(const QString &); + void on_syntaxHighlight_activated(const QString &); void on_openCSGWarningBox_toggled(bool); void on_enableOpenCSGBox_toggled(bool); void on_cgalCacheSizeEdit_textChanged(const QString &); @@ -47,7 +49,7 @@ signals: void fontChanged(const QString &family, uint size) const; void colorSchemeChanged(const QString &scheme) const; void openCSGSettingsChanged() const; - void syntaxHighlightChanged(const QString &s); + void syntaxHighlightChanged(const QString &s) const; void editorTypeChanged(const QString &type); private: diff --git a/src/Preferences.ui b/src/Preferences.ui index 0988b3c4..324a4a87 100644 --- a/src/Preferences.ui +++ b/src/Preferences.ui @@ -54,43 +54,8 @@ false - 0 + -1 - - - Cornfield - - - - - Metallic - - - - - Sunset - - - - - Starnight - - - - - BeforeDawn - - - - - Nature - - - - - DeepOcean - - @@ -264,31 +229,6 @@ 0 - - - For Light Background - - - - - For Dark Background - - - - - Monokai - - - - - Solarized - - - - - Off - - diff --git a/src/color.cc b/src/color.cc index 390a11d4..7792f0bf 100644 --- a/src/color.cc +++ b/src/color.cc @@ -31,22 +31,180 @@ #include "printutils.h" #include #include +#include #include #include #include using namespace boost::assign; // bring 'operator+=()' into scope -#include "colormap.h" class ColorModule : public AbstractModule { public: - ColorModule() : webcolors(ColorMap::inst()->webColors()) { } + ColorModule(); + virtual ~ColorModule(); virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; private: - const boost::unordered_map &webcolors; + boost::unordered_map webcolors; }; +ColorModule::ColorModule() +{ + webcolors = map_list_of + ("aliceblue", Color4f(240, 248, 255)) + ("antiquewhite", Color4f(250, 235, 215)) + ("aqua", Color4f(0, 255, 255)) + ("aquamarine", Color4f(127, 255, 212)) + ("azure", Color4f(240, 255, 255)) + ("beige", Color4f(245, 245, 220)) + ("bisque", Color4f(255, 228, 196)) + ("black", Color4f(0, 0, 0)) + ("blanchedalmond", Color4f(255, 235, 205)) + ("blue", Color4f(0, 0, 255)) + ("blueviolet", Color4f(138, 43, 226)) + ("brown", Color4f(165, 42, 42)) + ("burlywood", Color4f(222, 184, 135)) + ("cadetblue", Color4f(95, 158, 160)) + ("chartreuse", Color4f(127, 255, 0)) + ("chocolate", Color4f(210, 105, 30)) + ("coral", Color4f(255, 127, 80)) + ("cornflowerblue", Color4f(100, 149, 237)) + ("cornsilk", Color4f(255, 248, 220)) + ("crimson", Color4f(220, 20, 60)) + ("cyan", Color4f(0, 255, 255)) + ("darkblue", Color4f(0, 0, 139)) + ("darkcyan", Color4f(0, 139, 139)) + ("darkgoldenrod", Color4f(184, 134, 11)) + ("darkgray", Color4f(169, 169, 169)) + ("darkgreen", Color4f(0, 100, 0)) + ("darkgrey", Color4f(169, 169, 169)) + ("darkkhaki", Color4f(189, 183, 107)) + ("darkmagenta", Color4f(139, 0, 139)) + ("darkolivegreen", Color4f(85, 107, 47)) + ("darkorange", Color4f(255, 140, 0)) + ("darkorchid", Color4f(153, 50, 204)) + ("darkred", Color4f(139, 0, 0)) + ("darksalmon", Color4f(233, 150, 122)) + ("darkseagreen", Color4f(143, 188, 143)) + ("darkslateblue", Color4f(72, 61, 139)) + ("darkslategray", Color4f(47, 79, 79)) + ("darkslategrey", Color4f(47, 79, 79)) + ("darkturquoise", Color4f(0, 206, 209)) + ("darkviolet", Color4f(148, 0, 211)) + ("deeppink", Color4f(255, 20, 147)) + ("deepskyblue", Color4f(0, 191, 255)) + ("dimgray", Color4f(105, 105, 105)) + ("dimgrey", Color4f(105, 105, 105)) + ("dodgerblue", Color4f(30, 144, 255)) + ("firebrick", Color4f(178, 34, 34)) + ("floralwhite", Color4f(255, 250, 240)) + ("forestgreen", Color4f(34, 139, 34)) + ("fuchsia", Color4f(255, 0, 255)) + ("gainsboro", Color4f(220, 220, 220)) + ("ghostwhite", Color4f(248, 248, 255)) + ("gold", Color4f(255, 215, 0)) + ("goldenrod", Color4f(218, 165, 32)) + ("gray", Color4f(128, 128, 128)) + ("green", Color4f(0, 128, 0)) + ("greenyellow", Color4f(173, 255, 47)) + ("grey", Color4f(128, 128, 128)) + ("honeydew", Color4f(240, 255, 240)) + ("hotpink", Color4f(255, 105, 180)) + ("indianred", Color4f(205, 92, 92)) + ("indigo", Color4f(75, 0, 130)) + ("ivory", Color4f(255, 255, 240)) + ("khaki", Color4f(240, 230, 140)) + ("lavender", Color4f(230, 230, 250)) + ("lavenderblush", Color4f(255, 240, 245)) + ("lawngreen", Color4f(124, 252, 0)) + ("lemonchiffon", Color4f(255, 250, 205)) + ("lightblue", Color4f(173, 216, 230)) + ("lightcoral", Color4f(240, 128, 128)) + ("lightcyan", Color4f(224, 255, 255)) + ("lightgoldenrodyellow", Color4f(250, 250, 210)) + ("lightgray", Color4f(211, 211, 211)) + ("lightgreen", Color4f(144, 238, 144)) + ("lightgrey", Color4f(211, 211, 211)) + ("lightpink", Color4f(255, 182, 193)) + ("lightsalmon", Color4f(255, 160, 122)) + ("lightseagreen", Color4f(32, 178, 170)) + ("lightskyblue", Color4f(135, 206, 250)) + ("lightslategray", Color4f(119, 136, 153)) + ("lightslategrey", Color4f(119, 136, 153)) + ("lightsteelblue", Color4f(176, 196, 222)) + ("lightyellow", Color4f(255, 255, 224)) + ("lime", Color4f(0, 255, 0)) + ("limegreen", Color4f(50, 205, 50)) + ("linen", Color4f(250, 240, 230)) + ("magenta", Color4f(255, 0, 255)) + ("maroon", Color4f(128, 0, 0)) + ("mediumaquamarine", Color4f(102, 205, 170)) + ("mediumblue", Color4f(0, 0, 205)) + ("mediumorchid", Color4f(186, 85, 211)) + ("mediumpurple", Color4f(147, 112, 219)) + ("mediumseagreen", Color4f(60, 179, 113)) + ("mediumslateblue", Color4f(123, 104, 238)) + ("mediumspringgreen", Color4f(0, 250, 154)) + ("mediumturquoise", Color4f(72, 209, 204)) + ("mediumvioletred", Color4f(199, 21, 133)) + ("midnightblue", Color4f(25, 25, 112)) + ("mintcream", Color4f(245, 255, 250)) + ("mistyrose", Color4f(255, 228, 225)) + ("moccasin", Color4f(255, 228, 181)) + ("navajowhite", Color4f(255, 222, 173)) + ("navy", Color4f(0, 0, 128)) + ("oldlace", Color4f(253, 245, 230)) + ("olive", Color4f(128, 128, 0)) + ("olivedrab", Color4f(107, 142, 35)) + ("orange", Color4f(255, 165, 0)) + ("orangered", Color4f(255, 69, 0)) + ("orchid", Color4f(218, 112, 214)) + ("palegoldenrod", Color4f(238, 232, 170)) + ("palegreen", Color4f(152, 251, 152)) + ("paleturquoise", Color4f(175, 238, 238)) + ("palevioletred", Color4f(219, 112, 147)) + ("papayawhip", Color4f(255, 239, 213)) + ("peachpuff", Color4f(255, 218, 185)) + ("peru", Color4f(205, 133, 63)) + ("pink", Color4f(255, 192, 203)) + ("plum", Color4f(221, 160, 221)) + ("powderblue", Color4f(176, 224, 230)) + ("purple", Color4f(128, 0, 128)) + ("red", Color4f(255, 0, 0)) + ("rosybrown", Color4f(188, 143, 143)) + ("royalblue", Color4f(65, 105, 225)) + ("saddlebrown", Color4f(139, 69, 19)) + ("salmon", Color4f(250, 128, 114)) + ("sandybrown", Color4f(244, 164, 96)) + ("seagreen", Color4f(46, 139, 87)) + ("seashell", Color4f(255, 245, 238)) + ("sienna", Color4f(160, 82, 45)) + ("silver", Color4f(192, 192, 192)) + ("skyblue", Color4f(135, 206, 235)) + ("slateblue", Color4f(106, 90, 205)) + ("slategray", Color4f(112, 128, 144)) + ("slategrey", Color4f(112, 128, 144)) + ("snow", Color4f(255, 250, 250)) + ("springgreen", Color4f(0, 255, 127)) + ("steelblue", Color4f(70, 130, 180)) + ("tan", Color4f(210, 180, 140)) + ("teal", Color4f(0, 128, 128)) + ("thistle", Color4f(216, 191, 216)) + ("tomato", Color4f(255, 99, 71)) + ("transparent", Color4f(0, 0, 0, 0)) + ("turquoise", Color4f(64, 224, 208)) + ("violet", Color4f(238, 130, 238)) + ("wheat", Color4f(245, 222, 179)) + ("white", Color4f(255, 255, 255)) + ("whitesmoke", Color4f(245, 245, 245)) + ("yellow", Color4f(255, 255, 0)) + ("yellowgreen", Color4f(154, 205, 50)); +} + +ColorModule::~ColorModule() +{ +} + AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { ColorNode *node = new ColorNode(inst); diff --git a/src/colormap.cc b/src/colormap.cc index 8aea7e99..c3a1b18a 100644 --- a/src/colormap.cc +++ b/src/colormap.cc @@ -1,8 +1,108 @@ #include "colormap.h" +#include #include +#include "boosty.h" #include "printutils.h" +#include "PlatformUtils.h" + using namespace boost::assign; // bring map_list_of() into scope +static const char *DEFAULT_COLOR_SCHEME_NAME = "Cornfield"; + +RenderColorScheme::RenderColorScheme() : path("") +{ + _name = DEFAULT_COLOR_SCHEME_NAME; + _index = 1000; + _show_in_gui = true; + + _color_scheme.insert(ColorScheme::value_type(BACKGROUND_COLOR, Color4f(0xff, 0xff, 0xe5))); + _color_scheme.insert(ColorScheme::value_type(OPENCSG_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c))); + _color_scheme.insert(ColorScheme::value_type(OPENCSG_FACE_BACK_COLOR, Color4f(0x9d, 0xcb, 0x51))); + _color_scheme.insert(ColorScheme::value_type(CGAL_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c))); + _color_scheme.insert(ColorScheme::value_type(CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99))); + _color_scheme.insert(ColorScheme::value_type(CGAL_FACE_BACK_COLOR, Color4f(0x9d, 0xcb, 0x51))); + _color_scheme.insert(ColorScheme::value_type(CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0xec, 0x5e))); + _color_scheme.insert(ColorScheme::value_type(CGAL_EDGE_BACK_COLOR, Color4f(0xab, 0xd8, 0x56))); + _color_scheme.insert(ColorScheme::value_type(CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00))); + _color_scheme.insert(ColorScheme::value_type(CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00))); +} + +RenderColorScheme::RenderColorScheme(fs::path path) : path(path) +{ + try { + boost::property_tree::read_json(boosty::stringy(path).c_str(), pt); + _name = pt.get("name"); + _index = pt.get("index"); + _show_in_gui = pt.get("show-in-gui"); + + addColor(BACKGROUND_COLOR, "background"); + addColor(OPENCSG_FACE_FRONT_COLOR, "opencsg-face-front"); + addColor(OPENCSG_FACE_BACK_COLOR, "opencsg-face-back"); + addColor(CGAL_FACE_FRONT_COLOR, "cgal-face-front"); + addColor(CGAL_FACE_2D_COLOR, "cgal-face-2d"); + addColor(CGAL_FACE_BACK_COLOR, "cgal-face-back"); + addColor(CGAL_EDGE_FRONT_COLOR, "cgal-edge-front"); + addColor(CGAL_EDGE_BACK_COLOR, "cgal-edge-back"); + addColor(CGAL_EDGE_2D_COLOR, "cgal-edge-2d"); + addColor(CROSSHAIR_COLOR, "crosshair"); + } catch (const std::exception & e) { + PRINTB("Error reading color scheme file '%s': %s", path.c_str() % e.what()); + _name = ""; + _index = 0; + _show_in_gui = false; + } +} + +RenderColorScheme::~RenderColorScheme() +{ +} + +bool RenderColorScheme::valid() const +{ + return !_name.empty(); +} + +const std::string & RenderColorScheme::name() const +{ + return _name; +} + +int RenderColorScheme::index() const +{ + return _index; +} + +bool RenderColorScheme::showInGui() const +{ + return _show_in_gui; +} + +ColorScheme & RenderColorScheme::colorScheme() +{ + return _color_scheme; +} + +const boost::property_tree::ptree & RenderColorScheme::propertyTree() const +{ + return pt; +} + +void RenderColorScheme::addColor(RenderColor colorKey, std::string key) +{ + const boost::property_tree::ptree& colors = pt.get_child("colors"); + std::string color = colors.get(key); + if ((color.length() == 7) && (color.at(0) == '#')) { + char *endptr; + unsigned int val = strtol(color.substr(1).c_str(), &endptr, 16); + int r = (val >> 16) & 0xff; + int g = (val >> 8) & 0xff; + int b = val & 0xff; + _color_scheme.insert(ColorScheme::value_type(colorKey, Color4f(r, g, b))); + } else { + throw std::invalid_argument(std::string("invalid color value for key '") + key + "': '" + color + "'"); + } +} + ColorMap *ColorMap::inst(bool erase) { static ColorMap *instance = new ColorMap; @@ -13,286 +113,44 @@ ColorMap *ColorMap::inst(bool erase) return instance; } -ColorMap::ColorMap() { - boost::unordered_map tmpwebcolors = map_list_of - ("aliceblue", Color4f(240, 248, 255)) - ("antiquewhite", Color4f(250, 235, 215)) - ("aqua", Color4f(0, 255, 255)) - ("aquamarine", Color4f(127, 255, 212)) - ("azure", Color4f(240, 255, 255)) - ("beige", Color4f(245, 245, 220)) - ("bisque", Color4f(255, 228, 196)) - ("black", Color4f(0, 0, 0)) - ("blanchedalmond", Color4f(255, 235, 205)) - ("blue", Color4f(0, 0, 255)) - ("blueviolet", Color4f(138, 43, 226)) - ("brown", Color4f(165, 42, 42)) - ("burlywood", Color4f(222, 184, 135)) - ("cadetblue", Color4f(95, 158, 160)) - ("chartreuse", Color4f(127, 255, 0)) - ("chocolate", Color4f(210, 105, 30)) - ("coral", Color4f(255, 127, 80)) - ("cornflowerblue", Color4f(100, 149, 237)) - ("cornsilk", Color4f(255, 248, 220)) - ("crimson", Color4f(220, 20, 60)) - ("cyan", Color4f(0, 255, 255)) - ("darkblue", Color4f(0, 0, 139)) - ("darkcyan", Color4f(0, 139, 139)) - ("darkgoldenrod", Color4f(184, 134, 11)) - ("darkgray", Color4f(169, 169, 169)) - ("darkgreen", Color4f(0, 100, 0)) - ("darkgrey", Color4f(169, 169, 169)) - ("darkkhaki", Color4f(189, 183, 107)) - ("darkmagenta", Color4f(139, 0, 139)) - ("darkolivegreen", Color4f(85, 107, 47)) - ("darkorange", Color4f(255, 140, 0)) - ("darkorchid", Color4f(153, 50, 204)) - ("darkred", Color4f(139, 0, 0)) - ("darksalmon", Color4f(233, 150, 122)) - ("darkseagreen", Color4f(143, 188, 143)) - ("darkslateblue", Color4f(72, 61, 139)) - ("darkslategray", Color4f(47, 79, 79)) - ("darkslategrey", Color4f(47, 79, 79)) - ("darkturquoise", Color4f(0, 206, 209)) - ("darkviolet", Color4f(148, 0, 211)) - ("deeppink", Color4f(255, 20, 147)) - ("deepskyblue", Color4f(0, 191, 255)) - ("dimgray", Color4f(105, 105, 105)) - ("dimgrey", Color4f(105, 105, 105)) - ("dodgerblue", Color4f(30, 144, 255)) - ("firebrick", Color4f(178, 34, 34)) - ("floralwhite", Color4f(255, 250, 240)) - ("forestgreen", Color4f(34, 139, 34)) - ("fuchsia", Color4f(255, 0, 255)) - ("gainsboro", Color4f(220, 220, 220)) - ("ghostwhite", Color4f(248, 248, 255)) - ("gold", Color4f(255, 215, 0)) - ("goldenrod", Color4f(218, 165, 32)) - ("gray", Color4f(128, 128, 128)) - ("green", Color4f(0, 128, 0)) - ("greenyellow", Color4f(173, 255, 47)) - ("grey", Color4f(128, 128, 128)) - ("honeydew", Color4f(240, 255, 240)) - ("hotpink", Color4f(255, 105, 180)) - ("indianred", Color4f(205, 92, 92)) - ("indigo", Color4f(75, 0, 130)) - ("ivory", Color4f(255, 255, 240)) - ("khaki", Color4f(240, 230, 140)) - ("lavender", Color4f(230, 230, 250)) - ("lavenderblush", Color4f(255, 240, 245)) - ("lawngreen", Color4f(124, 252, 0)) - ("lemonchiffon", Color4f(255, 250, 205)) - ("lightblue", Color4f(173, 216, 230)) - ("lightcoral", Color4f(240, 128, 128)) - ("lightcyan", Color4f(224, 255, 255)) - ("lightgoldenrodyellow", Color4f(250, 250, 210)) - ("lightgray", Color4f(211, 211, 211)) - ("lightgreen", Color4f(144, 238, 144)) - ("lightgrey", Color4f(211, 211, 211)) - ("lightpink", Color4f(255, 182, 193)) - ("lightsalmon", Color4f(255, 160, 122)) - ("lightseagreen", Color4f(32, 178, 170)) - ("lightskyblue", Color4f(135, 206, 250)) - ("lightslategray", Color4f(119, 136, 153)) - ("lightslategrey", Color4f(119, 136, 153)) - ("lightsteelblue", Color4f(176, 196, 222)) - ("lightyellow", Color4f(255, 255, 224)) - ("lime", Color4f(0, 255, 0)) - ("limegreen", Color4f(50, 205, 50)) - ("linen", Color4f(250, 240, 230)) - ("magenta", Color4f(255, 0, 255)) - ("maroon", Color4f(128, 0, 0)) - ("mediumaquamarine", Color4f(102, 205, 170)) - ("mediumblue", Color4f(0, 0, 205)) - ("mediumorchid", Color4f(186, 85, 211)) - ("mediumpurple", Color4f(147, 112, 219)) - ("mediumseagreen", Color4f(60, 179, 113)) - ("mediumslateblue", Color4f(123, 104, 238)) - ("mediumspringgreen", Color4f(0, 250, 154)) - ("mediumturquoise", Color4f(72, 209, 204)) - ("mediumvioletred", Color4f(199, 21, 133)) - ("midnightblue", Color4f(25, 25, 112)) - ("mintcream", Color4f(245, 255, 250)) - ("mistyrose", Color4f(255, 228, 225)) - ("moccasin", Color4f(255, 228, 181)) - ("navajowhite", Color4f(255, 222, 173)) - ("navy", Color4f(0, 0, 128)) - ("oldlace", Color4f(253, 245, 230)) - ("olive", Color4f(128, 128, 0)) - ("olivedrab", Color4f(107, 142, 35)) - ("orange", Color4f(255, 165, 0)) - ("orangered", Color4f(255, 69, 0)) - ("orchid", Color4f(218, 112, 214)) - ("palegoldenrod", Color4f(238, 232, 170)) - ("palegreen", Color4f(152, 251, 152)) - ("paleturquoise", Color4f(175, 238, 238)) - ("palevioletred", Color4f(219, 112, 147)) - ("papayawhip", Color4f(255, 239, 213)) - ("peachpuff", Color4f(255, 218, 185)) - ("peru", Color4f(205, 133, 63)) - ("pink", Color4f(255, 192, 203)) - ("plum", Color4f(221, 160, 221)) - ("powderblue", Color4f(176, 224, 230)) - ("purple", Color4f(128, 0, 128)) - ("red", Color4f(255, 0, 0)) - ("rosybrown", Color4f(188, 143, 143)) - ("royalblue", Color4f(65, 105, 225)) - ("saddlebrown", Color4f(139, 69, 19)) - ("salmon", Color4f(250, 128, 114)) - ("sandybrown", Color4f(244, 164, 96)) - ("seagreen", Color4f(46, 139, 87)) - ("seashell", Color4f(255, 245, 238)) - ("sienna", Color4f(160, 82, 45)) - ("silver", Color4f(192, 192, 192)) - ("skyblue", Color4f(135, 206, 235)) - ("slateblue", Color4f(106, 90, 205)) - ("slategray", Color4f(112, 128, 144)) - ("slategrey", Color4f(112, 128, 144)) - ("snow", Color4f(255, 250, 250)) - ("springgreen", Color4f(0, 255, 127)) - ("steelblue", Color4f(70, 130, 180)) - ("tan", Color4f(210, 180, 140)) - ("teal", Color4f(0, 128, 128)) - ("thistle", Color4f(216, 191, 216)) - ("tomato", Color4f(255, 99, 71)) - ("transparent", Color4f(0, 0, 0, 0)) - ("turquoise", Color4f(64, 224, 208)) - ("violet", Color4f(238, 130, 238)) - ("wheat", Color4f(245, 222, 179)) - ("white", Color4f(255, 255, 255)) - ("whitesmoke", Color4f(245, 245, 245)) - ("yellow", Color4f(255, 255, 0)) - ("yellowgreen", Color4f(154, 205, 50)); - webcolors = tmpwebcolors; - - ColorScheme cornfield = map_list_of - (BACKGROUND_COLOR, Color4f(0xff, 0xff, 0xe5)) - (OPENCSG_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c)) - (OPENCSG_FACE_BACK_COLOR, Color4f(0x9d, 0xcb, 0x51)) - (CGAL_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c)) - (CGAL_FACE_BACK_COLOR, Color4f(0x9d, 0xcb, 0x51)) - (CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99)) - (CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0xec, 0x5e)) - (CGAL_EDGE_BACK_COLOR, Color4f(0xab, 0xd8, 0x56)) - (CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00)) - (CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00)); - - ColorScheme metallic = map_list_of - (BACKGROUND_COLOR, Color4f(0xaa, 0xaa, 0xff)) - (OPENCSG_FACE_FRONT_COLOR, Color4f(0xdd, 0xdd, 0xff)) - (OPENCSG_FACE_BACK_COLOR, Color4f(0xdd, 0x22, 0xdd)) - (CGAL_FACE_FRONT_COLOR, Color4f(0xdd, 0xdd, 0xff)) - (CGAL_FACE_BACK_COLOR, Color4f(0xdd, 0x22, 0xdd)) - (CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99)) - (CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00)) - (CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00)); - - ColorScheme sunset = map_list_of - (BACKGROUND_COLOR, Color4f(0xaa, 0x44, 0x44)) - (OPENCSG_FACE_FRONT_COLOR, Color4f(0xff, 0xaa, 0xaa)) - (OPENCSG_FACE_BACK_COLOR, Color4f(0x88, 0x22, 0x33)) - (CGAL_FACE_FRONT_COLOR, Color4f(0xff, 0xaa, 0xaa)) - (CGAL_FACE_BACK_COLOR, Color4f(0x88, 0x22, 0x33)) - (CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99)) - (CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00)) - (CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00)); - - ColorScheme starnight = map_list_of - (BACKGROUND_COLOR, webcolors["black"]) - (OPENCSG_FACE_FRONT_COLOR, webcolors["lightyellow"]) - (OPENCSG_FACE_BACK_COLOR, webcolors["cyan"]) - (CGAL_FACE_FRONT_COLOR, webcolors["lightyellow"]) - (CGAL_FACE_BACK_COLOR, webcolors["cyan"]) - (CGAL_FACE_2D_COLOR, webcolors["mediumpurple"]) - (CGAL_EDGE_FRONT_COLOR, Color4f(0x00, 0x00, 0xff)) - (CGAL_EDGE_BACK_COLOR, Color4f(0x00, 0x00, 0xff)) - (CGAL_EDGE_2D_COLOR, webcolors["magenta"]) - (CROSSHAIR_COLOR, Color4f(0xf0, 0xf0, 0xf0)); - - ColorScheme beforedawn = map_list_of - (BACKGROUND_COLOR, Color4f(0x33, 0x33, 0x33)) - (OPENCSG_FACE_FRONT_COLOR, Color4f(0xcc, 0xcc, 0xcc)) - (OPENCSG_FACE_BACK_COLOR, Color4f(0x55, 0x63, 0xdd)) - (CGAL_FACE_FRONT_COLOR, Color4f(0xcc, 0xcc, 0xcc)) - (CGAL_FACE_BACK_COLOR, Color4f(0x55, 0x63, 0xdd)) - (CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99)) - (CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00)) - (CROSSHAIR_COLOR, Color4f(0xf0, 0xf0, 0xf0)); - - ColorScheme nature = map_list_of - (BACKGROUND_COLOR, Color4f(0xfa, 0xfa, 0xfa)) - (OPENCSG_FACE_FRONT_COLOR, Color4f(0x16, 0xa0, 0x85)) - (OPENCSG_FACE_BACK_COLOR, Color4f(0xdb, 0xf4, 0xda)) - (CGAL_FACE_FRONT_COLOR, Color4f(0x16, 0xa0, 0x85)) - (CGAL_FACE_BACK_COLOR, Color4f(0xdb, 0xf4, 0xda)) - (CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99)) - (CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00)) - (CROSSHAIR_COLOR, Color4f(0x11, 0x11, 0x11)); - - ColorScheme deepocean = map_list_of - (BACKGROUND_COLOR, Color4f(0x33, 0x33, 0x33)) - (OPENCSG_FACE_FRONT_COLOR, Color4f(0xee, 0xee, 0xee)) - (OPENCSG_FACE_BACK_COLOR, Color4f(0x0b, 0xab, 0xc8)) - (CGAL_FACE_FRONT_COLOR, Color4f(0xee, 0xee, 0xee)) - (CGAL_FACE_BACK_COLOR, Color4f(0x0b, 0xab, 0xc8)) - (CGAL_FACE_2D_COLOR, webcolors["mediumpurple"]) - (CGAL_EDGE_FRONT_COLOR, Color4f(0x00, 0x00, 0xff)) - (CGAL_EDGE_BACK_COLOR, Color4f(0x00, 0x00, 0xff)) - (CGAL_EDGE_2D_COLOR, webcolors["magenta"]) - (CROSSHAIR_COLOR, Color4f(0xf0, 0xf0, 0xf0)); - - // Monotone - no difference between 'back face' and 'front face' - ColorScheme monotone = map_list_of - (BACKGROUND_COLOR, Color4f(0xff, 0xff, 0xe5)) - (OPENCSG_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c)) - (OPENCSG_FACE_BACK_COLOR, Color4f(0xf9, 0xd7, 0x2c)) - (CGAL_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c)) - (CGAL_FACE_BACK_COLOR, Color4f(0xf9, 0xd7, 0x2c)) - (CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99)) - (CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00)) - (CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00)) - (CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00)); - - boost::unordered_map tmpcolorschemes = map_list_of - ("Cornfield", cornfield) - ("Metallic", metallic) - ("Sunset", sunset) - ("Starnight", starnight) - ("BeforeDawn", beforedawn) - ("Nature", nature) - ("DeepOcean", deepocean) - ("Monotone", monotone); // Hidden, not in GUI - colorschemes = tmpcolorschemes; +ColorMap::ColorMap() +{ + colorSchemeSet = enumerateColorSchemes(); +} +ColorMap::~ColorMap() +{ } const ColorScheme &ColorMap::defaultColorScheme() const { - return colorschemes.at("Cornfield"); + return *findColorScheme(DEFAULT_COLOR_SCHEME_NAME); } const ColorScheme *ColorMap::findColorScheme(const std::string &name) const { - if (colorschemes.find(name) != colorschemes.end()) return &colorschemes.at(name); - return NULL; + for (colorscheme_set_t::const_iterator it = colorSchemeSet.begin();it != colorSchemeSet.end();it++) { + RenderColorScheme *scheme = (*it).second.get(); + if (name == scheme->name()) { + return &scheme->colorScheme(); + } + } + + return NULL; } -std::list ColorMap::colorSchemeNames() const +std::list ColorMap::colorSchemeNames(bool guiOnly) const { - std::list names; - for (boost::unordered_map::const_iterator iter=colorschemes.begin(); iter!=colorschemes.end(); iter++) { - names.push_back(iter->first); + std::list colorSchemeNames; + for (colorscheme_set_t::const_iterator it = colorSchemeSet.begin();it != colorSchemeSet.end();it++) { + RenderColorScheme *scheme = (*it).second.get(); + if (guiOnly && !scheme->showInGui()) { + continue; } - return names; + colorSchemeNames.push_back(scheme->name()); + } + + return colorSchemeNames; } Color4f ColorMap::getColor(const ColorScheme &cs, const RenderColor rc) @@ -302,19 +160,42 @@ Color4f ColorMap::getColor(const ColorScheme &cs, const RenderColor rc) return Color4f(0, 0, 0, 127); } -/* - void printcolorscheme(const ColorScheme &cs) - { - for (ColorScheme::const_iterator j=cs.begin();j!=cs.end();j++) - PRINTB("%i %s",j->first % j->second.transpose()); +void ColorMap::enumerateColorSchemesInPath(colorscheme_set_t &result_set, const fs::path path) +{ + const fs::path color_schemes = path / "color-schemes" / "render"; + + fs::directory_iterator end_iter; + + if (fs::exists(color_schemes) && fs::is_directory(color_schemes)) { + for (fs::directory_iterator dir_iter(color_schemes); dir_iter != end_iter; ++dir_iter) { + if (!fs::is_regular_file(dir_iter->status())) { + continue; + } + + const fs::path path = (*dir_iter).path(); + if (!(path.extension().string() == ".json")) { + continue; + } + + RenderColorScheme *colorScheme = new RenderColorScheme(path); + if (colorScheme->valid() && (findColorScheme(colorScheme->name()) == 0)) { + result_set.insert(colorscheme_set_t::value_type(colorScheme->index(), boost::shared_ptr(colorScheme))); + } else { + delete colorScheme; + } } + } +} - void printcolorschemes() - { - for (boost::unordered_map::const_iterator i=colorschemes.begin();i!=colorschemes.end();i++) { - PRINTB("-- %s --", i->first); - for (ColorScheme::const_iterator j=i->second.begin();j!=i->second.end();j++) - PRINTB("%i %s",j->first % j->second.transpose()); - } - } -*/ +ColorMap::colorscheme_set_t ColorMap::enumerateColorSchemes() +{ + colorscheme_set_t result_set; + + RenderColorScheme *defaultColorScheme = new RenderColorScheme(); + result_set.insert(colorscheme_set_t::value_type(defaultColorScheme->index(), + boost::shared_ptr(defaultColorScheme))); + enumerateColorSchemesInPath(result_set, PlatformUtils::resourcesPath()); + enumerateColorSchemesInPath(result_set, PlatformUtils::userConfigPath()); + + return result_set; +} \ No newline at end of file diff --git a/src/colormap.h b/src/colormap.h index 9f305efd..168fa463 100644 --- a/src/colormap.h +++ b/src/colormap.h @@ -4,7 +4,13 @@ #include #include #include "linalg.h" -#include + +#include +#include +#include +#include + +namespace fs = boost::filesystem; enum RenderColor { BACKGROUND_COLOR, @@ -21,23 +27,59 @@ enum RenderColor { typedef std::map ColorScheme; +class RenderColorScheme +{ +private: + const fs::path path; + + boost::property_tree::ptree pt; + std::string _name; + int _index; + bool _show_in_gui; + + ColorScheme _color_scheme; + +public: + /** + * Constructor for the default color scheme Cornfield. + */ + RenderColorScheme(); + /** + * Constructor for reading external JSON files. + */ + RenderColorScheme(const fs::path path); + virtual ~RenderColorScheme(); + + const std::string & name() const; + int index() const; + bool valid() const; + bool showInGui() const; + ColorScheme & colorScheme(); + const boost::property_tree::ptree & propertyTree() const; + +private: + void addColor(RenderColor colorKey, std::string key); + + friend class ColorMap; +}; + class ColorMap { + typedef std::multimap, std::less > colorscheme_set_t; + public: static ColorMap *inst(bool erase = false); - const ColorScheme &defaultColorScheme() const; - - const boost::unordered_map &webColors() const { return webcolors; } + const ColorScheme & defaultColorScheme() const; const ColorScheme *findColorScheme(const std::string &name) const; - std::list colorSchemeNames() const; + std::list colorSchemeNames(bool guiOnly = false) const; static Color4f getColor(const ColorScheme &cs, const RenderColor rc); private: ColorMap(); - ~ColorMap() {} - - boost::unordered_map webcolors; - boost::unordered_map colorschemes; + virtual ~ColorMap(); + colorscheme_set_t enumerateColorSchemes(); + void enumerateColorSchemesInPath(colorscheme_set_t &result_set, const fs::path path); + colorscheme_set_t colorSchemeSet; }; diff --git a/src/editor.h b/src/editor.h index 7dbea023..553e42a8 100644 --- a/src/editor.h +++ b/src/editor.h @@ -21,6 +21,7 @@ public: virtual QString selectedText() = 0; virtual bool find(const QString &, bool findNext = false, bool findBackwards = false) = 0; virtual void replaceSelectedText(const QString &) = 0; + virtual QStringList colorSchemes() = 0; signals: void contentsChanged(); diff --git a/src/highlighter.cc b/src/highlighter.cc index 67c343e2..2db4b3da 100644 --- a/src/highlighter.cc +++ b/src/highlighter.cc @@ -235,9 +235,6 @@ Highlighter::Highlighter(QTextDocument *parent) tokentypes["_$quote"] << "_$quote"; tokentypes["_$number"] << "_$number"; - QString syntaxhighlight = Preferences::inst()->getValue("editor/syntaxhighlight").toString(); - this->assignFormatsToTokens(syntaxhighlight); - errorFormat.setBackground(Qt::red); errorState = false; errorPos = -1; diff --git a/src/legacyeditor.cc b/src/legacyeditor.cc index 09c71a37..abb50007 100644 --- a/src/legacyeditor.cc +++ b/src/legacyeditor.cc @@ -271,3 +271,15 @@ bool LegacyEditor::isContentModified() { return textedit->document()->isModified(); } + +QStringList LegacyEditor::colorSchemes() +{ + QStringList colorSchemes; + + colorSchemes + << "For Light Background" + << "For Dark Background" + << "Off"; + + return colorSchemes; +} diff --git a/src/legacyeditor.h b/src/legacyeditor.h index 663cc307..1b37e14f 100644 --- a/src/legacyeditor.h +++ b/src/legacyeditor.h @@ -15,6 +15,7 @@ public: bool find(const QString &, bool findNext = false, bool findBackwards = false); void replaceSelectedText(const QString &newText); bool findString(const QString & exp, bool findBackwards) const; + QStringList colorSchemes(); public slots: void zoomIn(); diff --git a/src/mainwin.cc b/src/mainwin.cc index a9099946..38daa18e 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -187,8 +187,9 @@ MainWindow::MainWindow(const QString &filename) this->consoleDock->setConfigKey("view/hideConsole"); this->consoleDock->setAction(this->viewActionHideConsole); - editortype = Preferences::inst()->getValue("editor/editortype").toString(); - useScintilla = (editortype == "QScintilla Editor"); + QSettings settings; + editortype = settings.value("editor/editortype").toString(); + useScintilla = (editortype != "Simple Editor"); #ifdef USE_SCINTILLA_EDITOR if (useScintilla) { @@ -198,6 +199,8 @@ MainWindow::MainWindow(const QString &filename) #endif editor = new LegacyEditor(editorDockContents); + Preferences::create(this, editor->colorSchemes()); + editorDockContents->layout()->addWidget(editor); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); @@ -521,7 +524,6 @@ MainWindow::MainWindow(const QString &filename) } // make sure it looks nice.. - QSettings settings; QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray(); restoreState(windowState); resize(settings.value("window/size", QSize(800, 600)).toSize()); diff --git a/src/openscad.cc b/src/openscad.cc index 433f9aa1..5f660284 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -56,13 +56,6 @@ #include -#ifdef __APPLE__ -#include "AppleEvents.h" -#ifdef OPENSCAD_DEPLOY - #include "SparkleAutoUpdater.h" -#endif -#endif - #include "Camera.h" #include #include @@ -70,6 +63,13 @@ #include #include "boosty.h" +#ifdef __APPLE__ +#include "AppleEvents.h" +#ifdef OPENSCAD_DEPLOY + #include "SparkleAutoUpdater.h" +#endif +#endif + #ifdef _MSC_VER #define snprintf _snprintf #endif @@ -557,9 +557,9 @@ int gui(vector &inputFiles, const fs::path &original_path, int argc, cha #endif #if defined(OPENSCAD_DEPLOY) && defined(Q_OS_MAC) - AutoUpdater *updater = new SparkleAutoUpdater; - AutoUpdater::setUpdater(updater); - if (updater->automaticallyChecksForUpdates()) updater->checkForUpdates(); +// AutoUpdater *updater = new SparkleAutoUpdater; +// AutoUpdater::setUpdater(updater); +// if (updater->automaticallyChecksForUpdates()) updater->checkForUpdates(); #endif #if 0 /*** disabled by clifford wolf: adds rendering artefacts with OpenCSG ***/ diff --git a/src/rendersettings.cc b/src/rendersettings.cc index b3eb86b2..36c69293 100644 --- a/src/rendersettings.cc +++ b/src/rendersettings.cc @@ -1,5 +1,4 @@ #include "rendersettings.h" -#include "colormap.h" #include "printutils.h" RenderSettings *RenderSettings::inst(bool erase) diff --git a/src/rendersettings.h b/src/rendersettings.h index 09be9ded..4320dad0 100644 --- a/src/rendersettings.h +++ b/src/rendersettings.h @@ -2,7 +2,6 @@ #include #include "linalg.h" -#include "colormap.h" class RenderSettings { diff --git a/src/scintillaeditor.cpp b/src/scintillaeditor.cpp index 37fce125..d29d28f3 100644 --- a/src/scintillaeditor.cpp +++ b/src/scintillaeditor.cpp @@ -4,6 +4,45 @@ #include "scintillaeditor.h" #include #include "Preferences.h" +#include "PlatformUtils.h" + +EditorColorScheme::EditorColorScheme(fs::path path) : path(path) +{ + try { + boost::property_tree::read_json(boosty::stringy(path).c_str(), pt); + _name = QString(pt.get("name").c_str()); + _index = pt.get("index"); + } catch (const std::exception & e) { + PRINTB("Error reading color scheme file '%s': %s", path.c_str() % e.what()); + _name = ""; + _index = 0; + } +} + +EditorColorScheme::~EditorColorScheme() +{ + +} + +bool EditorColorScheme::valid() const +{ + return !_name.isEmpty(); +} + +const QString & EditorColorScheme::name() const +{ + return _name; +} + +int EditorColorScheme::index() const +{ + return _index; +} + +const boost::property_tree::ptree & EditorColorScheme::propertyTree() const +{ + return pt; +} ScintillaEditor::ScintillaEditor(QWidget *parent) : EditorInterface(parent) { @@ -51,7 +90,6 @@ ScintillaEditor::ScintillaEditor(QWidget *parent) : EditorInterface(parent) initMargin(); qsci->setFolding(QsciScintilla::BoxedTreeFoldStyle, 4); qsci->setCaretLineVisible(true); - this->setHighlightScheme(Preferences::inst()->getValue("editor/syntaxhighlight").toString()); connect(qsci, SIGNAL(textChanged()), this, SIGNAL(contentsChanged())); connect(qsci, SIGNAL(modificationChanged(bool)), this, SIGNAL(modificationChanged(bool))); @@ -87,7 +125,6 @@ void ScintillaEditor::highlightError(int error_pos) int line, index; qsci->lineIndexFromPosition(error_pos, &line, &index); qsci->fillIndicatorRange(line, index, line, index+1, indicatorNumber); - qsci->setIndicatorForegroundColor(QColor(255,0,0,100)); qsci->markerAdd(line, markerNumber); } @@ -100,115 +137,155 @@ void ScintillaEditor::unhighlightLastError() qsci->markerDeleteAll(markerNumber); } -//Editor themes -void ScintillaEditor::forLightBackground() +QColor ScintillaEditor::readColor(const boost::property_tree::ptree &pt, const std::string name, const QColor defaultColor) { - lexer->setPaper("#fff"); - lexer->setColor(QColor("#272822")); // -> Style: Default text - lexer->setColor(QColor("Green"), QsciLexerCPP::Keyword); // -> Style: Keyword - lexer->setColor(QColor("Green"), QsciLexerCPP::KeywordSet2); // -> Style: KeywordSet2 - lexer->setColor(Qt::blue, QsciLexerCPP::CommentDocKeyword); // -> used in comments only like /*! \cube */ - lexer->setColor(QColor("DarkBlue"), QsciLexerCPP::GlobalClass); // -> Style: GlobalClass - lexer->setColor(Qt::blue, QsciLexerCPP::Operator); - lexer->setColor(Qt::darkMagenta, QsciLexerCPP::DoubleQuotedString); - lexer->setColor(Qt::darkCyan, QsciLexerCPP::Comment); - lexer->setColor(Qt::darkCyan, QsciLexerCPP::CommentLine); - lexer->setColor(QColor("DarkRed"), QsciLexerCPP::Number); - qsci->setMarkerBackgroundColor(QColor(255, 0, 0, 100), markerNumber); - qsci->setCaretLineBackgroundColor(QColor("#ffe4e4")); - qsci->setMarginsBackgroundColor(QColor("#ccc")); - qsci->setMarginsForegroundColor(QColor("#111")); - qsci->setMatchedBraceBackgroundColor(QColor("#333")); - qsci->setMatchedBraceForegroundColor(QColor("#fff")); + try { + const std::string val = pt.get(name); + return QColor(val.c_str()); + } catch (std::exception e) { + return defaultColor; + } } -void ScintillaEditor::forDarkBackground() +int ScintillaEditor::readInt(const boost::property_tree::ptree &pt, const std::string name, const int defaultValue) { - lexer->setPaper(QColor("#272822")); - lexer->setColor(QColor(Qt::white)); - lexer->setColor(QColor("#f12971"), QsciLexerCPP::Keyword); - lexer->setColor(QColor("#56dbf0"),QsciLexerCPP::KeywordSet2); - lexer->setColor(QColor("#ccdf32"), QsciLexerCPP::CommentDocKeyword); - lexer->setColor(QColor("#56d8f0"), QsciLexerCPP::GlobalClass); - lexer->setColor(QColor("#d8d8d8"), QsciLexerCPP::Operator); - lexer->setColor(QColor("#e6db74"), QsciLexerCPP::DoubleQuotedString); - lexer->setColor(QColor("#e6db74"), QsciLexerCPP::CommentLine); - lexer->setColor(QColor("#af7dff"), QsciLexerCPP::Number); - qsci->setCaretLineBackgroundColor(QColor(104,225,104, 127)); - qsci->setMarkerBackgroundColor(QColor(255, 0, 0, 100), markerNumber); - qsci->setMarginsBackgroundColor(QColor("20,20,20,150")); - qsci->setMarginsForegroundColor(QColor("#fff")); - qsci->setCaretWidth(2); - qsci->setCaretForegroundColor(QColor("#ffff00")); + try { + const int val = pt.get(name); + return val; + } catch (std::exception e) { + return defaultValue; + } } -void ScintillaEditor::Monokai() +void ScintillaEditor::setColormap(const EditorColorScheme *colorScheme) { - lexer->setPaper("#272822"); - lexer->setColor(QColor("#f8f8f2")); // -> Style: Default text - lexer->setColor(QColor("#66c3b3"), QsciLexerCPP::Keyword); // -> Style: Keyword - lexer->setColor(QColor("#79abff"), QsciLexerCPP::KeywordSet2); // -> Style: KeywordSet2 - lexer->setColor(QColor("#ccdf32"), QsciLexerCPP::CommentDocKeyword); // -> used in comments only like /*! \cube */ - lexer->setColor(QColor("#ffffff"), QsciLexerCPP::GlobalClass); // -> Style: GlobalClass - lexer->setColor(QColor("#d8d8d8"), QsciLexerCPP::Operator); - lexer->setColor(QColor("#e6db74"), QsciLexerCPP::DoubleQuotedString); - lexer->setColor(QColor("#75715e"), QsciLexerCPP::CommentLine); - lexer->setColor(QColor("#7fb347"), QsciLexerCPP::Number); - qsci->setMarkerBackgroundColor(QColor(255, 0, 0, 100), markerNumber); - qsci->setCaretLineBackgroundColor(QColor("#3e3d32")); - qsci->setMarginsBackgroundColor(QColor("#757575")); - qsci->setMarginsForegroundColor(QColor("#f8f8f2")); - qsci->setCaretWidth(2); - qsci->setCaretForegroundColor(QColor("#ffff00")); -} + const boost::property_tree::ptree & pt = colorScheme->propertyTree(); -void ScintillaEditor::Solarized_light() -{ - lexer->setPaper("#fdf6e3"); - lexer->setColor(QColor("#657b83")); // -> Style: Default text - lexer->setColor(QColor("#268ad1"), QsciLexerCPP::Keyword); // -> Style: Keyword - lexer->setColor(QColor("#6c71c4"), QsciLexerCPP::KeywordSet2); // -> Style: KeywordSet2 - lexer->setColor(QColor("#b58900"), QsciLexerCPP::CommentDocKeyword); // -> used in comments only like /*! \cube */ - lexer->setColor(QColor("#b58800"), QsciLexerCPP::GlobalClass); // -> Style: GlobalClass - lexer->setColor(QColor("#859900"), QsciLexerCPP::Operator); - lexer->setColor(QColor("#2aa198"), QsciLexerCPP::DoubleQuotedString); - lexer->setColor(QColor("#b58800"), QsciLexerCPP::CommentLine); - lexer->setColor(QColor("#cb4b16"), QsciLexerCPP::Number); - qsci->setMarkerBackgroundColor(QColor(255, 0, 0, 100), markerNumber); - qsci->setCaretLineBackgroundColor(QColor("#eeead5")); - qsci->setMarginsBackgroundColor(QColor("#eee8d5")); - qsci->setMarginsForegroundColor(QColor("#93a1a1")); - qsci->setMatchedBraceBackgroundColor(QColor("#0000ff")); - qsci->setMatchedBraceBackgroundColor(QColor("#333")); - qsci->setMatchedBraceForegroundColor(QColor("#fff")); + try { + const QColor textColor(pt.get("text").c_str()); + const QColor paperColor(pt.get("paper").c_str()); + + lexer->setColor(textColor); + lexer->setPaper(paperColor); + + const boost::property_tree::ptree& colors = pt.get_child("colors"); + lexer->setColor(readColor(colors, "keyword1", textColor), QsciLexerCPP::Keyword); + lexer->setColor(readColor(colors, "keyword2", textColor), QsciLexerCPP::KeywordSet2); + lexer->setColor(readColor(colors, "keyword3", textColor), QsciLexerCPP::GlobalClass); + lexer->setColor(readColor(colors, "comment", textColor), QsciLexerCPP::CommentDocKeyword); + lexer->setColor(readColor(colors, "number", textColor), QsciLexerCPP::Number); + lexer->setColor(readColor(colors, "string", textColor), QsciLexerCPP::DoubleQuotedString); + lexer->setColor(readColor(colors, "operator", textColor), QsciLexerCPP::Operator); + lexer->setColor(readColor(colors, "commentline", textColor), QsciLexerCPP::CommentLine); + + const boost::property_tree::ptree& caret = pt.get_child("caret"); + + qsci->setCaretWidth(readInt(caret, "width", 1)); + qsci->setCaretForegroundColor(readColor(caret, "foreground", textColor)); + qsci->setCaretLineBackgroundColor(readColor(caret, "line-background", paperColor)); + + qsci->setMarkerBackgroundColor(readColor(colors, "error-marker", QColor(255, 0, 0, 100)), markerNumber); + qsci->setMarginsBackgroundColor(readColor(colors, "margin-background", paperColor)); + qsci->setMarginsForegroundColor(readColor(colors, "margin-foreground", textColor)); + qsci->setMatchedBraceBackgroundColor(readColor(colors, "matched-brace-background", paperColor)); + qsci->setMatchedBraceForegroundColor(readColor(colors, "matched-brace-foreground", textColor)); + qsci->setUnmatchedBraceBackgroundColor(readColor(colors, "unmatched-brace-background", paperColor)); + qsci->setUnmatchedBraceForegroundColor(readColor(colors, "unmatched-brace-foreground", textColor)); + qsci->setSelectionForegroundColor(readColor(colors, "selection-foreground", paperColor)); + qsci->setSelectionBackgroundColor(readColor(colors, "selection-background", textColor)); + qsci->setFoldMarginColors(readColor(colors, "margin-foreground", textColor), + readColor(colors, "margin-background", paperColor)); + qsci->setEdgeColor(readColor(colors, "edge", textColor)); + } catch (std::exception e) { + noColor(); + } } void ScintillaEditor::noColor() { - lexer->setPaper(Qt::white); - lexer->setColor(Qt::black); - qsci->setMarginsBackgroundColor(QColor("#ccc")); - qsci->setMarginsForegroundColor(QColor("#111")); + lexer->setPaper(Qt::white); + lexer->setColor(Qt::black); + qsci->setCaretWidth(2); + qsci->setCaretForegroundColor(Qt::black); + qsci->setMarkerBackgroundColor(QColor(255, 0, 0, 100), markerNumber); + qsci->setCaretLineBackgroundColor(Qt::white); + qsci->setMarginsBackgroundColor(Qt::white); + qsci->setMarginsForegroundColor(Qt::black); + qsci->setSelectionForegroundColor(Qt::white); + qsci->setSelectionBackgroundColor(Qt::black); + qsci->setMatchedBraceBackgroundColor(Qt::white); + qsci->setMatchedBraceForegroundColor(Qt::black); + qsci->setUnmatchedBraceBackgroundColor(Qt::white); + qsci->setUnmatchedBraceForegroundColor(Qt::black); + qsci->setMarginsBackgroundColor(Qt::lightGray); + qsci->setMarginsForegroundColor(Qt::black); + qsci->setFoldMarginColors(Qt::black, Qt::lightGray); + qsci->setEdgeColor(Qt::black); +} + +void ScintillaEditor::enumerateColorSchemesInPath(ScintillaEditor::colorscheme_set_t &result_set, const fs::path path) +{ + const fs::path color_schemes = path / "color-schemes" / "editor"; + + fs::directory_iterator end_iter; + + if (fs::exists(color_schemes) && fs::is_directory(color_schemes)) { + for (fs::directory_iterator dir_iter(color_schemes); dir_iter != end_iter; ++dir_iter) { + if (!fs::is_regular_file(dir_iter->status())) { + continue; + } + + const fs::path path = (*dir_iter).path(); + if (!(path.extension().string() == ".json")) { + continue; + } + + EditorColorScheme *colorScheme = new EditorColorScheme(path); + if (colorScheme->valid()) { + result_set.insert(colorscheme_set_t::value_type(colorScheme->index(), boost::shared_ptr(colorScheme))); + } else { + delete colorScheme; + } + } + } +} + +ScintillaEditor::colorscheme_set_t ScintillaEditor::enumerateColorSchemes() +{ + colorscheme_set_t result_set; + + enumerateColorSchemesInPath(result_set, PlatformUtils::resourcesPath()); + enumerateColorSchemesInPath(result_set, PlatformUtils::userConfigPath()); + + return result_set; +} + +QStringList ScintillaEditor::colorSchemes() +{ + const colorscheme_set_t colorscheme_set = enumerateColorSchemes(); + + QStringList colorSchemes; + for (colorscheme_set_t::const_iterator it = colorscheme_set.begin();it != colorscheme_set.end();it++) { + colorSchemes << (*it).second.get()->name(); + } + colorSchemes << "Off"; + return colorSchemes; } void ScintillaEditor::setHighlightScheme(const QString &name) { - if(name == "For Light Background") { - forLightBackground(); - } - else if(name == "For Dark Background") { - forDarkBackground(); - } - else if(name == "Monokai") { - Monokai(); - } - else if(name == "Solarized") { - Solarized_light(); - } - else if(name == "Off") { + const colorscheme_set_t colorscheme_set = enumerateColorSchemes(); + + for (colorscheme_set_t::const_iterator it = colorscheme_set.begin();it != colorscheme_set.end();it++) { + const EditorColorScheme *colorScheme = (*it).second.get(); + if (colorScheme->name() == name) { + setColormap(colorScheme); + return; + } + } + noColor(); - } } void ScintillaEditor::insert(const QString &text) @@ -307,7 +384,7 @@ void ScintillaEditor::replaceSelectedText(const QString &newText) if (qsci->selectedText() != newText) qsci->replaceSelectedText(newText); } -void ScintillaEditor::get_range(int *lineFrom, int *lineTo) +void ScintillaEditor::getRange(int *lineFrom, int *lineTo) { int indexFrom, indexTo; if (qsci->hasSelectedText()) { @@ -324,7 +401,7 @@ void ScintillaEditor::get_range(int *lineFrom, int *lineTo) void ScintillaEditor::indentSelection() { int lineFrom, lineTo; - get_range(&lineFrom, &lineTo); + getRange(&lineFrom, &lineTo); for (int line = lineFrom;line <= lineTo;line++) { qsci->indent(line); } @@ -333,7 +410,7 @@ void ScintillaEditor::indentSelection() void ScintillaEditor::unindentSelection() { int lineFrom, lineTo; - get_range(&lineFrom, &lineTo); + getRange(&lineFrom, &lineTo); for (int line = lineFrom;line <= lineTo;line++) { qsci->unindent(line); } @@ -344,7 +421,7 @@ void ScintillaEditor::commentSelection() bool hasSelection = qsci->hasSelectedText(); int lineFrom, lineTo; - get_range(&lineFrom, &lineTo); + getRange(&lineFrom, &lineTo); for (int line = lineFrom;line <= lineTo;line++) { qsci->insertAt("//", line, 0); } @@ -359,7 +436,7 @@ void ScintillaEditor::uncommentSelection() bool hasSelection = qsci->hasSelectedText(); int lineFrom, lineTo; - get_range(&lineFrom, &lineTo); + getRange(&lineFrom, &lineTo); for (int line = lineFrom;line <= lineTo;line++) { QString lineText = qsci->text(line); if (lineText.startsWith("//")) { diff --git a/src/scintillaeditor.h b/src/scintillaeditor.h index 38193eb6..3b582ea6 100644 --- a/src/scintillaeditor.h +++ b/src/scintillaeditor.h @@ -1,16 +1,46 @@ #pragma once +#include #include +#include #include #include #include #include #include "editor.h" #include "scadlexer.h" +#include "parsersettings.h" + +#include +#include +#include + +class EditorColorScheme +{ +private: + const fs::path path; + + boost::property_tree::ptree pt; + QString _name; + int _index; + +public: + EditorColorScheme(const fs::path path); + virtual ~EditorColorScheme(); + + const QString & name() const; + int index() const; + bool valid() const; + const boost::property_tree::ptree & propertyTree() const; + +}; class ScintillaEditor : public EditorInterface -{ +{ Q_OBJECT; + + typedef std::multimap, std::less > colorscheme_set_t; + public: ScintillaEditor(QWidget *parent); virtual ~ScintillaEditor() {} @@ -18,17 +48,19 @@ public: QString toPlainText(); void initMargin(); void initLexer(); - void forLightBackground(); - void forDarkBackground(); - void Monokai(); - void Solarized_light(); void noColor(); QString selectedText(); bool find(const QString &, bool findNext = false, bool findBackwards = false); void replaceSelectedText(const QString&); + QStringList colorSchemes(); private: - void get_range(int *lineFrom, int *lineTo); + void getRange(int *lineFrom, int *lineTo); + void setColormap(const EditorColorScheme *colorScheme); + int readInt(const boost::property_tree::ptree &pt, const std::string name, const int defaultValue); + QColor readColor(const boost::property_tree::ptree &pt, const std::string name, const QColor defaultColor); + void enumerateColorSchemesInPath(colorscheme_set_t &result_set, const fs::path path); + colorscheme_set_t enumerateColorSchemes(); public slots: void zoomIn(); diff --git a/xcode/OpenSCAD.xcodeproj/project.pbxproj b/xcode/OpenSCAD.xcodeproj/project.pbxproj index e878f77e..418fa3fc 100644 --- a/xcode/OpenSCAD.xcodeproj/project.pbxproj +++ b/xcode/OpenSCAD.xcodeproj/project.pbxproj @@ -638,7 +638,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "rm -rf \"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME\"\ncp -Rf \"$PROJECT_DIR/../$FULL_PRODUCT_NAME\" \"$PROJECT_DIR/../libraries\" \"$PROJECT_DIR/../examples\" \"$PROJECT_DIR/../fonts\" \"$BUILT_PRODUCTS_DIR\""; + shellScript = "rm -rf \"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME\"\ncp -Rf \"$PROJECT_DIR/../$FULL_PRODUCT_NAME\" \"$PROJECT_DIR/../libraries\" \"$PROJECT_DIR/../examples\" \"$PROJECT_DIR/../fonts\" \"$PROJECT_DIR/../color-schemes\" \"$BUILT_PRODUCTS_DIR\""; }; E0395E7C19AA884F00E43D12 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -651,7 +651,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "rm -rf \"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME\"\ncp -Rf \"$PROJECT_DIR/../tests/$FULL_PRODUCT_NAME\" \"$PROJECT_DIR/../libraries\" \"$PROJECT_DIR/../examples\" \"$PROJECT_DIR/../fonts\" \"$BUILT_PRODUCTS_DIR\""; + shellScript = "rm -rf \"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME\"\ncp -Rf \"$PROJECT_DIR/../tests/$FULL_PRODUCT_NAME\" \"$PROJECT_DIR/../libraries\" \"$PROJECT_DIR/../examples\" \"$PROJECT_DIR/../fonts\" \"$PROJECT_DIR/../color-schemes\" \"$BUILT_PRODUCTS_DIR\""; }; /* End PBXShellScriptBuildPhase section */