2019-08-23 11:56:54 -07:00
using System ;
2020-04-29 06:40:03 -07:00
using System.Collections ;
2019-08-23 11:56:54 -07:00
using System.Text ;
using System.Threading.Tasks ;
using IDE.ui ;
using System.Diagnostics ;
namespace IDE
{
public class TrackedTextElement
{
public int mRefCount = 1 ;
public bool mIsDead ;
public String mFileName ~ delete _ ;
public int32 mLineNum ;
public int32 mColumn ;
public bool mSnapToLineStart = true ;
public int32 mMoveIdx ; // Increments when we manually move an element (ie: a history location updating because the user types near the previous history location)
public virtual void Move ( int wantLineNum , int wantColumn )
{
mLineNum = ( int32 ) wantLineNum ;
mColumn = ( int32 ) wantColumn ;
}
public virtual void Kill ( )
{
mIsDead = true ;
Deref ( ) ;
}
public void AddRef ( )
{
mRefCount + + ;
}
public void Deref ( )
{
if ( - - mRefCount = = 0 )
delete this ;
}
public ~ this ( )
{
Debug . Assert ( mRefCount = = 0 ) ;
}
}
public class Bookmark : TrackedTextElement
2022-06-08 20:11:39 +02:00
{
public String mTitle ~ delete _ ;
2019-08-23 11:56:54 -07:00
public String mNotes ~ delete _ ;
2022-06-08 20:11:39 +02:00
public bool mIsDisabled ;
2022-06-09 12:25:48 +02:00
public BookmarkFolder mFolder ;
2019-08-23 11:56:54 -07:00
}
2022-06-09 12:25:48 +02:00
public class BookmarkFolder
{
/// The title of the bookmark-folder that will be visible in the bookmark-panel
public String mTitle ~ delete _ ;
public List < Bookmark > mBookmarkList = new List < Bookmark > ( ) ~
{
2019-08-23 11:56:54 -07:00
for ( var bookmark in mBookmarkList )
bookmark . Kill ( ) ;
2022-06-09 12:25:48 +02:00
gApp . mDebugger . mBreakpointsChangedDelegate ( ) ;
2019-08-23 11:56:54 -07:00
delete _ ;
2022-06-09 12:25:48 +02:00
} ;
/// Gets or Sets whether every bookmark in this folder is disabled or not.
public bool IsDisabled
{
get
{
for ( var bookmark in mBookmarkList )
if ( ! bookmark . mIsDisabled )
return false ;
return true ;
}
set
{
for ( var bookmark in mBookmarkList )
bookmark . mIsDisabled = value ;
gApp . mBookmarksPanel . mBookmarksDirty = true ;
}
}
/// Adds the given bookmark to this folder. If needed, removes it from its old folder.
public void AddBookmark ( Bookmark bookmark )
{
if ( bookmark . mFolder ! = null )
{
bookmark . mFolder . mBookmarkList . Remove ( bookmark ) ;
}
mBookmarkList . Add ( bookmark ) ;
bookmark . mFolder = this ;
//gApp.mBookmarksPanel.mBookmarksDirty = true;
}
}
public class BookmarkManager
{
public BookmarkFolder mRootFolder = new . ( ) ;
public List < BookmarkFolder > mBookmarkFolders = new . ( ) { mRootFolder } ~ DeleteContainerAndItems ! ( _ ) ;
private int mBookmarkCount ;
/// Index of the folder that was navigated to last
public int32 mFolderIdx ;
/// Index of the bookmark (inside of its folder) that was navigated to last
2019-08-23 11:56:54 -07:00
public int32 mBookmarkIdx ;
2022-06-08 20:11:39 +02:00
2022-06-09 12:25:48 +02:00
/// Number of bookmarks created, used to generate the names.
2022-06-08 20:11:39 +02:00
private int32 _createdBookmarks ;
2022-06-09 12:25:48 +02:00
/// Number of folders created, used to generate the names.
private int32 _createdFolders ;
/// Gets or sets whether all bookmarks are disabled or not.
2022-06-08 20:11:39 +02:00
public bool AllBookmarksDisabled
{
get
{
2022-06-09 12:25:48 +02:00
for ( var folder in mBookmarkFolders )
2022-06-08 20:11:39 +02:00
{
2022-06-09 12:25:48 +02:00
if ( ! folder . IsDisabled )
2022-06-08 20:11:39 +02:00
return false ;
}
return true ;
}
2022-06-09 12:25:48 +02:00
set
{
for ( var folder in mBookmarkFolders )
{
folder . IsDisabled = value ;
}
gApp . mBookmarksPanel . mBookmarksDirty = true ;
}
}
/ * *
* Creates a new bookmark folder
* @param title The title of the bookmark
* @returns the newly created BookmarkFolder
* /
public BookmarkFolder CreateFolder ( String title = null )
{
mBookmarkIdx = - 1 ;
BookmarkFolder folder = new . ( ) ;
if ( title = = null )
folder . mTitle = new $"Folder {_createdFolders++}" ;
else
folder . mTitle = new String ( title ) ;
mBookmarkFolders . Add ( folder ) ;
gApp . mBookmarksPanel . mBookmarksDirty = true ;
return folder ;
2022-06-08 20:11:39 +02:00
}
2022-06-09 12:25:48 +02:00
/// Deletes the given bookmark folder and all bookmarks inside it.
public void DeleteFolder ( BookmarkFolder folder )
2022-06-08 20:11:39 +02:00
{
2022-06-09 12:25:48 +02:00
int folderIdx = mBookmarkFolders . IndexOf ( folder ) ;
mBookmarkFolders . Remove ( folder ) ;
delete folder ;
// Select the previous folder
if ( mFolderIdx = = folderIdx )
folderIdx - - ;
if ( mFolderIdx > = mBookmarkFolders . Count )
mFolderIdx = ( int32 ) mBookmarkFolders . Count - 1 ;
// Select last bookmark inside the newly selected folder
if ( mBookmarkIdx > = mBookmarkFolders [ mFolderIdx ] . mBookmarkList . Count )
mBookmarkIdx = ( int32 ) mBookmarkFolders [ mFolderIdx ] . mBookmarkList . Count - 1 ;
gApp . mBookmarksPanel . mBookmarksDirty = true ;
}
public Bookmark CreateBookmark ( String fileName , int wantLineNum , int wantColumn , bool isDisabled = false , String title = null , BookmarkFolder folder = null )
{
var folder ;
folder = folder ? ? mRootFolder ;
mFolderIdx = ( int32 ) mBookmarkFolders . IndexOf ( folder ) ;
mBookmarkIdx = ( int32 ) folder . mBookmarkList . Count ;
2019-08-23 11:56:54 -07:00
Bookmark bookmark = new Bookmark ( ) ;
bookmark . mFileName = new String ( fileName ) ;
bookmark . mLineNum = ( int32 ) wantLineNum ;
bookmark . mColumn = ( int32 ) wantColumn ;
2022-06-08 20:11:39 +02:00
if ( title = = null )
bookmark . mTitle = new $"Bookmark {_createdBookmarks++}" ;
else
bookmark . mTitle = new String ( title ) ;
bookmark . mIsDisabled = isDisabled ;
2022-06-09 12:25:48 +02:00
folder . AddBookmark ( bookmark ) ;
2019-08-23 11:56:54 -07:00
gApp . mDebugger . mBreakpointsChangedDelegate ( ) ;
2022-06-08 20:11:39 +02:00
gApp . mBookmarksPanel . mBookmarksDirty = true ;
2022-06-09 12:25:48 +02:00
mBookmarkCount + + ;
2019-08-23 11:56:54 -07:00
return bookmark ;
}
2022-06-09 12:25:48 +02:00
/ * * Moves the bookmark to the specified folder .
* @param bookmark The bookmark to move .
* @param folder The folder to which the bookmark will be moved .
* @param insertBefore If null the bookmark will be added at the end of the folder . Otherwise it will be inserted before the specified bookmark .
* /
public void MoveBookmarkToFolder ( Bookmark bookmark , BookmarkFolder folder , Bookmark insertBefore = null )
{
if ( bookmark . mFolder ! = null )
{
bookmark . mFolder . mBookmarkList . Remove ( bookmark ) ;
}
if ( insertBefore = = null )
folder . mBookmarkList . Add ( bookmark ) ;
else
{
Debug . Assert ( folder = = insertBefore . mFolder , "Insert before must be in folder." ) ;
int index = folder . mBookmarkList . IndexOf ( insertBefore ) ;
folder . mBookmarkList . Insert ( index , bookmark ) ;
}
bookmark . mFolder = folder ;
FixupIndices ( ) ;
gApp . mBookmarksPanel . mBookmarksDirty = true ;
}
enum Placement
{
Before ,
After
}
public void MoveFolder ( BookmarkFolder folder , Placement place = . After , BookmarkFolder target = null )
{
if ( folder = = target )
return ;
if ( mBookmarkFolders . Contains ( folder ) )
mBookmarkFolders . Remove ( folder ) ;
if ( target = = null )
{
mBookmarkFolders . Add ( folder ) ;
}
else
{
int index = mBookmarkFolders . IndexOf ( target ) ;
if ( place = = . After )
index + + ;
mBookmarkFolders . Insert ( index , folder ) ;
}
FixupIndices ( ) ;
gApp . mBookmarksPanel . mBookmarksDirty = true ;
}
/// Make sure that the bookmark and folder indices are valid.
private void FixupIndices ( )
{
if ( mBookmarkIdx < = 0 | | mBookmarkIdx > = mBookmarkFolders [ mFolderIdx ] . mBookmarkList . Count )
{
mBookmarkIdx = 0 ;
// Don't have an empty folder selected
if ( mBookmarkFolders [ mFolderIdx ] . mBookmarkList . Count = = 0 )
mFolderIdx = 0 ;
}
}
2019-08-23 11:56:54 -07:00
public void DeleteBookmark ( Bookmark bookmark )
{
2022-06-09 12:25:48 +02:00
BookmarkFolder folder = bookmark . mFolder ;
folder . mBookmarkList . Remove ( bookmark ) ;
FixupIndices ( ) ;
gApp . mDebugger . mBreakpointsChangedDelegate ( ) ;
2019-08-23 11:56:54 -07:00
bookmark . Kill ( ) ;
2022-06-08 20:11:39 +02:00
gApp . mBookmarksPanel . mBookmarksDirty = true ;
2022-06-09 12:25:48 +02:00
mBookmarkCount - - ;
2019-08-23 11:56:54 -07:00
}
public void Clear ( )
{
2022-06-09 12:25:48 +02:00
for ( var folder in mBookmarkFolders )
{
for ( var bookmark in folder . mBookmarkList )
bookmark . Kill ( ) ;
folder . mBookmarkList . Clear ( ) ;
}
ClearAndDeleteItems ! ( mBookmarkFolders ) ;
mRootFolder = new BookmarkFolder ( ) ;
mBookmarkFolders . Add ( mRootFolder ) ;
mFolderIdx = 0 ;
2019-08-23 11:56:54 -07:00
mBookmarkIdx = 0 ;
gApp . mDebugger . mBreakpointsChangedDelegate ( ) ;
2022-06-08 20:11:39 +02:00
gApp . mBookmarksPanel . mBookmarksDirty = true ;
2019-08-23 11:56:54 -07:00
}
2022-06-09 12:25:48 +02:00
public void PrevBookmark ( bool currentFolderOnly = false )
2019-08-23 11:56:54 -07:00
{
2022-06-09 12:25:48 +02:00
if ( mBookmarkCount = = 0 )
return ;
2019-08-23 11:56:54 -07:00
2022-06-09 12:25:48 +02:00
int32 currentFolderIdx = mFolderIdx ;
int32 currentBookmarkIdx = mBookmarkIdx ;
2022-06-08 20:11:39 +02:00
2022-06-09 12:25:48 +02:00
Bookmark nextBookmark = null ;
2022-06-08 20:11:39 +02:00
repeat
{
2022-06-09 12:25:48 +02:00
mBookmarkIdx + + ;
if ( mBookmarkIdx > = mBookmarkFolders [ mFolderIdx ] . mBookmarkList . Count )
{
if ( ! currentFolderOnly )
{
mFolderIdx + + ;
if ( mFolderIdx > = mBookmarkFolders . Count )
{
// wrap to first folder
mFolderIdx = 0 ;
}
}
// Select first bookmark in current folder (or -1 if there is no bookmark)
mBookmarkIdx = mBookmarkFolders [ mFolderIdx ] . mBookmarkList . IsEmpty ? - 1 : 0 ;
}
if ( mBookmarkIdx > = 0 )
nextBookmark = mBookmarkFolders [ mFolderIdx ] . mBookmarkList [ mBookmarkIdx ] ;
else
nextBookmark = null ;
2022-06-08 20:11:39 +02:00
}
// skip disabled bookmarks, stop when we reach starting point
2022-06-09 12:25:48 +02:00
while ( ( nextBookmark = = null | | nextBookmark . mIsDisabled ) & & ( ( currentFolderIdx ! = mFolderIdx ) | | ( currentBookmarkIdx ! = mBookmarkIdx ) & & mBookmarkIdx ! = - 1 ) ) ;
2019-08-23 11:56:54 -07:00
2022-06-09 12:25:48 +02:00
// If nextBookmark is disabled no bookmark is enabled.
if ( nextBookmark ! = null & & ! nextBookmark . mIsDisabled )
GotoBookmark ( nextBookmark ) ;
2019-08-23 11:56:54 -07:00
}
2022-06-09 12:25:48 +02:00
public void NextBookmark ( bool currentFolderOnly = false )
2019-08-23 11:56:54 -07:00
{
2022-06-09 12:25:48 +02:00
if ( mBookmarkCount = = 0 )
return ;
2019-08-23 11:56:54 -07:00
2022-06-09 12:25:48 +02:00
int32 currentFolderIdx = mFolderIdx ;
int32 currentBookmarkIdx = mBookmarkIdx ;
2022-06-08 20:11:39 +02:00
2022-06-09 12:25:48 +02:00
Bookmark nextBookmark = null ;
2019-08-23 11:56:54 -07:00
2022-06-08 20:11:39 +02:00
repeat
{
mBookmarkIdx - - ;
2022-06-09 12:25:48 +02:00
2022-06-08 20:11:39 +02:00
if ( mBookmarkIdx < 0 )
2022-06-09 12:25:48 +02:00
{
if ( ! currentFolderOnly )
{
mFolderIdx - - ;
if ( mFolderIdx < 0 )
{
// wrap to last folder
mFolderIdx = ( int32 ) mBookmarkFolders . Count - 1 ;
}
}
// Select last bookmark in current folder
mBookmarkIdx = ( int32 ) mBookmarkFolders [ mFolderIdx ] . mBookmarkList . Count - 1 ;
}
2022-06-08 20:11:39 +02:00
2022-06-09 12:25:48 +02:00
if ( mBookmarkIdx > = 0 )
nextBookmark = mBookmarkFolders [ mFolderIdx ] . mBookmarkList [ mBookmarkIdx ] ;
else
nextBookmark = null ;
2022-06-08 20:11:39 +02:00
}
// skip disabled bookmarks, stop when we reach starting point
2022-06-09 12:25:48 +02:00
while ( ( nextBookmark = = null | | nextBookmark . mIsDisabled ) & & ( ( currentFolderIdx ! = mFolderIdx ) | | ( currentBookmarkIdx ! = mBookmarkIdx ) & & mBookmarkIdx ! = - 1 ) ) ;
2022-06-08 20:11:39 +02:00
2022-06-09 12:25:48 +02:00
// If nextBookmark is disabled no bookmark is enabled.
if ( nextBookmark ! = null & & ! nextBookmark . mIsDisabled )
GotoBookmark ( nextBookmark ) ;
2019-08-23 11:56:54 -07:00
}
2022-06-08 20:11:39 +02:00
public void GotoBookmark ( Bookmark bookmark )
{
2022-06-09 12:25:48 +02:00
mFolderIdx = ( int32 ) mBookmarkFolders . IndexOf ( bookmark . mFolder ) ;
mBookmarkIdx = ( int32 ) bookmark . mFolder . mBookmarkList . IndexOf ( bookmark ) ;
2022-06-08 20:11:39 +02:00
gApp . ShowSourceFileLocation ( bookmark . mFileName , - 1 , - 1 , bookmark . mLineNum , bookmark . mColumn , LocatorType . Smart ) ;
}
2019-08-23 11:56:54 -07:00
}
}