Переглянути джерело

页面编辑-补充粘贴undo redo操作,跟注释页undo 统一记录

ZhouJieSheng 1 рік тому
батько
коміт
e852da9294

+ 26 - 3
PDF Office/Model/PageEdit/PageEditHistory.cs

@@ -1,4 +1,6 @@
-using System;
+using ComPDFKitViewer;
+using PDF_Master.ViewModels.PageEdit;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -7,7 +9,7 @@ using System.Windows;
 
 namespace PDF_Master.Model.PageEdit
 {
-    public class PageEditHistory
+    public class PageEditHistory:IHistory
     {
         /// <summary>
         /// 操作类型
@@ -43,6 +45,23 @@ namespace PDF_Master.Model.PageEdit
         /// 插入的页面尺寸大小
         /// </summary>
         public Size PageSize { get; set; }
+
+        /// <summary>
+        /// 为方便处理 暂时直接调用页面编辑部分的undo redo 方法
+        /// </summary>
+        public PageEditContentViewModel viewmodel { get; set; }
+
+        public bool Redo()
+        {
+            viewmodel.Redo(this);
+            return true;
+        }
+
+        public bool Undo()
+        {
+            viewmodel.Undo(this);
+            return true;
+        }
     }
 
     /// <summary>
@@ -73,7 +92,11 @@ namespace PDF_Master.Model.PageEdit
         /// <summary>
         /// 倒序
         /// </summary>
-        Reverse
+        Reverse,
+        /// <summary>
+        /// 粘贴
+        /// </summary>
+        Paste
 
     }
 }

+ 16 - 16
PDF Office/Model/SettingsDialog/AnnotateModel.cs

@@ -296,22 +296,22 @@ namespace PDF_Master.Model.SettingsDialog
         /// </summary>
         public void Reset()
         {
-            var annote = new AnnotatePropertyClass();
-            this.HighLightColor = annote.HighLightColor;
-            this.UnderLineColor = annote.UnderLineColor;
-            this.StrikethroughColor = annote.StrikethroughColor;
-            this.FreeHandColor = annote.FreeHandColor;
-            this.TextAnnoteColor = annote.TextAnnoteColor;
-            this.NoteAnnoteColor = annote.NoteAnnoteColor;
-            this.RectangleBorderColor = annote.RectangleBorderColor;
-            this.RectangleFillColor = annote.RectangleFillColor;
-            this.CircleBorderColor = annote.CircleBorderColor;
-            this.CircleFillColor = annote.CircleFillColor;
-            this.LineColor = annote.LineColor;
-            this.ArrowColor = annote.ArrowColor;
-            this.TextFontFamaily = annote.TextFontFamaily;
-            this.AnchoredFamaily = annote.AnchoredFamaily;
-            this.TextAlign = annote.TextAlign;
+            var defualtannote = new AnnotatePropertyClass();
+            this.HighLightColor = defualtannote.HighLightColor;
+            this.UnderLineColor = defualtannote.UnderLineColor;
+            this.StrikethroughColor = defualtannote.StrikethroughColor;
+            this.FreeHandColor = defualtannote.FreeHandColor;
+            this.TextAnnoteColor = defualtannote.TextAnnoteColor;
+            this.NoteAnnoteColor = defualtannote.NoteAnnoteColor;
+            this.RectangleBorderColor = defualtannote.RectangleBorderColor;
+            this.RectangleFillColor = defualtannote.RectangleFillColor;
+            this.CircleBorderColor = defualtannote.CircleBorderColor;
+            this.CircleFillColor = defualtannote.CircleFillColor;
+            this.LineColor = defualtannote.LineColor;
+            this.ArrowColor = defualtannote.ArrowColor;
+            this.TextFontFamaily = defualtannote.TextFontFamaily;
+            this.AnchoredFamaily = defualtannote.AnchoredFamaily;
+            this.TextAlign = defualtannote.TextAlign;
         }
 
     }

+ 64 - 137
PDF Office/ViewModels/PageEdit/PageEditContentViewModel.cs

@@ -70,18 +70,6 @@ namespace PDF_Master.ViewModels.PageEdit
         /// </summary>
         private string unicode = null;
 
