Separate work and personal contacts search result
This change allows sms app to show search result of different directories in different partitions. Currently, only personal default and enterprise default directory are searched. BUG=26021888 BUG=28016344 (cherry picked from commit 59666b32c192bd28807ccd2f9153c796668bdf13) Change-Id: I733ceaae806d13661861126ce61c34108ac7e662
This commit is contained in:
24
res/layout/work_directory_header.xml
Normal file
24
res/layout/work_directory_header.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2009 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF A`NY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Layout used for list section separators. -->
|
||||||
|
<TextView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:text="@string/work_directory_display_name"
|
||||||
|
style="@style/DirectoryHeaderStyle"
|
||||||
|
/>
|
||||||
@@ -188,4 +188,10 @@
|
|||||||
<dimen name="fastscroll_preview_margin_left_right">8dp</dimen>
|
<dimen name="fastscroll_preview_margin_left_right">8dp</dimen>
|
||||||
<dimen name="fastscroll_preview_text_size">24sp</dimen>
|
<dimen name="fastscroll_preview_text_size">24sp</dimen>
|
||||||
|
|
||||||
|
<dimen name="directory_header_padding_start">16dp</dimen>
|
||||||
|
<dimen name="directory_header_padding_end">32dp</dimen>
|
||||||
|
<dimen name="directory_header_padding_top">18dp</dimen>
|
||||||
|
<dimen name="directory_header_padding_bottom">8dp</dimen>
|
||||||
|
<dimen name="directory_header_text_size">14sp</dimen>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -973,4 +973,6 @@
|
|||||||
|
|
||||||
<!-- The accessibility text read when the sim chooser pops up to read the current selected sim -->
|
<!-- The accessibility text read when the sim chooser pops up to read the current selected sim -->
|
||||||
<string name="selected_sim_content_message"><xliff:g id="selected_sim">%s</xliff:g> selected</string>
|
<string name="selected_sim_content_message"><xliff:g id="selected_sim">%s</xliff:g> selected</string>
|
||||||
|
|
||||||
|
<string name="work_directory_display_name">Work Profile contacts</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -623,4 +623,14 @@
|
|||||||
<item name="android:textColor">@android:color/white</item>
|
<item name="android:textColor">@android:color/white</item>
|
||||||
<item name="android:gravity">center</item>
|
<item name="android:gravity">center</item>
|
||||||
</style>
|
</style>
|
||||||
|
<style name="DirectoryHeaderStyle">
|
||||||
|
<item name="android:paddingLeft">@dimen/directory_header_padding_start</item>
|
||||||
|
<item name="android:paddingStart">@dimen/directory_header_padding_start</item>
|
||||||
|
<item name="android:paddingRight">@dimen/directory_header_padding_end</item>
|
||||||
|
<item name="android:paddingEnd">@dimen/directory_header_padding_end</item>
|
||||||
|
<item name="android:paddingTop">@dimen/directory_header_padding_top</item>
|
||||||
|
<item name="android:paddingBottom">@dimen/directory_header_padding_bottom</item>
|
||||||
|
<item name="android:textSize">@dimen/directory_header_text_size</item>
|
||||||
|
<item name="android:textStyle">bold</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -22,12 +22,17 @@ import android.support.v4.util.Pair;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.util.Rfc822Token;
|
import android.text.util.Rfc822Token;
|
||||||
import android.text.util.Rfc822Tokenizer;
|
import android.text.util.Rfc822Tokenizer;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.widget.Filter;
|
import android.widget.Filter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.ex.chips.BaseRecipientAdapter;
|
import com.android.ex.chips.BaseRecipientAdapter;
|
||||||
import com.android.ex.chips.RecipientAlternatesAdapter;
|
import com.android.ex.chips.RecipientAlternatesAdapter;
|
||||||
import com.android.ex.chips.RecipientAlternatesAdapter.RecipientMatchCallback;
|
import com.android.ex.chips.RecipientAlternatesAdapter.RecipientMatchCallback;
|
||||||
import com.android.ex.chips.RecipientEntry;
|
import com.android.ex.chips.RecipientEntry;
|
||||||
|
import com.android.messaging.R;
|
||||||
import com.android.messaging.util.Assert;
|
import com.android.messaging.util.Assert;
|
||||||
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
|
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
|
||||||
import com.android.messaging.util.BugleGservices;
|
import com.android.messaging.util.BugleGservices;
|
||||||
@@ -54,6 +59,18 @@ import java.util.Map;
|
|||||||
* for {@link ContactRecipientAutoCompleteView}
|
* for {@link ContactRecipientAutoCompleteView}
|
||||||
*/
|
*/
|
||||||
public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
||||||
|
private static final int WORD_DIRECTORY_HEADER_POS_NONE = -1;
|
||||||
|
/**
|
||||||
|
* Stores the index of work directory header.
|
||||||
|
*/
|
||||||
|
private int mWorkDirectoryHeaderPos = WORD_DIRECTORY_HEADER_POS_NONE;
|
||||||
|
private final LayoutInflater mInflater;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of directory entry.
|
||||||
|
*/
|
||||||
|
private static final int ENTRY_TYPE_DIRECTORY = RecipientEntry.ENTRY_TYPE_SIZE;
|
||||||
|
|
||||||
public ContactRecipientAdapter(final Context context,
|
public ContactRecipientAdapter(final Context context,
|
||||||
final ContactListItemView.HostInterface clivHost) {
|
final ContactListItemView.HostInterface clivHost) {
|
||||||
this(context, Integer.MAX_VALUE, QUERY_TYPE_PHONE, clivHost);
|
this(context, Integer.MAX_VALUE, QUERY_TYPE_PHONE, clivHost);
|
||||||
@@ -63,6 +80,7 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
|||||||
final int queryMode, final ContactListItemView.HostInterface clivHost) {
|
final int queryMode, final ContactListItemView.HostInterface clivHost) {
|
||||||
super(context, preferredMaxResultCount, queryMode);
|
super(context, preferredMaxResultCount, queryMode);
|
||||||
setPhotoManager(new ContactRecipientPhotoManager(context, clivHost));
|
setPhotoManager(new ContactRecipientPhotoManager(context, clivHost));
|
||||||
|
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -82,6 +100,7 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
|||||||
* results.
|
* results.
|
||||||
*/
|
*/
|
||||||
public class ContactFilter extends Filter {
|
public class ContactFilter extends Filter {
|
||||||
|
|
||||||
// Used to sort filtered contacts when it has combined results from email and phone.
|
// Used to sort filtered contacts when it has combined results from email and phone.
|
||||||
private final RecipientEntryComparator mComparator = new RecipientEntryComparator();
|
private final RecipientEntryComparator mComparator = new RecipientEntryComparator();
|
||||||
|
|
||||||
@@ -96,8 +115,7 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
|||||||
* return the merged results.
|
* return the merged results.
|
||||||
*/
|
*/
|
||||||
@DoesNotRunOnMainThread
|
@DoesNotRunOnMainThread
|
||||||
private Pair<Cursor, Boolean> getFilteredResultsCursor(final Context context,
|
private CursorResult getFilteredResultsCursor(final String searchText) {
|
||||||
final String searchText) {
|
|
||||||
Assert.isNotMainThread();
|
Assert.isNotMainThread();
|
||||||
if (BugleGservices.get().getBoolean(
|
if (BugleGservices.get().getBoolean(
|
||||||
BugleGservicesKeys.ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS,
|
BugleGservicesKeys.ALWAYS_AUTOCOMPLETE_EMAIL_ADDRESS,
|
||||||
@@ -107,44 +125,35 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
|||||||
.filterPhones(getContext(), searchText).performSynchronousQuery();
|
.filterPhones(getContext(), searchText).performSynchronousQuery();
|
||||||
final Cursor personalFilterEmailsCursor = ContactUtil
|
final Cursor personalFilterEmailsCursor = ContactUtil
|
||||||
.filterEmails(getContext(), searchText).performSynchronousQuery();
|
.filterEmails(getContext(), searchText).performSynchronousQuery();
|
||||||
Cursor resultCursor;
|
final Cursor personalCursor = new MergeCursor(
|
||||||
|
new Cursor[]{personalFilterEmailsCursor, personalFilterPhonesCursor});
|
||||||
|
final CursorResult cursorResult =
|
||||||
|
new CursorResult(personalCursor, false /* sorted */);
|
||||||
if (OsUtil.isAtLeastN()) {
|
if (OsUtil.isAtLeastN()) {
|
||||||
// Including enterprise result starting from N.
|
// Including enterprise result starting from N.
|
||||||
final Cursor enterpriseFilterPhonesCursor = ContactUtil.filterPhonesEnterprise(
|
final Cursor enterpriseFilterPhonesCursor = ContactUtil.filterPhonesEnterprise(
|
||||||
getContext(), searchText).performSynchronousQuery();
|
getContext(), searchText).performSynchronousQuery();
|
||||||
final Cursor enterpriseFilterEmailsCursor = ContactUtil.filterEmailsEnterprise(
|
final Cursor enterpriseFilterEmailsCursor = ContactUtil.filterEmailsEnterprise(
|
||||||
getContext(), searchText).performSynchronousQuery();
|
getContext(), searchText).performSynchronousQuery();
|
||||||
// TODO: Separating enterprise result from personal result (b/26021888)
|
final Cursor enterpriseCursor = new MergeCursor(
|
||||||
resultCursor = new MergeCursor(
|
new Cursor[]{enterpriseFilterEmailsCursor,
|
||||||
new Cursor[]{personalFilterEmailsCursor, enterpriseFilterEmailsCursor,
|
enterpriseFilterPhonesCursor});
|
||||||
personalFilterPhonesCursor, enterpriseFilterPhonesCursor});
|
cursorResult.enterpriseCursor = enterpriseCursor;
|
||||||
} else {
|
|
||||||
resultCursor = new MergeCursor(
|
|
||||||
new Cursor[]{personalFilterEmailsCursor, personalFilterPhonesCursor});
|
|
||||||
}
|
}
|
||||||
return Pair.create(
|
return cursorResult;
|
||||||
resultCursor,
|
|
||||||
false /* the merged cursor is not sorted */
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
final Cursor personalFilterDestinationCursor = ContactUtil
|
final Cursor personalFilterDestinationCursor = ContactUtil
|
||||||
.filterDestination(getContext(), searchText).performSynchronousQuery();
|
.filterDestination(getContext(), searchText).performSynchronousQuery();
|
||||||
Cursor resultCursor;
|
final CursorResult cursorResult = new CursorResult(personalFilterDestinationCursor,
|
||||||
boolean sorted;
|
true);
|
||||||
if (OsUtil.isAtLeastN()) {
|
if (OsUtil.isAtLeastN()) {
|
||||||
// Including enterprise result starting from N.
|
// Including enterprise result starting from N.
|
||||||
final Cursor enterpriseFilterDestinationCursor = ContactUtil
|
final Cursor enterpriseFilterDestinationCursor = ContactUtil
|
||||||
.filterDestinationEnterprise(getContext(), searchText)
|
.filterDestinationEnterprise(getContext(), searchText)
|
||||||
.performSynchronousQuery();
|
.performSynchronousQuery();
|
||||||
// TODO: Separating enterprise result from personal result (b/26021888)
|
cursorResult.enterpriseCursor = enterpriseFilterDestinationCursor;
|
||||||
resultCursor = new MergeCursor(new Cursor[]{personalFilterDestinationCursor,
|
|
||||||
enterpriseFilterDestinationCursor});
|
|
||||||
sorted = false;
|
|
||||||
} else {
|
|
||||||
resultCursor = personalFilterDestinationCursor;
|
|
||||||
sorted = true;
|
|
||||||
}
|
}
|
||||||
return Pair.create(resultCursor, sorted);
|
return cursorResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,44 +172,57 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
|||||||
|
|
||||||
// Query for auto-complete results, since performFiltering() is not done on the
|
// Query for auto-complete results, since performFiltering() is not done on the
|
||||||
// main thread, perform the cursor loader queries directly.
|
// main thread, perform the cursor loader queries directly.
|
||||||
final Pair<Cursor, Boolean> filteredResults = getFilteredResultsCursor(getContext(),
|
|
||||||
searchText);
|
|
||||||
final Cursor cursor = filteredResults.first;
|
|
||||||
final boolean sorted = filteredResults.second;
|
|
||||||
if (cursor != null) {
|
|
||||||
try {
|
|
||||||
final List<RecipientEntry> entries = new ArrayList<RecipientEntry>();
|
|
||||||
|
|
||||||
// First check if the constraint is a valid SMS destination. If so, add the
|
final CursorResult cursorResult = getFilteredResultsCursor(searchText);
|
||||||
// destination as a suggestion item to the drop down.
|
final List<RecipientEntry> entries = new ArrayList<>();
|
||||||
if (PhoneUtils.isValidSmsMmsDestination(searchText)) {
|
|
||||||
entries.add(ContactRecipientEntryUtils
|
|
||||||
.constructSendToDestinationEntry(searchText));
|
|
||||||
}
|
|
||||||
|
|
||||||
HashSet<Long> existingContactIds = new HashSet<Long>();
|
// First check if the constraint is a valid SMS destination. If so, add the
|
||||||
while (cursor.moveToNext()) {
|
// destination as a suggestion item to the drop down.
|
||||||
// Make sure there's only one first-level contact (i.e. contact for which
|
if (PhoneUtils.isValidSmsMmsDestination(searchText)) {
|
||||||
// we show the avatar picture and name) for every contact id.
|
entries.add(ContactRecipientEntryUtils
|
||||||
final long contactId = cursor.getLong(ContactUtil.INDEX_CONTACT_ID);
|
.constructSendToDestinationEntry(searchText));
|
||||||
final boolean isFirstLevel = !existingContactIds.contains(contactId);
|
}
|
||||||
if (isFirstLevel) {
|
|
||||||
existingContactIds.add(contactId);
|
|
||||||
}
|
|
||||||
entries.add(ContactUtil.createRecipientEntryForPhoneQuery(cursor,
|
|
||||||
isFirstLevel));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sorted) {
|
// Only show work directory header if more than one result in work directory.
|
||||||
Collections.sort(entries, mComparator);
|
int workDirectoryHeaderPos = WORD_DIRECTORY_HEADER_POS_NONE;
|
||||||
}
|
if (cursorResult.enterpriseCursor != null
|
||||||
results.values = entries;
|
&& cursorResult.enterpriseCursor.getCount() > 0) {
|
||||||
results.count = 1;
|
if (cursorResult.personalCursor != null) {
|
||||||
|
workDirectoryHeaderPos = entries.size();
|
||||||
} finally {
|
workDirectoryHeaderPos += cursorResult.personalCursor.getCount();
|
||||||
cursor.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Cursor[] cursors = new Cursor[]{cursorResult.personalCursor,
|
||||||
|
cursorResult.enterpriseCursor};
|
||||||
|
for (Cursor cursor : cursors) {
|
||||||
|
if (cursor != null) {
|
||||||
|
try {
|
||||||
|
final List<RecipientEntry> tempEntries = new ArrayList<>();
|
||||||
|
HashSet<Long> existingContactIds = new HashSet<>();
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
// Make sure there's only one first-level contact (i.e. contact for
|
||||||
|
// which we show the avatar picture and name) for every contact id.
|
||||||
|
final long contactId = cursor.getLong(ContactUtil.INDEX_CONTACT_ID);
|
||||||
|
final boolean isFirstLevel = !existingContactIds.contains(contactId);
|
||||||
|
if (isFirstLevel) {
|
||||||
|
existingContactIds.add(contactId);
|
||||||
|
}
|
||||||
|
tempEntries.add(ContactUtil.createRecipientEntryForPhoneQuery(cursor,
|
||||||
|
isFirstLevel));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cursorResult.isSorted) {
|
||||||
|
Collections.sort(tempEntries, mComparator);
|
||||||
|
}
|
||||||
|
entries.addAll(tempEntries);
|
||||||
|
} finally {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.values = new ContactReceipientFilterResult(entries, workDirectoryHeaderPos);
|
||||||
|
results.count = 1;
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,16 +231,20 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
|||||||
mCurrentConstraint = constraint;
|
mCurrentConstraint = constraint;
|
||||||
clearTempEntries();
|
clearTempEntries();
|
||||||
|
|
||||||
if (results.values != null) {
|
final ContactReceipientFilterResult contactReceipientFilterResult
|
||||||
@SuppressWarnings("unchecked")
|
= (ContactReceipientFilterResult) results.values;
|
||||||
final List<RecipientEntry> entries = (List<RecipientEntry>) results.values;
|
if (contactReceipientFilterResult != null) {
|
||||||
updateEntries(entries);
|
mWorkDirectoryHeaderPos = contactReceipientFilterResult.workDirectoryPos;
|
||||||
} else {
|
if (contactReceipientFilterResult.recipientEntries != null) {
|
||||||
updateEntries(Collections.<RecipientEntry>emptyList());
|
updateEntries(contactReceipientFilterResult.recipientEntries);
|
||||||
|
} else {
|
||||||
|
updateEntries(Collections.<RecipientEntry>emptyList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RecipientEntryComparator implements Comparator<RecipientEntry> {
|
private class RecipientEntryComparator implements Comparator<RecipientEntry> {
|
||||||
|
|
||||||
private final Collator mCollator;
|
private final Collator mCollator;
|
||||||
|
|
||||||
public RecipientEntryComparator() {
|
public RecipientEntryComparator() {
|
||||||
@@ -272,6 +298,38 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CursorResult {
|
||||||
|
|
||||||
|
public final Cursor personalCursor;
|
||||||
|
|
||||||
|
public Cursor enterpriseCursor;
|
||||||
|
|
||||||
|
public final boolean isSorted;
|
||||||
|
|
||||||
|
public CursorResult(Cursor personalCursor, boolean isSorted) {
|
||||||
|
this.personalCursor = personalCursor;
|
||||||
|
this.isSorted = isSorted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ContactReceipientFilterResult {
|
||||||
|
/**
|
||||||
|
* Recipient entries in all directories.
|
||||||
|
*/
|
||||||
|
public final List<RecipientEntry> recipientEntries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index of row that showing work directory header.
|
||||||
|
*/
|
||||||
|
public final int workDirectoryPos;
|
||||||
|
|
||||||
|
public ContactReceipientFilterResult(List<RecipientEntry> recipientEntries,
|
||||||
|
int workDirectoryPos) {
|
||||||
|
this.recipientEntries = recipientEntries;
|
||||||
|
this.workDirectoryPos = workDirectoryPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -318,4 +376,81 @@ public final class ContactRecipientAdapter extends BaseRecipientAdapter {
|
|||||||
// report matches
|
// report matches
|
||||||
callback.matchesFound(recipientEntries);
|
callback.matchesFound(recipientEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We handle directory header here and then delegate the work of creating recipient views to
|
||||||
|
* the {@link BaseRecipientAdapter}. Please notice that we need to fix the position
|
||||||
|
* before passing to {@link BaseRecipientAdapter} because it is not aware of the existence of
|
||||||
|
* directory headers.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
TextView textView;
|
||||||
|
if (isDirectoryEntry(position)) {
|
||||||
|
if (convertView == null) {
|
||||||
|
textView = (TextView) mInflater.inflate(R.layout.work_directory_header, parent,
|
||||||
|
false);
|
||||||
|
} else {
|
||||||
|
textView = (TextView) convertView;
|
||||||
|
}
|
||||||
|
return textView;
|
||||||
|
}
|
||||||
|
return super.getView(fixPosition(position), convertView, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipientEntry getItem(int position) {
|
||||||
|
if (isDirectoryEntry(position)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return super.getItem(fixPosition(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewTypeCount() {
|
||||||
|
return RecipientEntry.ENTRY_TYPE_SIZE + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
if (isDirectoryEntry(position)) {
|
||||||
|
return ENTRY_TYPE_DIRECTORY;
|
||||||
|
}
|
||||||
|
return super.getItemViewType(fixPosition(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(int position) {
|
||||||
|
if (isDirectoryEntry(position)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.isEnabled(fixPosition(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return super.getCount() + ((hasWorkDirectoryHeader()) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDirectoryEntry(int position) {
|
||||||
|
return position == mWorkDirectoryHeaderPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the position of items without counting directory headers.
|
||||||
|
*/
|
||||||
|
private int fixPosition(int position) {
|
||||||
|
if (hasWorkDirectoryHeader()) {
|
||||||
|
Assert.isTrue(position != mWorkDirectoryHeaderPos);
|
||||||
|
if (position > mWorkDirectoryHeaderPos) {
|
||||||
|
return position - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasWorkDirectoryHeader() {
|
||||||
|
return mWorkDirectoryHeaderPos != WORD_DIRECTORY_HEADER_POS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user