/// <summary> /// Initializes tooltip provider for "search language" or "script" button. /// </summary> /// <param name="button">The actual button.</param> /// <param name="isLang">If true, this is tooltip for "search lang"; otherwise, for "script".</param> /// <param name="tprov">Localized UI strings provider.</param> /// <param name="script">Current search script.</param> /// <param name="lang">Current search language.</param> /// <param name="needleHeight">Needle's height at today's scaling.</param> public SearchOptionsTooltip(ZenGradientButton button, bool isLang, ITextProvider tprov, SearchScript script, SearchLang lang, int needleHeight, int boxRight) { this.button = button; this.needleHeight = needleHeight; this.topOrSide = -boxRight; if (isLang) { if (lang == SearchLang.Chinese) { text = tprov.GetString("LangZhoTooltip"); } else { text = tprov.GetString("LangTrgTooltip"); } } else { if (script == SearchScript.Simplified) { text = tprov.GetString("ScriptSimpTooltip"); } else if (script == SearchScript.Traditional) { text = tprov.GetString("ScriptTradTooltip"); } else { text = tprov.GetString("ScriptBothTooltip"); } } }
/// <summary> /// Ctor: intialize immutable object. /// </summary> public CedictLookupResult(string query, List <CedictResult> results, List <CedictAnnotation> annotations, SearchLang actualSearchLang) { Query = query; Results = new ReadOnlyCollection <CedictResult>(results); Annotations = new ReadOnlyCollection <CedictAnnotation>(annotations); ActualSearchLang = actualSearchLang; }
/// <summary> /// Ctor: intialize immutable object. /// </summary> public CedictLookupResult(ICedictEntryProvider entryProvider, ReadOnlyCollection<CedictResult> results, SearchLang actualSearchLang) { EntryProvider = entryProvider; Results = results; ActualSearchLang = actualSearchLang; }
public void LogStatic(string query, SearchLang lang, string userAgent, TimeSpan ts) { string strLang = lang == SearchLang.Chinese ? "ZHO" : "TRG"; SQItem itm = new SQItem(strLang, query, userAgent, ts); lock (ilist) { ilist.Add(itm); evt.Set(); } }
/// <summary> /// Event handler: search language button clicked. /// </summary> private void onSearchLang(ZenControlBase sender) { // Toggle between English and Chinese if (searchLang == SearchLang.Chinese) { searchLang = SearchLang.Target; } else { searchLang = SearchLang.Chinese; } // Update button searchLangChanged(); }
public CedictLookupResult Lookup(string query) { // Prepare EntryProvider ep = new EntryProvider(); List <CedictResult> res = new List <CedictResult>(); List <CedictAnnotation> anns = new List <CedictAnnotation>(); SearchLang sl = SearchLang.Chinese; if (hasHanzi(query)) { lookupHanzi(query, ep, res, anns); } else { lookupPinyin(query, ep, res); } // Done return(new CedictLookupResult(ep, query, res, anns, sl)); }
/// <summary> /// Infuses walkthrough links at bottom of page. /// </summary> public void SetStaticQuery(string query, SearchLang slang, DateTime dtStart) { // No query: seeding walkthrough from start page if (query == null) { string hanzi, target; Global.Dict.GetFirstWords(out hanzi, out target); string inner = getWalkPara(hanzi, true); inner += getWalkPara(target, false); walkthroughDiv.InnerHtml = inner; } // This was a static query; walk down hanzi headwords or german words else { // Link back and forth bool isTarget = slang == SearchLang.Target; string prev, next; Global.Dict.GetPrevNextWords(query, isTarget, out prev, out next); string inner = ""; if (prev != null) { inner += getWalkPara(prev, !isTarget); } if (next != null) { inner += getWalkPara(next, !isTarget); } walkthroughDiv.InnerHtml = inner; // Keywords and decription string keyw = TextProvider.Instance.GetString(uiLang, isTarget ? "MetaKeywordsTrg" : "MetaKeywordsZho"); keyw = string.Format(keyw, query); Page.MetaKeywords = keyw; string desc = TextProvider.Instance.GetString(uiLang, isTarget ? "MetaDescriptionTrg" : "MetaDescriptionZho"); desc = string.Format(desc, query); Page.MetaDescription = desc; descrAndKeywSet = true; // Log that we've been crawled QueryLogger.Instance.LogStatic(query, slang, Request.UserAgent, DateTime.UtcNow.Subtract(dtStart)); } }
/// <summary> /// Dictionary lookup and results rendering in worker thread. /// </summary> /// <param name="ctxt"></param> private void search(object ctxt) { LookupItem li; // Pick very last item in queue to look up; clear rest of queue lock (lookupItems) { if (lookupItems.Count == 0) { return; } li = lookupItems[lookupItems.Count - 1]; lookupItems.Clear(); // If this is not very last request, don't even bother if (li.ID != lookupId) { return; } } // Look up in dictionary CedictLookupResult res = dict.Lookup(li.Text, li.Script, li.Lang); // Call below transfers ownership of entry provider to results control. clearWhite(); bool shown = ctrlResults.SetResults(li.ID, res.EntryProvider, res.Results, searchScript); // If these results came too late (a long query completing too late, when a later fast query already completed) // Then we're done, no flashing. if (!shown) { return; } // Did lookup language change? if (res.ActualSearchLang != li.Lang) { searchLang = res.ActualSearchLang; searchLangChanged(); btnSearchLang.Flash(); } }
/// <summary> /// Find entries that match the search expression. /// </summary> /// <param name="query">The query string, as entered by the user.</param> /// <param name="script">For hanzi lookup: simplified, traditional or both.</param> /// <param name="lang">Chinese or target language (English).</param> /// <returns>The lookup result.</returns> public CedictLookupResult Lookup(string query, SearchScript script, SearchLang lang) { List <CedictResult> res = new List <CedictResult>(); List <CedictAnnotation> anns = new List <CedictAnnotation>(); // BinReader: I own it until I successfully return results to caller. BinReader br = new BinReader(dictFileName); EntryProvider ep = new EntryProvider(br); try { // Try first in language requested by user // If no results that way, try in opposite language // Override if lookup in opposite language is successful if (lang == SearchLang.Chinese) { res = doChineseLookup(br, query, script); // We got fish if (res.Count > 0) { return(new CedictLookupResult(ep, query, res, anns, lang)); } // Try to annotate anns = doAnnotate(br, query); if (anns.Count > 0) { return(new CedictLookupResult(ep, query, res, anns, lang)); } // OK, try opposite (target) res = doTargetLookup(br, query); // We got fish: override if (res.Count > 0) { return(new CedictLookupResult(ep, query, res, anns, SearchLang.Target)); } } else { res = doTargetLookup(br, query); // We got fish if (res.Count > 0) { return(new CedictLookupResult(ep, query, res, anns, lang)); } // OK, try opposite (target) res = doChineseLookup(br, query, script); // We got fish: override if (res.Count > 0) { return(new CedictLookupResult(ep, query, res, anns, SearchLang.Chinese)); } // Try to annotate anns = doAnnotate(br, query); if (anns.Count > 0) { return(new CedictLookupResult(ep, query, res, anns, SearchLang.Chinese)); } } // Sorry, no results, no override return(new CedictLookupResult(ep, query, res, anns, lang)); } catch { br.Dispose(); throw; } }
/// <summary> /// Ctor. /// </summary> public LookupControl(ZenControlBase owner, ICedictEngineFactory dictFact, ITextProvider tprov) : base(owner) { this.dictFact = dictFact; this.tprov = tprov; padding = (int)Math.Round(5.0F * Scale); // Init search language and script from user settings searchLang = AppSettings.SearchLang; searchScript = AppSettings.SearchScript; // Init HanziLookup fsStrokes = new FileStream(Magic.StrokesFileName, FileMode.Open, FileAccess.Read); brStrokes = new BinaryReader(fsStrokes); strokesData = new StrokesDataSource(brStrokes); // Writing pad writingPad = new WritingPad(this, tprov); writingPad.RelLocation = new Point(padding, padding); writingPad.LogicalSize = new Size(200, 200); writingPad.StrokesChanged += writingPad_StrokesChanged; // Images for buttons under writing pad; will get owned by buttons, not that it matters. Assembly a = Assembly.GetExecutingAssembly(); var imgStrokesClear = Image.FromStream(a.GetManifestResourceStream("ZD.Gui.Resources.strokes-clear.png")); var imgStrokesUndo = Image.FromStream(a.GetManifestResourceStream("ZD.Gui.Resources.strokes-undo.png")); // Clear and undo buttons under writing pad. float leftBtnWidth = writingPad.Width / 2 + 1; float btnHeight = 22.0F * Scale; // -- btnClearWritingPad = new ZenGradientButton(this); btnClearWritingPad.RelLocation = new Point(writingPad.RelLeft, writingPad.RelBottom - 1); btnClearWritingPad.Size = new Size((int)leftBtnWidth, (int)btnHeight); btnClearWritingPad.Text = tprov.GetString("WritingPadClear"); btnClearWritingPad.SetFont(SystemFontProvider.Instance.GetSystemFont(FontStyle.Regular, 9.0F)); btnClearWritingPad.Padding = (int)(3.0F * Scale); btnClearWritingPad.ImageExtraPadding = (int)(3.0F * Scale); btnClearWritingPad.Image = imgStrokesClear; btnClearWritingPad.Enabled = false; btnClearWritingPad.MouseClick += onClearWritingPad; // -- btnUndoStroke = new ZenGradientButton(this); btnUndoStroke.RelLocation = new Point(btnClearWritingPad.RelRight - 1, writingPad.RelBottom - 1); btnUndoStroke.Size = new Size(writingPad.RelRight - btnUndoStroke.RelLeft, (int)btnHeight); btnUndoStroke.Text = tprov.GetString("WritingPadUndo"); btnUndoStroke.SetFont(SystemFontProvider.Instance.GetSystemFont(FontStyle.Regular, 9.0F)); btnUndoStroke.Padding = (int)(3.0F * Scale); btnUndoStroke.ImageExtraPadding = (int)(1.5F * Scale); btnUndoStroke.Image = imgStrokesUndo; btnUndoStroke.Enabled = false; btnUndoStroke.MouseClick += onUndoStroke; // -- btnClearWritingPad.Tooltip = new ClearUndoTooltips(btnClearWritingPad, true, tprov, padding); btnUndoStroke.Tooltip = new ClearUndoTooltips(btnUndoStroke, false, tprov, padding); // -- // Character picker control under writing pad. ctrlCharPicker = new CharPicker(this, tprov); ctrlCharPicker.FontFam = Magic.ZhoContentFontFamily; ctrlCharPicker.FontScript = searchScript == SearchScript.Traditional ? IdeoScript.Trad : IdeoScript.Simp; ctrlCharPicker.RelLocation = new Point(padding, btnClearWritingPad.RelBottom + padding); ctrlCharPicker.LogicalSize = new Size(200, 80); ctrlCharPicker.CharPicked += onCharPicked; // Search input control at top ctrlSearchInput = new SearchInputControl(this, tprov); ctrlSearchInput.RelLocation = new Point(writingPad.RelRight + padding, padding); ctrlSearchInput.StartSearch += onStartSearch; // Tweaks for Chinese text on UI buttons // This is specific to Segoe UI and Noto Sans S Chinese fonts. float ofsZho = 0; //if (!(SystemFontProvider.Instance as ZydeoSystemFontProvider).SegoeExists) // ofsZho = Magic.ZhoButtonFontSize * Scale / 3.7F; // Script selector button to the right of search input control btnSimpTrad = new ZenGradientButton(this); btnSimpTrad.RelTop = padding; btnSimpTrad.Height = ctrlSearchInput.Height; btnSimpTrad.SetFont((SystemFontProvider.Instance as ZydeoSystemFontProvider).GetZhoButtonFont( FontStyle.Regular, Magic.ZhoButtonFontSize)); btnSimpTrad.Width = getSimpTradWidth(); btnSimpTrad.ForcedCharVertOfs = ofsZho; btnSimpTrad.RelLeft = Width - padding - btnSimpTrad.Width; btnSimpTrad.Height = ctrlSearchInput.Height; btnSimpTrad.MouseClick += onSimpTrad; // Search language selector to the right of search input control btnSearchLang = new ZenGradientButton(this); btnSearchLang.RelTop = padding; btnSearchLang.Height = ctrlSearchInput.Height; btnSearchLang.SetFont((SystemFontProvider.Instance as ZydeoSystemFontProvider).GetZhoButtonFont( FontStyle.Regular, Magic.ZhoButtonFontSize)); btnSearchLang.Width = getSearchLangWidth(); btnSearchLang.ForcedCharVertOfs = ofsZho; btnSearchLang.RelLeft = btnSimpTrad.RelLeft - padding - btnSearchLang.Width; btnSearchLang.Height = ctrlSearchInput.Height; btnSearchLang.MouseClick += onSearchLang; // Update button texts; do it here so tooltip locations will be correct. simpTradChanged(); searchLangChanged(); // Lookup results control. ctrlResults = new ResultsControl(this, tprov, onLookupThroughLink, onGetEntry); ctrlResults.RelLocation = new Point(writingPad.RelRight + padding, ctrlSearchInput.RelBottom + padding); }
private void langDeButton_Checked(object sender, RoutedEventArgs e) { langEnum = SearchLang.GERMAN; }
public LookupItem(int id, string text, SearchScript script, SearchLang lang) { ID = id; Text = text; Script = script; Lang = lang; }
/// <summary> /// Dictionary lookup and results rendering in worker thread. /// </summary> /// <param name="ctxt"></param> private void search(object ctxt) { LookupItem li; // Pick very last item in queue to look up; clear rest of queue lock (lookupItems) { if (lookupItems.Count == 0) return; li = lookupItems[lookupItems.Count - 1]; lookupItems.Clear(); // If this is not very last request, don't even bother if (li.ID != lookupId) return; } // Look up in dictionary CedictLookupResult res = dict.Lookup(li.Text, li.Script, li.Lang); // Call below transfers ownership of entry provider to results control. clearWhite(); bool shown = ctrlResults.SetResults(li.ID, res.EntryProvider, res.Results, searchScript); // If these results came too late (a long query completing too late, when a later fast query already completed) // Then we're done, no flashing. if (!shown) return; // Did lookup language change? if (res.ActualSearchLang != li.Lang) { searchLang = res.ActualSearchLang; searchLangChanged(); btnSearchLang.Flash(); } }
/// <summary> /// Event handler: search language button clicked. /// </summary> private void onSearchLang(ZenControlBase sender) { // Toggle between English and Chinese if (searchLang == SearchLang.Chinese) searchLang = SearchLang.Target; else searchLang = SearchLang.Chinese; // Update button searchLangChanged(); }
private void langJpButton_Checked(object sender, RoutedEventArgs e) { langEnum = SearchLang.JAPANESE; }
private void langEnButton_Checked(object sender, RoutedEventArgs e) { langEnum = SearchLang.ENGLISH; }
private void langAllButton_Checked(object sender, RoutedEventArgs e) { langEnum = SearchLang.ALL; }
/// <summary> /// Find entries that match the search expression. /// </summary> /// <param name="query">The query string, as entered by the user.</param> /// <param name="script">For hanzi lookup: simplified, traditional or both.</param> /// <param name="lang">Chinese or target language (English).</param> /// <returns>The lookup result.</returns> public CedictLookupResult Lookup(string query, SearchScript script, SearchLang lang) { List<CedictResult> res = new List<CedictResult>(); // BinReader: I own it until I successfully return results to caller. BinReader br = new BinReader(dictFileName); EntryProvider ep = new EntryProvider(br); try { // Try first in language requested by user // If no results that way, try in opposite language // Override if lookup in opposite language is successful if (lang == SearchLang.Chinese) { res = doChineseLookup(br, query, script); // We got fish if (res.Count > 0) return new CedictLookupResult(ep, new ReadOnlyCollection<CedictResult>(res), lang); // OK, try opposite (target) res = doTargetLookup(br, query); // We got fish: override if (res.Count > 0) return new CedictLookupResult(ep, new ReadOnlyCollection<CedictResult>(res), SearchLang.Target); } else { res = doTargetLookup(br, query); // We got fish if (res.Count > 0) return new CedictLookupResult(ep, new ReadOnlyCollection<CedictResult>(res), lang); // OK, try opposite (target) res = doChineseLookup(br, query, script); // We got fish: override if (res.Count > 0) return new CedictLookupResult(ep, new ReadOnlyCollection<CedictResult>(res), SearchLang.Chinese); } // Sorry, no results, no override return new CedictLookupResult(ep, new ReadOnlyCollection<CedictResult>(res), lang); } catch { br.Dispose(); throw; } }
/// <summary> /// Initializes tooltip provider for "search language" or "script" button. /// </summary> /// <param name="button">The actual button.</param> /// <param name="isLang">If true, this is tooltip for "search lang"; otherwise, for "script".</param> /// <param name="tprov">Localized UI strings provider.</param> /// <param name="script">Current search script.</param> /// <param name="lang">Current search language.</param> /// <param name="needleHeight">Needle's height at today's scaling.</param> public SearchOptionsTooltip(ZenGradientButton button, bool isLang, ITextProvider tprov, SearchScript script, SearchLang lang, int needleHeight, int boxRight) { this.button = button; this.needleHeight = needleHeight; this.topOrSide = -boxRight; if (isLang) { if (lang == SearchLang.Chinese) text = tprov.GetString("LangZhoTooltip"); else text = tprov.GetString("LangTrgTooltip"); } else { if (script == SearchScript.Simplified) text = tprov.GetString("ScriptSimpTooltip"); else if (script == SearchScript.Traditional) text = tprov.GetString("ScriptTradTooltip"); else text = tprov.GetString("ScriptBothTooltip"); } }
protected void Page_Load(object sender, EventArgs e) { // Only do this manually, and offline: generate sitemaps //SitemapGenerator.Generate(); var tprov = TextProvider.Instance; // Server-side inline localization strokeClear.InnerText = tprov.GetString(Master.UILang, "BtnStrokeClear"); strokeUndo.InnerText = tprov.GetString(Master.UILang, "BtnStrokeUndo"); txtSearch.Attributes["placeholder"] = tprov.GetString(Master.UILang, "TxtSearchPlacholder"); resultsHolder.Visible = false; soaBox.Visible = false; isStaticQuery = Request.RawUrl.StartsWith("/search/"); string qlang = Request["lang"]; string query = Request["query"]; if (query != null) { query = query.Trim(); } // No query: show welcome screen, and we're done. if (string.IsNullOrEmpty(query)) { resultsHolder.Visible = false; welcomeScreen.Visible = true; welcomeScreen.InnerHtml = tprov.GetSnippet(Master.UILang, "welcome"); Title = tprov.GetString(Master.UILang, "TitleMain"); // Seed walkthrough Master.SetStaticQuery(null, SearchLang.Chinese, DateTime.UtcNow); return; } // From here on ---> lookup string strMobile = Request["mobile"]; isMobile = strMobile == "yes"; // Auto-add "mobile" class to body if we know it already if (isMobile) { Master.SetMobile(); } queryInfo = new QueryInfo(Request.UserHostAddress, query); resultsHolder.Visible = true; welcomeScreen.Visible = false; SearchLang slang = qlang == "trg" ? SearchLang.Target : SearchLang.Chinese; var lr = Global.Dict.Lookup(query, SearchScript.Both, slang); queryInfo.ResCount = lr.Results.Count; queryInfo.AnnCount = lr.Annotations.Count; queryInfo.Lang = lr.ActualSearchLang; queryInfo.DTLookup = DateTime.UtcNow; prov = lr.EntryProvider; // Add regular results for (int i = 0; i != lr.Results.Count; ++i) { if (i >= 256) { break; } var res = lr.Results[i]; OneResultCtrl resCtrl = new OneResultCtrl(res, lr.EntryProvider, Master.UiScript, Master.UiTones, isMobile); resultsHolder.Controls.Add(resCtrl); } // Add annotations (we never get both, so don't need to worry about the order) for (int i = 0; i != lr.Annotations.Count; ++i) { var ann = lr.Annotations[i]; OneResultCtrl resCtrl = new OneResultCtrl(lr.Query, ann, lr.EntryProvider, Master.UiTones, isMobile); resultsHolder.Controls.Add(resCtrl); } txtSearch.Value = query; // No results if (lr.Results.Count == 0 && lr.Annotations.Count == 0) { resultsHolder.Visible = false; welcomeScreen.Visible = true; welcomeScreen.InnerHtml = tprov.GetSnippet(Master.UILang, "noresults"); Title = tprov.GetString(Master.UILang, "TitleMain"); } // We got results else { // Page title string title; // Regular lookup results if (lr.Results.Count != 0) { if (lr.ActualSearchLang == SearchLang.Chinese) { title = tprov.GetString(Master.UILang, "TitleSearchChinese"); } else { title = tprov.GetString(Master.UILang, "TitleSearchGerman"); } } // Annotation else { title = tprov.GetString(Master.UILang, "TitleSearchAnnotation"); } title = string.Format(title, query); Title = title; // For annotatio mode, show notice at top if (lr.Annotations.Count != 0) { topNotice.Visible = true; tnTitle.InnerText = tprov.GetString(Master.UILang, "AnnotationTitle"); tnMessage.InnerText = tprov.GetString(Master.UILang, "AnnotationMessage"); } // SOA BOX soaBox.Visible = true; soaTitle.InnerText = tprov.GetString(Master.UILang, "AnimPopupTitle"); string attrLink = "<a href='https://github.com/skishore/makemeahanzi' target='_blank'>{0}</a>"; attrLink = string.Format(attrLink, tprov.GetString(Master.UILang, "AnimPopupMMAH")); string attrHtml = tprov.GetString(Master.UILang, "AnimPopupAttr"); attrHtml = string.Format(attrHtml, attrLink); soaFooter.InnerHtml = attrHtml; // Seed walkthrough - if query is static and we have regular results (not annotations) if (isStaticQuery && lr.Results.Count != 0) { Master.SetStaticQuery(query, slang, queryInfo.DTStart); } } }