-        /// <summary>
-        /// Undo操作记录栈
-        /// 只有插入、移位、旋转,倒序需要记录
-        /// </summary>
-        private Stack<PageEditHistory> UndoStack = new Stack<PageEditHistory>();
-
-        /// <summary>
-        /// Redo操作记录栈
-        /// </summary>
-
-        private Stack<PageEditHistory> RedoStack = new Stack<PageEditHistory>();
-
         /// <summary>
         /// 项数据集合
         /// </summary>
@@ -306,45 +294,6 @@ namespace PDF_Master.ViewModels.PageEdit
             }
         }
 
-
-
-
-        private bool canUndo;
-
-        /// <summary>
-        /// 是否可以进行Undo操作
-        /// </summary>
-        public bool CanUndo
-        {
-            get { return canUndo; }
-            set
-            {
-                SetProperty(ref canUndo, value);
-                if (viewContentViewModel != null)
-                {
-                    viewContentViewModel.CanUndo = this.CanUndo;
-                }
-            }
-        }
-
-        private bool canRedo;
-        /// <summary>
-        /// 是否可以进行Redo操作
-        /// </summary>
-        public bool CanRedo
-        {
-            get { return canRedo; }
-            set
-            {
-                SetProperty(ref canRedo, value);
-                if (viewContentViewModel != null)
-                {
-                    viewContentViewModel.CanRedo = this.CanRedo;
-                }
-
-            }
-        }
-
         private bool canPaste = false;
         /// <summary>
         /// 是否可以粘贴
@@ -496,7 +445,7 @@ namespace PDF_Master.ViewModels.PageEdit
             ZoomOutCommand = new DelegateCommand(ZoomOutCommandEvent, CanZoomOut).ObservesProperty(() => ZoomIndex);
             ShowPageSizeCommand = new DelegateCommand(ShowPageSize);
             CopyCommand = new DelegateCommand(copy);
-            PasteCommand = new DelegateCommand(paste, CanPasteExcute).ObservesProperty(() => CanPaste);
+            PasteCommand = new DelegateCommand(()=> { paste(); }, CanPasteExcute).ObservesProperty(() => CanPaste);
             CutCommand = new DelegateCommand(cut);
             PrintCommand = new DelegateCommand(print);
             ClearSelectedCommand = new DelegateCommand(clearSelected);
@@ -556,7 +505,7 @@ namespace PDF_Master.ViewModels.PageEdit
                     DoRemoveSelectedPages(new List<int>() { listSelecedIndex });
                 }
 
-                ReloadAfterOption(true, true, Tuple.Create(insertIndex - 1, insertIndex + pageCount));
+                ReloadAfterOption(true, false, Tuple.Create(insertIndex - 1, insertIndex + pageCount));
                 IsLoading = Visibility.Collapsed;
             }
         }
@@ -649,7 +598,7 @@ namespace PDF_Master.ViewModels.PageEdit
                 PageEditItems.Insert(insertIndex, item);
 
 
-                ReloadAfterOption(true, true, Tuple.Create(insertIndex, insertIndex + 1));
+                ReloadAfterOption(true, false, Tuple.Create(insertIndex, insertIndex + 1));
                 await Task.Delay(10);
                 //选中插入的页面
                 ListSelectedIndex = insertIndex;
@@ -670,7 +619,7 @@ namespace PDF_Master.ViewModels.PageEdit
                         return;
                     }
 
-                    ReloadAfterOption(true, true, Tuple.Create(0, PDFViewer.Document.PageCount));
+                    ReloadAfterOption(true, false, Tuple.Create(0, PDFViewer.Document.PageCount));
                 }
                 IsLoading = Visibility.Collapsed;
                 //里面附带了Undo栈记录,需要提前返回,避免重复记录
@@ -699,14 +648,14 @@ namespace PDF_Master.ViewModels.PageEdit
                         history.Type = ActionType.InsertCustomPages;
                         history.InsertFilePath = model.filepath;
                         history.PageSize = new Size(model.width, model.height);
-
                     }
                 });
             }
             IsLoading = Visibility.Collapsed;
 
             //添加记录到Undo栈,清除Redo栈
-            AddToUndoStack(history);
+            history.viewmodel = this;
+            PDFViewer.UndoManager.AddHistory(history);
         }
 
         /// <summary>
