Added Full-text search function.

Jayden Platell [04-28-14 - 21:56]
Added Full-text search function.
Filename
Librarian.lua
Librarian.xml
diff --git a/Librarian.lua b/Librarian.lua
index 6fa4b21..c29faa0 100644
--- a/Librarian.lua
+++ b/Librarian.lua
@@ -16,10 +16,13 @@ ZO_CreateStringId("SI_LIBRARIAN_UNREAD_COUNT", "%s (%d Unread)")
 ZO_CreateStringId("SI_LIBRARIAN_SHOW_ALL_BOOKS", "Show books for all characters")
 ZO_CreateStringId("SI_LIBRARIAN_NEW_BOOK_FOUND", "Book added to librarian")
 ZO_CreateStringId("SI_LIBRARIAN_NEW_BOOK_FOUND_WITH_TITLE", "Book added to librarian: %s")
+ZO_CreateStringId("SI_LIBRARIAN_FULLTEXT_SEARCH", "Full-text Search:")
+ZO_CreateStringId("SI_LIBRARIAN_SEARCH_HINT", "Enter text to search for.")

 local SORT_ARROW_UP = "EsoUI/Art/Miscellaneous/list_sortUp.dds"
 local SORT_ARROW_DOWN = "EsoUI/Art/Miscellaneous/list_sortDown.dds"
 local LIBRARIAN_DATA = 1
