Introduce API for proper bundle item titles

When a bundle item’s title contains “«unit» / Selection” then the UI should only show either “«unit»” or “Selection” depending on whether or not the text view has selected text.
This commit is contained in:
Allan Odgaard
2012-09-04 20:30:30 +02:00
parent a026e4ad11
commit 1bc81ed7dc
6 changed files with 46 additions and 13 deletions

View File

@@ -22,6 +22,7 @@ PUBLIC @interface BundleItemChooser : NSObject <FilterListDataSource>
{
OBJC_WATCH_LEAKS(BundleItemChooser);
scope::context_t scope;
BOOL hasSelection;
std::vector<bundles::item_ptr> all_items;
std::set<oak::uuid_t> items_filtered_by_scope;
BOOL searchAllScopes;
@@ -34,6 +35,7 @@ PUBLIC @interface BundleItemChooser : NSObject <FilterListDataSource>
+ (id)bundleItemChooserForScope:(scope::context_t const&)aScope;
@property (nonatomic, retain) NSString* filterString;
@property (nonatomic, assign) BOOL keyEquivalentSearch;
@property (nonatomic, assign) BOOL textViewHasSelection;
@property (nonatomic, assign) BOOL searchAllScopes;
@property (nonatomic, assign) search::type searchType;
@end

View File

@@ -299,9 +299,9 @@ static NSString* const AllScopes = @"AllScopes";
@end
@implementation BundleItemChooser
@synthesize keyEquivalentSearch, searchAllScopes, searchType;
@synthesize keyEquivalentSearch, textViewHasSelection = hasSelection, searchAllScopes, searchType;
static std::vector<bundles::item_ptr> relevant_items_in_scope (search::type searchType, scope::context_t const& scope)
static std::vector<bundles::item_ptr> relevant_items_in_scope (search::type searchType, scope::context_t const& scope, bool hasSelection)
{
int kindMask = 0;
if(searchType == search::actions)
@@ -313,7 +313,7 @@ static std::vector<bundles::item_ptr> relevant_items_in_scope (search::type sear
std::multimap<std::string, bundles::item_ptr, text::less_t> sorted;
citerate(item, bundles::query(bundles::kFieldAny, NULL_STR, scope, kindMask, oak::uuid_t(), false))
sorted.insert(std::make_pair((*item)->full_name(), *item));
sorted.insert(std::make_pair(full_name_with_selection(*item, hasSelection), *item));
std::vector<bundles::item_ptr> res;
std::transform(sorted.begin(), sorted.end(), back_inserter(res), [](std::pair<std::string, bundles::item_ptr> const& p){ return p.second; });
@@ -357,9 +357,9 @@ static std::vector<bundles::item_ptr> relevant_items_in_scope (search::type sear
if(newType != searchType || all_items.empty())
{
searchType = newType;
all_items = relevant_items_in_scope(searchType, scope::wildcard);
all_items = relevant_items_in_scope(searchType, scope::wildcard, hasSelection);
citerate(item, relevant_items_in_scope(searchType, scope))
citerate(item, relevant_items_in_scope(searchType, scope, hasSelection))
items_filtered_by_scope.insert((*item)->uuid());
[[NSNotificationCenter defaultCenter] postNotificationName:FLDataSourceItemsDidChangeNotification object:self];
}
@@ -455,7 +455,7 @@ static std::vector<bundles::item_ptr> relevant_items_in_scope (search::type sear
}
else if(!filterString.empty())
{
double nameRank = oak::rank(filterString, all_items[index]->full_name());
double nameRank = oak::rank(filterString, full_name_with_selection(all_items[index], hasSelection));
double triggerRank = oak::rank(filterString, all_items[index]->value_for_field(bundles::kFieldTabTrigger));
if(nameRank == 0 && triggerRank == 0)
continue;
@@ -479,10 +479,10 @@ static std::vector<bundles::item_ptr> relevant_items_in_scope (search::type sear
- (NSAttributedString*)displayStringForItem:(BundleItemChooserItem*)item
{
NSUInteger index = [item index];
std::string const& itemName = all_items[index]->full_name();
std::string const itemName = full_name_with_selection(all_items[index], hasSelection);
std::vector< std::pair<size_t, size_t> > ranges;
double nameRank = oak::rank(filterString, all_items[index]->full_name());
double nameRank = oak::rank(filterString, full_name_with_selection(all_items[index], hasSelection));
double triggerRank = oak::rank(filterString, all_items[index]->value_for_field(bundles::kFieldTabTrigger));
if(nameRank > triggerRank)
oak::rank(text::lowercase(filterString), itemName, &ranges);
@@ -506,7 +506,7 @@ static std::vector<bundles::item_ptr> relevant_items_in_scope (search::type sear
std::string const& tabTrigger = all_items[index]->value_for_field(bundles::kFieldTabTrigger);
if(tabTrigger != NULL_STR)
{
double nameRank = oak::rank(filterString, all_items[index]->full_name());
double nameRank = oak::rank(filterString, full_name_with_selection(all_items[index], hasSelection));
double triggerRank = oak::rank(filterString, tabTrigger);
if(triggerRank > nameRank)
{

View File

@@ -6,7 +6,7 @@
namespace bundles
{
PUBLIC item_ptr show_menu_for_items (std::vector<item_ptr> const& items, CGPoint const& pos);
PUBLIC item_ptr show_menu_for_items (std::vector<item_ptr> const& items, CGPoint const& pos, bool hasSelection = false);
} /* bundles */

View File

@@ -1,4 +1,5 @@
#import "menu.h"
#import "query.h"
#import <OakFoundation/NSString Additions.h>
#import <text/ctype.h>
#import <cf/cf.h>
@@ -59,7 +60,7 @@ namespace bundles
return res;
}
item_ptr show_menu_for_items (std::vector<item_ptr> const& items, CGPoint const& pos)
item_ptr show_menu_for_items (std::vector<item_ptr> const& items, CGPoint const& pos, bool hasSelection)
{
if(items.empty())
return item_ptr();
@@ -116,7 +117,7 @@ namespace bundles
std::multimap<std::string, item_ptr, text::less_t> ordering;
iterate(item, includedItems)
ordering.insert(std::make_pair((*item)->name(), *item));
ordering.insert(std::make_pair(name_with_selection(*item, hasSelection), *item));
std::transform(ordering.begin(), ordering.end(), back_inserter(menuItems), [](std::pair<std::string, item_ptr> const& p){ return p.second; });
menus.insert(std::make_pair(bundle->name(), menuItems));
@@ -143,7 +144,7 @@ namespace bundles
[menu addItem:[NSMenuItem separatorItem]];
pendingSeparator = false;
NSMenuItem* menuItem = [menu addItemWithTitle:[NSString stringWithCxxString:(*item)->name()] action:@selector(takeSelectedItemIndexFrom:) keyEquivalent:@""];
NSMenuItem* menuItem = [menu addItemWithTitle:[NSString stringWithCxxString:name_with_selection(*item, hasSelection)] action:@selector(takeSelectedItemIndexFrom:) keyEquivalent:@""];
[menuItem setTarget:menuTarget];
[menuItem setTag:key];

View File

@@ -263,4 +263,32 @@ namespace bundles
return res;
}
static std::string format_bundle_item_title (std::string title, bool hasSelection)
{
static std::string const kSelectionSubString = " / Selection";
std::string::size_type pos = title.find(kSelectionSubString);
if(pos == 0 || pos == std::string::npos)
return title;
if(hasSelection)
{
std::string::size_type from = title.rfind(' ', pos - 1);
if(from == std::string::npos)
return title.erase(0, pos + 3);
return title.erase(from + 1, pos + 3 - from - 1);
}
return title.erase(pos, kSelectionSubString.size());
}
std::string name_with_selection (item_ptr const& item, bool hasSelection)
{
return format_bundle_item_title(item->name(), hasSelection);
}
std::string full_name_with_selection (item_ptr const& item, bool hasSelection)
{
return format_bundle_item_title(item->full_name(), hasSelection);
}
} /* bundles */

View File

@@ -10,6 +10,8 @@ namespace bundles
PUBLIC std::vector<item_ptr> query (std::string const& field, std::string const& value, scope::context_t const& scope = scope::wildcard, int kind = kItemTypeCommand|kItemTypeDragCommand|kItemTypeGrammar|kItemTypeMacro|kItemTypeSnippet|kItemTypeProxy|kItemTypeTheme, oak::uuid_t const& bundle = oak::uuid_t(), bool filter = true, bool includeDisabledItems = false);
PUBLIC item_ptr lookup (oak::uuid_t const& uuid);
PUBLIC std::string name_with_selection (item_ptr const& item, bool hasSelection);
PUBLIC std::string full_name_with_selection (item_ptr const& item, bool hasSelection);
} /* bundles */