2 * \file InsetBranch.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Martin Vermeer
8 * Full author contact details are available in file CREDITS.
13 #include "InsetBranch.h"
16 #include "BufferParams.h"
17 #include "BufferView.h"
18 #include "BranchList.h"
21 #include "DispatchResult.h"
22 #include "FuncRequest.h"
23 #include "FuncStatus.h"
25 #include "LaTeXFeatures.h"
28 #include "output_docbook.h"
29 #include "output_xhtml.h"
30 #include "TextClass.h"
31 #include "TocBackend.h"
33 #include "support/convert.h"
34 #include "support/debug.h"
35 #include "support/gettext.h"
36 #include "support/lstrings.h"
38 #include "frontends/alert.h"
39 #include "frontends/Application.h"
48 InsetBranch::InsetBranch(Buffer * buf, InsetBranchParams const & params)
49 : InsetCollapsible(buf, InsetText::DefaultLayout), params_(params)
53 void InsetBranch::write(ostream & os) const
58 InsetCollapsible::write(os);
62 void InsetBranch::read(Lexer & lex)
65 InsetCollapsible::read(lex);
69 docstring InsetBranch::toolTip(BufferView const & bv, int, int) const
71 docstring const masterstatus = isBranchSelected() ?
72 _("active") : _("non-active");
73 docstring const childstatus = isBranchSelected(true) ?
74 _("active") : _("non-active");
75 docstring const status = (masterstatus == childstatus) ?
77 support::bformat(_("master %1$s, child %2$s"),
78 masterstatus, childstatus);
80 docstring const masteron = producesOutput() ?
82 docstring const childon =
83 (isBranchSelected(true) != params_.inverted) ?
85 docstring const onoff = (masteron == childon) ?
87 support::bformat(_("master %1$s, child %2$s"),
90 docstring const heading =
91 support::bformat(_("Branch Name: %1$s\nBranch Status: %2$s\nInset Status: %3$s"),
92 params_.branch, status, onoff);
96 return toolTipText(heading + from_ascii("\n"));
100 docstring const InsetBranch::buttonLabel(BufferView const &) const
102 static char_type const tick = 0x2714; // ✔ U+2714 HEAVY CHECK MARK
103 static char_type const cross = 0x2716; // ✖ U+2716 HEAVY MULTIPLICATION X
105 Buffer const & realbuffer = *buffer().masterBuffer();
106 BranchList const & branchlist = realbuffer.params().branchlist();
107 bool const inmaster = branchlist.find(params_.branch);
108 bool const inchild = buffer().params().branchlist().find(params_.branch);
110 bool const master_selected = producesOutput();
111 bool const child_selected = isBranchSelected(true) != params_.inverted;
113 docstring symb = docstring(1, master_selected ? tick : cross);
114 if (inchild && master_selected != child_selected)
115 symb += (child_selected ? tick : cross);
117 docstring inv_symb = from_ascii(params_.inverted ? "~" : "");
119 if (decoration() == InsetDecoration::MINIMALISTIC)
120 return symb + inv_symb + params_.branch;
123 return symb + inv_symb + _("Branch (undefined): ")
126 bool const has_layout =
127 buffer().params().documentClass().hasInsetLayout(layoutName());
129 InsetLayout const & il = getLayout();
130 docstring const & label_string = il.labelstring();
131 if (!label_string.empty())
132 return symb + inv_symb + label_string;
135 if (inmaster && inchild)
137 else if (inchild) // && !inmaster
138 s = _("Branch (child): ");
139 else if (inmaster) // && !inchild
140 s = _("Branch (master): ");
141 else // !inmaster && !inchild
142 s = _("Branch (undefined): ");
143 s += inv_symb + params_.branch;
149 ColorCode InsetBranch::backgroundColor(PainterInfo const & pi) const
151 if (params_.branch.empty())
152 return Inset::backgroundColor(pi);
153 string const branch_id = (buffer().masterParams().branchlist().find(params_.branch))
154 ? convert<string>(buffer().masterParams().branchlist().id())
155 : convert<string>(buffer().params().branchlist().id());
157 string const branchcol = "branch" + branch_id + to_utf8(params_.branch);
158 ColorCode c = lcolor.getFromLyXName(branchcol);
165 void InsetBranch::doDispatch(Cursor & cur, FuncRequest & cmd)
167 switch (cmd.action()) {
168 case LFUN_INSET_MODIFY: {
169 InsetBranchParams params;
170 InsetBranch::string2params(to_utf8(cmd.argument()), params);
172 cur.recordUndoInset(this);
173 params_.branch = params.branch;
174 params_.inverted = params.inverted;
175 // what we really want here is a TOC update, but that means
176 // a full buffer update
177 cur.forceBufferUpdate();
180 case LFUN_BRANCH_ACTIVATE:
181 case LFUN_BRANCH_DEACTIVATE:
182 case LFUN_BRANCH_MASTER_ACTIVATE:
183 case LFUN_BRANCH_MASTER_DEACTIVATE:
184 buffer().branchActivationDispatch(cmd.action(), params_.branch);
186 case LFUN_BRANCH_INVERT:
187 cur.recordUndoInset(this);
188 params_.inverted = !params_.inverted;
189 // what we really want here is a TOC update, but that means
190 // a full buffer update
191 cur.forceBufferUpdate();
193 case LFUN_BRANCH_ADD:
194 lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, params_.branch));
196 case LFUN_BRANCH_SYNC_ALL:
197 lyx::dispatch(FuncRequest(LFUN_INSET_FORALL, "Branch:" + params_.branch + " inset-toggle assign"));
199 case LFUN_INSET_TOGGLE:
200 if (cmd.argument() == "assign")
201 setStatus(cur, (isBranchSelected(true) != params_.inverted) ? Open : Collapsed);
203 InsetCollapsible::doDispatch(cur, cmd);
207 InsetCollapsible::doDispatch(cur, cmd);
213 bool InsetBranch::getStatus(Cursor & cur, FuncRequest const & cmd,
214 FuncStatus & flag) const
216 bool const known_branch =
217 buffer().params().branchlist().find(params_.branch);
219 switch (cmd.action()) {
220 case LFUN_INSET_MODIFY:
221 flag.setEnabled(true);
224 case LFUN_BRANCH_ACTIVATE:
225 case LFUN_BRANCH_DEACTIVATE:
226 case LFUN_BRANCH_MASTER_ACTIVATE:
227 case LFUN_BRANCH_MASTER_DEACTIVATE:
228 flag.setEnabled(buffer().branchActivationEnabled(cmd.action(), params_.branch));
231 case LFUN_BRANCH_INVERT:
232 flag.setEnabled(true);
233 flag.setOnOff(params_.inverted);
236 case LFUN_BRANCH_ADD:
237 flag.setEnabled(!known_branch);
240 case LFUN_BRANCH_SYNC_ALL:
241 flag.setEnabled(known_branch);
244 case LFUN_INSET_TOGGLE:
245 if (cmd.argument() == "assign")
246 flag.setEnabled(true);
248 return InsetCollapsible::getStatus(cur, cmd, flag);
252 return InsetCollapsible::getStatus(cur, cmd, flag);
258 bool InsetBranch::isBranchSelected(bool const child) const
260 Buffer const & realbuffer = child ? buffer() : *buffer().masterBuffer();
261 BranchList const & branchlist = realbuffer.params().branchlist();
262 Branch const * ourBranch = branchlist.find(params_.branch);
265 // this branch is defined in child only
266 ourBranch = buffer().params().branchlist().find(params_.branch);
270 return ourBranch->isSelected();
274 bool InsetBranch::producesOutput() const
276 return isBranchSelected() != params_.inverted;
280 void InsetBranch::latex(otexstream & os, OutputParams const & runparams) const
282 if (producesOutput() || runparams.find_with_non_output()) {
283 OutputParams rp = runparams;
285 InsetText::latex(os, rp);
286 // These need to be passed upstream
287 runparams.need_maketitle = rp.need_maketitle;
288 runparams.have_maketitle = rp.have_maketitle;
293 int InsetBranch::plaintext(odocstringstream & os,
294 OutputParams const & runparams, size_t max_length) const
296 if (!producesOutput() && !runparams.find_with_non_output())
299 int len = InsetText::plaintext(os, runparams, max_length);
304 void InsetBranch::docbook(XMLStream & xs, OutputParams const & runparams) const
306 if (producesOutput()) {
307 OutputParams rp = runparams;
309 rp.par_end = text().paragraphs().size();
310 docbookParagraphs(text(), buffer(), xs, rp);
315 docstring InsetBranch::xhtml(XMLStream & xs, OutputParams const & rp) const
317 if (producesOutput()) {
318 OutputParams newrp = rp;
320 newrp.par_end = text().paragraphs().size();
321 xhtmlParagraphs(text(), buffer(), xs, newrp);
327 void InsetBranch::toString(odocstream & os) const
329 if (producesOutput())
330 InsetCollapsible::toString(os);
334 void InsetBranch::forOutliner(docstring & os, size_t const maxlen,
335 bool const shorten) const
337 if (producesOutput())
338 InsetCollapsible::forOutliner(os, maxlen, shorten);
342 void InsetBranch::validate(LaTeXFeatures & features) const
344 // Showing previews in a disabled branch may require stuff
345 if (producesOutput() || features.runparams().for_preview)
346 InsetCollapsible::validate(features);
350 string InsetBranch::contextMenuName() const
352 return "context-branch";
356 docstring InsetBranch::layoutName() const
358 docstring const name = support::subst(branch(), '_', ' ');
359 return from_ascii("Branch:") + name;
364 bool InsetBranch::isMacroScope() const
366 // Its own scope if not selected by buffer
367 return !producesOutput();
371 string InsetBranch::params2string(InsetBranchParams const & params)
379 void InsetBranch::string2params(string const & in, InsetBranchParams & params)
381 params = InsetBranchParams();
385 istringstream data(in);
388 lex.setContext("InsetBranch::string2params");
393 void InsetBranch::updateBuffer(ParIterator const & it, UpdateType utype, bool const deleted)
395 setLabel(params_.branch + (params_.inverted ? " (-)" : ""));
396 InsetCollapsible::updateBuffer(it, utype, deleted);
400 void InsetBranchParams::write(ostream & os) const
402 os << to_utf8(branch)
409 void InsetBranchParams::read(Lexer & lex)
411 // There may be a space in branch name
412 // if we wanted to use lex>>, the branch name should be properly in quotes
414 branch = lex.getDocString();
415 lex >> "inverted" >> inverted;