@@ -805,14 +754,15 @@ namespace PDF_Master.ViewModels.PageEdit
 
             NotifyUIToRefresh(pageRange);
 
-            ReloadAfterOption(true, true, null);
+            ReloadAfterOption(true, false, null);
 
             if (!isFromUndoRedo)
             {
                 PageEditHistory history = new PageEditHistory();
                 history.Type = ActionType.Reverse;
                 history.SourceTargetValue = sourceTarget;
-                AddToUndoStack(history);
+                history.viewmodel = this;
+                PDFViewer.UndoManager.AddHistory(history);
             }
         }
 
@@ -1203,7 +1153,7 @@ namespace PDF_Master.ViewModels.PageEdit
         /// <summary>
         /// 粘贴
         /// </summary>
-        private async void paste()
+        private async void paste(int Index=-1)
         {
             //付费锁
             if (!App.IsLogin)
@@ -1214,6 +1164,16 @@ namespace PDF_Master.ViewModels.PageEdit
             IsLoading = Visibility.Visible;
             int insertindex = maxSelectedIndex > listSelecedIndex ? maxSelectedIndex : listSelecedIndex;
             insertindex++;
+            if (Index >= 0)
+            {
+                insertindex = Index;
+            }
+
+            if (CacheFilePath.Instance.CopyDoc==null)
+            {
+                return;
+            }
+
             int pagecount = CacheFilePath.Instance.CopyDoc.PageCount;
             bool result = PDFViewer.Document.ImportPagesAtIndex(CacheFilePath.Instance.CopyDoc, "1-" + pagecount, insertindex);
             if (!result)
@@ -1239,8 +1199,15 @@ namespace PDF_Master.ViewModels.PageEdit
             }
             NotifyUIToRefresh(pageRange);
 
+            PageEditHistory history = new PageEditHistory();
+            history.InsertIndex = insertindex;
+            history.InsertPageCount = pagecount;
+            history.Type = ActionType.Paste;
+            history.viewmodel = this;
+            PDFViewer.UndoManager.AddHistory(history);
+
             //刷新页码等
-            ReloadAfterOption(true, true, new Tuple<int, int>(0, PDFViewer.Document.PageCount));
+            ReloadAfterOption(true, false, new Tuple<int, int>(0, PDFViewer.Document.PageCount));
             NotifyUIToRefresh(pageRange);
             IsLoading = Visibility.Collapsed;
         }
@@ -1248,38 +1215,29 @@ namespace PDF_Master.ViewModels.PageEdit
         /// <summary>
         /// 页面编辑执行Undo操作的方法
         /// </summary>
-        private async void Undo()
+        public async void Undo(PageEditHistory history)
         {
-            var history = UndoStack.Pop();
-            PageEditHistory redoHistory = new PageEditHistory();
             switch (history.Type)
             {
                 case ActionType.RightRotate:
                     var rightlist = history.SourceTargetValue.Keys.ToList<int>();
                     RotateSelectedPages(false, rightlist, true);
-
-                    redoHistory.SourceTargetValue = history.SourceTargetValue;
-                    redoHistory.Type = ActionType.LeftRotate;
                     break;
                 case ActionType.LeftRotate:
                     var leftlist = history.SourceTargetValue.Keys.ToList<int>();
                     RotateSelectedPages(true, leftlist, true);
-
-                    redoHistory.SourceTargetValue = history.SourceTargetValue;
-                    redoHistory.Type = ActionType.RightRotate;
                     break;
                 case ActionType.InsertFromFile:
+                case ActionType.Paste:
                     List<int> pageList = new List<int>();
                     for (int i = 0; i < history.InsertPageCount; i++)
                     {
                         pageList.Add(history.InsertIndex + i);
                     }
                     DoRemoveSelectedPages(pageList, true);
-                    redoHistory = history;
                     break;
                 case ActionType.InsertCustomPages:
                     DoRemoveSelectedPages(new List<int> { history.InsertIndex }, true);
-                    redoHistory = history;
                     break;
                 case ActionType.DragSort:
                     //将字典倒序后,将每个Source的值恢复到Key的位置
@@ -1291,7 +1249,7 @@ namespace PDF_Master.ViewModels.PageEdit
                         MoveItemToIndex(SourceTargets[key], key);
                     }
                     //刷新页码等
-                    ReloadAfterOption(true, true, new Tuple<int, int>(0, PDFViewer.Document.PageCount));
+                    ReloadAfterOption(true, false, new Tuple<int, int>(0, PDFViewer.Document.PageCount));
 
                     List<int> selectedPages = new List<int>();
                     //将索引集合转换成页码集合
@@ -1301,7 +1259,6 @@ namespace PDF_Master.ViewModels.PageEdit
                     }
                     //通知UI选中Item
                     NotifyUIToRefresh(selectedPages);
