implement API to save lists in configs file and terminal history

This commit is contained in:
Eduardo Bart 2012-01-15 13:13:22 -02:00
parent a238111c07
commit 9ec40f016d
20 changed files with 228 additions and 58 deletions

11
TODO
View File

@ -2,14 +2,13 @@
High priority TODO in order (before first public disclose) High priority TODO in order (before first public disclose)
[bart] tab widgets [bart] tab widgets
[bart] multiline rich text widget
[bart] chat with tabs [bart] chat with tabs
[bart] scrollbar [bart] scrollbar
[bart] scrollable widgets [bart] scrollable widgets
[bart] complete miniwindow (close, minimize, resize) [bart] complete miniwindow (close, minimize, resize)
[bart] move windows [bart] move windows
[bart] add top menu buttons [bart] add top menu buttons
[bart] console history, scrolling [bart] console scrolling
[bart] modules managment interface [bart] modules managment interface
[bart] adjust interface design [bart] adjust interface design
@ -34,7 +33,6 @@ Low priority TODO
[bart] load modules from zip packages [bart] load modules from zip packages
[bart] create a class for reading binary files [bart] create a class for reading binary files
[bart] rework lua/c++ logger [bart] rework lua/c++ logger
[bart] save lists on config manager
[bart] make protocol class compatible with old tibia protocols [bart] make protocol class compatible with old tibia protocols
== Graphics == Graphics
@ -42,20 +40,19 @@ Low priority TODO
[bart] cache renders into framebuffers [bart] cache renders into framebuffers
[bart] use hardware buffer [bart] use hardware buffer
[bart] use indices [bart] use indices
[bart] change mouse icon
== Lua == Lua
[bart] make possible to bind non LuaObject derived classes on lua engine (for usage with Point,Rect,Color,Size) [bart] make possible to bind non LuaObject derived classes on lua engine (for usage with Point,Rect,Color,Size)
[bart] bind every global lua function in static classes
[bart] review usage of x,y/width,height in lua instead of point/size [bart] review usage of x,y/width,height in lua instead of point/size
== Platform == Platform
[bart] port to MacOs and iphone [bart] port to MacOs and iphone
[bart] KeyDown, KeyText events
change win32 mouse cursor icon change win32 mouse cursor icon
== UI == UI
[bart] fix massive hotkeys when holding down a key [bart] fix massive hotkeys when holding down a key
[bart] horizontal box layout [bart] multiline rich text widget
[bart] move layout proprieties to widget style [bart] move layout proprieties to widget style
[bart] multiline text editor widget [bart] multiline text editor widget
[bart] create UIMessageBox, UIToolTip and UIInputBox [bart] create UIMessageBox, UIToolTip and UIInputBox
@ -66,7 +63,7 @@ change win32 mouse cursor icon
[bart] reapply anchor styles when adding new childs [bart] reapply anchor styles when adding new childs
[bart] ui text selection [bart] ui text selection
[bart] make set of background/icon/image width alone work [bart] make set of background/icon/image width alone work
[bart] check for recursive anchors to print a error and avoid crashes [bart] check for recursive anchors and print a error instead of crashing
== Client modules == Client modules
[bart] make possible to reload modules [bart] make possible to reload modules

View File

