lyx_mirror/src/frontends/Toolbars.cpp

383 lines
10 KiB
C++
Raw Normal View History

/**
* \file Toolbars.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Lars Gullik Bj<EFBFBD>nnes
* \author Angus Leeming
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "frontends/Toolbars.h"
#include "frontends/LyXView.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "debug.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
#include "gettext.h"
#include "LyX.h"
#include "LyXFunc.h"
#include "TextClass.h"
using std::endl;
using std::string;
namespace lyx {
namespace frontend {
Toolbars::Toolbars(LyXView & owner)
: owner_(owner),
layout_(0),
This is one of a series of patches that will merge the layout modules development in personal/branches/rgheck back into the tree. Design goal: Allow the use of layout "modules", which are to LaTeX packages as layout files are to LaTeX document classes. Thus, one could have a module that defined certain character styles, environments, commands, or what have you, and include it in various documents, each of which uses a different document class, without having to modify the layout files themselves. For example, a theorems.module could be used with article.layout to provide support for theorem-type environments, without having to modify article.layout itself, and the same module could be used with book.layout, etc. This first patch does some reworking of the infrastructrue. We need to distinguish between the TextClass that a particular document is using and the layout of that document, since modules, in particular, can modify the layout. The solution adopted here is to add a TextClass pointer to BufferParams, which will hold the layout. The layout itself is then constructed from the TextClass the document is using. At present, this is completely trivial, but that will change when modules are added. The pointer in question is a boost::shared_ptr. This is needed because CutAndPaste saves a copy of the layout with each cut or copied selection. We cannot assume the selection vanishes when the document is closed, so there are two options: (i) keep a list of all the layouts that have ever been used by any document; (ii) used some kind of smart pointer. The latter seems preferable, as the former would waste memory. More importantly, the use of a smart pointer allows modules to be modified on disk and then reloaded while LyX is running, and it will eventually allow the same for layout files. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19756 a592a061-630c-0410-9148-cb99ea01b6c8
2007-08-23 16:41:13 +00:00
last_textclass_(TextClass_ptr())
{}
#define TurnOnFlag(x) flags |= ToolbarInfo::x
#define TurnOffFlag(x) flags &= ~ToolbarInfo::x
void Toolbars::initFlags(ToolbarInfo & tbinfo)
{
ToolbarSection::ToolbarInfo & info = LyX::ref().session().toolbars().load(tbinfo.name);
unsigned int flags = static_cast<unsigned int>(tbinfo.flags);
// Remove default.ui positions. Only when a valid postion is stored
// in the session file the default.ui value will be overwritten
unsigned int save = flags;
TurnOffFlag(TOP);
TurnOffFlag(BOTTOM);
TurnOffFlag(RIGHT);
TurnOffFlag(LEFT);
bool valid_location = true;
// init tbinfo.flags with saved location
if (info.location == ToolbarSection::ToolbarInfo::TOP)
TurnOnFlag(TOP);
else if (info.location == ToolbarSection::ToolbarInfo::BOTTOM)
TurnOnFlag(BOTTOM);
else if (info.location == ToolbarSection::ToolbarInfo::RIGHT)
TurnOnFlag(RIGHT);
else if (info.location == ToolbarSection::ToolbarInfo::LEFT)
TurnOnFlag(LEFT);
else {
// use setting from default.ui
flags = save;
valid_location = false;
}
// invalid location is for a new toolbar that has no saved information,
// so info.visible is not used for this case.
if (valid_location) {
// init tbinfo.flags with saved visibility,
TurnOffFlag(ON);
TurnOffFlag(OFF);
TurnOffFlag(AUTO);
if (info.state == ToolbarSection::ToolbarInfo::ON)
TurnOnFlag(ON);
else if (info.state == ToolbarSection::ToolbarInfo::OFF)
TurnOnFlag(OFF);
else
TurnOnFlag(AUTO);
}
/*
std::cout << "State " << info.state << " FLAGS: " << flags
<< " ON:" << (flags & ToolbarBackend::ON)
<< " OFF:" << (flags & ToolbarBackend::OFF)
<< " L:" << (flags & ToolbarBackend::LEFT)
<< " R:" << (flags & ToolbarBackend::RIGHT)
<< " T:" << (flags & ToolbarBackend::TOP)
<< " B:" << (flags & ToolbarBackend::BOTTOM)
<< " MA:" << (flags & ToolbarBackend::MATH)
<< " RE:" << (flags & ToolbarBackend::REVIEW)
<< " TB:" << (flags & ToolbarBackend::TABLE)
<< " AU:" << (flags & ToolbarBackend::AUTO)
<< std::endl;
*/
// now set the flags
tbinfo.flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
}
void Toolbars::init()
{
// extracts the toolbars from the backend
ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
ToolbarBackend::Toolbars::iterator end = toolbarbackend.end();
// init flags will also add these toolbars to session if they
// are not already there (e.g. first run of lyx).
for (; cit != end; ++cit)
initFlags(*cit);
// add toolbars according the order in session
ToolbarSection::ToolbarList::const_iterator tb = LyX::ref().session().toolbars().begin();
ToolbarSection::ToolbarList::const_iterator te = LyX::ref().session().toolbars().end();
ToolbarSection::ToolbarInfo::Location last_loc = ToolbarSection::ToolbarInfo::NOTSET;
int last_posx = 0;
int last_posy = 0;
for (; tb != te; ++tb) {
LYXERR(Debug::INIT) << "Adding " << tb->get<0>() << " at position " << tb->get<1>().posx << " " << tb->get<1>().posy << endl;
// add toolbar break if posx or posy changes
bool newline = tb->get<1>().location == last_loc && (
// if two toolbars at the same location, assume uninitialized and add toolbar break
(tb->get<1>().posx == last_posx && tb->get<1>().posy == last_posy) ||
(last_loc == ToolbarSection::ToolbarInfo::TOP && tb->get<1>().posy != last_posy) ||
(last_loc == ToolbarSection::ToolbarInfo::BOTTOM && tb->get<1>().posy != last_posy) ||
(last_loc == ToolbarSection::ToolbarInfo::LEFT && tb->get<1>().posx != last_posx) ||
(last_loc == ToolbarSection::ToolbarInfo::RIGHT && tb->get<1>().posx != last_posx) );
// find the backend item and add
for (cit = toolbarbackend.begin(); cit != end; ++cit)
if (cit->name == tb->get<0>()) {
add(*cit, newline);
last_loc = tb->get<1>().location;
last_posx = tb->get<1>().posx;
last_posy = tb->get<1>().posy;
break;
}
}
}
Toolbar * Toolbars::display(string const & name, bool show)
{
ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
ToolbarBackend::Toolbars::iterator end = toolbarbackend.end();
for (; cit != end; ++cit) {
if (cit->name == name) {
unsigned int flags = cit->flags;
TurnOffFlag(ON);
TurnOffFlag(OFF);
TurnOffFlag(AUTO);
if (show)
TurnOnFlag(ON);
else
TurnOnFlag(OFF);
cit->flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
return displayToolbar(*cit, show);
}
}
LYXERR(Debug::GUI) << "Toolbar::display: no toolbar named "
<< name << endl;
return 0;
}
ToolbarInfo * Toolbars::getToolbarInfo(string const & name)
{
return toolbarbackend.getUsedToolbarInfo(name);
}
void Toolbars::toggleToolbarState(string const & name, bool allowauto)
{
ToolbarInfo * tbi = toolbarbackend.getUsedToolbarInfo(name);
if (!tbi) {
LYXERR(Debug::GUI) << "Toolbar::display: no toolbar named "
<< name << endl;
return;
}
int flags = tbi->flags;
// off -> on
if (flags & ToolbarInfo::OFF) {
TurnOffFlag(OFF);
TurnOnFlag(ON);
// auto -> off
} else if (flags & ToolbarInfo::AUTO) {
TurnOffFlag(AUTO);
TurnOnFlag(OFF);
} else if (allowauto
&& ((flags & ToolbarInfo::MATH)
|| (flags & ToolbarInfo::TABLE)
|| (flags & ToolbarInfo::REVIEW))) {
// for math etc, toggle from on -> auto
TurnOffFlag(ON);
TurnOnFlag(AUTO);
} else {
// for others, toggle from on -> off
TurnOffFlag(ON);
TurnOnFlag(OFF);
}
tbi->flags = static_cast<ToolbarInfo::Flags>(flags);
}
#undef TurnOnFlag
#undef TurnOffFlag
void Toolbars::update(bool in_math, bool in_table, bool review)
{
update();
// extracts the toolbars from the backend
ToolbarBackend::Toolbars::const_iterator cit = toolbarbackend.begin();
ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end();
for (; cit != end; ++cit) {
if (cit->flags & ToolbarInfo::ON)
displayToolbar(*cit, true);
else if (cit->flags & ToolbarInfo::OFF)
displayToolbar(*cit, false);
else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::MATH))
displayToolbar(*cit, in_math);
else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::TABLE))
displayToolbar(*cit, in_table);
else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::REVIEW))
displayToolbar(*cit, review);
}
}
bool Toolbars::visible(string const & name) const
{
std::map<string, ToolbarPtr>::const_iterator it =
toolbars_.find(name);
if (it == toolbars_.end())
return false;
return it->second.get()->isVisible();
}
void Toolbars::saveToolbarInfo()
{
ToolbarSection & tb = LyX::ref().session().toolbars();
for (ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
cit != toolbarbackend.end(); ++cit) {
ToolbarsMap::iterator it = toolbars_.find(cit->name);
BOOST_ASSERT(it != toolbars_.end());
// get toolbar info from session.
ToolbarSection::ToolbarInfo & info = tb.load(cit->name);
if (cit->flags & ToolbarInfo::ON)
info.state = ToolbarSection::ToolbarInfo::ON;
else if (cit->flags & ToolbarInfo::OFF)
info.state = ToolbarSection::ToolbarInfo::OFF;
else if (cit->flags & ToolbarInfo::AUTO)
info.state = ToolbarSection::ToolbarInfo::AUTO;
// save other information
// if auto, frontend should *not* set on/off
it->second->saveInfo(info);
// maybe it is useful to update flags with real status. I do not know
/*
if (!(cit->flags & ToolbarInfo::AUTO)) {
unsigned int flags = static_cast<unsigned int>(cit->flags);
flags &= ~(info.state == ToolbarSection::ToolbarInfo::ON ? ToolbarInfo::OFF : ToolbarInfo::ON);
flags |= (info.state == ToolbarSection::ToolbarInfo::ON ? ToolbarInfo::ON : ToolbarInfo::OFF);
if (info.state == ToolbarSection::ToolbarInfo::ON)
cit->flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
}
*/
}
}
void Toolbars::setLayout(docstring const & layout)
{
if (layout_)
layout_->set(layout);
}
This is one of a series of patches that will merge the layout modules development in personal/branches/rgheck back into the tree. Design goal: Allow the use of layout "modules", which are to LaTeX packages as layout files are to LaTeX document classes. Thus, one could have a module that defined certain character styles, environments, commands, or what have you, and include it in various documents, each of which uses a different document class, without having to modify the layout files themselves. For example, a theorems.module could be used with article.layout to provide support for theorem-type environments, without having to modify article.layout itself, and the same module could be used with book.layout, etc. This first patch does some reworking of the infrastructrue. We need to distinguish between the TextClass that a particular document is using and the layout of that document, since modules, in particular, can modify the layout. The solution adopted here is to add a TextClass pointer to BufferParams, which will hold the layout. The layout itself is then constructed from the TextClass the document is using. At present, this is completely trivial, but that will change when modules are added. The pointer in question is a boost::shared_ptr. This is needed because CutAndPaste saves a copy of the layout with each cut or copied selection. We cannot assume the selection vanishes when the document is closed, so there are two options: (i) keep a list of all the layouts that have ever been used by any document; (ii) used some kind of smart pointer. The latter seems preferable, as the former would waste memory. More importantly, the use of a smart pointer allows modules to be modified on disk and then reloaded while LyX is running, and it will eventually allow the same for layout files. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19756 a592a061-630c-0410-9148-cb99ea01b6c8
2007-08-23 16:41:13 +00:00
bool Toolbars::updateLayoutList(TextClass_ptr textclass)
{
// update the layout display
if (last_textclass_ != textclass) {
if (layout_)
layout_->update();
last_textclass_ = textclass;
return true;
} else
return false;
}
void Toolbars::openLayoutList()
{
if (layout_)
layout_->open();
}
void Toolbars::clearLayoutList()
{
This is one of a series of patches that will merge the layout modules development in personal/branches/rgheck back into the tree. Design goal: Allow the use of layout "modules", which are to LaTeX packages as layout files are to LaTeX document classes. Thus, one could have a module that defined certain character styles, environments, commands, or what have you, and include it in various documents, each of which uses a different document class, without having to modify the layout files themselves. For example, a theorems.module could be used with article.layout to provide support for theorem-type environments, without having to modify article.layout itself, and the same module could be used with book.layout, etc. This first patch does some reworking of the infrastructrue. We need to distinguish between the TextClass that a particular document is using and the layout of that document, since modules, in particular, can modify the layout. The solution adopted here is to add a TextClass pointer to BufferParams, which will hold the layout. The layout itself is then constructed from the TextClass the document is using. At present, this is completely trivial, but that will change when modules are added. The pointer in question is a boost::shared_ptr. This is needed because CutAndPaste saves a copy of the layout with each cut or copied selection. We cannot assume the selection vanishes when the document is closed, so there are two options: (i) keep a list of all the layouts that have ever been used by any document; (ii) used some kind of smart pointer. The latter seems preferable, as the former would waste memory. More importantly, the use of a smart pointer allows modules to be modified on disk and then reloaded while LyX is running, and it will eventually allow the same for layout files. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19756 a592a061-630c-0410-9148-cb99ea01b6c8
2007-08-23 16:41:13 +00:00
last_textclass_ = TextClass_ptr();
if (layout_)
layout_->clear();
}
void Toolbars::add(ToolbarInfo const & tbinfo, bool newline)
{
ToolbarPtr tb_ptr = owner_.makeToolbar(tbinfo, newline);
toolbars_[tbinfo.name] = tb_ptr;
if (tbinfo.flags & ToolbarInfo::ON)
tb_ptr->show(false);
else
tb_ptr->hide(false);
if (tb_ptr->layout())
layout_ = tb_ptr->layout();
}
Toolbar * Toolbars::displayToolbar(ToolbarInfo const & tbinfo,
bool show_it)
{
ToolbarsMap::iterator it = toolbars_.find(tbinfo.name);
BOOST_ASSERT(it != toolbars_.end());
if (show_it)
it->second->show(true);
else
it->second->hide(true);
return it->second.get();
}
void Toolbars::update()
{
ToolbarsMap::const_iterator it = toolbars_.begin();
ToolbarsMap::const_iterator const end = toolbars_.end();
for (; it != end; ++it)
it->second->update();
bool const enable =
lyx::getStatus(FuncRequest(LFUN_LAYOUT)).enabled();
if (layout_)
layout_->setEnabled(enable);
}
void layoutSelected(LyXView & lv, docstring const & name)
{
TextClass const & tc = lv.buffer()->params().getTextClass();
TextClass::const_iterator it = tc.begin();
TextClass::const_iterator const end = tc.end();
for (; it != end; ++it) {
docstring const & itname = (*it)->name();
if (translateIfPossible(itname) == name) {
FuncRequest const func(LFUN_LAYOUT, itname,
FuncRequest::TOOLBAR);
lv.dispatch(func);
return;
}
}
lyxerr << "ERROR (layoutSelected): layout not found!"
<< endl;
}
} // namespace frontend
} // namespace lyx