+local LIBRARIAN_SEARCH = 1

 local ENTRY_SORT_KEYS =
 {
@@ -54,6 +57,11 @@ function Librarian:Initialise()
 	if not self.localSavedVars.characterBooks then self.localSavedVars.characterBooks = {} end
 	self.characterBooks = self.localSavedVars.characterBooks

+	self.searchBox = GetControl(LibrarianFrame, "SearchBox")
+    self.searchBox:SetHandler("OnTextChanged", function() self:OnSearchTextChanged() end)
+    self.search = ZO_StringSearch:New()
+    self.search:AddProcessor(LIBRARIAN_SEARCH, function(stringSearch, data, searchTerm, cache) return self:ProcessBookEntry(stringSearch, data, searchTerm, cache) end)
+
 	self.sortFunction = function(listEntry1, listEntry2) return ZO_TableOrderingFunction(listEntry1.data, listEntry2.data, self.currentSortKey, ENTRY_SORT_KEYS, self.currentSortOrder) end

 	self:UpdateSavedVariables()
@@ -79,101 +87,6 @@ function Librarian:Initialise()
 	self:InitializeScene()
 end

-function Librarian:ImportFromLoreLibrary()
-	local hasImportedBooks = false
-	local chatEnabled = self.settings.chatEnabled
-	local alertEnabled = self.settings.alertEnabled
-	self.settings.chatEnabled = true
-	self.settings.alertEnabled = false
-
-	for categoryIndex = 1, GetNumLoreCategories() do
-		local categoryName, numCollections = GetLoreCategoryInfo(categoryIndex)
-		for collectionIndex = 1, numCollections do
-            local collectionName, description, numKnownBooks, totalBooks, hidden = GetLoreCollectionInfo(categoryIndex, collectionIndex)
-            if not hidden then
-            	for bookIndex = 1, totalBooks do
-            		local title, icon, known = GetLoreBookInfo(categoryIndex, collectionIndex, bookIndex)
-            		if known then
-            			if not self:FindCharacterBook(title) then
-            				local body, medium, showTitle = ReadLoreBook(categoryIndex, collectionIndex, bookIndex)
-            				local book = {title = title, body = body, medium = medium, showTitle = showTitle}
-            				self:AddBook(book)
-            			end
-            		end
-            	end
-            end
-        end
-	end
-
-	self.settings.chatEnabled = chatEnabled
-	self.settings.alertEnabled = alertEnabled
-end
-
-function Librarian:SetupBookRow(control, data)
-	control.data = data
-	control.unread = GetControl(control, "Unread")
-	control.found = GetControl(control, "Found")
-	control.title = GetControl(control, "Title")
-	control.wordCount = GetControl(control, "WordCount")
-
-	control.unread.nonRecolorable = true
-	if data.unread then control.unread:SetAlpha(1) else control.unread:SetAlpha(0) end
-
-	control.found.normalColor = ZO_NORMAL_TEXT
-	control.found:SetText(self:FormatClockTime(data.timeStamp))
-
-	control.title.normalColor = ZO_NORMAL_TEXT
-	control.title:SetText(data.title)
-
-	control.wordCount.normalColor = ZO_NORMAL_TEXT
-	control.wordCount:SetText(data.wordCount)
-
-	ZO_SortFilterList.SetupRow(self, control, data)
-end
-
-function Librarian:BuildMasterList()
-    for i, book in ipairs(self.books) do
-		local bookCopy = {}
-		for k,v in pairs(book) do
-    		bookCopy[k] = v
-  		end
-  		local characterBook = self:FindCharacterBook(book.title)
-  		if characterBook then
-			bookCopy.seenByCurrentCharacter = true
-			bookCopy.timeStamp = characterBook.timeStamp
-		else
-			bookCopy.seenByCurrentCharacter = false
-			bookCopy.timeStamp = book.timeStamp
-		end
-  		self.masterList[i] = bookCopy
-    end
-end
-
-function Librarian:FilterScrollList()
-    local scrollData = ZO_ScrollList_GetDataList(self.list)
-    ZO_ClearNumericallyIndexedTable(scrollData)
-
-    local bookCount = 0
-    local unreadCount = 0
-    for i = 1, #self.masterList do
-        local book = self.masterList[i]
-        if self.settings.showAllBooks or book.seenByCurrentCharacter then
-            table.insert(scrollData, ZO_ScrollList_CreateDataEntry(LIBRARIAN_DATA, book))
-            bookCount = bookCount + 1
-            if book.unread then unreadCount = unreadCount + 1 end
-        end
-    end
-
-    local message = string.format(GetString(SI_LIBRARIAN_BOOK_COUNT), bookCount)
-    if unreadCount > 0 then message = string.format(GetString(SI_LIBRARIAN_UNREAD_COUNT), message, unreadCount) end
-	LibrarianFrameBookCount:SetText(message)
-end
-
-function Librarian:SortScrollList()
-    local scrollData = ZO_ScrollList_GetDataList(self.list)
-    table.sort(scrollData, self.sortFunction)
-end
-
 function Librarian:UpdateSavedVariables()
 	-- Version 1.0.4 - Settings moved to global variables.
 	if self.localSavedVars.setting_time_format then
@@ -265,6 +178,119 @@ function Librarian:InitializeScene()
 	end
 end

+function Librarian:ImportFromLoreLibrary()
+	local hasImportedBooks = false
+	local chatEnabled = self.settings.chatEnabled
+	local alertEnabled = self.settings.alertEnabled
+	self.settings.chatEnabled = true
+	self.settings.alertEnabled = false
+
+	for categoryIndex = 1, GetNumLoreCategories() do
+		local categoryName, numCollections = GetLoreCategoryInfo(categoryIndex)
+		for collectionIndex = 1, numCollections do
+            local collectionName, description, numKnownBooks, totalBooks, hidden = GetLoreCollectionInfo(categoryIndex, collectionIndex)
+            if not hidden then
+            	for bookIndex = 1, totalBooks do
+            		local title, icon, known = GetLoreBookInfo(categoryIndex, collectionIndex, bookIndex)
+            		if known then
+            			if not self:FindCharacterBook(title) then
+            				local body, medium, showTitle = ReadLoreBook(categoryIndex, collectionIndex, bookIndex)
+            				local book = {title = title, body = body, medium = medium, showTitle = showTitle}
+            				self:AddBook(book)
+            			end
+            		end
+            	end
+            end
+        end
+	end
+
+	self.settings.chatEnabled = chatEnabled
+	self.settings.alertEnabled = alertEnabled
+end
+
+function Librarian:BuildMasterList()
+    for i, book in ipairs(self.books) do
+		local data = {}
+		for k,v in pairs(book) do
+    		data[k] = v
+  		end
+  		data.type = LIBRARIAN_SEARCH
+  		local characterBook = self:FindCharacterBook(book.title)
+  		if characterBook then
+			data.seenByCurrentCharacter = true
+			data.timeStamp = characterBook.timeStamp
+		else
+			data.seenByCurrentCharacter = false
+			data.timeStamp = book.timeStamp
+		end
+  		self.masterList[i] = data
+    end
+end
+
+function Librarian:FilterScrollList()
+    local scrollData = ZO_ScrollList_GetDataList(self.list)
+    ZO_ClearNumericallyIndexedTable(scrollData)
+
+    local bookCount = 0
+    local unreadCount = 0
+    local searchTerm = self.searchBox:GetText()
+    for i = 1, #self.masterList do
+        local data = self.masterList[i]
+        if self.settings.showAllBooks or data.seenByCurrentCharacter then
+        	if(searchTerm == "" or self.search:IsMatch(searchTerm, data)) then
+            	table.insert(scrollData, ZO_ScrollList_CreateDataEntry(LIBRARIAN_DATA, data))
+            	bookCount = bookCount + 1
+            	if data.unread then unreadCount = unreadCount + 1 end
+            end
+        end
+    end
+
+    local message = string.format(GetString(SI_LIBRARIAN_BOOK_COUNT), bookCount)
+    if unreadCount > 0 then message = string.format(GetString(SI_LIBRARIAN_UNREAD_COUNT), message, unreadCount) end
+	LibrarianFrameBookCount:SetText(message)
+end
+
+function Librarian:SortScrollList()
+    local scrollData = ZO_ScrollList_GetDataList(self.list)
+    table.sort(scrollData, self.sortFunction)
+end
+
+function Librarian:SetupBookRow(control, data)
+	control.data = data
+	control.unread = GetControl(control, "Unread")
+	control.found = GetControl(control, "Found")
+	control.title = GetControl(control, "Title")
+	control.wordCount = GetControl(control, "WordCount")
+
+	control.unread.nonRecolorable = true
+	if data.unread then control.unread:SetAlpha(1) else control.unread:SetAlpha(0) end
+
+	control.found.normalColor = ZO_NORMAL_TEXT
+	control.found:SetText(self:FormatClockTime(data.timeStamp))
+
+	control.title.normalColor = ZO_NORMAL_TEXT
+	control.title:SetText(data.title)
+
+	control.wordCount.normalColor = ZO_NORMAL_TEXT
+	control.wordCount:SetText(data.wordCount)
+
+	ZO_SortFilterList.SetupRow(self, control, data)
+end
+
+function Librarian:ProcessBookEntry(stringSearch, data, searchTerm, cache)
+    local lowerSearchTerm = searchTerm:lower()
+
+    if(zo_plainstrfind(data.title:lower(), lowerSearchTerm)) then
+        return true
+    end
+
+    if(zo_plainstrfind(data.body:lower(), lowerSearchTerm)) then
+        return true
+    end
+
+    return false
+end
+
 function Librarian:FindCharacterBook(title)
 	if not self.characterBooks then return nil end
 	for _,book in pairs(self.characterBooks) do
@@ -338,6 +364,11 @@ function Librarian:FormatClockTime(time)
 	return string.format("%s %s", dateString, timeString)
 end

+function Librarian:OnSearchTextChanged()
+    ZO_EditDefaultText_OnTextChanged(self.searchBox)
+    self:RefreshFilters()
+end
+
 local function SlashCommand(args)
 	Librarian:Toggle()
 end
diff --git a/Librarian.xml b/Librarian.xml
index 4061cc9..5ed5901 100644
--- a/Librarian.xml
+++ b/Librarian.xml
@@ -30,12 +30,26 @@
         </Button>
         <TopLevelControl name="LibrarianFrame" inherits="ZO_RightPanelFootPrint"  hidden="true">
             <Controls>
-                <Label name="$(parent)BookCount" font="ZoFontWindowTitle" color="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_SELECTED" modifyTextType="UPPERCASE">
-                    <Anchor point="TOPRIGHT" offsetX="-15" offsetY="-40" />
+                <Label name="$(parent)BookCount" font="ZoFontHeader3" color="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_NORMAL">
+                    <Anchor point="TOPLEFT" offsetY="10" />
+                </Label>
+                <Backdrop name="$(parent)Search" inherits="ZO_EditBackdrop">
+                    <Anchor point="TOPRIGHT" offsetX="-12" offsetY="10"/>
+                    <Dimensions x="270"/>
+                    <Controls>
+                        <EditBox name="$(parent)Box" inherits="ZO_DefaultEditForBackdrop ZO_EditDefaultText">
+                            <OnInitialized>
+                                ZO_EditDefaultText_Initialize(self, GetString(SI_LIBRARIAN_SEARCH_HINT))
+                            </OnInitialized>
+                        </EditBox>
+                    </Controls>
+                </Backdrop>
+                <Label name="$(parent)SearchLabel" text="SI_LIBRARIAN_FULLTEXT_SEARCH" font="ZoFontGameLargeBold" color="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_NORMAL">
+                    <Anchor point="TOPRIGHT" relativePoint="TOPLEFT" relativeTo="$(parent)Search" offsetX="-5" offsetY="3"/>
                 </Label>
                 <Control name="$(parent)Headers">
-                    <Anchor point="TOPLEFT" relativeTo="$(parent)" offsetY="5" />
-                    <Anchor point="TOPRIGHT" relativeTo="$(parent)" offsetY="5" />
+                    <Anchor point="TOPLEFT" relativeTo="$(parent)" offsetY="40" />
+                    <Anchor point="TOPRIGHT" relativeTo="$(parent)" offsetY="40" />
                     <Dimensions y="32" />
                     <Controls>
                         <Control name="$(parent)Unread" inherits="ZO_SortHeader">