@ -6,6 +6,7 @@ local LogColors = { [LogInfo] = 'white',
[LogError] = 'red' } [LogError] = 'red' }
local MaxLogLines = 80 local MaxLogLines = 80
local LabelHeight = 16 local LabelHeight = 16
local MaxHistory = 1000
-- private variables -- private variables
local terminalWidget local terminalWidget
@ -109,6 +110,8 @@ function Terminal.init()
terminalButton = TopMenu.addButton('terminalButton', 'Terminal (Ctrl + T)', '/core_styles/icons/terminal.png', Terminal.toggle) terminalButton = TopMenu.addButton('terminalButton', 'Terminal (Ctrl + T)', '/core_styles/icons/terminal.png', Terminal.toggle)
Hotkeys.bind('Ctrl+T', Terminal.toggle) Hotkeys.bind('Ctrl+T', Terminal.toggle)
commandHistory = Settings.getList('terminal-history')
commandLineEdit = terminalWidget:getChildById('commandLineEdit') commandLineEdit = terminalWidget:getChildById('commandLineEdit')
Hotkeys.bind('Up', function() navigateCommand(1) end, commandLineEdit) Hotkeys.bind('Up', function() navigateCommand(1) end, commandLineEdit)
Hotkeys.bind('Down', function() navigateCommand(-1) end, commandLineEdit) Hotkeys.bind('Down', function() navigateCommand(-1) end, commandLineEdit)
@ -122,6 +125,7 @@ function Terminal.init()
end end
function Terminal.terminate() function Terminal.terminate()
Settings.setList('terminal-history', commandHistory)
Hotkeys.unbind('Ctrl+T') Hotkeys.unbind('Ctrl+T')
Logger.setOnLog(nil) Logger.setOnLog(nil)
terminalButton:destroy() terminalButton:destroy()
@ -186,6 +190,9 @@ function Terminal.executeCommand(command)
-- add new command to history -- add new command to history
table.insert(commandHistory, command) table.insert(commandHistory, command)
if #commandHistory > MaxHistory then
table.remove(commandHistory, 1)
end
-- add command line -- add command line
Terminal.addLine(">> " .. command, "#ffffff") Terminal.addLine(">> " .. command, "#ffffff")

View File

@ -4,6 +4,7 @@ TopMenu = {}
local topMenu local topMenu
local leftButtonsPanel local leftButtonsPanel
local rightButtonsPanel local rightButtonsPanel
local gameButtonsPanel
-- private functions -- private functions
local function onLogout() local function onLogout()
@ -19,6 +20,7 @@ function TopMenu.init()
topMenu = displayUI('topmenu.otui') topMenu = displayUI('topmenu.otui')
leftButtonsPanel = topMenu:getChildById('leftButtonsPanel') leftButtonsPanel = topMenu:getChildById('leftButtonsPanel')
rightButtonsPanel = topMenu:getChildById('rightButtonsPanel') rightButtonsPanel = topMenu:getChildById('rightButtonsPanel')
gameButtonsPanel = topMenu:getChildById('gameButtonsPanel')
TopMenu.addRightButton('logoutButton', 'Logout (Ctrl+Q)', '/core_styles/icons/logout.png', onLogout) TopMenu.addRightButton('logoutButton', 'Logout (Ctrl+Q)', '/core_styles/icons/logout.png', onLogout)
Hotkeys.bind('Ctrl+Q', onLogout) Hotkeys.bind('Ctrl+Q', onLogout)
@ -51,6 +53,15 @@ function TopMenu.addButton(id, description, icon, callback, right)
return button return button
end end
function TopMenu.addGameButton(id, description, icon, callback)
local button = createWidget('GameTopButton', gameButtonsPanel)
button:setId(id)
button:setTooltip(description)
button:setIcon(resolvepath(icon, 2))
button.onClick = callback
return button
end
function TopMenu.addLeftButton(id, description, icon, callback) function TopMenu.addLeftButton(id, description, icon, callback)
return TopMenu.addButton(id, description, icon, callback, false) return TopMenu.addButton(id, description, icon, callback, false)
end end

View File

@ -1,22 +1,45 @@
TopButton < UIButton TopButton < UIButton
size: 26 26 size: 26 26
image-color: white
image-source: /core_styles/images/top_button.png image-source: /core_styles/images/top_button.png
image-clip: 0 0 26 26 image-clip: 0 0 26 26
image-border: 3 image-border: 3
image-color: #ffffffff
icon-color: #ffffffff
$hover: $hover:
image-source: /core_styles/images/top_button.png image-color: #ffffff99
image-clip: 26 0 26 26 image-clip: 26 0 26 26
image-border: 3
$pressed: $pressed:
image-source: /core_styles/images/top_button.png
image-clip: 52 0 26 26 image-clip: 52 0 26 26
image-border: 3
$disabled: $disabled:
image-color: #ffffff66 image-color: #ffffff44
icon-color: #ffffff44
GameTopButton < UIButton
size: 26 26
image-source: /core_styles/images/top_button2.png
image-clip: 26 0 26 26
image-color: #ffffff22
icon-color: #ffffffff
image-border: 3
$hover:
image-clip: 0 0 26 26
image-color: #ffffffff
icon-color: #ffffffff
$first:
anchors.top: parent.top
anchors.left: parent.left
margin-top: 4
margin-left: 6
$!first:
anchors.top: prev.top
anchors.left: prev.right
margin-left: 6
TopLeftButton < TopButton TopLeftButton < TopButton
$first: $first:
@ -54,6 +77,13 @@ TopPanel
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
width: 150
Panel
id: gameButtonsPanel
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: prev.right
anchors.right: next.left anchors.right: next.left
Panel Panel

