8 Commits

Author SHA1 Message Date
613c2c80f5 build: fix msvc builds 2025-12-18 11:51:28 +03:00
1a1747a472 chore: got build working on mac (kind of) 2025-12-18 01:29:32 +03:00
57c3c55a94 bump version 2025-12-18 00:45:10 +03:00
d4ff415f45 fix: gtk dialogs freezing 2025-12-18 00:42:47 +03:00
4c0502d8ee fix missing XDG_DATA_DIRS on NixOS 2025-12-18 00:11:55 +03:00
0acb36445f adjusted default theme 2025-12-17 16:13:14 +03:00
b08ba4d754 fix: coloring 2025-12-17 15:49:48 +03:00
231e9f0176 updated preview 2025-12-17 14:46:32 +03:00
29 changed files with 726 additions and 393 deletions

View File

@@ -2,7 +2,7 @@ name: Test PKGBUILD-git
on: on:
push: push:
branch: master branches: master
pull_request: pull_request:
branches: master branches: master

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@
out out
build/ build/
build-msvc/
CMakeCache.txt CMakeCache.txt
CMakeFiles/ CMakeFiles/
cmake_install.cmake cmake_install.cmake

18
.vscode/launch.json vendored
View File

@@ -5,7 +5,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Debug current target", "name": "Debug current target (GDB)",
"type": "cppdbg", "type": "cppdbg",
"request": "launch", "request": "launch",
"program": "${command:cmake.launchTargetPath}", "program": "${command:cmake.launchTargetPath}",
@@ -31,6 +31,22 @@
"ignoreFailures": true "ignoreFailures": true
} }
] ]
},
{
"name": "Debug current target (LLDB)",
"type": "cppdbg",
"request": "launch",
"program": "${command:cmake.launchTargetPath}",
"args": [
"--apply",
"--theme",
"dark"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "lldb",
}, },
] ]
} }

View File

@@ -1,6 +1,6 @@
# Maintainer: Daniel Dada <dan@binarygoose.dev> # Maintainer: Daniel Dada <dan@binarygoose.dev>
pkgname=clrsync pkgname=clrsync
pkgver=0.1.5 pkgver=0.1.6
pkgrel=1 pkgrel=1
pkgdesc="Color scheme manager" pkgdesc="Color scheme manager"
arch=('x86_64') arch=('x86_64')

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(clrsync VERSION 0.1.5 LANGUAGES CXX) project(clrsync VERSION 0.1.6 LANGUAGES CXX)
include(GNUInstallDirs) include(GNUInstallDirs)

View File

@@ -1 +1 @@
0.1.5 0.1.6

View File

@@ -8,6 +8,21 @@ if(WIN32)
URL https://download.savannah.gnu.org/releases/freetype/freetype-2.14.1.tar.gz URL https://download.savannah.gnu.org/releases/freetype/freetype-2.14.1.tar.gz
) )
FetchContent_MakeAvailable(freetype) FetchContent_MakeAvailable(freetype)
elseif(APPLE)
option(USE_SYSTEM_GLFW ON)
find_package(Freetype REQUIRED)
find_package(ZLIB REQUIRED)
find_package(BZip2 REQUIRED)
find_package(PNG REQUIRED)
find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
pkg_check_modules(HARFBUZZ harfbuzz)
endif()
else() else()
find_package(Freetype REQUIRED) find_package(Freetype REQUIRED)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
@@ -30,7 +45,18 @@ if (LINUX)
endif() endif()
if(USE_SYSTEM_GLFW) if(USE_SYSTEM_GLFW)
if(APPLE)
find_package(glfw3 QUIET)
if(glfw3_FOUND)
set(GLFW_FOUND TRUE)
set(GLFW_LIBRARIES glfw)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLFW REQUIRED glfw3) pkg_check_modules(GLFW REQUIRED glfw3)
endif()
else()
pkg_check_modules(GLFW REQUIRED glfw3)
endif()
else() else()
include(FetchContent) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
@@ -62,6 +88,7 @@ if(HARFBUZZ_FOUND)
endif() endif()
set(WAYLAND_LIBS "") set(WAYLAND_LIBS "")
if(NOT APPLE)
if(WAYLAND_CLIENT_FOUND) if(WAYLAND_CLIENT_FOUND)
list(APPEND WAYLAND_LIBS ${WAYLAND_CLIENT_LIBRARIES}) list(APPEND WAYLAND_LIBS ${WAYLAND_CLIENT_LIBRARIES})
message(STATUS "Found Wayland client") message(STATUS "Found Wayland client")
@@ -70,4 +97,4 @@ if(WAYLAND_EGL_FOUND)
list(APPEND WAYLAND_LIBS ${WAYLAND_EGL_LIBRARIES}) list(APPEND WAYLAND_LIBS ${WAYLAND_EGL_LIBRARIES})
message(STATUS "Found Wayland EGL") message(STATUS "Found Wayland EGL")
endif() endif()
endif()

View File

@@ -1,5 +1,5 @@
[general] [general]
default_theme = 'cursed' default_theme = 'dark'
palettes_path = '~/.config/clrsync/palettes' palettes_path = '~/.config/clrsync/palettes'
font = 'JetBrainsMono Nerd Font Mono' font = 'JetBrainsMono Nerd Font Mono'
font_size = 14 font_size = 14

View File

@@ -1,67 +0,0 @@
[colors]
# General
background = "#f5f5f5FF"
on_background = "#3d3d2fFF"
surface = "#e8e8e8FF"
on_surface = "#3d3d2fFF"
surface_variant = "#d0d0c8FF"
on_surface_variant = "#3d3d2fFF"
border_focused = "#c9a305FF"
border = "#d0d0c8FF"
foreground = "#3d3d2fFF"
cursor = "#c9a305FF"
accent = "#b44242FF"
# Terminal
base00 = "#f5f5f5FF"
base01 = "#b44242FF"
base02 = "#95a328FF"
base03 = "#c9a305FF"
base04 = "#60928fFF"
base05 = "#7c435aFF"
base06 = "#a48b4aFF"
base07 = "#3d3d2fFF"
base08 = "#c0c0b8FF"
base09 = "#dc7671FF"
base0A = "#d4d430FF"
base0B = "#9e9052FF"
base0C = "#76c39bFF"
base0D = "#86596cFF"
base0E = "#b89a1fFF"
base0F = "#4f4f48FF"
# Semantic
success = "#95a328FF"
info = "#60928fFF"
warning = "#c9a305FF"
error = "#b44242FF"
on_success = "#f5f5f5FF"
on_info = "#f5f5f5FF"
on_warning = "#f5f5f5FF"
on_error = "#f5f5f5FF"
# Code editor
editor_background = "#f5f5f5FF"
editor_command = "#b89a1fFF"
editor_comment = "#a0a098FF"
editor_disabled = "#c0c0b8FF"
editor_emphasis = "#dc7671FF"
editor_error = "#b44242FF"
editor_inactive = "#a0a098FF"
editor_line_number = "#86596cFF"
editor_link = "#60928fFF"
editor_main = "#3d3d2fFF"
editor_selected = "#d0d0c8FF"
editor_selection_inactive = "#e0e0d8FF"
editor_string = "#5fa37bFF"
editor_success = "#95a328FF"
editor_warning = "#c9a305FF"
[general]
name = 'cursed-light'

View File

@@ -0,0 +1,54 @@
[colors]
accent = '#9A8652FF'
background = '#111111FF'
base00 = '#111111FF'
base01 = '#668A51FF'
base02 = '#9A8652FF'
base03 = '#B47837FF'
base04 = '#9A5552FF'
base05 = '#AA477BFF'
base06 = '#3A898CFF'
base07 = '#B5B5B5FF'
base08 = '#AA4E4AFF'
base09 = '#A9DC86FF'
base0A = '#B6AB82FF'
base0B = '#C5916BFF'
base0C = '#AC7676FF'
base0D = '#B0779EFF'
base0E = '#849899FF'
base0F = '#D2D2D2FF'
border = '#242424FF'
border_focused = '#2E2E2EFF'
cursor = '#D2D2D2FF'
editor_background = '#111111FF'
editor_command = '#3A898CFF'
editor_comment = '#849899FF'
editor_disabled = '#849899FF'
editor_emphasis = '#A9DC86FF'
editor_error = '#AA4E4AFF'
editor_inactive = '#849899FF'
editor_line_number = '#849899FF'
editor_link = '#B0779EFF'
editor_main = '#D2D2D2FF'
editor_selected = '#242424FF'
editor_selection_inactive = '#1D1C1CFF'
editor_string = '#9A8652FF'
editor_success = '#668A51FF'
editor_warning = '#B47837FF'
error = '#AA4E4AFF'
foreground = '#D2D2D2FF'
info = '#3A898CFF'
on_background = '#D4D4D4FF'
on_error = '#D2D2D2FF'
on_info = '#D2D2D2FF'
on_success = '#D2D2D2FF'
on_surface = '#D4D4D4FF'
on_surface_variant = '#D4D4D4FF'
on_warning = '#D2D2D2FF'
success = '#668A51FF'
surface = '#111111FF'
surface_variant = '#191919FF'
warning = '#B47837FF'
[general]
name = 'dark'

