From 3301251d90b8c015062b70b1fd3f5c46ff99f7c3 Mon Sep 17 00:00:00 2001 From: "Christopher A. Mosher" Date: Sun, 4 Dec 2022 16:33:27 -0500 Subject: [PATCH] re-work build/package; add prefs dlg; add config.h generation --- .github/workflows/build.yaml | 371 ++++---- .gitignore | 1 + CMakeLists.txt | 82 +- bin/Linux/setup.sh | 10 + bin/Windows/setup.sh | 3 + bin/build.sh | 32 + bin/macOS/setup.sh | 6 + share/FixBundle.cmake.in | 16 + share/Info.plist.in | 22 + .../Resources/conf}/epple2.a2bare.conf | 0 .../Resources/conf}/epple2.a2dos31.conf | 0 .../Resources/conf}/epple2.a2dos33.conf | 0 .../Resources/conf}/epple2.a2loaded.conf | 0 .../Resources/conf}/epple2.a2pbare.conf | 0 .../Resources/conf}/epple2.a2pdos33.conf | 0 .../Resources/conf}/epple2.a2ploaded.conf | 0 {conf => share/Resources/conf}/epple2.conf | 0 .../Resources/conf}/epple2.rev0bare.conf | 0 .../Resources/conf}/epple2.visual6502.conf | 0 share/Resources/epple2.fbp | 879 ++++++++++++++++++ share/Resources/epple2.png | Bin 0 -> 17383 bytes share/Resources/epple2.xrc | 181 ++++ {rom => share/Resources/rom}/.gitignore | 0 {rom => share/Resources/rom}/CMakeLists.txt | 0 {rom => share/Resources/rom}/Makefile | 0 {rom => share/Resources/rom}/asm.m4h | 0 {rom => share/Resources/rom}/clock.m4 | 0 {rom => share/Resources/rom}/epple2sys.m4 | 0 {rom => share/Resources/rom}/stdin.m4 | 0 {rom => share/Resources/rom}/stdout.m4 | 0 src/E2wxFrame.cpp | 8 +- src/PreferencesDialog.cpp | 335 +++++++ src/PreferencesDialog.h | 35 + src/config.h.in | 9 + 34 files changed, 1826 insertions(+), 164 deletions(-) create mode 100755 bin/Linux/setup.sh create mode 100755 bin/Windows/setup.sh create mode 100755 bin/build.sh create mode 100755 bin/macOS/setup.sh create mode 100644 share/FixBundle.cmake.in create mode 100644 share/Info.plist.in rename {conf => share/Resources/conf}/epple2.a2bare.conf (100%) rename {conf => share/Resources/conf}/epple2.a2dos31.conf (100%) rename {conf => share/Resources/conf}/epple2.a2dos33.conf (100%) rename {conf => share/Resources/conf}/epple2.a2loaded.conf (100%) rename {conf => share/Resources/conf}/epple2.a2pbare.conf (100%) rename {conf => share/Resources/conf}/epple2.a2pdos33.conf (100%) rename {conf => share/Resources/conf}/epple2.a2ploaded.conf (100%) rename {conf => share/Resources/conf}/epple2.conf (100%) rename {conf => share/Resources/conf}/epple2.rev0bare.conf (100%) rename {conf => share/Resources/conf}/epple2.visual6502.conf (100%) create mode 100644 share/Resources/epple2.fbp create mode 100644 share/Resources/epple2.png create mode 100644 share/Resources/epple2.xrc rename {rom => share/Resources/rom}/.gitignore (100%) rename {rom => share/Resources/rom}/CMakeLists.txt (100%) rename {rom => share/Resources/rom}/Makefile (100%) rename {rom => share/Resources/rom}/asm.m4h (100%) rename {rom => share/Resources/rom}/clock.m4 (100%) rename {rom => share/Resources/rom}/epple2sys.m4 (100%) rename {rom => share/Resources/rom}/stdin.m4 (100%) rename {rom => share/Resources/rom}/stdout.m4 (100%) create mode 100644 src/PreferencesDialog.cpp create mode 100644 src/PreferencesDialog.h create mode 100644 src/config.h.in diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 20539cc..eb2d59d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -7,7 +7,6 @@ on: env: name: "epple2" desc: "Apple ][ emulator" - deb_depends: "libsdl2-2.0-0" jobs: "build-roms": @@ -24,7 +23,7 @@ jobs: - name: "Build" run: | set -x - cd rom + cd share/Resources/rom mkdir build cd build cmake .. @@ -33,174 +32,234 @@ jobs: - uses: "actions/upload-artifact@v3" with: name: "epple2-roms" - path: "./rom/*.a65" + path: "share/Resources/rom/*.a65" - "build-epple2-ubuntu": - needs: "build-roms" - runs-on: "ubuntu-latest" + "build": + strategy: + matrix: + include: + - os: "ubuntu-22.04" + shell: "bash" + - os: "macos-12" + shell: "bash" + - os: "windows-latest" + shell: "msys2 {0}" + + runs-on: "${{ matrix.os }}" + + defaults: + run: + shell: "${{ matrix.shell }}" + steps: - - name: "Prepare runner" - run: | - set -x - sudo apt-get update -qqqq - sudo apt-get install -qqqq libsdl2-dev tree - - uses: "actions/checkout@v3" - - name: "Build" - run: | - set -x - mkdir build - cd build - cmake .. - cmake --build . + - uses: "msys2/setup-msys2@v2" + if: ${{ runner.os == 'Windows' }} + with: + update: true + pacboy: >- + toolchain:p + cmake:p + ninja:p + boost:p + wxwidgets3.2-msw:p + SDL2:p + + - name: "Set up environment" + run: "./bin/${{ runner.os }}/setup.sh" - uses: "actions/download-artifact@v3" with: name: "epple2-roms" - path: "build/epple2-roms" - - - name: "Stage" - run: | - set -x - pwd - cd build - mkdir -p stage/usr/local/bin - mkdir -p stage/usr/local/etc/epple2 - mkdir -p stage/usr/local/lib/epple2/system - mkdir -p stage/usr/local/lib/epple2/cards - cp src/epple2 stage/usr/local/bin/ - cp conf/*.conf stage/usr/local/etc/epple2/ - cp epple2-roms/epple2sys.a65 stage/usr/local/lib/epple2/system/ - cp epple2-roms/stdout.a65 stage/usr/local/lib/epple2/cards/ - cp epple2-roms/stdin.a65 stage/usr/local/lib/epple2/cards/ - cp epple2-roms/clock.a65 stage/usr/local/lib/epple2/cards/ - tree stage - - - name: "Package" - uses: "jiro4989/build-deb-action@v2" - with: - package: "${{ env.name }}" - desc: "${{ env.desc }}" - maintainer: "${{ github.repository_owner }}" - version: "${{ github.ref }}" - arch: "amd64" - package_root: "build/stage" - depends: "${{ env.deb_depends }}" - - - uses: "softprops/action-gh-release@v1" - with: - files: | - *.deb - - - - "build-epple2-macos": - needs: "build-roms" - runs-on: "macos-latest" - steps: - - name: "Prepare runner" - run: | - set -x - HOMEBREW_NO_AUTO_UPDATE=1 brew install sdl2 tree - - - uses: "actions/checkout@v3" + path: "share/Resources/rom" - name: "Build" - run: | - set -x - mkdir build - cd build - cmake .. - cmake --build . - - - uses: "actions/download-artifact@v3" - with: - name: "epple2-roms" - path: "build/epple2-roms" - - - name: "Stage" - run: | - set -x - pwd - cd build - mkdir -p stage/local/bin - mkdir -p stage/local/etc/epple2 - mkdir -p stage/local/lib/epple2/system - mkdir -p stage/local/lib/epple2/cards - cp src/epple2 stage/local/bin/ - cp conf/*.conf stage/local/etc/epple2/ - cp epple2-roms/epple2sys.a65 stage/local/lib/epple2/system/ - cp epple2-roms/stdout.a65 stage/local/lib/epple2/cards/ - cp epple2-roms/stdin.a65 stage/local/lib/epple2/cards/ - cp epple2-roms/clock.a65 stage/local/lib/epple2/cards/ - cp /usr/local/lib/libSDL2.dylib stage/local/bin/ - tree stage - - - name: "Package" - run: | - set -x - pkgbuild --identifier nu.mine.mosher.$name --root build/stage --install-location /usr $name.pkg + run: "./bin/build.sh" - uses: "softprops/action-gh-release@v1" with: + draft: true + prerelease: true + tag_name: "${{ env.git_tag }}" files: | - *.pkg + tmp/cpack/*.zip + tmp/cpack/*.tar.gz + tmp/cpack/*.7z + tmp/cpack/*.deb + tmp/cpack/*.dmg + tmp/cpack/*.exe - - - "build-epple2-windows": - needs: "build-roms" - runs-on: "windows-latest" - steps: - - name: "Prepare runner" - run: | - Invoke-WebRequest -Uri "https://github.com/libsdl-org/SDL/releases/download/release-2.24.2/SDL2-devel-2.24.2-VC.zip" -OutFile "C:/Program Files/SDL2-devel-VC.zip" - Expand-Archive -LiteralPath "C:/Program Files/SDL2-devel-VC.zip" -DestinationPath "C:/Program Files/" - - - uses: "actions/checkout@v3" - - - name: "Build" - shell: "bash" - run: | - set -x - mkdir build - cd build - cmake .. - cmake --build . - - - uses: "actions/download-artifact@v3" - with: - name: "epple2-roms" - path: "build/epple2-roms" - - - name: "Stage" - shell: "bash" - run: | - set -x - pwd - cd build - mkdir -p stage/epple2/etc/epple2 - mkdir -p stage/epple2/lib/epple2/system - mkdir -p stage/epple2/lib/epple2/cards - cp src/Debug/epple2.exe stage/epple2/ - cp conf/*.conf stage/epple2/etc/epple2/ - cp epple2-roms/epple2sys.a65 stage/epple2/lib/epple2/system/ - cp epple2-roms/stdout.a65 stage/epple2/lib/epple2/cards/ - cp epple2-roms/stdin.a65 stage/epple2/lib/epple2/cards/ - cp epple2-roms/clock.a65 stage/epple2/lib/epple2/cards/ - cp "C:/Program Files/SDL2-2.24.2/lib/x64/SDL2.dll" stage/epple2/ - - - name: "Package" - uses: "thedoctor0/zip-release@main" - with: - directory: "build/stage" - path: "${{ env.name }}" - filename: "${{ env.name }}-windows.zip" - - - uses: "softprops/action-gh-release@v1" - with: - files: | - build/stage/*.zip + + + + +# "build-epple2-ubuntu": +# needs: "build-roms" +# runs-on: "ubuntu-latest" +# steps: +# - name: "Prepare runner" +# run: | +# set -x +# sudo apt-get update -qqqq +# sudo apt-get install -qqqq libsdl2-dev tree +# +# - uses: "actions/checkout@v3" +# +# - name: "Build" +# run: | +# set -x +# mkdir build +# cd build +# cmake .. +# cmake --build . +# +# - uses: "actions/download-artifact@v3" +# with: +# name: "epple2-roms" +# path: "build/epple2-roms" +# +# - name: "Stage" +# run: | +# set -x +# pwd +# cd build +# mkdir -p stage/usr/local/bin +# mkdir -p stage/usr/local/etc/epple2 +# mkdir -p stage/usr/local/lib/epple2/system +# mkdir -p stage/usr/local/lib/epple2/cards +# cp src/epple2 stage/usr/local/bin/ +# cp conf/*.conf stage/usr/local/etc/epple2/ +# cp epple2-roms/epple2sys.a65 stage/usr/local/lib/epple2/system/ +# cp epple2-roms/stdout.a65 stage/usr/local/lib/epple2/cards/ +# cp epple2-roms/stdin.a65 stage/usr/local/lib/epple2/cards/ +# cp epple2-roms/clock.a65 stage/usr/local/lib/epple2/cards/ +# tree stage +# +# - name: "Package" +# uses: "jiro4989/build-deb-action@v2" +# with: +# package: "${{ env.name }}" +# desc: "${{ env.desc }}" +# maintainer: "${{ github.repository_owner }}" +# version: "${{ github.ref }}" +# arch: "amd64" +# package_root: "build/stage" +# depends: "${{ env.deb_depends }}" +# +# - uses: "softprops/action-gh-release@v1" +# with: +# files: | +# *.deb +# +# +# +# "build-epple2-macos": +# needs: "build-roms" +# runs-on: "macos-latest" +# steps: +# - name: "Prepare runner" +# run: | +# set -x +# HOMEBREW_NO_AUTO_UPDATE=1 brew install sdl2 tree +# +# - uses: "actions/checkout@v3" +# +# - name: "Build" +# run: | +# set -x +# mkdir build +# cd build +# cmake .. +# cmake --build . +# +# - uses: "actions/download-artifact@v3" +# with: +# name: "epple2-roms" +# path: "build/epple2-roms" +# +# - name: "Stage" +# run: | +# set -x +# pwd +# cd build +# mkdir -p stage/local/bin +# mkdir -p stage/local/etc/epple2 +# mkdir -p stage/local/lib/epple2/system +# mkdir -p stage/local/lib/epple2/cards +# cp src/epple2 stage/local/bin/ +# cp conf/*.conf stage/local/etc/epple2/ +# cp epple2-roms/epple2sys.a65 stage/local/lib/epple2/system/ +# cp epple2-roms/stdout.a65 stage/local/lib/epple2/cards/ +# cp epple2-roms/stdin.a65 stage/local/lib/epple2/cards/ +# cp epple2-roms/clock.a65 stage/local/lib/epple2/cards/ +# cp /usr/local/lib/libSDL2.dylib stage/local/bin/ +# tree stage +# +# - name: "Package" +# run: | +# set -x +# pkgbuild --identifier nu.mine.mosher.$name --root build/stage --install-location /usr $name.pkg +# +# - uses: "softprops/action-gh-release@v1" +# with: +# files: | +# *.pkg +# +# +# +# "build-epple2-windows": +# needs: "build-roms" +# runs-on: "windows-latest" +# steps: +# - name: "Prepare runner" +# run: | +# Invoke-WebRequest -Uri "https://github.com/libsdl-org/SDL/releases/download/release-2.24.2/SDL2-devel-2.24.2-VC.zip" -OutFile "C:/Program Files/SDL2-devel-VC.zip" +# Expand-Archive -LiteralPath "C:/Program Files/SDL2-devel-VC.zip" -DestinationPath "C:/Program Files/" +# +# - uses: "actions/checkout@v3" +# +# - name: "Build" +# shell: "bash" +# run: | +# set -x +# mkdir build +# cd build +# cmake .. +# cmake --build . +# +# - uses: "actions/download-artifact@v3" +# with: +# name: "epple2-roms" +# path: "build/epple2-roms" +# +# - name: "Stage" +# shell: "bash" +# run: | +# set -x +# pwd +# cd build +# mkdir -p stage/epple2/etc/epple2 +# mkdir -p stage/epple2/lib/epple2/system +# mkdir -p stage/epple2/lib/epple2/cards +# cp src/Debug/epple2.exe stage/epple2/ +# cp conf/*.conf stage/epple2/etc/epple2/ +# cp epple2-roms/epple2sys.a65 stage/epple2/lib/epple2/system/ +# cp epple2-roms/stdout.a65 stage/epple2/lib/epple2/cards/ +# cp epple2-roms/stdin.a65 stage/epple2/lib/epple2/cards/ +# cp epple2-roms/clock.a65 stage/epple2/lib/epple2/cards/ +# cp "C:/Program Files/SDL2-2.24.2/lib/x64/SDL2.dll" stage/epple2/ +# +# - name: "Package" +# uses: "thedoctor0/zip-release@main" +# with: +# directory: "build/stage" +# path: "${{ env.name }}" +# filename: "${{ env.name }}-windows.zip" +# +# - uses: "softprops/action-gh-release@v1" +# with: +# files: | +# build/stage/*.zip diff --git a/.gitignore b/.gitignore index bfb82e2..70015a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # cmake /build/ +/tmp/ # netbeans /nbproject/ diff --git a/CMakeLists.txt b/CMakeLists.txt index c0b9e8c..734eb64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,13 @@ cmake_minimum_required(VERSION 3.22.1) set(CMAKE_VERBOSE_MAKEFILE TRUE CACHE BOOL "Echo make commands.") set(PACKAGE_SUITE TRUE CACHE BOOL "Build entire suite of packages; otherwise just ZIP file.") -#set(CMAKE_BUILD_TYPE RelWithDebInfo) -set(CMAKE_BUILD_TYPE Debug) +set(CMAKE_BUILD_TYPE RelWithDebInfo) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) + + + + set(APP_NAME epple2) project(${APP_NAME} @@ -100,6 +103,7 @@ paddlebuttonstates.cpp paddles.cpp picturegenerator.cpp powerupreset.cpp +PreferencesDialog.cpp screenimage.cpp SegmentCache.cpp slots.cpp @@ -123,10 +127,24 @@ wozfile.cpp list(TRANSFORM sources PREPEND "src/") set(resources -#epple2.xrc -#epple2.png +epple2.xrc +epple2.png conf/epple2.conf +conf/epple2.rev0bare.conf +conf/epple2.a2bare.conf +conf/epple2.a2dos31.conf +conf/epple2.a2dos33.conf +conf/epple2.a2loaded.conf +conf/epple2.a2pbare.conf +conf/epple2.a2pdos33.conf +conf/epple2.a2ploaded.conf +conf/epple2.visual6502.conf +rom/epple2sys.a65 +rom/stdout.a65 +rom/clock.a65 +rom/stdin.a65 ) +list(TRANSFORM resources PREPEND "share/Resources/") add_executable(${APP_NAME} WIN32 MACOSX_BUNDLE ${sources} ${resources}) @@ -158,6 +176,12 @@ target_link_libraries(${APP_NAME} PRIVATE ${wxWidgets_LIBRARIES}) +configure_file(src/config.h.in config.h) +include_directories(${PROJECT_BINARY_DIR}) + + + +# TODO: can we remove this without being too backwardly incompatible? target_compile_definitions(${APP_NAME} PRIVATE ETCDIR="${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}") @@ -165,3 +189,53 @@ target_compile_definitions(${APP_NAME} PRIVATE ETCDIR="${CMAKE_INSTALL_PREFIX}/$ set_target_properties(${APP_NAME} PROPERTIES RESOURCE "${resources}") + + + + + +include(InstallRequiredSystemLibraries) + +if(APPLE) + set_target_properties(${APP_NAME} PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${PROJECT_BINARY_DIR}/Info.plist) + install(TARGETS ${APP_NAME} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + BUNDLE DESTINATION .) + configure_file(share/FixBundle.cmake.in ${PROJECT_BINARY_DIR}/FixBundle.cmake @ONLY) + install(SCRIPT ${PROJECT_BINARY_DIR}/FixBundle.cmake) +elseif(WIN32) + install(TARGETS ${APP_NAME} + RUNTIME_DEPENDENCIES + DIRECTORIES ${CMAKE_SYSTEM_LIBRARY_PATH} + PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-" + POST_EXCLUDE_REGEXES ".*system32/.*\\.dll" + BUNDLE DESTINATION . + RESOURCE DESTINATION share/Resources) +else() + install(TARGETS ${APP_NAME} + RUNTIME_DEPENDENCIES + DIRECTORIES ${CMAKE_SYSTEM_LIBRARY_PATH} + RESOURCE DESTINATION share/Resources) +endif() + + + + + +set(CPACK_GENERATOR ZIP) + +if(PACKAGE_SUITE) + set(CPACK_GENERATOR ${CPACK_GENERATOR} TGZ 7Z) + if(APPLE) + set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-macOS") + configure_file(share/Info.plist.in ${PROJECT_BINARY_DIR}/Info.plist) + set(CPACK_GENERATOR ${CPACK_GENERATOR} DragNDrop) + elseif(WIN32) + set(CPACK_GENERATOR ${CPACK_GENERATOR} NSIS) + else() + set(CPACK_GENERATOR ${CPACK_GENERATOR} DEB) + endif() +endif() + +include(CPack) diff --git a/bin/Linux/setup.sh b/bin/Linux/setup.sh new file mode 100755 index 0000000..fcf5d6e --- /dev/null +++ b/bin/Linux/setup.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +echo "::group::configure kinetic" +sudo add-apt-repository "deb http://mirror.math.princeton.edu/pub/ubuntu kinetic main universe" +echo "::endgroup::" + +echo "::group::install dependencies" +sudo apt-get -qqqq update +sudo apt-get -qqqq install libboost-all-dev libwxgtk3.2-dev libsdl2-dev +echo "::endgroup::" diff --git a/bin/Windows/setup.sh b/bin/Windows/setup.sh new file mode 100755 index 0000000..c52d3c2 --- /dev/null +++ b/bin/Windows/setup.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 0 diff --git a/bin/build.sh b/bin/build.sh new file mode 100755 index 0000000..bcf5d92 --- /dev/null +++ b/bin/build.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -e + +if [ -e "$1/CMakeCache.txt" ] ; then + builddir="$1" +else + mkdir -p tmp + builddir=$(mktemp -d tmp/tmp.XXXXXXXXXX) +fi +cd $builddir + +# TODO: fix version number +if [ "$GITHUB_ENV" != "" ] ; then + echo "git_tag=2.0.0-$(date +%Y%m%d.%H%M%S)" >>$GITHUB_ENV +fi + +echo "::group::cmake" +cmake ../.. +echo "::endgroup::" + +echo "::group::cmake --build" +cmake --build . +echo "::endgroup::" + +if [ "$1" = "-n" ] ; then + exit 0 +fi + +echo "::group::cpack" +cpack -B ../cpack/ +echo "::endgroup::" diff --git a/bin/macOS/setup.sh b/bin/macOS/setup.sh new file mode 100755 index 0000000..d4c1422 --- /dev/null +++ b/bin/macOS/setup.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +echo "::group::install dependencies" +export HOMEBREW_NO_AUTO_UPDATE=1 +brew install boost wxwidgets sdl2 +echo "::endgroup::" diff --git a/share/FixBundle.cmake.in b/share/FixBundle.cmake.in new file mode 100644 index 0000000..8f35844 --- /dev/null +++ b/share/FixBundle.cmake.in @@ -0,0 +1,16 @@ +include(BundleUtilities) + +# Set bundle to the full path name of the executable already +# existing in the install tree: +set(bundle "${CMAKE_INSTALL_PREFIX}/@APP_NAME@.app") + +# Set other_libs to a list of full path names to additional +# libraries that cannot be reached by dependency analysis. +# (Dynamically loaded PlugIns, for example.) +set(other_libs "") + +# Set dirs to a list of directories where prerequisite libraries +# may be found: +set(dirs "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@" "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@") + +fixup_bundle("${bundle}" "${other_libs}" "${dirs}") diff --git a/share/Info.plist.in b/share/Info.plist.in new file mode 100644 index 0000000..96e5477 --- /dev/null +++ b/share/Info.plist.in @@ -0,0 +1,22 @@ + + + + + CFBundleName + @CMAKE_PROJECT_NAME@ + CFBundleDisplayName + @CMAKE_PROJECT_NAME@ + CFBundleIdentifier + @CPACK_PACKAGE_VENDOR@.@CMAKE_PROJECT_NAME@ + CFBundleVersion + @PROJECT_VERSION@ + CFBundlePackageType + APPL + CFBundleSignature + @PROJECT_FOURCC@ + CFBundleExecutable + @CMAKE_PROJECT_NAME@ + CFBundleIconFile + @CMAKE_PROJECT_NAME@ + + diff --git a/conf/epple2.a2bare.conf b/share/Resources/conf/epple2.a2bare.conf similarity index 100% rename from conf/epple2.a2bare.conf rename to share/Resources/conf/epple2.a2bare.conf diff --git a/conf/epple2.a2dos31.conf b/share/Resources/conf/epple2.a2dos31.conf similarity index 100% rename from conf/epple2.a2dos31.conf rename to share/Resources/conf/epple2.a2dos31.conf diff --git a/conf/epple2.a2dos33.conf b/share/Resources/conf/epple2.a2dos33.conf similarity index 100% rename from conf/epple2.a2dos33.conf rename to share/Resources/conf/epple2.a2dos33.conf diff --git a/conf/epple2.a2loaded.conf b/share/Resources/conf/epple2.a2loaded.conf similarity index 100% rename from conf/epple2.a2loaded.conf rename to share/Resources/conf/epple2.a2loaded.conf diff --git a/conf/epple2.a2pbare.conf b/share/Resources/conf/epple2.a2pbare.conf similarity index 100% rename from conf/epple2.a2pbare.conf rename to share/Resources/conf/epple2.a2pbare.conf diff --git a/conf/epple2.a2pdos33.conf b/share/Resources/conf/epple2.a2pdos33.conf similarity index 100% rename from conf/epple2.a2pdos33.conf rename to share/Resources/conf/epple2.a2pdos33.conf diff --git a/conf/epple2.a2ploaded.conf b/share/Resources/conf/epple2.a2ploaded.conf similarity index 100% rename from conf/epple2.a2ploaded.conf rename to share/Resources/conf/epple2.a2ploaded.conf diff --git a/conf/epple2.conf b/share/Resources/conf/epple2.conf similarity index 100% rename from conf/epple2.conf rename to share/Resources/conf/epple2.conf diff --git a/conf/epple2.rev0bare.conf b/share/Resources/conf/epple2.rev0bare.conf similarity index 100% rename from conf/epple2.rev0bare.conf rename to share/Resources/conf/epple2.rev0bare.conf diff --git a/conf/epple2.visual6502.conf b/share/Resources/conf/epple2.visual6502.conf similarity index 100% rename from conf/epple2.visual6502.conf rename to share/Resources/conf/epple2.visual6502.conf diff --git a/share/Resources/epple2.fbp b/share/Resources/epple2.fbp new file mode 100644 index 0000000..0ad801f --- /dev/null +++ b/share/Resources/epple2.fbp @@ -0,0 +1,879 @@ + + + + + ; + XRC + 1 + source_name + 0 + 0 + res + UTF-8 + connect + epple2 + 1000 + none + + + 0 + epple2 + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + Preferences + + 1024,768 + wxCAPTION|wxCLOSE_BOX|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU + ; ; forward_declare + Preferences + + 0 + + + + + + szrvTop + wxVERTICAL + none + + 10 + wxALL|wxEXPAND + 1 + + + szrvMain + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_splitter1 + 1 + + + protected + 1 + + Resizable + 0.25 + 0 + -1 + 1 + + wxSPLIT_VERTICAL + wxSP_LIVE_UPDATE + ; ; forward_declare + 0 + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panel1 + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + szrvItemTree + wxVERTICAL + none + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + treItems + 1 + + + protected + 1 + + Resizable + 1 + + wxTR_FULL_ROW_HIGHLIGHT|wxTR_HAS_BUTTONS|wxTR_HAS_VARIABLE_ROW_HEIGHT|wxTR_LINES_AT_ROOT|wxTR_TWIST_BUTTONS + ; ; forward_declare + 0 + + + + wxHSCROLL|wxVSCROLL + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panel2 + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + szrvCurrentItem + wxVERTICAL + none + + 5 + wxEXPAND + 0 + + + szrvItemFields + wxVERTICAL + none + + 0 + wxEXPAND + 0 + + + szrhItemControl + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Active + + 0 + + + 0 + + 1 + chkActive + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 25 + wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Duplicate + + 0 + + 0 + + + 0 + + 1 + btnDuplicate + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 0 + + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Delete + + 0 + + 0 + + + 0 + + 1 + btnDelete + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + 5 + wxBOTTOM|wxEXPAND|wxLEFT + 0 + + wxID_ANY + name + + szrsName + wxHORIZONTAL + 1 + none + + 7 + wxLEFT|wxTOP + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Example text here + 0 + + 0 + + + 0 + + 1 + txtName + 1 + + + protected + 1 + + Resizable + 1 + + wxST_ELLIPSIZE_MIDDLE + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxBOTTOM|wxEXPAND|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Rename + + 0 + + 0 + + + 0 + + 1 + btnRename + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + 5 + wxBOTTOM|wxEXPAND|wxTOP + 1 + + + szrhConfig + wxHORIZONTAL + none + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + -1,-1 + 1 + txtConfig + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_PROCESS_TAB + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + 0 + wxEXPAND + 0 + + + szrhControl + wxHORIZONTAL + none + + 0 + wxALIGN_BOTTOM + 1 + + 0 + protected + 0 + + + + 0 + wxALIGN_BOTTOM|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 1 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Close + + 0 + + 0 + + + 0 + + 1 + wxID_OK + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + m_btnCloseOnButtonClick + + + + + + + + + + diff --git a/share/Resources/epple2.png b/share/Resources/epple2.png new file mode 100644 index 0000000000000000000000000000000000000000..09fc86c82ec8f3f96a9c9dab5336dca20b04f9ad GIT binary patch literal 17383 zcmch9by$>LyYHG|kReo%R=O3G5a}2ZMN~pXLL{US=@x`RMG+7r1SAASL_z7!F$ifv z2}uP8=@{ucYi4-AZ|_t4ob$)=y12xd=UI2hTI+ZFSXWzPKh0qp0Kk6D^XgXsK*C>< z0KE_X_1EY72K)=*enmqKA?_)lcjBn9dGTCvaX%SzQeD%v4kqU_ch2Z-(8b zxp^7Gi$T*dLlZX+T~hNN&T`kemg2rMys4zLc0T3m#IAhi=2nH%V8vt9LgGo= zwg+=_bI&!STbQEay*)fyE_HbXGCa51(d_bYix$8K>Y&p&9)^C|_Mn=x`+;DH*H+=DuKgY;fR+FNB_}N#!B?SigGwL?$ za@zF|h^t_6Xr%Y!#z^%sJR}@!aKp9Ey++fQ5!@>N87{5m7cC%frXIl?{Z{mb$5+qXp(hV@a$`B8&wsuO1c0uo9) zhHyXlG4RykC*u3*=){it(P!+#zIgG%Qc+P+HTKPJ07a(6!zqa4_AfTyorQVn#cpui6 zfcN}hRESr$PuxifnPK>;E@4WP6oEQM@1vj@-G1r0)cDdmVZ!<7)K)Mhk%>`71qFOq zWB%FwF9H}aJQzgIbt*Y~x^ljt$|Fzes~~;FP`N-}L|SR-DurgW{}uImR!O@Jb&_P5 z$GCcFE!7J1kN4Uub9(GS*}^B<)!quv=^pjhJSB!RE}8=ITC4yEZO6c{tJ;mR)QQ}Nr1{hV~O3`Cis<}+}*(E{;* zS62hm$D`6YI`qMx>FG_E#5cRWZNM&!IV5@7f>#b|joL#{lgJ~+4r!lQ9oz5*Q0q z#6;Y|+aI?)Uo1>47M+wv(KiZWZnxCcef)(Md)qTzEcUsT36v=J?-q!0y3vu{2dyXk z^vxtyp}#k#8RX3xZ##{L-OWn6)D})=;Xu%nC+9}L>ksqE-2w@+&Za$6Ke7YA8f@Ur zCv?evmBm`-H}(BpZlY>n&H4jeUhZX*DK0c=y@tAw^1}b0mdS?GxJ5Qi%3Q=JK8GVsWBNI6e&7(pOh_C2Dl_^z28YKM1I$6!oRY~3OgE0sTVFIpO zgQr?WiE46JP*A8bSbi&~x@RvYQK)JB0Xn)HU3B2?-MgteU4OUhUPKT56MDCxs5Ko> z)F2z8W8yC&Bi`N7P39(N1QZQxS*B?&cT&sqleVAATt~Yj?;r2nL@g5 z&%hj+9ew@7%2fvWx^`ZvWB+IjGh!$hi+7R4D@-=MX+}n$h>SIJnc* z$QDNQz#O4skpmLuLBd>x`^K5Q&z&jt6F}Z+^?E-=^?eUX5eASslro9Hd~SCvc<+Ny z6dHsIC0!v4(|ZB~%#ZV=oyNBNIwV-%x-F>tr~UNHl+vu0sai(xzSoXi`Y^pnCnUz_ zqwtK8mQjSDn-Kyn}kPT>xrUz9C5100RtUNVtNd7HdClK=*YpyQkv8u@Y6?7l^EEC|#Mxa19y zPEwWz$RKKZfJ~BjNJ_F;EG=A{wytwyM9tOydomhoJ>&)!(66Jea*-MO44?NmX5EUK z?+=$C)@Pmz2qY%9>%wI+#c-l3f{9fR&6B2!1!*pwM~&`-c|m)q7Z3il<;-9(Vzb>r zOJ43YT<%`tiG6$Ik3jNAH13e2kVgcrtlL#*PFAuDKL)sro);(6K?!02`c?(oUSe{B z_Hg2u6cj>yNTm+7Kk$wcfx1pZ53V0Ns)XII`|I`90tZAu_>Hj6R0l}I;qsonc>tsV zV!qJt(Krri9KR5_M}r5_Fpp;AL!O}YasHVhbeESt2lE(#HB`i_kZaiKU-@mfT|61Uy(Fo9d(~zW`sd32Nd#G>5vcc%TI>|(h$4xc;aTx^Km+Ud zd~HD_2hhU}vz-RI6$06!{lnZ3r!L8zgwp8N07ROkqg6Dxz0Vn_b%f6;>2jCkarqI>5 znXdAXDTzbl2xI=qF9tm1PVr2zS z(vz8>hcfKjtEnOwper{SOEx4xU{8@#4pt5N&?n7IEAks?@Se;viU|e~leU6jJTGp- zv{@I=f#xw6$AG-jbV0I)KEem?r6}wpMFJLE4fQ*uUDnvYk4uXr#xbZNy{7iBWSQQc zgUP1*h(f9GoDnenRCs?sYL&16xQFA16uwC`n{4{#(O!7VBz$yD&hRo z8aAqB_xMXM4e-_ajyfNcbN92nmx_R+omNC$d>U>X@t!GYLeAMVx3QZ@_|-}fo{Nfb?!bIlz+YF2m{`0 zicJn#0YkN}MHP|8X24oqQ8Nsq!b1NKMUWCQCoq(dtoX{38q{49B7V>9CkWQ$M8l~O z%*a_mUL-~`>;cdX&yK7<1pJekiMyWTlv0$~6{&O0lD!-_Ev(F~5B)BT<__s5kvw2b zHa++m_EGKQ4^wGT;>hPntoZ%Gn;a;tg-|efI{Xa>MS|MuK2WBxsHt$6DODJM#>T zjJ}tE)xhp32H0s@c|y&H9&bE{!t!K3ISr#9K6?trb^VV9Q)-~nMq{Z4g5qEt#i{F4 z(Zhmt@3uNXyZvO7M#5?kYD59a{eN5*mxtiNQu!_k;I_K7K%?_HS`_^P#(X?V)VhvA zl!p6j9JR64*Q7W(#mEv3MA8%A2?IVpq041=wak=ER&Eq!_G|OcKiMlw+9>22ZHH#c zXOG_-(PbrI#IO47ha~z9LGVE0VmJfbR59{^A`Km2*Ph$hjl%MIP98y^?yPLRuqha0c{XoGc_!t8Q z=T4@mY!(oFK)e&+#_y{c>`&pR55|-XGm=Q0%a1)C79tG{Z*|bY(Cs}-V#lj(BFT5&461EJ2NudD+cGwlftGUMYmEOP2 zPk)arDewD_ujH|t%jwci_ZBR< z*n&Th7cQCRd+3G2ve`r(hTWkAd0|>(IfTchy}}LmPHB#3zUw=Cie_(|WCU5M6fg@R zxoAm3PA_(f`rDzfpB~F2kmv_uCz2g zfg*enVZfyEk@*$9u5X$g2S)0oi94u;Yh>e@^_Z}aLM6X!k*5za;#n%SDJD9{lXZ>4 zYmO+azS@>Iie8t@TrR#&3v?)Leuw5ePI;k^Ub!Ol%7yCVKjhQsV3K8TN~VAg&)iYM zdn;SEH+a%~1O=!TmY`6fpbc0^h+g9Z;4YeD9VS=^Bq*uA)WOM{p?$i937 zFmPi)h>zP*M-(E`smvl`iSU)-j~CmJ86$|A7`3vq0)UK$6v$*2c5_2}oS zE{#XRWLzU}s}6#&WGCBicT|D<7{XlON{+6)*=>&yObBrmm+A3%uc1_NB*s)S0*ai6 z`Z>V*X^?*Qjizz6*9G6}#pQsId~6~gg-tf+7>dBws-kE0&i0p4lA`vB-*SX0Cjvv5 zxvGdn7coJtD7^E2^xkYbyI2~Jy#+gwA7$?P+>~XQU!(8!RD^_&{627Ptp=K;bcs^` z7eE8%-|n#7FOZ|sbl1S#m0tib*gqALsvV ze-b;6%miY_!^D{`+TE*8|l)smA3#QXP9Q!iAAD>_NZEM)x zBH-ulf)qj4rYix@;pH^xzcYNleYdN)=3>3FqPCE#ypfQ2k{F}GrQ2;M#bwEQsW1|} zxuOOZ?1oy-ImrZHdz2IXgDTg_X)DQVSnnsg6<^!WSo!tE!I`670VlOqwtv)Ib{06; zdiVU?cDi56TH=${nblNfi>DI2mVJ+#t@@~&t$s8ce8p=fY0x?NQdvng(z^0Kv%yGw zbXuAhmOV45;yu%~RZ2};Q$w>hT5t4@6fz3NA_y;a@YbiZd$w3RzgV?1R@$KBAXWJFBc+7M@Tw^Qy|J*XMGj)>0faE~5i@8k~Im3&N+= z-v?`VZW`$sfA{aNuQWI&wex&YY821jDu2qEd*QIrUWsu?1-idyl2&Kpt6U!|Nl)^vf#KFb0u8+1EV`7ZXjtfdv)uAK1VTMGyO5u`Wx&% zeeI?~k4)SR2`coa;w+?uVn9d~2C>qcc<~*x+U=eK&#mt0Hp3bF`VZ{Fg*B2FSE}z0 zTj=PS&!3>cmNT>)D!Fzt7I@zFalbt@CpoIRlGNaK);#`HCMo#`)ml`||4auX?T(le z8U+CxcgnY;`>kQWQEf&iL!q?x@cwv0psG#gYK`N@yH`(|fo|Pen4InEPbc}E=>}P6 zFuq(xj=;p8at#DejlE&OUpJ$*kHM{x({)>kOMjT;mrrIk_1ZS z8l<;>=Q=pYD{SUf5N>irKhM2-hZNSH)uw7wkw6!BTlvmLx?6*wH&aL9ut_3SN6XII z?dJ=BQMFVRjvgp%cNcV&zqP6+LhorTwT%s8chRIWO~?)LxlRu_+B1BgwmWi{&z{wB zbN4^&T-m>!KR6y9nauD-7^bSexTx|9OEqk_D1zk0Hk(I72yc0i*jYbsYn{G|_?(y{ zs@|4_%Q=Z=n*%kG$!>i|hZyNWflgF;yXA_ojVw3shuI9G)VU?gRhHGKQCMA}KMko{ z`AXYMnP=FYUXCi^ha;lS1iIM0oUki(M`Bb?6VCs-sxlFn*KBZYI-OMR9IKJPmG6NO zJEzu|;ki3KCJ}dNYmX2H*4=kDICAHyVEb%li|4<0GC-O?@H5t!RMn3xbl&#+gTj_j zXRJHA4R3Co>eLOG3^Zt}4y-P%TH!XG#*`(TK!bIY)_A&<^Xi|KSK3Wjnu_q z;xl4yG6D{X6L+Thj0OsOPwOmt-b7-lkt#K4;8j>KEWQ#GQ{xkDG760CiEY)9k!TMY zD^R3Iod-}C163dysu7W1K!`dIzDV*lX(sOzo<3|!dV`ej4b1_1 z{IlPz*6x0@s?#s}=gU_VzJB}ZZy&baEkm$Y!k5qD3;XbQjU)%ss}7qy!OQ-59@srs zSh7A}U|QqE@{AIz_eDwCev1EU((a|}D(}`86$rsY|?t<9!t+BBJZKFP4l3#wfeY0F8zb?+$9JrXI1a3b! ztC0=(RsV^~hAYP%_kpVMBG;YARb!>%QLm$l?zVaQeTW(6-u3exd#{lgl-3x}K0n~y zdROJG&);K;AR%*#b7%H*(s0GZh9Bc435nXWRE3pycmwSujPBp*g`m&lZ+GRh{&eXL z)si~tXX1G@RB#_ev0GC*D17k6s`(M+@F9=(IzJiN@ann2>^%4Ld;gV#t4DiD)zV9jdJTPek4!r{6Xlb))k{u?#~ANzE!sdvMx*Mp#8Tu z&4!n<&R(7n&o&#DRS#3$I+sDH9xA|_eD*~H$Cjn#U5~pr1C`sW?!2k`9coY{S>dnM zIzAfAZ73odaXl*cW_^0=eoNb}S$6iw6BBt-NUZO}oujGBXWxjWT+zO)m|TZKxStx? zp`DL^>9neoDQ)1@vdt;C=aj${P-rxqAV@Xr z;lg`2vin`1#9Xp>rqZ4I^tSet*N>A|BM4S4ZzS6`OJ?)_fR3%iF`d-w>nH#AaFm@3 zSXxz$`uO#Ji5`DR(t7ptrO;giQ(aF}%)%i1^6RuehD`4E4-X3Ia1vq(KTWqY44QXThlhP@OE_8BL5ts( z?cG0O?6p55b2UtTzg#F^<}VE`Xa7F#@H5)JRXi|sos=S+TO3NsO)dY{s^5@nq?m8l zq2}(-vL|J~R{yGYe!FEOPq=-bdnc8<>F3?SAr8Aagv2UxZRwa8c+FR+DsQ}UW2`4* zkxwnV{FVF4W?RI@^gUAkSRP-!%sdLu;If9dCX=jx+;nozlak%y^nAwceJ!c-tMg`m zznJGkXB(B)g^hzXL-wh&9{PG9!IeNKzhf5RY-<->Y_hf!TrhL3IeBGwD)3J6Ol?Q1 zsG@clqkTZd?~2?T6Yu-4n>qfiITpa0_V-T8*UrnPu;(_-cWelpP^}qVnGAf_n6$H{ zWx6dmzR|zGm2vFOP`BmLxf&w|1a5%MHs^Oj`}*dZ)XN_a4B~U+&9>d-H$u}*ye6-i zk;45>aqk5#Is^_`6>H3-?82{olemTI=K2lPShqLf)upJ-DcN@WD(}C*$Uwa=JKqdHJoBOVjxuH80V(G$Z-fH=7c z<21p~vMT1JBGmh%*+28++bSA5>aeJi={ac#EivX^STherk*$%zai~S$@nNB8d9Vd~Zl@Enla+g~UdR z6GZy_cE)a>4@Lij1>mwh(?1%dJoYy-W$t~gmx3D?IQ%%-Z?U}9d6}?o{erM?UwjuM zqtz!pC81F}=sNMH;qJDa{2vXf^&2J2y(F_1o3b%Thf4t_W${w~85Seo*OjYv4YxV? zCu&ExUOjUBvCD6((&?|1m)+x}Gb3bccBdqJ?&nly2#{F)UEWzelnL8~HlI?jFAGpBIp zhS!(^NN8_JI#TcNV}AhPjX?H6x6+4}JKBI`(YtFVdOz6EfMrS6|JT0EK;?A~z@+RU~*Rp8*A@5G$gb6-%uj~=e^ z7r))*>6cq*$3DaidJt(2Ch^IuZG_~$;x6c1gUs0b0X|PTWOvKF-hA#aA;(nZ!UZ-q z7*p#%1IzVgwEGhZ#~Vxa>?@GwDpFoM{o7^3L15$rSlimBk`L51^C%?K5j!2p8VJSo z*Xc6wB$x%8LxHWMzvrk1-Udv;&JmC4H~aE)>OWgx2>FlXdZb3uKbtov9STg)1bG;K z(3>vr1n+OCvPgS@njiE%-%ucIT>u!SF@TwG97L5<{2-P4;aefoc93!ZL(nQ{uwutw zR8(D?0-ib_BSqkUru%Qp|BovB83udy;oOypq2h6h300m|GoRYR12O0L+{Isr4o+95 zEE}n7K&Q$2A74Fe@LzEiVSETI1y%IZ$KYdvedu*n0wYdn!%MB37ypyMQzw8@peeN4 z|NQGjMNm{$4bQsUQ`5uXQLSO`KT<~+M{t1`wU<&>Jx7jHHBp->^EwyuM6`2)>w3)U zplnNlp^%BA%0IW~^y80Sr=gcrEKy(w#jV3SX`DZKBbc-YmQXhkcA7<9h+`DkSK_Ko z{|cFLDiC)1&QAf@82#=%!A&tngNfr-9Ny*YX7MR#F?!zsz11cT`g6T8)PIDr8|8oD z?f*wMe@gf>#qFaog{21a6I~pp>fq17fW2h&LZXM`pJ@3&g@&*og2>2^Hhho{!YcFq z78jN!>B@Tqj!-SPiFET3fR5hf3H}7+7`NT+DQDq-si_DrmXMgZWya};a#v=dPZsR6 zP<{xrLLo6L9898zCrd_g8Kgip>c+fpkfs3f=a#g@5j?5!xiDkPSHB$7@B7Y(Z!VCo2is>a`BM8ebQ<^ocJ zmu)^AvdjjfpoQoUO1ISjylyj!BRQk)@N8E9}Lm=+QrX`ulME7p946n0_`Jl&Qs zW=|5m5Yj_n!BcA^QbA6#-oJL|Qe|l+T#;nl|0|064Mm$1CZRML;2|@H*BKVe z<_uuPF;HkUM(w(fp%)MX`%g7Re%LJ9dnx<7E`G!~4)GNKKG(Tc})pD$3`atVG?%vBJY4?%0z~&!)+ZE@c1f8#2 zd~+KUs%HIrq4Rw5il%Kk?H6WH(7poqq+_t*7QP>|uTb`u>zJmQlIF^0T|nCg;T=D@ zuek1D9T^PFd3P}F6mGl5^QCt3ZZWcEOE&Dax2n2SCc}Y5GPZ9mcfI~p=bzhhMtq#c z3b5IFaiWXs1^%__umTio=cOru>T!9&_o3`=1BYCS>#RcX&NFR$b~;ehyLQ?sERJ7R ze%w8?5uW#r7U?MP13KZnl?;dRja|R$!trm_CB|**)9zL?Kl9r*{=Va{M&Me-m>57o z?XU4S4-Nf@K{ON7pnOzydqL;;^@srheC68|HTjuK)5ah&b*pUacW&UXOKzP@nr>}= z?NI_x2*<^c7{7}dA)sR@#ID)|rr3NInc13mzSKX)9XhYZjP0Mld%yX_WOgvN8<@)k zG9qtOzZq6F(cT=h7faKqQHs=*5|=gjU1@w+g!P2d%G7diVB0v(isaovHxI~{fT!wUKb z%6I59?{0j5PI5$*55)xyY9NoPb~SSD*(1D)6>)o+8L*+(H$7CHyn68wJP>37-8yFC zvi^&(SKJmp^SEj*u+}M42k324y(eVkkdB!Ml#IHMP@wtioqsk)*3(f*PmE7$o32Ln zeEsr_F=bWjks_@f4LDRrASjQ*XW`E!4#wf`dji)b8!* z<&|7Tyylz@)b{G(y<{p=zHV@Bb;GIo+c&W=Y#iwLbE`3BzUFFNn`vUOV2>o#xvf*U zeqM5kE*{}mG&BG%{*Fuk9DC6k9ja8$PfA{E7jF8lQGPU!-kjkZJ&>8nKRvhBrD(M- z8qfO4=l8g96QYz$_xx~;N22eUmbJ~g)ym%|dy-u5`RB@7vR~%Hs{pGl-jLITj|8sR z%^@$dn;8ij6x^QUm!$}PC)2mXJ#YH3D@4eHgo$l&Wk-AWy9czrRvU*ojan(NEgA-v zwO7dd?uTZ~-?)CO0QHN@zdy-n4~q2cG#B$xs_t6N6k3jtBpq@DO-Q)VtiGD$ZnlvFD{=3=3GeuD;c)UPR(AT zZoREFt!8WZliN0*16Q!N*0U-O)~yH!tJc#FRxTEjfs6BovE>S3tb+bsR zmH>G8@V8pOWD18qkKr@Lzv((YTGH52#@nahm3=!U??+$!#u$4pb!wrijG|7Ac_g_> zBVVLpWf-~y90T&3Dyn;m`>rar>TG|1SI~2JN3}UE1kksOMO@K5=GJ7Z6Loj4b8-9{ zNkds{&pBV7M`G{yiBCNT2OjEcvZAmTdM_$YUYz%TSA{RkJv!@uE%iL9o@MnIJev>( za-F;1Yy$+^IhMlHhd#~KHv@^5ewQ1F#@aRoS?|#GHX8SXp>gpg`@iK3Ma{eaw!|v# zzFzZySR>pw=lpArK13&}dbv}X93!|?fMg+PfgTr8yY(C z)Y(Es3epw3qzHEQpq0^p=foU_Mh8x%Hp`eXzhA$KfOTC|Fxj%A$208t)en&w-K4sc zoT|RcF9^zH9aZF8Zcz8GML(hZI~N#_0=p9;)9A`>@2^MWQ#$?EV!NS6;AQ*up5k{& zK(}KiNw{!uqt=<3U@i936or+u@n4FG8UG@lDgsLYi^l1=Yos&eBxj>9OLMz~Ym8v2 zH6SNlcD}?YVC7fp*Q_(1gNzu^SbV8UY3=Fs!Kn1zO*{5N`|$WtQFmREb>qt8{1sUd zX(R0Ru!7cv&BY8?P0HR<;e%J;K9`w$x7Tdzo8i?!^j)W(#n@W0Skha2Esco1O{+W7 zX}7T7dN#n}qJpJoCNI#l9d3KR3U8>SrjHa_4HWv1jzvVkJIjQrC)4-tDyj~CE+s01 zGhc%s`7t9?{MlJ&lkZzBrG{oGEY?Qm8Ge5NKKsq;=6ZldjcasI8&c9S#0al%Ty1oT z*emLOY)Q;@J2l)_GnOpan(Ouio;oiCo@>bE5IPI3M+ui(` z?;w#U_9{)$3Ju~2Q5iKXDY_rl-o;1N5VZt;a1VabHA*1f3H8T13xG$J1o;Hbu*04bH6e- z-600|!kf=>DFWTnF5QsKZ{oF5D4iCkkP7rn{aY7fHB*s4rG^odgr}&UK-#|B0_xpI}NV5JG-+$kF zMh}*fzVRI*LRO+02f`*UtZvMme<1Rie3PE-`-~Atx7RHFqy|l_nEEC1X1k2;l~OpM zA1}J1#{$nOSp*|Uoty!IMwocnKVHlTV#TrHg+QbXzCI?|4Vg}fodq`0^DiyLMK?Z{w!Am5g*e!)OTL;6Ij$*wGFduTeomh*+ z&qE9tM5}H<9N9u(gg@KMlG+e>Qug_9_ANRR%+Glo5^Boi2|>(M@!G7ZM6kpk_1_Ik z0Q6r9JfvXKWIU%peHo(Te!t(o*%Edu%*xf#)#a=mEwI+=U|8lKYut#kPB{@upa-uK z&V}YN@POX8>s`>xTW*xqAaz?r%mzdeJhjsBhy6Go{Q7}%)Hf>Zu{j^Hk#7ywAEc0& z0DJgz^13=7goF94if06%+oGc4q)+bkPVzq)!Opkh*6dl!7I=^MFSCB#UScGeCi1A*o@Xp9jHu z+r$*y?~8s-+2jRd-hxC>*jWLnhdkkE$oJMF3q~?WW#s}`aMfqKdK7+fC4p8^vk`$? zdUfq)oTAqyAQIdc2GJB%3H$b44uh5LH4{hn*^z@n`kzJa08u=bqtr*IPg>ApSIzF~EoRKY-odF$Jwq z;MzV5fLJL<@nj<4P4+*6;ocbrInK8q0-@F?D!d^i?$dt+n7z4zqB#guhNnzIUGjx_ z0n_Nk{|Hq(b~bGR=w4vHqoW4t&OuNKQMU+OgVD`P8Ibi0H&4t6!1e6@ufD+xe4}+K zy!iGiga&!y*}VIq7E7onA#N4P!UIrBzI4^fFd+N_iq1js2W2t}oB+Yq=%NS+qVmMQ zgOIUsYzzQ`NL~nfR7*Zp4`Gx!(93fKCWYnTi!N8|u@J2Vp{qDvA(LQ1=sFHHY{!x4 zGG-o7w*0yj3m-;kv7CYM#|gM+pLp%T1|5Yb_PIqegv368HbYi5o~xkb$b`kolQgg0B~A3y(>+DV%!r zZ?1_5Zf#T*4cKZOvC^JI5h0=GOo)}l30L^xd&50+sfY%Q=ZKTGWb`vm6y6jWbbU0Z zCt>{m`I7oPc9m-Tg&4kJe*LD$FZ3Teu(glcHdyKkag`u7l*c}-n#d#*33eLf0`>H( zg_)lW6U9A;3S}4M-m=~4*HVtyomm)s_2WUVe9H1d%a=-9Gc#V9x3Pr zR*V#2$$e|*@v=m-u*sXt*3fX2-X4Uw7rdn*V{{FmCmBTly-!9; zW1xUop|F>Hq%}t_V8O_R=m4^~Xy{J#9ag@QdUL5u7KhnTNF&O%sMcc{^KwXRjeMpB znX3l?2eTe=aSU{2o;b}31v9aelWz`m--p0_YBlV*ldKjBD9T>nvq%wq>d&O*0$J)_ zYQ00C?1rVRQ4x920{09fh`{|AnWRFXVyV9@^qiqPC1UKAA9oRic-p+9g_QD`c+w3& zQFg2IiTN=dLf|K35a$;#;V3;vKP2JVv6$!ZZK+~;(wEp(q^o~p z?x~Y|z&VnGra*O69DS0`bDUZ!qVE+AiXKfaR+2VE!GcUsYlXb?(a;f?M}5emCe!FK znxcWWa8#QcwO%3KeSg$_C`*tbJbBJ<6Z0f1S^_2u>^PYXtQtI40r9cSCvIMV+3Eu2 zvCV4ZzQ>~DUcO6ZNbE)S4Wja^4w-)@+*06U3$FpVc3o6++#!-H{ABK6h3Lj~h;AfC zIRliCFG2mno;Gu#0MOCMx}%4>GmqCCV+lg*pAsZK4WVriI4kfQka_>j2%T6qv(Dg) zb@cBi@)U4M-8`sobMp#_Idh?GtRN0NI3I_%^NwE_UZNNJ703y1^96{vB{JA%|4ag^^T4EHerWVqkVCm^>%_{fgdVwxXIW~nZah%(3+D_>-rIU!{z0G)inu; zL6QZ+PdvTJf1%6cY-fM}rc1N{)i1Ie1LQ3fmy7|JV~8?fx$gE*I(mMqO|ixMP6SC+ z7@pffW=UWH4oC^kD6s8W8a+n8X4Ki!<87VzhIP#D%S#os3&WR3M&@)-OPHrf&FCA} zbBHycXaR280^~mO_ys`rQI>2kCcK#xz68p6G^0feOY!GXpO{BJX_5zBa48tLo)8>A zYamYPjprEOA;&&Iq*5M!QvcqnEm@wi{>c$Ik{q<}q|8ngolO>-2vkto-qaX{ZuXBk zrYNIC$)av;n{Nt)?~ryVHf;*Ybullqn#zAbGrTQ(C_y#zR0Z+>%4$7)uy#I?BGPjpI3wXsHhA=8hh#X z%af`Zbg55Fy#s@T%G;r$IX*cMuaK>uy?set`#>SrxqpObN3nEIFXOuc&CsB_x|;iZ z^jHDilYgy%WIEsV_dYF)*xHshM2=^-(nk%4p4Y&hlH8l7pl35lc;a4Bfn{npd7%4(lz>h$CI6XN(44=ZW> zDvDM>bLqv-&Q31f5%O?mfx5cT**T0a*~je;84B|~g3M+<+)pI5mKAd2m1gjDQd)%T zj5t7rwR^vJ&4fe(|4dHG7p13<1~5!UaNJ)a*N6@tiC#PDh{J4b5(aB#KGh;1VfP<@ zvD1BdjvVtAEKmtqkP%w%53aocXMk#`VtPxO(8I)F*QbVw)6gd=fxGTM!=XX~x5(9; zM+gr6kq1K`W!v|P0zA$!6*;RaD`vsUE zxZ_|pym{Duqwe0mxI*KS0SLm4z-c45Q29Lc9fJSNtsZ_ib(sQJn<2(>E|&QnD39mPL7yv z*7)<%Omlk*=!D(>J!?J7=Vl%kA^!#-qID5(JzyLM&@P0DH*ASJB87m;e5)vgqFim8CP!Dadxhq=^ODmR8RPI(IYTX~3JVy#Z`x zhRK#Yha$+Mj6Bzaro^w%32I7}*4FM;DAku!;7aHh=A^YICgd6Z8DPfx!2wYGG910; zcW&25m>Z+lh;!Eos}DFLi8&04!-Q$|45Emz{HCzMdg0rPc+3>g$3hZQ|es+ow-!My* z{Vd(X64>I^V3t?U1UsLnM2GV&gojjRz!~1xCW695-sG;Uw`5ZIXk#i1)%?ibXeySc zr;hKQ_9SRkJJu#sf|JpX2WdC1U(=zxZG8U#iSz}=kz1EfOi^0ahnEXXp9v`VJ0lHl ztNtpPKd>fX#uIBzBUfJyYV`+_I{A@kJ%Kz)t**!uhIu1|oOZMGK;r(u%JF-6BZU96 zylJC!RTAO-NN?H0Pkj0BW}8)lU`RIazZ>iSHfL@RRd^g#w)XMRX`X#SnK1(EEwM+h zo=8;<+=+Wda}4sp?eRgsUs0{7lwOa)T$a6V7y0I{?4qu2KIzN!M&L*y zeHOM-wN{PUeBd;Vw7S(zI8UEpub^9>u@e=0Y(G#ukOi~f`K}^i%|nD0oNLut`ms+o z9gs1sHE_B_S{q;yUCzp*1-(6`0(M4uN@s7j>Fq?-aSggZMQ3hqV;x{q`*v*lx zNBP9(|NKdK{$_FqzXP+3FeEj{pU`suQI?r*c$ygE;Le+)*?MjFv1Z64XRRC)-%Ljf z7>V-Xha;gKAE}Rhl-A-t%)#ORC($9NZ=@&BOet~q;I*gTLYChjvjX@>^Q^Xdj+*(s F{|4}6-TnXo literal 0 HcmV?d00001 diff --git a/share/Resources/epple2.xrc b/share/Resources/epple2.xrc new file mode 100644 index 0000000..9134b60 --- /dev/null +++ b/share/Resources/epple2.xrc @@ -0,0 +1,181 @@ + + + + + 1024,768 + Preferences + 1 + + wxVERTICAL + + + wxALL|wxEXPAND + 10 + + wxVERTICAL + + + wxEXPAND + 5 + + + 0 + 0.25 + 0 + vertical + + + + wxVERTICAL + + + wxALL|wxEXPAND + 5 + + + + + + + + + + wxVERTICAL + + + wxEXPAND + 5 + + wxVERTICAL + + + wxEXPAND + 0 + + wxHORIZONTAL + + + wxALIGN_CENTER_VERTICAL|wxLEFT + 5 + + + 0 + + + + + wxEXPAND + 5 + 0,0 + + + + wxRIGHT + 25 + + + 0 + 0 + 0 + + + + + + + 0 + + + 0 + 0 + 0 + + + + + + + + wxBOTTOM|wxEXPAND|wxLEFT + 5 + + wxHORIZONTAL + + + + wxLEFT|wxTOP + 7 + + + + -1 + + + + + wxBOTTOM|wxEXPAND|wxRIGHT + 5 + + + 0 + 0 + 0 + + + + + + + + + + wxBOTTOM|wxEXPAND|wxTOP + 5 + + wxHORIZONTAL + + + wxEXPAND + 5 + + + + + + + + + + + + + + wxEXPAND + 0 + + wxHORIZONTAL + + + wxALIGN_BOTTOM + 0 + 0,0 + + + + wxALIGN_BOTTOM|wxALL + 0 + + + 1 + 0 + 0 + + + + + + + + + + diff --git a/rom/.gitignore b/share/Resources/rom/.gitignore similarity index 100% rename from rom/.gitignore rename to share/Resources/rom/.gitignore diff --git a/rom/CMakeLists.txt b/share/Resources/rom/CMakeLists.txt similarity index 100% rename from rom/CMakeLists.txt rename to share/Resources/rom/CMakeLists.txt diff --git a/rom/Makefile b/share/Resources/rom/Makefile similarity index 100% rename from rom/Makefile rename to share/Resources/rom/Makefile diff --git a/rom/asm.m4h b/share/Resources/rom/asm.m4h similarity index 100% rename from rom/asm.m4h rename to share/Resources/rom/asm.m4h diff --git a/rom/clock.m4 b/share/Resources/rom/clock.m4 similarity index 100% rename from rom/clock.m4 rename to share/Resources/rom/clock.m4 diff --git a/rom/epple2sys.m4 b/share/Resources/rom/epple2sys.m4 similarity index 100% rename from rom/epple2sys.m4 rename to share/Resources/rom/epple2sys.m4 diff --git a/rom/stdin.m4 b/share/Resources/rom/stdin.m4 similarity index 100% rename from rom/stdin.m4 rename to share/Resources/rom/stdin.m4 diff --git a/rom/stdout.m4 b/share/Resources/rom/stdout.m4 similarity index 100% rename from rom/stdout.m4 rename to share/Resources/rom/stdout.m4 diff --git a/src/E2wxFrame.cpp b/src/E2wxFrame.cpp index 34d523d..bb755ca 100644 --- a/src/E2wxFrame.cpp +++ b/src/E2wxFrame.cpp @@ -20,7 +20,7 @@ #include "E2wxFrame.h" #include "E2wxApp.h" -//#include "PreferencesDialog.h" +#include "PreferencesDialog.h" #include @@ -90,7 +90,7 @@ void E2wxFrame::OnAbout(wxCommandEvent& event) { } void E2wxFrame::OnPreferences(wxCommandEvent& event) { -// PreferencesDialog *dlg = new PreferencesDialog(this); -// dlg->OnInit(); -// dlg->ShowModal(); + PreferencesDialog *dlg = new PreferencesDialog(this); + dlg->OnInit(); + dlg->ShowModal(); } diff --git a/src/PreferencesDialog.cpp b/src/PreferencesDialog.cpp new file mode 100644 index 0000000..c2b9e2e --- /dev/null +++ b/src/PreferencesDialog.cpp @@ -0,0 +1,335 @@ +#include +#ifndef WX_PRECOMP + #include +#endif + +#include "PreferencesDialog.h" +#include "E2wxApp.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CTRL(t,n) t* n = XRCCTRL(*this, #n, t) + +static const wxSize& SIZ_DLG = wxSize(1024,768); + + + +wxBEGIN_EVENT_TABLE(PreferencesDialog, wxDialog) + EVT_CLOSE(PreferencesDialog::OnClose) + EVT_BUTTON(wxID_OK, PreferencesDialog::OnCloseButton) + EVT_TREE_SEL_CHANGED(XRCID("treItems"), PreferencesDialog::OnTreeSelectionChanged) + EVT_CHECKBOX(XRCID("chkActive"), PreferencesDialog::OnActive) + EVT_BUTTON(XRCID("btnDuplicate"), PreferencesDialog::OnDuplicate) + EVT_BUTTON(XRCID("btnDelete"), PreferencesDialog::OnDelete) + EVT_BUTTON(XRCID("btnRename"), PreferencesDialog::OnRename) +wxEND_EVENT_TABLE() + + + + + + + +class TreeItemData : public wxTreeItemData { + const std::filesystem::path *m_path; + const bool m_editable; +public: + TreeItemData() : m_path(NULL), m_editable(false) {} + TreeItemData(const std::filesystem::path& path, bool editable) : + m_path(new std::filesystem::path(path)), + m_editable(editable) { + } + virtual bool isFile() const { return true; } + bool isEditable() const { return m_editable; } + const std::filesystem::path path() const { return *m_path; } +}; + +class EmptyTreeItem : public TreeItemData { + virtual bool isFile() const { return false; } +}; + + + + +class TreeSink : public wxDirTraverser { +public: + TreeSink(wxTreeCtrl *tree, wxTreeItemId parent, const std::filesystem::path& dir, bool editable) : + m_tree(tree), m_parent(parent), m_dir(dir), m_editable(editable) { + } + + wxDirTraverseResult OnFile(const wxString& filename) { + wxFileName n = wxFileName::FileName(filename); + if (n.GetExt() == "conf") { + const std::filesystem::path& full = std::filesystem::path(n.GetFullName().t_str()); + const std::filesystem::path path = m_dir / full; + m_tree->AppendItem(m_parent, n.GetName(), -1, -1, new TreeItemData(path, m_editable)); + } + return wxDIR_CONTINUE; + } + + wxDirTraverseResult OnDir(const wxString& dirname) { + return wxDIR_CONTINUE; + } +private: + wxTreeCtrl *m_tree; + const wxTreeItemId m_parent; + const std::filesystem::path& m_dir; + const bool m_editable; +}; + + + + +PreferencesDialog::PreferencesDialog(wxWindow* parent) : parent(parent) { +} + +PreferencesDialog::~PreferencesDialog() { +} + +void PreferencesDialog::OnClose(wxCloseEvent& event) { + CTRL(wxTreeCtrl, treItems); + const TreeItemData *data = (TreeItemData*)treItems->GetItemData(treItems->GetSelection()); + if (data->isFile()) { + if (data->isEditable()) { + Save(data->path()); + } + } + EndModal(wxID_OK); +} + +static void fillDir(wxTreeCtrl *treItems, wxTreeItemId item, const std::filesystem::path& dir, bool editable = false) { + TreeSink sink(treItems, item, dir, editable); + wxDir dirBuiltIn = wxDir(dir.c_str()); + dirBuiltIn.Traverse(sink, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN); +} + +void PreferencesDialog::BuildItemTree() { + CTRL(wxTreeCtrl, treItems); + + treItems->DeleteAllItems(); + + wxTreeItemId configs = treItems->AddRoot(wxT("configurations"), -1, -1, new EmptyTreeItem()); + + wxTreeItemId user = treItems->AppendItem(configs, wxT("user"), -1, -1, new EmptyTreeItem()); + fillDir(treItems, user, wxGetApp().GetConfigDir(), true); + treItems->SortChildren(user); + + wxTreeItemId built_in = treItems->AppendItem(configs, wxT("built-in"), -1, -1, new EmptyTreeItem()); + fillDir(treItems, built_in, wxGetApp().GetResDir()); + treItems->SortChildren(built_in); + + treItems->ExpandAll(); + + this->GetSizer()->Layout(); +} + +void PreferencesDialog::OnInit() { + wxConfigBase *appconf = wxConfigBase::Get(); + if (!appconf->Read(wxT("/ActivePreferences/name"), &this->active)) { + // TODO what to do when no config? + this->active = ".template"; + appconf->Write(wxT("/ActivePreferences/name"), this->active); + appconf->Flush(); + } + + wxXmlResource::Get()->LoadDialog(this, this->parent, "Preferences"); + + SetSize(SIZ_DLG); + + BuildItemTree(); + + CTRL(wxTreeCtrl, treItems); + treItems->SetFocus(); + treItems->SelectItem(treItems->GetRootItem()); +} + +void PreferencesDialog::Save(const std::filesystem::path& to) { + CTRL(wxTextCtrl, txtConfig); + const wxString sConfig = txtConfig->GetValue(); + if (sConfig != this->sOrigConfig) { + std::ofstream out(to); + out << sConfig; + this->sOrigConfig = sConfig; + } +} + +void PreferencesDialog::OnTreeSelectionChanged(wxTreeEvent& evt) { + // note: we don't get the first select upon dialog creation, + // nor the final de-select upon dialog destruction + + CTRL(wxTreeCtrl, treItems); + CTRL(wxStaticText, txtName); + CTRL(wxTextCtrl, txtConfig); + CTRL(wxCheckBox, chkActive); + + const TreeItemData *dataOld = (TreeItemData*)treItems->GetItemData(evt.GetOldItem()); + wxString pathOld = "(not a file)"; + if (dataOld->isFile()) { + pathOld = dataOld->path().c_str(); + Save(dataOld->path()); + } + + const TreeItemData *dataNew = (TreeItemData*)treItems->GetItemData(evt.GetItem()); + wxString pathNew = "(not a file)"; + if (dataNew->isFile()) { + pathNew = dataNew->path().c_str(); + std::ifstream t(dataNew->path()); + std::stringstream buffer; + buffer << t.rdbuf(); + this->sOrigConfig = buffer.str(); + txtConfig->SetValue(this->sOrigConfig); + wxString name = wxFileName::FileName(dataNew->path().c_str()).GetName(); + txtName->SetLabel(name); + chkActive->SetValue(name == this->active); + } else { + this->sOrigConfig = wxEmptyString; + txtConfig->SetValue(this->sOrigConfig); + txtName->SetLabel(wxEmptyString); + chkActive->SetValue(false); + } +} + +void PreferencesDialog::PreSelectUserConfigItemName(const std::filesystem::path& n) { + CTRL(wxTreeCtrl, treItems); + wxTreeItemId id = treItems->GetRootItem(); + wxTreeItemIdValue ctx; + wxTreeItemId i = treItems->GetFirstChild(id, ctx); + while (i.IsOk() && treItems->GetItemText(i) != wxT("user")) { + i = treItems->GetNextChild(id, ctx); + } + if (!i.IsOk()) { + return; + } + + id = i; + i = treItems->GetFirstChild(id, ctx); + while (i.IsOk() && treItems->GetItemText(i) != wxFileName::FileName(n.c_str()).GetName()) { + i = treItems->GetNextChild(id, ctx); + } + if (!i.IsOk()) { + return; + } + + treItems->SelectItem(i); + treItems->SetFocus(); +} + +const std::filesystem::path BuildNewConfFilePath() { + std::filesystem::path f = wxGetApp().GetConfigDir(); + + wxString ts = to_iso_string(boost::posix_time::microsec_clock::universal_time()); + ts.Replace(wxT("."), wxT("_")); + f /= (wxT("Untitled_") + ts + wxT(".conf")).t_str(); + + BOOST_LOG_TRIVIAL(info) << "will create file: " << f.c_str(); + + return f; +} + +void PreferencesDialog::OnActive(wxCommandEvent& evt) { + if (evt.IsChecked()) { + CTRL(wxTreeCtrl, treItems); + const TreeItemData *data = (TreeItemData*)treItems->GetItemData(treItems->GetSelection()); + if (data->isFile()) { + const std::filesystem::path p = data->path(); + wxString name = wxFileName::FileName(p.c_str()).GetName(); + this->active = name; + wxConfigBase::Get()->Write(wxT("/ActivePreferences/name"), this->active); + BuildItemTree(); // invalidates "data" pointer variable + PreSelectUserConfigItemName(p); + } + } else { + // TODO what if they uncheck the active checkbox? + } +} + +void PreferencesDialog::OnDuplicate(wxCommandEvent& evt) { + CTRL(wxTreeCtrl, treItems); + const TreeItemData *data = (TreeItemData*)treItems->GetItemData(treItems->GetSelection()); + if (data->isFile()) { + if (data->isEditable()) { + Save(data->path()); + } + const std::filesystem::path f = BuildNewConfFilePath(); + BOOST_LOG_TRIVIAL(info) << "copy from: " << data->path().c_str(); + if (!std::filesystem::exists(f)) { + std::filesystem::copy_file(data->path(), f, std::filesystem::copy_options::skip_existing); + BuildItemTree(); + PreSelectUserConfigItemName(f); + } else { + BOOST_LOG_TRIVIAL(error) << "file already exists: " << f.c_str(); + } + } +} + +void PreferencesDialog::OnDelete(wxCommandEvent& evt) { + CTRL(wxTreeCtrl, treItems); + CTRL(wxStaticText, txtName); + CTRL(wxTextCtrl, txtConfig); + const TreeItemData *data = (TreeItemData*)treItems->GetItemData(treItems->GetSelection()); + if (data->isFile()) { + if (data->isEditable()) { + if (wxMessageBox( + wxT("Are you sure to want to permanently DELETE this configuration file?"), + wxT("Delete"), wxYES_NO|wxCENTER, this) == wxYES) { + std::filesystem::remove(data->path()); + BuildItemTree(); + treItems->SetFocus(); + treItems->SelectItem(treItems->GetRootItem()); + // clear out fields (TODO is there a better way?) + this->sOrigConfig = wxEmptyString; + txtConfig->SetValue(this->sOrigConfig); + txtName->SetLabel(wxEmptyString); + } + } + } +} + +void PreferencesDialog::OnRename(wxCommandEvent& evt) { + CTRL(wxTreeCtrl, treItems); + const TreeItemData *data = (TreeItemData*)treItems->GetItemData(treItems->GetSelection()); + if (data->isFile()) { + if (data->isEditable()) { + Save(data->path()); + wxString name = wxFileName::FileName(data->path().c_str()).GetName(); + wxString newname = wxGetTextFromUser(wxT("new name:"), wxT("Rename configuration"), name, this, -1, -1, true); + if (!newname.IsEmpty() && newname != name) { + wxFileName fn(data->path().c_str()); + fn.SetName(newname); + // TODO should we check for existence of name in built-in (to prevent override)? + if (fn.Exists()) { + wxMessageBox(wxT("That name is already being used."), wxT("File exists"), wxOK|wxCENTER, this); + } else { + const std::filesystem::path newpath(fn.GetFullPath().t_str()); + std::filesystem::rename(data->path(), newpath); + BuildItemTree(); + PreSelectUserConfigItemName(newpath); + } + } + } + } +} + +void PreferencesDialog::OnCloseButton(wxCommandEvent& evt) { + CTRL(wxTreeCtrl, treItems); + const TreeItemData *data = (TreeItemData*)treItems->GetItemData(treItems->GetSelection()); + if (data->isFile()) { + if (data->isEditable()) { + Save(data->path()); + } + } + EndModal(wxID_OK); +} diff --git a/src/PreferencesDialog.h b/src/PreferencesDialog.h new file mode 100644 index 0000000..3efa79b --- /dev/null +++ b/src/PreferencesDialog.h @@ -0,0 +1,35 @@ +#ifndef PREFERENCESDIALOG_H +#define PREFERENCESDIALOG_H + +#include +#include +#include +#include + +class PreferencesDialog : public wxDialog { + wxWindow *parent; + wxString sOrigConfig; + wxString active; + + void BuildItemTree(); + void PreSelectUserConfigItemName(const std::filesystem::path& n); + void Save(const std::filesystem::path& to); + + void OnClose(wxCloseEvent& event); + void OnCloseButton(wxCommandEvent& evt); + void OnTreeSelectionChanged(wxTreeEvent& evt); + void OnActive(wxCommandEvent& evt); + void OnDuplicate(wxCommandEvent& evt); + void OnDelete(wxCommandEvent& evt); + void OnRename(wxCommandEvent& evt); + + wxDECLARE_EVENT_TABLE(); + +public: + PreferencesDialog(wxWindow *parent); + ~PreferencesDialog(); + + void OnInit(); +}; + +#endif /* PREFERENCESDIALOG_H */ diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..6a5c50c --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,9 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#cmakedefine PROJECT_VENDOR @PROJECT_VENDOR@ +#cmakedefine PROJECT_NAME @PROJECT_NAME@ +#cmakedefine PROJECT_VERSION @PROJECT_VERSION@ +#cmakedefine PROJECT_DESCRIPTION "@PROJECT_DESCRIPTION@" + +#endif /* CONFIG_H */