2 * \file insetcollapsable.C
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alejandro Aguilar Sierra
8 * \author Lars Gullik Bjønnes
10 * Full author contact details are available in file CREDITS
15 #include "insetcollapsable.h"
16 #include "insettext.h"
18 #include "BufferView.h"
20 #include "dimension.h"
25 #include "WordLangTuple.h"
26 #include "funcrequest.h"
29 #include "frontends/font_metrics.h"
30 #include "frontends/Painter.h"
31 #include "frontends/LyXView.h"
33 #include "support/LAssert.h"
34 #include "support/LOstream.h"
42 InsetCollapsable::InsetCollapsable(BufferParams const & bp, bool collapsed)
43 : UpdatableInset(), collapsed_(collapsed), inset(bp),
44 button_length(0), button_top_y(0), button_bottom_y(0),
49 oldWidth(0), in_update(false), first_after_edit(false)
52 inset.setAutoBreakRows(true);
53 inset.setDrawFrame(0, InsetText::ALWAYS);
54 inset.setFrameColor(0, LColor::collapsableframe);
55 setInsetName("Collapsable");
59 InsetCollapsable::InsetCollapsable(InsetCollapsable const & in, bool same_id)
60 : UpdatableInset(in, same_id), collapsed_(in.collapsed_),
61 framecolor(in.framecolor), labelfont(in.labelfont), inset(in.inset),
62 button_length(0), button_top_y(0), button_bottom_y(0),
65 autocollapse(in.autocollapse),
67 oldWidth(0), in_update(false), first_after_edit(false)
69 inset.init(&(in.inset), same_id);
74 bool InsetCollapsable::insertInset(BufferView * bv, Inset * in)
76 if (!insetAllowed(in->lyxCode())) {
77 lyxerr << "InsetCollapsable::InsertInset: "
78 "Unable to insert inset." << endl;
81 return inset.insertInset(bv, in);
85 void InsetCollapsable::write(Buffer const * buf, ostream & os) const
87 os << "collapsed " << (collapsed_ ? "true" : "false") << "\n";
88 inset.writeParagraphData(buf, os);
92 void InsetCollapsable::read(Buffer const * buf, LyXLex & lex)
96 string const token = lex.getString();
97 if (token == "collapsed") {
99 collapsed_ = lex.getBool();
101 lyxerr << "InsetCollapsable::Read: Missing collapsed!"
103 // Take countermeasures
104 lex.pushToken(token);
107 inset.read(buf, lex);
111 void InsetCollapsable::dimension_collapsed(Dimension & dim) const
113 font_metrics::buttonText(label, labelfont, dim.w, dim.a, dim.d);
114 dim.w += 2 * TEXT_TO_INSET_OFFSET;
118 int InsetCollapsable::height_collapsed() const
121 font_metrics::buttonText(label, labelfont, dim.w, dim.a, dim.d);
122 return dim.a + dim.d;
126 void InsetCollapsable::dimension(BufferView * bv, LyXFont const & font,
127 Dimension & dim) const
129 dimension_collapsed(dim);
133 inset.dimension(bv, font, insetdim);
134 dim.d += insetdim.height() + TEXT_TO_BOTTOM_OFFSET;
135 dim.w = max(dim.w, insetdim.width());
139 void InsetCollapsable::draw_collapsed(Painter & pain,
140 int baseline, float & x) const
142 pain.buttonText(int(x) + TEXT_TO_INSET_OFFSET,
143 baseline, label, labelfont);
145 dimension_collapsed(dim);
150 void InsetCollapsable::draw(BufferView * bv, LyXFont const & f,
151 int baseline, float & x, bool inlined) const
159 Dimension dim_collapsed;
160 dimension_collapsed(dim_collapsed);
162 Painter & pain = bv->painter();
164 button_length = dim_collapsed.width();
165 button_top_y = -ascent(bv, f);
166 button_bottom_y = -ascent(bv, f) + dim_collapsed.height();
169 draw_collapsed(pain, baseline, x);
179 top_baseline = baseline;
181 int const bl = baseline - ascent(bv, f) + dim_collapsed.ascent();
184 inset.draw(bv, f, baseline, x);
186 draw_collapsed(pain, bl, old_x);
187 int const yy = bl + dim_collapsed.descent() + inset.ascent(bv, f);
188 inset.draw(bv, f, yy, x);
189 // contained inset may be shorter than the button
190 if (x < top_x + button_length + TEXT_TO_INSET_OFFSET)
191 x = top_x + button_length + TEXT_TO_INSET_OFFSET;
196 void InsetCollapsable::draw(BufferView * bv, LyXFont const & f,
197 int baseline, float & x) const
199 // by default, we are not inlined-drawing
200 draw(bv, f, baseline, x, false);
204 Inset::EDITABLE InsetCollapsable::editable() const
206 return collapsed_ ? IS_EDITABLE : HIGHLY_EDITABLE;
210 void InsetCollapsable::insetUnlock(BufferView * bv)
214 if (change_label_with_text) {
215 draw_label = get_new_label();
222 inset.insetUnlock(bv);
225 bv->updateInset(this);
229 FuncRequest InsetCollapsable::adjustCommand(FuncRequest const & cmd)
231 LyXFont font(LyXFont::ALL_SANE);
232 FuncRequest cmd1 = cmd;
233 cmd1.y = ascent(cmd.view(), font) + cmd.y -
234 (height_collapsed() + inset.ascent(cmd.view(), font));
239 void InsetCollapsable::lfunMouseRelease(FuncRequest const & cmd)
242 BufferView * bv = cmd.view();
244 if (collapsed_ && cmd.button() != mouse_button::button3) {
246 inset.setUpdateStatus(bv, InsetText::FULL);
247 bv->updateInset(this);
248 bv->buffer()->markDirty();
252 if ((cmd.button() != mouse_button::button3) && (cmd.x < button_length) &&
253 (cmd.y >= button_top_y) && (cmd.y <= button_bottom_y))
257 inset.setUpdateStatus(bv, InsetText::FULL);
258 bv->updateInset(this);
259 bv->buffer()->markDirty();
262 bv->unlockInset(this);
263 bv->updateInset(this);
264 bv->buffer()->markDirty();
266 } else if (!collapsed_ && (cmd.y > button_bottom_y)) {
267 ret = (inset.localDispatch(adjustCommand(cmd)) == DISPATCHED);
269 if (cmd.button() == mouse_button::button3 && !ret)
274 int InsetCollapsable::latex(Buffer const * buf, ostream & os,
275 LatexRunParams const & runparams) const
277 return inset.latex(buf, os, runparams);
281 int InsetCollapsable::ascii(Buffer const * buf, ostream & os, int ll) const
283 return inset.ascii(buf, os, ll);
287 int InsetCollapsable::linuxdoc(Buffer const * buf, ostream & os) const
289 return inset.linuxdoc(buf, os);
293 int InsetCollapsable::docbook(Buffer const * buf, ostream & os, bool mixcont) const
295 return inset.docbook(buf, os, mixcont);
299 void InsetCollapsable::update(BufferView * bv, bool reinit)
302 if (reinit && owner()) {
303 owner()->update(bv, true);
308 inset.update(bv, reinit);
309 if (reinit && owner()) {
310 owner()->update(bv, true);
316 Inset::RESULT InsetCollapsable::localDispatch(FuncRequest const & cmd)
318 //lyxerr << "InsetCollapsable::localDispatch: " << cmd.action << "\n";
319 BufferView * bv = cmd.view();
320 switch (cmd.action) {
321 case LFUN_INSET_EDIT: {
322 if (!cmd.argument.empty()) {
323 UpdatableInset::localDispatch(cmd);
326 if (bv->lockInset(this)) {
327 inset.setUpdateStatus(bv, InsetText::FULL);
328 bv->updateInset(this);
329 bv->buffer()->markDirty();
330 inset.localDispatch(cmd);
331 first_after_edit = true;
334 if (bv->lockInset(this))
335 inset.localDispatch(cmd);
341 #warning Fix this properly in BufferView_pimpl::workAreaButtonRelease
343 if (cmd.button() == mouse_button::button3)
346 UpdatableInset::localDispatch(cmd);
350 // set this only here as it should be recollapsed only if
351 // it was already collapsed!
352 first_after_edit = true;
353 if (!bv->lockInset(this))
355 bv->updateInset(this);
356 bv->buffer()->markDirty();
357 inset.localDispatch(cmd);
359 FuncRequest cmd1 = cmd;
360 if (!bv->lockInset(this))
362 if (cmd.y <= button_bottom_y) {
365 LyXFont font(LyXFont::ALL_SANE);
366 cmd1.y = ascent(bv, font) + cmd.y -
367 (height_collapsed() + inset.ascent(bv, font));
369 inset.localDispatch(cmd);
374 case LFUN_MOUSE_PRESS:
375 if (!collapsed_ && cmd.y > button_bottom_y)
376 inset.localDispatch(adjustCommand(cmd));
379 case LFUN_MOUSE_MOTION:
380 if (!collapsed_ && cmd.y > button_bottom_y)
381 inset.localDispatch(adjustCommand(cmd));
384 case LFUN_MOUSE_RELEASE:
385 lfunMouseRelease(cmd);
389 UpdatableInset::RESULT result = inset.localDispatch(cmd);
390 if (result >= FINISHED)
391 bv->unlockInset(this);
392 first_after_edit = false;
398 bool InsetCollapsable::lockInsetInInset(BufferView * bv, UpdatableInset * in)
402 return inset.lockInsetInInset(bv, in);
406 bool InsetCollapsable::unlockInsetInInset(BufferView * bv, UpdatableInset * in,
410 bv->unlockInset(this);
413 return inset.unlockInsetInInset(bv, in, lr);
417 bool InsetCollapsable::updateInsetInInset(BufferView * bv, Inset *in)
421 return inset.updateInsetInInset(bv, in);
425 int InsetCollapsable::insetInInsetY() const
427 return inset.insetInInsetY() - (top_baseline - inset.y());
431 void InsetCollapsable::validate(LaTeXFeatures & features) const
433 inset.validate(features);
437 void InsetCollapsable::getCursor(BufferView & bv, int & x, int & y) const
439 inset.getCursor(bv, x, y);
443 void InsetCollapsable::getCursorPos(BufferView * bv, int & x, int & y) const
445 inset.getCursorPos(bv, x , y);
449 UpdatableInset * InsetCollapsable::getLockingInset() const
451 UpdatableInset * in = inset.getLockingInset();
452 if (const_cast<InsetText *>(&inset) == in)
453 return const_cast<InsetCollapsable *>(this);
458 UpdatableInset * InsetCollapsable::getFirstLockingInsetOfType(Inset::Code c)
462 return inset.getFirstLockingInsetOfType(c);
466 void InsetCollapsable::setFont(BufferView * bv, LyXFont const & font,
467 bool toggleall, bool selectall)
469 inset.setFont(bv, font, toggleall, selectall);
473 LyXText * InsetCollapsable::getLyXText(BufferView const * bv,
474 bool const recursive) const
476 return inset.getLyXText(bv, recursive);
480 void InsetCollapsable::deleteLyXText(BufferView * bv, bool recursive) const
482 inset.deleteLyXText(bv, recursive);
486 void InsetCollapsable::resizeLyXText(BufferView * bv, bool force) const
488 inset.resizeLyXText(bv, force);
489 LyXFont font(LyXFont::ALL_SANE);
490 oldWidth = width(bv, font);
494 vector<string> const InsetCollapsable::getLabelList() const
496 return inset.getLabelList();
500 bool InsetCollapsable::nodraw() const
502 return inset.nodraw();
506 int InsetCollapsable::scroll(bool recursive) const
508 int sx = UpdatableInset::scroll(false);
511 sx += inset.scroll(recursive);
517 ParagraphList * InsetCollapsable::getParagraphs(int i) const
519 return inset.getParagraphs(i);
523 LyXCursor const & InsetCollapsable::cursor(BufferView * bv) const
525 return inset.cursor(bv);
529 Inset * InsetCollapsable::getInsetFromID(int id_arg) const
532 return const_cast<InsetCollapsable *>(this);
533 return inset.getInsetFromID(id_arg);
537 void InsetCollapsable::open(BufferView * bv)
539 if (!collapsed_) return;
542 bv->updateInset(this);
546 void InsetCollapsable::close(BufferView * bv) const
552 bv->updateInset(const_cast<InsetCollapsable *>(this));
556 void InsetCollapsable::setLabel(string const & l) const
562 void InsetCollapsable::markErased()
568 bool InsetCollapsable::nextChange(BufferView * bv, lyx::pos_type & length)
570 bool found = inset.nextChange(bv, length);
572 if (first_after_edit && !found)
575 first_after_edit = false;
580 bool InsetCollapsable::searchForward(BufferView * bv, string const & str,
583 bool found = inset.searchForward(bv, str, cs, mw);
584 if (first_after_edit && !found)
587 first_after_edit = false;
592 bool InsetCollapsable::searchBackward(BufferView * bv, string const & str,
595 bool found = inset.searchBackward(bv, str, cs, mw);
596 if (first_after_edit && !found)
599 first_after_edit = false;
605 InsetCollapsable::selectNextWordToSpellcheck(BufferView * bv, float & value) const
607 WordLangTuple word = inset.selectNextWordToSpellcheck(bv, value);
608 if (first_after_edit && word.word().empty())
610 first_after_edit = false;
615 void InsetCollapsable::addPreview(grfx::PreviewLoader & loader) const
617 inset.addPreview(loader);
621 void InsetCollapsable::cache(BufferView * bv) const
623 view_ = bv->owner()->view();
627 BufferView * InsetCollapsable::view() const
629 return view_.lock().get();