View File

@@ -0,0 +1,54 @@
[colors]
accent = '#9A8652FF'
background = '#E0E0E0FF'
base00 = '#E0E0E0FF'
base01 = '#668A51FF'
base02 = '#9A8652FF'
base03 = '#B47837FF'
base04 = '#9A5552FF'
base05 = '#AA477BFF'
base06 = '#3A898CFF'
base07 = '#5A5A5AFF'
base08 = '#AA4E4AFF'
base09 = '#4A7A2EFF'
base0A = '#7A6A42FF'
base0B = '#A5714BFF'
base0C = '#8C5656FF'
base0D = '#90577EFF'
base0E = '#2A6A6DFF'
base0F = '#2A2A2AFF'
border = '#C5C5C5FF'
border_focused = '#B9B9B9FF'
cursor = '#2A2A2AFF'
editor_background = '#E0E0E0FF'
editor_command = '#3A898CFF'
editor_comment = '#849899FF'
editor_disabled = '#A0A0A0FF'
editor_emphasis = '#4A7A2EFF'
editor_error = '#AA4E4AFF'
editor_inactive = '#A0A0A0FF'
editor_line_number = '#9A9A95FF'
editor_link = '#90577EFF'
editor_main = '#2A2A2AFF'
editor_selected = '#C9C9C9FF'
editor_selection_inactive = '#D2D2D2FF'
editor_string = '#9A8652FF'
editor_success = '#668A51FF'
editor_warning = '#B47837FF'
error = '#AA4E4AFF'
foreground = '#2A2A2AFF'
info = '#3A898CFF'
on_background = '#2A2A2AFF'
on_error = '#FAFAF8FF'
on_info = '#FAFAF8FF'
on_success = '#FAFAF8FF'
on_surface = '#2A2A2AFF'
on_surface_variant = '#3A3A3AFF'
on_warning = '#FAFAF8FF'
success = '#668A51FF'
surface = '#E0E0E0FF'
surface_variant = '#CECECEFF'
warning = '#B47837FF'
[general]
name = 'light'

View File

@@ -0,0 +1,54 @@
[colors]
accent = '#95A328FF'
background = '#F5F5F5FF'
base00 = '#F5F5F5FF'
base01 = '#B44242FF'
base02 = '#95A328FF'
base03 = '#C9A305FF'
base04 = '#60928FFF'
base05 = '#7C435AFF'
base06 = '#A48B4AFF'
base07 = '#3D3D2FFF'
base08 = '#C0C0B8FF'
base09 = '#DC7671FF'
base0A = '#D4D430FF'
base0B = '#9E9052FF'
base0C = '#76C39BFF'
base0D = '#86596CFF'
base0E = '#B89A1FFF'
base0F = '#4F4F48FF'
border = '#D0D0C8FF'
border_focused = '#C9A305FF'
cursor = '#C9A305FF'
editor_background = '#F5F5F5FF'
editor_command = '#B89A1FFF'
editor_comment = '#A0A098FF'
editor_disabled = '#C0C0B8FF'
editor_emphasis = '#DC7671FF'
editor_error = '#B44242FF'
editor_inactive = '#A0A098FF'
editor_line_number = '#86596CFF'
editor_link = '#60928FFF'
editor_main = '#3D3D2FFF'
editor_selected = '#D0D0C8FF'
editor_selection_inactive = '#E0E0D8FF'
editor_string = '#5FA37BFF'
editor_success = '#95A328FF'
editor_warning = '#C9A305FF'
error = '#B44242FF'
foreground = '#3D3D2FFF'
info = '#60928FFF'
on_background = '#3D3D2FFF'
on_error = '#F5F5F5FF'
on_info = '#F5F5F5FF'
on_success = '#F5F5F5FF'
on_surface = '#3D3D2FFF'
on_surface_variant = '#CCCCCCFF'
on_warning = '#F5F5F5FF'
success = '#95A328FF'
surface = '#E8E8E8FF'
surface_variant = '#D0D0C8FF'
warning = '#C9A305FF'
[general]
name = 'cursed-light'

View File

@@ -1,5 +1,5 @@
[colors] [colors]
accent = '#B44242FF' accent = '#95A328FF'
background = '#151515FF' background = '#151515FF'
base00 = '#151515FF' base00 = '#151515FF'
base01 = '#B44242FF' base01 = '#B44242FF'
@@ -22,7 +22,7 @@ border_focused = '#E1C135FF'
cursor = '#E1C135FF' cursor = '#E1C135FF'
editor_background = '#151515FF' editor_background = '#151515FF'
editor_command = '#CEB34FFF' editor_command = '#CEB34FFF'
editor_comment = '#3F3639FF' editor_comment = '#7A7A7AFF'
editor_disabled = '#3F3639FF' editor_disabled = '#3F3639FF'
editor_emphasis = '#DC7671FF' editor_emphasis = '#DC7671FF'
editor_error = '#B44242FF' editor_error = '#B44242FF'
@@ -43,7 +43,7 @@ on_error = '#151515FF'
on_info = '#151515FF' on_info = '#151515FF'
on_success = '#151515FF' on_success = '#151515FF'
on_surface = '#C2C2B0FF' on_surface = '#C2C2B0FF'
on_surface_variant = '#C2C2B0FF' on_surface_variant = '#CCCCCCFF'
on_warning = '#151515FF' on_warning = '#151515FF'
success = '#95A328FF' success = '#95A328FF'
surface = '#1C1C1CFF' surface = '#1C1C1CFF'

54
extra/palletes/nord.toml Normal file
View File

@@ -0,0 +1,54 @@
[colors]
accent = '#5E81ACFF'
background = '#2E3440FF'
base00 = '#2E3440FF'
base01 = '#BF616AFF'
base02 = '#A3BE8CFF'
base03 = '#EBCB8BFF'
base04 = '#81A1C1FF'
base05 = '#B48EADFF'
base06 = '#88C0D0FF'
base07 = '#E5E9F0FF'
base08 = '#4C566AFF'
base09 = '#D08770FF'
base0A = '#EBCB8BFF'
base0B = '#A3BE8CFF'
base0C = '#8FBCBBFF'
base0D = '#5E81ACFF'
base0E = '#B48EADFF'
base0F = '#ECEFF4FF'
border = '#4C566AFF'
border_focused = '#88C0D0FF'
cursor = '#D8DEE9FF'
editor_background = '#2E3440FF'
editor_command = '#81A1C1FF'
editor_comment = '#616E88FF'
editor_disabled = '#4C566AFF'
editor_emphasis = '#B48EADFF'
editor_error = '#BF616AFF'
editor_inactive = '#616E88FF'
editor_line_number = '#4C566AFF'
editor_link = '#88C0D0FF'
editor_main = '#D8DEE9FF'
editor_selected = '#434C5EFF'
editor_selection_inactive = '#3B4252FF'
editor_string = '#A3BE8CFF'
editor_success = '#A3BE8CFF'
editor_warning = '#EBCB8BFF'
error = '#BF616AFF'
foreground = '#D8DEE9FF'
info = '#5E81ACFF'
on_background = '#D8DEE9FF'
on_error = '#2E3440FF'
on_info = '#2E3440FF'
on_success = '#2E3440FF'
on_surface = '#ECEFF4FF'
on_surface_variant = '#ECEFF4FF'
on_warning = '#2E3440FF'
success = '#A3BE8CFF'
surface = '#3B4252FF'
surface_variant = '#434C5EFF'
warning = '#EBCB8BFF'
[general]
name = 'nord'

