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);
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) 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;
259 switch (cmd.action) {
260 case LFUN_MOUSE_PRESS:
261 if (status_ == Inlined)
262 InsetText::priv_dispatch(cur, cmd);
263 else if (status_ == Open && !hitButton(cmd))
264 InsetText::priv_dispatch(cur, cmd);
269 case LFUN_MOUSE_MOTION:
270 if (status_ == Inlined)
271 InsetText::priv_dispatch(cur, cmd);
272 else if (status_ == Open && !hitButton(cmd))
273 InsetText::priv_dispatch(cur, cmd);
276 case LFUN_MOUSE_RELEASE:
277 if (cmd.button() == mouse_button::button3) {
278 showInsetDialog(&cur.bv());
285 lyxerr << "InsetCollapsable::lfunMouseRelease 1" << endl;
288 cur.bv().cursor() = cur;
292 if (hitButton(cmd)) {
293 lyxerr << "InsetCollapsable::lfunMouseRelease 2" << endl;
294 setStatus(Collapsed);
295 leaveInset(cur, *this);
296 cur.bv().cursor() = cur;
298 lyxerr << "InsetCollapsable::lfunMouseRelease 3" << endl;
299 InsetText::priv_dispatch(cur, cmd);
305 lyxerr << "InsetCollapsable::lfunMouseRelease 4" << endl;
306 InsetText::priv_dispatch(cur, cmd);
311 case LFUN_INSET_TOGGLE:
312 if (cmd.argument == "open")
314 else if (cmd.argument == "close") {
315 setStatus(Collapsed);
316 leaveInset(cur, *this);
317 } else if (cmd.argument == "toggle"
318 || cmd.argument.empty()) {
320 setStatus(Collapsed);
321 leaveInset(cur, *this);
324 } else // if assign or anything else
330 InsetText::priv_dispatch(cur, cmd);
336 int InsetCollapsable::scroll(bool recursive) const
338 int sx = UpdatableInset::scroll(false);
341 sx += InsetText::scroll(false);
347 void InsetCollapsable::open()
349 if (status_ == Collapsed) // ...but not inlined
354 void InsetCollapsable::close()
356 setStatus(Collapsed);
360 void InsetCollapsable::setLabel(string const & l)
366 void InsetCollapsable::setStatus(CollapseStatus st)
373 void InsetCollapsable::setLabelFont(LyXFont & font)
379 void InsetCollapsable::scroll(BufferView & bv, float sx) const
381 UpdatableInset::scroll(bv, sx);
385 void InsetCollapsable::scroll(BufferView & bv, int offset) const
387 UpdatableInset::scroll(bv, offset);
391 Box const & InsetCollapsable::buttonDim() const