View File

@ -10,6 +10,8 @@ local function convertSettingValue(value)
return sizetostring(value) return sizetostring(value)
elseif value.r then elseif value.r then
return colortostring(value) return colortostring(value)
else
return value
end end
elseif value == nil then elseif value == nil then
return '' return ''
@ -30,6 +32,10 @@ function Settings.set(key, value)
g_configs.set(key, convertSettingValue(value)) g_configs.set(key, convertSettingValue(value))
end end
function Settings.setList(key, list)
g_configs.setList(key, list)
end
function Settings.setDefault(key, value) function Settings.setDefault(key, value)
if Settings.exists(key) then return false end if Settings.exists(key) then return false end
Settings.set(key, value) Settings.set(key, value)
@ -43,6 +49,10 @@ function Settings.get(key, default)
return g_configs.get(key) return g_configs.get(key)
end end
function Settings.getList(key)
return g_configs.getList(key)
end
function Settings.getString(key, default) function Settings.getString(key, default)
return Settings.get(key, default) return Settings.get(key, default)
end end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

View File

@ -2,16 +2,16 @@ UIComboBox = extends(UIWidget)
function UIComboBox.create() function UIComboBox.create()
local combobox = UIComboBox.internalCreate() local combobox = UIComboBox.internalCreate()
combobox.options = {} combobox.m_options = {}
combobox.currentIndex = -1 combobox.m_currentIndex = -1
return combobox return combobox
end end
function UIComboBox:setCurrentOption(text) function UIComboBox:setCurrentOption(text)
if not self.options then return end if not self.m_options then return end
for i,v in ipairs(self.options) do for i,v in ipairs(self.m_options) do
if v.text == text and self.currentIndex ~= i then if v.text == text and self.m_currentIndex ~= i then
self.currentIndex = i self.m_currentIndex = i
self:setText(text) self:setText(text)
self:onOptionChange(text, data) self:onOptionChange(text, data)
return return
@ -20,15 +20,15 @@ function UIComboBox:setCurrentOption(text)
end end
function UIComboBox:addOption(text, data) function UIComboBox:addOption(text, data)
table.insert(self.options, { text = text, data = data }) table.insert(self.m_options, { text = text, data = data })
local index = #self.options local index = #self.m_options
if index == 1 then self:setCurrentOption(text) end if index == 1 then self:setCurrentOption(text) end
return index return index
end end
function UIComboBox:onMousePress(mousePos, mouseButton) function UIComboBox:onMousePress(mousePos, mouseButton)
local menu = createWidget(self:getStyleName() .. 'PopupMenu', self) local menu = createWidget(self:getStyleName() .. 'PopupMenu', self)
for i,v in ipairs(self.options) do for i,v in ipairs(self.m_options) do
menu:addOption(v.text, function() self:setCurrentOption(v.text) end) menu:addOption(v.text, function() self:setCurrentOption(v.text) end)
end end
menu:setWidth(self:getWidth()) menu:setWidth(self:getWidth())

View File

