changeset 11:d2cbfe498c4d

first beta
author Jay Bird <a4blank@yahoo.com>
date Sat, 04 Dec 2010 05:53:52 +0300
parents f93b554bb7cf
children cc98f28b1c7c
files .pkgmeta Icon.lua Main.lua NameDialog.lua PartyInfo.lua RaidTargetTactics.toc RoleField.lua UserSelect.lua _requires.xml class.lua locale/locale.lua locale/locale.ru.lua
diffstat 12 files changed, 477 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/.pkgmeta	Sun Nov 28 18:59:31 2010 +0300
+++ b/.pkgmeta	Sat Dec 04 05:53:52 2010 +0300
@@ -24,6 +24,8 @@
         url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0
     libs/AceGUI-3.0:
         url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceGUI-3.0
+    libs/AceGUI-3.0-Completing-EditBox:
+        url: svn://svn.wowace.com/wow/acegui-3-0-completing-editbox/mainline/trunk
     libs/AceAddon-3.0:
         url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0
     libs/LibDataBroker-1.1:
--- a/Icon.lua	Sun Nov 28 18:59:31 2010 +0300
+++ b/Icon.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -15,7 +15,10 @@
     tex:SetAllPoints(frame)
     tex:SetTexture("Interface\\TARGETINGFRAME\\UI-RaidTargetingIcon_" .. self.num)
     frame:Show()
-    return frame
+end
+
+function RaidIcon:GetChatCommand()
+    return "{rt" .. self.num .. "}"
 end
 
 _G.RaidIcons = {}
--- a/Main.lua	Sun Nov 28 18:59:31 2010 +0300
+++ b/Main.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -1,18 +1,38 @@
 
 
-RTT = LibStub("AceAddon-3.0"):NewAddon("RaidTargetTactics", "AceConsole-3.0")
+RTT = LibStub("AceAddon-3.0"):NewAddon("RaidTargetTactics", "AceConsole-3.0", "AceEvent-3.0")
+local _G = _G
 local L = LibStub("AceLocale-3.0"):GetLocale("RaidTargetTactics")
-
-
 local LDB = LibStub("LibDataBroker-1.1", true)
 local LDBIcon = LibStub("LibDBIcon-1.0", true)
-local AceGUI = LibStub("AceGUI-3.0")
+local Completion = LibStub("AceGUI-3.0-Completing-EditBox");
+
+Completion:Register("Raid", -1, 0)
+local GetAutoCompleteResults_original = _G.GetAutoCompleteResults
+_G.GetAutoCompleteResults = function(text, include, exclude, results, position)
+    if include == -1 then -- special hack for Raid members and self
+        local users = RTT.partyInfo:GetUsers()
+        local result = {}
+        for _, name in ipairs(users) do
+            if name:find(text) == 1 then
+                table.insert(result, name)
+            end
+            if #result > results then
+                break
+            end
+        end
+        return unpack(result)
+    else
+        return GetAutoCompleteResults_original(text, include, exclude, results, position)
+    end
+end
+
 
 local RTTIcon = LibStub("LibDataBroker-1.1"):NewDataObject("RTTIcon", {
     type = "data source",
     text = "Raid Target Tactics",
     icon = "Interface\\TARGETINGFRAME\\UI-RaidTargetingIcon_8",
-    OnClick = function() RTT:OnIconClick() end,
+    OnClick = function(frame, button) RTT:OnIconClick(frame, button) end,
     OnTooltipShow = function(tooltip)
         tooltip:AddLine("Raid Target Tactics")
         tooltip:AddLine(L.Minimap_Icon_Tooltip)
@@ -25,14 +45,21 @@
         minimap = {
             hide = false,
         },
+        setups = {},
+        locked = false,
     },
 }
 
 function RTT:OnInitialize()
     self.db = LibStub("AceDB-3.0"):New("TacticsSettings", defaults, true)
+    self.partyInfo = PartyInfo()
+    self.nameDialog = NameDialog(self:GetSetupNames())
 
     LDBIcon:Register("RTTIcon", RTTIcon, self.db.profile.minimap)
     self:InitFrame()
