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 getOutOfInset(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);
58 setDrawFrame(InsetText::ALWAYS);
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)
246 //lyxerr << "InsetCollapsable: edit xy" << endl;
247 if (status_ == Collapsed) {
249 // We are not calling editXY() because the row cache of the
250 // inset might be invalid. 'Entering from the left' should be
252 InsetText::edit(cur, true);
255 return InsetText::editXY(cur, x, y);
259 void InsetCollapsable::priv_dispatch(LCursor & cur, FuncRequest & cmd)
261 //lyxerr << "\nInsetCollapsable::priv_dispatch (begin): cmd: " << cmd
262 // << " button y: " << button_dim.y2 << 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);
271 case LFUN_MOUSE_MOTION:
272 if (status_ == Inlined)
273 InsetText::priv_dispatch(cur, cmd);
274 else if (status_ == Open && !hitButton(cmd))
275 InsetText::priv_dispatch(cur, cmd);
278 case LFUN_MOUSE_RELEASE:
279 if (cmd.button() == mouse_button::button3) {
280 showInsetDialog(&cur.bv());
287 lyxerr << "InsetCollapsable::lfunMouseRelease 1" << endl;
293 FuncRequest cmd1 = cmd;
294 if (hitButton(cmd1)) {
295 lyxerr << "InsetCollapsable::lfunMouseRelease 2" << endl;
296 setStatus(Collapsed);
298 cmd = FuncRequest(LFUN_FINISHED_RIGHT);
300 lyxerr << "InsetCollapsable::lfunMouseRelease 3" << endl;
301 InsetText::priv_dispatch(cur, cmd);
307 lyxerr << "InsetCollapsable::lfunMouseRelease 4" << endl;
308 InsetText::priv_dispatch(cur, cmd);
313 case LFUN_INSET_TOGGLE:
314 if (cmd.argument == "open")
316 else if (cmd.argument == "close") {
317 setStatus(Collapsed);
318 getOutOfInset(cur, *this);
319 } else if (cmd.argument == "toggle"
320 || cmd.argument.empty()) {
322 setStatus(Collapsed);
323 getOutOfInset(cur, *this);
331 InsetText::priv_dispatch(cur, cmd);
337 int InsetCollapsable::scroll(bool recursive) const
339 int sx = UpdatableInset::scroll(false);
342 sx += InsetText::scroll(false);
348 void InsetCollapsable::open()
350 if (status_ == Collapsed) // ...but not inlined
355 void InsetCollapsable::close()
357 setStatus(Collapsed);
361 void InsetCollapsable::setLabel(string const & l)
367 void InsetCollapsable::setStatus(CollapseStatus st)
374 void InsetCollapsable::setLabelFont(LyXFont & font)
380 void InsetCollapsable::scroll(BufferView & bv, float sx) const
382 UpdatableInset::scroll(bv, sx);
386 void InsetCollapsable::scroll(BufferView & bv, int offset) const
388 UpdatableInset::scroll(bv, offset);
392 Box const & InsetCollapsable::buttonDim() const