@ -0,0 +1,23 @@
UIMessageBox = extends(UIWindow)
function UIMessageBox.create(title, message)
local messagebox = UIMessageBox.internalCreate()
messagebox:setText(title)
local messageLabel = self:getChildById('messageLabel')
label:setText(message)
label:resizeToText()
window:setWidth(math.max(label:getWidth() + self:getPaddingLeft() + self:getPaddingRight(), self:getWidth()))
window:setHeight(label:getHeight() + self:getPaddingTop() + self:getPaddingBottom())
return messagebox
end
function UIMessageBox:setTitle(title)
end
function UIMessageBox:setMessage(message)
end
function

View File

@ -4,19 +4,28 @@ function UIProgressBar.create()
local progressbar = UIProgressBar.internalCreate() local progressbar = UIProgressBar.internalCreate()
progressbar:setFocusable(false) progressbar:setFocusable(false)
progressbar:setPhantom(true) progressbar:setPhantom(true)
progressbar.percent = 0 progressbar.m_percent = 0
progressbar:setBackgroundSize({width = 1, height = 1}) progressbar:updateBackground()
return progressbar return progressbar
end end
function UIProgressBar:setPercent(percent) function UIProgressBar:setPercent(percent)
self:setBackgroundHeight(self:getHeight()) self.m_percent = percent
local width = (percent * self:getWidth())/100 self:updateBackground()
if width == 0 then width = 1 end
self:setBackgroundWidth(width)
self.percent = percent
end end
function UIProgressBar:getPercent() function UIProgressBar:getPercent()
return self.percent return self.m_percent
end
function UIProgressBar:updateBackground()
local width = math.max((self.m_percent * self:getWidth())/100, 1)
local height = self:getHeight()
self:setBackgroundSize({width=width, height=height})
end
function UIProgressBar:onGeometryChange(oldRect, newRect)
self:updateBackground()
end end

View File

@ -7,9 +7,9 @@ Module
dependencies: dependencies:
- game_healthbar - game_healthbar
- game_inventory - game_inventory
- game_skills //- game_skills
- game_textmessage - game_textmessage
//- game_viplist - game_viplist
- game_console - game_console
- game_outfit - game_outfit
- game_containers - game_containers

View File

@ -43,8 +43,7 @@ end
-- public functions -- public functions
function Skills.create() function Skills.create()
skillWindow = displayUI('skills.otui', { parent = Game.gameRightPanel }) skillWindow = displayUI('skills.otui', { parent = Game.gameRightPanel })
--skillsButton = TopMenu.addButton('skillsButton', 'Skills (Ctrl+S)', '/core_styles/icons/skills.png', Skills.toggle) skillsButton = TopMenu.addGameButton('skillsButton', 'Skills (Ctrl+S)', '/core_styles/icons/skills.png', Skills.toggle)
--skillsButton:setWidth(32)
end end
function Skills.destroy() function Skills.destroy()

View File

