Quantcast

Redo config and prepare for profiles

p3lim [11-08-10 - 22:53]
Redo config and prepare for profiles
Filename
config/configuration.lua
config/module.checkbox.lua
config/module.dropdown.lua
config/module.palette.lua
config/module.slider.lua
libs/LibConfig-1.0.lua
pMinimap.lua
pMinimap.toc
diff --git a/config/configuration.lua b/config/configuration.lua
deleted file mode 100644
index 67f9e60..0000000
--- a/config/configuration.lua
+++ /dev/null
@@ -1,178 +0,0 @@
-local _, ns = ...
-
-local LSM = LibStub('LibSharedMedia-3.0')
-local OBJECTS = {
-	Zone = 'MinimapZoneTextButton',
-	Difficulty = 'MiniMapInstanceDifficulty',
-	Battlefield = 'MiniMapBattlefieldFrame',
-	Dungeon = 'MiniMapLFGFrame',
-	Tracking = 'MiniMapTracking',
-	Clock = 'TimeManagerClockButton',
-	Mail = 'MiniMapMailFrame',
-}
-
-function ns.UpdateObjects()
-	for name, setting in pairs(pMinimapDB.objects) do
-		local object = _G[OBJECTS[name]]
-
-		if(setting.shown) then
-			object:SetAlpha(1)
-			object:EnableMouse(true)
-		else
-			object:SetAlpha(0)
-			object:EnableMouse(false)
-		end
-
-		object:ClearAllPoints()
-		object:SetPoint(setting.point)
-	end
-end
-
-function ns.UpdateCore()
-	Minimap:SetScale(pMinimapDB.minimap.scale)
-	Minimap:SetFrameStrata(pMinimapDB.minimap.strata)
-	Minimap:SetFrameLevel(pMinimapDB.minimap.level)
-
-	local size = pMinimapDB.minimap.borderSize
-	Minimap:SetBackdrop({bgFile = [=[Interface\ChatFrame\ChatFrameBackground]=], insets = {left = -size, right = -size, top = -size, bottom = -size}})
-	Minimap:SetBackdropColor(unpack(pMinimapDB.minimap.borderColors))
-end
-
-function ns.UpdateFont()
-	local font, size = LSM:Fetch('font', pMinimapDB.font.name), pMinimapDB.font.size
-	local flag = pMinimapDB.font.shadow .. (pMinimapDB.font.monochrome and 'MONOCHROME' or '')
-
-	MinimapZoneText:SetFont(font, size, flag)
-	TimeManagerClockTicker:SetFont(font, size, flag)
-end
-
-function ns.UpdatePosition(save)
-	if(save) then
-		local point, _, _, x, y = Minimap:GetPoint()
-		pMinimapDB.minimap.position = string.format('%s\031%d\031%d', point, x, y)
-	else
-		local point, x, y = string.split('\031', pMinimapDB.minimap.position)
-		Minimap:ClearAllPoints()
-		Minimap:SetPoint(point, UIParent, point, x, y)
-	end
-end
-
-local function AddConfig(name, func)
-	local group = CreateFrame('Frame', nil, InterfaceOptionsFramePanelContainer)
-	group.name = name
-	group:SetScript('OnShow', func)
-	group:HookScript('OnShow', function(self) self:SetScript('OnShow', nil) end)
-
-	if(name ~= 'pMinimap') then
-		group.parent = 'pMinimap'
-		group.addonname = 'pMinimap'
-	end
-
-	InterfaceOptions_AddCategory(group)
-end
-
-AddConfig('pMinimap', function(self)
-	local scale = ns.slider(self, 'Scale', '%.1f', pMinimapDB.minimap.scale, 0.5, 2.5, 0.1, 'TOPLEFT', 30, -30)
-	scale:HookScript('OnValueChanged', function(frame, value)
-		pMinimapDB.minimap.scale = value
-		ns.UpdateCore()
-	end)
-
-	local unlock = ns.checkbox(self, 'Unlocked', 'TOPLEFT', 30, -80)
-	unlock:SetChecked(ns.UNLOCKED)
-	unlock:SetScript('OnClick', function()
-		ns.UNLOCKED = not ns.UNLOCKED
-		unlock:SetChecked(ns.UNLOCKED)
-	end)
-
-	local level = ns.slider(self, 'Frame Level', '%d', pMinimapDB.minimap.level, 0, 10, 1, 'TOPRIGHT', -30, -30)
-	level:HookScript('OnValueChanged', function(frame, value)
-		pMinimapDB.minimap.level = value
-		ns.UpdateCore()
-	end)
-
-	local strata = ns.dropdown(self, 'Frame Strata', pMinimapDB.minimap.strata, {'HIGH', 'MEDIUM', 'LOW', 'BACKGROUND'},
-		function(self)
-			pMinimapDB.minimap.strata = self.value
-			ns.UpdateCore()
-		end)
-	strata:SetPoint('TOPRIGHT', -10, -80)
-
-	local background1 = self:CreateTexture(nil, 'BACKGROUND')
-	background1:SetPoint('TOPLEFT', scale, -20, 20)
-	background1:SetPoint('BOTTOMRIGHT', strata, 0, -5)
-	background1:SetTexture(0, 0, 0, 0.5)
-
-	local borderSize = ns.slider(self, 'Border Thickness', '%d', pMinimapDB.minimap.borderSize, 0, 10, 1, 'LEFT', 30, 0)
-	borderSize:HookScript('OnValueChanged', function(frame, value)
-		pMinimapDB.minimap.borderSize = value
-		ns.UpdateCore()
-	end)
-
-	local borderColor = ns.palette(self, 'Border Color', pMinimapDB.minimap.borderColors, 'RIGHT', -130, 0)
-
-	local background2 = self:CreateTexture(nil, 'BACKGROUND')
-	background2:SetPoint('TOPLEFT', borderSize, -20, 20)
-	background2:SetPoint('BOTTOMRIGHT', borderColor, 120, -20)
-	background2:SetTexture(0, 0, 0, 0.5)
-
-	ns.dropdown(self, 'Font', pMinimapDB.font.name, LSM:List('font'),
-		function(self)
-			pMinimapDB.font.name = self.value
-			ns.UpdateFont()
-		end
-	):SetPoint('BOTTOMLEFT', 10, 20)
-
-	local size = ns.slider(self, 'Font Size', '%d', pMinimapDB.font.size, 6, 36, 1, 'BOTTOMLEFT', 30, 80)
-	size:HookScript('OnValueChanged', function(frame, value)
-		pMinimapDB.font.size = value
-		ns.UpdateFont()
-	end)
-
-	local shadow = ns.dropdown(self, 'Font Shadow', pMinimapDB.font.shadow, {'OUTLINE', 'THICKOUTLINE', 'NONE'},
-		function(self)
-			pMinimapDB.font.shadow = self.value
-			ns.UpdateFont()
-		end)
-	shadow:SetPoint('BOTTOMRIGHT', -10, 20)
-
-	local monochrome = ns.checkbox(self, 'Monochrome', 'BOTTOMRIGHT', -140, 75)
-	monochrome:SetChecked(pMinimapDB.font.monochrome)
-	monochrome:SetScript('OnClick', function()
-		pMinimapDB.font.monochrome = not pMinimapDB.font.monochrome
-		ns.UpdateFont()
-	end)
-
-	local background3 = self:CreateTexture(nil, 'BACKGROUND')
-	background3:SetPoint('TOPLEFT', size, -20, 20)
-	background3:SetPoint('BOTTOMRIGHT', shadow, 0, -5)
-	background3:SetTexture(0, 0, 0, 0.5)
-end)
-
-AddConfig('Objects', function(self)
-	local points = {'TOPLEFT', 'TOP', 'TOPRIGHT', 'LEFT', 'CENTER', 'RIGHT', 'BOTTOMLEFT', 'BOTTOM', 'BOTTOMRIGHT'}
-	local offset = 25
-
-	for name, setting in pairs(pMinimapDB.objects) do
-		local shown = ns.checkbox(self, name, 'TOPLEFT', 25, -offset)
-		shown:SetChecked(setting.shown)
-		shown:SetScript('OnClick', function()
-			setting.shown = not setting.shown
-			ns.UpdateObjects()
-		end)
-
-		local position = ns.dropdown(self, name..' Position', setting.point, points,
-			function(self)
-				setting.point = self.value
-				ns.UpdateObjects()
-			end)
-		position:SetPoint('TOPRIGHT', -10, -offset)
-
-		local background = self:CreateTexture(nil, 'BACKGROUND')
-		background:SetPoint('TOPLEFT', shown, -15, 15)
-		background:SetPoint('BOTTOMRIGHT', position)
-		background:SetTexture(0, 0, 0, 0.4)
-
-		offset = offset + 60
-	end
-end)
diff --git a/config/module.checkbox.lua b/config/module.checkbox.lua
deleted file mode 100644
index 8be23f9..0000000
--- a/config/module.checkbox.lua
+++ /dev/null
@@ -1,24 +0,0 @@
-local _, ns = ...
-
-local NORMAL = [=[Interface\Buttons\UI-CheckBox-Up]=]
-local PUSHED = [=[Interface\Buttons\UI-CheckBox-Down]=]
-local CHECKED = [=[Interface\Buttons\UI-CheckBox-Check]=]
-local HIGHLIGHT = [=[Interface\Buttons\UI-CheckBox-Highlight]=]
-
-function ns.checkbox(parent, str, ...)
-	local button = CreateFrame('CheckButton', nil, parent)
-	button:SetPoint(...)
-	button:SetSize(26, 26)
-	button:SetHitRectInsets(0, -100, 0, 0)
-
-	button:SetNormalTexture(NORMAL)
-	button:SetPushedTexture(PUSHED)
-	button:SetCheckedTexture(CHECKED)
-	button:SetHighlightTexture(HIGHLIGHT)
-
-	local label = button:CreateFontString(nil, 'ARTWORK', 'GameFontHighlight')
-	label:SetPoint('LEFT', button, 'RIGHT', 0, 1)
-	label:SetText(str)
-
-	return button
-end
diff --git a/config/module.dropdown.lua b/config/module.dropdown.lua
deleted file mode 100644
index 0687bce..0000000
--- a/config/module.dropdown.lua
+++ /dev/null
@@ -1,40 +0,0 @@
-local _, ns = ...
-
-local GLUE = [=[Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame]=]
-local NORMAL = [=[Interface\ChatFrame\UI-ChatIcon-ScrollDown-Up]=]
-local PUSHED = [=[Interface\ChatFrame\UI-ChatIcon-ScrollDown-Down]=]
-local HIGHLIGHT = [=[Interface\Buttons\UI-Common-MouseHilight]=]
-
-function ns.dropdown(parent, str, default, values, func)
-	local container = CreateFrame('Button', nil, parent)
-	container:SetSize(180, 30)
-
-	local frame = CreateFrame('Frame', 'pMinimapDropDown'..str, parent, 'UIDropDownMenuTemplate')
-	frame:SetPoint('TOPLEFT', container)
-	frame:EnableMouse(true)
-
-	UIDropDownMenu_SetWidth(frame, 130)
-	UIDropDownMenu_Initialize(frame, function()
-		local info = UIDropDownMenu_CreateInfo()
-		info.notCheckable = true
-		info.func = function(self)
-			_G[frame:GetName()..'Text']:SetText(self.value)
-			func(self)
-		end
-
-		for _, value in pairs(values) do
-			info.text = value
-			info.value = value
-			UIDropDownMenu_AddButton(info)
-		end
-	end)
-
-	local label = container:CreateFontString(nil, 'BACKGROUND', 'GameFontNormalSmall')
-	label:SetPoint('BOTTOM', container, 'TOP')
-	label:SetText(str)
-
-	_G['pMinimapDropDown'..str..'Text']:SetText(default)
-
-	return container
-end
-
diff --git a/config/module.palette.lua b/config/module.palette.lua
deleted file mode 100644
index 5fb7c96..0000000
--- a/config/module.palette.lua
+++ /dev/null
@@ -1,73 +0,0 @@
-local _, ns = ...
-
-local SWATCH = [=[Interface\ChatFrame\ChatFrameColorSwatch]=]
-local CHECKERS = [=[Tileset\Generic\Checkers]=]
-
-local function OnClick(self)
-	HideUIPanel(ColorPickerFrame)
-
-	local origR, origG, origB, origA = unpack(pMinimapDB.minimap.borderColors)
-	ColorPickerFrame:SetFrameStrata('FULLSCREEN_DIALOG')
-	ColorPickerFrame.func = function()
-		local r, g, b = ColorPickerFrame:GetColorRGB()
-		local a = 1 - OpacitySliderFrame:GetValue()
-		self.swatch:SetVertexColor(r, g, b, a)
-		pMinimapDB.minimap.borderColors = {r, g, b, a}
-		ns.UpdateCore()
-	end
-
-	ColorPickerFrame.hasOpacity = true
-	ColorPickerFrame.opacityFunc = function()
-		local r, g, b = ColorPickerFrame:GetColorRGB()
-		local a = 1 - OpacitySliderFrame:GetValue()
-		self.swatch:SetVertexColor(r, g, b, a)
-		pMinimapDB.minimap.borderColors = {r, g, b, a}
-		ns.UpdateCore()
-	end
-
-	ColorPickerFrame.cancelFunc = function()
-		self.swatch:SetVertexColor(origR, origG, origB, origA)
-		pMinimapDB.minimap.borderColors = {origR, origG, origB, origA}
-		ns.UpdateCore()
-	end
-
-	ColorPickerFrame.opacity = 1 - origA
-	ColorPickerFrame:SetColorRGB(origR, origG, origB)
-	ShowUIPanel(ColorPickerFrame)
-end
-
-function ns.palette(parent, str, default, ...)
-	local container = CreateFrame('Button', nil, parent)
-	container:SetPoint(...)
-	container:SetSize(22, 22)
-	container:SetHitRectInsets(0, -100, 0, 0)
-	container:SetScript('OnClick', OnClick)
-	container:EnableMouse(true)
-
-	local swatch = container:CreateTexture(nil, 'OVERLAY')
-	swatch:SetAllPoints()
-	swatch:SetTexture(SWATCH)
-	swatch:SetVertexColor(unpack(default))
-	container.swatch = swatch
-
-	local background = container:CreateTexture(nil, 'BACKGROUND')
-	background:SetPoint('CENTER')
-	background:SetSize(18, 18)
-	background:SetTexture(1, 1, 1)
-
-	local checkers = container:CreateTexture(nil, 'BACKGROUND')
-	checkers:SetPoint('CENTER')
-	checkers:SetSize(17, 17)
-	checkers:SetTexture(CHECKERS)
-	checkers:SetTexCoord(0.25, 0, 0.5, 0.25)
-	checkers:SetDesaturated(true)
-	checkers:SetVertexColor(1, 1, 1, 0.75)
-
-	local label = container:CreateFontString(nil, 'OVERLAY', 'GameFontHighlight')
-	label:SetPoint('LEFT', swatch, 'RIGHT', 2, 0)
-	label:SetHeight(24)
-	label:SetJustifyH('LEFT')
-	label:SetText(str)
-
-	return container
-end
diff --git a/config/module.slider.lua b/config/module.slider.lua
deleted file mode 100644
index 71a918b..0000000
--- a/config/module.slider.lua
+++ /dev/null
@@ -1,77 +0,0 @@
-local _, ns = ...
-
-local THUMB = [=[Interface\Buttons\UI-SliderBar-Button-Horizontal]=]
-local SLIDER = {
-	bgFile = [=[Interface\Buttons\UI-SliderBar-Background]=],
-	edgeFile = [=[Interface\Buttons\UI-SliderBar-Border]=],
-	edgeSize = 8, tile = true, tileSize = 8,
-	insets = {left = 3, right = 3, top = 6, bottom = 6},
-}
-
-local EDITBOX = {
-	bgFile = [=[Interface\ChatFrame\ChatFrameBackground]=],
-	edgeFile = [=[Interface\ChatFrame\ChatFrameBackground]=],
-	tile = true, edgeSize = 1, tileSize = 5,
-}
-
-local function OnEnterPressed(self)
-	local value = tonumber(self:GetText())
-	if(value) then
-		PlaySound('igMainMenuOptionCheckBoxOn')
-		self:GetParent():SetValue(value)
-	end
-end
-
-local function OnEnter(self)
-	self:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
-end
-
-local function OnLeave(self)
-	self:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
-end
-
-function ns.slider(parent, str, formatting, cur, min, max, step, ...)
-	local slider = CreateFrame('Slider', nil, parent)
-	slider:SetPoint(...)
-	slider:SetSize(144, 16)
-	slider:SetBackdrop(SLIDER)
-	slider:SetThumbTexture(THUMB)
-	slider:SetOrientation('HORIZONTAL')
-	slider:SetMinMaxValues(min, max)
-	slider:SetValueStep(step)
-	slider:SetValue(cur)
-
-	local left = slider:CreateFontString(nil, 'ARTWORK', 'GameFontHighlightSmall')
-	left:SetPoint('TOPLEFT', slider, 'BOTTOMLEFT', -4, 3)
-	left:SetText(min)
-
-	local right = slider:CreateFontString(nil, 'ARTWORK', 'GameFontHighlightSmall')
-	right:SetPoint('TOPRIGHT', slider, 'BOTTOMRIGHT', 4, 3)
-	right:SetText(max)
-
-	local label = slider:CreateFontString(nil, 'ARTWORK', 'GameFontNormal')
-	label:SetPoint('BOTTOM', slider, 'TOP')
-	label:SetText(str)
-
-	local editbox = CreateFrame('EditBox', nil, slider)
-	editbox:SetPoint('TOP', slider, 'BOTTOM')
-	editbox:SetSize(40, 14)
-	editbox:SetAutoFocus(false)
-	editbox:SetFontObject(GameFontHighlightSmall)
-	editbox:SetBackdrop(EDITBOX)
-	editbox:SetBackdropColor(0, 0, 0, 0.5)
-	editbox:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
-	editbox:EnableMouse(true)
-	editbox:SetScript('OnEnter', OnEnter)
-	editbox:SetScript('OnLeave', OnLeave)
-	editbox:SetScript('OnEnterPressed', OnEnterPressed)
-	editbox:SetScript('OnEscapePressed', editbox.ClearFocus)
-	editbox:SetJustifyH('CENTER')
-	editbox:SetText(string.format(formatting, cur))
-
-	slider:SetScript('OnValueChanged', function(self, value)
-		editbox:SetText(string.format(formatting, value))
-	end)
-
-	return slider
-end
diff --git a/libs/LibConfig-1.0.lua b/libs/LibConfig-1.0.lua
new file mode 100644
index 0000000..f54ca1e
--- /dev/null
+++ b/libs/LibConfig-1.0.lua
@@ -0,0 +1,439 @@
+local LibConfig = LibStub:NewLibrary('LibConfig-1.0', 40000.1)
+
+local panels, lib, args = {}, {}, {}
+LibConfig.panels = panels
+LibConfig.lib = lib
+
+local function getArgs(...)
+	wipe(args)
+	for index = 1, select('#', ...), 2 do
+		local k, v = select(index, ...)
+		args[k] = v
+	end
+
+	return args
+end
+
+do
+	-- XXX: fix/control
+	local function _okay(self)
+		for control in pairs(self.controls) do
+			control.oldValue = control.value
+			if(control.okayFunc) then
+				control.okayFunc()
+			end
+		end
+	end
+
+	-- XXX: fix/control
+	local function _cancel(self)
+		for control in pairs(self.controls) do
+			control.value = control.oldValue
+			control.setValue(control)
+			if(control.cancelFunc) then
+				control.cancelFunc()
+			end
+		end
+	end
+
+	-- XXX: fix/control
+	local function _default(self)
+		for control in pairs(self.controls) do
+			control.value = control.default
+			control.setValue(control)
+			if(control.defaultFunc) then
+				control.defaultFunc()
+			end
+		end
+	end
+
+	function LibConfig.AddConfig(name, parent, func, globalName)
+		if(parent) then
+			globalName = parent .. 'Config' .. name
+		else
+			globalName = name .. 'Configa'
+		end
+
+		local group = CreateFrame('Frame', globalName, InterfaceOptionsFramePanelContainer)
+		group.name = name
+		group.parent = parent
+		group.addonname = parent
+
+		group.controls = {}
+		group.okay = _okay
+		group.cancel = _cancel
+		group.default = _default
+
+		group:SetScript('OnShow', func)
+		group:HookScript('OnShow', function(self)
+			self:SetScript('OnShow', nil)
+		end)
+
+		InterfaceOptions_AddCategory(group)
+
+		panels[group] = true
+		for type, func in pairs(lib) do
+			group[type] = func
+		end
+
+		return group
+	end
+
+	function LibConfig.AddCommand(name, ...)
+		for index = 1, select('#', ...) do
+			_G['SLASH_'.. name .. index] = select(index, ...)
+		end
+
+		SlashCmdList[name] = function()
+			InterfaceOptionsFrame_OpenToCategory(name)
+		end
+	end
+end
+
+do
+	local function _onClick(self)
+		self.setFunc(self.value)
+		self:SetChecked(self.value)
+	end
+
+	local function _onClickWrapper(self)
+		self.value = not self.value
+		_onClick(self)
+	end
+
+	function lib:CreateCheckBox(...)
+		local args = getArgs(...)
+		local i, globalName = 0
+		repeat
+			i = i + 1
+			globalName = self:GetName() .. 'CheckButton' .. i
+		until not _G[globalName]
+
+		local object = CreateFrame('CheckButton', globalName, self, 'InterfaceOptionsCheckButtonTemplate')
+		local text = _G[globalName .. 'Text']
+		text:SetText(args.name)
+		object:SetHitRectInsets(0, - text:GetWidth() - 1, 0, 0)
+		object:SetScript('OnClick', _onClickWrapper)
+
+		object.default = args.default
+		object.value = args.getFunc()
+		object.oldValue = object.value or object.default
+
+		object.getFunc = args.getFunc
+		object.setFunc = args.setFunc
+		object.okayFunc = args.okayFunc
+		object.cancelFunc = args.cancelFunc
+		object.defaultFunc = args.defaultFunc
+
+		object:SetChecked(args.getFunc())
+		object.setValue = _onClick
+		self.controls[object] = true
+		return object
+	end
+end
+
+do
+	local function dummy() end
+
+	local function _onClick(self)
+		self.setFunc()
+	end
+
+	function lib:CreateButton(...)
+		local args = getArgs(...)
+		local i, globalName = 0
+		repeat
+			i = i + 1
+			globalName = self:GetName() .. 'Button' .. i
+		until not _G[globalName]
+
+		local object = CreateFrame('Button', globalName, self, 'UIPanelButtonTemplate2')
+		object:SetSize(90, 22)
+		object:SetScript('OnClick', _onClick)
+		object:SetText(args.name)
+
+		object.setFunc = args.setFunc
+		object.getFunc = dummy
+
+		object.setValue = dummy
+		self.controls[object] = true
+		return object
+	end
+end
+
+do
+	local function _value(self)
+		UIDropDownMenu_SetSelectedValue(self, self.value)
+		self.setFunc(self.value)
+	end
+
+	local function _valueWrapper(button, self, value)
+		self.value = value
+		_value(self)
+	end
+
+	local function _menu(self)
+		for value, text in pairs(self.values) do
+			local info = UIDropDownMenu_CreateInfo()
+			info.text = text
+			info.value = value
+			info.checked = self.value == value
+			info.func = _valueWrapper
+			info.arg1 = self
+			info.arg2 = value
+			UIDropDownMenu_AddButton(info)
+		end
+	end
+
+	function lib:CreateDropDown(...)
+		local args = getArgs(...)
+		local i, globalName = 0
+		repeat
+			i = i + 1
+			globalName = self:GetName() .. 'DropDown' .. i
+		until not _G[globalName]
+
+		local object = CreateFrame('Frame', globalName, self, 'UIDropDownMenuTemplate')
+		object:EnableMouse(true)
+
+		local label = object:CreateFontString(nil, 'BACKGROUND', 'GameFontNormal')
+		label:SetPoint('BOTTOMLEFT', object, 'TOPLEFT', 16, 3)
+		label:SetText(args.name)
+
+		object.values = args.values
+		object.default = args.default
+		object.value = args.getFunc()
+		object.oldValue = object.value or object.default
+
+		object.getFunc = args.getFunc
+		object.setFunc = args.setFunc
+		object.okayFunc = args.okayFunc
+		object.cancelFunc = args.cancelFunc
+		object.defaultFunc = args.defaultFunc
+
+		UIDropDownMenu_SetWidth(object, args.width or 130)
+		UIDropDownMenu_Initialize(object, _menu)
+		UIDropDownMenu_SetSelectedValue(object, args.getFunc())
+
+		object.setValue = _value
+		self.controls[object] = true
+		return object
+	end
+end
+
+do
+	local _backdrop = {
+		bgFile = [=[Interface\ChatFrame\ChatFrameBackground]=],
+		edgeFile = [=[Interface\ChatFrame\ChatFrameBackground]=],
+		tile = true, edgeSize = 1, tileSize = 5,
+	}
+
+	local function _value(self)
+		self.setFunc(self.value)
+		_G[self:GetName() .. 'EditBox']:SetText(self.currentTextFunc(self.value))
+	end
+
+	local function _onValueChanged(self)
+		self.value = self:GetValue()
+		_value(self)
+	end
+
+	local function _onEnterPressed(self)
+		local object = self:GetParent()
+		local value = tonumber(self:GetText())
+		local min, max = object:GetMinMaxValues()
+
+		if(value and (value <= max and value >= min)) then
+			object.value = value
+		end
+
+		_value(object)
+	end
+
+	local function _onEnter(self)
+		self:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
+	end
+
+	local function _onLeave(self)
+		self:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
+	end
+
+	function lib:CreateSlider(...)
+		local args = getArgs(...)
+		local i, globalName = 0
+		repeat
+			i = i + 1
+			globalName = self:GetName() .. 'Slider' .. i
+		until not _G[globalName]
+
+		local object = CreateFrame('Slider', globalName, self, 'OptionsSliderTemplate')
+		object.currentTextFunc = args.currentTextFunc
+		object.default = args.default
+		object.value = args.getFunc()
+		object.oldValue = object.value or object.default
+
+		object.getFunc = args.getFunc
+		object.setFunc = args.setFunc
+		object.okayFunc = args.okayFunc
+		object.cancelFunc = args.cancelFunc
+		object.defaultFunc = args.defaultFunc
+
+		object:SetScript('OnValueChanged', _onValueChanged)
+		object:SetMinMaxValues(args.minValue, args.maxValue)
+		object:SetValueStep(args.step)
+
+		_G[globalName .. 'Text']:SetText(args.name)
+		_G[globalName .. 'High']:SetText(tostring(args.maxValue))
+		_G[globalName .. 'Low']:SetText(tostring(args.minValue))
+
+		local editbox = CreateFrame('EditBox', globalName .. 'EditBox', object)
+		editbox:SetPoint('TOP', object, 'BOTTOM')
+		editbox:SetSize(40, 14)
+		editbox:SetAutoFocus(false)
+		editbox:SetFontObject(GameFontHighlightSmall)
+		editbox:SetBackdrop(_backdrop)
+		editbox:SetBackdropColor(0, 0, 0, 0.5)
+		editbox:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
+		editbox:EnableMouse(true)
+		editbox:SetScript('OnEnter', _onEnter)
+		editbox:SetScript('OnLeave', _onLeave)
+		editbox:SetScript('OnEnterPressed', _onEnterPressed)
+		editbox:SetScript('OnEscapePressed', editbox.ClearFocus)
+		editbox:SetJustifyH('CENTER')
+		editbox:SetText(args.currentTextFunc(args.getFunc()))
+
+		object:SetValue(args.getFunc())
+		object.setValue = _value
+		self.controls[object] = true
+		return object
+	end
+end
+
+do
+	local function _value(self)
+		local r, g, b, a = unpack(self.value)
+		if(not self.hasAlpha) then
+			a = 1
+		else
+			self.info.opacity = a
+		end
+
+		self.info.r, self.info.g, self.info.b = r, g, b
+
+		self.color:SetTexture(r, g, b, a)
+		self.value = {r, g, b, a}
+		self.setFunc(r, g, b, a)
+	end
+
+	local function _onClick(self)
+		OpenColorPicker(self.info)
+	end
+
+	local function _swatchFunc(self)
+		local r, g, b = ColorPickerFrame:GetColorRGB()
+		local a = 1 - OpacitySliderFrame:GetValue()
+
+		self.value = {r, g, b, a}
+		_value(self)
+	end
+
+	local function _cancelFunc(self)
+		local prev = ColorPickerFrame.previousValues
+		local r, g, b, a = prev.r, prev.g, prev.b, 1 - prev.opacity
+
+		self.value = {r, g, b, a}
+		_value(self)
+	end
+
+	function lib:CreatePalette(...)
+		local args = getArgs(...)
+		local i, globalName = 0
+		repeat
+			i = i + 1
+			globalName = self:GetName() .. 'Palette' .. i
+		until not _G[globalName]
+
+		local object = CreateFrame('Button', globalName, self)
+		object:SetScript('OnClick', _onClick)
+		object:RegisterForClicks('LeftButtonUp')
+		object:SetSize(26, 26)
+
+		local label = object:CreateFontString(nil, 'OVERLAY', 'GameFontHighlight')
+		label:SetPoint('LEFT', object, 'RIGHT', 0, 1)
+		label:SetText(args.name)
+		object:SetHitRectInsets(0, - label:GetWidth() - 1, 0, 0)
+
+		local currentR, currentG, currentB, currentA = args.getFunc()
+		object.hasAlpha = args.hasAlpha
+		object.default = {unpack(args.default)}
+		object.value = {currentR, currentG, currentB, defaultA}
+		object.oldValue = object.value or object.default
+
+		object.getFunc = args.getFunc
+		object.setFunc = args.setFunc
+		object.okayFunc = args.okayFunc
+		object.cancelFunc = args.cancelFunc
+		object.defaultFunc = args.defaultFunc
+
+		local color = object:CreateTexture(nil, 'ARTWORK')
+		color:SetPoint('CENTER')
+		color:SetSize(14, 14)
+		color:SetTexture(currentR, currentG, currentB, currentA)
+
+		local background = object:CreateTexture(nil, 'BORDER')
+		background:SetPoint('CENTER')
+		background:SetSize(14, 14)
+		background:SetTexture([=[Tileset\Generic\Checkers]=])
+		background:SetTexCoord(0, 0.5, 0, 0.5)
+
+		local border = object:CreateTexture(nil, 'BACKGROUND')
+		border:SetAllPoints()
+		border:SetTexture([=[Interface\ChatFrame\ChatFrameColorSwatch]=])
+
+		local function swatchFunc_wrapper()
+			_swatchFunc(object)
+		end
+
+		local function cancelFunc_wrapper()
+			_cancelFunc(object)
+		end
+
+		object.color = color
+		object.info = {
+			swatchFunc = swatchFunc_wrapper,
+			cancelFunc = cancelFunc_wrapper,
+			hasOpacity = args.hasAlpha,
+			r = currentR,
+			g = currentG,
+			b = currentB,
+		}
+
+		if(not args.hasAlpha) then
+			args.defaultA = 1
+			args.currentA = 1
+		else
+			object.info.opacityFunc = swatchFunc_wrapper
+			object.info.opacity = 1 - currentA
+		end
+
+		object.setValue = _value
+		self.controls[object] = true
+		return object
+	end
+end
+
+-- XXX: fix/control
+function lib:Refresh()
+	for control in pairs(self.controls) do
+		control.value = control.getFunc()
+		control.setValue(control)
+	end
+end
+
+for name, func in pairs(lib) do
+	LibConfig[name] = func
+
+--	for panel in pairs(panels) do
+--		panel[name] = func
+--	end
+end
diff --git a/pMinimap.lua b/pMinimap.lua
index 8d4b573..ab136a4 100644
--- a/pMinimap.lua
+++ b/pMinimap.lua
@@ -1,9 +1,14 @@
-local _, ns = ...
+
+local LibConfig = LibStub('LibConfig-1.0')
+local LibSharedMedia = LibStub('LibSharedMedia-3.0')

 local pMinimap = CreateFrame('Frame')
 pMinimap:SetScript('OnEvent', function(self, event, ...) self[event](self, ...) end)
 pMinimap:RegisterEvent('PLAYER_LOGIN')
