Guide to XML Frames - Final Code

This is the example add-on as it should appear after completing the Guide to XML Frames. This can be used as a reference while following the guide, or to simply see what the add-on does in the completed state.
Left-click and drag the frame to move it around, right-click and drag to re-size it. Press the lock button to lock the frame in place, press pause to pause the memory display updating.
== The Table of Contents (MemViewer.toc) ==
## Interface: 3.0.7.2322
## Title: MemViewer
## Version: 1.0
## Description: Displays the lua memory usage on screen.
## Author: Me
MemViewer.lua
MemViewer.xml
== The Script File (MemViewer.lua) ==
--[[
 MemViewer
 
 A simple add-on to display the Lua engine's memory usage. 
 This is the example add-on created from Peryl's Guide to XML Frames on the RoMWiki
 
 Version: 1.0
 Author: Me
 License: Public Domain
]]--
local MemViewer = {};
_G.MemViewer = MemViewer;
--[[ Slash command handler ]]--
SLASH_MemViewer1 = "/mview";
SlashCmdList["MemViewer"] = function(ebox, msg)
 if(MemViewerFrame:IsVisible()) then
 MemViewerFrame:Hide();
 else
 MemViewerFrame:Show();
 end
end
--[[ Helper function to set the text on the frame ]]--
local function SetMemViewerText(current, previous)
 local change = current - previous;
 MemViewerFrameDesc:SetText(string.format("Mem: %.2f KB (%.4f KB)", current, change), 1, 1, 1);
end
--[[ The OnLoad handler ]]--
function MemViewer.OnLoadHandler()
 MemViewer.PrevMem = collectgarbage("count");
 SetMemViewerText(MemViewer.PrevMem, MemViewer.PrevMem);
 MemViewer.UpdateTime = 0;
 
 SaveVariables("MemViewerPos");
 MemViewerFrame:RegisterEvent("VARIABLES_LOADED");
 MemViewerFrame:RegisterEvent("SAVE_VARIABLES");
end
--[[ The OnUpdate handler ]]--
function MemViewer.OnUpdateHandler(elapsed)
 MemViewer.UpdateTime = MemViewer.UpdateTime + elapsed;
 if(MemViewer.UpdateTime >= 2.0) then
 local curmem = collectgarbage("count");
 SetMemViewerText(curmem, MemViewer.PrevMem);
 MemViewer.PrevMem = curmem;
 MemViewer.UpdateTime = 0;
 end
end
--[[ The OnEvent handler ]]--
function MemViewer.OnEventHandler(event)
 if(event == "VARIABLES_LOADED") then 
 if(not MemViewerPos.x) then
 MemViewerPos.x, MemViewerPos.y = MemViewerFrame:GetPos();
 else
 MemViewerFrame:SetPos(MemViewerPos.x, MemViewerPos.y);
 end
 elseif(event == "SAVE_VARIABLES") then
 MemViewerPos.x, MemViewerPos.y = MemViewerFrame:GetPos(); 
 end
end
== The XML File (MemViewer.xml) ==
<Ui xmlns="http://www.runewaker.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.runewaker.com/UI.xsd">
 <Button name="OurButtonTemplate" inherits="UIPanelButtonTemplate" enableMouse="true" virtual="true">
 <Size>
 <AbsDimension x="90" y="26"/>
 </Size>
 </Button>
 <Frame name="MemViewerFrame" parent="UIParent" enableMouse="true">
 <Size>
 <AbsDimension x="200" y="80"/>
 </Size>
 <Anchors>
 <Anchor point="TOP" relativePoint="TOP" relativeTo="UIParent">
 <Offset>
 <AbsDimension x="0" y="50"/>
 </Offset>
 </Anchor>
 </Anchors>
 <Backdrop edgeFile="Interface\Tooltips\Tooltip-border" bgFile="Interface\Tooltips\Tooltip-Background">
 <BackgroundInsets>
 <AbsInset top="4" left="4" bottom="4" right="4"/>
 </BackgroundInsets>
 <EdgeSize>
 <AbsValue val="16"/>
 </EdgeSize>
 <TileSize>
 <AbsValue val="16"/>
 </TileSize>
 </Backdrop>
 <Layers>
 <Layer level="ARTWORK">
 <FontString name="$parentDesc" inherits="GameFontHighlight" text="Displayed Text">
 <Anchors>
 <Anchor point="CENTER" relativePoint="CENTER"/>
 </Anchors>
 </FontString>
 </Layer>
 <Layer level="BORDER">
 <Texture name="$parentGlow" file="interface/transportbook/tb_highlight-01" alphaMode="ADD">
 <Size>
 <AbsDimension x="175" y="16"/>
 </Size>
 <Anchors>
 <Anchor point="CENTER" relativePoint="CENTER"/>
 </Anchors>
 <TexCoords left="0" right="1" top="0" bottom="1"/>
 </Texture>
 </Layer>
 </Layers>
 <Frames>
 <Button name="MemViewerPauseButton" inherits="OurButtonTemplate" text="Pause">
 <Anchors>
 <Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT">
 <Offset>
 <AbsDimension x="7" y="-5"/>
 </Offset>
 </Anchor>
 </Anchors>
 <Scripts>
 <OnClick>
 MemViewer.Paused = not MemViewer.Paused;
 if(MemViewer.Paused) then
 this:SetText("Unpause");
 else
 this:SetText("Pause");
 end
 </OnClick>
 </Scripts>
 </Button>
 <Button name="MemViewerLockButton" inherits="OurButtonTemplate" text="Lock">
 <Anchors>
 <Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT">
 <Offset>
 <AbsDimension x="-5" y="-5"/>
 </Offset>
 </Anchor>
 </Anchors>
 <Scripts>
 <OnClick>
 MemViewer.Locked = not MemViewer.Locked;
 if(MemViewer.Locked) then
 this:SetText("Unlock");
 else
 this:SetText("Lock");
 end
 </OnClick>
 </Scripts>
 </Button>
 <Button name="$parentCloseButton" inherits="UIPanelCloseButtonTemplate">
 <Anchors>
 <Anchor point="TOPRIGHT" relativePoint="TOPRIGHT">
 <Offset>							
 <AbsDimension x="-6" y="6"/>
 </Offset>
 </Anchor>
 </Anchors>
 </Button>
 </Frames>
 <Scripts>
 <OnLoad>
 MemViewer.Paused = false; 
 MemViewer.Locked = false;
 MemViewer.OnLoadHandler();
 </OnLoad>
 <OnUpdate>
 if(not MemViewer.Paused) then
 MemViewer.OnUpdateHandler(elapsedTime);
 end
 </OnUpdate>
 <OnMouseDown>
 if(not MemViewer.Locked) then
 if(key == "LBUTTON") then 
 MemViewerFrame:StartMoving("TOPLEFT");
 elseif(key == "RBUTTON") then
 MemViewerFrame:StartSizing("BOTTOMRIGHT");
 end
 end
 </OnMouseDown>
 <OnMouseUp> 
 MemViewerFrame:StopMovingOrSizing();
 </OnMouseUp>
 <OnEvent>
 MemViewer.OnEventHandler(event);
 </OnEvent>
 </Scripts>
 </Frame>
</Ui>