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"
24 #include "WordLangTuple.h"
25 #include "funcrequest.h"
28 #include "frontends/font_metrics.h"
29 #include "frontends/Painter.h"
30 #include "frontends/LyXView.h"
32 #include "support/LAssert.h"
33 #include "support/LOstream.h"
41 InsetCollapsable::InsetCollapsable(BufferParams const & bp, bool collapsed)
42 : UpdatableInset(), collapsed_(collapsed), inset(bp),
43 button_length(0), button_top_y(0), button_bottom_y(0),
48 oldWidth(0), in_update(false), first_after_edit(false)
51 inset.setAutoBreakRows(true);
52 inset.setDrawFrame(0, InsetText::ALWAYS);
53 inset.setFrameColor(0, LColor::collapsableframe);
54 setInsetName("Collapsable");
58 InsetCollapsable::InsetCollapsable(InsetCollapsable const & in, bool same_id)
59 : UpdatableInset(in, same_id), collapsed_(in.collapsed_),
60 framecolor(in.framecolor), labelfont(in.labelfont), inset(in.inset),
61 button_length(0), button_top_y(0), button_bottom_y(0),
64 autocollapse(in.autocollapse),
66 oldWidth(0), in_update(false), first_after_edit(false)
68 inset.init(&(in.inset), same_id);
73 bool InsetCollapsable::insertInset(BufferView * bv, Inset * in)
75 if (!insetAllowed(in->lyxCode())) {
76 lyxerr << "InsetCollapsable::InsertInset: "
77 "Unable to insert inset." << endl;
80 return inset.insertInset(bv, in);
84 void InsetCollapsable::write(Buffer const * buf, ostream & os) const
86 os << "collapsed " << (collapsed_ ? "true" : "false") << "\n";
87 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 int InsetCollapsable::ascent_collapsed() const
116 font_metrics::buttonText(label, labelfont, width, ascent, descent);
121 int InsetCollapsable::descent_collapsed() const
126 font_metrics::buttonText(label, labelfont, width, ascent, descent);
131 //int InsetCollapsable::width_collapsed(Painter & pain) const
132 int InsetCollapsable::width_collapsed() const
137 font_metrics::buttonText(label, labelfont, width, ascent, descent);
138 return width + 2 * TEXT_TO_INSET_OFFSET;
142 int InsetCollapsable::ascent(BufferView * /*bv*/, LyXFont const &) const
144 return ascent_collapsed();
148 int InsetCollapsable::descent(BufferView * bv, LyXFont const & font) const
151 return descent_collapsed();
153 return descent_collapsed()
154 + inset.descent(bv, font)
155 + inset.ascent(bv, font)
156 + TEXT_TO_BOTTOM_OFFSET;
160 int InsetCollapsable::width(BufferView * bv, LyXFont const & font) const
163 return width_collapsed();
165 int const collapsed_width = width_collapsed();
166 int const contents_width = inset.width(bv, font);
168 return max(collapsed_width, contents_width);
172 void InsetCollapsable::draw_collapsed(Painter & pain,
173 int baseline, float & x) const
175 pain.buttonText(int(x) + TEXT_TO_INSET_OFFSET,
176 baseline, label, labelfont);
177 x += width_collapsed();
181 void InsetCollapsable::draw(BufferView * bv, LyXFont const & f,
182 int baseline, float & x, bool inlined) const
190 Painter & pain = bv->painter();
192 button_length = width_collapsed();
193 button_top_y = -ascent(bv, f);
194 button_bottom_y = -ascent(bv, f) + ascent_collapsed() +
198 draw_collapsed(pain, baseline, x);
208 top_baseline = baseline;
210 int const bl = baseline - ascent(bv, f) + ascent_collapsed();
213 inset.draw(bv, f, baseline, x);
215 draw_collapsed(pain, bl, old_x);
216 inset.draw(bv, f, bl + descent_collapsed() + inset.ascent(bv, f), x);
217 // contained inset may be shorter than the button
218 if (x < (top_x + button_length + TEXT_TO_INSET_OFFSET))
219 x = top_x + button_length + TEXT_TO_INSET_OFFSET;
224 void InsetCollapsable::draw(BufferView * bv, LyXFont const & f,
225 int baseline, float & x) const
227 // by default, we are not inlined-drawing
228 draw(bv, f, baseline, x, false);
232 Inset::EDITABLE InsetCollapsable::editable() const
234 return collapsed_ ? IS_EDITABLE : HIGHLY_EDITABLE;
238 void InsetCollapsable::insetUnlock(BufferView * bv)
242 if (change_label_with_text) {
243 draw_label = get_new_label();
250 inset.insetUnlock(bv);
253 bv->updateInset(this);
257 FuncRequest InsetCollapsable::adjustCommand(FuncRequest const & cmd)
259 LyXFont font(LyXFont::ALL_SANE);
260 FuncRequest cmd1 = cmd;
261 cmd1.y = ascent(cmd.view(), font) + cmd.y -
262 (ascent_collapsed() +
263 descent_collapsed() +
264 inset.ascent(cmd.view(), font));
269 void InsetCollapsable::lfunMouseRelease(FuncRequest const & cmd)
272 BufferView * bv = cmd.view();
274 if (collapsed_ && cmd.button() != mouse_button::button3) {
276 inset.setUpdateStatus(bv, InsetText::FULL);
277 bv->updateInset(this);
278 bv->buffer()->markDirty();
282 if ((cmd.button() != mouse_button::button3) && (cmd.x < button_length) &&
283 (cmd.y >= button_top_y) && (cmd.y <= button_bottom_y))
287 inset.setUpdateStatus(bv, InsetText::FULL);
288 bv->updateInset(this);
289 bv->buffer()->markDirty();
292 bv->unlockInset(this);
293 bv->updateInset(this);
294 bv->buffer()->markDirty();
296 } else if (!collapsed_ && (cmd.y > button_bottom_y)) {
297 ret = (inset.localDispatch(adjustCommand(cmd)) == DISPATCHED);
299 if (cmd.button() == mouse_button::button3 && !ret)
304 int InsetCollapsable::latex(Buffer const * buf, ostream & os,
305 bool fragile, bool free_spc) const
307 return inset.latex(buf, os, fragile, free_spc);
311 int InsetCollapsable::ascii(Buffer const * buf, ostream & os, int ll) const
313 return inset.ascii(buf, os, ll);
317 int InsetCollapsable::linuxdoc(Buffer const * buf, ostream & os) const
319 return inset.linuxdoc(buf, os);
323 int InsetCollapsable::docbook(Buffer const * buf, ostream & os, bool mixcont) const
325 return inset.docbook(buf, os, mixcont);
329 void InsetCollapsable::update(BufferView * bv, bool reinit)
332 if (reinit && owner()) {
333 owner()->update(bv, true);
338 inset.update(bv, reinit);
339 if (reinit && owner()) {
340 owner()->update(bv, true);
346 Inset::RESULT InsetCollapsable::localDispatch(FuncRequest const & cmd)
348 //lyxerr << "InsetCollapsable::localDispatch: " << cmd.action << "\n";
349 BufferView * bv = cmd.view();
350 switch (cmd.action) {
351 case LFUN_INSET_EDIT: {
352 if (!cmd.argument.empty()) {
353 UpdatableInset::localDispatch(cmd);
356 if (bv->lockInset(this)) {
357 inset.setUpdateStatus(bv, InsetText::FULL);
358 bv->updateInset(this);
359 bv->buffer()->markDirty();
360 inset.localDispatch(cmd);
361 first_after_edit = true;
364 if (bv->lockInset(this))
365 inset.localDispatch(cmd);
371 #warning Fix this properly in BufferView_pimpl::workAreaButtonRelease
373 if (cmd.button() == mouse_button::button3)
376 UpdatableInset::localDispatch(cmd);
380 // set this only here as it should be recollapsed only if
381 // it was already collapsed!
382 first_after_edit = true;
383 if (!bv->lockInset(this))
385 bv->updateInset(this);
386 bv->buffer()->markDirty();
387 inset.localDispatch(cmd);
389 FuncRequest cmd1 = cmd;
390 if (!bv->lockInset(this))
392 if (cmd.y <= button_bottom_y) {
395 LyXFont font(LyXFont::ALL_SANE);
396 cmd1.y = ascent(bv, font) + cmd.y -
397 (ascent_collapsed() +
398 descent_collapsed() +
399 inset.ascent(bv, font));
401 inset.localDispatch(cmd);
406 case LFUN_MOUSE_PRESS:
407 if (!collapsed_ && cmd.y > button_bottom_y)
408 inset.localDispatch(adjustCommand(cmd));
411 case LFUN_MOUSE_MOTION:
412 if (!collapsed_ && cmd.y > button_bottom_y)
413 inset.localDispatch(adjustCommand(cmd));
416 case LFUN_MOUSE_RELEASE:
417 lfunMouseRelease(cmd);
421 UpdatableInset::RESULT result = inset.localDispatch(cmd);
422 if (result >= FINISHED)
423 bv->unlockInset(this);
424 first_after_edit = false;
430 bool InsetCollapsable::lockInsetInInset(BufferView * bv, UpdatableInset * in)
434 return inset.lockInsetInInset(bv, in);
438 bool InsetCollapsable::unlockInsetInInset(BufferView * bv, UpdatableInset * in,
442 bv->unlockInset(this);
445 return inset.unlockInsetInInset(bv, in, lr);
449 bool InsetCollapsable::updateInsetInInset(BufferView * bv, Inset *in)
453 return inset.updateInsetInInset(bv, in);
457 int InsetCollapsable::insetInInsetY() const
459 return inset.insetInInsetY() - (top_baseline - inset.y());
463 void InsetCollapsable::validate(LaTeXFeatures & features) const
465 inset.validate(features);
469 void InsetCollapsable::getCursor(BufferView & bv, int & x, int & y) const
471 inset.getCursor(bv, x, y);
475 void InsetCollapsable::getCursorPos(BufferView * bv, int & x, int & y) const
477 inset.getCursorPos(bv, x , y);
481 UpdatableInset * InsetCollapsable::getLockingInset() const
483 UpdatableInset * in = inset.getLockingInset();
484 if (const_cast<InsetText *>(&inset) == in)
485 return const_cast<InsetCollapsable *>(this);
490 UpdatableInset * InsetCollapsable::getFirstLockingInsetOfType(Inset::Code c)
494 return inset.getFirstLockingInsetOfType(c);
498 void InsetCollapsable::setFont(BufferView * bv, LyXFont const & font,
499 bool toggleall, bool selectall)
501 inset.setFont(bv, font, toggleall, selectall);
505 LyXText * InsetCollapsable::getLyXText(BufferView const * bv,
506 bool const recursive) const
508 return inset.getLyXText(bv, recursive);
512 void InsetCollapsable::deleteLyXText(BufferView * bv, bool recursive) const
514 inset.deleteLyXText(bv, recursive);
518 void InsetCollapsable::resizeLyXText(BufferView * bv, bool force) const
520 inset.resizeLyXText(bv, force);
521 LyXFont font(LyXFont::ALL_SANE);
522 oldWidth = width(bv, font);
526 vector<string> const InsetCollapsable::getLabelList() const
528 return inset.getLabelList();
532 bool InsetCollapsable::nodraw() const
534 return inset.nodraw();
538 int InsetCollapsable::scroll(bool recursive) const
540 int sx = UpdatableInset::scroll(false);
543 sx += inset.scroll(recursive);
549 ParagraphList * InsetCollapsable::getParagraphs(int i) const
551 return inset.getParagraphs(i);
555 LyXCursor const & InsetCollapsable::cursor(BufferView * bv) const
557 return inset.cursor(bv);
561 Inset * InsetCollapsable::getInsetFromID(int id_arg) const
564 return const_cast<InsetCollapsable *>(this);
565 return inset.getInsetFromID(id_arg);
569 void InsetCollapsable::open(BufferView * bv)
571 if (!collapsed_) return;
574 bv->updateInset(this);
578 void InsetCollapsable::close(BufferView * bv) const
584 bv->updateInset(const_cast<InsetCollapsable *>(this));
588 void InsetCollapsable::setLabel(string const & l) const
594 void InsetCollapsable::markErased()
600 bool InsetCollapsable::nextChange(BufferView * bv, lyx::pos_type & length)
602 bool found = inset.nextChange(bv, length);
604 if (first_after_edit && !found)
607 first_after_edit = false;
612 bool InsetCollapsable::searchForward(BufferView * bv, string const & str,
615 bool found = inset.searchForward(bv, str, cs, mw);
616 if (first_after_edit && !found)
619 first_after_edit = false;
624 bool InsetCollapsable::searchBackward(BufferView * bv, string const & str,
627 bool found = inset.searchBackward(bv, str, cs, mw);
628 if (first_after_edit && !found)
631 first_after_edit = false;
637 InsetCollapsable::selectNextWordToSpellcheck(BufferView * bv, float & value) const
639 WordLangTuple word = inset.selectNextWordToSpellcheck(bv, value);
640 if (first_after_edit && word.word().empty())
642 first_after_edit = false;
647 void InsetCollapsable::addPreview(grfx::PreviewLoader & loader) const
649 inset.addPreview(loader);
653 void InsetCollapsable::cache(BufferView * bv) const
655 view_ = bv->owner()->view();
659 BufferView * InsetCollapsable::view() const
661 return view_.lock().get();