├── .dockerignore ├── .gitignore ├── .gitlab-ci.yml ├── ColorHighlighter.sublime-settings ├── ColorPicker ├── ColorPicker_linux_x32 ├── ColorPicker_linux_x64 ├── ColorPicker_osx_x64 ├── ColorPicker_win.exe ├── colorPickOsx │ ├── .gitignore │ ├── Makefile │ ├── README.md │ └── colorpick.m ├── qt │ ├── ColorPicker.pro │ └── main.cpp └── winapi │ ├── Cyotek.Windows.Forms.ColorPicker.sln │ ├── Cyotek.Windows.Forms.ColorPicker │ ├── AdobePhotoShopColorSwatchSerializer.cs │ ├── AdobePhotoshopColorSwatchColorSpace.cs │ ├── AdobePhotoshopColorSwatchFileVersion.cs │ ├── ColorBarStyle.cs │ ├── ColorCellBorderStyle.cs │ ├── ColorCollection.cs │ ├── ColorCollectionEventArgs.cs │ ├── ColorCollectionSortOrder.cs │ ├── ColorComparer.cs │ ├── ColorEditingMode.cs │ ├── ColorEditor.Designer.cs │ ├── ColorEditor.cs │ ├── ColorEditor.resx │ ├── ColorEditorManager.cs │ ├── ColorGrid.cs │ ├── ColorGridSelectedCellStyle.cs │ ├── ColorHitTestInfo.cs │ ├── ColorPalette.cs │ ├── ColorPalettes.cs │ ├── ColorPickerDialog.Designer.cs │ ├── ColorPickerDialog.cs │ ├── ColorPickerDialog.resx │ ├── ColorSlider.cs │ ├── ColorSliderNubStyle.cs │ ├── ColorSource.cs │ ├── ColorWheel.cs │ ├── Cyotek.Windows.Forms.ColorPicker.csproj │ ├── Cyotek.Windows.Forms.ColorPicker.ncrunchproject │ ├── Cyotek.Windows.Forms.ColorPicker.v2.ncrunchproject │ ├── EditColorCancelEventArgs.cs │ ├── EditColorEventArgs.cs │ ├── GimpPaletteSerializer.cs │ ├── HslColor.cs │ ├── HsvColor.cs │ ├── HueColorSlider.cs │ ├── IColorEditor.cs │ ├── IPaletteSerializer.cs │ ├── InterleavedBitmapPaletteSerializer.cs │ ├── JascPaletteSerializer.cs │ ├── LightnessColorSlider.cs │ ├── NativeMethods.cs │ ├── NavigationOrigin.cs │ ├── PaintNetPaletteSerializer.cs │ ├── PaletteSerializer.cs │ ├── Program.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── RawPaletteSerializer.cs │ ├── Resources │ │ ├── cellbackground.png │ │ ├── eyedropper.cur │ │ ├── eyedropper.png │ │ ├── palette-load.png │ │ └── palette-save.png │ ├── RgbaChannel.cs │ ├── RgbaColorSlider.cs │ ├── SaturationColorSlider.cs │ ├── ScreenColorPicker.cs │ └── cyopublic.snk │ └── Sample-Palettes │ ├── Hex256.pal │ ├── PaintNet.txt │ ├── arne-v20-16.aco │ ├── arnev-20-16.pal │ ├── atari-800xl-palette.pal │ ├── background.lbm │ ├── background.pal │ ├── db16.gpl │ ├── db32.gpl │ └── grayscale.pal ├── Context.sublime-menu ├── Default (OSX).sublime-keymap ├── Default.sublime-keymap ├── Main.sublime-menu ├── README.md ├── ci ├── Dockerfile ├── integration-tests.sh ├── run-container.sh ├── run-integration-test.sh ├── run-integration-tests.sh ├── run-linters.sh └── test-python.sh ├── color_converter.py ├── color_highlighter.py ├── color_hover_listener.py ├── color_scheme.py ├── color_scheme_color_highlighter.py ├── color_searcher.py ├── color_selection_listener.py ├── colors.py ├── content_listener.py ├── convert_color_command.py ├── css_colors.py ├── docs ├── src │ └── index.md └── theme │ ├── extra.css │ └── partials │ └── footer.html ├── dummy_event_listener.py ├── elementtree ├── ElementPath.py ├── ElementTree.py ├── SimpleXMLTreeBuilder.py └── __init__.py ├── gutter_icons_color_highlighter.py ├── integration_tests ├── ColorHighlighter.ss ├── check-exceptions.sh ├── empty.css ├── st2 │ ├── empty.expected.log │ ├── test-empty.sh │ ├── test-white.sh │ └── white.expected.log ├── st3 │ ├── empty.expected.log │ ├── test-empty.sh │ ├── test-white.sh │ └── white.expected.log └── white.css ├── load_resource.py ├── main.py ├── messages.json ├── messages └── install.txt ├── mkdocs.yml ├── path.py ├── phantoms_color_highlighter.py ├── pick_color_command.py ├── regex_compiler.py ├── regions.py ├── set_setting_command.py ├── settings.py ├── st_helper.py ├── test_plugin ├── __init__.py ├── flushing_file.py ├── main.py └── test_flushing_file.py ├── tests ├── __init__.py ├── run_tests.sh ├── sublime.py ├── sublime_plugin.py ├── test_color_highlighter.py ├── test_color_scheme.py ├── test_color_scheme_color_highlighter.py ├── test_color_searcher.py ├── test_color_selection_listener.py ├── test_colors.py ├── test_gutter_icons_color_highlighter.py ├── test_icon_factory.py ├── test_load_resource.py ├── test_normalized_region.py ├── test_path.py ├── test_phantom_color_highlighter.py ├── test_regions.py └── test_settings.py └── topsort.py /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .cache/ 3 | *.pyc 4 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build-container 3 | - test 4 | - cleanup 5 | 6 | variables: 7 | TEST_IMAGE_NAME: gxservers.com:5500/${CI_PROJECT_PATH}:${CI_BUILD_REF_NAME} 8 | TEST_CONTAINER_NAME: ${CI_PROJECT_NAME}--${CI_BUILD_REF_NAME} 9 | TIMEOUT: 2h 10 | 11 | build-container: 12 | stage: build-container 13 | script: 14 | - echo CI image name ${TEST_IMAGE_NAME} 15 | - docker build -f ci/Dockerfile -t ${TEST_IMAGE_NAME} --build-arg LINTER_TOKEN=${PRIVATE_LINTER_TOKEN} ./ 16 | - docker rm -f ${TEST_CONTAINER_NAME} || true 17 | - ci/run-container.sh --image ${TEST_IMAGE_NAME} --name ${TEST_CONTAINER_NAME} --timeout ${TIMEOUT} 18 | 19 | lint: 20 | stage: test 21 | script: 22 | - ci/run-linters.sh --container ${TEST_CONTAINER_NAME} 23 | 24 | test: 25 | stage: test 26 | script: 27 | - docker exec -i ${TEST_CONTAINER_NAME} ci/test-python.sh 28 | 29 | integration-test: 30 | stage: test 31 | script: 32 | - docker exec -i ${TEST_CONTAINER_NAME} ci/integration-tests.sh 33 | 34 | cleanup: 35 | stage: cleanup 36 | script: 37 | - docker stop ${TEST_CONTAINER_NAME} 38 | -------------------------------------------------------------------------------- /ColorHighlighter.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "search_colors_in": { 3 | "selection": { 4 | "enabled": true, 5 | "color_highlighters": { 6 | "color_scheme": { 7 | "enabled": false, 8 | "highlight_style": "filled" 9 | }, 10 | "gutter_icons": { 11 | "enabled": false, 12 | "icon_style": "circle" 13 | }, 14 | "phantoms": { 15 | "enabled": true, 16 | "style": "right", 17 | "length": 2 18 | } 19 | } 20 | }, 21 | "all_content": { 22 | "enabled": true, 23 | "color_highlighters": { 24 | "color_scheme": { 25 | "enabled": true, 26 | "highlight_style": "text" 27 | }, 28 | "gutter_icons": { 29 | "enabled": true, 30 | "icon_style": "circle" 31 | }, 32 | "phantoms": { 33 | "enabled": false, 34 | "style": "right", 35 | "length": 2 36 | } 37 | } 38 | }, 39 | "hover": { 40 | "enabled": true, 41 | "color_highlighters": { 42 | "color_scheme": { 43 | "enabled": false, 44 | "highlight_style": "filled" 45 | }, 46 | "gutter_icons": { 47 | "enabled": false, 48 | "icon_style": "circle" 49 | }, 50 | "phantoms": { 51 | "enabled": false, 52 | "style": "right", 53 | "length": 2 54 | } 55 | } 56 | } 57 | }, 58 | "default_keybindings": true, 59 | "file_extensions": [".css", ".less", ".scss", ".sass", ".styl"], 60 | "icon_factory": { 61 | "convert_command": "convert", 62 | "convert_timeout": 5 63 | }, 64 | "autoreload": { 65 | "when_settings_change": true, 66 | "when_color_scheme_change": true 67 | }, 68 | "regex_compiler": { 69 | "channels": { 70 | "hex": "[0-9a-fA-F]", 71 | "dec": "\\d{1,3}", 72 | "float": "(?:[0|1])|(?:[1][\\.]?[0]*)|(?:[0]?[\\.]\\d*)", 73 | "perc": "(?:\\d{1,3}[%])|(?:0)" 74 | }, 75 | "formats": { 76 | "sharp8": { 77 | "description": "Hex #RRGGBBAA color format", 78 | "regex": "#[0-9a-fA-F]{8}", 79 | "white": "#FFFFFFFF" 80 | }, 81 | "sharp6": { 82 | "description": "Hex #RRGGBBAA color format", 83 | "regex": "#[0-9a-fA-F]{6}", 84 | "white": "#FFFFFF", 85 | "after": "sharp8" 86 | }, 87 | "sharp4": { 88 | "description": "Hex #RGBA color format", 89 | "regex": "#(?Phex)(?Phex)(?Phex)(?Phex)", 90 | "white": "#FFFF", 91 | "after": "sharp6" 92 | }, 93 | "sharp3": { 94 | "description": "Hex #RGB color format", 95 | "regex": "#(?Phex)(?Phex)(?Phex)", 96 | "white": "#FFF", 97 | "after": "sharp4" 98 | }, 99 | "rgba": { 100 | "description": "rgba(255,255,100%,1) color format", 101 | "regex": "rgba[(][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pfloat)[ ]*[)]", 102 | "white": "rgba(255, 255, 100%, 1)" 103 | }, 104 | "rgb": { 105 | "description": "rgb(255,255,100%) color format", 106 | "regex": "rgb[(][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pdec|perc)[ ]*[)]", 107 | "white": "rgb(255, 255, 100%)" 108 | }, 109 | "hsva": { 110 | "description": "hsva(hue 0..360, s%, v%, alpha 0.0 .. 1.0) color format", 111 | "regex": "hsva[(][ ]*(?Pdec)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pfloat)[ ]*[)]", 112 | "white": "hsva(0, 0%, 100%, 1.)" 113 | }, 114 | "hsv": { 115 | "description": "hsv(hue 0..360, s%, v%) color format", 116 | "regex": "hsv[(][ ]*(?Pdec)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pperc)[ ]*[)]", 117 | "white": "hsv(0, 0%, 100%)" 118 | }, 119 | "hsla": { 120 | "description": "hsla(hue 0..360, s%, v%, alpha 0.0 .. 1.0) color format", 121 | "regex": "hsla[(][ ]*(?Pdec)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pfloat)[ ]*[)]", 122 | "white": "hsla(0, 0%, 100%, 1.)" 123 | }, 124 | "hsl": { 125 | "description": "hsl(hue 0..360, s%, v%) color format", 126 | "regex": "hsl[(][ ]*(?Pdec)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pperc)[ ]*[)]", 127 | "white": "hsl(0, 0%, 100%)" 128 | } 129 | } 130 | }, 131 | "experimental": { 132 | "asynchronosly_update_color_scheme": false 133 | }, 134 | "debug": false 135 | } 136 | -------------------------------------------------------------------------------- /ColorPicker/ColorPicker_linux_x32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/ColorPicker_linux_x32 -------------------------------------------------------------------------------- /ColorPicker/ColorPicker_linux_x64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/ColorPicker_linux_x64 -------------------------------------------------------------------------------- /ColorPicker/ColorPicker_osx_x64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/ColorPicker_osx_x64 -------------------------------------------------------------------------------- /ColorPicker/ColorPicker_win.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/ColorPicker_win.exe -------------------------------------------------------------------------------- /ColorPicker/colorPickOsx/.gitignore: -------------------------------------------------------------------------------- 1 | colorpick 2 | -------------------------------------------------------------------------------- /ColorPicker/colorPickOsx/Makefile: -------------------------------------------------------------------------------- 1 | 2 | color-pick: 3 | gcc -arch i386 -arch x86_64 -Wall -O3 -x objective-c -fobjc-exceptions -framework Foundation -framework AppKit -o colorpick colorpick.m 4 | 5 | install: 6 | cp colorpick /usr/local/bin/ 7 | 8 | clean: 9 | rm colorpick 10 | -------------------------------------------------------------------------------- /ColorPicker/colorPickOsx/README.md: -------------------------------------------------------------------------------- 1 | 2 | # color-pick 3 | 4 | Command line wrapper around OS X built in color picker. 5 | 6 | ## usages 7 | 8 | `colorpick` 9 | 10 | `colorpick -startColor ffff00ff -mode 3` 11 | 12 | `colorpick ffff00ff` 13 | 14 | `colorpick #ffff00ff` 15 | 16 | 17 | Writes color in hex format to stdout: 18 | 19 | `#ffff00ff` 20 | 21 | On cancel / exit, nothing is written to stdout 22 | 23 | 24 | Avalible modes: 25 | 26 | NSGrayModeColorPanel = 0 27 | NSRGBModeColorPanel = 1 28 | NSCMYKModeColorPanel = 2 29 | NSHSBModeColorPanel = 3 30 | NSCustomPaletteModeColorPanel = 4 31 | NSColorListModeColorPanel = 5 32 | NSWheelModeColorPanel = 6 33 | NSCrayonModeColorPanel = 7 34 | 35 | ## wishlist 36 | 37 | * Different formats (rgb, rgba, hsl) 38 | -------------------------------------------------------------------------------- /ColorPicker/colorPickOsx/colorpick.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // color-pick 4 | // 5 | // Created by Johan Nordberg on 2011-09-20. 6 | // Copyright 2011 FFFF00 Agents AB. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NSColor (Additions) 13 | +(NSColor *)colorFromString:(NSString *)colorRepresentation; 14 | 15 | -(NSString *)toHexString; 16 | 17 | @end 18 | 19 | 20 | @implementation NSColor (Additions) 21 | +(NSColor *)colorFromString:(NSString *)colorRepresentation { 22 | 23 | if([colorRepresentation length] != 8) 24 | return [NSColor whiteColor]; 25 | 26 | NSString* rString = [colorRepresentation substringWithRange:NSMakeRange(0, 2)]; 27 | NSString* gString = [colorRepresentation substringWithRange:NSMakeRange(2, 2)]; 28 | NSString* bString = [colorRepresentation substringWithRange:NSMakeRange(4, 2)]; 29 | NSString* aString = [colorRepresentation substringWithRange:NSMakeRange(6, 2)]; 30 | 31 | return [NSColor colorWithCalibratedRed: strtol([rString UTF8String], NULL, 16) / 255.0 32 | green: strtol([gString UTF8String], NULL, 16) / 255.0 33 | blue: strtol([bString UTF8String], NULL, 16) / 255.0 34 | alpha: strtol([aString UTF8String], NULL, 16) / 255.0]; 35 | } 36 | 37 | -(NSString *)toHexString { 38 | NSColor *color = [self colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; 39 | 40 | return [NSString stringWithFormat: @"#%02X%02X%02X%02X", 41 | (unsigned int)(255 * [color redComponent]), 42 | (unsigned int)(255 * [color greenComponent]), 43 | (unsigned int)(255 * [color blueComponent]), 44 | (unsigned int)(255 * [color alphaComponent])]; 45 | } 46 | 47 | @end 48 | 49 | 50 | @interface Picker : NSObject { 51 | NSColorPanel *panel; // weak ref 52 | } 53 | 54 | - (void)show; 55 | - (void)writeColor; 56 | - (void)exit; 57 | 58 | @end 59 | 60 | @implementation Picker 61 | 62 | - (void)show { 63 | // setup panel and its accessory view 64 | 65 | NSView *accessoryView = [[NSView alloc] initWithFrame:(NSRect){{0, 0}, {220, 30}}]; 66 | 67 | NSButton *button = [[NSButton alloc] initWithFrame:(NSRect){{110, 4}, {110 - 8, 24}}]; 68 | [button setButtonType:NSMomentaryPushInButton]; 69 | [button setBezelStyle:NSRoundedBezelStyle]; 70 | button.title = @"Pick"; 71 | button.action = @selector(writeColor); 72 | button.target = self; 73 | 74 | NSButton *cancelButton = [[NSButton alloc] initWithFrame:(NSRect){{8, 4}, {110 - 8, 24}}]; 75 | [cancelButton setButtonType:NSMomentaryPushInButton]; 76 | [cancelButton setBezelStyle:NSRoundedBezelStyle]; 77 | cancelButton.title = @"Cancel"; 78 | cancelButton.action = @selector(exit); 79 | cancelButton.target = self; 80 | 81 | [accessoryView addSubview:[button autorelease]]; 82 | [accessoryView addSubview:[cancelButton autorelease]]; 83 | 84 | panel = [NSColorPanel sharedColorPanel]; 85 | [panel setDelegate:self]; 86 | [panel setShowsAlpha:YES]; // TODO: support for rgba() output values 87 | [panel setAccessoryView:[accessoryView autorelease]]; 88 | [panel setDefaultButtonCell:[button cell]]; 89 | 90 | // load user settings 91 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 92 | NSString *color = [defaults stringForKey:@"startColor"]; 93 | if (color != nil) { 94 | [panel setColor:[NSColor colorFromString:color]]; 95 | } 96 | [panel setMode:[defaults integerForKey:@"mode"]]; // will be 0 if not set, wich is NSGrayModeColorPanel 97 | 98 | // show panel 99 | [panel makeKeyAndOrderFront:self]; 100 | //[NSApp runModalForWindow:panel]; // resets panel position 101 | } 102 | 103 | - (void)writeColor { 104 | NSString *hex = [panel.color toHexString]; 105 | 106 | // save color and current mode to defaults 107 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 108 | [defaults setObject:hex forKey:@"startColor"]; 109 | [defaults setInteger:panel.mode forKey:@"mode"]; 110 | [defaults synchronize]; // force a save since we are exiting 111 | 112 | // write color to stdout 113 | NSFileHandle *stdOut = [NSFileHandle fileHandleWithStandardOutput]; 114 | [stdOut writeData:[hex dataUsingEncoding:NSASCIIStringEncoding]]; 115 | 116 | [self exit]; 117 | } 118 | 119 | 120 | - (void)exit { 121 | [panel close]; 122 | } 123 | 124 | // panel delegate methods 125 | 126 | - (void)windowWillClose:(NSNotification *)notification { 127 | [NSApp terminate:self]; 128 | } 129 | 130 | // application delegate methods 131 | 132 | - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { 133 | ProcessSerialNumber psn = {0, kCurrentProcess}; 134 | TransformProcessType(&psn, kProcessTransformToForegroundApplication); 135 | SetFrontProcess(&psn); 136 | [self show]; 137 | } 138 | 139 | - (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) theApplication { 140 | return YES; 141 | } 142 | 143 | @end 144 | 145 | int main (int argc, const char * argv[]) { 146 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 147 | 148 | if(argc == 2){ 149 | NSString* color = [NSString stringWithUTF8String:argv[1]]; 150 | NSString* colorWithoutHash = [color stringByReplacingOccurrencesOfString:@"#" 151 | withString:@""]; 152 | [[NSUserDefaults standardUserDefaults] setObject:colorWithoutHash forKey:@"startColor"]; 153 | [[NSUserDefaults standardUserDefaults] synchronize]; 154 | } 155 | 156 | NSApplication *app = [NSApplication sharedApplication]; 157 | app.delegate = [[[Picker alloc] init] autorelease]; 158 | [app run]; 159 | [pool drain]; 160 | return 0; 161 | } 162 | -------------------------------------------------------------------------------- /ColorPicker/qt/ColorPicker.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Qt Creator / qmake Project 4 | # Compiled 2014-10-05T12:05:00 5 | # 6 | #------------------------------------------------- 7 | 8 | TARGET = ColorPicker 9 | TEMPLATE = app 10 | LANGUAGE = c++ 11 | 12 | SOURCES += main.cpp 13 | HEADERS += 14 | FORMS += 15 | 16 | CONFIG += static c++11 warn_on 17 | 18 | QT += core gui 19 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 20 | 21 | QMAKE_CXXFLAGS += -s -fvisibility=hidden -fomit-frame-pointer -march=nocona -Os 22 | QMAKE_LFLAGS += -s -fvisibility=hidden -dead_strip 23 | 24 | macx { 25 | CONFIG -= app_bundle 26 | CONFIG += x86_64 27 | 28 | QMAKE_MAC_PLATFORM_NAME = macosx 29 | QMAKE_MAC_SDK = macosx 30 | QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 31 | 32 | greaterThan(QT_VERSION, 5.3.0) { 33 | message("Remove new default plugins in QT>5.3.0: 'imageformats', 'accessible', and only 'cocoa' portion of 'platforms'.") 34 | QTPLUGIN.platforms = qcocoa 35 | QTPLUGIN.accessible = - 36 | QTPLUGIN.imageformats = - 37 | } 38 | 39 | system(which g++-4.9) { 40 | message("Compiling with Homebrew-built GCC 4.9 instead of Apple-built Clang.") 41 | QMAKE_PLATFORM = macx-g++ 42 | QMAKE_COMPILER = g++-4.9 43 | QMAKE_CXX = g++-4.9 44 | QMAKE_CXXFLAGS += -mmacosx-version-min=$$QMAKE_MACOSX_DEPLOYMENT_TARGET 45 | QMAKE_CXXFLAGS_CXX11 = -std=c++11 46 | 47 | message("Linking with Apple-built Clang.") 48 | QMAKE_LINK = g++ 49 | QMAKE_LFLAGS += -mmacosx-version-min=$$QMAKE_MACOSX_DEPLOYMENT_TARGET 50 | QMAKE_LFLAGS_CXX11 = -lc++ 51 | } else { 52 | message("Compiling with Apple-built GCC or Clang, depending on your OS version.") 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ColorPicker/qt/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | 10 | int main(int argc, char *argv[]) { 11 | QString input(argc > 1 ? QString("#") + argv[1] : QString("#000000FF")); 12 | 13 | QString col = input.left(7); 14 | QString al = input.right(2); 15 | 16 | bool ok = false; 17 | uint alpha = ("0x" + al).toUInt(&ok, 16); 18 | if(!ok) 19 | return 1; 20 | 21 | QColor color(col); 22 | color.setAlpha(alpha); 23 | 24 | QApplication a(argc, argv); 25 | 26 | bool selected = false; 27 | QColor result; 28 | QColorDialog colorDialog(color); 29 | colorDialog.setOptions(QColorDialog::ShowAlphaChannel); 30 | QObject::connect(&colorDialog, &QColorDialog::colorSelected, [&] (const QColor& col) { 31 | selected = true; 32 | result = col; 33 | }); 34 | colorDialog.show(); 35 | 36 | const int rc = a.exec(); 37 | 38 | if(!selected) 39 | printf("CANCEL"); 40 | else { 41 | QString hexAlpha; 42 | hexAlpha.setNum(result.alpha(), 16); 43 | if(hexAlpha.length() == 1) 44 | hexAlpha = "0" + hexAlpha; 45 | printf("%s%s", result.name().toUpper().toUtf8().constData(), hexAlpha.toUpper().toUtf8().constData()); 46 | } 47 | 48 | return rc; 49 | } 50 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | # SharpDevelop 5.1 5 | VisualStudioVersion = 12.0.31101.0 6 | MinimumVisualStudioVersion = 10.0.40219.1 7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cyotek.Windows.Forms.ColorPicker", "Cyotek.Windows.Forms.ColorPicker\Cyotek.Windows.Forms.ColorPicker.csproj", "{FB2A5786-CD2E-42CE-BC5D-0FCE90034221}" 8 | EndProject 9 | Global 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | Debug|Any CPU = Debug|Any CPU 12 | Release|Any CPU = Release|Any CPU 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {FB2A5786-CD2E-42CE-BC5D-0FCE90034221}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 16 | {FB2A5786-CD2E-42CE-BC5D-0FCE90034221}.Debug|Any CPU.Build.0 = Debug|Any CPU 17 | {FB2A5786-CD2E-42CE-BC5D-0FCE90034221}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {FB2A5786-CD2E-42CE-BC5D-0FCE90034221}.Release|Any CPU.Build.0 = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(SolutionProperties) = preSolution 21 | HideSolutionNode = FALSE 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/AdobePhotoshopColorSwatchColorSpace.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | /// 12 | /// Specifies the color space of an Adobe Photoshop color swatch file 13 | /// 14 | public enum AdobePhotoshopColorSwatchColorSpace 15 | { 16 | /// 17 | /// RGB 18 | /// 19 | Rgb = 0, 20 | 21 | /// 22 | /// HSB 23 | /// 24 | Hsb = 1, 25 | 26 | /// 27 | /// CMYK 28 | /// 29 | Cmyk = 2, 30 | 31 | /// 32 | /// Lab 33 | /// 34 | Lab = 7, 35 | 36 | /// 37 | /// Grayscale 38 | /// 39 | Grayscale = 8 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/AdobePhotoshopColorSwatchFileVersion.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | /// 12 | /// Specifies the version of a Abode Photoshop color swatch file 13 | /// 14 | public enum AdobePhotoshopColorSwatchFileVersion 15 | { 16 | /// 17 | /// Version 1 18 | /// 19 | Version1 = 1, 20 | 21 | /// 22 | /// Version 2 23 | /// 24 | Version2 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorBarStyle.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | /// 12 | /// Specifies the style of a color bar 13 | /// 14 | public enum ColorBarStyle 15 | { 16 | /// 17 | /// A gradient from one color to another. 18 | /// 19 | TwoColor, 20 | 21 | /// 22 | /// A gradient between three colors. 23 | /// 24 | ThreeColor, 25 | 26 | /// 27 | /// A gadient between a user defined number of colors. 28 | /// 29 | Custom 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorCellBorderStyle.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | /// 12 | /// Specifies the style of a color cell border. 13 | /// 14 | public enum ColorCellBorderStyle 15 | { 16 | /// 17 | /// No border. 18 | /// 19 | None, 20 | 21 | /// 22 | /// A single line border. 23 | /// 24 | FixedSingle, 25 | 26 | /// 27 | /// A contrasting double border with a soft inner outline using the color of the cell. 28 | /// 29 | DoubleSoft 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorCollectionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace Cyotek.Windows.Forms 5 | { 6 | // Cyotek Color Picker controls library 7 | // Copyright © 2013-2015 Cyotek Ltd. 8 | // http://cyotek.com/blog/tag/colorpicker 9 | 10 | // Licensed under the MIT License. See license.txt for the full text. 11 | 12 | // If you use this code in your applications, donations or attribution are welcome 13 | 14 | /// Provides data for the event of a instance. 15 | public class ColorCollectionEventArgs : EventArgs 16 | { 17 | #region Public Constructors 18 | 19 | /// 20 | /// Initializes a new instance of the class for the specified color. 21 | /// 22 | /// The color index that the event is responding to. 23 | /// The %Color% that the event is responding to. 24 | public ColorCollectionEventArgs(int index, Color color) 25 | { 26 | this.Index = index; 27 | this.Color = color; 28 | } 29 | 30 | #endregion 31 | 32 | #region Protected Constructors 33 | 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | protected ColorCollectionEventArgs() 38 | { } 39 | 40 | #endregion 41 | 42 | #region Public Properties 43 | 44 | /// 45 | /// Gets the color that raised the event. 46 | /// 47 | /// The color that raised the event. 48 | public Color Color { get; protected set; } 49 | 50 | /// 51 | /// Gets the color index that raised the event. 52 | /// 53 | /// The color index that raised the event. 54 | public int Index { get; protected set; } 55 | 56 | #endregion 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorCollectionSortOrder.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | /// 12 | /// Specifies the sort order of colors 13 | /// 14 | public enum ColorCollectionSortOrder 15 | { 16 | /// 17 | /// Ordered by hue. 18 | /// 19 | Hue, 20 | 21 | /// 22 | /// Ordered by brightness. 23 | /// 24 | Brightness, 25 | 26 | /// 27 | /// Ordered by value 28 | /// 29 | Value 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorComparer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace Cyotek.Windows.Forms 5 | { 6 | // Cyotek Color Picker controls library 7 | // Copyright © 2013-2015 Cyotek Ltd. 8 | // http://cyotek.com/blog/tag/colorpicker 9 | 10 | // Licensed under the MIT License. See license.txt for the full text. 11 | 12 | // If you use this code in your applications, donations or attribution are welcome 13 | 14 | /// 15 | /// Provides access to color comparison operations. 16 | /// 17 | public static class ColorComparer 18 | { 19 | #region Constants 20 | 21 | private const double RedLuminance = 0.212655; 22 | 23 | private const double GreenLuminance = 0.715158; 24 | 25 | private const double BlueLuminance = 0.072187; 26 | 27 | #endregion 28 | 29 | #region Public Class Members 30 | 31 | /// 32 | /// Compares two colors by brightness and returns an indication of their relative sort order. 33 | /// 34 | /// A color to compare to y. 35 | /// A color to compare to x. 36 | public static int Brightness(Color x, Color y) 37 | { 38 | int v1; 39 | int v2; 40 | int result; 41 | 42 | v1 = GetBrightness(x); 43 | v2 = GetBrightness(y); 44 | 45 | if (v1 < v2) 46 | { 47 | result = -1; 48 | } 49 | else if (v1 > v2) 50 | { 51 | result = 1; 52 | } 53 | else 54 | { 55 | result = 0; 56 | } 57 | 58 | return result; 59 | } 60 | 61 | /// 62 | /// Compares two colors by hue and returns an indication of their relative sort order. 63 | /// 64 | /// A color to compare to y. 65 | /// A color to compare to x. 66 | public static int Hue(Color x, Color y) 67 | { 68 | float v1; 69 | float v2; 70 | int result; 71 | 72 | v1 = x.GetHue(); 73 | v2 = y.GetHue(); 74 | 75 | if (v1 < v2) 76 | { 77 | result = -1; 78 | } 79 | else if (v1 > v2) 80 | { 81 | result = 1; 82 | } 83 | else 84 | { 85 | result = 0; 86 | } 87 | 88 | return result; 89 | } 90 | 91 | /// 92 | /// Compares two colors by value and returns an indication of their relative sort order. 93 | /// 94 | /// A color to compare to y. 95 | /// A color to compare to x. 96 | public static int Value(Color x, Color y) 97 | { 98 | int v1; 99 | int v2; 100 | int result; 101 | 102 | v1 = x.R << 16 | x.G << 8 | x.B; 103 | v2 = y.R << 16 | y.G << 8 | y.B; 104 | 105 | if (v1 > v2) 106 | { 107 | result = -1; 108 | } 109 | else if (v1 < v2) 110 | { 111 | result = 1; 112 | } 113 | else 114 | { 115 | result = 0; 116 | } 117 | 118 | return result; 119 | } 120 | 121 | #endregion 122 | 123 | #region Private Class Members 124 | 125 | private static int GetBrightness(Color color) 126 | { 127 | //http://stackoverflow.com/a/13558570/148962 128 | 129 | // GRAY VALUE ("brightness") 130 | 131 | return GetGamma(RedLuminance * GetInverseGamma(color.R) + GreenLuminance * GetInverseGamma(color.G) + BlueLuminance * GetInverseGamma(color.B)); 132 | } 133 | 134 | private static int GetGamma(double v) 135 | { 136 | // sRGB "gamma" function (approx 2.2) 137 | 138 | if (v <= 0.0031308) 139 | { 140 | v *= 12.92; 141 | } 142 | else 143 | { 144 | v = 1.055 * Math.Pow(v, 1.0 / 2.4) - 0.055; 145 | } 146 | 147 | return (int)(v * 255 + .5); 148 | } 149 | 150 | private static double GetInverseGamma(int ic) 151 | { 152 | double result; 153 | 154 | // Inverse of sRGB "gamma" function. (approx 2.2) 155 | 156 | double c = ic / 255.0; 157 | if (c <= 0.04045) 158 | { 159 | result = c / 12.92; 160 | } 161 | else 162 | { 163 | result = Math.Pow(((c + 0.055) / (1.055)), 2.4); 164 | } 165 | 166 | return result; 167 | } 168 | 169 | #endregion 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorEditingMode.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | /// 12 | /// Specifies the edit mode of a . 13 | /// 14 | public enum ColorEditingMode 15 | { 16 | /// 17 | /// None. No editing is allowed. 18 | /// 19 | None, 20 | 21 | /// 22 | /// Only custom colors can be edited. 23 | /// 24 | CustomOnly, 25 | 26 | /// 27 | /// Custom or standard colors can be edited. 28 | /// 29 | Both, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorGridSelectedCellStyle.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | /// 12 | /// Determines how the selected cell in a control is rendered. 13 | /// 14 | public enum ColorGridSelectedCellStyle 15 | { 16 | /// 17 | /// The selected cell is drawn no differently to any other cell. 18 | /// 19 | None, 20 | 21 | /// 22 | /// The selected cell displays a basic outline and focus rectangle. 23 | /// 24 | Standard, 25 | 26 | /// 27 | /// The selected cell is displayed larger than other cells 28 | /// 29 | Zoomed 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorHitTestInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace Cyotek.Windows.Forms 4 | { 5 | // Cyotek Color Picker controls library 6 | // Copyright © 2013-2015 Cyotek Ltd. 7 | // http://cyotek.com/blog/tag/colorpicker 8 | 9 | // Licensed under the MIT License. See license.txt for the full text. 10 | 11 | // If you use this code in your applications, donations or attribution are welcome 12 | 13 | public class ColorHitTestInfo 14 | { 15 | #region Public Properties 16 | 17 | public Color Color { get; set; } 18 | 19 | public int Index { get; set; } 20 | 21 | public ColorSource Source { get; set; } 22 | 23 | #endregion 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorPalette.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | public enum ColorPalette 12 | { 13 | None, 14 | 15 | Named, 16 | 17 | Office2010, 18 | 19 | Paint, 20 | 21 | Standard, 22 | 23 | WebSafe, 24 | 25 | Standard256 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorSliderNubStyle.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | public enum ColorSliderNubStyle 12 | { 13 | None, 14 | 15 | TopLeft, 16 | 17 | BottomRight 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/ColorSource.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | public enum ColorSource 12 | { 13 | None, 14 | 15 | Standard, 16 | 17 | Custom 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Cyotek.Windows.Forms.ColorPicker.ncrunchproject: -------------------------------------------------------------------------------- 1 | 2 | false 3 | false 4 | false 5 | true 6 | false 7 | false 8 | false 9 | false 10 | true 11 | true 12 | false 13 | true 14 | true 15 | 60000 16 | 17 | 18 | 19 | AutoDetect 20 | STA 21 | x86 22 | 23 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Cyotek.Windows.Forms.ColorPicker.v2.ncrunchproject: -------------------------------------------------------------------------------- 1 | 2 | false 3 | false 4 | false 5 | true 6 | false 7 | false 8 | false 9 | false 10 | true 11 | true 12 | false 13 | true 14 | true 15 | 60000 16 | 17 | 18 | 19 | AutoDetect 20 | STA 21 | x86 22 | 23 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/EditColorCancelEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Drawing; 3 | 4 | namespace Cyotek.Windows.Forms 5 | { 6 | public class EditColorCancelEventArgs : CancelEventArgs 7 | { 8 | #region Public Constructors 9 | 10 | public EditColorCancelEventArgs(Color color, int colorIndex) 11 | { 12 | this.Color = color; 13 | this.ColorIndex = colorIndex; 14 | } 15 | 16 | #endregion 17 | 18 | #region Protected Constructors 19 | 20 | protected EditColorCancelEventArgs() 21 | { } 22 | 23 | #endregion 24 | 25 | #region Public Properties 26 | 27 | public Color Color { get; protected set; } 28 | 29 | public int ColorIndex { get; protected set; } 30 | 31 | #endregion 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/EditColorEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace Cyotek.Windows.Forms 5 | { 6 | public class EditColorEventArgs : EventArgs 7 | { 8 | #region Public Constructors 9 | 10 | public EditColorEventArgs(Color color, int colorIndex) 11 | { 12 | this.Color = color; 13 | this.ColorIndex = colorIndex; 14 | } 15 | 16 | #endregion 17 | 18 | #region Protected Constructors 19 | 20 | protected EditColorEventArgs() 21 | { } 22 | 23 | #endregion 24 | 25 | #region Public Properties 26 | 27 | public Color Color { get; protected set; } 28 | 29 | public int ColorIndex { get; protected set; } 30 | 31 | #endregion 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/HueColorSlider.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Drawing; 3 | using System.Linq; 4 | #if USEEXTERNALCYOTEKLIBS 5 | using Cyotek.Drawing; 6 | 7 | #endif 8 | 9 | namespace Cyotek.Windows.Forms 10 | { 11 | // Cyotek Color Picker controls library 12 | // Copyright © 2013-2015 Cyotek Ltd. 13 | // http://cyotek.com/blog/tag/colorpicker 14 | 15 | // Licensed under the MIT License. See license.txt for the full text. 16 | 17 | // If you use this code in your applications, donations or attribution are welcome 18 | 19 | public class HueColorSlider : ColorSlider 20 | { 21 | #region Public Constructors 22 | 23 | public HueColorSlider() 24 | { 25 | this.BarStyle = ColorBarStyle.Custom; 26 | this.Maximum = 359; 27 | this.CustomColors = new ColorCollection(Enumerable.Range(0, 359).Select(h => new HslColor(h, 1, 0.5).ToRgbColor())); 28 | } 29 | 30 | #endregion 31 | 32 | #region Overridden Properties 33 | 34 | [Browsable(false)] 35 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 36 | public override ColorBarStyle BarStyle 37 | { 38 | get { return base.BarStyle; } 39 | set { base.BarStyle = value; } 40 | } 41 | 42 | [Browsable(false)] 43 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 44 | public override Color Color1 45 | { 46 | get { return base.Color1; } 47 | set { base.Color1 = value; } 48 | } 49 | 50 | [Browsable(false)] 51 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 52 | public override Color Color2 53 | { 54 | get { return base.Color2; } 55 | set { base.Color2 = value; } 56 | } 57 | 58 | [Browsable(false)] 59 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 60 | public override Color Color3 61 | { 62 | get { return base.Color3; } 63 | set { base.Color3 = value; } 64 | } 65 | 66 | [Browsable(false)] 67 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 68 | public override float Maximum 69 | { 70 | get { return base.Maximum; } 71 | set { base.Maximum = value; } 72 | } 73 | 74 | [Browsable(false)] 75 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 76 | public override float Minimum 77 | { 78 | get { return base.Minimum; } 79 | set { base.Minimum = value; } 80 | } 81 | 82 | public override float Value 83 | { 84 | get { return base.Value; } 85 | set { base.Value = (int)value; } 86 | } 87 | 88 | #endregion 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/IColorEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace Cyotek.Windows.Forms 5 | { 6 | // Cyotek Color Picker controls library 7 | // Copyright © 2013-2015 Cyotek Ltd. 8 | // http://cyotek.com/blog/tag/colorpicker 9 | 10 | // Licensed under the MIT License. See license.txt for the full text. 11 | 12 | // If you use this code in your applications, donations or attribution are welcome 13 | 14 | /// 15 | /// Provides functionality required by color editors that are bindable 16 | /// 17 | public interface IColorEditor 18 | { 19 | #region Events 20 | 21 | /// 22 | /// Occurs when the property is changed. 23 | /// 24 | event EventHandler ColorChanged; 25 | 26 | #endregion 27 | 28 | #region Properties 29 | 30 | /// 31 | /// Gets or sets the component color. 32 | /// 33 | /// The component color. 34 | Color Color { get; set; } 35 | 36 | #endregion 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/IPaletteSerializer.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace Cyotek.Windows.Forms 4 | { 5 | // Cyotek Color Picker controls library 6 | // Copyright © 2013-2015 Cyotek Ltd. 7 | // http://cyotek.com/blog/tag/colorpicker 8 | 9 | // Licensed under the MIT License. See license.txt for the full text. 10 | 11 | // If you use this code in your applications, donations or attribution are welcome 12 | 13 | /// 14 | /// Serializes and deserializes color palettes into and from other documents. 15 | /// 16 | public interface IPaletteSerializer 17 | { 18 | #region Properties 19 | 20 | /// 21 | /// Gets a value indicating whether this serializer can be used to read palettes. 22 | /// 23 | /// true if palettes can be read using this serializer; otherwise, false. 24 | bool CanRead { get; } 25 | 26 | /// 27 | /// Gets a value indicating whether this serializer can be used to write palettes. 28 | /// 29 | /// true if palettes can be written using this serializer; otherwise, false. 30 | bool CanWrite { get; } 31 | 32 | /// 33 | /// Gets the default extension for files generated with this palette format. 34 | /// 35 | /// The default extension for files generated with this palette format. 36 | string DefaultExtension { get; } 37 | 38 | /// 39 | /// Gets a descriptive name of the palette format 40 | /// 41 | /// The descriptive name of the palette format. 42 | string Name { get; } 43 | 44 | #endregion 45 | 46 | #region Methods 47 | 48 | /// 49 | /// Determines whether this instance can read palette data from the specified stream. 50 | /// 51 | /// The stream. 52 | /// true if this instance can read palette data from the specified stream; otherwise, false. 53 | bool CanReadFrom(Stream stream); 54 | 55 | /// 56 | /// Deserializes the contained by the specified . 57 | /// 58 | /// The that contains the palette to deserialize. 59 | /// The being deserialized. 60 | ColorCollection Deserialize(Stream stream); 61 | 62 | /// 63 | /// Serializes the specified and writes the palette to a file using the specified . 64 | /// 65 | /// The used to write the palette. 66 | /// The to serialize. 67 | void Serialize(Stream stream, ColorCollection palette); 68 | 69 | #endregion 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/JascPaletteSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace Cyotek.Windows.Forms 7 | { 8 | // Cyotek Color Picker controls library 9 | // Copyright © 2013-2015 Cyotek Ltd. 10 | // http://cyotek.com/blog/tag/colorpicker 11 | 12 | // Licensed under the MIT License. See license.txt for the full text. 13 | 14 | // If you use this code in your applications, donations or attribution are welcome 15 | 16 | /// 17 | /// Serializes and deserializes color palettes into and from the Jasc palette format. 18 | /// 19 | public class JascPaletteSerializer : PaletteSerializer 20 | { 21 | #region Overridden Properties 22 | 23 | /// 24 | /// Gets the default extension for files generated with this palette format. 25 | /// 26 | /// The default extension for files generated with this palette format. 27 | public override string DefaultExtension 28 | { 29 | get { return "pal"; } 30 | } 31 | 32 | /// 33 | /// Gets a descriptive name of the palette format 34 | /// 35 | /// The descriptive name of the palette format. 36 | public override string Name 37 | { 38 | get { return "JASC Palette"; } 39 | } 40 | 41 | #endregion 42 | 43 | #region Overridden Methods 44 | 45 | /// 46 | /// Determines whether this instance can read palette from data the specified stream. 47 | /// 48 | /// The stream. 49 | /// true if this instance can read palette data from the specified stream; otherwise, false. 50 | public override bool CanReadFrom(Stream stream) 51 | { 52 | bool result; 53 | 54 | if (stream == null) 55 | { 56 | throw new ArgumentNullException("stream"); 57 | } 58 | 59 | try 60 | { 61 | using (StreamReader reader = new StreamReader(stream)) 62 | { 63 | string header; 64 | string version; 65 | 66 | // check signature 67 | header = reader.ReadLine(); 68 | version = reader.ReadLine(); 69 | 70 | result = (header == "JASC-PAL" && version == "0100"); 71 | } 72 | } 73 | catch 74 | { 75 | result = false; 76 | } 77 | 78 | return result; 79 | } 80 | 81 | /// 82 | /// Deserializes the contained by the specified . 83 | /// 84 | /// The that contains the palette to deserialize. 85 | /// The being deserialized. 86 | public override ColorCollection Deserialize(Stream stream) 87 | { 88 | ColorCollection results; 89 | 90 | if (stream == null) 91 | { 92 | throw new ArgumentNullException("stream"); 93 | } 94 | 95 | results = new ColorCollection(); 96 | 97 | using (StreamReader reader = new StreamReader(stream)) 98 | { 99 | string header; 100 | string version; 101 | int colorCount; 102 | 103 | // check signature 104 | header = reader.ReadLine(); 105 | version = reader.ReadLine(); 106 | 107 | if (header != "JASC-PAL" || version != "0100") 108 | { 109 | throw new InvalidDataException("Invalid palette file"); 110 | } 111 | 112 | colorCount = Convert.ToInt32(reader.ReadLine()); 113 | for (int i = 0; i < colorCount; i++) 114 | { 115 | int r; 116 | int g; 117 | int b; 118 | string data; 119 | string[] parts; 120 | 121 | data = reader.ReadLine(); 122 | parts = !string.IsNullOrEmpty(data) ? data.Split(new[] 123 | { 124 | ' ', '\t' 125 | }, StringSplitOptions.RemoveEmptyEntries) : new string[0]; 126 | 127 | if (!int.TryParse(parts[0], out r) || !int.TryParse(parts[1], out g) || !int.TryParse(parts[2], out b)) 128 | { 129 | throw new InvalidDataException(string.Format("Invalid palette contents found with data '{0}'", data)); 130 | } 131 | 132 | results.Add(Color.FromArgb(r, g, b)); 133 | } 134 | } 135 | 136 | return results; 137 | } 138 | 139 | /// 140 | /// Serializes the specified and writes the palette to a file using the specified . 141 | /// 142 | /// The used to write the palette. 143 | /// The to serialize. 144 | public override void Serialize(Stream stream, ColorCollection palette) 145 | { 146 | if (stream == null) 147 | { 148 | throw new ArgumentNullException("stream"); 149 | } 150 | 151 | if (palette == null) 152 | { 153 | throw new ArgumentNullException("palette"); 154 | } 155 | 156 | using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8)) 157 | { 158 | writer.WriteLine("JASC-PAL"); 159 | writer.WriteLine("0100"); 160 | writer.WriteLine(palette.Count); 161 | foreach (Color color in palette) 162 | { 163 | writer.Write("{0} ", color.R); 164 | writer.Write("{0} ", color.G); 165 | writer.Write("{0} ", color.B); 166 | writer.WriteLine(); 167 | } 168 | } 169 | } 170 | 171 | #endregion 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/LightnessColorSlider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Drawing; 4 | #if USEEXTERNALCYOTEKLIBS 5 | using Cyotek.Drawing; 6 | 7 | #endif 8 | 9 | namespace Cyotek.Windows.Forms 10 | { 11 | // Cyotek Color Picker controls library 12 | // Copyright © 2013-2015 Cyotek Ltd. 13 | // http://cyotek.com/blog/tag/colorpicker 14 | 15 | // Licensed under the MIT License. See license.txt for the full text. 16 | 17 | // If you use this code in your applications, donations or attribution are welcome 18 | 19 | public class LightnessColorSlider : ColorSlider, IColorEditor 20 | { 21 | #region Instance Fields 22 | 23 | private Color _color; 24 | 25 | #endregion 26 | 27 | #region Public Constructors 28 | 29 | public LightnessColorSlider() 30 | { 31 | this.BarStyle = ColorBarStyle.TwoColor; 32 | this.Color = Color.Black; 33 | } 34 | 35 | #endregion 36 | 37 | #region Events 38 | 39 | /// 40 | /// Occurs when the Color property value changes 41 | /// 42 | [Category("Property Changed")] 43 | public event EventHandler ColorChanged; 44 | 45 | #endregion 46 | 47 | #region Overridden Properties 48 | 49 | [Browsable(false)] 50 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 51 | public override ColorBarStyle BarStyle 52 | { 53 | get { return base.BarStyle; } 54 | set { base.BarStyle = value; } 55 | } 56 | 57 | [Browsable(false)] 58 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 59 | public override Color Color1 60 | { 61 | get { return base.Color1; } 62 | set { base.Color1 = value; } 63 | } 64 | 65 | [Browsable(false)] 66 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 67 | public override Color Color2 68 | { 69 | get { return base.Color2; } 70 | set { base.Color2 = value; } 71 | } 72 | 73 | [Browsable(false)] 74 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 75 | public override Color Color3 76 | { 77 | get { return base.Color3; } 78 | set { base.Color3 = value; } 79 | } 80 | 81 | [Browsable(false)] 82 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 83 | public override float Maximum 84 | { 85 | get { return base.Maximum; } 86 | set { base.Maximum = value; } 87 | } 88 | 89 | [Browsable(false)] 90 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 91 | public override float Minimum 92 | { 93 | get { return base.Minimum; } 94 | set { base.Minimum = value; } 95 | } 96 | 97 | public override float Value 98 | { 99 | get { return base.Value; } 100 | set { base.Value = (int)value; } 101 | } 102 | 103 | #endregion 104 | 105 | #region Overridden Methods 106 | 107 | /// 108 | /// Raises the event. 109 | /// 110 | /// The instance containing the event data. 111 | protected override void OnValueChanged(EventArgs e) 112 | { 113 | if (!this.LockUpdates) 114 | { 115 | HslColor color; 116 | 117 | this.LockUpdates = true; 118 | color = new HslColor(this.Color); 119 | color.L = this.Value / 100D; 120 | _color = color.ToRgbColor(); 121 | this.OnColorChanged(e); 122 | this.LockUpdates = false; 123 | } 124 | 125 | base.OnValueChanged(e); 126 | } 127 | 128 | #endregion 129 | 130 | #region Public Properties 131 | 132 | [Category("Appearance")] 133 | [DefaultValue(typeof(Color), "Black")] 134 | public virtual Color Color 135 | { 136 | get { return _color; } 137 | set 138 | { 139 | if (this.Color != value) 140 | { 141 | _color = value; 142 | 143 | if (!this.LockUpdates) 144 | { 145 | this.LockUpdates = true; 146 | this.Value = (float)new HslColor(value).L * 100; 147 | this.OnColorChanged(EventArgs.Empty); 148 | this.LockUpdates = false; 149 | } 150 | } 151 | } 152 | } 153 | 154 | #endregion 155 | 156 | #region Protected Properties 157 | 158 | /// 159 | /// Gets or sets a value indicating whether input changes should be processed. 160 | /// 161 | /// true if input changes should be processed; otherwise, false. 162 | protected bool LockUpdates { get; set; } 163 | 164 | #endregion 165 | 166 | #region Protected Members 167 | 168 | protected virtual void CreateScale() 169 | { 170 | HslColor color; 171 | 172 | color = new HslColor(this.Color); 173 | 174 | color.L = 0; 175 | this.Color1 = color.ToRgbColor(); 176 | 177 | color.L = 1; 178 | this.Color2 = color.ToRgbColor(); 179 | } 180 | 181 | /// 182 | /// Raises the event. 183 | /// 184 | /// The instance containing the event data. 185 | protected virtual void OnColorChanged(EventArgs e) 186 | { 187 | EventHandler handler; 188 | 189 | this.CreateScale(); 190 | this.Invalidate(); 191 | 192 | handler = this.ColorChanged; 193 | 194 | if (handler != null) 195 | { 196 | handler(this, e); 197 | } 198 | } 199 | 200 | #endregion 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Cyotek.Windows.Forms 5 | { 6 | // Cyotek Color Picker controls library 7 | // Copyright © 2013-2015 Cyotek Ltd. 8 | // http://cyotek.com/blog/tag/colorpicker 9 | 10 | // Licensed under the MIT License. See license.txt for the full text. 11 | 12 | // If you use this code in your applications, donations or attribution are welcome 13 | 14 | internal class NativeMethods 15 | { 16 | // ReSharper disable InconsistentNaming 17 | 18 | #region Constants 19 | 20 | public const int R2_NOT = 6; // Inverted drawing mode 21 | 22 | #endregion 23 | 24 | #region Protected Constructors 25 | 26 | protected NativeMethods() 27 | { } 28 | 29 | #endregion 30 | 31 | #region Public Class Members 32 | 33 | [DllImport("user32.dll", EntryPoint = "GetDC", CallingConvention = CallingConvention.StdCall)] 34 | public static extern IntPtr GetDC(IntPtr hWnd); 35 | 36 | [DllImport("gdi32.dll", EntryPoint = "LineTo", CallingConvention = CallingConvention.StdCall)] 37 | public static extern bool LineTo(IntPtr hdc, int x, int y); 38 | 39 | [DllImport("gdi32.dll", EntryPoint = "MoveToEx", CallingConvention = CallingConvention.StdCall)] 40 | public static extern bool MoveToEx(IntPtr hdc, int x, int y, IntPtr lpPoint); 41 | 42 | [DllImport("user32.dll", EntryPoint = "ReleaseDC", CallingConvention = CallingConvention.StdCall)] 43 | public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC); 44 | 45 | [DllImport("gdi32.dll", EntryPoint = "SetROP2", CallingConvention = CallingConvention.StdCall)] 46 | public static extern int SetROP2(IntPtr hdc, int fnDrawMode); 47 | 48 | #endregion 49 | 50 | // ReSharper restore InconsistentNaming 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/NavigationOrigin.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | /// 12 | /// Specifies the origin of a navigation operation 13 | /// 14 | public enum NavigationOrigin 15 | { 16 | /// 17 | /// Specifies the beginning 18 | /// 19 | Begin, 20 | 21 | /// 22 | /// Specifies the current position 23 | /// 24 | Current, 25 | 26 | /// 27 | /// Specifies the end 28 | /// 29 | End 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/PaintNetPaletteSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Text; 6 | 7 | namespace Cyotek.Windows.Forms 8 | { 9 | // Cyotek Color Picker controls library 10 | // Copyright © 2013-2015 Cyotek Ltd. 11 | // http://cyotek.com/blog/tag/colorpicker 12 | 13 | // Licensed under the MIT License. See license.txt for the full text. 14 | 15 | // If you use this code in your applications, donations or attribution are welcome 16 | 17 | /// 18 | /// Serializes and deserializes color palettes into and from the Paint.NET palette format. 19 | /// 20 | public class PaintNetPaletteSerializer : PaletteSerializer 21 | { 22 | #region Overridden Properties 23 | 24 | /// 25 | /// Gets the default extension for files generated with this palette format. 26 | /// 27 | /// The default extension for files generated with this palette format. 28 | public override string DefaultExtension 29 | { 30 | get { return "txt"; } 31 | } 32 | 33 | /// 34 | /// Gets a descriptive name of the palette format 35 | /// 36 | /// The descriptive name of the palette format. 37 | public override string Name 38 | { 39 | get { return "Paint.NET Palette"; } 40 | } 41 | 42 | #endregion 43 | 44 | #region Overridden Methods 45 | 46 | /// 47 | /// Determines whether this instance can read palette from data the specified stream. 48 | /// 49 | /// The stream. 50 | /// true if this instance can read palette data from the specified stream; otherwise, false. 51 | public override bool CanReadFrom(Stream stream) 52 | { 53 | bool result; 54 | 55 | if (stream == null) 56 | { 57 | throw new ArgumentNullException("stream"); 58 | } 59 | 60 | try 61 | { 62 | using (StreamReader reader = new StreamReader(stream)) 63 | { 64 | string firstLine; 65 | 66 | firstLine = reader.ReadLine(); 67 | 68 | result = !string.IsNullOrEmpty(firstLine) && firstLine[0] == ';'; 69 | } 70 | } 71 | catch 72 | { 73 | result = false; 74 | } 75 | 76 | return result; 77 | } 78 | 79 | /// 80 | /// Deserializes the contained by the specified . 81 | /// 82 | /// The that contains the palette to deserialize. 83 | /// The being deserialized. 84 | public override ColorCollection Deserialize(Stream stream) 85 | { 86 | ColorCollection results; 87 | 88 | if (stream == null) 89 | { 90 | throw new ArgumentNullException("stream"); 91 | } 92 | 93 | results = new ColorCollection(); 94 | 95 | using (StreamReader reader = new StreamReader(stream)) 96 | { 97 | while (!reader.EndOfStream) 98 | { 99 | string line; 100 | 101 | line = reader.ReadLine(); 102 | if (!string.IsNullOrEmpty(line) && !line.StartsWith(";") && line.Length == 8) 103 | { 104 | int a; 105 | int r; 106 | int g; 107 | int b; 108 | 109 | a = int.Parse(line.Substring(0, 2), NumberStyles.HexNumber); 110 | r = int.Parse(line.Substring(2, 2), NumberStyles.HexNumber); 111 | g = int.Parse(line.Substring(4, 2), NumberStyles.HexNumber); 112 | b = int.Parse(line.Substring(6, 2), NumberStyles.HexNumber); 113 | 114 | results.Add(Color.FromArgb(a, r, g, b)); 115 | } 116 | } 117 | } 118 | 119 | return results; 120 | } 121 | 122 | /// 123 | /// Serializes the specified and writes the palette to a file using the specified . 124 | /// 125 | /// The used to write the palette. 126 | /// The to serialize. 127 | public override void Serialize(Stream stream, ColorCollection palette) 128 | { 129 | if (stream == null) 130 | { 131 | throw new ArgumentNullException("stream"); 132 | } 133 | 134 | if (palette == null) 135 | { 136 | throw new ArgumentNullException("palette"); 137 | } 138 | 139 | // TODO: Not writing 96 colors, but the entire contents of the palette, wether that's less than 96 or more 140 | 141 | using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8)) 142 | { 143 | writer.WriteLine(@"; Paint.NET Palette File 144 | ; Lines that start with a semicolon are comments 145 | ; Colors are written as 8-digit hexadecimal numbers: aarrggbb 146 | ; For example, this would specify green: FF00FF00 147 | ; The alpha ('aa') value specifies how transparent a color is. FF is fully opaque, 00 is fully transparent. 148 | ; A palette must consist of ninety six (96) colors. If there are less than this, the remaining color 149 | ; slots will be set to white (FFFFFFFF). If there are more, then the remaining colors will be ignored."); 150 | foreach (Color color in palette) 151 | { 152 | writer.WriteLine("{0:X2}{1:X2}{2:X2}{3:X2}", color.A, color.R, color.G, color.B); 153 | } 154 | } 155 | } 156 | 157 | #endregion 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Program.cs: -------------------------------------------------------------------------------- 1 | // 2015/10/14 - 20:49 2 | 3 | using System; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | namespace Cyotek.Windows.Forms 8 | { 9 | /// 10 | /// Class with program entry point. 11 | /// 12 | internal sealed class Program 13 | { 14 | /// 15 | /// Program entry point. 16 | /// 17 | [STAThread] 18 | private static void Main(string[] args) 19 | { 20 | Application.EnableVisualStyles(); 21 | Application.SetCompatibleTextRenderingDefault(false); 22 | var app = new Cyotek.Windows.Forms.ColorPickerDialog(); 23 | 24 | if (args.Length > 0) { 25 | var incolor = args[0]; 26 | System.Diagnostics.Debug.WriteLine("Inputing color: {0}", incolor); 27 | app.Color = ColorTranslator.FromHtml('#' + incolor.Substring(6, 2) + incolor.Substring(0, 6)); 28 | } else { 29 | app.Color = Color.White; 30 | } 31 | 32 | Application.Run(app); 33 | 34 | var color = string.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", app.Color.R, app.Color.G, app.Color.B, app.Color.A); 35 | 36 | Console.Write(app.DialogResult == DialogResult.OK ? color : "CANCEL"); 37 | System.Diagnostics.Debug.WriteLine(color); 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | // Cyotek Color Picker controls library 6 | // Copyright © 2013-2015 Cyotek Ltd. 7 | // http://cyotek.com/blog/tag/colorpicker 8 | 9 | // Licensed under the MIT License. See license.txt for the full text. 10 | 11 | // If you use this code in your applications, donations or attribution are welcome 12 | 13 | [assembly: AssemblyTitle("Cyotek Color Picker Controls")] 14 | [assembly: AssemblyDescription("")] 15 | [assembly: AssemblyConfiguration("")] 16 | [assembly: AssemblyCompany("")] 17 | [assembly: AssemblyProduct("Cyotek Color Picker Controls")] 18 | [assembly: AssemblyCopyright("Copyright © 2013-2015 Cyotek Ltd.")] 19 | [assembly: AssemblyTrademark("")] 20 | [assembly: AssemblyCulture("")] 21 | [assembly: ComVisible(false)] 22 | [assembly: Guid("de546619-59b3-438e-8b5a-3d149e146b22")] 23 | [assembly: CLSCompliant(true)] 24 | [assembly: AssemblyVersion("1.0.0.0")] 25 | [assembly: AssemblyFileVersion("1.0.5.0")] 26 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18051 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Cyotek.Windows.Forms.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Cyotek.Windows.Forms.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap eyedropper { 67 | get { 68 | object obj = ResourceManager.GetObject("eyedropper", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap LoadPalette { 77 | get { 78 | object obj = ResourceManager.GetObject("LoadPalette", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap SavePalette { 87 | get { 88 | object obj = ResourceManager.GetObject("SavePalette", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/RawPaletteSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.IO; 4 | 5 | namespace Cyotek.Windows.Forms 6 | { 7 | // Cyotek Color Picker controls library 8 | // Copyright © 2013-2015 Cyotek Ltd. 9 | // http://cyotek.com/blog/tag/colorpicker 10 | 11 | // Licensed under the MIT License. See license.txt for the full text. 12 | 13 | // If you use this code in your applications, donations or attribution are welcome 14 | 15 | /// 16 | /// Serializes and deserializes 8bit color palettes from raw byte data. 17 | /// 18 | public class RawPaletteSerializer : PaletteSerializer 19 | { 20 | #region Overridden Properties 21 | 22 | /// 23 | /// Gets the default extension for files generated with this palette format. 24 | /// 25 | /// The default extension for files generated with this palette format. 26 | public override string DefaultExtension 27 | { 28 | get { return "pal"; } 29 | } 30 | 31 | /// 32 | /// Gets a descriptive name of the palette format 33 | /// 34 | /// The descriptive name of the palette format. 35 | public override string Name 36 | { 37 | get { return "Raw Palette"; } 38 | } 39 | 40 | #endregion 41 | 42 | #region Overridden Methods 43 | 44 | /// 45 | /// Determines whether this instance can read palette from data the specified stream. 46 | /// 47 | /// The stream. 48 | /// true if this instance can read palette data from the specified stream; otherwise, false. 49 | public override bool CanReadFrom(Stream stream) 50 | { 51 | bool result; 52 | 53 | if (stream == null) 54 | { 55 | throw new ArgumentNullException("stream"); 56 | } 57 | 58 | try 59 | { 60 | result = stream.Length % 3 == 0; 61 | } 62 | catch 63 | { 64 | result = false; 65 | } 66 | 67 | return result; 68 | } 69 | 70 | /// 71 | /// Deserializes the contained by the specified . 72 | /// 73 | /// The that contains the palette to deserialize. 74 | /// The being deserialized. 75 | public override ColorCollection Deserialize(Stream stream) 76 | { 77 | ColorCollection results; 78 | 79 | if (stream == null) 80 | { 81 | throw new ArgumentNullException("stream"); 82 | } 83 | 84 | results = new ColorCollection(); 85 | 86 | for (int i = 0; i < stream.Length / 3; i++) 87 | { 88 | int r; 89 | int g; 90 | int b; 91 | 92 | r = stream.ReadByte(); 93 | g = stream.ReadByte(); 94 | b = stream.ReadByte(); 95 | 96 | results.Add(Color.FromArgb(r, g, b)); 97 | } 98 | 99 | return results; 100 | } 101 | 102 | /// 103 | /// Serializes the specified and writes the palette to a file using the specified . 104 | /// 105 | /// The used to write the palette. 106 | /// The to serialize. 107 | public override void Serialize(Stream stream, ColorCollection palette) 108 | { 109 | if (stream == null) 110 | { 111 | throw new ArgumentNullException("stream"); 112 | } 113 | 114 | if (palette == null) 115 | { 116 | throw new ArgumentNullException("palette"); 117 | } 118 | 119 | foreach (Color color in palette) 120 | { 121 | stream.WriteByte(color.R); 122 | stream.WriteByte(color.G); 123 | stream.WriteByte(color.B); 124 | } 125 | 126 | stream.Flush(); 127 | } 128 | 129 | #endregion 130 | 131 | #region Private Members 132 | 133 | private int ReadInt(Stream stream) 134 | { 135 | byte[] buffer; 136 | 137 | // big endian conversion: http://stackoverflow.com/a/14401341/148962 138 | 139 | buffer = new byte[4]; 140 | stream.Read(buffer, 0, buffer.Length); 141 | 142 | return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; 143 | } 144 | 145 | #endregion 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/cellbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/cellbackground.png -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/eyedropper.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/eyedropper.cur -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/eyedropper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/eyedropper.png -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/palette-load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/palette-load.png -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/palette-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/palette-save.png -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/RgbaChannel.cs: -------------------------------------------------------------------------------- 1 | namespace Cyotek.Windows.Forms 2 | { 3 | // Cyotek Color Picker controls library 4 | // Copyright © 2013-2015 Cyotek Ltd. 5 | // http://cyotek.com/blog/tag/colorpicker 6 | 7 | // Licensed under the MIT License. See license.txt for the full text. 8 | 9 | // If you use this code in your applications, donations or attribution are welcome 10 | 11 | public enum RgbaChannel 12 | { 13 | Red, 14 | 15 | Green, 16 | 17 | Blue, 18 | 19 | Alpha 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/SaturationColorSlider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Drawing; 4 | #if USEEXTERNALCYOTEKLIBS 5 | using Cyotek.Drawing; 6 | 7 | #endif 8 | 9 | namespace Cyotek.Windows.Forms 10 | { 11 | // Cyotek Color Picker controls library 12 | // Copyright © 2013-2015 Cyotek Ltd. 13 | // http://cyotek.com/blog/tag/colorpicker 14 | 15 | // Licensed under the MIT License. See license.txt for the full text. 16 | 17 | // If you use this code in your applications, donations or attribution are welcome 18 | 19 | /// 20 | /// Represents a control for selecting the saturation of a color 21 | /// 22 | public class SaturationColorSlider : ColorSlider 23 | { 24 | #region Instance Fields 25 | 26 | private Color _color; 27 | 28 | #endregion 29 | 30 | #region Public Constructors 31 | 32 | public SaturationColorSlider() 33 | { 34 | this.BarStyle = ColorBarStyle.TwoColor; 35 | this.Color = Color.Black; 36 | } 37 | 38 | #endregion 39 | 40 | #region Events 41 | 42 | /// 43 | /// Occurs when the Color property value changes 44 | /// 45 | [Category("Property Changed")] 46 | public event EventHandler ColorChanged; 47 | 48 | #endregion 49 | 50 | #region Overridden Properties 51 | 52 | [Browsable(false)] 53 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 54 | public override ColorBarStyle BarStyle 55 | { 56 | get { return base.BarStyle; } 57 | set { base.BarStyle = value; } 58 | } 59 | 60 | [Browsable(false)] 61 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 62 | public override Color Color1 63 | { 64 | get { return base.Color1; } 65 | set { base.Color1 = value; } 66 | } 67 | 68 | [Browsable(false)] 69 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 70 | public override Color Color2 71 | { 72 | get { return base.Color2; } 73 | set { base.Color2 = value; } 74 | } 75 | 76 | [Browsable(false)] 77 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 78 | public override Color Color3 79 | { 80 | get { return base.Color3; } 81 | set { base.Color3 = value; } 82 | } 83 | 84 | [Browsable(false)] 85 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 86 | public override float Maximum 87 | { 88 | get { return base.Maximum; } 89 | set { base.Maximum = value; } 90 | } 91 | 92 | [Browsable(false)] 93 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 94 | public override float Minimum 95 | { 96 | get { return base.Minimum; } 97 | set { base.Minimum = value; } 98 | } 99 | 100 | public override float Value 101 | { 102 | get { return base.Value; } 103 | set { base.Value = (int)value; } 104 | } 105 | 106 | #endregion 107 | 108 | #region Public Properties 109 | 110 | [Category("Appearance")] 111 | [DefaultValue(typeof(Color), "Black")] 112 | public virtual Color Color 113 | { 114 | get { return _color; } 115 | set 116 | { 117 | if (this.Color != value) 118 | { 119 | _color = value; 120 | 121 | this.OnColorChanged(EventArgs.Empty); 122 | } 123 | } 124 | } 125 | 126 | #endregion 127 | 128 | #region Protected Members 129 | 130 | protected virtual void CreateScale() 131 | { 132 | HslColor color; 133 | 134 | color = new HslColor(this.Color); 135 | 136 | color.S = 0; 137 | this.Color1 = color.ToRgbColor(); 138 | 139 | color.S = 1; 140 | this.Color2 = color.ToRgbColor(); 141 | } 142 | 143 | /// 144 | /// Raises the event. 145 | /// 146 | /// The instance containing the event data. 147 | protected virtual void OnColorChanged(EventArgs e) 148 | { 149 | EventHandler handler; 150 | 151 | this.CreateScale(); 152 | this.Invalidate(); 153 | 154 | handler = this.ColorChanged; 155 | 156 | if (handler != null) 157 | { 158 | handler(this, e); 159 | } 160 | } 161 | 162 | #endregion 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/cyopublic.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/cyopublic.snk -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/Hex256.pal: -------------------------------------------------------------------------------- 1 | JASC-PAL 2 | 0100 3 | 256 4 | 0 0 0 5 | 0 48 96 6 | 47 96 144 7 | 47 96 192 8 | 0 48 144 9 | 0 0 144 10 | 0 0 207 11 | 0 0 96 12 | 0 96 96 13 | 0 96 144 14 | 0 151 192 15 | 0 103 207 16 | 0 48 207 17 | 0 0 255 18 | 48 48 255 19 | 48 48 144 20 | 96 152 144 21 | 0 152 159 22 | 48 200 207 23 | 0 200 255 24 | 0 152 255 25 | 0 103 255 26 | 48 103 255 27 | 48 48 192 28 | 96 103 144 29 | 48 152 96 30 | 0 200 144 31 | 0 200 192 32 | 0 255 255 33 | 48 200 255 34 | 48 151 255 35 | 96 151 255 36 | 96 96 255 37 | 95 0 255 38 | 96 0 192 39 | 48 151 48 40 | 0 200 96 41 | 0 255 144 42 | 96 255 207 43 | 96 255 255 44 | 96 200 255 45 | 144 200 255 46 | 144 151 255 47 | 144 103 255 48 | 144 48 255 49 | 144 0 255 50 | 0 96 0 51 | 0 200 0 52 | 0 255 0 53 | 96 255 144 54 | 144 255 192 55 | 207 255 255 56 | 192 200 255 57 | 192 151 255 58 | 192 96 255 59 | 192 48 255 60 | 192 0 255 61 | 144 0 192 62 | 0 48 0 63 | 0 152 48 64 | 47 200 47 65 | 96 255 96 66 | 144 255 144 67 | 207 255 207 68 | 255 255 255 69 | 255 200 255 70 | 255 151 255 71 | 255 104 255 72 | 255 0 255 73 | 207 0 207 74 | 96 0 96 75 | 47 96 0 76 | 0 152 0 77 | 96 255 48 78 | 144 255 96 79 | 192 255 144 80 | 255 255 207 81 | 255 200 207 82 | 255 151 207 83 | 255 96 192 84 | 255 48 207 85 | 207 0 144 86 | 144 47 144 87 | 48 48 0 88 | 96 151 0 89 | 144 255 47 90 | 207 255 96 91 | 255 255 144 92 | 255 200 144 93 | 255 152 96 94 | 255 96 144 95 | 255 48 144 96 | 207 48 144 97 | 144 0 144 98 | 96 96 47 99 | 144 200 0 100 | 192 255 57 101 | 255 255 96 102 | 255 200 96 103 | 255 152 96 104 | 255 96 96 105 | 255 0 96 106 | 207 103 144 107 | 144 48 96 108 | 144 151 96 109 | 192 200 0 110 | 255 255 0 111 | 255 200 0 112 | 255 151 47 113 | 255 103 0 114 | 255 96 96 115 | 192 0 95 116 | 96 0 47 117 | 159 103 48 118 | 207 151 0 119 | 255 151 0 120 | 192 96 0 121 | 255 48 0 122 | 255 0 0 123 | 192 0 0 124 | 144 0 47 125 | 96 48 0 126 | 144 96 0 127 | 192 48 0 128 | 144 48 0 129 | 144 0 0 130 | 127 0 0 131 | 144 48 48 132 | 255 255 255 133 | 0 0 0 134 | 207 200 207 135 | 144 151 144 136 | 96 103 96 137 | 192 192 192 138 | 127 127 127 139 | 48 48 48 140 | 0 0 0 141 | 0 0 0 142 | 0 0 0 143 | 0 0 0 144 | 0 0 0 145 | 0 0 0 146 | 0 0 0 147 | 0 0 0 148 | 0 0 0 149 | 0 0 0 150 | 0 0 0 151 | 0 0 0 152 | 0 0 0 153 | 0 0 0 154 | 0 0 0 155 | 0 0 0 156 | 0 0 0 157 | 0 0 0 158 | 0 0 0 159 | 0 0 0 160 | 0 0 0 161 | 0 0 0 162 | 0 0 0 163 | 0 0 0 164 | 0 0 0 165 | 0 0 0 166 | 0 0 0 167 | 0 0 0 168 | 0 0 0 169 | 0 0 0 170 | 0 0 0 171 | 0 0 0 172 | 0 0 0 173 | 0 0 0 174 | 0 0 0 175 | 0 0 0 176 | 0 0 0 177 | 0 0 0 178 | 0 0 0 179 | 0 0 0 180 | 0 0 0 181 | 0 0 0 182 | 0 0 0 183 | 0 0 0 184 | 0 0 0 185 | 0 0 0 186 | 0 0 0 187 | 0 0 0 188 | 0 0 0 189 | 0 0 0 190 | 0 0 0 191 | 0 0 0 192 | 0 0 0 193 | 0 0 0 194 | 0 0 0 195 | 0 0 0 196 | 0 0 0 197 | 0 0 0 198 | 0 0 0 199 | 0 0 0 200 | 0 0 0 201 | 0 0 0 202 | 0 0 0 203 | 0 0 0 204 | 0 0 0 205 | 0 0 0 206 | 0 0 0 207 | 0 0 0 208 | 0 0 0 209 | 0 0 0 210 | 0 0 0 211 | 0 0 0 212 | 0 0 0 213 | 0 0 0 214 | 0 0 0 215 | 0 0 0 216 | 0 0 0 217 | 0 0 0 218 | 0 0 0 219 | 0 0 0 220 | 0 0 0 221 | 0 0 0 222 | 0 0 0 223 | 0 0 0 224 | 0 0 0 225 | 0 0 0 226 | 0 0 0 227 | 0 0 0 228 | 0 0 0 229 | 0 0 0 230 | 0 0 0 231 | 0 0 0 232 | 0 0 0 233 | 0 0 0 234 | 0 0 0 235 | 0 0 0 236 | 0 0 0 237 | 0 0 0 238 | 0 0 0 239 | 0 0 0 240 | 0 0 0 241 | 0 0 0 242 | 0 0 0 243 | 0 0 0 244 | 0 0 0 245 | 0 0 0 246 | 0 0 0 247 | 0 0 0 248 | 0 0 0 249 | 0 0 0 250 | 0 0 0 251 | 0 0 0 252 | 0 0 0 253 | 0 0 0 254 | 0 0 0 255 | 0 0 0 256 | 0 0 0 257 | 0 0 0 258 | 0 0 0 259 | 0 0 0 260 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/PaintNet.txt: -------------------------------------------------------------------------------- 1 | ; Paint.NET Palette File 2 | ; Lines that start with a semicolon are comments 3 | ; Colors are written as 8-digit hexadecimal numbers: aarrggbb 4 | ; For example, this would specify green: FF00FF00 5 | ; The alpha ('aa') value specifies how transparent a color is. FF is fully opaque, 00 is fully transparent. 6 | ; A palette must consist of ninety six (96) colors. If there are less than this, the remaining color 7 | ; slots will be set to white (FFFFFFFF). If there are more, then the remaining colors will be ignored. 8 | FF000000 9 | FF404040 10 | FFFF0000 11 | FFFF6A00 12 | FFFFD800 13 | FFB6FF00 14 | FF4CFF00 15 | FF00FF21 16 | FF00FF90 17 | FF00FFFF 18 | FF0094FF 19 | FF0026FF 20 | FF4800FF 21 | FFB200FF 22 | FFFF00DC 23 | FFFF006E 24 | FFFFFFFF 25 | FF808080 26 | FF7F0000 27 | FF7F3300 28 | FF7F6A00 29 | FF5B7F00 30 | FF267F00 31 | FF007F0E 32 | FF007F46 33 | FF007F7F 34 | FF004A7F 35 | FF00137F 36 | FF21007F 37 | FF57007F 38 | FF7F006E 39 | FF7F0037 40 | FFA0A0A0 41 | FF303030 42 | FFFF7F7F 43 | FFFFB27F 44 | FFFFE97F 45 | FFDAFF7F 46 | FFA5FF7F 47 | FF7FFF8E 48 | FF7FFFC5 49 | FF7FFFFF 50 | FF7FC9FF 51 | FF7F92FF 52 | FFA17FFF 53 | FFD67FFF 54 | FFFF7FED 55 | FFFF7FB6 56 | FFC0C0C0 57 | FF606060 58 | FF7F3F3F 59 | FF7F593F 60 | FF7F743F 61 | FF6D7F3F 62 | FF527F3F 63 | FF3F7F47 64 | FF3F7F62 65 | FF3F7F7F 66 | FF3F647F 67 | FF3F497F 68 | FF503F7F 69 | FF6B3F7F 70 | FF7F3F76 71 | FF7F3F5B 72 | 80000000 73 | 80404040 74 | 80FF0000 75 | 80FF6A00 76 | 80FFD800 77 | 80B6FF00 78 | 804CFF00 79 | 8000FF21 80 | 8000FF90 81 | 8000FFFF 82 | 800094FF 83 | 800026FF 84 | 804800FF 85 | 80B200FF 86 | 80FF00DC 87 | 80FF006E 88 | 80FFFFFF 89 | 80808080 90 | 807F0000 91 | 807F3300 92 | 807F6A00 93 | 805B7F00 94 | 80267F00 95 | 80007F0E 96 | 80007F46 97 | 80007F7F 98 | 80004A7F 99 | 8000137F 100 | 8021007F 101 | 8057007F 102 | 807F006E 103 | 807F0037 104 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/arne-v20-16.aco: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/winapi/Sample-Palettes/arne-v20-16.aco -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/arnev-20-16.pal: -------------------------------------------------------------------------------- 1 | JASC-PAL 2 | 0100 3 | 16 4 | 0 0 0 5 | 157 157 157 6 | 255 255 255 7 | 190 38 51 8 | 224 111 139 9 | 73 60 43 10 | 164 100 34 11 | 235 137 49 12 | 247 226 107 13 | 47 72 78 14 | 68 137 26 15 | 163 206 39 16 | 27 38 50 17 | 0 87 132 18 | 49 162 242 19 | 178 220 239 20 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/atari-800xl-palette.pal: -------------------------------------------------------------------------------- 1 | JASC-PAL 2 | 0100 3 | 256 4 | 0 0 0 5 | 37 37 37 6 | 52 52 52 7 | 78 78 78 8 | 104 104 104 9 | 117 117 117 10 | 142 142 142 11 | 164 164 164 12 | 184 184 184 13 | 197 197 197 14 | 208 208 208 15 | 215 215 215 16 | 225 225 225 17 | 234 234 234 18 | 244 244 244 19 | 255 255 255 20 | 65 32 0 21 | 84 40 0 22 | 118 55 0 23 | 154 80 0 24 | 195 104 6 25 | 228 123 7 26 | 255 145 26 27 | 255 171 29 28 | 255 197 31 29 | 255 208 59 30 | 255 216 76 31 | 255 230 81 32 | 255 244 86 33 | 255 249 112 34 | 255 255 144 35 | 255 255 170 36 | 69 25 4 37 | 114 30 17 38 | 159 36 30 39 | 179 58 32 40 | 200 81 32 41 | 227 105 32 42 | 252 129 32 43 | 253 140 37 44 | 254 152 44 45 | 255 174 56 46 | 255 185 70 47 | 255 191 81 48 | 255 198 109 49 | 255 213 135 50 | 255 228 152 51 | 255 230 171 52 | 93 31 12 53 | 122 36 13 54 | 152 44 14 55 | 176 47 15 56 | 191 54 36 57 | 211 78 42 58 | 231 98 62 59 | 243 110 74 60 | 253 120 84 61 | 255 138 106 62 | 255 152 124 63 | 255 164 139 64 | 255 179 158 65 | 255 194 178 66 | 255 208 195 67 | 255 218 208 68 | 74 23 0 69 | 114 31 0 70 | 168 19 0 71 | 200 33 10 72 | 223 37 18 73 | 236 59 36 74 | 250 82 54 75 | 252 97 72 76 | 255 112 95 77 | 255 126 126 78 | 255 143 143 79 | 255 157 158 80 | 255 171 173 81 | 255 185 189 82 | 255 199 206 83 | 255 202 222 84 | 73 0 54 85 | 102 0 75 86 | 128 3 95 87 | 149 15 116 88 | 170 34 136 89 | 186 61 153 90 | 202 77 169 91 | 215 90 182 92 | 228 103 195 93 | 239 114 206 94 | 251 126 218 95 | 255 141 225 96 | 255 157 229 97 | 255 165 231 98 | 255 175 234 99 | 255 184 236 100 | 72 3 108 101 | 92 4 136 102 | 101 13 144 103 | 123 35 167 104 | 147 59 191 105 | 157 69 201 106 | 167 79 211 107 | 178 90 222 108 | 189 101 233 109 | 197 109 241 110 | 206 118 250 111 | 213 131 255 112 | 218 144 255 113 | 222 156 255 114 | 226 169 255 115 | 230 182 255 116 | 5 30 129 117 | 6 38 165 118 | 8 47 202 119 | 38 61 212 120 | 68 76 222 121 | 79 90 236 122 | 90 104 255 123 | 101 117 255 124 | 113 131 255 125 | 128 145 255 126 | 144 160 255 127 | 151 169 255 128 | 159 178 255 129 | 175 190 255 130 | 192 203 255 131 | 205 211 255 132 | 11 7 121 133 | 32 28 142 134 | 53 49 163 135 | 70 66 180 136 | 87 83 197 137 | 97 93 207 138 | 109 105 219 139 | 123 119 233 140 | 137 133 247 141 | 145 141 255 142 | 156 152 255 143 | 167 164 255 144 | 178 175 255 145 | 187 184 255 146 | 195 193 255 147 | 211 209 255 148 | 29 41 90 149 | 29 56 118 150 | 29 72 146 151 | 29 92 172 152 | 29 113 198 153 | 50 134 207 154 | 72 155 217 155 | 78 168 236 156 | 85 182 255 157 | 105 202 255 158 | 116 203 255 159 | 130 211 255 160 | 141 218 255 161 | 159 212 255 162 | 180 226 255 163 | 192 235 255 164 | 0 75 89 165 | 0 93 110 166 | 0 111 132 167 | 0 132 156 168 | 0 153 191 169 | 0 171 202 170 | 0 188 222 171 | 0 208 245 172 | 16 220 255 173 | 62 225 255 174 | 100 231 255 175 | 118 234 255 176 | 139 237 255 177 | 154 239 255 178 | 177 243 255 179 | 199 246 255 180 | 0 72 0 181 | 0 84 0 182 | 3 107 3 183 | 14 118 14 184 | 24 128 24 185 | 39 146 39 186 | 54 164 54 187 | 78 185 78 188 | 81 205 81 189 | 114 218 114 190 | 124 228 124 191 | 133 237 133 192 | 153 242 153 193 | 179 247 179 194 | 195 249 195 195 | 205 252 205 196 | 22 64 0 197 | 28 83 0 198 | 35 102 0 199 | 40 120 0 200 | 46 140 0 201 | 58 152 12 202 | 71 165 25 203 | 81 175 35 204 | 92 186 46 205 | 113 207 67 206 | 133 227 87 207 | 141 235 95 208 | 151 245 105 209 | 160 254 114 210 | 177 255 138 211 | 188 255 154 212 | 44 53 0 213 | 56 68 0 214 | 68 82 0 215 | 73 86 0 216 | 96 113 0 217 | 108 127 0 218 | 121 141 10 219 | 139 159 28 220 | 158 178 47 221 | 171 191 60 222 | 184 204 73 223 | 194 214 83 224 | 205 225 83 225 | 219 239 108 226 | 232 252 121 227 | 242 255 171 228 | 70 58 9 229 | 77 63 9 230 | 84 69 9 231 | 108 88 9 232 | 144 118 9 233 | 171 139 10 234 | 193 161 32 235 | 208 176 47 236 | 222 190 61 237 | 230 198 69 238 | 237 205 76 239 | 245 216 98 240 | 251 226 118 241 | 252 238 152 242 | 253 243 169 243 | 253 243 190 244 | 64 26 2 245 | 88 31 5 246 | 112 36 8 247 | 141 58 19 248 | 171 81 31 249 | 181 100 39 250 | 191 119 48 251 | 208 133 58 252 | 225 147 68 253 | 237 160 78 254 | 249 173 88 255 | 252 183 92 256 | 255 193 96 257 | 255 202 105 258 | 255 207 126 259 | 255 218 150 260 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/background.lbm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Monnoroch/ColorHighlighter/833bcfb55820c1a36c554c127d6c8ff2d5ea36b0/ColorPicker/winapi/Sample-Palettes/background.lbm -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/background.pal: -------------------------------------------------------------------------------- 1 | JASC-PAL 2 | 0100 3 | 256 4 | 4 3 5 5 | 39 43 24 6 | 56 58 51 7 | 53 63 64 8 | 24 87 22 9 | 28 92 33 10 | 23 102 28 11 | 25 109 39 12 | 44 88 23 13 | 47 89 36 14 | 44 100 28 15 | 43 114 45 16 | 59 74 71 17 | 56 117 68 18 | 61 99 99 19 | 67 61 45 20 | 117 61 3 21 | 81 89 23 22 | 83 80 55 23 | 81 99 27 24 | 76 116 50 25 | 116 83 18 26 | 105 91 56 27 | 110 99 26 28 | 107 113 54 29 | 85 85 69 30 | 72 93 100 31 | 72 108 71 32 | 70 103 88 33 | 71 119 70 34 | 71 120 83 35 | 90 101 69 36 | 89 101 86 37 | 87 121 69 38 | 86 122 86 39 | 74 100 102 40 | 74 107 112 41 | 74 115 119 42 | 84 103 100 43 | 84 108 113 44 | 89 120 101 45 | 88 119 119 46 | 101 92 67 47 | 105 101 69 48 | 102 104 85 49 | 103 121 69 50 | 104 118 85 51 | 118 104 69 52 | 118 108 82 53 | 120 119 71 54 | 121 118 84 55 | 105 108 102 56 | 105 120 103 57 | 104 123 118 58 | 112 110 107 59 | 113 110 115 60 | 116 119 105 61 | 120 122 117 62 | 84 126 131 63 | 103 124 131 64 | 28 132 44 65 | 47 135 54 66 | 50 161 62 67 | 29 153 71 68 | 56 145 67 69 | 57 165 72 70 | 78 132 58 71 | 77 162 55 72 | 108 132 59 73 | 115 164 59 74 | 80 139 73 75 | 88 140 103 76 | 78 169 83 77 | 90 181 98 78 | 112 137 73 79 | 102 135 104 80 | 104 137 117 81 | 103 151 102 82 | 104 147 119 83 | 120 135 103 84 | 119 135 119 85 | 119 149 103 86 | 120 148 120 87 | 105 168 88 88 | 108 180 104 89 | 86 192 92 90 | 91 195 104 91 | 100 195 93 92 | 112 200 114 93 | 90 135 141 94 | 91 157 168 95 | 93 165 176 96 | 105 137 133 97 | 101 140 146 98 | 107 147 132 99 | 107 152 155 100 | 118 139 132 101 | 121 142 147 102 | 120 149 136 103 | 118 153 151 104 | 108 157 166 105 | 104 157 177 106 | 114 156 164 107 | 115 156 180 108 | 117 161 155 109 | 107 160 168 110 | 108 167 180 111 | 108 177 181 112 | 115 163 171 113 | 117 171 181 114 | 119 176 172 115 | 122 177 187 116 | 124 182 193 117 | 121 214 128 118 | 118 230 128 119 | 144 83 15 120 | 141 90 35 121 | 146 100 23 122 | 142 114 52 123 | 167 91 16 124 | 167 91 33 125 | 176 101 22 126 | 175 109 39 127 | 140 120 78 128 | 139 125 100 129 | 170 122 74 130 | 164 127 100 131 | 197 92 10 132 | 206 92 35 133 | 209 111 20 134 | 210 114 35 135 | 234 118 20 136 | 232 120 35 137 | 198 125 71 138 | 132 128 18 139 | 139 134 60 140 | 171 133 61 141 | 145 138 82 142 | 147 143 114 143 | 146 164 86 144 | 147 167 113 145 | 178 143 84 146 | 175 147 109 147 | 180 161 90 148 | 182 164 106 149 | 140 203 114 150 | 169 202 116 151 | 216 137 14 152 | 205 136 57 153 | 218 170 0 154 | 245 137 21 155 | 242 138 36 156 | 251 174 23 157 | 249 170 37 158 | 208 151 85 159 | 201 153 101 160 | 216 161 90 161 | 212 167 102 162 | 226 157 81 163 | 229 158 99 164 | 229 162 87 165 | 238 174 106 166 | 251 204 23 167 | 255 206 33 168 | 255 233 39 169 | 222 198 126 170 | 242 193 122 171 | 140 151 140 172 | 143 157 161 173 | 148 162 148 174 | 135 164 166 175 | 131 173 180 176 | 138 176 173 177 | 135 179 187 178 | 151 166 167 179 | 155 173 177 180 | 153 177 172 181 | 147 182 187 182 | 166 154 135 183 | 160 157 166 184 | 171 167 149 185 | 172 179 174 186 | 133 174 192 187 | 136 186 195 188 | 139 190 208 189 | 150 187 195 190 | 155 189 208 191 | 164 190 196 192 | 161 190 208 193 | 182 190 192 194 | 149 198 138 195 | 151 196 179 196 | 150 239 140 197 | 168 201 139 198 | 184 194 185 199 | 169 224 130 200 | 141 192 198 201 | 140 193 210 202 | 153 195 202 203 | 156 200 209 204 | 155 209 211 205 | 159 203 226 206 | 166 198 203 207 | 169 204 211 208 | 169 209 205 209 | 173 208 215 210 | 183 199 199 211 | 178 205 211 212 | 185 209 205 213 | 183 212 217 214 | 186 217 225 215 | 184 224 223 216 | 189 226 228 217 | 202 175 140 218 | 195 186 172 219 | 239 186 134 220 | 192 190 194 221 | 212 202 147 222 | 200 198 184 223 | 241 195 145 224 | 239 202 164 225 | 197 202 198 226 | 198 205 209 227 | 202 210 203 228 | 196 217 220 229 | 211 205 198 230 | 212 206 208 231 | 213 212 203 232 | 214 218 215 233 | 199 221 225 234 | 200 221 241 235 | 210 222 227 236 | 214 222 242 237 | 212 226 220 238 | 204 225 228 239 | 203 229 243 240 | 207 243 233 241 | 214 230 233 242 | 220 235 241 243 | 218 241 238 244 | 220 241 244 245 | 226 220 214 246 | 225 222 227 247 | 227 227 218 248 | 226 235 236 249 | 228 237 241 250 | 233 241 236 251 | 234 242 245 252 | 242 234 234 253 | 241 239 243 254 | 243 244 235 255 | 243 247 249 256 | 0 0 0 257 | 0 0 0 258 | 0 0 0 259 | 0 0 0 260 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/db16.gpl: -------------------------------------------------------------------------------- 1 | GIMP Palette 2 | Name: DB's Palette 3 | Columns: 8 4 | # 5 | 20 12 28 Dark1 6 | 68 36 52 Dark2 7 | 48 52 109 Dark3 8 | 78 74 78 Dark4 9 | 133 76 48 Dark5 10 | 52 101 36 Dark6 11 | 208 70 72 Dark7 12 | 117 113 97 Dark8 13 | 89 125 206 Light1 14 | 210 125 44 Light2 15 | 133 149 161 Light3 16 | 109 170 44 Light4 17 | 210 170 153 Light5 18 | 109 194 202 Light6 19 | 218 212 94 Light7 20 | 222 238 214 Light8 21 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/db32.gpl: -------------------------------------------------------------------------------- 1 | GIMP Palette 2 | Name: db32.gpl 3 | Columns: 8 4 | # 5 | 0 0 0 Black 6 | 34 32 52 Valhalla 7 | 69 40 60 Loulou 8 | 102 57 49 Oiled cedar 9 | 143 86 59 Rope 10 | 223 113 38 Tahiti gold 11 | 217 160 102 Twine 12 | 238 195 154 Pancho 13 | 251 242 54 Golden fizz 14 | 153 229 80 Atlantis 15 | 106 190 48 Christi 16 | 55 148 110 Elf green 17 | 75 105 47 Dell 18 | 82 75 36 Verdigris 19 | 50 60 57 Opal 20 | 63 63 116 Deep koamaru 21 | 48 96 130 Venice blue 22 | 91 110 225 Royal blue 23 | 99 155 255 Cornflower 24 | 95 205 228 Viking 25 | 203 219 252 Light steel blue 26 | 255 255 255 White 27 | 155 173 183 Heather 28 | 132 126 135 Topaz 29 | 105 106 106 Dim gray 30 | 89 86 82 Smokey ash 31 | 118 66 138 Clairvoyant 32 | 172 50 50 Brown 33 | 217 87 99 Mandy 34 | 215 123 186 Plum 35 | 143 151 74 Rain forest 36 | 138 111 48 Stinger 37 | -------------------------------------------------------------------------------- /ColorPicker/winapi/Sample-Palettes/grayscale.pal: -------------------------------------------------------------------------------- 1 | JASC-PAL 2 | 0100 3 | 254 4 | 0 0 0 5 | 1 1 1 6 | 2 2 2 7 | 3 3 3 8 | 4 4 4 9 | 5 5 5 10 | 6 6 6 11 | 7 7 7 12 | 8 8 8 13 | 9 9 9 14 | 10 10 10 15 | 11 11 11 16 | 12 12 12 17 | 13 13 13 18 | 14 14 14 19 | 15 15 15 20 | 16 16 16 21 | 17 17 17 22 | 18 18 18 23 | 19 19 19 24 | 20 20 20 25 | 21 21 21 26 | 22 22 22 27 | 23 23 23 28 | 24 24 24 29 | 25 25 25 30 | 26 26 26 31 | 27 27 27 32 | 28 28 28 33 | 29 29 29 34 | 30 30 30 35 | 31 31 31 36 | 32 32 32 37 | 33 33 33 38 | 34 34 34 39 | 35 35 35 40 | 36 36 36 41 | 37 37 37 42 | 38 38 38 43 | 39 39 39 44 | 40 40 40 45 | 41 41 41 46 | 42 42 42 47 | 43 43 43 48 | 44 44 44 49 | 45 45 45 50 | 46 46 46 51 | 47 47 47 52 | 48 48 48 53 | 49 49 49 54 | 50 50 50 55 | 51 51 51 56 | 52 52 52 57 | 53 53 53 58 | 54 54 54 59 | 55 55 55 60 | 56 56 56 61 | 57 57 57 62 | 58 58 58 63 | 59 59 59 64 | 60 60 60 65 | 61 61 61 66 | 62 62 62 67 | 63 63 63 68 | 64 64 64 69 | 65 65 65 70 | 66 66 66 71 | 67 67 67 72 | 68 68 68 73 | 69 69 69 74 | 70 70 70 75 | 71 71 71 76 | 72 72 72 77 | 73 73 73 78 | 74 74 74 79 | 75 75 75 80 | 76 76 76 81 | 77 77 77 82 | 78 78 78 83 | 79 79 79 84 | 80 80 80 85 | 81 81 81 86 | 82 82 82 87 | 83 83 83 88 | 84 84 84 89 | 85 85 85 90 | 86 86 86 91 | 87 87 87 92 | 88 88 88 93 | 89 89 89 94 | 90 90 90 95 | 91 91 91 96 | 92 92 92 97 | 93 93 93 98 | 94 94 94 99 | 95 95 95 100 | 96 96 96 101 | 97 97 97 102 | 98 98 98 103 | 99 99 99 104 | 100 100 100 105 | 101 101 101 106 | 102 102 102 107 | 103 103 103 108 | 104 104 104 109 | 105 105 105 110 | 106 106 106 111 | 107 107 107 112 | 108 108 108 113 | 109 109 109 114 | 110 110 110 115 | 111 111 111 116 | 112 112 112 117 | 113 113 113 118 | 114 114 114 119 | 115 115 115 120 | 116 116 116 121 | 117 117 117 122 | 118 118 118 123 | 119 119 119 124 | 120 120 120 125 | 121 121 121 126 | 122 122 122 127 | 123 123 123 128 | 124 124 124 129 | 125 125 125 130 | 126 126 126 131 | 127 127 127 132 | 128 128 128 133 | 129 129 129 134 | 130 130 130 135 | 131 131 131 136 | 132 132 132 137 | 133 133 133 138 | 134 134 134 139 | 135 135 135 140 | 136 136 136 141 | 137 137 137 142 | 138 138 138 143 | 139 139 139 144 | 140 140 140 145 | 141 141 141 146 | 142 142 142 147 | 143 143 143 148 | 144 144 144 149 | 145 145 145 150 | 146 146 146 151 | 147 147 147 152 | 148 148 148 153 | 149 149 149 154 | 150 150 150 155 | 151 151 151 156 | 152 152 152 157 | 153 153 153 158 | 154 154 154 159 | 155 155 155 160 | 156 156 156 161 | 157 157 157 162 | 158 158 158 163 | 159 159 159 164 | 160 160 160 165 | 161 161 161 166 | 162 162 162 167 | 163 163 163 168 | 164 164 164 169 | 165 165 165 170 | 166 166 166 171 | 167 167 167 172 | 168 168 168 173 | 169 169 169 174 | 170 170 170 175 | 171 171 171 176 | 172 172 172 177 | 173 173 173 178 | 174 174 174 179 | 175 175 175 180 | 176 176 176 181 | 177 177 177 182 | 178 178 178 183 | 179 179 179 184 | 180 180 180 185 | 181 181 181 186 | 182 182 182 187 | 183 183 183 188 | 184 184 184 189 | 185 185 185 190 | 186 186 186 191 | 187 187 187 192 | 188 188 188 193 | 189 189 189 194 | 190 190 190 195 | 191 191 191 196 | 192 192 192 197 | 193 193 193 198 | 194 194 194 199 | 195 195 195 200 | 196 196 196 201 | 197 197 197 202 | 198 198 198 203 | 199 199 199 204 | 200 200 200 205 | 201 201 201 206 | 202 202 202 207 | 203 203 203 208 | 204 204 204 209 | 205 205 205 210 | 206 206 206 211 | 207 207 207 212 | 208 208 208 213 | 209 209 209 214 | 210 210 210 215 | 211 211 211 216 | 212 212 212 217 | 213 213 213 218 | 214 214 214 219 | 215 215 215 220 | 216 216 216 221 | 217 217 217 222 | 218 218 218 223 | 219 219 219 224 | 220 220 220 225 | 221 221 221 226 | 222 222 222 227 | 223 223 223 228 | 224 224 224 229 | 225 225 225 230 | 226 226 226 231 | 227 227 227 232 | 228 228 228 233 | 229 229 229 234 | 230 230 230 235 | 231 231 231 236 | 232 232 232 237 | 233 233 233 238 | 234 234 234 239 | 235 235 235 240 | 236 236 236 241 | 237 237 237 242 | 238 238 238 243 | 239 239 239 244 | 240 240 240 245 | 241 241 241 246 | 242 242 242 247 | 243 243 243 248 | 244 244 244 249 | 245 245 245 250 | 246 246 246 251 | 247 247 247 252 | 248 248 248 253 | 249 249 249 254 | 250 250 250 255 | 251 251 251 256 | 252 252 252 257 | 253 253 253 258 | -------------------------------------------------------------------------------- /Context.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { "caption": "-", "id": "Color Highlighter" }, 3 | { "command": "color_highlighter_pick_color", "caption": "Insert color with color picker"}, 4 | { "command": "color_highlighter_next_color", "caption": "Convert color to the next format"}, 5 | { "command": "color_highlighter_previous_color", "caption": "Convert color to the previous format"} 6 | ] 7 | -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["super+shift+,"], 4 | "command": "color_highlighter_next_color", 5 | "context": [ 6 | { 7 | "key": "color_highlighter.color_highlighter_next_color" 8 | } 9 | ] 10 | }, 11 | { 12 | "keys": ["super+shift+."], 13 | "command": "color_highlighter_previous_color", 14 | "context": [ 15 | { 16 | "key": "color_highlighter.color_highlighter_previous_color" 17 | } 18 | ] 19 | }, 20 | { 21 | "keys": ["super+shift+c"], 22 | "command": "color_highlighter_pick_color", 23 | "context": [ 24 | { 25 | "key": "color_highlighter.color_highlighter_pick_color" 26 | } 27 | ] 28 | } 29 | ] 30 | -------------------------------------------------------------------------------- /Default.sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["ctrl+shift+,"], 4 | "command": "color_highlighter_next_color", 5 | "context": [ 6 | { 7 | "key": "color_highlighter.color_highlighter_next_color" 8 | } 9 | ] 10 | }, 11 | { 12 | "keys": ["ctrl+shift+."], 13 | "command": "color_highlighter_previous_color", 14 | "context": [ 15 | { 16 | "key": "color_highlighter.color_highlighter_previous_color" 17 | } 18 | ] 19 | }, 20 | { 21 | "keys": ["ctrl+shift+c"], 22 | "command": "color_highlighter_pick_color", 23 | "context": [ 24 | { 25 | "key": "color_highlighter.color_highlighter_pick_color" 26 | } 27 | ] 28 | } 29 | ] 30 | -------------------------------------------------------------------------------- /ci/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM buildpack-deps:jessie-scm 2 | 3 | LABEL \ 4 | Maintainer="Monnoroch" \ 5 | Description="This image contains utilities required to run CI scripts in color_highlighter project." 6 | 7 | # This code needs for ability to reset the docker build cache. 8 | RUN echo Dokerfile version: 1 9 | 10 | RUN \ 11 | echo "deb http://ftp.de.debian.org/debian unstable main" >> /etc/apt/sources.list && \ 12 | apt-get update && \ 13 | apt-get install -y --no-install-recommends apt-utils=1.0.* psmisc=22.2* python3.5=3.5.* python3-pip=9.0.* \ 14 | bzip2=1.0.* libgtk2.0-0=2.24.* xvfb=2:1.16* imagemagick=8:6.9.7.* && \ 15 | apt-get clean && \ 16 | rm -rf /var/lib/apt/lists/* 17 | 18 | RUN \ 19 | pip3 install setuptools==36.0.1 20 | 21 | WORKDIR /tmp 22 | 23 | RUN \ 24 | FILE_NAME="sublime_text_3_build_3143_x64.tar.bz2" && \ 25 | wget "https://download.sublimetext.com/$FILE_NAME" && \ 26 | tar -jxvf "$FILE_NAME" && \ 27 | mv sublime_text_3 /opt/sublime_text_3 && \ 28 | rm -rf /tmp/* 29 | 30 | RUN \ 31 | FILE_NAME="Sublime Text 2.0.2 x64.tar.bz2" && \ 32 | wget "https://download.sublimetext.com/$FILE_NAME" && \ 33 | tar -jxvf "$FILE_NAME" && \ 34 | mv "Sublime Text 2" /opt/sublime_text_2 && \ 35 | rm -rf /tmp/* 36 | 37 | WORKDIR /ColorHighlighter 38 | 39 | # Install linters. 40 | 41 | ARG LINTER_TOKEN 42 | 43 | RUN \ 44 | repo_path=/tmp/linters-repo && \ 45 | git clone "http://linter:${LINTER_TOKEN}@gitlab.gxservers.com/monno/linters.git" "${repo_path}" && \ 46 | (cd "${repo_path}" && git checkout 812c4a6cb2b894ed2f1efc3ca7abc32447c26e3e) && \ 47 | mkdir -p generated && \ 48 | linters=/opt/linters-system && \ 49 | mv "${repo_path}"/linters ${linters} && \ 50 | rm -rf "${repo_path}" && \ 51 | linters_generator=${linters}/linters-generator && \ 52 | curl -fksSL -o ${linters_generator} --header "PRIVATE-TOKEN: ${LINTER_TOKEN}" \ 53 | "http://gitlab.gxservers.com/monno/linters/builds/artifacts/master/raw/artifacts/generator?job=release" && \ 54 | chmod +x ${linters_generator} && \ 55 | ${linters_generator} -config ${linters} \ 56 | -tags python && \ 57 | ${linters}/generated/install-linux.sh 58 | 59 | RUN \ 60 | pip3 install pytest==3.1.2 mockito==1.0.12 61 | 62 | # This will create ~/.config/sublime-text-3 and ~/.config/sublime-text-2 and put the plugins there. 63 | RUN \ 64 | export DISPLAY=:1.0; \ 65 | (Xvfb :1 -screen 0 1024x768x16 &> /opt/xvfb.log &); \ 66 | sleep 3; \ 67 | (/opt/sublime_text_3/sublime_text &); \ 68 | sleep 5; \ 69 | (/opt/sublime_text_2/sublime_text &); \ 70 | sleep 5 71 | -------------------------------------------------------------------------------- /ci/integration-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Running $0..." 4 | 5 | export DISPLAY=:1.0 6 | 7 | Xvfb :1 -screen 0 1024x768x16 & 8 | XVFB_PID=$! 9 | 10 | sleep 5 11 | 12 | ci/run-integration-tests.sh 13 | exitcode=$? 14 | 15 | kill -9 "${XVFB_PID}" 16 | 17 | exit $exitcode 18 | -------------------------------------------------------------------------------- /ci/run-container.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | echo "Running $0..." 6 | 7 | PARSED=$(getopt -o "" --longoptions image:,name:,timeout: --name "$0" -- "$@") 8 | 9 | eval set -- "$PARSED" 10 | while true; do 11 | case "$1" in 12 | --image ) IMAGE_NAME="$2"; shift 2 ;; 13 | --name ) CONTAINER_NAME="$2"; shift 2 ;; 14 | --timeout ) TIMEOUT="$2"; shift 2 ;; 15 | * ) break ;; 16 | esac 17 | done 18 | 19 | if [[ ! ${IMAGE_NAME} ]] || [[ ! ${CONTAINER_NAME} ]] || [[ ! ${TIMEOUT} ]]; then 20 | echo "Error: Missing one or more of script arguments: \"image\", \"name\", \"timeout\"." 21 | exit 1 22 | fi 23 | 24 | docker run -d --rm --name "${CONTAINER_NAME}" "${IMAGE_NAME}" sleep "${TIMEOUT}" 25 | workdir=$(docker exec -i "${CONTAINER_NAME}" pwd) 26 | docker cp ./ "${CONTAINER_NAME}:${workdir}/" 27 | 28 | test_files=( 29 | __init__.py 30 | sublime.py 31 | sublime_plugin.py 32 | ) 33 | for file in "${test_files[@]}"; do 34 | docker exec -i "${CONTAINER_NAME}" cp "./tests/${file}" "${workdir}/${file}" 35 | done 36 | 37 | packages_dirs=( 38 | "/root/.config/sublime-text-3/Packages" 39 | "/root/.config/sublime-text-2/Packages" 40 | ) 41 | plugin_name="ColorHighlighter" 42 | for packages in "${packages_dirs[@]}"; do 43 | docker exec -i "${CONTAINER_NAME}" mkdir ${packages}/${plugin_name} 44 | docker exec -i "${CONTAINER_NAME}" mkdir ${packages}/0_test_plugin 45 | 46 | test_files=( 47 | __init__.py 48 | flushing_file.py 49 | main.py 50 | ) 51 | 52 | for file in "${test_files[@]}"; do 53 | docker cp "./test_plugin/${file}" "${CONTAINER_NAME}:${packages}/0_test_plugin/${file}" 54 | done 55 | 56 | for file in *.py; do 57 | docker cp "./${file}" "${CONTAINER_NAME}:${packages}/${plugin_name}/${file}" 58 | done 59 | docker cp "./elementtree" "${CONTAINER_NAME}:${packages}/${plugin_name}/elementtree" 60 | docker cp "./ColorPicker" "${CONTAINER_NAME}:${packages}/${plugin_name}/ColorPicker" 61 | 62 | settings_files=( 63 | "ColorHighlighter.sublime-settings" 64 | "Context.sublime-menu" 65 | "Main.sublime-menu" 66 | "Default.sublime-keymap" 67 | "Default (OSX).sublime-keymap" 68 | ) 69 | for file in "${settings_files[@]}"; do 70 | docker cp "./${file}" "${CONTAINER_NAME}:${packages}/${plugin_name}/${file}" 71 | done 72 | docker cp "./integration_tests/ColorHighlighter.ss" \ 73 | "${CONTAINER_NAME}:${packages}/${plugin_name}/ColorHighlighter.sublime-settings" 74 | done 75 | -------------------------------------------------------------------------------- /ci/run-integration-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Running $0 $1..." 4 | 5 | $1 6 | exitcode=$? 7 | 8 | rm -r \ 9 | /root/.config/sublime-text-3/Packages/User/Preferences.sublime-settings \ 10 | /root/.config/sublime-text-3/Packages/User/ColorHighlighter \ 11 | /root/.config/sublime-text-2/Packages/User/Preferences.sublime-settings \ 12 | /root/.config/sublime-text-2/Packages/User/ColorHighlighter 13 | 14 | exit $exitcode 15 | -------------------------------------------------------------------------------- /ci/run-integration-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | echo "Running $0..." 6 | 7 | ci/run-integration-test.sh integration_tests/st3/test-empty.sh 8 | ci/run-integration-test.sh integration_tests/st3/test-white.sh 9 | ci/run-integration-test.sh integration_tests/st2/test-empty.sh 10 | -------------------------------------------------------------------------------- /ci/run-linters.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | echo "Running $0..." 6 | 7 | PARSED=$(getopt -o "" --longoptions container: --name "$0" -- "$@") 8 | 9 | eval set -- "$PARSED" 10 | while true; do 11 | case "$1" in 12 | --container ) container_name="$2"; shift 2 ;; 13 | * ) break ;; 14 | esac 15 | done 16 | 17 | if [[ ! ${container_name} ]]; then 18 | echo "Error: Missing \"container\" script argument." 19 | exit 1 20 | fi 21 | 22 | ENDLINECHECK_EXCLUDE="ColorPicker/ColorPicker_linux_x32" 23 | ENDLINECHECK_EXCLUDE="$ENDLINECHECK_EXCLUDE:ColorPicker/ColorPicker_linux_x64" 24 | ENDLINECHECK_EXCLUDE="$ENDLINECHECK_EXCLUDE:ColorPicker/ColorPicker_osx_x64" 25 | ENDLINECHECK_EXCLUDE="$ENDLINECHECK_EXCLUDE:ColorPicker/ColorPicker_win.exe" 26 | ENDLINECHECK_EXCLUDE="$ENDLINECHECK_EXCLUDE:ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/Resources/eyedropper.cur" 27 | ENDLINECHECK_EXCLUDE="$ENDLINECHECK_EXCLUDE:ColorPicker/winapi/Cyotek.Windows.Forms.ColorPicker/cyopublic.snk" 28 | ENDLINECHECK_EXCLUDE="$ENDLINECHECK_EXCLUDE:ColorPicker/winapi/Sample-Palettes/background.lbm" 29 | 30 | docker exec -e ENDLINECHECK_EXCLUDE="${ENDLINECHECK_EXCLUDE}" -i "${container_name}" \ 31 | /opt/linters-system/generated/run-linux.sh 32 | -------------------------------------------------------------------------------- /ci/test-python.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | echo "Running $0..." 6 | 7 | py.test 8 | -------------------------------------------------------------------------------- /color_hover_listener.py: -------------------------------------------------------------------------------- 1 | """Component for listening for selection changes in a view and highlighting selected colors.""" 2 | 3 | try: 4 | from . import st_helper 5 | from .regions import NormalizedRegion, intersects 6 | except ValueError: 7 | import st_helper 8 | from regions import NormalizedRegion, intersects 9 | 10 | 11 | if st_helper.running_in_st(): 12 | import sublime # pylint: disable=import-error 13 | else: 14 | from . import sublime 15 | 16 | 17 | class ColorHoverListener(object): 18 | """Component for listening for cursor position changes in a view and highlighting colors under the cursor.""" 19 | 20 | def __init__(self, color_searcher, view, color_highlighter): 21 | """ 22 | Init ColorSelectionListener. 23 | 24 | Arguments: 25 | - color_searcher - a color searcher to search colors with. 26 | - view - a view to highlight colors in. 27 | - color_highlighter - a combined color highlighter to highlight colors with. 28 | """ 29 | self._color_searcher = color_searcher 30 | self._view = view 31 | self._color_highlighter = color_highlighter 32 | self._selection = [] 33 | self._regions = [] 34 | self._point = None 35 | 36 | def on_hover(self, point, hover_zone): 37 | """ 38 | on_hover event. 39 | 40 | Arguments: 41 | - point - the position of the cursor. 42 | - hover_zone - the soze where the cursor is currently. 43 | """ 44 | if hover_zone != sublime.HOVER_TEXT: 45 | self._unhighlight() 46 | return 47 | self._point = point 48 | self._update_highlighting() 49 | 50 | def on_modified(self): 51 | """on_modified event.""" 52 | if _intersects(self._regions, self._selection): 53 | self._update_highlighting() 54 | 55 | def on_selection_modified(self): 56 | """on_selection_modified event.""" 57 | new_selection = [NormalizedRegion(region) for region in self._view.sel()] 58 | if self._selection != new_selection: 59 | self._selection = new_selection 60 | self._on_selection_really_modified() 61 | 62 | def _unhighlight(self): 63 | self._color_highlighter.highlight_regions([]) 64 | 65 | def _update_highlighting(self): 66 | color_regions = self._generate_color_regions(self._point) 67 | self._color_highlighter.highlight_regions(color_regions) 68 | 69 | def _on_selection_really_modified(self): 70 | if not _intersects(self._regions, self._selection): 71 | self._unhighlight() 72 | 73 | def _generate_color_regions(self, point): 74 | self._regions = [] 75 | region = sublime.Region(point, point) 76 | normalized_region = NormalizedRegion(region) 77 | for line in self._view.lines(region): 78 | for (region, color, _) in self._color_searcher.search(self._view, NormalizedRegion(line)): 79 | if intersects(region, normalized_region): 80 | self._regions.append(region) 81 | yield (region, color) 82 | 83 | 84 | def _intersects(regions1, regions2): 85 | for region1 in regions1: 86 | for region2 in regions2: 87 | if intersects(region1, region2): 88 | return True 89 | return False 90 | -------------------------------------------------------------------------------- /color_searcher.py: -------------------------------------------------------------------------------- 1 | """The module with tools for searching for colors in ST views.""" 2 | 3 | try: 4 | from . import regions 5 | except ValueError: 6 | import regions 7 | 8 | 9 | class ColorSearcher(object): 10 | """Class for searching for colors in ST views.""" 11 | 12 | def __init__(self, regex, color_converter): 13 | """ 14 | Init a ColorSearcher. 15 | 16 | Arguments: 17 | - regex - the regex for matching colors. 18 | - color_converter - the color converter to convert color text into cannical form. 19 | """ 20 | self._color_regex = regex 21 | self._color_converter = color_converter 22 | 23 | def search(self, view, region): 24 | """ 25 | Get a region with a color in the view. 26 | 27 | Given a region, yield regions inside of it that contain colors. 28 | Arguments: 29 | - view - the view to look in. 30 | - region - the initial region to look around. 31 | Yields tuples of of NormalizedRegion-s, canonical colors that are in this regions and color matches for them. 32 | """ 33 | region_text = view.substr(region.region()) 34 | match = self._color_regex.search(region_text) 35 | while match: 36 | start = match.start() 37 | end = match.end() 38 | color_region = regions.NormalizedRegion(region.a + start, region.a + end) 39 | groups = match.groupdict() 40 | color = self._color_converter.to_color(groups) 41 | if color is not None: 42 | yield color_region, color, groups 43 | match = self._color_regex.search(region_text, end) 44 | -------------------------------------------------------------------------------- /color_selection_listener.py: -------------------------------------------------------------------------------- 1 | """Component for listening for selection changes in a view and highlighting selected colors.""" 2 | 3 | try: 4 | from .regions import NormalizedRegion, intersects_any, deduplicate_regions 5 | except ValueError: 6 | from regions import NormalizedRegion, intersects_any, deduplicate_regions 7 | 8 | 9 | class ColorSelectionListener(object): 10 | """Component for listening for selection changes in a view and highlighting selected colors.""" 11 | 12 | def __init__(self, color_searcher, view, color_highlighter): 13 | """ 14 | Init ColorSelectionListener. 15 | 16 | Arguments: 17 | - color_searcher - a color searcher to search colors with. 18 | - view - a view to highlight colors in. 19 | - color_highlighter - a combined color highlighter to highlight colors with. 20 | """ 21 | self._color_searcher = color_searcher 22 | self._view = view 23 | self._color_highlighter = color_highlighter 24 | self._selection = [] 25 | 26 | def on_selection_modified(self): 27 | """ 28 | Call when view's selection was modified. 29 | 30 | Because ST sometimes call EventListener.on_selection_modified even when the selection didn't change, this class 31 | also handles such cases by ignoring them. 32 | """ 33 | new_selection = [region for region in self._view.sel()] 34 | if self._selection != new_selection: 35 | self._selection = new_selection 36 | self._on_selection_really_modified() 37 | 38 | def on_modified(self): 39 | """on_modified event.""" 40 | self._on_selection_really_modified() 41 | 42 | def _on_selection_really_modified(self): 43 | color_regions = _drop_match(_generate_color_regions(self._view, self._color_searcher, self._selection)) 44 | self._color_highlighter.highlight_regions(color_regions) 45 | 46 | 47 | def search_colors_in_selection(view, color_searcher): 48 | """ 49 | Search colors in selection. 50 | 51 | Arguments: 52 | - view - the view to search colors in. 53 | - color_searcher - the color searcher to search colors with. 54 | """ 55 | return _generate_color_regions(view, color_searcher, view.sel()) 56 | 57 | 58 | def _drop_match(values): 59 | for value in values: 60 | yield (value[0], value[1]) 61 | 62 | 63 | def _generate_color_regions(view, color_searcher, regions): 64 | normalized_regions = [NormalizedRegion(region) for region in regions] 65 | for line in deduplicate_regions(_generate_lines(view, regions)): 66 | for color_data in color_searcher.search(view, line): 67 | if intersects_any(color_data[0], normalized_regions): 68 | yield color_data 69 | 70 | 71 | def _generate_lines(view, regions): 72 | for region in regions: 73 | for line in view.lines(region): 74 | yield NormalizedRegion(line) 75 | -------------------------------------------------------------------------------- /colors.py: -------------------------------------------------------------------------------- 1 | """A module with tools for working with colors.""" 2 | 3 | import colorsys 4 | 5 | 6 | def normalize_hex_color(color): 7 | """ 8 | Normalize any hex color to #RRGGBBAA format. 9 | 10 | Arguments: 11 | - color - the color to normalize. 12 | Returns normalized color in #RRGGBBAA format. 13 | """ 14 | while len(color) < 9: 15 | color += "F" 16 | return color 17 | 18 | 19 | def background_color_for_text_workaround(background_color, theme_background_color): # pylint: disable=invalid-name 20 | """ 21 | Background color bug workaround for ST. 22 | 23 | If one to set for a scope background color identical to the global background color, it doesn't work properly. 24 | Because of that, one needs to use this hack, which does a minimal change to the input color's green channel. 25 | Thus, after this transformation the color will be different from the background color and will be displayed 26 | correctly. This new color, whle different, is very hard to distinguish from the original color, so from the UX 27 | perspective, everything's fine. 28 | Argumetns: 29 | - background_color - the color to be used as a background color for a scope. 30 | - theme_background_color - the theme's backgroud color. 31 | Returns a background_color if it's not the same as the theme_background_color or a slightly modified 32 | background_color, if it is the same. 33 | """ 34 | if background_color != theme_background_color: 35 | return background_color 36 | 37 | second_blue_symbol = background_color[-3] 38 | if second_blue_symbol == 'F': 39 | second_blue_symbol = 'E' 40 | else: 41 | second_blue_symbol = hex(int(second_blue_symbol, 16) + 1)[2:] 42 | return background_color[:-3] + second_blue_symbol + background_color[-2:] 43 | 44 | 45 | def rgb_to_hex(r, g, b): # pylint: disable=invalid-name 46 | """ 47 | Convert numeric r, g, b color channels to a hex standard #RRGGBBAA color format. 48 | 49 | Arguments: 50 | - r - red channel in (0, 255). 51 | - g - green channel in (0, 255). 52 | - b - blue channel in (0, 255). 53 | """ 54 | return "#%02X%02X%02XFF" % (r, g, b) 55 | 56 | 57 | def complementary_color(color): 58 | """ 59 | Get a complementary color to the input color. 60 | 61 | For example, white is the complementary color for black, yellow for cyan, etc. 62 | Argumets: 63 | - color - color in #RRGGBBAA format. 64 | Returns the complementary color to the input color. 65 | """ 66 | (h, l, s) = colorsys.rgb_to_hls( # pylint: disable=invalid-name 67 | int(color[1:3], 16) / 255.0, int(color[3:5], 16) / 255.0, int(color[5:7], 16) / 255.0) 68 | new_l = 1 - l 69 | if abs(new_l - l) < .15: 70 | new_l = .15 71 | (r, g, b) = colorsys.hls_to_rgb(h, new_l, s) # pylint: disable=invalid-name 72 | return rgb_to_hex(int(r * 255), int(g * 255), int(b * 255)) 73 | -------------------------------------------------------------------------------- /content_listener.py: -------------------------------------------------------------------------------- 1 | """Component for listening for loaded views and highlighting colors in them.""" 2 | 3 | try: 4 | from .regions import NormalizedRegion, deduplicate_regions 5 | except ValueError: 6 | from regions import NormalizedRegion, deduplicate_regions 7 | 8 | 9 | class ContentListener(object): 10 | """Component for listening for loaded views and highlighting colors in them.""" 11 | 12 | def __init__(self, color_searcher, view, color_highlighter): 13 | """ 14 | Init ContentListener. 15 | 16 | Arguments: 17 | - color_searcher - a color searcher to search colors with. 18 | - view - a view to highlight colors in. 19 | - color_highlighter - a combined color highlighter to highlight colors with. 20 | """ 21 | self._color_searcher = color_searcher 22 | self._view = view 23 | self._color_highlighter = color_highlighter 24 | 25 | def on_load(self): 26 | """Call when view's content is loaded.""" 27 | color_regions = self._generate_color_regions() 28 | self._color_highlighter.highlight_regions(color_regions) 29 | 30 | def on_modified(self): 31 | """on_modified event.""" 32 | lines = deduplicate_regions(self._generate_lines_for_selection()) 33 | color_regions = self._generate_color_regions_for_selection(lines) 34 | self._color_highlighter.highlight_regions_in(color_regions, lines) 35 | 36 | def _generate_color_regions(self): 37 | for line in self._generate_lines(): 38 | for (region, color, _) in self._color_searcher.search(self._view, line): 39 | yield (region, color) 40 | 41 | def _generate_lines(self): 42 | for line in self._view.lines(NormalizedRegion(0, self._view.size()).region()): 43 | yield NormalizedRegion(line) 44 | 45 | def _generate_color_regions_for_selection(self, lines): 46 | for line in lines: 47 | for (region, color, _) in self._color_searcher.search(self._view, line): 48 | yield (region, color) 49 | 50 | def _generate_lines_for_selection(self): 51 | for region in self._view.sel(): 52 | for line in self._view.lines(region): 53 | yield NormalizedRegion(line) 54 | -------------------------------------------------------------------------------- /convert_color_command.py: -------------------------------------------------------------------------------- 1 | """A ST3 commands for converting colors between formats.""" 2 | 3 | try: 4 | from . import st_helper 5 | from .color_converter import ColorConverter 6 | from .color_searcher import ColorSearcher 7 | from .color_selection_listener import search_colors_in_selection 8 | from .regex_compiler import compile_regex 9 | from .settings import Settings, COLOR_HIGHLIGHTER_SETTINGS_NAME 10 | except ValueError: 11 | import st_helper 12 | from color_converter import ColorConverter 13 | from color_searcher import ColorSearcher 14 | from color_selection_listener import search_colors_in_selection 15 | from regex_compiler import compile_regex 16 | from settings import Settings, COLOR_HIGHLIGHTER_SETTINGS_NAME 17 | 18 | 19 | if st_helper.running_in_st(): 20 | import sublime # pylint: disable=import-error 21 | import sublime_plugin # pylint: disable=import-error 22 | else: 23 | from . import sublime 24 | from . import sublime_plugin 25 | 26 | 27 | class ColorHighlighterNextColor(sublime_plugin.TextCommand): 28 | """Convert currently selected colors to a next color format.""" 29 | 30 | def run(self, edit): 31 | """ 32 | Run the command. 33 | 34 | Arguments: 35 | - edit - an edit object. 36 | """ 37 | settings = Settings(sublime.load_settings(COLOR_HIGHLIGHTER_SETTINGS_NAME)) 38 | formats = [value for value in sorted(settings.regex_compiler.formats.keys())] 39 | color_converter = ColorConverter(formats) 40 | for (region, color, format_name) in _get_colors(self.view, settings, formats, color_converter): 41 | index = formats.index(format_name) + 1 42 | if index == len(formats): 43 | index = 0 44 | new_format = formats[index] 45 | new_color = color_converter.from_color((color, new_format)) 46 | if settings.debug: 47 | print(("ColorHighlighter: action=run_command name=color_highlighter_next_color region=%s format=%s " + 48 | "color=%s new_format=%s new_color=%s") 49 | % (str(region.region()), format_name, color, new_format, new_color)) 50 | self.view.replace(edit, region.region(), new_color) 51 | 52 | def is_visible(self): 53 | """Check if the command can be ran.""" 54 | return _any_colors_selected(self.view) 55 | 56 | 57 | class ColorHighlighterPreviousColor(sublime_plugin.TextCommand): 58 | """Convert currently selected colors to a prevoius color format.""" 59 | 60 | def run(self, edit): 61 | """ 62 | Run the command. 63 | 64 | Arguments: 65 | - edit - an edit object. 66 | """ 67 | settings = Settings(sublime.load_settings(COLOR_HIGHLIGHTER_SETTINGS_NAME)) 68 | formats = [value for value in sorted(settings.regex_compiler.formats.keys())] 69 | color_converter = ColorConverter(formats) 70 | for (region, color, format_name) in _get_colors(self.view, settings, formats, color_converter): 71 | index = formats.index(format_name) - 1 72 | if index == -1: 73 | index = len(formats) - 1 74 | new_format = formats[index] 75 | new_color = color_converter.from_color((color, new_format)) 76 | if settings.debug: 77 | print(("ColorHighlighter: action=run_command name=color_highlighter_previous_color region=%s " + 78 | "format=%s color=%s new_format=%s new_color=%s") 79 | % (str(region.region()), format_name, color, new_format, new_color)) 80 | self.view.replace(edit, region.region(), new_color) 81 | 82 | def is_visible(self): 83 | """Check if the command can be ran.""" 84 | return _any_colors_selected(self.view) 85 | 86 | 87 | def _get_colors(view, settings, formats, color_converter): 88 | color_searcher = ColorSearcher(compile_regex(settings.regex_compiler), color_converter) 89 | for (region, color, match) in search_colors_in_selection(view, color_searcher): 90 | format_name = _get_format_name(match, formats) 91 | yield region, color, format_name 92 | 93 | 94 | def _any_colors_selected(view): 95 | settings = Settings(sublime.load_settings(COLOR_HIGHLIGHTER_SETTINGS_NAME)) 96 | formats = [value for value in sorted(settings.regex_compiler.formats.keys())] 97 | color_converter = ColorConverter(formats) 98 | color_searcher = ColorSearcher(compile_regex(settings.regex_compiler), color_converter) 99 | for _ in search_colors_in_selection(view, color_searcher): 100 | return True 101 | return False 102 | 103 | 104 | def _get_format_name(match, formats): 105 | for name in formats: 106 | if match.get(name, None) is not None: 107 | return name 108 | raise Exception("Unreachable code.") 109 | -------------------------------------------------------------------------------- /css_colors.py: -------------------------------------------------------------------------------- 1 | """ 2 | HTML color names. 3 | 4 | For more details, see https://developer.mozilla.org/ru/docs/Web/CSS/color_value. 5 | """ 6 | 7 | COLOR_NAMES_TO_HEX = { 8 | """ 9 | A map of HTML color names to their hex values. 10 | """ 11 | 12 | "black": "#000000ff", 13 | "silver": "#c0c0c0ff", 14 | "gray": "#808080ff", 15 | "white": "#ffffffff", 16 | "maroon": "#800000ff", 17 | "red": "#ff0000ff", 18 | "purple": "#800080ff", 19 | "fuchsia": "#ff00ffff", 20 | "green": "#008000ff", 21 | "lime": "#00ff00ff", 22 | "olive": "#808000ff", 23 | "yellow": "#ffff00ff", 24 | "navy": "#000080ff", 25 | "blue": "#0000ffff", 26 | "teal": "#008080ff", 27 | "aqua": "#00ffffff", 28 | "orange": "#ffa500ff", 29 | "aliceblue": "#f0f8ffff", 30 | "antiquewhite": "#faebd7ff", 31 | "aquamarine": "#7fffd4ff", 32 | "azure": "#f0ffffff", 33 | "beige": "#f5f5dcff", 34 | "bisque": "#ffe4c4ff", 35 | "blanchedalmond": "#ffebcdff", 36 | "blueviolet": "#8a2be2ff", 37 | "brown": "#a52a2aff", 38 | "burlywood": "#deb887ff", 39 | "cadetblue": "#5f9ea0ff", 40 | "chartreuse": "#7fff00ff", 41 | "chocolate": "#d2691eff", 42 | "coral": "#ff7f50ff", 43 | "cornflowerblue": "#6495edff", 44 | "cornsilk": "#fff8dcff", 45 | "crimson": "#dc143cff", 46 | "cyan": "#00ffffff", 47 | "darkblue": "#00008bff", 48 | "darkcyan": "#008b8bff", 49 | "darkgoldenrod": "#b8860bff", 50 | "darkgray": "#a9a9a9ff", 51 | "darkgreen": "#006400ff", 52 | "darkgrey": "#a9a9a9ff", 53 | "darkkhaki": "#bdb76bff", 54 | "darkmagenta": "#8b008bff", 55 | "darkolivegreen": "#556b2fff", 56 | "darkorange": "#ff8c00ff", 57 | "darkorchid": "#9932ccff", 58 | "darkred": "#8b0000ff", 59 | "darksalmon": "#e9967aff", 60 | "darkseagreen": "#8fbc8fff", 61 | "darkslateblue": "#483d8bff", 62 | "darkslategray": "#2f4f4fff", 63 | "darkslategrey": "#2f4f4fff", 64 | "darkturquoise": "#00ced1ff", 65 | "darkviolet": "#9400d3ff", 66 | "deeppink": "#ff1493ff", 67 | "deepskyblue": "#00bfffff", 68 | "dimgray": "#696969ff", 69 | "dimgrey": "#696969ff", 70 | "dodgerblue": "#1e90ffff", 71 | "firebrick": "#b22222ff", 72 | "floralwhite": "#fffaf0ff", 73 | "forestgreen": "#228b22ff", 74 | "gainsboro": "#dcdcdcff", 75 | "ghostwhite": "#f8f8ffff", 76 | "gold": "#ffd700ff", 77 | "goldenrod": "#daa520ff", 78 | "greenyellow": "#adff2fff", 79 | "grey": "#808080ff", 80 | "honeydew": "#f0fff0ff", 81 | "hotpink": "#ff69b4ff", 82 | "indianred": "#cd5c5cff", 83 | "indigo": "#4b0082ff", 84 | "ivory": "#fffff0ff", 85 | "khaki": "#f0e68cff", 86 | "lavender": "#e6e6faff", 87 | "lavenderblush": "#fff0f5ff", 88 | "lawngreen": "#7cfc00ff", 89 | "lemonchiffon": "#fffacdff", 90 | "lightblue": "#add8e6ff", 91 | "lightcoral": "#f08080ff", 92 | "lightcyan": "#e0ffffff", 93 | "lightgoldenrodyellow": "#fafad2ff", 94 | "lightgray": "#d3d3d3ff", 95 | "lightgreen": "#90ee90ff", 96 | "lightgrey": "#d3d3d3ff", 97 | "lightpink": "#ffb6c1ff", 98 | "lightsalmon": "#ffa07aff", 99 | "lightseagreen": "#20b2aaff", 100 | "lightskyblue": "#87cefaff", 101 | "lightslategray": "#778899ff", 102 | "lightslategrey": "#778899ff", 103 | "lightsteelblue": "#b0c4deff", 104 | "lightyellow": "#ffffe0ff", 105 | "limegreen": "#32cd32ff", 106 | "linen": "#faf0e6ff", 107 | "magenta": "#ff00ffff", 108 | "mediumaquamarine": "#66cdaaff", 109 | "mediumblue": "#0000cdff", 110 | "mediumorchid": "#ba55d3ff", 111 | "mediumpurple": "#9370dbff", 112 | "mediumseagreen": "#3cb371ff", 113 | "mediumslateblue": "#7b68eeff", 114 | "mediumspringgreen": "#00fa9aff", 115 | "mediumturquoise": "#48d1ccff", 116 | "mediumvioletred": "#c71585ff", 117 | "midnightblue": "#191970ff", 118 | "mintcream": "#f5fffaff", 119 | "mistyrose": "#ffe4e1ff", 120 | "moccasin": "#ffe4b5ff", 121 | "navajowhite": "#ffdeadff", 122 | "oldlace": "#fdf5e6ff", 123 | "olivedrab": "#6b8e23ff", 124 | "orangered": "#ff4500ff", 125 | "orchid": "#da70d6ff", 126 | "palegoldenrod": "#eee8aaff", 127 | "palegreen": "#98fb98ff", 128 | "paleturquoise": "#afeeeeff", 129 | "palevioletred": "#db7093ff", 130 | "papayawhip": "#ffefd5ff", 131 | "peachpuff": "#ffdab9ff", 132 | "peru": "#cd853fff", 133 | "pink": "#ffc0cbff", 134 | "plum": "#dda0ddff", 135 | "powderblue": "#b0e0e6ff", 136 | "rosybrown": "#bc8f8fff", 137 | "royalblue": "#4169e1ff", 138 | "saddlebrown": "#8b4513ff", 139 | "salmon": "#fa8072ff", 140 | "sandybrown": "#f4a460ff", 141 | "seagreen": "#2e8b57ff", 142 | "seashell": "#fff5eeff", 143 | "sienna": "#a0522dff", 144 | "skyblue": "#87ceebff", 145 | "slateblue": "#6a5acdff", 146 | "slategray": "#708090ff", 147 | "slategrey": "#708090ff", 148 | "snow": "#fffafaff", 149 | "springgreen": "#00ff7fff", 150 | "steelblue": "#4682b4ff", 151 | "tan": "#d2b48cff", 152 | "thistle": "#d8bfd8ff", 153 | "tomato": "#ff6347ff", 154 | "turquoise": "#40e0d0ff", 155 | "violet": "#ee82eeff", 156 | "wheat": "#f5deb3ff", 157 | "whitesmoke": "#f5f5f5ff", 158 | "yellowgreen": "#9acd32ff", 159 | "rebeccapurple": "#663399ff" 160 | } 161 | -------------------------------------------------------------------------------- /docs/theme/extra.css: -------------------------------------------------------------------------------- 1 | .md-typeset .keys kbd::before, 2 | .md-typeset .keys kbd::after { 3 | position: relative; 4 | margin: 0; 5 | color: #bdbdbd; 6 | font-family: sans-serif; 7 | -moz-osx-font-smoothing: initial; 8 | -webkit-font-smoothing: initial; 9 | font-weight: 400; 10 | } 11 | 12 | .md-typeset .keys span { 13 | padding: 0 0.2rem; 14 | color: #bdbdbd; 15 | } 16 | 17 | .md-typeset .keys .key-backspace::before { 18 | padding-left: 0.2rem; 19 | content: "←"; 20 | } 21 | 22 | .md-typeset .keys .key-command::before { 23 | padding-left: 0.2rem; 24 | content: "⌘"; 25 | } 26 | 27 | .md-typeset .keys .key-windows::before { 28 | padding-left: 0.2rem; 29 | content: "⊞"; 30 | } 31 | 32 | .md-typeset .keys .key-caps-lock::before { 33 | padding-left: 0.2rem; 34 | content: "⇪"; 35 | } 36 | 37 | .md-typeset .keys .key-control::before { 38 | padding-left: 0.2rem; 39 | content: "⌃"; 40 | } 41 | 42 | .md-typeset .keys .key-meta::before { 43 | padding-left: 0.2rem; 44 | content: "◆"; 45 | } 46 | 47 | .md-typeset .keys .key-shift::before { 48 | padding-left: 0.2rem; 49 | content: "⇧"; 50 | } 51 | 52 | .md-typeset .keys .key-option::before { 53 | padding-left: 0.2rem; 54 | content: "⌥"; 55 | } 56 | 57 | .md-typeset .keys .key-tab::after { 58 | padding-left: 0.2rem; 59 | content: "↹"; 60 | } 61 | 62 | .md-typeset .keys .key-num-enter::after { 63 | padding-left: 0.2rem; 64 | content: "↵"; 65 | } 66 | 67 | .md-typeset .keys .key-enter::after { 68 | padding-left: 0.2rem; 69 | content: "↩"; 70 | } 71 | -------------------------------------------------------------------------------- /docs/theme/partials/footer.html: -------------------------------------------------------------------------------- 1 | {% import "partials/language.html" as lang %} 2 | 61 | -------------------------------------------------------------------------------- /dummy_event_listener.py: -------------------------------------------------------------------------------- 1 | """A dummy event listener.""" 2 | 3 | 4 | class DummyEventListener(object): 5 | """ 6 | An event listener that ignores events. 7 | 8 | Supposed to be used in place of any other event listener when it is disabled. 9 | """ 10 | 11 | def __init__(self): 12 | """Init ColorSelectionListener.""" 13 | pass 14 | 15 | def on_selection_modified(self): 16 | """Call when view's selection was modified.""" 17 | pass 18 | 19 | def on_load(self): 20 | """Call when view's content is loaded.""" 21 | pass 22 | 23 | def on_hover(self, point, hover_zone): 24 | """on_hover event.""" 25 | pass 26 | 27 | def on_modified(self): 28 | """on_modified event.""" 29 | pass 30 | -------------------------------------------------------------------------------- /elementtree/SimpleXMLTreeBuilder.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | # pylint: skip-file 3 | 4 | # 5 | # ElementTree 6 | # $Id$ 7 | # 8 | # A simple XML tree builder, based on Python's xmllib 9 | # 10 | # Note that due to bugs in xmllib, this builder does not fully support 11 | # namespaces (unqualified attributes are put in the default namespace, 12 | # instead of being left as is). Run this module as a script to find 13 | # out if this affects your Python version. 14 | # 15 | # history: 16 | # 2001-10-20 fl created 17 | # 2002-05-01 fl added namespace support for xmllib 18 | # 2002-08-17 fl added xmllib sanity test 19 | # 20 | # Copyright (c) 1999-2004 by Fredrik Lundh. All rights reserved. 21 | # 22 | # fredrik@pythonware.com 23 | # http://www.pythonware.com 24 | # 25 | # -------------------------------------------------------------------- 26 | # The ElementTree toolkit is 27 | # 28 | # Copyright (c) 1999-2004 by Fredrik Lundh 29 | # 30 | # By obtaining, using, and/or copying this software and/or its 31 | # associated documentation, you agree that you have read, understood, 32 | # and will comply with the following terms and conditions: 33 | # 34 | # Permission to use, copy, modify, and distribute this software and 35 | # its associated documentation for any purpose and without fee is 36 | # hereby granted, provided that the above copyright notice appears in 37 | # all copies, and that both that copyright notice and this permission 38 | # notice appear in supporting documentation, and that the name of 39 | # Secret Labs AB or the author not be used in advertising or publicity 40 | # pertaining to distribution of the software without specific, written 41 | # prior permission. 42 | # 43 | # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD 44 | # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- 45 | # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR 46 | # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 47 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 48 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 49 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 50 | # OF THIS SOFTWARE. 51 | # -------------------------------------------------------------------- 52 | 53 | ## 54 | # Tools to build element trees from XML files, using xmllib. 55 | # This module can be used instead of the standard tree builder, for 56 | # Python versions where "expat" is not available (such as 1.5.2). 57 | #

