mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-27 02:25:36 +00:00
Autosize token field autocomplete menu.
The new menu is much more efficient for the user: * Less tall items makes it much easier to select among many completions. * Exactly wide enough for widest item. * Tall enough to show all items (instead of just 3 as before). * Uses a maximum width and height defined by the screen edges and some Cocoa-like constants.
This commit is contained in:
1 parent
85cfb18906
commit
9575fd7771
1 file changed
+48
-9
@@ -25,6 +25,8 @@
|
||||
@import "CPTextField.j"
|
||||
@import "_CPMenuWindow.j"
|
||||
|
||||
// TODO Make themable.
|
||||
var _CPAutocompleteMenuMaximumHeight = 307;
|
||||
|
||||
/*!
|
||||
An "autocomplete" menu displayed by a text field.
|
||||
@@ -33,6 +35,7 @@
|
||||
{
|
||||
CPTextField textField @accessors;
|
||||
CPArray contentArray @accessors;
|
||||
float widestItemWidth;
|
||||
|
||||
CPWindow _menuWindow;
|
||||
CPScrollView scrollView;
|
||||
@@ -73,7 +76,7 @@
|
||||
[tableView setAllowsMultipleSelection:NO];
|
||||
[tableView setHeaderView:nil];
|
||||
[tableView setCornerView:nil];
|
||||
[tableView setRowHeight:30.0];
|
||||
[tableView setRowHeight:24.0];
|
||||
[tableView setGridStyleMask:CPTableViewSolidHorizontalGridLineMask];
|
||||
[tableView setBackgroundColor:[CPColor clearColor]];
|
||||
[tableView setGridColor:[CPColor colorWithRed:242.0 / 255.0 green:243.0 / 255.0 blue:245.0 / 255.0 alpha:1.0]];
|
||||
@@ -89,9 +92,19 @@
|
||||
*/
|
||||
- (void)setContentArray:(CPArray)anArray
|
||||
{
|
||||
contentArray = anArray;
|
||||
if (contentArray === anArray || [contentArray isEqualToArray:anArray])
|
||||
return;
|
||||
|
||||
contentArray = [anArray copy];
|
||||
|
||||
// Go away automatically if there are no suggestions.
|
||||
if (![contentArray count])
|
||||
[self _hideCompletions];
|
||||
|
||||
widestItemWidth = CPNotFound;
|
||||
|
||||
[tableView reloadData];
|
||||
[self layoutSubviews];
|
||||
}
|
||||
|
||||
- (void)setIndexOfSelectedItem:(int)anIndex
|
||||
@@ -126,21 +139,44 @@
|
||||
*/
|
||||
|
||||
var frame = [textField frame],
|
||||
origin = frame.origin;
|
||||
origin = frame.origin,
|
||||
tableColumn = [[tableView tableColumns] firstObject];
|
||||
|
||||
if ([textField respondsToSelector:@selector(_completionOrigin:)])
|
||||
origin = [textField _completionOrigin:self];
|
||||
|
||||
if (widestItemWidth === CPNotFound)
|
||||
{
|
||||
// This calculation could be slow for many items.
|
||||
|
||||
var dataView = [tableColumn dataView],
|
||||
fontNormal = [dataView valueForThemeAttribute:@"font" inState:CPThemeStateTableDataView],
|
||||
fontSelected = [dataView valueForThemeAttribute:@"font" inState:CPThemeStateTableDataView | CPThemeStateSelectedTableDataView],
|
||||
contentInsetNormal = [dataView valueForThemeAttribute:@"content-inset" inState:CPThemeStateTableDataView],
|
||||
contentInsetSelected = [dataView valueForThemeAttribute:@"content-inset" inState:CPThemeStateTableDataView | CPThemeStateSelectedTableDataView];
|
||||
|
||||
var mergedString = contentArray.join("\n");
|
||||
|
||||
widestItemWidth = MAX([mergedString sizeWithFont:fontNormal].width + contentInsetNormal.left + contentInsetNormal.right, [mergedString sizeWithFont:fontSelected].width + contentInsetSelected.left + contentInsetSelected.right) + [tableView intercellSpacing].width + 2.0 + 5.0; // 2.0 because we inset by 1.0 below, 5.0 mystery constant.
|
||||
// TODO Track down why mystery constant is needed to allocate enough width. Scroll view insets?
|
||||
}
|
||||
|
||||
// Manually sizeToFit because CPTableView's sizeToFit doesn't work properly
|
||||
var frameOrigin = [textField convertPoint:origin toView:nil],
|
||||
newFrame = CGRectMake(frameOrigin.x, frameOrigin.y, CPRectGetWidth([textField bounds]), 92.0);
|
||||
screenSize = [[_menuWindow screen] visibleFrame].size,
|
||||
availableWidth = screenSize.width - frameOrigin.x,
|
||||
availableHeight = screenSize.height - frameOrigin.y,
|
||||
width = MIN(widestItemWidth, availableWidth),
|
||||
spacingHeight = [tableView intercellSpacing].height,
|
||||
height = MIN(MIN(spacingHeight + [contentArray count] * ([tableView rowHeight] + spacingHeight), _CPAutocompleteMenuMaximumHeight), availableHeight),
|
||||
newFrame = CGRectMake(frameOrigin.x, frameOrigin.y, width, height);
|
||||
|
||||
newFrame = [_menuWindow frameRectForContentRect:newFrame];
|
||||
[_menuWindow setFrame:newFrame];
|
||||
[scrollView setFrame:CGRectInset([[_menuWindow contentView] bounds], 1.0, 1.0)];
|
||||
// Correctly size the tableview
|
||||
// FIXME Horizontal scrolling will not work because we are not actually looking at the content to set the width for the table column
|
||||
[[[tableView tableColumns] firstObject] setWidth:[[scrollView contentView] frame].size.width];
|
||||
|
||||
var scrollFrame = CGRectInset([[_menuWindow contentView] bounds], 1.0, 1.0);
|
||||
[scrollView setFrame:scrollFrame];
|
||||
|
||||
[tableColumn setWidth:[[scrollView contentView] frame].size.width];
|
||||
}
|
||||
|
||||
- (void)_showCompletions:(CPTimer)timer
|
||||
@@ -149,6 +185,9 @@
|
||||
|
||||
[self setContentArray:[textField _completionsForSubstring:[textField _inputElement].value indexOfToken:0 indexOfSelectedItem:indexOfSelectedItem]];
|
||||
|
||||
if (![contentArray count])
|
||||
return;
|
||||
|
||||
// TODO Support indexOfSelectedItem. Always 0 right now.
|
||||
[self setIndexOfSelectedItem:indexOfSelectedItem];
|
||||
|
||||
|
||||
Reference in new issue
Block a user