@ -7,6 +7,8 @@ local addVipWindow = nil
-- public functions -- public functions
function VipList.create() function VipList.create()
vipWindow = displayUI('viplist.otui', { parent = Game.gameRightPanel }) vipWindow = displayUI('viplist.otui', { parent = Game.gameRightPanel })
vipWindow:hide()
TopMenu.addGameButton('vipListButton', 'VIP list', '/core_styles/icons/viplist.png', VipList.toggle)
end end
function VipList.destroy() function VipList.destroy()
@ -43,21 +45,21 @@ function VipList.onAddVip(id, name, online)
end end
label.vipOnline = online label.vipOnline = online
local nameLower = name:lower() local nameLower = name:lower()
local childrenCount = vipList:getChildCount() local childrenCount = vipList:getChildCount()
for i=1,childrenCount do for i=1,childrenCount do
local child = vipList:getChildByIndex(i) local child = vipList:getChildByIndex(i)
if online and not child.vipOnline then if online and not child.vipOnline then
vipList:insertChild(i, label) vipList:insertChild(i, label)
return return
end end
if (not online and not child.vipOnline) or (online and child.vipOnline) then if (not online and not child.vipOnline) or (online and child.vipOnline) then
local childText = child:getText():lower() local childText = child:getText():lower()
local length = math.min(childText:len(), nameLower:len()) local length = math.min(childText:len(), nameLower:len())
for j=1,length do for j=1,length do
if nameLower:byte(j) < childText:byte(j) then if nameLower:byte(j) < childText:byte(j) then
vipList:insertChild(i, label) vipList:insertChild(i, label)
@ -68,7 +70,7 @@ function VipList.onAddVip(id, name, online)
end end
end end
end end
vipList:insertChild(childrenCount+1, label) vipList:insertChild(childrenCount+1, label)
end end
@ -77,7 +79,7 @@ function VipList.onVipStateChange(id, online)
local label = vipList:getChildById('vip' .. id) local label = vipList:getChildById('vip' .. id)
local text = label:getText() local text = label:getText()
vipList:removeChild(label) vipList:removeChild(label)
VipList.onAddVip(id, text, online) VipList.onAddVip(id, text, online)
end end
@ -89,7 +91,7 @@ function VipList.onVipListMousePress(widget, mousePos, mouseButton)
local menu = createWidget('PopupMenu') local menu = createWidget('PopupMenu')
menu:addOption('Add new VIP', function() VipList.createAddWindow() end) menu:addOption('Add new VIP', function() VipList.createAddWindow() end)
menu:display(mousePos) menu:display(mousePos)
return true return true
end end
@ -104,7 +106,7 @@ function VipList.onVipListLabelMousePress(widget, mousePos, mouseButton)
menu:addSeparator() menu:addSeparator()
menu:addOption('Copy Name', function() g_window.setClipboardText(widget:getText()) end) menu:addOption('Copy Name', function() g_window.setClipboardText(widget:getText()) end)
menu:display(mousePos) menu:display(mousePos)
return true return true
end end

View File