58 | # Note that due to bugs in xmllib, the namespace support is 59 | # not reliable (you can run the module as a script to find out exactly 60 | # how unreliable it is on your Python version). 61 | ## 62 | 63 | import xmllib 64 | import string 65 | 66 | import ElementTree 67 | 68 | ## 69 | # ElementTree builder for XML source data. 70 | # 71 | # @see elementtree.ElementTree 72 | 73 | 74 | class TreeBuilder(xmllib.XMLParser): 75 | 76 | def __init__(self, html=0): 77 | self.__builder = ElementTree.TreeBuilder() 78 | if html: 79 | import htmlentitydefs 80 | self.entitydefs.update(htmlentitydefs.entitydefs) 81 | xmllib.XMLParser.__init__(self) 82 | 83 | ## 84 | # Feeds data to the parser. 85 | # 86 | # @param data Encoded data. 87 | 88 | def feed(self, data): 89 | xmllib.XMLParser.feed(self, data) 90 | 91 | ## 92 | # Finishes feeding data to the parser. 93 | # 94 | # @return An element structure. 95 | # @defreturn Element 96 | 97 | def close(self): 98 | xmllib.XMLParser.close(self) 99 | return self.__builder.close() 100 | 101 | def handle_data(self, data): 102 | self.__builder.data(data) 103 | 104 | handle_cdata = handle_data 105 | 106 | def unknown_starttag(self, tag, attrs): 107 | attrib = {} 108 | for key, value in attrs.items(): 109 | attrib[fixname(key)] = value 110 | self.__builder.start(fixname(tag), attrib) 111 | 112 | def unknown_endtag(self, tag): 113 | self.__builder.end(fixname(tag)) 114 | 115 | 116 | def fixname(name, split=string.split): 117 | # xmllib in 2.0 and later provides limited (and slightly broken) 118 | # support for XML namespaces. 119 | if " " not in name: 120 | return name 121 | return "{%s}%s" % tuple(split(name, " ", 1)) 122 | -------------------------------------------------------------------------------- /elementtree/__init__.py: -------------------------------------------------------------------------------- 1 | """ST2 polyfill for xml.etree.ElementTree.""" 2 | -------------------------------------------------------------------------------- /integration_tests/ColorHighlighter.ss: -------------------------------------------------------------------------------- 1 | { 2 | "search_colors_in": { 3 | "selection": { 4 | "enabled": true, 5 | "color_highlighters": { 6 | "color_scheme": { 7 | "enabled": true, 8 | "highlight_style": "text" 9 | }, 10 | "gutter_icons": { 11 | "enabled": false, 12 | "icon_style": "circle" 13 | }, 14 | "phantoms": { 15 | "enabled": true, 16 | "style": "right", 17 | "length": 2 18 | } 19 | } 20 | }, 21 | "all_content": { 22 | "enabled": true, 23 | "color_highlighters": { 24 | "color_scheme": { 25 | "enabled": false, 26 | "highlight_style": "text" 27 | }, 28 | "gutter_icons": { 29 | "enabled": true, 30 | "icon_style": "circle" 31 | }, 32 | "phantoms": { 33 | "enabled": false, 34 | "style": "right", 35 | "length": 2 36 | } 37 | } 38 | }, 39 | "hover": { 40 | "enabled": true, 41 | "color_highlighters": { 42 | "color_scheme": { 43 | "enabled": false, 44 | "highlight_style": "filled" 45 | }, 46 | "gutter_icons": { 47 | "enabled": false, 48 | "icon_style": "circle" 49 | }, 50 | "phantoms": { 51 | "enabled": false, 52 | "style": "right", 53 | "length": 2 54 | } 55 | } 56 | } 57 | }, 58 | "default_keybindings": true, 59 | "file_extensions": [".css", ".less", ".scss", ".sass", ".styl"], 60 | "icon_factory": { 61 | "convert_command": "convert", 62 | "convert_timeout": 5 63 | }, 64 | "autoreload": { 65 | "when_settings_change": true, 66 | "when_color_scheme_change": true 67 | }, 68 | "regex_compiler": { 69 | "channels": { 70 | "hex": "[0-9a-fA-F]", 71 | "dec": "\\d{1,3}", 72 | "float": "(?:[0|1])|(?:[1][\\.]?[0]*)|(?:[0]?[\\.]\\d*)", 73 | "perc": "(?:\\d{1,3}[%])|(?:0)" 74 | }, 75 | "formats": { 76 | "sharp8": { 77 | "description": "Hex #RRGGBBAA color format", 78 | "regex": "#[0-9a-fA-F]{8}", 79 | "white": "#FFFFFFFF" 80 | }, 81 | "sharp6": { 82 | "description": "Hex #RRGGBBAA color format", 83 | "regex": "#[0-9a-fA-F]{6}", 84 | "white": "#FFFFFF", 85 | "after": "sharp8" 86 | }, 87 | "sharp4": { 88 | "description": "Hex #RGBA color format", 89 | "regex": "#(?Phex)(?Phex)(?Phex)(?Phex)", 90 | "white": "#FFFF", 91 | "after": "sharp6" 92 | }, 93 | "sharp3": { 94 | "description": "Hex #RGB color format", 95 | "regex": "#(?Phex)(?Phex)(?Phex)", 96 | "white": "#FFF", 97 | "after": "sharp4" 98 | }, 99 | "rgba": { 100 | "description": "rgba(255,255,100%,1) color format", 101 | "regex": "rgba[(][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pfloat)[ ]*[)]", 102 | "white": "rgba(255, 255, 100%, 1)" 103 | }, 104 | "rgb": { 105 | "description": "rgb(255,255,100%) color format", 106 | "regex": "rgb[(][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pdec|perc)[ ]*[,][ ]*(?Pdec|perc)[ ]*[)]", 107 | "white": "rgb(255, 255, 100%)" 108 | }, 109 | "hsva": { 110 | "description": "hsva(hue 0..360, s%, v%, alpha 0.0 .. 1.0) color format", 111 | "regex": "hsva[(][ ]*(?Pdec)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pfloat)[ ]*[)]", 112 | "white": "hsva(0, 0%, 100%, 1.)" 113 | }, 114 | "hsv": { 115 | "description": "hsv(hue 0..360, s%, v%) color format", 116 | "regex": "hsv[(][ ]*(?Pdec)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pperc)[ ]*[)]", 117 | "white": "hsv(0, 0%, 100%)" 118 | }, 119 | "hsla": { 120 | "description": "hsla(hue 0..360, s%, v%, alpha 0.0 .. 1.0) color format", 121 | "regex": "hsla[(][ ]*(?Pdec)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pfloat)[ ]*[)]", 122 | "white": "hsla(0, 0%, 100%, 1.)" 123 | }, 124 | "hsl": { 125 | "description": "hsl(hue 0..360, s%, v%) color format", 126 | "regex": "hsl[(][ ]*(?Pdec)[ ]*[,][ ]*(?Pperc)[ ]*[,][ ]*(?Pperc)[ ]*[)]", 127 | "white": "hsl(0, 0%, 100%)" 128 | } 129 | } 130 | }, 131 | "experimental": { 132 | "asynchronosly_update_color_scheme": false 133 | }, 134 | "debug": true 135 | } 136 | -------------------------------------------------------------------------------- /integration_tests/check-exceptions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Running $0 $1..." 4 | 5 | EXCEPTIONS_NUMBER=$(grep -c "Traceback" < "$1") 6 | if [[ ${EXCEPTIONS_NUMBER} != 0 ]]; then 7 | exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /integration_tests/empty.css: -------------------------------------------------------------------------------- 1 | // empty 2 | -------------------------------------------------------------------------------- /integration_tests/st2/empty.expected.log: -------------------------------------------------------------------------------- 1 | ColorHighlighter: action=start st=st2 2 | ColorHighlighter: action=copy_color_scheme scheme=Packages/Color Scheme - Default/Monokai.tmTheme fake_scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 3 | ColorHighlighter: action=set_view_color_scheme scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 4 | -------------------------------------------------------------------------------- /integration_tests/st2/test-empty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Running $0..." 4 | 5 | /opt/sublime_text_2/sublime_text integration_tests/empty.css & 6 | 7 | sleep 7 8 | 9 | killall -9 sublime_text 10 | 11 | set -e 12 | 13 | test_dir=integration_tests/tmp 14 | rm -rf "${test_dir}" 15 | mkdir -p "${test_dir}" 16 | log_file="${test_dir}"/sublime_text.log 17 | 18 | mv /opt/sublime_text.log "${log_file}" 19 | 20 | echo "Log:" 21 | cat "${log_file}" 22 | 23 | integration_tests/check-exceptions.sh "${log_file}" 24 | 25 | filtered_log_file="${test_dir}"/sublime_text_filtered.log 26 | set +e 27 | grep "ColorHighlighter:" < "${log_file}" > "${filtered_log_file}" 28 | set -e 29 | 30 | expected_log_file=integration_tests/st2/empty.expected.log 31 | cmp -s "${filtered_log_file}" "${expected_log_file}" 32 | -------------------------------------------------------------------------------- /integration_tests/st2/test-white.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Running $0..." 4 | 5 | /opt/sublime_text_2/sublime_text integration_tests/white.css 6 | 7 | sleep 7 8 | 9 | killall -9 sublime_text 10 | 11 | set -e 12 | 13 | test_dir=integration_tests/tmp 14 | rm -rf "${test_dir}" 15 | mkdir -p "${test_dir}" 16 | log_file="${test_dir}"/sublime_text.log 17 | 18 | mv /opt/sublime_text.log "${log_file}" 19 | 20 | echo "Log:" 21 | cat "${log_file}" 22 | 23 | integration_tests/check-exceptions.sh "${log_file}" 24 | 25 | filtered_log_file="${test_dir}"/sublime_text_filtered.log 26 | set +e 27 | grep "ColorHighlighter:" < "${log_file}" > "${filtered_log_file}" 28 | set -e 29 | 30 | expected_log_file=integration_tests/st2/white.expected.log 31 | cmp -s "${filtered_log_file}" "${expected_log_file}" 32 | -------------------------------------------------------------------------------- /integration_tests/st2/white.expected.log: -------------------------------------------------------------------------------- 1 | ColorHighlighter: action=start st=st3 2 | ColorHighlighter: action=copy_color_scheme scheme=Packages/Color Scheme - Default/Monokai.tmTheme fake_scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 3 | ColorHighlighter: action=set_view_color_scheme scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 4 | ColorHighlighter: action=write_color_scheme scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 5 | ColorHighlighter: action=highlight highlighter=ColorSchemeColorHighlighter region=(0, 9) color=#ffffffff 6 | -------------------------------------------------------------------------------- /integration_tests/st3/empty.expected.log: -------------------------------------------------------------------------------- 1 | ColorHighlighter: action=start st=st3 2 | ColorHighlighter: action=create_icon style=circle color=#ffffffff 3 | ColorHighlighter: action=fix_color_scheme 4 | ColorHighlighter: action=write_color_scheme scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 5 | ColorHighlighter: action=set_view_color_scheme scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 6 | -------------------------------------------------------------------------------- /integration_tests/st3/test-empty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Running $0..." 4 | 5 | /opt/sublime_text_3/sublime_text integration_tests/empty.css 6 | 7 | sleep 7 8 | 9 | killall -9 sublime_text 10 | 11 | set -e 12 | 13 | test_dir=integration_tests/tmp 14 | rm -rf "${test_dir}" 15 | mkdir -p "${test_dir}" 16 | log_file="${test_dir}"/sublime_text.log 17 | 18 | mv /opt/sublime_text.log "${log_file}" 19 | 20 | echo "Log:" 21 | cat "${log_file}" 22 | 23 | integration_tests/check-exceptions.sh "${log_file}" 24 | 25 | filtered_log_file="${test_dir}"/sublime_text_filtered.log 26 | set +e 27 | grep "ColorHighlighter:" < "${log_file}" > "${filtered_log_file}" 28 | set -e 29 | 30 | expected_log_file=integration_tests/st3/empty.expected.log 31 | cmp -s "${filtered_log_file}" "${expected_log_file}" 32 | -------------------------------------------------------------------------------- /integration_tests/st3/test-white.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Running $0..." 4 | 5 | /opt/sublime_text_3/sublime_text integration_tests/white.css 6 | 7 | sleep 7 8 | 9 | killall -9 sublime_text 10 | 11 | set -e 12 | 13 | test_dir=integration_tests/tmp 14 | rm -rf "${test_dir}" 15 | mkdir -p "${test_dir}" 16 | log_file="${test_dir}"/sublime_text.log 17 | 18 | mv /opt/sublime_text.log "${log_file}" 19 | 20 | echo "Log:" 21 | cat "${log_file}" 22 | 23 | integration_tests/check-exceptions.sh "${log_file}" 24 | 25 | filtered_log_file="${test_dir}"/sublime_text_filtered.log 26 | set +e 27 | grep "ColorHighlighter:" < "${log_file}" > "${filtered_log_file}" 28 | set -e 29 | 30 | expected_log_file=integration_tests/st3/white.expected.log 31 | cmp -s "${filtered_log_file}" "${expected_log_file}" 32 | -------------------------------------------------------------------------------- /integration_tests/st3/white.expected.log: -------------------------------------------------------------------------------- 1 | ColorHighlighter: action=start st=st3 2 | ColorHighlighter: action=create_icon style=circle color=#ffffffff 3 | ColorHighlighter: action=fix_color_scheme 4 | ColorHighlighter: action=write_color_scheme scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 5 | ColorHighlighter: action=set_view_color_scheme scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 6 | ColorHighlighter: action=highlight highlighter=GutterIconsColorHighlighter region=(0, 9) color=#ffffffff 7 | ColorHighlighter: action=highlight highlighter=PhantomColorHighlighter region=(0, 9) color=#ffffffff 8 | ColorHighlighter: action=write_color_scheme scheme=Packages/User/ColorHighlighter/themes/Monokai.tmTheme 9 | ColorHighlighter: action=highlight highlighter=ColorSchemeColorHighlighter region=(0, 9) color=#ffffffff 10 | -------------------------------------------------------------------------------- /integration_tests/white.css: -------------------------------------------------------------------------------- 1 | #FFFFFFFF 2 | -------------------------------------------------------------------------------- /load_resource.py: -------------------------------------------------------------------------------- 1 | """A module with tools loading ST resources.""" 2 | 3 | import codecs 4 | import os 5 | 6 | try: 7 | from .st_helper import running_in_st 8 | from . import st_helper 9 | from . import path 10 | except ValueError: 11 | from st_helper import running_in_st 12 | import st_helper 13 | import path 14 | 15 | if running_in_st(): 16 | import sublime # pylint: disable=import-error 17 | else: 18 | from . import sublime 19 | 20 | 21 | def load_resource(file_path): 22 | """ 23 | Polyfill for ST3 sublime.load_resource function. 24 | 25 | Arguments: 26 | - file_path - a resource path. 27 | Returns a string with the resource's content. 28 | """ 29 | if st_helper.is_st3(): 30 | return sublime.load_resource(file_path) 31 | 32 | file_path = os.path.join(os.path.dirname(path.packages_path(path.ABSOLUTE)), file_path) 33 | return _read_file(file_path) 34 | 35 | 36 | def load_binary_resource(file_path): 37 | """ 38 | Polyfill for ST3 sublime.load_binary_resource function. 39 | 40 | Arguments: 41 | - file_path - a resource path. 42 | Returns a byte string with the resource's content. 43 | """ 44 | if st_helper.is_st3(): 45 | return sublime.load_binary_resource(file_path) 46 | 47 | file_path = os.path.join(os.path.dirname(path.packages_path(path.ABSOLUTE)), file_path) 48 | return _read_binary_file(file_path) 49 | 50 | 51 | def get_binary_resource_size(file_path): 52 | """ 53 | Polyfill for ST3 sublime.load_binary_resource function. 54 | 55 | Arguments: 56 | - file_path - a resource path. 57 | Returns a byte string with the resource's content. 58 | """ 59 | if st_helper.is_st3(): 60 | return len(sublime.load_binary_resource(file_path)) 61 | 62 | file_path = os.path.join(os.path.dirname(path.packages_path(path.ABSOLUTE)), file_path) 63 | return os.path.getsize(file_path) 64 | 65 | 66 | def copy_resource(resource, destination_path): 67 | """ 68 | Copy resource to a file. 69 | 70 | Arguments: 71 | - resource - the resource to copy. 72 | - destination_path - the path where to copy the resource. 73 | """ 74 | with open(destination_path, "wb") as file: 75 | file.write(load_binary_resource(resource)) 76 | 77 | 78 | def _read_file(file_path): 79 | with codecs.open(file_path, "r", "utf-8") as file: 80 | return file.read() 81 | 82 | 83 | def _read_binary_file(file_path): 84 | with open(file_path, "rb") as file: 85 | return file.read() 86 | -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "install": "messages/install.txt", 3 | "8.0": "messages/install.txt" 4 | } 5 | -------------------------------------------------------------------------------- /messages/install.txt: -------------------------------------------------------------------------------- 1 | 2 | Color Highlighter v8.0 is released! 3 | 4 | For more info about the plugin visit https://github.com/Monnoroch/ColorHighlighter. 5 | 6 | Color Highlighter was developed for many years and features were added without consideration. 7 | As a result it has plenty of bugs and code is completely unmaintainable. 8 | Because of it, I've decided to rewrite the plugin from scratch using all the good programming practices I learned 9 | over the years. 10 | 11 | This is the first release of the new version and it might have some subtle bugs, especially on Windows and Mac, as I 12 | don't have machines with these systems. If you find any bugs, please file them in 13 | the bug tracker here: https://github.com/Monnoroch/ColorHighlighter/issues. I always appreciate your help and try to fix 14 | problems as soon as possible. 15 | 16 | The plugin is being developed by me alone in my spare time, so if you want to encourage me to build it 17 | better and faster, donations as always welcome. 18 | 19 | Thank you guys for your support, every little bit helps! 20 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: ColorHighlighter Documentation 2 | site_url: https://Monnoroch.github.io/ColorHighlighter 3 | repo_url: https://github.com/Monnoroch/ColorHighlighter 4 | edit_uri: tree/master/docs/src 5 | site_description: A color highlighting plugin for Sublime Text 2 and 3. 6 | 7 | pages: 8 | - ColorHighlighter: index.md 9 | 10 | theme: material 11 | docs_dir: docs/src 12 | theme_dir: docs/theme 13 | 14 | markdown_extensions: 15 | - markdown.extensions.toc: 16 | slugify: !!python/name:pymdownx.slugs.gfm 17 | - markdown.extensions.admonition: 18 | - markdown.extensions.smarty: 19 | smart_quotes: false 20 | - pymdownx.betterem: 21 | - markdown.extensions.attr_list: 22 | - markdown.extensions.def_list: 23 | - markdown.extensions.tables: 24 | - markdown.extensions.abbr: 25 | - pymdownx.extrarawhtml: 26 | - pymdownx.superfences: 27 | - pymdownx.highlight: 28 | css_class: codehilite 29 | - pymdownx.inlinehilite: 30 | - pymdownx.magiclink: 31 | repo_url_shortener: true 32 | base_repo_url: https://github.com/Monnoroch/ColorHighlighter 33 | - pymdownx.tilde: 34 | - pymdownx.caret: 35 | - pymdownx.smartsymbols: 36 | - pymdownx.emoji: 37 | emoji_generator: !!python/name:pymdownx.emoji.to_png 38 | - pymdownx.escapeall: 39 | hardbreak: true 40 | nbsp: true 41 | - pymdownx.tasklist: 42 | custom_checkbox: true 43 | # TODO: Setup common includes in _snippets like links etc. 44 | # - pymdownx.snippets: 45 | # base_path: docs/src/_snippets 46 | - pymdownx.keys: 47 | separator: "\uff0b" 48 | - pymdownx.details: 49 | 50 | extra: 51 | palette: 52 | primary: blue 53 | accent: blue 54 | font: 55 | text: Roboto 56 | code: Roboto Mono 57 | social: 58 | - type: github 59 | link: https://github.com/Monnoroch 60 | 61 | extra_css: 62 | - extra.css 63 | -------------------------------------------------------------------------------- /path.py: -------------------------------------------------------------------------------- 1 | """A module with tools for paths.""" 2 | 3 | import os 4 | 5 | try: 6 | from . import st_helper 7 | from .settings import COLOR_HIGHLIGHTER_SETTINGS_NAME 8 | except ValueError: 9 | from settings import COLOR_HIGHLIGHTER_SETTINGS_NAME 10 | import st_helper 11 | 12 | if st_helper.running_in_st(): 13 | import sublime # pylint: disable=import-error 14 | else: 15 | from . import sublime 16 | 17 | 18 | def normalize_path_for_st(path): 19 | """ 20 | Normalize path for ST. 21 | 22 | On Linux, does nothing. On windows, maps windows directory separators to linux ones, as ST wants linux 23 | directory separators. 24 | Arguments: 25 | - path - the path to normalize. 26 | """ 27 | if sublime.platform() == "windows": 28 | return path.replace("\\", "/") 29 | return path 30 | 31 | 32 | RELATIVE = True 33 | ABSOLUTE = False 34 | 35 | 36 | def plugin_name(): 37 | """ 38 | Determine if the plugin is installed via a Package Control package or manually. 39 | 40 | Returns the plugin directory or package name. 41 | """ 42 | manual_install_plugin_name = "ColorHighlighter" 43 | package_install_plugin_name = "Color Highlighter" 44 | if (os.path.exists(os.path.join( 45 | packages_path(ABSOLUTE), manual_install_plugin_name, COLOR_HIGHLIGHTER_SETTINGS_NAME))): 46 | return manual_install_plugin_name 47 | return package_install_plugin_name 48 | 49 | 50 | def packages_path(relative): 51 | """ 52 | Get packages path. 53 | 54 | Arguments: 55 | - relative - whether to get an absolute path or a relative to sublime packages directory. 56 | """ 57 | path = sublime.packages_path() 58 | if relative: 59 | path = os.path.basename(path) 60 | return path 61 | 62 | 63 | def data_path(relative): 64 | """ 65 | Get Color Highlighter path. 66 | 67 | Arguments: 68 | - relative - whether to get an absolute path or a relative to sublime packages directory. 69 | """ 70 | return os.path.join(packages_path(relative), "User", plugin_name()) 71 | 72 | 73 | def icons_path(relative): 74 | """ 75 | Get Color Highlighter icons path. 76 | 77 | Arguments: 78 | - relative - whether to get an absolute path or a relative to sublime packages directory. 79 | """ 80 | return os.path.join(data_path(relative), "icons") 81 | 82 | 83 | def themes_path(relative): 84 | """ 85 | Get Color Highlighter themes path. 86 | 87 | Arguments: 88 | - relative - whether to get an absolute path or a relative to sublime packages directory. 89 | """ 90 | return os.path.join(data_path(relative), "themes") 91 | 92 | 93 | def color_picker_path(relative): 94 | """ 95 | Get color picker directory path. 96 | 97 | Arguments: 98 | - relative - whether to get an absolute path or a relative to sublime packages directory. 99 | """ 100 | return os.path.join(data_path(relative), "ColorPicker") 101 | 102 | 103 | def _color_picker_file(): 104 | executable_suffix = None 105 | platform = sublime.platform() 106 | if platform == "windows": 107 | executable_suffix = "win.exe" 108 | else: 109 | executable_suffix = "%s_%s" % (platform, sublime.arch()) 110 | return "ColorPicker_" + executable_suffix 111 | 112 | 113 | def color_picker_file(relative): 114 | """ 115 | Get color picker file. 116 | 117 | Arguments: 118 | - relative - whether to get an absolute path or a relative to sublime packages directory. 119 | """ 120 | return os.path.join(color_picker_path(relative), _color_picker_file()) 121 | 122 | 123 | def color_picker_binary(relative): 124 | """ 125 | Get color picker file. 126 | 127 | Arguments: 128 | - relative - whether to get an absolute path or a relative to sublime packages directory. 129 | """ 130 | path = os.path.join(packages_path(relative), plugin_name(), "ColorPicker", _color_picker_file()) 131 | if relative: 132 | path = normalize_path_for_st(path) 133 | return path 134 | 135 | 136 | def fake_color_scheme_path(color_scheme, relative): 137 | """ 138 | Given a color scheme, get a fake color scheme path. 139 | 140 | Arguments: 141 | - color_scheme - color scheme sublime relative path. 142 | - relative - whether to get an absolute path or a relative to sublime packages directory. 143 | Returns a path to the fake color scheme for this color scheme. 144 | """ 145 | file_name = os.path.basename(color_scheme) 146 | path = os.path.join(themes_path(relative), file_name) 147 | if relative: 148 | path = normalize_path_for_st(path) 149 | return path 150 | 151 | 152 | def cached_scheme_path(color_scheme): 153 | """ 154 | Get the .cache file path for a color scheme file. 155 | 156 | Arguments: 157 | - color_scheme - the absolute color scheme file path. 158 | """ 159 | cache_suffix = ".cache" 160 | if st_helper.is_st3(): 161 | packages = packages_path(ABSOLUTE) 162 | cache_dir = os.path.join(os.path.dirname(packages), "Cache") 163 | return os.path.join(cache_dir, color_scheme[len(packages) + 1:] + cache_suffix) 164 | return color_scheme + cache_suffix 165 | -------------------------------------------------------------------------------- /phantoms_color_highlighter.py: -------------------------------------------------------------------------------- 1 | """A color highlighters that uses phantom sets to highlight colors.""" 2 | 3 | try: 4 | from . import st_helper 5 | from .color_highlighter import ColorHighlighter 6 | except ValueError: 7 | import st_helper 8 | from color_highlighter import ColorHighlighter 9 | 10 | 11 | if st_helper.running_in_st(): 12 | import sublime # pylint: disable=import-error 13 | else: 14 | from . import sublime 15 | 16 | 17 | class PhantomColorHighlighter(ColorHighlighter): 18 | """ 19 | A color highlighter that highlights colors using phantoms. 20 | 21 | Only supported on ST3. 22 | """ 23 | 24 | phantom_key_template = "CH_phantom_%s_%d_%d" 25 | 26 | html_template = ''' 27 | 28 | 33 | %s 34 | 35 | ''' 36 | space_symbol = " " 37 | 38 | if st_helper.is_st3(): 39 | _phantom_styles = { 40 | "right": sublime.LAYOUT_INLINE, 41 | "left": sublime.LAYOUT_INLINE, 42 | "below": sublime.LAYOUT_BELOW 43 | } 44 | 45 | _inline_styles = {"right": True, "left": True} 46 | 47 | def __init__(self, view, name, style, length, debug): # pylint: disable=too-many-arguments 48 | """ 49 | Create a phantom color highlighter. 50 | 51 | Arguments: 52 | - view - a view to highlight colors in. 53 | - name - the name of the color highlighter. 54 | - style - the style of the phantoms. 55 | - length - the length of the block in the "inline" mode. 56 | - debug - whether to enable debug mode. 57 | """ 58 | assert style in self._phantom_styles 59 | self._view = view 60 | self._name = name 61 | self._style = style 62 | self._length = length 63 | self._debug = debug 64 | 65 | def highlight_region(self, context, value): 66 | """ 67 | Highlight a region. 68 | 69 | Arguments: 70 | - context - a dict with color highlighter run data. 71 | - value - tuple (region to highlight, it's color). 72 | Returns True, if highlighted, False otherwise. 73 | """ 74 | (region, color) = value 75 | html = self._generate_phantom_html(region, color) 76 | if self._debug: 77 | print("ColorHighlighter: action=highlight highlighter=PhantomColorHighlighter region=%s color=%s" 78 | % (str(region), str(color))) 79 | self._view.add_phantom( 80 | PhantomColorHighlighter.phantom_key_template % (self._name, region.a, region.b), 81 | self._get_region(region), html, 82 | self._phantom_styles[self._style], None) 83 | 84 | def unhighlight_region(self, context, value): 85 | """ 86 | Unhighlight a region. 87 | 88 | Arguments: 89 | - context - a dict with color highlighter run data. 90 | - value - tuple (region to unhighlight, it's color). 91 | """ 92 | (region, _) = value 93 | self._view.erase_phantoms(PhantomColorHighlighter.phantom_key_template % (self._name, region.a, region.b)) 94 | 95 | def _get_region(self, region): 96 | if self._style == "below": 97 | return region.region() 98 | elif self._style == "right": 99 | return sublime.Region(region.b, region.b) 100 | elif self._style == "left": 101 | return sublime.Region(region.a, region.a) 102 | 103 | def _generate_phantom_html(self, region, color): 104 | if self._style == "below": 105 | size = region.length() 106 | elif self._style in self._inline_styles: 107 | size = self._length 108 | return PhantomColorHighlighter.html_template % (color, PhantomColorHighlighter.space_symbol * size) 109 | -------------------------------------------------------------------------------- /regex_compiler.py: -------------------------------------------------------------------------------- 1 | """A module with tools for paths.""" 2 | 3 | import copy 4 | import re 5 | 6 | try: 7 | from . import topsort 8 | except ValueError: 9 | import topsort 10 | 11 | 12 | def compile_regex(config): 13 | """ 14 | Build a regex from the config. 15 | 16 | Arguments: 17 | config -- a dict with two dicts inside: channels and formats. Channels are named definitions of how a channel might 18 | look. Formats use channel names to define how colors look and how to extract channels from them. 19 | Returns a regex for the input config. 20 | """ 21 | channels = _normalize_channels(config.channels) 22 | channels["empty"] = "" 23 | formats = _normalize_regexes(config.formats, channels) 24 | sorted_regexes = [formats[key].regex for key in topsort.sort(formats, lambda value: value.after)] 25 | regexes = "|".join(sorted_regexes) 26 | return re.compile(regexes) 27 | 28 | 29 | def _normalize_regexes(formats, channels): 30 | formats = copy.deepcopy(formats) 31 | for name in formats: 32 | color_format = formats[name] 33 | color_format.regex = _normalize_regex(color_format.regex, channels, name) 34 | return formats 35 | 36 | 37 | def _normalize_regex(regex, channels, format_name): 38 | group_str_template = "(?P<%s>" 39 | group_template = "(?P<%s>%s)" 40 | groups = re.compile(regex).groupindex.keys() 41 | for group in groups: 42 | group_str = group_str_template % group 43 | group_start = regex.find(group_str) 44 | assert group_start != -1 45 | start = group_start + len(group_str) 46 | end = regex.find(")", start) 47 | assert end != -1 48 | channel_names = regex[start:end] 49 | group_channels = [] 50 | for channel_name in channel_names.split("|"): 51 | channel = channels.get(channel_name, None) 52 | if channel is None: 53 | raise ValueError("Regex %s uses a non-existent channel %s for group %s." % (regex, channel_name, group)) 54 | group_channels.append(channel) 55 | regex = regex.replace( 56 | group_template % (group, channel_names), 57 | group_template % ("%s_%s" % (format_name, group), "|".join(group_channels))) 58 | return group_template % (format_name, regex) 59 | 60 | 61 | def _normalize_channels(channels): 62 | normalized_channels = {} 63 | for name in channels: 64 | normalized_channels[name] = _get_channel_value(channels, name, {}) 65 | return normalized_channels 66 | 67 | 68 | def _get_channel_value(channels, name, used_names): 69 | if name in used_names: 70 | # TODO(monnoroch): explain in more detail which channels depend on each other. # pylint: disable=fixme 71 | raise ValueError("Reccurent dependencies between channels!") 72 | used_names[name] = True 73 | 74 | value = channels[name] 75 | if value in channels: 76 | return _get_channel_value(channels, value, used_names) 77 | return value 78 | -------------------------------------------------------------------------------- /regions.py: -------------------------------------------------------------------------------- 1 | """Helper functions for manipulating regions.""" 2 | 3 | try: 4 | from .st_helper import running_in_st 5 | except ValueError: 6 | from st_helper import running_in_st 7 | 8 | 9 | if running_in_st(): 10 | import sublime # pylint: disable=import-error 11 | else: 12 | from . import sublime 13 | 14 | 15 | class NormalizedRegion(object): 16 | """ 17 | A convenient wrapper around sublime.Region. 18 | 19 | Regions can have their end smaller than their beginning. This happens, for example, when the user selects from 20 | right to left. This function normalizes such regions to have their end always before their beginning. 21 | """ 22 | 23 | def __init__(self, a, b=None): 24 | """ 25 | Initialize a region with a sublime.Region. 26 | 27 | Arguments: 28 | a -- a sublime.Region to normalize or the regions's beginning. 29 | b -- the regions's end. Only set if a is the regions's beginning. 30 | """ 31 | if b is None: 32 | # a is a sublime.Region. 33 | b = a.b 34 | a = a.a 35 | else: 36 | a = a 37 | b = b 38 | 39 | if a > b: 40 | self.a = b # pylint: disable=invalid-name 41 | self.b = a # pylint: disable=invalid-name 42 | else: 43 | self.a = a # pylint: disable=invalid-name 44 | self.b = b # pylint: disable=invalid-name 45 | 46 | def length(self): 47 | """Get the normalizer region's length.""" 48 | return self.b - self.a 49 | 50 | def region(self): 51 | """Return a sublime.Region for this normalized region.""" 52 | return sublime.Region(self.a, self.b) 53 | 54 | def __eq__(self, other): 55 | """Compare normalized regions for equality.""" 56 | if not isinstance(other, NormalizedRegion): 57 | return False 58 | return self.a == other.a and self.b == other.b 59 | 60 | def __hash__(self): 61 | """Get the normalized regions hash.""" 62 | return hash(self.a) ^ hash(self.b) 63 | 64 | def __str__(self): 65 | """Get the normalided regions string representation.""" 66 | return "(%d, %d)" % (self.a, self.b) 67 | 68 | def __repr__(self): 69 | """Get the normalided regions string representation.""" 70 | return self.__str__() 71 | 72 | 73 | def intersects(region1, region2): 74 | """ 75 | Check if two regions intersect. 76 | 77 | If regions share an end, they don't intersect unless one of the regions has zero length in which case they do 78 | intersect. 79 | 80 | Arguments: 81 | region1 -- a first region. 82 | region2 -- a second region. 83 | Returns True if regions intersect and False otherwise. 84 | """ 85 | if region1.a == region1.b: 86 | return region2.a <= region1.a and region2.b >= region1.b 87 | if region2.a == region2.b: 88 | return region1.a <= region2.a and region1.b >= region2.b 89 | if region1.a >= region2.b: 90 | return False 91 | if region1.b <= region2.a: 92 | return False 93 | return True 94 | 95 | 96 | def intersects_any(input_region, regions): 97 | """ 98 | Check a region intersects with any of the other regions. 99 | 100 | If regions share an end, they don't intersect unless one of the regions has zero length in which case they do 101 | intersect. 102 | 103 | Arguments: 104 | input_region -- a region to check. 105 | regions -- a list of regions. 106 | Returns True if the first region intersects with any of the other regions and False otherwise. 107 | """ 108 | for region in regions: 109 | if intersects(input_region, region): 110 | return True 111 | return False 112 | 113 | 114 | def deduplicate_regions(regions): 115 | """ 116 | Deduplicate regions. 117 | 118 | Argumens: 119 | - regions - an iterable of pairs (region, color). 120 | Returns an iterable of (region, color) with unique regions. 121 | """ 122 | processed_regions = {} 123 | for region in regions: 124 | if region in processed_regions: 125 | continue 126 | processed_regions[region] = True 127 | return processed_regions.keys() 128 | -------------------------------------------------------------------------------- /st_helper.py: -------------------------------------------------------------------------------- 1 | """Helper functions for checking for Sublime Text.""" 2 | 3 | try: 4 | import sublime # noqa: F401 # pylint: disable=unused-import 5 | SUBLIME_IMPORTED = True # For prod. 6 | except ImportError: 7 | SUBLIME_IMPORTED = False # For tests. 8 | 9 | 10 | def running_in_st(): 11 | """Whether the code runs in ST or not.""" 12 | return SUBLIME_IMPORTED 13 | 14 | 15 | def version(): 16 | """Return a ST version. Return 0 if not running in ST.""" 17 | if not running_in_st(): 18 | return 0 19 | 20 | return int(sublime.version()) 21 | 22 | 23 | def is_st3(): 24 | """ 25 | Whether the code runs in ST3 or not. 26 | 27 | Plugin development is mainly for ST3, so tests execute ST3 code. 28 | """ 29 | if not running_in_st(): 30 | return True 31 | 32 | return version() >= 3000 33 | 34 | 35 | def st_version(): 36 | """Return a string representation of a major ST version.""" 37 | if running_in_st(): 38 | if is_st3(): 39 | major_version = "st3" 40 | else: 41 | major_version = "st2" 42 | else: 43 | major_version = "none" 44 | return major_version 45 | -------------------------------------------------------------------------------- /test_plugin/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test plugin. 3 | 4 | A Sublime Text plugin for writing logs into a file. 5 | """ 6 | -------------------------------------------------------------------------------- /test_plugin/flushing_file.py: -------------------------------------------------------------------------------- 1 | """ 2 | Flushing file. 3 | 4 | A module with the FlushingFile component that wraps a file and flushes it on writes. 5 | """ 6 | 7 | 8 | class FlushingFile(object): 9 | """ 10 | Flushing file. 11 | 12 | A wrapper around a file that flushes every time anything is written. 13 | """ 14 | 15 | def __init__(self, file): 16 | """ 17 | Flushing file constructor. 18 | 19 | Arguments: 20 | file -- a file to wrap. 21 | """ 22 | self.file = file 23 | 24 | def write(self, message): 25 | """ 26 | Write to a file. 27 | 28 | Arguments: 29 | message -- a message to write. 30 | """ 31 | self.file.write(message) 32 | self.file.flush() 33 | -------------------------------------------------------------------------------- /test_plugin/main.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test plugin. 3 | 4 | A plugin for sublime text that redirects all console output to /opt/sublime_text.log. 5 | """ 6 | 7 | import sys 8 | 9 | try: 10 | from .flushing_file import FlushingFile 11 | except ValueError: 12 | from flushing_file import FlushingFile 13 | 14 | OUTPUT_FILE = FlushingFile(open("/opt/sublime_text.log", "w")) 15 | 16 | sys.stdout = OUTPUT_FILE 17 | sys.stderr = OUTPUT_FILE 18 | 19 | print("Start!") 20 | -------------------------------------------------------------------------------- /test_plugin/test_flushing_file.py: -------------------------------------------------------------------------------- 1 | """Tests for flushing_file module.""" 2 | 3 | import unittest 4 | 5 | from mockito import mock, verify 6 | 7 | from .flushing_file import FlushingFile 8 | 9 | 10 | class FlushingFileTest(unittest.TestCase): 11 | """Tests for FlushingFile.""" 12 | 13 | def test_write(self): # pylint: disable=no-self-use 14 | """ 15 | Test write. 16 | 17 | Test that the write method calls write and flush on a wrapped file. 18 | """ 19 | file = mock() 20 | flushing_file = FlushingFile(file) 21 | message = "test message" 22 | flushing_file.write(message) 23 | verify(file).write(message) 24 | verify(file).flush() 25 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ColorHighligter. 3 | 4 | A Sublime Text plugin for highlighting CSS colors in code. 5 | """ 6 | -------------------------------------------------------------------------------- /tests/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Running $0..." 4 | 5 | test_files=( 6 | __init__.py 7 | sublime.py 8 | sublime_plugin.py 9 | ) 10 | 11 | for file in "${test_files[@]}"; do 12 | mv "./tests/${file}" ./ 13 | done 14 | 15 | py.test 16 | exitcode=$? 17 | 18 | for file in "${test_files[@]}"; do 19 | mv "${file}" ./tests/ 20 | done 21 | 22 | exit $exitcode 23 | -------------------------------------------------------------------------------- /tests/sublime.py: -------------------------------------------------------------------------------- 1 | """A dummy package for mocking ST API.""" 2 | 3 | 4 | def Region(*args): # noqa: D103 # pylint: disable=invalid-name,missing-docstring,unused-argument 5 | return None 6 | 7 | 8 | def version(): # noqa: D103 # pylint: disable=missing-docstring 9 | return None 10 | 11 | 12 | def platform(): # noqa: D103 # pylint: disable=missing-docstring 13 | return None 14 | 15 | 16 | def arch(): # noqa: D103 # pylint: disable=missing-docstring 17 | return None 18 | 19 | 20 | def packages_path(): # noqa: D103 # pylint: disable=missing-docstring 21 | return None 22 | 23 | 24 | def load_resource(*args): # noqa: D103 # pylint: disable=missing-docstring,unused-argument 25 | return None 26 | 27 | 28 | def load_binary_resource(*args): # noqa: D103 # pylint: disable=missing-docstring,unused-argument 29 | return None 30 | 31 | 32 | def load_settings(*args): # noqa: D103 # pylint: disable=missing-docstring,unused-argument 33 | return None 34 | 35 | 36 | def save_settings(*args): # noqa: D103 # pylint: disable=missing-docstring,unused-argument 37 | return None 38 | 39 | 40 | def set_timeout(*args): # noqa: D103 # pylint: disable=missing-docstring,unused-argument 41 | return None 42 | 43 | 44 | def set_timeout_async(*args): # noqa: D103 # pylint: disable=missing-docstring,unused-argument 45 | return None 46 | 47 | 48 | def windows(): # noqa: D103 # pylint: disable=missing-docstring 49 | return [] 50 | 51 | 52 | LAYOUT_BELOW = 1 53 | HIDDEN = 2 54 | DRAW_NO_OUTLINE = 3 55 | DRAW_NO_FILL = 4 56 | DRAW_SOLID_UNDERLINE = 5 57 | DRAW_STIPPLED_UNDERLINE = 6 58 | DRAW_SQUIGGLY_UNDERLINE = 7 59 | DRAW_OUTLINED = 8 60 | HOVER_TEXT = 9 61 | LAYOUT_INLINE = 10 62 | -------------------------------------------------------------------------------- /tests/sublime_plugin.py: -------------------------------------------------------------------------------- 1 | """A dummy package for mocking ST API.""" 2 | 3 | 4 | class ApplicationCommand(object): # pylint: disable=too-few-public-methods 5 | """Dummy ApplicationCommand.""" 6 | 7 | pass 8 | 9 | 10 | class TextCommand(object): # pylint: disable=too-few-public-methods 11 | """Dummy TextCommand.""" 12 | 13 | pass 14 | 15 | 16 | class EventListener(object): # pylint: disable=too-few-public-methods 17 | """Dummy EventListener.""" 18 | 19 | pass 20 | -------------------------------------------------------------------------------- /tests/test_color_searcher.py: -------------------------------------------------------------------------------- 1 | """Tests for color_searcher.ColorSearcher.""" 2 | 3 | import re 4 | import unittest 5 | 6 | from ColorHighlighter import sublime # pylint: disable=no-name-in-module 7 | from ColorHighlighter.color_searcher import ColorSearcher # pylint: disable=no-name-in-module,import-error 8 | from ColorHighlighter.regions import NormalizedRegion # pylint: disable=no-name-in-module,import-error 9 | 10 | from mockito import ANY, mock, when 11 | 12 | 13 | class ColorSearcherTest(unittest.TestCase): 14 | """Tests for ColorSearcher.""" 15 | 16 | def test_search_found(self): 17 | """Test found color.""" 18 | begin = 5 19 | end = 10 20 | region = NormalizedRegion(begin, end) 21 | whole_region = mock() 22 | when(sublime).Region(begin, end).thenReturn(whole_region) 23 | color_region = mock() 24 | when(sublime).Region(begin + 1, end - 1).thenReturn(color_region) 25 | view = mock() 26 | test_color_text = "#FA" 27 | when(view).substr(whole_region).thenReturn(" %s " % test_color_text) 28 | when(view).substr(color_region).thenReturn(test_color_text) 29 | test_color = "#FB" 30 | test_group = "test_group" 31 | color_converter = mock() 32 | when(color_converter).to_color({test_group: test_color_text}).thenReturn(test_color) 33 | color_searcher = ColorSearcher(re.compile("(?P<%s>#[0-9a-fA-F]{2})" % test_group), color_converter) 34 | 35 | results = [result for result in color_searcher.search(view, region)] 36 | self.assertEqual( 37 | [(NormalizedRegion(begin + 1, end - 1), test_color, {test_group: test_color_text})], results) 38 | 39 | def test_search_found_bad(self): 40 | """Test found color which could not be converted to a canonical form.""" 41 | begin = 5 42 | end = 10 43 | region = NormalizedRegion(begin, end) 44 | whole_region = mock() 45 | when(sublime).Region(begin, end).thenReturn(whole_region) 46 | color_region = mock() 47 | when(sublime).Region(begin + 1, end - 1).thenReturn(color_region) 48 | view = mock() 49 | test_color_text = "#FA" 50 | when(view).substr(whole_region).thenReturn(" %s " % test_color_text) 51 | when(view).substr(color_region).thenReturn(test_color_text) 52 | color_searcher = ColorSearcher(re.compile("#[0-9a-fA-F]{2}"), mock()) 53 | 54 | results = [result for result in color_searcher.search(view, region)] 55 | self.assertEqual([], results) 56 | 57 | def test_search_found_multiple(self): # pylint: disable=too-many-locals 58 | """Test found multiple colors.""" 59 | begin = 5 60 | end = 15 61 | region = NormalizedRegion(begin, end) 62 | whole_region = mock() 63 | when(sublime).Region(begin, end).thenReturn(whole_region) 64 | color_region1 = mock() 65 | when(sublime).Region(begin + 1, begin + 4).thenReturn(color_region1) 66 | color_region2 = mock() 67 | when(sublime).Region(end - 4, end - 1).thenReturn(color_region2) 68 | view = mock() 69 | test_color_text1 = "#FA" 70 | test_color_text2 = "#E5" 71 | when(view).substr(whole_region).thenReturn(" %s %s " % (test_color_text1, test_color_text2)) 72 | when(view).substr(color_region1).thenReturn(test_color_text1) 73 | when(view).substr(color_region2).thenReturn(test_color_text2) 74 | test_color1 = "#FB" 75 | test_color2 = "#DB" 76 | test_group = "test_group" 77 | color_converter = mock() 78 | when(color_converter).to_color({test_group: test_color_text1}).thenReturn(test_color1) 79 | when(color_converter).to_color({test_group: test_color_text2}).thenReturn(test_color2) 80 | color_searcher = ColorSearcher(re.compile("(?P<%s>#[0-9a-fA-F]{2})" % test_group), color_converter) 81 | 82 | results = [result for result in color_searcher.search(view, region)] 83 | self.assertEqual( 84 | [(NormalizedRegion(begin + 1, begin + 4), test_color1, {test_group: test_color_text1}), 85 | (NormalizedRegion(end - 4, end - 1), test_color2, {test_group: test_color_text2})], results) 86 | 87 | def test_search_not_found(self): 88 | """Test search.""" 89 | begin = 5 90 | end = 10 91 | region = NormalizedRegion(begin, end) 92 | whole_region = mock() 93 | when(sublime).Region(begin, end).thenReturn(whole_region) 94 | view = mock() 95 | when(view).substr(ANY).thenReturn(" " * 30) 96 | 97 | color_searcher = ColorSearcher(re.compile("#[0-9a-fA-F]{2}"), mock()) 98 | 99 | results = [result for result in color_searcher.search(view, region)] 100 | self.assertEqual([], results) 101 | -------------------------------------------------------------------------------- /tests/test_color_selection_listener.py: -------------------------------------------------------------------------------- 1 | """Tests for color_searcher.ColorSearcher.""" 2 | 3 | import unittest 4 | 5 | from ColorHighlighter.color_selection_listener import ( # pylint: disable=no-name-in-module,import-error 6 | ColorSelectionListener) 7 | from ColorHighlighter.regions import NormalizedRegion # pylint: disable=no-name-in-module,import-error 8 | 9 | from mockito import ANY, mock, verify, when 10 | from mockito.matchers import captor 11 | 12 | 13 | class ColorSelectionListenerTest(unittest.TestCase): 14 | """Tests for ColorSelectionListener.""" 15 | 16 | def test_selection_changed(self): 17 | """Test modify selection.""" 18 | color_searcher = mock() 19 | view = mock() 20 | color_highlighter = mock() 21 | color_selection_listener = ColorSelectionListener(color_searcher, view, color_highlighter) 22 | 23 | color_region1 = (NormalizedRegion(10, 11), 1) 24 | color_region2 = (NormalizedRegion(11, 12), 2) 25 | color_region3 = (NormalizedRegion(17, 21), 3) 26 | 27 | sel_region1 = NormalizedRegion(10, 13) 28 | sel_region2 = NormalizedRegion(16, 20) 29 | sel_line1 = NormalizedRegion(14, 15) 30 | sel_line2 = NormalizedRegion(16, 17) 31 | when(view).lines(sel_region1).thenReturn([sel_line1]) 32 | when(view).lines(sel_region2).thenReturn([sel_line2]) 33 | when(view).sel().thenReturn([sel_region1, sel_region2]) 34 | when(color_searcher).search(view, sel_line1).thenReturn([color_region1 + (None,), color_region2 + (None,)]) 35 | when(color_searcher).search(view, sel_line2).thenReturn([color_region3 + (None,)]) 36 | color_selection_listener.on_selection_modified() 37 | color_regions = captor() 38 | verify(color_highlighter).highlight_regions(color_regions) 39 | self.assertEqual([color_region1, color_region2, color_region3], [region for region in color_regions.value]) 40 | 41 | def test_selection_unchanged(self): # pylint: disable=no-self-use 42 | """Test modify selection without it actually changing.""" 43 | color_searcher = mock() 44 | view = mock() 45 | color_highlighter = mock() 46 | color_selection_listener = ColorSelectionListener(color_searcher, view, color_highlighter) 47 | 48 | when(view).sel().thenReturn([]) 49 | 50 | color_selection_listener.on_selection_modified() 51 | color_selection_listener.on_selection_modified() 52 | verify(color_highlighter, times=0).highlight_regions(ANY) 53 | 54 | def test_selection_no_intersections(self): 55 | """Test modify selection with color searher returning regions with no intersections with the selection.""" 56 | color_searcher = mock() 57 | view = mock() 58 | color_highlighter = mock() 59 | color_selection_listener = ColorSelectionListener(color_searcher, view, color_highlighter) 60 | 61 | color_region = (NormalizedRegion(4, 5), 1) 62 | 63 | sel_region = NormalizedRegion(10, 13) 64 | sel_line = NormalizedRegion(14, 15) 65 | when(view).lines(sel_region).thenReturn([sel_line]) 66 | when(view).sel().thenReturn([sel_region]) 67 | when(color_searcher).search(view, sel_line).thenReturn([color_region + (None,)]) 68 | color_selection_listener.on_selection_modified() 69 | color_regions = captor() 70 | verify(color_highlighter).highlight_regions(color_regions) 71 | self.assertEqual([], [region for region in color_regions.value]) 72 | 73 | def test_deduplicate_lines(self): 74 | """Test that having two selections on the same line yields that line only one time .""" 75 | color_searcher = mock() 76 | view = mock() 77 | color_highlighter = mock() 78 | color_selection_listener = ColorSelectionListener(color_searcher, view, color_highlighter) 79 | 80 | color_region = (NormalizedRegion(11, 14), 1) 81 | 82 | sel_region1 = NormalizedRegion(10, 11) 83 | sel_region2 = NormalizedRegion(12, 13) 84 | sel_line = NormalizedRegion(14, 15) 85 | when(view).lines(sel_region1).thenReturn([sel_line]) 86 | when(view).lines(sel_region2).thenReturn([sel_line]) 87 | when(view).sel().thenReturn([sel_region1, sel_region2]) 88 | when(color_searcher).search(view, sel_line).thenReturn([color_region + (None,)]) 89 | color_selection_listener.on_selection_modified() 90 | color_regions = captor() 91 | verify(color_highlighter).highlight_regions(color_regions) 92 | self.assertEqual([color_region], [region for region in color_regions.value]) 93 | -------------------------------------------------------------------------------- /tests/test_colors.py: -------------------------------------------------------------------------------- 1 | """Tests for colors module.""" 2 | 3 | import unittest 4 | 5 | from ColorHighlighter import colors # pylint: disable=no-name-in-module 6 | 7 | 8 | class NormalizeHexColorTest(unittest.TestCase): 9 | """Tests for normalize_hex_color.""" 10 | 11 | def test_noop(self): 12 | """Normalizing a normalized color is a noop.""" 13 | test_color = "#FFFFFFFF" 14 | self.assertEqual(test_color, colors.normalize_hex_color(test_color)) 15 | 16 | def test_normalize(self): 17 | """Normalize color.""" 18 | self.assertEqual("#FFFFFFFF", colors.normalize_hex_color("#FFFF")) 19 | 20 | 21 | class BackgroundColorForTextWorkaroundTest(unittest.TestCase): 22 | """Tests for background_color_for_text_workaround.""" 23 | 24 | def test_noop(self): 25 | """Normalizing a non-background color is a noop.""" 26 | test_color = "#FFFFFFFF" 27 | self.assertEqual(test_color, colors.background_color_for_text_workaround(test_color, test_color + "F")) 28 | 29 | def test_normalize_f(self): 30 | """Normalize color with F in the second green channel half-byte.""" 31 | test_color = "#FFFFFFFF" 32 | self.assertEqual("#FFFFFEFF", colors.background_color_for_text_workaround(test_color, test_color)) 33 | 34 | def test_normalize(self): 35 | """Normalize color with something other than F in the second green channel half-byte.""" 36 | test_color = "#FFFFF1FF" 37 | self.assertEqual("#FFFFF2FF", colors.background_color_for_text_workaround(test_color, test_color)) 38 | 39 | 40 | class RgbToHexTest(unittest.TestCase): 41 | """Tests for rgb_to_hex.""" 42 | 43 | def test_convert(self): 44 | """Convert r, g, b to #RRGGBBAA.""" 45 | self.assertEqual("#FFFFFFFF", colors.rgb_to_hex(255, 255, 255)) 46 | 47 | 48 | class ComplementaryColorTest(unittest.TestCase): 49 | """Tests for complementary_color.""" 50 | 51 | def test_convert(self): 52 | """Convert r, g, b to #RRGGBBAA.""" 53 | self.assertEqual("#FFFFFFFF", colors.complementary_color("#000000FF")) 54 | 55 | def test_ignore_alpha(self): 56 | """Convert r, g, b to #RRGGBBAA.""" 57 | self.assertEqual("#FFFFFFFF", colors.complementary_color("#000000AA")) 58 | -------------------------------------------------------------------------------- /tests/test_gutter_icons_color_highlighter.py: -------------------------------------------------------------------------------- 1 | """Tests for GutterIconsColorHighlighter.""" 2 | 3 | import unittest 4 | 5 | from ColorHighlighter import sublime # pylint: disable=no-name-in-module 6 | from ColorHighlighter.gutter_icons_color_highlighter import ( # pylint: disable=no-name-in-module,import-error 7 | GutterIconsColorHighlighter) 8 | from ColorHighlighter.regions import NormalizedRegion # pylint: disable=no-name-in-module,import-error 9 | 10 | from mockito import mock, verify, when 11 | 12 | 13 | class GutterIconsColorHighlighterTest(unittest.TestCase): 14 | """Tests for PhantomColorHighlighter.""" 15 | 16 | test_name = "test-name" 17 | 18 | def test_highlight(self): # pylint: disable=no-self-use 19 | """Check highlighting a region.""" 20 | view = mock() 21 | icon_factory = mock() 22 | test_style = "circle" 23 | color_highlighter = GutterIconsColorHighlighter(view, test_style, icon_factory, self.test_name, False) 24 | 25 | test_color = "test" 26 | begin = 4 27 | end = begin + len(test_color) 28 | normalized_region = NormalizedRegion(begin, end) 29 | region = mock() 30 | when(sublime).Region(begin, end).thenReturn(region) 31 | 32 | test_path = "test/path" 33 | when(icon_factory).get_icon_path(test_style, test_color).thenReturn(test_path) 34 | 35 | color_highlighter.highlight_region(None, (normalized_region, test_color)) 36 | verify(view).add_regions( 37 | GutterIconsColorHighlighter.region_name_template % 38 | (self.test_name, normalized_region.a, normalized_region.b), 39 | [region], GutterIconsColorHighlighter.region_scope, test_path, sublime.HIDDEN) 40 | 41 | def test_unhighlight(self): # pylint: disable=no-self-use 42 | """Check unhighlighting a region.""" 43 | view = mock() 44 | color_highlighter = GutterIconsColorHighlighter(view, "circle", mock(), self.test_name, False) 45 | normalized_region = NormalizedRegion(4, 9) 46 | 47 | color_highlighter.unhighlight_region(None, (normalized_region, None)) 48 | verify(view).erase_regions( 49 | GutterIconsColorHighlighter.region_name_template % 50 | (self.test_name, normalized_region.a, normalized_region.b)) 51 | -------------------------------------------------------------------------------- /tests/test_load_resource.py: -------------------------------------------------------------------------------- 1 | """Tests for load_resource module.""" 2 | 3 | import builtins 4 | import codecs 5 | import os 6 | import unittest 7 | 8 | from ColorHighlighter import path, st_helper, sublime # pylint: disable=no-name-in-module 9 | from ColorHighlighter.load_resource import ( # pylint: disable=no-name-in-module,import-error 10 | get_binary_resource_size, load_binary_resource, load_resource) 11 | 12 | from mockito import ANY, mock, unstub, verify, when 13 | 14 | 15 | class LoadResourceTest(unittest.TestCase): 16 | """Tests for load_resource.""" 17 | 18 | def test_st3(self): 19 | """In ST3 load_resource just calls sublime.load_resource.""" 20 | when(st_helper).is_st3().thenReturn(True) 21 | test_path = "test/path" 22 | content = "content" 23 | when(sublime).load_resource(test_path).thenReturn(content) 24 | self.assertEqual(content, load_resource(test_path)) 25 | verify(sublime).load_resource(test_path) 26 | unstub(sublime) 27 | 28 | def test_st2(self): 29 | """In ST2 load_resource reads the resource's file.""" 30 | when(st_helper).is_st3().thenReturn(False) 31 | test_path = "Packages/test/path" 32 | content = "content" 33 | file = mock() 34 | when(file).read().thenReturn(content) 35 | when(file).__enter__().thenReturn(file) 36 | when(file).__exit__() 37 | when(codecs).open(ANY, ANY, ANY).thenReturn(file) 38 | when(sublime).packages_path().thenReturn("/sublime/Packages") 39 | self.assertEqual(content, load_resource(test_path)) 40 | test_absolute_path = os.path.join(os.path.dirname(path.packages_path(path.ABSOLUTE)), test_path) 41 | verify(codecs).open(test_absolute_path, "r", "utf-8") 42 | verify(file).read() 43 | unstub(sublime, codecs) 44 | 45 | 46 | class LoadBinaryResourceTest(unittest.TestCase): 47 | """Tests for load_binary_resource.""" 48 | 49 | def test_st3(self): 50 | """In ST3 load_binary_resource just calls sublime.load_binary_resource.""" 51 | when(st_helper).is_st3().thenReturn(True) 52 | test_path = "test/path" 53 | content = "content" 54 | when(sublime).load_binary_resource(test_path).thenReturn(content) 55 | self.assertEqual(content, load_binary_resource(test_path)) 56 | verify(sublime).load_binary_resource(test_path) 57 | unstub(sublime) 58 | 59 | def test_st2(self): 60 | """In ST2 load_binary_resource reads the resource's file.""" 61 | when(st_helper).is_st3().thenReturn(False) 62 | test_path = "Packages/test/path" 63 | content = "content" 64 | file = mock() 65 | when(file).read().thenReturn(content) 66 | when(file).__enter__().thenReturn(file) 67 | when(file).__exit__() 68 | when(builtins).open(ANY, ANY).thenReturn(file) 69 | when(sublime).packages_path().thenReturn("/sublime/Packages") 70 | self.assertEqual(content, load_binary_resource(test_path)) 71 | test_absolute_path = os.path.join(os.path.dirname(path.packages_path(path.ABSOLUTE)), test_path) 72 | verify(builtins).open(test_absolute_path, "rb") 73 | verify(file).read() 74 | unstub(sublime, builtins) 75 | 76 | 77 | class GetBinaryResourceSizeTest(unittest.TestCase): 78 | """Tests for get_binary_resource_size.""" 79 | 80 | def test_st3(self): 81 | """In ST3 get_binary_resource_size just calls sublime.load_binary_resource.""" 82 | when(st_helper).is_st3().thenReturn(True) 83 | test_path = "test/path" 84 | content = "content" 85 | when(sublime).load_binary_resource(test_path).thenReturn(content) 86 | self.assertEqual(len(content), get_binary_resource_size(test_path)) 87 | verify(sublime).load_binary_resource(test_path) 88 | unstub(sublime) 89 | 90 | def test_st2(self): 91 | """In ST2 get_binary_resource_size reads the resource's file.""" 92 | when(st_helper).is_st3().thenReturn(False) 93 | test_path = "Packages/test/path" 94 | file_size = 17 95 | when(os.path).getsize(ANY).thenReturn(file_size) 96 | when(sublime).packages_path().thenReturn("/sublime/Packages") 97 | self.assertEqual(file_size, get_binary_resource_size(test_path)) 98 | test_absolute_path = os.path.join(os.path.dirname(path.packages_path(path.ABSOLUTE)), test_path) 99 | verify(os.path).getsize(test_absolute_path) 100 | unstub(sublime, os.path) 101 | -------------------------------------------------------------------------------- /tests/test_normalized_region.py: -------------------------------------------------------------------------------- 1 | """Tests for regions.NormalizedRegion.""" 2 | 3 | import unittest 4 | 5 | from ColorHighlighter import sublime # pylint: disable=no-name-in-module 6 | from ColorHighlighter.regions import NormalizedRegion # pylint: disable=no-name-in-module,import-error 7 | 8 | from mockito import mock, when 9 | 10 | 11 | class _RegionMock(object): # pylint: disable=too-few-public-methods 12 | def __init__(self, a, b): 13 | self.a = a # pylint: disable=invalid-name 14 | self.b = b # pylint: disable=invalid-name 15 | 16 | 17 | class NormalizedRegionTest(unittest.TestCase): 18 | """Tests for NormalizedRegionTest.""" 19 | 20 | def test_begin_end(self): 21 | """Test normal region.""" 22 | a = 10 # pylint: disable=invalid-name 23 | b = 20 # pylint: disable=invalid-name 24 | region = NormalizedRegion(a, b) 25 | self.assertEqual(a, region.a) 26 | self.assertEqual(b, region.b) 27 | self.assertEqual(10, region.length()) 28 | 29 | def test_begin_end_inversed(self): 30 | """Test normal region.""" 31 | a = 20 # pylint: disable=invalid-name 32 | b = 10 # pylint: disable=invalid-name 33 | region = NormalizedRegion(a, b) 34 | self.assertEqual(b, region.a) 35 | self.assertEqual(a, region.b) 36 | self.assertEqual(10, region.length()) 37 | 38 | def test_region(self): 39 | """Test normal region.""" 40 | a = 10 # pylint: disable=invalid-name 41 | b = 20 # pylint: disable=invalid-name 42 | region = NormalizedRegion(_RegionMock(a, b)) 43 | self.assertEqual(a, region.a) 44 | self.assertEqual(b, region.b) 45 | self.assertEqual(10, region.length()) 46 | 47 | def test_inversed_region(self): 48 | """Test inversed region.""" 49 | a = 20 # pylint: disable=invalid-name 50 | b = 10 # pylint: disable=invalid-name 51 | region = NormalizedRegion(_RegionMock(a, b)) 52 | self.assertEqual(b, region.a) 53 | self.assertEqual(a, region.b) 54 | self.assertEqual(10, region.length()) 55 | 56 | def test_region_call(self): 57 | """Test region call.""" 58 | a = 10 # pylint: disable=invalid-name 59 | b = 20 # pylint: disable=invalid-name 60 | mock_region = mock() 61 | region = NormalizedRegion(_RegionMock(a, b)) 62 | when(sublime).Region(a, b).thenReturn(mock_region) 63 | self.assertEqual(mock_region, region.region()) 64 | 65 | def test_equal(self): 66 | """Test region equals operator.""" 67 | region = NormalizedRegion(10, 20) 68 | other_region = NormalizedRegion(10, 30) 69 | self.assertEqual(region, region) 70 | self.assertNotEqual(region, other_region) 71 | 72 | def test_str(self): 73 | """Test region string operator.""" 74 | region = NormalizedRegion(10, 20) 75 | self.assertEqual("(10, 20)", str(region)) 76 | 77 | def test_hash(self): 78 | """Test region hash operator.""" 79 | region = NormalizedRegion(10, 20) 80 | self.assertEqual(30, hash(region)) 81 | -------------------------------------------------------------------------------- /tests/test_phantom_color_highlighter.py: -------------------------------------------------------------------------------- 1 | """Tests for PhantomColorHighlighter.""" 2 | 3 | import unittest 4 | 5 | from ColorHighlighter import sublime # pylint: disable=no-name-in-module 6 | from ColorHighlighter.phantoms_color_highlighter import ( # pylint: disable=no-name-in-module,import-error 7 | PhantomColorHighlighter) 8 | from ColorHighlighter.regions import NormalizedRegion # pylint: disable=no-name-in-module,import-error 9 | 10 | from mockito import ANY, mock, verify, when 11 | 12 | 13 | class PhantomColorHighlighterTest(unittest.TestCase): 14 | """Tests for PhantomColorHighlighter.""" 15 | 16 | test_name = "test-name" 17 | 18 | def test_highlight(self): # pylint: disable=no-self-use 19 | """Test highlighting a region adds a phantom to the view.""" 20 | view = mock() 21 | 22 | test_color = "test" 23 | begin = 4 24 | end = begin + len(test_color) 25 | region = mock() 26 | when(sublime).Region(begin, end).thenReturn(region) 27 | 28 | html = ''' 29 | 30 | 35 |      36 | 37 | ''' 38 | phantom_id = 95 39 | when(view).add_phantom( 40 | PhantomColorHighlighter.phantom_key_template % 41 | (self.test_name, begin, end), region, html, sublime.LAYOUT_BELOW, None).thenReturn(phantom_id) 42 | 43 | PhantomColorHighlighter(view, self.test_name, "below", 10, False).highlight_region( 44 | None, (NormalizedRegion(begin, end), test_color)) 45 | verify(view).add_phantom( 46 | PhantomColorHighlighter.phantom_key_template % 47 | (self.test_name, begin, end), region, html, sublime.LAYOUT_BELOW, None) 48 | 49 | def test_highlight_right(self): # pylint: disable=no-self-use 50 | """Test highlighting a region adds a phantom to the right of the color to the view.""" 51 | view = mock() 52 | 53 | test_color = "test" 54 | begin = 4 55 | end = begin + len(test_color) 56 | region = mock() 57 | when(sublime).Region(end, end).thenReturn(region) 58 | 59 | html = ''' 60 | 61 | 66 |       67 | 68 | ''' 69 | phantom_id = 95 70 | when(view).add_phantom( 71 | PhantomColorHighlighter.phantom_key_template % 72 | (self.test_name, begin, end), region, html, sublime.LAYOUT_INLINE, None).thenReturn(phantom_id) 73 | 74 | PhantomColorHighlighter(view, self.test_name, "right", 5, False).highlight_region( 75 | None, (NormalizedRegion(begin, end), test_color)) 76 | verify(view).add_phantom( 77 | PhantomColorHighlighter.phantom_key_template % 78 | (self.test_name, begin, end), region, html, sublime.LAYOUT_INLINE, None) 79 | 80 | def test_highlight_left(self): # pylint: disable=no-self-use 81 | """Test highlighting a region adds a phantom to the left of the color to the view.""" 82 | view = mock() 83 | 84 | test_color = "test" 85 | begin = 4 86 | end = begin + len(test_color) 87 | region = mock() 88 | when(sublime).Region(begin, begin).thenReturn(region) 89 | 90 | html = ''' 91 | 92 | 97 |       98 | 99 | ''' 100 | phantom_id = 95 101 | when(view).add_phantom( 102 | PhantomColorHighlighter.phantom_key_template % 103 | (self.test_name, begin, end), region, html, sublime.LAYOUT_INLINE, None).thenReturn(phantom_id) 104 | 105 | PhantomColorHighlighter(view, self.test_name, "left", 5, False).highlight_region( 106 | None, (NormalizedRegion(begin, end), test_color)) 107 | verify(view).add_phantom( 108 | PhantomColorHighlighter.phantom_key_template % 109 | (self.test_name, begin, end), region, html, sublime.LAYOUT_INLINE, None) 110 | 111 | def test_unhighlight(self): # pylint: disable=no-self-use 112 | """Test unhighlighting a region removes the added phantom from the view.""" 113 | view = mock() 114 | color_highlighter = PhantomColorHighlighter(view, self.test_name, "below", 1, False) 115 | 116 | begin = 4 117 | end = 9 118 | region = mock() 119 | when(sublime).Region(begin, end).thenReturn(region) 120 | 121 | phantom_id = 95 122 | when(view).add_phantom(ANY, ANY, ANY, ANY, ANY).thenReturn(phantom_id) 123 | 124 | color_highlighter.unhighlight_region(None, (NormalizedRegion(begin, end), None)) 125 | verify(view).erase_phantoms(PhantomColorHighlighter.phantom_key_template % (self.test_name, begin, end)) 126 | -------------------------------------------------------------------------------- /tests/test_regions.py: -------------------------------------------------------------------------------- 1 | """Tests for regions.NormalizedRegion.""" 2 | 3 | import unittest 4 | 5 | from ColorHighlighter.regions import ( # pylint: disable=no-name-in-module,import-error 6 | NormalizedRegion, deduplicate_regions, intersects, intersects_any) 7 | 8 | 9 | class IntersectTest(unittest.TestCase): 10 | """Tests for intersects.""" 11 | 12 | def test_intersects(self): 13 | """Test all cases.""" 14 | region = NormalizedRegion(4, 7) 15 | self.assertFalse(intersects(NormalizedRegion(1, 3), region)) 16 | self.assertFalse(intersects(NormalizedRegion(2, 4), region)) 17 | self.assertTrue(intersects(NormalizedRegion(4, 4), region)) 18 | self.assertTrue(intersects(NormalizedRegion(3, 5), region)) 19 | self.assertTrue(intersects(NormalizedRegion(4, 7), region)) 20 | self.assertTrue(intersects(NormalizedRegion(5, 8), region)) 21 | self.assertTrue(intersects(NormalizedRegion(7, 7), region)) 22 | self.assertFalse(intersects(NormalizedRegion(7, 9), region)) 23 | self.assertFalse(intersects(NormalizedRegion(8, 10), region)) 24 | 25 | 26 | class IntersectAnyTest(unittest.TestCase): 27 | """Tests for intersects_any.""" 28 | 29 | def test_intersects_any(self): 30 | """Test all cases.""" 31 | region = NormalizedRegion(4, 7) 32 | self.assertFalse(intersects_any(region, [NormalizedRegion(1, 3)])) 33 | self.assertFalse(intersects_any(region, [NormalizedRegion(1, 3), NormalizedRegion(0, 1)])) 34 | self.assertTrue(intersects_any(region, [NormalizedRegion(3, 5)])) 35 | self.assertTrue(intersects_any(region, [NormalizedRegion(3, 5), NormalizedRegion(5, 6)])) 36 | self.assertTrue(intersects_any(region, [NormalizedRegion(3, 5), NormalizedRegion(1, 3)])) 37 | 38 | 39 | class DeduplicateRegionsTest(unittest.TestCase): 40 | """Tests for deduplicate_regions.""" 41 | 42 | def test_deduplicate(self): 43 | """Test deduplicating regions.""" 44 | region1 = 1 45 | region2 = 2 46 | regions = [region1, region2, region1] 47 | output = [value for value in deduplicate_regions(regions)] 48 | self.assertEqual([region1, region2], output) 49 | -------------------------------------------------------------------------------- /topsort.py: -------------------------------------------------------------------------------- 1 | """An implementation of the topological sorting algorithm.""" 2 | 3 | 4 | def sort(data, get_depencencies): 5 | """ 6 | Topologically sort data. 7 | 8 | Arguments: 9 | - data - a dict from object ids to their dependencies. 10 | - get_depencencies - a function that gets a list of dependend object ids. 11 | Returns a list of object ids sorted topologically. 12 | """ 13 | nodes = {} 14 | for key in data.keys(): 15 | value = data[key] 16 | nodes[key] = _Node(value, get_depencencies(value)) 17 | 18 | results = [] 19 | while _visit_node(nodes, results): 20 | pass 21 | return results 22 | 23 | 24 | def _visit_node(data, results): 25 | for key in data.keys(): 26 | if not data[key].visited: 27 | _visit(data, key, results) 28 | return True 29 | return False 30 | 31 | 32 | def _visit(data, key, results): 33 | value = data[key] 34 | if value.in_stack: 35 | raise ValueError("Not a DAG!") 36 | if value.visited: 37 | return 38 | 39 | value.in_stack = True 40 | for depencency in value.depencencies: 41 | _visit(data, depencency, results) 42 | value.visited = True 43 | value.in_stack = False 44 | results.append(key) 45 | 46 | 47 | class _Node(object): # pylint: disable=too-few-public-methods 48 | def __init__(self, value, depencencies): 49 | self.value = value 50 | self.depencencies = depencencies 51 | self.in_stack = False 52 | self.visited = False 53 | --------------------------------------------------------------------------------