This is quick implementation of a long-standing feature request:
autoopening/closing collapsables. This is really easy with the new scheme
(most of this patch is a replace of status_ -> status())

On a side note, we should keep the following tree bools of
insetcollapsable.h inside a "metrics cache" so they can be different in
different bufferviews (and so one can open an inset in one of them and
close it in another). 

How will these heterogeneous type caches (among different insets) would be
best handled? What comes obviously to mind is a 

static map<BufferView *, something>

in insetcollapsable.C. Or would it be better to have a more general
mechanism somehow/where?

///
mutable CollapseStatus status_;
/// a substatus of the Open status, determined automatically in metrics
mutable bool openinlined_;
/// the inset will automatically open when the cursor is inside
mutable bool autoOpen_;

Opinions?

Alfredo
Index: insetcollapsable.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insetcollapsable.C,v
retrieving revision 1.264
diff -u -p -r1.264 insetcollapsable.C
--- insetcollapsable.C	30 Nov 2004 01:59:47 -0000	1.264
+++ insetcollapsable.C	1 Dec 2004 01:38:52 -0000
@@ -39,6 +39,12 @@ using std::min;
 using std::ostream;
 
 
+InsetCollapsable::CollapseStatus InsetCollapsable::status() const
+{
+	return autoOpen_ ? Open : status_;
+}
+
+
 void leaveInset(LCursor & cur, InsetBase const & in)
 {
 	for (unsigned int i = 0; i != cur.size(); ++i) {
@@ -52,7 +58,8 @@ void leaveInset(LCursor & cur, InsetBase
 
 InsetCollapsable::InsetCollapsable
 		(BufferParams const & bp, CollapseStatus status)
-	: InsetText(bp), label("Label"), status_(status), openinlined_(false)
+	: InsetText(bp), label("Label"), status_(status),
+	  openinlined_(false), autoOpen_(false)
 {
 	setAutoBreakRows(true);
 	setDrawFrame(true);
@@ -132,12 +139,14 @@ Dimension InsetCollapsable::dimensionCol
 
 void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const
 {
+	autoOpen_ = mi.base.bv->cursor().isInside(this);
 	mi.base.textwidth -= 2 * TEXT_TO_INSET_OFFSET;
-	if (status_ == Inlined) {
+
+	if (status() == Inlined) {
 		InsetText::metrics(mi, dim);
 	} else {
 		dim = dimensionCollapsed();
-		if (status_ == Open) {
+		if (status() == Open) {
 			InsetText::metrics(mi, textdim_);
 			openinlined_ = (textdim_.wid + dim.wid <= mi.base.textwidth);
 			if (openinlined_) {
@@ -161,7 +170,7 @@ void InsetCollapsable::metrics(MetricsIn
 void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const
 {
 	const int xx = x + TEXT_TO_INSET_OFFSET;
-	if (status_ == Inlined) {
+	if (status() == Inlined) {
 		InsetText::draw(pi, xx, y);
 	} else {
 		Dimension dimc = dimensionCollapsed();
@@ -172,7 +181,7 @@ void InsetCollapsable::draw(PainterInfo 
 		button_dim.y2 = top + dimc.height();
 
 		pi.pain.buttonText(xx, top + dimc.asc, label, labelfont_);
-		if (status_ == Open) {
+		if (status() == Open) {
 			int textx, texty;
 			if (openinlined_) {
 				textx = xx + dimc.width();
@@ -191,13 +200,13 @@ void InsetCollapsable::draw(PainterInfo 
 void InsetCollapsable::drawSelection(PainterInfo & pi, int x, int y) const
 {
 	x += TEXT_TO_INSET_OFFSET;
-	if (status_ == Open) {
+	if (status() == Open) {
 		if (openinlined_)
 			x += dimensionCollapsed().wid;
 		else
 			y += dimensionCollapsed().des + textdim_.asc;
 	}
-	if (status_ != Collapsed)
+	if (status() != Collapsed)
 		InsetText::drawSelection(pi, x, y);
 }
 
@@ -205,14 +214,10 @@ void InsetCollapsable::drawSelection(Pai
 void InsetCollapsable::getCursorPos
 	(CursorSlice const & sl, int & x, int & y) const
 {
-	if (status_ == Collapsed) {
-		x = xo();
-		y = yo();
-		return;
-	}
+	BOOST_ASSERT(status() != Collapsed);
 	
 	InsetText::getCursorPos(sl, x, y);
-	if (status_ == Open) {
+	if (status() == Open) {
 		if (openinlined_)
 			x += dimensionCollapsed().wid;
 		else
@@ -225,13 +230,13 @@ void InsetCollapsable::getCursorPos
 
 InsetBase::EDITABLE InsetCollapsable::editable() const
 {
-	return status_ != Collapsed ? HIGHLY_EDITABLE : IS_EDITABLE;
+	return status() != Collapsed ? HIGHLY_EDITABLE : IS_EDITABLE;
 }
 
 
 bool InsetCollapsable::descendable() const
 {
-	return status_ != Collapsed;
+	return status() != Collapsed;
 }
 
 
@@ -267,14 +272,14 @@ void InsetCollapsable::edit(LCursor & cu
 	//lyxerr << "InsetCollapsable: edit left/right" << endl;
 	cur.push(*this);
 	InsetText::edit(cur, left);
-	open();
+//	open();
 }
 
 
 InsetBase * InsetCollapsable::editXY(LCursor & cur, int x, int y) const
 {
 	//lyxerr << "InsetCollapsable: edit xy" << endl;
-	if (status_ == Collapsed) {
+	if (status() == Collapsed) {
 		return const_cast<InsetCollapsable*>(this);
 	}
 	cur.push(const_cast<InsetCollapsable&>(*this));
@@ -289,9 +294,9 @@ void InsetCollapsable::doDispatch(LCurso
 
 	switch (cmd.action) {
 	case LFUN_MOUSE_PRESS:
-		if (status_ == Inlined)
+		if (status() == Inlined)
 			InsetText::doDispatch(cur, cmd);
-		else if (status_ == Open && !hitButton(cmd))
+		else if (status() == Open && !hitButton(cmd))
 			InsetText::doDispatch(cur, cmd);
 		else
 			cur.noUpdate();
@@ -300,7 +305,7 @@ void InsetCollapsable::doDispatch(LCurso
 	case LFUN_MOUSE_MOTION:
 		if (status_ == Inlined)
 			InsetText::doDispatch(cur, cmd);
-		else if (status_ == Open && !hitButton(cmd))
+		else if (status() && !hitButton(cmd))
 			InsetText::doDispatch(cur, cmd);
 		else
 			cur.undispatched();
@@ -312,11 +317,12 @@ void InsetCollapsable::doDispatch(LCurso
 			break;
 		}
 
-		switch (status_) {
+		switch (status()) {
 
 		case Collapsed:
 			lyxerr << "InsetCollapsable::lfunMouseRelease 1" << endl;
 			edit(cur, true);
+			open();
 			cur.bv().cursor() = cur;
 			break;
 
Index: insetcollapsable.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insetcollapsable.h,v
retrieving revision 1.179
diff -u -p -r1.179 insetcollapsable.h
--- insetcollapsable.h	30 Nov 2004 01:59:47 -0000	1.179
+++ insetcollapsable.h	1 Dec 2004 01:38:52 -0000
@@ -81,7 +81,7 @@ public:
 	///
 	bool inlined() const { return status_ == Inlined; }
 	///
-	CollapseStatus status() const { return status_; }
+	CollapseStatus status() const;
 	///
 	void open();
 	///
@@ -121,6 +121,8 @@ private:
 	mutable CollapseStatus status_;
 	/// a substatus of the Open status, determined automatically in metrics
 	mutable bool openinlined_;
+	/// the inset will automatically open when the cursor is inside
+	mutable bool autoOpen_;
 	///
 	mutable Dimension textdim_;
 };

Reply via email to