View File

@@ -5,6 +5,7 @@
git, git,
pkg-config, pkg-config,
makeWrapper, makeWrapper,
wrapGAppsHook3,
wayland-protocols, wayland-protocols,
glfw, glfw,
freetype, freetype,
@@ -17,7 +18,9 @@
bzip2, bzip2,
wayland-scanner, wayland-scanner,
gtk3, gtk3,
semver glib,
gsettings-desktop-schemas,
semver,
}: }:
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
@@ -49,6 +52,7 @@ stdenv.mkDerivation rec {
git git
pkg-config pkg-config
makeWrapper makeWrapper
wrapGAppsHook3
wayland-protocols wayland-protocols
]; ];
@@ -69,6 +73,8 @@ stdenv.mkDerivation rec {
zlib zlib
bzip2 bzip2
gtk3 gtk3
gsettings-desktop-schemas
glib
]; ];
cmakeFlags = [ cmakeFlags = [
@@ -82,21 +88,17 @@ stdenv.mkDerivation rec {
cmake --install . --prefix $out cmake --install . --prefix $out
wrapProgram $out/bin/clrsync_gui \
--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath buildInputs}
wrapProgram $out/bin/clrsync_cli \
--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath buildInputs}
runHook postInstall runHook postInstall
''; '';
dontWrapGApps = false;
meta = with lib; { meta = with lib; {
description = "Color scheme manager with GUI and CLI"; description = "Color scheme manager with GUI and CLI";
homepage = "https://github.com/obsqrbtz/clrsync"; homepage = "https://github.com/obsqrbtz/clrsync";
license = licenses.mit; license = licenses.mit;
platforms = platforms.linux; platforms = platforms.linux;
mainProgram = "clrsync_gui"; mainProgram = "clrsync_gui";
maintainers = [ ]; maintainers = [ "Daniel Dada" ];
}; };
} }

View File

