WoWInterface SVN Notebook

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 32 to Rev 31
    Reverse comparison

Rev 32 → Rev 31

trunk/Localization-en.lua New file
0,0 → 1,142
--[[--------------------------------------------------------------------
Notebook
Allows you to record and share notes in-game.
Written by Cirk of Doomhammer, 2005-2009
Updated by Phanx with permission, 2012-2014
Do not redistribute. See accompanying LICENSE file for details.
http://www.wowinterface.com/downloads/info4544-Notebook
http://www.curse.com/addons/wow/notebook
----------------------------------------------------------------------]]
-- English Localization
 
local NOTEBOOK, Notebook = ...
local L = {}
Notebook.L = L
 
BINDING_NAME_NOTEBOOK_PANEL = "Toggle Notebook"
 
L.FRAME_TITLE_FORMAT = "%s’s Notebook"
L.ALL_TAB = "All"
L.ALL_TAB_TOOLTIP = "All notes"
L.MINE_TAB = "Mine"
L.MINE_TAB_TOOLTIP_FORMAT = "%s’s notes"
L.KNOWN_TAB = "Saved"
L.KNOWN_TAB_TOOLTIP = "Saved notes only"
L.RECENT_TAB = "Recent"
L.RECENT_TAB_TOOLTIP = "Recent notes"
L.SAVE_BUTTON = "Save"
L.SAVE_BUTTON_TOOLTIP = "Save the current changes"
L.CANCEL_BUTTON = "Cancel"
L.CANCEL_BUTTON_TOOLTIP = "Revert to the previous text"
L.ADD_BUTTON = "Add"
L.ADD_BUTTON_TOOLTIP = "Add this note to Notebook's saved list"
L.UPDATE_BUTTON = "Update"
L.UPDATE_BUTTON_TOOLTIP = "Update your previously saved note with this new text"
L.NEW_BUTTON = "New"
L.NEW_BUTTON_TOOLTIP = "Create a new note"
L.CHECK_SEND_BUTTON = "Can be sent"
L.CHECK_CAN_SEND_TOOLTIP = "This note can be sent"
L.CHECK_NOT_SEND_TOOLTIP = "This note will not be sent"
 
L.DETAILS_DATE_KNOWN_SAVED_FORMAT = "Saved %s"
L.DETAILS_DATE_KNOWN_UPDATED_FORMAT = "%s by %s"
L.DETAILS_DATE_UNSAVED_FORMAT = "%s from %s"
L.DETAILS_SIZE_FORMAT = "- %d characters"
L.DETAILS_NOT_KNOWN_TEXT = "- not saved"
L.DETAILS_SENT_FORMAT = "- sent %s"
L.TITLE_CHANGE_NOT_SAVED = "*"
 
L.NOTE_RECEIVED_FORMAT = "Notebook added note “%s” from %s."
 
-- Right-click menu
L.SAVE_OPTION = "Save"
L.ADD_OPTION = "Add"
L.UPDATE_OPTION = "Update"
L.RENAME_OPTION = "Rename"
L.DELETE_OPTION = "Delete"
L.SEND_OPTION = "Send To"
L.SEND_TO_TARGET = "Target"
L.SEND_TO_PLAYER = "Player"
L.SEND_TO_INSTANCE = "Instance"
L.SEND_TO_PARTY = "Party"
L.SEND_TO_RAID = "Raid"
L.SEND_TO_GUILD = "Guild"
L.SEND_TO_OFFICER = "Officer"
L.SEND_TO_CHANNEL = "Channel"
L.CHANNEL_NAME_FORMAT = "%d. %s"
 
-- Popup dialogs
L.ENTER_PLAYER_NAME_TEXT = "Enter name of player to send to:"
L.ENTER_NEW_TITLE_TEXT = "Enter new title for note:"
L.CONFIRM_REMOVE_FORMAT = "Really delete “%s”?"
L.CONFIRM_UPDATE_FORMAT = "Really replace “%s” with the one from %s?"
L.CONFIRM_SERVER_CHANNEL_FORMAT = "Really send “%s” to the %s channel?"
 
-- Slash commands
L.CMD_HELP = "help"
L.CMD_LIST = "list"
L.CMD_SHOW = "show"
L.CMD_HIDE = "hide"
L.CMD_SEND = "send"
L.CMD_OPTIONS = "options"
L.CMD_DEBUGON = "debugon"
L.CMD_DEBUGOFF = "debugoff"
L.CMD_WELCOME = "welcome"
L.CMD_STATUS = "status"
 
-- Slash command responses
L.CMD_DEBUGON_CONFIRM = "Notebook debugging is enabled."
L.CMD_DEBUGOFF_CONFIRM = "Notebook debugging is disabled."
L.CMD_LIST_CONFIRM = "Notebook contains the following notes:"
L.CMD_LIST_FORMAT = "- %s (%d characters, by %s, %s)"
L.CMD_STATUS_FORMAT = "Notebook currently contains %d notes and is using %.0fkB of memory."
 
-- Error messages
L.ERR_RENAME_NOT_UNIQUE_FORMAT = "You already have a note titled “%s”. Titles must be unique."
L.ERR_RENAME_EMPTY = "You cannot have an empty title."
L.ERR_SEND_COOLDOWN = "You cannot send another note just yet."
L.ERR_SEND_INVALID = "You must provide a valid note title and channel."
L.ERR_SEND_INVALID_NOTE = "Could not find a note titled “%s”."
L.ERR_SEND_EDITING = "You cannot send a note with unsaved changes."
L.ERR_SEND_RAID_LEADER = "You are not the raid leader or assistant."
L.ERR_SEND_NO_NAME = "You must enter a character name or BattleTag."
L.ERR_SEND_NO_CHANNEL = "You must enter a channel name."
L.ERR_SEND_INVALID_CHANNEL = "Could not find a channel “%s”."
L.ERR_SEND_UNKNOWN_CHANNEL = "“%s” is not a supported channel type."
 
------------------------------------------------------------------------
-- Help text
 
-- Notebook.SLASH_COMMAND not needed for English
 
Notebook.HELP_TEXT = {
"Use /notebook or /note with the following commands:",
" " .. L.CMD_SHOW .. " - show Notebook",
" " .. L.CMD_HIDE .. " - hide Notebook",
" " .. L.CMD_STATUS .. " - report the status of Notebook",
" " .. L.CMD_LIST .. " - list the notes in your Notebook",
" " .. L.CMD_WELCOME .. " - restore the Welcome note",
" " .. L.CMD_HELP .. " - show this help message",
"Use the slash command without any additional commands, or bind a key in the Key Bindings menu, to toggle the Notebook window.",
}
 
------------------------------------------------------------------------
-- First timer's brief manual
 
L.WELCOME_NOTE_TITLE = "Welcome to Notebook!"
L.WELCOME_NOTE_DESCRIPTION = [[
Notebook allows you to write and keep track of notes on different topics and then share them with your guildmates, raid members, or even chat channels! So if you usually use macros for raid instructions, loot rules, enchanting lists, and the like, Notebook might be for you!
 
To create a new Note, simply click on the New button and enter a title for the note. Titles can be up to 60 characters long and can contain any characters you want to use. But they must be unique - you can't have two Notes both titled "Things to do" for example. (You could have "Things to do" and "Other things to do" instead though :)
 
Once you've created your note you can then edit it and save it as you need. Notes can be up to 4096 characters in length (about twice the length of this Note about Notebook). If you need more room, just create another note! There is no limit (apart from memory) to the number of Notes you can have.
 
The more interesting features that Notebook provides are available through right-clicking on the title of a Note in the above Notes list, which will bring up a menu showing you various options, including allowing you to send the note to other players through party, raid, or guild chat, by whisper, or any of your current chat channels. (You may first need to enable sending for that specific Note via the "Can be sent" box at the bottom of the window first).
 
After sending a note you will have to wait a few seconds before you can send something else. Remember though that just like with macros, it is still your responsibility to make sure that you don't abuse the features of Notebook and spam other players!
 
Notebook will also automatically recognize Notes sent by other players, and will show these under the Recent tab along with any you have sent this session. You will then be able to add these Notes to your own saved list, or get an update if you already had it. (If the Note hasn't changed, you'll just see your own existing Note there).
 
I hope you enjoy Notebook and find it useful!
 
-- Cirk of Doomhammer]]
\ No newline at end of file
trunk/NotebookFrame.lua New file
0,0 → 1,599
--[[--------------------------------------------------------------------
Notebook
Allows you to record and share notes in-game.
Written by Cirk of Doomhammer, 2005-2009
Updated by Phanx with permission, 2012-2014
Do not redistribute. See accompanying LICENSE file for details.
http://www.wowinterface.com/downloads/info4544-Notebook
http://www.curse.com/addons/wow/notebook
----------------------------------------------------------------------]]
 
local NOTEBOOK, Notebook = ...
local L = Notebook.L
 
local NotebookFrame = CreateFrame("Frame", "NotebookFrame", UIParent)
UIPanelWindows["NotebookFrame"] = { area = "left", pushable = 3, whileDead = 1, xoffset = -16, yoffset = 12 }
tinsert(UISpecialFrames, "NotebookFrame")
Notebook.Frame = NotebookFrame
-- HideUIPanel(NotebookFrame)
-- NotebookFrame:Hide()
 
NotebookFrame:SetWidth(384)
NotebookFrame:SetHeight(512)
NotebookFrame:SetHitRectInsets(10, 34, 8, 72)
NotebookFrame:SetToplevel(true)
NotebookFrame:EnableMouse(true)
NotebookFrame:SetMovable(true)
 
NotebookFrame:SetScript("OnShow", function(self)
-- Set the frame title and "mine" tab tooltip with the player's name
local playerName = UnitName("player")
NotebookFrame.TitleText:SetFormattedText(L.FRAME_TITLE_FORMAT, playerName)
NotebookFrame.FilterTab2.tooltipText = format(L.MINE_TAB_TOOLTIP_FORMAT, playerName)
Notebook.Frame_UpdateList()
end)
 
------------------------------------------------------------------------
-- BACKGROUND TEXTURES
 
local topLeftIcon = NotebookFrame:CreateTexture(nil, "BACKGROUND")
topLeftIcon:SetPoint("TOPLEFT", 7, -6)
topLeftIcon:SetWidth(60)
topLeftIcon:SetHeight(60)
SetPortraitToTexture(topLeftIcon, "Interface\\FriendsFrame\\FriendsFrameScrollIcon")
NotebookFrame.TopLeftIcon = topLeftIcon
 
local topLeft = NotebookFrame:CreateTexture(nil, "BORDER")
topLeft:SetPoint("TOPLEFT")
topLeft:SetWidth(256)
topLeft:SetHeight(256)
topLeft:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-General-TopLeft")
NotebookFrame.TopLeft = topLeft
 
local topRight = NotebookFrame:CreateTexture(nil, "BORDER")
topRight:SetPoint("TOPRIGHT")
topRight:SetWidth(128)
topRight:SetHeight(256)
topRight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-General-TopRight")
NotebookFrame.BopRight = topRight
 
local bottomLeft = NotebookFrame:CreateTexture(nil, "BORDER")
bottomLeft:SetPoint("BOTTOMLEFT")
bottomLeft:SetWidth(256)
bottomLeft:SetHeight(256)
bottomLeft:SetTexture("Interface\\PaperDollInfoFrame\\SkillFrame-BotLeft")
NotebookFrame.BottomLeft = bottomLeft
 
local bottomRight = NotebookFrame:CreateTexture(nil, "BORDER")
bottomRight:SetPoint("BOTTOMRIGHT")
bottomRight:SetWidth(128)
bottomRight:SetHeight(256)
bottomRight:SetTexture("Interface\\PaperDollInfoFrame\\SkillFrame-BotRight")
NotebookFrame.BottomRight = bottomRight
 
local barLeft = NotebookFrame:CreateTexture(nil, "ARTWORK")
barLeft:SetPoint("TOPLEFT", 15, -186)
barLeft:SetWidth(256)
barLeft:SetHeight(16)
barLeft:SetTexture("Interface\\ClassTrainerFrame\\UI-ClassTrainer-HorizontalBar")
barLeft:SetTexCoord(0, 1, 0, 0.25)
NotebookFrame.BarLeft = barLeft
 
local barRight = NotebookFrame:CreateTexture(nil, "ARTWORK")
barRight:SetPoint("LEFT", barLeft, "RIGHT")
barRight:SetWidth(75)
barRight:SetHeight(16)
barRight:SetTexture("Interface\\ClassTrainerFrame\\UI-ClassTrainer-HorizontalBar")
barRight:SetTexCoord(0, 0.29296875, 0.25, 0.5)
NotebookFrame.BarRight = barRight
 
------------------------------------------------------------------------
-- TITLE TEXT
 
local title = NotebookFrame:CreateFontString(nil, "ARTWORK", "GameFontNormal")
title:SetPoint("TOP", 0, -17)
NotebookFrame.TitleText = title
 
------------------------------------------------------------------------
-- DRAG REGION
 
local drag = CreateFrame("Frame", nil, NotebookFrame)
drag:SetPoint("TOP", 8, -10)
drag:SetWidth(256)
drag:SetHeight(28)
NotebookFrame.DragFrame = drag
 
