Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 2208e44

Browse files
committed
[[ Bug 22121 ]] Implement delete undo for widgets
This patch ensures that when widgets are added to the undo queue when the selected objects are deleted that the undo will rebind the widget correctly. This special case of deleting a widget but leaving it in a state where no data loss will occur if it is replaced with undo is handled by a new method `delforundo`. This method ensures that the widget on the undo queue is in its correct unbound state with an updated rep if the widget was bound. When the undo operation is a replace of a deleted widget then the widget is re-bound. When the undo operation is a delete of a replaced widget then the `delforundo` method is again called.
1 parent 138724e commit 2208e44

File tree

6 files changed

+116
-2
lines changed

6 files changed

+116
-2
lines changed

docs/notes/bugfix-22121.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Fix widgets not rebinding when undo is called after deletion

engine/src/control.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
4444
#include "bitmapeffect.h"
4545
#include "graphicscontext.h"
4646
#include "graphics_util.h"
47+
#include "widget.h"
4748

4849
#include "exec.h"
4950

@@ -631,7 +632,14 @@ void MCControl::undo(Ustruct *us)
631632
}
632633
return;
633634
case UT_REPLACE:
634-
del(true);
635+
if (gettype() == CT_WIDGET)
636+
{
637+
static_cast<MCWidget*>(this)->delforundo(true);
638+
}
639+
else
640+
{
641+
del(true);
642+
}
635643
us->type = UT_DELETE;
636644
return;
637645
default:

engine/src/sellst.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
2929
#include "field.h"
3030
#include "paragraf.h"
3131
#include "image.h"
32+
#include "widget.h"
3233
#include "mcerror.h"
3334
#include "sellst.h"
3435
#include "undolst.h"
@@ -583,8 +584,18 @@ Boolean MCSellist::del()
583584
MCControl *cptr = tptr->m_ref.GetAs<MCControl>();
584585
uint2 num = 0;
585586
cptr->getcard()->count(CT_LAYER, CT_UNDEFINED, cptr, num, True);
587+
588+
bool t_del;
589+
if (cptr->gettype() == CT_WIDGET)
590+
{
591+
t_del = static_cast<MCWidget*>(cptr)->delforundo(true);
592+
}
593+
else
594+
{
595+
t_del = cptr->del(true);
596+
}
586597

587-
if (cptr->del(true))
598+
if (t_del)
588599
{
589600
Ustruct *us = new (nothrow) Ustruct;
590601
us->type = UT_DELETE;

engine/src/widget.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "system.h"
4545
#include "globals.h"
4646
#include "context.h"
47+
#include "undolst.h"
4748

4849
#include "widget-ref.h"
4950
#include "widget-events.h"
@@ -776,6 +777,54 @@ Boolean MCWidget::del(bool p_check_flag)
776777
return True;
777778
}
778779

780+
void MCWidget::undo(Ustruct *us)
781+
{
782+
MCControl::undo(us);
783+
784+
if (us->type == UT_REPLACE)
785+
{
786+
MCAutoValueRef t_rep;
787+
t_rep.Give(m_rep);
788+
m_rep = nullptr;
789+
790+
MCNewAutoNameRef t_kind;
791+
t_kind.Give(m_kind);
792+
m_kind = nullptr;
793+
794+
bind(*t_kind, *t_rep);
795+
}
796+
}
797+
798+
Boolean MCWidget::delforundo(bool p_check_flag)
799+
{
800+
MCAutoValueRef t_rep;
801+
// Make the widget generate a rep.
802+
if (m_rep == nullptr)
803+
{
804+
if (m_widget != nullptr)
805+
{
806+
MCWidgetOnSave(m_widget, &t_rep);
807+
}
808+
809+
if (!t_rep.IsSet())
810+
{
811+
t_rep = kMCNull;
812+
}
813+
}
814+
815+
if (!del(p_check_flag))
816+
{
817+
return false;
818+
}
819+
820+
if (t_rep.IsSet())
821+
{
822+
m_rep = t_rep.Take();
823+
}
824+
return true;
825+
}
826+
827+
779828
void MCWidget::OnOpen()
780829
{
781830
if (m_widget != nil)

engine/src/widget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ class MCWidget: public MCControl, public MCMixinObjectHandle<MCWidget>
195195

196196
virtual Boolean del(bool p_check_flag);
197197

198+
virtual void undo(Ustruct *us);
199+
Boolean delforundo(bool p_check_flag);
200+
198201
virtual void OnOpen();
199202
virtual void OnClose();
200203

tests/lcs/core/engine/widget.livecodescript

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,45 @@ on TestWidgetRetainRep
115115
delete stack "WidgetRetainRepTest"
116116
delete file tPath
117117
end TestWidgetRetainRep
118+
119+
on TestWidgetDeleteUndo
120+
-- ensure the extension is not already loaded
121+
if "com.livecode.lcs_tests.core.widget_save" is \
122+
among the lines of the loadedExtensions then
123+
unload extension "com.livecode.lcs_tests.core.widget_save"
124+
end if
125+
126+
create stack "WidgetDeleteUndo"
127+
set the defaultStack to "WidgetDeleteUndo"
128+
129+
local tWidget
130+
put "com.livecode.lcs_tests.core.widget_save" into tWidget["$kind"]
131+
put uuid() into tWidget["$state"]["info"]
132+
import widget from array tWidget
133+
134+
select widget 1
135+
delete
136+
undo
137+
138+
local tOut
139+
export widget 1 to array tOut
140+
TestAssert "Undo on deleted unbound extension retains rep", tOut["$state"]["info"] is tWidget["$state"]["info"]
141+
142+
select widget 1
143+
delete
144+
145+
TestLoadAuxiliaryExtension "_widget_save"
146+
undo
147+
TestAssert "Undo on deleted unbound extension rebinds and retains rep", the savedInfo of widget 1 is tWidget["$state"]["info"]
148+
149+
select widget 1
150+
delete
151+
undo -- replace
152+
TestAssert "Undo on deleted bound extension rebinds and retains rep", the savedInfo of widget 1 is tWidget["$state"]["info"]
153+
154+
undo -- delete
155+
undo -- replace
156+
TestAssert "Undo delete/replace on deleted bound extension rebinds and retains rep", the savedInfo of widget 1 is tWidget["$state"]["info"]
157+
158+
delete stack "WidgetDeleteUndo"
159+
end TestWidgetDeleteUndo

0 commit comments

Comments
 (0)