@@ -3,7 +3,6 @@
#include <cstdio> #include <cstdio>
#include <format> #include <format>
#include <stdexcept> #include <stdexcept>
#include <unordered_map>
namespace clrsync::core namespace clrsync::core
{ {

View File

@@ -77,65 +77,65 @@ constexpr const char* COLOR_KEYS[] = {
constexpr size_t NUM_COLOR_KEYS = std::size(COLOR_KEYS); constexpr size_t NUM_COLOR_KEYS = std::size(COLOR_KEYS);
inline const std::unordered_map<std::string, uint32_t> DEFAULT_COLORS = { inline const std::unordered_map<std::string, uint32_t> DEFAULT_COLORS = {
{"background", 0x1e1e1eff}, {"background", 0x111111ff},
{"on_background", 0xd4d4d4ff}, {"on_background", 0xd4d4d4ff},
{"surface", 0x252526ff}, {"surface", 0x111111ff},
{"on_surface", 0xe8e8e8ff}, {"on_surface", 0xd4d4d4ff},
{"surface_variant", 0x2d2d30ff}, {"surface_variant", 0x191919ff},
{"on_surface_variant", 0xccccccff}, {"on_surface_variant", 0xd4d4d4ff},
{"border_focused", 0x007accff}, {"border_focused", 0x2e2e2eff},
{"border", 0x3e3e42ff}, {"border", 0x242424ff},
{"foreground", 0xccccccff}, {"foreground", 0xd2d2d2ff},
{"cursor", 0xaeafadff}, {"cursor", 0xd2d2d2ff},
{"accent", 0x0e639cff}, {"accent", 0x9a8652ff},
{"success", 0x4ec9b0ff}, {"success", 0x668a51ff},
{"info", 0x4fc1ffff}, {"info", 0x3a898cff},
{"warning", 0xdcdcaaff}, {"warning", 0xb47837ff},
{"error", 0xf48771ff}, {"error", 0xaa4e4aff},
{"on_success", 0x000000ff}, {"on_success", 0xd2d2d2ff},
{"on_info", 0x000000ff}, {"on_info", 0xd2d2d2ff},
{"on_warning", 0x000000ff}, {"on_warning", 0xd2d2d2ff},
{"on_error", 0xffffffff}, {"on_error", 0xd2d2d2ff},
{"editor_background", 0x1e1e1eff}, {"editor_background", 0x111111ff},
{"editor_command", 0xd7ba7dff}, {"editor_command", 0x3a898cff},
{"editor_comment", 0x6a9955ff}, {"editor_comment", 0x849899ff},
{"editor_disabled", 0x808080ff}, {"editor_disabled", 0x849899ff},
{"editor_emphasis", 0x569cd6ff}, {"editor_emphasis", 0xa9dc86ff},
{"editor_error", 0xf44747ff}, {"editor_error", 0xaa4e4aff},
{"editor_inactive", 0x858585ff}, {"editor_inactive", 0x849899ff},
{"editor_line_number", 0x858585ff}, {"editor_line_number", 0x849899ff},
{"editor_link", 0x3794ffff}, {"editor_link", 0xb0779eff},
{"editor_main", 0xd4d4d4ff}, {"editor_main", 0xd2d2d2ff},
{"editor_selected", 0x264f78ff}, {"editor_selected", 0x242424ff},
{"editor_selection_inactive", 0x3a3d41ff}, {"editor_selection_inactive", 0x1d1c1cff},
{"editor_string", 0xce9178ff}, {"editor_string", 0x9a8652ff},
{"editor_success", 0x89d185ff}, {"editor_success", 0x668a51ff},
{"editor_warning", 0xcca700ff}, {"editor_warning", 0xb47837ff},
{"base00", 0x181818ff}, {"base00", 0x111111ff},
{"base01", 0x282828ff}, {"base01", 0x668a51ff},
{"base02", 0x383838ff}, {"base02", 0x9a8652ff},
{"base03", 0x585858ff}, {"base03", 0xb47837ff},
{"base04", 0xb8b8b8ff}, {"base04", 0x9a5552ff},
{"base05", 0xd8d8d8ff}, {"base05", 0xaa477bff},
{"base06", 0xe8e8e8ff}, {"base06", 0x3a898cff},
{"base07", 0xf8f8f8ff}, {"base07", 0xb5b5b5ff},
{"base08", 0xab4642ff}, {"base08", 0xaa4e4aff},
{"base09", 0xdc9656ff}, {"base09", 0xa9dc86ff},
{"base0A", 0xf7ca88ff}, {"base0A", 0xb6ab82ff},
{"base0B", 0xa1b56cff}, {"base0B", 0xc5916bff},
{"base0C", 0x86c1b9ff}, {"base0C", 0xac7676ff},
{"base0D", 0x7cafc2ff}, {"base0D", 0xb0779eff},
{"base0E", 0xba8bafff}, {"base0E", 0x849899ff},
{"base0F", 0xa16946ff}, {"base0F", 0xd2d2d2ff},
}; };
} // namespace clrsync::core } // namespace clrsync::core
#endif #endif

View File

@@ -6,7 +6,7 @@
namespace clrsync::core namespace clrsync::core
{ {
const std::string GIT_SEMVER = "0.1.4+git.g92b06a9"; const std::string GIT_SEMVER = "0.1.6+git.g1a1747a";
const std::string version_string(); const std::string version_string();
} // namespace clrsync::core } // namespace clrsync::core

View File

@@ -15,8 +15,15 @@ set(GUI_SOURCES
file_browser.cpp file_browser.cpp
${CMAKE_SOURCE_DIR}/lib/color_text_edit/TextEditor.cpp ${CMAKE_SOURCE_DIR}/lib/color_text_edit/TextEditor.cpp
) )
if(APPLE)
list(APPEND GUI_SOURCES file_browser_macos.mm)
endif()
if(WIN32)
add_executable(clrsync_gui WIN32 ${GUI_SOURCES})
else()
add_executable(clrsync_gui ${GUI_SOURCES}) add_executable(clrsync_gui ${GUI_SOURCES})
endif()
target_include_directories(clrsync_gui PRIVATE target_include_directories(clrsync_gui PRIVATE
${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src
@@ -35,6 +42,9 @@ if(WIN32)
comdlg32 comdlg32
shlwapi shlwapi
) )
if (MSVC)
target_link_options(clrsync_gui PRIVATE /ENTRY:mainCRTStartup)
endif()
elseif(APPLE) elseif(APPLE)
target_link_libraries(clrsync_gui PRIVATE target_link_libraries(clrsync_gui PRIVATE
clrsync_core clrsync_core

View File

@@ -107,7 +107,8 @@ void color_table_renderer::render(const clrsync::core::palette& current,
{ {
if (current.colors().empty()) if (current.colors().empty())
{ {
ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.4f, 1.0f), "No palette loaded"); ImVec4 warning_color = palette_utils::get_color(current, "warning", "accent");
ImGui::TextColored(warning_color, "No palette loaded");
return; return;
} }
@@ -131,16 +132,6 @@ void color_table_renderer::render(const clrsync::core::palette& current,
ImGui::SetTooltip("Clear filter"); ImGui::SetTooltip("Clear filter");
} }
ImGui::SameLine();
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::TextUnformatted("Click on a color name to copy its template variable");
ImGui::TextUnformatted("Example: clicking 'background' copies {background.hex}");
ImGui::EndTooltip();
}
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::Spacing(); ImGui::Spacing();

View File

@@ -138,85 +138,7 @@ std::string select_folder_dialog(const std::string& title,
} }
#else #elif !defined(__APPLE__)
#ifdef __APPLE__
#include <Cocoa/Cocoa.h>
namespace file_dialogs {
std::string open_file_dialog(const std::string& title,
const std::string& initial_path,
const std::vector<std::string>& filters) {
@autoreleasepool {
NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel setTitle:[NSString stringWithUTF8String:title.c_str()]];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO];
[panel setAllowsMultipleSelection:NO];
if (!initial_path.empty()) {
NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:initial_path.c_str()]];
[panel setDirectoryURL:url];
}
if ([panel runModal] == NSModalResponseOK) {
NSURL* url = [[panel URLs] objectAtIndex:0];
return std::string([[url path] UTF8String]);
}
}
return "";
}
std::string save_file_dialog(const std::string& title,
const std::string& initial_path,
const std::vector<std::string>& filters) {
@autoreleasepool {
NSSavePanel* panel = [NSSavePanel savePanel];
[panel setTitle:[NSString stringWithUTF8String:title.c_str()]];
if (!initial_path.empty()) {
std::filesystem::path p(initial_path);
if (std::filesystem::exists(p.parent_path())) {
NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:p.parent_path().c_str()]];
[panel setDirectoryURL:url];
[panel setNameFieldStringValue:[NSString stringWithUTF8String:p.filename().c_str()]];
}
}
if ([panel runModal] == NSModalResponseOK) {
NSURL* url = [panel URL];
return std::string([[url path] UTF8String]);
}
}
return "";
}
std::string select_folder_dialog(const std::string& title,
const std::string& initial_path) {
@autoreleasepool {
NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel setTitle:[NSString stringWithUTF8String:title.c_str()]];
[panel setCanChooseFiles:NO];
[panel setCanChooseDirectories:YES];
[panel setAllowsMultipleSelection:NO];
if (!initial_path.empty()) {
NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:initial_path.c_str()]];
[panel setDirectoryURL:url];
}
if ([panel runModal] == NSModalResponseOK) {
NSURL* url = [[panel URLs] objectAtIndex:0];
return std::string([[url path] UTF8String]);
}
}
return "";
}
}
#else
#include <gtk/gtk.h> #include <gtk/gtk.h>
@@ -229,36 +151,38 @@ std::string open_file_dialog(const std::string& title,
return ""; return "";
} }
GtkWidget* dialog = gtk_file_chooser_dialog_new( GtkFileChooserNative *native = gtk_file_chooser_native_new(
title.c_str(), title.c_str(),
nullptr, nullptr,
GTK_FILE_CHOOSER_ACTION_OPEN, GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL, "_Open",
"Open", GTK_RESPONSE_ACCEPT, "_Cancel");
nullptr);
GtkFileChooser *chooser = GTK_FILE_CHOOSER(native);
if (!initial_path.empty()) { if (!initial_path.empty()) {
std::filesystem::path p(initial_path); std::filesystem::path p(initial_path);
if (std::filesystem::exists(p)) { if (std::filesystem::exists(p)) {
if (std::filesystem::is_directory(p)) { if (std::filesystem::is_directory(p)) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), initial_path.c_str()); gtk_file_chooser_set_current_folder(chooser, initial_path.c_str());
} else { } else {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), p.parent_path().c_str()); gtk_file_chooser_set_current_folder(chooser, p.parent_path().c_str());
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), p.filename().c_str()); gtk_file_chooser_set_current_name(chooser, p.filename().c_str());
} }
} }
} }
std::string result; std::string result;
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { if (gtk_native_dialog_run(GTK_NATIVE_DIALOG(native)) == GTK_RESPONSE_ACCEPT) {
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); char* filename = gtk_file_chooser_get_filename(chooser);
if (filename) { if (filename) {
result = filename; result = filename;
g_free(filename); g_free(filename);
} }
} }
gtk_widget_destroy(dialog); g_object_unref(native);
while (gtk_events_pending()) gtk_main_iteration();
return result; return result;
} }
@@ -269,34 +193,35 @@ std::string save_file_dialog(const std::string& title,
return ""; return "";
} }
GtkWidget* dialog = gtk_file_chooser_dialog_new( GtkFileChooserNative *native = gtk_file_chooser_native_new(
title.c_str(), title.c_str(),
nullptr, nullptr,
GTK_FILE_CHOOSER_ACTION_SAVE, GTK_FILE_CHOOSER_ACTION_SAVE,
"Cancel", GTK_RESPONSE_CANCEL, "_Save",
"Save", GTK_RESPONSE_ACCEPT, "_Cancel");
nullptr);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); GtkFileChooser *chooser = GTK_FILE_CHOOSER(native);
gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE);
if (!initial_path.empty()) { if (!initial_path.empty()) {
std::filesystem::path p(initial_path); std::filesystem::path p(initial_path);
if (std::filesystem::exists(p.parent_path())) { if (std::filesystem::exists(p.parent_path())) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), p.parent_path().c_str()); gtk_file_chooser_set_current_folder(chooser, p.parent_path().c_str());
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), p.filename().c_str()); gtk_file_chooser_set_current_name(chooser, p.filename().c_str());
} }
} }
std::string result; std::string result;
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { if (gtk_native_dialog_run(GTK_NATIVE_DIALOG(native)) == GTK_RESPONSE_ACCEPT) {
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); char* filename = gtk_file_chooser_get_filename(chooser);
if (filename) { if (filename) {
result = filename; result = filename;
g_free(filename); g_free(filename);
} }
} }
gtk_widget_destroy(dialog); g_object_unref(native);
while (gtk_events_pending()) gtk_main_iteration();
return result; return result;
} }
@@ -306,33 +231,33 @@ std::string select_folder_dialog(const std::string& title,
return ""; return "";
} }
GtkWidget* dialog = gtk_file_chooser_dialog_new( GtkFileChooserNative *native = gtk_file_chooser_native_new(
title.c_str(), title.c_str(),
nullptr, nullptr,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
"Cancel", GTK_RESPONSE_CANCEL, "_Select",
"Select", GTK_RESPONSE_ACCEPT, "_Cancel");
nullptr);
GtkFileChooser *chooser = GTK_FILE_CHOOSER(native);
if (!initial_path.empty() && std::filesystem::exists(initial_path)) { if (!initial_path.empty() && std::filesystem::exists(initial_path)) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), initial_path.c_str()); gtk_file_chooser_set_current_folder(chooser, initial_path.c_str());
} }
std::string result; std::string result;
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { if (gtk_native_dialog_run(GTK_NATIVE_DIALOG(native)) == GTK_RESPONSE_ACCEPT) {
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); char* filename = gtk_file_chooser_get_filename(chooser);
if (filename) { if (filename) {
result = filename; result = filename;
g_free(filename); g_free(filename);
} }
} }
gtk_widget_destroy(dialog); g_object_unref(native);
while (gtk_events_pending()) gtk_main_iteration();
return result; return result;
} }
} }
#endif #endif
#endif

View File