-                    redoHistory = history;
                     break;
                 case ActionType.Reverse:
                     //将字典倒序后,将每个Source的值恢复到Key的位置
@@ -1317,7 +1274,7 @@ namespace PDF_Master.ViewModels.PageEdit
 
                     await Task.Delay(20);
                     //刷新页码等
-                    ReloadAfterOption(true, true, null);
+                    ReloadAfterOption(true, false, null);
 
                     List<int> Pages = new List<int>();
                     //将索引集合转换成页码集合
@@ -1331,70 +1288,48 @@ namespace PDF_Master.ViewModels.PageEdit
                     }
                     //通知UI选中Item
                     NotifyUIToRefresh(Pages);
-                    redoHistory = history;
                     break;
                 default:
                     break;
             }
-            RedoStack.Push(redoHistory);
-            CanRedo = true;
-            //检查是否可以再进行Undo
-            if (UndoStack.Count <= 0)
-            {
-                this.CanUndo = false;
-            }
         }
 
         /// <summary>
         /// 页面编辑执行Redo操作的方法
         /// </summary>
-        private async void Redo()
+        public async void Redo(PageEditHistory history)
         {
-            var history = RedoStack.Pop();
-            PageEditHistory undoHistory = new PageEditHistory();
             switch (history.Type)
             {
                 case ActionType.RightRotate:
                     var rightlist = history.SourceTargetValue.Keys.ToList<int>();
-                    RotateSelectedPages(false, rightlist, true);
-
-                    undoHistory.SourceTargetValue = history.SourceTargetValue;
-                    undoHistory.Type = ActionType.LeftRotate;
+                    RotateSelectedPages(true, rightlist, true);
                     break;
                 case ActionType.LeftRotate:
                     var leftlist = history.SourceTargetValue.Keys.ToList<int>();
-                    RotateSelectedPages(true, leftlist, true);
-                    undoHistory.SourceTargetValue = history.SourceTargetValue;
-                    undoHistory.Type = ActionType.RightRotate;
+                    RotateSelectedPages(false, leftlist, true);
                     break;
                 case ActionType.InsertFromFile:
                     await InsertFromFile(history.InsertIndex, history.InsertFilePath, history.InsertFilePassWord, true);
-                    ReloadAfterOption(true, true, Tuple.Create(history.InsertIndex - 1, history.InsertIndex + history.InsertPageCount));
-                    undoHistory = history;
+                    ReloadAfterOption(true, false, Tuple.Create(history.InsertIndex - 1, history.InsertIndex + history.InsertPageCount));
                     break;
                 case ActionType.InsertCustomPages:
                     InsertFromCustomPage(history.InsertIndex, history.PageSize.Width, history.PageSize.Height, history.InsertFilePath);
                     ListSelectedIndex = history.InsertIndex;
-                    undoHistory = history;
                     break;
                 case ActionType.DragSort:
                     DragToSort(history.InsertIndex, history.SourceTargetValue.Keys.ToList<int>(), true);
-                    undoHistory = history;
                     break;
                 case ActionType.Reverse:
                     var list = history.SourceTargetValue.Keys.ToList<int>().Union(history.SourceTargetValue.Values.ToList<int>()).ToList<int>();
                     DoReverse(list, true);
-                    undoHistory = history;
+                    break;
+                case ActionType.Paste:
+                    paste(history.InsertIndex);
                     break;
                 default:
                     break;
             }
-            UndoStack.Push(undoHistory);
-            CanUndo = true;
-            if (RedoStack.Count <= 0)
-            {
-                this.CanRedo = false;
-            }
         }
 
         /// <summary>
