mirror of
https://git.lyx.org/repos/lyx.git
synced 2025-01-03 08:28:25 +00:00
Implement AddToToc for paragraph layouts
Enables table of Theorems & Definitions
This commit is contained in:
parent
d6b1dc4724
commit
68109443f3
@ -3333,11 +3333,11 @@ docstring Paragraph::asString(pos_type beg, pos_type end, int options, const Out
|
|||||||
|
|
||||||
|
|
||||||
void Paragraph::forOutliner(docstring & os, size_t const maxlen,
|
void Paragraph::forOutliner(docstring & os, size_t const maxlen,
|
||||||
bool const shorten) const
|
bool const shorten, bool const label) const
|
||||||
{
|
{
|
||||||
size_t tmplen = shorten ? maxlen + 1 : maxlen;
|
size_t tmplen = shorten ? maxlen + 1 : maxlen;
|
||||||
if (!d->params_.labelString().empty())
|
if (label && !labelString().empty())
|
||||||
os += d->params_.labelString() + ' ';
|
os += labelString() + ' ';
|
||||||
for (pos_type i = 0; i < size() && os.length() < tmplen; ++i) {
|
for (pos_type i = 0; i < size() && os.length() < tmplen; ++i) {
|
||||||
if (isDeleted(i))
|
if (isDeleted(i))
|
||||||
continue;
|
continue;
|
||||||
|
@ -181,8 +181,8 @@ public:
|
|||||||
int options = AS_STR_NONE,
|
int options = AS_STR_NONE,
|
||||||
const OutputParams *runparams = 0) const;
|
const OutputParams *runparams = 0) const;
|
||||||
///
|
///
|
||||||
void forOutliner(docstring &, size_t const maxlen,
|
void forOutliner(docstring &, size_t maxlen, bool shorten = true,
|
||||||
bool const shorten = true) const;
|
bool label = true) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
void write(std::ostream &, BufferParams const &,
|
void write(std::ostream &, BufferParams const &,
|
||||||
|
47
src/Text.cpp
47
src/Text.cpp
@ -240,6 +240,21 @@ bool Text::isFirstInSequence(pit_type par_offset) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pit_type Text::lastInSequence(pit_type pit) const
|
||||||
|
{
|
||||||
|
depth_type const depth = pars_[pit].getDepth();
|
||||||
|
pit_type newpit = pit;
|
||||||
|
|
||||||
|
while (size_t(newpit + 1) < pars_.size() &&
|
||||||
|
(pars_[newpit + 1].getDepth() > depth ||
|
||||||
|
(pars_[newpit + 1].getDepth() == depth &&
|
||||||
|
pars_[newpit + 1].layout() == pars_[pit].layout())))
|
||||||
|
++newpit;
|
||||||
|
|
||||||
|
return newpit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Text::getTocLevel(pit_type par_offset) const
|
int Text::getTocLevel(pit_type par_offset) const
|
||||||
{
|
{
|
||||||
Paragraph const & par = pars_[par_offset];
|
Paragraph const & par = pars_[par_offset];
|
||||||
@ -2042,20 +2057,36 @@ docstring Text::asString(pit_type beg, pit_type end, int options) const
|
|||||||
void Text::shortenForOutliner(docstring & str, size_t const maxlen)
|
void Text::shortenForOutliner(docstring & str, size_t const maxlen)
|
||||||
{
|
{
|
||||||
support::truncateWithEllipsis(str, maxlen);
|
support::truncateWithEllipsis(str, maxlen);
|
||||||
docstring::iterator it = str.begin();
|
for (char_type & c : str)
|
||||||
docstring::iterator end = str.end();
|
if (c == L'\n' || c == L'\t')
|
||||||
for (; it != end; ++it)
|
c = L' ';
|
||||||
if ((*it) == L'\n' || (*it) == L'\t')
|
|
||||||
(*it) = L' ';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Text::forOutliner(docstring & os, size_t const maxlen,
|
void Text::forOutliner(docstring & os, size_t const maxlen,
|
||||||
bool const shorten) const
|
bool const shorten) const
|
||||||
|
{
|
||||||
|
pit_type end = pars_.size() - 1;
|
||||||
|
if (0 <= end && !pars_[0].labelString().empty())
|
||||||
|
os += pars_[0].labelString() + ' ';
|
||||||
|
forOutliner(os, maxlen, 0, end, shorten);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Text::forOutliner(docstring & os, size_t const maxlen,
|
||||||
|
pit_type pit_start, pit_type pit_end,
|
||||||
|
bool const shorten) const
|
||||||
{
|
{
|
||||||
size_t tmplen = shorten ? maxlen + 1 : maxlen;
|
size_t tmplen = shorten ? maxlen + 1 : maxlen;
|
||||||
for (size_t i = 0; i != pars_.size() && os.length() < tmplen; ++i)
|
pit_type end = min(size_t(pit_end), pars_.size() - 1);
|
||||||
pars_[i].forOutliner(os, tmplen, false);
|
bool first = true;
|
||||||
|
for (pit_type i = pit_start; i <= end && os.length() < tmplen; ++i) {
|
||||||
|
if (!first)
|
||||||
|
os += ' ';
|
||||||
|
// This function lets the first label be treated separately
|
||||||
|
pars_[i].forOutliner(os, tmplen, false, !first);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
if (shorten)
|
if (shorten)
|
||||||
shortenForOutliner(os, maxlen);
|
shortenForOutliner(os, maxlen);
|
||||||
}
|
}
|
||||||
|
13
src/Text.h
13
src/Text.h
@ -130,9 +130,13 @@ public:
|
|||||||
|
|
||||||
/// Appends a possibly abbreviated representation of our text to \param os,
|
/// Appends a possibly abbreviated representation of our text to \param os,
|
||||||
/// where \param maxlen defines the maximum size of \param os. If \param
|
/// where \param maxlen defines the maximum size of \param os. If \param
|
||||||
/// shorten is true, then os is shortened as above
|
/// shorten is true, then os is shortened as above.
|
||||||
void forOutliner(docstring & os, size_t const maxlen,
|
void forOutliner(docstring & os, size_t maxlen, bool shorten = true) const;
|
||||||
bool const shorten = true) const;
|
/// Appends a possibly abbreviated representation of our text, from
|
||||||
|
/// start to end, to \param os, where \param maxlen defines the
|
||||||
|
/// maximum size of \param os. Omits the label of the first paragraph.
|
||||||
|
void forOutliner(docstring & os, size_t maxlen, pit_type start, pit_type end,
|
||||||
|
bool shorten = true) const;
|
||||||
|
|
||||||
/// insert a character at cursor position
|
/// insert a character at cursor position
|
||||||
/// FIXME: replace Cursor with DocIterator.
|
/// FIXME: replace Cursor with DocIterator.
|
||||||
@ -329,6 +333,9 @@ public:
|
|||||||
pit_type outerHook(pit_type pit) const;
|
pit_type outerHook(pit_type pit) const;
|
||||||
/// Is it the first par with same depth and layout?
|
/// Is it the first par with same depth and layout?
|
||||||
bool isFirstInSequence(pit_type pit) const;
|
bool isFirstInSequence(pit_type pit) const;
|
||||||
|
/// Return the last paragraph with same depth and layout, or a strictly
|
||||||
|
/// greater depth
|
||||||
|
pit_type lastInSequence(pit_type pit) const;
|
||||||
/// Is this paragraph in the table of contents?
|
/// Is this paragraph in the table of contents?
|
||||||
int getTocLevel(pit_type pit) const;
|
int getTocLevel(pit_type pit) const;
|
||||||
/// Get the font of the "environment" of paragraph \p par_offset in \p pars.
|
/// Get the font of the "environment" of paragraph \p par_offset in \p pars.
|
||||||
|
@ -200,7 +200,7 @@ void TocBuilder::argumentItem(docstring const & arg_str)
|
|||||||
TocItem & item = (*toc_)[stack_.top().pos];
|
TocItem & item = (*toc_)[stack_.top().pos];
|
||||||
docstring const & str = item.str();
|
docstring const & str = item.str();
|
||||||
string const & delim =
|
string const & delim =
|
||||||
str.empty() ? "" : stack_.top().is_captioned ? ", " : ": ";
|
(str.empty() || !stack_.top().is_captioned) ? "" : ", ";
|
||||||
item.str(str + from_ascii(delim) + arg_str);
|
item.str(str + from_ascii(delim) + arg_str);
|
||||||
stack_.top().is_captioned = true;
|
stack_.top().is_captioned = true;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ enum TocType {
|
|||||||
MATH_MACRO,//"math-macro"
|
MATH_MACRO,//"math-macro"
|
||||||
EXTERNAL,//"external"
|
EXTERNAL,//"external"
|
||||||
SENSELESS,//"senseless"
|
SENSELESS,//"senseless"
|
||||||
|
USER_DEFINED,//any value defined in the layouts
|
||||||
TOC_TYPE_COUNT
|
TOC_TYPE_COUNT
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -119,16 +120,16 @@ private:
|
|||||||
class TocBuilder
|
class TocBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TocBuilder(std::shared_ptr<Toc> const toc);
|
TocBuilder(std::shared_ptr<Toc> toc);
|
||||||
/// When entering a float or flex (AddToToc)
|
/// When entering a float or flex or paragraph (with AddToToc)
|
||||||
void pushItem(DocIterator const & dit, docstring const & s,
|
void pushItem(DocIterator const & dit, docstring const & s,
|
||||||
bool output_active, bool is_captioned = false);
|
bool output_active, bool is_captioned = false);
|
||||||
/// When encountering a float caption
|
/// When encountering a float caption
|
||||||
void captionItem(DocIterator const & dit, docstring const & s,
|
void captionItem(DocIterator const & dit, docstring const & s,
|
||||||
bool output_active);
|
bool output_active);
|
||||||
/// When encountering an argument (isTocCaption)
|
/// When encountering an argument (with isTocCaption) for flex or paragraph
|
||||||
void argumentItem(docstring const & arg_str);
|
void argumentItem(docstring const & arg_str);
|
||||||
/// When exiting a float or flex
|
/// When exiting a float or flex or paragraph
|
||||||
void pop();
|
void pop();
|
||||||
private:
|
private:
|
||||||
TocBuilder(){}
|
TocBuilder(){}
|
||||||
|
@ -175,7 +175,8 @@ void InsetFlex::addToToc(DocIterator const & cpit, bool output_active,
|
|||||||
// Cursor inside the inset
|
// Cursor inside the inset
|
||||||
DocIterator pit = cpit;
|
DocIterator pit = cpit;
|
||||||
pit.push_back(CursorSlice(const_cast<InsetFlex &>(*this)));
|
pit.push_back(CursorSlice(const_cast<InsetFlex &>(*this)));
|
||||||
b.pushItem(pit, getLabel(), output_active);
|
docstring const label = getLabel();
|
||||||
|
b.pushItem(pit, label + (label.empty() ? "" : ": "), output_active);
|
||||||
// Proceed with the rest of the inset.
|
// Proceed with the rest of the inset.
|
||||||
InsetCollapsable::addToToc(cpit, output_active, utype);
|
InsetCollapsable::addToToc(cpit, output_active, utype);
|
||||||
if (layout.isTocCaption()) {
|
if (layout.isTocCaption()) {
|
||||||
|
@ -851,13 +851,29 @@ void InsetText::iterateForToc(DocIterator const & cdit, bool output_active,
|
|||||||
// can't hurt too much to do it again
|
// can't hurt too much to do it again
|
||||||
bool const doing_output = output_active && producesOutput();
|
bool const doing_output = output_active && producesOutput();
|
||||||
|
|
||||||
// For each paragraph, traverse its insets and let them add
|
// For each paragraph,
|
||||||
// their toc items
|
// * Add a toc item for the paragraph if it is AddToToc--merging adjacent
|
||||||
|
// paragraphs as needed.
|
||||||
|
// * Traverse its insets and let them add their toc items
|
||||||
|
// * Compute the main table of contents (this is hardcoded)
|
||||||
|
// * Add the list of changes
|
||||||
ParagraphList const & pars = paragraphs();
|
ParagraphList const & pars = paragraphs();
|
||||||
pit_type pend = paragraphs().size();
|
pit_type pend = paragraphs().size();
|
||||||
|
// Record pairs {start,end} of where a toc item was opened for a paragraph
|
||||||
|
// and where it must be closed
|
||||||
|
stack<pair<pit_type, pit_type>> addtotoc_stack;
|
||||||
|
|
||||||
for (pit_type pit = 0; pit != pend; ++pit) {
|
for (pit_type pit = 0; pit != pend; ++pit) {
|
||||||
Paragraph const & par = pars[pit];
|
Paragraph const & par = pars[pit];
|
||||||
dit.pit() = pit;
|
dit.pit() = pit;
|
||||||
|
dit.pos() = 0;
|
||||||
|
|
||||||
|
// Custom AddToToc in paragraph layouts (i.e. theorems)
|
||||||
|
if (par.layout().addToToc() && text().isFirstInSequence(pit)) {
|
||||||
|
pit_type end = openAddToTocForParagraph(pit, dit, output_active);
|
||||||
|
addtotoc_stack.push({pit, end});
|
||||||
|
}
|
||||||
|
|
||||||
// if we find an optarg, we'll save it for use later.
|
// if we find an optarg, we'll save it for use later.
|
||||||
InsetText const * arginset = 0;
|
InsetText const * arginset = 0;
|
||||||
InsetList::const_iterator it = par.insetList().begin();
|
InsetList::const_iterator it = par.insetList().begin();
|
||||||
@ -870,7 +886,16 @@ void InsetText::iterateForToc(DocIterator const & cdit, bool output_active,
|
|||||||
if (inset.lyxCode() == ARG_CODE)
|
if (inset.lyxCode() == ARG_CODE)
|
||||||
arginset = inset.asInsetText();
|
arginset = inset.asInsetText();
|
||||||
}
|
}
|
||||||
// now the toc entry for the paragraph
|
|
||||||
|
// End custom AddToToc in paragraph layouts
|
||||||
|
while (!addtotoc_stack.empty() && addtotoc_stack.top().second == pit) {
|
||||||
|
// execute the closing function
|
||||||
|
closeAddToTocForParagraph(addtotoc_stack.top().first,
|
||||||
|
addtotoc_stack.top().second);
|
||||||
|
addtotoc_stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now the toc entry for the paragraph in the main table of contents
|
||||||
int const toclevel = text().getTocLevel(pit);
|
int const toclevel = text().getTocLevel(pit);
|
||||||
if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) {
|
if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) {
|
||||||
// insert this into the table of contents
|
// insert this into the table of contents
|
||||||
@ -895,6 +920,31 @@ void InsetText::iterateForToc(DocIterator const & cdit, bool output_active,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pit_type InsetText::openAddToTocForParagraph(pit_type pit,
|
||||||
|
DocIterator const & dit,
|
||||||
|
bool output_active) const
|
||||||
|
{
|
||||||
|
Paragraph const & par = paragraphs()[pit];
|
||||||
|
TocBuilder & b = buffer().tocBackend().builder(par.layout().tocType());
|
||||||
|
docstring const label = par.labelString();
|
||||||
|
b.pushItem(dit, label + (label.empty() ? "" : " "), output_active);
|
||||||
|
return text().lastInSequence(pit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InsetText::closeAddToTocForParagraph(pit_type start, pit_type end) const
|
||||||
|
{
|
||||||
|
Paragraph const & par = paragraphs()[start];
|
||||||
|
TocBuilder & b = buffer().tocBackend().builder(par.layout().tocType());
|
||||||
|
if (par.layout().isTocCaption()) {
|
||||||
|
docstring str;
|
||||||
|
text().forOutliner(str, TOC_ENTRY_LENGTH, start, end);
|
||||||
|
b.argumentItem(str);
|
||||||
|
}
|
||||||
|
b.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool InsetText::notifyCursorLeaves(Cursor const & old, Cursor & cur)
|
bool InsetText::notifyCursorLeaves(Cursor const & old, Cursor & cur)
|
||||||
{
|
{
|
||||||
if (buffer().isClean())
|
if (buffer().isClean())
|
||||||
|
@ -223,6 +223,13 @@ protected:
|
|||||||
void iterateForToc(DocIterator const & cdit, bool output_active,
|
void iterateForToc(DocIterator const & cdit, bool output_active,
|
||||||
UpdateType utype) const;
|
UpdateType utype) const;
|
||||||
private:
|
private:
|
||||||
|
/// Open the toc item for paragraph pit. Returns the paragraph index where
|
||||||
|
/// it should end.
|
||||||
|
pit_type openAddToTocForParagraph(pit_type pit,
|
||||||
|
DocIterator const & dit,
|
||||||
|
bool output_active) const;
|
||||||
|
/// Close a toc item opened in start and closed in end
|
||||||
|
void closeAddToTocForParagraph(pit_type start, pit_type end) const;
|
||||||
///
|
///
|
||||||
bool drawFrame_;
|
bool drawFrame_;
|
||||||
///
|
///
|
||||||
|
Loading…
Reference in New Issue
Block a user