// ------------------------------ // private // ------------------------------ private void ShowPreview(Link link, Point loc) { if (link != null && UriUtil.IsMemoUri(link.Uri)) { var info = UriUtil.GetMemoInfo(link.Uri); if (info != null) { var bmp = default(Bitmap); if (_app.IsLoadedMemo(info)) { /// Loadされていればそのcanvasからbitmapを作る var content = _app.FindPageContent(info); bmp = MemoOutlineUtil.CreateOutline(content.EditorCanvas); } else { bmp = MemoOutlineUtil.LoadOrSaveAndLoadOutline(info); } DisposePreviewPopup(); var canvas = Host.Site.EditorCanvas; var bounds = _Figure.Bounds; var screen = Screen.FromRectangle(bounds); var outline = new OutlinePreviewControl(screen, info.Title, bmp, 1f); _previewPopup = new Popup(outline); /// AutoClose = falseにしておかないとPopupにフォーカスを取られてしまう _previewPopup.AutoClose = false; _previewPopup.Tag = bmp; var locDelta = 20; var locOnScreen = canvas.PointToScreen(canvas.TranslateToControlPoint(loc)); var preferredSize = outline.GetPreferredSize(new Size(int.MaxValue, int.MaxValue)); var isEnoughLowerSpace = preferredSize.Height < screen.WorkingArea.Height - (locOnScreen.Y + locDelta) - 2; var isLocUpper = locOnScreen.Y <= screen.WorkingArea.Height / 2; var y = 0; if (isEnoughLowerSpace || isLocUpper) { outline.MaxHeight = screen.WorkingArea.Height - (locOnScreen.Y + locDelta) - 2; y = locOnScreen.Y + locDelta; } else { outline.MaxHeight = locOnScreen.Y - locDelta - 2; y = locOnScreen.Y - locDelta - Math.Min(preferredSize.Height, outline.MaxHeight); } var isEnoughRighterSpace = preferredSize.Width < screen.WorkingArea.Width - (locOnScreen.X + locDelta) - 2; var isLocLefter = locOnScreen.X <= screen.WorkingArea.Width / 2; var x = 0; if (isEnoughRighterSpace || isLocLefter) { outline.MaxWidth = screen.WorkingArea.Width - (locOnScreen.X + locDelta) - 2; x = locOnScreen.X + locDelta; } else { outline.MaxWidth = locOnScreen.X - locDelta - 2; x = locOnScreen.X - locDelta - Math.Min(preferredSize.Width, outline.MaxWidth); } _previewPopup.Show(new Point(x, y)); } } }
/// <summary> /// infos内からqueryに適合するものだけを返す。 /// </summary> public IEnumerable <MemoInfo> Search(IEnumerable <MemoInfo> infos, MemoQuery query) { if (query == null || query.IsEmptyQuery) { return(new List <MemoInfo>()); } var matched = infos; /// タイトル if (query.NarrowByTitle) { matched = matched.Where( info => info.Title.IndexOf(query.Title, StringComparison.OrdinalIgnoreCase) > -1 ); } /// タグ if (query.NarrowByTagIds) { var tags = GetTags(query); var noTag = query.NoTag; var compKind = query.TagCompoundKind; Func <MemoInfo, bool> tagFilter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); return /// noTagかつ「allでタグを指定」を満たすことはあり得ないので,noTagは常にorでつなぐだけにしておく ((noTag && !memo.Tags.Any()) || (compKind == MemoConditionCompoundKind.Any && memo.Tags.ContainsAny(tags)) || (compKind == MemoConditionCompoundKind.All && memo.Tags.ContainsAll(tags))); }; matched = matched.Where(tagFilter); } /// 重要度 if (query.NarrowByImportanceKind) { var importances = query.ImportanceKinds; Func <MemoInfo, bool> importanceFilter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); return(importances.Contains(memo.Importance)); }; matched = matched.Where(importanceFilter); } /// recent if (query.NarrowByRecentTimeSpan) { var recent = query.RecentTimeSpan; var filter = default(Func <MemoInfo, bool>); switch (recent.DateKind) { case MemoDateKind.Created: { filter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); return (memo.CreatedDate >= recent.FromDate && memo.CreatedDate < recent.ToDate); }; break; } case MemoDateKind.Modified: { filter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); return (memo.ModifiedDate >= recent.FromDate && memo.ModifiedDate < recent.ToDate); }; break; } case MemoDateKind.Accessed: { filter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); return (memo.AccessedDate >= recent.FromDate && memo.AccessedDate < recent.ToDate); }; break; } } matched = matched.Where(filter); } /// 期間 if (query.NarrowByTimeSpan) { var timeSpan = query.TimeSpan; var filter = default(Func <MemoInfo, bool>); switch (timeSpan.DateKind) { case MemoDateKind.Created: { filter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); return (memo.CreatedDate >= timeSpan.FromDate && memo.CreatedDate < timeSpan.ToDate); }; break; } case MemoDateKind.Modified: { filter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); return (memo.ModifiedDate >= timeSpan.FromDate && memo.ModifiedDate < timeSpan.ToDate); }; break; } case MemoDateKind.Accessed: { filter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); return (memo.AccessedDate >= timeSpan.FromDate && memo.AccessedDate < timeSpan.ToDate); }; break; } } matched = matched.Where(filter); } /// マーク if (query.NarrowByMarkKinds) { var noMarkKind = query.NoMarkKind; Func <MemoInfo, bool> markFilter = info => { var memo = _facade.Container.Find <Memo>(info.MemoId); var opened = _facade.FindPageContent(info); var markIds = default(IEnumerable <string>); if (opened == null) { /// 開かれていなければキャッシュを見る markIds = MemoMarkUtil.LoadMarkIdsCache(memo); if (markIds == null) { markIds = MemoMarkUtil.GetMemoMarkIds(memo); MemoMarkUtil.SaveMarkIdsCache(memo, markIds); } } else { markIds = MemoMarkUtil.GetMemoMarkIds(memo); } if (noMarkKind && !markIds.Any()) { return(true); } var marks = MemoMarkUtil.GetMarks(markIds); var markKinds = marks.Select(mark => mark.Kind).ToArray(); var compKind = query.MarkCompoundKind; return ((compKind == MemoConditionCompoundKind.Any && query.MarkKinds.Any(kind => markKinds.Contains(kind))) || (compKind == MemoConditionCompoundKind.All && query.MarkKinds.All(kind => markKinds.Contains(kind)))); }; matched = matched.Where(markFilter); } /// 全文検索 if (!query.NarrowByKeywords) { return(matched); } else { var ret = new List <MemoInfo>(); var keywords = query.Condition.Split(' '); foreach (var info in matched.ToArray()) { /// MemoInfoのFullTextを取得 var fullText = default(string); var opened = _facade.FindPageContent(info); if (opened == null) { fullText = _facade.Container.LoadExtendedTextData(typeof(Memo), info.MemoId, "FullText"); if (fullText == null) { /// 見つからなかった場合はノートをロードしてGetText()できるようにしておく _facade.LoadMemo(info, true); opened = _facade.FindPageContent(info); if (opened != null) { var canvas = opened.EditorCanvas; _facade.Container.SaveExtendedTextData( canvas.EditorContent, "FullText", canvas.GetFullText() ); } } } if (opened != null && fullText == null) { var canvas = opened.EditorCanvas; fullText = canvas.GetFullText(); } if (fullText != null) { var matchFailed = false; foreach (var keyword in keywords) { //if (Regex.IsMatch(fullText, keyword, RegexOptions.IgnoreCase | RegexOptions.Multiline)) { if (keyword.StartsWith("-")) { /// "-"で始まる場合は除外キーワード var realKeyword = keyword.Substring(1); /// "-"を除去 if (fullText.IndexOf(realKeyword, StringComparison.OrdinalIgnoreCase) > -1) { matchFailed = true; break; } } else { /// "-"で始まらなければ普通のキーワード if (fullText.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) < 0) { matchFailed = true; break; } } } if (!matchFailed) { ret.Add(info); } } } return(ret); } }