@@ -1509,11 +1444,11 @@ namespace PDF_Master.ViewModels.PageEdit
 
             if (!isFromUndoRedo)
             {
-                //清除页面编辑Undo,Redo栈
-                UndoStack.Clear();
-                RedoStack.Clear();
-                this.CanUndo = false;
-                this.CanRedo = false;
+                ////清除页面编辑Undo,Redo栈
+                //UndoStack.Clear();
+                //RedoStack.Clear();
+                //this.CanUndo = false;
+                //this.CanRedo = false;
             }
         }
 
@@ -1600,7 +1535,7 @@ namespace PDF_Master.ViewModels.PageEdit
             if (isDeleteAfterExtract)
             {
                 DoRemoveSelectedPages();
-                ReloadAfterOption(true, true, Tuple.Create(0, PDFViewer.Document.PageCount));
+                ReloadAfterOption(true, false, Tuple.Create(0, PDFViewer.Document.PageCount));
             }
 
             CommonHelper.ShowFileBrowser(selectedfile);
@@ -1865,24 +1800,12 @@ namespace PDF_Master.ViewModels.PageEdit
                 history.InsertFilePath = filePath;
                 history.InsertFilePassWord = password;
                 history.InsertPageCount = pageCount;
-
-                AddToUndoStack(history);
+                history.viewmodel = this;
+                PDFViewer.UndoManager.AddHistory(history);
             }
             return true;
         }
 
-        /// <summary>
-        /// 添加记录到Undo栈
-        /// </summary>
-        /// <param name="history"></param>
-        private void AddToUndoStack(PageEditHistory history)
-        {
-            UndoStack.Push(history);
-            CanUndo = true;
-            RedoStack.Clear();
-            CanRedo = false;
-        }
-
         /// <summary>
         /// 插入自定义页面
         /// </summary>
@@ -1916,7 +1839,7 @@ namespace PDF_Master.ViewModels.PageEdit
                 PageEditItem item = new PageEditItem();
                 item.Size = PDFViewer.Document.GetPageSize(insertIndex);
                 PageEditItems.Insert(insertIndex, item);
-                ReloadAfterOption(true, true, Tuple.Create(insertIndex - 1, insertIndex + 1));
+                ReloadAfterOption(true, false, Tuple.Create(insertIndex - 1, insertIndex + 1));
                 return true;
             }
             catch
@@ -1954,7 +1877,7 @@ namespace PDF_Master.ViewModels.PageEdit
         /// <param name="needRefreshPageNum">是否需要刷新页码</param>
         /// <param name="needClearUndoHistory">是否需要清空注释Undo栈</param>
         /// <param name="pageRange">需要刷新的页面范围图片</param>
-        public void ReloadAfterOption(bool needRefreshPageNum = false, bool needClearUndoHistory = true, Tuple<int, int> pageRange = null)
+        public void ReloadAfterOption(bool needRefreshPageNum = false, bool needClearUndoHistory = false, Tuple<int, int> pageRange = null)
         {
             if (needRefreshPageNum)
             {
@@ -1962,6 +1885,8 @@ namespace PDF_Master.ViewModels.PageEdit
             }
             if (needClearUndoHistory)
             {
+                //只有删除操作清空undo栈
+                //可能会引起注释模块联动问题 需要留意
                 PDFViewer.UndoManager.ClearHistory();
             }
             if (pageRange != null)
@@ -2039,10 +1964,11 @@ namespace PDF_Master.ViewModels.PageEdit
                 PageEditHistory history = new PageEditHistory();
                 history.Type = rightRotate ? ActionType.RightRotate : ActionType.LeftRotate;
                 history.SourceTargetValue = items;
-                AddToUndoStack(history);
+                history.viewmodel = this;
+                PDFViewer.UndoManager.AddHistory(history);
             }
 
-            ReloadAfterOption(false, true, Tuple.Create(0, PageEditItems.Count));
+            ReloadAfterOption(false, false, Tuple.Create(0, PageEditItems.Count));
             IsLoading = Visibility.Collapsed;
         }
 
@@ -2359,7 +2285,7 @@ namespace PDF_Master.ViewModels.PageEdit
             //通知UI选中Items
             NotifyUIToRefresh(selectedPages);
             //刷新页码和图片
