mirror of
https://github.com/coteditor/CotEditor.git
synced 2024-09-11 11:25:57 +03:00
Add ability to draw invisibles to find panel fields
This commit is contained in:
parent
2732985c09
commit
dd57aeb50b
@ -10,6 +10,7 @@ Change Log
|
||||
- Change place to create backup files (Now, backup files are always created in `~/Library/Autosave Information/`).
|
||||
- Improve find panel:
|
||||
- Add scroll bars to the text fields.
|
||||
- Show invisible characters in text fields.
|
||||
- Now, “Swap Yen and backslash keys” option is also applied to the fields in the find panel.
|
||||
- Remove “Escape Character” option for regular expression search.
|
||||
- Add “Cyrillic (Windows)” to the encoding list.
|
||||
|
@ -124,6 +124,7 @@
|
||||
2AD5322A19779FD000A925CA /* CELineHeightTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD5322919779FD000A925CA /* CELineHeightTransformer.m */; };
|
||||
2AD67C241AA7285F0078BB95 /* CEFindPanelTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD67C231AA7285F0078BB95 /* CEFindPanelTextView.m */; };
|
||||
2AD67C2A1AA75E7F0078BB95 /* CEFindPanelTextClipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD67C291AA75E7F0078BB95 /* CEFindPanelTextClipView.m */; };
|
||||
2AD67C2F1AA7651B0078BB95 /* CEFindPanelLayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD67C2E1AA7651B0078BB95 /* CEFindPanelLayoutManager.m */; };
|
||||
2AD84CAA1966314100DE49BD /* CEODBEventSender.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AD84CA91966314100DE49BD /* CEODBEventSender.m */; };
|
||||
2AE2E9D519D2CF00000D66A9 /* CEEncodingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2E9D419D2CF00000D66A9 /* CEEncodingManager.m */; };
|
||||
2AE356461A86D32500E29FEF /* CEClipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AE356451A86D32500E29FEF /* CEClipView.m */; };
|
||||
@ -487,6 +488,8 @@
|
||||
2AD67C231AA7285F0078BB95 /* CEFindPanelTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CEFindPanelTextView.m; sourceTree = "<group>"; };
|
||||
2AD67C281AA75E7F0078BB95 /* CEFindPanelTextClipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CEFindPanelTextClipView.h; sourceTree = "<group>"; };
|
||||
2AD67C291AA75E7F0078BB95 /* CEFindPanelTextClipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CEFindPanelTextClipView.m; sourceTree = "<group>"; };
|
||||
2AD67C2D1AA7651B0078BB95 /* CEFindPanelLayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CEFindPanelLayoutManager.h; sourceTree = "<group>"; };
|
||||
2AD67C2E1AA7651B0078BB95 /* CEFindPanelLayoutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CEFindPanelLayoutManager.m; sourceTree = "<group>"; };
|
||||
2AD84CA81966314100DE49BD /* CEODBEventSender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CEODBEventSender.h; sourceTree = "<group>"; };
|
||||
2AD84CA91966314100DE49BD /* CEODBEventSender.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CEODBEventSender.m; sourceTree = "<group>"; };
|
||||
2AE2E9D319D2CF00000D66A9 /* CEEncodingManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CEEncodingManager.h; sourceTree = "<group>"; };
|
||||
@ -1043,6 +1046,8 @@
|
||||
2A009AD01A58ED1D00C3D542 /* CEFindResultViewController.m */,
|
||||
2AD67C221AA7285F0078BB95 /* CEFindPanelTextView.h */,
|
||||
2AD67C231AA7285F0078BB95 /* CEFindPanelTextView.m */,
|
||||
2AD67C2D1AA7651B0078BB95 /* CEFindPanelLayoutManager.h */,
|
||||
2AD67C2E1AA7651B0078BB95 /* CEFindPanelLayoutManager.m */,
|
||||
2A009ADB1A5AB96F00C3D542 /* Views */,
|
||||
);
|
||||
name = "Text Finder";
|
||||
@ -1437,6 +1442,7 @@
|
||||
2A3A759419E77D66001DAB88 /* CEMigrationWindowController.m in Sources */,
|
||||
2A51793A1A40A3B500A3F852 /* CEShortcutKeyField.m in Sources */,
|
||||
2AD67C2A1AA75E7F0078BB95 /* CEFindPanelTextClipView.m in Sources */,
|
||||
2AD67C2F1AA7651B0078BB95 /* CEFindPanelLayoutManager.m in Sources */,
|
||||
2A7846DE18FE0C0C006BDF00 /* CETheme.m in Sources */,
|
||||
2A68F93818FB04F400673440 /* CEMenuItemCell.m in Sources */,
|
||||
2AB432711912AF7200835004 /* CEGlyphPopoverController.m in Sources */,
|
||||
|
35
CotEditor/Sources/CEFindPanelLayoutManager.h
Normal file
35
CotEditor/Sources/CEFindPanelLayoutManager.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
==============================================================================
|
||||
CEFindPanelLayoutManager
|
||||
|
||||
CotEditor
|
||||
http://coteditor.com
|
||||
|
||||
Created on 2015-03-04 by 1024jp
|
||||
encoding="UTF-8"
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
© 2015 1024jp
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
@import Cocoa;
|
||||
|
||||
|
||||
@interface CEFindPanelLayoutManager : NSLayoutManager
|
||||
|
||||
@end
|
180
CotEditor/Sources/CEFindPanelLayoutManager.m
Normal file
180
CotEditor/Sources/CEFindPanelLayoutManager.m
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
==============================================================================
|
||||
CEFindPanelLayoutManager
|
||||
|
||||
CotEditor
|
||||
http://coteditor.com
|
||||
|
||||
Created on 2015-03-04 by 1024jp
|
||||
encoding="UTF-8"
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
© 2015 1024jp
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#import "CEFindPanelLayoutManager.h"
|
||||
#import "CEUtils.h"
|
||||
#import "constants.h"
|
||||
|
||||
|
||||
// constants
|
||||
static const CGFloat kLineSpacing = 4.0;
|
||||
|
||||
|
||||
@interface CEFindPanelLayoutManager ()
|
||||
|
||||
@property (nonatomic, copy) NSDictionary *invisibleAttributes;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation CEFindPanelLayoutManager
|
||||
|
||||
|
||||
#pragma mark Superclass Methods
|
||||
|
||||
// ------------------------------------------------------
|
||||
/// initialize instance
|
||||
- (instancetype)init
|
||||
// ------------------------------------------------------
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self setUsesScreenFonts:YES];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
/// show invisible characters
|
||||
- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(NSPoint)origin
|
||||
// ------------------------------------------------------
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
BOOL showInvisibles = YES;
|
||||
|
||||
if (showInvisibles) {
|
||||
NSTextView *textView = [self firstTextView];
|
||||
NSString *completeStr = [[self textStorage] string];
|
||||
NSUInteger lengthToRedraw = NSMaxRange(glyphsToShow);
|
||||
NSSize size = [textView textContainerInset];
|
||||
|
||||
NSColor *color;
|
||||
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_9) {
|
||||
color = [NSColor tertiaryLabelColor];
|
||||
} else {
|
||||
color = [NSColor colorWithCalibratedWhite:0.0 alpha:0.25];
|
||||
}
|
||||
|
||||
NSFont *font = [[self firstTextView] font];
|
||||
font = [font screenFont] ? : font;
|
||||
NSFont *fullwidthFont = [[NSFont fontWithName:@"HiraKakuProN-W3" size:[font pointSize]] screenFont] ? : font;
|
||||
NSDictionary *attributes = @{NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: color};
|
||||
NSDictionary *fullwidthAttributes = @{NSFontAttributeName: fullwidthFont,
|
||||
NSForegroundColorAttributeName: color};
|
||||
|
||||
BOOL showsSpace = [defaults boolForKey:CEDefaultShowInvisibleSpaceKey];
|
||||
BOOL showsTab = [defaults boolForKey:CEDefaultShowInvisibleTabKey];
|
||||
BOOL showsNewLine = [defaults boolForKey:CEDefaultShowInvisibleNewLineKey];
|
||||
BOOL showsFullwidthSpace = [defaults boolForKey:CEDefaultShowInvisibleFullwidthSpaceKey];
|
||||
BOOL showsOtherInvisibles = [defaults boolForKey:CEDefaultShowOtherInvisibleCharsKey];
|
||||
|
||||
unichar spaceCharacter = [CEUtils invisibleSpaceChar:[defaults integerForKey:CEDefaultInvisibleSpaceKey]];
|
||||
NSAttributedString *space = [[NSAttributedString alloc] initWithString:[NSString stringWithCharacters:&spaceCharacter length:1]
|
||||
attributes:attributes];
|
||||
|
||||
unichar tabCharacter = [CEUtils invisibleTabChar:[defaults integerForKey:CEDefaultInvisibleTabKey]];
|
||||
NSAttributedString *tab = [[NSAttributedString alloc] initWithString:[NSString stringWithCharacters:&tabCharacter length:1]
|
||||
attributes:attributes];
|
||||
|
||||
unichar newLineCharacter = [CEUtils invisibleNewLineChar:[defaults integerForKey:CEDefaultInvisibleNewLineKey]];
|
||||
NSAttributedString *newLine = [[NSAttributedString alloc] initWithString:[NSString stringWithCharacters:&newLineCharacter length:1]
|
||||
attributes:attributes];
|
||||
|
||||
unichar fullwidthSpaceCharacter = [CEUtils invisibleFullwidthSpaceChar:[defaults integerForKey:CEDefaultInvisibleFullwidthSpaceKey]];
|
||||
NSAttributedString *fullwidthSpace = [[NSAttributedString alloc] initWithString:[NSString stringWithCharacters:&fullwidthSpaceCharacter length:1]
|
||||
attributes:fullwidthAttributes];
|
||||
|
||||
for (NSUInteger glyphIndex = glyphsToShow.location; glyphIndex < lengthToRedraw; glyphIndex++) {
|
||||
NSUInteger charIndex = [self characterIndexForGlyphAtIndex:glyphIndex];
|
||||
unichar character = [completeStr characterAtIndex:charIndex];
|
||||
|
||||
if (showsSpace && ((character == ' ') || (character == 0x00A0))) {
|
||||
NSPoint pointToDraw = [self pointToDrawGlyphAtIndex:glyphIndex adjust:size];
|
||||
[space drawAtPoint:pointToDraw];
|
||||
|
||||
} else if (showsTab && (character == '\t')) {
|
||||
NSPoint pointToDraw = [self pointToDrawGlyphAtIndex:glyphIndex adjust:size];
|
||||
[tab drawAtPoint:pointToDraw];
|
||||
|
||||
} else if (showsNewLine && (character == '\n')) {
|
||||
NSPoint pointToDraw = [self pointToDrawGlyphAtIndex:glyphIndex adjust:size];
|
||||
[newLine drawAtPoint:pointToDraw];
|
||||
|
||||
} else if (showsFullwidthSpace && (character == 0x3000)) { // Fullwidth-space (JP)
|
||||
NSPoint pointToDraw = [self pointToDrawGlyphAtIndex:glyphIndex adjust:size];
|
||||
[fullwidthSpace drawAtPoint:pointToDraw];
|
||||
|
||||
} else if (showsOtherInvisibles && ([self glyphAtIndex:glyphIndex] == NSControlGlyph)) {
|
||||
NSFont *replaceFont = [NSFont fontWithName:@"Lucida Grande" size:[font pointSize]];
|
||||
NSGlyph replaceGlyph = [replaceFont glyphWithName:@"replacement"];
|
||||
NSUInteger charLength = CFStringIsSurrogateHighCharacter(character) ? 2 : 1;
|
||||
NSRange charRange = NSMakeRange(charIndex, charLength);
|
||||
NSString *baseStr = [completeStr substringWithRange:charRange];
|
||||
NSGlyphInfo *glyphInfo = [NSGlyphInfo glyphInfoWithGlyph:replaceGlyph forFont:replaceFont baseString:baseStr];
|
||||
|
||||
if (glyphInfo) {
|
||||
NSDictionary *replaceAttrs = @{NSGlyphInfoAttributeName: glyphInfo,
|
||||
NSFontAttributeName: replaceFont,
|
||||
NSForegroundColorAttributeName: color};
|
||||
NSDictionary *attrs = [[self textStorage] attributesAtIndex:charIndex effectiveRange:NULL];
|
||||
if (attrs[NSGlyphInfoAttributeName] == nil) {
|
||||
[[self textStorage] addAttributes:replaceAttrs range:charRange];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[super drawGlyphsForGlyphRange:glyphsToShow atPoint:origin];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark Private Methods
|
||||
|
||||
//------------------------------------------------------
|
||||
/// calculate point to draw invisible character
|
||||
- (NSPoint)pointToDrawGlyphAtIndex:(NSUInteger)glyphIndex adjust:(NSSize)size
|
||||
//------------------------------------------------------
|
||||
{
|
||||
NSPoint drawPoint = [self locationForGlyphAtIndex:glyphIndex];
|
||||
NSRect theGlyphRect = [self lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange:NULL];
|
||||
|
||||
drawPoint.x += size.width;
|
||||
drawPoint.y = theGlyphRect.origin.y + size.height;
|
||||
|
||||
return drawPoint;
|
||||
}
|
||||
|
||||
@end
|
@ -28,6 +28,7 @@
|
||||
*/
|
||||
|
||||
#import "CEFindPanelTextView.h"
|
||||
#import "CEFindPanelLayoutManager.h"
|
||||
#import "CEFindPanelController.h"
|
||||
#import "constants.h"
|
||||
|
||||
@ -65,6 +66,10 @@
|
||||
[[self textContainer] setWidthTracksTextView:NO];
|
||||
[[self textContainer] setContainerSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||
[self setHorizontallyResizable:YES];
|
||||
|
||||
// set subclassed layout manager for invisible characters
|
||||
CEFindPanelLayoutManager *layoutManager = [[CEFindPanelLayoutManager alloc] init];
|
||||
[[self textContainer] replaceLayoutManager:layoutManager];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user