diff --git a/.gitignore b/.gitignore index b596d1a..f203271 100644 --- a/.gitignore +++ b/.gitignore @@ -266,5 +266,7 @@ nimcache/ # wxnim - Linux doesn't need .exe or similar file ending. Putting this here until a better solution is found examples/genuimacro/controlgallery examples/genuimacro/threads +examples/genuimacro/string_interop examples/purewx/example1 examples/purewx/example2 + diff --git a/README.md b/README.md index 12da7c3..5b6d0b1 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Still in development, is shown to work fine, but needs more testing! - [Installation](#installation) * [Installation on Linux](#installation-on-linux) * [Installation on Windows](#installation-on-windows) + * [Installation on macOS](#installation-on-macOS) - [Examples](#examples) * [With GenUI macro](#with-genui-macro) * [Running work on background threads](#running-work-on-background-threads) @@ -22,7 +23,7 @@ Still in development, is shown to work fine, but needs more testing! # Installation -wxWidgets works across all major platforms but the build process is slightly different. Below follows instructions on how to build for Linux and Windows. If you use Mac OSX it would be great if you shared how to build on a Mac and it can be added here as well. Since a simple nim.cfg file doesn't quite cut it here we use the file wxCompile.nim to decide which flags to pass so you would have to modify that to make changes. +wxWidgets works across all major platforms but the build process is slightly different. Below are instructions for building on Linux, Windows, and macOS. Since a simple nim.cfg file doesn't quite cut it here we use the file wxCompile.nim to decide which flags to pass so you would have to modify that to make changes. ## Installation on Linux @@ -39,6 +40,33 @@ More details can be found here: https://wiki.wxwidgets.org/Compiling_wxWidgets_with_MinGW +## Installation on macOS + +Both methods below work for Apple Silicon (M1) as well as x86_64. + +### Method 1: Install wxWidgets with Homebrew +``brew install wxmac`` + +This installs 3.0.5, which doesn't support dark mode. +If you want to support dark mode, you need version 3.1.x by building it yourself. See steps below. + +### Method 2: Build wxWidgets yourself (recommended) + +The following steps work even if you have already installed wxWidgets via Homebrew (they can live side-by-side). + +1. Get [latest development release](https://www.wxwidgets.org/downloads/) (3.1.4 as of this writing) +2. Unarchive into an appropriate directory. For remaining steps, assume /usr/local +3. ``cd /usr/local/wxWidgets-3.1.4`` +4. ``mkdir build_macOS && cd build_macOS`` (make a build output directory and cd into it) +5. ``../configure CXXFLAGS="-I/opt/homebrew/include"`` (pass include directory for brew-installed libs like ``libtiff``) +6. ``make`` + +wxWidgets is now built in ``/usr/local/wxWidgets-3.1.4/build_macOS/``. +To build your Nim/wxWidgets project, pass this path to the nim compiler. + +For instance, to build the ``controlgallery.nim`` example, execute ``nim cpp -r -d:"wxWidgetsPath:/usr/local/wxWidgets-3.1.4/build_macOS" controlgallery.nim`` + + # Examples ## With GenUI macro @@ -49,16 +77,21 @@ This module ships with a macro to easily create GUIs. To see it in use look at o nim cpp -r controlgallery.nim -The output of the macro should look like these images from Linux and Windows respectively: +The output of the macro should look like these images from Linux, Windows, and macOS: -On Linux wxWidgets uses GTK+ as it's backend and looks will vary greatly depending on theme (this screenshot is taken with the Arc theme and M+ 2p font). +On Linux, wxWidgets uses GTK+ as it's backend and looks will vary greatly depending on theme (this screenshot is taken with the Arc theme and M+ 2p font). ![Linux](/screenshots/linux.png) -On Windows wxWidgets uses Win32 Forms, so looks might change depending on Windows version, this is from Windows 10: +On Windows, wxWidgets uses Win32 Forms, so looks might change depending on Windows version, this is from Windows 10: ![Windows](/screenshots/windows.png) +On macOS, wxWidgets uses Apple's Cocoa toolkit. + +![macOS-darkmode](/screenshots/macOS-darkmode.png) +![macOS-lightmode](/screenshots/macOS-lightmode.png) + ## Running work on background threads Since wxWidgets requires the main thread to perform UI actions you would want to perform long running tasks in threads. To see an example of how you can use threads with wxWidgets look at the ``threads`` example found in ``examples/genuimacro``. diff --git a/examples/genuimacro/string_interop.nim b/examples/genuimacro/string_interop.nim new file mode 100644 index 0000000..e14b26e --- /dev/null +++ b/examples/genuimacro/string_interop.nim @@ -0,0 +1,24 @@ + +import "../../wxnim/wx", "../../wxnim/genui" + +{.experimental.} + +var + textCtrl: ptr WxTextCtrl + + +proc buttonClicked(e: var WxCommandEvent) = + var + theText = string(textCtrl.getValue()) + echo theText + + +genui: + mainFrame % Frame(title = "Hello World"): + Panel | BoxSizer(orient = wxHorizontal): + StaticBox(label = "Basic controls") | StaticBoxSizer(orient = wxVertical): + textCtrl % TextCtrl + theButton % Button -> (wxEVT_BUTTON, buttonClicked): "Click me" + +mainFrame.show() +runMainLoop() \ No newline at end of file diff --git a/screenshots/macOS-darkmode.png b/screenshots/macOS-darkmode.png new file mode 100644 index 0000000..e5a3996 Binary files /dev/null and b/screenshots/macOS-darkmode.png differ diff --git a/screenshots/macOS-lightmode.png b/screenshots/macOS-lightmode.png new file mode 100644 index 0000000..265dbd8 Binary files /dev/null and b/screenshots/macOS-lightmode.png differ diff --git a/wxnim/wx.nim b/wxnim/wx.nim index 497a61a..6a2f0c6 100644 --- a/wxnim/wx.nim +++ b/wxnim/wx.nim @@ -20,6 +20,30 @@ include private/string converter toWxString*(s: string): WxString = result = constructWxString(cstring(s), s.len) +converter toString*(s: WxString): string = + #[ + Context about wxString handling: + - wxString class reference, particularly .ToUTF8() method + https://docs.wxwidgets.org/3.0/classwx_string.html + - wxScopedCharTypeBuffer reference, particularly .data() method + https://docs.wxwidgets.org/3.0/classwx_scoped_char_type_buffer.html#a7cd7ba0ab32e9f63779f602c2bdfd9b8 + + Nim emit pragma for embedding C++ code: + - https://nim-lang.github.io/Nim/manual.html#implementation-specific-pragmas-emit-pragma + + C++11 limits on implicit conversion from const char* to char* + - https://stackoverflow.com/questions/48554625/vs-2017-doesnt-implicitly-convert-const-char-to-char/48554786 + - https://en.cppreference.com/w/cpp/language/const_cast + ]# + var r: cstring + + {.emit: """ + `r` = const_cast((const char*)s.ToUTF8().data()); + """.} + + result = $r #convert cstring to string + + converter wxOrientationToClong*(inType:WxOrientation): clong = cast[clong](inType) converter wxStretchToCint*(inType:WxStretch): cint = cast[cint](inType) diff --git a/wxnim/wxCompile.nim b/wxnim/wxCompile.nim index 2560519..0820b08 100644 --- a/wxnim/wxCompile.nim +++ b/wxnim/wxCompile.nim @@ -100,4 +100,4 @@ elif defined(gcc) or defined(clang): "wx-config" const wxConfigOptions {.strdefine.}: string = "" {.passC: "`" & wxConfig & " " & wxConfigOptions & " --cppflags`".} - {.passL: "`" & wxConfig & " " & wxConfigOptions & " --libs`".} + {.passL: "`" & wxConfig & " " & wxConfigOptions & " --libs all`".}