platform-ui-home/R3_1/undo-redo-proposal/undo-redo support.html
Parent Directory
|
Revision Log
Revision 1.1 -
(download)
(as text)
(annotate)
Tue Nov 9 17:20:03 2004 UTC (5 years ago) by nick
Branch: MAIN
Tue Nov 9 17:20:03 2004 UTC (5 years ago) by nick
Branch: MAIN
Added Susan's undo/redo proposal
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"> <head> <meta http-equiv=Content-Type content="text/html; charset=windows-1252"> <meta name=ProgId content=Word.Document> <meta name=Generator content="Microsoft Word 10"> <meta name=Originator content="Microsoft Word 10"> <link rel=File-List href="undo-redo%20support_files/filelist.xml"> <title>Undo/redo support in Eclipse</title> <!--[if gte mso 9]><xml> <o:DocumentProperties> <o:Author>IBM_USER</o:Author> <o:LastAuthor>IBM_USER</o:LastAuthor> <o:Revision>2</o:Revision> <o:TotalTime>4244</o:TotalTime> <o:LastPrinted>2004-11-08T17:14:00Z</o:LastPrinted> <o:Created>2004-11-09T00:31:00Z</o:Created> <o:LastSaved>2004-11-09T00:31:00Z</o:LastSaved> <o:Pages>1</o:Pages> <o:Words>6200</o:Words> <o:Characters>35342</o:Characters> <o:Company>IBM</o:Company> <o:Lines>294</o:Lines> <o:Paragraphs>82</o:Paragraphs> <o:CharactersWithSpaces>41460</o:CharactersWithSpaces> <o:Version>10.6626</o:Version> </o:DocumentProperties> </xml><![endif]--><!--[if gte mso 9]><xml> <w:WordDocument> <w:SpellingState>Clean</w:SpellingState> <w:GrammarState>Clean</w:GrammarState> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--> <style> <!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} h1 {mso-style-next:Normal; margin-top:12.0pt; margin-right:0in; margin-bottom:3.0pt; margin-left:0in; mso-pagination:widow-orphan; page-break-after:avoid; mso-outline-level:1; font-size:16.0pt; font-family:Arial; mso-font-kerning:16.0pt;} h2 {mso-style-next:Normal; margin-top:12.0pt; margin-right:0in; margin-bottom:3.0pt; margin-left:0in; mso-pagination:widow-orphan; page-break-after:avoid; mso-outline-level:2; font-size:14.0pt; font-family:Arial; font-style:italic;} h3 {mso-style-next:Normal; margin-top:12.0pt; margin-right:0in; margin-bottom:3.0pt; margin-left:0in; mso-pagination:widow-orphan; page-break-after:avoid; mso-outline-level:3; font-size:13.0pt; font-family:Arial;} h4 {mso-style-next:Normal; margin-top:12.0pt; margin-right:0in; margin-bottom:3.0pt; margin-left:0in; mso-pagination:widow-orphan; page-break-after:avoid; mso-outline-level:4; font-size:14.0pt; font-family:"Times New Roman";} h5 {mso-style-next:Normal; margin-top:12.0pt; margin-right:0in; margin-bottom:3.0pt; margin-left:0in; mso-pagination:widow-orphan; mso-outline-level:5; font-size:13.0pt; font-family:"Times New Roman"; font-style:italic;} p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText {mso-style-noshow:yes; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} span.MsoFootnoteReference {mso-style-noshow:yes; vertical-align:super;} p.MsoBodyText2, li.MsoBodyText2, div.MsoBodyText2 {margin-top:0in; margin-right:0in; margin-bottom:6.0pt; margin-left:0in; line-height:200%; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} span.SpellE {mso-style-name:""; mso-spl-e:yes;} span.GramE {mso-style-name:""; mso-gram-e:yes;} @page Section1 {size:8.5in 11.0in; margin:1.0in .75in .5in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:-132; mso-list-type:simple; mso-list-template-ids:-446383164;} @list l0:level1 {mso-level-tab-stop:1.25in; mso-level-number-position:left; margin-left:1.25in; text-indent:-.25in;} @list l1 {mso-list-id:-131; mso-list-type:simple; mso-list-template-ids:1534092348;} @list l1:level1 {mso-level-tab-stop:1.0in; mso-level-number-position:left; margin-left:1.0in; text-indent:-.25in;} @list l2 {mso-list-id:-130; mso-list-type:simple; mso-list-template-ids:710070486;} @list l2:level1 {mso-level-tab-stop:.75in; mso-level-number-position:left; margin-left:.75in; text-indent:-.25in;} @list l3 {mso-list-id:-129; mso-list-type:simple; mso-list-template-ids:682940366;} @list l3:level1 {mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in;} @list l4 {mso-list-id:-128; mso-list-type:simple; mso-list-template-ids:949130314;} @list l4:level1 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:1.25in; mso-level-number-position:left; margin-left:1.25in; text-indent:-.25in; font-family:Symbol;} @list l5 {mso-list-id:-127; mso-list-type:simple; mso-list-template-ids:-1842289842;} @list l5:level1 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:1.0in; mso-level-number-position:left; margin-left:1.0in; text-indent:-.25in; font-family:Symbol;} @list l6 {mso-list-id:-126; mso-list-type:simple; mso-list-template-ids:819084850;} @list l6:level1 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:.75in; mso-level-number-position:left; margin-left:.75in; text-indent:-.25in; font-family:Symbol;} @list l7 {mso-list-id:-125; mso-list-type:simple; mso-list-template-ids:-676417338;} @list l7:level1 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Symbol;} @list l8 {mso-list-id:-120; mso-list-type:simple; mso-list-template-ids:1291634668;} @list l8:level1 {mso-level-tab-stop:.25in; mso-level-number-position:left; margin-left:.25in; text-indent:-.25in;} @list l9 {mso-list-id:-119; mso-list-type:simple; mso-list-template-ids:964484384;} @list l9:level1 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:.25in; mso-level-number-position:left; margin-left:.25in; text-indent:-.25in; font-family:Symbol;} @list l10 {mso-list-id:172575666; mso-list-type:hybrid; mso-list-template-ids:1725869360 67698703 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l10:level1 {mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in;} @list l10:level2 {mso-level-number-format:bullet; mso-level-text:o; mso-level-tab-stop:1.0in; mso-level-number-position:left; text-indent:-.25in; font-family:"Courier New";} @list l10:level3 {mso-level-number-format:bullet; mso-level-text:\F0A7; mso-level-tab-stop:1.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Wingdings;} @list l10:level4 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:2.0in; mso-level-number-position:left; text-indent:-.25in; font-family:Symbol;} @list l11 {mso-list-id:190000114; mso-list-type:hybrid; mso-list-template-ids:1560301118 423934604 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l11:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Arial; mso-fareast-font-family:"Times New Roman";} @list l12 {mso-list-id:215170042; mso-list-type:hybrid; mso-list-template-ids:1511950680 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l12:level1 {mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in;} @list l13 {mso-list-id:359431469; mso-list-type:hybrid; mso-list-template-ids:84734878 67698689 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l13:level1 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Symbol;} @list l14 {mso-list-id:458649110; mso-list-type:hybrid; mso-list-template-ids:-38738056 423934604 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l14:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:1.0in; mso-level-number-position:left; margin-left:1.0in; text-indent:-.25in; font-family:Arial; mso-fareast-font-family:"Times New Roman";} @list l15 {mso-list-id:547566703; mso-list-type:hybrid; mso-list-template-ids:1798573620 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l15:level1 {mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in;} @list l16 {mso-list-id:752435528; mso-list-type:hybrid; mso-list-template-ids:968014730 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l16:level1 {mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in;} @list l17 {mso-list-id:1072436292; mso-list-type:hybrid; mso-list-template-ids:1681550614 423934604 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l17:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:.75in; mso-level-number-position:left; margin-left:.75in; text-indent:-.25in; font-family:Arial; mso-fareast-font-family:"Times New Roman";} @list l17:level2 {mso-level-number-format:bullet; mso-level-text:o; mso-level-tab-stop:1.25in; mso-level-number-position:left; margin-left:1.25in; text-indent:-.25in; font-family:"Courier New";} @list l18 {mso-list-id:1209411371; mso-list-type:hybrid; mso-list-template-ids:-1603923158 67698689 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l18:level1 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:.75in; mso-level-number-position:left; margin-left:.75in; text-indent:-.25in; font-family:Symbol;} @list l19 {mso-list-id:1432318865; mso-list-type:hybrid; mso-list-template-ids:2137158298 423934604 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l19:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Arial; mso-fareast-font-family:"Times New Roman";} @list l20 {mso-list-id:1611356098; mso-list-type:hybrid; mso-list-template-ids:-854709908 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l20:level1 {mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in;} @list l21 {mso-list-id:1614744623; mso-list-type:hybrid; mso-list-template-ids:-1496942198 423934604 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l21:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Arial; mso-fareast-font-family:"Times New Roman";} @list l21:level2 {mso-level-number-format:bullet; mso-level-text:o; mso-level-tab-stop:1.0in; mso-level-number-position:left; text-indent:-.25in; font-family:"Courier New";} @list l21:level3 {mso-level-number-format:bullet; mso-level-text:\F0A7; mso-level-tab-stop:1.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Wingdings;} @list l21:level4 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:2.0in; mso-level-number-position:left; text-indent:-.25in; font-family:Symbol;} @list l22 {mso-list-id:1693457207; mso-list-type:hybrid; mso-list-template-ids:-1668623746 67698703 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l22:level1 {mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in;} @list l22:level2 {mso-level-number-format:bullet; mso-level-text:o; mso-level-tab-stop:1.0in; mso-level-number-position:left; text-indent:-.25in; font-family:"Courier New";} @list l22:level3 {mso-level-number-format:bullet; mso-level-text:\F0A7; mso-level-tab-stop:1.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Wingdings;} @list l22:level4 {mso-level-number-format:bullet; mso-level-text:\F0B7; mso-level-tab-stop:2.0in; mso-level-number-position:left; text-indent:-.25in; font-family:Symbol;} @list l23 {mso-list-id:1731031428; mso-list-type:hybrid; mso-list-template-ids:1886447558 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l23:level1 {mso-level-tab-stop:39.0pt; mso-level-number-position:left; margin-left:39.0pt; text-indent:-.25in;} @list l24 {mso-list-id:1832519519; mso-list-type:hybrid; mso-list-template-ids:-658358596 423934604 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l24:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Arial; mso-fareast-font-family:"Times New Roman";} @list l25 {mso-list-id:1853185266; mso-list-type:hybrid; mso-list-template-ids:403894856 423934604 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l25:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Arial; mso-fareast-font-family:"Times New Roman";} @list l25:level2 {mso-level-number-format:bullet; mso-level-text:o; mso-level-tab-stop:1.0in; mso-level-number-position:left; text-indent:-.25in; font-family:"Courier New";} @list l26 {mso-list-id:1938905931; mso-list-type:hybrid; mso-list-template-ids:1084264292 423934604 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;} @list l26:level1 {mso-level-start-at:0; mso-level-number-format:bullet; mso-level-text:-; mso-level-tab-stop:.5in; mso-level-number-position:left; text-indent:-.25in; font-family:Arial; mso-fareast-font-family:"Times New Roman";} ol {margin-bottom:0in;} ul {margin-bottom:0in;} --> </style> <!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman";} </style> <![endif]--> </head> <body lang=EN-US style='tab-interval:.5in'> <div class=Section1> <h1>Generalized Undo Support in Eclipse</h1> <h2>Problem Description<o:p></o:p></h2> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>In R3.0.1 of the Eclipse SDK, there is no generalized support for undoing user actions.<span style='mso-spacerun:yes'> </span>Each plug-in is left to implement its own strategy for undo, if at all.<span style='mso-spacerun:yes'> </span>This approach can cause many general problems as independently developed plug-ins implement their own undo strategies:<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Undo and redo actions appear in different menus.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Undo and redo implementations can have different semantics.<span style='mso-spacerun:yes'> </span>Different approaches to undo by different plug-ins may confuse the user if they choose different semantics.<span style='mso-spacerun:yes'> </span>For example:<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:1.0in;text-indent:-.25in;mso-list:l21 level2 lfo1; tab-stops:list 1.0in'><![if !supportLists]><span style='font-size:10.0pt; font-family:"Courier New";mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>o<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Is <span class=GramE>undo</span> strictly linear?<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:1.0in;text-indent:-.25in;mso-list:l21 level2 lfo1; tab-stops:list 1.0in'><![if !supportLists]><span style='font-size:10.0pt; font-family:"Courier New";mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>o<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>If it is not linear, what techniques are used to undo an operation?<span style='mso-spacerun:yes'> </span>Implementation models for non-linear undo (rollback and perform the history again, dynamic reversal) can affect the user outcome.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:1.0in;text-indent:-.25in;mso-list:l21 level2 lfo1; tab-stops:list 1.0in'><![if !supportLists]><span style='font-size:10.0pt; font-family:"Courier New";mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>o<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>What is the scope of an undo?<span style='mso-spacerun:yes'> </span>Is it global to the system?<span style='mso-spacerun:yes'> </span>Is it local to the window?<span style='mso-spacerun:yes'> </span>Is it model-dependent?<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Plug-ins that want to add undo support may have to choose between different undo strategies and implementations provided by their required plug-ins, or worse yet, implement yet another strategy.<o:p></o:p></span></p> <h3>Challenges with generalized undo support<o:p></o:p></h3> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>While implementation of a centralized undo mechanism should be straightforward, it has not been provided in previous releases due to problems in defining the proper undo semantics across different plug-ins.<span style='mso-spacerun:yes'> </span>The challenge in defining consistent, predictable undo semantics can best be understood by looking at the two different undo models provided in the R3.0.1 release of the base Eclipse SDK.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The SDK currently contains two undo implementations and user commands:<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l26 level1 lfo2; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Text undo (Edit>Undo) provides a linear undo model for text-level operations.<span style='mso-spacerun:yes'> </span>That is, textual insert/replace/delete operations can be undone in the reverse order in which they are applied.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=SpellE><span style='font-size:10.0pt; font-family:Arial'>Refactoring</span></span><span style='font-size:10.0pt; font-family:Arial'> undo (<span class=SpellE>Refactor</span>>Undo) allows an undo of the last <span class=SpellE>refactoring</span> operation, but only when the workspace has not been otherwise modified since the last <span class=SpellE>refactoring</span>.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>In discussing the appropriate semantics for workbench undo, it is useful to introduce terminology that is independent of any particular implementation for undo support.<o:p></o:p></span></p> <h3>Undo contexts </h3> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Undo implementations must provide a history of operations performed by the user and some knowledge of the “context” for these operations.<span style='mso-spacerun:yes'> </span>For example, the text editor undo operates within the context of a single document, while <span class=SpellE>refactoring</span> undo operates within the context of some workspace resources.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The context for an operation helps determine where the undo for that operation is available.<span style='mso-spacerun:yes'> </span>When the contexts for different operations are completely separate, the semantics for undoing an operation from either context are easily understood.<span style='mso-spacerun:yes'> </span>Undoing an operation from one context does not affect the operation history from the other context. <o:p></o:p></span></p> <h3>Undo scopes </h3> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Even when completely separate undo contexts exist, the scope of the operation history and resulting undo operation must be defined.<span style='mso-spacerun:yes'> </span>There are a few different alternatives:<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The UI that manipulates each separate undo context provides its own undo command.<span style='mso-spacerun:yes'> </span>This is done in R3.0.1 with Edit>Undo and <span class=SpellE>Refactoring</span>>Undo.<span style='mso-spacerun:yes'> </span>This does not scale well, but makes it clear which context is to be undone by forcing the user to explicitly choose the context for the undo.<span style='mso-spacerun:yes'> </span>We call this an <b style='mso-bidi-font-weight: normal'>explicit local undo scope</b>.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>A unified undo command exists and its meaning is interpreted according to some current context (such as the active part or the currently edited model).<span style='mso-spacerun:yes'> </span>The unified command only ever operates on the current context.<span style='mso-spacerun:yes'> </span>This is analogous to retargeted global actions in the Eclipse workbench.<span style='mso-spacerun:yes'> </span>We call this <b style='mso-bidi-font-weight: normal'>implicit local undo scope</b>.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>A unified undo command exists and its meaning is global for all operations performed in the system.<span style='mso-spacerun:yes'> </span>The history list and default operation to be undone have no relationship to the user’s current context.<span style='mso-spacerun:yes'> </span>We call this <b style='mso-bidi-font-weight:normal'>global undo scope</b>.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The appropriate scope to be used depends on what the user is doing.<span style='mso-spacerun:yes'> </span>When the operations performed by a user are sequential steps in a larger task, a global scope may be appropriate.<span style='mso-spacerun:yes'> </span>When a user is performing separate tasks while working in separate views, a more localized scope is appropriate.<span style='mso-spacerun:yes'> </span>The decision is largely subjective and often cannot be predicted by the system. <a style='mso-footnote-id:ftn1' href="#_ftn1" name="_ftnref1" title=""><span class=MsoFootnoteReference><span style='mso-special-character:footnote'><![if !supportFootnotes]><span class=MsoFootnoteReference><span style='font-size:10.0pt;font-family:Arial; mso-fareast-font-family:"Times New Roman";mso-ansi-language:EN-US;mso-fareast-language: EN-US;mso-bidi-language:AR-SA'>[1]</span></span><![endif]></span></span></a><o:p></o:p></span></p> <h3>Shared undo contexts<o:p></o:p></h3> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Unfortunately, the SDK model for undo is more complicated.<span style='mso-spacerun:yes'> </span>The contexts for edit and <span class=SpellE>refactoring</span> undo are not completely separate.<span style='mso-spacerun:yes'> </span>The user can trigger <span class=SpellE>refactoring</span> changes from the editor itself.<span style='mso-spacerun:yes'> </span>These changes can manipulate both the document being edited and other workspace resources.<span style='mso-spacerun:yes'> </span>Further, these changes occur alongside localized text editing changes, creating an operation history with multiple contexts that are initiated from a single part.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Even when a local undo scope is employed, there are different possibilities for interpreting “undo” when a <span class=SpellE>refactoring</span> operation is triggered from an editor:<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <ol style='margin-top:0in' start=1 type=1> <li class=MsoNormal style='mso-list:l22 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>Edit>Undo causes reversal of the <span class=SpellE>refactoring</span> operation that was triggered inside the editor.<o:p></o:p></span></li> <li class=MsoNormal style='mso-list:l22 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>Edit>Undo causes reversal of only the editor’s text-related changes that were caused by the <span class=SpellE>refactoring</span> operation.<span style='mso-spacerun:yes'> </span>Thus, the text editing caused by the <span class=SpellE>refactor</span> is undone, but the <span class=SpellE>refactor</span> itself is not undone (this happens in R3.0.1).<o:p></o:p></span></li> <li class=MsoNormal style='mso-list:l22 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>Edit>Undo is unaware of the <span class=SpellE>refactoring</span> operation since it affected a context larger than the editor itself.<span style='mso-spacerun:yes'> </span>The text operation that occurred before the <span class=SpellE>refactor</span> is undone. <o:p></o:p></span></li> </ol> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Examining scenarios and the desired behavior shows that any one (or more) of the three alternatives are desirable at different times, depending on what the user is trying to achieve.<span style='mso-spacerun:yes'> </span>Appendix A collects various <span class=SpellE>refactoring</span> and edit scenarios to help demonstrate the challenge.<o:p></o:p></span></p> <h3>Linear vs. selective undo<o:p></o:p></h3> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The appearance of a simple Edit>Undo command in the UI typically implies a linear undo.<span style='mso-spacerun:yes'> </span>That is, the most recent operation executed is undone.<span style='mso-spacerun:yes'> </span>Descriptive undo labels (such as “Undo Typing” or “Undo Rename”) help to remind the user of the last “undoable” operation.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>As we’ve shown in discussing scopes and contexts, a strictly linear global undo is not the ideal behavior when working across contexts.<span style='mso-spacerun:yes'> </span>Once an attempt is made to choose the “appropriate” operation to be undone in the user’s current context, it’s possible that the chosen operation is not the most recently executed operation.<span style='mso-spacerun:yes'> </span>Decisions must be made about how to handle more recently executed operations.<span style='mso-spacerun:yes'> </span>A strictly linear model would force more recent operations to be undone before allowing the chosen operation to be undone.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>In a selective undo approach, users are given an opportunity to view the history list and select the operation to be undone.<span style='mso-spacerun:yes'> </span>Operations that can be undone in the current state of the application are available for undo at any time, even if there are more recent operations in the history.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The workbench support should minimally be a hybrid of these approaches.<span style='mso-spacerun:yes'> </span>When the operation appropriate for one context is not the most recently executed one, then the user (by prompt or by preference) should have input into the decision to roll back any more recent operations or perform the undo selectively and retain the rest of the history list.<o:p></o:p></span></p> <h2>Proposed Undo Support<o:p></o:p></h2> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>While the discussion and scenarios surrounding scopes and contexts have focused on the “hard cases,” it should be realized that most users will seek out “undo” in the simple cases.<span style='mso-spacerun:yes'> </span>Single context, strictly linear undo, particularly in text editing, is provided in most popular applications.<span style='mso-spacerun:yes'> </span>The availability of a more selective undo for the “hard cases” should not hinder the expected behavior of the simple cases. <o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Support for undo should be “pay as you go,” in terms of efficiency, burden on the user, and burden on the implementer.<span style='mso-spacerun:yes'> </span>Validation of operations in the history list against the current state of the application should be on demand, rather than forcing operation objects to watch the current state of the application and react to changes (even when the user might never choose “undo.”)<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Undo support should not assume the presence of a user interface.<span style='mso-spacerun:yes'> </span>The operations history and associated interfaces can be defined independent of the UI.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>With these goals in mind, the following implementation is proposed:<o:p></o:p></span></p> <h3>Operations Framework</h3> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>A framework for defining executable, undoable operations (<span class=SpellE>IOperation</span>) will be provided in a core package, <span class=SpellE>org.eclipse.core.operations</span>.<span style='mso-spacerun:yes'> </span>As actions are run, an object describing the operation to be performed is created, executed, and added to an operations history (<span class=SpellE>IOperationHistory</span>).<span style='mso-spacerun:yes'> </span>Operations which are comprised of distinct steps are represented as compound operations.<span style='mso-spacerun:yes'> </span>Compound operations must be executed as a unit, and can never be partially undone. <span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Operations can be assigned one or more contexts (<span class=SpellE>IOperationContext</span>) to which they apply.<span style='mso-spacerun:yes'> </span>The interface for operation contexts is left very general so that operation implementers may choose the appropriate representation for their contexts.<span style='mso-spacerun:yes'> </span>In some cases, a part-oriented context may be appropriate (an editor’s undo context is the editor part itself).<span style='mso-spacerun:yes'> </span>In other cases, a model object may serve as the context (the navigator’s context is the workspace). The interface leaves this to the discretion of the implementer and requires only that equality of contexts can be established.<span style='mso-spacerun:yes'> </span>User-appropriate labels and descriptions for operation contexts are required so that any filtered operation history views can appropriately label the contexts that are filtering the view.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Contexts can be assigned in multiple ways:<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:39.0pt;text-indent:-.25in;mso-list:l23 level1 lfo24; tab-stops:list 39.0pt'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>1.<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>When the triggering object knows the context of the operation, the context can be assigned up front.<span style='mso-spacerun:yes'> </span>For example, text operations are triggered by typing in the editor, and the editor can assign its context to the operation before adding it to the history.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal style='margin-left:39.0pt;text-indent:-.25in;mso-list:l23 level1 lfo24; tab-stops:list 39.0pt'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>2.<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Depending on the structure of the code, the object that creates the operation object may not know what context is appropriate, or if other contexts should be included.<span style='mso-spacerun:yes'> </span>In these cases, a listener can be added to the operations history.<span style='mso-spacerun:yes'> </span>When an operation is added to the history, listeners can decide if their context should be added to the operation.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal style='margin-left:21.0pt'><span style='font-size:10.0pt; font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Representing the contexts for an operation as a collection (empty graph) assumes that there is no inherent relationship between operation contexts.<span style='mso-spacerun:yes'> </span>This allows the most flexibility in defining contexts.<span style='mso-spacerun:yes'> </span>For example, an editor may perform an operation that affects both the editor’s document and the workspace at large.<span style='mso-spacerun:yes'> </span>These will be considered two independent contexts and assigned to the operation.<span style='mso-spacerun:yes'> </span>One could argue that the context for the document is simply a refinement of the workspace context, and that a hierarchical relationship between those contexts should exist.<span style='mso-spacerun:yes'> </span>Without more use cases, we avoid establishing any relationship between contexts at this time<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Operation contexts that are used when manipulating well-known models should be accessible by API.<span style='mso-spacerun:yes'> </span>This can be done in multiple ways:<o:p></o:p></span></p> <ol style='margin-top:0in' start=1 type=1> <li class=MsoNormal style='mso-list:l20 level1 lfo25;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>API for obtaining a context can be added in the same place where the associated model can be obtained.<span style='mso-spacerun:yes'> </span>For example, an editor can provide both the document and the context for performing operations on the document as API.<o:p></o:p></span></li> <li class=MsoNormal style='mso-list:l20 level1 lfo25;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>Contexts that are related directly to certain preexisting platform objects can be obtained using an adapter on that object.<span style='mso-spacerun:yes'> </span>For example, the workbench could add an operation context adapter factory for the workspace.<span style='mso-spacerun:yes'> </span>Clients could retrieve this adapter using context=<span class=SpellE>workspace.getAdapter</span>(<span class=SpellE>IOperationContext.class</span>);<o:p></o:p></span></li> </ol> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The following interfaces represent the operation, the operation history, and the operation context.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>public</span></span><span style='font-size:10.0pt;font-family:Arial'> interface <span class=SpellE>IOperation</span> {<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>addContext</span>(<span class=SpellE>IOperationContext</span>);<span style='mso-tab-count:1'> </span>// add the context to the operation’s contexts<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=SpellE><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>boolean</span></span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>hasContext</span>(<span class=SpellE>IOperationContext</span>);<span style='mso-tab-count:1'> </span>//answer whether the receiver’s contexts contain the context<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span style='font-size:10.0pt; font-family:Arial'>List <span class=SpellE><span class=GramE>getContexts</span></span><span class=GramE>(</span>);<span style='mso-tab-count:1'> </span>// answer the list of contexts assigned to the receiver.<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IStatus</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE><span class=GramE>canExecute</span></span><span class=GramE>(</span>);<span style='mso-tab-count:1'> </span>// answer whether the receiver can be executed<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IStatus</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE><span class=GramE>canRedo</span></span><span class=GramE>(</span>);<span style='mso-tab-count:1'> </span>// answer whether the receiver can be redone<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IStatus</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE><span class=GramE>canUndo</span></span><span class=GramE>(</span>);<span style='mso-tab-count:1'> </span>// answer whether the receiver can be undone<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> execute(<span class=SpellE>IProgressMonitor</span>);<span style='mso-tab-count:1'> </span>// execute the operation <o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> redo(<span class=SpellE>IProgressMonitor</span>);<span style='mso-tab-count:1'> </span>// redo the operation<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> undo(<span class=SpellE>IProgressMonitor</span>);<span style='mso-tab-count:1'> </span>// undo the operation<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> dispose();<span style='mso-tab-count: 1'> </span>// the operation is no longer needed<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span style='font-size:10.0pt; font-family:Arial'>String <span class=SpellE><span class=GramE>getLabel</span></span><span class=GramE>(</span>);<span style='mso-tab-count:1'> </span>// provide a label to name this operation for the user<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span style='font-size:10.0pt; font-family:Arial'>String <span class=SpellE><span class=GramE>getDescription</span></span><span class=GramE>(</span>);<span style='mso-tab-count:1'> </span>// provide a description of this operation for the user<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in 189.0pt'><span style='font-size:10.0pt; font-family:Arial'>}<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>public</span></span><span style='font-size:10.0pt;font-family:Arial'> interface <span class=SpellE>IOperationHistory</span> {<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> add(<span class=SpellE>IOperation</span>);<span style='mso-tab-count:1'> </span>// add the specified operation to the history<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> redo(<span class=SpellE>IOperationContext</span>, <span class=SpellE>IProgressMonitor</span>);<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// perform the redo operation for the given context<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> undo(<span class=SpellE>IOperationContext</span>, <span class=SpellE>IProgressMonitor</span>);<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// perform the undo operation appropriate for the given context.<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IStatus</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE><span class=GramE>canRedoIn</span></span><span class=GramE>(</span><span class=SpellE>IOperationContext</span>);<span style='mso-tab-count:1'> </span>// answer whether redo is available in the given context<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IStatus</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE><span class=GramE>canUndoIn</span></span><span class=GramE>(</span><span class=SpellE>IOperationContext</span>);<span style='mso-tab-count:1'> </span>// answer whether undo is available in the given context<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>addOperationHistoryListener</span>(<span class=SpellE>IOperationHistoryListener</span>);<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// add a listener for changes to the operation history<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>removeOperationHistoryListener</span>(<span class=SpellE>IOperationHistoryListener</span>);<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// remove the specified history listener from the receiver.<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IOperation</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE><span class=GramE>getRedoFor</span></span><span class=GramE>(</span><span class=SpellE>IOperationContext</span>);<span style='mso-tab-count:1'> </span>// get the redo operation for the given context<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IOperation</span></span><span style='font-size:10.0pt;font-family:Arial'> [] <span class=SpellE><span class=GramE>getRedoHistoryFor</span></span><span class=GramE>(</span><span class=SpellE>IOperationContext</span>);<span style='mso-spacerun:yes'> </span>// answer the redo history list for the given context<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IOperation</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE><span class=GramE>getUndoFor</span></span><span class=GramE>(</span><span class=SpellE>IOperationContext</span>);<span style='mso-tab-count:1'> </span>// answer the undo operation for the given context<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IOperation</span></span><span style='font-size:10.0pt;font-family:Arial'> [] <span class=SpellE><span class=GramE>getUndoHistoryFor</span></span><span class=GramE>(</span><span class=SpellE>IOperationContext</span>);<span style='mso-spacerun:yes'> </span>// answer the undo history list for the given context<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>disposeAll</span>(<span class=SpellE>IOperationContext</span>);<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// Remove all operations that have only the specified context.<span style='mso-spacerun:yes'> </span>Implementers must<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// determine how to handle operations that have additional contexts.<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>setLimit</span>(<span class=SpellE>int</span>);<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// set a limit on the operation history.<span style='mso-spacerun:yes'> </span>When the limit is reached, the oldest operation <o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.5in .75in 207.0pt 3.5in 297.0pt 4.75in'><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// will be disposed to make room for new operations.<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.75in 207.0pt'><span style='font-size:10.0pt; font-family:Arial'>}<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:.75in 207.0pt'><span style='font-size:10.0pt; font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal style='tab-stops:207.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>public</span></span><span style='font-size:10.0pt;font-family:Arial'> interface <span class=SpellE>IOperationHistoryListener</span> {<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:207.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>operationAdded</span>(<span class=SpellE>IOperation</span>);<span style='mso-tab-count:1'> </span>// an operation has been added to the history<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:207.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>aboutToUndo</span>(<span class=SpellE>IOperation</span>);<span style='mso-tab-count:1'> </span>// the operation is about to be undone<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:207.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> undone(<span class=SpellE>IOperation</span>);<span style='mso-tab-count:1'> </span>// the operation was undone<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:207.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>aboutToRedo</span>(<span class=SpellE>IOperation</span>);<span style='mso-tab-count:1'> </span>// the operation is about to be redone<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:207.0pt'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>void</span></span><span style='font-size:10.0pt;font-family:Arial'> redone(<span class=SpellE>IOperation</span>);<span style='mso-tab-count:1'> </span>// the operation was redone<o:p></o:p></span></p> <p class=MsoNormal style='tab-stops:207.0pt'><span style='font-size:10.0pt; font-family:Arial'>}<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span class=GramE><span style='font-size:10.0pt;font-family: Arial'>public</span></span><span style='font-size:10.0pt;font-family:Arial'> interface <span class=SpellE>IOperationContext</span> {<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span style='font-size:10.0pt;font-family: Arial'>IOperationApproval</span></span><span style='font-size:10.0pt; font-family:Arial'> <span class=SpellE><span class=GramE>getOperationApproval</span></span><span class=GramE>(</span>);<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>String <span class=SpellE><span class=GramE>getDescription</span></span><span class=GramE>(</span>);<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>String <span class=SpellE><span class=GramE>getLabel</span></span><span class=GramE>(</span>);<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><span style='font-size: 10.0pt;font-family:Arial'>boolean</span></span></span><span style='font-size: 10.0pt;font-family:Arial'> equals(<span class=SpellE>IOperationContext</span>);<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>}<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span class=GramE><span style='font-size:10.0pt;font-family: Arial'>public</span></span><span style='font-size:10.0pt;font-family:Arial'> interface <span class=SpellE>IOperationApproval</span> {<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><span style='font-size: 10.0pt;font-family:Arial'>boolean</span></span></span><span style='font-size: 10.0pt;font-family:Arial'> <span class=SpellE>proceedUndoing</span>(<span class=SpellE>IOperation</span>);<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><span style='font-size: 10.0pt;font-family:Arial'>boolean</span></span></span><span style='font-size: 10.0pt;font-family:Arial'> <span class=SpellE>proceedRedoing</span>(<span class=SpellE>IOperation</span>);<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>}<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>An operation is responsible for validating its ability to execute and undo against the current state of the application.<span style='mso-spacerun:yes'> </span>Validation may be requested even when an operation is not the most recently executed operation (or most recently undone operation).<span style='mso-spacerun:yes'> </span>This is important since operations in unrelated contexts may coexist in the same history unaware of one another’s existence.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>As operations are executed, they are added to the operation history.<span style='mso-spacerun:yes'> </span>Note that the operation history does not necessarily perform the initial execution, but rather assumes the operation is already executed before it is added to the history.<span style='mso-spacerun:yes'> </span>This is necessary for text editing operations, where the operations are happening as the user types and the recording/batching of operations for the history occur afterwards.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The operation history is responsible for implementing the application’s undo model, and the decisions about handling multiple contexts.<span style='mso-spacerun:yes'> </span>If an application chooses to implement a strictly linear, global undo, then its implementation of <span class=SpellE>IOperationHistory</span> can ensure that requests to perform undo or redo in a particular context will fail if the most recent operation does not have that context.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>More flexible undo models may be implemented with the assistance of the <span class=SpellE>IOperationApproval</span> that is assigned to an operation context.<span style='mso-spacerun:yes'> </span>This interface allows other contexts to be consulted when an operation is to be executed or undone.<span style='mso-spacerun:yes'> </span>The undo model defined by the operation history determines when to consult the <span class=SpellE>IOperationApproval</span>.<span style='mso-spacerun:yes'> </span>Possible implementations will be discussed in more detail in the workbench scenarios.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <h3>Workbench Undo Semantics</h3> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The workbench will adopt a hybrid undo approach that allows selective undo across multiple contexts.<span style='mso-spacerun:yes'> </span>The workbench will allow undo/redo of any valid operation in the history, <i style='mso-bidi-font-style: normal'>as long as there are no more recent operations in the history that share a context with the operation to be executed.</i><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'> </span>If the operation to be undone/redone has contexts that are also present in operations appearing later in the history, then the <span class=SpellE>IOperationApproval</span> for the contexts that have the conflicts will be consulted.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>A concrete example will help explain this.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user makes local edits in editor A.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user initiates a <span class=SpellE>refactoring</span> operation whose context is “A” and “workspace.”<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user makes additional local edits to editor A.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user goes to the navigator and selects Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>In the proposed implementation, the navigator would request an undo for the context “workspace.”<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactoring</span> operation triggered in the editor is the most recent operation that has the workspace context, but it also contains context “A.”<span style='mso-spacerun:yes'> </span>Since subsequent operations in the history also have context “A,<span class=GramE>”,</span> the <span class=SpellE>IOperationApproval</span> for context “A” is consulted as to whether the undo should proceed.<span style='mso-spacerun:yes'> </span>The <span class=SpellE><span class=GramE>IOperationApproval</span></span><span class=GramE> <span style='mso-spacerun:yes'> </span>supplied</span> by context “A” could do one of the following:<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=GramE><span style='font-size:10.0pt; font-family:Arial'>allow</span></span><span style='font-size:10.0pt;font-family: Arial'> the undo to proceed, leaving the local changes to “A” in the undo history.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=GramE><span style='font-size:10.0pt; font-family:Arial'>quietly</span></span><span style='font-size:10.0pt; font-family:Arial'> undo the subsequent local changes to “A” and then allow the original undo to proceed.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=GramE><span style='font-size:10.0pt; font-family:Arial'>switch</span></span><span style='font-size:10.0pt; font-family:Arial'> to the editor and non-quietly undo the local changes to “A” before allowing the original undo to proceed.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=GramE><span style='font-size:10.0pt; font-family:Arial'>prompt</span></span><span style='font-size:10.0pt; font-family:Arial'> the user for the preferred action.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=GramE><span style='font-size:10.0pt; font-family:Arial'>provide</span></span><span style='font-size:10.0pt; font-family:Arial'> a user preference that drives the behavior of the scenario.<o:p></o:p></span></p> <h4>Workbench IDE undo contexts<o:p></o:p></h4> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>To support the existing workbench undo scenarios, there will be two kinds of contexts defined in the workbench IDE.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <ol style='margin-top:0in' start=1 type=1> <li class=MsoNormal style='mso-list:l10 level1 lfo26;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>The “workspace” context will be used to represent changes that affect resources in the workspace.<span style='mso-spacerun:yes'> </span><span class=SpellE>Refactoring</span> operations will use this context.<span style='mso-spacerun:yes'> </span>Additional actions that affect the workspace (such as delete and create resources) would use this context.<span style='mso-spacerun:yes'> </span>Views that manipulate the workspace, such as the navigator and package explorer, will use this context when creating operations and querying for the current “undo operation.”<span style='mso-spacerun:yes'> </span>Views or editors that may be affected by workspace operations can add a listener to the operation history and add their context as needed to operations that have been added to the history.<span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'> </span>The workspace context implementation is not defined at this time, but it should be accessible by API.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></li> <li class=MsoNormal style='mso-list:l10 level1 lfo26;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>Editors will define a context that represents their particular editing session.<span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'> </span>That is, the context will be unique per editor, but editors may in fact share the context implementation class.<span style='mso-spacerun:yes'> </span>Workspace-affecting operations, such as <span class=SpellE>refactoring</span> operations, that are triggered from an editor will be considered to occur in the context of both the editor and the workspace.<span style='mso-spacerun:yes'> </span>This allows <span class=SpellE>refactoring</span> operations to coexist with text editing operations in the editor’s operation history and also be accessible from the operation history of other views that support the workspace context, such as the navigator. The editor’s context can be added using the listener as described above.<o:p></o:p></span></li> </ol> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Further definition of contexts and the supported operations are required:<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The complete set of workspace operations (besides <span class=SpellE>refactoring</span>) that should be undoable must be defined.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Any additional contexts required by the SDK (Team?<span style='mso-spacerun:yes'> </span>Debug?) <span class=GramE>must</span> be defined.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The operation contexts for the major views in the SDK must be defined.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The semantics for assigning multiple contexts must be defined.<span style='mso-spacerun:yes'> </span>For example, do <span class=SpellE>refactoring</span> operations that affect an open editor (but were triggered elsewhere) carry the context of that editor? <span style='mso-spacerun:yes'> </span>Should the editor decide this by listening for new operations that are added to the history? <o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The following are working assumptions about the undo operations:<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>There is no relationship between a perspective and an operation context, since switching perspectives will change the active part, and thus may or may not affect the current context.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Actions that only change the presentation in the workbench (open a view, switch perspectives, change the sort order) are not considered to be operations since they are<span style='mso-spacerun:yes'> </span>easily undone and redone through the same window mechanics.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <h4>Workbench UI for Undo/Redo<o:p></o:p></h4> <h5>Minimal support</h5> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The Edit>Undo and Edit>Redo commands should be retargeted by most of the major views (list of views TBD).<span style='mso-spacerun:yes'> </span>If a view retargets Undo/Redo, then it knows what operation contexts it supports, and it uses these contexts to retrieve the available undo operation.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Edit>Undo is enabled based on the active part.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><span class=SpellE>IStatus</span> status = <span class=SpellE><span class=GramE>operationHistory.canUndoIn</span></span><span class=GramE>(</span><span class=SpellE>myContext</span>);<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span>// up to the active part to define behavior for anything between OK and FATAL.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The label for the undo action should be appended with a description of the operation.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><span class=SpellE><span class=GramE>operationToUndo</span></span> = <span class=SpellE>operationHistory.getUndoFor</span>(<span class=SpellE>myContext</span>);<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><span class=GramE>label</span> = “Undo “+ <span class=SpellE>operationToUndo.label</span>();<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Undo and Redo on the toolbar include a drop down that shows the operation history.<span style='mso-spacerun:yes'> </span>This history depends on the current part’s context.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><span class=SpellE><span class=GramE>operationHistory.getUndoHistoryFor</span></span><span class=GramE>(</span><span class=SpellE>myContext</span>);<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The drop down permits range selection of operations from the top down (see MS Word and other applications).<span style='mso-spacerun:yes'> </span>This UI implies a linear undo within any particular set of contexts.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The UI for handling special cases should be determined.<span style='mso-spacerun:yes'> </span>Consider the following scenarios:<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Scenario #1:</span></b><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span>Mixed contexts in an editor, undo from another view<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user makes local edits in editor A.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user initiates a <span class=SpellE>refactoring</span> operation whose context is “A” and “workspace.”<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user makes additional local edits to editor A.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user goes to the navigator and selects Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The <span class=SpellE>IOperationApproval</span> for the editor’s context can implement UI for handling this case if desired.<span style='mso-spacerun:yes'> </span>Possible options include:<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>warn the user about the local changes in A and ask whether to undo them or leave them<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=GramE><span style='font-size:10.0pt; font-family:Arial'>provide</span></span><span style='font-size:10.0pt; font-family:Arial'> a user preference that drives the behavior of the scenario.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The exact solution will be prototyped and may involve both a first-time prompt and subsequent preference (“Don’t ask me again”).<o:p></o:p></span></p> <p class=MsoNormal><o:p> </o:p></p> <p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Scenario #2</span></b><span style='font-size:10.0pt;font-family:Arial'>:<span style='mso-spacerun:yes'> </span>Editor <span class=GramE>undo</span> triggers a non-local operation<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user makes local edits in editor A.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user initiates a <span class=SpellE>refactoring</span> operation whose context is “A” and “workspace.”<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user makes additional local edits to editor A.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>The user selects undo repeatedly from the editor<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Most operations in the editor’s context affect only the editor.<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactoring</span> operation affects not only the editor, but other objects in the workspace.<span style='mso-spacerun:yes'> </span>It might surprise the user for the <span class=SpellE>refactoring</span> to be undone.<span style='mso-spacerun:yes'> </span>The editor could implement a warning dialog when it detects that the proposed undo operation has additional contexts.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>If the <span class=SpellE>refactoring</span> had been triggered elsewhere (say, editor “B” or the navigator), but resulted in changes to editor “A,” it is even more important that the user be warned about the operation invoked by the undo command.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span class=GramE><span style='font-size:10.0pt;font-family: Arial'>The<span style='mso-spacerun:yes'> </span>solution</span></span><span style='font-size:10.0pt;font-family:Arial'> for this scenario will be prototyped and may involve both a warning and subsequent preference.<span style='mso-spacerun:yes'> </span>For example, a prompt could provide the label and description of the operation and warn that it affects other views.<span style='mso-spacerun:yes'> </span>The user could choose whether to proceed, and the choice could be remembered in a preference.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>It appears that the proposed framework allows detection of these cases and hooks for supplying the necessary UI.<o:p></o:p></span></p> <h5>Advanced support</h5> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>More selective undo approaches can be supported by the framework, but the ability to support them in the workbench depends upon the implementation of the individual operations and their ability to be undone independently.<span style='mso-spacerun:yes'> </span>The priority is TBD.<span style='mso-spacerun:yes'> </span>Ideas include:<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Additional menu commands show the operation history.<o:p></o:p></span></p> <p class=MsoNormal style='text-indent:.5in'><span style='font-size:10.0pt; font-family:Arial'>Edit>Undo… shows the undo operation history based on the active part’s context.<o:p></o:p></span></p> <p class=MsoNormal style='text-indent:.5in'><span style='font-size:10.0pt; font-family:Arial'>Edit>Redo… shows the redo operation history based on the active part’s context.<o:p></o:p></span></p> <p class=MsoNormal style='text-indent:.5in'><span style='font-size:10.0pt; font-family:Arial'><span style='mso-tab-count:1'> </span><span class=SpellE><span class=GramE>operationHistory.getUndoHistoryFor</span></span><span class=GramE>(</span><span class=SpellE>myContext</span>);<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The operation history can be shown in a view or dialog.<span style='mso-spacerun:yes'> </span>Operations that are valid can be selected (one at a time) and undone (or redone) regardless of sequential order.<span style='mso-spacerun:yes'> </span>Multiple selections are not allowed since the validation state for an operation might change as other operations are undone.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The operation history view could allow changing of the filtering.<span style='mso-spacerun:yes'> </span>While the default filtering could depend on the active part’s context, the user could be shown the available contexts and choose one or more contexts (or none at all) that affect the filtering of the list.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Note that the UI for the advanced cases can be implemented independently from the operations, and may be useful for testing the framework.<o:p></o:p></span></p> <h3>Compatibility Issues</h3> <h4><span class=SpellE>JFace</span> Text</h4> <p class=MsoNormal><span class=SpellE><span style='font-size:10.0pt;font-family: Arial'>JFace</span></span><span style='font-size:10.0pt;font-family:Arial'> text currently has API for retrieving an <span class=SpellE>IUndoManager</span> from a text viewer.<span style='mso-spacerun:yes'> </span>The undo manager is connected to a text viewer and watches the changes that happen in the viewer.<span style='mso-spacerun:yes'> </span>As editing actions occurs, commands (<span class=SpellE>TextCommand</span>) are created and then “committed” to a command stack.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span class=SpellE><span style='font-size:10.0pt;font-family: Arial'>TextCommand</span></span><span style='font-size:10.0pt;font-family:Arial'> could be changed to implement <span class=SpellE>IOperation</span>.<span style='mso-spacerun:yes'> </span>The mapping from <span class=SpellE>IOperation</span> to <span class=SpellE>TextCommand</span> protocol is straightforward.<span style='mso-spacerun:yes'> </span>Currently the <span class=SpellE>TextCommand</span> directly pushes itself onto a local command stack of a viewer when a set of pending changes are committed.<span style='mso-spacerun:yes'> </span>Instead, it would need to set its context to one appropriate for the text viewer and add itself to the workbench operation history.<span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span class=SpellE><span style='font-size:10.0pt;font-family: Arial'>IUndoManager</span></span><span style='font-size:10.0pt;font-family: Arial'> API could be mapped as follows:<o:p></o:p></span></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>connect(</span></b></span><span class=SpellE><b style='mso-bidi-font-weight:normal'><span style='font-size: 10.0pt;font-family:Arial'>ITextViewer</span></b></span><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>) <o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Creates a context (<span class=SpellE>myContext</span>) appropriate for representing this document’s operations<o:p></o:p></span></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>disconnect(</span></b></span><span class=SpellE><b style='mso-bidi-font-weight:normal'><span style='font-size: 10.0pt;font-family:Arial'>ITextViewer</span></b></span><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>) <o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Performs necessary disconnect behavior and clears the operation history of operations involving the viewer.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in'><span class=SpellE><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>operationHistory.disposeAll</span></span></span><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>(</span></span><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>myContext</span></span><span style='font-size:10.0pt;font-family:Arial'>);<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>beginCompoundChange</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'> <o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Creates a <span class=SpellE>CompoundOperation</span> and stores subsequent <span class=SpellE>TextCommands</span> in this operation.<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>endCompoundChange</span></b></span></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span class=GramE><span style='font-size:10.0pt;font-family: Arial'>Adds the current compound operation to the operation history.</span></span><span style='font-size:10.0pt;font-family:Arial'><o:p></o:p></span></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>reset()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span class=GramE><span style='font-size:10.0pt;font-family: Arial'>Clears the operation history of operations involving the viewer.</span></span><span style='font-size:10.0pt;font-family:Arial'><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><span class=SpellE><span class=GramE>operationHistory.disposeAll</span></span><span class=GramE>(</span><span class=SpellE>myContext</span>);<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>setMaximumUndoLevel</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><span class=SpellE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>int</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'>) – TBD<o:p></o:p></span></b></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>undoable()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'> <o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Maps as follows:<o:p></o:p></span></p> <p class=MsoNormal style='text-indent:.5in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>status</span></span><span style='font-size:10.0pt;font-family:Arial'> = <span class=SpellE>operationHistory.canUndoIn</span>(<span class=SpellE>myContext</span>);<o:p></o:p></span></p> <p class=MsoNormal style='text-indent:.5in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>return</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>status.isOK</span>();<span style='mso-spacerun:yes'> </span>// may require further checking of other cases<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>redoable</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'> <o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Maps as follows:<o:p></o:p></span></p> <p class=MsoNormal style='text-indent:.5in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>status</span></span><span style='font-size:10.0pt;font-family:Arial'> = <span class=SpellE>operationHistory.canRedoIn</span>(<span class=SpellE>myContext</span>);<o:p></o:p></span></p> <p class=MsoNormal style='text-indent:.5in'><span class=GramE><span style='font-size:10.0pt;font-family:Arial'>return</span></span><span style='font-size:10.0pt;font-family:Arial'> <span class=SpellE>status.isOK</span>();<span style='mso-spacerun:yes'> </span>// may require further checking of other cases<o:p></o:p></span></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>undo()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Use <span class=SpellE><span class=GramE>operationHistory.performUndoFor</span></span><span class=GramE>(</span><span class=SpellE>myContext</span>) instead of managing its own stack.<o:p></o:p></span></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>redo()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Use <span class=SpellE><span class=GramE>operationHistory.performRedoFor</span></span><span class=GramE>(</span><span class=SpellE>myContext</span>) instead of managing its own stack.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The <span class=SpellE>TextCommand</span> class is private, so no API mapping is discussed here.<span style='mso-spacerun:yes'> </span>However, its protocol is very similar to <span class=SpellE>IOperation</span> and the reimplementation/mapping is straightforward.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Issues:<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>As discussed throughout this document, additional operations (such as compound operations or <span class=SpellE>refactoring</span> operations) might appear in the text viewer’s context, and therefore in its <span class=SpellE>IUndoManager</span>.<span style='mso-spacerun:yes'> </span>The implementation should be checked for any assumptions that the current operation is a <span class=SpellE>TextCommand</span>.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.5in;text-indent:-.25in;mso-list:l21 level1 lfo1; tab-stops:list .5in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=SpellE><span style='font-size:10.0pt; font-family:Arial'>IUndoManager</span></span><span style='font-size:10.0pt; font-family:Arial'> currently keeps a local history limit.<span style='mso-spacerun:yes'> </span>How do we handle this?<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.75in;text-indent:-.25in;mso-list:l17 level1 lfo20; tab-stops:list .75in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>allow local history limits per context (seems complicated)<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.75in;text-indent:-.25in;mso-list:l17 level1 lfo20; tab-stops:list .75in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>ignore this part of the API in the new world<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.75in;text-indent:-.25in;mso-list:l17 level1 lfo20; tab-stops:list .75in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>decide how to affect the global history limit based on the local limit<o:p></o:p></span></p> <h4><span class=SpellE>Refactoring</span> </h4> <p class=MsoNormal><span class=SpellE><span style='font-size:10.0pt;font-family: Arial'>Refactoring</span></span><span style='font-size:10.0pt;font-family:Arial'> undo is currently implemented with change objects<span class=GramE>,<span style='mso-spacerun:yes'> </span>Change</span> objects record workspace changes initiated by <span class=SpellE>refactoring</span> operations.<span style='mso-spacerun:yes'> </span>When a <span class=SpellE>refactoring</span> change is performed, it can optionally return another change that could be used to undo the change just executed.<span style='mso-spacerun:yes'> </span>The undo change is placed in <span class=SpellE>refactoring’s</span> <span class=SpellE>IUndoManager</span>.<span style='mso-spacerun:yes'> </span>Changes can be performed, but any undo or redo causes a new change to be created vs. having each change know how to undo and redo itself. <o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>While this approach simplifies the protocol for an operation, it has not been used in the proposed framework for several reasons:<o:p></o:p></span></p> <ol style='margin-top:0in' start=1 type=1> <li class=MsoNormal style='mso-list:l12 level1 lfo27;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>It is not compatible with the implementation used by text, EMF, or GEF. <o:p></o:p></span></li> <li class=MsoNormal style='mso-list:l12 level1 lfo27;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>It causes additional operations to be created before an undo is ever requested.<span style='mso-spacerun:yes'> </span>This violates the goal of “pay as you go.”<o:p></o:p></span></li> </ol> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Additional protocol is provided for initializing data needed to do a live validation for execution.<span style='mso-spacerun:yes'> </span>Validation can be done with this cached information or on the fly.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Protocol is also provided to return the object modified by a change (<span class=SpellE><span class=GramE>getModifiedElement</span></span><span class=GramE>(</span>)).<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The Change API could be mapped as follows.<span style='mso-spacerun:yes'> </span>Note that much of the protocol could be provided in an abstract “<span class=SpellE>RefactoringOperation</span>” or perhaps in a more generic “<span class=SpellE>WorkspaceOperation</span>.”<span style='mso-spacerun:yes'> </span>However we do not promote these concepts to the framework since different kinds of operations have different needs for caching model objects, validation state, etc.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>getModifiedElement</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'> <o:p></o:p></span></b></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>getAdapter</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Class)<o:p></o:p></span></b></p> <p class=MsoNormal><span class=SpellE><span style='font-size:10.0pt;font-family: Arial'>Refactoring</span></span><span style='font-size:10.0pt;font-family:Arial'> changes need to know which model element is modified by the change.<span style='mso-spacerun:yes'> </span>They must also implement <span class=SpellE>IAdaptable</span>.<span style='mso-spacerun:yes'> </span>This protocol can be provided in an abstract <span class=SpellE>RefactoringOperation</span> and interpreted by individual subclasses as done today.<span style='mso-spacerun:yes'> </span>This protocol might in fact be suitable for all workspace-affecting operations.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>getParent</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>setParent</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Change)<o:p></o:p></span></b></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>isEnabled</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>setEnabled</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><span class=SpellE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>boolean</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'>)<o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The associated fields and protocol can be defined in an abstract class. <o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>initializeValidationData</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><span class=SpellE><span style='font-size:10.0pt;font-family:Arial'>IProgressMonitor</span></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'>)<o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>This hook allows changes to cache local validation data, or to hook up listeners to the model and listen for changes that may invalidate the change.<span style='mso-spacerun:yes'> </span>This protocol could be provided in the abstract <span class=SpellE>refactoring</span> class. <o:p></o:p></span></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>dispose()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span class=GramE><span style='font-size:10.0pt;font-family: Arial'>Maps directly.</span></span><span style='font-size:10.0pt;font-family: Arial'><o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>getName</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Maps to <span class=SpellE>operation.getLabel</span><o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>isValid</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><span class=SpellE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>IProgressMonitor</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'>)<o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Maps to <span class=SpellE><span class=GramE>canUndo</span></span><span class=GramE>(</span>), <span class=SpellE>canRedo</span>(), and <span class=SpellE>canExecute</span>().<span style='mso-spacerun:yes'> </span>See discussion below.<o:p></o:p></span></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>perform(</span></b></span><span class=SpellE><b style='mso-bidi-font-weight:normal'><span style='font-size: 10.0pt;font-family:Arial'>IProgressMonitor</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'>)<o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Maps to <span class=GramE>undo(</span><span class=SpellE>IProgressMonitor</span>), redo(<span class=SpellE>IProgressMonitor</span>) and <span class=SpellE>canExecute</span>(<span class=SpellE>IProgressMonitor</span>).<span style='mso-spacerun:yes'> </span>See discussion below.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Issues<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.75in;text-indent:-.25in;mso-list:l17 level1 lfo20; tab-stops:list .75in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span class=SpellE><span style='font-size:10.0pt; font-family:Arial'>Refactoring</span></span><span style='font-size:10.0pt; font-family:Arial'> change objects do not support direct <span class=GramE>undo(</span>) or redo().<span style='mso-spacerun:yes'> </span>Rather, a change that supports <span class=GramE>undo(</span>) returns a new change that “undoes” it whenever it is executed.<span style='mso-spacerun:yes'> </span>The code for <span class=SpellE>refactoring</span> changes would have to be <span class=SpellE>refactored</span> in one of these ways:<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:1.25in;text-indent:-.25in;mso-list:l17 level2 lfo20; tab-stops:list 1.25in'><![if !supportLists]><span style='font-size:10.0pt; font-family:"Courier New";mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>o<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Eliminate the creation of the undo change and move this work into an <span class=GramE>undo(</span>) method.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:1.25in;text-indent:-.25in;mso-list:l17 level2 lfo20; tab-stops:list 1.25in'><![if !supportLists]><span style='font-size:10.0pt; font-family:"Courier New";mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>o<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Continue to create the undo change when performing a change, but instead of returning it, cache it in the change itself.<span style='mso-spacerun:yes'> </span>Undo protocol checks for the presence of this change and uses it for any undo validation or execution requests.<o:p></o:p></span></p> <p class=MsoNormal style='margin-left:.75in;text-indent:-.25in;mso-list:l17 level1 lfo20; tab-stops:list .75in'><![if !supportLists]><span style='font-size:10.0pt; font-family:Arial;mso-fareast-font-family:Arial'><span style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span style='font-size:10.0pt;font-family:Arial'>Validation of <span class=SpellE>refactoring</span> changes is assumed to be expensive, so a progress monitor is provided in validation protocol.<span style='mso-spacerun:yes'> </span>This concept is not promoted to the framework since validity is checked when building the undo menu command.<span style='mso-spacerun:yes'> </span>Is the progress monitor absolutely necessary for validation vs. execution?<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>It is likely that many views and editors in the workbench IDE will be aware of this special kind of <span class=SpellE>IOperation</span>. <span style='mso-spacerun:yes'> </span>An additional interface, <span class=SpellE>IWorkspaceOperation</span>, may evolve as <span class=SpellE>refactoring</span> changes are adapted to the new operations framework.<span style='mso-spacerun:yes'> </span>Patterns surrounding the workspace operation will develop, particularly involving operation contexts.<span style='mso-spacerun:yes'> </span>For example, views and editors (such as text editors) that are workspace-aware could listen to the operations history.<span style='mso-spacerun:yes'> </span>As new workspace operations are added to the history, the modified element can be queried by the listener.<span style='mso-spacerun:yes'> </span>The listener can add its operation context to the operation if desired.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <h4>GEF</h4> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>GEF supplies a Command framework and a <span class=SpellE>CommandStack</span> which manages an internal undo and redo stack.<span style='mso-spacerun:yes'> </span>Commands are pushed onto the stack when they are executed by the stack.<span style='mso-spacerun:yes'> </span>Most GEF command protocol can be mapped to the proposed operation protocol.<span style='mso-spacerun:yes'> </span>The GEF commands are very similar to <span class=SpellE>IOperation</span> without the notion of contexts.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Issues for GEF arise in the differences between <span class=SpellE>GEF’s</span> command stack and the proposed operation history.<span style='mso-spacerun:yes'> </span>We assume that GEF intends for GEF commands to coexist with other workbench operations in a shared undo history.<span style='mso-spacerun:yes'> </span>If so, then the command stack must be replaced by the operation history.<span style='mso-spacerun:yes'> </span>Issues include:<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>isDirty</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>markSaveLocation</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>()</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'><o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>GEF supports a marker (<span class=SpellE>saveLocation</span>) that becomes dirty if any commands are added after the mark is made.<span style='mso-spacerun:yes'> </span>If this concept is still needed in light of the new framework, then GEF might have to mark the location inside its own commands or using a dummy marker command.<o:p></o:p></span></p> <p class=MsoNormal><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>execute(</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'>Command)<o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The GEF command stack executes commands on behalf of the client and adds them to the stack, while the operation history does not do the execution on behalf of the client.<span style='mso-spacerun:yes'> </span>GEF clients that create GEF commands would alter the pattern “<span class=SpellE><span class=GramE>commandStack.execute</span></span><span class=GramE>(</span><span class=SpellE>someCommand</span>)” to instead use “<span class=SpellE>someCommand.execute</span>(null); <span class=SpellE>operationHistory.add</span>(<span class=SpellE>someCommand</span>)”<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>addCommandStackListener</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><span class=SpellE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>CommandStackListener</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family: Arial'>)<o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>GEF is evolving its <span class=SpellE>CommandListener</span> interface in R3.1 to include additional notification.<span style='mso-spacerun:yes'> </span>This must be reconciled with the proposed support in <span class=SpellE>IOperationHistoryListener</span> and the ability to further validate commands using <span class=SpellE>IOperationApproval</span>.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <h4>EMF/WTP</h4> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The EMF command framework is very similar to the GEF support and has similar issues to those described above.<span style='mso-spacerun:yes'> </span>Additional issues arise for:<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>getResult</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>);<o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>This method answers the result of command execution when the command is in certain states.<span style='mso-spacerun:yes'> </span>Since clients can execute an operation explicitly in the framework, EMF code could query the result after execution and store it in an EMF abstract operation.<span style='mso-spacerun:yes'> </span>This protocol could then be provided in the EMF operations.<o:p></o:p></span></p> <p class=MsoNormal><span class=SpellE><span class=GramE><b style='mso-bidi-font-weight: normal'><span style='font-size:10.0pt;font-family:Arial'>getAffectedObjects</span></b></span></span><span class=GramE><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt; font-family:Arial'>(</span></b></span><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>);<o:p></o:p></span></b></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>This method is used to highlight the appropriate objects in a view to show what the EMF command did.<span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'> </span>It is not clear that this will be generally necessary.<span style='mso-spacerun:yes'> </span>This protocol could be added in an EMF operation abstract class.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>As discussed with <span class=SpellE>refactoring</span> changes, an abstract class providing the mapped protocol will likely evolve, along with usage patterns for listening for new EMF operations and assigning appropriate operation contexts. <o:p></o:p></span></p> <b><span style='font-size:16.0pt;font-family:Arial;mso-fareast-font-family: "Times New Roman";mso-font-kerning:16.0pt;mso-ansi-language:EN-US;mso-fareast-language: EN-US;mso-bidi-language:AR-SA'><br clear=all style='page-break-before:always'> </span></b> <h1>Appendix A:<span style='mso-spacerun:yes'> </span>Workbench Undo Scenarios<span style='font-size:10.0pt'><o:p></o:p></span></h1> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The following scenarios were used while discussing possible designs for a common undo framework.<span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'> </span>Most of these scenarios involve conflicting contexts or scopes.<span style='mso-spacerun:yes'> </span>These scenarios, involving mixed text edits and <span class=SpellE>refactoring</span> operations, have complicated previous efforts to define a common undo framework.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>The scenarios assume that an integrated undo in the workbench should present a common “Undo” command rather than the separate commands employed today, and that the “Undo” command is descriptive enough to imply the operation that will take place.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>For each scenario described, we attempt to describe the desired outcome, the outcome in R3.0.1 where applicable, and any interesting alternative outcomes. <o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Note that some scenarios involve nearly the same user interactions, but are different in desired outcome based on what the user was trying to accomplish while performing the operations.<span style='mso-spacerun:yes'> </span>Specific user intent is described in order to clarify the scenario.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Scenario #1:</span></b><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span>User is editing source file “A.”<span style='mso-spacerun:yes'> </span>While editing the document, some interrupt occurs causing the user to go to the navigator and <span class=SpellE>refactor</span> some code unrelated to A.<span style='mso-spacerun:yes'> </span>When the <span class=SpellE>refactoring</span> is complete, the user returns to the editor on “A” and notices a typo.<span style='mso-spacerun:yes'> </span>The user selects Edit>Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Desired Outcome:<span style='mso-spacerun:yes'> </span>The last text editing operation made before the unrelated <span class=SpellE>refactoring</span> operation is undone.<span style='mso-spacerun:yes'> </span>The typo is corrected.<span style='mso-spacerun:yes'> </span>The undo command was described as “undo typing”<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>R3.0.1 Outcome:<span style='mso-spacerun:yes'> </span>Desired Outcome.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Proposal Outcome:<span style='mso-spacerun:yes'> </span>Desired Outcome.<span style='mso-spacerun:yes'> </span>(Unrelated <span class=SpellE>refactoring</span> operation did not have the editor’s context).<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Scenario #2:</span></b><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span>User is editing source file “A.”<span style='mso-spacerun:yes'> </span>While editing the document, some interrupt occurs causing the user to go to the navigator and <span class=SpellE>refactor</span> some code.<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactoring</span> operation updates references to the <span class=SpellE>refactored</span> code in file “A.”<span style='mso-spacerun:yes'> </span>When the <span class=SpellE>refactoring</span> is complete, the user returns to the editor on “A” and notices a typo.<span style='mso-spacerun:yes'> </span>The user selects Edit>Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Desired Outcome:<span style='mso-spacerun:yes'> </span>This scenario depends largely on the user’s intent.<span style='mso-spacerun:yes'> </span>If the typo was in a location completely unrelated to the <span class=SpellE>refactor</span>, the user expects the last text editing operation made before the <span class=SpellE>refactoring</span> operation to be undone, correcting the typo.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>R3.0.1 Outcome:<span style='mso-spacerun:yes'> </span>The text edit caused by the <span class=SpellE>refactoring</span> operation is undone, but the <span class=SpellE>refactoring</span> itself is not undone.<span style='mso-spacerun:yes'> </span>The typo remains until the user invokes subsequent “Undo.”<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Proposal Outcome:<span style='mso-spacerun:yes'> </span>This outcome can be implemented in different ways.<span style='mso-spacerun:yes'> </span>If the <span class=SpellE>refactoring</span> operation command is assigned the context for “A,” since A was affected, then the <span class=SpellE>refactoring</span> operation would be undone before the typo.<span style='mso-spacerun:yes'> </span>However, the editor could notice that the operation has multiple contexts and prompt the user with an operation history.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Scenario #3:</span></b><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span>User is editing source file “A.”<span style='mso-spacerun:yes'> </span>While editing the document, some interrupt occurs causing the user to go to the navigator and <span class=SpellE>refactor</span> some code.<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactoring</span> operation updates references to the <span class=SpellE>refactored</span> code in file “A.”<span style='mso-spacerun:yes'> </span>When the <span class=SpellE>refactoring</span> is complete, the user recalls making a typo just before the <span class=SpellE>refactor</span>.<span style='mso-spacerun:yes'> </span>The user returns to the editor on “A” and looks for the typo.<span style='mso-spacerun:yes'> </span>It is not there, as it has been replaced with new code due to the <span class=SpellE>refactoring</span> operation. The user selects Edit>Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Desired Outcome:<span style='mso-spacerun:yes'> </span>At this point, the user needs information that helps explain the disappearance of the typo.<span style='mso-spacerun:yes'> </span>In this case, there are two helpful options:<o:p></o:p></span></p> <ol style='margin-top:0in' start=1 type=1> <li class=MsoNormal style='mso-list:l16 level1 lfo5;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>The last performed <span class=SpellE>refactoring</span> operation is undone.<span style='mso-spacerun:yes'> </span>This returns the user to the typo, in effect showing why the typo had disappeared.<span style='mso-spacerun:yes'> </span>The user then selects “Redo,” having been satisfied that the typo was corrected by the <span class=SpellE>refactoring</span> operation.<span style='mso-spacerun:yes'> </span>This operation is somewhat “<span class=GramE>heavyweight</span>,” but one could argue that it’s the more expected outcome.<o:p></o:p></span></li> <li class=MsoNormal style='mso-list:l16 level1 lfo5;tab-stops:list .5in'><span style='font-size:10.0pt;font-family:Arial'>The text edit caused by the <span class=SpellE>refactoring</span> is undone, exposing the typo and, in effect, showing why it’s gone.<span style='mso-spacerun:yes'> </span>The user then selects “Redo,” having been satisfied that the typo was already corrected by the <span class=SpellE>refactoring</span> operation. <span style='mso-spacerun:yes'> </span>This is a “lighter weight” solution but perhaps more confusing.<o:p></o:p></span></li> </ol> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>R3.0.1 Outcome:<span style='mso-spacerun:yes'> </span>Desired Outcome #2.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Proposal outcome:<span style='mso-spacerun:yes'> </span>Desired Outcome #1.<span style='mso-spacerun:yes'> </span>This scenario is the same as scenario #2 except for user intent, so the UI could present similar choices as described above.<span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Scenario #4:</span></b><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span>User is editing source file “A” and considers renaming a method in “A.”<span style='mso-spacerun:yes'> </span>While typing a new name for the method, the user realizes that a <span class=SpellE>refactoring</span> operation will simplify the editing process.<span style='mso-spacerun:yes'> </span>The user chooses “<span class=SpellE>Refactor</span>>Rename” to rename the method.<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactor</span> causes references to be updated in other files.<span style='mso-spacerun:yes'> </span>The user then decides that the rename was not appropriate.<span style='mso-spacerun:yes'> </span>The user selects Edit>Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Desired Outcome:<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactoring</span> operation is undone, updating all of the references. The user is returned to the typing state before the <span class=SpellE>refactor</span>.<span style='mso-spacerun:yes'> </span>Selecting another Edit>Undo will undo the typing of the new name and return to the old name. <o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>R3.0.1 Outcome:<span style='mso-spacerun:yes'> </span>The text edit implied by the <span class=SpellE>refactoring</span> operation is undone, and the user is returned to the typing state before the <span class=SpellE>refactor</span>.<span style='mso-spacerun:yes'> </span>However, the <span class=SpellE>refactoring</span> itself is not undone.<span style='mso-spacerun:yes'> </span>This is undoable from a separate <span class=SpellE>Refactor</span>>Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Proposal outcome:<span style='mso-spacerun:yes'> </span>Desired Outcome.<span style='mso-spacerun:yes'> </span>A user prompt or verification may occur as discussed in other scenarios.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Scenario #5:</span></b><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span>User is editing source file “A” and considers renaming a method in “A.”<span style='mso-spacerun:yes'> </span>The user decides that a <span class=SpellE>refactoring</span> operation is in order.<span style='mso-spacerun:yes'> </span>The user chooses “<span class=SpellE>Refactor</span>>Rename” to rename the method.<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactor</span> causes references to be updated in other files.<span style='mso-spacerun:yes'> </span>The user then makes additional edits to the <span class=SpellE>javadoc</span> for the renamed method and realizes that the rename was not appropriate.<span style='mso-spacerun:yes'> </span>The user selects Edit>Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Desired Outcome:<span style='mso-spacerun:yes'> </span>The most recent editing changes to the <span class=SpellE>javadoc</span> are undone.<span style='mso-spacerun:yes'> </span>The user can continue selecting “Undo” until the <span class=SpellE>refactoring</span> operation is undone, updating all of the references. <o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>R3.0.1 Outcome:<span style='mso-spacerun:yes'> </span>The most recent editing changes to the <span class=SpellE>javadoc</span> are undone.<span style='mso-spacerun:yes'> </span>The user can continue selecting “Undo” until the text edit implied by the <span class=SpellE>refactoring</span> operation is undone.<span style='mso-spacerun:yes'> </span>However, the <span class=SpellE>refactoring</span> itself is not undone.<span style='mso-spacerun:yes'> </span>This is undoable from a separate <span class=SpellE>Refactor</span>>Undo.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Proposal outcome:<span style='mso-spacerun:yes'> </span>Desired Outcome.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span style='font-size:10.0pt;font-family:Arial'>Scenario #6:</span></b><span style='font-size:10.0pt;font-family:Arial'><span style='mso-spacerun:yes'> </span>User is editing source file “A” and considers renaming a method in “A.”<span style='mso-spacerun:yes'> </span>The user decides that a <span class=SpellE>refactoring</span> operation is in order.<span style='mso-spacerun:yes'> </span>The user chooses “<span class=SpellE>Refactor</span>>Rename” to rename the method.<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactor</span> causes references to be updated in other files.<span style='mso-spacerun:yes'> </span>The user then proceeds to edit <span class=SpellE>javadoc</span> in another part of the file, unrelated to change.<span style='mso-spacerun:yes'> </span>The user realizes the <span class=SpellE>refactor</span> was not appropriate, and not wanting to undo the edits to the <span class=SpellE>javadoc</span>, selects the navigator view, and selects Edit>Undo, assuming that the navigator undo won’t affect local edit changes.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><span style='mso-tab-count:1'> </span><o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Desired Outcome:<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactoring</span> operation is undone, but the changes to the <span class=SpellE>javadoc</span> made afterward are not undone.<span style='mso-spacerun:yes'> </span>The local changes to file “A” could only be undone while inside editor A.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>R3.0.1 Outcome:<span style='mso-spacerun:yes'> </span>The <span class=SpellE>refactoring</span> operation is undone, and the most recent changes to the file are lost.<o:p></o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'><o:p> </o:p></span></p> <p class=MsoNormal><span style='font-size:10.0pt;font-family:Arial'>Proposal outcome:<span style='mso-spacerun:yes'> </span>This can be implemented in different ways with <span class=SpellE>IOperationApproval</span>.<span style='mso-spacerun:yes'> </span>The operation history would notice that the chosen operation has context “A” and that later changes for “<span class=GramE>A</span>” are in the history.<span style='mso-spacerun:yes'> </span>The <span class=SpellE>IOperationApproval</span> assigned to context “A” could prompt the user as to whether to undo the more recent changes in “A.”<o:p></o:p></span></p> <p class=MsoNormal style='text-align:justify'><span style='font-size:10.0pt; font-family:Arial'><o:p> </o:p></span></p> </div> <div style='mso-element:footnote-list'><![if !supportFootnotes]><br clear=all> <hr align=left size=1 width="33%"> <![endif]> <div style='mso-element:footnote' id=ftn1> <p class=MsoNormal><a style='mso-footnote-id:ftn1' href="#_ftnref1" name="_ftn1" title=""><span class=MsoFootnoteReference><span style='mso-special-character: footnote'><![if !supportFootnotes]><span class=MsoFootnoteReference><span style='font-size:12.0pt;font-family:"Times New Roman";mso-fareast-font-family: "Times New Roman";mso-ansi-language:EN-US;mso-fareast-language:EN-US; mso-bidi-language:AR-SA'>[1]</span></span><![endif]></span></span></a> <span style='font-size:10.0pt;font-family:Arial'>Literature addressing multi-user undo [<span class=SpellE>Abowd</span> & Dix] addresses similar scoping issues in a multi-user model.<span style='mso-spacerun:yes'> </span>Collaborating users may expect a global undo scope while users working in separate contexts may not.<span style='mso-spacerun:yes'> </span>Users may be moving between collaboration and separation in a single work session, and the system cannot detect which is the case.<span style='mso-spacerun:yes'> </span>Undo implementations in these systems typically keep track of the user who initiated the operation within a global history and filter the history appropriately.<span style='mso-spacerun:yes'> </span>Potential conflicts are brought to the attention of the user(s).<o:p></o:p></span></p> <p class=MsoFootnoteText><o:p> </o:p></p> </div> </div> </body> </html>
| help@eclipse.org | ViewVC Help |
| Powered by ViewVC 1.0.3 |
