Revision: 22216 http://sourceforge.net/p/bibdesk/svn/22216 Author: hofman Date: 2018-05-04 14:57:07 +0000 (Fri, 04 May 2018) Log Message: ----------- implement location for completion window in completion controller class
Modified Paths: -------------- trunk/bibdesk/BDSKTextViewCompletionController.h trunk/bibdesk/BDSKTextViewCompletionController.m trunk/bibdesk/NSTextView_BDSKExtensions.h trunk/bibdesk/NSTextView_BDSKExtensions.m Modified: trunk/bibdesk/BDSKTextViewCompletionController.h =================================================================== --- trunk/bibdesk/BDSKTextViewCompletionController.h 2018-05-04 06:31:25 UTC (rev 22215) +++ trunk/bibdesk/BDSKTextViewCompletionController.h 2018-05-04 14:57:07 UTC (rev 22216) @@ -37,8 +37,6 @@ */ #import <Cocoa/Cocoa.h> -/* need the locationForCompletionWindow declaration */ -#import "NSTextView_BDSKExtensions.h" @interface BDSKTextViewCompletionController : NSWindowController <NSTableViewDelegate, NSTableViewDataSource> Modified: trunk/bibdesk/BDSKTextViewCompletionController.m =================================================================== --- trunk/bibdesk/BDSKTextViewCompletionController.m 2018-05-04 06:31:25 UTC (rev 22215) +++ trunk/bibdesk/BDSKTextViewCompletionController.m 2018-05-04 14:57:07 UTC (rev 22216) @@ -50,6 +50,7 @@ - (void)setupTable; - (void)updateCompletionsAndInsert:(BOOL)insert; - (void)setWindowFrameForCurrentTextView; +- (NSPoint)windowLocation; - (NSSize)windowContentSize; - (void)registerForNotifications; - (void)handleWindowChangedNotification:(NSNotification *)notification; @@ -347,7 +348,7 @@ { NSRect frame; - frame.origin = [[self currentTextView] locationForCompletionWindow]; + frame.origin = [self windowLocation]; frame.size = [self windowContentSize]; // if the point is NSZeroPoint, it's not valid, so don't move the window; alternately, could endDisplayNoComplete, but we're probably ending anyway @@ -372,6 +373,55 @@ [[self window] setFrame:frame display:NO]; } +- (NSPoint)windowLocation +{ + NSPoint point = NSZeroPoint; + NSTextView *tv = [self currentTextView]; + NSRange selRange = [tv rangeForUserCompletion]; + + // @@ hack: if there is no character at this point (it may be just an accent), our line fragment rect will not be accurate for what we really need, so returning NSZeroPoint indicates to the caller that this is invalid + if(selRange.length == 0 || selRange.location == NSNotFound) + return point; + + NSLayoutManager *layoutManager = [tv layoutManager]; + + // get the rect for the first glyph in our affected range + NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:selRange actualCharacterRange:NULL]; + NSRect rect = NSZeroRect; + + // check length, or the layout manager will raise an exception + if(glyphRange.length > 0){ + rect = [layoutManager lineFragmentRectForGlyphAtIndex:glyphRange.location effectiveRange:NULL]; + point = rect.origin; + + // the above gives the rect for the full line + NSPoint glyphLoc = [layoutManager locationForGlyphAtIndex:glyphRange.location]; + point.x += glyphLoc.x; + // don't adjust based on glyphLoc.y; we'll use the lineFragmentRect for that + } + + // adjust for the line height + border/focus ring + point.y += NSHeight(rect) + 3; + + // adjust for the text container origin + NSPoint tcOrigin = [tv textContainerOrigin]; + point.x += tcOrigin.x; + point.y += tcOrigin.y; + + // make sure we have integral coordinates + point.x = ceil(point.x); + point.y = ceil(point.y); + + // make sure we don't put the window before the textfield when the text is scrolled + if (point.x < [tv visibleRect].origin.x) + point.x = [tv visibleRect].origin.x; + + // convert to screen coordinates + point = [[tv window] convertBaseToScreen:[tv convertPoint:point toView:nil]]; + + return point; +} + - (NSSize)windowContentSize { CGFloat hSize = 0.0f; @@ -414,7 +464,7 @@ - (void)handleWindowChangedNotification:(NSNotification *)notification { [self endDisplayAndComplete:NO]; } -// retain the text view, just in case; we've seen some unreproducible crashes in objc_msgSend_stret when calling updateCompletionsAndInsert:, which is presumably the call to rangeForUserCompletion or locationForCompletionWindow +// retain the text view, just in case; we've seen some unreproducible crashes in objc_msgSend_stret when calling updateCompletionsAndInsert:, which is presumably the call to rangeForUserCompletion or windowLocation - (void)setCurrentTextView:(NSTextView *)tv; { if(tv != textView){ Modified: trunk/bibdesk/NSTextView_BDSKExtensions.h =================================================================== --- trunk/bibdesk/NSTextView_BDSKExtensions.h 2018-05-04 06:31:25 UTC (rev 22215) +++ trunk/bibdesk/NSTextView_BDSKExtensions.h 2018-05-04 14:57:07 UTC (rev 22216) @@ -46,6 +46,4 @@ - (void)setSafeSelectedRanges:(NSArray *)ranges; -- (NSPoint)locationForCompletionWindow; - @end Modified: trunk/bibdesk/NSTextView_BDSKExtensions.m =================================================================== --- trunk/bibdesk/NSTextView_BDSKExtensions.m 2018-05-04 06:31:25 UTC (rev 22215) +++ trunk/bibdesk/NSTextView_BDSKExtensions.m 2018-05-04 14:57:07 UTC (rev 22216) @@ -208,54 +208,4 @@ [self setSelectedRanges:mutableRanges]; } -- (NSPoint)locationForCompletionWindow; -{ - NSPoint point = NSZeroPoint; - - NSRange selRange = [self rangeForUserCompletion]; - - // @@ hack: if there is no character at this point (it may be just an accent), our line fragment rect will not be accurate for what we really need, so returning NSZeroPoint indicates to the caller that this is invalid - if(selRange.length == 0 || selRange.location == NSNotFound) - return point; - - NSLayoutManager *layoutManager = [self layoutManager]; - - // get the rect for the first glyph in our affected range - NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:selRange actualCharacterRange:NULL]; - NSRect rect = NSZeroRect; - - // check length, or the layout manager will raise an exception - if(glyphRange.length > 0){ - rect = [layoutManager lineFragmentRectForGlyphAtIndex:glyphRange.location effectiveRange:NULL]; - point = rect.origin; - - // the above gives the rect for the full line - NSPoint glyphLoc = [layoutManager locationForGlyphAtIndex:glyphRange.location]; - point.x += glyphLoc.x; - // don't adjust based on glyphLoc.y; we'll use the lineFragmentRect for that - } - - // adjust for the line height + border/focus ring - point.y += NSHeight(rect) + 3; - - // adjust for the text container origin - NSPoint tcOrigin = [self textContainerOrigin]; - point.x += tcOrigin.x; - point.y += tcOrigin.y; - - // make sure we have integral coordinates - point.x = ceil(point.x); - point.y = ceil(point.y); - - // make sure we don't put the window before the textfield when the text is scrolled - if (point.x < [self visibleRect].origin.x) - point.x = [self visibleRect].origin.x; - - // convert to screen coordinates - point = [self convertPoint:point toView:nil]; - point = [[self window] convertBaseToScreen:point]; - - return point; -} - @end This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Bibdesk-commit mailing list Bibdesk-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/bibdesk-commit