drag:SetScript("OnMouseDown", function(self, button)
if button == "LeftButton" then
NotebookFrame.isMoving = true
NotebookFrame:StartMoving()
CloseDropDownMenus()
-- Clear editBox focus while moving because of problems with the empty
-- editbox (editBox only updates the actual cursor position when there
-- is text in the editBox. Also, if the editbox was empty, then give
-- it a temporary space character while we are moving it.
if NotebookFrame.EditBox.hasFocus then
NotebookFrame.editHadFocus = true
NotebookFrame.EditBox:ClearFocus()
end
if NotebookFrame.EditBox:GetNumLetters() == 0 then
NotebookFrame.editWasEmpty = true
NotebookFrame.EditBox:SetText(" ")
end
end
end)
 
drag:SetScript("OnMouseUp", function(self, button)
if NotebookFrame.isMoving then
NotebookFrame:StopMovingOrSizing()
NotebookFrame:SetUserPlaced(false)
NotebookFrame.isMoving = nil
-- Restore the editbox's focus and empty status if needed
if NotebookFrame.editWasEmpty then
NotebookFrame.EditBox:SetText("")
NotebookFrame.editWasEmpty = nil
end
if NotebookFrame.editHadFocus then
NotebookFrame.editHadFocus = nil
NotebookFrame.EditBox:SetFocus()
end
end
end)
 
drag:SetScript("OnHide", function(self)
if NotebookFrame.isMoving then
NotebookFrame:StopMovingOrSizing()
NotebookFrame:SetUserPlaced(false)
NotebookFrame.isMoving = nil
-- Restore the editbox's empty status if needed
if NotebookFrame.editWasEmpty then
NotebookFrame.EditBox:SetText("")
NotebookFrame.editWasEmpty = nil
end
NotebookFrame.editHadFocus = nil
end
end)
 
------------------------------------------------------------------------
-- CLOSE X BUTTON
 
local closeX = CreateFrame("Button", nil, NotebookFrame, "UIPanelCloseButton")
closeX:SetPoint("TOPRIGHT", -30, -8)
NotebookFrame.CloseButtonX = closeX
 
------------------------------------------------------------------------
--[[ CLOSE BUTTON
 
local close = CreateFrame("Button", nil, NotebookFrame, "UIPanelButtonTemplate")
close:SetPoint("BOTTOMRIGHT", -42, 80)
close:SetSize(80, 22)
close:SetNormalFontObject(GameFontNormalSmall)
close:SetHighlightFontObject(GameFontHighlightSmall)
close:SetDisabledFontObject(GameFontDisableSmall)
close:SetScript("OnClick", HideParentPanel)
close:SetText(CLOSE)
NotebookFrame.CloseButton = close
]]
------------------------------------------------------------------------
-- SAVE BUTTON
 
local save = CreateFrame("Button", "$parentSave", NotebookFrame, "UIPanelButtonTemplate")
--save:SetPoint("BOTTOMLEFT", 20, 80)
--save:SetSize(60, 22)
save:SetPoint("BOTTOMRIGHT", -42, 80)
save:SetSize(86, 22)
save:SetNormalFontObject(GameFontNormalSmall)
save:SetHighlightFontObject(GameFontHighlightSmall)
save:SetDisabledFontObject(GameFontDisableSmall)
save:SetScript("OnClick", Notebook.Frame_SaveButtonOnClick)
save:SetText(L.SAVE_BUTTON)
save.tooltipText = L.SAVE_BUTTON_TOOLTIP
save.newbieText = L.SAVE_BUTTON_TOOLTIP
NotebookFrame.SaveButton = save
 
------------------------------------------------------------------------
-- CANCEL BUTTON
 
local cancel = CreateFrame("Button", "$parentCancel", NotebookFrame, "UIPanelButtonTemplate")
--cancel:SetPoint("BOTTOMLEFT", save, "BOTTOMRIGHT")
cancel:SetPoint("BOTTOMRIGHT", save, "BOTTOMLEFT", -2, 0)
cancel:SetSize(86, 22)
cancel:SetNormalFontObject(GameFontNormalSmall)
cancel:SetHighlightFontObject(GameFontHighlightSmall)
cancel:SetDisabledFontObject(GameFontDisableSmall)
cancel:SetScript("OnClick", Notebook.Frame_CancelButtonOnClick)
cancel:SetText(L.CANCEL_BUTTON)
cancel.tooltipText = L.CANCEL_BUTTON_TOOLTIP
cancel.newbieText = L.CANCEL_BUTTON_TOOLTIP
NotebookFrame.CancelButton = cancel
 
------------------------------------------------------------------------
-- NEW BUTTON
 
local new = CreateFrame("Button", "$parentNew", NotebookFrame, "UIPanelButtonTemplate")
NotebookFrame.NewButton = new
 
new:SetPoint("TOPRIGHT", -40, -49)
new:SetWidth(60)
new:SetHeight(22)
new:SetNormalFontObject(GameFontNormalSmall)
new:SetHighlightFontObject(GameFontHighlightSmall)
new:SetDisabledFontObject(GameFontDisableSmall)
new:SetScript("OnClick", Notebook.Frame_NewButtonOnClick)
new:SetText(L.NEW_BUTTON)
new.tooltipText = L.NEW_BUTTON_TOOLTIP
new.newbieText = L.NEW_BUTTON_TOOLTIP
 
------------------------------------------------------------------------
-- CAN SEND CHECKBOX
 
local canSend = CreateFrame("CheckButton", "$parentCanSend", NotebookFrame, "InterfaceOptionsSmallCheckButtonTemplate")
NotebookFrame.CanSendCheckButton = canSend
 
canSend.Text = _G[canSend:GetName().."Text"]
canSend.Text:SetPoint("LEFT", canSend, "RIGHT", 0, 0) -- remove default 1px y-offset
canSend:SetFontString(canSend.Text)
canSend:SetNormalFontObject(GameFontHighlightSmall)
canSend:SetHighlightFontObject(GameFontNormalSmall)
canSend:SetDisabledFontObject(GameFontDisableSmall)
 
canSend:SetPoint("BOTTOMLEFT", 20, 81)
canSend:SetSize(22, 22) -- default is 26
canSend:SetHitRectInsets(0, -70, 0, 0)
 
canSend:SetText(L.CHECK_SEND_BUTTON)
canSend.tooltipOnText = L.CHECK_CAN_SEND_TOOLTIP
canSend.tooltipOffText = L.CHECK_NOT_SEND_TOOLTIP
 
canSend:SetScript("OnEnter", function(self)
local text
if self:GetChecked() then
text = self.tooltipOnText
else
text = self.tooltipOffText
end
if text then
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(text)
GameTooltip:Show()
end
end)
 
canSend:SetScript("OnLeave", GameTooltip_Hide)
 
canSend:SetScript("OnClick", function(self, button)
local text
if self:GetChecked() then
PlaySound("igMainMenuOptionCheckBoxOn")
text = self.tooltipOnText
else
PlaySound("igMainMenuOptionCheckBoxOff")
text = self.tooltipOffText
end
if text and GameTooltip:IsOwned(self) then
GameTooltip:SetText(text)
end
 
CloseDropDownMenus()
 
local ndata = Notebook:FindNoteByID(NotebookFrame.selectedID)
if ndata then
if ndata.send then
ndata.send = nil
else
ndata.send = true
end
end
end)
 
------------------------------------------------------------------------
-- FILTER TAB BUTTONS
 
local function tab_OnShow(self)
PanelTemplates_TabResize(self, 0)
_G[self:GetName() .. "HighlightTexture"]:SetWidth(self:GetTextWidth() + 31)
end
 
local function tab_OnEnter(self)
if self.tooltipText then
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(self.tooltipText, nil, nil, nil, nil, 1)
GameTooltip:Show()
end
end
 
local function tab_OnClick(self)
Notebook.Frame_TabButtonOnClick(self:GetID())
end
 
local filterTab1 = CreateFrame("Button", "$parentFilterTab1", NotebookFrame, "TabButtonTemplate")
filterTab1:SetPoint("TOPLEFT", 70, -39)
filterTab1:SetID(1)
filterTab1:SetScript("OnShow", tab_OnShow)
filterTab1:SetScript("OnEnter", tab_OnEnter)
filterTab1:SetScript("OnLeave", GameTooltip_Hide)
filterTab1:SetScript("OnClick", tab_OnClick)
filterTab1:SetText(L.ALL_TAB)
filterTab1.tooltipText = L.ALL_TAB_TOOLTIP
PanelTemplates_SelectTab(filterTab1)
NotebookFrame.FilterTab1 = filterTab1
 
local filterTab2 = CreateFrame("Button", "$parentFilterTab2", NotebookFrame, "TabButtonTemplate")
filterTab2:SetPoint("TOPLEFT", filterTab1, "TOPRIGHT")
filterTab2:SetID(2)
filterTab2:SetScript("OnShow", tab_OnShow)
filterTab2:SetScript("OnEnter", tab_OnEnter)
filterTab2:SetScript("OnLeave", GameTooltip_Hide)
filterTab2:SetScript("OnClick", tab_OnClick)
filterTab2:SetText(L.MINE_TAB)
PanelTemplates_DeselectTab(filterTab2)
NotebookFrame.FilterTab2 = filterTab2
 
local filterTab3 = CreateFrame("Button", "$parentFilterTab3", NotebookFrame, "TabButtonTemplate")
filterTab3:SetPoint("TOPLEFT", filterTab2, "TOPRIGHT")
filterTab3:SetID(3)
filterTab3:SetScript("OnShow", tab_OnShow)
filterTab3:SetScript("OnEnter", tab_OnEnter)
filterTab3:SetScript("OnLeave", GameTooltip_Hide)
filterTab3:SetScript("OnClick", tab_OnClick)
filterTab3:SetText(L.RECENT_TAB)
filterTab3.tooltipText = L.RECENT_TAB_TOOLTIP
PanelTemplates_DeselectTab(filterTab3)
NotebookFrame.FilterTab3 = filterTab3
 
------------------------------------------------------------------------
-- LIST FRAME
 
local listFrame = CreateFrame("Frame", "$parentListFrame", NotebookFrame)
listFrame:SetPoint("TOPLEFT", 20, -74)
listFrame:SetWidth(320)
listFrame:SetHeight(112)
NotebookFrame.ListFrame = listFrame
 
------------------------------------------------------------------------
-- LIST BUTTONS
 
local function createListButton(id)
local button = CreateFrame("Button", "NotebookListButton"..id, listFrame)
button:SetWidth(298)
button:SetHeight(NOTEBOOK_LIST_BUTTON_HEIGHT)
button:SetID(id)
 
local text = button:CreateFontString(nil, "OVERLAY")
button:SetFontString(text)
button:SetNormalFontObject(GameFontNormalSmall)
button:SetHighlightFontObject(GameFontHighlightSmall)
button:SetDisabledFontObject(GameFontDisableSmall)
text:ClearAllPoints()
text:SetPoint("LEFT", button, 10, -2)
text:SetWidth(288)
text:SetHeight(14)
text:SetJustifyH("LEFT")
button.TitleText = text
 
local highlight = button:CreateTexture("$parentHighlight", "HIGHLIGHT")
highlight:SetPoint("LEFT", 2, -2)
highlight:SetPoint("RIGHT", 2, -2)
highlight:SetHeight(NOTEBOOK_LIST_BUTTON_HEIGHT)
highlight:SetTexture("Interface\\Buttons\\UI-Listbox-Highlight2", "ADD")
button:SetHighlightTexture(highlight)
button.TitleHighlight = highlight
 
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
button:SetScript("OnClick", function(self, button)
PlaySound("igMainMenuOptionCheckBoxOn")
Notebook.Frame_ListButtonOnClick(self, button)
end)
button:SetScript("OnEnter", function(self)
if self.tooltipText then
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(self.tooltipText, 1, 1, 1)
GameTooltip:Show()
end
end)
button:SetScript("OnLeave", GameTooltip_Hide)
 
return button
end
 
local listButtons = { }
for id = 1, NOTEBOOK_LIST_BUTTON_COUNT do
local button = createListButton(id)
if id == 1 then
button:SetPoint("TOPLEFT")
else
button:SetPoint("TOPLEFT", listButtons[id - 1], "BOTTOMLEFT")
end
listButtons[id] = button
end
 
NotebookFrame.ListButtons = listButtons
 
------------------------------------------------------------------------
-- LIST SCROLL BAR
 
local scrollFrame = CreateFrame("ScrollFrame", "NotebookFrameListScrollFrame", listFrame, "UIPanelScrollFrameTemplate")
scrollFrame:SetPoint("TOPLEFT", 0, -2)
scrollFrame:SetWidth(296)
scrollFrame:SetHeight(112)
NotebookFrame.ListScrollFrame = scrollFrame
 
scrollFrame:SetScript("OnVerticalScroll", function(self, offset)
FauxScrollFrame_OnVerticalScroll(self, offset, NOTEBOOK_LIST_BUTTON_HEIGHT, Notebook.Frame_UpdateList)
end)
 
local scrollChild = CreateFrame("Frame", "$parentScrollChildFrame", scrollFrame)
scrollChild:SetWidth(296)
scrollChild:SetHeight(112)
scrollFrame:SetScrollChild(scrollChild)
NotebookFrame.ListScrollChild = scrollChild
 
------------------------------------------------------------------------
-- DESCRIPTION FRAME
 
local description = CreateFrame("Frame", nil, NotebookFrame)
description:SetPoint("TOPLEFT", 25, -202)
description:SetWidth(317)
description:SetHeight(204)
NotebookFrame.DescriptionFrame = description
 
------------------------------------------------------------------------
-- EDIT SCROLL FRAME
 
local editScroll = CreateFrame("ScrollFrame", "$parentEditScrollFrame", description)
editScroll:SetPoint("TOPLEFT")
editScroll:SetWidth(314)
editScroll:SetHeight(204)
editScroll.scrollBarHideable = true
NotebookFrame.EditScrollFrame = editScroll
 
editScroll:SetScript("OnMouseWheel", ScrollFrameTemplate_OnMouseWheel)
editScroll:SetScript("OnVerticalScroll", Notebook.Frame_OnVerticalScroll)
 
editScroll:EnableMouse(true)
editScroll:SetScript("OnMouseUp", function(self, button)
-- Focus the edit box when clicking anywhere in the description NotebookFrame,
-- since the edit box magically resizes itself based on the height of
-- its contents since some patches ago.
if button == "LeftButton" and NotebookFrame.EditBox:IsShown()
and not NotebookFrame.EditBox:IsMouseOver() and not NotebookFrame.EditScrollFrame.ScrollBar:IsMouseOver() then
NotebookFrame.EditBox:SetFocus()
end
end)
 
local editBar = CreateFrame("Slider", "$parentScrollBar", editScroll, "UIPanelScrollBarTemplate")
editBar:SetPoint("TOPRIGHT", 0, -14)
editBar:SetPoint("BOTTOMRIGHT", 0, 14)
NotebookFrame.EditScrollFrame.ScrollBar = editBar
 
ScrollFrame_OnLoad(editScroll)
ScrollFrame_OnScrollRangeChanged(editScroll, 0)
 
local editBox = CreateFrame("EditBox", "NotebookEditBox", editScroll)
editBox:SetPoint("TOPLEFT")
editBox:SetWidth(292)
editBox:SetHeight(204)
editBox:EnableMouse(true)
editBox:SetAutoFocus(false)
editBox:SetFontObject(GameFontNormal)
editBox:SetJustifyH("LEFT")
editBox:SetMaxLetters(4096)
editBox:SetMultiLine(true)
editBox:SetIndentedWordWrap(false)
-- Set the text insets to make sure the editbox doesn't
-- chop the bottom off letters which extend below the
-- baseline (e.g., p, y, q, etc.)
editBox:SetTextInsets(0, -2, 0, 2)
editScroll:SetScrollChild(editBox)
NotebookFrame.EditBox = editBox
 
editScroll:SetScript("OnScrollRangeChanged", function(self, xOffset, yOffset)
ScrollFrame_OnScrollRangeChanged(self, xOffset, yOffset)
if floor(yOffset) == 0 then
editBox:SetWidth(292 + 18)
else
editBox:SetWidth(292)
end
end)
 
editBox.cursorOffset = 0
 
editBox:SetScript("OnCursorChanged", function(self, x, y, width, height)
ScrollingEdit_OnCursorChanged(self, x, y - 2, width, height)
ScrollingEdit_OnUpdate(self, 0, self:GetParent())
end)
 
editBox:SetScript("OnTextChanged", function(self, isUserInput)
-- A minor kludge to move to the top of the scroll-NotebookFrame
-- when resetting the text in the edit box
if self.textReset then
if self.textResetToEmpty then
self:SetText("")
self.textResetToEmpty = nil
else
self.textReset = nil
end
else
if self.textResetToEmpty then
self:SetText("")
self.textResetToEmpty = nil
else
Notebook.Frame_TextChanged(self)
end
end
ScrollingEdit_OnTextChanged(self, self:GetParent())
end)
 
editBox:SetScript("OnEscapePressed", editBox.ClearFocus)
 
editBox:SetScript("OnEditFocusLost", function(self)
self.hasFocus = nil
end)
 
editBox:SetScript("OnEditFocusGained", function(self)
if not NotebookFrame.selectedID then
return self:ClearFocus()
end
self.textReset = nil
self.hasFocus = true
end)
 
------------------------------------------------------------------------
-- TEXT SCROLL FRAME (for non-editable text)
 
local textScroll = CreateFrame("ScrollFrame", "NotebookFrameTextScrollFrame", description)
textScroll:SetPoint("TOPLEFT")
textScroll:SetWidth(306)
textScroll:SetHeight(204)
textScroll:Hide()
textScroll.scrollBarHideable = true
NotebookFrame.TextScrollFrame = textScroll
 
textScroll:SetScript("OnMouseWheel", ScrollFrameTemplate_OnMouseWheel)
textScroll:SetScript("OnVerticalScroll", Notebook.Frame_OnVerticalScroll)
textScroll:SetScript("OnScrollRangeChanged", function(self, xOffset, yOffset)
-- Scroll range will only change when we put new text into the
-- textbox, so when this happens we also set the scrollbar
-- position to zero to show the top of the text always.
ScrollFrame_OnScrollRangeChanged(self, yOffset)
NotebookFrameTextScrollFrameScrollBar:SetValue(0)
end)
 
local textBar = CreateFrame("Slider", "$parentScrollBar", textScroll, "UIPanelScrollBarTemplate")
textBar:SetPoint("TOPLEFT", textScroll, "TOPRIGHT", -4, -14)
textBar:SetPoint("BOTTOMLEFT", textScroll, "BOTTOMRIGHT", -4, 14)
NotebookFrame.TextScrollFrame.ScrollBar = textBar
 
ScrollFrame_OnLoad(textScroll)
ScrollFrame_OnScrollRangeChanged(textScroll, 0)
 
local textChild = CreateFrame("Frame", "$parentScrollChild", textScroll)
textChild:SetPoint("TOPLEFT")
textChild:SetWidth(296)
textChild:SetHeight(204)
textChild:EnableMouse(true)
textScroll:SetScrollChild(textChild)
NotebookFrame.TextScrollChild = textChild
 
local textBox = textChild:CreateFontString(nil, "OVERLAY", "GameFontNormal")
textBox:SetPoint("TOPLEFT", 10, -2)
textBox:SetWidth(286)
textBox:SetHeight(0)
textBox:SetJustifyH("LEFT")
textBox:SetIndentedWordWrap(false)
NotebookFrame.TextBox = textBox
 
------------------------------------------------------------------------
-- DROPDOWN MENU
 
local dropdown = CreateFrame("Frame", "NotebookDropDown", NotebookFrame, "UIDropDownMenuTemplate")
NotebookFrame.DropDown = dropdown
 
------------------------------------------------------------------------
-- Addon
------------------------------------------------------------------------
 
NotebookFrame:SetScript("OnEvent", Notebook.OnEvent)
 
Notebook.OnLoad(NotebookFrame)
Notebook.Frame_OnLoad(NotebookFrame)
\ No newline at end of file
trunk/README.txt New file
0,0 → 1,108
Notebook
============
 
Download from [WoWInterface](http://www.wowinterface.com/downloads/info4544-Notebook.html)
or [Curse](http://www.curse.com/addons/wow/notebook).
 
 
Description
---------------
 
Notebook lets you create and share text notes in-game. Each note can be
up to 2048 characters long, and there is no limit on the number of notes
you can create.
 
Notebook will recognize notes sent by other players and automatically
add them to a temporary section of your Notebook, where you can read
them at your leisure, save them permanently, or update your note if you
already have one of the same name.
 
Type "/notebook" or just "/note" to toggle the Notebook window, or bind
a key in the standard Key Bindings window.
 
 
Creating notes
------------------
 
The first time you use Notebook, it will create a "Welcome to Notebook"
note with a brief description of Notebook's features. Feel free to
delete this note.
 
To create a new note, click the "New" button in the top right corner of
the Notebook window, enter a unique title for your new note, and start
typing!
 
 
Editing notes
-----------------
 
To edit an existing note, just click in the text area and start making
changes. Press the "Save" button to save your changes, or "Cancel" to
revert the note to its last saved contents.
 
You can edit multiple notes at once. An asterisk will appear next to the
note's title to show that you have unsaved changes. Remember, though,
that unsaved changes will be lost on logout!
 
 
Sending notes
-----------------
 
Before you can send a note, you must check the "Can be sent" option at
the bottom of the Notebook window for that note. You must also save or
revert any unsaved changes to a note before you can send it, and you
must wait 5 seconds between sending multiple notes.
 
To send a note, right-click its title, select "Send", and select which
channel to send the note to. When sending to a player, a dialog box will
pop up asking for the name of the player to send the note to. When
sending to a public server channel, a dialog box will pop up asking for
confirmation.
 
 
Receiving notes
-------------------
 
When another player sends a Notebook note to you (by whisper, guild,
officer, party, raid, instance, or a custom channel) Notebook will
automatically add the note to your "All" and "Recent" tabs. Notes seen
in public server channels (like Trade) are ignored.
 
You can permanently save a received note to your Notebook by clicking
the "Add" button in the bottom left corner of the Notebook window.
 
If you receive a note with the same name as one of your notes, you can
update your note with the contents of the received note by clicking the
"Update" button in the bottom left corner of the Notebook window.
 
Any received notes you have not saved will be lost on logout.
 
 
History & Credits
---------------------
 
* Cirk of Doomhammer EU -- original author, 2005-2006, 2008
* Kortanis -- maintainer, 2007
* Phanx -- maintainer, 2009-present
 
 
Feedback
-----------
 
Post a ticket on either download site, or a comment on WoWInterface.
 
If you are reporting a bug, please include directions I can follow to
reproduce the bug, whether it still happens when all other addons are
disabled, and the exact text of the related error message (if any) from
[Bugger](http://www.wowinterface.com/downloads/info23144-Bugger.html).
 
If you need to contact me privately, you can send me a private message
on either download site, or email me at <addons@phanx.net>.
 
 
License
----------
 
Copyright (c) 2005-2008 Cirk, 2009-2014 Phanx. All rights reserved.
See the accompanying LICENSE file for information about the conditions
under which redistribution and modification may be allowed.
trunk/Bindings.xml New file
0,0 → 1,5
<Bindings>
<Binding name="NOTEBOOK_PANEL" header="NOTEBOOK_TITLE" category="ADDONS">
ToggleFrame(NotebookFrame)
</Binding>
</Bindings>
\ No newline at end of file
trunk/Localization-ru.lua New file
0,0 → 1,144
--[[--------------------------------------------------------------------
Notebook
Allows you to record and share notes in-game.
Written by Cirk of Doomhammer, 2005-2009
Updated by Phanx with permission, 2012-2014
Do not redistribute. See accompanying LICENSE file for details.
http://www.wowinterface.com/downloads/info4544-Notebook
http://www.curse.com/addons/wow/notebook
----------------------------------------------------------------------]]
-- Перевод на Русский: Джоан-Подземье, Су-Гордунни
 
if GetLocale() ~= "ruRU" then return end
local NOTEBOOK, Notebook = ...
local T = Notebook.L
 
BINDING_NAME_NOTEBOOK_PANEL = "Отобразить Блокнот"
 
L.FRAME_TITLE_FORMAT = "Личный Блокнот %s"
L.ALL_TAB = "Все"
L.ALL_TAB_TOOLTIP = "Все заметки"
L.MINE_TAB = "Личные"
L.MINE_TAB_TOOLTIP_FORMAT = "Личные заметки %s"
L.KNOWN_TAB = "Сохраненные"
L.KNOWN_TAB_TOOLTIP = "Только Сохранить"
L.RECENT_TAB = "Отправ."
L.RECENT_TAB_TOOLTIP = "Отправленные заметки"
L.SAVE_BUTTON = "Сохранить"
L.SAVE_BUTTON_TOOLTIP = "Сохранить изменения"
L.CANCEL_BUTTON = "Отмена"
L.CANCEL_BUTTON_TOOLTIP = "Откат изменений заметки"
L.ADD_BUTTON = "Добавить"
L.ADD_BUTTON_TOOLTIP = "Добавить эту заметку в блокнот"
L.UPDATE_BUTTON = "Обновить"
L.UPDATE_BUTTON_TOOLTIP = "Обновить существующую заметку этим текстом"
L.NEW_BUTTON = "Новая"
L.NEW_BUTTON_TOOLTIP = "Создать новую заметку"
L.CHECK_SEND_BUTTON = "Возможно отпр."
L.CHECK_CAN_SEND_TOOLTIP = "Эту заметку возможно отправить"
L.CHECK_NOT_SEND_TOOLTIP = "Эту заметку невозможно отправить"
 
L.DETAILS_DATE_KNOWN_SAVED_FORMAT = "Сохранено %s"
L.DETAILS_DATE_KNOWN_UPDATED_FORMAT = "%s от %s"
L.DETAILS_DATE_UNSAVED_FORMAT = "%s для %s"
L.DETAILS_SIZE_FORMAT = "- %d символов"
L.DETAILS_NOT_KNOWN_TEXT = "- Не сохранено"
L.DETAILS_SENT_FORMAT = "- Отправить %s"
L.TITLE_CHANGE_NOT_SAVED = "*"
 
L.NOTE_RECEIVED_FORMAT = "В Блокнот Добавлена Заметка “%s” от %s"
 
-- Right-click menu
L.SAVE_OPTION = "Сохранить"
L.ADD_OPTION = "Добавить"
L.UPDATE_OPTION = "Обновить"
L.RENAME_OPTION = "Переименовать"
L.DELETE_OPTION = "Удалить"
L.SEND_OPTION = "Отправить"
L.SEND_TO_TARGET = "Цель"
L.SEND_TO_PLAYER = "Игрок"
L.SEND_TO_INSTANCE = "Образец"
L.SEND_TO_PARTY = "Группа"
L.SEND_TO_RAID = "Рейд"
L.SEND_TO_GUILD = "Гильдия"
L.SEND_TO_OFFICER = "Офицеры"
L.SEND_TO_CHANNEL = "Канал"
L.CHANNEL_NAME_FORMAT = "%d. %s"
 
-- Popup dialogs
L.ENTER_PLAYER_NAME_TEXT = "Укажите имя игрока-получателя для отправки:"
L.ENTER_NEW_TITLE_TEXT = "Укажите название новой заметки:"
L.CONFIRM_REMOVE_FORMAT = "Вы действительно хотите удалить “%s”?"
L.CONFIRM_UPDATE_FORMAT = "Хоите заменить “%s” заметку от %s?"
L.CONFIRM_SERVER_CHANNEL_FORMAT = "Хотите отправить “%s” в канал %s ?"
 
-- Slash commands
L.CMD_HELP = "помощь"
L.CMD_LIST = "лист"
L.CMD_SHOW = "показать"
L.CMD_HIDE = "скрыть"
L.CMD_SEND = "послать"
L.CMD_OPTIONS = "опции"
L.CMD_DEBUGON = "debugon"
L.CMD_DEBUGOFF = "debugoff"
L.CMD_WELCOME = "welcome"
L.CMD_STATUS = "статус"
 
-- Slash command responses
L.CMD_DEBUGON_CONFIRM = "Отладка Блокнота Включена"
L.CMD_DEBUGOFF_CONFIRM = "Отладка Блокнота Выключена"
L.CMD_LIST_CONFIRM = "Блокнот содержит следующие заметки:"
L.CMD_LIST_FORMAT = "- %s (%d символов, от %s, %s)"
L.CMD_STATUS_FORMAT = "Блокнот содержит %d заметок и они занимают %.0fkB памяти"
 
-- Error messages
L.ERR_RENAME_NOT_UNIQUE_FORMAT = "Заметка с названием “%s” уже существует. Названия должны быть уникальны."
L.ERR_RENAME_EMPTY = "Название заметки не должно быть пустым."
L.ERR_SEND_COOLDOWN = "Пока невозможно отправить. Попробуйте позже."
L.ERR_SEND_INVALID = "Укажите корректные названия заметки и канала."
L.ERR_SEND_INVALID_NOTE = "Заметка с названием “%s” не найдена."
L.ERR_SEND_EDITING = "Невозможно отправить заметку с несохраненными изменениями."
L.ERR_SEND_RAID_LEADER = "Вы не являетесь лидером или ассистентом рейда."
L.ERR_SEND_NO_NAME = "Необходимо указать имя персонажа или BattleTag."
L.ERR_SEND_NO_CHANNEL = "Необходимо указать название канала."
L.ERR_SEND_INVALID_CHANNEL = "Канал “%s” не найден."
L.ERR_SEND_UNKNOWN_CHANNEL = "“%s” не является каналом поддерживаемого типа."
 
------------------------------------------------------------------------
-- Help text
 
Notebook.SLASH_COMMAND = "/блокнот"
 
Notebook.HELP_TEXT = {
"Наберите /блокнот, /notebook или /note с этих команд:", -- needs check
"- " .. L.CMD_SHOW .. " - Показать окно Блокнота",
"- " .. L.CMD_HIDE .. " - Скрыть окно Блокнота",
"- " .. L.CMD_LIST .. " - Вывести лист названий заметок с данными о них",
"- " .. L.CMD_WELCOME .. " - Восстановить заметку \"Добро Пожаловать в Блокнот!\"",
"- " .. L.CMD_STATUS .. " - Вевести статус Блокнота, количествозаметок и объем использованной памяти",
"- " .. L.CMD_HELP .. " - Показать это сообщение:",
"Для вызова Блокнота наберите данную команду в чате или используйте ее для назначения кнопки вызова окна Блокнота.",
}
 
------------------------------------------------------------------------
-- First timer's brief manual
 
L.WELCOME_NOTE_TITLE = "Добро Пожаловать в Блокнот!"
L.WELCOME_NOTE_DESCRIPTION = [[
Блокнот позволяет записывать, сохранять и упорядочивать ваши заметки на самые разные темы. Кроме этого вы так же можете отправить как саму заметку так и ее текст игроку или в любой из каналов. Например в общий канал, канал гильдии, канал офицеров канал группы или рейда!
 
Что бы создать новую заметку нажмите на кнопку “Новая” после укажите название. Название заметок может содержать до 60 абсолютно любых символов, но должно быть уникальным! Например вы не сможете создать две заметки с одинаковыми названиями “Развлечения” и “Развлечения”, используйте фантазию и назовите вторую заметку “Развлечения 2” или “Другие Развлечения”
 
После того как вы создали новую заметку вы можете внести в нее нужный текст. Есть один нюанс, если вы кликаете по окну где вводить заметку и ввод символов не возможен, совершите клик в верхней части этого окна примерно по середине. Всего любая заметка может содержать до 4096 символов.
 
Одна из особенностей Блокнота эта отправка ваших заметок, в каналы чата или другим обладателям Блокнота. Для этого Кликните по названию заметки в списке и выберите нужный пункт в контекстном меню. Отправлять заметки можно с любые каналы чата!
 
После отправки заметки нужно подождать несколько секунд прежде чем вы сможете отправить еще одну.
 
Блокнот так же распознает заметки присланные другими игроками, что бы посмотреть их зайдите во вкладку “Отправ.” это сокращенно отправленные, из-за того что слово большое оно попросту не вместилось, по этому пришлось сократить.
 
Я надеюсь, вам понравится Блокнот, и найдете ее полезной!
 
-- Cirk - Doomhammer
 
(Перевод на Русский: Джоан - Подземье)]]
\ No newline at end of file
trunk/Localization-es.lua New file
0,0 → 1,142
--[[--------------------------------------------------------------------
Notebook
Allows you to record and share notes in-game.
Written by Cirk of Doomhammer, 2005-2009
Updated by Phanx with permission, 2012-2014
Do not redistribute. See accompanying LICENSE file for details.
http://www.wowinterface.com/downloads/info4544-Notebook
http://www.curse.com/addons/wow/notebook
----------------------------------------------------------------------]]
-- Traducción al español por Phanx
 
if not GetLocale():match("^es") then return end
local NOTEBOOK, Notebook = ...
local L = Notebook.L
 
BINDING_NAME_NOTEBOOK_PANEL = "Mostrar/ocultar Notebook"
 
L.FRAME_TITLE_FORMAT = "Notebook de %s"
L.ALL_TAB = "Todas"
L.ALL_TAB_TOOLTIP = "Todas notas"
L.MINE_TAB = "Mis"
L.MINE_TAB_TOOLTIP_FORMAT = "Notas creadas por %s"
L.KNOWN_TAB = "Guardadas"
L.KNOWN_TAB_TOOLTIP = "Notas que tú ha guardado de otros jugadores"
L.RECENT_TAB = "Nuevas"
L.RECENT_TAB_TOOLTIP = "Notas que tú ha recibido recientemente"
L.SAVE_BUTTON = "Guardar"
L.SAVE_BUTTON_TOOLTIP = "Guardar los cambios actuales"
L.CANCEL_BUTTON = "Cancelar"
L.CANCEL_BUTTON_TOOLTIP = "Volver a la última versión guardada"
L.ADD_BUTTON = "Agregar"
L.ADD_BUTTON_TOOLTIP = "Agregar esta nota a la lista guardada"
L.UPDATE_BUTTON = "Actualizar"
L.UPDATE_BUTTON_TOOLTIP = "Actualizar su nota guadada con este nuevo texto"
L.NEW_BUTTON = "Crear"
L.NEW_BUTTON_TOOLTIP = "Crear una nueva nota"
L.CHECK_SEND_BUTTON = "Puede enviarse"
L.CHECK_CAN_SEND_TOOLTIP = "Esta nota puede enviarse"
L.CHECK_NOT_SEND_TOOLTIP = "Esta nota no se enviará"
 
L.DETAILS_DATE_KNOWN_SAVED_FORMAT = "Guardó %s"
L.DETAILS_DATE_KNOWN_UPDATED_FORMAT = "%s por %s"
L.DETAILS_DATE_UNSAVED_FORMAT = "%s de %s"
L.DETAILS_SIZE_FORMAT = "- %d caracteres"
L.DETAILS_NOT_KNOWN_TEXT = "- no se guarda"
L.DETAILS_SENT_FORMAT = "- enviado %s"
L.TITLE_CHANGE_NOT_SAVED = "*"
 
L.NOTE_RECEIVED_FORMAT = "Notebook añadió nota “%s” de %s."
 
-- Right-click menu
L.SAVE_OPTION = "Guardar"
L.ADD_OPTION = "Agregar"
L.UPDATE_OPTION = "Actualizar"
L.RENAME_OPTION = "Cambiar nombre"
L.DELETE_OPTION = "Borrar"
L.SEND_OPTION = "Enviar a"
L.SEND_TO_TARGET = "Objetivo"
L.SEND_TO_PLAYER = "Personaje"
L.SEND_TO_INSTANCE = "Instancia"
L.SEND_TO_PARTY = "Gruop"
L.SEND_TO_RAID = "Banda"
L.SEND_TO_GUILD = "Hermandad"
L.SEND_TO_OFFICER = "Oficial"
L.SEND_TO_CHANNEL = "Canal"
L.CHANNEL_NAME_FORMAT = "%d. %s"
 
-- Popup dialogs
L.ENTER_PLAYER_NAME_TEXT = "Escribe el nombre del jugardor al que enviar:"
L.ENTER_NEW_TITLE_TEXT = "Escribe un nuevo título para esta nota:"
L.CONFIRM_REMOVE_FORMAT = "¿Seguro que desea borrar “%s”?"
L.CONFIRM_UPDATE_FORMAT = "¿Seguro que desea reemplazar “%s” con la versión de %s?"
L.CONFIRM_SERVER_CHANNEL_FORMAT = "¿Seguro que desea enviar “%s” al canal %s?"
 
-- Slash commands
L.CMD_HELP = "ayuda"
L.CMD_LIST = "lista"
L.CMD_SHOW = "muestra"
L.CMD_HIDE = "oculta"
L.CMD_SEND = "envía"
L.CMD_OPTIONS = "opciones"
L.CMD_DEBUGON = "debugon"
L.CMD_DEBUGOFF = "debugoff"
L.CMD_WELCOME = "bienvenida"
L.CMD_STATUS = "estado"
 
-- Slash command responses
L.CMD_DEBUGON_CONFIRM = "Depuración de Notebook está activada."
L.CMD_DEBUGOFF_CONFIRM = "Depuración de Notebook está desactivada."
L.CMD_LIST_CONFIRM = "Notebook contiene las siguientes notas:"
L.CMD_LIST_FORMAT = "- %s (%d caracteres, de %s, %s)"
L.CMD_STATUS_FORMAT = "Notebook contiene %d notas y se utiliza %.0fkB de memoria."
 
-- Error messages
L.ERR_RENAME_NOT_UNIQUE_FORMAT = "Ya tienes una nota titulado “%s”. Títulos deben ser únicos."
L.ERR_RENAME_EMPTY = "Títulos no pueden estar vacíos."
L.ERR_SEND_COOLDOWN = "No puedes enviar otra nota todavía."
L.ERR_SEND_INVALID = "Debes introducir un título y un canal valido."
L.ERR_SEND_INVALID_NOTE = "No se puede encontrar una nota “%s”."
L.ERR_SEND_EDITING = "No puedes enviar una nota con cambios sin guardar."
L.ERR_SEND_RAID_LEADER = "No estás el líder o un asistente de la banda."
L.ERR_SEND_NO_NAME = "Debes indroducir un nombre de personaje o un BattleTag."
L.ERR_SEND_NO_CHANNEL = "Debes introducir un nombre de canal."
L.ERR_SEND_INVALID_CHANNEL = "No se puede encontrar un canal “%s”."
L.ERR_SEND_UNKNOWN_CHANNEL = "“%s” no es un tipo compatible de canal."
 
------------------------------------------------------------------------
-- Help text
 
Notebook.SLASH_COMMAND = "/cuaderno"
 
Notebook.NOTEBOOK_HELP = {
"Utilizar /cuaderno, /notebook o /note con los siguientes comandos:",
"- " .. L.CMD_SHOW .. " - mostrar Notebook",
"- " .. L.CMD_HIDE .. " - ocultar Notebook",
"- " .. L.CMD_STATUS .. " - informarle el estado de Notebook",
"- " .. L.CMD_LIST .. " - enumerar las notas en su Notebook",
"- " .. L.CMD_WELCOME .. " - restaurar la nota Bienvenida",
"- " .. L.CMD_HELP .. " - mostrar este ayuda",
"Utilizarlo sin comando para mostrar o ocultar Notebook, o asignar una tecla.",
}
 
------------------------------------------------------------------------
-- First timer’s brief manual
 
L.WELCOME_NOTE_TITLE = "Bienvenido a Notebook!"
L.WELCOME_NOTE_DESCRIPTION = [[
Notebook te permite escribar y guardar notas sobre diversos temas, y compartirlas con tus amigos, tu grupo, tu hermandad, y los canales de chat! Si normalmente utiliza macros para dar instrucciones al grupo, explicar explicar las reglas de saqueo, recordar listas de encantamientos, o propósitos similares -- Notebook puede ser útil para ti!
 
Para crearon una nueva nota, sólo clic en la boton “Crear” y escriba un título para la nota. Títulos pueden tener hasta 60 caracteres de largo, y pueden incluyir cualqier carácter. Pero, cada título tiene que ser único -- no puedes tener dos notas con el mismo título.
 
Después de crear la nota, puedes editarlo y guardarlo en cualquier momento. Notas pueden tener hasta 4096 caracters de largo. Sí necesitas más espacio, simplemente crear otra nota! No hay un límite en el número de notas que puedes tener.
 
Las funcionas más interesantes de Notebook son disponibles haciendo clic derecho sobre el título de una nota en la lista de notas. Esto aparecerá un menú con muchas opciones, incluyendo opciones para enviar la nota a otros jugadores en tu grupo, banda, o hermandad, por susurro, o por un canal de chat. (Antes de puedes enviar una nota, debes activar la opción “Puede enviarse” para esa nota específica, en el abajo del marco.)
 
Despúes de enviar una nota, debes esperar unos segundos antes de poder enviar otras. Recuerde, al igual que con los macros, es tu responsabilidad para evitar molestar a otros jugadores por el abuso de esta función!
 
Notebook reconocerá automáticamente las notas enviadas por otros jugadores, y las mostrará en la pestaña “Recientes” junto con las notas que ha enviado en esta sesión. Podrás guardar estas notas a su propia lista, o actualizar tu copia si ya tenías. (Si la nota no ha cambiado, verás tu propria noa existente allí.)
 
Espero que disfrutes de Notebook, y es te útil!
 
-- Cirk de Doomhammer]]
\ No newline at end of file
trunk/Localization-de.lua New file
0,0 → 1,142
--[[--------------------------------------------------------------------
Notebook
Allows you to record and share notes in-game.
Written by Cirk of Doomhammer, 2005-2009
Updated by Phanx with permission, 2012-2014
Do not redistribute. See accompanying LICENSE file for details.
http://www.wowinterface.com/downloads/info4544-Notebook
http://www.curse.com/addons/wow/notebook
----------------------------------------------------------------------]]
-- Deutsche Übersetzung von Phanx
 
if GetLocale() ~= "deDE" then return end
local NOTEBOOK, Notebook = ...
local L = Notebook.L
 
BINDING_NAME_NOTEBOOK_PANEL = "Notebook ein/aus"
 
L.FRAME_TITLE_FORMAT = "Notebook von %s"
L.ALL_TAB = "Alle"
L.ALL_TAB_TOOLTIP = "Alle Notizen"
L.MINE_TAB = "Meine"
L.MINE_TAB_TOOLTIP_FORMAT = "Die Notizen, die %s sich selbst geschaffen"
L.KNOWN_TAB = "Bekannte"
L.KNOWN_TAB_TOOLTIP = "Die Noitzen, die Ihr habt gespeichert"
L.RECENT_TAB = "Kürzliche"
L.RECENT_TAB_TOOLTIP = "Die Notizen, die Ihr habt kürzlich erhalten"
L.SAVE_BUTTON = "Spiechen"
L.SAVE_BUTTON_TOOLTIP = "Die aktuellen Änderungen spiechen"
L.CANCEL_BUTTON = "Abbrechen"
L.CANCEL_BUTTON_TOOLTIP = "Nicht gespeichterte Änderungen verwerfen, und zum zuvor gespiecherte Version zurückkehren"
L.ADD_BUTTON = "Hinzufügen"
L.ADD_BUTTON_TOOLTIP = "Diese Notiz auf Euer Liste der zuvor gespiecherten Notizen hinzufügen"
L.UPDATE_BUTTON = "Aktualisieren"
L.UPDATE_BUTTON_TOOLTIP = "Eure zuvor gespiecherten Notiz mit diesem neuen Text aktualisieren"
L.NEW_BUTTON = "Neue"
L.NEW_BUTTON_TOOLTIP = "Eine neue Notiz schaffen"
L.CHECK_SEND_BUTTON = "Sendbare"
L.CHECK_CAN_SEND_TOOLTIP = "Diese Notiz kann gesendet werden"
L.CHECK_NOT_SEND_TOOLTIP = "Diese Notiz kann nicht gesendet werden"
 
L.DETAILS_DATE_KNOWN_SAVED_FORMAT = "Gespiechert %s"
L.DETAILS_DATE_KNOWN_UPDATED_FORMAT = "%s von %s"
L.DETAILS_DATE_UNSAVED_FORMAT = "%s von %s"
L.DETAILS_SIZE_FORMAT = "- %d Zeichen"
L.DETAILS_NOT_KNOWN_TEXT = "- nicht gespeichert"
L.DETAILS_SENT_FORMAT = "- gesendet %s"
L.TITLE_CHANGE_NOT_SAVED = "*"
 
L.NOTE_RECEIVED_FORMAT = "Notebook hat die Notiz „%s“ von %s hinzugefügt."
 
-- Right-click menu
L.SAVE_OPTION = "Spiechern"
L.ADD_OPTION = "Hinzufügen"
L.UPDATE_OPTION = "Aktualisieren"
L.RENAME_OPTION = "Unenennen"
L.DELETE_OPTION = "Löschen"
L.SEND_OPTION = "Senden zu"
L.SEND_TO_TARGET = "Ziel"
L.SEND_TO_PLAYER = "Spieler"
L.SEND_TO_INSTANCE = "Instanz"
L.SEND_TO_PARTY = "Gruppe"
L.SEND_TO_RAID = "Schlachtzug"
L.SEND_TO_GUILD = "Gilde"
L.SEND_TO_OFFICER = "Offizier"
L.SEND_TO_CHANNEL = "Channel"
L.CHANNEL_NAME_FORMAT = "%d. %s"
 
-- Popup dialogs
L.ENTER_PLAYER_NAME_TEXT = "Gebt den Spielername ein, denen diese Notiz senden:"
L.ENTER_NEW_TITLE_TEXT = "Gebt einen neuen Name für dieser Notiz ein:"
L.CONFIRM_REMOVE_FORMAT = "Wollt Ihr wirklich die Notiz „%s“ dauerhaft löschen?"
L.CONFIRM_UPDATE_FORMAT = "Wollt Ihr wirklich die Notiz „%s“ durch der Version von %s ersetzen?"
L.CONFIRM_SERVER_CHANNEL_FORMAT = "Wollt Ihr wirklich die Notiz „%s“ zu dem Channel %s senden?"
 
-- Slash commands
L.CMD_HELP = "hilf"
L.CMD_LIST = "liste"
L.CMD_SHOW = "ein"
L.CMD_HIDE = "aus"
L.CMD_SEND = "send"
L.CMD_OPTIONS = "optionen"
L.CMD_DEBUGON = "debugein"
L.CMD_DEBUGOFF = "debugaus"
L.CMD_WELCOME = "wilkommen"
L.CMD_STATUS = "status"
 
-- Slash command responses
L.CMD_DEBUGON_CONFIRM = "Notebook-Debugging wird aktiviert."
L.CMD_DEBUGOFF_CONFIRM = "Notebook-Debugging wird deaktiviert."
L.CMD_LIST_CONFIRM = "Notebook enthält die folgenden Notizen:"
L.CMD_LIST_FORMAT = " - %s (%d Zeichen, von %s, %s)"
L.CMD_STATUS_FORMAT = "Notebook enthält %d Noitzen, und benutzt %.0fkB Spiecher."
 
-- Error messages
L.ERR_RENAME_NOT_UNIQUE_FORMAT = "Ihr habt bereits eine Notiz von dem Namen „%s“. Namen müssen einzigartig sein."
L.ERR_RENAME_EMPTY = "Namen dürfen nicht leer sein."
L.ERR_SEND_COOLDOWN = "Ihr dürft eine weitere Notiz noch nicht senden."
L.ERR_SEND_INVALID = "Ihr müsst eine gültige Notiz und Channel eingeben."
L.ERR_SEND_INVALID_NOTE = "Notiz „%s“ nicht gefunden."
L.ERR_SEND_EDITING = "Ihr dürft eine Notiz mit nicht gespeicherten Änderungen nicht senden."
L.ERR_SEND_RAID_LEADER = "Ihr seid nicht der Schlachtzugsleiter oder Assistent."
L.ERR_SEND_NO_NAME = "Ihr müsst einen Charakternamen oder BattleTag eingeben."
L.ERR_SEND_NO_CHANNEL = "Ihr müsst einen Channelnamen eingeben."
L.ERR_SEND_INVALID_CHANNEL = "Channel „%s“ nicht gefunden."
L.ERR_SEND_UNKNOWN_CHANNEL = "„%s“ ist kein unterstützter Chatnachrichtentyp."
 
------------------------------------------------------------------------
-- Help text
 
Notebook.SLASH_COMMAND = "/notizbuch"
 
Notebook.HELP_TEXT = {
"Gebt /notizbuch, /notebook oder /note mit den folgenden Befehlen ein:",
"- " .. L.CMD_SHOW .. " - Notebook anzeigen",
"- " .. L.CMD_HIDE .. " - Notebook ausblenden",
"- " .. L.CMD_STATUS .. " - die Status von Notebook anzeigen",
"- " .. L.CMD_LIST .. " - die Notizen in Eurem Notebook listen",
"- " .. L.CMD_WELCOME .. " - die Wilkommen-Notiz wiederherstellen",
"- " .. L.CMD_HELP .. " - diese Hilfe anzeigen",
"Gebt den Slash-Befehl ohne weiteren Befehlen ein, oder eine Taste in Tastaturbelegungsmenü belegen, um den Notebook-Fenster zu anzeigen oder ausblenden.",
}
 
------------------------------------------------------------------------
-- First timer's brief manual
 
L.WELCOME_NOTE_TITLE = "Wilkommen in Notebook!"
L.WELCOME_NOTE_DESCRIPTION = [[
Mit Notebook kann man viele Notizen im Spiel schreiben und spiechern, und sie zu die Freunde, Gruppe, Gilde und Chat-Kanäle senden. Wenn man normalerweise Makros benutzte, um Anweisung die Gruppe zu geben, oder Listen von Gegenständte zu führen -- Notebook könnte nützlich sein!
 
Um eine neue Notiz zu schaffen, einfach klickt auf den Button „Schaffen“ und schreibt einen Namen für der Notiz. Namen können bis zu 60 Zeichen lang sein, und können beliebige Zeichen beinhalten. Jedoch müssen jeder Name einzigartich sein -- man kann nicht mehrere Noten mit dem gleichen Namen haben.
 
Nach der Schaffung einer Notiz kann man sie jederzeit ändern. Notizen können bis zu 4096 Zeichen lang sein. Wenn man mehr Platz benötigt, kann eine weitere Notiz einfach geschaffen werden. Man kann beliebig viele Notizen haben -- es gibt kein Limit!
 
Die interessanteren Funktionen von Notebook können durch Rechtsklick auf dem Name einer Notiz gefunden werden. Bei diesem Menü kann man die Notiz zu anderen Spielern senden, obwohl muss man zuerst die Option „Sendbare“ für die individuelle Notiz an der Unterseite der Fenster aktivieren.
 
Nach dem Senden einer Notiz muss man einige Sekunden warten, bevor es möglich wird, weitere Notizen senden. Erinnert Euch -- wie bei Makros, es liegt in Euer Verantwortung, um andere Spieler durch diese Funktion nicht spammen!
 
Notebook speichert automatisch die Notizen, die von anderen Spielern empfangen werden, und zeigt sie in dem „Kürzlich“-Fach zusammen mit den Notizen, die Ihr in dieser Sitzung gesendet habt. Bei diesem Fach könnt Ihr diesen Notizen in eiginer Liste hinzufügen, oder Eure eigene Note zu aktualisieren.
 
Ich hoffe, Ihr erfreut über Notebook seid, und das nützlich findet!
 
-- Cirk von Doomhammer]]
\ No newline at end of file
trunk/LICENSE.txt New file
0,0 → 1,32
Copyright (c) 2005-2008 Cirk, 2012-2014 Phanx. All rights reserved.
 
Permission is granted for anyone to use, read, or otherwise interpret
this software for any purpose, without any restrictions.
 
Permission is granted for anyone to modify this software or sample from
it, and to distribute such modified versions or derivative works as long
as neither the names of this software nor its authors are used in the
name or title of the work or in any other way that may cause it to be
confused with this software.
 
Permission is granted for anyone to aggregate this software with other
works not derived from this software for the purpose of creating a user
interface compilation for "World of Warcraft" and to distribute such
compilations as long as the software is not modified in any way,
including by modifying or removing any files.
 
This software may not be distributed standalone or in any other way, in
whole or in part, modified or unmodified, without specific prior written
permission from the authors of this software.
 
The names of this software and/or its authors may not be used to
promote or endorse works derived from this software without specific
prior written permission from the authors of this software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
trunk/Notebook.lua New file
0,0 → 1,2122
--[[--------------------------------------------------------------------
Notebook
Allows you to record and share notes in-game.
Written by Cirk of Doomhammer, 2005-2009
Updated by Phanx with permission, 2012-2014
Do not redistribute. See accompanying LICENSE file for details.
http://www.wowinterface.com/downloads/info4544-Notebook
http://www.curse.com/addons/wow/notebook
----------------------------------------------------------------------]]
 
local NOTEBOOK, Notebook = ...
local L = Notebook.L
local HELP_TEXT = Notebook.HELP_TEXT
 
Notebook.name = GetAddOnMetadata(NOTEBOOK, "Title")
Notebook.description = GetAddOnMetadata(NOTEBOOK, "Notes")
Notebook.version = GetAddOnMetadata(NOTEBOOK, "Version")
 
BINDING_HEADER_NOTEBOOK_TITLE = Notebook.name
 
NotebookState = {}
 
------------------------------------------------------------------------
-- Global constants
 
NOTEBOOK_LIST_BUTTON_COUNT = 7 -- number of buttons in list frame
NOTEBOOK_LIST_BUTTON_HEIGHT = 16 -- height of each button in list frame
 
------------------------------------------------------------------------
-- Local constants
 
local NOTEBOOK_CHANNEL_VALUE_FORMAT = "%s:%d:%s"
local NOTEBOOK_CHANNEL_VALUE_FIND = "(.+):(%d+):(.+)"
local NOTEBOOK_MAX_LINE_LENGTH = 240 -- maximum characters in one line
local NOTEBOOK_MAX_NUM_LINES = 64 -- maximum number of lines sent from a note
local NOTEBOOK_NEW_LINE = "\n" -- newline character
local NOTEBOOK_GETDATE_FORMAT = "%y-%m-%d" -- see strftime
 
local NOTEBOOK_SEND_PREFIX = "\032" -- used to indicate start of a sent line (a non-printing character)
local NOTEBOOK_SEND_POSTFIX = "\032" -- used to indicate where lines join (a non-printing character)
local NOTEBOOK_HEADER_PRE = "\032##\032 "
local NOTEBOOK_HEADER_POST = "\032 ##"
local NOTEBOOK_HEADER_LINECOUNT_CHAR = "\032"
local NOTEBOOK_HEADER_PATTERN = "^" .. NOTEBOOK_HEADER_PRE .. "(.+)" .. NOTEBOOK_HEADER_POST .. "(" .. NOTEBOOK_HEADER_LINECOUNT_CHAR .. "+)$"
 
local NOTEBOOK_SEND_LINE_COOLDOWN = 0.25 -- 250 ms per line (max message rate of 1 per sec average over 10)
local NOTEBOOK_SEND_FINISHED_COOLDOWN = 5 -- delay after sending last line
local NOTEBOOK_RECEIVE_TIMEOUT = 3 -- how long to wait after it all should have been received
 
local NOTEBOOK_MAX_STRING_LENGTH = 768 -- If we go over 900 characters or so (exact value unknown) in a single string,
-- WoW gets unhappy when saving the string to a file, so use a maximum limit
-- and wrap longer lines into a table.
 
------------------------------------------------------------------------
-- Color information
 
local _colorKnown = { r = 1, g = 0.82, b = 0, a = 0.6 } -- GameFontNormal yellow ("a" used for highlight alpha)
local _colorNotKnown = { r = 0.8, g = 0.8, b = 0.8, a = 0.6 } -- Light grey ("a" used for highlight alpha)
local _colorTextEnabled = { r = 1, g = 0.82, b = 0 } -- GameFontNormal yellow
local _colorTextDisabled = { r = 0.5, g = 0.5, b = 0.5 } -- Light grey
 
------------------------------------------------------------------------
-- Local variables
 
local NotebookFrame -- The frame pointer
local _debugFrame -- debug output chat frame
 
local _serverName = GetRealmName()
local _playerName = UnitName("player")
 
local _original_ChatFrameEditBox_IsVisible -- original ChatFrameEditBox:IsVisible()
local _original_ChatFrameEditBox_Insert -- original ChatFrameEditBox:Insert()
 
local _notesList
-- notes contents:
-- title text of title
-- author who provided or last edited the text
-- date date at which text was last edited
-- sent date at which text was last sent
-- id unique ID for the note
-- description contents of note
-- known true if note is in our own database, nil otherwise
-- recent true if note has been edited/sent recently, nil otherwise
-- send true if can send, nil otherwise
-- update true if this is an update for an existing known note, nil otherwise
 
local _notesCount = 0 -- count of how many notes are in notesList
local _notesLastID = 0 -- last note ID used
local _filteredList = {} -- filtered list of notes, contains indices into notesList
local _filteredCount = 0
local _filterBy = L.ALL_TAB
 
local _sendInProgress -- set when sending a message to someone (nil otherwise)
local _sendCooldownTimer -- set to time to send next line or to allow next send (nil if not used)
local _sendLines = {} -- the pending lines to be sent
local _sendChannel -- channel to use ("GUILD", "PARTY", "CHANNEL", etc.)
local _sendTarget -- target for send
local _lastPlayer -- last player we sent a note to
local _currentTitle -- current title to be edited (if there is one)
 
local _firstTimeLoad -- set to true if this Notebook has not been run on the current server yet
 
local _receiveInProgress -- true when receiving a message
local _receiveTimer -- set to an expiration time when receiving
local _receiveSender -- set to the name of the player we are listening to
local _receiveChannel -- set to the channel we are listening to
local _receiveTarget -- set to the channel # we are listening to (for chat channels)
local _receiveLinesExpected = 0 -- number of lines expected
local _receiveLines = {} -- lines so far received
local _receiveTitle -- title of new note
 
------------------------------------------------------------------------
-- Configuration flags
 
local _addSavedToRecent = true -- false means that only sent and received notes go in the
-- recent tab, true would add recently saved notes also
 
------------------------------------------------------------------------
-- First timer's brief manual
------------------------------------------------------------------------
 
local _firstTimeNote = {
title = L.WELCOME_NOTE_TITLE,
description = L.WELCOME_NOTE_DESCRIPTION,
author = "Cirk",
date = "05-12-24",
}
 
------------------------------------------------------------------------
-- Popup defines (see Blizzard's StaticPopup.lua)
------------------------------------------------------------------------
 
StaticPopupDialogs["NOTEBOOK_SEND_TO_PLAYER"] = {
text = L.ENTER_PLAYER_NAME_TEXT,
button1 = ACCEPT,
button2 = CANCEL,
hasEditBox = 1,
maxLetters = 32,
OnShow = function(self)
local editBox = self.editBox or _G[self:GetName() .. "EditBox"]
editBox:SetText(Notebook:GetPopupData("PLAYER"))
editBox:HighlightText()
editBox:SetFocus()
NotebookFrame.NewButton:Disable()
end,
OnHide = function(self)
local editBox = self.editBox or _G[self:GetName() .. "EditBox"]
editBox:SetText("")
NotebookFrame.NewButton:Enable()
ChatEdit_FocusActiveWindow()
end,
OnAccept = function(self, data)
local editBox = self.editBox or _G[self:GetName() .. "EditBox"]
Notebook:HandlePopupInput("PLAYER", data, editBox:GetText())
end,
EditBoxOnEnterPressed = function(self, data)
Notebook:HandlePopupInput("PLAYER", data, self:GetText())
self:GetParent():Hide()
end,
EditBoxOnEscapePressed = function(self)
self:GetParent():Hide()
end,
timeout = 60,
exclusive = 1,
whileDead = 1,
hideOnEscape = 1,
}
 
StaticPopupDialogs["NOTEBOOK_NEW_TITLE"] = {
text = L.ENTER_NEW_TITLE_TEXT,
button1 = ACCEPT,
button2 = CANCEL,
hasEditBox = 1,
maxLetters = 60,
OnShow = function(self)
local editBox = self.editBox or _G[self:GetName() .. "WideEditBox"]
editBox:SetText(Notebook:GetPopupData("TITLE"))
editBox:HighlightText()
editBox:SetFocus()
NotebookFrame.NewButton:Disable()
end,
OnHide = function(self)
local editBox = self.editBox or _G[self:GetName() .. "EditBox"]
editBox:SetText("")
NotebookFrame.NewButton:Enable()
ChatEdit_FocusActiveWindow()
end,
OnAccept = function(self, data)
local editBox = self.editBox or _G[self:GetName() .. "EditBox"]
Notebook:HandlePopupInput("TITLE", data, editBox:GetText())
end,
EditBoxOnEnterPressed = function(self, data)
Notebook:HandlePopupInput("TITLE", data, self:GetText())
self:GetParent():Hide()
end,
EditBoxOnEscapePressed = function(self)
self:GetParent():Hide()
end,
timeout = 60,
exclusive = 1,
whileDead = 1,
hideOnEscape = 1,
}
 
StaticPopupDialogs["NOTEBOOK_REMOVE_CONFIRM"] = {
text = L.CONFIRM_REMOVE_FORMAT,
button1 = YES,
button2 = NO,
sound = "igCharacterInfoOpen",
OnAccept = function(self, data)
Notebook:HandlePopupInput("CONFIRM", data)
end,
timeout = 60,
exclusive = 1,
whileDead = 1,
hideOnEscape = 1,
showAlert = 1,
}
 
StaticPopupDialogs["NOTEBOOK_UPDATE_CONFIRM"] = {
text = L.CONFIRM_UPDATE_FORMAT,
button1 = YES,
button2 = NO,
sound = "igCharacterInfoOpen",
OnAccept = function(self, data)
Notebook:HandlePopupInput("UPDATE", data)
end,
timeout = 60,
exclusive = 1,
whileDead = 1,
hideOnEscape = 1,
showAlert = 1,
}
 
StaticPopupDialogs["NOTEBOOK_SERVER_CONFIRM"] = {
text = L.CONFIRM_SERVER_CHANNEL_FORMAT,
button1 = YES,
button2 = NO,
sound = "igCharacterInfoOpen",
OnAccept = function(self, data)
Notebook:HandlePopupInput("SERVER", data)
end,
timeout = 60,
exclusive = 1,
whileDead = 1,
hideOnEscape = 1,
showAlert = 1,
}
 
------------------------------------------------------------------------
-- Local functions
------------------------------------------------------------------------
 
local PRINT_PREFIX = NORMAL_FONT_COLOR_CODE .. Notebook.name .. ":|r "
local ERROR_PREFIX = "|cffff7f7f" .. Notebook.name .. ":|r "
local DEBUG_PREFIX = "|cff7fff7f" .. NOTEBOOK .. ":|r "
 
function Notebook:Print(str, noPrefix)
DEFAULT_CHAT_FRAME:AddMessage((noPrefix and " " or PRINT_PREFIX) .. str)
end
 
function Notebook:Error(str)
DEFAULT_CHAT_FRAME:AddMessage(ERROR_PREFIX .. str)
end
 
function Notebook:Debug(str)
if not _debugFrame then return end
_debugFrame:AddMessage(DEBUG_PREFIX .. str)
end
 
------------------------------------------------------------------------
 
local MONTH_NAMES = {
["01"] = FULLDATE_MONTH_JANUARY,
["02"] = FULLDATE_MONTH_FEBRUARY,
["03"] = FULLDATE_MONTH_MARCH,
["04"] = FULLDATE_MONTH_APRIL,
["05"] = FULLDATE_MONTH_MAY,
["06"] = FULLDATE_MONTH_JUNE,
["07"] = FULLDATE_MONTH_JULY,
["08"] = FULLDATE_MONTH_AUGUST,
["09"] = FULLDATE_MONTH_SEPTEMBER,
["10"] = FULLDATE_MONTH_OCTOBER,
["11"] = FULLDATE_MONTH_NOVEMBER,
["12"] = FULLDATE_MONTH_DECEMBER,
}
 
function Notebook:GetDateText(packedDate)
-- Notebook uses a date format of yymmdd, returned automatically by
-- calling date("%y%m%d"), however we unpack this into a more human
-- readable form.
-- local year, month, day = strmatch(packedDate, "(%d%d)(%d%d)(%d%d)")
local year, month, day = strsplit("-", packedDate)
return format("%s %s 20%s", day, MONTH_NAMES[month], year)
end
 
------------------------------------------------------------------------
 
function Notebook:GenerateSignature(text, numLines)
-- Generates a "secret" signature version of the provided text string
-- that other Notebooks can automatically recognize.
return NOTEBOOK_HEADER_PRE .. text .. NOTEBOOK_HEADER_POST .. strrep(NOTEBOOK_HEADER_LINECOUNT_CHAR, numLines)
end
 
------------------------------------------------------------------------
 
function Notebook:Reset()
-- Resets the Notebook back to empty
_notesList = {}
_filteredList = {}
_notesCount = 0
_filteredCount = 0
_notesLastID = 0
end
 
function Notebook:SaveData()
-- Saves the currently known entries in the Notebook (not-known are not saved)
local notes = {}
for i = 1, #_notesList do
local ndata = _notesList[i]
if ndata.known then
local saveNote = {}
saveNote.author = ndata.author
saveNote.date = ndata.date
saveNote.sent = ndata.sent
if strlen(ndata.description) < NOTEBOOK_MAX_STRING_LENGTH then
saveNote.description = ndata.description
else
local data = ndata.description
local result = {}
while strlen(data or "") > 0 do
local prefix = strsub(data, 1, NOTEBOOK_MAX_STRING_LENGTH)
data = strsub(data, NOTEBOOK_MAX_STRING_LENGTH + 1)
tinsert(result, prefix)
end
saveNote.description = result
end
if ndata.send then
saveNote.send = 1
end
notes[ndata.title] = saveNote
end
end
NotebookState.Notes = notes
NotebookState.Servers = nil
end
 
function Notebook:LoadOneNote(title, ndata)
-- Given a saved note defined by a title and by ndata, this function
-- creates a note structure for use in-memory. The _notesLastID value is
-- also automatically incremented to form the note's id value
local newNote = {
title = title,
author = ndata.author,
date = ndata.date,
sent = ndata.sent,
known = true,
}
if not strfind(ndata.date, "%-") then
-- @PHANX, 15 Mar 2014, upgrade old date storage format
local y, m, d = strmatch(ndata.date, "(%d%d)(%d%d)(%d%d)")
newNote.date = strjoin("-", y, m, d)
end
if type(ndata.description) == "string" then
newNote.description = ndata.description
else
newNote.description = ""
if type(ndata.description) == "table" then
for i = 1, #ndata.description do
newNote.description = newNote.description .. ndata.description[i]
end
end
end
if ndata.send then
newNote.send = true
end
_notesLastID = _notesLastID + 1
newNote.id = _notesLastID
return newNote
end
 
function Notebook:LoadData()
-- Loads all the notes from the current saved variables file. This
-- function implements code to read the previous save file format (where
-- notes were saved per server) and handles notes with the same name from
-- different servers by appending the server name.
Notebook:Reset()
for entry, ndata in pairs(NotebookState.Notes) do
_notesCount = _notesCount + 1
_notesList[_notesCount] = Notebook:LoadOneNote(entry, ndata)
end
if NotebookState.Servers then
for server, sdata in pairs(NotebookState.Servers) do
if sdata.Notes then
for entry, ndata in pairs(sdata.Notes) do
local title = entry
repeat
local found = nil
for i = 1, #_notesList do
if _notesList[i].title == title then
title = title .. " -" .. server
found = true
break
end
end
until not found
_notesCount = _notesCount + 1
_notesList[_notesCount] = Notebook:LoadOneNote(title, ndata)
end
end
end
end
if _notesCount > 0 then
_firstTimeLoad = nil
end
end
 
function Notebook:CalculateChecksum(string)
Notebook:Debug("Notebook:CalculateChecksum is still TO DO")
return 0
end
 
function Notebook:FindByTitle(title, known)
-- Returns the entry of the note with the matching title or nil if not found. If known is true then only known entries are checked.
if known then
for i = 1, #_notesList do
local ndata = _notesList[i]
if ndata.known and ndata.title == title then
return ndata
end
end
else
for i = 1, #_notesList do
local ndata = _notesList[i]
if ndata.title == title then
return ndata
end
end
end
return nil
end
 
function Notebook:FindNoteByID(id)
-- Returns the entry with the matching id, or nil if not found
if id then
for i = 1, #_notesList do
local ndata = _notesList[i]
if ndata.id == id then
return ndata
end
end
end
return nil
end
 
function Notebook:AddNote(title, author, date, description, known, recent, send)
-- Adds a new entry to the notebook. Note that it is the callers
-- responsibility to make sure the title is valid and unique! The
-- function then returns the newly added note entry.
local newNote = {
title = title,
author = author,
date = date,
description = description,
known = known,
recent = recent,
send = send,
}
_notesLastID = _notesLastID + 1
newNote.id = _notesLastID
_notesCount = _notesCount + 1
_notesList[_notesCount] = newNote
return newNote
end
 
function Notebook:RemoveNoteByID(id)
-- Removes (deletes) the note with the indicated id from the list. Note
-- that it appears that sometimes tremove does not work properly (or
-- at least reliably), at least when the index being removed is not the
-- first or last index, so we do it the somewhat slower way of recreating
-- the table entries without the one we don't want.
local newList = {}
for index = 1, _notesCount do
local ndata = _notesList[index]
if ndata.id ~= id then
tinsert(newList, ndata)
end
_notesList[index] = nil
end
_notesCount = #newList
_notesList = newList
end
 
function Notebook:Rename(ndata, title)
-- Renames the indicated note entry with the given title. It is the
-- caller's responsibility to ensure that the new title is valid and
-- unique.
ndata.title = title
if _addSavedToRecent then
ndata.recent = true
end
end
 
function Notebook:UpdateDescription(ndata, description)
-- Updates the description in the note, and also sets the author (to the
-- player) and date (to the current server date).
ndata.description = description
ndata.author = _playerName
ndata.date = date(NOTEBOOK_GETDATE_FORMAT)
if _addSavedToRecent then
ndata.recent = true
end
end
 
function Notebook:CompareDescription(desc1, desc2)
-- Does a simple compare on the two passed descriptions to see if they are
-- equal (or close enough to equal) by converting all whitespace sequences
-- in the descriptions to single spaces. If the two strings are then
-- equal, the function will return true.
local text1 = gsub(desc1 .. " ", "(%s+)", " ")
local text2 = gsub(desc2 .. " ", "(%s+)", " ")
if text1 == text2 then
return true
end
end
 
function Notebook.CompareOnTitle(index1, index2)
-- Filters the list into ascending title order. If the title's are the
-- same then we choose the known one first. Note that it is important to
-- check for the indices being different because the sort algorithm
-- doesn't like sorting on secondary parameters.
if index1 == index2 then
return false
end
if _notesList[index1].title == _notesList[index2].title then
return _notesList[index1].known
end
return _notesList[index1].title < _notesList[index2].title
end
 
function Notebook:FilterList()
_filteredList = {}
_filteredCount = 0
if _filterBy == L.KNOWN_TAB then
for i = 1, #_notesList do
local ndata = _notesList[i]
if ndata.known then
_filteredCount = _filteredCount + 1
_filteredList[_filteredCount] = i
end
end
elseif _filterBy == L.MINE_TAB then
for i = 1, #_notesList do
local ndata = _notesList[i]
if ndata.author == _playerName then
_filteredCount = _filteredCount + 1
_filteredList[_filteredCount] = i
end
end
elseif _filterBy == L.RECENT_TAB then
for i = 1, #_notesList do
local ndata = _notesList[i]
if ndata.recent then
_filteredCount = _filteredCount + 1
_filteredList[_filteredCount] = i
end
end
else
for i = 1, #_notesList do
tinsert(_filteredList, i)
end
_filteredCount = _notesCount
end
sort(_filteredList, Notebook.CompareOnTitle)
end
 
function Notebook:UpdateNotKnown(removeTitle)
-- This function looks through all the notes currently not known, and
-- determines whether they should be flagged for adding or for updating.
-- If a note that is not-known is identical (title and description) to a
-- existing known note, then the not-known note will be discarded, and the
-- recent status transfered from it to the known note instead. If the
-- removeTitle parameter is set, then any not known entries with matching
-- titles will be automatically removed (irrespective of their
-- description)
local removeList = {}
for i = 1, #_notesList do
local ndata = _notesList[i]
if not ndata.known then
if ndata.title == removeTitle then
tinsert(removeList, ndata.id)
else
local pdata = Notebook:FindByTitle(ndata.title, true)
if pdata then
if Notebook:CompareDescription(pdata.description, ndata.description) then
if ndata.recent then
pdata.recent = true
end
tinsert(removeList, ndata.id)
else
ndata.update = true
end
else
ndata.update = nil
end
end
end
end
for i = 1, #removeList do
Notebook:RemoveNoteByID(removeList[i])
end
end
 
function Notebook:ConvertToLines(text, maxLines, debug)
-- Given a text string, this function converts it into a line-formatted
-- table, suitable for sending to a target channel. The formatting
-- enforces a maximum per-line length of NOTEBOOK_MAX_NUM_LINES (with
-- word-wrapping), reduces multiple empty lines to single empty lines,
-- and enforces a maximum of maxLines in the resulting table, which is
-- then returned.
local lines = {}
local lastLine = nil
local numLines = 0
while text and text ~= "" do
local thisLine
local checkWrap
local start = strfind(text, NOTEBOOK_NEW_LINE, 1, true)
if start then
if start <= NOTEBOOK_MAX_LINE_LENGTH then
thisLine = strsub(text, 1, start - 1)
text = strsub(text, start + 1)
checkWrap = nil
else
thisLine = strsub(text, 1, NOTEBOOK_MAX_LINE_LENGTH)
if start == NOTEBOOK_MAX_LINE_LENGTH + 1 then
text = strsub(text, NOTEBOOK_MAX_LINE_LENGTH + 2)
checkWrap = nil
else
text = strsub(text, NOTEBOOK_MAX_LINE_LENGTH + 1)
checkWrap = true
end
end
else
if strlen(text) > NOTEBOOK_MAX_LINE_LENGTH then
thisLine = strsub(text, 1, NOTEBOOK_MAX_LINE_LENGTH)
text = strsub(text, NOTEBOOK_MAX_LINE_LENGTH + 1)
checkWrap = true
else
thisLine = text
text = ""
checkWrap = nil
end
end
if checkWrap then
-- Do word wrapping and also whitespace stripping from the end and
-- start of the broken line.
local thisLength = strfind(thisLine, "[%s]+[^%s]*$")
if thisLength then
text = strsub(thisLine, thisLength + 1) .. text
thisLine = strsub(thisLine, 1, thisLength - 1) .. NOTEBOOK_SEND_POSTFIX
local textStart = strfind(text, "[^%s]")
if textStart then
text = strsub(text, textStart)
end
end
else
-- Strip any whitespace from the end of the line (no need to send
-- spaces at the end of a line)
thisLine = gsub(thisLine, "(%s+)$", "")
end
if thisLine == "" then
if lastLine ~= "" then
numLines = numLines + 1
lines[numLines] = ""
end
else
numLines = numLines + 1
lines[numLines] = thisLine
end
lastLine = thisLine
if maxLines and numLines > maxLines then
-- We wait until we get numLines greater than maxLines to allow
-- for trailing "empty" lines to not show as an error.
Notebook:Debug("--> limiting number of lines to " .. maxLines)
lines[numLines] = nil
numLines = maxLines
break
end
end
-- Remove any trailing empty lines (there can only be one at most)
if lines[numLines] == "" then
lines[numLines] = nil
numLines = numLines - 1
end
return lines, numLines
end
 
function Notebook:SendNote(ndata, channel, target)
-- Formats the provided note to be sent using the indicated channel and
-- target (if needed). Note that the actual sending of all text lines
-- (apart from the title dois done via timer in OnUpdate.
if target then
Notebook:Debug("SendNote: " .. ndata.title .. ", " .. channel .. ", " .. target)
else
Notebook:Debug("SendNote: " .. ndata.title .. ", " .. channel)
end
-- Convert into lines table for sending
local lines, numLines = Notebook:ConvertToLines(ndata.description, NOTEBOOK_MAX_NUM_LINES, _debugFrame)
-- Format title string with our "secret" notebook code for any other
-- notebooks to recognize.
if channel == "BN_WHISPER" then
BNSendWhisper(target, Notebook:GenerateSignature(ndata.title, numLines))
else
SendChatMessage(Notebook:GenerateSignature(ndata.title, numLines), channel, nil, target)
end
if numLines > 0 then
_sendInProgress = true
_sendCooldownTimer = GetTime() + NOTEBOOK_SEND_LINE_COOLDOWN
_sendLines = lines
_sendChannel = channel
_sendTarget = target
NotebookFrame:SetScript("OnUpdate", Notebook.Frame_OnUpdate)
end
-- Set the recent flag (we don't have to refilter the list because this
-- entry must already be on the current one)
ndata.recent = true
-- Update the sent date
ndata.sent = date(NOTEBOOK_GETDATE_FORMAT)
-- Update the displayed list
Notebook:FilterList()
Notebook.Frame_UpdateList()
end
 
------------------------------------------------------------------------
-- Chat event parsing functions
------------------------------------------------------------------------
 
function Notebook:ProcessChatMessage(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)
-- Called for raid, party, guild, whisper, and channel events. Note that
-- system channels (e.g., General, Trade, etc.) are indicated by arg7
-- being non-zero, and are always ignored. Similarly anything sent by
-- ourselves should also be ignored.
if arg2 == _playerName or tonumber(arg7) ~= 0 then
return
end
local channel = strsub(event, 10)
if not _receiveInProgress then
local _, _, title, countString = strfind(arg1, NOTEBOOK_HEADER_PATTERN)
if title and countString then
local lineCount = strlen(countString)
if lineCount >= 1 and lineCount <= NOTEBOOK_MAX_NUM_LINES then
_receiveInProgress = true
_receiveTimer = GetTime() + (NOTEBOOK_SEND_LINE_COOLDOWN * lineCount) + NOTEBOOK_RECEIVE_TIMEOUT
_receiveSender = arg2
_receiveChannel = channel
_receiveTarget = arg8
_receiveLinesExpected = lineCount
_receiveLines = {}
_receiveTitle = title
NotebookFrame:SetScript("OnUpdate", self.Frame_OnUpdate)
end
end
elseif arg2 == _receiveSender and _receiveChannel == channel and _receiveTarget == arg8 then
if strsub(arg1, 1, 1) == NOTEBOOK_SEND_PREFIX then
tinsert(_receiveLines, strsub(arg1, 2))
if #_receiveLines == _receiveLinesExpected then
self:Debug("Received note \"" .. _receiveTitle .. "\" from " .. _receiveSender)
_receiveInProgress = nil
_receiveTimer = nil
description = ""
for i = 1, #_receiveLines do
local text = _receiveLines[i]
local len = strlen(text)
if strsub(text, len) == NOTEBOOK_SEND_POSTFIX then
description = description .. strsub(text, 1, len - 1) .. " "
else
description = description .. text .. NOTEBOOK_NEW_LINE
end
end
-- Check to see if we have this entry already
local addNote = true
for i = 1, #_notesList do
local text = _notesList[i]
if ndata.title == _receiveTitle then
if self:CompareDescription(ndata.description, description) then
-- Same note already exists, so don't add it again
ndata.recent = true
addNote = nil
break
end
end
end
if addNote then
self:Print(format(L.NOTE_RECEIVED_FORMAT, _receiveTitle, _receiveSender))
Notebook:AddNote(_receiveTitle, _receiveSender, date(NOTEBOOK_GETDATE_FORMAT), description, false, true, true)
end
Notebook:UpdateNotKnown()
Notebook:FilterList()
Notebook.Frame_UpdateList()
end
end
end
end
 
------------------------------------------------------------------------
-- Initialization functions
------------------------------------------------------------------------
 
function Notebook:ADDON_LOADED(addon)
if addon ~= NOTEBOOK then return end
NotebookFrame:UnregisterEvent("ADDON_LOADED")
 
if not NotebookState then
NotebookState = {}
end
if not NotebookState.Notes then
NotebookState.Notes = {}
_firstTimeLoad = true
end
_notesList = NotebookState.Notes
 
if IsLoggedIn() then
Notebook:PLAYER_LOGIN()
end
end
 
function Notebook:PLAYER_LOGIN()
NotebookFrame:UnregisterEvent("PLAYER_LOGIN")
 
-- Load notes
Notebook:LoadData()
if _firstTimeLoad then
Notebook:AddNote(_firstTimeNote.title, _firstTimeNote.author, _firstTimeNote.date, _firstTimeNote.description, true, false, false)
end
Notebook:FilterList()
Notebook.Frame_UpdateList()
 
-- Register for required events now
NotebookFrame:RegisterEvent("CHAT_MSG_INSTANCE_CHAT")
NotebookFrame:RegisterEvent("CHAT_MSG_RAID")
NotebookFrame:RegisterEvent("CHAT_MSG_RAID_LEADER")
NotebookFrame:RegisterEvent("CHAT_MSG_PARTY")
NotebookFrame:RegisterEvent("CHAT_MSG_PARTY_LEADER")
NotebookFrame:RegisterEvent("CHAT_MSG_GUILD")
NotebookFrame:RegisterEvent("CHAT_MSG_OFFICER")
NotebookFrame:RegisterEvent("CHAT_MSG_WHISPER")
NotebookFrame:RegisterEvent("CHAT_MSG_CHANNEL")
 
-- Register for events and hook functions
-- See the comments for the Notebook.ChatFrameEditBox_IsVisible and
-- Notebook.ChatFrameEditBox_Insert functions as to why these are disabled
-- for now.
-- if not _original_ChatFrameEditBox_IsVisible then
-- _original_ChatFrameEditBox_IsVisible = ChatFrameEditBox.IsVisible
-- ChatFrameEditBox.IsVisible = Notebook.ChatFrameEditBox_IsVisible
-- end
-- if not _original_ChatFrameEditBox_Insert then
-- _original_ChatFrameEditBox_Insert = ChatFrameEditBox.Insert
-- ChatFrameEditBox.Insert = Notebook.ChatFrameEditBox_Insert
-- end
end
 
function Notebook:PLAYER_LOGOUT()
Notebook:SaveData()
end
 
------------------------------------------------------------------------
-- NotebookFrame UI functions
------------------------------------------------------------------------
 
function Notebook.Frame_SetDescriptionText(text, known)
-- For notes that are known (known is true) we use the scrolling editbox
-- to show the text. In order to get the scrolling editbox to play nicely
-- when we reset its text contents (specifically to force the scrollbar to
-- go to the top of the text rather than the bottom) we have to jump
-- through a few hoops, which is done between this function and the
-- editbox scripts in the XML file. Basically the function here sets some
-- flags to reset the cursor position when the actual text update occurs,
-- or when a cursor update occurs (if the text didn't change), and in the
-- case where neither the text or cursor position changed, we set a
-- private variable that ScrollingEdit_OnUpdate uses (normally set by the
-- ScrollingEdit_OnCursorChanged function) and trigger an OnUpdate call.
-- The case where we are setting the editbox to the empty string has to be
-- dealt with as a special case due to the way the editbox doesn't perform
-- updates correctly if it is empty. To avoid that we set instead a
-- special character to force a text update, and set a flag to request the
-- XML script code to reset the contents back to empty (which will occur
-- after the editbox scrolling, etc., has been updated).
-- For notes that are not known (known is nil or false) we instead use the
-- scrolling textbox to display the text, which is a little simpler to
-- reset to the top of the text when needed.
-- This function also stores the id of the note being edited or displayed
-- in NotebookFrame object itself, so that this can be checked for easily
-- when changing between tabs or knowing when to start an edit.
if known then
NotebookFrame.TextScrollFrame:Hide()
NotebookFrame.EditScrollFrame:Show()
NotebookFrame.EditBox:ClearFocus()
if text == "" then
-- Set a fake string into the editbox, noting that it is important
-- that this string doesn't match what the editbox has in it
-- already (or else it won't generate a OnTextUpdate event) so we
-- use a non-visible non-enterable character simply to avoid
-- having to check the current contents.
NotebookFrame.EditBox.textResetToEmpty = true
NotebookFrame.EditBox:SetText(NOTEBOOK_SEND_PREFIX)
else
NotebookFrame.EditBox:SetText(text)
NotebookFrame.EditBox:SetCursorPosition(0)
end
NotebookFrame.EditBox.textReset = true
NotebookFrame.EditBox.cursorOffset = 0
ScrollingEdit_OnUpdate( NotebookFrame.EditBox, 0, NotebookFrame.EditBox:GetParent() )
else
NotebookFrame.EditBox:ClearFocus()
NotebookFrame.EditScrollFrame:Hide()
NotebookFrame.TextScrollFrame:Show()
NotebookFrame.TextBox:SetText(text)
NotebookFrame.TextScrollFrame.ScrollBar:SetValue(0)
NotebookFrame.TextScrollFrame:UpdateScrollChildRect()
end
end
 
function Notebook.Frame_SetCanSendCheckbox(enable, send)
-- Sets whether the Can-send checkbox is enabled or not, and if enabled,
-- whether it should be checked or not
if enable then
NotebookFrame.CanSendCheckButton:SetChecked(send)
NotebookFrame.CanSendCheckButton:Enable()
NotebookFrame.CanSendCheckButton.Text:SetTextColor(_colorTextEnabled.r, _colorTextEnabled.g, _colorTextEnabled.b)
if GameTooltip:IsOwned(NotebookFrame.CanSendCheckButton) then
if send then
GameTooltip:SetText(NotebookFrame.CanSendCheckButton.tooltipOnText)
else
GameTooltip:SetText(NotebookFrame.CanSendCheckButton.tooltipOffText)
end
end
else
NotebookFrame.CanSendCheckButton:SetChecked(nil)
NotebookFrame.CanSendCheckButton:Disable()
NotebookFrame.CanSendCheckButton.Text:SetTextColor(_colorTextDisabled.r, _colorTextDisabled.g, _colorTextDisabled.b)
end
end
 
function Notebook.Frame_UpdateButtons(editing, known, update)
-- Sets the status of the Add, Save, Cancel, Update buttons as required
-- based on whether the current entry is known, being edited, etc.
if editing then
NotebookFrame.SaveButton:Enable()
NotebookFrame.SaveButton:SetScript("OnClick", Notebook.Frame_SaveButtonOnClick)
NotebookFrame.SaveButton:SetText(L.SAVE_BUTTON)
NotebookFrame.SaveButton.tooltipText = L.SAVE_BUTTON_TOOLTIP
NotebookFrame.SaveButton.newbieText = L.SAVE_BUTTON_TOOLTIP
NotebookFrame.CancelButton:Enable()
elseif known then
NotebookFrame.SaveButton:Disable()
NotebookFrame.SaveButton:SetScript("OnClick", Notebook.Frame_SaveButtonOnClick)
NotebookFrame.SaveButton:SetText(L.SAVE_BUTTON)
NotebookFrame.SaveButton.tooltipText = L.SAVE_BUTTON_TOOLTIP
NotebookFrame.SaveButton.newbieText = L.SAVE_BUTTON_TOOLTIP
NotebookFrame.CancelButton:Disable()
elseif update then
NotebookFrame.SaveButton:Enable()
NotebookFrame.SaveButton:SetScript("OnClick", Notebook.Frame_UpdateButtonOnClick)
NotebookFrame.SaveButton:SetText(L.UPDATE_BUTTON)
NotebookFrame.SaveButton.tooltipText = L.UPDATE_BUTTON_TOOLTIP
NotebookFrame.SaveButton.newbieText = L.UPDATE_BUTTON_TOOLTIP
NotebookFrame.CancelButton:Disable()
else
NotebookFrame.SaveButton:Enable()
NotebookFrame.SaveButton:SetScript("OnClick", Notebook.Frame_AddButtonOnClick)
NotebookFrame.SaveButton:SetText(L.ADD_BUTTON)
NotebookFrame.SaveButton.tooltipText = L.ADD_BUTTON_TOOLTIP
NotebookFrame.SaveButton.newbieText = L.ADD_BUTTON_TOOLTIP
NotebookFrame.CancelButton:Disable()
end
end
 
function Notebook.Frame_OnLoad(self)
-- Set the Can-send check button initial state
Notebook.Frame_SetCanSendCheckbox()
 
-- Set the text colors of the editbox and textbox
NotebookFrame.EditBox:SetTextColor(_colorKnown.r, _colorKnown.g, _colorKnown.b)
NotebookFrame.TextBox:SetTextColor(_colorNotKnown.r, _colorNotKnown.g, _colorNotKnown.b)
end
 
function Notebook.Frame_UpdateList(self, offset, autoScroll)
-- Updates the displayed list of notes in the NotebookListFrame. If the
-- offset parameter is specified then it is used as the new offset
-- (adjusted for the actual size of the list). If autoScroll is true
-- then the offset is automatically adjusted to show the currently
-- selected entry (if available).
if not NotebookFrame:IsShown() then
return
end
local currentOffset = FauxScrollFrame_GetOffset(NotebookFrame.ListScrollFrame)
if not offset then
offset = currentOffset
end
if (offset + NOTEBOOK_LIST_BUTTON_COUNT) > _filteredCount then
offset = _filteredCount - NOTEBOOK_LIST_BUTTON_COUNT
if offset < 0 then
offset = 0
end
end
if autoScroll and NotebookFrame.selectedID then
local index
for i = 1, _filteredCount do
local ndata = _notesList[_filteredList[i]]
if ndata.id == NotebookFrame.selectedID then
index = i
break
end
end
if index then
local newOffset = offset
if (offset + NOTEBOOK_LIST_BUTTON_COUNT) < index then
offset = index - NOTEBOOK_LIST_BUTTON_COUNT
elseif index < offset then
offset = index - 1
end
end
end
if offset ~= currentOffset then
FauxScrollFrame_SetOffset(NotebookFrame.ListScrollFrame, offset)
NotebookFrame.ListScrollBar:SetValue(offset * NOTEBOOK_LIST_BUTTON_HEIGHT)
end
 
-- Update buttons
NotebookFrame.selectedButton = nil
for i = 1, NOTEBOOK_LIST_BUTTON_COUNT do
local button = NotebookFrame.ListButtons[i]
local index = i + offset
if index <= _filteredCount then
local titleText = button.TitleText
local titleHighlight = button.TitleHighlight
local filteredIndex = _filteredList[index]
local ndata = _notesList[filteredIndex]
button.nindex = filteredIndex
if ndata.saved or (NotebookFrame.editing and NotebookFrame.selectedID == ndata.id) then
titleText:SetText(ndata.title .. L.TITLE_CHANGE_NOT_SAVED)
else
titleText:SetText(ndata.title)
end
if ndata.known then
titleText:SetTextColor(_colorKnown.r, _colorKnown.g, _colorKnown.b)
titleHighlight:SetVertexColor(_colorKnown.r, _colorKnown.g, _colorKnown.b, _colorKnown.a)
else
titleText:SetTextColor(_colorNotKnown.r, _colorNotKnown.g, _colorNotKnown.b)
titleHighlight:SetVertexColor(_colorNotKnown.r, _colorNotKnown.g, _colorNotKnown.b, _colorNotKnown.a)
end
if NotebookFrame.selectedID == ndata.id then
NotebookFrame.selectedButton = button
button:LockHighlight()
else
button:UnlockHighlight()
end
 
local tooltipText
if ndata.known then
if ndata.author == _playerName then
tooltipText = format(L.DETAILS_DATE_KNOWN_SAVED_FORMAT, Notebook:GetDateText(ndata.date))
else
tooltipText = format(L.DETAILS_DATE_KNOWN_UPDATED_FORMAT, Notebook:GetDateText(ndata.date), ndata.author)
end
else
tooltipText = format(L.DETAILS_DATE_UNSAVED_FORMAT, Notebook:GetDateText(ndata.date), ndata.author)
end
if ndata.sent then
tooltipText = tooltipText .. "\n" .. format(L.DETAILS_SENT_FORMAT, Notebook:GetDateText(ndata.sent))
end
if not ndata.known then
tooltipText = tooltipText .. "\n" .. L.DETAILS_NOT_KNOWN_TEXT
end
tooltipText = tooltipText .. "\n" .. format(L.DETAILS_SIZE_FORMAT, strlen(ndata.description))
button.tooltipText = tooltipText
if GameTooltip:IsOwned(button) then
GameTooltip:SetText(button.tooltipText, 1, 1, 1)
end
 
button:Show()
else
button.nindex = nil
button:Hide()
end
end
 
-- Update scrollbar
FauxScrollFrame_Update(NotebookFrame.ListScrollFrame, _filteredCount, NOTEBOOK_LIST_BUTTON_COUNT, NOTEBOOK_LIST_BUTTON_HEIGHT)
end
 
function Notebook.Frame_ListButtonOnClick(self, clicked)
-- On either a left or right mouse button click we switch focus to the
-- indicated note (which will discard any unsaved changes in the previous
-- note). This means we don't have to worry about indicating which note
-- we are referring to in the drop-down menu (with note titles able to be
-- quite long, this can cause a problem).
 
-- Close any open drop-down menus (do this even on a left-click)
CloseDropDownMenus()
 
-- If we are changing focus to a different note, check if we were editing
-- the previous entry and save its contents if needed. Then set the new
-- text and set the button and editing status flags before updating the
-- list to show the current status.
local ndata = _notesList[self.nindex]
if NotebookFrame.selectedID ~= ndata.id then
if NotebookFrame.editing then
local pdata = Notebook:FindNoteByID(NotebookFrame.selectedID)
if pdata then
local text = NotebookFrame.EditBox:GetText()
if text ~= pdata.description then
pdata.saved = text
else
pdata.saved = nil
end
end
end
if ndata.saved then
Notebook.Frame_SetDescriptionText(ndata.saved, ndata.known)
NotebookFrame.editing = true
else
Notebook.Frame_SetDescriptionText(ndata.description, ndata.known)
NotebookFrame.editing = nil
end
Notebook.Frame_UpdateButtons(NotebookFrame.editing, ndata.known, ndata.update)
Notebook.Frame_SetCanSendCheckbox(true, ndata.send)
NotebookFrame.selectedID = ndata.id
Notebook.Frame_UpdateList()
end
if clicked == "RightButton" then
NotebookFrame.EditBox:ClearFocus()
NotebookDropDown.name = ndata.title
NotebookDropDown.noteIndex = self.nindex
NotebookDropDown.initialize = Notebook.Frame_DropdownInitialize
NotebookDropDown.displayMode = "MENU"
-- Calculate position of drop-down menu here manually based on the
-- cursor position so that OnUpdate can reuse it. This is effectively
-- the same as ToggleDropDownMenu(1, nil, NotebookDropDown, "cursor")
local cursorX, cursorY = GetCursorPosition()
local uiScale = UIParent:GetScale()
NotebookDropDown.offsetX = cursorX/uiScale
NotebookDropDown.offsetY = cursorY/uiScale
ToggleDropDownMenu(1, nil, NotebookDropDown, "UIParent", NotebookDropDown.offsetX, NotebookDropDown.offsetY)
end
end
 
function Notebook.Frame_DropdownInitialize(self)
-- Called by the UI dropdown code when building the dropdown menu, it sets
-- the UIDROPDOWNMENU_MENU_LEVEL (1 to N) and UIDROPDOWNMENU_MENU_VALUE
-- (set to passed text string) fields as needed for the various menus and
-- sub-menus
local info = UIDropDownMenu_CreateInfo()
local ndata = _notesList[NotebookDropDown.noteIndex]
local channelList = { GetChannelList() }
 
if UIDROPDOWNMENU_MENU_LEVEL == 1 then
-- Send options sub-menu. This is disabled when the note has been
-- edited but not saved, we are in send cooldown, or the note is not
-- flagged for sending.
info.text = L.SEND_OPTION
info.notCheckable = 1
info.keepShownOnClick = 1
if NotebookFrame.editing or _sendCooldownTimer or not ndata.send then
info.disabled = 1
info.hasArrow = nil
else
info.hasArrow = 1
end
UIDropDownMenu_AddButton(info)
 
-- Save/Add/Update option.
info.disabled = nil
info.hasArrow = nil
if ndata.known then
info.text = L.SAVE_OPTION
info.value = L.SAVE_OPTION
if not NotebookFrame.editing then
info.disabled = 1
end
elseif ndata.update then
info.text = L.UPDATE_OPTION
info.value = L.UPDATE_OPTION
else
info.text = L.ADD_OPTION
info.value = L.ADD_OPTION
end
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info)
 
-- Rename option
info.disabled = nil
info.text = L.RENAME_OPTION
info.value = L.RENAME_OPTION
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info)
 
-- Delete option
info.text = L.DELETE_OPTION
info.value = L.DELETE_OPTION
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info)
 
-- Cancel option
info.text = CANCEL
info.value = CANCEL
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info)
 
elseif UIDROPDOWNMENU_MENU_LEVEL == 2 then
if UIDROPDOWNMENU_MENU_VALUE == L.SEND_OPTION then
info = UIDropDownMenu_CreateInfo()
info.notCheckable = 1
info.func = Notebook.Frame_DropdownSelect
 
-- Send to specified player
info.text = L.SEND_TO_PLAYER
info.value = L.SEND_TO_PLAYER
info.colorCode = format( "\124cff%02x%02x%02x", ChatTypeInfo["WHISPER"].r * 255, ChatTypeInfo["WHISPER"].g * 255, ChatTypeInfo["WHISPER"].b * 255 )
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
 
if UnitCanCooperate("player", "target") then
-- Send to target
info.text = L.SEND_TO_TARGET
info.value = L.SEND_TO_TARGET
info.colorCode = format( "\124cff%02x%02x%02x", ChatTypeInfo["WHISPER"].r * 255, ChatTypeInfo["WHISPER"].g * 255, ChatTypeInfo["WHISPER"].b * 255 )
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
 
if IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
-- Send to instance
info.text = L.SEND_TO_INSTANCE
info.value = L.SEND_TO_INSTANCE
info.colorCode = format( "\124cff%02x%02x%02x", ChatTypeInfo["INSTANCE_CHAT"].r * 255, ChatTypeInfo["INSTANCE_CHAT"].g * 255, ChatTypeInfo["INSTANCE_CHAT"].b * 255 )
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
 
if IsInRaid() or IsInGroup(LE_PARTY_CATEGORY_HOME) then
-- Send to party
info.text = L.SEND_TO_PARTY
info.value = L.SEND_TO_PARTY
info.colorCode = format( "\124cff%02x%02x%02x", ChatTypeInfo["PARTY"].r * 255, ChatTypeInfo["PARTY"].g * 255, ChatTypeInfo["PARTY"].b * 255 )
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
 
if IsInRaid() and (UnitIsGroupLeader("player") and UnitIsGroupAssistant("player")) then
-- Send to raid (only if you are leader or officer)
info.text = L.SEND_TO_RAID
info.value = L.SEND_TO_RAID
info.colorCode = format( "\124cff%02x%02x%02x", ChatTypeInfo["RAID"].r * 255, ChatTypeInfo["RAID"].g * 255, ChatTypeInfo["RAID"].b * 255 )
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
 
if IsInGuild() then
local _, _, rank = GetGuildInfo("player")
GuildControlSetRank(1 + rank)
local _, guildSpeak, _, officerSpeak = GuildControlGetRankFlags()
 
if guildSpeak then
-- Send to guild
info.text = L.SEND_TO_GUILD
info.value = L.SEND_TO_GUILD
info.colorCode = format( "\124cff%02x%02x%02x", ChatTypeInfo["GUILD"].r * 255, ChatTypeInfo["GUILD"].g * 255, ChatTypeInfo["GUILD"].b * 255 )
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
 
if officerSpeak then
-- Send to officer
info.text = L.SEND_TO_OFFICER
info.value = L.SEND_TO_OFFICER
info.colorCode = format( "\124cff%02x%02x%02x", ChatTypeInfo["OFFICER"].r * 255, ChatTypeInfo["OFFICER"].g * 255, ChatTypeInfo["OFFICER"].b * 255 )
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
end
 
if #channelList > 0 or BNGetConversationInfo(1) then
-- Send to channel
info.text = L.SEND_TO_CHANNEL
info.value = L.SEND_TO_CHANNEL
info.colorCode = nil
info.func = nil
info.hasArrow = 1
info.keepShownOnClick = 1
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
end
 
elseif UIDROPDOWNMENU_MENU_LEVEL == 3 then
if UIDROPDOWNMENU_MENU_VALUE == L.SEND_TO_CHANNEL then
for i = 1, #channelList, 2 do
local channelNum = channelList[i]
local channelName = channelList[i + 1]
local displayNum = channelNum
if Chatmanager and Chatmanager.GetChannelInfo then
displayNum = Chatmanager.GetChannelInfo(channelNum)
end
local color = ChatTypeInfo["CHANNEL" .. channelNum]
info.text = format(L.CHANNEL_NAME_FORMAT, displayNum, channelName)
info.value = format(NOTEBOOK_CHANNEL_VALUE_FORMAT, L.SEND_TO_CHANNEL, channelNum, channelName)
info.colorCode = format("|cff%02x%02x%02x", 255*color.r, 255*color.g, 255*color.b)
info.notCheckable = 1
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
for i = 1, BNGetMaxNumConversations() do
if BNGetConversationInfo(i) == "conversation" then
local color = ChatTypeInfo["BN_CONVERSATION"]
info.text = format(CONVERSATION_NAME, i + MAX_WOW_CHAT_CHANNELS)
info.value = format(NOTEBOOK_CHANNEL_VALUE_FORMAT, L.SEND_TO_CHANNEL, i, "BN_CONVERSATION")
info.colorCode = format("|cff%02x%02x%02x", 255*color.r, 255*color.g, 255*color.b)
info.notCheckable = 1
info.func = Notebook.Frame_DropdownSelect
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
end
end
end
end
end
 
function Notebook.Frame_SaveButtonOnClick(self, ndata)
-- Saves the current changes in the editBox to the indicated (or current)
-- note entry.
CloseDropDownMenus()
if NotebookFrame.editing then
if type(ndata) ~= "table" then
ndata = Notebook:FindNoteByID(NotebookFrame.selectedID)
end
if ndata then
Notebook:UpdateDescription(ndata, NotebookFrame.EditBox:GetText())
NotebookFrame.editing = nil
ndata.known = true
ndata.saved = nil
Notebook:UpdateNotKnown()
Notebook:FilterList()
Notebook.Frame_UpdateList()
Notebook.Frame_UpdateButtons(nil, true)
end
end
end
 
function Notebook.Frame_AddButtonOnClick(self, ndata)
-- Adds the indicated (or current) note to the known list.
CloseDropDownMenus()
if not NotebookFrame.editing then
if type(ndata) ~= "table" then
ndata = Notebook:FindNoteByID(NotebookFrame.selectedID)
end
if ndata then
ndata.known = true
Notebook.Frame_SetDescriptionText(ndata.description, ndata.known)
Notebook:UpdateNotKnown(ndata.title)
Notebook:FilterList()
Notebook.Frame_UpdateList()
Notebook.Frame_UpdateButtons(nil, true)
end
end
end
 
function Notebook.Frame_UpdateButtonOnClick(self, ndata)
-- Launches the NOTEBOOK_UPDATE_CONFIRM dialog to prompt user about
-- updating an existing note.
CloseDropDownMenus()
if type(ndata) ~= "table" then
ndata = Notebook:FindNoteByID(NotebookFrame.selectedID)
end
if ndata then
local dialogFrame = StaticPopup_Show("NOTEBOOK_UPDATE_CONFIRM", ndata.title, ndata.author)
if dialogFrame then
dialogFrame.data = ndata.id
end
end
end
 
function Notebook.Frame_CancelButtonOnClick(self)
-- Restore the last saved contents of the current note
CloseDropDownMenus()
if NotebookFrame.editing then
local ndata = Notebook:FindNoteByID(NotebookFrame.selectedID)
if ndata then
Notebook.Frame_SetDescriptionText(ndata.description, ndata.known)
NotebookFrame.editing = nil
ndata.saved = nil
Notebook.Frame_UpdateList()
Notebook.Frame_UpdateButtons(nil, true)
end
end
end
 
function Notebook.Frame_NewButtonOnClick(self)
-- Launches the NOTEBOOK_NEW_TITLE dialog to prompt user to enter a new
-- note title
CloseDropDownMenus()
_currentTitle = ""
local dialogFrame = StaticPopup_Show("NOTEBOOK_NEW_TITLE")
if dialogFrame then
dialogFrame.data = nil
dialogFrame:SetWidth(420)
end
end
 
function Notebook.Frame_TabButtonOnClick(id)
-- Called when a tab button is selected, this function switches which set
-- of filtered list items is show, and switches between the two tab's
-- selected items, adjusting scrollbar positions, etc., as needed. This
-- tab switching code uses the following variables within the
-- NotebookFrame object:
-- lastSelectedID = last good selectedID value, used for returning to a
-- tab without selecting a new item on the other tab
-- lastKnownOffset = last offset of Known tab scrollbar
-- lastRecentOffset = last offset of Recent tab scrollbar
CloseDropDownMenus()
local filterMode = _filterBy
local showText = nil
local scrollOffset = nil
local ndata = Notebook:FindNoteByID(NotebookFrame.selectedID)
if ndata then
NotebookFrame.lastSelectedID = NotebookFrame.selectedID
else
ndata = Notebook:FindNoteByID(NotebookFrame.lastSelectedID)
end
 
if id == 1 and _filterBy ~= L.ALL_TAB then
PanelTemplates_DeselectTab(NotebookFrame.FilterTab2)
PanelTemplates_DeselectTab(NotebookFrame.FilterTab3)
PanelTemplates_SelectTab(NotebookFrame.FilterTab1)
filterMode = L.ALL_TAB
if ndata then
showText = true
end
scrollOffset = NotebookFrame.lastKnownOffset
NotebookFrame.lastRecentOffset = FauxScrollFrame_GetOffset(NotebookFrame.ListScrollFrame)
elseif id == 2 and _filterBy ~= L.MINE_TAB then
PanelTemplates_DeselectTab(NotebookFrame.FilterTab1)
PanelTemplates_DeselectTab(NotebookFrame.FilterTab3)
PanelTemplates_SelectTab(NotebookFrame.FilterTab2)
filterMode = L.MINE_TAB
if ndata and (ndata.author == _playerName) then
showText = true
end
scrollOffset = NotebookFrame.lastRecentOffset
NotebookFrame.lastKnownOffset = FauxScrollFrame_GetOffset(NotebookFrame.ListScrollFrame)
elseif id == 3 and _filterBy ~= L.RECENT_TAB then
PanelTemplates_DeselectTab(NotebookFrame.FilterTab1)
PanelTemplates_DeselectTab(NotebookFrame.FilterTab2)
PanelTemplates_SelectTab(NotebookFrame.FilterTab3)
filterMode = L.RECENT_TAB
if ndata and ndata.recent then
showText = true
end
scrollOffset = NotebookFrame.lastRecentOffset
NotebookFrame.lastKnownOffset = FauxScrollFrame_GetOffset(NotebookFrame.ListScrollFrame)
end
if _filterBy ~= filterMode then
if showText then
if NotebookFrame.selectedID ~= ndata.id then
if NotebookFrame.editing then
local pdata = Notebook:FindNoteByID(NotebookFrame.selectedID)
if pdata then
local text = NotebookFrame.EditBox:GetText()
if text ~= pdata.description then
pdata.saved = text
else
pdata.saved = nil
end
end
end
if ndata.saved then
Notebook.Frame_SetDescriptionText(ndata.saved, ndata.known)
NotebookFrame.editing = true
else
Notebook.Frame_SetDescriptionText(ndata.description, ndata.known)
NotebookFrame.editing = nil
end
Notebook.Frame_UpdateButtons(NotebookFrame.editing, ndata.known, ndata.update)
Notebook.Frame_SetCanSendCheckbox(true, ndata.send)
NotebookFrame.selectedID = ndata.id
end
else
if NotebookFrame.editing then
local pdata = Notebook:FindNoteByID(NotebookFrame.selectedID)
if pdata then
local text = NotebookFrame.EditBox:GetText()
if text ~= pdata.description then
pdata.saved = text
else
pdata.saved = nil
end
end
end
if NotebookFrame.selectedID then
Notebook.Frame_SetDescriptionText("")
NotebookFrame.editing = nil
Notebook.Frame_UpdateButtons(nil, true)
Notebook.Frame_SetCanSendCheckbox()
NotebookFrame.selectedID = nil
end
end
_filterBy = filterMode
Notebook:FilterList()
Notebook.Frame_UpdateList(nil, scrollOffset, true)
end
end
 
function Notebook.Frame_OnUpdate(self)
-- This function handles sending of messages (to limit send speed) and
-- cooldown and receive timing.
local time = GetTime()
if _sendInProgress then
if time > _sendCooldownTimer then
local thisLine = _sendLines[1]
if thisLine then
-- Prefix each line with something to assist in identifying it
-- on the receiving end and to make empty lines get sent.
if _sendChannel == "BN_WHISPER" then
BNSendWhisper(_sendTarget, NOTEBOOK_SEND_PREFIX .. thisLine)
else
SendChatMessage(NOTEBOOK_SEND_PREFIX .. thisLine, _sendChannel, nil, _sendTarget)
end
end
tremove(_sendLines, 1)
if #_sendLines > 0 then
-- More lines to send, set the timer for the next line
_sendCooldownTimer = time + NOTEBOOK_SEND_LINE_COOLDOWN
else
-- All lines sent, set cooldown timer
_sendInProgress = nil
_sendCooldownTimer = time + NOTEBOOK_SEND_FINISHED_COOLDOWN
end
end
elseif _sendCooldownTimer then
if time > _sendCooldownTimer then
_sendCooldownTimer = nil
-- If the UI dropdown list is already shown (i.e., the global
-- DropDownList1 frame is visible then refresh it so that it can
-- show the Send option again.
if DropDownList1:IsVisible() then
CloseDropDownMenus()
ToggleDropDownMenu(1, nil, NotebookDropDown, "UIParent", NotebookDropDown.offsetX, NotebookDropDown.offsetY)
end
end
end
if _receiveTimer then
if time > _receiveTimer then
_receiveInProgress = nil
_receiveTimer = nil
end
end
if not _sendInProgress and not _sendCooldownTimer and not _receiveTimer then
NotebookFrame:SetScript("OnUpdate", nil)
end
end
 
function Notebook.Frame_DropdownSelect(self)
-- Handles each of the options selected in the drop-down menu
CloseDropDownMenus()
local ndata = _notesList[NotebookDropDown.noteIndex]
if not ndata then
return
end
 
if self.value == CANCEL then
-- Dummy action for cancel just to close the drop down menus
 
elseif self.value == L.SAVE_OPTION then
-- Save the current description
Notebook.Frame_SaveButtonOnClick(ndata)
 
elseif self.value == L.UPDATE_OPTION then
-- Update the corresponding note with this one
Notebook.Frame_UpdateButtonOnClick(ndata)
 
elseif self.value == L.ADD_OPTION then
-- Add the current note
Notebook.Frame_AddButtonOnClick(self, ndata)
 
elseif self.value == L.RENAME_OPTION then
-- Set current title so that it will be set in the dialog box
_currentTitle = ndata.title
local dialogFrame = StaticPopup_Show("NOTEBOOK_NEW_TITLE")
if dialogFrame then
dialogFrame.data = ndata.id
dialogFrame:SetWidth(420)
end
 
elseif self.value == L.DELETE_OPTION then
-- If its a known entry, prompt for confirmation, otherwise just
-- remove it
if ndata.known then
local dialogFrame = StaticPopup_Show("NOTEBOOK_REMOVE_CONFIRM", ndata.title)
if dialogFrame then
dialogFrame.data = ndata.id
end
else
Notebook:RemoveNoteByID(ndata.id)
Notebook:UpdateNotKnown()
NotebookFrame.selectedID = nil
Notebook.Frame_SetDescriptionText("")
NotebookFrame.editing = nil
Notebook.Frame_UpdateButtons(nil, true)
Notebook.Frame_SetCanSendCheckbox()
Notebook:FilterList()
Notebook.Frame_UpdateList()
end
 
elseif self.value == L.SEND_TO_INSTANCE then
Notebook:SendNote(ndata, "INSTANCE_CHAT")
 
elseif self.value == L.SEND_TO_RAID then
Notebook:SendNote(ndata, "RAID")
 
elseif self.value == L.SEND_TO_PARTY then
Notebook:SendNote(ndata, "PARTY")
 
elseif self.value == L.SEND_TO_GUILD then
Notebook:SendNote(ndata, "GUILD")
 
elseif self.value == L.SEND_TO_OFFICER then
Notebook:SendNote(ndata, "OFFICER")
 
elseif self.value == L.SEND_TO_TARGET then
local target = GetUnitName("target", true)
if target then
Notebook:SendNote(ndata, "WHISPER", target)
end
 
elseif self.value == L.SEND_TO_PLAYER then
local dialogFrame = StaticPopup_Show("NOTEBOOK_SEND_TO_PLAYER")
if dialogFrame then
dialogFrame.data = ndata.id
end
 
else
local _, _, option, channelNum, channelName = strfind(self.value, NOTEBOOK_CHANNEL_VALUE_FIND)
if option == L.SEND_TO_CHANNEL then
if channelName == "BN_CONVERSATION" then
return Notebook:SendNote(ndata, "BN_CONVERSATION", channelNum)
end
 
local serverList = { EnumerateServerChannels() }
local isServerChannel
for index = 1, #serverList do
if serverList[index] == channelName then
isServerChannel = true
break
end
end
if isServerChannel then
local dialogFrame = StaticPopup_Show("NOTEBOOK_SERVER_CONFIRM", ndata.title, channelName)
if dialogFrame then
dialogFrame.data = {}
dialogFrame.data.id = ndata.id
dialogFrame.data.channelNum = channelNum
end
else
Notebook:SendNote(ndata, "CHANNEL", tonumber(channelNum))
end
end
end
end
 
function Notebook.Frame_TextChanged(self)
-- Called when the text in the description edit box changes
if not NotebookFrame.editing and self.hasFocus and NotebookFrame.selectedID then
-- We are now editing this note, which means we enable the save and
-- cancel buttons. Note that we don't need to update the filter list
-- here because if the note wasn't already on the list then it
-- wouldn't have been editable.
local ndata = Notebook:FindNoteByID(NotebookFrame.selectedID)
if ndata then
-- First work around the timing of setting focus and getting the
-- text changed notification by seeing if the description is ""
-- when the editBox text contents is empty.
if ndata.description ~= "" or self:GetNumLetters() ~= 0 then
NotebookFrame.editing = true
Notebook.Frame_UpdateButtons(true, true)
Notebook.Frame_UpdateList()
end
end
end
end
 
function Notebook.Frame_OnVerticalScroll(self, arg1)
-- Under some circumstances, when the OnVerticalScroll handler calls the
-- scrollbar:SetValue function, the scrollbar calls back into the
-- OnVerticalScroll handler itself, although in this nexted call arg1 is
-- set to nil and does not call itself further. As a result though, the
-- default implementation of the OnVerticalScroll handler in
-- UIPanelTemplates.lua will sometimes enable the scroll arrow buttons
-- when it shouldn't. This code below works around this by getting the
-- current scrollbar value after passing it arg1 (so arg1 is thereafter
-- ignored). It also accommodates rounding errors in the min/max
-- positions for robustness. Note that for some reason we cannot use
-- greater and less than comparisons in the script in the XML file itself,
-- which is why this is in its own function here.
local scrollbar = self.ScrollBar
scrollbar:SetValue(arg1)
local min, max = scrollbar:GetMinMaxValues()
local scroll = scrollbar:GetValue()
if scroll < (min + 0.1) then
scrollbar.ScrollUpButton:Disable()
else
scrollbar.ScrollUpButton:Enable()
end
if scroll > (max - 0.1) then
scrollbar.ScrollDownButton:Disable()
else
scrollbar.ScrollDownButton:Enable()
end
end
 
------------------------------------------------------------------------
-- Popup support functions
------------------------------------------------------------------------
 
function Notebook:GetPopupData(type)
if type == "PLAYER" then
if _lastPlayer then
return _lastPlayer
end
elseif type == "TITLE" then
if _currentTitle then
return _currentTitle
end
end
return ""
end
 
function Notebook:HandlePopupInput(type, data, text)
if text then
text = strtrim(text)
end
 
if type == "PLAYER" then
-- Dialog for accepting player name
text = gsub("%s", "") -- remove spaces
if text ~= "" then
local ndata = Notebook:FindNoteByID(data)
if ndata then
local presenceID = GetAutoCompletePresenceID(text)
--print("HandlePopupAccept", type, text, presenceID)
if presenceID then
_lastPlayer = presenceID
Notebook:SendNote(ndata, "BN_WHISPER", presenceID)
elseif text and text ~= "" then
_lastPlayer = text
Notebook:SendNote(ndata, "WHISPER", text)
end
end
end
elseif type == "TITLE" then
-- Dialog for accepting new title name. If the data parameter is not
-- nil then we are changing the name of an existing note, otherwise we
-- are doing the "New" dialog with a new note.
if text ~= "" then
if data then
-- Rename of note
local ndata = Notebook:FindNoteByID(data)
if ndata and (text ~= ndata.title) then
if not Notebook:FindByTitle(text) then
Notebook:Rename(ndata, text)
Notebook:UpdateNotKnown()
Notebook.Frame_UpdateButtons(NotebookFrame.editing, ndata.known, ndata.update)
Notebook:FilterList()
Notebook.Frame_UpdateList()
else
Notebook:Error(format(L.ERR_RENAME_NOT_UNIQUE_FORMAT, text))
end
end
else
-- Add a new (empty) note
if not Notebook:FindByTitle(text, true) then
local ndata = Notebook:AddNote(text, _playerName, date(NOTEBOOK_GETDATE_FORMAT), "", true, _addSavedToRecent, false)
NotebookFrame.selectedID = ndata.id
Notebook:FilterList()
Notebook.Frame_UpdateList(nil, nil, true)
NotebookFrame.editing = nil
Notebook.Frame_UpdateButtons(nil, true)
Notebook.Frame_SetCanSendCheckbox(true, ndata.send)
Notebook.Frame_SetDescriptionText(ndata.description, ndata.known)
NotebookFrame.EditBox:SetFocus()
else
Notebook:Error(format(L.ERR_RENAME_NOT_UNIQUE_FORMAT, text))
end
end
else
Notebook:Error(L.ERR_RENAME_EMPTY)
end
elseif type == "CONFIRM" then
local ndata = Notebook:FindNoteByID(data)
if ndata then
Notebook:RemoveNoteByID(ndata.id)
Notebook:UpdateNotKnown()
NotebookFrame.selectedID = nil
Notebook.Frame_SetDescriptionText("")
NotebookFrame.editing = nil
Notebook.Frame_UpdateButtons(nil, true)
Notebook.Frame_SetCanSendCheckbox()
Notebook:FilterList()
Notebook.Frame_UpdateList()
end
elseif type == "UPDATE" then
local ndata = Notebook:FindNoteByID(data)
if ndata then
local pdata = Notebook:FindByTitle(ndata.title, true)
if pdata then
-- Update description and author, but not send flag
Notebook:UpdateDescription(pdata, ndata.description)
pdata.author = ndata.author
pdata.saved = nil
pdata.recent = true
Notebook:UpdateNotKnown(pdata.title)
NotebookFrame.selectedID = pdata.id
Notebook.Frame_SetDescriptionText(pdata.description, true)
NotebookFrame.editing = nil
Notebook.Frame_UpdateButtons(nil, true)
Notebook.Frame_SetCanSendCheckbox(true, pdata.send)
Notebook:FilterList()
Notebook.Frame_UpdateList()
end
end
elseif type == "SERVER" then
if data then
local ndata = Notebook:FindNoteByID(data.id)
if ndata then
Notebook:SendNote(ndata, "CHANNEL", tonumber(data.channelNum))
end
end
end
end
 
------------------------------------------------------------------------
-- Hooked functions
--
-- These functions were intended to allow pasting of item links into Notes.
-- However the EditBox doesn't generate the OnHyperLinkClick event (in fact
-- only the ScrollingMessageFrame appears to do this) which means that once an
-- item was pasted into a Note, it can't easily be displayed through the usual
-- methods (we could add code to determine the location of the link in the
-- frame on a mouse event using a font object with SetText and GetStringWidth
-- for the location parsing, since SetText updates GetStringWidth immediately
-- unlike actions on an EditBox) but that'd be a lot of work. We'd also need
-- to make sure that the line wrapping code in Notebook.ConvertToLines would
-- never break a hyperlink when doing its wrap calculations, since doing so
-- results in an unrecoverable error in SendChatMessage (have to do a reload
-- to escape out of it). So for now these functions remain here, but unused.
-- See Notebook.Register for their initialization.
------------------------------------------------------------------------
 
function Notebook.ChatFrameEditBox_IsVisible(self)
-- Hooked version of ChatFrameEditBox:IsVisible that (in conjunction with
-- the hooked ChatFrameEditBox:Insert) allows us to get item links into
-- Notebook instead of always into the ChatFrameEditBox. Because the
-- :IsVisible call is not always associated with :Insert of a link, we
-- give the original :IsVisible check priority over Notebook having focus.
if _original_ChatFrameEditBox_IsVisible(self) then
return true
elseif IsShiftKeyDown() and NotebookFrame.EditBox:IsVisible() and NotebookFrame.EditBox.hasFocus then
return true
end
return false
end
 
function Notebook.ChatFrameEditBox_Insert(self, text)
-- Hooked version of ChatFrameEditBox:Insert that allows us to get item
-- links into Notebook instead of always into the ChatFrameEditBox.
if IsShiftKeyDown() and NotebookFrame.EditBox:IsVisible() and NotebookFrame.EditBox.hasFocus then
NotebookFrame.EditBox:Insert(text)
else
_original_ChatFrameEditBox_Insert(self, text)
end
end
 
------------------------------------------------------------------------
-- OnEvent handler
------------------------------------------------------------------------
 
function Notebook.OnEvent(self, event, ...)
return Notebook[event] and Notebook[event](Notebook, ...) or Notebook:ProcessChatMessage(event, ...)
end
 
------------------------------------------------------------------------
-- OnLoad function
------------------------------------------------------------------------
 
function Notebook.OnLoad(self)
-- Record our frame pointer for later
NotebookFrame = self
 
-- Register for player events
NotebookFrame:RegisterEvent("ADDON_LOADED")
NotebookFrame:RegisterEvent("PLAYER_LOGIN")
NotebookFrame:RegisterEvent("PLAYER_LOGOUT")
end
 
------------------------------------------------------------------------
-- Macro callable function
------------------------------------------------------------------------
 
function NotebookSendNote(title, channel, target)
-- This function is basically a wrapper for Notebook:SendNote, taking a
-- note title and determining the note to which this applies (looking at
-- known notes only) and then sending it to the indicated channel and
-- target. The target can either be a player name (for channel "WHISPER")
-- or the name of a chat channel (for target "CHANNEL").
if _sendCooldownTimer then
return Notebook:Error(L.ERR_SEND_COOLDOWN)
end
if not title or title == "" or not channel or channel == "" then
return Notebook:Error(L.ERR_SEND_INVALID)
end
 
local ndata = Notebook:FindByTitle(title, true)
if not ndata then
return Notebook:Error(format(L.ERR_SEND_INVALID_NOTE, title))
elseif NotebookFrame.selectedID == ndata.id and NotebookFrame.editing then
return Notebook:Error(L.ERR_SEND_EDITING)
 
elseif channel == "INSTANCE" then
if GetNumGroupMembers(LE_PARTY_CATEGORY_INSTANCE) > 0 then
return Notebook:SendNote(ndata, "INSTANCE_CHAT")
end
return Notebook:Error(ERR_NOT_IN_INSTANCE_GROUP)
 
elseif channel == "RAID" then
if IsInRaid() then
if UnitIsGroupLeader("player") or UnitIsGroupAssistant("player") then
return Notebook:SendNote(ndata, "RAID")
end
return Notebook:Error(L.ERR_SEND_RAID_LEADER)
end
return Notebook:Error(ERR_NOT_IN_RAID)
 
elseif channel == "PARTY" then
if IsInGroup() and not IsInRaid() then
return Notebook:CompareOnTitleSendNote(ndata, "PARTY")
end
return Notebook:Error(ERR_NOT_IN_GROUP)
 
elseif channel == "GUILD" then
if IsInGuild() then
return Notebook:CompareOnTitleSendNote(ndata, "GUILD")
end
return Notebook:Error(ERR_GUILD_PLAYER_NOT_IN_GUILD)
 
elseif channel == "TARGET" then
if UnitCanCooperate("player", "target") then
local target = GetUnitName("target", true)
return Notebook:SendNote(ndata, "WHISPER", target)
end
return Notebook:Error(ERR_GENERIC_NO_TARGET) -- TODO: better error message
 
elseif channel == "WHISPER" then
local presenceID = GetAutoCompletePresenceID(target)
if presenceID then
return Notebook:SendNote(ndata, "BN_WHISPER", presenceID)
elseif target and target ~= "" then
return Notebook:SendNote(ndata, "WHISPER", target)
end
return Notebook:Error(L.ERR_SEND_NO_NAME)
 
elseif channel == "BN_CONVERSATION" then
if target and target ~= "" then
if BNGetConversationInfo(target) then
return Notebook:SendNote(ndata, "BN_CONVERSATION", target)
end
return Notebook:Error(format(L.ERR_SEND_INVALID_CHANNEL, target))
end
return Notebook:Error(L.ERR_SEND_NO_CHANNEL)
 
elseif channel == "CHANNEL" then
if target and target ~= "" then
local channelNum = GetChannelName(target)
if channelNum and channelNum ~= 0 then
return Notebook:SendNote(ndata, "CHANNEL", channelNum)
end
return Notebook:Error(format(L.ERR_SEND_INVALID_CHANNEL, target))
end
return Notebook:Error(L.ERR_SEND_NO_CHANNEL)
end
 
return Notebook:Error(format(ERROR_SEND_UNKNOWN_CHANNEL, channel))
end
 
------------------------------------------------------------------------
-- Slash command function
------------------------------------------------------------------------
 
SLASH_NOTEBOOK1 = "/notebook"
SLASH_NOTEBOOK2 = "/note"
SLASH_NOTEBOOK3 = Notebook.SLASH_COMMAND
 
local SlashHandlers = {
[L.CMD_DEBUGON] = function(params)
_debugFrame = params and _G[params] or DEFAULT_CHAT_FRAME
Notebook:Print(L.CMD_DEBUGON_CONFIRM)
end,
[L.CMD_DEBUGOFF] = function()
_debugFrame = nil
Notebook:Print(L.CMD_DEBUGOFF_CONFIRM)
end,
[L.CMD_SHOW] = function()
ShowUIPanel(NotebookFrame)
end,
[L.CMD_HIDE] = function()
HideUIPanel(NotebookFrame)
end,
[L.CMD_STATUS] = function()
UpdateAddOnMemoryUsage()
Notebook:Print(format(L.CMD_STATUS_FORMAT, _notesCount, GetAddOnMemoryUsage(NOTEBOOK) + 0.5))
end,
[L.CMD_LIST] = function()
Notebook:Print(L.CMD_LIST_CONFIRM)
local filterMode = _filterBy
_filterBy = L.KNOWN_TAB
Notebook:FilterList()
for i = 1, #_filteredList do
local ndata = _notesList[_filteredList[i]]
if ndata then
local text = format(L.CMD_LIST_FORMAT, ndata.title, strlen(ndata.description), ndata.author, Notebook:GetDateText(ndata.date))
Notebook:Print(false, text)
end
end
if _filterBy ~= filterMode then
_filterBy = filterMode
Notebook:FilterList()
end
end,
[L.CMD_SEND] = function(params)
local title, channel, target = strmatch(params, "(.+) (%S+) (%S+)$")
if title and channel and target then
NotebookSendNote(title, channel, target)
end
end,
[L.CMD_WELCOME] = function()
local ndata = Notebook:FindByTitle(_firstTimeNote.title, true)
if not ndata then
local ndata = Notebook:AddNote(_firstTimeNote.title, _firstTimeNote.author, _firstTimeNote.date, _firstTimeNote.description, true, true, false)
Notebook:UpdateNotKnown()
Notebook:FilterList()
Notebook.Frame_UpdateList()
Notebook.Frame_TabButtonOnClick(1)
NotebookFrame:Show()
else
Notebook:Error(format(L.ERR_PREFIX, _firstTimeNote.title))
end
end,
}
 
SlashCmdList["NOTEBOOK"] = function(text)
if not text or text == "" then
return ToggleFrame(NotebookFrame)
end
 
local command, params = strsplit(" ", text, 2)
if SlashHandlers[command] then
SlashHandlers[command](params)
else
Notebook:Print(NORMAL_FONT_COLOR_CODE .. Notebook.name .. "|r " .. GAME_VERSION_LABEL .. " " .. Notebook.version)
Notebook:Print(false, Notebook.description)
for i = 1, #HELP_TEXT do
Notebook:Print(false, HELP_TEXT[i])
end
end
end
 
------------------------------------------------------------------------
-- Blizzard options panel functions
------------------------------------------------------------------------
 
do
local Options = CreateFrame("Frame", "NotebookOptions", InterfaceOptionsFramePanelContainer)
Options.name = Notebook.name
Notebook.OptionsPanel = Options
InterfaceOptions_AddCategory(Options)
 
Options:Hide()
Options:SetScript("OnShow", function(self)
local Title = self:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
Title:SetPoint("TOPLEFT", 16, -16)
Title:SetText(Notebook.name)
 
local Version = self:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
Version:SetPoint("BOTTOMLEFT", Title, "BOTTOMRIGHT", 16, 0)
Version:SetPoint("RIGHT", -24, 0)
Version:SetJustifyH("RIGHT")
Version:SetText(GAME_VERSION_LABEL .. ": " .. HIGHLIGHT_FONT_COLOR_CODE .. Notebook.version)
 
local SubText = self:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
SubText:SetPoint("TOPLEFT", Title, "BOTTOMLEFT", 0, -8)
SubText:SetPoint("TOPRIGHT", Version, "BOTTOMRIGHT", 0, -8)
SubText:SetJustifyH("LEFT")
SubText:SetText(Notebook.description)
 
local helpText = ""
local slash = Notebook.SLASH_COMMAND or "/notebook"
for i = 1, #HELP_TEXT do
local command, description = strmatch(HELP_TEXT[i], "%- (%S+) %- (.+)")
if command and description then
helpText = format("%s\n\n%s%s %s|r\n%s", helpText, NORMAL_FONT_COLOR_CODE, slash, command, description)
else
helpText = helpText .. "\n\n" .. gsub(HELP_TEXT[i], " /([^%s,]+)", NORMAL_FONT_COLOR_CODE .. " /%1|r")
end
end
helpText = strsub(helpText, 3)
 
local HelpText = self:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
HelpText:SetPoint("TOPLEFT", SubText, "BOTTOMLEFT", 0, -24)
HelpText:SetPoint("BOTTOMRIGHT", -24, 16)
HelpText:SetJustifyH("LEFT")
HelpText:SetJustifyV("TOP")
HelpText:SetText(helpText)
 
self:SetScript("OnShow", nil)
end)
end
\ No newline at end of file
trunk/Notebook.toc New file
0,0 → 1,31
## Interface: 60000
## Version: 6.0.2.wowi:revision
 
## Title: Notebook
## Title-deDE: Notizbuch
## Title-esES: Cuaderno
## Title-esMX: Cuaderno
## Title-ruRU: Блокнот
## Notes: Record and share notes in-game.
## Notes-deDE: Speichert und teilt Notizen im Spiel.
## Notes-esES: Escribir y compartir notas en el juego.
## Notes-esMX: Escribir y compartir notas en el juego.
## Notes-ruRU: Позволяет создавать заметки и делится ими в игре.
 
## Author: Phanx, Cirk
## X-Credits: Джоан-Подземье (ruRU localization)
## X-CompatibleLocales: deDE, enUS, esES, esMX, frFR, itIT, ptBR, koKR, ruRU, zhCN, zhTW
## X-Localizations: enUS, deDE, esES, esMX, ruRU
## X-Website: http://www.wowinterface.com/downloads/info4544-Notebook.html
## X-Curse-Project-ID: notebook
## X-WoWI-ID: 4544
 
## SavedVariables: NotebookState
 
Localization-en.lua
Localization-de.lua
Localization-es.lua
Localization-ru.lua
 
Notebook.lua
NotebookFrame.lua
\ No newline at end of file