1 //
2 // C++ Implementation: bookmarks dialog
3 //
4 // Description:
5 // Allows to set or go to bookmarks
6 //
7 // Author: Vadim Lopatin <vadim.lopatin@coolreader.org>, (C) 2008
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 // bmkdlg.cpp
12
13 #include <cri18n.h>
14 #include "bmkdlg.h"
15 #include "mainwnd.h"
16
17
CRBookmarkMenuItem(CRMenu * menu,int shortcut,CRBookmark * bookmark,int page)18 CRBookmarkMenuItem::CRBookmarkMenuItem( CRMenu * menu, int shortcut, CRBookmark * bookmark, int page )
19 : CRMenuItem(menu, shortcut, lString16(_("Empty slot")), LVImageSourceRef(), LVFontRef() ), _bookmark( bookmark ), _page(page)
20 {
21
22 }
23
Draw(LVDrawBuf & buf,lvRect & rc,CRRectSkinRef skin,CRRectSkinRef valueSkin,bool selected)24 void CRBookmarkMenuItem::Draw( LVDrawBuf & buf, lvRect & rc, CRRectSkinRef skin, CRRectSkinRef valueSkin, bool selected )
25 {
26 _itemDirty = false;
27 if ( !_bookmark ) {
28 CRMenuItem::Draw( buf, rc, skin, valueSkin, selected );
29 return;
30 }
31 lvRect itemBorders = skin->getBorderWidths();
32 skin->draw( buf, rc );
33 buf.SetTextColor( 0x000000 );
34 buf.SetBackgroundColor( 0xFFFFFF );
35 int imgWidth = 0;
36 int hh = rc.bottom - rc.top - itemBorders.top - itemBorders.bottom;
37 if ( !_image.isNull() ) {
38 int w = _image->GetWidth();
39 int h = _image->GetHeight();
40 buf.Draw( _image, rc.left + hh/2-w/2 + itemBorders.left, rc.top + hh/2 - h/2 + itemBorders.top, w, h );
41 imgWidth = w + 8;
42 }
43 lvRect textRect = rc;
44 textRect.left += imgWidth;
45 lvRect posRect = textRect;
46 lString16 text = _bookmark->getPosText();
47 if ( !text.empty() ) {
48 posRect.bottom = posRect.top + skin->getFont()->getHeight() + itemBorders.top + itemBorders.bottom;
49 textRect.top = posRect.bottom - itemBorders.bottom;
50 }
51 lString16 postext(_("Page $1 ($2%)"));
52 postext.replaceIntParam(1, _page+1);
53 postext.replaceParam(2, lString16::itoa( _bookmark->getPercent()/100 ) << "." << fmt::decimal(_bookmark->getPercent()%100));
54 postext << " " << _bookmark->getTitleText();
55 skin->drawText( buf, posRect, postext );
56 if ( !text.empty() )
57 valueSkin->drawText( buf, textRect, text );
58 }
59
setMode(bool goToMode)60 void CRBookmarkMenu::setMode( bool goToMode )
61 {
62 //if ( _goToMode==goToMode )
63 // return;
64 CRLog::trace("CRBookmarkMenu::setMode");
65 int k, f;
66 #ifdef CR_POCKETBOOK
67 lString16 selKeyName = getCommandKeyName( MCMD_SELECT );
68 #else
69 lString16 selKeyName = getItemNumberKeysName();
70 #endif
71 lString16 modeKeyName = getCommandKeyName( MCMD_NEXT_MODE );
72 bool hasModeSwitch = !modeKeyName.empty();
73 _goToMode = goToMode;
74 if ( _goToMode ) {
75 _caption = lString16(_("Go to bookmark"));
76 _label = _caption;
77 _statusText = lString16(
78 hasModeSwitch
79 ? _("Short press $1 - go to bookmark,\n$2 - switch to SET mode")
80 : _("Short press $1 - go to bookmark,\nlong press - set bookmark")
81 );
82 } else {
83 _caption = lString16(_("Set bookmark"));
84 _label = _caption;
85 _statusText = lString16(
86 hasModeSwitch
87 ? _("$1 - set bookmark,\n$2 - switch to GO mode")
88 : _("Short press $1 - set bookmark,\nlong press - go to bookmark")
89 );
90 }
91 _statusText.replaceParam(1, selKeyName);
92 _statusText.replaceParam(2, modeKeyName);
93 setDirty();
94 }
95
96 /// returns index of selected item, -1 if no item selected
getSelectedItemIndex()97 int CRBookmarkMenu::getSelectedItemIndex()
98 {
99 CRFileHistRecord * bookmarks = _docview->getCurrentFileHistRecord();
100 int curPage = _docview->getCurPage();
101 int n = bookmarks->getLastShortcutBookmark()+1;
102 for ( int i=1; i<=n; i++ ) {
103 CRBookmark * bm = bookmarks->getShortcutBookmark(i);
104 int page = 0;
105 if ( bm ) {
106 ldomXPointer p = _docview->getDocument()->createXPointer( bm->getStartPos() );
107 if ( !p.isNull() ) {
108 /// get page number by bookmark
109 page = _docview->getBookmarkPage( p );
110 /// get bookmark position text
111 if ( page>0 && page==curPage )
112 return i-1;
113 }
114 }
115 }
116 return -1;
117 }
118
119 #ifdef CR_POCKETBOOK
120 #include "cr3pocketbook.h"
121 #include "inkview.h"
122
123 static CRBookmarkMenu *bmkDialog = NULL;
124
125 static imenu _contextMenu[] = {
126 {ITEM_ACTIVE, DCMD_BOOKMARK_SAVE_N, NULL, NULL},
127 {ITEM_ACTIVE, DCMD_BOOKMARK_GO_N, NULL, NULL},
128 {ITEM_ACTIVE, PB_CMD_BOOKMARK_REMOVE, NULL, NULL},
129 { 0, 0, NULL, NULL }
130 };
131
handle_contextMenu(int index)132 static void handle_contextMenu(int index)
133 {
134 CRLog::trace("CRBookmarkMenu handle_contextMenu(%d)", index);
135 bmkDialog->handleContextMenu(index);
136 }
137
getDefaultSelectionIndex()138 int CRBookmarkMenu::getDefaultSelectionIndex()
139 {
140 if ( _goToMode )
141 return -1;
142 CRFileHistRecord * bookmarks = _docview->getCurrentFileHistRecord();
143 for ( int i=0; i<_items.length(); i++ ) {
144 CRBookmark * bm = bookmarks->getShortcutBookmark(i);
145 if ( bm == NULL)
146 return i;
147 }
148 return -1;
149 }
150
showContextMenu()151 void CRBookmarkMenu::showContextMenu()
152 {
153 CRBookmarkMenuItem *item = static_cast<CRBookmarkMenuItem *>(_items[_selectedItem]);
154 CRMenuSkinRef skin = getSkin();
155 CRRectSkinRef separatorSkin = skin->getSeparatorSkin();
156 int separatorHeight = 0;
157 if ( !separatorSkin.isNull() )
158 separatorHeight = separatorSkin->getMinSize().y;
159
160 lvRect clientRect;
161 getClientRect(clientRect);
162 lvPoint itemSize = getMaxItemSize();
163 _contextMenu[2].type = item->getBookmark() ? ITEM_ACTIVE : ITEM_INACTIVE;
164 int y = clientRect.top + (itemSize.y + separatorHeight) * (_selectedItem - _topItem) +
165 ((itemSize.y + separatorHeight)/4);
166 if (_contextMenu[0].text == NULL) {
167 _contextMenu[0].text = (char *)_("Set bookmark");
168 _contextMenu[1].text = (char *)_("Go to bookmark");
169 _contextMenu[2].text = (char *)_("Delete bookmark");
170 }
171 OpenMenu(_contextMenu,
172 _goToMode ? DCMD_BOOKMARK_GO_N : DCMD_BOOKMARK_SAVE_N,
173 ScreenWidth()/4,
174 y,
175 handle_contextMenu);
176 }
177
handleContextMenu(int index)178 void CRBookmarkMenu::handleContextMenu(int index)
179 {
180 _wm->postCommand(index, 0);
181 _wm->processPostedEvents();
182 }
183
184 #endif
185
186 #define MIN_BOOKMARK_ITEMS 32
CRBookmarkMenu(CRGUIWindowManager * wm,LVDocView * docview,int numItems,lvRect & rc,bool goToMode)187 CRBookmarkMenu::CRBookmarkMenu(CRGUIWindowManager * wm, LVDocView * docview, int numItems, lvRect & rc, bool goToMode)
188 : CRFullScreenMenu( wm, MCMD_BOOKMARK_LIST, lString16(_("Bookmarks")), numItems, rc )
189 , _docview(docview)
190 {
191 CRFileHistRecord * bookmarks = docview->getCurrentFileHistRecord();
192 CRGUIAcceleratorTableRef acc = _wm->getAccTables().get("bookmarks");
193 if ( acc.isNull() )
194 acc = _wm->getAccTables().get("menu");
195 setAccelerators( acc );
196 setSkinName(lString16("#bookmarks"));
197 int mc = getSkin()->getMinItemCount();
198 if ( _pageItems < mc )
199 _pageItems = mc;
200 int n = bookmarks->getLastShortcutBookmark()+1;
201 n = (n + _pageItems - 1) / _pageItems * _pageItems;
202 int minitems = (MIN_BOOKMARK_ITEMS + _pageItems - 1) / _pageItems * _pageItems;
203 if ( n<minitems )
204 n = minitems;
205 for ( int i=1; i<=n; i++ ) {
206 CRBookmark * bm = bookmarks->getShortcutBookmark(i);
207 int page = 0;
208 if ( bm ) {
209 ldomXPointer p = docview->getDocument()->createXPointer( bm->getStartPos() );
210 if ( !p.isNull() ) {
211 /// get page number by bookmark
212 page = docview->getBookmarkPage( p );
213 /// get bookmark position text
214 if ( page<0 )
215 bm = NULL;
216 }
217 }
218 CRBookmarkMenuItem * item = new CRBookmarkMenuItem( this, i, bm, page );
219 addItem( item );
220 }
221 setMode( goToMode );
222 #ifdef CR_POCKETBOOK
223 bmkDialog = this;
224 #endif
225 }
226
227 /// returns true if command is processed
onCommand(int command,int params)228 bool CRBookmarkMenu::onCommand( int command, int params )
229 {
230 if ( command>=MCMD_SELECT_1 && command<=MCMD_SELECT_9 ) {
231 int index = command - MCMD_SELECT_1 + 1;
232 if ( index >=1 && index <= _pageItems ) {
233 index += _topItem;
234 int cmd = _goToMode ? DCMD_BOOKMARK_GO_N : DCMD_BOOKMARK_SAVE_N;
235 closeMenu( cmd, index );
236 return true;
237 }
238 } else if ( command>=MCMD_SELECT_1_LONG && command<=MCMD_SELECT_9_LONG ) {
239 int index = command - MCMD_SELECT_1_LONG + 1;
240 if ( index >=1 && index <= _pageItems ) {
241 index += _topItem;
242 int cmd = _goToMode ? DCMD_BOOKMARK_SAVE_N : DCMD_BOOKMARK_GO_N;
243 closeMenu( cmd, index );
244 return true;
245 }
246 } else if ( command==MCMD_NEXT_MODE || command==MCMD_PREV_MODE ) {
247 setMode( !_goToMode );
248 return true;
249 } else if (command == MCMD_SELECT) {
250 if (_selectedItem >= 0)
251 closeMenu( _goToMode ? DCMD_BOOKMARK_GO_N : DCMD_BOOKMARK_SAVE_N, _selectedItem + 1 );
252 return true;
253 } else if (command == MCMD_SELECT_LONG) {
254 #ifdef CR_POCKETBOOK
255 if (_selectedItem >= 0)
256 showContextMenu();
257 #else
258 if (_selectedItem >= 0)
259 closeMenu( _goToMode ? DCMD_BOOKMARK_SAVE_N : DCMD_BOOKMARK_GO_N, _selectedItem + 1 );
260 #endif
261 return true;
262 } else if (command == MCMD_PREV_PAGE) {
263 if (_topItem == 0) {
264 closeMenu(0);
265 return true;
266 }
267 }
268 #ifdef CR_POCKETBOOK
269 else if (command == DCMD_BOOKMARK_SAVE_N || command == DCMD_BOOKMARK_GO_N) {
270 closeMenu( command, _selectedItem + 1 );
271 return true;
272 } else if (command == PB_CMD_BOOKMARK_REMOVE && _selectedItem >= 0) {
273 CRBookmarkMenuItem *item = static_cast<CRBookmarkMenuItem *>(_items[_selectedItem]);
274 CRBookmark *bm = item->getBookmark();
275 if (bm && _docview->removeBookmark(bm)) {
276 item->setBookmark(NULL);
277 setDirty();
278 }
279 return true;
280 }
281 #endif
282 return CRMenu::onCommand(command, params);
283 //closeMenu( 0 );
284 //return true;
285 }
286
287 #ifdef CR_POCKETBOOK
288 static CRCitesMenu *citesDialog = NULL;
289
290 static imenu _cites_contextMenu[] = {
291 {ITEM_ACTIVE, DCMD_BOOKMARK_GO_N, NULL, NULL},
292 {ITEM_ACTIVE, PB_CMD_BOOKMARK_REMOVE, NULL, NULL},
293 { 0, 0, NULL, NULL }
294 };
295
handle_citesContextMenu(int index)296 static void handle_citesContextMenu(int index)
297 {
298 citesDialog->handleContextMenu(index);
299 }
300
showContextMenu()301 void CRCitesMenu::showContextMenu()
302 {
303 CRBookmarkMenuItem *item = static_cast<CRBookmarkMenuItem *>(_items[_selectedItem]);
304 if (item->getBookmark() == NULL)
305 return;
306 CRMenuSkinRef skin = getSkin();
307 CRRectSkinRef separatorSkin = skin->getSeparatorSkin();
308 int separatorHeight = 0;
309 if ( !separatorSkin.isNull() )
310 separatorHeight = separatorSkin->getMinSize().y;
311 lvRect clientRect;
312 getClientRect(clientRect);
313 lvPoint itemSize = getMaxItemSize();
314 int y = clientRect.top + (itemSize.y + separatorHeight) * (_selectedItem - _topItem) +
315 ((itemSize.y + separatorHeight)/4);
316 if (_cites_contextMenu[0].text == NULL) {
317 _cites_contextMenu[0].text = (char *)_("Go to citation");
318 _cites_contextMenu[1].text = (char *)_("Delete citation");
319 }
320 OpenMenu(_cites_contextMenu, DCMD_BOOKMARK_GO_N, ScreenWidth()/4, y,
321 handle_citesContextMenu);
322 }
323
handleContextMenu(int index)324 void CRCitesMenu::handleContextMenu(int index)
325 {
326 _wm->postCommand(index, 0);
327 _wm->processPostedEvents();
328 }
329 #endif
330
CRCitesMenu(CRGUIWindowManager * wm,LVDocView * docview,int numItems,lvRect & rc)331 CRCitesMenu::CRCitesMenu(CRGUIWindowManager * wm, LVDocView * docview, int numItems, lvRect & rc)
332 : CRFullScreenMenu( wm, MCMD_CITES_LIST, lString16(_("Citations")), numItems, rc )
333 , _docview(docview)
334 {
335 CRGUIAcceleratorTableRef acc = _wm->getAccTables().get("bookmarks");
336 if ( acc.isNull() )
337 acc = _wm->getAccTables().get("menu");
338 setAccelerators( acc );
339 setSkinName(lString16("#bookmarks"));
340 int mc = getSkin()->getMinItemCount();
341 if ( _pageItems < mc )
342 _pageItems = mc;
343 CRFileHistRecord * rec = docview->getCurrentFileHistRecord();
344 LVPtrVector < CRBookmark > &bookmarks = rec->getBookmarks();
345 for ( int i=0; i < bookmarks.length(); i++ ) {
346 CRBookmark * bmk = bookmarks[i];
347 if (!bmk || ((bmk->getType() != bmkt_comment && bmk->getType() != bmkt_correction)))
348 continue;
349 ldomXPointer p = docview->getDocument()->createXPointer( bmk->getStartPos() );
350 if ( p.isNull() )
351 continue;
352 int page = docview->getBookmarkPage( p );
353 /// get bookmark position text
354 if ( page<0 )
355 continue;
356 CRBookmarkMenuItem * item = new CRBookmarkMenuItem( this, i, bmk, page );
357 addItem( item );
358 }
359 #ifdef CR_POCKETBOOK
360 citesDialog = this;
361 #endif
362 if (_items.length() == 0)
363 createDefaultItem();
364 }
365
366 /// returns true if command is processed
onCommand(int command,int params)367 bool CRCitesMenu::onCommand( int command, int params )
368 {
369 if ( command>=MCMD_SELECT_1 && command<=MCMD_SELECT_9 ) {
370 int index = command - MCMD_SELECT_1 + 1;
371 if ( index >=1 && index <= _pageItems ) {
372 index += _topItem;
373 goToCitePage( index - 1);
374 return true;
375 }
376 } else if (command == MCMD_SELECT) {
377 if (_selectedItem >= 0)
378 goToCitePage(_selectedItem );
379 return true;
380 } else if (command == MCMD_SELECT_LONG) {
381 #ifdef CR_POCKETBOOK
382 if (_selectedItem >= 0)
383 showContextMenu();
384 #endif
385 return true;
386 } else if (command == MCMD_PREV_PAGE) {
387 if (_topItem == 0) {
388 closeMenu(0);
389 return true;
390 }
391 }
392 #ifdef CR_POCKETBOOK
393 else if (command == DCMD_BOOKMARK_GO_N) {
394 goToCitePage( _selectedItem );
395 return true;
396 } else if (command == PB_CMD_BOOKMARK_REMOVE && _selectedItem >= 0) {
397 CRBookmarkMenuItem *item = static_cast<CRBookmarkMenuItem *>(_items[_selectedItem]);
398 CRBookmark *bm = item->getBookmark();
399 if (bm && _docview->removeBookmark(bm)) {
400 item = static_cast<CRBookmarkMenuItem *>(_items.remove(_selectedItem));
401 delete item;
402 if (_selectedItem >= _items.length()) {
403 _selectedItem = _items.length() -1;
404 if (_selectedItem < 0) {
405 createDefaultItem();
406 _selectedItem = 0;
407 }
408 }
409 setDirty();
410 _pageUpdate = true;
411 }
412 return true;
413 }
414 #endif
415 return CRMenu::onCommand(command, params);
416 }
417
goToCitePage(int selecteditem)418 void CRCitesMenu::goToCitePage(int selecteditem)
419 {
420 if (selecteditem >= 0 && selecteditem < _items.length()) {
421 CRBookmarkMenuItem *item = static_cast<CRBookmarkMenuItem *>(_items[_selectedItem]);
422 if (item->getBookmark() == NULL)
423 closeMenu(MCMD_CITE);
424 else
425 closeMenu( DCMD_GO_PAGE, item->getPage() );
426 }
427 }
428
getSelectedItemIndex()429 int CRCitesMenu::getSelectedItemIndex()
430 {
431 CRFileHistRecord * bookmarks = _docview->getCurrentFileHistRecord();
432 int curPage = _docview->getCurPage();
433 for (int i = 0; i < _items.length(); i++) {
434 CRBookmarkMenuItem *item = static_cast<CRBookmarkMenuItem *>(_items[i]);
435 if (item->getPage() == curPage)
436 return i;
437 }
438 return -1;
439 }
440
createDefaultItem()441 void CRCitesMenu::createDefaultItem()
442 {
443 CRBookmarkMenuItem * item = new CRBookmarkMenuItem( this, 0, NULL, 0 );
444 item->setLabel(lString16(_("Cite selection dialog")));
445 addItem( item );
446 }
447