+    self:BindEvents()
+    self.nameDialog:InitDialog()
+    self.partyInfo:Update()
     if self.f:IsShown() ~= self.db.profile.visible then
         if self.db.profile.visible then
             self:ShowFrame()
@@ -40,13 +67,43 @@
             self:HideFrame()
         end
     end
+    if self.db.profile.locked then
+        self.f:SetMovable(false)
+        self.f:EnableMouse(false)
+    end
+end
+
+function RTT:GetSetupNames()
+    local result = {}
+    for name, _ in pairs(self.db.profile.setups) do
+        table.insert(result, name)
+    end
+    return result
+end
+
+function RTT:BindEvents()
+    self:RegisterEvent("PARTY_MEMBERS_CHANGED")
+    self:RegisterEvent("RAID_ROSTER_UPDATE")
+end
+
+function RTT:PARTY_MEMBERS_CHANGED()
+    self.partyInfo:Update()
+end
+
+function RTT:RAID_ROSTER_UPDATE()
+    self.partyInfo:Update()
 end
 
 function RTT:InitFrame()
-    self.f = CreateFrame("Frame", nil, UIParent)
+    self.f = CreateFrame("Frame", "__RTT_MAIN", UIParent)
     self.f:SetWidth(300)
-    self.f:SetHeight(200)
+    self.f:SetHeight(270)
     self.f:SetAlpha(0.8)
