From 33fe1573aded38bed331cf677b8a6ca0fb6867cc Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Sun, 10 Jun 2012 22:19:42 +0100 Subject: [PATCH] Ensure autocomplete menu is on top. The menu should appear above other normal windows and controls like a regular CPMenu. To do this, put the pop up in its own window with the `CPPopUpMenuWindowLevel` window level. --- AppKit/CPTokenField.j | 37 ++++++++---------------------------- AppKit/_CPAutocompleteMenu.j | 37 ++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/AppKit/CPTokenField.j b/AppKit/CPTokenField.j index 384777b52e..7762eb5024 100755 --- a/AppKit/CPTokenField.j +++ b/AppKit/CPTokenField.j @@ -63,7 +63,7 @@ var CPScrollDestinationNone = 0, CPRange _selectedRange; - _CPAutocompleteMenu _autocompleteMenu @accessors; + _CPAutocompleteMenu _autocompleteMenu; CPTimeInterval _completionDelay; @@ -119,8 +119,13 @@ var CPScrollDestinationNone = 0, [_tokenScrollView setDocumentView:contentView]; [self addSubview:_tokenScrollView]; +} - _autocompleteMenu = [[_CPAutocompleteMenu alloc] initWithTextField:self]; +- (_CPAutocompleteMenu)_autocompleteMenu +{ + if (!_autocompleteMenu) + _autocompleteMenu = [[_CPAutocompleteMenu alloc] initWithTextField:self]; + return _autocompleteMenu; } - (void)_autocompleteWithDOMEvent:(JSObject)DOMEvent @@ -352,8 +357,6 @@ var CPScrollDestinationNone = 0, - (BOOL)resignFirstResponder { - CPLog("%@ resignFirstResponder", self); - if (_preventResign) return NO; @@ -566,25 +569,6 @@ var CPScrollDestinationNone = 0, { } -// ======== -// = VIEW = -// ======== -- (void)viewDidMoveToWindow -{ - // TODO Switch to a window. - [[[self window] contentView] addSubview:[_autocompleteMenu contentView]]; - -#if PLATFORM(DOM) - [_autocompleteMenu contentView]._DOMElement.style.zIndex = 1000; // Anything else doesn't seem to work -#endif -} - -- (void)removeFromSuperview -{ - // TODO - [[_autocompleteMenu contentView] removeFromSuperview]; -} - // ============= // = TEXTFIELD = // ============= @@ -1014,11 +998,6 @@ var CPScrollDestinationNone = 0, return [[_tokenScrollView documentView] scrollRectToVisible:[aToken frame]]; } -- (CPTableView)_autocompleteView -{ - return _autocompleteView; -} - @end @implementation CPTokenField (CPTokenFieldDelegate) @@ -1125,7 +1104,7 @@ var CPScrollDestinationNone = 0, - (void)_delayedShowCompletions { - [_autocompleteMenu _delayedShowCompletions]; + [[self _autocompleteMenu] _delayedShowCompletions]; } - (void)_hideCompletions diff --git a/AppKit/_CPAutocompleteMenu.j b/AppKit/_CPAutocompleteMenu.j index 196dd0a310..a8be9d0ef3 100644 --- a/AppKit/_CPAutocompleteMenu.j +++ b/AppKit/_CPAutocompleteMenu.j @@ -34,7 +34,7 @@ CPTextField textField @accessors; CPArray contentArray @accessors; - CPView contentView @accessors; + CPWindow _menuWindow; CPScrollView scrollView; CPTableView tableView; @@ -47,9 +47,15 @@ { textField = aTextField; - contentView = [[CPView alloc] initWithFrame:CGRectMakeZero()]; + _menuWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0, 0, 100, 100) styleMask:CPBorderlessWindowMask]; - [contentView setBackgroundColor:[_CPMenuWindow backgroundColorForBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle]]; + [_menuWindow setLevel:CPPopUpMenuWindowLevel]; + [_menuWindow setHasShadow:YES]; + [_menuWindow setShadowStyle:CPMenuWindowShadowStyle]; + [_menuWindow setAcceptsMouseMovedEvents:NO]; + [_menuWindow setBackgroundColor:[_CPMenuWindow backgroundColorForBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle]]; + + var contentView = [_menuWindow contentView]; scrollView = [[CPScrollView alloc] initWithFrame:CGRectMakeZero()]; [scrollView setAutohidesScrollers:YES]; @@ -107,11 +113,14 @@ - (void)layoutSubviews { // TODO - // The autocompletion menu should be underneath the current token, it should at least be wide enough to fit the widest - // option but no wider than the width of the token field. It might stick out on the right side, so that if the token - // is small enough to fit on the right side the menu might extend a full token field width more into space on the right - // side. It should not stick out outside of the screen. The height should be the smallest possible to fit all options - // or at most ~307px (based on Cocoa). If the options don't fit horizontally they should be truncated with an ellipsis. + /* + The autocompletion menu should be underneath the word/text being autocompleted. It should at least be wide enough to + fit the widest + option but no wider than the width of the text field. It might stick out on the right side, so that if the edited text + is on the right of the text field the menu might extend a full text field width more into space on the right + side. It should not stick out outside of the screen. The height should be the smallest possible to fit all options + or at most ~307px (based on Cocoa). If the options don't fit horizontally they should be truncated with an ellipsis. + */ var frame = [textField frame]; @@ -120,10 +129,10 @@ [[[tableView tableColumns] firstObject] setWidth:[[scrollView contentView] frame].size.width]; // Manually sizeToFit because CPTableView's sizeToFit doesn't work properly - var frameOrigin = [textField convertPoint:[textField bounds].origin toView:[contentView superview]], + var frameOrigin = [textField convertPoint:[textField bounds].origin toView:nil], newFrame = CGRectMake(frameOrigin.x, frameOrigin.y + frame.size.height, CPRectGetWidth([textField bounds]), 92.0); - [contentView setFrame:newFrame]; - [scrollView setFrame:CGRectInset([contentView bounds], 1.0, 1.0)]; + [_menuWindow setFrame:[_menuWindow frameRectForContentRect:newFrame]]; + [scrollView setFrame:CGRectInset([[_menuWindow contentView] bounds], 1.0, 1.0)]; } - (void)_showCompletions:(CPTimer)timer @@ -136,7 +145,7 @@ [self setIndexOfSelectedItem:indexOfSelectedItem]; [textField setThemeState:CPThemeStateAutocompleting]; - [contentView setHidden:NO]; + [_menuWindow orderFront:self]; [self layoutSubviews]; } @@ -161,7 +170,7 @@ _showCompletionsTimer = nil; [textField unsetThemeState:CPThemeStateAutocompleting]; - [contentView setHidden:YES]; + [_menuWindow orderOut:self]; [self layoutSubviews]; } @@ -201,7 +210,7 @@ // make sure a mouse click in the tableview doesn't steal first responder state window.setTimeout(function() { - [[contentView window] makeFirstResponder:textField]; + [[textField window] makeFirstResponder:textField]; }, 2.0); }