summaryrefslogtreecommitdiff
path: root/g_src/KeybindingScreen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'g_src/KeybindingScreen.cpp')
-rwxr-xr-xg_src/KeybindingScreen.cpp409
1 files changed, 409 insertions, 0 deletions
diff --git a/g_src/KeybindingScreen.cpp b/g_src/KeybindingScreen.cpp
new file mode 100755
index 0000000..02cbd81
--- /dev/null
+++ b/g_src/KeybindingScreen.cpp
@@ -0,0 +1,409 @@
+#ifdef __APPLE__
+# include "osx_messagebox.h"
+#elif defined(unix)
+# include <gtk/gtk.h>
+#endif
+
+#include "GL/glew.h"
+
+#ifdef WIN32
+
+#ifndef INTEGER_TYPES
+ #define INTEGER_TYPES
+ typedef short int16_t;
+ typedef int int32_t;
+ typedef long long int64_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+ typedef unsigned long long uint64_t;
+#endif
+
+typedef int32_t VIndex;
+typedef int32_t Ordinal;
+
+#endif
+
+#include "graphics.h"
+#include "init.h"
+#include "keybindings.h"
+#include "KeybindingScreen.h"
+
+#include <list>
+#include <map>
+#include <iostream>
+#include <sstream>
+#include <ctype.h>
+
+using namespace std;
+
+struct BindingGroup {
+ string name;
+ InterfaceKey start, end;
+};
+
+const BindingGroup groups[] = {
+ {"General" , INTERFACEKEY_NONE, WORLDKEY_START-1},
+ {"World" , WORLDKEY_START, ADVENTURERKEY_START-1},
+ {"Adventurer" , ADVENTURERKEY_START, EMBARKKEY_START-1},
+ {"Dwarf mode" , DWARFMAINKEY_START, MILITIAKEY_START-1},
+ {"Embark" , EMBARKKEY_START, BUILDINGKEY_START-1},
+ {"Building" , BUILDINGKEY_START, WORKSHOPKEY_START-1},
+ {"Workshop" , WORKSHOPKEY_START, PILEZONEKEY_START-1},
+ {"Pilezone" , PILEZONEKEY_START, STOCKORDERKEY_START-1},
+ {"Stockorder" , STOCKORDERKEY_START, DWARFMAINKEY_START-1},
+ {"Militia" , MILITIAKEY_START, INTERFACEKEY_STRING_A000-1},
+ {"Text entry" , INTERFACEKEY_STRING_A000, INTERFACEKEY_STRING_A255}
+};
+
+KeybindingScreen::KeybindingScreen() {
+ gview.addscreen(this, INTERFACE_PUSH_AT_BACK, NULL); // HACK
+ mode = mode_main;
+
+ main.add("Macros", sel_macros);
+ for (int i = 0; i < ARRSZ(groups); i++)
+ main.set(i+2, groups[i].name, sel_first_group + i);
+ main.set(ARRSZ(groups)+3, "Save and exit", sel_save_exit);
+ main.add("Exit, discard changes when DF quits", sel_just_exit);
+ enabler.flag |= ENABLERFLAG_RENDER;
+}
+
+void KeybindingScreen::feed(set<InterfaceKey> &input) {
+ enabler.flag|=ENABLERFLAG_RENDER;
+ if (input.count(INTERFACEKEY_KEYBINDING_COMPLETE)) {
+ list<RegisteredKey> keys = enabler.getRegisteredKey();
+ if (keys.size() == 0) {
+ puts("No keys registered ?!");
+ mode = mode_keyR;
+ } else {
+ keyRegister.clear();
+ list<RegisteredKey> keys = enabler.getRegisteredKey();
+ for (list<RegisteredKey>::iterator it = keys.begin(); it != keys.end(); ++it) {
+ string display;
+ switch (it->type) {
+ case type_button: display = "Mouse button: "; break;
+ case type_key: display = "By position: "; break;
+ case type_unicode: display = "By letter: "; break;
+ }
+ keyRegister.add(display + it->display, it->type);
+ }
+ }
+ } else if (input.count(INTERFACEKEY_STANDARDSCROLL_PAGEUP) ||
+ input.count(INTERFACEKEY_STANDARDSCROLL_PAGEDOWN) ||
+ input.count(INTERFACEKEY_STANDARDSCROLL_UP) ||
+ input.count(INTERFACEKEY_STANDARDSCROLL_DOWN)) {
+ switch (mode) {
+ case mode_main: main.feed(input); break;
+ case mode_keyL: keyL.feed(input); reset_keyR(); break;
+ case mode_keyR: keyR.feed(input); break;
+ case mode_macro: macro.feed(input); break;
+ case mode_register: keyRegister.feed(input); break;
+ }
+ } else if (mode == mode_keyL && input.count(INTERFACEKEY_STANDARDSCROLL_RIGHT))
+ mode = mode_keyR;
+ else if (mode == mode_main && input.count(INTERFACEKEY_STANDARDSCROLL_RIGHT)) {
+ if (main.get_selection() == sel_macros) enter_macros();
+ if (main.get_selection() >= sel_first_group)
+ enter_key(main.get_selection() - sel_first_group);
+ } else if (mode == mode_keyR && input.count(INTERFACEKEY_STANDARDSCROLL_LEFT))
+ mode = mode_keyL;
+ else if ((mode == mode_keyL || mode == mode_macro) && input.count(INTERFACEKEY_STANDARDSCROLL_LEFT))
+ mode = mode_main;
+ else if (input.count(INTERFACEKEY_STRING_A000)) { // Backspace: Delete something.
+ switch (mode) {
+ case mode_macro:
+ if (macro.get_selection() != "") {
+ enabler.delete_macro(macro.get_selection());
+ macro.del_selection();
+ if (!macro.size())
+ macro.add("No macros!", "");
+ }
+ break;
+ case mode_keyR:
+ keyR_selector sel = keyR.get_selection();
+ if (sel.sel == sel_event) {
+ enabler.remove_key(keyL.get_selection(), sel.event);
+ reset_keyR();
+ }
+ break;
+ }
+ } else if (input.count(INTERFACEKEY_SELECT)) {
+ switch (mode) {
+ case mode_main:
+ if (main.get_selection() == sel_macros) { // Macros
+ enter_macros();
+ } else if (main.get_selection() == sel_save_exit) { // Save and exit
+ enabler.save_keybindings();
+ breakdownlevel = INTERFACE_BREAKDOWN_STOPSCREEN;
+ return;
+ } else if (main.get_selection() == sel_just_exit) { // Just exit
+ breakdownlevel = INTERFACE_BREAKDOWN_STOPSCREEN;
+ return;
+ } else { // Some key-binding group
+ enter_key(main.get_selection() - sel_first_group);
+ }
+ break;
+ case mode_keyR: {
+ InterfaceKey key = keyL.get_selection();
+ switch (keyR.get_selection().sel) {
+ case sel_add:
+ enabler.register_key();
+ mode = mode_register;
+ break;
+ case sel_rep_none:
+ enabler.key_repeat(key, REPEAT_NOT);
+ reset_keyR();
+ break;
+ case sel_rep_slow:
+ enabler.key_repeat(key, REPEAT_SLOW);
+ reset_keyR();
+ break;
+ case sel_rep_fast:
+ enabler.key_repeat(key, REPEAT_FAST);
+ reset_keyR();
+ break;
+ }}
+ break;
+ case mode_register:
+ enabler.bindRegisteredKey(keyRegister.get_selection(), keyL.get_selection());
+ mode = mode_keyR;
+ reset_keyR();
+ break;
+ }
+ } else if (input.count(INTERFACEKEY_LEAVESCREEN) || input.count(INTERFACEKEY_OPTIONS)) {
+ if (mode == mode_register)
+ mode = mode_keyR;
+ else
+ mode = mode_main;
+ }
+}
+
+void KeybindingScreen::logic() {
+ if (mode == mode_register)
+ enabler.flag|=ENABLERFLAG_RENDER;
+}
+
+void KeybindingScreen::enter_macros() {
+ mode = mode_macro;
+ macro.clear();
+ list<string> macros = enabler.list_macros();
+ for (list<string>::iterator it = macros.begin(); it != macros.end(); ++it)
+ macro.add(*it, *it);
+ if (!macros.size())
+ macro.add("No macros!", "");
+}
+
+void KeybindingScreen::enter_key(int group) {
+ mode = mode_keyL;
+ keyL.clear();
+ for (InterfaceKey i = groups[group].start; i <= groups[group].end; i++) {
+ if (i != INTERFACEKEY_NONE)
+ keyL.add(enabler.GetBindingTextDisplay(i), i);
+ }
+ reset_keyR();
+}
+
+void KeybindingScreen::reset_keyR() {
+ int lastpos = keyR.get_pos();
+ keyR.clear();
+ struct keyR_selector sel;
+ sel.sel = sel_add;
+ keyR.add("Add binding", sel);
+ InterfaceKey key = keyL.get_selection();
+ list<EventMatch> matchers = enabler.list_keys(key);
+ Repeat rep = enabler.key_repeat(key);
+ sel.sel = sel_rep_none;
+ keyR.set(2, "Don't repeat", sel);
+ if (rep == REPEAT_NOT) keyR.set_color(2, 4, 0);
+ sel.sel = sel_rep_slow;
+ keyR.set(3, "Delayed repeat", sel);
+ if (rep == REPEAT_SLOW) keyR.set_color(3, 4, 0);
+ sel.sel = sel_rep_fast;
+ keyR.set(4, "Immediate repeat", sel);
+ if (rep == REPEAT_FAST) keyR.set_color(4, 4, 0);
+ int i = 6;
+ for (list<EventMatch>::iterator it = matchers.begin(); it != matchers.end(); ++it, ++i) {
+ ostringstream desc;
+ switch (it->type) {
+ case type_unicode:
+ desc << "By letter: ";
+ if (it->unicode < 256 && isgraph(it->unicode)) // Is it printable?
+ desc << (char)it->unicode;
+ else
+ desc << "U+" << hex << uppercase << it->unicode;
+ break;
+ case type_key:
+ desc << "By position: " << translate_mod(it->mod) << sdlNames.left[it->key];
+ break;
+ case type_button:
+ desc << "Mouse: " << (int)it->button;
+ break;
+ }
+ sel.sel = sel_event;
+ sel.event = *it;
+ keyR.set(i, desc.str(), sel);
+ }
+ keyR.set_pos(lastpos);
+}
+
+void KeybindingScreen::render_macro() {
+ drawborder("Macros");
+ gps.locate(3, 3);
+ gps.changecolor(4,0,1);
+ gps.addst("Select a macro, then press " + enabler.GetKeyDisplay(INTERFACEKEY_STRING_A000) + " to delete.");
+ macro.render(6, init.display.grid_x-2, 5, init.display.grid_y-2);
+}
+
+void KeybindingScreen::render_key() {
+ if (enabler.is_registering()) {
+ gps.changecolor(4,0,1);
+ drawborder("Keybinding - currently registering new key");
+ } else
+ drawborder("Keybinding");
+ gps.locate(3, 6);
+ gps.changecolor(4,0,1);
+ gps.addst("Select a binding, then press " + enabler.GetKeyDisplay(INTERFACEKEY_STRING_A000) + " to delete.");
+ keyL.render(6, init.display.grid_x/2 - 1, 5, init.display.grid_y-2);
+ if (mode == mode_keyL || mode == mode_register)
+ keyR.bleach(true);
+ else
+ keyR.bleach(false);
+ keyR.render(init.display.grid_x/2 + 1, init.display.grid_x-2, 5, init.display.grid_y-2);
+}
+
+void KeybindingScreen::render_register() {
+ int x1 = init.display.grid_x / 2 - 20,
+ x2 = init.display.grid_x / 2 + 20,
+ y1 = init.display.grid_y / 2 - 1,
+ y2 = init.display.grid_y / 2 + 1;
+ if (!enabler.is_registering()) {
+ y2 = y1 + keyRegister.size() + 1;
+ }
+ gps.erasescreen_rect(x1, x2, y1, y2);
+ gps.changecolor(1,1,1);
+ for (int x = x1; x <= x2; x++) {
+ gps.locate(y1, x); gps.addchar(' ');
+ gps.locate(y2, x); gps.addchar(' ');
+ }
+ for (int y = y1 + 1; y < y2; y++) {
+ gps.locate(y, x1); gps.addchar(' ');
+ gps.locate(y, x2); gps.addchar(' ');
+ }
+ if (enabler.is_registering()) {
+ gps.changecolor(7,0,1);
+ gps.locate(y1+1, x1+2);
+ gps.addst(translate_mod(getModState()));
+ } else {
+ keyRegister.render(x1+1, x2-1, y1+1, y2-1);
+ gps.locate(y2, x1+2);
+ gps.changecolor(7,1,1);
+ gps.addst("Select binding, or press " + enabler.GetKeyDisplay(INTERFACEKEY_LEAVESCREEN) + " to abort");
+ }
+}
+
+// Render the main menu
+void KeybindingScreen::render_main() {
+ drawborder("Key binding & macro center");
+ main.render(6, init.display.grid_x - 3, 3, init.display.grid_y - 4);
+}
+
+void KeybindingScreen::render() {
+ switch(mode) {
+ case mode_main: render_main(); break;
+ case mode_keyL: case mode_keyR: render_key(); break;
+ case mode_macro: render_macro(); break;
+ case mode_register:
+ render_key();
+ render_register();
+ break;
+ }
+}
+
+void KeybindingScreen::help() {
+}
+
+
+MacroScreenLoad::MacroScreenLoad() {
+ list<string> macros = enabler.list_macros();
+ width = 10;
+ if (!macros.size()) {
+ menu.add("No macros!", "");
+ height = 1;
+ } else
+ height = macros.size();
+
+ for (list<string>::iterator it = macros.begin(); it != macros.end(); ++it) {
+ if (it->length() > width) width = it->length();
+ menu.add(*it, *it);
+ }
+ enabler.flag |= ENABLERFLAG_RENDER;
+ // render();
+ // gps.renewscreen();
+}
+
+void MacroScreenLoad::feed(set<InterfaceKey> &input) {
+ enabler.flag|=ENABLERFLAG_RENDER;
+ if (input.count(INTERFACEKEY_SELECT)) {
+ string id = menu.get_selection();
+ if (id != "") enabler.load_macro(id);
+ breakdownlevel = INTERFACE_BREAKDOWN_STOPSCREEN;
+ return;
+ } else if (input.count(INTERFACEKEY_LEAVESCREEN)) {
+ breakdownlevel = INTERFACE_BREAKDOWN_STOPSCREEN;
+ return;
+ } else {
+ menu.feed(input);
+ }
+ if (input.count(INTERFACEKEY_OPTIONS)) {
+ breakdownlevel = INTERFACE_BREAKDOWN_STOPSCREEN;
+ }
+}
+
+void MacroScreenLoad::logic() {
+}
+
+void MacroScreenLoad::render() {
+ if (parent) parent->render();
+ const int x1 = MAX(init.display.grid_x/2 - ((width + 2) / 2), 0);
+ const int x2 = MIN(x1+width+1, init.display.grid_x-1);
+ const int y1 = MAX(init.display.grid_y/2 - ((height + 2) / 2), 0);
+ const int y2 = MIN(y1 + height + 1, init.display.grid_y-1);
+ gps.changecolor(0,3,1);
+ gps.draw_border(x1, x2, y1, y2);
+ menu.render(x1+1, x2-1, y1+1, y2-1);
+ // gps.renewscreen();
+}
+
+MacroScreenSave::MacroScreenSave() {
+ enabler.flag |= ENABLERFLAG_RENDER;
+}
+
+void MacroScreenSave::logic() {
+}
+
+void MacroScreenSave::feed(set<InterfaceKey> &input) {
+ enabler.flag|=ENABLERFLAG_RENDER;
+ id.feed(input);
+ if (input.count(INTERFACEKEY_SELECT)) {
+ string n = id.get_text();
+ if (n.length())
+ enabler.save_macro(n);
+ breakdownlevel = INTERFACE_BREAKDOWN_STOPSCREEN;
+ return;
+ }
+ if (input.count(INTERFACEKEY_OPTIONS)) {
+ breakdownlevel = INTERFACE_BREAKDOWN_STOPSCREEN;
+ }
+}
+
+void MacroScreenSave::render() {
+ if (parent) parent->render();
+ const int x1 = 3,
+ x2 = init.display.grid_x-4,
+ y1 = init.display.grid_y/2-1,
+ y2 = init.display.grid_y/2+1;
+ gps.changecolor(0,3,1);
+ gps.draw_border(x1, x2, y1, y2);
+ id.render(x1+1,x2-1,y1+1,y2-1);
+ // gps.renewscreen();
+}
+