@@ -0,0 +1,80 @@
#include "file_browser.hpp"
#include <filesystem>
#ifdef __APPLE__
#include <Cocoa/Cocoa.h>
namespace file_dialogs {
std::string open_file_dialog(const std::string& title,
const std::string& initial_path,
const std::vector<std::string>& filters) {
@autoreleasepool {
NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel setTitle:[NSString stringWithUTF8String:title.c_str()]];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO];
[panel setAllowsMultipleSelection:NO];
if (!initial_path.empty()) {
NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:initial_path.c_str()]];
[panel setDirectoryURL:url];
}
if ([panel runModal] == NSModalResponseOK) {
NSURL* url = [[panel URLs] objectAtIndex:0];
return std::string([[url path] UTF8String]);
}
}
return "";
}
std::string save_file_dialog(const std::string& title,
const std::string& initial_path,
const std::vector<std::string>& filters) {
@autoreleasepool {
NSSavePanel* panel = [NSSavePanel savePanel];
[panel setTitle:[NSString stringWithUTF8String:title.c_str()]];
if (!initial_path.empty()) {
std::filesystem::path p(initial_path);
if (std::filesystem::exists(p.parent_path())) {
NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:p.parent_path().c_str()]];
[panel setDirectoryURL:url];
[panel setNameFieldStringValue:[NSString stringWithUTF8String:p.filename().c_str()]];
}
}
if ([panel runModal] == NSModalResponseOK) {
NSURL* url = [panel URL];
return std::string([[url path] UTF8String]);
}
}
return "";
}
std::string select_folder_dialog(const std::string& title,
const std::string& initial_path) {
@autoreleasepool {
NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel setTitle:[NSString stringWithUTF8String:title.c_str()]];
[panel setCanChooseFiles:NO];
[panel setCanChooseDirectories:YES];
[panel setAllowsMultipleSelection:NO];
if (!initial_path.empty()) {
NSURL* url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:initial_path.c_str()]];
[panel setDirectoryURL:url];
}
if ([panel runModal] == NSModalResponseOK) {
NSURL* url = [[panel URLs] objectAtIndex:0];
return std::string([[url path] UTF8String]);
}
}
return "";
}
}
#endif

View File

@@ -123,25 +123,27 @@ std::vector<unsigned char> font_loader::load_font_macos(const char* font_name)
if (!desc) if (!desc)
return out; return out;
CTFontRef font = CTFontCreateWithFontDescriptor(desc, 0, nullptr); CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(desc, kCTFontURLAttribute);
CFRelease(desc); CFRelease(desc);
if (!font) if (!url)
return out; return out;
CFDataRef data = CTFontCopyTable(font, kCTFontTableCFF, 0); CFDataRef data = nullptr;
if (!data) Boolean success = CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, url, &data, nullptr, nullptr, nullptr);
data = CTFontCopyTable(font, kCTFontTableHead, 0); CFRelease(url);
if (data) if (success && data)
{ {
CFIndex size = CFDataGetLength(data); CFIndex size = CFDataGetLength(data);
if (size > 100)
{
out.resize(size); out.resize(size);
CFDataGetBytes(data, CFRangeMake(0, size), out.data()); CFDataGetBytes(data, CFRangeMake(0, size), out.data());
}
CFRelease(data); CFRelease(data);
} }
CFRelease(font);
return out; return out;
} }

View File

@@ -23,7 +23,11 @@ GLFWwindow * init_glfw()
} }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
#ifdef __APPLE__
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
#endif
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
GLFWwindow* w = glfwCreateWindow(1280, 720, "clrsync", nullptr, nullptr); GLFWwindow* w = glfwCreateWindow(1280, 720, "clrsync", nullptr, nullptr);
@@ -49,7 +53,11 @@ void init_imgui(GLFWwindow* window, const std::string& ini_path)
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 130"); #ifdef __APPLE__
ImGui_ImplOpenGL3_Init("#version 150");
#else
ImGui_ImplOpenGL3_Init("#version 120");
#endif
} }
void begin_frame() void begin_frame()
@@ -133,8 +141,8 @@ void setup_main_dockspace(bool& first_time)
} }
ImGui::DockBuilderDockWindow("Color Schemes", right); ImGui::DockBuilderDockWindow("Color Schemes", right);
ImGui::DockBuilderDockWindow("Templates", center);
ImGui::DockBuilderDockWindow("Color Preview", center); ImGui::DockBuilderDockWindow("Color Preview", center);
ImGui::DockBuilderDockWindow("Templates", center);
ImGui::DockBuilderFinish(dockspace_id); ImGui::DockBuilderFinish(dockspace_id);
} }

View File

@@ -77,9 +77,9 @@ int main(int, char**)
render_menu_bar(&aboutWindow, &settingsWindow); render_menu_bar(&aboutWindow, &settingsWindow);
setup_main_dockspace(first_time); setup_main_dockspace(first_time);
templateEditor.render();
colorEditor.render_controls_and_colors(); colorEditor.render_controls_and_colors();
colorEditor.render_preview(); colorEditor.render_preview();
templateEditor.render();
aboutWindow.render(colorEditor.controller().current_palette()); aboutWindow.render(colorEditor.controller().current_palette());
settingsWindow.render(); settingsWindow.render();

View File