@ -27,6 +27,11 @@
ConfigManager g_configs; ConfigManager g_configs;
ConfigManager::ConfigManager()
{
m_confsDoc = OTMLDocument::create();
}
bool ConfigManager::load(const std::string& file) bool ConfigManager::load(const std::string& file)
{ {
m_fileName = file; m_fileName = file;
@ -35,9 +40,9 @@ bool ConfigManager::load(const std::string& file)
return false; return false;
try { try {
OTMLDocumentPtr doc = OTMLDocument::parse(file); OTMLDocumentPtr confsDoc = OTMLDocument::parse(file);
for(const OTMLNodePtr& child : doc->children()) if(confsDoc)
m_confsMap[child->tag()] = child->value(); m_confsDoc = confsDoc;
return true; return true;
} catch(Exception& e) { } catch(Exception& e) {
logError("could not load configurations: ", e.what()); logError("could not load configurations: ", e.what());
@ -47,13 +52,65 @@ bool ConfigManager::load(const std::string& file)
bool ConfigManager::save() bool ConfigManager::save()
{ {
OTMLDocumentPtr doc = OTMLDocument::create(); if(m_fileName.length() == 0)
for(auto it : m_confsMap) { return false;
if(it.second == "") return m_confsDoc->save(m_fileName);
continue;
OTMLNodePtr node = OTMLNode::create(it.first, it.second);
doc->addChild(node);
}
return doc->save(m_fileName);
} }
void ConfigManager::set(const std::string& key, const std::string& value)
{
if(key == "") {
remove(key);
return;
}
OTMLNodePtr child = OTMLNode::create(key, value);
m_confsDoc->addChild(child);
}
void ConfigManager::setList(const std::string& key, const std::vector<std::string>& list)
{
remove(key);
if(list.size() == 0)
return;
OTMLNodePtr child = OTMLNode::create(key, true);
for(const std::string& value : list) {
child->writeIn(value);
dump << "insert" << value;
}
m_confsDoc->addChild(child);
}
bool ConfigManager::exists(const std::string& key)
{
return m_confsDoc->hasChildAt(key);
}
std::string ConfigManager::get(const std::string& key)
{
OTMLNodePtr child = m_confsDoc->get(key);
if(child)
return child->value();
else
return "";
}
std::vector<std::string> ConfigManager::getList(const std::string& key)
{
std::vector<std::string> list;
OTMLNodePtr child = m_confsDoc->get(key);
if(child) {
for(const OTMLNodePtr& subchild : child->children())
list.push_back(subchild->value());
}
return list;
}
void ConfigManager::remove(const std::string& key)
{
OTMLNodePtr child = m_confsDoc->get(key);
if(child)
m_confsDoc->removeChild(child);
}

View File

@ -24,21 +24,25 @@
#define CONFIGMANAGER_H #define CONFIGMANAGER_H
#include "declarations.h" #include "declarations.h"
#include <framework/otml/declarations.h>
class ConfigManager class ConfigManager
{ {
public: public:
ConfigManager();
bool load(const std::string& file); bool load(const std::string& file);
bool save(); bool save();
bool exists(const std::string& key) { return m_confsMap.find(key) != m_confsMap.end(); } void set(const std::string& key, const std::string& value);
void set(const std::string& key, const std::string& value) { m_confsMap[key] = value; } void setList(const std::string& key, const std::vector<std::string>& list);
std::string get(const std::string& key) { return m_confsMap[key]; } std::string get(const std::string& key);
void remove(const std::string& key) { m_confsMap[key] = ""; } std::vector<std::string> getList(const std::string& key);
bool exists(const std::string& key);
void remove(const std::string& key);
private: private:
std::string m_fileName; std::string m_fileName;
std::map<std::string, std::string> m_confsMap; OTMLDocumentPtr m_confsDoc;
}; };
extern ConfigManager g_configs; extern ConfigManager g_configs;

View File

@ -366,7 +366,9 @@ void Application::registerLuaFunctions()
// ConfigManager // ConfigManager
g_lua.registerStaticClass("g_configs"); g_lua.registerStaticClass("g_configs");
g_lua.bindClassStaticFunction("g_configs", "set", std::bind(&ConfigManager::set, &g_configs, _1, _2)); g_lua.bindClassStaticFunction("g_configs", "set", std::bind(&ConfigManager::set, &g_configs, _1, _2));
g_lua.bindClassStaticFunction("g_configs", "setList", std::bind(&ConfigManager::setList, &g_configs, _1, _2));
g_lua.bindClassStaticFunction("g_configs", "get", std::bind(&ConfigManager::get, &g_configs, _1)); g_lua.bindClassStaticFunction("g_configs", "get", std::bind(&ConfigManager::get, &g_configs, _1));
g_lua.bindClassStaticFunction("g_configs", "getList", std::bind(&ConfigManager::getList, &g_configs, _1));
g_lua.bindClassStaticFunction("g_configs", "exists", std::bind(&ConfigManager::exists, &g_configs, _1)); g_lua.bindClassStaticFunction("g_configs", "exists", std::bind(&ConfigManager::exists, &g_configs, _1));
g_lua.bindClassStaticFunction("g_configs", "remove", std::bind(&ConfigManager::remove, &g_configs, _1)); g_lua.bindClassStaticFunction("g_configs", "remove", std::bind(&ConfigManager::remove, &g_configs, _1));

View File

@ -125,6 +125,9 @@ luavalue_cast(int index, std::function<Ret(Args...)>& func);
template<typename T> template<typename T>
void push_luavalue(const std::vector<T>& vec); void push_luavalue(const std::vector<T>& vec);
template<typename T>
bool luavalue_cast(int index, std::vector<T>& vec);
// deque // deque
template<class T> template<class T>
void push_luavalue(const std::deque<T>& vec); void push_luavalue(const std::deque<T>& vec);
@ -249,6 +252,22 @@ void push_luavalue(const std::vector<T>& vec) {
} }
} }
template<typename T>
bool luavalue_cast(int index, std::vector<T>& vec)
{
if(g_lua.isTable(index)) {
g_lua.pushNil();
while(g_lua.next(index < 0 ? index-1 : index)) {
T value;
if(luavalue_cast(-1, value))
vec.push_back(value);
g_lua.pop();
}
return true;
}
return false;
}
template<typename T> template<typename T>
void push_luavalue(const std::deque<T>& vec) { void push_luavalue(const std::deque<T>& vec) {
g_lua.newTable(); g_lua.newTable();