+    self.f:SetMovable(true)
+    self.f:EnableMouse(true)
+    self.f:RegisterForDrag("LeftButton")
+    self.f:SetScript("OnDragStart", self.f.StartMoving)
+    self.f:SetScript("OnDragStop", self.f.StopMovingOrSizing)
     self.f:SetPoint("LEFT", UIParent, "LEFT", 10, 0)
     --[[self.f:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
                         edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
@@ -76,43 +133,118 @@
     self.f:SetFrameStrata("HIGH")
     --self.f:SetBackdropColor(0, 0, 0, 0.5)
 
+    local str1 = self.f:CreateFontString()
+    str1:SetFontObject(GameFontHighlightSmall)
+    str1:SetPoint("TOPLEFT", 45, -15)
+    str1:SetText(L.Action .. ":")
+    str1:SetTextColor(YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b)
+    str1:Show()
+
+    local str1 = self.f:CreateFontString()
+    str1:SetFontObject(GameFontHighlightSmall)
+    str1:SetPoint("TOPLEFT", 175, -15)
+    str1:SetText(L.Player .. ":")
+    str1:SetTextColor(YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b)
+    str1:Show()
+
+    self.icons = {}
     self.fields = {}
     self.selects = {}
     for num, icon in ipairs(RaidIcons) do
-        icon:draw(self.f, 20, num * -20)
+        self.icons[num] = icon
+        icon:draw(self.f, 16, (num - 1) * -25 - 30)
 
-        local field = CreateFrame("EditBox", "__RTT_EditBox_" .. tostring(num), self.f, "InputBoxTemplate")
-        field:SetAutoFocus(false)
-        field:SetFontObject(ChatFontNormal)
-        field:SetWidth(100)
-        field:SetHeight(16)
-        field:SetTextInsets(0, 0, 3, 3)
-        field:SetPoint("TOPLEFT", 40, num * -20)
-        table.insert(self.fields, field)
-        field:Show()
+        local field = RoleField()
+        field:draw(self.f, 45, (num -1) * -25 - 30)
+        self.fields[num] = field
 
-        local userSelect = AceGUI:Create("Dropdown")
-        userSelect.frame:SetParent(self.f)
-        local raid = {}
-        for i=1, GetNumRaidMembers() do
-            raid[i] = UnitName("raid" .. i)
+        local userSelect = UserSelect()
+        userSelect:draw(self.f, 170, ((num - 1) * -25) - 30)
+        self.selects[num] = userSelect
+    end
+    self.talkButton =  CreateFrame("Button", nil, self.f, "OptionsButtonTemplate")
+    self.talkButton:ClearAllPoints()
+    self.talkButton:SetText(L.Announce)
+    self.talkButton:SetPoint("TOPLEFT", 170, -230)
+    self.talkButton:SetWidth(102)
+    self.talkButton:SetScript("OnClick", function() RTT:Announce() end)
+
+    self.dropdown = CreateFrame("Frame", "__RTT_DROPDOWN", UIParent, "UIDropDownMenuTemplate");
+    UIDropDownMenu_Initialize(self.dropdown, self.InitDropdown, "MENU");
+end
+
+function RTT:InitDropdown(level)
+    level = level or 1
+    if (level == 1) then
+        local info = UIDropDownMenu_CreateInfo()
+        info.hasArrow = false
+        info.notCheckable = false
+        info.text = L.Lock
+        info.func = function() RTT:ToggleMovable() end
+        info.keepShownOnClick = true
+        info.checked = RTT.db.profile.locked
+        UIDropDownMenu_AddButton(info, level)
+
+        info.hasArrow = true
+        info.notCheckable = true
+        info.text = L.Load
+        info.value = "load"
+        info.keepShownOnClick = false
+        UIDropDownMenu_AddButton(info, level)
+
+        info.hasArrow = false
+        info.notCheckable = true
+        info.text = L.Save .. "…"
+        info.keepShownOnClick = false
+        local rows = RTT:GetFormData()
+        if #rows == 0 then
+            info.disabled = true
+        else
+            info.func = function() RTT:AskForSave() end
         end
-        userSelect:SetList(raid)
-        userSelect:SetWidth(100)
-        userSelect:SetHeight(16)
-        userSelect:SetPoint("TOPLEFT", 160, num * -20)
-        table.insert(self.selects, userSelect)
-        userSelect.frame:Show()
+        UIDropDownMenu_AddButton(info, level)
+    end
+
+    if (level == 2 and UIDROPDOWNMENU_MENU_VALUE == "load") then
+        local info = UIDropDownMenu_CreateInfo();
+        for key, setup in pairs(RTT.db.profile.setups) do
+            info.hasArrow = false
+            info.notCheckable = true
+            info.text = key
+            info.func = function() RTT:Load(key) end
+            UIDropDownMenu_AddButton(info, level);
+        end
     end
 end
 
-function RTT:OnIconClick()
-    if self.db.profile.visible then
-        self:HideFrame()
+function RTT:AskForSave()
+    local this = self
+    self.nameDialog:Show()
+    self.nameDialog:OnNameChosen(function(name) this:Save(name) end)
+end
+
+function RTT:Save(name)
+    self.db.profile.setups[name] = self:GetFormData(true)
+    self.nameDialog:SetInvalidNames(self:GetSetupNames())
+end
+
+function RTT:Load(name)
+    local data = self.db.profile.setups[name]
+    self:SetFormData(data)
+end
+
+function RTT:OnIconClick(frame, button)
+    if button == "RightButton" then
+        -- context menu
+        ToggleDropDownMenu(1, nil, self.dropdown, LDBIcon.objects["RTTIcon"], 0, 0)
     else
-        self:ShowFrame()
+        if self.db.profile.visible then
+            self:HideFrame()
+        else
+            self:ShowFrame()
+        end
+        self.db.profile.visible = not self.db.profile.visible
     end
-    self.db.profile.visible = not self.db.profile.visible
 end
 
 function RTT:HideFrame()
@@ -123,6 +255,62 @@
     self.f:Show()
 end
 
+function RTT:ToggleMovable()
+    if self.f:IsMovable() then
+        self.f:SetMovable(false)
+        self.f:EnableMouse(false)
+        self.db.profile.locked = true
+    else
+        self.f:SetMovable(true)
+        self.f:EnableMouse(true)
+        self.db.profile.locked = false
+    end
+end
 
+function RTT:GetDefaultChatChannel()
+    if self.partyInfo.is_in_raid then
+        return "RAID"
+    end
+    if self.partyInfo.is_in_party then
+        return "PARTY"
+    end
+    return nil
+end
 
+function RTT:SetFormData(data)
+    for idx, row in ipairs(data) do
+        self.fields[idx]:SetText(row[2])
+        self.selects[idx]:SetText(row[3])
+    end
+end
 
+function RTT:GetFormData(with_empty)
+    local result = {}
+    for idx, icon in ipairs(self.icons) do
+        local action = strtrim(self.fields[idx]:GetText())
+        local player = strtrim(self.selects[idx]:GetText())
+        -- Either we want empty rows (for save)
+        -- Or action or player are filled
+        if with_empty or (#action > 0 or #player > 0) then
+            table.insert(result, {icon:GetChatCommand(),
+                                  action,
+                                  player})
+        end
+    end
+    return result
+end
+
+function RTT:Announce()
+    local channel = self:GetDefaultChatChannel()
+    if channel then
+        for _, data in ipairs(self:GetFormData()) do
+            local str = table.concat(data, " — ")
+            SendChatMessage(str, channel)
+        end
+        if UnitName("player") == "Герадд" then
+            SendChatMessage("Герадд любит тебя!", channel)
+        end
+    end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NameDialog.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -0,0 +1,120 @@
+
+NameDialog = class()
+local L = LibStub("AceLocale-3.0"):GetLocale("RaidTargetTactics")
+
+function NameDialog:init(names)
+    self.invalidNames = names
+    self.callback = function() end
+end
+
+function NameDialog:InitDialog()
+    local this = self
+    
+    self.nameBox = CreateFrame("Frame", nil, UIParent)
+    self.nameBox:SetWidth(240)
+    self.nameBox:SetHeight(50)
+    local backdrop = {
+      -- path to the background texture
+      bgFile = "Interface\\FrameGeneral\\UI-Background-Marble",
+      -- path to the border texture
+      edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
+      -- true to repeat the background texture to fill the frame, false to scale it
+      tile = true,
+      -- size (width or height) of the square repeating background tiles (in pixels)
+      tileSize = 256,
+      -- thickness of edge segments and square size of edge corners (in pixels)
+      edgeSize = 32,
+      -- distance from the edges of the frame to those of the background texture (in pixels)
+      insets = {
+        left = 11,
+        right = 12,
+        top = 12,
+        bottom = 11
+      }
+    }
+    self.nameBox:SetBackdrop(backdrop)
+    self.nameBox:SetFrameStrata("DIALOG")
+    self.nameBox:SetPoint("CENTER")
+
+    self.nameLabel = self.nameBox:CreateFontString()
+    self.nameLabel:SetFontObject(GameFontHighlight)
+    self.nameLabel:SetPoint("LEFT", 20, 0)
+    self.nameLabel:SetText(L.Name .. ":")
+    self.nameLabel:SetTextColor(YELLOW_FONT_COLOR.r, YELLOW_FONT_COLOR.g, YELLOW_FONT_COLOR.b)
+    self.nameLabel:Show()
+
+    self.nameField = CreateFrame("EditBox", "__RTT_ASKNAME", self.nameBox, "InputBoxTemplate")
+    self.nameField:SetAutoFocus(false)
+    self.nameField:SetFontObject(ChatFontNormal)
+    self.nameField:SetWidth(100)
+    self.nameField:SetHeight(20)
+    self.nameField:SetPoint("LEFT", 60, 0)
+    self.nameField:SetTextInsets(0, 0, 3, 3)
+    self.nameField:SetScript("OnEscapePressed", function() this:Hide() end)
+    self.nameField:SetScript("OnTextChanged", function() this:OnChange() end)
+    self.nameField:SetScript("OnEnterPressed", function() this:OnEnter() end)
+
+    -- add button
+    self.okButton = CreateFrame("Button", nil, self.nameBox, "OptionsButtonTemplate")
+    self.okButton:SetText("OK")
+    self.okButton:Disable()
+    self.okButton:SetWidth(50)
+    self.okButton:SetPoint("left", 170, 0)
+    self.okButton:Show()
+    self.okButton:SetScript("OnClick", function() this:OnEnter() end)
+
+    self.nameBox:Hide()
+end
+
+function NameDialog:SetInvalidNames(names)
+    self.invalidNames = names
+end
+
+function NameDialog:Show()
+    self.nameBox:Show()
+    self.nameField:SetText("")
+    self.nameField:SetFocus()
+end
+
+function NameDialog:Hide()
+    self.nameBox:Hide()
+end
+
+function NameDialog:GetName()
+    return strtrim(self.nameField:GetText())
+end
+
+function NameDialog:IsValidName()
+    local name = self:GetName()
+    if #name > 0 then
+        for _, taken in ipairs(self.invalidNames) do
+            if name == taken then
+                return false
+            end
+        end
+        return true
+    end
+    return false
+end
+
+function NameDialog:OnChange()
+    if self:IsValidName() then
+        self.okButton:Enable()
+    else
+        self.okButton:Disable()
+    end
+end
+
+function NameDialog:OnEnter()
+    if not self:IsValidName() then
+        return
+    end
+    local name = self:GetName()
+    self:Hide()
+    self.callback(name)
+end
+
+function NameDialog:OnNameChosen(func)
+    self.callback = func
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PartyInfo.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -0,0 +1,58 @@
+
+PartyInfo = class()
+
+function PartyInfo:init()
+    self.players = {}
+    self.have_party = false
+    self.is_in_raid = false
+    self.is_in_party = false
+end
+
+function PartyInfo:Update()
+    self.players = {}
+    self.raidCount = GetNumRaidMembers()
+    if self.raidCount == 0 then
+        self.is_in_raid = false
+    else
+        self.have_party = true
+        self.is_in_raid = true
+        self.is_in_party = false
+        self:LoadRaidMembers()
+        table.sort(self.players)
+        return
+    end
+
+    self.partyCount = GetNumPartyMembers()
+    if self.partyCount == 0 then
+        self.is_in_party = false
+    else
+        self.have_party = true
+        self.is_in_party = true
+        self:LoadPartyMembers()
+        table.sort(self.players)
+        return
+    end
+
+    self.have_party = false
+end
+
+function PartyInfo:LoadRaidMembers()
+    local name
+    for i=1, self.raidCount do
+        name = UnitName("raid" .. i)
+        table.insert(self.players, name)
+    end
+end
+
+function PartyInfo:LoadPartyMembers()
+    local name = UnitName("player")
+    table.insert(self.players, name)
+    for i=1, self.partyCount do
+        name = UnitName("party" .. i)
+        table.insert(self.players, name)
+    end
+end
+
+function PartyInfo:GetUsers()
+    return self.players
+end
--- a/RaidTargetTactics.toc	Sun Nov 28 18:59:31 2010 +0300
+++ b/RaidTargetTactics.toc	Sat Dec 04 05:53:52 2010 +0300
@@ -3,11 +3,16 @@
 ## Title: Tactics
 ## Title-ruRU: Тактика
 ## Notes: Assign different roles to raid signs and post them to the chat
-## SavedVariables: TacticsGlobalSettings
-## SavedVariablesPerCharacter: TacticsProfileSettings
+## SavedVariables: TacticsSettings
 ## Author: jay
 
 _requires.xml
 _locale.xml
 
+class.lua
+Icon.lua
+RoleField.lua
+UserSelect.lua
+PartyInfo.lua
+NameDialog.lua
 Main.lua
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RoleField.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -0,0 +1,24 @@
+
+RoleField = class()
+local NEXT_FIELD_NUM = 1
+
+function RoleField:draw(parent, x, y)
+    self.field = CreateFrame("EditBox", "__RTT_RoleField_" .. tostring(NEXT_FIELD_NUM), parent, "InputBoxTemplate")
+    self.field:SetAutoFocus(false)
+    self.field:SetFontObject(ChatFontNormal)
+    self.field:SetWidth(120)
+    self.field:SetHeight(16)
+    self.field:SetTextInsets(0, 0, 3, 3)
+    self.field:SetPoint("TOPLEFT", x, y)
+    self.field:Show()
+
+    NEXT_FIELD_NUM = NEXT_FIELD_NUM + 1
+end
+
+function RoleField:GetText()
+    return self.field:GetText()
+end
+
+function RoleField:SetText(text)
+    self.field:SetText(text)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UserSelect.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -0,0 +1,21 @@
+
+UserSelect = class()
+local AceGUI = LibStub("AceGUI-3.0")
+
+function UserSelect:draw(parent, x, y)
+    self.field = AceGUI:Create("EditBoxRaid")
+    self.field.frame:SetParent(parent)
+    self.field:DisableButton(true)
+    self.field:SetWidth(100)
+    self.field:SetHeight(16)
+    self.field:SetPoint("TOPLEFT", x, y)
+    self.field.frame:Show()
+end
+
+function UserSelect:GetText()
+    return self.field:GetText()
+end
+
+function UserSelect:SetText(text)
+    self.field:SetText(text)
+end
--- a/_requires.xml	Sun Nov 28 18:59:31 2010 +0300
+++ b/_requires.xml	Sat Dec 04 05:53:52 2010 +0300
@@ -1,12 +1,12 @@
-
 <Ui xmlns="http://www.blizzard.com/wow/ui/">
-    <Script file="libs\LibStub\LibStub.lua"/>
+    <Script  file="libs\LibStub\LibStub.lua"/>
+    <Include file="libs\AceGUI-3.0\AceGUI-3.0.xml"/>
+    <Script  file="libs\AceGUI-3.0-Completing-EditBox\AceGUI-3.0-Completing-EditBox.lua"/>
     <Include file="libs\AceAddon-3.0\AceAddon-3.0.xml"/>
     <Include file="libs\CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
     <Include file="libs\AceEvent-3.0\AceEvent-3.0.xml"/>
     <Include file="libs\AceConsole-3.0\AceConsole-3.0.xml"/>
     <Include file="libs\AceLocale-3.0\AceLocale-3.0.xml"/>
-
-    <Script file="libs/LibDataBroker/LibDataBroker-1.1.lua"/>
-    <Script file="libs/LibDBIcon-1.0/LibDBIcon-1.0.lua"/>
+    <!--<Script file="libs/LibDataBroker/LibDataBroker-1.1.lua"/>-->
+    <!--<Script file="libs/LibDBIcon-1.0/LibDBIcon-1.0.lua"/>-->
 </Ui>
--- a/class.lua	Sun Nov 28 18:59:31 2010 +0300
+++ b/class.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -44,4 +44,3 @@
    setmetatable(c, mt)
    return c
 end
-
--- a/locale/locale.lua	Sun Nov 28 18:59:31 2010 +0300
+++ b/locale/locale.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -5,3 +5,10 @@
 local L = LibStub('AceLocale-3.0'):NewLocale('RaidTargetTactics', 'enUS', true)
 
 L.Minimap_Icon_Tooltip = "Click to toggle addon window"
+L.Announce = "Announce"
+L.Action = "Action"
+L.Player = "Player"
+L.Lock = "Lock window"
+L.Load = "Load setup"
+L.Save = "Save setup"
+L.Name = "Name"
\ No newline at end of file
--- a/locale/locale.ru.lua	Sun Nov 28 18:59:31 2010 +0300
+++ b/locale/locale.ru.lua	Sat Dec 04 05:53:52 2010 +0300
@@ -1,4 +1,4 @@
---[[
+--[[
     Raid Target Tactics Russian locale
 --]]
 
@@ -6,3 +6,10 @@
 if not L then return end
 
 L.Minimap_Icon_Tooltip = "Открыть/закрыть окно с тактикой"
+L.Announce = "Объявить"
+L.Action = "Действие"
+L.Player = "Игрок"
+L.Lock = "Закрепить окно"
+L.Load = "Загрузить"
+L.Save = "Сохранить"
+L.Name = "Имя"
\ No newline at end of file