@@ -1,7 +1,9 @@
#include "preview_renderer.hpp" #include "preview_renderer.hpp"
#include "theme_applier.hpp" #include "theme_applier.hpp"
#include "imgui_helpers.hpp"
#include "imgui.h" #include "imgui.h"
#include <algorithm> #include <algorithm>
#include <array>
preview_renderer::preview_renderer() preview_renderer::preview_renderer()
{ {
@@ -70,6 +72,16 @@ int main()
m_editor.SetShowWhitespaces(false); m_editor.SetShowWhitespaces(false);
} }
static ImVec4 hex_to_imvec4(uint32_t hex)
{
return {
((hex >> 24) & 0xFF) / 255.0f,
((hex >> 16) & 0xFF) / 255.0f,
((hex >> 8) & 0xFF) / 255.0f,
(hex & 0xFF) / 255.0f
};
}
void preview_renderer::apply_palette(const clrsync::core::palette& palette) void preview_renderer::apply_palette(const clrsync::core::palette& palette)
{ {
theme_applier::apply_to_editor(m_editor, palette); theme_applier::apply_to_editor(m_editor, palette);
@@ -78,9 +90,11 @@ void preview_renderer::apply_palette(const clrsync::core::palette& palette)
void preview_renderer::render_code_preview() void preview_renderer::render_code_preview()
{ {
const float avail_height = ImGui::GetContentRegionAvail().y; const float avail_height = ImGui::GetContentRegionAvail().y;
const float code_preview_height = std::max(250.0f, avail_height * 0.55f); const float code_preview_height = std::max(250.0f, avail_height * 0.50f);
ImGui::Text("Code Editor:"); ImGui::Text("Code Editor Preview:");
ImGui::SameLine();
ImGui::TextDisabled("(editor_* colors)");
m_editor.Render("##CodeEditor", ImVec2(0, code_preview_height), true); m_editor.Render("##CodeEditor", ImVec2(0, code_preview_height), true);
} }
@@ -88,46 +102,134 @@ void preview_renderer::render_terminal_preview(const clrsync::core::palette& cur
{ {
auto get_color = [&](const std::string &key) -> ImVec4 { auto get_color = [&](const std::string &key) -> ImVec4 {
const auto &col = current.get_color(key); const auto &col = current.get_color(key);
const uint32_t hex = col.hex(); return hex_to_imvec4(col.hex());
return {((hex >> 24) & 0xFF) / 255.0f, ((hex >> 16) & 0xFF) / 255.0f,
((hex >> 8) & 0xFF) / 255.0f, ((hex) & 0xFF) / 255.0f};
}; };
const ImVec4 bg = get_color("base00");
const ImVec4 fg = get_color("base07");
const ImVec4 cursor_col = get_color("cursor");
const ImVec4 border_col = get_color("border");
const ImVec4 editor_bg = get_color("editor_background"); const ImVec4 black = get_color("base00");
const ImVec4 fg = get_color("foreground"); const ImVec4 red = get_color("base01");
const ImVec4 accent = get_color("accent"); const ImVec4 green = get_color("base02");
const ImVec4 border = get_color("border"); const ImVec4 yellow = get_color("base03");
const ImVec4 error = get_color("error"); const ImVec4 blue = get_color("base04");
const ImVec4 warning = get_color("warning"); const ImVec4 magenta = get_color("base05");
const ImVec4 success = get_color("success"); const ImVec4 cyan = get_color("base06");
const ImVec4 info = get_color("info"); const ImVec4 white = get_color("base07");
const ImVec4 bright_black = get_color("base08");
const ImVec4 bright_red = get_color("base09");
const ImVec4 bright_green = get_color("base0A");
const ImVec4 bright_yellow = get_color("base0B");
const ImVec4 bright_blue = get_color("base0C");
const ImVec4 bright_magenta = get_color("base0D");
const ImVec4 bright_cyan = get_color("base0E");
const ImVec4 bright_white = get_color("base0F");
ImGui::Spacing(); ImGui::Spacing();
ImGui::Text("Terminal Preview:"); ImGui::Text("Terminal Preview:");
ImGui::SameLine();
ImGui::TextDisabled("(base00-base0F colors)");
ImGui::PushStyleColor(ImGuiCol_ChildBg, editor_bg); ImGui::PushStyleColor(ImGuiCol_ChildBg, bg);
ImGui::BeginChild("TerminalPreview", ImVec2(0, 0), true); ImGui::PushStyleColor(ImGuiCol_Border, border_col);
ImGui::PushStyleColor(ImGuiCol_Border, border);
struct term_line const float terminal_height = std::max(200.0f, ImGui::GetContentRegionAvail().y - 10.0f);
ImGui::BeginChild("TerminalPreview", ImVec2(0, terminal_height), true);
ImGui::TextColored(green, "user@host");
ImGui::SameLine(0, 0);
ImGui::TextColored(fg, ":");
ImGui::SameLine(0, 0);
ImGui::TextColored(blue, "~/projects");
ImGui::SameLine(0, 0);
ImGui::TextColored(fg, "$ ");
ImGui::SameLine(0, 0);
ImGui::TextColored(fg, "ls -la");
ImGui::TextColored(fg, "total 48");
ImGui::TextColored(blue, "drwxr-xr-x");
ImGui::SameLine();
ImGui::TextColored(fg, " 5 user group 4096 Dec 2 10:30 ");
ImGui::SameLine(0, 0);
ImGui::TextColored(blue, ".");
ImGui::TextColored(blue, "drwxr-xr-x");
ImGui::SameLine();
ImGui::TextColored(fg, " 3 user group 4096 Dec 1 09:15 ");
ImGui::SameLine(0, 0);
ImGui::TextColored(blue, "..");
ImGui::TextColored(fg, "-rw-r--r--");
ImGui::SameLine();
ImGui::TextColored(fg, " 1 user group 1234 Dec 2 10:30 ");
ImGui::SameLine(0, 0);
ImGui::TextColored(fg, "README.md");
ImGui::TextColored(fg, "-rwxr-xr-x");
ImGui::SameLine();
ImGui::TextColored(fg, " 1 user group 8192 Dec 2 10:28 ");
ImGui::SameLine(0, 0);
ImGui::TextColored(green, "build.sh");
ImGui::TextColored(cyan, "lrwxrwxrwx");
ImGui::SameLine();
ImGui::TextColored(fg, " 1 user group 24 Dec 1 15:00 ");
ImGui::SameLine(0, 0);
ImGui::TextColored(cyan, "config -> ~/.config/app");
ImGui::Spacing();
ImGui::TextColored(green, "user@host");
ImGui::SameLine(0, 0);
ImGui::TextColored(fg, ":");
ImGui::SameLine(0, 0);
ImGui::TextColored(blue, "~/projects");
ImGui::SameLine(0, 0);
ImGui::TextColored(fg, "$ ");
ImGui::SameLine(0, 0);
ImGui::TextColored(fg, "git status");
ImGui::TextColored(fg, "On branch ");
ImGui::SameLine(0, 0);
ImGui::TextColored(green, "main");
ImGui::TextColored(fg, "Changes to be committed:");
ImGui::TextColored(green, " modified: src/main.cpp");
ImGui::TextColored(green, " new file: src/utils.hpp");
ImGui::TextColored(fg, "Changes not staged:");
ImGui::TextColored(red, " modified: README.md");
ImGui::Spacing();
ImGui::TextColored(fg, "ANSI Colors (0-7 / 8-15):");
const float box_size = 20.0f;
const float spacing = 4.0f;
ImVec2 start_pos = ImGui::GetCursorScreenPos();
ImDrawList* draw_list = ImGui::GetWindowDrawList();
std::array<ImVec4, 8> normal_colors = {black, red, green, yellow, blue, magenta, cyan, white};
for (size_t i = 0; i < 8; i++)
{ {
const char *text{}; ImVec2 p0 = ImVec2(start_pos.x + i * (box_size + spacing), start_pos.y);
ImVec4 col; ImVec2 p1 = ImVec2(p0.x + box_size, p0.y + box_size);
}; draw_list->AddRectFilled(p0, p1, ImGui::ColorConvertFloat4ToU32(normal_colors[i]));
term_line term_lines[] = { draw_list->AddRect(p0, p1, ImGui::ColorConvertFloat4ToU32(border_col));
{"$ ls -la", fg},
{"drwxr-xr-x 5 user group 4096 Dec 2 10:30 .", accent},
{"Build successful", success},
{"Error: file not found", error},
{"Warning: low disk space", warning},
{"Info: update available", info},
};
for (auto &[text, col] : term_lines)
{
ImGui::TextColored(col, "%s", text);
} }
std::array<ImVec4, 8> bright_colors = {bright_black, bright_red, bright_green, bright_yellow,
bright_blue, bright_magenta, bright_cyan, bright_white};
for (size_t i = 0; i < 8; i++)
{
ImVec2 p0 = ImVec2(start_pos.x + i * (box_size + spacing), start_pos.y + box_size + spacing);
ImVec2 p1 = ImVec2(p0.x + box_size, p0.y + box_size);
draw_list->AddRectFilled(p0, p1, ImGui::ColorConvertFloat4ToU32(bright_colors[i]));
draw_list->AddRect(p0, p1, ImGui::ColorConvertFloat4ToU32(border_col));
}
ImGui::Dummy(ImVec2(8 * (box_size + spacing), 2 * box_size + spacing + 4));
ImGui::PopStyleColor(2); ImGui::PopStyleColor(2);
ImGui::EndChild(); ImGui::EndChild();
} }
@@ -136,7 +238,8 @@ void preview_renderer::render(const clrsync::core::palette& current)
{ {
if (current.colors().empty()) if (current.colors().empty())
{ {
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "Current palette is empty"); ImVec4 error_color = palette_utils::get_color(current, "error", "accent");
ImGui::TextColored(error_color, "Current palette is empty");
return; return;
} }

View File

@@ -250,12 +250,36 @@ void settings_window::render_status_messages()
if (!m_error_message.empty()) if (!m_error_message.empty())
{ {
ImGui::Spacing(); ImGui::Spacing();
auto error_color = palette_utils::get_color(m_current_palette, "error");
ImGui::PushStyleColor(ImGuiCol_Text, error_color); auto error_bg_color = palette_utils::get_color(m_current_palette, "error");
auto error_text_color = palette_utils::get_color(m_current_palette, "on_error");
ImGui::PushStyleColor(ImGuiCol_ChildBg, error_bg_color);
ImGui::PushStyleColor(ImGuiCol_Border, error_bg_color);
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 4.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 1.0f);
if (ImGui::BeginChild("##error_box", ImVec2(0, 0), ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_Borders))
{
ImGui::PushStyleColor(ImGuiCol_Text, error_text_color);
ImGui::TextWrapped("Error: %s", m_error_message.c_str()); ImGui::TextWrapped("Error: %s", m_error_message.c_str());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::Spacing();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(error_bg_color.x * 0.8f, error_bg_color.y * 0.8f, error_bg_color.z * 0.8f, error_bg_color.w));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(error_bg_color.x * 0.6f, error_bg_color.y * 0.6f, error_bg_color.z * 0.6f, error_bg_color.w));
ImGui::PushStyleColor(ImGuiCol_Text, error_text_color);
if (ImGui::Button("Dismiss##error")) if (ImGui::Button("Dismiss##error"))
m_error_message.clear(); m_error_message.clear();
ImGui::PopStyleColor(3);
}
ImGui::EndChild();
ImGui::PopStyleVar(2);
ImGui::PopStyleColor(2);
} }
} }