-            ReloadAfterOption(true, true, new Tuple<int, int>(0, PDFViewer.Document.PageCount));
+            ReloadAfterOption(true, false, new Tuple<int, int>(0, PDFViewer.Document.PageCount));
 
             if (!IsFromUndoRedo)
             {
@@ -2369,7 +2295,8 @@ namespace PDF_Master.ViewModels.PageEdit
                 history.SourceTargetValue = SourceTargetValue;
                 //用于Redo恢复
                 history.InsertIndex = targetIndex;
-                AddToUndoStack(history);
+                history.viewmodel = this;
+                PDFViewer.UndoManager.AddHistory(history);
             }
         }
 
@@ -2462,11 +2389,11 @@ namespace PDF_Master.ViewModels.PageEdit
                     PDFViewer.AnnotEditHandler += PDFViewer_AnnotEditHandler;
 
                     ZoomIndex = 0;
-                    if (viewContentViewModel != null)
-                    {
-                        viewContentViewModel.PageEditUndo = Undo;
-                        viewContentViewModel.PageEditRedo = Redo;
-                    }
+                    //if (viewContentViewModel != null)
+                    //{
+                    //    viewContentViewModel.PageEditUndo = Undo;
+                    //    viewContentViewModel.PageEditRedo = Redo;
+                    //}
                 }
                 //BOTA缩略图时,显示不同的菜单栏
                 if (isBOTA)
@@ -2483,8 +2410,8 @@ namespace PDF_Master.ViewModels.PageEdit
                 GetSourceItems(isFirstLoad);
 
                 ListSelectedIndex = PDFViewer.CurrentIndex;
-                viewContentViewModel.CanUndo = this.CanUndo;
-                viewContentViewModel.CanRedo = this.CanRedo;
+                //viewContentViewModel.CanUndo = this.CanUndo;
+                //viewContentViewModel.CanRedo = this.CanRedo;
                 RefreshBookMarkList();
                 isFirstLoad = false;
             }

+ 15 - 34
PDF Office/ViewModels/ViewContentViewModel.cs

@@ -340,11 +340,11 @@ namespace PDF_Master.ViewModels
             set
             {
                 SetProperty(ref _isInPageEdit, value);
-                if (!value)
-                {
-                    CanRedo = PDFViewer.UndoManager.CanRedo;
-                    CanUndo = PDFViewer.UndoManager.CanUndo;
-                }
+                //if (!value)
+                //{
+                //    CanRedo = PDFViewer.UndoManager.CanRedo;
+                //    CanUndo = PDFViewer.UndoManager.CanUndo;
+                //}
             }
         }
 
@@ -1487,19 +1487,16 @@ namespace PDF_Master.ViewModels
 
         private void UndoManager_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
         {
-            if (!isInPageEdit)
+            //不处于页面编辑模式下时,根据PDFVIewer的undo redo状态来更新按钮状态
+            if (e.PropertyName == "CanUndo")
             {
-                //不处于页面编辑模式下时,根据PDFVIewer的undo redo状态来更新按钮状态
-                //页面编辑模式下,按钮状态根据页面编辑的undo redo来显示
-                if (e.PropertyName == "CanUndo")
-                {
-                    CanUndo = PDFViewer.UndoManager.CanUndo;
-                }
-                if (e.PropertyName == "CanRedo")
-                {
-                    CanRedo = PDFViewer.UndoManager.CanRedo;
-                }
+                CanUndo = PDFViewer.UndoManager.CanUndo;
             }
+            if (e.PropertyName == "CanRedo")
+            {
+                CanRedo = PDFViewer.UndoManager.CanRedo;
+            }
+
             if (e.PropertyName == "CanSave")
             {
                 CanSave = PDFViewer.UndoManager.CanSave;
@@ -1841,28 +1838,12 @@ namespace PDF_Master.ViewModels
 
         private void Undo()
         {
-            if (isInPageEdit)
-            {
-                //执行页面编辑的Undo
-                PageEditUndo?.Invoke();
-            }
-            else
-            {
-                PDFViewer.UndoManager.Undo();
-            }
+            PDFViewer.UndoManager.Undo();
         }
 
         private void Redo()
         {
-            if (isInPageEdit)
-            {
-                //执行页面编辑的Redo
-                PageEditRedo?.Invoke();
-            }
-            else
-            {
-                PDFViewer.UndoManager.Redo();
-            }
+            PDFViewer.UndoManager.Redo();
         }
 
         private void LoadControl()