lyx_mirror/src/insets/InsetBranch.cpp

420 lines
10 KiB
C++
Raw Normal View History

/**
* \file InsetBranch.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Martin Vermeer
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "InsetBranch.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "BufferView.h"
#include "BranchList.h"
#include "ColorSet.h"
Rewrite the label numbering code. * buffer_funcs.cpp (updateLabels): new function taking a buffer and a ParIterator as arguments. This one is used to update labels into an InsetText. Cleanup the code to reset depth. Call setLabel for each paragraph, and then updateLabel on each inset it contains. (setCaptionLabels, setCaptions): removed. (setLabel): use Counters::current_float to make caption paragraphs labels. * insets/Inset.h (updateLabels): new virtual method, empty by default; this numbers the inset itself (if relevant) and then all the paragraphs it may contain. * insets/InsetText.cpp (updateLabels): basically calls lyx::updateLabels from buffer_func.cpp. * insets/InsetCaption.cpp (addToToc): use the label constructed by updateLabels. (computeFullLabel): removed. (metrics, plaintext): don't use computeFullLabel. (updateLabels): new method; set the label from Counters::current_float. * insets/InsetWrap.cpp (updateLabels): * insets/InsetFloat.cpp (updateLabel): new method; sets Counters::current_float to the float type. * insets/InsetBranch.cpp (updateLabels): new method; the numbering is reset afterwards if the branch is inactive. (bug 2671) * insets/InsetNote.cpp (updateLabels): new method; the numbering is reset after the underlying InsetText has been numbered. (bug 2671) * insets/InsetTabular.cpp (updateLabels): new method (also handles longtable) * insets/InsetListings.cpp (updateLabels): new method; mimics what is done for Floats (although Listings are not floats technically) * insets/InsetInclude.cpp (getScreenLabel): in the listings case, use the computed label. (updateLabels): new method; that either renumbers the child document or number the current listing. * LyXFunc.cpp (menuNew): do not updateLabels on empty documents (why do we do that at all?) git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19482 a592a061-630c-0410-9148-cb99ea01b6c8
2007-08-12 21:43:58 +00:00
#include "Counters.h"
#include "Cursor.h"
#include "DispatchResult.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
#include "Lexer.h"
#include "LyX.h"
#include "OutputParams.h"
#include "output_xhtml.h"
#include "TextClass.h"
#include "TocBackend.h"
#include "support/debug.h"
#include "support/gettext.h"
#include "support/lstrings.h"
#include "frontends/alert.h"
#include "frontends/Application.h"
#include <sstream>
using namespace std;
namespace lyx {
InsetBranch::InsetBranch(Buffer * buf, InsetBranchParams const & params)
: InsetCollapsible(buf, InsetText::DefaultLayout), params_(params)
{}
void InsetBranch::write(ostream & os) const
{
os << "Branch ";
params_.write(os);
os << '\n';
InsetCollapsible::write(os);
}
void InsetBranch::read(Lexer & lex)
{
params_.read(lex);
InsetCollapsible::read(lex);
}
docstring InsetBranch::toolTip(BufferView const & bv, int, int) const
{
docstring const masterstatus = isBranchSelected() ?
_("active") : _("non-active");
docstring const childstatus = isBranchSelected(true) ?
_("active") : _("non-active");
docstring const status = (masterstatus == childstatus) ?
masterstatus :
support::bformat(_("master %1$s, child %2$s"),
masterstatus, childstatus);
docstring const masteron = producesOutput() ?
_("on") : _("off");
docstring const childon =
(isBranchSelected(true) != params_.inverted) ?
_("on") : _("off");
docstring const onoff = (masteron == childon) ?
masteron :
support::bformat(_("master %1$s, child %2$s"),
masteron, childon);
2017-07-03 17:53:14 +00:00
docstring const heading =
support::bformat(_("Branch Name: %1$s\nBranch Status: %2$s\nInset Status: %3$s"),
params_.branch, status, onoff);
if (isOpen(bv))
return heading;
return toolTipText(heading + from_ascii("\n"));
}
docstring const InsetBranch::buttonLabel(BufferView const &) const
{
static char_type const tick = 0x2714; // ✔ U+2714 HEAVY CHECK MARK
static char_type const cross = 0x2716; // ✖ U+2716 HEAVY MULTIPLICATION X
Buffer const & realbuffer = *buffer().masterBuffer();
BranchList const & branchlist = realbuffer.params().branchlist();
bool const inmaster = branchlist.find(params_.branch);
bool const inchild = buffer().params().branchlist().find(params_.branch);
bool const master_selected = producesOutput();
bool const child_selected = isBranchSelected(true) != params_.inverted;
docstring symb = docstring(1, master_selected ? tick : cross);
if (inchild && master_selected != child_selected)
symb += (child_selected ? tick : cross);
if (decoration() == InsetLayout::MINIMALISTIC)
return symb + params_.branch;
docstring s;
if (inmaster && inchild)
s = _("Branch: ");
else if (inchild) // && !inmaster
s = _("Branch (child): ");
else if (inmaster) // && !inchild
s = _("Branch (master): ");
else // !inmaster && !inchild
s = _("Branch (undefined): ");
s += params_.branch;
return symb + s;
}
ColorCode InsetBranch::backgroundColor(PainterInfo const & pi) const
{
if (params_.branch.empty())
return Inset::backgroundColor(pi);
// FIXME UNICODE
ColorCode c = lcolor.getFromLyXName(to_utf8(params_.branch));
if (c == Color_none)
c = Color_error;
return c;
}
void InsetBranch::doDispatch(Cursor & cur, FuncRequest & cmd)
{
switch (cmd.action()) {
case LFUN_INSET_MODIFY: {
InsetBranchParams params;
InsetBranch::string2params(to_utf8(cmd.argument()), params);
cur.recordUndoInset(this);
params_.branch = params.branch;
params_.inverted = params.inverted;
// what we really want here is a TOC update, but that means
// a full buffer update
cur.forceBufferUpdate();
break;
}
case LFUN_BRANCH_ACTIVATE:
case LFUN_BRANCH_DEACTIVATE:
case LFUN_BRANCH_MASTER_ACTIVATE:
case LFUN_BRANCH_MASTER_DEACTIVATE: {
bool const master = (cmd.action() == LFUN_BRANCH_MASTER_ACTIVATE
2012-09-30 14:12:52 +00:00
|| cmd.action() == LFUN_BRANCH_MASTER_DEACTIVATE);
Buffer * buf = master ? const_cast<Buffer *>(buffer().masterBuffer())
2012-09-30 14:12:52 +00:00
: &buffer();
Branch * our_branch = buf->params().branchlist().find(params_.branch);
if (!our_branch)
break;
bool const activate = (cmd.action() == LFUN_BRANCH_ACTIVATE
2012-09-30 14:12:52 +00:00
|| cmd.action() == LFUN_BRANCH_MASTER_ACTIVATE);
if (our_branch->isSelected() != activate) {
// FIXME If the branch is in the master document, we cannot
// call recordUndo..., because the master may be hidden, and
// the code presently assumes that hidden documents can never
// be dirty. See GuiView::closeBufferAll(), for example.
// An option would be to check if the master is hidden.
// If it is, unhide.
if (!master)
buffer().undo().recordUndoBufferParams(cur);
else
// at least issue a warning for now (ugly, but better than dataloss).
frontend::Alert::warning(_("Branch state changes in master document"),
lyx::support::bformat(_("The state of the branch '%1$s' "
"was changed in the master file. "
"Please make sure to save the master."), params_.branch), true);
our_branch->setSelected(activate);
// cur.forceBufferUpdate() is not enough
buf->updateBuffer();
}
break;
}
case LFUN_BRANCH_INVERT:
cur.recordUndoInset(this);
params_.inverted = !params_.inverted;
// what we really want here is a TOC update, but that means
// a full buffer update
cur.forceBufferUpdate();
break;
case LFUN_BRANCH_ADD:
lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, params_.branch));
break;
case LFUN_INSET_TOGGLE:
if (cmd.argument() == "assign")
setStatus(cur, isBranchSelected() ? Open : Collapsed);
else
InsetCollapsible::doDispatch(cur, cmd);
break;
default:
InsetCollapsible::doDispatch(cur, cmd);
break;
}
}
bool InsetBranch::getStatus(Cursor & cur, FuncRequest const & cmd,
FuncStatus & flag) const
{
bool const known_branch =
buffer().params().branchlist().find(params_.branch);
switch (cmd.action()) {
case LFUN_INSET_MODIFY:
flag.setEnabled(true);
break;
case LFUN_BRANCH_ACTIVATE:
flag.setEnabled(known_branch && !isBranchSelected(true));
break;
case LFUN_BRANCH_INVERT:
flag.setEnabled(true);
flag.setOnOff(params_.inverted);
break;
case LFUN_BRANCH_ADD:
flag.setEnabled(!known_branch);
break;
case LFUN_BRANCH_DEACTIVATE:
flag.setEnabled(isBranchSelected(true));
break;
case LFUN_BRANCH_MASTER_ACTIVATE:
flag.setEnabled(buffer().parent()
&& buffer().masterBuffer()->params().branchlist().find(params_.branch)
&& !isBranchSelected());
break;
case LFUN_BRANCH_MASTER_DEACTIVATE:
flag.setEnabled(buffer().parent() && isBranchSelected());
break;
case LFUN_INSET_TOGGLE:
if (cmd.argument() == "assign")
flag.setEnabled(true);
else
return InsetCollapsible::getStatus(cur, cmd, flag);
break;
default:
return InsetCollapsible::getStatus(cur, cmd, flag);
}
return true;
}
bool InsetBranch::isBranchSelected(bool const child) const
{
Buffer const & realbuffer = child ? buffer() : *buffer().masterBuffer();
BranchList const & branchlist = realbuffer.params().branchlist();
Branch const * ourBranch = branchlist.find(params_.branch);
if (!ourBranch) {
// this branch is defined in child only
ourBranch = buffer().params().branchlist().find(params_.branch);
if (!ourBranch)
return false;
}
return ourBranch->isSelected();
}
bool InsetBranch::producesOutput() const
{
return isBranchSelected() != params_.inverted;
}
void InsetBranch::latex(otexstream & os, OutputParams const & runparams) const
{
if (producesOutput()) {
OutputParams rp = runparams;
rp.inbranch = true;
InsetText::latex(os, rp);
// These need to be passed upstream
runparams.need_maketitle = rp.need_maketitle;
runparams.have_maketitle = rp.have_maketitle;
}
}
int InsetBranch::plaintext(odocstringstream & os,
OutputParams const & runparams, size_t max_length) const
{
if (!producesOutput())
return 0;
int len = InsetText::plaintext(os, runparams, max_length);
return len;
}
int InsetBranch::docbook(odocstream & os,
OutputParams const & runparams) const
{
return producesOutput() ? InsetText::docbook(os, runparams) : 0;
}
docstring InsetBranch::xhtml(XHTMLStream & xs, OutputParams const & rp) const
{
if (producesOutput()) {
OutputParams newrp = rp;
newrp.par_begin = 0;
newrp.par_end = text().paragraphs().size();
xhtmlParagraphs(text(), buffer(), xs, newrp);
}
return docstring();
}
void InsetBranch::toString(odocstream & os) const
{
if (producesOutput())
InsetCollapsible::toString(os);
}
void InsetBranch::forOutliner(docstring & os, size_t const maxlen,
bool const shorten) const
{
if (producesOutput())
InsetCollapsible::forOutliner(os, maxlen, shorten);
}
void InsetBranch::validate(LaTeXFeatures & features) const
{
if (producesOutput())
InsetCollapsible::validate(features);
}
string InsetBranch::contextMenuName() const
{
return "context-branch";
}
2017-07-03 17:53:14 +00:00
bool InsetBranch::isMacroScope() const
{
// Its own scope if not selected by buffer
return !producesOutput();
}
string InsetBranch::params2string(InsetBranchParams const & params)
{
ostringstream data;
params.write(data);
return data.str();
}
void InsetBranch::string2params(string const & in, InsetBranchParams & params)
{
params = InsetBranchParams();
if (in.empty())
return;
istringstream data(in);
Lexer lex;
lex.setStream(data);
lex.setContext("InsetBranch::string2params");
params.read(lex);
}
void InsetBranch::updateBuffer(ParIterator const & it, UpdateType utype)
{
setLabel(params_.branch + (params_.inverted ? " (-)" : ""));
InsetCollapsible::updateBuffer(it, utype);
}
void InsetBranchParams::write(ostream & os) const
{
2017-07-03 17:53:14 +00:00
os << to_utf8(branch)
<< '\n'
<< "inverted "
<< inverted;
}
void InsetBranchParams::read(Lexer & lex)
{
// There may be a space in branch name
// if we wanted to use lex>>, the branch name should be properly in quotes
lex.eatLine();
branch = lex.getDocString();
lex >> "inverted" >> inverted;
}
} // namespace lyx