move toc menu code to menubackend

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4774 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jean-Marc Lasgouttes 2002-07-24 22:32:03 +00:00
parent e82c5a64dd
commit 041210bbe7
6 changed files with 171 additions and 183 deletions

View File

@ -1,5 +1,13 @@
2002-07-25 Jean-Marc Lasgouttes <lasgouttes@freesurf.fr>
* 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 <lasgouttes@freesurf.fr>
* 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)

View File

@ -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;

View File

@ -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) {}
///

View File

@ -1,3 +1,13 @@
2002-07-25 Jean-Marc Lasgouttes <lasgouttes@freesurf.fr>
* 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 <j.spitzmueller@gmx.de>
* FormFloat.C:

View File

@ -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<int> & smn, Window win)
{
@ -185,14 +175,15 @@ int get_new_submenu(vector<int> & smn, Window win)
max_number_of_menus =
fl_setpup_maxpup(static_cast<int>(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<int> & 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<int> & 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<int> & 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<ItemInfo *>(ob->u_vdata);
// lyxerr << "MenuCallback: ItemInfo address=" << iteminfo
// << "Val=(pimpl_=" << iteminfo->pimpl_
// << ", item_=" << iteminfo->item_
// << ", obj_=" << iteminfo->obj_ << ")" <<endl;
XFormsView * view = iteminfo->pimpl_->owner_;
MenuItem const * item = iteminfo->item_.get();

View File

@ -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();