Browse files

Finalized new Accelerators Dialog.

  • Loading branch information...
1 parent 0e981ba commit 5e82b9dd5334f9003472c8aff086f269fc896cde @ajpalkovic ajpalkovic committed Oct 26, 2010
View
28 src/Accelerators.cpp
@@ -75,6 +75,23 @@ void Accelerators::DefineBinding(wxString accel, int id) {
* and it checks if there is a custom binding for that menu item.
*/
void Accelerators::ParseMenu() {
+ std::map<int, KeyChord*>::iterator iterator;
+ for(iterator = m_chords.begin(); iterator != m_chords.end(); iterator++) {
+ KeyChord* chord = iterator->second;
+ std::map<int, KeyBinding*>::iterator iterator2;
+ for(iterator2 = chord->bindings.begin(); iterator2 != chord->bindings.end(); iterator2++) {
+ KeyBinding* binding = iterator2->second;
+ delete binding;
+ }
+ delete chord;
+ }
+
+ std::map<int, KeyBinding*>::iterator iterator2;
+ for(iterator2 = m_bindings.begin(); iterator2 != m_bindings.end(); iterator2++) {
+ KeyBinding* binding = iterator2->second;
+ delete binding;
+ }
+
m_chords.clear();
m_bindings.clear();
@@ -267,11 +284,7 @@ void Accelerators::ReadCustomShortcuts() {
}
}
-void Accelerators::SaveCustomShortcuts(wxString& jsonString) {
- wxJSONReader reader;
- wxJSONValue bindings;
- reader.Parse(jsonString, &bindings);
-
+void Accelerators::SaveCustomShortcuts(wxJSONValue& bindings) {
wxJSONValue root;
root[wxT("bindings")] = bindings;
@@ -451,6 +464,11 @@ void Accelerators::Reset() {
m_searchBundleBindings = false;
m_searchBundleChords = false;
+ std::map<int, BundleKeyChord*>::iterator iterator;
+ for(iterator = m_bundleChords.begin(); iterator != m_bundleChords.end(); iterator++) {
+ BundleKeyChord* b = iterator->second;
+ delete b;
+ }
m_bundleChords.clear();
m_bundleBindings.clear();
}
View
4 src/Accelerators.h
@@ -7,6 +7,7 @@
class EditorFrame;
class tmAction;
+class wxJSONValue;
int makeHash(wxString& accel);
wxString normalize(wxString str);
@@ -48,7 +49,7 @@ class Accelerators {
void DefineBinding(wxString accel, int id);
void ReadCustomShortcuts();
- void SaveCustomShortcuts(wxString& jsonRoot);
+ void SaveCustomShortcuts(wxJSONValue& jsonRoot);
void ParseMenu();
void ParseMenu(wxMenu* menu);
@@ -61,7 +62,6 @@ class Accelerators {
bool HandleKeyEvent(wxKeyEvent& event);
bool MatchMenus(int hash);
-
bool MatchBundle(int code, int flags, const tmAction* x);
bool BundlesParsed(int code, int flags);
View
175 src/AcceleratorsDialog.cpp
@@ -17,17 +17,29 @@
#include "BundleMenu.h"
#include "tmAction.h"
#include "tmBundle.h"
+#include "ShortcutChordCtrl.h"
+#include "jsonreader.h"
+#include "jsonwriter.h"
#include <wx/wx.h>
#include <wx/file.h>
+#include <map>
enum {
- CTRL_ACCELERATORS_BROWSER
+ CTRL_ACCELERATORS_BROWSER,
+ CTRL_ACCELERATORS_CLEAR,
+ CTRL_ACCELERATORS_KEY
};
BEGIN_EVENT_TABLE(AcceleratorsDialog, wxDialog)
EVT_BUTTON(wxID_OK, AcceleratorsDialog::OnSave)
+ EVT_TREE_ITEM_ACTIVATED(CTRL_ACCELERATORS_BROWSER, AcceleratorsDialog::OnClick)
+END_EVENT_TABLE()
+
+BEGIN_EVENT_TABLE(AcceleratorsDialog::AcceleratorDialog, wxDialog)
+ EVT_BUTTON(wxID_OK, AcceleratorsDialog::AcceleratorDialog::OnSave)
+ EVT_BUTTON(CTRL_ACCELERATORS_CLEAR, AcceleratorsDialog::AcceleratorDialog::OnClear)
END_EVENT_TABLE()
AcceleratorsDialog::AcceleratorsDialog(EditorFrame *parent):
@@ -40,16 +52,37 @@ AcceleratorsDialog::AcceleratorsDialog(EditorFrame *parent):
// Create Layout
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
+ mainSizer->Add(new wxStaticText(this, wxID_ANY, wxT("Double click any node to edit its shortcut. You may use chords such as Ctrl-X Ctrl-C.")), 0, wxALL, 5);
mainSizer->Add(m_treeView, 1, wxEXPAND);
mainSizer->Add(CreateButtonSizer(wxOK|wxCANCEL), 0, wxEXPAND|wxALL, 5);
ParseMenu();
SetSizer(mainSizer);
- SetSize(500, 580);
+ SetSize(400, 500);
Centre();
}
+wxString AcceleratorsDialog::GetBinding(wxString& label) {
+ map<wxString, wxString>::iterator iterator;
+ iterator = m_accelerators->m_customBindings.find(normalize(label));
+ if(iterator != m_accelerators->m_customBindings.end()) {
+ return iterator->second;
+ }
+
+ return wxEmptyString;
+}
+
+wxString AcceleratorsDialog::GetDefaultBinding(wxString& label) {
+ map<wxString, wxString>::iterator iterator;
+ iterator = m_accelerators->m_defaultBindings.find(normalize(label));
+ if(iterator != m_accelerators->m_defaultBindings.end()) {
+ return iterator->second;
+ }
+
+ return wxEmptyString;
+}
+
void AcceleratorsDialog::ParseMenu() {
wxMenuBar* menuBar = m_editorFrame->GetMenuBar();
if(!menuBar) return;
@@ -121,14 +154,146 @@ void AcceleratorsDialog::ParseMenu(wxMenuItem* item, wxTreeItemId parent) {
label.Replace(wxT("&"), wxT(""));
+ wxString display = label;
+ if(!customAccel.empty()) {
+ display = wxString::Format(wxT("%s -> %s"), label, customAccel);
+ } else if(!accel.empty()) {
+ display = wxString::Format(wxT("%s -> %s"), label, accel);
- m_treeView->AppendItem(parent, label);
+ }
+
+ m_treeView->AppendItem(parent, display);
+ m_bindings.insert(pair<wxString, AcceleratorData>(label, AcceleratorData(label, accel, customAccel)));
}
void AcceleratorsDialog::OnSave(wxCommandEvent& WXUNUSED(event)) {
- /*m_accelerators->SaveCustomShortcuts(jsonString);
+ std::map<wxString, wxString> existing;
+ std::vector<wxString> conflicts;
+ std::vector<wxTreeItemId> stack;
+ stack.push_back(m_treeView->GetRootItem());
+ while(stack.size() > 0) {
+ wxTreeItemId id = stack[stack.size()-1];
+ stack.pop_back();
+ wxString label = m_treeView->GetItemText(id);
+ if(label == wxT("Syntax") || label == wxT("Bundles")) continue;
+
+ if(m_treeView->GetChildrenCount(id, false) > 0) {
+ wxTreeItemIdValue cookie;
+ wxTreeItemId first = m_treeView->GetFirstChild(id, cookie);
+ while(first.IsOk()) {
+ stack.push_back(first);
+ first = m_treeView->GetNextChild(id, cookie);
+ }
+ } else {
+ int separator = label.Find(wxT(" -> "));
+ if(separator <= 0) continue;
+
+ wxString accel = label.Mid(separator+6);
+ accel = accel.Trim();
+ accel.Replace(wxT("+"), wxT("-"));
+
+ if(existing.find(accel) != existing.end()) {
+ wxString old = existing.find(accel)->second;
+ if(!old.empty()) conflicts.push_back(old);
+ conflicts.push_back(label);
+ existing[accel] = wxT("");
+ } else {
+ existing[accel] = label;
+ }
+ }
+ }
+
+ if(conflicts.size() > 0) {
+ wxString message;
+ for(unsigned int c = 0; c < conflicts.size(); c++) {
+ message << wxT(" ") << conflicts[c] << wxT("\n");
+ }
+
+ int result = wxMessageBox(wxString::Format(wxT("Some keystrokes are bound to multiple items:\n\n%s\nTo fix this, press Cancel. To ignore, press Ok."), message), wxT("Warning"), wxOK|wxCANCEL);
+ if(result == wxCANCEL) {
+ return;
+ }
+ }
+
+
+ wxJSONValue bindings;
+ std::map<wxString, AcceleratorData>::iterator iterator;
+ for(iterator = m_bindings.begin(); iterator != m_bindings.end(); iterator++) {
+ wxString& customAccel = iterator->second.customAccel;
+ if(!customAccel.empty()) {
+ bindings[normalize(iterator->second.label)] = customAccel;
+ }
+ }
+
+ m_accelerators->SaveCustomShortcuts(bindings);
m_accelerators->ReadCustomShortcuts();
- m_accelerators->ParseMenu();*/
+ m_accelerators->ParseMenu();
+
+ this->Close();
+}
+
+void AcceleratorsDialog::OnClick(wxTreeEvent& event) {
+ wxTreeItemId id = event.GetItem();
+ wxString display = m_treeView->GetItemText(id);
+ int separator = display.Find(wxT(" -> "));
+ wxString label = separator > 0 ? display.Left(separator) : display;
+ std::map<wxString, AcceleratorData>::iterator iterator = m_bindings.find(label);
+ if(iterator == m_bindings.end()) return;
+
+ AcceleratorData& data = iterator->second;
+
+ AcceleratorDialog dlg(data, this);
+ dlg.ShowModal();
+
+ if(dlg.save) {
+ data.customAccel = dlg.GetBinding();
+
+ wxString display = data.label;
+ if(!data.customAccel.empty()) {
+ display = wxString::Format(wxT("%s -> %s"), data.label, data.customAccel);
+ } else if(!data.defaultAccel.empty()) {
+ display = wxString::Format(wxT("%s -> %s"), data.label, data.defaultAccel);
+ }
+
+ m_treeView->SetItemText(id, display);
+ }
+}
+
+AcceleratorsDialog::AcceleratorDialog::AcceleratorDialog(AcceleratorData& data, AcceleratorsDialog* parent) :
+ wxDialog ((wxWindow*)parent, wxID_ANY, wxEmptyString, wxDefaultPosition), save(false)
+{
+ SetTitle(wxString::Format(wxT("Customize %s"), data.label));
+
+ wxStaticText* defaultBinding = new wxStaticText(this, wxID_ANY, wxString::Format(wxT("Default Binding: %s"), data.defaultAccel));
+ wxStaticText* customBinding = new wxStaticText(this, wxID_ANY, wxString::Format(wxT("Custom Binding: %s"), data.customAccel));
+ m_chordCtrl = new ShortcutChordCtrl(this, CTRL_ACCELERATORS_KEY);
+ m_chordCtrl->SetValue(data.customAccel);
+
+ wxSizer* buttonSizer = CreateButtonSizer(wxOK|wxCANCEL);
+ buttonSizer->Add(new wxButton(this, CTRL_ACCELERATORS_CLEAR, wxT("Clear")));
+
+ // Create Layout
+ wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
+ mainSizer->Add(defaultBinding, 0, wxALL, 3);
+ mainSizer->Add(customBinding, 0, wxALL, 3);
+ mainSizer->Add(m_chordCtrl, 1, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 8);
+ mainSizer->Add(buttonSizer, 0, wxEXPAND|wxALL, 5);
+
+ SetSizerAndFit(mainSizer);
+ Centre();
+
+ m_chordCtrl->SetFocus();
+}
+wxString AcceleratorsDialog::AcceleratorDialog::GetBinding() {
+ return m_chordCtrl->GetBinding();
+}
+
+void AcceleratorsDialog::AcceleratorDialog::OnSave(wxCommandEvent& WXUNUSED(event)) {
+ save = true;
this->Close();
+}
+
+void AcceleratorsDialog::AcceleratorDialog::OnClear(wxCommandEvent& WXUNUSED(event)) {
+ m_chordCtrl->Clear();
}
View
29 src/AcceleratorsDialog.h
@@ -6,9 +6,11 @@
#include <wx/wx.h>
#endif
#include <wx/treectrl.h>
+#include <map>
class EditorFrame;
class Accelerators;
+class ShortcutChordCtrl;
class AcceleratorsDialog : public wxDialog {
public:
@@ -18,12 +20,37 @@ class AcceleratorsDialog : public wxDialog {
void ParseMenu(wxMenu* menuItem, wxString label, wxTreeItemId parent);
void ParseMenu(wxMenuItem* menuItem, wxTreeItemId parent);
-private:
+ wxString GetBinding(wxString& label);
+ wxString GetDefaultBinding(wxString& label);
+
void OnSave(wxCommandEvent& event);
+ void OnClick(wxTreeEvent& event);
+
+private:
+ class AcceleratorData {
+ public:
+ AcceleratorData(wxString label, wxString defaultAccel, wxString customAccel) :
+ label(label), defaultAccel(defaultAccel), customAccel(customAccel) {}
+
+ wxString label, defaultAccel, customAccel;
+ };
+
+ class AcceleratorDialog : public wxDialog {
+ public:
+ AcceleratorDialog(AcceleratorData& data, AcceleratorsDialog* parent);
+ wxString GetBinding();
+ void OnSave(wxCommandEvent& event);
+ void OnClear(wxCommandEvent& event);
+ bool save;
+ private:
+ ShortcutChordCtrl* m_chordCtrl;
+ DECLARE_EVENT_TABLE();
+ };
EditorFrame* m_editorFrame;
Accelerators* m_accelerators;
wxTreeCtrl* m_treeView;
+ std::map<wxString, AcceleratorData> m_bindings;
DECLARE_EVENT_TABLE();
};
View
213 src/AcceleratorsDialog.html
@@ -1,213 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
- <style type='text/css'>
- #wrapper {
- width: 700px;
- margin: 10px;
- height: 500px;
- overflow: auto;
- }
- #left {
- float: left;
- width: 504px;
- }
- #right {
- width: 175px;
- float: left;
- }
- table, tr, td, div, span, p, input, body {
- padding: 0;
- margin: 0;
- border-spacing: 0;
- }
-
- ul {
- padding: 0;
- margin: 0 0 0 20px;
- }
-
- body {
- background-color: #F0F0F0;
- }
-
- body, input.textfield {
- font-family: Calibri;
- font-size: 12px;
- }
-
- input.textfield {
- margin: 1px 2px 1px 0;
- }
-
- #mainTable {
- border: 2px groove #FFF;
- width: 500px;
- }
-
- .toggleArrow {
- height: 15px;
- width: 15px;
- }
-
- .menuItemLabel, .menuLabel, .defaultBinding {
- padding: 1px 5px;
- }
-
- .newBinding {
- width: 100px;
- }
- .defaultBinding {
- width: 100px;
- }
-
- .odd {
- background-color: #FAFAFA;
- }
-
- .even {
- background-color: #E9E9E9;
- }
-
- td {
- border-top: 1px solid #CCC;
- border-collapse: collapse;
- }
-
- .save {
- padding: 2px;
- }
-
- .level0 { padding-left: 0px; }
- .level1 { padding-left: 15px; }
- .level2 { padding-left: 30px; }
- .level3 { padding-left: 45px; }
- .level4 { padding-left: 60px; }
- .level5 { padding-left: 75px; }
- .level6 { padding-left: 90px; }
-
- .menuLabel {
- font-weight: bold;
- }
- .menuLabel a, .menuLabel a:visited {
- color: black;
- text-decoration: none;
- padding-right: 5px;
- }
-
- </style>
-</head>
-<body>
-<div id='wrapper'>
- <div id='left'>
- $1
- </div>
- <div id='right'>
- <strong>Examples:</strong>
- <ul>
- <li>Ctrl-A</li>
- <li>Ctrl+A</li>
- <li>Ctrl-X Ctrl-A</li>
- <li>Ctrl-Alt-Win-Shift-Space</li>
- </ul>
-
- <strong>Notes:</strong>
- <ul>
- <li>Only the non-shift character for non-alpha characters works. In other words, Ctrl-; and Ctrl-: are the same thing.</li>
- <li>You can use these keys too:</li>
- </ul>
-
- <ul style='list-style-type: none;'>
- <li>BACK</li>
- <li>CANCEL</li>
- <li>CAPITAL</li>
- <li>CLEAR</li>
- <li>DELETE</li>
- <li>DOWN</li>
- <li>END</li>
- <li>ENTER</li>
- <li>ESCAPE</li>
- <li>F1 -> F24</li>
- <li>HOME</li>
- <li>INSERT</li>
- <li>KP_ADD</li>
- <li>KP_DECIMAL</li>
- <li>KP_DIVICE</li>
- <li>KP_MULTIPLY</li>
- <li>KP_SEPARATOR</li>
- <li>KP_SUBTRACT</li>
- <li>LEFT</li>
- <li>MENU</li>
- <li>NUM_LOCK</li>
- <li>PAUSE</li>
- <li>PGDN</li>
- <li>PGUP</li>
- <li>PRINT</li>
- <li>RETURN</li>
- <li>RIGHT</li>
- <li>SCOLL_LOCK</li>
- <li>SPACE</li>
- <li>TAB</li>
- <li>UP</li>
- </ul>
- </div>
-</div>
-<center>
- <input type='button' value='Save' class='save' id='save' />
-</center>
-<script type='text/javascript' src='http://code.jquery.com/jquery-1.4.3.min.js'></script>
-<script type='text/javascript'>
- // Show only the top level menus
- $("tr").hide();
- $("tr.menu0, #header").show();
-
- // Remove blank menus
- for(var c = 247; c > 0; c--) {
- if($('tr.menu'+c).length === 0) {
- $('#menu'+c).closest('tr').remove();
- }
- }
-
- // Have to recursively close all submenus as well
- function close(menu) {
- var openSubMenus = $('tr.'+menu+':visible');
- for(var c = 0; c < openSubMenus.length; c++) {
- var link = $(openSubMenus[c]).find('a');
- link.html("&rarr;");
- close(link.attr('id'));
- }
- openSubMenus.hide();
- }
-
- // Open menus when clicked
- $("a.expand").live('click', function() {
- var id = $(this).attr('id');
- var rows = $("tr."+id);
-
- if(rows.is(":visible")) {
- close(id);
- rows.hide();
- $(this).html("&rarr;");
- } else {
- rows.show();
- $(this).html("&darr;");
- }
-
- $("tr:visible:even").removeClass("odd").addClass("even");
- $("tr:visible:odd").removeClass("even").addClass("odd");
- });
-
- $("#save").click(function() {
- var bits = $("input.textfield").map(function() {
- var name = $(this).attr('name').replace("\"", "\\\"");
- var binding = $(this).val().replace("\"", "\\\"");
- if(binding.length == 0) return;
- return ["\"", name, "\"", ":", "\"", binding, "\""].join("");
- });
- var json = "http://localhost/{"+Array.prototype.join.call(bits, ",")+"}";
- window.location = json;
- });
-</script>
-</body>
-</html>
View
20 src/AcceleratorsDialogGenerator.rb
@@ -1,20 +0,0 @@
-name = "output"
-
-file = File.new('AcceleratorsDialog.html')
-size = file.read.size
-
-file = File.new('AcceleratorsDialog.html')
-str = file.read.gsub(/([\\\"])/) {|match| "\\#{match}"}
-str = str.split("\n").map do |line|
- "#{name}->Append(wxT(\"#{line}\\n\"));"
-end.join("\n")
-
-output = "#include \"wx/wx.h\"
-wxString* AcceleratorsDialogHtml() {
- wxString* #{name} = new wxString();
- #{name}->Alloc(#{size});
- #{str}
- return #{name};
-}"
-
-File.open('AcceleratorsDialogHtml.h', 'w+') {|file| file.write output }
View
219 src/AcceleratorsDialogHtml.h
@@ -1,219 +0,0 @@
-#include "wx/wx.h"
-wxString* AcceleratorsDialogHtml() {
- wxString* output = new wxString();
- output->Alloc(4348);
- output->Append(wxT("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> \n"));
-output->Append(wxT("<html xmlns=\"http://www.w3.org/1999/xhtml\"> \n"));
-output->Append(wxT(" <head> \n"));
-output->Append(wxT(" <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\" /> \n"));
-output->Append(wxT(" <style type='text/css'>\n"));
-output->Append(wxT(" #wrapper {\n"));
-output->Append(wxT(" width: 700px;\n"));
-output->Append(wxT(" margin: 10px;\n"));
-output->Append(wxT(" height: 500px;\n"));
-output->Append(wxT(" overflow: auto;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" #left {\n"));
-output->Append(wxT(" float: left;\n"));
-output->Append(wxT(" width: 504px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" #right {\n"));
-output->Append(wxT(" width: 175px;\n"));
-output->Append(wxT(" float: left;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" table, tr, td, div, span, p, input, body {\n"));
-output->Append(wxT(" padding: 0;\n"));
-output->Append(wxT(" margin: 0;\n"));
-output->Append(wxT(" border-spacing: 0;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" ul {\n"));
-output->Append(wxT(" padding: 0;\n"));
-output->Append(wxT(" margin: 0 0 0 20px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" body {\n"));
-output->Append(wxT(" background-color: #F0F0F0;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" body, input.textfield {\n"));
-output->Append(wxT(" font-family: Calibri;\n"));
-output->Append(wxT(" font-size: 12px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" input.textfield {\n"));
-output->Append(wxT(" margin: 1px 2px 1px 0;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" #mainTable {\n"));
-output->Append(wxT(" border: 2px groove #FFF;\n"));
-output->Append(wxT(" width: 500px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" .toggleArrow {\n"));
-output->Append(wxT(" height: 15px;\n"));
-output->Append(wxT(" width: 15px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" .menuItemLabel, .menuLabel, .defaultBinding {\n"));
-output->Append(wxT(" padding: 1px 5px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" .newBinding {\n"));
-output->Append(wxT(" width: 100px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" .defaultBinding {\n"));
-output->Append(wxT(" width: 100px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" .odd {\n"));
-output->Append(wxT(" background-color: #FAFAFA;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" .even {\n"));
-output->Append(wxT(" background-color: #E9E9E9;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" td {\n"));
-output->Append(wxT(" border-top: 1px solid #CCC;\n"));
-output->Append(wxT(" border-collapse: collapse;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" .save {\n"));
-output->Append(wxT(" padding: 2px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" .level0 { padding-left: 0px; }\n"));
-output->Append(wxT(" .level1 { padding-left: 15px; }\n"));
-output->Append(wxT(" .level2 { padding-left: 30px; }\n"));
-output->Append(wxT(" .level3 { padding-left: 45px; }\n"));
-output->Append(wxT(" .level4 { padding-left: 60px; }\n"));
-output->Append(wxT(" .level5 { padding-left: 75px; }\n"));
-output->Append(wxT(" .level6 { padding-left: 90px; }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" .menuLabel {\n"));
-output->Append(wxT(" font-weight: bold;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" .menuLabel a, .menuLabel a:visited {\n"));
-output->Append(wxT(" color: black;\n"));
-output->Append(wxT(" text-decoration: none;\n"));
-output->Append(wxT(" padding-right: 5px;\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" </style>\n"));
-output->Append(wxT("</head>\n"));
-output->Append(wxT("<body>\n"));
-output->Append(wxT("<div id='wrapper'>\n"));
-output->Append(wxT(" <div id='left'>\n"));
-output->Append(wxT(" $1\n"));
-output->Append(wxT(" </div>\n"));
-output->Append(wxT(" <div id='right'>\n"));
-output->Append(wxT(" <strong>Examples:</strong>\n"));
-output->Append(wxT(" <ul>\n"));
-output->Append(wxT(" <li>Ctrl-A</li>\n"));
-output->Append(wxT(" <li>Ctrl+A</li>\n"));
-output->Append(wxT(" <li>Ctrl-X Ctrl-A</li>\n"));
-output->Append(wxT(" <li>Ctrl-Alt-Win-Shift-Space</li>\n"));
-output->Append(wxT(" </ul>\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" <strong>Notes:</strong>\n"));
-output->Append(wxT(" <ul>\n"));
-output->Append(wxT(" <li>Only the non-shift character for non-alpha characters works. In other words, Ctrl-; and Ctrl-: are the same thing.</li>\n"));
-output->Append(wxT(" <li>You can use these keys too:</li>\n"));
-output->Append(wxT(" </ul>\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" <ul style='list-style-type: none;'>\n"));
-output->Append(wxT(" <li>BACK</li>\n"));
-output->Append(wxT(" <li>CANCEL</li>\n"));
-output->Append(wxT(" <li>CAPITAL</li>\n"));
-output->Append(wxT(" <li>CLEAR</li>\n"));
-output->Append(wxT(" <li>DELETE</li>\n"));
-output->Append(wxT(" <li>DOWN</li>\n"));
-output->Append(wxT(" <li>END</li>\n"));
-output->Append(wxT(" <li>ENTER</li>\n"));
-output->Append(wxT(" <li>ESCAPE</li>\n"));
-output->Append(wxT(" <li>F1 -> F24</li>\n"));
-output->Append(wxT(" <li>HOME</li>\n"));
-output->Append(wxT(" <li>INSERT</li>\n"));
-output->Append(wxT(" <li>KP_ADD</li>\n"));
-output->Append(wxT(" <li>KP_DECIMAL</li>\n"));
-output->Append(wxT(" <li>KP_DIVICE</li>\n"));
-output->Append(wxT(" <li>KP_MULTIPLY</li>\n"));
-output->Append(wxT(" <li>KP_SEPARATOR</li>\n"));
-output->Append(wxT(" <li>KP_SUBTRACT</li>\n"));
-output->Append(wxT(" <li>LEFT</li>\n"));
-output->Append(wxT(" <li>MENU</li>\n"));
-output->Append(wxT(" <li>NUM_LOCK</li>\n"));
-output->Append(wxT(" <li>PAUSE</li>\n"));
-output->Append(wxT(" <li>PGDN</li>\n"));
-output->Append(wxT(" <li>PGUP</li>\n"));
-output->Append(wxT(" <li>PRINT</li>\n"));
-output->Append(wxT(" <li>RETURN</li>\n"));
-output->Append(wxT(" <li>RIGHT</li>\n"));
-output->Append(wxT(" <li>SCOLL_LOCK</li>\n"));
-output->Append(wxT(" <li>SPACE</li>\n"));
-output->Append(wxT(" <li>TAB</li>\n"));
-output->Append(wxT(" <li>UP</li>\n"));
-output->Append(wxT(" </ul>\n"));
-output->Append(wxT(" </div>\n"));
-output->Append(wxT("</div>\n"));
-output->Append(wxT("<center>\n"));
-output->Append(wxT(" <input type='button' value='Save' class='save' id='save' />\n"));
-output->Append(wxT("</center>\n"));
-output->Append(wxT("<script type='text/javascript' src='http://code.jquery.com/jquery-1.4.3.min.js'></script>\n"));
-output->Append(wxT("<script type='text/javascript'>\n"));
-output->Append(wxT(" // Show only the top level menus\n"));
-output->Append(wxT(" $(\"tr\").hide();\n"));
-output->Append(wxT(" $(\"tr.menu0, #header\").show();\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" // Remove blank menus\n"));
-output->Append(wxT(" for(var c = 247; c > 0; c--) {\n"));
-output->Append(wxT(" if($('tr.menu'+c).length === 0) {\n"));
-output->Append(wxT(" $('#menu'+c).closest('tr').remove();\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" // Have to recursively close all submenus as well\n"));
-output->Append(wxT(" function close(menu) {\n"));
-output->Append(wxT(" var openSubMenus = $('tr.'+menu+':visible');\n"));
-output->Append(wxT(" for(var c = 0; c < openSubMenus.length; c++) {\n"));
-output->Append(wxT(" var link = $(openSubMenus[c]).find('a');\n"));
-output->Append(wxT(" link.html(\"&rarr;\");\n"));
-output->Append(wxT(" close(link.attr('id'));\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" openSubMenus.hide();\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" // Open menus when clicked\n"));
-output->Append(wxT(" $(\"a.expand\").live('click', function() {\n"));
-output->Append(wxT(" var id = $(this).attr('id');\n"));
-output->Append(wxT(" var rows = $(\"tr.\"+id);\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" if(rows.is(\":visible\")) {\n"));
-output->Append(wxT(" close(id);\n"));
-output->Append(wxT(" rows.hide();\n"));
-output->Append(wxT(" $(this).html(\"&rarr;\");\n"));
-output->Append(wxT(" } else {\n"));
-output->Append(wxT(" rows.show();\n"));
-output->Append(wxT(" $(this).html(\"&darr;\");\n"));
-output->Append(wxT(" }\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" $(\"tr:visible:even\").removeClass(\"odd\").addClass(\"even\");\n"));
-output->Append(wxT(" $(\"tr:visible:odd\").removeClass(\"even\").addClass(\"odd\");\n"));
-output->Append(wxT(" });\n"));
-output->Append(wxT(" \n"));
-output->Append(wxT(" $(\"#save\").click(function() {\n"));
-output->Append(wxT(" var bits = $(\"input.textfield\").map(function() { \n"));
-output->Append(wxT(" var name = $(this).attr('name').replace(\"\\\"\", \"\\\\\\\"\");\n"));
-output->Append(wxT(" var binding = $(this).val().replace(\"\\\"\", \"\\\\\\\"\");\n"));
-output->Append(wxT(" if(binding.length == 0) return;\n"));
-output->Append(wxT(" return [\"\\\"\", name, \"\\\"\", \":\", \"\\\"\", binding, \"\\\"\"].join(\"\");\n"));
-output->Append(wxT(" });\n"));
-output->Append(wxT(" var json = \"http://localhost/{\"+Array.prototype.join.call(bits, \",\")+\"}\";\n"));
-output->Append(wxT(" window.location = json;\n"));
-output->Append(wxT(" });\n"));
-output->Append(wxT("</script>\n"));
-output->Append(wxT("</body>\n"));
-output->Append(wxT("</html>\n"));
- return output;
-}
View
167 src/ShortcutChordCtrl.cpp
@@ -0,0 +1,167 @@
+#include "ShortcutChordCtrl.h"
+#include "tmKey.h"
+
+static const struct wxKeyName
+{
+ wxKeyCode code;
+ const wxChar *name;
+} wxKeyNames[] =
+{
+ { WXK_DELETE, wxTRANSLATE("DEL") },
+ { WXK_DELETE, wxTRANSLATE("DELETE") },
+ { WXK_BACK, wxTRANSLATE("BACK") },
+ { WXK_INSERT, wxTRANSLATE("INS") },
+ { WXK_INSERT, wxTRANSLATE("INSERT") },
+ { WXK_RETURN, wxTRANSLATE("ENTER") },
+ { WXK_RETURN, wxTRANSLATE("RETURN") },
+ { WXK_PAGEUP, wxTRANSLATE("PGUP") },
+ { WXK_PAGEDOWN, wxTRANSLATE("PGDN") },
+ { WXK_LEFT, wxTRANSLATE("LEFT") },
+ { WXK_RIGHT, wxTRANSLATE("RIGHT") },
+ { WXK_UP, wxTRANSLATE("UP") },
+ { WXK_DOWN, wxTRANSLATE("DOWN") },
+ { WXK_HOME, wxTRANSLATE("HOME") },
+ { WXK_END, wxTRANSLATE("END") },
+ { WXK_SPACE, wxTRANSLATE("SPACE") },
+ { WXK_TAB, wxTRANSLATE("TAB") },
+ { WXK_ESCAPE, wxTRANSLATE("ESC") },
+ { WXK_ESCAPE, wxTRANSLATE("ESCAPE") },
+ { WXK_CANCEL, wxTRANSLATE("CANCEL") },
+ { WXK_CLEAR, wxTRANSLATE("CLEAR") },
+ { WXK_MENU, wxTRANSLATE("MENU") },
+ { WXK_PAUSE, wxTRANSLATE("PAUSE") },
+ { WXK_CAPITAL, wxTRANSLATE("CAPITAL") },
+ { WXK_SELECT, wxTRANSLATE("SELECT") },
+ { WXK_PRINT, wxTRANSLATE("PRINT") },
+ { WXK_EXECUTE, wxTRANSLATE("EXECUTE") },
+ { WXK_SNAPSHOT, wxTRANSLATE("SNAPSHOT") },
+ { WXK_HELP, wxTRANSLATE("HELP") },
+ { WXK_ADD, wxTRANSLATE("ADD") },
+ { WXK_SEPARATOR, wxTRANSLATE("SEPARATOR") },
+ { WXK_SUBTRACT, wxTRANSLATE("SUBTRACT") },
+ { WXK_DECIMAL, wxTRANSLATE("DECIMAL") },
+ { WXK_DIVIDE, wxTRANSLATE("DIVIDE") },
+ { WXK_NUMLOCK, wxTRANSLATE("NUM_LOCK") },
+ { WXK_SCROLL, wxTRANSLATE("SCROLL_LOCK") },
+ { WXK_PAGEUP, wxTRANSLATE("PAGEUP") },
+ { WXK_PAGEDOWN, wxTRANSLATE("PAGEDOWN") },
+ { WXK_NUMPAD_SPACE, wxTRANSLATE("KP_SPACE") },
+ { WXK_NUMPAD_TAB, wxTRANSLATE("KP_TAB") },
+ { WXK_NUMPAD_ENTER, wxTRANSLATE("KP_ENTER") },
+ { WXK_NUMPAD_HOME, wxTRANSLATE("KP_HOME") },
+ { WXK_NUMPAD_LEFT, wxTRANSLATE("KP_LEFT") },
+ { WXK_NUMPAD_UP, wxTRANSLATE("KP_UP") },
+ { WXK_NUMPAD_RIGHT, wxTRANSLATE("KP_RIGHT") },
+ { WXK_NUMPAD_DOWN, wxTRANSLATE("KP_DOWN") },
+ { WXK_NUMPAD_PAGEUP, wxTRANSLATE("KP_PRIOR") },
+ { WXK_NUMPAD_PAGEUP, wxTRANSLATE("KP_PAGEUP") },
+ { WXK_NUMPAD_PAGEDOWN, wxTRANSLATE("KP_NEXT") },
+ { WXK_NUMPAD_PAGEDOWN, wxTRANSLATE("KP_PAGEDOWN") },
+ { WXK_NUMPAD_END, wxTRANSLATE("KP_END") },
+ { WXK_NUMPAD_BEGIN, wxTRANSLATE("KP_BEGIN") },
+ { WXK_NUMPAD_INSERT, wxTRANSLATE("KP_INSERT") },
+ { WXK_NUMPAD_DELETE, wxTRANSLATE("KP_DELETE") },
+ { WXK_NUMPAD_EQUAL, wxTRANSLATE("KP_EQUAL") },
+ { WXK_NUMPAD_MULTIPLY, wxTRANSLATE("KP_MULTIPLY") },
+ { WXK_NUMPAD_ADD, wxTRANSLATE("KP_ADD") },
+ { WXK_NUMPAD_SEPARATOR, wxTRANSLATE("KP_SEPARATOR") },
+ { WXK_NUMPAD_SUBTRACT, wxTRANSLATE("KP_SUBTRACT") },
+ { WXK_NUMPAD_DECIMAL, wxTRANSLATE("KP_DECIMAL") },
+ { WXK_NUMPAD_DIVIDE, wxTRANSLATE("KP_DIVIDE") },
+ { WXK_WINDOWS_LEFT, wxTRANSLATE("WINDOWS_LEFT") },
+ { WXK_WINDOWS_RIGHT, wxTRANSLATE("WINDOWS_RIGHT") },
+ { WXK_WINDOWS_MENU, wxTRANSLATE("WINDOWS_MENU") },
+ { WXK_COMMAND, wxTRANSLATE("COMMAND") },
+};
+
+wxString CodeToString(int code, int flags) {
+ wxString text;
+
+ if(flags & wxACCEL_ALT) text += _("Alt-");
+ if(flags & wxACCEL_CMD) text += _("Ctrl-");
+ if(flags & wxACCEL_SHIFT) text += _("Shift-");
+ if(flags & 0x0008) text += _("Win-");
+
+ if(code >= WXK_F1 && code <= WXK_F12)
+ text << _("F") << code - WXK_F1 + 1;
+ else if(code >= WXK_NUMPAD0 && code <= WXK_NUMPAD9)
+ text << _("KP_") << code - WXK_NUMPAD0;
+ else if(code >= WXK_SPECIAL1 && code <= WXK_SPECIAL20)
+ text << _("SPECIAL") << code - WXK_SPECIAL1 + 1;
+ else {
+ for(size_t n = 0; n < WXSIZEOF(wxKeyNames); n++) {
+ const wxKeyName& kn = wxKeyNames[n];
+ if(code == kn.code) {
+ text << wxGetTranslation(kn.name);
+ return text;
+ }
+ }
+
+ text << (wxChar)code;
+ }
+
+ return text;
+}
+
+ShortcutChordCtrl::ShortcutChordCtrl(wxWindow* parent, wxWindowID id) {
+ Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY|wxTE_CENTRE);
+ RegisterKeyHook(); // TextCtrl isn't automatically hooked, hook now
+}
+
+void ShortcutChordCtrl::Clear() {
+ m_binding.clear();
+ wxTextCtrl::Clear();
+}
+
+bool ShortcutChordCtrl::IsEmpty() const {
+ return m_binding.empty();
+}
+
+const wxString& ShortcutChordCtrl::GetBinding() const {
+ return m_binding;
+}
+
+void ShortcutChordCtrl::SetKey(const wxString& binding) {
+ m_binding = binding;
+ SetValue(binding);
+}
+
+bool ShortcutChordCtrl::OnPreKeyUp(wxKeyEvent& event) {
+ int id = event.GetKeyCode();
+
+ // Ignore initial presses on modifier keys
+ if (id == WXK_SHIFT || id == WXK_ALT || id == WXK_CONTROL ||
+ id == WXK_WINDOWS_LEFT || id == WXK_WINDOWS_RIGHT)
+ {
+ return false;
+ }
+
+ int modifiers = event.GetModifiers();
+
+#ifdef __WXMSW__
+ // GetModifiers does not report the windows keys
+ if (::GetKeyState(VK_LWIN) < 0) modifiers |= 0x0008; // wxMOD_META (Left Windows key)
+ if (::GetKeyState(VK_RWIN) < 0) modifiers |= 0x0008; // wxMOD_META (Right Windows key)
+#endif
+
+ wxString binding = CodeToString(id, modifiers);
+
+ wxString value = GetValue();
+ if(value.Contains(wxT(" "))) {
+ value = wxT("");
+ }
+
+ if(!value.empty()) {
+ value = wxString::Format(wxT("%s %s"), value, binding);
+ } else {
+ value = binding;
+ }
+
+ m_binding = value;
+ SetValue(value);
+
+ event.StopPropagation();
+
+ // wxLogDebug(wxT("Binding: %s"), m_binding.c_str());
+ return true;
+}
View
27 src/ShortcutChordCtrl.h
@@ -0,0 +1,27 @@
+#ifndef __SHORTCUTCHORDCTRL_H__
+#define __SHORTCUTCHORDCTRL_H__
+
+#include "wx/wxprec.h"
+#ifndef WX_PRECOMP
+ #include <wx/wx.h>
+#endif
+
+#include "key_hook.h"
+
+class ShortcutChordCtrl : public KeyHookable<wxTextCtrl> {
+public:
+ ShortcutChordCtrl(wxWindow* parent, wxWindowID id=wxID_ANY);
+ void Clear();
+ bool IsEmpty() const;
+
+ void SetKey(const wxString& binding);
+ const wxString& GetBinding() const;
+
+ virtual bool OnPreKeyUp(wxKeyEvent& event);
+
+private:
+ wxString m_binding;
+};
+
+
+#endif // __SHORTCUTCHORDCTRL_H__
View
12 src/e.vcproj
@@ -502,6 +502,14 @@
>
</File>
<File
+ RelativePath=".\ShortcutChordCtrl.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ShortcutChordCtrl.h"
+ >
+ </File>
+ <File
RelativePath="ShortcutCtrl.cpp"
>
</File>
@@ -562,10 +570,6 @@
>
</File>
<File
- RelativePath=".\AcceleratorsDialogHtml.h"
- >
- </File>
- <File
RelativePath="CommitDlg.cpp"
>
</File>

0 comments on commit 5e82b9d

Please sign in to comment.