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"
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/Lexer.h"
36 #include "support/lstrings.h"
38 #include "frontends/alert.h"
39 #include "frontends/Application.h"
50 InsetBranch::InsetBranch(Buffer * buf, InsetBranchParams const & params)
51 : InsetCollapsible(buf, InsetText::DefaultLayout), params_(params)
55 void InsetBranch::write(ostream & os) const
60 InsetCollapsible::write(os);
64 void InsetBranch::read(Lexer & lex)
67 InsetCollapsible::read(lex);
71 docstring InsetBranch::toolTip(BufferView const & bv, int, int) const
73 docstring const masterstatus = isBranchSelected() ?
74 _("active") : _("non-active");
75 docstring const childstatus = isBranchSelected(true) ?
76 _("active") : _("non-active");
77 docstring const status = (masterstatus == childstatus) ?
79 support::bformat(_("master %1$s, child %2$s"),
80 masterstatus, childstatus);
82 docstring const masteron = producesOutput() ?
84 docstring const childon =
85 (isBranchSelected(true) != params_.inverted) ?
87 docstring const onoff = (masteron == childon) ?
89 support::bformat(_("master %1$s, child %2$s"),
92 docstring const heading =
93 support::bformat(_("Branch Name: %1$s\nBranch Status: %2$s\nInset Status: %3$s"),
94 params_.branch, status, onoff);
98 return toolTipText(heading + from_ascii("\n"));
102 docstring const InsetBranch::buttonLabel(BufferView const &) const
104 static char_type const tick = 0x2714; // ✔ U+2714 HEAVY CHECK MARK
105 static char_type const cross = 0x2716; // ✖ U+2716 HEAVY MULTIPLICATION X
107 Buffer const & realbuffer = *buffer().masterBuffer();
108 BranchList const & branchlist = realbuffer.params().branchlist();
109 bool const inmaster = branchlist.find(params_.branch);
110 bool const inchild = buffer().params().branchlist().find(params_.branch);
112 bool const master_selected = producesOutput();
113 bool const child_selected = isBranchSelected(true) != params_.inverted;
115 docstring symb = docstring(1, master_selected ? tick : cross);
116 if (inchild && master_selected != child_selected)
117 symb += (child_selected ? tick : cross);
119 docstring inv_symb = from_ascii(params_.inverted ? "~" : "");
121 if (decoration() == InsetDecoration::MINIMALISTIC)
122 return symb + inv_symb + params_.branch;
125 return symb + inv_symb + _("Branch (undefined): ")
128 bool const has_layout =
129 buffer().params().documentClass().hasInsetLayout(layoutName());
131 InsetLayout const & il = getLayout();
132 docstring const & label_string = il.labelstring();
133 if (!label_string.empty())
134 return symb + inv_symb + label_string;
137 if (inmaster && inchild)
139 else if (inchild) // && !inmaster
140 s = _("Branch (child): ");
141 else if (inmaster) // && !inchild
142 s = _("Branch (master): ");
143 else // !inmaster && !inchild
144 s = _("Branch (undefined): ");
145 s += inv_symb + params_.branch;
151 ColorCode InsetBranch::backgroundColor(PainterInfo const & pi) const
153 if (params_.branch.empty())
154 return Inset::backgroundColor(pi);
155 string const branch_id = (buffer().masterParams().branchlist().find(params_.branch))
156 ? convert<string>(buffer().masterParams().branchlist().id())
157 : convert<string>(buffer().params().branchlist().id());
159 string const branchcol = "branch" + branch_id + to_utf8(params_.branch);
160 ColorCode c = lcolor.getFromLyXName(branchcol);
167 void InsetBranch::doDispatch(Cursor & cur, FuncRequest & cmd)
169 switch (cmd.action()) {
170 case LFUN_INSET_MODIFY: {
171 InsetBranchParams params;
172 InsetBranch::string2params(to_utf8(cmd.argument()), params);
174 cur.recordUndoInset(this);
175 params_.branch = params.branch;
176 params_.inverted = params.inverted;
177 // what we really want here is a TOC update, but that means
178 // a full buffer update
179 cur.forceBufferUpdate();
182 case LFUN_BRANCH_ACTIVATE:
183 case LFUN_BRANCH_DEACTIVATE:
184 case LFUN_BRANCH_MASTER_ACTIVATE:
185 case LFUN_BRANCH_MASTER_DEACTIVATE:
186 buffer().branchActivationDispatch(cmd.action(), params_.branch);
188 case LFUN_BRANCH_INVERT:
189 cur.recordUndoInset(this);
190 params_.inverted = !params_.inverted;
191 // what we really want here is a TOC update, but that means
192 // a full buffer update
193 cur.forceBufferUpdate();
195 case LFUN_BRANCH_ADD:
196 lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, params_.branch));
198 case LFUN_BRANCH_SYNC_ALL:
199 lyx::dispatch(FuncRequest(LFUN_INSET_FORALL, "Branch:" + params_.branch + " inset-toggle assign"));
201 case LFUN_INSET_TOGGLE:
202 if (cmd.argument() == "assign")
203 setStatus(cur, (isBranchSelected(true) != params_.inverted) ? Open : Collapsed);
205 InsetCollapsible::doDispatch(cur, cmd);
209 InsetCollapsible::doDispatch(cur, cmd);
215 bool InsetBranch::getStatus(Cursor & cur, FuncRequest const & cmd,
216 FuncStatus & flag) const
218 bool const known_branch =
219 buffer().params().branchlist().find(params_.branch);
221 switch (cmd.action()) {
222 case LFUN_INSET_MODIFY:
223 flag.setEnabled(true);
226 case LFUN_BRANCH_ACTIVATE:
227 case LFUN_BRANCH_DEACTIVATE:
228 case LFUN_BRANCH_MASTER_ACTIVATE:
229 case LFUN_BRANCH_MASTER_DEACTIVATE:
230 flag.setEnabled(buffer().branchActivationEnabled(cmd.action(), params_.branch));
233 case LFUN_BRANCH_INVERT:
234 flag.setEnabled(true);
235 flag.setOnOff(params_.inverted);
238 case LFUN_BRANCH_ADD:
239 flag.setEnabled(!known_branch);
242 case LFUN_BRANCH_SYNC_ALL:
243 flag.setEnabled(known_branch);
246 case LFUN_INSET_TOGGLE:
247 if (cmd.argument() == "assign")
248 flag.setEnabled(true);
250 return InsetCollapsible::getStatus(cur, cmd, flag);
254 return InsetCollapsible::getStatus(cur, cmd, flag);
260 bool InsetBranch::isBranchSelected(bool const child) const
262 Buffer const & realbuffer = child ? buffer() : *buffer().masterBuffer();
263 BranchList const & branchlist = realbuffer.params().branchlist();
264 Branch const * ourBranch = branchlist.find(params_.branch);
267 // this branch is defined in child only
268 ourBranch = buffer().params().branchlist().find(params_.branch);
272 return ourBranch->isSelected();
276 bool InsetBranch::producesOutput() const
278 return isBranchSelected() != params_.inverted;
282 void InsetBranch::latex(otexstream & os, OutputParams const & runparams) const
284 if (producesOutput() || runparams.find_with_non_output()) {
285 OutputParams rp = runparams;
287 InsetText::latex(os, rp);
288 // These need to be passed upstream
289 runparams.need_maketitle = rp.need_maketitle;
290 runparams.have_maketitle = rp.have_maketitle;
295 int InsetBranch::plaintext(odocstringstream & os,
296 OutputParams const & runparams, size_t max_length) const
298 if (!producesOutput() && !runparams.find_with_non_output())
301 int len = InsetText::plaintext(os, runparams, max_length);
306 void InsetBranch::docbook(XMLStream & xs, OutputParams const & runparams) const
308 if (producesOutput()) {
309 OutputParams rp = runparams;
311 rp.par_end = text().paragraphs().size();
312 docbookParagraphs(text(), buffer(), xs, rp);
317 docstring InsetBranch::xhtml(XMLStream & xs, OutputParams const & rp) const
319 if (producesOutput()) {
320 OutputParams newrp = rp;
322 newrp.par_end = text().paragraphs().size();
323 xhtmlParagraphs(text(), buffer(), xs, newrp);
329 void InsetBranch::toString(odocstream & os) const
331 if (producesOutput())
332 InsetCollapsible::toString(os);
336 void InsetBranch::forOutliner(docstring & os, size_t const maxlen,
337 bool const shorten) const
339 if (producesOutput())
340 InsetCollapsible::forOutliner(os, maxlen, shorten);
344 void InsetBranch::validate(LaTeXFeatures & features) const
346 // Showing previews in a disabled branch may require stuff
347 if (producesOutput() || features.runparams().for_preview)
348 InsetCollapsible::validate(features);
352 string InsetBranch::contextMenuName() const
354 return "context-branch";
358 docstring InsetBranch::layoutName() const
360 docstring const name = support::subst(branch(), '_', ' ');
361 return from_ascii("Branch:") + name;
366 bool InsetBranch::isMacroScope() const
368 // Its own scope if not selected by buffer
369 return !producesOutput();
373 string InsetBranch::params2string(InsetBranchParams const & params)
381 void InsetBranch::string2params(string const & in, InsetBranchParams & params)
383 params = InsetBranchParams();
387 istringstream data(in);
390 lex.setContext("InsetBranch::string2params");
395 void InsetBranch::updateBuffer(ParIterator const & it, UpdateType utype, bool const deleted)
397 setLabel(params_.branch + (params_.inverted ? " (-)" : ""));
398 InsetCollapsible::updateBuffer(it, utype, deleted);
402 void InsetBranchParams::write(ostream & os) const
404 os << to_utf8(branch)
411 void InsetBranchParams::read(Lexer & lex)
413 // There may be a space in branch name
414 // if we wanted to use lex>>, the branch name should be properly in quotes
416 branch = lex.getDocString();
417 lex >> "inverted" >> inverted;