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,
278 return inset.latex(buf, os, runparams, free_spc);
282 int InsetCollapsable::ascii(Buffer const * buf, ostream & os, int ll) const
284 return inset.ascii(buf, os, ll);
288 int InsetCollapsable::linuxdoc(Buffer const * buf, ostream & os) const
290 return inset.linuxdoc(buf, os);
294 int InsetCollapsable::docbook(Buffer const * buf, ostream & os, bool mixcont) const
296 return inset.docbook(buf, os, mixcont);
300 void InsetCollapsable::update(BufferView * bv, bool reinit)
303 if (reinit && owner()) {
304 owner()->update(bv, true);
309 inset.update(bv, reinit);
310 if (reinit && owner()) {
311 owner()->update(bv, true);
317 Inset::RESULT InsetCollapsable::localDispatch(FuncRequest const & cmd)
319 //lyxerr << "InsetCollapsable::localDispatch: " << cmd.action << "\n";
320 BufferView * bv = cmd.view();
321 switch (cmd.action) {
322 case LFUN_INSET_EDIT: {
323 if (!cmd.argument.empty()) {
324 UpdatableInset::localDispatch(cmd);
327 if (bv->lockInset(this)) {
328 inset.setUpdateStatus(bv, InsetText::FULL);
329 bv->updateInset(this);
330 bv->buffer()->markDirty();
331 inset.localDispatch(cmd);
332 first_after_edit = true;
335 if (bv->lockInset(this))
336 inset.localDispatch(cmd);
342 #warning Fix this properly in BufferView_pimpl::workAreaButtonRelease
344 if (cmd.button() == mouse_button::button3)
347 UpdatableInset::localDispatch(cmd);
351 // set this only here as it should be recollapsed only if
352 // it was already collapsed!
353 first_after_edit = true;
354 if (!bv->lockInset(this))
356 bv->updateInset(this);
357 bv->buffer()->markDirty();
358 inset.localDispatch(cmd);
360 FuncRequest cmd1 = cmd;
361 if (!bv->lockInset(this))
363 if (cmd.y <= button_bottom_y) {
366 LyXFont font(LyXFont::ALL_SANE);
367 cmd1.y = ascent(bv, font) + cmd.y -
368 (height_collapsed() + inset.ascent(bv, font));
370 inset.localDispatch(cmd);
375 case LFUN_MOUSE_PRESS:
376 if (!collapsed_ && cmd.y > button_bottom_y)
377 inset.localDispatch(adjustCommand(cmd));
380 case LFUN_MOUSE_MOTION:
381 if (!collapsed_ && cmd.y > button_bottom_y)
382 inset.localDispatch(adjustCommand(cmd));
385 case LFUN_MOUSE_RELEASE:
386 lfunMouseRelease(cmd);
390 UpdatableInset::RESULT result = inset.localDispatch(cmd);
391 if (result >= FINISHED)
392 bv->unlockInset(this);
393 first_after_edit = false;
399 bool InsetCollapsable::lockInsetInInset(BufferView * bv, UpdatableInset * in)
403 return inset.lockInsetInInset(bv, in);
407 bool InsetCollapsable::unlockInsetInInset(BufferView * bv, UpdatableInset * in,
411 bv->unlockInset(this);
414 return inset.unlockInsetInInset(bv, in, lr);
418 bool InsetCollapsable::updateInsetInInset(BufferView * bv, Inset *in)
422 return inset.updateInsetInInset(bv, in);
426 int InsetCollapsable::insetInInsetY() const
428 return inset.insetInInsetY() - (top_baseline - inset.y());
432 void InsetCollapsable::validate(LaTeXFeatures & features) const
434 inset.validate(features);
438 void InsetCollapsable::getCursor(BufferView & bv, int & x, int & y) const
440 inset.getCursor(bv, x, y);
444 void InsetCollapsable::getCursorPos(BufferView * bv, int & x, int & y) const
446 inset.getCursorPos(bv, x , y);
450 UpdatableInset * InsetCollapsable::getLockingInset() const
452 UpdatableInset * in = inset.getLockingInset();
453 if (const_cast<InsetText *>(&inset) == in)
454 return const_cast<InsetCollapsable *>(this);
459 UpdatableInset * InsetCollapsable::getFirstLockingInsetOfType(Inset::Code c)
463 return inset.getFirstLockingInsetOfType(c);
467 void InsetCollapsable::setFont(BufferView * bv, LyXFont const & font,
468 bool toggleall, bool selectall)
470 inset.setFont(bv, font, toggleall, selectall);
474 LyXText * InsetCollapsable::getLyXText(BufferView const * bv,
475 bool const recursive) const
477 return inset.getLyXText(bv, recursive);
481 void InsetCollapsable::deleteLyXText(BufferView * bv, bool recursive) const
483 inset.deleteLyXText(bv, recursive);
487 void InsetCollapsable::resizeLyXText(BufferView * bv, bool force) const
489 inset.resizeLyXText(bv, force);
490 LyXFont font(LyXFont::ALL_SANE);
491 oldWidth = width(bv, font);
495 vector<string> const InsetCollapsable::getLabelList() const
497 return inset.getLabelList();
501 bool InsetCollapsable::nodraw() const
503 return inset.nodraw();
507 int InsetCollapsable::scroll(bool recursive) const
509 int sx = UpdatableInset::scroll(false);
512 sx += inset.scroll(recursive);
518 ParagraphList * InsetCollapsable::getParagraphs(int i) const
520 return inset.getParagraphs(i);
524 LyXCursor const & InsetCollapsable::cursor(BufferView * bv) const
526 return inset.cursor(bv);
530 Inset * InsetCollapsable::getInsetFromID(int id_arg) const
533 return const_cast<InsetCollapsable *>(this);
534 return inset.getInsetFromID(id_arg);
538 void InsetCollapsable::open(BufferView * bv)
540 if (!collapsed_) return;
543 bv->updateInset(this);
547 void InsetCollapsable::close(BufferView * bv) const
553 bv->updateInset(const_cast<InsetCollapsable *>(this));
557 void InsetCollapsable::setLabel(string const & l) const
563 void InsetCollapsable::markErased()
569 bool InsetCollapsable::nextChange(BufferView * bv, lyx::pos_type & length)
571 bool found = inset.nextChange(bv, length);
573 if (first_after_edit && !found)
576 first_after_edit = false;
581 bool InsetCollapsable::searchForward(BufferView * bv, string const & str,
584 bool found = inset.searchForward(bv, str, cs, mw);
585 if (first_after_edit && !found)
588 first_after_edit = false;
593 bool InsetCollapsable::searchBackward(BufferView * bv, string const & str,
596 bool found = inset.searchBackward(bv, str, cs, mw);
597 if (first_after_edit && !found)
600 first_after_edit = false;
606 InsetCollapsable::selectNextWordToSpellcheck(BufferView * bv, float & value) const
608 WordLangTuple word = inset.selectNextWordToSpellcheck(bv, value);
609 if (first_after_edit && word.word().empty())
611 first_after_edit = false;
616 void InsetCollapsable::addPreview(grfx::PreviewLoader & loader) const
618 inset.addPreview(loader);
622 void InsetCollapsable::cache(BufferView * bv) const
624 view_ = bv->owner()->view();
628 BufferView * InsetCollapsable::view() const
630 return view_.lock().get();