Compare commits
4 Commits
master
...
keyboard-b
Author | SHA1 | Date | |
---|---|---|---|
|
9e3158b4dc | ||
|
348ef06a1f | ||
|
a2adff46ce | ||
|
bf0cc9ba5f |
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
#include "common/Singleton.h"
|
#include "common/Singleton.h"
|
||||||
@ -10,6 +12,77 @@
|
|||||||
|
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
|
|
||||||
|
template<class Item>
|
||||||
|
void JsonArrayItemToTupleItem(Item &i, Json::Value const &v);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void JsonArrayItemToTupleItem<bool>(bool &i, Json::Value const &v)
|
||||||
|
{
|
||||||
|
i = v.asBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void JsonArrayItemToTupleItem<int>(int &i, Json::Value const &v)
|
||||||
|
{
|
||||||
|
i = v.asInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void JsonArrayItemToTupleItem<ByteString>(ByteString &i, Json::Value const &v)
|
||||||
|
{
|
||||||
|
auto s = v.asString();
|
||||||
|
i = ByteString(s.begin(), s.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t Item = 0, class... Types>
|
||||||
|
typename std::enable_if<Item == sizeof...(Types), void>::type
|
||||||
|
JsonArrayToTuple(std::tuple<Types...> &, Json::Value const &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t Item = 0, class... Types>
|
||||||
|
typename std::enable_if<Item < sizeof...(Types), void>::type
|
||||||
|
JsonArrayToTuple(std::tuple<Types...> &t, Json::Value const &va)
|
||||||
|
{
|
||||||
|
JsonArrayItemToTupleItem(std::get<Item>(t), va[(Json::ArrayIndex)Item]);
|
||||||
|
JsonArrayToTuple<Item + 1, Types...>(t, va);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Item>
|
||||||
|
void JsonArrayItemFromTupleItem(Item const &i, Json::Value &v);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void JsonArrayItemFromTupleItem<bool>(bool const &i, Json::Value &v)
|
||||||
|
{
|
||||||
|
v = Json::Value((bool)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void JsonArrayItemFromTupleItem<int>(int const &i, Json::Value &v)
|
||||||
|
{
|
||||||
|
v = Json::Value((Json::Int)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void JsonArrayItemFromTupleItem<ByteString>(ByteString const &i, Json::Value &v)
|
||||||
|
{
|
||||||
|
v = Json::Value(std::string(i.begin(), i.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t Item = 0, class... Types>
|
||||||
|
typename std::enable_if<Item == sizeof...(Types), void>::type
|
||||||
|
JsonArrayFromTuple(std::tuple<Types...> const &, Json::Value &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t Item = 0, class... Types>
|
||||||
|
typename std::enable_if<Item < sizeof...(Types), void>::type
|
||||||
|
JsonArrayFromTuple(std::tuple<Types...> const &t, Json::Value &va)
|
||||||
|
{
|
||||||
|
JsonArrayItemFromTupleItem(std::get<Item>(t), va[(Json::ArrayIndex)Item]);
|
||||||
|
JsonArrayFromTuple<Item + 1, Types...>(t, va);
|
||||||
|
}
|
||||||
|
|
||||||
class SaveInfo;
|
class SaveInfo;
|
||||||
class SaveFile;
|
class SaveFile;
|
||||||
class SaveComment;
|
class SaveComment;
|
||||||
@ -185,6 +258,36 @@ public:
|
|||||||
void SetPref(ByteString prop, Json::Value value);
|
void SetPref(ByteString prop, Json::Value value);
|
||||||
void SetPref(ByteString property, std::vector<Json::Value> value);
|
void SetPref(ByteString property, std::vector<Json::Value> value);
|
||||||
void SetPrefUnicode(ByteString prop, String value);
|
void SetPrefUnicode(ByteString prop, String value);
|
||||||
|
|
||||||
|
template<class Tuple>
|
||||||
|
std::vector<Tuple> GetPrefTupleArray(ByteString prop)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Json::Value arr = GetPref(preferences, prop);
|
||||||
|
std::vector<Tuple> ret(arr.size());
|
||||||
|
for (int i = 0; i < (int)arr.size(); i++)
|
||||||
|
{
|
||||||
|
JsonArrayToTuple(ret[i], arr[i]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (std::exception &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return std::vector<Tuple>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Tuple>
|
||||||
|
void SetPref(ByteString prop, std::vector<Tuple> const &value)
|
||||||
|
{
|
||||||
|
std::vector<Json::Value> arr(value.size());
|
||||||
|
for (int i = 0; i < (int)arr.size(); i++)
|
||||||
|
{
|
||||||
|
JsonArrayFromTuple(value[i], arr[i]);
|
||||||
|
}
|
||||||
|
SetPref(prop, arr);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLIENT_H
|
#endif // CLIENT_H
|
||||||
|
@ -661,7 +661,7 @@ bool GameController::MouseDown(int x, int y, unsigned button)
|
|||||||
{
|
{
|
||||||
MouseDownEvent ev(x, y, button);
|
MouseDownEvent ev(x, y, button);
|
||||||
bool ret = commandInterface->HandleEvent(LuaEvents::mousedown, &ev);
|
bool ret = commandInterface->HandleEvent(LuaEvents::mousedown, &ev);
|
||||||
if (ret && y<YRES && x<XRES && !gameView->GetPlacingSave() && !gameView->GetPlacingZoom())
|
if (ret && y<YRES && x<XRES && gameView->IsIdle())
|
||||||
{
|
{
|
||||||
ui::Point point = gameModel->AdjustZoomCoords(ui::Point(x, y));
|
ui::Point point = gameModel->AdjustZoomCoords(ui::Point(x, y));
|
||||||
x = point.X;
|
x = point.X;
|
||||||
@ -687,7 +687,7 @@ bool GameController::MouseUp(int x, int y, unsigned button, char type)
|
|||||||
bool ret = commandInterface->HandleEvent(LuaEvents::mouseup, &ev);
|
bool ret = commandInterface->HandleEvent(LuaEvents::mouseup, &ev);
|
||||||
if (type)
|
if (type)
|
||||||
return ret;
|
return ret;
|
||||||
if (ret && foundSignID != -1 && y<YRES && x<XRES && !gameView->GetPlacingSave())
|
if (ret && foundSignID != -1 && y<YRES && x<XRES && gameView->IsIdle())
|
||||||
{
|
{
|
||||||
ui::Point point = gameModel->AdjustZoomCoords(ui::Point(x, y));
|
ui::Point point = gameModel->AdjustZoomCoords(ui::Point(x, y));
|
||||||
x = point.X;
|
x = point.X;
|
||||||
@ -752,7 +752,7 @@ bool GameController::KeyPress(int key, int scan, bool repeat, bool shift, bool c
|
|||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
Simulation * sim = gameModel->GetSimulation();
|
Simulation * sim = gameModel->GetSimulation();
|
||||||
if (!gameView->GetPlacingSave())
|
if (gameView->IsIdle())
|
||||||
{
|
{
|
||||||
// Go right command
|
// Go right command
|
||||||
if (key == SDLK_RIGHT)
|
if (key == SDLK_RIGHT)
|
||||||
|
@ -156,6 +156,8 @@ GameModel::GameModel():
|
|||||||
|
|
||||||
mouseClickRequired = Client::Ref().GetPrefBool("MouseClickRequired", false);
|
mouseClickRequired = Client::Ref().GetPrefBool("MouseClickRequired", false);
|
||||||
includePressure = Client::Ref().GetPrefBool("Simulation.IncludePressure", true);
|
includePressure = Client::Ref().GetPrefBool("Simulation.IncludePressure", true);
|
||||||
|
|
||||||
|
keyconfig = Client::Ref().GetPrefTupleArray<decltype(keyconfig)::value_type>("Keyconfig");
|
||||||
}
|
}
|
||||||
|
|
||||||
GameModel::~GameModel()
|
GameModel::~GameModel()
|
||||||
@ -188,6 +190,8 @@ GameModel::~GameModel()
|
|||||||
Client::Ref().SetPref("MouseClickRequired", mouseClickRequired);
|
Client::Ref().SetPref("MouseClickRequired", mouseClickRequired);
|
||||||
Client::Ref().SetPref("Simulation.IncludePressure", includePressure);
|
Client::Ref().SetPref("Simulation.IncludePressure", includePressure);
|
||||||
|
|
||||||
|
Client::Ref().SetPref("Keyconfig", keyconfig);
|
||||||
|
|
||||||
Favorite::Ref().SaveFavoritesToPrefs();
|
Favorite::Ref().SaveFavoritesToPrefs();
|
||||||
|
|
||||||
for (size_t i = 0; i < menuList.size(); i++)
|
for (size_t i = 0; i < menuList.size(); i++)
|
||||||
@ -546,6 +550,7 @@ void GameModel::AddObserver(GameView * observer){
|
|||||||
observer->NotifyColourActivePresetChanged(this);
|
observer->NotifyColourActivePresetChanged(this);
|
||||||
observer->NotifyQuickOptionsChanged(this);
|
observer->NotifyQuickOptionsChanged(this);
|
||||||
observer->NotifyLastToolChanged(this);
|
observer->NotifyLastToolChanged(this);
|
||||||
|
observer->NotifyKeyconfigChanged(this);
|
||||||
UpdateQuickOptions();
|
UpdateQuickOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,6 +696,14 @@ void GameModel::SetSave(SaveInfo * newSave, bool invertIncludePressure)
|
|||||||
UpdateQuickOptions();
|
UpdateQuickOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameModel::notifyKeyconfigChanged()
|
||||||
|
{
|
||||||
|
for (auto observer : observers)
|
||||||
|
{
|
||||||
|
observer->NotifyKeyconfigChanged(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SaveFile * GameModel::GetSaveFile()
|
SaveFile * GameModel::GetSaveFile()
|
||||||
{
|
{
|
||||||
return currentFile;
|
return currentFile;
|
||||||
@ -1320,3 +1333,14 @@ void GameModel::SetIncludePressure(bool includePressure_)
|
|||||||
{
|
{
|
||||||
includePressure = includePressure_;
|
includePressure = includePressure_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Keyconfig GameModel::GetKeyconfig()
|
||||||
|
{
|
||||||
|
return keyconfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameModel::SetKeyconfig(Keyconfig keyconfig_)
|
||||||
|
{
|
||||||
|
keyconfig = keyconfig_;
|
||||||
|
notifyKeyconfigChanged();
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "gui/interface/Colour.h"
|
#include "gui/interface/Colour.h"
|
||||||
#include "client/User.h"
|
#include "client/User.h"
|
||||||
#include "gui/interface/Point.h"
|
#include "gui/interface/Point.h"
|
||||||
|
#include "Keyconfig.h"
|
||||||
|
|
||||||
class Menu;
|
class Menu;
|
||||||
class Tool;
|
class Tool;
|
||||||
@ -103,6 +104,10 @@ private:
|
|||||||
void notifyToolTipChanged();
|
void notifyToolTipChanged();
|
||||||
void notifyQuickOptionsChanged();
|
void notifyQuickOptionsChanged();
|
||||||
void notifyLastToolChanged();
|
void notifyLastToolChanged();
|
||||||
|
void notifyKeyconfigChanged();
|
||||||
|
|
||||||
|
Keyconfig keyconfig;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GameModel();
|
GameModel();
|
||||||
~GameModel();
|
~GameModel();
|
||||||
@ -159,6 +164,9 @@ public:
|
|||||||
int GetBrushID();
|
int GetBrushID();
|
||||||
void SetBrushID(int i);
|
void SetBrushID(int i);
|
||||||
|
|
||||||
|
Keyconfig GetKeyconfig();
|
||||||
|
void SetKeyconfig(Keyconfig keyconfig);
|
||||||
|
|
||||||
void SetVote(int direction);
|
void SetVote(int direction);
|
||||||
SaveInfo * GetSave();
|
SaveInfo * GetSave();
|
||||||
SaveFile * GetSaveFile();
|
SaveFile * GetSaveFile();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,20 +3,19 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
|
#include <stack>
|
||||||
|
#include <functional>
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
#include "gui/interface/Window.h"
|
#include "gui/interface/Window.h"
|
||||||
#include "simulation/Sample.h"
|
#include "simulation/Sample.h"
|
||||||
|
#include "Keyconfig.h"
|
||||||
|
|
||||||
enum DrawMode
|
enum DrawMode
|
||||||
{
|
{
|
||||||
DrawPoints, DrawLine, DrawRect, DrawFill
|
DrawPoints, DrawLine, DrawRect, DrawFill
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SelectMode
|
|
||||||
{
|
|
||||||
SelectNone, SelectStamp, SelectCopy, SelectCut, PlaceSave
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
class Button;
|
class Button;
|
||||||
@ -32,6 +31,10 @@ class Brush;
|
|||||||
class GameModel;
|
class GameModel;
|
||||||
class GameView: public ui::Window
|
class GameView: public ui::Window
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using ViewFunctionOn = std::function<void ()>;
|
||||||
|
using ViewFunctionOff = std::function<void ()>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isMouseDown;
|
bool isMouseDown;
|
||||||
bool skipDraw;
|
bool skipDraw;
|
||||||
@ -102,7 +105,7 @@ private:
|
|||||||
ui::Point drawPoint1;
|
ui::Point drawPoint1;
|
||||||
ui::Point drawPoint2;
|
ui::Point drawPoint2;
|
||||||
|
|
||||||
SelectMode selectMode;
|
std::stack<ByteString> context;
|
||||||
ui::Point selectPoint1;
|
ui::Point selectPoint1;
|
||||||
ui::Point selectPoint2;
|
ui::Point selectPoint2;
|
||||||
|
|
||||||
@ -128,6 +131,30 @@ private:
|
|||||||
void disableAltBehaviour();
|
void disableAltBehaviour();
|
||||||
void UpdateDrawMode();
|
void UpdateDrawMode();
|
||||||
void UpdateToolStrength();
|
void UpdateToolStrength();
|
||||||
|
|
||||||
|
Keyconfig keyconfig;
|
||||||
|
|
||||||
|
struct ViewContext
|
||||||
|
{
|
||||||
|
ByteString description;
|
||||||
|
};
|
||||||
|
std::map<ByteString, ViewContext> view_contexts;
|
||||||
|
|
||||||
|
struct ViewFunction
|
||||||
|
{
|
||||||
|
ViewFunctionOn on;
|
||||||
|
ViewFunctionOff off;
|
||||||
|
ByteString description;
|
||||||
|
};
|
||||||
|
std::map<ByteString, ViewFunction> view_functions;
|
||||||
|
|
||||||
|
struct ActiveViewFunction
|
||||||
|
{
|
||||||
|
ByteString func;
|
||||||
|
int scan;
|
||||||
|
};
|
||||||
|
std::vector<ActiveViewFunction> active_view_functions;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GameView();
|
GameView();
|
||||||
virtual ~GameView();
|
virtual ~GameView();
|
||||||
@ -139,17 +166,15 @@ public:
|
|||||||
bool GetHudEnable();
|
bool GetHudEnable();
|
||||||
void SetDebugHUD(bool mode);
|
void SetDebugHUD(bool mode);
|
||||||
bool GetDebugHUD();
|
bool GetDebugHUD();
|
||||||
bool GetPlacingSave();
|
|
||||||
bool GetPlacingZoom();
|
|
||||||
void SetActiveMenuDelayed(int activeMenu) { delayedActiveMenu = activeMenu; }
|
void SetActiveMenuDelayed(int activeMenu) { delayedActiveMenu = activeMenu; }
|
||||||
bool CtrlBehaviour(){ return ctrlBehaviour; }
|
bool CtrlBehaviour(){ return ctrlBehaviour; }
|
||||||
bool ShiftBehaviour(){ return shiftBehaviour; }
|
bool ShiftBehaviour(){ return shiftBehaviour; }
|
||||||
bool AltBehaviour(){ return altBehaviour; }
|
bool AltBehaviour(){ return altBehaviour; }
|
||||||
SelectMode GetSelectMode() { return selectMode; }
|
|
||||||
void BeginStampSelection();
|
void BeginStampSelection();
|
||||||
ui::Point GetPlaceSaveOffset() { return placeSaveOffset; }
|
ui::Point GetPlaceSaveOffset() { return placeSaveOffset; }
|
||||||
void SetPlaceSaveOffset(ui::Point offset) { placeSaveOffset = offset; }
|
void SetPlaceSaveOffset(ui::Point offset) { placeSaveOffset = offset; }
|
||||||
int Record(bool record);
|
int Record(bool record);
|
||||||
|
bool IsIdle() const;
|
||||||
|
|
||||||
//all of these are only here for one debug lines
|
//all of these are only here for one debug lines
|
||||||
bool GetMouseDown() { return isMouseDown; }
|
bool GetMouseDown() { return isMouseDown; }
|
||||||
@ -182,6 +207,7 @@ public:
|
|||||||
void NotifyInfoTipChanged(GameModel * sender);
|
void NotifyInfoTipChanged(GameModel * sender);
|
||||||
void NotifyQuickOptionsChanged(GameModel * sender);
|
void NotifyQuickOptionsChanged(GameModel * sender);
|
||||||
void NotifyLastToolChanged(GameModel * sender);
|
void NotifyLastToolChanged(GameModel * sender);
|
||||||
|
void NotifyKeyconfigChanged(GameModel * sender);
|
||||||
|
|
||||||
|
|
||||||
void ToolTip(ui::Point senderPosition, String toolTip) override;
|
void ToolTip(ui::Point senderPosition, String toolTip) override;
|
||||||
@ -212,6 +238,15 @@ public:
|
|||||||
class ToolAction;
|
class ToolAction;
|
||||||
class OptionAction;
|
class OptionAction;
|
||||||
class OptionListener;
|
class OptionListener;
|
||||||
|
|
||||||
|
void PushContext(ByteString new_context);
|
||||||
|
void PopContext();
|
||||||
|
ByteString GetContext() const;
|
||||||
|
|
||||||
|
void AddFunction(ByteString name, ByteString description, ViewFunctionOn on = nullptr, ViewFunctionOff off = nullptr);
|
||||||
|
void RemoveFunction(ByteString name);
|
||||||
|
void AddContext(ByteString name, ByteString description);
|
||||||
|
void RemoveContext(ByteString name);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GAMEVIEW_H
|
#endif // GAMEVIEW_H
|
||||||
|
18
src/gui/game/Keyconfig.h
Normal file
18
src/gui/game/Keyconfig.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef KEYCONFIG_H_
|
||||||
|
#define KEYCONFIG_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using KeyconfigItem = std::tuple<
|
||||||
|
ByteString, // context
|
||||||
|
bool, // ctrl
|
||||||
|
bool, // shift
|
||||||
|
bool, // alt
|
||||||
|
int, // scancode
|
||||||
|
ByteString // function
|
||||||
|
>;
|
||||||
|
using Keyconfig = std::vector<KeyconfigItem>;
|
||||||
|
|
||||||
|
#endif // KEYCONFIG_H_
|
99
src/gui/keyconfig/KeyconfigController.cpp
Normal file
99
src/gui/keyconfig/KeyconfigController.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
static int Aa;
|
||||||
|
#if 0 // temporarily disabled so it doesn't interfere with what I'm doing -- LBPHacker
|
||||||
|
#include "KeyconfigController.h"
|
||||||
|
|
||||||
|
#include "KeyconfigView.h"
|
||||||
|
#include "Controller.h"
|
||||||
|
#include "client/Client.h"
|
||||||
|
#include "gui/options/OptionsController.h"
|
||||||
|
#include "KeyconfigModel.h"
|
||||||
|
|
||||||
|
KeyconfigController::KeyconfigController(OptionsController* _parent):
|
||||||
|
HasExited(false)
|
||||||
|
{
|
||||||
|
parent = _parent;
|
||||||
|
view = new KeyconfigView();
|
||||||
|
model = new KeyconfigModel();
|
||||||
|
model->AddObserver(view);
|
||||||
|
view->AttachController(this);
|
||||||
|
LoadBindingPrefs();
|
||||||
|
view->BuildKeyBindingsListView();
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyconfigView* KeyconfigController::GetView()
|
||||||
|
{
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::CreateModel(BindingModel _model)
|
||||||
|
{
|
||||||
|
model->CreateModel(_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::Save()
|
||||||
|
{
|
||||||
|
model->Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::ChangeModel(BindingModel _model)
|
||||||
|
{
|
||||||
|
model->RemoveModelByIndex(_model.index);
|
||||||
|
model->AddModel(_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::Exit()
|
||||||
|
{
|
||||||
|
view->CloseActiveWindow();
|
||||||
|
parent->NotifyKeyBindingsChanged();
|
||||||
|
HasExited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::LoadBindingPrefs()
|
||||||
|
{
|
||||||
|
model->LoadBindingPrefs();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BindingModel> KeyconfigController::GetBindingPrefs()
|
||||||
|
{
|
||||||
|
return model->GetBindingPrefs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::NotifyBindingsChanged()
|
||||||
|
{
|
||||||
|
bool hasConflict = model->HasConflictingCombo();
|
||||||
|
model->NotifyBindingsChanged(hasConflict);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::ForceHasConflict()
|
||||||
|
{
|
||||||
|
view->OnKeyCombinationChanged(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::NotifyKeyReleased()
|
||||||
|
{
|
||||||
|
view->OnKeyReleased();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::PopBindingByFunctionId(int functionId)
|
||||||
|
{
|
||||||
|
model->PopBindingByFunctionId(functionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigController::ResetToDefaults()
|
||||||
|
{
|
||||||
|
model->WriteDefaultPrefs(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyconfigController::FunctionHasShortcut(int functionId)
|
||||||
|
{
|
||||||
|
return model->FunctionHasShortcut(functionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyconfigController::~KeyconfigController()
|
||||||
|
{
|
||||||
|
view->CloseActiveWindow();
|
||||||
|
delete view;
|
||||||
|
delete callback;
|
||||||
|
delete model;
|
||||||
|
}
|
||||||
|
#endif
|
41
src/gui/keyconfig/KeyconfigController.h
Normal file
41
src/gui/keyconfig/KeyconfigController.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef KEYCONFIGSCONTROLLER_H
|
||||||
|
#define KEYCONFIGSCONTROLLER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class ControllerCallback;
|
||||||
|
class KeyconfigView;
|
||||||
|
class GameModel;
|
||||||
|
class OptionsController;
|
||||||
|
class KeyconfigModel;
|
||||||
|
struct BindingModel;
|
||||||
|
|
||||||
|
class KeyconfigController
|
||||||
|
{
|
||||||
|
ControllerCallback * callback;
|
||||||
|
KeyconfigView* view;
|
||||||
|
KeyconfigModel* model;
|
||||||
|
OptionsController* parent;
|
||||||
|
public:
|
||||||
|
bool HasExited;
|
||||||
|
KeyconfigController(OptionsController* _parent);
|
||||||
|
void Exit();
|
||||||
|
KeyconfigView * GetView();
|
||||||
|
virtual ~KeyconfigController();
|
||||||
|
void AddModel(BindingModel model);
|
||||||
|
void CreateModel(BindingModel model);
|
||||||
|
void ChangeModel(BindingModel model);
|
||||||
|
void Save();
|
||||||
|
void ForceHasConflict();
|
||||||
|
void NotifyKeyReleased();
|
||||||
|
void OnKeyReleased();
|
||||||
|
void NotifyBindingsChanged();
|
||||||
|
void PopBindingByFunctionId(int functionId);
|
||||||
|
bool FunctionHasShortcut(int functionId);
|
||||||
|
void ResetToDefaults();
|
||||||
|
|
||||||
|
void LoadBindingPrefs();
|
||||||
|
std::vector<BindingModel> GetBindingPrefs();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* KEYCONFIGSCONTROLLER_H */
|
152
src/gui/keyconfig/KeyconfigMap.h
Normal file
152
src/gui/keyconfig/KeyconfigMap.h
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#ifndef KEYCONFIGSMAP_H
|
||||||
|
#define KEYCONFIGSMAP_H
|
||||||
|
|
||||||
|
#include "common/String.h"
|
||||||
|
|
||||||
|
typedef struct KeyconfigMap
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
String description;
|
||||||
|
int functionId;
|
||||||
|
} KeyconfigMap;
|
||||||
|
|
||||||
|
typedef struct DefaultKeyconfigMap
|
||||||
|
{
|
||||||
|
ByteString keyCombo;
|
||||||
|
int bindingId; // KeyconfigMap id
|
||||||
|
} DefaultKeyconfigMap;
|
||||||
|
|
||||||
|
static KeyconfigMap keyboardBindingFunctionMap[] =
|
||||||
|
{
|
||||||
|
{ 0x00, "Reload Simulation", 0 },
|
||||||
|
{ 0x01, "Open Element Search", 1 },
|
||||||
|
{ 0x02, "Toggle Air Mode", 2 },
|
||||||
|
{ 0x03, "Toggle Heat", 3 },
|
||||||
|
{ 0x04, "Toggle Newtonian Gravity", 4 },
|
||||||
|
{ 0x05, "Open Stamps", 5 },
|
||||||
|
{ 0x06, "Invert Air Simulation", 6 },
|
||||||
|
{ 0x07, "Pause Simulation", 7 },
|
||||||
|
{ 0x08, "Enable Zoom", 8 },
|
||||||
|
{ 0x09, "Undo", 9 },
|
||||||
|
{ 0x0A, "Redo", 10 },
|
||||||
|
{ 0x0B, "Property Tool", 11 },
|
||||||
|
{ 0x0C, "Property Tool", 11 },
|
||||||
|
{ 0x0D, "Screenshot", 12 },
|
||||||
|
{ 0x0E, "Toggle Debug HUD", 13 },
|
||||||
|
{ 0x0F, "Save Authorship Info", 14 },
|
||||||
|
{ 0x10, "Reload Simulation", 0 },
|
||||||
|
{ 0x11, "Frame Step", 15 },
|
||||||
|
{ 0x12, "Find Mode", 16 },
|
||||||
|
{ 0x13, "Show Gravity Grid", 17 },
|
||||||
|
{ 0x14, "Increase Gravity Grid Size", 18 },
|
||||||
|
{ 0x15, "Decrease Gravity Grid Size", 19 },
|
||||||
|
{ 0x16, "Toggle Intro Text", 20 },
|
||||||
|
{ 0x17, "Toggle Intro Text", 20 },
|
||||||
|
{ 0x18, "Toggle HUD", 21 },
|
||||||
|
{ 0x19, "Toggle Decorations Layer", 22 },
|
||||||
|
{ 0x1A, "Toggle Decoration Tool", 23 },
|
||||||
|
{ 0x1B, "Redo", 10 },
|
||||||
|
{ 0x1C, "Quit", 24 },
|
||||||
|
{ 0x1D, "Quit", 24 },
|
||||||
|
{ 0x1E, "Reset Spark", 25 },
|
||||||
|
{ 0x1F, "Reset Air", 26 },
|
||||||
|
{ 0x20, "Copy", 27 },
|
||||||
|
{ 0x21, "Cut", 28 },
|
||||||
|
{ 0x22, "Paste", 29 },
|
||||||
|
{ 0x23, "Stamp Tool", 30 },
|
||||||
|
{ 0x24, "Increase Brush Size", 31 },
|
||||||
|
{ 0x25, "Decrease Brush Size", 32 },
|
||||||
|
{ 0x26, "Install Game", 33 },
|
||||||
|
{ 0x27, "Toggle Replace Mode", 34 },
|
||||||
|
{ 0x28, "Toggle Specific Delete Mode", 35 },
|
||||||
|
{ 0x29, "Toggle Console", 36 }
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KeyconfigFunction
|
||||||
|
{
|
||||||
|
RELOAD_SIMULATION,
|
||||||
|
OPEN_ELEMENT_SEARCH,
|
||||||
|
TOGGLE_AIR_MODE,
|
||||||
|
TOGGLE_HEAT,
|
||||||
|
TOGGLE_NEWTONIAN_GRAVITY,
|
||||||
|
OPEN_STAMPS,
|
||||||
|
INVERT_AIR_SIMULATION,
|
||||||
|
PAUSE_SIMULATION,
|
||||||
|
ENABLE_ZOOM,
|
||||||
|
UNDO,
|
||||||
|
REDO,
|
||||||
|
PROPERTY_TOOL,
|
||||||
|
SCREENSHOT,
|
||||||
|
TOGGLE_DEBUG_HUD,
|
||||||
|
SAVE_AUTHORSHIP_INFO,
|
||||||
|
FRAME_STEP,
|
||||||
|
FIND_MODE,
|
||||||
|
SHOW_GRAVITY_GRID,
|
||||||
|
INCREASE_GRAVITY_GRID_SIZE,
|
||||||
|
DECREASE_GRAVITY_GRID_SIZE,
|
||||||
|
TOGGLE_INTRO_TEXT,
|
||||||
|
TOGGLE_HUD,
|
||||||
|
TOGGLE_DECORATIONS_LAYER,
|
||||||
|
TOGGLE_DECORATION_TOOL,
|
||||||
|
QUIT,
|
||||||
|
RESET_SPARK,
|
||||||
|
RESET_AIR,
|
||||||
|
COPY,
|
||||||
|
CUT,
|
||||||
|
PASTE,
|
||||||
|
STAMP_TOOL,
|
||||||
|
INCREASE_BRUSH_SIZE,
|
||||||
|
DECREASE_BRUSH_SIZE,
|
||||||
|
INSTALL_GAME,
|
||||||
|
TOGGLE_REPLACE_MODE,
|
||||||
|
TOGGLE_SPECIFIC_DELETE_MODE,
|
||||||
|
TOGGLE_CONSOLE
|
||||||
|
};
|
||||||
|
|
||||||
|
static DefaultKeyconfigMap defaultKeyconfigMapArray[] =
|
||||||
|
{
|
||||||
|
{ "0+62", 0x00 },
|
||||||
|
{ "0+8", 0x01 },
|
||||||
|
{ "0+28", 0x02 },
|
||||||
|
{ "0+24", 0x03 },
|
||||||
|
{ "0+17", 0x04 },
|
||||||
|
{ "0+14", 0x05 },
|
||||||
|
{ "0+12", 0x06 },
|
||||||
|
{ "0+44", 0x07 },
|
||||||
|
{ "0+29", 0x08 },
|
||||||
|
{ "1+29", 0x09 },
|
||||||
|
{ "5+29", 0x0A },
|
||||||
|
{ "5+69", 0x0B },
|
||||||
|
{ "1+69", 0x0C },
|
||||||
|
{ "0+69", 0x0D },
|
||||||
|
{ "0+60", 0x0E },
|
||||||
|
{ "0+4", 0x0F },
|
||||||
|
{ "1+21", 0x10 },
|
||||||
|
{ "0+9", 0x11 },
|
||||||
|
{ "1+9", 0x12 },
|
||||||
|
{ "1+10", 0x13 },
|
||||||
|
{ "0+10", 0x14 },
|
||||||
|
{ "4+10", 0x15 },
|
||||||
|
{ "0+58", 0x16 },
|
||||||
|
{ "1+11", 0x17 },
|
||||||
|
{ "0+11", 0x18 },
|
||||||
|
{ "1+5", 0x19 },
|
||||||
|
{ "0+5", 0x1A },
|
||||||
|
{ "1+28", 0x1B },
|
||||||
|
{ "0+41", 0x1C },
|
||||||
|
{ "0+20", 0x1D },
|
||||||
|
{ "1+46", 0x1E },
|
||||||
|
{ "0+46", 0x1F },
|
||||||
|
{ "1+6", 0x20 },
|
||||||
|
{ "1+27", 0x21 },
|
||||||
|
{ "1+25", 0x22 },
|
||||||
|
{ "0+15", 0x23 },
|
||||||
|
{ "0+48", 0x24 },
|
||||||
|
{ "0+47", 0x25 },
|
||||||
|
{ "1+12", 0x26 },
|
||||||
|
{ "1+51", 0x27 },
|
||||||
|
{ "0+51", 0x28 },
|
||||||
|
{ "0+53", 0x29 }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
364
src/gui/keyconfig/KeyconfigModel.cpp
Normal file
364
src/gui/keyconfig/KeyconfigModel.cpp
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
static int Aa;
|
||||||
|
#if 0 // temporarily disabled so it doesn't interfere with what I'm doing -- LBPHacker
|
||||||
|
#include "KeyconfigModel.h"
|
||||||
|
|
||||||
|
// #include "client/Client.h"
|
||||||
|
// #include "SDLCompat.h"
|
||||||
|
// #include "KeyconfigMap.h"
|
||||||
|
// #include <algorithm>
|
||||||
|
// #include "KeyconfigView.h"
|
||||||
|
|
||||||
|
// void KeyconfigModel::WriteDefaultFuncArray(bool force)
|
||||||
|
// {
|
||||||
|
// if (force)
|
||||||
|
// Client::Ref().ClearPref(ByteString(KEYCONFIG_FUNCS_PREF));
|
||||||
|
|
||||||
|
// for (auto defaultBinding : defaultKeyconfigMapArray)
|
||||||
|
// {
|
||||||
|
// int functionId;
|
||||||
|
// String description;
|
||||||
|
// for (auto functions : keyboardBindingFunctionMap)
|
||||||
|
// {
|
||||||
|
// if (functions.id == defaultBinding.bindingId)
|
||||||
|
// {
|
||||||
|
// functionId = functions.functionId;
|
||||||
|
// description = functions.description;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ByteString pref = ByteString(KEYCONFIG_FUNCS_PREF) + ByteString(".") + ByteString(functionId);
|
||||||
|
// bool functionExists = Client::Ref().GetPrefJson(pref, Json::nullValue) != Json::nullValue;
|
||||||
|
|
||||||
|
// if (!force && functionExists)
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
// Json::Value prefValue;
|
||||||
|
|
||||||
|
// prefValue["hasShortcut"] = true;
|
||||||
|
// prefValue["functionId"] = functionId;
|
||||||
|
// Client::Ref().SetPref(pref, prefValue);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void KeyconfigModel::WriteDefaultPrefs(bool force)
|
||||||
|
// {
|
||||||
|
// // Load temporary bindings into memory
|
||||||
|
// // this is so we can add in any new axctions
|
||||||
|
// // from the KeyconfigMap into our prefs
|
||||||
|
// LoadBindingPrefs();
|
||||||
|
|
||||||
|
// if (force)
|
||||||
|
// Client::Ref().ClearPref(ByteString(KEYCONFIG_PREF));
|
||||||
|
|
||||||
|
// WriteDefaultFuncArray(force);
|
||||||
|
|
||||||
|
// for (auto defaultBinding : defaultKeyconfigMapArray)
|
||||||
|
// {
|
||||||
|
// int functionId;
|
||||||
|
// String description;
|
||||||
|
// for (auto functions : keyboardBindingFunctionMap)
|
||||||
|
// {
|
||||||
|
// if (functions.id == defaultBinding.bindingId)
|
||||||
|
// {
|
||||||
|
// functionId = functions.functionId;
|
||||||
|
// description = functions.description;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ByteString pref = ByteString(KEYCONFIG_PREF) + ByteString(".") + defaultBinding.keyCombo;
|
||||||
|
// Json::Value prefValue;
|
||||||
|
|
||||||
|
// // if we not forcing then check if the function is already set up as a pref
|
||||||
|
// // if it is then bail the current iteration
|
||||||
|
// if (!force)
|
||||||
|
// {
|
||||||
|
// if (bindingPrefs.size() > 0)
|
||||||
|
// {
|
||||||
|
// for (auto prefBinding : bindingPrefs)
|
||||||
|
// {
|
||||||
|
// if (prefBinding.functionId == functionId)
|
||||||
|
// goto end; // evil but necessary
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// prefValue["description"] = description.ToUtf8();
|
||||||
|
// prefValue["functionId"] = functionId;
|
||||||
|
// Client::Ref().SetPref(pref, prefValue);
|
||||||
|
|
||||||
|
// end:;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // force is from a user action so don't write into store
|
||||||
|
// // until user hits OK
|
||||||
|
// if (!force)
|
||||||
|
// Client::Ref().WritePrefs();
|
||||||
|
|
||||||
|
// LoadBindingPrefs();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void KeyconfigModel::LoadBindingPrefs()
|
||||||
|
// {
|
||||||
|
// Json::Value bindings = Client::Ref().GetPrefJson(KEYCONFIG_PREF);
|
||||||
|
// bindingPrefs.clear();
|
||||||
|
|
||||||
|
// if (bindings != Json::nullValue)
|
||||||
|
// {
|
||||||
|
// Json::Value::Members keyComboJson = bindings.getMemberNames();
|
||||||
|
// int index = 0;
|
||||||
|
|
||||||
|
// for (auto& member : keyComboJson)
|
||||||
|
// {
|
||||||
|
// ByteString keyCombo(member);
|
||||||
|
// ByteString pref = ByteString(KEYCONFIG_PREF) + "." + keyCombo;
|
||||||
|
// Json::Value result = Client::Ref().GetPrefJson(pref);
|
||||||
|
|
||||||
|
// if (result != Json::nullValue)
|
||||||
|
// {
|
||||||
|
// BindingModel model;
|
||||||
|
// std::pair<int, int> p = GetModifierAndScanFromString(keyCombo);
|
||||||
|
// model.modifier = p.first;
|
||||||
|
// model.scan = p.second;
|
||||||
|
// model.functionId = result["functionId"].asInt();
|
||||||
|
// model.description = ByteString(result["description"].asString()).FromUtf8();
|
||||||
|
// model.index = index;
|
||||||
|
// bindingPrefs.push_back(model);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// index++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// std::pair<int, int>
|
||||||
|
// KeyconfigModel::GetModifierAndScanFromString(ByteString str)
|
||||||
|
// {
|
||||||
|
// int modifier = 0;
|
||||||
|
// int scan = 0;
|
||||||
|
|
||||||
|
// if (str == "NULL")
|
||||||
|
// {
|
||||||
|
// scan = -1;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// ByteString::Split split = str.SplitBy("+");
|
||||||
|
|
||||||
|
// // not the last int so its a modifier
|
||||||
|
// ByteString modString = split.Before();
|
||||||
|
|
||||||
|
// modifier |= (std::stoi(modString) & BINDING_MASK);
|
||||||
|
// scan = std::stoi(split.After());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return std::make_pair(modifier, scan);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void KeyconfigModel::TurnOffFunctionShortcut(int functionId)
|
||||||
|
// {
|
||||||
|
// ByteString pref = ByteString(KEYCONFIG_FUNCS_PREF) + ByteString(".") + ByteString(functionId)
|
||||||
|
// + ByteString(".hasShortcut");
|
||||||
|
|
||||||
|
// Client::Ref().SetPref(pref, false);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void KeyconfigModel::TurnOnFunctionShortcut(int functionId)
|
||||||
|
// {
|
||||||
|
// ByteString pref = ByteString(KEYCONFIG_FUNCS_PREF) + ByteString(".") + ByteString(functionId)
|
||||||
|
// + ByteString(".hasShortcut");
|
||||||
|
|
||||||
|
// Client::Ref().SetPref(pref, true);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void KeyconfigModel::RemoveModelByIndex(int index)
|
||||||
|
// {
|
||||||
|
// std::vector<BindingModel>::iterator it = bindingPrefs.begin();
|
||||||
|
|
||||||
|
// while(it != bindingPrefs.end())
|
||||||
|
// {
|
||||||
|
// auto& pref = *it;
|
||||||
|
// if (pref.index == index)
|
||||||
|
// {
|
||||||
|
// bindingPrefs.erase(it);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// it++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void KeyconfigModel::CreateModel(BindingModel model)
|
||||||
|
// {
|
||||||
|
// // if the function has no shortcut then just turn it on
|
||||||
|
// if (!FunctionHasShortcut(model.functionId))
|
||||||
|
// {
|
||||||
|
// TurnOnFunctionShortcut(model.functionId);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // index is just an session based id that we use
|
||||||
|
// // to identify removals/changes
|
||||||
|
// // so whenever a new model is created we just set it to the
|
||||||
|
// // size of the container
|
||||||
|
// model.index = bindingPrefs.size();
|
||||||
|
// bindingPrefs.push_back(model);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void KeyconfigModel::AddModel(BindingModel model)
|
||||||
|
// {
|
||||||
|
// bindingPrefs.push_back(model);
|
||||||
|
// TurnOnFunctionShortcut(model.functionId);
|
||||||
|
// bool hasConflict = HasConflictingCombo();
|
||||||
|
// NotifyBindingsChanged(hasConflict);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool KeyconfigModel::FunctionHasShortcut(int functionId)
|
||||||
|
// {
|
||||||
|
// ByteString pref = ByteString(KEYCONFIG_FUNCS_PREF) + ByteString(".") + ByteString(functionId)
|
||||||
|
// + ByteString(".hasShortcut");
|
||||||
|
|
||||||
|
// return Client::Ref().GetPrefBool(pref, false);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void KeyconfigModel::Save()
|
||||||
|
// {
|
||||||
|
// Client::Ref().ClearPref(KEYCONFIG_PREF);
|
||||||
|
|
||||||
|
// for (auto& binding : bindingPrefs)
|
||||||
|
// {
|
||||||
|
// ByteString mod(std::to_string(binding.modifier));
|
||||||
|
// ByteString scan(std::to_string(binding.scan));
|
||||||
|
// ByteString pref = ByteString(KEYCONFIG_PREF) + ByteString(".") + mod + ByteString("+") + scan;
|
||||||
|
|
||||||
|
// Json::Value val;
|
||||||
|
// val["functionId"] = binding.functionId;
|
||||||
|
// val["description"] = binding.description.ToUtf8();
|
||||||
|
// Client::Ref().SetPref(pref, val);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Client::Ref().WritePrefs();
|
||||||
|
// }
|
||||||
|
|
||||||
|
int KeyconfigModel::GetFunctionForBinding(int scan, bool shift, bool ctrl, bool alt)
|
||||||
|
{
|
||||||
|
int modifier = 0;
|
||||||
|
|
||||||
|
if (ctrl)
|
||||||
|
modifier |= BINDING_CTRL;
|
||||||
|
|
||||||
|
if (alt)
|
||||||
|
modifier |= BINDING_ALT;
|
||||||
|
|
||||||
|
if (shift)
|
||||||
|
modifier |= BINDING_SHIFT;
|
||||||
|
|
||||||
|
auto it = std::find_if(bindingPrefs.begin(), bindingPrefs.end(), [modifier, scan](BindingModel m)
|
||||||
|
{
|
||||||
|
return m.modifier == modifier && m.scan == scan;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != bindingPrefs.end())
|
||||||
|
{
|
||||||
|
BindingModel binding = *it;
|
||||||
|
|
||||||
|
if (FunctionHasShortcut(binding.functionId))
|
||||||
|
return binding.functionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Here we pop off a hotkey if the user clicks delete
|
||||||
|
* however if we are on the last remaining hotkey
|
||||||
|
* then we turn off hasShortcut for the associated function
|
||||||
|
* so it renders as *No Shortcut* on the view
|
||||||
|
*/
|
||||||
|
// void KeyconfigModel::PopBindingByFunctionId(int functionId)
|
||||||
|
// {
|
||||||
|
// std::sort(bindingPrefs.begin(), bindingPrefs.end(), [](BindingModel a, BindingModel b)
|
||||||
|
// {
|
||||||
|
// return a.index > b.index;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// std::vector<BindingModel> v;
|
||||||
|
// for (auto b : bindingPrefs)
|
||||||
|
// {
|
||||||
|
// if (b.functionId == functionId)
|
||||||
|
// v.push_back(b);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (v.size() == 1)
|
||||||
|
// {
|
||||||
|
// auto it = std::find(bindingPrefs.begin(), bindingPrefs.end(), v[0]);
|
||||||
|
// TurnOffFunctionShortcut((*it).functionId);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// auto it = bindingPrefs.begin();
|
||||||
|
// while (it != bindingPrefs.end())
|
||||||
|
// {
|
||||||
|
// if ((*it).functionId == functionId)
|
||||||
|
// {
|
||||||
|
// bindingPrefs.erase(it);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// it++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// String KeyconfigModel::GetDisplayForModel(BindingModel model)
|
||||||
|
// {
|
||||||
|
// return model.description;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool KeyconfigModel::HasConflictingCombo()
|
||||||
|
// {
|
||||||
|
// for (auto& binding : bindingPrefs)
|
||||||
|
// {
|
||||||
|
// // if we have any new bindings then we
|
||||||
|
// // need to return a conflict until
|
||||||
|
// // the user types out a binding
|
||||||
|
// if (binding.isNew)
|
||||||
|
// return true;
|
||||||
|
|
||||||
|
// // if the current binding has no shortcut then skip
|
||||||
|
// if (!FunctionHasShortcut(binding.functionId))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
// // if key combo appears twice then there is a conflicting combo
|
||||||
|
// auto iter = std::find(bindingPrefs.begin(), bindingPrefs.end(), binding);
|
||||||
|
// if (iter != bindingPrefs.end())
|
||||||
|
// {
|
||||||
|
// // if this time round we don't have a shortcut either
|
||||||
|
// // then we can safely continue because this means
|
||||||
|
// // we don't have a conflict for the current binding
|
||||||
|
// if (!FunctionHasShortcut((*iter).functionId))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
// iter++;
|
||||||
|
// iter = std::find(iter, bindingPrefs.end(), binding);
|
||||||
|
// if (iter != bindingPrefs.end())
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void KeyconfigModel::AddObserver(KeyconfigView* view)
|
||||||
|
{
|
||||||
|
observers.push_back(view);
|
||||||
|
view->NotifyKeyconfigChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigModel::notifyKeyconfigChanged(bool hasConflict)
|
||||||
|
{
|
||||||
|
for (auto& observer : observers)
|
||||||
|
{
|
||||||
|
observer->NotifyKeyconfigChanged(hasConflict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
81
src/gui/keyconfig/KeyconfigModel.h
Normal file
81
src/gui/keyconfig/KeyconfigModel.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef KEYCONFIGSMODEL_H
|
||||||
|
#define KEYCONFIGSMODEL_H
|
||||||
|
|
||||||
|
// #include <vector>
|
||||||
|
// #include <utility>
|
||||||
|
// #include "common/String.h"
|
||||||
|
|
||||||
|
// #define KEYCONFIG_PREF "Keyconfig"
|
||||||
|
// #define KEYCONFIG_FUNCS_PREF "KeyconfigFunctions"
|
||||||
|
|
||||||
|
// #define BINDING_MASK 0x07
|
||||||
|
// #define BINDING_CTRL 0x01
|
||||||
|
// #define BINDING_ALT 0x02
|
||||||
|
// #define BINDING_SHIFT 0x04
|
||||||
|
|
||||||
|
// struct BindingModel
|
||||||
|
// {
|
||||||
|
// int modifier;
|
||||||
|
// int scan;
|
||||||
|
// int functionId;
|
||||||
|
// String description;
|
||||||
|
// int index;
|
||||||
|
// bool noShortcut;
|
||||||
|
// bool isNew;
|
||||||
|
|
||||||
|
// BindingModel() : noShortcut(false), isNew(false){};
|
||||||
|
|
||||||
|
// bool operator==(const BindingModel& other) const
|
||||||
|
// {
|
||||||
|
// return modifier == other.modifier && scan == other.scan;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool operator< (const BindingModel &other) const
|
||||||
|
// {
|
||||||
|
// if (description == other.description)
|
||||||
|
// return index < other.index;
|
||||||
|
|
||||||
|
// return description < other.description;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
class KeyconfigView;
|
||||||
|
|
||||||
|
class KeyconfigModel
|
||||||
|
{
|
||||||
|
GameModel *gModel;
|
||||||
|
std::vector<KeyconfigView *> observers;
|
||||||
|
void notifyKeyconfigChanged();
|
||||||
|
|
||||||
|
public:
|
||||||
|
KeyconfigModel(GameModel *gModel);
|
||||||
|
void AddObserver(KeyconfigView* observer);
|
||||||
|
std::vector<BindingModel> GetBindingPrefs();
|
||||||
|
virtual ~KeyconfigModel();
|
||||||
|
|
||||||
|
// void RemoveModelByIndex(int index);
|
||||||
|
// void AddModel(BindingModel model);
|
||||||
|
// void CreateModel(BindingModel model);
|
||||||
|
// String GetDisplayForModel(BindingModel model);
|
||||||
|
// void NotifyBindingsChanged(bool hasConflict);
|
||||||
|
// bool HasConflictingCombo();
|
||||||
|
// void PopBindingByFunctionId(int functionId);
|
||||||
|
// void WriteDefaultFuncArray(bool force = false);
|
||||||
|
// bool FunctionHasShortcut(int functionId);
|
||||||
|
// int GetFunctionForBinding(int scan, bool shift, bool ctrl, bool alt);
|
||||||
|
|
||||||
|
|
||||||
|
// void Save();
|
||||||
|
// void WriteDefaultPrefs(bool force = false); // true if user clicks reset to defaults
|
||||||
|
// inline std::vector<BindingModel> GetBindingPrefs() const { return bindingPrefs; }
|
||||||
|
// void LoadBindingPrefs();
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
// void TurnOffFunctionShortcut(int functionId);
|
||||||
|
// void TurnOnFunctionShortcut(int functionId);
|
||||||
|
|
||||||
|
// std::vector<BindingModel> bindingPrefs;
|
||||||
|
// std::pair<int, int> GetModifierAndScanFromString(ByteString str);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KEYCONFIGSMODEL_H
|
122
src/gui/keyconfig/KeyconfigTextbox.cpp
Normal file
122
src/gui/keyconfig/KeyconfigTextbox.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
static int Aa;
|
||||||
|
#if 0 // temporarily disabled so it doesn't interfere with what I'm doing -- LBPHacker
|
||||||
|
#include "KeyconfigTextbox.h"
|
||||||
|
#include "SDLCompat.h"
|
||||||
|
#include "gui/interface/Window.h"
|
||||||
|
#include "client/Client.h"
|
||||||
|
#include "KeyconfigModel.h"
|
||||||
|
#include "KeyconfigController.h"
|
||||||
|
|
||||||
|
KeyconfigTextbox::KeyconfigTextbox(ui::Point position, ui::Point size) :
|
||||||
|
ui::Textbox(position, size)
|
||||||
|
{
|
||||||
|
// reasonable defaults
|
||||||
|
SetTextColour(ui::Colour(255, 255, 255));
|
||||||
|
Appearance.HorizontalAlign = ui::Appearance::AlignCentre;
|
||||||
|
Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigTextbox::OnMouseClick(int x, int y, unsigned button)
|
||||||
|
{
|
||||||
|
prevKey = GetText();
|
||||||
|
SetText("");
|
||||||
|
c->ForceHasConflict();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigTextbox::AttachController(KeyconfigController* _c)
|
||||||
|
{
|
||||||
|
c = _c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigTextbox::SetModel(BindingModel _model)
|
||||||
|
{
|
||||||
|
model = _model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigTextbox::SetTextToPrevious()
|
||||||
|
{
|
||||||
|
SetText(prevKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigTextbox::SetTextFromModifierAndScan(int modifier, int scan)
|
||||||
|
{
|
||||||
|
ByteString modDisplay;
|
||||||
|
|
||||||
|
if (modifier & BINDING_CTRL)
|
||||||
|
{
|
||||||
|
modDisplay += "CTRL+";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifier & BINDING_ALT)
|
||||||
|
{
|
||||||
|
modDisplay += "ALT+";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifier & BINDING_SHIFT)
|
||||||
|
{
|
||||||
|
modDisplay += "SHIFT+";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* scanDisplay = SDL_GetScancodeName((SDL_Scancode) scan);
|
||||||
|
ByteString keyNameDisplay(scanDisplay);
|
||||||
|
keyNameDisplay = modDisplay + keyNameDisplay.ToUpper();
|
||||||
|
|
||||||
|
SetText(keyNameDisplay.FromUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigTextbox::OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt)
|
||||||
|
{
|
||||||
|
ui::Textbox::OnKeyRelease(key, scan, repeat, shift, ctrl, alt);
|
||||||
|
|
||||||
|
int mod = 0x00;
|
||||||
|
ByteString modDisplay = "";
|
||||||
|
|
||||||
|
if (ctrl)
|
||||||
|
{
|
||||||
|
mod |= BINDING_CTRL;
|
||||||
|
modDisplay += "CTRL+";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alt)
|
||||||
|
{
|
||||||
|
mod |= BINDING_ALT;
|
||||||
|
modDisplay += "ALT+";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shift)
|
||||||
|
{
|
||||||
|
mod |= BINDING_SHIFT;
|
||||||
|
modDisplay += "SHIFT+";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* scanDisplay = SDL_GetScancodeName((SDL_Scancode) scan);
|
||||||
|
ByteString keyNameDisplay(scanDisplay);
|
||||||
|
keyNameDisplay = modDisplay + keyNameDisplay.ToUpper();
|
||||||
|
|
||||||
|
if (!scan)
|
||||||
|
{
|
||||||
|
SetText(prevKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetText(keyNameDisplay.FromUtf8());
|
||||||
|
GetParentWindow()->FocusComponent(NULL);
|
||||||
|
|
||||||
|
BindingModel newModel;
|
||||||
|
newModel.modifier = mod;
|
||||||
|
newModel.scan = (int) scan;
|
||||||
|
newModel.functionId = model.functionId;
|
||||||
|
newModel.description = model.description;
|
||||||
|
newModel.index = model.index;
|
||||||
|
newModel.isNew = false;
|
||||||
|
newModel.noShortcut = false;
|
||||||
|
|
||||||
|
c->ChangeModel(newModel);
|
||||||
|
|
||||||
|
model = newModel;
|
||||||
|
|
||||||
|
// we notify the controller so the view can recover all empty textboxes
|
||||||
|
// should the user carelessly click about
|
||||||
|
c->NotifyKeyReleased();
|
||||||
|
}
|
||||||
|
#endif
|
31
src/gui/keyconfig/KeyconfigTextbox.h
Normal file
31
src/gui/keyconfig/KeyconfigTextbox.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef KEYCONFIGSTEXTBOX_H
|
||||||
|
#define KEYCONFIGSTEXTBOX_H
|
||||||
|
|
||||||
|
#include "gui/interface/Textbox.h"
|
||||||
|
#include "KeyconfigModel.h"
|
||||||
|
|
||||||
|
class KeyconfigController;
|
||||||
|
|
||||||
|
class KeyconfigTextbox: public ui::Textbox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyconfigTextbox(ui::Point position, ui::Point size);
|
||||||
|
|
||||||
|
void OnKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt);
|
||||||
|
void OnMouseClick(int x, int y, unsigned button);
|
||||||
|
|
||||||
|
void SetModel(BindingModel _model);
|
||||||
|
void SetTextFromModifierAndScan(int modifier, int scan);
|
||||||
|
void SetTextToPrevious();
|
||||||
|
|
||||||
|
void OnTextInput(String text) {}
|
||||||
|
|
||||||
|
void AttachController(KeyconfigController* _c);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
String prevKey;
|
||||||
|
KeyconfigController* c;
|
||||||
|
BindingModel model;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* KEYCONFIGSTEXTBOX_H */
|
293
src/gui/keyconfig/KeyconfigView.cpp
Normal file
293
src/gui/keyconfig/KeyconfigView.cpp
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
static int Aa;
|
||||||
|
#if 0 // temporarily disabled so it doesn't interfere with what I'm doing -- LBPHacker
|
||||||
|
#include "KeyconfigView.h"
|
||||||
|
#include "gui/interface/Button.h"
|
||||||
|
#include "gui/interface/Label.h"
|
||||||
|
#include "gui/interface/DropDown.h"
|
||||||
|
#include "gui/interface/Engine.h"
|
||||||
|
#include "gui/interface/Checkbox.h"
|
||||||
|
#include "gui/interface/ScrollPanel.h"
|
||||||
|
#include "gui/Style.h"
|
||||||
|
#include "graphics/Graphics.h"
|
||||||
|
#include "KeyconfigMap.h"
|
||||||
|
#include "KeyconfigTextbox.h"
|
||||||
|
#include "KeyconfigModel.h"
|
||||||
|
#include "KeyconfigController.h"
|
||||||
|
#include "client/Client.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
KeyconfigView::KeyconfigView() :
|
||||||
|
ui::Window(ui::Point(-1, -1), ui::Point(320, 340)) {
|
||||||
|
|
||||||
|
ui::Label * tempLabel = new ui::Label(ui::Point(4, 1), ui::Point(Size.X / 2, 22), "Keyboard Bindings");
|
||||||
|
tempLabel->SetTextColour(style::Colour::InformationTitle);
|
||||||
|
tempLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||||
|
tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||||
|
AddComponent(tempLabel);
|
||||||
|
|
||||||
|
class ResetDefaultsAction: public ui::ButtonAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyconfigView * v;
|
||||||
|
ResetDefaultsAction(KeyconfigView * v_) { v = v_; }
|
||||||
|
void ActionCallback(ui::Button * sender) override
|
||||||
|
{
|
||||||
|
v->c->ResetToDefaults();
|
||||||
|
v->BuildKeyBindingsListView();
|
||||||
|
v->c->NotifyBindingsChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui::Button* resetDefaults = new ui::Button(ui::Point(Size.X - 150, 5), ui::Point(140, 18), "Reset to Defaults");
|
||||||
|
resetDefaults->SetActionCallback(new ResetDefaultsAction(this));
|
||||||
|
AddComponent(resetDefaults);
|
||||||
|
|
||||||
|
conflictLabel = new ui::Label(ui::Point(4, resetDefaults->Size.Y + 10), ui::Point(Size.X / 2, 18), "Please resolve conflicts or empty bindings");
|
||||||
|
conflictLabel->SetTextColour(style::Colour::ErrorTitle);
|
||||||
|
conflictLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||||
|
conflictLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||||
|
conflictLabel->Visible = false;
|
||||||
|
AddComponent(conflictLabel);
|
||||||
|
|
||||||
|
class CloseAction: public ui::ButtonAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyconfigView * v;
|
||||||
|
CloseAction(KeyconfigView * v_) { v = v_; }
|
||||||
|
void ActionCallback(ui::Button * sender) override
|
||||||
|
{
|
||||||
|
v->c->Save();
|
||||||
|
v->c->Exit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
okayButton = new ui::Button(ui::Point(0, Size.Y-16), ui::Point(Size.X, 16), "OK");
|
||||||
|
okayButton->SetActionCallback(new CloseAction(this));
|
||||||
|
AddComponent(okayButton);
|
||||||
|
SetCancelButton(okayButton);
|
||||||
|
SetOkayButton(okayButton);
|
||||||
|
scrollPanel = new ui::ScrollPanel(ui::Point(1, 50), ui::Point(Size.X-2, Size.Y-70));
|
||||||
|
AddComponent(scrollPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigView::ClearScrollPanel()
|
||||||
|
{
|
||||||
|
int count = scrollPanel->GetChildCount();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
auto com = scrollPanel->GetChild(i);
|
||||||
|
scrollPanel->RemoveChild(com);
|
||||||
|
RemoveComponent(com);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveComponent(scrollPanel);
|
||||||
|
textboxes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigView::BuildKeyBindingsListView()
|
||||||
|
{
|
||||||
|
int currentY = 0;
|
||||||
|
float scrollPos = scrollPanel->GetScrollPositionY();
|
||||||
|
ClearScrollPanel();
|
||||||
|
|
||||||
|
scrollPanel = new ui::ScrollPanel(ui::Point(1, 50), ui::Point(Size.X-2, Size.Y-70));
|
||||||
|
AddComponent(scrollPanel);
|
||||||
|
|
||||||
|
std::vector<BindingModel> bindingModel = c->GetBindingPrefs();
|
||||||
|
std::sort(bindingModel.begin(), bindingModel.end());
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)bindingModel.size(); i++)
|
||||||
|
{
|
||||||
|
BindingModel& binding = bindingModel[i];
|
||||||
|
|
||||||
|
ui::Label * functionLabel = new ui::Label(ui::Point(4, currentY), ui::Point(Size.X / 2, 16), binding.description);
|
||||||
|
functionLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||||
|
scrollPanel->AddChild(functionLabel);
|
||||||
|
|
||||||
|
KeyconfigTextbox* textbox;
|
||||||
|
ui::Label* noShortCutLabel;
|
||||||
|
|
||||||
|
bool hasBinding = true;
|
||||||
|
int removeButtonPosX = 0;
|
||||||
|
|
||||||
|
if (!c->FunctionHasShortcut(binding.functionId))
|
||||||
|
{
|
||||||
|
hasBinding = false;
|
||||||
|
noShortCutLabel = new ui::Label(ui::Point(functionLabel->Position.X + functionLabel->Size.X + 20, currentY), ui::Point(95, 16), "(No shortcut)");
|
||||||
|
noShortCutLabel->Appearance.HorizontalAlign = ui::Appearance::AlignCentre;
|
||||||
|
scrollPanel->AddChild(noShortCutLabel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textbox = new KeyconfigTextbox(ui::Point(functionLabel->Position.X + functionLabel->Size.X + 20, currentY), ui::Point(95, 16));
|
||||||
|
textbox->SetTextFromModifierAndScan(binding.modifier, binding.scan);
|
||||||
|
textbox->SetModel(binding);
|
||||||
|
textbox->AttachController(c);
|
||||||
|
textboxes.push_back(textbox);
|
||||||
|
scrollPanel->AddChild(textbox);
|
||||||
|
removeButtonPosX = textbox->Position.X + textbox->Size.X + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addButtonPosX = functionLabel->Position.X + functionLabel->Size.X - 5;
|
||||||
|
int addRemoveButtonsPosY = currentY;
|
||||||
|
currentY += 20;
|
||||||
|
|
||||||
|
// add in all the bindings associated with the current functionId
|
||||||
|
if (hasBinding)
|
||||||
|
{
|
||||||
|
auto it = bindingModel.begin() + i + 1;
|
||||||
|
while (it != bindingModel.end())
|
||||||
|
{
|
||||||
|
BindingModel nextBinding = *it;
|
||||||
|
if (nextBinding.functionId == binding.functionId)
|
||||||
|
{
|
||||||
|
KeyconfigTextbox* tb = new KeyconfigTextbox(ui::Point(functionLabel->Position.X + functionLabel->Size.X + 20, currentY), ui::Point(95, 16));
|
||||||
|
if (!nextBinding.isNew)
|
||||||
|
tb->SetTextFromModifierAndScan(nextBinding.modifier, nextBinding.scan);
|
||||||
|
else
|
||||||
|
tb->SetText("");
|
||||||
|
|
||||||
|
tb->SetModel(nextBinding);
|
||||||
|
tb->AttachController(c);
|
||||||
|
textboxes.push_back(tb);
|
||||||
|
scrollPanel->AddChild(tb);
|
||||||
|
currentY += 20;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the vector is sorted so once we hit unequality
|
||||||
|
// in function id then it means we are onto the next function
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::Button* addButton = new ui::Button(ui::Point(addButtonPosX, addRemoveButtonsPosY), ui::Point(20, 16), "+", "Add a binding to this action");
|
||||||
|
|
||||||
|
scrollPanel->AddChild(addButton);
|
||||||
|
|
||||||
|
class AddBindingAction: public ui::ButtonAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyconfigView * v;
|
||||||
|
int functionId;
|
||||||
|
String desc;
|
||||||
|
|
||||||
|
AddBindingAction(KeyconfigView * v_, int _functionId, String _desc)
|
||||||
|
{
|
||||||
|
v = v_;
|
||||||
|
functionId = _functionId;
|
||||||
|
desc = _desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionCallback(ui::Button * sender) override
|
||||||
|
{
|
||||||
|
auto modelArr = v->c->GetBindingPrefs();
|
||||||
|
auto it = std::find_if(modelArr.begin(), modelArr.end(), [this](BindingModel b)
|
||||||
|
{
|
||||||
|
return b.functionId == functionId && b.isNew;
|
||||||
|
});
|
||||||
|
|
||||||
|
// do not add more KBT's if we have an empty one on the
|
||||||
|
// current function
|
||||||
|
if (it != modelArr.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
BindingModel model;
|
||||||
|
model.isNew = true;
|
||||||
|
model.functionId = functionId;
|
||||||
|
model.description = desc; // for sorting
|
||||||
|
v->c->CreateModel(model);
|
||||||
|
v->BuildKeyBindingsListView();
|
||||||
|
v->c->NotifyBindingsChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RemoveBindingAction: public ui::ButtonAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyconfigView * v;
|
||||||
|
int functionId;
|
||||||
|
|
||||||
|
RemoveBindingAction(KeyconfigView * v_, int _functionId)
|
||||||
|
{
|
||||||
|
v = v_;
|
||||||
|
functionId = _functionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionCallback(ui::Button * sender) override
|
||||||
|
{
|
||||||
|
v->c->PopBindingByFunctionId(functionId);
|
||||||
|
v->BuildKeyBindingsListView();
|
||||||
|
v->c->NotifyBindingsChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
addButton->SetActionCallback(new AddBindingAction(this, binding.functionId, binding.description));
|
||||||
|
|
||||||
|
// only add in a remove button if we have a binding attached to the current function
|
||||||
|
if (hasBinding)
|
||||||
|
{
|
||||||
|
ui::Button* removeButton = new ui::Button(ui::Point(removeButtonPosX, addRemoveButtonsPosY), ui::Point(20, 16), "-", "Remove a binding from this action");
|
||||||
|
scrollPanel->AddChild(removeButton);
|
||||||
|
removeButton->SetActionCallback(new RemoveBindingAction(this, binding.functionId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollPanel->InnerSize = ui::Point(Size.X, currentY);
|
||||||
|
scrollPanel->SetScrollPosition(scrollPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigView::OnKeyReleased()
|
||||||
|
{
|
||||||
|
for (auto textbox : textboxes)
|
||||||
|
{
|
||||||
|
if (textbox->GetText().length() == 0)
|
||||||
|
{
|
||||||
|
textbox->SetTextToPrevious();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigView::AttachController(KeyconfigController* c_)
|
||||||
|
{
|
||||||
|
c = c_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigView::OnDraw()
|
||||||
|
{
|
||||||
|
Graphics * g = GetGraphics();
|
||||||
|
g->clearrect(Position.X-2, Position.Y-2, Size.X+3, Size.Y+3);
|
||||||
|
g->drawrect(Position.X, Position.Y, Size.X, Size.Y, 255, 255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigView::OnTryExit(ExitMethod method)
|
||||||
|
{
|
||||||
|
c->Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyconfigView::OnKeyCombinationChanged(bool hasConflict)
|
||||||
|
{
|
||||||
|
// disable OK button if there's a conflict
|
||||||
|
if (hasConflict)
|
||||||
|
{
|
||||||
|
okayButton->Enabled = false;
|
||||||
|
conflictLabel->Visible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
okayButton->Enabled = true;
|
||||||
|
conflictLabel->Visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyconfigView::~KeyconfigView()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
37
src/gui/keyconfig/KeyconfigView.h
Normal file
37
src/gui/keyconfig/KeyconfigView.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef KEYCONFIGSVIEW_H
|
||||||
|
#define KEYCONFIGSVIEW_H
|
||||||
|
|
||||||
|
#include "gui/interface/Window.h"
|
||||||
|
|
||||||
|
namespace ui
|
||||||
|
{
|
||||||
|
class ScrollPanel;
|
||||||
|
class Button;
|
||||||
|
class Label;
|
||||||
|
}
|
||||||
|
|
||||||
|
class KeyconfigController;
|
||||||
|
class KeyconfigTextbox;
|
||||||
|
|
||||||
|
class KeyconfigView: public ui::Window
|
||||||
|
{
|
||||||
|
ui::ScrollPanel* scrollPanel;
|
||||||
|
KeyconfigController* c;
|
||||||
|
public:
|
||||||
|
KeyconfigView();
|
||||||
|
void OnDraw() override;
|
||||||
|
void OnTryExit(ExitMethod method) override;
|
||||||
|
void AttachController(KeyconfigController* controller);
|
||||||
|
virtual ~KeyconfigView();
|
||||||
|
void OnKeyCombinationChanged(bool hasConflict);
|
||||||
|
void BuildKeyBindingsListView();
|
||||||
|
void OnKeyReleased();
|
||||||
|
void ClearScrollPanel();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ui::Button* okayButton;
|
||||||
|
ui::Label* conflictLabel;
|
||||||
|
std::vector<KeyconfigTextbox*> textboxes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* KEYCONFIGSVIEW_H */
|
@ -111,7 +111,6 @@ void OptionsController::Exit()
|
|||||||
HasExited = true;
|
HasExited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OptionsController::~OptionsController()
|
OptionsController::~OptionsController()
|
||||||
{
|
{
|
||||||
view->CloseActiveWindow();
|
view->CloseActiveWindow();
|
||||||
|
@ -448,6 +448,29 @@ OptionsView::OptionsView():
|
|||||||
tempLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
tempLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||||
tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||||
scrollPanel->AddChild(tempLabel);
|
scrollPanel->AddChild(tempLabel);
|
||||||
|
currentY+=20;
|
||||||
|
|
||||||
|
class KeyconfigAction: public ui::ButtonAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyconfigAction() { }
|
||||||
|
void ActionCallback(ui::Button * sender) override
|
||||||
|
{
|
||||||
|
// OptionsView* v = (OptionsView*) sender->GetParentWindow();
|
||||||
|
// KeyconfigController* keyboardBindingsController = new KeyconfigController(v->c);
|
||||||
|
// ui::Engine::Ref().ShowWindow(keyboardBindingsController->GetView());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui::Button * keyboardBindingsButton = new ui::Button(ui::Point(8, currentY), ui::Point(130, 16), "Open Keyboard Bindings");
|
||||||
|
keyboardBindingsButton->SetActionCallback(new KeyconfigAction());
|
||||||
|
scrollPanel->AddChild(keyboardBindingsButton);
|
||||||
|
|
||||||
|
tempLabel = new ui::Label(ui::Point(keyboardBindingsButton->Position.X+keyboardBindingsButton->Size.X+3, currentY), ui::Point(1, 16), "\bg- Change the keyboard bindings");
|
||||||
|
autowidth(tempLabel);
|
||||||
|
tempLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||||
|
tempLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
|
||||||
|
scrollPanel->AddChild(tempLabel);
|
||||||
|
|
||||||
class CloseAction: public ui::ButtonAction
|
class CloseAction: public ui::ButtonAction
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user