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)
60 : UpdatableInset(in), 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));
74 // InsetCollapsable::InsetCollapsable(InsetCollapsable const & in, bool same_id)
75 // : UpdatableInset(in, same_id), collapsed_(in.collapsed_),
76 // framecolor(in.framecolor), labelfont(in.labelfont), inset(in.inset),
77 // button_length(0), button_top_y(0), button_bottom_y(0),
80 // autocollapse(in.autocollapse),
82 // oldWidth(0), in_update(false), first_after_edit(false)
84 // inset.init(&(in.inset), same_id);
85 // inset.setOwner(this);
89 bool InsetCollapsable::insertInset(BufferView * bv, Inset * in)
91 if (!insetAllowed(in->lyxCode())) {
92 lyxerr << "InsetCollapsable::InsertInset: "
93 "Unable to insert inset." << endl;
96 return inset.insertInset(bv, in);
100 void InsetCollapsable::write(Buffer const * buf, ostream & os) const
102 os << "collapsed " << (collapsed_ ? "true" : "false") << "\n";
103 inset.writeParagraphData(buf, os);
107 void InsetCollapsable::read(Buffer const * buf, LyXLex & lex)
111 string const token = lex.getString();
112 if (token == "collapsed") {
114 collapsed_ = lex.getBool();
116 lyxerr << "InsetCollapsable::Read: Missing collapsed!"
118 // Take countermeasures
119 lex.pushToken(token);
122 inset.read(buf, lex);
126 void InsetCollapsable::dimension_collapsed(Dimension & dim) const
128 font_metrics::buttonText(label, labelfont, dim.w, dim.a, dim.d);
129 dim.w += 2 * TEXT_TO_INSET_OFFSET;
133 int InsetCollapsable::height_collapsed() const
136 font_metrics::buttonText(label, labelfont, dim.w, dim.a, dim.d);
137 return dim.a + dim.d;
141 void InsetCollapsable::dimension(BufferView * bv, LyXFont const & font,
142 Dimension & dim) const
144 dimension_collapsed(dim);
148 inset.dimension(bv, font, insetdim);
149 dim.d += insetdim.height() + TEXT_TO_BOTTOM_OFFSET;
150 dim.w = max(dim.w, insetdim.width());
154 void InsetCollapsable::draw_collapsed(Painter & pain,
155 int baseline, float & x) const
157 pain.buttonText(int(x) + TEXT_TO_INSET_OFFSET,
158 baseline, label, labelfont);
160 dimension_collapsed(dim);
165 void InsetCollapsable::draw(BufferView * bv, LyXFont const & f,
166 int baseline, float & x, bool inlined) const
174 Dimension dim_collapsed;
175 dimension_collapsed(dim_collapsed);
177 Painter & pain = bv->painter();
179 button_length = dim_collapsed.width();
180 button_top_y = -ascent(bv, f);
181 button_bottom_y = -ascent(bv, f) + dim_collapsed.height();
184 draw_collapsed(pain, baseline, x);
194 top_baseline = baseline;
196 int const bl = baseline - ascent(bv, f) + dim_collapsed.ascent();
199 inset.draw(bv, f, baseline, x);
201 draw_collapsed(pain, bl, old_x);
202 int const yy = bl + dim_collapsed.descent() + inset.ascent(bv, f);
203 inset.draw(bv, f, yy, x);
204 // contained inset may be shorter than the button
205 if (x < top_x + button_length + TEXT_TO_INSET_OFFSET)
206 x = top_x + button_length + TEXT_TO_INSET_OFFSET;
211 void InsetCollapsable::draw(BufferView * bv, LyXFont const & f,
212 int baseline, float & x) const
214 // by default, we are not inlined-drawing
215 draw(bv, f, baseline, x, false);
219 Inset::EDITABLE InsetCollapsable::editable() const
221 return collapsed_ ? IS_EDITABLE : HIGHLY_EDITABLE;
225 void InsetCollapsable::insetUnlock(BufferView * bv)
229 if (change_label_with_text) {
230 draw_label = get_new_label();
237 inset.insetUnlock(bv);
240 bv->updateInset(this);
244 FuncRequest InsetCollapsable::adjustCommand(FuncRequest const & cmd)
246 LyXFont font(LyXFont::ALL_SANE);
247 FuncRequest cmd1 = cmd;
248 cmd1.y = ascent(cmd.view(), font) + cmd.y -
249 (height_collapsed() + inset.ascent(cmd.view(), font));
254 void InsetCollapsable::lfunMouseRelease(FuncRequest const & cmd)
257 BufferView * bv = cmd.view();
259 if (collapsed_ && cmd.button() != mouse_button::button3) {
261 inset.setUpdateStatus(bv, InsetText::FULL);
262 bv->updateInset(this);
263 bv->buffer()->markDirty();
267 if ((cmd.button() != mouse_button::button3) && (cmd.x < button_length) &&
268 (cmd.y >= button_top_y) && (cmd.y <= button_bottom_y))
272 inset.setUpdateStatus(bv, InsetText::FULL);
273 bv->updateInset(this);
274 bv->buffer()->markDirty();
277 bv->unlockInset(this);
278 bv->updateInset(this);
279 bv->buffer()->markDirty();
281 } else if (!collapsed_ && (cmd.y > button_bottom_y)) {
282 ret = (inset.localDispatch(adjustCommand(cmd)) == DISPATCHED);
284 if (cmd.button() == mouse_button::button3 && !ret)
289 int InsetCollapsable::latex(Buffer const * buf, ostream & os,
290 LatexRunParams const & runparams) const
292 return inset.latex(buf, os, runparams);
296 int InsetCollapsable::ascii(Buffer const * buf, ostream & os, int ll) const
298 return inset.ascii(buf, os, ll);
302 int InsetCollapsable::linuxdoc(Buffer const * buf, ostream & os) const
304 return inset.linuxdoc(buf, os);
308 int InsetCollapsable::docbook(Buffer const * buf, ostream & os, bool mixcont) const
310 return inset.docbook(buf, os, mixcont);
314 void InsetCollapsable::update(BufferView * bv, bool reinit)
317 if (reinit && owner()) {
318 owner()->update(bv, true);
323 inset.update(bv, reinit);
324 if (reinit && owner()) {
325 owner()->update(bv, true);
331 Inset::RESULT InsetCollapsable::localDispatch(FuncRequest const & cmd)
333 //lyxerr << "InsetCollapsable::localDispatch: " << cmd.action << "\n";
334 BufferView * bv = cmd.view();
335 switch (cmd.action) {
336 case LFUN_INSET_EDIT: {
337 if (!cmd.argument.empty()) {
338 UpdatableInset::localDispatch(cmd);
341 if (bv->lockInset(this)) {
342 inset.setUpdateStatus(bv, InsetText::FULL);
343 bv->updateInset(this);
344 bv->buffer()->markDirty();
345 inset.localDispatch(cmd);
346 first_after_edit = true;
349 if (bv->lockInset(this))
350 inset.localDispatch(cmd);
356 #warning Fix this properly in BufferView_pimpl::workAreaButtonRelease
358 if (cmd.button() == mouse_button::button3)
361 UpdatableInset::localDispatch(cmd);
365 // set this only here as it should be recollapsed only if
366 // it was already collapsed!
367 first_after_edit = true;
368 if (!bv->lockInset(this))
370 bv->updateInset(this);
371 bv->buffer()->markDirty();
372 inset.localDispatch(cmd);
374 FuncRequest cmd1 = cmd;
375 if (!bv->lockInset(this))
377 if (cmd.y <= button_bottom_y) {
380 LyXFont font(LyXFont::ALL_SANE);
381 cmd1.y = ascent(bv, font) + cmd.y -
382 (height_collapsed() + inset.ascent(bv, font));
384 inset.localDispatch(cmd);
389 case LFUN_MOUSE_PRESS:
390 if (!collapsed_ && cmd.y > button_bottom_y)
391 inset.localDispatch(adjustCommand(cmd));
394 case LFUN_MOUSE_MOTION:
395 if (!collapsed_ && cmd.y > button_bottom_y)
396 inset.localDispatch(adjustCommand(cmd));
399 case LFUN_MOUSE_RELEASE:
400 lfunMouseRelease(cmd);
404 UpdatableInset::RESULT result = inset.localDispatch(cmd);
405 if (result >= FINISHED)
406 bv->unlockInset(this);
407 first_after_edit = false;
413 bool InsetCollapsable::lockInsetInInset(BufferView * bv, UpdatableInset * in)
417 return inset.lockInsetInInset(bv, in);
421 bool InsetCollapsable::unlockInsetInInset(BufferView * bv, UpdatableInset * in,
425 bv->unlockInset(this);
428 return inset.unlockInsetInInset(bv, in, lr);
432 bool InsetCollapsable::updateInsetInInset(BufferView * bv, Inset *in)
436 return inset.updateInsetInInset(bv, in);
440 int InsetCollapsable::insetInInsetY() const
442 return inset.insetInInsetY() - (top_baseline - inset.y());
446 void InsetCollapsable::validate(LaTeXFeatures & features) const
448 inset.validate(features);
452 void InsetCollapsable::getCursor(BufferView & bv, int & x, int & y) const
454 inset.getCursor(bv, x, y);
458 void InsetCollapsable::getCursorPos(BufferView * bv, int & x, int & y) const
460 inset.getCursorPos(bv, x , y);
464 UpdatableInset * InsetCollapsable::getLockingInset() const
466 UpdatableInset * in = inset.getLockingInset();
467 if (const_cast<InsetText *>(&inset) == in)
468 return const_cast<InsetCollapsable *>(this);
473 UpdatableInset * InsetCollapsable::getFirstLockingInsetOfType(Inset::Code c)
477 return inset.getFirstLockingInsetOfType(c);
481 void InsetCollapsable::setFont(BufferView * bv, LyXFont const & font,
482 bool toggleall, bool selectall)
484 inset.setFont(bv, font, toggleall, selectall);
488 LyXText * InsetCollapsable::getLyXText(BufferView const * bv,
489 bool const recursive) const
491 return inset.getLyXText(bv, recursive);
495 void InsetCollapsable::deleteLyXText(BufferView * bv, bool recursive) const
497 inset.deleteLyXText(bv, recursive);
501 void InsetCollapsable::resizeLyXText(BufferView * bv, bool force) const
503 inset.resizeLyXText(bv, force);
504 LyXFont font(LyXFont::ALL_SANE);
505 oldWidth = width(bv, font);
509 vector<string> const InsetCollapsable::getLabelList() const
511 return inset.getLabelList();
515 bool InsetCollapsable::nodraw() const
517 return inset.nodraw();
521 int InsetCollapsable::scroll(bool recursive) const
523 int sx = UpdatableInset::scroll(false);
526 sx += inset.scroll(recursive);
532 ParagraphList * InsetCollapsable::getParagraphs(int i) const
534 return inset.getParagraphs(i);
538 LyXCursor const & InsetCollapsable::cursor(BufferView * bv) const
540 return inset.cursor(bv);
544 Inset * InsetCollapsable::getInsetFromID(int id_arg) const
547 return const_cast<InsetCollapsable *>(this);
548 return inset.getInsetFromID(id_arg);
552 void InsetCollapsable::open(BufferView * bv)
554 if (!collapsed_) return;
557 bv->updateInset(this);
561 void InsetCollapsable::close(BufferView * bv) const
567 bv->updateInset(const_cast<InsetCollapsable *>(this));
571 void InsetCollapsable::setLabel(string const & l) const
577 void InsetCollapsable::markErased()
583 bool InsetCollapsable::nextChange(BufferView * bv, lyx::pos_type & length)
585 bool found = inset.nextChange(bv, length);
587 if (first_after_edit && !found)
590 first_after_edit = false;
595 bool InsetCollapsable::searchForward(BufferView * bv, string const & str,
598 bool found = inset.searchForward(bv, str, cs, mw);
599 if (first_after_edit && !found)
602 first_after_edit = false;
607 bool InsetCollapsable::searchBackward(BufferView * bv, string const & str,
610 bool found = inset.searchBackward(bv, str, cs, mw);
611 if (first_after_edit && !found)
614 first_after_edit = false;
620 InsetCollapsable::selectNextWordToSpellcheck(BufferView * bv, float & value) const
622 WordLangTuple word = inset.selectNextWordToSpellcheck(bv, value);
623 if (first_after_edit && word.word().empty())
625 first_after_edit = false;
630 void InsetCollapsable::addPreview(grfx::PreviewLoader & loader) const
632 inset.addPreview(loader);
636 void InsetCollapsable::cache(BufferView * bv) const
638 view_ = bv->owner()->view();
642 BufferView * InsetCollapsable::view() const
644 return view_.lock().get();