1 /*
2 * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 #include <ZLOptionsDialog.h>
21 #include <ZLApplication.h>
22 #include <ZLOptionEntry.h>
23
24 #include <optionEntries/ZLSimpleOptionEntry.h>
25 #include <optionEntries/ZLSimpleKeyOptionEntry.h>
26
27 #include "ReadingOptionsDialog.h"
28
29 #include "../../fbreader/FBReader.h"
30 #include "../../fbreader/FBReaderActions.h"
31
32 class KeyboardControlEntry : public ZLSimpleBooleanOptionEntry {
33
34 public:
35 KeyboardControlEntry();
36 void onStateChanged(bool state);
37 };
38
KeyboardControlEntry()39 KeyboardControlEntry::KeyboardControlEntry() : ZLSimpleBooleanOptionEntry(FBReader::Instance().KeyboardControlOption) {
40 }
41
onStateChanged(bool state)42 void KeyboardControlEntry::onStateChanged(bool state) {
43 ZLSimpleBooleanOptionEntry::onStateChanged(state);
44 FBReader::Instance().grabAllKeys(state);
45 }
46
47 class SingleKeyOptionEntry : public ZLSimpleKeyOptionEntry {
48
49 public:
50 SingleKeyOptionEntry(const CodeIndexBimap &bimap, ZLKeyBindings &bindings);
51 const CodeIndexBimap &codeIndexBimap() const;
52
53 private:
54 const CodeIndexBimap &myBimap;
55 };
56
SingleKeyOptionEntry(const CodeIndexBimap & bimap,ZLKeyBindings & bindings)57 SingleKeyOptionEntry::SingleKeyOptionEntry(const CodeIndexBimap &bimap, ZLKeyBindings &bindings) : ZLSimpleKeyOptionEntry(bindings), myBimap(bimap) {
58 }
59
codeIndexBimap() const60 const ZLSimpleKeyOptionEntry::CodeIndexBimap &SingleKeyOptionEntry::codeIndexBimap() const {
61 return myBimap;
62 }
63
64 class MultiKeyOptionEntry : public ZLKeyOptionEntry {
65
66 public:
67 MultiKeyOptionEntry(const ZLResource &resource);
68 void onAccept();
69 int actionIndex(const std::string &key);
70 void onValueChanged(const std::string &key, int index);
71 void onKeySelected(const std::string &key);
72
73 void setOrientation(ZLView::Angle);
74 void setExitOnCancelEntry(ZLOptionEntry *exitOnCancelEntry);
75
76 private:
77 void addAction(const std::string &actionId);
78
79 private:
80 const ZLResource &myResource;
81 ZLSimpleKeyOptionEntry::CodeIndexBimap myBimap;
82
83 SingleKeyOptionEntry myEntry0;
84 SingleKeyOptionEntry myEntry90;
85 SingleKeyOptionEntry myEntry180;
86 SingleKeyOptionEntry myEntry270;
87 SingleKeyOptionEntry *myCurrentEntry;
88 ZLOptionEntry *myExitOnCancelEntry;
89 };
90
addAction(const std::string & actionId)91 void MultiKeyOptionEntry::addAction(const std::string &actionId) {
92 myBimap.insert(actionId);
93 addActionName(myResource[ZLResourceKey(actionId)].value());
94 }
95
MultiKeyOptionEntry(const ZLResource & resource)96 MultiKeyOptionEntry::MultiKeyOptionEntry(const ZLResource &resource) :
97 ZLKeyOptionEntry(),
98 myResource(resource),
99 myEntry0(myBimap, *FBReader::Instance().keyBindings(ZLView::DEGREES0)),
100 myEntry90(myBimap, *FBReader::Instance().keyBindings(ZLView::DEGREES90)),
101 myEntry180(myBimap, *FBReader::Instance().keyBindings(ZLView::DEGREES180)),
102 myEntry270(myBimap, *FBReader::Instance().keyBindings(ZLView::DEGREES270)),
103 myCurrentEntry(&myEntry0),
104 myExitOnCancelEntry(0) {
105 addAction(ZLApplication::NoAction);
106
107 // switch view
108 addAction(ActionCode::SHOW_LIBRARY);
109 addAction(ActionCode::SHOW_NETWORK_LIBRARY);
110 addAction(ActionCode::OPEN_PREVIOUS_BOOK);
111 addAction(ActionCode::SHOW_TOC);
112
113 // navigation
114 addAction(ActionCode::SCROLL_TO_HOME);
115 addAction(ActionCode::SCROLL_TO_START_OF_TEXT);
116 addAction(ActionCode::SCROLL_TO_END_OF_TEXT);
117 addAction(ActionCode::GOTO_NEXT_TOC_SECTION);
118 addAction(ActionCode::GOTO_PREVIOUS_TOC_SECTION);
119 addAction(ActionCode::PAGE_SCROLL_FORWARD);
120 addAction(ActionCode::PAGE_SCROLL_BACKWARD);
121 addAction(ActionCode::LINE_SCROLL_FORWARD);
122 addAction(ActionCode::LINE_SCROLL_BACKWARD);
123 addAction(ActionCode::UNDO);
124 addAction(ActionCode::REDO);
125
126 // selection
127 addAction(ActionCode::COPY_SELECTED_TEXT_TO_CLIPBOARD);
128 addAction(ActionCode::OPEN_SELECTED_TEXT_IN_DICTIONARY);
129 addAction(ActionCode::CLEAR_SELECTION);
130
131 // search
132 addAction(ActionCode::SEARCH);
133 addAction(ActionCode::FIND_PREVIOUS);
134 addAction(ActionCode::FIND_NEXT);
135
136 // look
137 addAction(ActionCode::INCREASE_FONT);
138 addAction(ActionCode::DECREASE_FONT);
139 addAction(ActionCode::SHOW_HIDE_POSITION_INDICATOR);
140 addAction(ActionCode::TOGGLE_FULLSCREEN);
141 addAction(ActionCode::ROTATE_SCREEN);
142
143 // dialogs
144 addAction(ActionCode::SHOW_OPTIONS_DIALOG);
145 addAction(ActionCode::SHOW_BOOK_INFO_DIALOG);
146 addAction(ActionCode::ADD_BOOK);
147
148 // quit
149 addAction(ActionCode::CANCEL);
150 addAction(ActionCode::QUIT);
151 }
152
setOrientation(ZLView::Angle angle)153 void MultiKeyOptionEntry::setOrientation(ZLView::Angle angle) {
154 switch (angle) {
155 case ZLView::DEGREES0:
156 myCurrentEntry = &myEntry0;
157 break;
158 case ZLView::DEGREES90:
159 myCurrentEntry = &myEntry90;
160 break;
161 case ZLView::DEGREES180:
162 myCurrentEntry = &myEntry180;
163 break;
164 case ZLView::DEGREES270:
165 myCurrentEntry = &myEntry270;
166 break;
167 }
168 resetView();
169 }
170
onAccept()171 void MultiKeyOptionEntry::onAccept() {
172 myEntry0.onAccept();
173 myEntry90.onAccept();
174 myEntry180.onAccept();
175 myEntry270.onAccept();
176 }
177
actionIndex(const std::string & key)178 int MultiKeyOptionEntry::actionIndex(const std::string &key) {
179 return myCurrentEntry->actionIndex(key);
180 }
181
onValueChanged(const std::string & key,int index)182 void MultiKeyOptionEntry::onValueChanged(const std::string &key, int index) {
183 myCurrentEntry->onValueChanged(key, index);
184 if (myExitOnCancelEntry != 0) {
185 myExitOnCancelEntry->setVisible(myBimap.codeByIndex(index) == ActionCode::CANCEL);
186 }
187 }
188
setExitOnCancelEntry(ZLOptionEntry * exitOnCancelEntry)189 void MultiKeyOptionEntry::setExitOnCancelEntry(ZLOptionEntry *exitOnCancelEntry) {
190 myExitOnCancelEntry = exitOnCancelEntry;
191 }
192
onKeySelected(const std::string & key)193 void MultiKeyOptionEntry::onKeySelected(const std::string &key) {
194 if (myExitOnCancelEntry != 0) {
195 myExitOnCancelEntry->setVisible(myBimap.codeByIndex(myCurrentEntry->actionIndex(key)) == ActionCode::CANCEL);
196 }
197 }
198
199 class OrientationEntry : public ZLComboOptionEntry {
200
201 public:
202 OrientationEntry(MultiKeyOptionEntry &keyEntry, const ZLResource &resource);
203 const std::string &initialValue() const;
204 const std::vector<std::string> &values() const;
205 void onValueSelected(int index);
206 void onAccept(const std::string &value);
207
208 private:
209 MultiKeyOptionEntry &myKeyEntry;
210 const ZLResource &myResource;
211 };
212
OrientationEntry(MultiKeyOptionEntry & keyEntry,const ZLResource & resource)213 OrientationEntry::OrientationEntry(MultiKeyOptionEntry &keyEntry, const ZLResource &resource) : myKeyEntry(keyEntry), myResource(resource) {
214 }
215
initialValue() const216 const std::string &OrientationEntry::initialValue() const {
217 return values()[0];
218 }
219
values() const220 const std::vector<std::string> &OrientationEntry::values() const {
221 static std::vector<std::string> _values;
222 if (_values.empty()) {
223 _values.push_back(myResource["degrees0"].value());
224 _values.push_back(myResource["degrees90ccw"].value());
225 _values.push_back(myResource["degrees180"].value());
226 _values.push_back(myResource["degrees90cw"].value());
227 }
228 return _values;
229 }
230
onValueSelected(int index)231 void OrientationEntry::onValueSelected(int index) {
232 static ZLView::Angle angles[] = {
233 ZLView::DEGREES0,
234 ZLView::DEGREES90,
235 ZLView::DEGREES180,
236 ZLView::DEGREES270
237 };
238 myKeyEntry.setOrientation(angles[index]);
239 }
240
onAccept(const std::string &)241 void OrientationEntry::onAccept(const std::string&) {
242 }
243
244 class UseSeparateOptionsEntry : public ZLSimpleBooleanOptionEntry {
245
246 public:
247 UseSeparateOptionsEntry(ZLOptionEntry &keyEntry, OrientationEntry &orientationEntry);
248 void onStateChanged(bool state);
249
250 private:
251 ZLOptionEntry &myKeyEntry;
252 OrientationEntry &myOrientationEntry;
253 };
254
UseSeparateOptionsEntry(ZLOptionEntry & keyEntry,OrientationEntry & orientationEntry)255 UseSeparateOptionsEntry::UseSeparateOptionsEntry(ZLOptionEntry &keyEntry, OrientationEntry &orientationEntry) : ZLSimpleBooleanOptionEntry(FBReader::Instance().UseSeparateBindingsOption), myKeyEntry(keyEntry), myOrientationEntry(orientationEntry) {
256 }
257
onStateChanged(bool state)258 void UseSeparateOptionsEntry::onStateChanged(bool state) {
259 ZLSimpleBooleanOptionEntry::onStateChanged(state);
260 myOrientationEntry.setVisible(state);
261 myKeyEntry.resetView();
262 }
263
264
createKeyBindingsTab()265 void ReadingOptionsDialog::createKeyBindingsTab() {
266 ZLDialogContent &dialogTab = dialog().createTab(ZLResourceKey("Keys"));
267 FBReader &fbreader = FBReader::Instance();
268 if (ZLBooleanOption(ZLCategoryKey::EMPTY, ZLOption::PLATFORM_GROUP, ZLOption::FULL_KEYBOARD_CONTROL, false).value()) {
269 dialogTab.addOption(ZLResourceKey("grabSystemKeys"), new KeyboardControlEntry());
270 }
271 ZLResourceKey actionKey("action");
272 ZLResourceKey separateKey("separate");
273 ZLResourceKey orientationKey("orientation");
274 MultiKeyOptionEntry *keyEntry = new MultiKeyOptionEntry(dialogTab.resource(actionKey));
275 OrientationEntry *orientationEntry = new OrientationEntry(*keyEntry, dialogTab.resource(orientationKey));
276 ZLBooleanOptionEntry *useSeparateBindingsEntry = new UseSeparateOptionsEntry(*keyEntry, *orientationEntry);
277 dialogTab.addOption(separateKey, useSeparateBindingsEntry);
278 dialogTab.addOption(orientationKey, orientationEntry);
279 dialogTab.addOption("", "", keyEntry);
280 ZLOptionEntry *exitOnCancelEntry = new ZLSimpleBooleanOptionEntry(fbreader.QuitOnCancelOption);
281 keyEntry->setExitOnCancelEntry(exitOnCancelEntry);
282 dialogTab.addOption(ZLResourceKey("quitOnCancel"), exitOnCancelEntry);
283 exitOnCancelEntry->setVisible(false);
284 useSeparateBindingsEntry->onStateChanged(useSeparateBindingsEntry->initialState());
285 dialogTab.addOption(ZLResourceKey("keyDelay"), new ZLSimpleSpinOptionEntry(fbreader.KeyDelayOption, 50));
286 }
287