mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-22 13:18:28 +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,
|
||||
bool const shorten) const
|
||||
bool const shorten, bool const label) const
|
||||
{
|
||||
size_t tmplen = shorten ? maxlen + 1 : maxlen;
|
||||
if (!d->params_.labelString().empty())
|
||||
os += d->params_.labelString() + ' ';
|
||||
if (label && !labelString().empty())
|
||||
os += labelString() + ' ';
|
||||
for (pos_type i = 0; i < size() && os.length() < tmplen; ++i) {
|
||||
if (isDeleted(i))
|
||||
continue;
|
||||
|
@ -181,8 +181,8 @@ public:
|
||||
int options = AS_STR_NONE,
|
||||
const OutputParams *runparams = 0) const;
|
||||
///
|
||||
void forOutliner(docstring &, size_t const maxlen,
|
||||
bool const shorten = true) const;
|
||||
void forOutliner(docstring &, size_t maxlen, bool shorten = true,
|
||||
bool label = true) const;
|
||||
|
||||
///
|
||||
void write(std::ostream &, BufferParams const &,
|
||||
|
45
src/Text.cpp
45
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
support::truncateWithEllipsis(str, maxlen);
|
||||
docstring::iterator it = str.begin();
|
||||
docstring::iterator end = str.end();
|
||||
for (; it != end; ++it)
|
||||
if ((*it) == L'\n' || (*it) == L'\t')
|
||||
(*it) = L' ';
|
||||
for (char_type & c : str)
|
||||
if (c == L'\n' || c == L'\t')
|
||||
c = L' ';
|
||||
}
|
||||
|
||||
|
||||
void Text::forOutliner(docstring & os, size_t const maxlen,
|
||||
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;
|
||||
for (size_t i = 0; i != pars_.size() && os.length() < tmplen; ++i)
|
||||
pars_[i].forOutliner(os, tmplen, false);
|
||||
pit_type end = min(size_t(pit_end), pars_.size() - 1);
|
||||
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)
|
||||
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,
|
||||
/// where \param maxlen defines the maximum size of \param os. If \param
|
||||
/// shorten is true, then os is shortened as above
|
||||
void forOutliner(docstring & os, size_t const maxlen,
|
||||
bool const shorten = true) const;
|
||||
/// shorten is true, then os is shortened as above.
|
||||
void forOutliner(docstring & os, size_t maxlen, bool 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
|
||||
/// FIXME: replace Cursor with DocIterator.
|
||||
@ -329,6 +333,9 @@ public:
|
||||
pit_type outerHook(pit_type pit) const;
|
||||
/// Is it the first par with same depth and layout?
|
||||
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?
|
||||
int getTocLevel(pit_type pit) const;
|
||||
/// 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];
|
||||
docstring const & str = item.str();
|
||||
string const & delim =
|
||||
str.empty() ? "" : stack_.top().is_captioned ? ", " : ": ";
|
||||
(str.empty() || !stack_.top().is_captioned) ? "" : ", ";
|
||||
item.str(str + from_ascii(delim) + arg_str);
|
||||
stack_.top().is_captioned = true;
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ enum TocType {
|
||||
MATH_MACRO,//"math-macro"
|
||||
EXTERNAL,//"external"
|
||||
SENSELESS,//"senseless"
|
||||
USER_DEFINED,//any value defined in the layouts
|
||||
TOC_TYPE_COUNT
|
||||
}
|
||||
*/
|
||||
@ -119,16 +120,16 @@ private:
|
||||
class TocBuilder
|
||||
{
|
||||
public:
|
||||
TocBuilder(std::shared_ptr<Toc> const toc);
|
||||
/// When entering a float or flex (AddToToc)
|
||||
TocBuilder(std::shared_ptr<Toc> toc);
|
||||
/// When entering a float or flex or paragraph (with AddToToc)
|
||||
void pushItem(DocIterator const & dit, docstring const & s,
|
||||
bool output_active, bool is_captioned = false);
|
||||
/// When encountering a float caption
|
||||
void captionItem(DocIterator const & dit, docstring const & s,
|
||||
bool output_active);
|
||||
/// When encountering an argument (isTocCaption)
|
||||
/// When encountering an argument (with isTocCaption) for flex or paragraph
|
||||
void argumentItem(docstring const & arg_str);
|
||||
/// When exiting a float or flex
|
||||
/// When exiting a float or flex or paragraph
|
||||
void pop();
|
||||
private:
|
||||
TocBuilder(){}
|
||||
|
@ -175,7 +175,8 @@ void InsetFlex::addToToc(DocIterator const & cpit, bool output_active,
|
||||
// Cursor inside the inset
|
||||
DocIterator pit = cpit;
|
||||
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.
|
||||
InsetCollapsable::addToToc(cpit, output_active, utype);
|
||||
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
|
||||
bool const doing_output = output_active && producesOutput();
|
||||
|
||||
// For each paragraph, traverse its insets and let them add
|
||||
// their toc items
|
||||
// For each paragraph,
|
||||
// * 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();
|
||||
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) {
|
||||
Paragraph const & par = pars[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.
|
||||
InsetText const * arginset = 0;
|
||||
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)
|
||||
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);
|
||||
if (toclevel != Layout::NOT_IN_TOC && toclevel >= min_toclevel) {
|
||||
// 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)
|
||||
{
|
||||
if (buffer().isClean())
|
||||
|
@ -223,6 +223,13 @@ protected:
|
||||
void iterateForToc(DocIterator const & cdit, bool output_active,
|
||||
UpdateType utype) const;
|
||||
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_;
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user