View File

@@ -102,13 +102,13 @@ void template_editor::apply_current_palette(const clrsync::core::palette &pal)
m_editor.SetPalette(palette); m_editor.SetPalette(palette);
m_autocomplete_bg_color = palette_utils::get_color(pal, "editor_background", "background"); m_autocomplete_bg_color = palette_utils::get_color(pal, "surface", "background");
m_autocomplete_bg_color.w = 0.98f; m_autocomplete_bg_color.w = 0.98f;
m_autocomplete_border_color = palette_utils::get_color(pal, "border", "editor_inactive"); m_autocomplete_border_color = palette_utils::get_color(pal, "border", "surface_variant");
m_autocomplete_selected_color = palette_utils::get_color(pal, "editor_selected", "surface_variant"); m_autocomplete_selected_color = palette_utils::get_color(pal, "accent", "surface_variant");
m_autocomplete_text_color = palette_utils::get_color(pal, "editor_main", "foreground"); m_autocomplete_text_color = palette_utils::get_color(pal, "on_surface", "foreground");
m_autocomplete_selected_text_color = palette_utils::get_color(pal, "foreground", "editor_main"); m_autocomplete_selected_text_color = palette_utils::get_color(pal, "on_surface", "foreground");
m_autocomplete_dim_text_color = palette_utils::get_color(pal, "editor_comment", "editor_inactive"); m_autocomplete_dim_text_color = palette_utils::get_color(pal, "on_surface_variant", "editor_inactive");
} }
void template_editor::update_autocomplete_suggestions() void template_editor::update_autocomplete_suggestions()
@@ -433,20 +433,20 @@ void template_editor::render_controls()
if (m_enabled) if (m_enabled)
{ {
ImVec4 success_color = palette_utils::get_color(m_current_palette, "success", "accent"); ImVec4 success_color = palette_utils::get_color(m_current_palette, "success", "accent");
ImVec4 success_on_color = palette_utils::get_color(m_current_palette, "on_success", "on_surface");
ImVec4 success_hover = ImVec4(success_color.x * 1.2f, success_color.y * 1.2f, success_color.z * 1.2f, 0.6f); ImVec4 success_hover = ImVec4(success_color.x * 1.2f, success_color.y * 1.2f, success_color.z * 1.2f, 0.6f);
ImVec4 success_check = ImVec4(success_color.x * 1.5f, success_color.y * 1.5f, success_color.z * 1.5f, 1.0f);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(success_color.x, success_color.y, success_color.z, 0.5f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(success_color.x, success_color.y, success_color.z, 0.5f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, success_hover); ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, success_hover);
ImGui::PushStyleColor(ImGuiCol_CheckMark, success_check); ImGui::PushStyleColor(ImGuiCol_CheckMark, success_on_color);
} }
else else
{ {
ImVec4 error_color = palette_utils::get_color(m_current_palette, "error", "accent"); ImVec4 error_color = palette_utils::get_color(m_current_palette, "error", "accent");
ImVec4 error_on_color = palette_utils::get_color(m_current_palette, "on_error", "on_surface");
ImVec4 error_hover = ImVec4(error_color.x * 1.2f, error_color.y * 1.2f, error_color.z * 1.2f, 0.6f); ImVec4 error_hover = ImVec4(error_color.x * 1.2f, error_color.y * 1.2f, error_color.z * 1.2f, 0.6f);
ImVec4 error_check = ImVec4(error_color.x * 1.5f, error_color.y * 1.5f, error_color.z * 1.5f, 1.0f);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(error_color.x, error_color.y, error_color.z, 0.5f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(error_color.x, error_color.y, error_color.z, 0.5f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, error_hover); ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, error_hover);
ImGui::PushStyleColor(ImGuiCol_CheckMark, error_check); ImGui::PushStyleColor(ImGuiCol_CheckMark, error_on_color);
} }
enabled_changed = ImGui::Checkbox("Enabled", &m_enabled); enabled_changed = ImGui::Checkbox("Enabled", &m_enabled);
@@ -569,7 +569,8 @@ void template_editor::render_controls()
if (!m_validation_error.empty()) if (!m_validation_error.empty())
{ {
ImGui::Spacing(); ImGui::Spacing();
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f)); ImVec4 error_color = palette_utils::get_color(m_current_palette, "error", "accent");
ImGui::PushStyleColor(ImGuiCol_Text, error_color);
ImGui::TextWrapped("%s", m_validation_error.c_str()); ImGui::TextWrapped("%s", m_validation_error.c_str());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
} }
@@ -581,7 +582,8 @@ void template_editor::render_editor()
if (!m_is_editing_existing) if (!m_is_editing_existing)
{ {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.4f, 0.8f, 0.4f, 1.0f)); ImVec4 success_color = palette_utils::get_color(m_current_palette, "success", "accent");
ImGui::PushStyleColor(ImGuiCol_Text, success_color);
ImGui::Text(" New Template"); ImGui::Text(" New Template");
ImGui::PopStyleColor(); ImGui::PopStyleColor();
} }
@@ -600,35 +602,13 @@ void template_editor::render_editor()
if (m_has_unsaved_changes) if (m_has_unsaved_changes)
{ {
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.6f, 0.2f, 1.0f)); ImVec4 warning_color = palette_utils::get_color(m_current_palette, "warning", "accent");
ImGui::PushStyleColor(ImGuiCol_Text, warning_color);
ImGui::Text("(unsaved)"); ImGui::Text("(unsaved)");
ImGui::PopStyleColor(); ImGui::PopStyleColor();
} }
} }
ImGui::SameLine(ImGui::GetContentRegionAvail().x - 30);
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 25.0f);
ImGui::TextUnformatted("Template Syntax:");
ImGui::Separator();
ImGui::TextUnformatted("Use {color_key.format} for color variables");
ImGui::Spacing();
ImGui::TextUnformatted("Color Keys: background, foreground, accent, etc.");
ImGui::TextUnformatted("Formats: hex, rgb, rgba, r, g, b, hsl, hsla, etc.");
ImGui::Spacing();
ImGui::TextUnformatted("Examples:");
ImGui::BulletText("{background.hex} -> #1E1E1E");
ImGui::BulletText("{accent.rgb} -> rgb(14,99,156)");
ImGui::BulletText("{foreground.r} -> 204");
ImGui::Spacing();
ImGui::TextUnformatted("Tip: Type '{' to trigger autocomplete!");
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::Separator(); ImGui::Separator();
@@ -728,7 +708,8 @@ void template_editor::render_template_list()
if (!tmpl.enabled()) if (!tmpl.enabled())
{ {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 0.5f, 1.0f)); ImVec4 disabled_color = palette_utils::get_color(m_current_palette, "on_surface_variant", "editor_inactive");
ImGui::PushStyleColor(ImGuiCol_Text, disabled_color);
} }
if (ImGui::Selectable(key.c_str(), selected)) if (ImGui::Selectable(key.c_str(), selected))

View File

