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"
27 #include "output_docbook.h"
28 #include "output_xhtml.h"
29 #include "TextClass.h"
30 #include "TocBackend.h"
32 #include "support/convert.h"
33 #include "support/debug.h"
34 #include "support/gettext.h"
35 #include "support/lstrings.h"
37 #include "frontends/alert.h"
38 #include "frontends/Application.h"
47 InsetBranch::InsetBranch(Buffer * buf, InsetBranchParams const & params)
48 : InsetCollapsible(buf, InsetText::DefaultLayout), params_(params)
52 void InsetBranch::write(ostream & os) const
57 InsetCollapsible::write(os);
61 void InsetBranch::read(Lexer & lex)
64 InsetCollapsible::read(lex);
68 docstring InsetBranch::toolTip(BufferView const & bv, int, int) const
70 docstring const masterstatus = isBranchSelected() ?
71 _("active") : _("non-active");
72 docstring const childstatus = isBranchSelected(true) ?
73 _("active") : _("non-active");
74 docstring const status = (masterstatus == childstatus) ?
76 support::bformat(_("master %1$s, child %2$s"),
77 masterstatus, childstatus);
79 docstring const masteron = producesOutput() ?
81 docstring const childon =
82 (isBranchSelected(true) != params_.inverted) ?
84 docstring const onoff = (masteron == childon) ?
86 support::bformat(_("master %1$s, child %2$s"),
89 docstring const heading =
90 support::bformat(_("Branch Name: %1$s\nBranch Status: %2$s\nInset Status: %3$s"),
91 params_.branch, status, onoff);
95 return toolTipText(heading + from_ascii("\n"));
99 docstring const InsetBranch::buttonLabel(BufferView const &) const
101 static char_type const tick = 0x2714; // ✔ U+2714 HEAVY CHECK MARK
102 static char_type const cross = 0x2716; // ✖ U+2716 HEAVY MULTIPLICATION X
104 Buffer const & realbuffer = *buffer().masterBuffer();
105 BranchList const & branchlist = realbuffer.params().branchlist();
106 bool const inmaster = branchlist.find(params_.branch);
107 bool const inchild = buffer().params().branchlist().find(params_.branch);
109 bool const master_selected = producesOutput();
110 bool const child_selected = isBranchSelected(true) != params_.inverted;
112 docstring symb = docstring(1, master_selected ? tick : cross);
113 if (inchild && master_selected != child_selected)
114 symb += (child_selected ? tick : cross);
116 docstring inv_symb = from_ascii(params_.inverted ? "~" : "");
118 if (decoration() == InsetDecoration::MINIMALISTIC)
119 return symb + inv_symb + params_.branch;
122 return symb + inv_symb + _("Branch (undefined): ")
125 bool const has_layout =
126 buffer().params().documentClass().hasInsetLayout(layoutName());
128 InsetLayout const & il = getLayout();
129 docstring const & label_string = il.labelstring();
130 if (!label_string.empty())
131 return symb + inv_symb + label_string;
134 if (inmaster && inchild)
136 else if (inchild) // && !inmaster
137 s = _("Branch (child): ");
138 else if (inmaster) // && !inchild
139 s = _("Branch (master): ");
140 else // !inmaster && !inchild
141 s = _("Branch (undefined): ");
142 s += inv_symb + params_.branch;
148 ColorCode InsetBranch::backgroundColor(PainterInfo const & pi) const
150 if (params_.branch.empty())
151 return Inset::backgroundColor(pi);
152 string const branch_id = (buffer().masterParams().branchlist().find(params_.branch))
153 ? convert<string>(buffer().masterParams().branchlist().id())
154 : convert<string>(buffer().params().branchlist().id());
156 string const branchcol = "branch" + branch_id + to_utf8(params_.branch);
157 ColorCode c = lcolor.getFromLyXName(branchcol);
164 void InsetBranch::doDispatch(Cursor & cur, FuncRequest & cmd)
166 switch (cmd.action()) {
167 case LFUN_INSET_MODIFY: {
168 InsetBranchParams params;
169 InsetBranch::string2params(to_utf8(cmd.argument()), params);
171 cur.recordUndoInset(this);
172 params_.branch = params.branch;
173 params_.inverted = params.inverted;
174 // what we really want here is a TOC update, but that means
175 // a full buffer update
176 cur.forceBufferUpdate();
179 case LFUN_BRANCH_ACTIVATE:
180 case LFUN_BRANCH_DEACTIVATE:
181 case LFUN_BRANCH_MASTER_ACTIVATE:
182 case LFUN_BRANCH_MASTER_DEACTIVATE:
183 buffer().branchActivationDispatch(cmd.action(), params_.branch);
185 case LFUN_BRANCH_INVERT:
186 cur.recordUndoInset(this);
187 params_.inverted = !params_.inverted;
188 // what we really want here is a TOC update, but that means
189 // a full buffer update
190 cur.forceBufferUpdate();
192 case LFUN_BRANCH_ADD:
193 lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, params_.branch));
195 case LFUN_BRANCH_SYNC_ALL:
196 lyx::dispatch(FuncRequest(LFUN_INSET_FORALL, "Branch:" + params_.branch + " inset-toggle assign"));
198 case LFUN_INSET_TOGGLE:
199 if (cmd.argument() == "assign")
200 setStatus(cur, (isBranchSelected(true) != params_.inverted) ? Open : Collapsed);
202 InsetCollapsible::doDispatch(cur, cmd);
206 InsetCollapsible::doDispatch(cur, cmd);
212 bool InsetBranch::getStatus(Cursor & cur, FuncRequest const & cmd,
213 FuncStatus & flag) const
215 bool const known_branch =
216 buffer().params().branchlist().find(params_.branch);
218 switch (cmd.action()) {
219 case LFUN_INSET_MODIFY:
220 flag.setEnabled(true);
223 case LFUN_BRANCH_ACTIVATE:
224 case LFUN_BRANCH_DEACTIVATE:
225 case LFUN_BRANCH_MASTER_ACTIVATE:
226 case LFUN_BRANCH_MASTER_DEACTIVATE:
227 flag.setEnabled(buffer().branchActivationEnabled(cmd.action(), params_.branch));
230 case LFUN_BRANCH_INVERT:
231 flag.setEnabled(true);
232 flag.setOnOff(params_.inverted);
235 case LFUN_BRANCH_ADD:
236 flag.setEnabled(!known_branch);
239 case LFUN_BRANCH_SYNC_ALL:
240 flag.setEnabled(known_branch);
243 case LFUN_INSET_TOGGLE:
244 if (cmd.argument() == "assign")
245 flag.setEnabled(true);
247 return InsetCollapsible::getStatus(cur, cmd, flag);
251 return InsetCollapsible::getStatus(cur, cmd, flag);
257 bool InsetBranch::isBranchSelected(bool const child) const
259 Buffer const & realbuffer = child ? buffer() : *buffer().masterBuffer();
260 BranchList const & branchlist = realbuffer.params().branchlist();
261 Branch const * ourBranch = branchlist.find(params_.branch);
264 // this branch is defined in child only
265 ourBranch = buffer().params().branchlist().find(params_.branch);
269 return ourBranch->isSelected();
273 bool InsetBranch::producesOutput() const
275 return isBranchSelected() != params_.inverted;
279 void InsetBranch::latex(otexstream & os, OutputParams const & runparams) const
281 if (producesOutput() || runparams.find_with_non_output()) {
282 OutputParams rp = runparams;
284 InsetText::latex(os, rp);
285 // These need to be passed upstream
286 runparams.need_maketitle = rp.need_maketitle;
287 runparams.have_maketitle = rp.have_maketitle;
292 int InsetBranch::plaintext(odocstringstream & os,
293 OutputParams const & runparams, size_t max_length) const
295 if (!producesOutput() && !runparams.find_with_non_output())
298 int len = InsetText::plaintext(os, runparams, max_length);
303 void InsetBranch::docbook(XMLStream & xs, OutputParams const & runparams) const
305 if (producesOutput()) {
306 OutputParams rp = runparams;
308 rp.par_end = text().paragraphs().size();
309 docbookParagraphs(text(), buffer(), xs, rp);
314 docstring InsetBranch::xhtml(XMLStream & xs, OutputParams const & rp) const
316 if (producesOutput()) {
317 OutputParams newrp = rp;
319 newrp.par_end = text().paragraphs().size();
320 xhtmlParagraphs(text(), buffer(), xs, newrp);
326 void InsetBranch::toString(odocstream & os) const
328 if (producesOutput())
329 InsetCollapsible::toString(os);
333 void InsetBranch::forOutliner(docstring & os, size_t const maxlen,
334 bool const shorten) const
336 if (producesOutput())
337 InsetCollapsible::forOutliner(os, maxlen, shorten);
341 void InsetBranch::validate(LaTeXFeatures & features) const
343 if (producesOutput())
344 InsetCollapsible::validate(features);
348 string InsetBranch::contextMenuName() const
350 return "context-branch";
354 docstring InsetBranch::layoutName() const
356 docstring const name = support::subst(branch(), '_', ' ');
357 return from_ascii("Branch:") + name;
362 bool InsetBranch::isMacroScope() const
364 // Its own scope if not selected by buffer
365 return !producesOutput();
369 string InsetBranch::params2string(InsetBranchParams const & params)
377 void InsetBranch::string2params(string const & in, InsetBranchParams & params)
379 params = InsetBranchParams();
383 istringstream data(in);
386 lex.setContext("InsetBranch::string2params");
391 void InsetBranch::updateBuffer(ParIterator const & it, UpdateType utype, bool const deleted)
393 setLabel(params_.branch + (params_.inverted ? " (-)" : ""));
394 InsetCollapsible::updateBuffer(it, utype, deleted);
398 void InsetBranchParams::write(ostream & os) const
400 os << to_utf8(branch)
407 void InsetBranchParams::read(Lexer & lex)
409 // There may be a space in branch name
410 // if we wanted to use lex>>, the branch name should be properly in quotes
412 branch = lex.getDocString();
413 lex >> "inverted" >> inverted;