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"
18 #include "BufferView.h"
21 #include "dispatchresult.h"
24 #include "funcrequest.h"
25 #include "metricsinfo.h"
26 #include "paragraph.h"
28 #include "frontends/font_metrics.h"
29 #include "frontends/Painter.h"
30 #include "frontends/LyXView.h"
33 using lyx::graphics::PreviewLoader;
42 void leaveInset(LCursor & cur, InsetBase const & in)
44 for (unsigned int i = 0; i != cur.size(); ++i) {
45 if (&cur[i].inset() == &in) {
53 InsetCollapsable::InsetCollapsable(BufferParams const & bp,
54 CollapseStatus status)
55 : InsetText(bp), label("Label"), status_(status), openinlined_(false)
57 setAutoBreakRows(true);
59 setFrameColor(LColor::collapsableframe);
60 setInsetName("Collapsable");
65 void InsetCollapsable::write(Buffer const & buf, ostream & os) const
84 void InsetCollapsable::read(Buffer const & buf, LyXLex & lex)
86 bool token_found = false;
89 string const token = lex.getString();
90 if (token == "status") {
92 string const tmp_token = lex.getString();
94 if (tmp_token == "inlined") {
97 } else if (tmp_token == "collapsed") {
100 } else if (tmp_token == "open") {
104 lyxerr << "InsetCollapsable::read: Missing status!"
106 // Take countermeasures
107 lex.pushToken(token);
110 lyxerr << "InsetCollapsable::read: Missing 'status'-tag!"
112 // take countermeasures
113 lex.pushToken(token);
116 InsetText::read(buf, lex);
119 status_ = isOpen() ? Open : Collapsed;
125 void InsetCollapsable::dimension_collapsed(Dimension & dim) const
127 font_metrics::buttonText(label, labelfont_, dim.wid, dim.asc, dim.des);
131 void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const
133 mi.base.textwidth -= 2 * TEXT_TO_INSET_OFFSET;
134 if (status_ == Inlined) {
135 InsetText::metrics(mi, dim);
137 dimension_collapsed(dim);
138 if (status_ == Open) {
139 InsetText::metrics(mi, textdim_);
140 openinlined_ = (textdim_.wid + dim.wid <= mi.base.textwidth);
142 dim.wid += textdim_.wid;
143 dim.des = max(dim.des, textdim_.des);
144 dim.asc = max(dim.asc, textdim_.asc);
146 dim.des += textdim_.height() + TEXT_TO_BOTTOM_OFFSET;
147 dim.wid = max(dim.wid, textdim_.wid);
151 dim.asc += TEXT_TO_INSET_OFFSET;
152 dim.des += TEXT_TO_INSET_OFFSET;
153 dim.wid += 2 * TEXT_TO_INSET_OFFSET;
154 mi.base.textwidth += 2 * TEXT_TO_INSET_OFFSET;
159 void InsetCollapsable::draw_collapsed(PainterInfo & pi, int x, int y) const
161 pi.pain.buttonText(x, y, label, labelfont_);
165 void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const
167 x += TEXT_TO_INSET_OFFSET;
168 y += TEXT_TO_INSET_OFFSET;
170 if (status_ == Inlined) {
171 InsetText::draw(pi, x, y);
174 dimension_collapsed(dimc);
175 int const aa = ascent();
176 button_dim.x1 = x + 0;
177 button_dim.x2 = x + dimc.width();
178 button_dim.y1 = y - aa + pi.base.bv->top_y();
179 button_dim.y2 = y - aa + pi.base.bv->top_y() + dimc.height();
181 draw_collapsed(pi, x, y - aa + dimc.asc);
182 if (status_ == Open) {
184 InsetText::draw(pi, x + dimc.width(),
185 y - aa + textdim_.asc);
187 InsetText::draw(pi, x, dimc.height()
188 + y - aa + textdim_.asc);
191 setPosCache(pi, x, y);
195 InsetOld::EDITABLE InsetCollapsable::editable() const
197 return status_ != Collapsed ? HIGHLY_EDITABLE : IS_EDITABLE;
201 bool InsetCollapsable::descendable() const
203 return status_ != Collapsed;
207 bool InsetCollapsable::hitButton(FuncRequest & cmd) const
209 return button_dim.contains(cmd.x, cmd.y);
213 string const InsetCollapsable::getNewLabel(string const & l) const
216 pos_type const max_length = 15;
217 pos_type const p_siz = paragraphs().begin()->size();
218 pos_type const n = min(max_length, p_siz);
221 for( ; i < n && j < p_siz; ++j) {
222 if (paragraphs().begin()->isInset(j))
224 label += paragraphs().begin()->getChar(j);
227 if (paragraphs().size() > 1 || (i > 0 && j < p_siz)) {
230 return label.empty() ? l : label;
234 void InsetCollapsable::edit(LCursor & cur, bool left)
236 //lyxerr << "InsetCollapsable: edit left/right" << endl;
238 InsetText::edit(cur, left);
243 InsetBase * InsetCollapsable::editXY(LCursor & cur, int x, int y) const
245 cur.push(const_cast<InsetCollapsable&>(*this));
246 //lyxerr << "InsetCollapsable: edit xy" << endl;
247 if (status_ == Collapsed) {
248 return const_cast<InsetCollapsable*>(this);
250 return InsetText::editXY(cur, x, y);
254 void InsetCollapsable::priv_dispatch(LCursor & cur, FuncRequest & cmd)
256 // lyxerr << "InsetCollapsable::priv_dispatch (begin): cmd: " << cmd
257 // << " button y: " << button_dim.y2
258 // << " coll/inline/open: " << status_ << endl;
260 lyxerr << "InsetCollapsable::priv_dispatch (begin): cmd: " << cmd
261 << " cur: " << cur << " bvcur: " << cur.bv().cursor() << endl;
263 switch (cmd.action) {
264 case LFUN_MOUSE_PRESS:
265 if (status_ == Inlined)
266 InsetText::priv_dispatch(cur, cmd);
267 else if (status_ == Open && !hitButton(cmd))
268 InsetText::priv_dispatch(cur, cmd);
273 case LFUN_MOUSE_MOTION:
274 if (status_ == Inlined)
275 InsetText::priv_dispatch(cur, cmd);
276 else if (status_ == Open && !hitButton(cmd))
277 InsetText::priv_dispatch(cur, cmd);
280 case LFUN_MOUSE_RELEASE:
281 if (cmd.button() == mouse_button::button3) {
282 showInsetDialog(&cur.bv());
289 lyxerr << "InsetCollapsable::lfunMouseRelease 1" << endl;
292 cur.bv().cursor() = cur;
296 if (hitButton(cmd)) {
297 lyxerr << "InsetCollapsable::lfunMouseRelease 2" << endl;
298 setStatus(Collapsed);
299 leaveInset(cur, *this);
300 cur.bv().cursor() = cur;
302 lyxerr << "InsetCollapsable::lfunMouseRelease 3" << endl;
303 InsetText::priv_dispatch(cur, cmd);
309 lyxerr << "InsetCollapsable::lfunMouseRelease 4" << endl;
310 InsetText::priv_dispatch(cur, cmd);
315 case LFUN_INSET_TOGGLE:
316 if (cmd.argument == "open")
318 else if (cmd.argument == "close") {
319 setStatus(Collapsed);
320 leaveInset(cur, *this);
321 } else if (cmd.argument == "toggle"
322 || cmd.argument.empty()) {
324 setStatus(Collapsed);
325 leaveInset(cur, *this);
328 } else // if assign or anything else
334 InsetText::priv_dispatch(cur, cmd);
340 int InsetCollapsable::scroll(bool recursive) const
342 int sx = UpdatableInset::scroll(false);
345 sx += InsetText::scroll(false);
351 void InsetCollapsable::open()
353 if (status_ == Collapsed) // ...but not inlined
358 void InsetCollapsable::close()
360 setStatus(Collapsed);
364 void InsetCollapsable::setLabel(string const & l)
370 void InsetCollapsable::setStatus(CollapseStatus st)
377 void InsetCollapsable::setLabelFont(LyXFont & font)
383 void InsetCollapsable::scroll(BufferView & bv, float sx) const
385 UpdatableInset::scroll(bv, sx);
389 void InsetCollapsable::scroll(BufferView & bv, int offset) const
391 UpdatableInset::scroll(bv, offset);
395 Box const & InsetCollapsable::buttonDim() const