@@ -4,9 +4,8 @@
namespace theme_applier namespace theme_applier
{ {
void apply_to_editor(TextEditor& editor, const clrsync::core::palette& current) static uint32_t get_color_u32(const clrsync::core::palette& current, const std::string &key)
{ {
auto get_color_u32 = [&](const std::string &key) -> uint32_t {
const auto &col = current.get_color(key); const auto &col = current.get_color(key);
const uint32_t hex = col.hex(); const uint32_t hex = col.hex();
// Convert from RRGGBBAA to AABBGGRR (ImGui format) // Convert from RRGGBBAA to AABBGGRR (ImGui format)
@@ -15,36 +14,39 @@ void apply_to_editor(TextEditor& editor, const clrsync::core::palette& current)
const uint32_t b = (hex >> 8) & 0xFF; const uint32_t b = (hex >> 8) & 0xFF;
const uint32_t a = hex & 0xFF; const uint32_t a = hex & 0xFF;
return (a << 24) | (b << 16) | (g << 8) | r; return (a << 24) | (b << 16) | (g << 8) | r;
}; }
void apply_to_editor(TextEditor& editor, const clrsync::core::palette& current)
{
auto palette = editor.GetPalette(); auto palette = editor.GetPalette();
palette[int(TextEditor::PaletteIndex::Default)] = get_color_u32("editor_main"); palette[int(TextEditor::PaletteIndex::Default)] = get_color_u32(current, "editor_main");
palette[int(TextEditor::PaletteIndex::Keyword)] = get_color_u32("editor_command"); palette[int(TextEditor::PaletteIndex::Keyword)] = get_color_u32(current, "editor_command");
palette[int(TextEditor::PaletteIndex::Number)] = get_color_u32("editor_warning"); palette[int(TextEditor::PaletteIndex::Number)] = get_color_u32(current, "editor_warning");
palette[int(TextEditor::PaletteIndex::String)] = get_color_u32("editor_string"); palette[int(TextEditor::PaletteIndex::String)] = get_color_u32(current, "editor_string");
palette[int(TextEditor::PaletteIndex::CharLiteral)] = get_color_u32("editor_string"); palette[int(TextEditor::PaletteIndex::CharLiteral)] = get_color_u32(current, "editor_string");
palette[int(TextEditor::PaletteIndex::Punctuation)] = get_color_u32("editor_main"); palette[int(TextEditor::PaletteIndex::Punctuation)] = get_color_u32(current, "editor_main");
palette[int(TextEditor::PaletteIndex::Preprocessor)] = get_color_u32("editor_emphasis"); palette[int(TextEditor::PaletteIndex::Preprocessor)] = get_color_u32(current, "editor_emphasis");
palette[int(TextEditor::PaletteIndex::Identifier)] = get_color_u32("editor_main"); palette[int(TextEditor::PaletteIndex::Identifier)] = get_color_u32(current, "editor_main");
palette[int(TextEditor::PaletteIndex::KnownIdentifier)] = get_color_u32("editor_link"); palette[int(TextEditor::PaletteIndex::KnownIdentifier)] = get_color_u32(current, "editor_link");
palette[int(TextEditor::PaletteIndex::PreprocIdentifier)] = get_color_u32("editor_link"); palette[int(TextEditor::PaletteIndex::PreprocIdentifier)] = get_color_u32(current, "editor_link");
palette[int(TextEditor::PaletteIndex::Comment)] = get_color_u32("editor_comment"); palette[int(TextEditor::PaletteIndex::Comment)] = get_color_u32(current, "editor_comment");
palette[int(TextEditor::PaletteIndex::MultiLineComment)] = get_color_u32("editor_comment"); palette[int(TextEditor::PaletteIndex::MultiLineComment)] = get_color_u32(current, "editor_comment");
palette[int(TextEditor::PaletteIndex::Background)] = get_color_u32("editor_background"); palette[int(TextEditor::PaletteIndex::Background)] = get_color_u32(current, "editor_background");
palette[int(TextEditor::PaletteIndex::Cursor)] = get_color_u32("cursor"); palette[int(TextEditor::PaletteIndex::Cursor)] = get_color_u32(current, "cursor");
palette[int(TextEditor::PaletteIndex::Selection)] = get_color_u32("editor_selected"); palette[int(TextEditor::PaletteIndex::Selection)] = get_color_u32(current, "editor_selected");
palette[int(TextEditor::PaletteIndex::ErrorMarker)] = get_color_u32("editor_error"); palette[int(TextEditor::PaletteIndex::ErrorMarker)] = get_color_u32(current, "editor_error");
palette[int(TextEditor::PaletteIndex::Breakpoint)] = get_color_u32("editor_error"); palette[int(TextEditor::PaletteIndex::Breakpoint)] = get_color_u32(current, "editor_error");
palette[int(TextEditor::PaletteIndex::LineNumber)] = get_color_u32("editor_line_number"); palette[int(TextEditor::PaletteIndex::LineNumber)] = get_color_u32(current, "editor_line_number");
palette[int(TextEditor::PaletteIndex::CurrentLineFill)] = get_color_u32("surface_variant");
palette[int(TextEditor::PaletteIndex::CurrentLineFillInactive)] = get_color_u32("surface");
palette[int(TextEditor::PaletteIndex::CurrentLineEdge)] = get_color_u32("border_focused"); palette[int(TextEditor::PaletteIndex::CurrentLineFill)] = get_color_u32(current, "surface_variant");
palette[int(TextEditor::PaletteIndex::CurrentLineFillInactive)] = get_color_u32(current, "surface");
palette[int(TextEditor::PaletteIndex::CurrentLineEdge)] = get_color_u32(current, "border_focused");
editor.SetPalette(palette); editor.SetPalette(palette);
} }
@@ -61,13 +63,25 @@ void apply_to_imgui(const clrsync::core::palette& current)
ImGuiStyle &style = ImGui::GetStyle(); ImGuiStyle &style = ImGui::GetStyle();
const ImVec4 bg = getColor("background"); const ImVec4 bg = getColor("background");
const ImVec4 onBg = getColor("on_background");
const ImVec4 surface = getColor("surface"); const ImVec4 surface = getColor("surface");
const ImVec4 onSurface = getColor("on_surface");
const ImVec4 surfaceVariant = getColor("surface_variant"); const ImVec4 surfaceVariant = getColor("surface_variant");
const ImVec4 onSurfaceVariant = getColor("on_surface_variant");
const ImVec4 fg = getColor("foreground"); const ImVec4 fg = getColor("foreground");
const ImVec4 fgInactive = getColor("editor_inactive"); const ImVec4 fgInactive = getColor("editor_inactive");
const ImVec4 accent = getColor("accent"); const ImVec4 accent = getColor("accent");
const ImVec4 border = getColor("border"); const ImVec4 border = getColor("border");
const ImVec4 error = getColor("error");
const ImVec4 onError = getColor("on_error");
const ImVec4 success = getColor("success");
const ImVec4 onSuccess = getColor("on_success");
const ImVec4 warning = getColor("warning");
const ImVec4 onWarning = getColor("on_warning");
const ImVec4 info = getColor("info");
const ImVec4 onInfo = getColor("on_info");
style.Colors[ImGuiCol_WindowBg] = bg; style.Colors[ImGuiCol_WindowBg] = bg;
style.Colors[ImGuiCol_ChildBg] = surface; style.Colors[ImGuiCol_ChildBg] = surface;
style.Colors[ImGuiCol_PopupBg] = surface; style.Colors[ImGuiCol_PopupBg] = surface;
@@ -75,8 +89,9 @@ void apply_to_imgui(const clrsync::core::palette& current)
style.Colors[ImGuiCol_Border] = border; style.Colors[ImGuiCol_Border] = border;
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0, 0, 0, 0); style.Colors[ImGuiCol_BorderShadow] = ImVec4(0, 0, 0, 0);
style.Colors[ImGuiCol_Text] = fg; style.Colors[ImGuiCol_Text] = onSurface;
style.Colors[ImGuiCol_TextDisabled] = fgInactive; style.Colors[ImGuiCol_TextDisabled] = onSurfaceVariant;
style.Colors[ImGuiCol_TextSelectedBg] = accent;
style.Colors[ImGuiCol_Header] = surfaceVariant; style.Colors[ImGuiCol_Header] = surfaceVariant;
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(accent.x, accent.y, accent.z, 0.8f); style.Colors[ImGuiCol_HeaderHovered] = ImVec4(accent.x, accent.y, accent.z, 0.8f);
@@ -123,7 +138,7 @@ void apply_to_imgui(const clrsync::core::palette& current)
ImVec4(border.x * 0.7f, border.y * 0.7f, border.z * 0.7f, border.w); ImVec4(border.x * 0.7f, border.y * 0.7f, border.z * 0.7f, border.w);
style.Colors[ImGuiCol_TableRowBg] = ImVec4(0, 0, 0, 0); style.Colors[ImGuiCol_TableRowBg] = ImVec4(0, 0, 0, 0);
style.Colors[ImGuiCol_TableRowBgAlt] = ImVec4(fg.x, fg.y, fg.z, 0.06f); style.Colors[ImGuiCol_TableRowBgAlt] = ImVec4(onSurfaceVariant.x, onSurfaceVariant.y, onSurfaceVariant.z, 0.06f);
style.Colors[ImGuiCol_Separator] = border; style.Colors[ImGuiCol_Separator] = border;
style.Colors[ImGuiCol_SeparatorHovered] = accent; style.Colors[ImGuiCol_SeparatorHovered] = accent;