<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Monday, November 24, 2008, 11:16 PM -->
<!-- MuClient version 4.38 -->

<!-- Plugin "InfoBox_Demo" generated by Plugin Wizard -->

<muclient>
<plugin
   name="InfoBox_Demo"
   author="Spellbound"
   id="48b09fb93b098e1fac548e10"
   language="Lua"
   purpose="Demonstrate the InfoBox.lua module"
   date_written="2008-11-24 23:12:53"
   requires="4.37"
   version="1.0"
   >
<description trim="y">
<![CDATA[
This demo module will walk you through the functionality of the InfoBox lua module. Start the demo with "Demo Intro" or "Demo 1" to see what this module can do for you.
]]>
</description>

</plugin>


<!--  Get our standard constants -->

<include name="constants.lua"/>

<!--  Aliases  -->

<aliases>
  <alias
   script="Demofunc"
   match="Demo *"
   enabled="y"
   sequence="100"
  >
  </alias>
  <alias
   match="Example"
   enabled="y"
   send_to="12"
   sequence="100"
  >
  <send>print() print()
print(Demo[ThisTopic].code)</send>
  </alias>
</aliases>

<!--  Script  -->


<script>
<![CDATA[
require "InfoBox"

ThisTopic = "Intro"

function Demofunc (a, l, w, sr)
	print(string.rep("\n", 40))
	for i,v in ipairs(WindowList() or {}) do
		if v:match("^IBDemo") then WindowDelete(v) end
	end
	ThisTopic = w[1]
	if tonumber(w[1]) then ThisTopic = Demo[tonumber(w[1])] end
	if Demo[ThisTopic] then
		print(ThisTopic, "\n")
		print ( Demo[ThisTopic].text)
		ColourNote("white", "black", "\nExample:\n")
		assert(loadstring(Demo[ThisTopic].code))()
		ColourNote("white", "black", Demo[ThisTopic].code )
		print("\nDemo Topics:\n\t")
		print ( Demo:concat(", ") )
		print('\n\nSelect a "Demo <Topic>", or press enter to continue.\n\n')
		AddTimer('Next', 0, 0, .3, '', timer_flag.Enabled + timer_flag.OneShot + timer_flag.Temporary + timer_flag.ActiveWhenClosed, 'SetCmdArea')
end	end


function SetCmdArea (t,l,w)
	SelectCommand()
	PasteCommand ("Demo " .. Demo[ThisTopic].NextTopic)
	SelectCommand()
end



-- The Samples -- 

Demo = { "Intro", 
		"MiniWindowOverview", 
		"Bar-Overview", "BarStyles-Fills", "BarStyles-Frames", "MiniWindowGrid", "ThresholdAndFade",  
		 "Text", "Text-Placement", "Text-Font", "Text-Advanced", "MiniWindowPosition",
		 "BarSpacing", "Watches", "Misc", "Putting-It-Together"}

		
setmetatable(Demo, {__index = table})

Demo.Intro = {
text =[[This Plugin will demonstrate the functions in the InfoBox.lua module.
The Module itself is meant to give you flexible, powerful results with minimal scripting on your part. The white example text is the exact script that generates the sample boxes for each topic.

For a Quick start, you can be up and running with only the following lines of code:

require "InfoBox"
box = InfoBox:New("HP")
hp = box:AddBar("HP: ", 50)

and in your prompt/hpbar trigger:
hp.value = <new percentage number>
box:Update()
]],
code = [[box = InfoBox:New("IBDemo")
box:AddBar("HP: ", 75)
box:Update() 
]]}


Demo.MiniWindowOverview = {text = [[
The InfoBox has 3 main tables that you will deal with.
The MiniWindow itself, is the table that's created by 
	MW = InfoBox:New("name")
	
MiniWindow.Bar is the table where default settings for gauges are set.
MiniWindow.Bars is a table with a reference to all bars within the 
miniwindow.

A bar is a table created by calling MW:AddBar(<options>). 
This table is added to MW.Bars, and has a metatable referring to MW.Bar, which in turn refers to MW, which also refers back to InfoBox itself.
This allows you to inherit default values.

Naming conventions within the module are:
all values begin with a lower case letter. i.e. hp.value, box.backgroundColour
all functions begin with a capital letter. i.e. box:Update()
The exceptions to this convention are the .Bar and .Bars subtables.  ]] , -- [[Crimson's shadow routine is buggy.]]
code = 
[[ ]]}

Demo["Bar-Overview"] = {text = 
[[The AddBar function takes a numer of optional parameters. Parameters 
not specified will be supplied from the MW.Bar table, the MW itself, or the module.

	bar = MW:AddBar(caption, value, goodColour, badColour, anchorRight, barStyle)

The values all have coresponding functions that perform any additional validation.
The bar variable assignment is optional. You can still access the created bar 
through the MW.Bars table. 

The anchorRight value determines what side of the gauge has the 0 value.

:InsertBar() takes an index as the first parameter, and then the same parameters the AddBar() function does. 
:RemoveBar() takes the index of the bar you want to remove. It is recommended using the RemoveBar() function instead of just setting .Bars[n] = nil since the Draw routine depends on ipairs() and not having any gaps in the indices of the .Bars table.
]] ,
code = [[
MW = InfoBox:New("IBDemoAddBar")
MW:AddBar() ; MW.Bars[1].barStyle = 0 -- An empty bar.
MW:AddBar("2nd", 80, "green", 0x000000, false, MW.barStyles.flat + MW.barStyles.solid)
MW:AddBar("3rd", 80, "#FFaa55", "cyan", true, MW.barStyles.flat + MW.barStyles.solid)
MW:AddBar("4th")
MW:Update() 
]]}

Demo.ThresholdAndFade = {text = [[
The .threshold value has slightly different effects based on what barStyle the 
gauge currently has. It is the value where goodColour transitions to badColour.
.value > .threshold is .goodColour; .value <= .threshold is .badColour.

The .fade property changes the gauge's color based on its .value. The gauge 
will be drawn in .badColour from 0% to its .threshold value; it will then step 
towards goodColour at 100%, in 5% increments. The fade property affects goodColour on gradient type fills as well.
]] , --']] >
code =[[
MW = InfoBox:New("IBDemoFade")
MW.windowWidth = 360 ; MW:Columns(2)
MW.Bar.fade = true ; MW.Bar.threshold = 40
for i = 100,30,-5 do
	MW:AddBar(i, i, "#00FFFF", "red")
end
for i = 100,30,-5 do
	MW:AddBar(i, i, "cyan", "firebrick")
	MW.Bars[#MW.Bars].barStyle = MW.barStyles.glass + MW.barStyles.gradientFixed
end
MW:Update() 
]]}


Demo["BarStyles-Fills"] = {text =[[
The look of a gauge is determined by its .barStyle value, which is a 
combination of a fill and a frame. The values are enumerated in the 
InfoBox.barStyles table.
.barStyles.solid is a standard solid color. The .fade property looks best on this fillstyle. 
.barStyles.gradientScale has goodColour at the value. The midpoint of the gradient is one half of the value.
.barStyles.gradientFixed has goodColour at 100%, and the visibility changes. The midpoint is set by .threshold.
.barStyles.gradientShift has its midpoint at value. It always fills 100% of .gaugeWidth .
]],
code =[[
local stylename = {[0]="sunken","raised","raisedCap", "flat","glass", 
              "solid", "gradientScale", "gradientFixed", "gradientShift"}
MWs = {}
for i = 5,8 do
  MWs [#MWs+1] = InfoBox:New("IBDemo" .. i)
  MWs[#MWs]:AddBar(string.format(".barStyles.%s = %i", stylename[i], 2^i), 
	                 0,0,0,false,0)
  for j = 1,4 do 
    MWs[#MWs]:AddBar("",100 - (14*j), "green","firebrick",
       false,InfoBox.barStyles[ stylename[i] ] + InfoBox.barStyles.glass)
    MWs[#MWs].Bars[j+1].threshold = 35
end end
for i=1,3 do
  MWs[3]:AddBar("",90, "dodgerblue", "purple", false, 
      MWs[3].barStyles.gradientFixed + MWs[3].barStyles.glass)
  MWs[3].Bars[i+5].threshold = i * 25
end
for i=1,4 do MWs[i]:Update() end
]]}

Demo["BarStyles-Frames"] = {text = [[
The complement to barStyles fills are frames.
The difference between .raised and .raisedCap is only noticable when the bar has 
a .captionPlacment of .left or .right; in which case, the frame extends around 
the caption as well.
]]
,
code = [[
MW = InfoBox:New("IBDemoFrames")
MW:AddBar("none", 80, "green", 0, false, MW.barStyles.solid)
MW:AddBar("sunken", 80, "green", 0, false, MW.barStyles.solid + MW.barStyles.sunken)
MW:AddBar("raised", 80, "green", 0, false, MW.barStyles.solid + MW.barStyles.raised)
MW:AddBar("raisedCap", 80, "green", 0, false, MW.barStyles.solid + MW.barStyles.raisedCap)
MW:AddBar("flat", 80, "green", 0, false, MW.barStyles.solid + MW.barStyles.flat)
MW:AddBar("glass", 80, "green", 0, false, MW.barStyles.solid + MW.barStyles.glass)
MW:Update()
]]}

Demo["Text"] = {text = [[
Simple text can be added by setting a bar's .caption value.
The Caption function sets the value, or if given a number,
it sets the caption with commas added to the ciphers.

The .textColour value is a number specifying the color of the text.
  (i.e. .textColour = 255, not "red")
The TextColour function will do the appropriate conversion between a color 
name, the (long) number value, and an HTML formatted hex string ("#FF00AA").

Text effects can be added with the .textStyle value. They are enumerated in the .textStyles table.
]], -- ']]
code = [[
MW = InfoBox:New("IBDemoText")
for i = 1,2 do MW:AddBar() end
MW.Bars[1].caption = "Sample Text" ; MW.Bars[1].textColour = 0x006600
MW.Bars[2]:Caption(100000)
MW:Update()


MW2 = InfoBox:New("IBDemoTextStyles")
local txtstyles ={"plain", "matte", "raised", "raised + matte", "sunken", "sunken + matte"} 
for i = 0,5 do
MW2:AddBar(txtstyles[i+1], 45, "dodgerblue", 0x272727, false, 65)
MW2.Bars[#MW2.Bars].textStyle = i
end
MW2:Update()
]]}


Demo["Text-Advanced"] = {text = [[
The ColourText function is designed to take a value, a threshold, and 3 colors; 
good, bad, neutral(optional). This is intended to simplify coloring changes to 
HP (-17, 0, "green", "red", "black"), or displaying your hp (MyHP, maxHP*.3, 
   "darkgreen", "red").
This function sets .textColour accordingly, and returns no value.

The caption also supports coloring syntax similar to the chat plugin, with 
the @ symbol denoting a color identifier. The 16 ansi values are set to 
MushClient's color settings (c,m,y,k,r,g,b,w & bolds C,M,Y,K...). Additional 
colors can be specified in a table attached to the .customColourCodes value 
on the bar or MiniWindow tables.
This table should have a single character key, and the number value of the
color. 

An  "@~" identifies the .textColour value in the caption.
]], --']]
code = [[
MW = InfoBox:New("IBDemoColor")
MW.customColourCodes = { O = colour_names.orange, I = colour_names.indigo }
MW:AddBar("@RR @Oa @Yi @Gn @Bb @Io @mw")
MW.Bars[1].textStyle = MW.textStyles.raised
HPGauge = MW:AddBar("", 75)
local hpCaptionFmt = "@kHP: %i/%i (@~%+3i@k)"
local hpDelta = -25
HPGauge:ColourText(hpDelta, 0, "green", "red", "black")
HPGauge.caption = hpCaptionFmt:format(530, 600, hpDelta)
MW:Update()
]]}

Demo["Text-Placement"] = {text =[[You should call CaptionPlacement() function when changing the value of .captionPlacement as it calculates the .gaugeLeft and .gaugeWidth values for you.
Bar:CaptionPlacement(x) sets and recalculates the column. MW:CaptionPlacement([x]) sets the default for bars, or recalculates all columns if left blank.
]] ,

code =[[MWs = {}
caps = { "left", "innerLeft", "innerRight","right", "center","centerCell", "both",}
for i = 1,7 do
 MWs[i] = InfoBox:New("IBDemoCap" .. i)
 MWs[i]:AddBar(caps[i],100) ; MWs[i]:AddBar(caps[i],100)
 MWs[i].Bars[1].captionPlacement = i-1
 MWs[i].Bars[2].captionPlacement = i-1
 if i > 4 then
    MWs[i].Bars[1].captionPlacement = i-1
    MWs[i].Bars[2].captionPlacement = 3
 end
 if i == 7 then
   MWs[i].Bars[1].captionPlacement = 0
 end
 MWs[i]:CaptionPlacement()
end
MWs[4].Bars[1].barStyle = MWs[4].barStyles.solid + MWs[4].barStyles.raised
MWs[4].Bars[2].barStyle = MWs[4].barStyles.solid + MWs[4].barStyles.raisedCap
for i = 1,7 do
MWs[i]:Update()
end
 
]]

}


Demo["MiniWindowGrid"] = { text =[[So far, you've seen an InfoBox window with a column of gauges. The InfoBox window is actually a grid.
The size and layout is determined by 3 values in the MiniWindow table, .rows, .columns, and .axis
The height of the MiniWindow is determined by the number of rows.
The width of the Miniwindow is determined by the .windowWidth value.
The size of the cell for the gauge and caption is the windowWidth divided by the number of columns.
The .axis value should be either "rows" or "columns" and determines which value is incremented if the grid is not large enough to display all bars.
Bars are displayed in columns, filling one before moving over to the top of the next.]], --']]

code = [[MW1 = InfoBox:New("IBDemoColumn")
MW1.axis = "columns"
MW1:AddBar("1",50) MW1:AddBar("2",50) MW1:AddBar("3",50) 
MW2 = InfoBox:New("IBDemoGrid")
MW2.columns = 2
MW2:AddBar("1",50) MW2:AddBar("2",50) MW2:AddBar("3",50) 
MW1:Update() MW2:Update()
]]} 


Demo["Text-Font"] = {text = [[Fonts can be specified on a per bar or per window basis. Module supplies the windowName and fontID values automatically, other optional values are:
"fontName", "fontSize", "fontBold", "fontItalic", "fontUnderline", "fontStrikeout", "fontCharset", "fontPitchAndFamily"

Calling :Font() with no parameters deletes the font on the specified object so that you can re-inherit from a parent object.
]],

code = [[MW = InfoBox:New("IBDemoFonts")
bar = MW:AddBar("Test") bar:Font("Sylvaen", 12)
bar = MW:AddBar("Test") bar:Font("Comic Sans MS", 14)
bar = MW:AddBar("Test") bar:Font("Courier New", 8)
MW:Update()
]]
}

Demo["MiniWindowPosition"] ={ text=[[The .windowPosition value should be read only; you should always use the :WindowPosition() function to set the value.
The positions are enumerated in the .windowPositions table. They are named after the cardinal points of the compass to help you remember. 
The N and S (north/top and south/bottom) automatically set the .axis value to "columns". The W,SW and S positions resize the output window to not overlap each other. InfoBox windows share screen space with other miniwindows from other plugins nicely. The resizing routines for the N and S windows won't overlap E and W windows. If there are enough windows, the module will size windows accordingly:
 WNNNNE
 W    E
 W    E
 SSSSSS
 
 Setting the .displaceOutput value to true will cause other window positions to resize the mud text area.]], --']]

code = [[SE = InfoBox:New("IBDemoSE") ; SE:AddBar() ; SE:AddBar() ; SE:AddBar() 
SE:WindowPosition(SE.windowPositions.SE)
MW = InfoBox:New("IBDemoWinPosS")
MW:WindowPosition(MW.windowPositions.S)
MW:AddBar("Hi") MW:AddBar("There") 
MW2 = InfoBox:New("IBDemoWinPosE")
MW2:AddBar("Default")
SE:Update() MW:Update() MW2:Update()
]]

}


Demo["BarSpacing"] ={ text=[[You can tweak the appearance of gauges with the following values:
.fontHeight is set automatically from the loaded font's properties. Don't change it. :)
.cellPadding is added to .fontHeight to generate the default value for .cellHeight
.cellHeight actually determines the bottom edge of the gauge.
.gaugeHeight is subtracted from cellHeight to get the top edge of the gauge.
.padding is added to cellHeight before drawing the next Bar.
.fontPadding is used to adjust the text position. It's added from the top of the cell.]], --']]

code = [[MW = InfoBox:New("IBDemoFunky")
a = MW:AddBar("First", 50) ; a.padding = 10
b = MW:AddBar("Second", 50)
c = MW:AddBar("Third", 50) ; c.fontPadding = 0
d = MW:AddBar("Fourth", 50) ; d.gaugeHeight = d.cellHeight *.5 ; d.textStyle=1
e = MW:AddBar("Fifth", 50)
MW:Update()

]]

}
Demo["Watches"] ={ text=[[There are 2 more convenient functions in the bar object.
The WatchCaption() and WatchValue() functions take the name of a variable and use the contents of that variable for the respective property values.
This can simplify your prompt triggers. Clearing them is done by setting a specific value with the Caption() or Value() functions.]],

code = [[myVars ={hp=100, maxHp=200} myVars.percentHP=(myVars.hp/myVars.maxHp)*100

MW = InfoBox:New("IBDemoWatch")
MW:AddBar()
MW.Bars[1]:WatchValue("myVars.percentHP")
MW:Update()
--myVars.percentHP = 20 ; MW:Update()
--myVars.percentHP = 80 ; MW:Update()
--etc...

]]

}
Demo["Misc"] ={ text=[[The CloseWindow() and ReloadFonts() functions are for plugin authors and Disable/enable features.
The Resize() function is useful for the PluginOnWorldOutputResized callback for InfoBoxes positioned at the top or bottom.

The Update function will only redraw once a second, to prevent slamming the CPU during speedwalks. It returns true or false on whether it did update. This is useful for keeping displayed Deltas in sync.

The CaptionPlacement() function uses a different algorithm for determining a bar's column placement than the Update() and Resize() functions.
The CaptionPlacement() routine just uses the bar.id modulo .columns to determine which column a bar is in.

  This Update() routine enables the following behaviour when, for example:
  You have a 2x3 grid, 5 bars, and bar #3 is a larger font size than the other bars; the grid will shift bar 4 to the next column so that it can be as short as possible.
  
  The difference in algorithms means that if bar 3's .captionPlacement is left, but bar 4's .captionPlacement is innerLeft, bar 4's .gaugeLeft and .gaugeWidth are still set as if it draws in column 2.
  Reset bar4's .gaugeLeft and .gaugeWidth manually in this fringe case.
]],

code = [[local wp = InfoBox.windowPositions
MW=InfoBox:New("IBDemoBug") ; 
MW.windowWidth = 400 ; MW.rows=2 ; MW.columns = 3 
for i=1,5 do MW:AddBar("Blah",75,"blue") end
A = MW.Bars[3] ; A.caption = "Big" ; A:Font("Comic Sans MS", 16) 
A:CaptionPlacement(A.captionPlacements.left)
B = MW.Bars[4] ; B.caption = "Oops" ; B:TextColour("cyan")

MW2 = InfoBox:New("IBDemoBugWorkaround") 
MW2.windowWidth = 400 ; MW2.rows=2 ; MW2.columns = 3 
for i=1,5 do MW2:AddBar("Whee",75,"cyan") end
C = MW2.Bars[3] ; C.caption = "Big" ; C:Font("Comic Sans MS", 16) 
C:CaptionPlacement(C.captionPlacements.left)
D = MW2.Bars[4] ; D.caption = "Fixed" 
D.gaugeWidth = nil ; D.gaugeLeft = nil
MW:Update() ; MW2:Update()]]

}
Demo["Putting-It-Together"] ={ text=[[Here's a sample from my own character.]],

code = [[sty = InfoBox.barStyles
HPBox = InfoBox:New("IBDemoHP")
	HPBox.Bar.textStyle = HPBox.textStyles.sunken
	HPBox.Bar.barStyle = sty.glass + sty.gradientFixed
HPBar 	  = HPBox:AddBar("HP", 0, "green", "firebrick", false)
	HPBar.threshold = 52
	HPBar:WatchValue ("vars.pHP")
HPStatus = HPBox:AddBar("",0,0,0,false,0)
HPStatus.textStyle = 1
KarmaBar  =	HPBox:AddBar("Karma", 0,"dodgerblue", "firebrick", false)
	KarmaBar.threshold = 40
	KarmaBar:WatchValue("vars.pKarma")
KStatus = HPBox:AddBar("",0,0,0,false,0)
KStatus:TextColour ("peachpuff")
KStatus.captionPlacement = 4
SPBar 	  =	HPBox:AddBar("SP", 0, "deepskyblue", "dimgray", false, sty.glass + sty.gradientShift)
	SPBar:WatchValue("vars.pSP")
VoiceBar  =	HPBox:AddBar("Voice", 0, "mediumpurple", "indigo", false, sty.glass + sty.gradientScale)
	VoiceBar:WatchValue("vars.cVoice")
EnemyBar = HPBox:AddBar("", 0, 0x222222, 0x000070, true, sty.glass + sty.gradientScale)
	EnemyBar.fade = true ; EnemyBar.threshold = 10
	EnemyBar.textStyle = 1
	EnemyBar:CaptionPlacement(1)
HPBox:WindowPosition ( InfoBox.windowPositions.S )
HPBox:Rows  (2)
HPBox:Columns(4)
--Following values are normally set by other triggers.
vars = {pHP = 90, pSP=80, cVoice = 57, pKarma = 85}
EnemyBar.caption = "Bad Guy" ; EnemyBar.value = 65
KStatus.caption = "Perfoming: Amazing Grace"
HPStatus.caption = " HP: 900/1027 (@G+25@~)"
HPBox:Update()
]]

}

for i,v in ipairs (Demo) do Demo[v].NextTopic = Demo[i+1] or Demo[1] end

function OnPluginInstall()
  Demofunc(nil,nil,{"Intro"})
end

]]>
</script>


<!--  Plugin help  -->

<aliases>
  <alias
   script="OnHelp"
   match="InfoBox_Demo:help"
   enabled="y"
  >
  </alias>
</aliases>

<script>
<![CDATA[
function OnHelp ()
  world.Note (world.GetPluginInfo (world.GetPluginID (), 3))
end
]]>
</script> 

</muclient>