+pMinimap:RegisterEvent('PLAYER_LOGOUT')

+local DB, UNLOCKED
+local PLAYER = GetRealmName() .. ' - ' .. UnitName('player')
 local DEFAULTS = {
 	minimap = {
 		scale = 0.9,
@@ -14,24 +19,82 @@ local DEFAULTS = {
 		position = 'TOPRIGHT\031-15\031-15',
 	},
 	objects = {
-		Zone = {point = 'TOP', shown = false},
-		Difficulty = {point = 'BOTTOM', shown = false},
-		Battlefield = {point = 'TOPRIGHT', shown = true},
-		Dungeon = {point = 'TOPRIGHT', shown = true},
-		Tracking = {point = 'TOPLEFT', shown = true},
-		Clock = {point = 'BOTTOM', shown = true},
-		Mail = {point = 'BOTTOMRIGHT', shown = true},
+		Zone = {shown = false, point = 'TOP'},
+		Difficulty = {shown = false, point = 'BOTTOM'},
+		Battlefield = {shown = true, point = 'TOPRIGHT'},
+		Dungeon = {shown = true, point = 'TOPRIGHT'},
+		Tracking = {shown = true, point = 'TOPLEFT'},
+		Clock = {shown = true, point = 'BOTTOM'},
+		Mail = {shown = true, point = 'BOTTOMRIGHT'},
 	},
 	font = {
-		name = LibStub('LibSharedMedia-3.0'):GetDefault('font'),
+		index = 2,
 		size = 12,
 		shadow = 'OUTLINE',
 		monochrome = false,
 	},
 }

+local OBJECTS = {
+	Zone = 'MinimapZoneTextButton',
+	Difficulty = 'MiniMapInstanceDifficulty',
+	Battlefield = 'MiniMapBattlefieldFrame',
+	Dungeon = 'MiniMapLFGFrame',
+	Tracking = 'MiniMapTracking',
+	Clock = 'TimeManagerClockButton',
+	Mail = 'MiniMapMailFrame',
+}
+
+function UpdateObjects()
+	for name, setting in pairs(DB.objects) do
+		local object = _G[OBJECTS[name]]
+
+		if(setting.shown) then
+			object:SetAlpha(1)
+			object:EnableMouse(true)
+		else
+			object:SetAlpha(0)
+			object:EnableMouse(false)
+		end
+
+		object:ClearAllPoints()
+		object:SetPoint(setting.point)
+	end
+end
+
+function UpdateCore()
+	Minimap:SetScale(DB.minimap.scale)
+	Minimap:SetFrameStrata(DB.minimap.strata)
+	Minimap:SetFrameLevel(DB.minimap.level)
+
+	local size = DB.minimap.borderSize
+	Minimap:SetBackdrop({bgFile = [=[Interface\ChatFrame\ChatFrameBackground]=], insets = {left = -size, right = -size, top = -size, bottom = -size}})
+	Minimap:SetBackdropColor(unpack(DB.minimap.borderColors))
+end
+
+function UpdateFont()
+	local fonts = LibSharedMedia:List('font')
+	local font, size = LibSharedMedia:Fetch('font', fonts[DB.font.index]), DB.font.size
+	local flag = DB.font.shadow .. (DB.font.monochrome and 'MONOCHROME' or '')
+
+	MinimapZoneText:SetFont(font, size, flag)
+	TimeManagerClockTicker:SetFont(font, size, flag)
+end
+
+function UpdatePosition(save)
+	if(save) then
+		local point, _, _, x, y = Minimap:GetPoint()
+		DB.minimap.position = string.format('%s\031%d\031%d', point, x, y)
+	else
+		local point, x, y = string.split('\031', DB.minimap.position)
+		Minimap:ClearAllPoints()
+		Minimap:SetPoint(point, UIParent, point, x, y)
+	end
+end
+
 function pMinimap:PLAYER_LOGIN()
-	pMinimapDB = setmetatable(pMinimapDB or {}, {__index = DEFAULTS})
+	pMinimapProfiles = pMinimapProfiles or {}
+	DB = pMinimapProfiles[PLAYER] or DEFAULTS

 	MinimapZoomIn:Hide()
 	MinimapZoomOut:Hide()
@@ -49,13 +112,12 @@ function pMinimap:PLAYER_LOGIN()
 	Minimap:RegisterForDrag('LeftButton')
 	Minimap:SetMaskTexture([=[Interface\ChatFrame\ChatFrameBackground]=])
 	Minimap:SetScript('OnDragStart', function(self)
-		if(not ns.UNLOCKED) then return end
+		if(not UNLOCKED) then return end
 		self:StartMoving()
 	end)
 	Minimap:SetScript('OnDragStop', function(self)
-		if(not ns.UNLOCKED) then return end
+		if(not UNLOCKED) then return end
 		self:StopMovingOrSizing()
-		ns.UpdatePosition(true)
 	end)

 	MinimapCluster:EnableMouse(false)
@@ -94,20 +156,132 @@ function pMinimap:PLAYER_LOGIN()
 	TimeManagerClockTicker:SetPoint('CENTER', TimeManagerClockButton)
 	TimeManagerClockTicker:SetShadowOffset(0, 0)

-	ns.UNLOCKED = false
-	ns.UpdatePosition()
-	ns.UpdateObjects()
-	ns.UpdateCore()
-	ns.UpdateFont()
+	UNLOCKED = false
+	UpdatePosition()
+	UpdateObjects()
+	UpdateCore()
+	UpdateFont()
+end

-	SLASH_pMinimap1 = '/pmm'
-	SLASH_pMinimap2 = '/pminimap'
-	SlashCmdList.pMinimap = function()
-		InterfaceOptionsFrame_OpenToCategory('pMinimap')
-	end
+function pMinimap:PLAYER_LOGOUT()
+	pMinimapProfiles = pMinimapProfiles or {}
+	pMinimapProfiles[PLAYER] = DB
 end

 -- http://wowwiki.com/GetMinimapShape
 function GetMinimapShape()
 	return 'SQUARE'
 end
+
+
+LibConfig.AddConfig('pMinimap', nil, function(self)
+	self:CreateSlider(
+		'name', 'Scale', 'step', 0.1,
+		'minValue', 0.5, 'maxValue', 2.5,
+		'default', DEFAULTS.minimap.scale,
+		'currentTextFunc', function(value) return string.format('%.1f', value) end,
+		'getFunc', function() return DB.minimap.scale end,
+		'setFunc', function(value) DB.minimap.scale = value; UpdateCore() end
+	):SetPoint('TOPLEFT', 30, -30)
+
+	self:CreateCheckBox(
+		'name', 'Unlock',
+		'default', false,
+		'getFunc', function() return UNLOCKED end,
+		'setFunc', function() UNLOCKED = not UNLOCKED end,
+		'okayFunc', function() UpdatePosition(true) end,
+		'cancelFunc', function() UpdatePosition() end,
+		'defaultFunc', function() DB.minimap.position = DEFAULTS.minimap.position; UpdatePosition() end
+	):SetPoint('TOPLEFT', 30, -80)
+
+	self:CreateSlider(
+		'name', 'Frame Level', 'step', 1,
+		'minValue', 0, 'maxValue', 10,
+		'default', DEFAULTS.minimap.level,
+		'currentTextFunc', function(value) return value end,
+		'getFunc', function() return DB.minimap.level end,
+		'setFunc', function(value) DB.minimap.level = value; UpdateCore() end
+	):SetPoint('TOPRIGHT', -30, -30)
+
+	self:CreateDropDown(
+		'name', 'Frame Strata',
+		'default', DEFAULTS.minimap.strata,
+		'getFunc', function() return DB.minimap.strata end,
+		'setFunc', function(value) DB.minimap.strata = value; UpdateCore() end,
+		'values', {HIGH = 'High', MEDIUM = 'Medium', LOW = 'Low', BACKGROUND = 'Background'}
+	):SetPoint('TOPRIGHT', -10, -80)
+
+	self:CreateSlider(
+		'name', 'Border Thickness', 'step', 1,
+		'minValue', 0, 'maxValue', 10,
+		'default', DEFAULTS.minimap.borderSize,
+		'currentTextFunc', function(value) return value end,
+		'getFunc', function() return DB.minimap.borderSize end,
+		'setFunc', function(value) DB.minimap.borderSize = value; UpdateCore() end
+	):SetPoint('LEFT', 30, 0)
+
+	self:CreatePalette(
+		'name', 'Border Color', 'hasAlpha', true,
+		'default', DEFAULTS.minimap.borderColors,
+		'getFunc', function() return unpack(DB.minimap.borderColors) end,
+		'setFunc', function(r, g, b, a) DB.minimap.borderColors = {r, g, b, a}; UpdateCore() end
+	):SetPoint('RIGHT', -130, 0)
+
+	self:CreateDropDown(
+		'name', 'Font',
+		'default', DEFAULTS.font.index,
+		'getFunc', function() return DB.font.index end,
+		'setFunc', function(value) DB.font.index = value; UpdateFont() end,
+		'values', LibSharedMedia:List('font')
+	):SetPoint('BOTTOMLEFT', 10, 20)
+
+	self:CreateSlider(
+		'name', 'Font Size', 'step', 1,
+		'minValue', 6, 'maxValue', 36,
+		'default', DEFAULTS.font.size,
+		'currentTextFunc', function(value) return value end,
+		'getFunc', function() return DB.font.size end,
+		'setFunc', function(value) DB.font.size = value; UpdateFont() end
+	):SetPoint('BOTTOMLEFT', 30, 80)
+
+	self:CreateDropDown(
+		'name', 'Font Shadow',
+		'default', DEFAULTS.font.shadow,
+		'getFunc', function() return DB.font.shadow end,
+		'setFunc', function(value) DB.font.shadow = value; UpdateFont() end,
+		'values', {OUTLINE = 'Outline', THICKOUTLINE = 'Thick Outline', NONE = 'None'}
+	):SetPoint('BOTTOMRIGHT', -10, 20)
+
+	self:CreateCheckBox(
+		'name', 'Monochrome',
+		'default', DEFAULTS.font.monochrome,
+		'getFunc', function() return DB.font.monochrome end,
+		'setFunc', function(value) DB.font.monochrome = value; UpdateFont() end
+	):SetPoint('BOTTOMRIGHT', -140, 75)
+end)
+
+LibConfig.AddConfig('Objects', 'pMinimap', function(self)
+	local points = {TOPLEFT = 'Top Left', TOP = 'Top', TOPRIGHT = 'Top Right', LEFT = 'Left', RIGHT = 'Right', BOTTOMLEFT = 'Bottom Left', BOTTOM = 'Bottom', BOTTOMRIGHT = 'Bottom Right'}
+	local offset = 25
+
+	for name, default in pairs(DEFAULTS.objects) do
+		self:CreateCheckBox(
+			'name', name,
+			'default', default.shown,
+			'getFunc', function() local o = DB.objects[name]; return o.shown end,
+			'setFunc', function(value) local o = DB.objects[name]; o.shown = value; DB.objects[name] = o; UpdateObjects() end
+		):SetPoint('TOPLEFT', 25, -offset)
+
+		self:CreateDropDown(
+			'name', name..' Position',
+			'default', default.point,
+			'getFunc', function() local o = DB.objects[name]; return o.point end,
+			'setFunc', function(value) local o = DB.objects[name]; o.point = value; DB.objects[name] = o; UpdateObjects() end,
+			'values', points
+		):SetPoint('TOPRIGHT', -10, -offset)
+
+		offset = offset + 60
+	end
+end)
+
+LibConfig.AddCommand('pMinimap', '/pmm', '/pminimap')
diff --git a/pMinimap.toc b/pMinimap.toc
index 03ed650..2cf0ef7 100644
--- a/pMinimap.toc
+++ b/pMinimap.toc
@@ -3,17 +3,12 @@
 ## Version: Alpha
 ## Title: pMinimap
 ## Notes: Yet another square minimap addon
-## SavedVariablesPerChar: pMinimapDB
-## OptionalDeps: LibSharedMedia-3.0, SharedMedia
+## SavedVariables: pMinimapProfiles
+## OptionalDeps: LibConfig-1.0, LibSharedMedia-3.0, SharedMedia

 libs\LibStub.lua
 libs\CallbackHandler-1.0.lua
 libs\LibSharedMedia-3.0.lua
+libs\LibConfig-1.0.lua

 pMinimap.lua
-
-config\module.checkbox.lua
-config\module.dropdown.lua
-config\module.palette.lua
-config\module.slider.lua
-config\configuration.lua