diff --git a/src/ChangeLog b/src/ChangeLog index f4f572de65..e715735680 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,13 @@ +2002-07-25 Jean-Marc Lasgouttes + + * MenuBackend.C (expandToc): + (expandToc2): code moved from xforms menu frontend. It is now + generic and TOCs are transparent to menu frontends. + 2002-07-24 Jean-Marc Lasgouttes + * toc.C (getTocList): protect against buf=0 + * MenuBackend.C (expand): move from Menu to MenuBackend; pass a Menu as first parameter. Now, this calls itself recursively to expand a whole tree (this will be useful for TOC handling) diff --git a/src/MenuBackend.C b/src/MenuBackend.C index 206e880174..d8bb1620b6 100644 --- a/src/MenuBackend.C +++ b/src/MenuBackend.C @@ -28,6 +28,7 @@ #include "exporter.h" #include "importer.h" #include "FloatList.h" +#include "toc.h" #include "support/LAssert.h" #include "support/filetools.h" #include "support/lyxfunctional.h" @@ -262,6 +263,17 @@ public: } }; +string const limit_string_length(string const & str) +{ + string::size_type const max_item_length = 45; + + if (str.size() > max_item_length) + return str.substr(0, max_item_length - 3) + "..."; + else + return str; +} + + void expandLastfiles(Menu & tomenu) { int ii = 1; @@ -361,6 +373,7 @@ void expandFormats(MenuItem::Kind kind, Menu & tomenu, Buffer const * buf) } } + void expandFloatListInsert(Menu & tomenu) { FloatList::const_iterator cit = floatList.begin(); @@ -374,6 +387,7 @@ void expandFloatListInsert(Menu & tomenu) } } + void expandFloatInsert(Menu & tomenu) { FloatList::const_iterator cit = floatList.begin(); @@ -388,6 +402,90 @@ void expandFloatInsert(Menu & tomenu) } } + +Menu::size_type const max_number_of_items = 25; + +void expandToc2(Menu & tomenu, toc::Toc const & toc_list, + toc::Toc::size_type from, toc::Toc::size_type to, int depth) +{ + int shortcut_count = 0; + if (to - from <= max_number_of_items) { + for (toc::Toc::size_type i = from; i < to; ++i) { + int const action = toc_list[i].action(); + string label(4 * max(0, toc_list[i].depth - depth),' '); + label += limit_string_length(toc_list[i].str); + if (toc_list[i].depth == depth + && ++shortcut_count <= 9) { + label += "|" + tostr(shortcut_count); + } + tomenu.add(MenuItem(MenuItem::Command, label, action)); + } + } else { + toc::Toc::size_type pos = from; + while (pos < to) { + toc::Toc::size_type new_pos = pos + 1; + while (new_pos < to && + toc_list[new_pos].depth > depth) + ++new_pos; + + int const action = toc_list[pos].action(); + string label(4 * max(0, toc_list[pos].depth - depth), ' '); + label += limit_string_length(toc_list[pos].str); + if (toc_list[pos].depth == depth && + ++shortcut_count <= 9) + label += '|' + tostr(shortcut_count); + + if (new_pos == pos + 1) { + tomenu.add(MenuItem(MenuItem::Command, + label, action)); + } else { + MenuItem item(MenuItem::Submenu, label); + item.submenu(new Menu); + expandToc2(*item.submenu(), + toc_list, pos, new_pos, depth + 1); + tomenu.add(item); + } + pos = new_pos; + } + } +} + + +void expandToc(Menu & tomenu, Buffer const * buf) +{ + toc::TocList toc_list = toc::getTocList(buf); + toc::TocList::const_iterator cit = toc_list.begin(); + toc::TocList::const_iterator end = toc_list.end(); + for (; cit != end; ++cit) { + // Handle this later + if (cit->first == "TOC") continue; + + // All the rest is for floats + Menu * menu = new Menu; + toc::Toc::const_iterator ccit = cit->second.begin(); + toc::Toc::const_iterator eend = cit->second.end(); + for (; ccit != eend; ++ccit) { + string const label = limit_string_length(ccit->str); + menu->add(MenuItem(MenuItem::Command, + label, ccit->action())); + } + MenuItem item(MenuItem::Submenu, + floatList[cit->first]->second.name()); + item.submenu(menu); + tomenu.add(item); + } + + // Handle normal TOC + cit = toc_list.find("TOC"); + if (cit == end) { + tomenu.add(MenuItem(MenuItem::Command, + _("No Table of contents"))); + } else { + expandToc2(tomenu, cit->second, 0, cit->second.size(), 0); + } +} + + } // namespace anon @@ -420,11 +518,15 @@ void MenuBackend::expand(Menu const & frommenu, Menu & tomenu, expandFloatInsert(tomenu); break; + case MenuItem::Toc: + expandToc(tomenu, buf); + break; + case MenuItem::Submenu: { MenuItem item(*cit); - item.submenu_.reset(new Menu(cit->submenuname_)); - expand(getMenu(cit->submenuname_), - *item.submenu_, buf); + item.submenu(new Menu(cit->submenuname())); + expand(getMenu(cit->submenuname()), + *item.submenu(), buf); tomenu.add(item); } break; diff --git a/src/MenuBackend.h b/src/MenuBackend.h index 5cc405bf22..b7a3abeb7a 100644 --- a/src/MenuBackend.h +++ b/src/MenuBackend.h @@ -88,14 +88,19 @@ public: Kind kind() const { return kind_; } /// the action (if relevant) int action() const { return action_; } - /// the description of the submenu (if relevant) - string const & submenuname() const { return submenuname_; } /// returns true if the entry should be ommited when disabled bool optional() const { return optional_; } + /// the description of the submenu (if relevant) + string const & submenuname() const { return submenuname_; } + /// the description of the submenu (if relevant) + void submenuname(string const & name) { submenuname_ = name; } /// - Menu & submenu() const { return *submenu_.get(); } + Menu * submenu() const { return submenu_.get(); } + /// + void submenu(Menu * menu) { submenu_.reset(menu); } + private: - friend class MenuBackend; + //friend class MenuBackend; /// Kind kind_; /// @@ -119,6 +124,8 @@ public: /// typedef ItemList::const_iterator const_iterator; /// + typedef ItemList::size_type size_type; + /// explicit Menu(string const & name = string()) : name_(name) {} /// diff --git a/src/frontends/xforms/ChangeLog b/src/frontends/xforms/ChangeLog index a0dcd2d2b8..6f0e64e797 100644 --- a/src/frontends/xforms/ChangeLog +++ b/src/frontends/xforms/ChangeLog @@ -1,3 +1,13 @@ +2002-07-25 Jean-Marc Lasgouttes + + * Menubar_pimpl.C (create_submenu): add the code for splitting too + long menus here. Remove call to add_toc. + + * Menubar_pimpl.C (add_toc): + (add_toc2): remove. This code is now in MenuBackend; now, all the + frontend has to do is to support the item kinds Command, Submenu + and Separator. The rest is done transparently. + 2002-07-24 Juergen Spitzmueller * FormFloat.C: diff --git a/src/frontends/xforms/Menubar_pimpl.C b/src/frontends/xforms/Menubar_pimpl.C index c5503dca2c..b452a10161 100644 --- a/src/frontends/xforms/Menubar_pimpl.C +++ b/src/frontends/xforms/Menubar_pimpl.C @@ -166,17 +166,7 @@ void Menubar::Pimpl::openByName(string const & name) namespace { -inline -string const limit_string_length(string const & str) -{ - string::size_type const max_item_length = 45; - - if (str.size() > max_item_length) - return str.substr(0, max_item_length - 3) + "..."; - else - return str; -} - +Menu::size_type const max_number_of_items = 25; int get_new_submenu(vector & smn, Window win) { @@ -185,14 +175,15 @@ int get_new_submenu(vector & smn, Window win) max_number_of_menus = fl_setpup_maxpup(static_cast(2*smn.size())); int menu = fl_newpup(win); + fl_setpup_softedge(menu, true); + fl_setpup_bw(menu, -1); + lyxerr[Debug::GUI] << "Adding menu " << menu + << " in deletion list" << endl; smn.push_back(menu); return menu; } -size_type const max_number_of_items = 25; - -inline string const fixlabel(string const & str) { #if FL_VERSION < 1 && FL_REVISION < 89 @@ -204,149 +195,16 @@ string const fixlabel(string const & str) -void add_toc2(int menu, string const & extra_label, - vector & smn, Window win, - toc::Toc const & toc_list, - size_type from, size_type to, int depth) -{ - int shortcut_count = 0; - if (to - from <= max_number_of_items) { - for (size_type i = from; i < to; ++i) { - int const action = toc_list[i].action(); - string label(4 * max(0, toc_list[i].depth - depth),' '); - label += fixlabel(toc_list[i].str); - label = limit_string_length(label); - label += "%x" + tostr(action + action_offset); - if (i == to - 1 && depth == 0) - label += extra_label; - if (toc_list[i].depth == depth - && ++shortcut_count <= 9) { - label += "%h"; - fl_addtopup(menu, label.c_str(), - tostr(shortcut_count).c_str()); - } else - fl_addtopup(menu, label.c_str()); - } - } else { - size_type pos = from; - size_type count = 0; - while (pos < to) { - ++count; - if (count > max_number_of_items) { - int menu2 = get_new_submenu(smn, win); - add_toc2(menu2, extra_label, smn, win, - toc_list, pos, to, depth); - string label = _("More"); - label += "...%m"; - if (depth == 0) - label += extra_label; - fl_addtopup(menu, label.c_str(), menu2); - break; - } - size_type new_pos = pos+1; - while (new_pos < to && - toc_list[new_pos].depth > depth) - ++new_pos; - - int const action = toc_list[pos].action(); - string label(4 * max(0, toc_list[pos].depth - depth), ' '); - label += fixlabel(toc_list[pos].str); - label = limit_string_length(label); - if (new_pos == to && depth == 0) - label += extra_label; - string shortcut; - if (toc_list[pos].depth == depth && - ++shortcut_count <= 9) - shortcut = tostr(shortcut_count); - - if (new_pos == pos + 1) { - label += "%x" + tostr(action + action_offset); - if (!shortcut.empty()) { - label += "%h"; - fl_addtopup(menu, label.c_str(), - shortcut.c_str()); - } else - fl_addtopup(menu, label.c_str()); - } else { - int menu2 = get_new_submenu(smn, win); - add_toc2(menu2, extra_label, smn, win, - toc_list, pos, new_pos, depth+1); - label += "%m"; - if (!shortcut.empty()) { - label += "%h"; - fl_addtopup(menu, label.c_str(), menu2, - shortcut.c_str()); - } else - fl_addtopup(menu, label.c_str(), menu2); - } - pos = new_pos; - } - } -} - } // namespace anon -void Menubar::Pimpl::add_toc(int menu, string const & extra_label, - vector & smn, Window win) -{ - if (!owner_->buffer()) - return; - toc::TocList toc_list = toc::getTocList(owner_->buffer()); - toc::TocList::const_iterator cit = toc_list.begin(); - toc::TocList::const_iterator end = toc_list.end(); - for (; cit != end; ++cit) { - // Handle this elsewhere - if (cit->first == "TOC") continue; - - // All the rest is for floats - int menu_first_sub = get_new_submenu(smn, win); - int menu_current = menu_first_sub; - toc::Toc::const_iterator ccit = cit->second.begin(); - toc::Toc::const_iterator eend = cit->second.end(); - size_type count = 0; - for (; ccit != eend; ++ccit) { - ++count; - if (count > max_number_of_items) { - int menu_tmp = get_new_submenu(smn, win); - string label = _("More"); - label += "...%m"; - fl_addtopup(menu_current, label.c_str(), menu_tmp); - count = 1; - menu_current = menu_tmp; - } - int const action = ccit->action(); - string label = fixlabel(ccit->str); - label = limit_string_length(label); - label += "%x" + tostr(action + action_offset); - fl_addtopup(menu_current, label.c_str()); - } - string const m = floatList[cit->first]->second.name() + "%m"; - fl_addtopup(menu, m.c_str(), menu_first_sub); - } - - - // Handle normal TOC - cit = toc_list.find("TOC"); - if (cit == end) { - string const tmp = _("No Table of contents%i") + extra_label; - fl_addtopup(menu, tmp.c_str()); - return; - } else { - add_toc2(menu, extra_label, smn, win, - cit->second, 0, cit->second.size(), 0); - } -} - int Menubar::Pimpl::create_submenu(Window win, XFormsView * view, Menu const & menu, vector & smn) { - int const menuid = get_new_submenu(smn, win); - fl_setpup_softedge(menuid, true); - fl_setpup_bw(menuid, -1); - lyxerr[Debug::GUI] << "Adding menu " << menuid - << " in deletion list" << endl; + const int menuid = get_new_submenu(smn, win); + lyxerr[Debug::GUI] << "Menubar::Pimpl::create_submenu: creating " + << menu.name() << " as menuid=" << menuid << endl; // Compute the size of the largest label (because xforms is // not able to support shortcuts correctly...) @@ -380,10 +238,24 @@ int Menubar::Pimpl::create_submenu(Window win, XFormsView * view, last = it; it = extra_labels.begin(); + size_type count = 0; + int curmenuid = menuid; for (Menu::const_iterator i = menu.begin(); i != end; ++i, ++it) { MenuItem const & item = (*i); string & extra_label = *it; + ++count; + if (count > max_number_of_items) { + int tmpmenuid = get_new_submenu(smn, win); + lyxerr[Debug::GUI] << "Too many items, creating " + << "new menu " << tmpmenuid << endl; + string label = _("More"); + label += "...%m"; + fl_addtopup(curmenuid, label.c_str(), tmpmenuid); + count = 1; + curmenuid = tmpmenuid; + } + switch (item.kind()) { case MenuItem::Command: { FuncStatus const flag = @@ -399,9 +271,10 @@ int Menubar::Pimpl::create_submenu(Window win, XFormsView * view, // Get the keys bound to this action, but keep only the // first one later - string const accel = toplevel_keymap->findbinding(kb_action(item.action())); + string const accel = + toplevel_keymap->findbinding(item.action()); // Build the menu label from all the info - string label = item.label(); + string label = fixlabel(item.label()); if (!accel.empty()) { // Try to be clever and add just enough @@ -430,34 +303,36 @@ int Menubar::Pimpl::create_submenu(Window win, XFormsView * view, if (!shortcut.empty()) { shortcut += lowercase(shortcut[0]); label += "%h"; - fl_addtopup(menuid, label.c_str(), + fl_addtopup(curmenuid, label.c_str(), shortcut.c_str()); } else - fl_addtopup(menuid, label.c_str()); + fl_addtopup(curmenuid, label.c_str()); lyxerr[Debug::GUI] << "Command: \"" << lyxaction.getActionName(item.action()) << "\", binding \"" << accel << "\", shortcut \"" << shortcut - << "\"" << endl; + << "\" (added to menu" + << curmenuid << ")" << endl; break; } case MenuItem::Submenu: { int submenuid = create_submenu(win, view, - item.submenu(), smn); + *item.submenu(), smn); if (submenuid == -1) return -1; - string label = item.label(); + string label = fixlabel(item.label()); label += extra_label + "%m"; string shortcut = item.shortcut(); if (!shortcut.empty()) { shortcut += lowercase(shortcut[0]); label += "%h"; - fl_addtopup(menuid, label.c_str(), + fl_addtopup(curmenuid, label.c_str(), submenuid, shortcut.c_str()); } else { - fl_addtopup(menuid, label.c_str(), submenuid); + fl_addtopup(curmenuid, label.c_str(), + submenuid); } break; } @@ -467,22 +342,11 @@ int Menubar::Pimpl::create_submenu(Window win, XFormsView * view, // we just ignore it. break; - case MenuItem::Toc: - add_toc(menuid, extra_label, smn, win); - break; - case MenuItem::Documents: - case MenuItem::Lastfiles: - case MenuItem::ViewFormats: - case MenuItem::UpdateFormats: - case MenuItem::ExportFormats: - case MenuItem::ImportFormats: - case MenuItem::FloatListInsert: - case MenuItem::FloatInsert: + default: lyxerr << "Menubar::Pimpl::create_submenu: " "this should not happen" << endl; break; - } } return menuid; @@ -492,11 +356,6 @@ int Menubar::Pimpl::create_submenu(Window win, XFormsView * view, void Menubar::Pimpl::MenuCallback(FL_OBJECT * ob, long button) { ItemInfo * iteminfo = static_cast(ob->u_vdata); -// lyxerr << "MenuCallback: ItemInfo address=" << iteminfo -// << "Val=(pimpl_=" << iteminfo->pimpl_ -// << ", item_=" << iteminfo->item_ -// << ", obj_=" << iteminfo->obj_ << ")" <pimpl_->owner_; MenuItem const * item = iteminfo->item_.get(); diff --git a/src/toc.C b/src/toc.C index 06b4062b7f..7a307b0565 100644 --- a/src/toc.C +++ b/src/toc.C @@ -72,6 +72,8 @@ string const getType(string const & cmdName) TocList const getTocList(Buffer const * buf) { TocList toclist; + if (!buf) + return toclist; Paragraph * par = buf->paragraph; LyXTextClass const & textclass = buf->params.getLyXTextClass();